github.com/hashgraph/hedera-sdk-go/v2@v2.48.0/examples/schedule_identical_transaction/main.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "os" 6 7 "github.com/hashgraph/hedera-sdk-go/v2" 8 ) 9 10 func main() { 11 var client *hedera.Client 12 var err error 13 14 // Retrieving network type from environment variable HEDERA_NETWORK 15 client, err = hedera.ClientForName(os.Getenv("HEDERA_NETWORK")) 16 if err != nil { 17 panic(fmt.Sprintf("%v : error creating client", err)) 18 } 19 20 // Retrieving operator ID from environment variable OPERATOR_ID 21 operatorAccountID, err := hedera.AccountIDFromString(os.Getenv("OPERATOR_ID")) 22 if err != nil { 23 panic(fmt.Sprintf("%v : error converting string to AccountID", err)) 24 } 25 26 // Retrieving operator key from environment variable OPERATOR_KEY 27 operatorKey, err := hedera.PrivateKeyFromString(os.Getenv("OPERATOR_KEY")) 28 if err != nil { 29 panic(fmt.Sprintf("%v : error converting string to PrivateKey", err)) 30 } 31 32 // Setting the client operator ID and key 33 client.SetOperator(operatorAccountID, operatorKey) 34 35 pubKeys := make([]hedera.PublicKey, 3) 36 clients := make([]*hedera.Client, 3) 37 accounts := make([]hedera.AccountID, 3) 38 39 fmt.Println("threshold key example") 40 fmt.Println("Keys: ") 41 42 var scheduleID *hedera.ScheduleID 43 44 // Loop to generate keys, clients, and accounts 45 for i := range pubKeys { 46 newKey, err := hedera.GeneratePrivateKey() 47 if err != nil { 48 panic(fmt.Sprintf("%v : error generating PrivateKey", err)) 49 } 50 51 fmt.Printf("Key %v:\n", i) 52 fmt.Printf("private = %v\n", newKey) 53 fmt.Printf("public = %v\n", newKey.PublicKey()) 54 55 pubKeys[i] = newKey.PublicKey() 56 57 createResponse, err := hedera.NewAccountCreateTransaction(). 58 // The key that must sign each transfer out of the account. If receiverSigRequired is true, then 59 // it must also sign any transfer into the account. 60 SetKey(newKey). 61 SetInitialBalance(hedera.NewHbar(1)). 62 Execute(client) 63 if err != nil { 64 panic(fmt.Sprintf("%v : error creating account", err)) 65 } 66 67 // Make sure the transaction succeeded 68 transactionReceipt, err := createResponse.GetReceipt(client) 69 if err != nil { 70 panic(fmt.Sprintf("%v : error getting receipt 1", err)) 71 } 72 73 newClient, err := hedera.ClientForName(os.Getenv("HEDERA_NETWORK")) 74 if err != nil { 75 panic(fmt.Sprintf("%v : error creating client", err)) 76 } 77 newClient = newClient.SetOperator(*transactionReceipt.AccountID, newKey) 78 79 clients[i] = newClient 80 accounts[i] = *transactionReceipt.AccountID 81 82 fmt.Printf("account = %v\n", accounts[i]) 83 } 84 85 // A threshold key with a threshold of 2 and length of 3 requires 86 // at least 2 of the 3 keys to sign anything modifying the account 87 keyList := hedera.KeyListWithThreshold(2). 88 AddAllPublicKeys(pubKeys) 89 90 // We are using all of these keys, so the scheduled transaction doesn't automatically go through 91 // It works perfectly fine with just one key 92 createResponse, err := hedera.NewAccountCreateTransaction(). 93 // The key that must sign each transfer out of the account. If receiverSigRequired is true, then 94 // it must also sign any transfer into the account. 95 SetKey(keyList). 96 SetInitialBalance(hedera.NewHbar(10)). 97 Execute(client) 98 if err != nil { 99 panic(fmt.Sprintf("%v : error executing create account transaction", err)) 100 } 101 102 // Make sure the transaction succeeded 103 transactionReceipt, err := createResponse.GetReceipt(client) 104 if err != nil { 105 panic(fmt.Sprintf("%v : error getting receipt 2", err)) 106 } 107 thresholdAccount := *transactionReceipt.AccountID 108 109 fmt.Printf("threshold account = %v\n", thresholdAccount) 110 111 for _, client := range clients { 112 operator := client.GetOperatorAccountID().String() 113 114 // Each client creates an identical transaction, sending 1 hbar to each of the created accounts, 115 // sent from the threshold Account 116 tx := hedera.NewTransferTransaction() 117 for _, account := range accounts { 118 tx.AddHbarTransfer(account, hedera.NewHbar(1)) 119 } 120 tx.AddHbarTransfer(thresholdAccount, hedera.NewHbar(3).Negated()) 121 122 tx, err := tx.FreezeWith(client) 123 if err != nil { 124 panic(fmt.Sprintf("%v : error while freezing transaction for client ", err)) 125 } 126 127 signedTransaction, err := tx.SignWithOperator(client) 128 if err != nil { 129 panic(fmt.Sprintf("%v : error while signing with operator client ", operator)) 130 } 131 132 scheduledTx, err := hedera.NewScheduleCreateTransaction(). 133 SetScheduledTransaction(signedTransaction) 134 if err != nil { 135 panic(fmt.Sprintf("%v : error while setting scheduled transaction with operator client", operator)) 136 } 137 138 scheduledTx = scheduledTx. 139 SetPayerAccountID(thresholdAccount) 140 141 response, err := scheduledTx.Execute(client) 142 if err != nil { 143 panic(fmt.Sprintf("%v : error while executing schedule create transaction with operator", operator)) 144 } 145 146 receipt, err := hedera.NewTransactionReceiptQuery(). 147 SetTransactionID(response.TransactionID). 148 SetNodeAccountIDs([]hedera.AccountID{response.NodeID}). 149 Execute(client) 150 if err != nil { 151 panic(fmt.Sprintf("%v : error while getting schedule create receipt transaction with operator", operator)) 152 } 153 154 fmt.Printf("operator [%s]: scheduleID = %v\n", operator, receipt.ScheduleID) 155 156 // Save the schedule ID, so that it can be asserted for each client submission 157 if scheduleID == nil { 158 scheduleID = receipt.ScheduleID 159 } 160 161 if scheduleID.String() != receipt.ScheduleID.String() { 162 panic("invalid generated schedule id, expected " + scheduleID.String() + ", got "+ receipt.ScheduleID.String()) 163 } 164 165 // If the status return by the receipt is related to already created, execute a schedule sign transaction 166 if receipt.Status == hedera.StatusIdenticalScheduleAlreadyCreated { 167 signTransaction, err := hedera.NewScheduleSignTransaction(). 168 SetNodeAccountIDs([]hedera.AccountID{createResponse.NodeID}). 169 SetScheduleID(*receipt.ScheduleID). 170 Execute(client) 171 172 if err != nil { 173 panic(fmt.Sprintf("%v : error while executing scheduled sign with operator", operator)) 174 } 175 176 _, err = signTransaction.GetReceipt(client) 177 if err != nil { 178 if err.Error() != "exceptional receipt status: SCHEDULE_ALREADY_EXECUTED" { 179 panic(fmt.Sprintf("%v : error while getting scheduled sign with operator ", operator)) 180 } 181 } 182 } 183 } 184 185 // Making sure the scheduled transaction executed properly with schedule info query 186 info, err := hedera.NewScheduleInfoQuery(). 187 SetScheduleID(*scheduleID). 188 SetNodeAccountIDs([]hedera.AccountID{createResponse.NodeID}). 189 Execute(client) 190 if err != nil { 191 panic(fmt.Sprintf("%v : error retrieving schedule info after signing", err)) 192 } 193 194 // Checking if the scheduled transaction was executed and signed, and retrieving the signatories 195 if !info.ExecutedAt.IsZero() { 196 println("Signing success, signed at: ", info.ExecutedAt.String()) 197 println("Signatories: ", info.Signatories.String()) 198 }else{ 199 panic("Signing failed") 200 } 201 }