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 }