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  }