github.com/hashgraph/hedera-sdk-go/v2@v2.48.0/contract_execute_transaction.go (about)

     1  package hedera
     2  
     3  /*-
     4   *
     5   * Hedera Go SDK
     6   *
     7   * Copyright (C) 2020 - 2024 Hedera Hashgraph, LLC
     8   *
     9   * Licensed under the Apache License, Version 2.0 (the "License");
    10   * you may not use this file except in compliance with the License.
    11   * You may obtain a copy of the License at
    12   *
    13   *      http://www.apache.org/licenses/LICENSE-2.0
    14   *
    15   * Unless required by applicable law or agreed to in writing, software
    16   * distributed under the License is distributed on an "AS IS" BASIS,
    17   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    18   * See the License for the specific language governing permissions and
    19   * limitations under the License.
    20   *
    21   */
    22  
    23  import (
    24  	"github.com/hashgraph/hedera-protobufs-go/services"
    25  
    26  	"time"
    27  )
    28  
    29  // ContractExecuteTransaction calls a function of the given smart contract instance, giving it ContractFuncionParams as
    30  // its inputs. it can use the given amount of gas, and any unspent gas will be refunded to the paying account.
    31  //
    32  // If tx function stores information, it is charged gas to store it. There is a fee in hbars to maintain that storage
    33  // until the expiration time, and that fee is added as part of the transaction fee.
    34  //
    35  // For a cheaper but more limited _Method to call functions, see ContractCallQuery.
    36  type ContractExecuteTransaction struct {
    37  	Transaction
    38  	contractID *ContractID
    39  	gas        int64
    40  	amount     int64
    41  	parameters []byte
    42  }
    43  
    44  // NewContractExecuteTransaction creates a ContractExecuteTransaction transaction which can be
    45  // used to construct and execute a Contract Call Transaction.
    46  func NewContractExecuteTransaction() *ContractExecuteTransaction {
    47  	tx := ContractExecuteTransaction{
    48  		Transaction: _NewTransaction(),
    49  	}
    50  	tx._SetDefaultMaxTransactionFee(NewHbar(2))
    51  
    52  	return &tx
    53  }
    54  
    55  func _ContractExecuteTransactionFromProtobuf(tx Transaction, pb *services.TransactionBody) *ContractExecuteTransaction {
    56  	return &ContractExecuteTransaction{
    57  		Transaction: tx,
    58  		contractID:  _ContractIDFromProtobuf(pb.GetContractCall().GetContractID()),
    59  		gas:         pb.GetContractCall().GetGas(),
    60  		amount:      pb.GetContractCall().GetAmount(),
    61  		parameters:  pb.GetContractCall().GetFunctionParameters(),
    62  	}
    63  }
    64  
    65  // SetContractID sets the contract instance to call.
    66  func (tx *ContractExecuteTransaction) SetContractID(contractID ContractID) *ContractExecuteTransaction {
    67  	tx._RequireNotFrozen()
    68  	tx.contractID = &contractID
    69  	return tx
    70  }
    71  
    72  // GetContractID returns the contract instance to call.
    73  func (tx *ContractExecuteTransaction) GetContractID() ContractID {
    74  	if tx.contractID == nil {
    75  		return ContractID{}
    76  	}
    77  
    78  	return *tx.contractID
    79  }
    80  
    81  // SetGas sets the maximum amount of gas to use for the call.
    82  func (tx *ContractExecuteTransaction) SetGas(gas uint64) *ContractExecuteTransaction {
    83  	tx._RequireNotFrozen()
    84  	tx.gas = int64(gas)
    85  	return tx
    86  }
    87  
    88  // GetGas returns the maximum amount of gas to use for the call.
    89  func (tx *ContractExecuteTransaction) GetGas() uint64 {
    90  	return uint64(tx.gas)
    91  }
    92  
    93  // SetPayableAmount sets the amount of Hbar sent (the function must be payable if this is nonzero)
    94  func (tx *ContractExecuteTransaction) SetPayableAmount(amount Hbar) *ContractExecuteTransaction {
    95  	tx._RequireNotFrozen()
    96  	tx.amount = amount.AsTinybar()
    97  	return tx
    98  }
    99  
   100  // GetPayableAmount returns the amount of Hbar sent (the function must be payable if this is nonzero)
   101  func (tx *ContractExecuteTransaction) GetPayableAmount() Hbar {
   102  	return HbarFromTinybar(tx.amount)
   103  }
   104  
   105  // SetFunctionParameters sets the function parameters
   106  func (tx *ContractExecuteTransaction) SetFunctionParameters(params []byte) *ContractExecuteTransaction {
   107  	tx._RequireNotFrozen()
   108  	tx.parameters = params
   109  	return tx
   110  }
   111  
   112  // GetFunctionParameters returns the function parameters
   113  func (tx *ContractExecuteTransaction) GetFunctionParameters() []byte {
   114  	return tx.parameters
   115  }
   116  
   117  // SetFunction sets which function to call, and the ContractFunctionParams to pass to the function
   118  func (tx *ContractExecuteTransaction) SetFunction(name string, params *ContractFunctionParameters) *ContractExecuteTransaction {
   119  	tx._RequireNotFrozen()
   120  	if params == nil {
   121  		params = NewContractFunctionParameters()
   122  	}
   123  
   124  	tx.parameters = params._Build(&name)
   125  	return tx
   126  }
   127  
   128  // ---- Required Interfaces ---- //
   129  
   130  // Sign uses the provided privateKey to sign the transaction.
   131  func (tx *ContractExecuteTransaction) Sign(
   132  	privateKey PrivateKey,
   133  ) *ContractExecuteTransaction {
   134  	tx.Transaction.Sign(privateKey)
   135  	return tx
   136  }
   137  
   138  // SignWithOperator signs the transaction with client's operator privateKey.
   139  func (tx *ContractExecuteTransaction) SignWithOperator(
   140  	client *Client,
   141  ) (*ContractExecuteTransaction, error) {
   142  	_, err := tx.Transaction.signWithOperator(client, tx)
   143  	if err != nil {
   144  		return nil, err
   145  	}
   146  	return tx, nil
   147  }
   148  
   149  // SignWith executes the TransactionSigner and adds the resulting signature data to the Transaction's signature map
   150  // with the publicKey as the map key.
   151  func (tx *ContractExecuteTransaction) SignWith(
   152  	publicKey PublicKey,
   153  	signer TransactionSigner,
   154  ) *ContractExecuteTransaction {
   155  	tx.Transaction.SignWith(publicKey, signer)
   156  	return tx
   157  }
   158  
   159  // AddSignature adds a signature to the transaction.
   160  func (tx *ContractExecuteTransaction) AddSignature(publicKey PublicKey, signature []byte) *ContractExecuteTransaction {
   161  	tx.Transaction.AddSignature(publicKey, signature)
   162  	return tx
   163  }
   164  
   165  // When execution is attempted, a single attempt will timeout when tx deadline is reached. (The SDK may subsequently retry the execution.)
   166  func (tx *ContractExecuteTransaction) SetGrpcDeadline(deadline *time.Duration) *ContractExecuteTransaction {
   167  	tx.Transaction.SetGrpcDeadline(deadline)
   168  	return tx
   169  }
   170  
   171  func (tx *ContractExecuteTransaction) Freeze() (*ContractExecuteTransaction, error) {
   172  	return tx.FreezeWith(nil)
   173  }
   174  
   175  func (tx *ContractExecuteTransaction) FreezeWith(client *Client) (*ContractExecuteTransaction, error) {
   176  	_, err := tx.Transaction.freezeWith(client, tx)
   177  	return tx, err
   178  }
   179  
   180  // SetMaxTransactionFee sets the maximum transaction fee the operator (paying account) is willing to pay.
   181  func (tx *ContractExecuteTransaction) SetMaxTransactionFee(fee Hbar) *ContractExecuteTransaction {
   182  	tx._RequireNotFrozen()
   183  	tx.Transaction.SetMaxTransactionFee(fee)
   184  	return tx
   185  }
   186  
   187  // SetRegenerateTransactionID sets if transaction IDs should be regenerated when `TRANSACTION_EXPIRED` is received
   188  func (tx *ContractExecuteTransaction) SetRegenerateTransactionID(regenerateTransactionID bool) *ContractExecuteTransaction {
   189  	tx._RequireNotFrozen()
   190  	tx.Transaction.SetRegenerateTransactionID(regenerateTransactionID)
   191  	return tx
   192  }
   193  
   194  // SetTransactionMemo sets the memo for this ContractExecuteTransaction.
   195  func (tx *ContractExecuteTransaction) SetTransactionMemo(memo string) *ContractExecuteTransaction {
   196  	tx._RequireNotFrozen()
   197  	tx.Transaction.SetTransactionMemo(memo)
   198  	return tx
   199  }
   200  
   201  // SetTransactionValidDuration sets the valid duration for this ContractExecuteTransaction.
   202  func (tx *ContractExecuteTransaction) SetTransactionValidDuration(duration time.Duration) *ContractExecuteTransaction {
   203  	tx._RequireNotFrozen()
   204  	tx.Transaction.SetTransactionValidDuration(duration)
   205  	return tx
   206  }
   207  
   208  // ToBytes serialise the tx to bytes, no matter if it is signed (locked), or not
   209  func (tx *ContractExecuteTransaction) ToBytes() ([]byte, error) {
   210  	bytes, err := tx.Transaction.toBytes(tx)
   211  	if err != nil {
   212  		return nil, err
   213  	}
   214  	return bytes, nil
   215  }
   216  
   217  // SetTransactionID sets the TransactionID for this ContractExecuteTransaction.
   218  func (tx *ContractExecuteTransaction) SetTransactionID(transactionID TransactionID) *ContractExecuteTransaction {
   219  	tx._RequireNotFrozen()
   220  
   221  	tx.Transaction.SetTransactionID(transactionID)
   222  	return tx
   223  }
   224  
   225  // SetNodeAccountIDs sets the _Node AccountID for this ContractExecuteTransaction.
   226  func (tx *ContractExecuteTransaction) SetNodeAccountIDs(nodeID []AccountID) *ContractExecuteTransaction {
   227  	tx._RequireNotFrozen()
   228  	tx.Transaction.SetNodeAccountIDs(nodeID)
   229  	return tx
   230  }
   231  
   232  // SetMaxRetry sets the max number of errors before execution will fail.
   233  func (tx *ContractExecuteTransaction) SetMaxRetry(count int) *ContractExecuteTransaction {
   234  	tx.Transaction.SetMaxRetry(count)
   235  	return tx
   236  }
   237  
   238  // SetMaxBackoff The maximum amount of time to wait between retries.
   239  // Every retry attempt will increase the wait time exponentially until it reaches this time.
   240  func (tx *ContractExecuteTransaction) SetMaxBackoff(max time.Duration) *ContractExecuteTransaction {
   241  	tx.Transaction.SetMaxBackoff(max)
   242  	return tx
   243  }
   244  
   245  // SetMinBackoff sets the minimum amount of time to wait between retries.
   246  func (tx *ContractExecuteTransaction) SetMinBackoff(min time.Duration) *ContractExecuteTransaction {
   247  	tx.Transaction.SetMinBackoff(min)
   248  	return tx
   249  }
   250  
   251  func (tx *ContractExecuteTransaction) SetLogLevel(level LogLevel) *ContractExecuteTransaction {
   252  	tx.Transaction.SetLogLevel(level)
   253  	return tx
   254  }
   255  
   256  func (tx *ContractExecuteTransaction) Execute(client *Client) (TransactionResponse, error) {
   257  	return tx.Transaction.execute(client, tx)
   258  }
   259  
   260  func (tx *ContractExecuteTransaction) Schedule() (*ScheduleCreateTransaction, error) {
   261  	return tx.Transaction.schedule(tx)
   262  }
   263  
   264  // ----------- Overridden functions ----------------
   265  
   266  func (tx *ContractExecuteTransaction) getName() string {
   267  	return "ContractExecuteTransaction"
   268  }
   269  func (tx *ContractExecuteTransaction) validateNetworkOnIDs(client *Client) error {
   270  	if client == nil || !client.autoValidateChecksums {
   271  		return nil
   272  	}
   273  
   274  	if tx.contractID != nil {
   275  		if err := tx.contractID.ValidateChecksum(client); err != nil {
   276  			return err
   277  		}
   278  	}
   279  
   280  	return nil
   281  }
   282  
   283  func (tx *ContractExecuteTransaction) build() *services.TransactionBody {
   284  	return &services.TransactionBody{
   285  		TransactionFee:           tx.transactionFee,
   286  		Memo:                     tx.Transaction.memo,
   287  		TransactionValidDuration: _DurationToProtobuf(tx.GetTransactionValidDuration()),
   288  		TransactionID:            tx.transactionID._ToProtobuf(),
   289  		Data: &services.TransactionBody_ContractCall{
   290  			ContractCall: tx.buildProtoBody(),
   291  		},
   292  	}
   293  }
   294  
   295  func (tx *ContractExecuteTransaction) buildScheduled() (*services.SchedulableTransactionBody, error) {
   296  	return &services.SchedulableTransactionBody{
   297  		TransactionFee: tx.transactionFee,
   298  		Memo:           tx.Transaction.memo,
   299  		Data: &services.SchedulableTransactionBody_ContractCall{
   300  			ContractCall: tx.buildProtoBody(),
   301  		},
   302  	}, nil
   303  }
   304  
   305  func (tx *ContractExecuteTransaction) buildProtoBody() *services.ContractCallTransactionBody {
   306  	body := &services.ContractCallTransactionBody{
   307  		Gas:                tx.gas,
   308  		Amount:             tx.amount,
   309  		FunctionParameters: tx.parameters,
   310  	}
   311  
   312  	if tx.contractID != nil {
   313  		body.ContractID = tx.contractID._ToProtobuf()
   314  	}
   315  
   316  	return body
   317  }
   318  
   319  func (tx *ContractExecuteTransaction) getMethod(channel *_Channel) _Method {
   320  	return _Method{
   321  		transaction: channel._GetContract().ContractCallMethod,
   322  	}
   323  }
   324  func (tx *ContractExecuteTransaction) _ConstructScheduleProtobuf() (*services.SchedulableTransactionBody, error) {
   325  	return tx.buildScheduled()
   326  }