github.com/hashgraph/hedera-sdk-go/v2@v2.48.0/examples/create_stateful_contract/main.go (about) 1 package main 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "os" 7 8 "github.com/hashgraph/hedera-sdk-go/v2" 9 ) 10 11 type contract struct { 12 Abi string `json:"abi"` 13 Bin string `json:"bin"` 14 } 15 16 type contracts struct { 17 Contracts map[string]contract `json:"contracts"` 18 Version string `json:"version"` 19 } 20 21 func main() { 22 var client *hedera.Client 23 var err error 24 25 // Retrieving network type from environment variable HEDERA_NETWORK 26 client, err = hedera.ClientForName(os.Getenv("HEDERA_NETWORK")) 27 if err != nil { 28 panic(fmt.Sprintf("%v : error creating client", err)) 29 } 30 31 // Retrieving operator ID from environment variable OPERATOR_ID 32 operatorAccountID, err := hedera.AccountIDFromString(os.Getenv("OPERATOR_ID")) 33 if err != nil { 34 panic(fmt.Sprintf("%v : error converting string to AccountID", err)) 35 } 36 37 // Retrieving operator key from environment variable OPERATOR_KEY 38 operatorKey, err := hedera.PrivateKeyFromString(os.Getenv("OPERATOR_KEY")) 39 if err != nil { 40 panic(fmt.Sprintf("%v : error converting string to PrivateKey", err)) 41 } 42 43 // Setting the client operator ID and key 44 client.SetOperator(operatorAccountID, operatorKey) 45 46 // Make sure to close client after running 47 defer func() { 48 err = client.Close() 49 if err != nil { 50 panic(fmt.Sprintf("%v : error closing client", err)) 51 } 52 }() 53 54 // Read in the compiled contract from stateful.json 55 rawSmartContract, err := os.ReadFile("./stateful.json") 56 if err != nil { 57 panic(fmt.Sprintf("%v : error reading stateful.json", err)) 58 } 59 60 // Initialize contracts 61 var smartContract contracts = contracts{} 62 63 // Parse the rawSmartContract into smartContract 64 err = json.Unmarshal([]byte(rawSmartContract), &smartContract) 65 if err != nil { 66 panic(fmt.Sprintf("%v : error unmarshaling", err)) 67 } 68 69 // Retrieve the bytecode from the parsed smart contract 70 smartContractByteCode := smartContract.Contracts["stateful.sol:StatefulContract"].Bin 71 72 fmt.Println("Stateful contract example") 73 fmt.Printf("Contract bytecode size: %v bytes\n", len(smartContractByteCode)) 74 75 // Upload a file containing the byte code 76 byteCodeTransactionResponse, err := hedera.NewFileCreateTransaction(). 77 // A file is not implicitly owned by anyone, even the operator 78 // But we do use operator's key for this one 79 SetKeys(client.GetOperatorPublicKey()). 80 // Set the stateful contract bytes for this 81 SetContents([]byte(smartContractByteCode)). 82 Execute(client) 83 if err != nil { 84 panic(fmt.Sprintf("%v : error creating file", err)) 85 } 86 87 // Retrieve the receipt to make sure the transaction went through and to get bytecode file ID 88 byteCodeTransactionReceipt, err := byteCodeTransactionResponse.GetReceipt(client) 89 if err != nil { 90 panic(fmt.Sprintf("%v : error getting file create transaction receipt", err)) 91 } 92 93 // Retrieve bytecode file ID from the receipt 94 byteCodeFileID := *byteCodeTransactionReceipt.FileID 95 96 fmt.Printf("contract bytecode file: %v\n", byteCodeFileID) 97 98 // Set the parameters that should be passed to the contract constructor 99 // In this case we are passing in a string with the value "hello from hedera!" 100 // as the only parameter that is passed to the contract 101 contractFunctionParams := hedera.NewContractFunctionParameters(). 102 AddString("hello from hedera") 103 104 // Instantiate the contract instance 105 contractTransactionID, err := hedera.NewContractCreateTransaction(). 106 // Set gas to create the contract 107 // Failing to set this to a sufficient amount will result in "INSUFFICIENT_GAS" status 108 SetGas(200000). 109 // Failing to set parameters when required will result in "CONTRACT_REVERT_EXECUTED" status 110 SetConstructorParameters(contractFunctionParams). 111 // The contract bytecode must be set to the file ID containing the contract bytecode 112 SetBytecodeFileID(byteCodeFileID). 113 // Set the admin key on the contract in case the contract should be deleted or 114 // updated in the future 115 SetAdminKey(client.GetOperatorPublicKey()). 116 Execute(client) 117 118 if err != nil { 119 panic(fmt.Sprintf("%v : error creating contract", err)) 120 } 121 122 // Get the new contract record to make sure the transaction ran successfully 123 contractRecord, err := contractTransactionID.GetRecord(client) 124 if err != nil { 125 panic(fmt.Sprintf("%v : error retrieving contract creation record", err)) 126 } 127 128 // Get the contract create result from the record 129 contractCreateResult, err := contractRecord.GetContractCreateResult() 130 if err != nil { 131 panic(fmt.Sprintf("%v : error retrieving contract creation result", err)) 132 } 133 134 // Get the new contract ID from the receipt contained in the record 135 newContractID := *contractRecord.Receipt.ContractID 136 137 fmt.Printf("Contract create gas used: %v\n", contractCreateResult.GasUsed) 138 fmt.Printf("Contract create transaction fee: %v\n", contractRecord.TransactionFee) 139 fmt.Printf("contract: %v\n", newContractID) 140 141 // Ask for the current message (set on creation) 142 callResult, err := hedera.NewContractCallQuery(). 143 // Set which contract 144 SetContractID(newContractID). 145 // The amount of gas to use for the call 146 // All of the gas offered will be used and charged a corresponding fee 147 SetGas(100000). 148 // This query requires payment, depends on gas used 149 SetQueryPayment(hedera.NewHbar(1)). 150 // nil -> no parameters 151 // Specified which function to call, and the parameters to pass to the function 152 SetFunction("getMessage", nil). 153 Execute(client) 154 if err != nil { 155 panic(fmt.Sprintf("%v : error executing contract call query", err)) 156 } 157 158 fmt.Printf("Call gas used: %v\n", callResult.GasUsed) 159 // Get the message from the result 160 // The `0` is the index to fetch a particular type from 161 // 162 // e.g. type of `getMessage` was `(uint32, string)` 163 // then you'd need to get each field separately using: 164 // uint32 := callResult.getUint32(0); 165 // string := callResult.getString(1); 166 fmt.Printf("Message: %v\n", callResult.GetString(0)) 167 168 // In this case we are passing in a string with the value "Hello from Hedera again!" 169 // as the only parameter that is passed to the contract 170 contractFunctionParams = hedera.NewContractFunctionParameters(). 171 AddString("Hello from Hedera again!") 172 173 // Update the message 174 contractExecuteID, err := hedera.NewContractExecuteTransaction(). 175 // Set which contract 176 SetContractID(newContractID). 177 // Set the gas to execute the contract call 178 SetGas(100000). 179 // Set the function to call and the parameters to send 180 // in this case we're calling function "set_message" with a single 181 // string parameter of value "Hello from Hedera again!" 182 // If instead the "setMessage" method were to require "uint32, string" 183 // parameters then you must do: 184 // contractFunctionParams := hedera.NewContractFunctionParameters(). 185 // .addUint32(1) 186 // .addString("string 3") 187 SetFunction("setMessage", contractFunctionParams). 188 Execute(client) 189 190 if err != nil { 191 panic(fmt.Sprintf("%v : error executing contract", err)) 192 } 193 194 // Retrieve the record to make sure the execute transaction ran 195 contractExecuteRecord, err := contractExecuteID.GetRecord(client) 196 if err != nil { 197 panic(fmt.Sprintf("%v : error retrieving contract execution record", err)) 198 } 199 200 // Get the contract execute result, that contains gas used 201 contractExecuteResult, err := contractExecuteRecord.GetContractExecuteResult() 202 if err != nil { 203 panic(fmt.Sprintf("%v : error retrieving contract exe", err)) 204 } 205 206 // Print gas used 207 fmt.Printf("Execute gas used: %v\n", contractExecuteResult.GasUsed) 208 209 // Call a method on a contract that exists on Hedera 210 secondCallResult, err := hedera.NewContractCallQuery(). 211 // Set which contract 212 SetContractID(newContractID). 213 // Set gas to use 214 SetGas(100000). 215 // Set the query payment explicitly since sometimes automatic payment calculated 216 // is too low 217 SetQueryPayment(hedera.NewHbar(1)). 218 // Set the function to call on the contract 219 SetFunction("getMessage", nil). 220 Execute(client) 221 222 if err != nil { 223 panic(fmt.Sprintf("%v : error executing contract call query", err)) 224 } 225 226 // Get gas used 227 fmt.Printf("Call gas used: %v\n", secondCallResult.GasUsed) 228 // Get a string from the result at index 0 229 fmt.Printf("Message: %v\n", secondCallResult.GetString(0)) 230 }