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  }