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  }