github.com/hashgraph/hedera-sdk-go/v2@v2.48.0/examples/schedule_multisig_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 keys := make([]hedera.PrivateKey, 3) 36 pubKeys := make([]hedera.PublicKey, 3) 37 38 fmt.Println("threshold key example") 39 fmt.Println("Keys: ") 40 41 // Loop to generate keys for the KeyList 42 for i := range keys { 43 newKey, err := hedera.GeneratePrivateKey() 44 if err != nil { 45 panic(fmt.Sprintf("%v : error generating PrivateKey}", err)) 46 } 47 48 fmt.Printf("Key %v:\n", i) 49 fmt.Printf("private = %v\n", newKey) 50 fmt.Printf("public = %v\n", newKey.PublicKey()) 51 52 keys[i] = newKey 53 pubKeys[i] = newKey.PublicKey() 54 } 55 56 // A threshold key with a threshold of 2 and length of 3 requires 57 // at least 2 of the 3 keys to sign anything modifying the account 58 keyList := hedera.NewKeyList(). 59 AddAllPublicKeys(pubKeys) 60 61 // We are using all of these keys, so the scheduled transaction doesn't automatically go through 62 // It works perfectly fine with just one key 63 createResponse, err := hedera.NewAccountCreateTransaction(). 64 // The key that must sign each transfer out of the account. If receiverSigRequired is true, then 65 // it must also sign any transfer into the account. 66 SetKey(keyList). 67 SetInitialBalance(hedera.NewHbar(10)). 68 Execute(client) 69 if err != nil { 70 panic(fmt.Sprintf("%v : error executing create account transaction", err)) 71 } 72 73 // Make sure the transaction succeeded 74 transactionReceipt, err := createResponse.GetReceipt(client) 75 if err != nil { 76 panic(fmt.Sprintf("%v : error getting receipt", err)) 77 } 78 79 // Pre-generating transaction id for the scheduled transaction so we can track it 80 transactionID := hedera.TransactionIDGenerate(client.GetOperatorAccountID()) 81 82 println("transactionId for scheduled transaction = ", transactionID.String()) 83 84 // Not really necessary as its client.GetOperatorAccountID() 85 newAccountID := *transactionReceipt.AccountID 86 87 fmt.Printf("account = %v\n", newAccountID) 88 89 // Creating a non frozen transaction for the scheduled transaction 90 // In this case its TransferTransaction 91 transferTx := hedera.NewTransferTransaction(). 92 SetTransactionID(transactionID). 93 AddHbarTransfer(newAccountID, hedera.HbarFrom(-1, hedera.HbarUnits.Hbar)). 94 AddHbarTransfer(client.GetOperatorAccountID(), hedera.HbarFrom(1, hedera.HbarUnits.Hbar)) 95 96 // Scheduling it, this gives us hedera.ScheduleCreateTransaction 97 scheduled, err := transferTx.Schedule() 98 if err != nil { 99 panic(fmt.Sprintf("%v : error scheduling Transfer Transaction", err)) 100 } 101 102 // Executing the scheduled transaction 103 scheduleResponse, err := scheduled.Execute(client) 104 if err != nil { 105 panic(fmt.Sprintf("%v : error executing schedule create", err)) 106 } 107 108 // Make sure it executed successfully 109 scheduleReceipt, err := scheduleResponse.GetReceipt(client) 110 if err != nil { 111 panic(fmt.Sprintf("%v : error getting schedule create receipt", err)) 112 } 113 114 // Taking out the schedule ID 115 scheduleID := *scheduleReceipt.ScheduleID 116 117 // Using the schedule ID to get the schedule transaction info, which contains the whole scheduled transaction 118 info, err := hedera.NewScheduleInfoQuery(). 119 SetNodeAccountIDs([]hedera.AccountID{createResponse.NodeID}). 120 SetScheduleID(scheduleID). 121 Execute(client) 122 if err != nil { 123 panic(fmt.Sprintf("%v : error getting schedule info", err)) 124 } 125 126 // Taking out the TransferTransaction from earlier 127 transfer, err := info.GetScheduledTransaction() 128 if err != nil { 129 panic(fmt.Sprintf("%v : error getting transaction from schedule info", err)) 130 } 131 132 // Converting it from interface to hedera.TransferTransaction() and retrieving the amount of transfers 133 // to check if we have the right one, and that it's not empty 134 var transfers map[hedera.AccountID]hedera.Hbar 135 switch tx := transfer.(type) { 136 case *hedera.TransferTransaction: 137 transfers = tx.GetHbarTransfers() 138 } 139 140 if len(transfers) != 2 { 141 println("more transfers than expected") 142 } 143 144 // Checking if the Hbar values are correct 145 if transfers[newAccountID].AsTinybar() != -hedera.NewHbar(1).AsTinybar() { 146 println("transfer for ", newAccountID.String(), " is not whats is expected") 147 } 148 149 // Checking if the Hbar values are correct 150 if transfers[client.GetOperatorAccountID()].AsTinybar() != hedera.NewHbar(1).AsTinybar() { 151 println("transfer for ", client.GetOperatorAccountID().String(), " is not whats is expected") 152 } 153 154 println("sending schedule sign transaction") 155 156 // Creating a scheduled sign transaction, we have to sign with all of the keys in the KeyList 157 signTransaction, err := hedera.NewScheduleSignTransaction(). 158 SetNodeAccountIDs([]hedera.AccountID{createResponse.NodeID}). 159 SetScheduleID(scheduleID). 160 FreezeWith(client) 161 if err != nil { 162 panic(fmt.Sprintf("%v : error freezing sign transaction", err)) 163 } 164 165 // Signing the scheduled transaction 166 signTransaction.Sign(keys[0]) 167 signTransaction.Sign(keys[1]) 168 signTransaction.Sign(keys[2]) 169 170 resp, err := signTransaction.Execute(client) 171 if err != nil { 172 panic(fmt.Sprintf("%v : error executing schedule sign transaction", err)) 173 } 174 175 // Getting the receipt to make sure the signing executed properly 176 _, err = resp.GetReceipt(client) 177 if err != nil { 178 panic(fmt.Sprintf("%v : error executing schedule sign receipt", err)) 179 } 180 181 // Making sure the scheduled transaction executed properly with schedule info query 182 info, err = hedera.NewScheduleInfoQuery(). 183 SetScheduleID(scheduleID). 184 SetNodeAccountIDs([]hedera.AccountID{createResponse.NodeID}). 185 Execute(client) 186 if err != nil { 187 panic(fmt.Sprintf("%v : error retrieving schedule info after signing", err)) 188 } 189 190 // Checking if the scheduled transaction was executed and signed, and retrieving the signatories 191 if !info.ExecutedAt.IsZero() { 192 println("Singing success, signed at: ", info.ExecutedAt.String()) 193 println("Signatories: ", info.Signatories.String()) 194 }else{ 195 panic("Signing failed") 196 } 197 }