github.com/hashgraph/hedera-sdk-go/v2@v2.48.0/examples/transfer_tokens/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  	key1, err := hedera.GeneratePrivateKey()
    36  	if err != nil {
    37  		panic(fmt.Sprintf("%v : error generating PrivateKey", err))
    38  	}
    39  	key2, err := hedera.GeneratePrivateKey()
    40  	if err != nil {
    41  		panic(fmt.Sprintf("%v : error generating PrivateKey", err))
    42  	}
    43  
    44  	fmt.Printf("privateKey = %v\n", key1.String())
    45  	fmt.Printf("publicKey = %v\n", key1.PublicKey().String())
    46  	fmt.Printf("privateKey = %v\n", key2.String())
    47  	fmt.Printf("publicKey = %v\n", key2.PublicKey().String())
    48  
    49  	// Creating 2 accounts for transferring tokens
    50  	transactionResponse, err := hedera.NewAccountCreateTransaction().
    51  		// The key that must sign each transfer out of the account. If receiverSigRequired is true, then
    52  		// it must also sign any transfer into the account.
    53  		SetKey(key1.PublicKey()).
    54  		Execute(client)
    55  	if err != nil {
    56  		panic(fmt.Sprintf("%v : error creating account", err))
    57  	}
    58  
    59  	// First receipt with account ID 1, will error if transaction failed
    60  	transactionReceipt, err := transactionResponse.GetReceipt(client)
    61  	if err != nil {
    62  		panic(fmt.Sprintf("%v : error retrieving account creation receipt", err))
    63  	}
    64  
    65  	// Retrieving account ID out of the first receipt
    66  	accountID1 := *transactionReceipt.AccountID
    67  
    68  	fmt.Printf("account = %v\n", accountID1.String())
    69  
    70  	// Creating a new account for the token
    71  	transactionResponse, err = hedera.NewAccountCreateTransaction().
    72  		// The key that must sign each transfer out of the account. If receiverSigRequired is true, then
    73  		// it must also sign any transfer into the account.
    74  		SetKey(key2.PublicKey()).
    75  		Execute(client)
    76  	if err != nil {
    77  		panic(fmt.Sprintf("%v : error creating second account", err))
    78  	}
    79  
    80  	// Second receipt with account ID 2, will error if transaction failed
    81  	transactionReceipt, err = transactionResponse.GetReceipt(client)
    82  	if err != nil {
    83  		panic(fmt.Sprintf("%v : error retrieving second account creation receipt", err))
    84  	}
    85  
    86  	// Retrieving account ID out of the second receipt
    87  	accountID2 := *transactionReceipt.AccountID
    88  
    89  	fmt.Printf("account = %v\n", accountID2.String())
    90  
    91  	// Creating a new token
    92  	transactionResponse, err = hedera.NewTokenCreateTransaction().
    93  		// The publicly visible name of the token
    94  		SetTokenName("ffff").
    95  		// The publicly visible token symbol
    96  		SetTokenSymbol("F").
    97  		SetMaxTransactionFee(hedera.NewHbar(1000)).
    98  		SetNodeAccountIDs([]hedera.AccountID{transactionResponse.NodeID}).
    99  		// For tokens of type FUNGIBLE_COMMON - the number of decimal places a
   100  		// token is divisible by. For tokens of type NON_FUNGIBLE_UNIQUE - value
   101  		// must be 0
   102  		SetDecimals(3).
   103  		// Specifies the initial supply of tokens to be put in circulation. The
   104  		// initial supply is sent to the Treasury Account. The supply is in the
   105  		// lowest denomination possible. In the case for NON_FUNGIBLE_UNIQUE Type
   106  		// the value must be 0
   107  		SetInitialSupply(1000000).
   108  		// The account which will act as a treasury for the token. This account
   109  		// will receive the specified initial supply or the newly minted NFTs in
   110  		// the case for NON_FUNGIBLE_UNIQUE Type
   111  		SetTreasuryAccountID(client.GetOperatorAccountID()).
   112  		// The key which can perform update/delete operations on the token. If empty, the token can be
   113  		// perceived as immutable (not being able to be updated/deleted)
   114  		SetAdminKey(client.GetOperatorPublicKey()).
   115  		// The key which can sign to freeze or unfreeze an account for token transactions. If empty,
   116  		// freezing is not possible
   117  		SetFreezeKey(client.GetOperatorPublicKey()).
   118  		// The key which can wipe the token balance of an account. If empty, wipe is not possible
   119  		SetWipeKey(client.GetOperatorPublicKey()).
   120  		// The key which can grant or revoke KYC of an account for the token's transactions. If empty,
   121  		// KYC is not required, and KYC grant or revoke operations are not possible.
   122  		SetKycKey(client.GetOperatorPublicKey()).
   123  		// The key which can change the supply of a token. The key is used to sign Token Mint/Burn
   124  		// operations
   125  		SetSupplyKey(client.GetOperatorPublicKey()).
   126  		// The default Freeze status (frozen or unfrozen) of Hedera accounts relative to this token. If
   127  		// true, an account must be unfrozen before it can receive the token
   128  		SetFreezeDefault(false).
   129  		Execute(client)
   130  	if err != nil {
   131  		panic(fmt.Sprintf("%v : error creating token", err))
   132  	}
   133  
   134  	// Make sure the token create transaction ran
   135  	transactionReceipt, err = transactionResponse.GetReceipt(client)
   136  	if err != nil {
   137  		panic(fmt.Sprintf("%v : error retrieving token creation receipt", err))
   138  	}
   139  
   140  	// Retrieve the token out of the receipt
   141  	tokenID := *transactionReceipt.TokenID
   142  
   143  	fmt.Printf("token = %v\n", tokenID.String())
   144  
   145  	// Associating the token with the first account, so it can interact with the token
   146  	transaction, err := hedera.NewTokenAssociateTransaction().
   147  		// The account ID to be associated
   148  		SetAccountID(accountID1).
   149  		SetNodeAccountIDs([]hedera.AccountID{transactionResponse.NodeID}).
   150  		// The token ID that the account will be associated to
   151  		SetTokenIDs(tokenID).
   152  		FreezeWith(client)
   153  	if err != nil {
   154  		panic(fmt.Sprintf("%v : error freezing token associate transaction", err))
   155  	}
   156  
   157  	// Has to be signed by the account1's key
   158  	transactionResponse, err = transaction.
   159  		Sign(key1).
   160  		Execute(client)
   161  	if err != nil {
   162  		panic(fmt.Sprintf("%v : error associating token", err))
   163  	}
   164  
   165  	// Make sure the transaction succeeded
   166  	transactionReceipt, err = transactionResponse.GetReceipt(client)
   167  	if err != nil {
   168  		panic(fmt.Sprintf("%v : error retrieving token associate transaction receipt", err))
   169  	}
   170  
   171  	fmt.Printf("Associated account %v with token %v\n", accountID1.String(), tokenID.String())
   172  
   173  	// Associating the token with the first account, so it can interact with the token
   174  	transaction, err = hedera.NewTokenAssociateTransaction().
   175  		// The account ID to be associated
   176  		SetAccountID(accountID2).
   177  		SetNodeAccountIDs([]hedera.AccountID{transactionResponse.NodeID}).
   178  		// The token ID that the account will be associated to
   179  		SetTokenIDs(tokenID).
   180  		FreezeWith(client)
   181  	if err != nil {
   182  		panic(fmt.Sprintf("%v : error freezing token associate transaction", err))
   183  	}
   184  
   185  	// Has to be signed by the account1's key
   186  	transactionResponse, err = transaction.
   187  		Sign(key2).
   188  		Execute(client)
   189  	if err != nil {
   190  		panic(fmt.Sprintf("%v : error associating token", err))
   191  	}
   192  
   193  	// Make sure the transaction succeeded
   194  	transactionReceipt, err = transactionResponse.GetReceipt(client)
   195  	if err != nil {
   196  		panic(fmt.Sprintf("%v : error retrieving token associate transaction receipt", err))
   197  	}
   198  
   199  	fmt.Printf("Associated account %v with token %v\n", accountID2.String(), tokenID.String())
   200  
   201  	// This transaction grants Kyc to the first account
   202  	// Must be signed by the Token's kycKey.
   203  	transactionResponse, err = hedera.NewTokenGrantKycTransaction().
   204  		SetTokenID(tokenID).
   205  		SetNodeAccountIDs([]hedera.AccountID{transactionResponse.NodeID}).
   206  		// The account that KYC is being granted to
   207  		SetAccountID(accountID1).
   208  		// As the token kyc key is client.GetOperatorPublicKey(), we don't have to explicitly sign with anything
   209  		// as it's done automatically by execute for the operator
   210  		Execute(client)
   211  	if err != nil {
   212  		panic(fmt.Sprintf("%v : error granting kyc", err))
   213  	}
   214  
   215  	transactionReceipt, err = transactionResponse.GetReceipt(client)
   216  	if err != nil {
   217  		panic(fmt.Sprintf("%v : error retrieving grant kyc transaction receipt", err))
   218  	}
   219  
   220  	fmt.Printf("Granted KYC for account %v on token %v\n", accountID1.String(), tokenID.String())
   221  
   222  	// This transaction grants Kyc to the second account
   223  	transactionResponse, err = hedera.NewTokenGrantKycTransaction().
   224  		SetTokenID(tokenID).
   225  		SetNodeAccountIDs([]hedera.AccountID{transactionResponse.NodeID}).
   226  		// The account that KYC is being granted to
   227  		SetAccountID(accountID2).
   228  		// As the token kyc key is client.GetOperatorPublicKey(), we don't have to explicitly sign with anything
   229  		// as it's done automatically by execute for the operator
   230  		Execute(client)
   231  	if err != nil {
   232  		panic(fmt.Sprintf("%v : error granting kyc to second account", err))
   233  	}
   234  
   235  	// Make sure the transaction succeeded
   236  	transactionReceipt, err = transactionResponse.GetReceipt(client)
   237  	if err != nil {
   238  		panic(fmt.Sprintf("%v : error retrieving grant kyc transaction receipt", err))
   239  	}
   240  
   241  	fmt.Printf("Granted KYC for account %v on token %v\n", accountID2.String(), tokenID.String())
   242  
   243  	transactionResponse, err = hedera.NewTransferTransaction().
   244  		// Same as for Hbar transfer, token value has to be negated to denote they are being taken out
   245  		AddTokenTransfer(tokenID, client.GetOperatorAccountID(), -10).
   246  		// Same as for Hbar transfer, the 2 transfers here have to be equal, otherwise it will lead to an error
   247  		AddTokenTransfer(tokenID, accountID1, 10).
   248  		// We don't have to sign this one as we are transferring tokens from the operator
   249  		Execute(client)
   250  	if err != nil {
   251  		panic(fmt.Sprintf("%v : error transferring from operator to account1", err))
   252  	}
   253  
   254  	// Make sure the transaction succeeded
   255  	transactionReceipt, err = transactionResponse.GetReceipt(client)
   256  	if err != nil {
   257  		panic(fmt.Sprintf("%v : error retrieving transfer from operator to account1 receipt", err))
   258  	}
   259  
   260  	fmt.Printf(
   261  		"Sent 10 tokens from account %v to account %v on token %v\n",
   262  		client.GetOperatorAccountID().String(),
   263  		accountID1.String(),
   264  		tokenID.String(),
   265  	)
   266  
   267  	transferTransaction, err := hedera.NewTransferTransaction().
   268  		// 10 tokens from account 1
   269  		AddTokenTransfer(tokenID, accountID1, -10).
   270  		// 10 token to account 2
   271  		AddTokenTransfer(tokenID, accountID2, 10).
   272  		FreezeWith(client)
   273  	if err != nil {
   274  		panic(fmt.Sprintf("%v : error freezing transfer from account1 to account2", err))
   275  	}
   276  
   277  	// As we are now transferring tokens from accountID1 to accountID2, this has to be signed by accountID1's key
   278  	transferTransaction = transferTransaction.Sign(key1)
   279  
   280  	// Execute the transfer transaction
   281  	transactionResponse, err = transferTransaction.Execute(client)
   282  	if err != nil {
   283  		panic(fmt.Sprintf("%v : error transferring from account1 to account2", err))
   284  	}
   285  
   286  	// Make sure the transaction succeeded
   287  	transactionReceipt, err = transactionResponse.GetReceipt(client)
   288  	if err != nil {
   289  		panic(fmt.Sprintf("%v : error retrieving transfer from account1 to account2 receipt", err))
   290  	}
   291  
   292  	fmt.Printf(
   293  		"Sent 10 tokens from account %v to account %v on token %v\n",
   294  		accountID1.String(),
   295  		accountID2.String(),
   296  		tokenID.String(),
   297  	)
   298  
   299  	transferTransaction, err = hedera.NewTransferTransaction().
   300  		// 10 tokens from account 2
   301  		AddTokenTransfer(tokenID, accountID2, -10).
   302  		// 10 token to account 1
   303  		AddTokenTransfer(tokenID, accountID1, 10).
   304  		FreezeWith(client)
   305  	if err != nil {
   306  		panic(fmt.Sprintf("%v : error freezing transfer from account2 to account1", err))
   307  	}
   308  
   309  	// As we are now transferring tokens from accountID2 back to accountID1, this has to be signed by accountID2's key
   310  	transferTransaction = transferTransaction.Sign(key2)
   311  
   312  	// Executing the transfer transaction
   313  	transactionResponse, err = transferTransaction.Execute(client)
   314  	if err != nil {
   315  		panic(fmt.Sprintf("%v : error transferring from account2 to account1", err))
   316  	}
   317  
   318  	// Make sure the transaction succeeded
   319  	transactionReceipt, err = transactionResponse.GetReceipt(client)
   320  	if err != nil {
   321  		panic(fmt.Sprintf("%v : error retrieving transfer from account2 to account1 receipt", err))
   322  	}
   323  
   324  	fmt.Printf(
   325  		"Sent 10 tokens from account %v to account %v on token %v\n",
   326  		accountID2.String(),
   327  		accountID1.String(),
   328  		tokenID.String(),
   329  	)
   330  
   331  	// Clean up
   332  
   333  	// Now we can wipe the 10 tokens that are in possession of accountID1
   334  	// Has to be signed by wipe key of the token, in this case it was the operator key
   335  	transactionResponse, err = hedera.NewTokenWipeTransaction().
   336  		SetNodeAccountIDs([]hedera.AccountID{transactionResponse.NodeID}).
   337  		// From which account
   338  		SetAccountID(accountID1).
   339  		// For which token
   340  		SetTokenID(tokenID).
   341  		// How many
   342  		SetAmount(10).
   343  		Execute(client)
   344  	if err != nil {
   345  		panic(fmt.Sprintf("%v : error wiping from token", err))
   346  	}
   347  
   348  	// Make sure the transaction succeeded
   349  	_, err = transactionResponse.GetReceipt(client)
   350  	if err != nil {
   351  		panic(fmt.Sprintf("%v : error retrieving token wipe transaction receipt", err))
   352  	}
   353  
   354  	fmt.Printf("Wiped account %v on token %v\n", accountID1.String(), tokenID.String())
   355  
   356  	// Now to delete the token
   357  	// Has to be signed by admin key of the token, in this case it was the operator key
   358  	transactionResponse, err = hedera.NewTokenDeleteTransaction().
   359  		SetTokenID(tokenID).
   360  		SetNodeAccountIDs([]hedera.AccountID{transactionResponse.NodeID}).
   361  		Execute(client)
   362  	if err != nil {
   363  		panic(fmt.Sprintf("%v : error deleting token", err))
   364  	}
   365  
   366  	// Make sure the transaction succeeded
   367  	transactionReceipt, err = transactionResponse.GetReceipt(client)
   368  	if err != nil {
   369  		panic(fmt.Sprintf("%v : error retrieving token delete transaction receipt", err))
   370  	}
   371  
   372  	fmt.Printf("DeletedAt token %v\n", tokenID.String())
   373  
   374  	// Now that the tokens have been wiped from accountID1, we can safely delete it
   375  	accountDeleteTx, err := hedera.NewAccountDeleteTransaction().
   376  		SetAccountID(accountID1).
   377  		SetNodeAccountIDs([]hedera.AccountID{transactionResponse.NodeID}).
   378  		// Tp which account to transfer the account 1 balance
   379  		SetTransferAccountID(client.GetOperatorAccountID()).
   380  		FreezeWith(client)
   381  	if err != nil {
   382  		panic(fmt.Sprintf("%v : error freezing account delete transaction", err))
   383  	}
   384  
   385  	// Account deletion has to always be signed by the key for the account
   386  	transactionResponse, err = accountDeleteTx.
   387  		Sign(key1).
   388  		Execute(client)
   389  	if err != nil {
   390  		panic(fmt.Sprintf("%v : error deleting account 1", err))
   391  	}
   392  
   393  	// Make sure the transaction succeeded
   394  	transactionReceipt, err = transactionResponse.GetReceipt(client)
   395  	if err != nil {
   396  		panic(fmt.Sprintf("%v : error retrieving transfer transaction receipt", err))
   397  	}
   398  
   399  	fmt.Printf("DeletedAt account %v\n", accountID1.String())
   400  
   401  	accountDeleteTx, err = hedera.NewAccountDeleteTransaction().
   402  		SetAccountID(accountID2).
   403  		SetNodeAccountIDs([]hedera.AccountID{transactionResponse.NodeID}).
   404  		// Tp which account to transfer the account 2 balance
   405  		SetTransferAccountID(client.GetOperatorAccountID()).
   406  		FreezeWith(client)
   407  	if err != nil {
   408  		panic(fmt.Sprintf("%v : error freezing account delete transaction", err))
   409  	}
   410  
   411  	// Account deletion has to always be signed by the key for the account
   412  	transactionResponse, err = accountDeleteTx.
   413  		Sign(key2).
   414  		Execute(client)
   415  	if err != nil {
   416  		panic(fmt.Sprintf("%v : error deleting account2", err))
   417  	}
   418  
   419  	// Make sure the transaction succeeded
   420  	transactionReceipt, err = transactionResponse.GetReceipt(client)
   421  	if err != nil {
   422  		panic(fmt.Sprintf("%v : error retrieving account delete transaction receipt", err))
   423  	}
   424  
   425  	fmt.Printf("DeletedAt account %v\n", accountID2.String())
   426  }