github.com/hashgraph/hedera-sdk-go/v2@v2.48.0/contract_create_flow.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 "encoding/hex" 25 "time" 26 27 "github.com/pkg/errors" 28 ) 29 30 type ContractCreateFlow struct { 31 Transaction 32 bytecode []byte 33 proxyAccountID *AccountID 34 adminKey *Key 35 gas int64 36 initialBalance int64 37 autoRenewPeriod *time.Duration 38 parameters []byte 39 nodeAccountIDs []AccountID 40 createBytecode []byte 41 appendBytecode []byte 42 autoRenewAccountID *AccountID 43 maxAutomaticTokenAssociations int32 44 maxChunks *uint64 45 } 46 47 // NewContractCreateFlow creates a new ContractCreateFlow transaction builder object. 48 func NewContractCreateFlow() *ContractCreateFlow { 49 this := ContractCreateFlow{ 50 Transaction: _NewTransaction(), 51 } 52 53 this.SetAutoRenewPeriod(131500 * time.Minute) 54 this.SetMaxTransactionFee(NewHbar(20)) 55 56 return &this 57 } 58 59 // SetBytecodeWithString sets the bytecode of the contract in hex-encoded string format. 60 func (tx *ContractCreateFlow) SetBytecodeWithString(bytecode string) *ContractCreateFlow { 61 tx._RequireNotFrozen() 62 tx.bytecode, _ = hex.DecodeString(bytecode) 63 return tx 64 } 65 66 // SetBytecode sets the bytecode of the contract in raw bytes. 67 func (tx *ContractCreateFlow) SetBytecode(bytecode []byte) *ContractCreateFlow { 68 tx._RequireNotFrozen() 69 tx.bytecode = bytecode 70 return tx 71 } 72 73 // GetBytecode returns the hex-encoded bytecode of the contract. 74 func (tx *ContractCreateFlow) GetBytecode() string { 75 return hex.EncodeToString(tx.bytecode) 76 } 77 78 // Sets the state of the instance and its fields can be modified arbitrarily if this key signs a transaction 79 // to modify it. If this is null, then such modifications are not possible, and there is no administrator 80 // that can override the normal operation of this smart contract instance. Note that if it is created with no 81 // admin keys, then there is no administrator to authorize changing the admin keys, so 82 // there can never be any admin keys for that instance. 83 func (tx *ContractCreateFlow) SetAdminKey(adminKey Key) *ContractCreateFlow { 84 tx._RequireNotFrozen() 85 tx.adminKey = &adminKey 86 return tx 87 } 88 89 // GetAdminKey returns the admin key of the contract. 90 func (tx *ContractCreateFlow) GetAdminKey() Key { 91 if tx.adminKey != nil { 92 return *tx.adminKey 93 } 94 95 return PrivateKey{} 96 } 97 98 // SetGas sets the gas to run the constructor. 99 func (tx *ContractCreateFlow) SetGas(gas int64) *ContractCreateFlow { 100 tx._RequireNotFrozen() 101 tx.gas = gas 102 return tx 103 } 104 105 // GetGas returns the gas to run the constructor. 106 func (tx *ContractCreateFlow) GetGas() int64 { 107 return tx.gas 108 } 109 110 // SetInitialBalance sets the initial number of hbars to put into the cryptocurrency account 111 // associated with and owned by the smart contract. 112 func (tx *ContractCreateFlow) SetInitialBalance(initialBalance Hbar) *ContractCreateFlow { 113 tx._RequireNotFrozen() 114 tx.initialBalance = initialBalance.AsTinybar() 115 return tx 116 } 117 118 // GetInitialBalance returns the initial number of hbars to put into the cryptocurrency account 119 // associated with and owned by the smart contract. 120 func (tx *ContractCreateFlow) GetInitialBalance() Hbar { 121 return HbarFromTinybar(tx.initialBalance) 122 } 123 124 // SetAutoRenewPeriod sets the period that the instance will charge its account every this many seconds to renew. 125 func (tx *ContractCreateFlow) SetAutoRenewPeriod(autoRenewPeriod time.Duration) *ContractCreateFlow { 126 tx._RequireNotFrozen() 127 tx.autoRenewPeriod = &autoRenewPeriod 128 return tx 129 } 130 131 // GetAutoRenewPeriod returns the period that the instance will charge its account every this many seconds to renew. 132 func (tx *ContractCreateFlow) GetAutoRenewPeriod() time.Duration { 133 if tx.autoRenewPeriod != nil { 134 return *tx.autoRenewPeriod 135 } 136 137 return time.Duration(0) 138 } 139 140 // Deprecated 141 func (tx *ContractCreateFlow) SetProxyAccountID(proxyAccountID AccountID) *ContractCreateFlow { 142 tx._RequireNotFrozen() 143 tx.proxyAccountID = &proxyAccountID 144 return tx 145 } 146 147 // Deprecated 148 func (tx *ContractCreateFlow) GetProxyAccountID() AccountID { 149 if tx.proxyAccountID == nil { 150 return AccountID{} 151 } 152 153 return *tx.proxyAccountID 154 } 155 156 // Sets the constructor parameters 157 func (tx *ContractCreateFlow) SetConstructorParameters(params *ContractFunctionParameters) *ContractCreateFlow { 158 tx._RequireNotFrozen() 159 tx.parameters = params._Build(nil) 160 return tx 161 } 162 163 // Sets the constructor parameters as their raw bytes. 164 func (tx *ContractCreateFlow) SetConstructorParametersRaw(params []byte) *ContractCreateFlow { 165 tx._RequireNotFrozen() 166 tx.parameters = params 167 return tx 168 } 169 170 func (tx *ContractCreateFlow) GetConstructorParameters() []byte { 171 return tx.parameters 172 } 173 174 // Sets the memo to be associated with this contract. 175 func (tx *ContractCreateFlow) SetContractMemo(memo string) *ContractCreateFlow { 176 tx._RequireNotFrozen() 177 tx.memo = memo 178 return tx 179 } 180 181 // Gets the memo to be associated with this contract. 182 func (tx *ContractCreateFlow) GetContractMemo() string { 183 return tx.memo 184 } 185 186 // SetMaxChunks sets the maximum number of chunks that the contract bytecode can be split into. 187 func (tx *ContractCreateFlow) SetMaxChunks(max uint64) *ContractCreateFlow { 188 tx._RequireNotFrozen() 189 tx.maxChunks = &max 190 return tx 191 } 192 193 // GetMaxChunks returns the maximum number of chunks that the contract bytecode can be split into. 194 func (tx *ContractCreateFlow) GetMaxChunks() uint64 { 195 if tx.maxChunks == nil { 196 return 0 197 } 198 199 return *tx.maxChunks 200 } 201 202 // SetAutoRenewAccountID 203 // An account to charge for auto-renewal of this contract. If not set, or set to an 204 // account with zero hbar balance, the contract's own hbar balance will be used to 205 // cover auto-renewal fees. 206 func (tx *ContractCreateFlow) SetAutoRenewAccountID(id AccountID) *ContractCreateFlow { 207 tx._RequireNotFrozen() 208 tx.autoRenewAccountID = &id 209 return tx 210 } 211 212 // GetAutoRenewAccountID returns the account to charge for auto-renewal of this contract. 213 func (tx *ContractCreateFlow) GetAutoRenewAccountID() AccountID { 214 if tx.autoRenewAccountID == nil { 215 return AccountID{} 216 } 217 218 return *tx.autoRenewAccountID 219 } 220 221 // SetMaxAutomaticTokenAssociations 222 // The maximum number of tokens that this contract can be automatically associated 223 // with (i.e., receive air-drops from). 224 func (tx *ContractCreateFlow) SetMaxAutomaticTokenAssociations(max int32) *ContractCreateFlow { 225 tx._RequireNotFrozen() 226 tx.maxAutomaticTokenAssociations = max 227 return tx 228 } 229 230 // GetMaxAutomaticTokenAssociations returns the maximum number of tokens that this 231 // contract can be automatically associated with. 232 func (tx *ContractCreateFlow) GetMaxAutomaticTokenAssociations() int32 { 233 return tx.maxAutomaticTokenAssociations 234 } 235 236 func (tx *ContractCreateFlow) splitBytecode() *ContractCreateFlow { 237 if len(tx.bytecode) > 2048 { 238 tx.createBytecode = tx.bytecode[0:2048] 239 tx.appendBytecode = tx.bytecode[2048:] 240 return tx 241 } 242 243 tx.createBytecode = tx.bytecode 244 tx.appendBytecode = []byte{} 245 return tx 246 } 247 248 func (tx *ContractCreateFlow) _CreateFileCreateTransaction(client *Client) *FileCreateTransaction { 249 if client == nil { 250 return &FileCreateTransaction{} 251 } 252 fileCreateTx := NewFileCreateTransaction(). 253 SetKeys(client.GetOperatorPublicKey()). 254 SetContents(tx.createBytecode) 255 256 if len(tx.nodeAccountIDs) > 0 { 257 fileCreateTx.SetNodeAccountIDs(tx.nodeAccountIDs) 258 } 259 260 return fileCreateTx 261 } 262 263 func (tx *ContractCreateFlow) _CreateFileAppendTransaction(fileID FileID) *FileAppendTransaction { 264 fileAppendTx := NewFileAppendTransaction(). 265 SetFileID(fileID). 266 SetContents(tx.appendBytecode) 267 268 if len(tx.nodeAccountIDs) > 0 { 269 fileAppendTx.SetNodeAccountIDs(tx.nodeAccountIDs) 270 } 271 if tx.maxChunks != nil { 272 fileAppendTx.SetMaxChunks(*tx.maxChunks) 273 } 274 275 return fileAppendTx 276 } 277 278 func (tx *ContractCreateFlow) _CreateContractCreateTransaction(fileID FileID) *ContractCreateTransaction { 279 contractCreateTx := NewContractCreateTransaction(). 280 SetGas(uint64(tx.gas)). 281 SetConstructorParametersRaw(tx.parameters). 282 SetInitialBalance(HbarFromTinybar(tx.initialBalance)). 283 SetBytecodeFileID(fileID). 284 SetContractMemo(tx.memo) 285 286 if len(tx.nodeAccountIDs) > 0 { 287 contractCreateTx.SetNodeAccountIDs(tx.nodeAccountIDs) 288 } 289 290 if tx.adminKey != nil { 291 contractCreateTx.SetAdminKey(*tx.adminKey) 292 } 293 294 if tx.proxyAccountID != nil { 295 contractCreateTx.SetProxyAccountID(*tx.proxyAccountID) 296 } 297 298 if tx.autoRenewPeriod != nil { 299 contractCreateTx.SetAutoRenewPeriod(*tx.autoRenewPeriod) 300 } 301 302 if tx.autoRenewAccountID != nil { 303 contractCreateTx.SetAutoRenewAccountID(*tx.autoRenewAccountID) 304 } 305 306 if tx.maxAutomaticTokenAssociations != 0 { 307 contractCreateTx.SetMaxAutomaticTokenAssociations(tx.maxAutomaticTokenAssociations) 308 } 309 310 return contractCreateTx 311 } 312 313 func (tx *ContractCreateFlow) Execute(client *Client) (TransactionResponse, error) { 314 tx.splitBytecode() 315 316 fileCreateResponse, err := tx._CreateFileCreateTransaction(client).Execute(client) 317 if err != nil { 318 return TransactionResponse{}, err 319 } 320 fileCreateReceipt, err := fileCreateResponse.SetValidateStatus(true).GetReceipt(client) 321 if err != nil { 322 return TransactionResponse{}, err 323 } 324 if fileCreateReceipt.FileID == nil { 325 return TransactionResponse{}, errors.New("fileID is nil") 326 } 327 fileID := *fileCreateReceipt.FileID 328 if len(tx.appendBytecode) > 0 { 329 fileAppendResponse, err := tx._CreateFileAppendTransaction(fileID).Execute(client) 330 if err != nil { 331 return TransactionResponse{}, err 332 } 333 334 _, err = fileAppendResponse.SetValidateStatus(true).GetReceipt(client) 335 if err != nil { 336 return TransactionResponse{}, err 337 } 338 } 339 contractCreateResponse, err := tx._CreateContractCreateTransaction(fileID).Execute(client) 340 if err != nil { 341 return TransactionResponse{}, err 342 } 343 _, err = contractCreateResponse.SetValidateStatus(true).GetReceipt(client) 344 if err != nil { 345 return TransactionResponse{}, err 346 } 347 348 return contractCreateResponse, nil 349 } 350 351 // SetNodeAccountIDs sets the node AccountID for this ContractCreateFlow. 352 func (tx *ContractCreateFlow) SetNodeAccountIDs(nodeID []AccountID) *ContractCreateFlow { 353 tx._RequireNotFrozen() 354 tx.nodeAccountIDs = nodeID 355 return tx 356 } 357 358 // GetNodeAccountIDs returns the node AccountID for this ContractCreateFlow. 359 func (tx *ContractCreateFlow) GetNodeAccountIDs() []AccountID { 360 return tx.nodeAccountIDs 361 }