From bad39649b4ec9810e67e4561313778695121b18f Mon Sep 17 00:00:00 2001 From: Exca-DK Date: Sat, 15 Feb 2025 00:17:49 +0100 Subject: [PATCH 1/2] Expose context flow to user --- client.go | 178 +++++++++--------- client_test.go | 115 +++++------ client_util.go | 5 +- examples/alternative_signing/main.go | 10 +- examples/external_signing/main.go | 10 +- examples/fungible_asset/main.go | 38 ++-- examples/multi_agent/main.go | 20 +- examples/offchain_multisig/main.go | 20 +- examples/onchain_multisig/main.go | 16 +- examples/performance_transaction/main.go | 12 +- .../sending_concurrent_transactions/main.go | 14 +- examples/sponsored_transaction/main.go | 33 ++-- examples/transfer_coin/main.go | 27 +-- faucet.go | 9 +- fungible_asset_client.go | 95 +++++----- indexerClient.go | 19 +- multisig.go | 10 +- nodeClient.go | 169 +++++++++-------- nodeClient_test.go | 6 +- transactionSubmission.go | 33 ++-- 20 files changed, 439 insertions(+), 400 deletions(-) diff --git a/client.go b/client.go index 9e07b7d..72aec09 100644 --- a/client.go +++ b/client.go @@ -1,6 +1,7 @@ package aptos import ( + "context" "fmt" "net/http" "time" @@ -105,10 +106,10 @@ type AptosRpcClient interface { RemoveHeader(key string) // Info Retrieves the node info about the network and it's current state - Info() (info NodeInfo, err error) + Info(ctx context.Context) (info NodeInfo, err error) // Account Retrieves information about the account such as [SequenceNumber] and [crypto.AuthenticationKey] - Account(address AccountAddress, ledgerVersion ...uint64) (info AccountInfo, err error) + Account(ctx context.Context, address AccountAddress, ledgerVersion ...uint64) (info AccountInfo, err error) // AccountResource Retrieves a single resource given its struct name. // @@ -119,7 +120,7 @@ type AptosRpcClient interface { // // address := AccountOne // dataMap, _ := client.AccountResource(address, "0x1::coin::CoinStore", 1) - AccountResource(address AccountAddress, resourceType string, ledgerVersion ...uint64) (data map[string]any, err error) + AccountResource(ctx context.Context, address AccountAddress, resourceType string, ledgerVersion ...uint64) (data map[string]any, err error) // AccountResources fetches resources for an account into a JSON-like map[string]any in AccountResourceInfo.Data // For fetching raw Move structs as BCS, See #AccountResourcesBCS @@ -131,10 +132,10 @@ type AptosRpcClient interface { // // address := AccountOne // dataMap, _ := client.AccountResource(address, 1) - AccountResources(address AccountAddress, ledgerVersion ...uint64) (resources []AccountResourceInfo, err error) + AccountResources(ctx context.Context, address AccountAddress, ledgerVersion ...uint64) (resources []AccountResourceInfo, err error) // AccountResourcesBCS fetches account resources as raw Move struct BCS blobs in AccountResourceRecord.Data []byte - AccountResourcesBCS(address AccountAddress, ledgerVersion ...uint64) (resources []AccountResourceRecord, err error) + AccountResourcesBCS(ctx context.Context, address AccountAddress, ledgerVersion ...uint64) (resources []AccountResourceRecord, err error) // BlockByHeight fetches a block by height // @@ -143,7 +144,7 @@ type AptosRpcClient interface { // Can also fetch with transactions // // block, _ := client.BlockByHeight(1, true) - BlockByHeight(blockHeight uint64, withTransactions bool) (data *api.Block, err error) + BlockByHeight(ctx context.Context, blockHeight uint64, withTransactions bool) (data *api.Block, err error) // BlockByVersion fetches a block by ledger version // @@ -152,7 +153,7 @@ type AptosRpcClient interface { // Can also fetch with transactions // // block, _ := client.BlockByVersion(123, true) - BlockByVersion(ledgerVersion uint64, withTransactions bool) (data *api.Block, err error) + BlockByVersion(ctx context.Context, ledgerVersion uint64, withTransactions bool) (data *api.Block, err error) // TransactionByHash gets info on a transaction // The transaction may be pending or recently committed. @@ -169,7 +170,7 @@ type AptosRpcClient interface { // // known to local mempool, but not committed yet // } // } - TransactionByHash(txnHash string) (data *api.Transaction, err error) + TransactionByHash(ctx context.Context, txnHash string) (data *api.Transaction, err error) // TransactionByVersion gets info on a transaction from its LedgerVersion. It must have been // committed to have a ledger version @@ -182,7 +183,7 @@ type AptosRpcClient interface { // } // } // } - TransactionByVersion(version uint64) (data *api.CommittedTransaction, err error) + TransactionByVersion(ctx context.Context, version uint64) (data *api.CommittedTransaction, err error) // PollForTransactions Waits up to 10 seconds for transactions to be done, polling at 10Hz // Accepts options PollPeriod and PollTimeout which should wrap time.Duration values. @@ -194,12 +195,12 @@ type AptosRpcClient interface { // // hashes := []string{"0x1234", "0x4567"} // err := client.PollForTransactions(hashes, PollPeriod(500 * time.Milliseconds), PollTimeout(5 * time.Seconds)) - PollForTransactions(txnHashes []string, options ...any) error + PollForTransactions(ctx context.Context, txnHashes []string, options ...any) error // WaitForTransaction Do a long-GET for one transaction and wait for it to complete // // data, err := client.WaitForTransaction("0x1234") - WaitForTransaction(txnHash string, options ...any) (data *api.UserTransaction, err error) + WaitForTransaction(ctx context.Context, txnHash string, options ...any) (data *api.UserTransaction, err error) // Transactions Get recent transactions. // Start is a version number. Nil for most recent transactions. @@ -207,7 +208,7 @@ type AptosRpcClient interface { // // client.Transactions(0, 2) // Returns 2 transactions // client.Transactions(1, 100) // Returns 100 transactions - Transactions(start *uint64, limit *uint64) (data []*api.CommittedTransaction, err error) + Transactions(ctx context.Context, start *uint64, limit *uint64) (data []*api.CommittedTransaction, err error) // AccountTransactions Get transactions associated with an account. // Start is a version number. Nil for most recent transactions. @@ -215,7 +216,7 @@ type AptosRpcClient interface { // // client.AccountTransactions(AccountOne, 0, 2) // Returns 2 transactions for 0x1 // client.AccountTransactions(AccountOne, 1, 100) // Returns 100 transactions for 0x1 - AccountTransactions(address AccountAddress, start *uint64, limit *uint64) (data []*api.CommittedTransaction, err error) + AccountTransactions(ctx context.Context, address AccountAddress, start *uint64, limit *uint64) (data []*api.CommittedTransaction, err error) // SubmitTransaction Submits an already signed transaction to the blockchain // @@ -237,7 +238,7 @@ type AptosRpcClient interface { // rawTxn, _ := client.BuildTransaction(sender.AccountAddress(), txnPayload) // signedTxn, _ := sender.SignTransaction(rawTxn) // submitResponse, err := client.SubmitTransaction(signedTxn) - SubmitTransaction(signedTransaction *SignedTransaction) (data *api.SubmitTransactionResponse, err error) + SubmitTransaction(ctx context.Context, signedTransaction *SignedTransaction) (data *api.SubmitTransactionResponse, err error) // BatchSubmitTransaction submits a collection of signed transactions to the network in a single request // @@ -262,7 +263,7 @@ type AptosRpcClient interface { // rawTxn, _ := client.BuildTransaction(sender.AccountAddress(), txnPayload) // signedTxn, _ := sender.SignTransaction(rawTxn) // submitResponse, err := client.BatchSubmitTransaction([]*SignedTransaction{signedTxn}) - BatchSubmitTransaction(signedTxns []*SignedTransaction) (response *api.BatchSubmitTransactionResponse, err error) + BatchSubmitTransaction(ctx context.Context, signedTxns []*SignedTransaction) (response *api.BatchSubmitTransactionResponse, err error) // SimulateTransaction Simulates a raw transaction without sending it to the blockchain // @@ -283,11 +284,11 @@ type AptosRpcClient interface { // } // rawTxn, _ := client.BuildTransaction(sender.AccountAddress(), txnPayload) // simResponse, err := client.SimulateTransaction(rawTxn, sender) - SimulateTransaction(rawTxn *RawTransaction, sender TransactionSigner, options ...any) (data []*api.UserTransaction, err error) + SimulateTransaction(ctx context.Context, rawTxn *RawTransaction, sender TransactionSigner, options ...any) (data []*api.UserTransaction, err error) // GetChainId Retrieves the ChainId of the network // Note this will be cached forever, or taken directly from the config - GetChainId() (chainId uint8, err error) + GetChainId(ctx context.Context) (chainId uint8, err error) // BuildTransaction Builds a raw transaction from the payload and fetches any necessary information from on-chain // @@ -307,7 +308,7 @@ type AptosRpcClient interface { // } // } // rawTxn, err := client.BuildTransaction(sender.AccountAddress(), txnPayload) - BuildTransaction(sender AccountAddress, payload TransactionPayload, options ...any) (rawTxn *RawTransaction, err error) + BuildTransaction(ctx context.Context, sender AccountAddress, payload TransactionPayload, options ...any) (rawTxn *RawTransaction, err error) // BuildTransactionMultiAgent Builds a raw transaction for MultiAgent or FeePayer from the payload and fetches any necessary information from on-chain // @@ -327,7 +328,7 @@ type AptosRpcClient interface { // } // } // rawTxn, err := client.BuildTransactionMultiAgent(sender.AccountAddress(), txnPayload, FeePayer(AccountZero)) - BuildTransactionMultiAgent(sender AccountAddress, payload TransactionPayload, options ...any) (rawTxn *RawTransactionWithData, err error) + BuildTransactionMultiAgent(ctx context.Context, sender AccountAddress, payload TransactionPayload, options ...any) (rawTxn *RawTransactionWithData, err error) // BuildSignAndSubmitTransaction Convenience function to do all three in one // for more configuration, please use them separately @@ -348,7 +349,7 @@ type AptosRpcClient interface { // } // } // submitResponse, err := client.BuildSignAndSubmitTransaction(sender, txnPayload) - BuildSignAndSubmitTransaction(sender TransactionSigner, payload TransactionPayload, options ...any) (data *api.SubmitTransactionResponse, err error) + BuildSignAndSubmitTransaction(ctx context.Context, sender TransactionSigner, payload TransactionPayload, options ...any) (data *api.SubmitTransactionResponse, err error) // View Runs a view function on chain returning a list of return values. // @@ -364,23 +365,23 @@ type AptosRpcClient interface { // } // vals, err := client.aptosClient.View(payload) // balance := StrToU64(vals.(any[])[0].(string)) - View(payload *ViewPayload, ledgerVersion ...uint64) (vals []any, err error) + View(ctx context.Context, payload *ViewPayload, ledgerVersion ...uint64) (vals []any, err error) // EstimateGasPrice Retrieves the gas estimate from the network. - EstimateGasPrice() (info EstimateGasInfo, err error) + EstimateGasPrice(ctx context.Context) (info EstimateGasInfo, err error) // AccountAPTBalance retrieves the APT balance in the account - AccountAPTBalance(address AccountAddress, ledgerVersion ...uint64) (uint64, error) + AccountAPTBalance(ctx context.Context, address AccountAddress, ledgerVersion ...uint64) (uint64, error) // NodeAPIHealthCheck checks if the node is within durationSecs of the current time, if not provided the node default is used - NodeAPIHealthCheck(durationSecs ...uint64) (api.HealthCheckResponse, error) + NodeAPIHealthCheck(ctx context.Context, durationSecs ...uint64) (api.HealthCheckResponse, error) } // AptosFaucetClient is an interface for all functionality on the Client that is Faucet related. Its main implementation // is [FaucetClient] type AptosFaucetClient interface { // Fund Uses the faucet to fund an address, only applies to non-production networks - Fund(address AccountAddress, amount uint64) error + Fund(ctx context.Context, address AccountAddress, amount uint64) error } // AptosIndexerClient is an interface for all functionality on the Client that is Indexer related. Its main implementation @@ -413,13 +414,13 @@ type AptosIndexerClient interface { // } // // return out, nil - QueryIndexer(query any, variables map[string]any, options ...graphql.Option) error + QueryIndexer(ctx context.Context, query any, variables map[string]any, options ...graphql.Option) error // GetProcessorStatus returns the ledger version up to which the processor has processed - GetProcessorStatus(processorName string) (uint64, error) + GetProcessorStatus(ctx context.Context, processorName string) (uint64, error) // GetCoinBalances gets the balances of all coins associated with a given address - GetCoinBalances(address AccountAddress) ([]CoinBalance, error) + GetCoinBalances(ctx context.Context, address AccountAddress) ([]CoinBalance, error) } // Client is a facade over the multiple types of underlying clients, as the user doesn't actually care where the data @@ -478,7 +479,7 @@ func NewClient(config NetworkConfig, options ...any) (client *Client, err error) // Fetch the chain Id if it isn't in the config if config.ChainId == 0 { - _, _ = nodeClient.GetChainId() + _, _ = nodeClient.GetChainId(context.Background()) } client = &Client{ @@ -489,13 +490,6 @@ func NewClient(config NetworkConfig, options ...any) (client *Client, err error) return } -// SetTimeout adjusts the HTTP client timeout -// -// client.SetTimeout(5 * time.Millisecond) -func (client *Client) SetTimeout(timeout time.Duration) { - client.nodeClient.SetTimeout(timeout) -} - // SetHeader sets the header for all future requests // // client.SetHeader("Authorization", "Bearer abcde") @@ -511,13 +505,13 @@ func (client *Client) RemoveHeader(key string) { } // Info Retrieves the node info about the network and it's current state -func (client *Client) Info() (info NodeInfo, err error) { - return client.nodeClient.Info() +func (client *Client) Info(ctx context.Context) (info NodeInfo, err error) { + return client.nodeClient.Info(ctx) } // Account Retrieves information about the account such as [SequenceNumber] and [crypto.AuthenticationKey] -func (client *Client) Account(address AccountAddress, ledgerVersion ...uint64) (info AccountInfo, err error) { - return client.nodeClient.Account(address, ledgerVersion...) +func (client *Client) Account(ctx context.Context, address AccountAddress, ledgerVersion ...uint64) (info AccountInfo, err error) { + return client.nodeClient.Account(ctx, address, ledgerVersion...) } // AccountResource Retrieves a single resource given its struct name. @@ -529,8 +523,8 @@ func (client *Client) Account(address AccountAddress, ledgerVersion ...uint64) ( // // address := AccountOne // dataMap, _ := client.AccountResource(address, "0x1::coin::CoinStore", 1) -func (client *Client) AccountResource(address AccountAddress, resourceType string, ledgerVersion ...uint64) (data map[string]any, err error) { - return client.nodeClient.AccountResource(address, resourceType, ledgerVersion...) +func (client *Client) AccountResource(ctx context.Context, address AccountAddress, resourceType string, ledgerVersion ...uint64) (data map[string]any, err error) { + return client.nodeClient.AccountResource(ctx, address, resourceType, ledgerVersion...) } // AccountResources fetches resources for an account into a JSON-like map[string]any in AccountResourceInfo.Data @@ -543,13 +537,13 @@ func (client *Client) AccountResource(address AccountAddress, resourceType strin // // address := AccountOne // dataMap, _ := client.AccountResource(address, 1) -func (client *Client) AccountResources(address AccountAddress, ledgerVersion ...uint64) (resources []AccountResourceInfo, err error) { - return client.nodeClient.AccountResources(address, ledgerVersion...) +func (client *Client) AccountResources(ctx context.Context, address AccountAddress, ledgerVersion ...uint64) (resources []AccountResourceInfo, err error) { + return client.nodeClient.AccountResources(ctx, address, ledgerVersion...) } // AccountResourcesBCS fetches account resources as raw Move struct BCS blobs in AccountResourceRecord.Data []byte -func (client *Client) AccountResourcesBCS(address AccountAddress, ledgerVersion ...uint64) (resources []AccountResourceRecord, err error) { - return client.nodeClient.AccountResourcesBCS(address, ledgerVersion...) +func (client *Client) AccountResourcesBCS(ctx context.Context, address AccountAddress, ledgerVersion ...uint64) (resources []AccountResourceRecord, err error) { + return client.nodeClient.AccountResourcesBCS(ctx, address, ledgerVersion...) } // BlockByHeight fetches a block by height @@ -559,8 +553,8 @@ func (client *Client) AccountResourcesBCS(address AccountAddress, ledgerVersion // Can also fetch with transactions // // block, _ := client.BlockByHeight(1, true) -func (client *Client) BlockByHeight(blockHeight uint64, withTransactions bool) (data *api.Block, err error) { - return client.nodeClient.BlockByHeight(blockHeight, withTransactions) +func (client *Client) BlockByHeight(ctx context.Context, blockHeight uint64, withTransactions bool) (data *api.Block, err error) { + return client.nodeClient.BlockByHeight(ctx, blockHeight, withTransactions) } // BlockByVersion fetches a block by ledger version @@ -570,8 +564,8 @@ func (client *Client) BlockByHeight(blockHeight uint64, withTransactions bool) ( // Can also fetch with transactions // // block, _ := client.BlockByVersion(123, true) -func (client *Client) BlockByVersion(ledgerVersion uint64, withTransactions bool) (data *api.Block, err error) { - return client.nodeClient.BlockByVersion(ledgerVersion, withTransactions) +func (client *Client) BlockByVersion(ctx context.Context, ledgerVersion uint64, withTransactions bool) (data *api.Block, err error) { + return client.nodeClient.BlockByVersion(ctx, ledgerVersion, withTransactions) } // TransactionByHash gets info on a transaction @@ -589,8 +583,8 @@ func (client *Client) BlockByVersion(ledgerVersion uint64, withTransactions bool // // known to local mempool, but not committed yet // } // } -func (client *Client) TransactionByHash(txnHash string) (data *api.Transaction, err error) { - return client.nodeClient.TransactionByHash(txnHash) +func (client *Client) TransactionByHash(ctx context.Context, txnHash string) (data *api.Transaction, err error) { + return client.nodeClient.TransactionByHash(ctx, txnHash) } // TransactionByVersion gets info on a transaction from its LedgerVersion. It must have been @@ -604,8 +598,8 @@ func (client *Client) TransactionByHash(txnHash string) (data *api.Transaction, // } // } // } -func (client *Client) TransactionByVersion(version uint64) (data *api.CommittedTransaction, err error) { - return client.nodeClient.TransactionByVersion(version) +func (client *Client) TransactionByVersion(ctx context.Context, version uint64) (data *api.CommittedTransaction, err error) { + return client.nodeClient.TransactionByVersion(ctx, version) } // PollForTransactions Waits up to 10 seconds for transactions to be done, polling at 10Hz @@ -618,15 +612,15 @@ func (client *Client) TransactionByVersion(version uint64) (data *api.CommittedT // // hashes := []string{"0x1234", "0x4567"} // err := client.PollForTransactions(hashes, PollPeriod(500 * time.Milliseconds), PollTimeout(5 * time.Seconds)) -func (client *Client) PollForTransactions(txnHashes []string, options ...any) error { - return client.nodeClient.PollForTransactions(txnHashes, options...) +func (client *Client) PollForTransactions(ctx context.Context, txnHashes []string, options ...any) error { + return client.nodeClient.PollForTransactions(ctx, txnHashes, options...) } // WaitForTransaction Do a long-GET for one transaction and wait for it to complete // // data, err := client.WaitForTransaction("0x1234") -func (client *Client) WaitForTransaction(txnHash string, options ...any) (data *api.UserTransaction, err error) { - return client.nodeClient.WaitForTransaction(txnHash, options...) +func (client *Client) WaitForTransaction(ctx context.Context, txnHash string, options ...any) (data *api.UserTransaction, err error) { + return client.nodeClient.WaitForTransaction(ctx, txnHash, options...) } // Transactions Get recent transactions. @@ -635,8 +629,8 @@ func (client *Client) WaitForTransaction(txnHash string, options ...any) (data * // // client.Transactions(0, 2) // Returns 2 transactions // client.Transactions(1, 100) // Returns 100 transactions -func (client *Client) Transactions(start *uint64, limit *uint64) (data []*api.CommittedTransaction, err error) { - return client.nodeClient.Transactions(start, limit) +func (client *Client) Transactions(ctx context.Context, start *uint64, limit *uint64) (data []*api.CommittedTransaction, err error) { + return client.nodeClient.Transactions(ctx, start, limit) } // AccountTransactions Get transactions associated with an account. @@ -645,8 +639,8 @@ func (client *Client) Transactions(start *uint64, limit *uint64) (data []*api.Co // // client.AccountTransactions(AccountOne, 0, 2) // Returns 2 transactions for 0x1 // client.AccountTransactions(AccountOne, 1, 100) // Returns 100 transactions for 0x1 -func (client *Client) AccountTransactions(address AccountAddress, start *uint64, limit *uint64) (data []*api.CommittedTransaction, err error) { - return client.nodeClient.AccountTransactions(address, start, limit) +func (client *Client) AccountTransactions(ctx context.Context, address AccountAddress, start *uint64, limit *uint64) (data []*api.CommittedTransaction, err error) { + return client.nodeClient.AccountTransactions(ctx, address, start, limit) } // SubmitTransaction Submits an already signed transaction to the blockchain @@ -669,8 +663,8 @@ func (client *Client) AccountTransactions(address AccountAddress, start *uint64, // rawTxn, _ := client.BuildTransaction(sender.AccountAddress(), txnPayload) // signedTxn, _ := sender.SignTransaction(rawTxn) // submitResponse, err := client.SubmitTransaction(signedTxn) -func (client *Client) SubmitTransaction(signedTransaction *SignedTransaction) (data *api.SubmitTransactionResponse, err error) { - return client.nodeClient.SubmitTransaction(signedTransaction) +func (client *Client) SubmitTransaction(ctx context.Context, signedTransaction *SignedTransaction) (data *api.SubmitTransactionResponse, err error) { + return client.nodeClient.SubmitTransaction(ctx, signedTransaction) } // BatchSubmitTransaction submits a collection of signed transactions to the network in a single request @@ -696,8 +690,8 @@ func (client *Client) SubmitTransaction(signedTransaction *SignedTransaction) (d // rawTxn, _ := client.BuildTransaction(sender.AccountAddress(), txnPayload) // signedTxn, _ := sender.SignTransaction(rawTxn) // submitResponse, err := client.BatchSubmitTransaction([]*SignedTransaction{signedTxn}) -func (client *Client) BatchSubmitTransaction(signedTxns []*SignedTransaction) (response *api.BatchSubmitTransactionResponse, err error) { - return client.nodeClient.BatchSubmitTransaction(signedTxns) +func (client *Client) BatchSubmitTransaction(ctx context.Context, signedTxns []*SignedTransaction) (response *api.BatchSubmitTransactionResponse, err error) { + return client.nodeClient.BatchSubmitTransaction(ctx, signedTxns) } // SimulateTransaction Simulates a raw transaction without sending it to the blockchain @@ -719,19 +713,19 @@ func (client *Client) BatchSubmitTransaction(signedTxns []*SignedTransaction) (r // } // rawTxn, _ := client.BuildTransaction(sender.AccountAddress(), txnPayload) // simResponse, err := client.SimulateTransaction(rawTxn, sender) -func (client *Client) SimulateTransaction(rawTxn *RawTransaction, sender TransactionSigner, options ...any) (data []*api.UserTransaction, err error) { - return client.nodeClient.SimulateTransaction(rawTxn, sender, options...) +func (client *Client) SimulateTransaction(ctx context.Context, rawTxn *RawTransaction, sender TransactionSigner, options ...any) (data []*api.UserTransaction, err error) { + return client.nodeClient.SimulateTransaction(ctx, rawTxn, sender, options...) } // GetChainId Retrieves the ChainId of the network // Note this will be cached forever, or taken directly from the config -func (client *Client) GetChainId() (chainId uint8, err error) { - return client.nodeClient.GetChainId() +func (client *Client) GetChainId(ctx context.Context) (chainId uint8, err error) { + return client.nodeClient.GetChainId(ctx) } // Fund Uses the faucet to fund an address, only applies to non-production networks -func (client *Client) Fund(address AccountAddress, amount uint64) error { - return client.faucetClient.Fund(address, amount) +func (client *Client) Fund(ctx context.Context, address AccountAddress, amount uint64) error { + return client.faucetClient.Fund(ctx, address, amount) } // BuildTransaction Builds a raw transaction from the payload and fetches any necessary information from on-chain @@ -752,8 +746,8 @@ func (client *Client) Fund(address AccountAddress, amount uint64) error { // } // } // rawTxn, err := client.BuildTransaction(sender.AccountAddress(), txnPayload) -func (client *Client) BuildTransaction(sender AccountAddress, payload TransactionPayload, options ...any) (rawTxn *RawTransaction, err error) { - return client.nodeClient.BuildTransaction(sender, payload, options...) +func (client *Client) BuildTransaction(ctx context.Context, sender AccountAddress, payload TransactionPayload, options ...any) (rawTxn *RawTransaction, err error) { + return client.nodeClient.BuildTransaction(ctx, sender, payload, options...) } // BuildTransactionMultiAgent Builds a raw transaction for MultiAgent or FeePayer from the payload and fetches any necessary information from on-chain @@ -774,8 +768,8 @@ func (client *Client) BuildTransaction(sender AccountAddress, payload Transactio // } // } // rawTxn, err := client.BuildTransactionMultiAgent(sender.AccountAddress(), txnPayload, FeePayer(AccountZero)) -func (client *Client) BuildTransactionMultiAgent(sender AccountAddress, payload TransactionPayload, options ...any) (rawTxn *RawTransactionWithData, err error) { - return client.nodeClient.BuildTransactionMultiAgent(sender, payload, options...) +func (client *Client) BuildTransactionMultiAgent(ctx context.Context, sender AccountAddress, payload TransactionPayload, options ...any) (rawTxn *RawTransactionWithData, err error) { + return client.nodeClient.BuildTransactionMultiAgent(ctx, sender, payload, options...) } // BuildSignAndSubmitTransaction Convenience function to do all three in one @@ -797,8 +791,8 @@ func (client *Client) BuildTransactionMultiAgent(sender AccountAddress, payload // } // } // submitResponse, err := client.BuildSignAndSubmitTransaction(sender, txnPayload) -func (client *Client) BuildSignAndSubmitTransaction(sender TransactionSigner, payload TransactionPayload, options ...any) (data *api.SubmitTransactionResponse, err error) { - return client.nodeClient.BuildSignAndSubmitTransaction(sender, payload, options...) +func (client *Client) BuildSignAndSubmitTransaction(ctx context.Context, sender TransactionSigner, payload TransactionPayload, options ...any) (data *api.SubmitTransactionResponse, err error) { + return client.nodeClient.BuildSignAndSubmitTransaction(ctx, sender, payload, options...) } // View Runs a view function on chain returning a list of return values. @@ -815,18 +809,18 @@ func (client *Client) BuildSignAndSubmitTransaction(sender TransactionSigner, pa // } // vals, err := client.aptosClient.View(payload) // balance := StrToU64(vals.(any[])[0].(string)) -func (client *Client) View(payload *ViewPayload, ledgerVersion ...uint64) (vals []any, err error) { - return client.nodeClient.View(payload, ledgerVersion...) +func (client *Client) View(ctx context.Context, payload *ViewPayload, ledgerVersion ...uint64) (vals []any, err error) { + return client.nodeClient.View(ctx, payload, ledgerVersion...) } // EstimateGasPrice Retrieves the gas estimate from the network. -func (client *Client) EstimateGasPrice() (info EstimateGasInfo, err error) { - return client.nodeClient.EstimateGasPrice() +func (client *Client) EstimateGasPrice(ctx context.Context) (info EstimateGasInfo, err error) { + return client.nodeClient.EstimateGasPrice(ctx) } // AccountAPTBalance retrieves the APT balance in the account -func (client *Client) AccountAPTBalance(address AccountAddress, ledgerVersion ...uint64) (uint64, error) { - return client.nodeClient.AccountAPTBalance(address, ledgerVersion...) +func (client *Client) AccountAPTBalance(ctx context.Context, address AccountAddress, ledgerVersion ...uint64) (uint64, error) { + return client.nodeClient.AccountAPTBalance(ctx, address, ledgerVersion...) } // QueryIndexer queries the indexer using GraphQL to fill the `query` struct with data. See examples in the indexer client on how to make queries @@ -855,21 +849,21 @@ func (client *Client) AccountAPTBalance(address AccountAddress, ledgerVersion .. // } // // return out, nil -func (client *Client) QueryIndexer(query any, variables map[string]any, options ...graphql.Option) error { - return client.indexerClient.Query(query, variables, options...) +func (client *Client) QueryIndexer(ctx context.Context, query any, variables map[string]any, options ...graphql.Option) error { + return client.indexerClient.Query(ctx, query, variables, options...) } // GetProcessorStatus returns the ledger version up to which the processor has processed -func (client *Client) GetProcessorStatus(processorName string) (uint64, error) { - return client.indexerClient.GetProcessorStatus(processorName) +func (client *Client) GetProcessorStatus(ctx context.Context, processorName string) (uint64, error) { + return client.indexerClient.GetProcessorStatus(ctx, processorName) } // GetCoinBalances gets the balances of all coins associated with a given address -func (client *Client) GetCoinBalances(address AccountAddress) ([]CoinBalance, error) { - return client.indexerClient.GetCoinBalances(address) +func (client *Client) GetCoinBalances(ctx context.Context, address AccountAddress) ([]CoinBalance, error) { + return client.indexerClient.GetCoinBalances(ctx, address) } // NodeAPIHealthCheck checks if the node is within durationSecs of the current time, if not provided the node default is used -func (client *Client) NodeAPIHealthCheck(durationSecs ...uint64) (api.HealthCheckResponse, error) { - return client.nodeClient.NodeAPIHealthCheck(durationSecs...) +func (client *Client) NodeAPIHealthCheck(ctx context.Context, durationSecs ...uint64) (api.HealthCheckResponse, error) { + return client.nodeClient.NodeAPIHealthCheck(ctx, durationSecs...) } diff --git a/client_test.go b/client_test.go index 89e10e9..67ce8de 100644 --- a/client_test.go +++ b/client_test.go @@ -1,6 +1,7 @@ package aptos import ( + "context" "strings" "sync" "testing" @@ -100,7 +101,7 @@ func setupIntegrationTest(t *testing.T, createAccount CreateSigner) (*Client, Tr assert.NoError(t, err) // Verify chain id retrieval works - chainId, err := client.GetChainId() + chainId, err := client.GetChainId(context.Background()) assert.NoError(t, err) if testConfig == DevnetConfig { assert.Greater(t, chainId, LocalnetConfig.ChainId) @@ -109,7 +110,7 @@ func setupIntegrationTest(t *testing.T, createAccount CreateSigner) (*Client, Tr } // Verify gas estimation works - _, err = client.EstimateGasPrice() + _, err = client.EstimateGasPrice(context.Background()) assert.NoError(t, err) // Create an account @@ -117,7 +118,7 @@ func setupIntegrationTest(t *testing.T, createAccount CreateSigner) (*Client, Tr assert.NoError(t, err) // Fund the account with 1 APT - err = client.Fund(account.AccountAddress(), fundAmount) + err = client.Fund(context.Background(), account.AccountAddress(), fundAmount) assert.NoError(t, err) return client, account @@ -135,17 +136,17 @@ func testTransaction(t *testing.T, createAccount CreateSigner, buildTransaction assert.NoError(t, err) // Send transaction - result, err := client.SubmitTransaction(signedTxn) + result, err := client.SubmitTransaction(context.Background(), signedTxn) assert.NoError(t, err) hash := result.Hash // Wait for the transaction - _, err = client.WaitForTransaction(hash) + _, err = client.WaitForTransaction(context.Background(), hash) assert.NoError(t, err) // Read transaction by hash - txn, err := client.TransactionByHash(hash) + txn, err := client.TransactionByHash(context.Background(), hash) assert.NoError(t, err) // Read transaction by version @@ -153,7 +154,7 @@ func testTransaction(t *testing.T, createAccount CreateSigner, buildTransaction version := userTxn.Version // Load the transaction again - txnByVersion, err := client.TransactionByVersion(version) + txnByVersion, err := client.TransactionByVersion(context.Background(), version) assert.NoError(t, err) // Assert that both are the same @@ -170,7 +171,7 @@ func testTransactionSimulation(t *testing.T, createAccount CreateSigner, buildTr // Simulate transaction (no options) rawTxn, err := buildTransaction(client, account) assert.NoError(t, err) - simulatedTxn, err := client.SimulateTransaction(rawTxn, account) + simulatedTxn, err := client.SimulateTransaction(context.Background(), rawTxn, account) switch account.(type) { case *MultiKeyTestSigner: // multikey simulation currently not supported @@ -187,7 +188,7 @@ func testTransactionSimulation(t *testing.T, createAccount CreateSigner, buildTr // simulate transaction (estimate gas unit price) rawTxnZeroGasUnitPrice, err := buildTransaction(client, account, GasUnitPrice(0)) assert.NoError(t, err) - simulatedTxn, err = client.SimulateTransaction(rawTxnZeroGasUnitPrice, account, EstimateGasUnitPrice(true)) + simulatedTxn, err = client.SimulateTransaction(context.Background(), rawTxnZeroGasUnitPrice, account, EstimateGasUnitPrice(true)) assert.NoError(t, err) assert.Equal(t, true, simulatedTxn[0].Success) assert.Equal(t, vmStatusSuccess, simulatedTxn[0].VmStatus) @@ -197,7 +198,7 @@ func testTransactionSimulation(t *testing.T, createAccount CreateSigner, buildTr // simulate transaction (estimate max gas amount) rawTxnZeroMaxGasAmount, err := buildTransaction(client, account, MaxGasAmount(0)) assert.NoError(t, err) - simulatedTxn, err = client.SimulateTransaction(rawTxnZeroMaxGasAmount, account, EstimateMaxGasAmount(true)) + simulatedTxn, err = client.SimulateTransaction(context.Background(), rawTxnZeroMaxGasAmount, account, EstimateMaxGasAmount(true)) assert.NoError(t, err) assert.Equal(t, true, simulatedTxn[0].Success) assert.Equal(t, vmStatusSuccess, simulatedTxn[0].VmStatus) @@ -206,7 +207,7 @@ func testTransactionSimulation(t *testing.T, createAccount CreateSigner, buildTr // simulate transaction (estimate prioritized gas unit price and max gas amount) rawTxnZeroGasConfig, err := buildTransaction(client, account, GasUnitPrice(0), MaxGasAmount(0)) assert.NoError(t, err) - simulatedTxn, err = client.SimulateTransaction(rawTxnZeroGasConfig, account, EstimatePrioritizedGasUnitPrice(true), EstimateMaxGasAmount(true)) + simulatedTxn, err = client.SimulateTransaction(context.Background(), rawTxnZeroGasConfig, account, EstimatePrioritizedGasUnitPrice(true), EstimateMaxGasAmount(true)) assert.NoError(t, err) assert.Equal(t, true, simulatedTxn[0].Success) assert.Equal(t, vmStatusSuccess, simulatedTxn[0].VmStatus) @@ -223,12 +224,12 @@ func TestAPTTransferTransaction(t *testing.T) { client, err := createTestClient() assert.NoError(t, err) - signedTxn, err := APTTransferTransaction(client, sender, dest.Address, 1337, MaxGasAmount(123123), GasUnitPrice(111), ExpirationSeconds(42), ChainIdOption(71), SequenceNumber(31337)) + signedTxn, err := APTTransferTransaction(context.Background(), client, sender, dest.Address, 1337, MaxGasAmount(123123), GasUnitPrice(111), ExpirationSeconds(42), ChainIdOption(71), SequenceNumber(31337)) assert.NoError(t, err) assert.NotNil(t, signedTxn) // use defaults for: max gas amount, gas unit price - signedTxn, err = APTTransferTransaction(client, sender, dest.Address, 1337, ExpirationSeconds(42), ChainIdOption(71), SequenceNumber(31337)) + signedTxn, err = APTTransferTransaction(context.Background(), client, sender, dest.Address, 1337, ExpirationSeconds(42), ChainIdOption(71), SequenceNumber(31337)) assert.NoError(t, err) assert.NotNil(t, signedTxn) } @@ -241,14 +242,14 @@ func Test_Indexer(t *testing.T) { account, err := NewEd25519Account() assert.NoError(t, err) - err = client.Fund(account.AccountAddress(), 10) + err = client.Fund(context.Background(), account.AccountAddress(), 10) assert.NoError(t, err) - balance, err := client.AccountAPTBalance(account.AccountAddress()) + balance, err := client.AccountAPTBalance(context.Background(), account.AccountAddress()) assert.NoError(t, err) // TODO: May need to wait on indexer for this one - coins, err := client.GetCoinBalances(account.AccountAddress()) + coins, err := client.GetCoinBalances(context.Background(), account.AccountAddress()) assert.NoError(t, err) switch len(coins) { case 0: @@ -265,7 +266,7 @@ func Test_Indexer(t *testing.T) { } // Get current version - status, err := client.GetProcessorStatus("default_processor") + status, err := client.GetProcessorStatus(context.Background(), "default_processor") assert.NoError(t, err) // TODO: When we have waiting on indexer, we can add this check to be more accurate assert.GreaterOrEqual(t, status, uint64(0)) @@ -275,7 +276,7 @@ func Test_Genesis(t *testing.T) { client, err := createTestClient() assert.NoError(t, err) - genesis, err := client.BlockByHeight(0, true) + genesis, err := client.BlockByHeight(context.Background(), 0, true) assert.NoError(t, err) txn, err := genesis.Transactions[0].GenesisTransaction() @@ -287,7 +288,7 @@ func Test_Genesis(t *testing.T) { func Test_Block(t *testing.T) { client, err := createTestClient() assert.NoError(t, err) - info, err := client.Info() + info, err := client.Info(context.Background()) assert.NoError(t, err) // TODO: I need to add hardcoded testing sets for these conversions @@ -300,7 +301,7 @@ func Test_Block(t *testing.T) { for i := uint64(0); i < numToCheck; i++ { go func() { blockNumber := blockHeight - i - blockByHeight, err := client.BlockByHeight(blockNumber, true) + blockByHeight, err := client.BlockByHeight(context.Background(), blockNumber, true) assert.NoError(t, err) assert.Equal(t, blockNumber, blockByHeight.BlockHeight) @@ -309,7 +310,7 @@ func Test_Block(t *testing.T) { assert.Equal(t, 1+blockByHeight.LastVersion-blockByHeight.FirstVersion, uint64(len(blockByHeight.Transactions))) // Version should be the same - blockByVersion, err := client.BlockByVersion(blockByHeight.FirstVersion, true) + blockByVersion, err := client.BlockByVersion(context.Background(), blockByHeight.FirstVersion, true) assert.NoError(t, err) assert.Equal(t, blockByHeight, blockByVersion) @@ -323,7 +324,7 @@ func Test_Block(t *testing.T) { func Test_Account(t *testing.T) { client, err := createTestClient() assert.NoError(t, err) - account, err := client.Account(AccountOne) + account, err := client.Account(context.Background(), AccountOne) assert.NoError(t, err) sequenceNumber, err := account.SequenceNumber() assert.NoError(t, err) @@ -340,22 +341,22 @@ func Test_Transactions(t *testing.T) { start := uint64(1) count := uint64(2) // Specific 2 should only give 2 - transactions, err := client.Transactions(&start, &count) + transactions, err := client.Transactions(context.Background(), &start, &count) assert.NoError(t, err) assert.Len(t, transactions, 2) // This will give the latest 2 - transactions, err = client.Transactions(nil, &count) + transactions, err = client.Transactions(context.Background(), nil, &count) assert.NoError(t, err) assert.Len(t, transactions, 2) // This will give the 25 from 2 - transactions, err = client.Transactions(&start, nil) + transactions, err = client.Transactions(context.Background(), &start, nil) assert.NoError(t, err) assert.Len(t, transactions, 25) // This will give the latest 25 - transactions, err = client.Transactions(nil, nil) + transactions, err = client.Transactions(context.Background(), nil, nil) assert.NoError(t, err) assert.Len(t, transactions, 25) } @@ -363,13 +364,13 @@ func Test_Transactions(t *testing.T) { func submitAccountTransaction(t *testing.T, client *Client, account *Account, seqNo uint64) { payload, err := CoinTransferPayload(nil, AccountOne, 1) assert.NoError(t, err) - rawTxn, err := client.BuildTransaction(account.AccountAddress(), TransactionPayload{Payload: payload}, SequenceNumber(seqNo)) + rawTxn, err := client.BuildTransaction(context.Background(), account.AccountAddress(), TransactionPayload{Payload: payload}, SequenceNumber(seqNo)) assert.NoError(t, err) signedTxn, err := rawTxn.SignedTransaction(account) assert.NoError(t, err) - txn, err := client.SubmitTransaction(signedTxn) + txn, err := client.SubmitTransaction(context.Background(), signedTxn) assert.NoError(t, err) - _, err = client.WaitForTransaction(txn.Hash) + _, err = client.WaitForTransaction(context.Background(), txn.Hash) assert.NoError(t, err) } @@ -381,7 +382,7 @@ func Test_AccountTransactions(t *testing.T) { // Create a bunch of transactions so we can test the pagination account, err := NewEd25519Account() assert.NoError(t, err) - err = client.Fund(account.AccountAddress(), 100_000_000) + err = client.Fund(context.Background(), account.AccountAddress(), 100_000_000) assert.NoError(t, err) // Build and submit 100 transactions @@ -400,7 +401,7 @@ func Test_AccountTransactions(t *testing.T) { submitAccountTransaction(t, client, account, 100) // Fetch default - transactions, err := client.AccountTransactions(account.AccountAddress(), nil, nil) + transactions, err := client.AccountTransactions(context.Background(), account.AccountAddress(), nil, nil) assert.NoError(t, err) assert.Len(t, transactions, 25) @@ -410,69 +411,69 @@ func Test_AccountTransactions(t *testing.T) { ten := uint64(10) hundredOne := uint64(101) - transactions, err = client.AccountTransactions(account.AccountAddress(), nil, &hundredOne) + transactions, err = client.AccountTransactions(context.Background(), account.AccountAddress(), nil, &hundredOne) assert.NoError(t, err) assert.Len(t, transactions, 101) // Fetch 101 with start - transactions, err = client.AccountTransactions(account.AccountAddress(), &zero, &hundredOne) + transactions, err = client.AccountTransactions(context.Background(), account.AccountAddress(), &zero, &hundredOne) assert.NoError(t, err) assert.Len(t, transactions, 101) // Fetch 100 from 1 - transactions, err = client.AccountTransactions(account.AccountAddress(), &one, &hundredOne) + transactions, err = client.AccountTransactions(context.Background(), account.AccountAddress(), &one, &hundredOne) assert.NoError(t, err) assert.Len(t, transactions, 100) // Fetch default from 0 - transactions, err = client.AccountTransactions(account.AccountAddress(), &zero, nil) + transactions, err = client.AccountTransactions(context.Background(), account.AccountAddress(), &zero, nil) assert.NoError(t, err) assert.Len(t, transactions, 25) // Check global transactions API t.Run("Default transaction size, no start", func(t *testing.T) { - transactions, err = client.Transactions(nil, nil) + transactions, err = client.Transactions(context.Background(), nil, nil) assert.NoError(t, err) assert.Len(t, transactions, 25) }) t.Run("Default transaction size, start from zero", func(t *testing.T) { - transactions, err = client.Transactions(&zero, nil) + transactions, err = client.Transactions(context.Background(), &zero, nil) assert.NoError(t, err) assert.Len(t, transactions, 25) }) t.Run("Default transaction size, start from one", func(t *testing.T) { - transactions, err = client.Transactions(&one, nil) + transactions, err = client.Transactions(context.Background(), &one, nil) assert.NoError(t, err) assert.Len(t, transactions, 25) }) t.Run("101 transactions, no start", func(t *testing.T) { - transactions, err = client.Transactions(nil, &hundredOne) + transactions, err = client.Transactions(context.Background(), nil, &hundredOne) assert.NoError(t, err) assert.Len(t, transactions, 101) }) t.Run("101 transactions, start zero", func(t *testing.T) { - transactions, err = client.Transactions(&zero, &hundredOne) + transactions, err = client.Transactions(context.Background(), &zero, &hundredOne) assert.NoError(t, err) assert.Len(t, transactions, 101) }) t.Run("101 transactions, start one", func(t *testing.T) { - transactions, err = client.Transactions(&one, &hundredOne) + transactions, err = client.Transactions(context.Background(), &one, &hundredOne) assert.NoError(t, err) assert.Len(t, transactions, 101) }) t.Run("10 transactions, no start", func(t *testing.T) { - transactions, err = client.Transactions(nil, &ten) + transactions, err = client.Transactions(context.Background(), nil, &ten) assert.NoError(t, err) assert.Len(t, transactions, 10) }) t.Run("10 transactions, start one", func(t *testing.T) { - transactions, err = client.Transactions(&one, &ten) + transactions, err = client.Transactions(context.Background(), &one, &ten) assert.NoError(t, err) assert.Len(t, transactions, 10) }) @@ -482,7 +483,7 @@ func Test_Info(t *testing.T) { client, err := createTestClient() assert.NoError(t, err) - info, err := client.Info() + info, err := client.Info(context.Background()) assert.NoError(t, err) assert.Greater(t, info.BlockHeight(), uint64(0)) } @@ -491,11 +492,11 @@ func Test_AccountResources(t *testing.T) { client, err := createTestClient() assert.NoError(t, err) - resources, err := client.AccountResources(AccountOne) + resources, err := client.AccountResources(context.Background(), AccountOne) assert.NoError(t, err) assert.Greater(t, len(resources), 0) - resourcesBcs, err := client.AccountResourcesBCS(AccountOne) + resourcesBcs, err := client.AccountResourcesBCS(context.Background(), AccountOne) assert.NoError(t, err) assert.Greater(t, len(resourcesBcs), 0) } @@ -516,7 +517,7 @@ func concurrentTxnWaiter( responseCount++ assert.NoError(t, response.Err) - waitResponse, err := client.WaitForTransaction(response.Response.Hash, PollTimeout(21*time.Second)) + waitResponse, err := client.WaitForTransaction(context.Background(), response.Response.Hash, PollTimeout(21*time.Second)) if err != nil { t.Logf("%s err %s", response.Response.Hash, err) } else if waitResponse == nil { @@ -544,15 +545,15 @@ func Test_Concurrent_Submission(t *testing.T) { account2, err := NewEd25519Account() assert.NoError(t, err) - err = client.Fund(account1.AccountAddress(), 100_000_000) + err = client.Fund(context.Background(), account1.AccountAddress(), 100_000_000) assert.NoError(t, err) - err = client.Fund(account2.AccountAddress(), 0) + err = client.Fund(context.Background(), account2.AccountAddress(), 0) assert.NoError(t, err) // start submission goroutine payloads := make(chan TransactionBuildPayload, 50) results := make(chan TransactionSubmissionResponse, 50) - go client.BuildSignAndSubmitTransactions(account1, payloads, results, ExpirationSeconds(20)) + go client.BuildSignAndSubmitTransactions(context.Background(), account1, payloads, results, ExpirationSeconds(20)) transferPayload, err := CoinTransferPayload(nil, AccountOne, 100) assert.NoError(t, err) @@ -638,7 +639,7 @@ func TestClient_View(t *testing.T) { ArgTypes: []TypeTag{AptosCoinTypeTag}, Args: [][]byte{AccountOne[:]}, } - vals, err := client.View(payload) + vals, err := client.View(context.Background(), payload) assert.NoError(t, err) assert.Len(t, vals, 1) _, err = StrToUint64(vals[0].(string)) @@ -649,7 +650,7 @@ func TestClient_BlockByHeight(t *testing.T) { client, err := createTestClient() assert.NoError(t, err) - _, err = client.BlockByHeight(1, true) + _, err = client.BlockByHeight(context.Background(), 1, true) assert.NoError(t, err) } @@ -659,7 +660,7 @@ func TestClient_NodeAPIHealthCheck(t *testing.T) { t.Run("Node API health check default", func(t *testing.T) { t.Parallel() - response, err := client.NodeAPIHealthCheck() + response, err := client.NodeAPIHealthCheck(context.Background()) assert.NoError(t, err) assert.True(t, strings.Contains(response.Message, "ok"), "Node API health check failed"+response.Message) }) @@ -667,7 +668,7 @@ func TestClient_NodeAPIHealthCheck(t *testing.T) { // Now, check node API health check with a future time that should never fail t.Run("Node API health check far future", func(t *testing.T) { t.Parallel() - response, err := client.NodeAPIHealthCheck(10000) + response, err := client.NodeAPIHealthCheck(context.Background(), 10000) assert.NoError(t, err) assert.True(t, strings.Contains(response.Message, "ok"), "Node API health check failed"+response.Message) }) @@ -676,13 +677,13 @@ func TestClient_NodeAPIHealthCheck(t *testing.T) { t.Run("Node API health check fail", func(t *testing.T) { t.Parallel() // Now, check node API health check with a time that should probably fail - _, err := client.NodeAPIHealthCheck(0) + _, err := client.NodeAPIHealthCheck(context.Background(), 0) assert.Error(t, err) }) } func buildSingleSignerEntryFunction(client *Client, sender TransactionSigner, options ...any) (*RawTransaction, error) { - return APTTransferTransaction(client, sender, AccountOne, 100, options...) + return APTTransferTransaction(context.Background(), client, sender, AccountOne, 100, options...) } func buildSingleSignerScript(client *Client, sender TransactionSigner, options ...any) (*RawTransaction, error) { @@ -694,7 +695,7 @@ func buildSingleSignerScript(client *Client, sender TransactionSigner, options . amount := uint64(1) dest := AccountOne - rawTxn, err := client.BuildTransaction(sender.AccountAddress(), + rawTxn, err := client.BuildTransaction(context.Background(), sender.AccountAddress(), TransactionPayload{Payload: &Script{ Code: scriptBytes, ArgTypes: []TypeTag{}, diff --git a/client_util.go b/client_util.go index e61a118..fd3b08f 100644 --- a/client_util.go +++ b/client_util.go @@ -1,6 +1,7 @@ package aptos import ( + "context" "fmt" "net/url" "runtime/debug" @@ -53,13 +54,13 @@ func init() { // // options may be: MaxGasAmount, GasUnitPrice, ExpirationSeconds, ValidUntil, SequenceNumber, ChainIdOption // deprecated, please use the EntryFunction APIs -func APTTransferTransaction(client *Client, sender TransactionSigner, dest AccountAddress, amount uint64, options ...any) (rawTxn *RawTransaction, err error) { +func APTTransferTransaction(ctx context.Context, client *Client, sender TransactionSigner, dest AccountAddress, amount uint64, options ...any) (rawTxn *RawTransaction, err error) { entryFunction, err := CoinTransferPayload(nil, dest, amount) if err != nil { return nil, err } - rawTxn, err = client.BuildTransaction(sender.AccountAddress(), + rawTxn, err = client.BuildTransaction(ctx, sender.AccountAddress(), TransactionPayload{Payload: entryFunction}, options...) return } diff --git a/examples/alternative_signing/main.go b/examples/alternative_signing/main.go index eb484c4..ddad3ec 100644 --- a/examples/alternative_signing/main.go +++ b/examples/alternative_signing/main.go @@ -2,7 +2,9 @@ package main import ( + "context" "fmt" + "github.com/aptos-labs/aptos-go-sdk" "github.com/aptos-labs/aptos-go-sdk/crypto" "golang.org/x/crypto/ed25519" @@ -90,7 +92,7 @@ func example(network aptos.NetworkConfig) { } // Fund the sender with the faucet to create it on-chain - err = client.Fund(sender.Address, 100_000_000) + err = client.Fund(context.Background(), sender.Address, 100_000_000) fmt.Printf("We fund the signer account %s with the faucet\n", sender.Address.String()) // Prep arguments @@ -102,7 +104,7 @@ func example(network aptos.NetworkConfig) { amount := uint64(100) // Build transaction - rawTxn, err := aptos.APTTransferTransaction(client, sender, receiver, amount) + rawTxn, err := aptos.APTTransferTransaction(context.Background(), client, sender, receiver, amount) if err != nil { panic("Failed to build transaction:" + err.Error()) } @@ -115,7 +117,7 @@ func example(network aptos.NetworkConfig) { fmt.Printf("Submit a coin transfer to address %s\n", receiver.String()) // Submit and wait for it to complete - submitResult, err := client.SubmitTransaction(signedTxn) + submitResult, err := client.SubmitTransaction(context.Background(), signedTxn) if err != nil { panic("Failed to submit transaction:" + err.Error()) } @@ -123,7 +125,7 @@ func example(network aptos.NetworkConfig) { // Wait for the transaction fmt.Printf("And we wait for the transaction %s to complete...\n", txnHash) - userTxn, err := client.WaitForTransaction(txnHash) + userTxn, err := client.WaitForTransaction(context.Background(), txnHash) if err != nil { panic("Failed to wait for transaction:" + err.Error()) } diff --git a/examples/external_signing/main.go b/examples/external_signing/main.go index 1229ec1..d468c84 100644 --- a/examples/external_signing/main.go +++ b/examples/external_signing/main.go @@ -2,7 +2,9 @@ package main import ( + "context" "fmt" + "github.com/aptos-labs/aptos-go-sdk" "github.com/aptos-labs/aptos-go-sdk/crypto" "golang.org/x/crypto/ed25519" @@ -91,7 +93,7 @@ func example(networkConfig aptos.NetworkConfig) { } // Fund the sender with the faucet to create it on-chain - err = client.Fund(sender.Address, 100_000_000) + err = client.Fund(context.Background(), sender.Address, 100_000_000) fmt.Printf("We fund the signer account %s with the faucet\n", sender.Address.String()) // Prep arguments @@ -108,7 +110,7 @@ func example(networkConfig aptos.NetworkConfig) { // Sign transaction fmt.Printf("Submit a coin transfer to address %s\n", receiver.String()) - rawTxn, err := client.BuildTransaction(sender.Address, + rawTxn, err := client.BuildTransaction(context.Background(), sender.Address, aptos.TransactionPayload{Payload: payload}, ) if err != nil { @@ -139,7 +141,7 @@ func example(networkConfig aptos.NetworkConfig) { // TODO: Show how to send over a wire with an encoding // Submit and wait for it to complete - submitResult, err := client.SubmitTransaction(signedTxn) + submitResult, err := client.SubmitTransaction(context.Background(), signedTxn) if err != nil { panic("Failed to submit transaction:" + err.Error()) } @@ -147,7 +149,7 @@ func example(networkConfig aptos.NetworkConfig) { // Wait for the transaction fmt.Printf("And we wait for the transaction %s to complete...\n", txnHash) - userTxn, err := client.WaitForTransaction(txnHash) + userTxn, err := client.WaitForTransaction(context.Background(), txnHash) if err != nil { panic("Failed to wait for transaction:" + err.Error()) } diff --git a/examples/fungible_asset/main.go b/examples/fungible_asset/main.go index 09c8c3c..f606ef4 100644 --- a/examples/fungible_asset/main.go +++ b/examples/fungible_asset/main.go @@ -2,8 +2,10 @@ package main import ( + "context" "encoding/json" "fmt" + "github.com/aptos-labs/aptos-go-sdk" "github.com/aptos-labs/aptos-go-sdk/bcs" "github.com/aptos-labs/aptos-go-sdk/crypto" @@ -38,7 +40,7 @@ func example(networkConfig aptos.NetworkConfig) { // Fund the sender with the faucet to create it on-chain println("SENDER: ", sender.Address.String()) - err = client.Fund(sender.Address, FundAmount) + err = client.Fund(context.Background(), sender.Address, FundAmount) if err != nil { panic("Failed to fund sender:" + err.Error()) } @@ -50,11 +52,11 @@ func example(networkConfig aptos.NetworkConfig) { if err != nil { panic("Failed to create publish payload:" + err.Error()) } - response, err := client.BuildSignAndSubmitTransaction(sender, *payload) + response, err := client.BuildSignAndSubmitTransaction(context.Background(), sender, *payload) if err != nil { panic("Failed to build sign and submit publish transaction:" + err.Error()) } - waitResponse, err := client.WaitForTransaction(response.Hash) + waitResponse, err := client.WaitForTransaction(context.Background(), response.Hash) if err != nil { panic("Failed to wait for publish transaction:" + err.Error()) } @@ -66,7 +68,7 @@ func example(networkConfig aptos.NetworkConfig) { // Get the fungible asset address by view function rupeeModule := aptos.ModuleId{Address: sender.Address, Name: "rupee"} var noTypeTags []aptos.TypeTag - viewResponse, err := client.View(&aptos.ViewPayload{ + viewResponse, err := client.View(context.Background(), &aptos.ViewPayload{ Module: rupeeModule, Function: "fa_address", ArgTypes: noTypeTags, @@ -85,7 +87,7 @@ func example(networkConfig aptos.NetworkConfig) { panic("Failed to create fungible asset client:" + err.Error()) } - beforeBalance, err := faClient.PrimaryBalance(&sender.Address) + beforeBalance, err := faClient.PrimaryBalance(context.Background(), &sender.Address) if err != nil { panic("Failed to get balance:" + err.Error()) } @@ -96,7 +98,7 @@ func example(networkConfig aptos.NetworkConfig) { panic("Failed to serialize amount:" + err.Error()) } serializedSenderAddress, _ := bcs.Serialize(&sender.Address) // This can't fail - response, err = client.BuildSignAndSubmitTransaction(sender, aptos.TransactionPayload{ + response, err = client.BuildSignAndSubmitTransaction(context.Background(), sender, aptos.TransactionPayload{ Payload: &aptos.EntryFunction{ Module: rupeeModule, Function: "mint", @@ -108,12 +110,12 @@ func example(networkConfig aptos.NetworkConfig) { panic("Failed to build sign and submit mint transaction:" + err.Error()) } fmt.Printf("Submitted mint as: %s\n", response.Hash) - _, err = client.WaitForTransaction(response.Hash) + _, err = client.WaitForTransaction(context.Background(), response.Hash) if err != nil { panic("Failed to wait for publish transaction:" + err.Error()) } - afterBalance, err := faClient.PrimaryBalance(&sender.Address) + afterBalance, err := faClient.PrimaryBalance(context.Background(), &sender.Address) if err != nil { panic("Failed to get balance:" + err.Error()) } @@ -127,24 +129,24 @@ func example(networkConfig aptos.NetworkConfig) { } // Transfer some to 0xCAFE - receiverBeforeBalance, err := faClient.PrimaryBalance(receiver) + receiverBeforeBalance, err := faClient.PrimaryBalance(context.Background(), receiver) if err != nil { panic("Failed to get balance:" + err.Error()) } - transferTxn, err := faClient.TransferPrimaryStore(sender, *receiver, TransferAmount) + transferTxn, err := faClient.TransferPrimaryStore(context.Background(), sender, *receiver, TransferAmount) if err != nil { panic("Failed to create primary store transfer transaction:" + err.Error()) } - response, err = client.SubmitTransaction(transferTxn) + response, err = client.SubmitTransaction(context.Background(), transferTxn) if err != nil { panic("Failed to submit transaction:" + err.Error()) } fmt.Printf("Submitted transfer as: %s\n", response.Hash) - err = client.PollForTransactions([]string{response.Hash}) + err = client.PollForTransactions(context.Background(), []string{response.Hash}) if err != nil { panic("Failed to wait for transaction:" + err.Error()) } - receiverAfterBalance, err := faClient.PrimaryBalance(receiver) + receiverAfterBalance, err := faClient.PrimaryBalance(context.Background(), receiver) if err != nil { panic("Failed to get store balance:" + err.Error()) } @@ -155,7 +157,7 @@ func example(networkConfig aptos.NetworkConfig) { fmt.Printf("\n== Now running script version ==\n") runScript(client, sender, receiver, faMetadataAddress) - receiverAfterAfterBalance, err := faClient.PrimaryBalance(receiver) + receiverAfterAfterBalance, err := faClient.PrimaryBalance(context.Background(), receiver) if err != nil { panic("Failed to get store balance:" + err.Error()) } @@ -171,7 +173,7 @@ func runScript(client *aptos.Client, alice *aptos.Account, bob *aptos.AccountAdd } // 1. Build transaction - rawTxn, err := client.BuildTransaction(alice.AccountAddress(), aptos.TransactionPayload{ + rawTxn, err := client.BuildTransaction(context.Background(), alice.AccountAddress(), aptos.TransactionPayload{ Payload: &aptos.Script{ Code: scriptBytes, ArgTypes: []aptos.TypeTag{}, @@ -191,7 +193,7 @@ func runScript(client *aptos.Client, alice *aptos.Account, bob *aptos.AccountAdd // This is useful for understanding how much the transaction will cost // and to ensure that the transaction is valid before sending it to the network // This is optional, but recommended - simulationResult, err := client.SimulateTransaction(rawTxn, alice) + simulationResult, err := client.SimulateTransaction(context.Background(), rawTxn, alice) if err != nil { panic("Failed to simulate transaction:" + err.Error()) } @@ -208,14 +210,14 @@ func runScript(client *aptos.Client, alice *aptos.Account, bob *aptos.AccountAdd } // 4. Submit transaction - submitResult, err := client.SubmitTransaction(signedTxn) + submitResult, err := client.SubmitTransaction(context.Background(), signedTxn) if err != nil { panic("Failed to submit transaction:" + err.Error()) } txnHash := submitResult.Hash // 5. Wait for the transaction to complete - _, err = client.WaitForTransaction(txnHash) + _, err = client.WaitForTransaction(context.Background(), txnHash) if err != nil { panic("Failed to wait for transaction:" + err.Error()) } diff --git a/examples/multi_agent/main.go b/examples/multi_agent/main.go index 940907f..3ce25f5 100644 --- a/examples/multi_agent/main.go +++ b/examples/multi_agent/main.go @@ -2,7 +2,9 @@ package main import ( + "context" "fmt" + "github.com/aptos-labs/aptos-go-sdk/crypto" "github.com/aptos-labs/aptos-go-sdk/internal/util" @@ -37,19 +39,19 @@ func example(networkConfig aptos.NetworkConfig) { fmt.Printf("Bob:%s\n", bob.Address.String()) // Fund the sender with the faucet to create it on-chain - err = client.Fund(alice.Address, FundAmount) + err = client.Fund(context.Background(), alice.Address, FundAmount) if err != nil { panic("Failed to fund alice:" + err.Error()) } - err = client.Fund(bob.Address, FundAmount) + err = client.Fund(context.Background(), bob.Address, FundAmount) if err != nil { panic("Failed to fund bob:" + err.Error()) } - aliceBalance, err := client.AccountAPTBalance(alice.Address) + aliceBalance, err := client.AccountAPTBalance(context.Background(), alice.Address) if err != nil { panic("Failed to retrieve alice balance:" + err.Error()) } - bobBalance, err := client.AccountAPTBalance(bob.Address) + bobBalance, err := client.AccountAPTBalance(context.Background(), bob.Address) if err != nil { panic("Failed to retrieve bob balance:" + err.Error()) } @@ -62,7 +64,7 @@ func example(networkConfig aptos.NetworkConfig) { if err != nil { panic("Failed to deserialize script:" + err.Error()) } - rawTxn, err := client.BuildTransactionMultiAgent(alice.AccountAddress(), aptos.TransactionPayload{ + rawTxn, err := client.BuildTransactionMultiAgent(context.Background(), alice.AccountAddress(), aptos.TransactionPayload{ Payload: &aptos.Script{ Code: script, ArgTypes: []aptos.TypeTag{aptos.AptosCoinTypeTag, aptos.AptosCoinTypeTag}, @@ -113,24 +115,24 @@ func example(networkConfig aptos.NetworkConfig) { } // 4. Submit transaction - submitResult, err := client.SubmitTransaction(signedTxn) + submitResult, err := client.SubmitTransaction(context.Background(), signedTxn) if err != nil { panic("Failed to submit transaction:" + err.Error()) } txnHash := submitResult.Hash // 5. Wait for the transaction to complete - _, err = client.WaitForTransaction(txnHash) + _, err = client.WaitForTransaction(context.Background(), txnHash) if err != nil { panic("Failed to wait for transaction:" + err.Error()) } // Check balances - aliceBalance, err = client.AccountAPTBalance(alice.Address) + aliceBalance, err = client.AccountAPTBalance(context.Background(), alice.Address) if err != nil { panic("Failed to retrieve alice balance:" + err.Error()) } - bobBalance, err = client.AccountAPTBalance(bob.Address) + bobBalance, err = client.AccountAPTBalance(context.Background(), bob.Address) if err != nil { panic("Failed to retrieve bob balance:" + err.Error()) } diff --git a/examples/offchain_multisig/main.go b/examples/offchain_multisig/main.go index 2e59b8d..92bfe58 100644 --- a/examples/offchain_multisig/main.go +++ b/examples/offchain_multisig/main.go @@ -2,7 +2,9 @@ package main import ( + "context" "fmt" + "github.com/aptos-labs/aptos-go-sdk" "github.com/aptos-labs/aptos-go-sdk/bcs" "github.com/aptos-labs/aptos-go-sdk/crypto" @@ -183,20 +185,20 @@ func example(networkConfig aptos.NetworkConfig) { } // Fund the sender with the faucet to create it on-chain - err = client.Fund(alice.AccountAddress(), TransferAmount) + err = client.Fund(context.Background(), alice.AccountAddress(), TransferAmount) if err != nil { panic("Failed to fund alice:" + err.Error()) } - err = client.Fund(multikeySigner.AccountAddress(), FundAmount) + err = client.Fund(context.Background(), multikeySigner.AccountAddress(), FundAmount) if err != nil { panic("Failed to fund multikey:" + err.Error()) } - aliceBalance, err := client.AccountAPTBalance(alice.Address) + aliceBalance, err := client.AccountAPTBalance(context.Background(), alice.Address) if err != nil { panic("Failed to retrieve alice balance:" + err.Error()) } - multikeyBalance, err := client.AccountAPTBalance(multikeySigner.AccountAddress()) + multikeyBalance, err := client.AccountAPTBalance(context.Background(), multikeySigner.AccountAddress()) if err != nil { panic("Failed to retrieve multikey balance:" + err.Error()) } @@ -215,7 +217,7 @@ func example(networkConfig aptos.NetworkConfig) { if err != nil { panic("Failed to serialize transfer amount:" + err.Error()) } - rawTxn, err := client.BuildTransaction(multikeyAddress, aptos.TransactionPayload{ + rawTxn, err := client.BuildTransaction(context.Background(), multikeyAddress, aptos.TransactionPayload{ Payload: &aptos.EntryFunction{ Module: aptos.ModuleId{ Address: aptos.AccountOne, @@ -257,24 +259,24 @@ func example(networkConfig aptos.NetworkConfig) { } // 4. Submit transaction - submitResult, err := client.SubmitTransaction(signedTxn) + submitResult, err := client.SubmitTransaction(context.Background(), signedTxn) if err != nil { panic("Failed to submit transaction:" + err.Error()) } txnHash := submitResult.Hash // 5. Wait for the transaction to complete - _, err = client.WaitForTransaction(txnHash) + _, err = client.WaitForTransaction(context.Background(), txnHash) if err != nil { panic("Failed to wait for transaction:" + err.Error()) } // Check balances - aliceBalance, err = client.AccountAPTBalance(alice.Address) + aliceBalance, err = client.AccountAPTBalance(context.Background(), alice.Address) if err != nil { panic("Failed to retrieve alice balance:" + err.Error()) } - multikeyBalance, err = client.AccountAPTBalance(multikeyAddress) + multikeyBalance, err = client.AccountAPTBalance(context.Background(), multikeyAddress) if err != nil { panic("Failed to retrieve bob balance:" + err.Error()) } diff --git a/examples/onchain_multisig/main.go b/examples/onchain_multisig/main.go index 238299e..afe75bf 100644 --- a/examples/onchain_multisig/main.go +++ b/examples/onchain_multisig/main.go @@ -2,12 +2,14 @@ package main import ( + "context" "encoding/json" "fmt" + "time" + "github.com/aptos-labs/aptos-go-sdk" "github.com/aptos-labs/aptos-go-sdk/api" "github.com/aptos-labs/aptos-go-sdk/bcs" - "time" ) const TransferAmount = uint64(1_000_000) @@ -112,7 +114,7 @@ func example(networkConfig aptos.NetworkConfig) { } func assertBalance(client *aptos.Client, address aptos.AccountAddress, expectedBalance uint64) { - amount, err := client.AccountAPTBalance(address) + amount, err := client.AccountAPTBalance(context.Background(), address) if err != nil { panic("failed to get balance: " + err.Error()) } @@ -135,7 +137,7 @@ func generateOwnerAccounts() []*aptos.Account { func fundAccounts(client *aptos.Client, accounts []*aptos.AccountAddress) { for _, account := range accounts { - err := client.Fund(*account, 100_000_000) + err := client.Fund(context.Background(), *account, 100_000_000) if err != nil { panic("Failed to fund account " + err.Error()) } @@ -149,7 +151,7 @@ func setUpMultisig(client *aptos.Client, accounts []*aptos.Account) *aptos.Accou // =========================================================================================== // Get the next multisig account address. This will be the same as the account address of the multisig account we'll // be creating. - multisigAddress, err := client.FetchNextMultisigAddress(accounts[0].Address) + multisigAddress, err := client.FetchNextMultisigAddress(context.Background(), accounts[0].Address) if err != nil { panic("Failed to fetch next multisig address: " + err.Error()) } @@ -193,7 +195,7 @@ func createMultisig(client *aptos.Client, account *aptos.Account, additionalAddr // TODO: This should be a view function func multisigResource(client *aptos.Client, multisigAddress *aptos.AccountAddress) (uint64, []any) { - resource, err := client.AccountResource(*multisigAddress, "0x1::multisig_account::MultisigAccount") + resource, err := client.AccountResource(context.Background(), *multisigAddress, "0x1::multisig_account::MultisigAccount") if err != nil { panic("Failed to get resource for multisig account: " + err.Error()) } @@ -300,12 +302,12 @@ func executeTransaction(client *aptos.Client, multisigAddress aptos.AccountAddre } func submitAndWait(client *aptos.Client, sender *aptos.Account, payload aptos.TransactionPayloadImpl) *api.UserTransaction { - submitResponse, err := client.BuildSignAndSubmitTransaction(sender, aptos.TransactionPayload{Payload: payload}) + submitResponse, err := client.BuildSignAndSubmitTransaction(context.Background(), sender, aptos.TransactionPayload{Payload: payload}) if err != nil { panic("Failed to submit transaction: " + err.Error()) } - txn, err := client.WaitForTransaction(submitResponse.Hash) + txn, err := client.WaitForTransaction(context.Background(), submitResponse.Hash) if err != nil { panic("Failed to wait for transaction: " + err.Error()) } diff --git a/examples/performance_transaction/main.go b/examples/performance_transaction/main.go index 0a1b2a8..9aa58b5 100644 --- a/examples/performance_transaction/main.go +++ b/examples/performance_transaction/main.go @@ -2,9 +2,11 @@ package main import ( + "context" "encoding/json" - "github.com/aptos-labs/aptos-go-sdk" "time" + + "github.com/aptos-labs/aptos-go-sdk" ) // example This example shows you how to improve performance of the transaction submission @@ -31,7 +33,7 @@ func example(networkConfig aptos.NetworkConfig) { before = time.Now() // Fund the sender with the faucet to create it on-chain - err = client.Fund(sender.Address, 100_000_000) + err = client.Fund(context.Background(), sender.Address, 100_000_000) println("Fund sender:", time.Since(before).Milliseconds(), "ms") @@ -51,7 +53,7 @@ func example(networkConfig aptos.NetworkConfig) { panic("Failed to serialize arguments:" + err.Error()) } - rawTxn, err := client.BuildTransaction(sender.Address, + rawTxn, err := client.BuildTransaction(context.Background(), sender.Address, aptos.TransactionPayload{Payload: payload}, aptos.SequenceNumber(0)) // Use the sequence number to skip fetching it if err != nil { panic("Failed to build transaction:" + err.Error()) @@ -70,7 +72,7 @@ func example(networkConfig aptos.NetworkConfig) { println("Sign transaction:", time.Since(before).Milliseconds(), "ms") before = time.Now() - submitResult, err := client.SubmitTransaction(signedTxn) + submitResult, err := client.SubmitTransaction(context.Background(), signedTxn) if err != nil { panic("Failed to submit transaction:" + err.Error()) } @@ -79,7 +81,7 @@ func example(networkConfig aptos.NetworkConfig) { // Wait for the transaction before = time.Now() - txn, err := client.WaitForTransaction(txnHash) + txn, err := client.WaitForTransaction(context.Background(), txnHash) if err != nil { panic("Failed to wait for transaction:" + err.Error()) } diff --git a/examples/sending_concurrent_transactions/main.go b/examples/sending_concurrent_transactions/main.go index 15356d1..216bfb9 100644 --- a/examples/sending_concurrent_transactions/main.go +++ b/examples/sending_concurrent_transactions/main.go @@ -2,9 +2,11 @@ package main import ( + "context" + "time" + "github.com/aptos-labs/aptos-go-sdk" "github.com/aptos-labs/aptos-go-sdk/api" - "time" ) func setup(networkConfig aptos.NetworkConfig) (*aptos.Client, aptos.TransactionSigner) { @@ -18,7 +20,7 @@ func setup(networkConfig aptos.NetworkConfig) (*aptos.Client, aptos.TransactionS panic("Failed to create sender:" + err.Error()) } - err = client.Fund(sender.Address, 100_000_000) + err = client.Fund(context.Background(), sender.Address, 100_000_000) if err != nil { panic("Failed to fund sender:" + err.Error()) } @@ -49,7 +51,7 @@ func sendManyTransactionsSerially(networkConfig aptos.NetworkConfig, numTransact senderAddress := sender.AccountAddress() sequenceNumber := uint64(0) for i := uint64(0); i < numTransactions; i++ { - rawTxn, err := client.BuildTransaction(senderAddress, payload, aptos.SequenceNumber(sequenceNumber)) + rawTxn, err := client.BuildTransaction(context.Background(), senderAddress, payload, aptos.SequenceNumber(sequenceNumber)) if err != nil { panic("Failed to build transaction:" + err.Error()) } @@ -59,7 +61,7 @@ func sendManyTransactionsSerially(networkConfig aptos.NetworkConfig, numTransact panic("Failed to sign transaction:" + err.Error()) } - submitResult, err := client.SubmitTransaction(signedTxn) + submitResult, err := client.SubmitTransaction(context.Background(), signedTxn) if err != nil { panic("Failed to submit transaction:" + err.Error()) } @@ -68,7 +70,7 @@ func sendManyTransactionsSerially(networkConfig aptos.NetworkConfig, numTransact } // Wait on last transaction - response, err := client.WaitForTransaction(responses[numTransactions-1].Hash) + response, err := client.WaitForTransaction(context.Background(), responses[numTransactions-1].Hash) if err != nil { panic("Failed to wait for transaction:" + err.Error()) } @@ -84,7 +86,7 @@ func sendManyTransactionsConcurrently(networkConfig aptos.NetworkConfig, numTran // start submission goroutine payloads := make(chan aptos.TransactionBuildPayload, 50) results := make(chan aptos.TransactionSubmissionResponse, 50) - go client.BuildSignAndSubmitTransactions(sender, payloads, results) + go client.BuildSignAndSubmitTransactions(context.Background(), sender, payloads, results) // Submit transactions to goroutine go func() { diff --git a/examples/sponsored_transaction/main.go b/examples/sponsored_transaction/main.go index 8122d1a..8512914 100644 --- a/examples/sponsored_transaction/main.go +++ b/examples/sponsored_transaction/main.go @@ -2,6 +2,7 @@ package main import ( + "context" "fmt" "github.com/aptos-labs/aptos-go-sdk" @@ -39,26 +40,26 @@ func example(networkConfig aptos.NetworkConfig) { fmt.Printf("Sponsor:%s\n", sponsor.Address.String()) // Fund the alice with the faucet to create it on-chain - err = client.Fund(alice.Address, FundAmount) + err = client.Fund(context.Background(), alice.Address, FundAmount) if err != nil { panic("Failed to fund alice:" + err.Error()) } // And the sponsor - err = client.Fund(sponsor.Address, FundAmount) + err = client.Fund(context.Background(), sponsor.Address, FundAmount) if err != nil { panic("Failed to fund sponsor:" + err.Error()) } - aliceBalance, err := client.AccountAPTBalance(alice.Address) + aliceBalance, err := client.AccountAPTBalance(context.Background(), alice.Address) if err != nil { panic("Failed to retrieve alice balance:" + err.Error()) } - bobBalance, err := client.AccountAPTBalance(bob.Address) + bobBalance, err := client.AccountAPTBalance(context.Background(), bob.Address) if err != nil { panic("Failed to retrieve bob balance:" + err.Error()) } - sponsorBalance, err := client.AccountAPTBalance(sponsor.Address) + sponsorBalance, err := client.AccountAPTBalance(context.Background(), sponsor.Address) if err != nil { panic("Failed to retrieve sponsor balance:" + err.Error()) } @@ -73,6 +74,7 @@ func example(networkConfig aptos.NetworkConfig) { panic("Failed to build transfer payload:" + err.Error()) } rawTxn, err := client.BuildTransactionMultiAgent( + context.Background(), alice.Address, aptos.TransactionPayload{ Payload: transferPayload, @@ -103,7 +105,7 @@ func example(networkConfig aptos.NetworkConfig) { } // Submit and wait for it to complete - submitResult, err := client.SubmitTransaction(signedFeePayerTxn) + submitResult, err := client.SubmitTransaction(context.Background(), signedFeePayerTxn) if err != nil { panic("Failed to submit transaction:" + err.Error()) } @@ -111,19 +113,19 @@ func example(networkConfig aptos.NetworkConfig) { println("Submitted transaction hash:", txnHash) // Wait for the transaction - _, err = client.WaitForTransaction(txnHash) + _, err = client.WaitForTransaction(context.Background(), txnHash) if err != nil { panic("Failed to wait for transaction:" + err.Error()) } - aliceBalance, err = client.AccountAPTBalance(alice.Address) + aliceBalance, err = client.AccountAPTBalance(context.Background(), alice.Address) if err != nil { panic("Failed to retrieve alice balance:" + err.Error()) } - bobBalance, err = client.AccountAPTBalance(bob.Address) + bobBalance, err = client.AccountAPTBalance(context.Background(), bob.Address) if err != nil { panic("Failed to retrieve bob balance:" + err.Error()) } - sponsorBalance, err = client.AccountAPTBalance(sponsor.Address) + sponsorBalance, err = client.AccountAPTBalance(context.Background(), sponsor.Address) if err != nil { panic("Failed to retrieve sponsor balance:" + err.Error()) } @@ -135,6 +137,7 @@ func example(networkConfig aptos.NetworkConfig) { fmt.Printf("\n=== Now do it without knowing the signer ahead of time ===\n") rawTxn, err = client.BuildTransactionMultiAgent( + context.Background(), alice.Address, aptos.TransactionPayload{ Payload: transferPayload, @@ -173,7 +176,7 @@ func example(networkConfig aptos.NetworkConfig) { } // Submit and wait for it to complete - submitResult, err = client.SubmitTransaction(signedFeePayerTxn) + submitResult, err = client.SubmitTransaction(context.Background(), signedFeePayerTxn) if err != nil { panic("Failed to submit transaction:" + err.Error()) } @@ -181,19 +184,19 @@ func example(networkConfig aptos.NetworkConfig) { println("Submitted transaction hash:", txnHash) // Wait for the transaction - _, err = client.WaitForTransaction(txnHash) + _, err = client.WaitForTransaction(context.Background(), txnHash) if err != nil { panic("Failed to wait for transaction:" + err.Error()) } - aliceBalance, err = client.AccountAPTBalance(alice.Address) + aliceBalance, err = client.AccountAPTBalance(context.Background(), alice.Address) if err != nil { panic("Failed to retrieve alice balance:" + err.Error()) } - bobBalance, err = client.AccountAPTBalance(bob.Address) + bobBalance, err = client.AccountAPTBalance(context.Background(), bob.Address) if err != nil { panic("Failed to retrieve bob balance:" + err.Error()) } - sponsorBalance, err = client.AccountAPTBalance(sponsor.Address) + sponsorBalance, err = client.AccountAPTBalance(context.Background(), sponsor.Address) if err != nil { panic("Failed to retrieve sponsor balance:" + err.Error()) } diff --git a/examples/transfer_coin/main.go b/examples/transfer_coin/main.go index 949f7e4..d85876c 100644 --- a/examples/transfer_coin/main.go +++ b/examples/transfer_coin/main.go @@ -2,6 +2,7 @@ package main import ( + "context" "fmt" "github.com/aptos-labs/aptos-go-sdk" @@ -34,16 +35,16 @@ func example(networkConfig aptos.NetworkConfig) { fmt.Printf("Bob:%s\n", bob.Address.String()) // Fund the sender with the faucet to create it on-chain - err = client.Fund(alice.Address, FundAmount) + err = client.Fund(context.Background(), alice.Address, FundAmount) if err != nil { panic("Failed to fund alice:" + err.Error()) } - aliceBalance, err := client.AccountAPTBalance(alice.Address) + aliceBalance, err := client.AccountAPTBalance(context.Background(), alice.Address) if err != nil { panic("Failed to retrieve alice balance:" + err.Error()) } - bobBalance, err := client.AccountAPTBalance(bob.Address) + bobBalance, err := client.AccountAPTBalance(context.Background(), bob.Address) if err != nil { panic("Failed to retrieve bob balance:" + err.Error()) } @@ -61,7 +62,7 @@ func example(networkConfig aptos.NetworkConfig) { if err != nil { panic("Failed to serialize transfer amount:" + err.Error()) } - rawTxn, err := client.BuildTransaction(alice.AccountAddress(), aptos.TransactionPayload{ + rawTxn, err := client.BuildTransaction(context.Background(), alice.AccountAddress(), aptos.TransactionPayload{ Payload: &aptos.EntryFunction{ Module: aptos.ModuleId{ Address: aptos.AccountOne, @@ -84,7 +85,7 @@ func example(networkConfig aptos.NetworkConfig) { // This is useful for understanding how much the transaction will cost // and to ensure that the transaction is valid before sending it to the network // This is optional, but recommended - simulationResult, err := client.SimulateTransaction(rawTxn, alice) + simulationResult, err := client.SimulateTransaction(context.Background(), rawTxn, alice) if err != nil { panic("Failed to simulate transaction:" + err.Error()) } @@ -101,24 +102,24 @@ func example(networkConfig aptos.NetworkConfig) { } // 4. Submit transaction - submitResult, err := client.SubmitTransaction(signedTxn) + submitResult, err := client.SubmitTransaction(context.Background(), signedTxn) if err != nil { panic("Failed to submit transaction:" + err.Error()) } txnHash := submitResult.Hash // 5. Wait for the transaction to complete - _, err = client.WaitForTransaction(txnHash) + _, err = client.WaitForTransaction(context.Background(), txnHash) if err != nil { panic("Failed to wait for transaction:" + err.Error()) } // Check balances - aliceBalance, err = client.AccountAPTBalance(alice.Address) + aliceBalance, err = client.AccountAPTBalance(context.Background(), alice.Address) if err != nil { panic("Failed to retrieve alice balance:" + err.Error()) } - bobBalance, err = client.AccountAPTBalance(bob.Address) + bobBalance, err = client.AccountAPTBalance(context.Background(), bob.Address) if err != nil { panic("Failed to retrieve bob balance:" + err.Error()) } @@ -127,7 +128,7 @@ func example(networkConfig aptos.NetworkConfig) { fmt.Printf("Bob:%d\n", bobBalance) // Now do it again, but with a different method - resp, err := client.BuildSignAndSubmitTransaction(alice, aptos.TransactionPayload{ + resp, err := client.BuildSignAndSubmitTransaction(context.Background(), alice, aptos.TransactionPayload{ Payload: &aptos.EntryFunction{ Module: aptos.ModuleId{ Address: aptos.AccountOne, @@ -145,16 +146,16 @@ func example(networkConfig aptos.NetworkConfig) { panic("Failed to sign transaction:" + err.Error()) } - _, err = client.WaitForTransaction(resp.Hash) + _, err = client.WaitForTransaction(context.Background(), resp.Hash) if err != nil { panic("Failed to wait for transaction:" + err.Error()) } - aliceBalance, err = client.AccountAPTBalance(alice.Address) + aliceBalance, err = client.AccountAPTBalance(context.Background(), alice.Address) if err != nil { panic("Failed to retrieve alice balance:" + err.Error()) } - bobBalance, err = client.AccountAPTBalance(bob.Address) + bobBalance, err = client.AccountAPTBalance(context.Background(), bob.Address) if err != nil { panic("Failed to retrieve bob balance:" + err.Error()) } diff --git a/faucet.go b/faucet.go index 95fb175..f7d941f 100644 --- a/faucet.go +++ b/faucet.go @@ -1,6 +1,7 @@ package aptos import ( + "context" "errors" "fmt" "log/slog" @@ -28,7 +29,7 @@ func NewFaucetClient(nodeClient *NodeClient, faucetUrl string) (*FaucetClient, e } // Fund account with the given amount of AptosCoin -func (faucetClient *FaucetClient) Fund(address AccountAddress, amount uint64) error { +func (faucetClient *FaucetClient) Fund(ctx context.Context, address AccountAddress, amount uint64) error { if faucetClient.nodeClient == nil { return errors.New("faucet's node-client not initialized") } @@ -41,7 +42,7 @@ func (faucetClient *FaucetClient) Fund(address AccountAddress, amount uint64) er mintUrl.RawQuery = params.Encode() // Make request for funds - txnHashes, err := Post[[]string](faucetClient.nodeClient, mintUrl.String(), "text/plain", nil) + txnHashes, err := Post[[]string](ctx, faucetClient.nodeClient, mintUrl.String(), "text/plain", nil) if err != nil { return fmt.Errorf("response api decode error, %w", err) } @@ -49,9 +50,9 @@ func (faucetClient *FaucetClient) Fund(address AccountAddress, amount uint64) er // Wait for fund transactions to go through slog.Debug("FundAccount wait for transactions", "number of transactions", len(txnHashes)) if len(txnHashes) == 1 { - _, err = faucetClient.nodeClient.WaitForTransaction(txnHashes[0]) + _, err = faucetClient.nodeClient.WaitForTransaction(ctx, txnHashes[0]) return err } else { - return faucetClient.nodeClient.PollForTransactions(txnHashes) + return faucetClient.nodeClient.PollForTransactions(ctx, txnHashes) } } diff --git a/fungible_asset_client.go b/fungible_asset_client.go index 6216548..705949f 100644 --- a/fungible_asset_client.go +++ b/fungible_asset_client.go @@ -1,6 +1,7 @@ package aptos import ( + "context" "errors" "math/big" "strconv" @@ -15,7 +16,7 @@ type FungibleAssetClient struct { // NewFungibleAssetClient verifies the [AccountAddress] of the metadata exists when creating the client func NewFungibleAssetClient(client *Client, metadataAddress *AccountAddress) (faClient *FungibleAssetClient, err error) { // Retrieve the Metadata resource to ensure the fungible asset actually exists - _, err = client.AccountResource(*metadataAddress, "0x1::fungible_asset::Metadata") + _, err = client.AccountResource(context.Background(), *metadataAddress, "0x1::fungible_asset::Metadata") if err != nil { return } @@ -30,14 +31,14 @@ func NewFungibleAssetClient(client *Client, metadataAddress *AccountAddress) (fa // -- Entry functions -- // // Transfer sends amount of the fungible asset from senderStore to receiverStore -func (client *FungibleAssetClient) Transfer(sender TransactionSigner, senderStore AccountAddress, receiverStore AccountAddress, amount uint64) (signedTxn *SignedTransaction, err error) { +func (client *FungibleAssetClient) Transfer(ctx context.Context, sender TransactionSigner, senderStore AccountAddress, receiverStore AccountAddress, amount uint64) (signedTxn *SignedTransaction, err error) { payload, err := FungibleAssetTransferPayload(client.metadataAddress, senderStore, receiverStore, amount) if err != nil { return nil, err } // Build transaction - rawTxn, err := client.aptosClient.BuildTransaction(sender.AccountAddress(), TransactionPayload{Payload: payload}) + rawTxn, err := client.aptosClient.BuildTransaction(ctx, sender.AccountAddress(), TransactionPayload{Payload: payload}) if err != nil { return } @@ -48,13 +49,13 @@ func (client *FungibleAssetClient) Transfer(sender TransactionSigner, senderStor } // TransferPrimaryStore sends amount of the fungible asset from the primary store of the sender to receiverAddress -func (client *FungibleAssetClient) TransferPrimaryStore(sender TransactionSigner, receiverAddress AccountAddress, amount uint64) (signedTxn *SignedTransaction, err error) { +func (client *FungibleAssetClient) TransferPrimaryStore(ctx context.Context, sender TransactionSigner, receiverAddress AccountAddress, amount uint64) (signedTxn *SignedTransaction, err error) { // Build transaction payload, err := FungibleAssetPrimaryStoreTransferPayload(client.metadataAddress, receiverAddress, amount) if err != nil { return nil, err } - rawTxn, err := client.aptosClient.BuildTransaction(sender.AccountAddress(), TransactionPayload{Payload: payload}) + rawTxn, err := client.aptosClient.BuildTransaction(ctx, sender.AccountAddress(), TransactionPayload{Payload: payload}) if err != nil { return } @@ -68,8 +69,8 @@ func (client *FungibleAssetClient) TransferPrimaryStore(sender TransactionSigner // PrimaryStoreAddress returns the [AccountAddress] of the primary store for the owner // // Note that the primary store may not exist at the address. Use [FungibleAssetClient.PrimaryStoreExists] to check. -func (client *FungibleAssetClient) PrimaryStoreAddress(owner *AccountAddress) (address *AccountAddress, err error) { - val, err := client.viewPrimaryStoreMetadata([][]byte{owner[:], client.metadataAddress[:]}, "primary_store_address") +func (client *FungibleAssetClient) PrimaryStoreAddress(ctx context.Context, owner *AccountAddress) (address *AccountAddress, err error) { + val, err := client.viewPrimaryStoreMetadata(ctx, [][]byte{owner[:], client.metadataAddress[:]}, "primary_store_address") if err != nil { return } @@ -79,8 +80,8 @@ func (client *FungibleAssetClient) PrimaryStoreAddress(owner *AccountAddress) (a } // PrimaryStoreExists returns true if the primary store for the owner exists -func (client *FungibleAssetClient) PrimaryStoreExists(owner *AccountAddress) (exists bool, err error) { - val, err := client.viewPrimaryStoreMetadata([][]byte{owner[:], client.metadataAddress[:]}, "primary_store_exists") +func (client *FungibleAssetClient) PrimaryStoreExists(ctx context.Context, owner *AccountAddress) (exists bool, err error) { + val, err := client.viewPrimaryStoreMetadata(ctx, [][]byte{owner[:], client.metadataAddress[:]}, "primary_store_exists") if err != nil { return } @@ -90,8 +91,8 @@ func (client *FungibleAssetClient) PrimaryStoreExists(owner *AccountAddress) (ex } // PrimaryBalance returns the balance of the primary store for the owner -func (client *FungibleAssetClient) PrimaryBalance(owner *AccountAddress, ledgerVersion ...uint64) (balance uint64, err error) { - val, err := client.viewPrimaryStoreMetadata([][]byte{owner[:], client.metadataAddress[:]}, "balance", ledgerVersion...) +func (client *FungibleAssetClient) PrimaryBalance(ctx context.Context, owner *AccountAddress, ledgerVersion ...uint64) (balance uint64, err error) { + val, err := client.viewPrimaryStoreMetadata(ctx, [][]byte{owner[:], client.metadataAddress[:]}, "balance", ledgerVersion...) if err != nil { return } @@ -100,8 +101,8 @@ func (client *FungibleAssetClient) PrimaryBalance(owner *AccountAddress, ledgerV } // PrimaryIsFrozen returns true if the primary store for the owner is frozen -func (client *FungibleAssetClient) PrimaryIsFrozen(owner *AccountAddress, ledgerVersion ...uint64) (isFrozen bool, err error) { - val, err := client.viewPrimaryStore([][]byte{owner[:], client.metadataAddress[:]}, "is_frozen", ledgerVersion...) +func (client *FungibleAssetClient) PrimaryIsFrozen(ctx context.Context, owner *AccountAddress, ledgerVersion ...uint64) (isFrozen bool, err error) { + val, err := client.viewPrimaryStore(ctx, [][]byte{owner[:], client.metadataAddress[:]}, "is_frozen", ledgerVersion...) if err != nil { return } @@ -110,8 +111,8 @@ func (client *FungibleAssetClient) PrimaryIsFrozen(owner *AccountAddress, ledger } // Balance returns the balance of the store -func (client *FungibleAssetClient) Balance(storeAddress *AccountAddress, ledgerVersion ...uint64) (balance uint64, err error) { - val, err := client.viewStore([][]byte{storeAddress[:]}, "balance", ledgerVersion...) +func (client *FungibleAssetClient) Balance(ctx context.Context, storeAddress *AccountAddress, ledgerVersion ...uint64) (balance uint64, err error) { + val, err := client.viewStore(ctx, [][]byte{storeAddress[:]}, "balance", ledgerVersion...) if err != nil { return } @@ -120,8 +121,8 @@ func (client *FungibleAssetClient) Balance(storeAddress *AccountAddress, ledgerV } // IsFrozen returns true if the store is frozen -func (client *FungibleAssetClient) IsFrozen(storeAddress *AccountAddress, ledgerVersion ...uint64) (isFrozen bool, err error) { - val, err := client.viewStore([][]byte{storeAddress[:]}, "is_frozen", ledgerVersion...) +func (client *FungibleAssetClient) IsFrozen(ctx context.Context, storeAddress *AccountAddress, ledgerVersion ...uint64) (isFrozen bool, err error) { + val, err := client.viewStore(ctx, [][]byte{storeAddress[:]}, "is_frozen", ledgerVersion...) if err != nil { return } @@ -130,8 +131,8 @@ func (client *FungibleAssetClient) IsFrozen(storeAddress *AccountAddress, ledger } // IsUntransferable returns true if the store can't be transferred -func (client *FungibleAssetClient) IsUntransferable(storeAddress *AccountAddress, ledgerVersion ...uint64) (isFrozen bool, err error) { - val, err := client.viewStore([][]byte{storeAddress[:]}, "is_untransferable", ledgerVersion...) +func (client *FungibleAssetClient) IsUntransferable(ctx context.Context, storeAddress *AccountAddress, ledgerVersion ...uint64) (isFrozen bool, err error) { + val, err := client.viewStore(ctx, [][]byte{storeAddress[:]}, "is_untransferable", ledgerVersion...) if err != nil { return } @@ -140,8 +141,8 @@ func (client *FungibleAssetClient) IsUntransferable(storeAddress *AccountAddress } // StoreExists returns true if the store exists -func (client *FungibleAssetClient) StoreExists(storeAddress *AccountAddress, ledgerVersion ...uint64) (exists bool, err error) { - val, err := client.viewStore([][]byte{storeAddress[:]}, "store_exists", ledgerVersion...) +func (client *FungibleAssetClient) StoreExists(ctx context.Context, storeAddress *AccountAddress, ledgerVersion ...uint64) (exists bool, err error) { + val, err := client.viewStore(ctx, [][]byte{storeAddress[:]}, "store_exists", ledgerVersion...) if err != nil { return } @@ -151,8 +152,8 @@ func (client *FungibleAssetClient) StoreExists(storeAddress *AccountAddress, led } // StoreMetadata returns the [AccountAddress] of the metadata for the store -func (client *FungibleAssetClient) StoreMetadata(storeAddress *AccountAddress, ledgerVersion ...uint64) (metadataAddress *AccountAddress, err error) { - val, err := client.viewStore([][]byte{storeAddress[:]}, "store_metadata", ledgerVersion...) +func (client *FungibleAssetClient) StoreMetadata(ctx context.Context, storeAddress *AccountAddress, ledgerVersion ...uint64) (metadataAddress *AccountAddress, err error) { + val, err := client.viewStore(ctx, [][]byte{storeAddress[:]}, "store_metadata", ledgerVersion...) if err != nil { return } @@ -160,8 +161,8 @@ func (client *FungibleAssetClient) StoreMetadata(storeAddress *AccountAddress, l } // Supply returns the total supply of the fungible asset -func (client *FungibleAssetClient) Supply(ledgerVersion ...uint64) (supply *big.Int, err error) { - val, err := client.viewMetadata([][]byte{client.metadataAddress[:]}, "supply", ledgerVersion...) +func (client *FungibleAssetClient) Supply(ctx context.Context, ledgerVersion ...uint64) (supply *big.Int, err error) { + val, err := client.viewMetadata(ctx, [][]byte{client.metadataAddress[:]}, "supply", ledgerVersion...) if err != nil { return } @@ -169,8 +170,8 @@ func (client *FungibleAssetClient) Supply(ledgerVersion ...uint64) (supply *big. } // Maximum returns the maximum possible supply of the fungible asset -func (client *FungibleAssetClient) Maximum(ledgerVersion ...uint64) (maximum *big.Int, err error) { - val, err := client.viewMetadata([][]byte{client.metadataAddress[:]}, "maximum", ledgerVersion...) +func (client *FungibleAssetClient) Maximum(ctx context.Context, ledgerVersion ...uint64) (maximum *big.Int, err error) { + val, err := client.viewMetadata(ctx, [][]byte{client.metadataAddress[:]}, "maximum", ledgerVersion...) if err != nil { return } @@ -178,8 +179,8 @@ func (client *FungibleAssetClient) Maximum(ledgerVersion ...uint64) (maximum *bi } // Name returns the name of the fungible asset -func (client *FungibleAssetClient) Name() (name string, err error) { - val, err := client.viewMetadata([][]byte{client.metadataAddress[:]}, "name") +func (client *FungibleAssetClient) Name(ctx context.Context) (name string, err error) { + val, err := client.viewMetadata(ctx, [][]byte{client.metadataAddress[:]}, "name") if err != nil { return } @@ -188,8 +189,8 @@ func (client *FungibleAssetClient) Name() (name string, err error) { } // Symbol returns the symbol of the fungible asset -func (client *FungibleAssetClient) Symbol() (symbol string, err error) { - val, err := client.viewMetadata([][]byte{client.metadataAddress[:]}, "symbol") +func (client *FungibleAssetClient) Symbol(ctx context.Context) (symbol string, err error) { + val, err := client.viewMetadata(ctx, [][]byte{client.metadataAddress[:]}, "symbol") if err != nil { return } @@ -198,8 +199,8 @@ func (client *FungibleAssetClient) Symbol() (symbol string, err error) { } // Decimals returns the number of decimal places for the fungible asset -func (client *FungibleAssetClient) Decimals() (decimals uint8, err error) { - val, err := client.viewMetadata([][]byte{client.metadataAddress[:]}, "decimals") +func (client *FungibleAssetClient) Decimals(ctx context.Context) (decimals uint8, err error) { + val, err := client.viewMetadata(ctx, [][]byte{client.metadataAddress[:]}, "decimals") if err != nil { return } @@ -208,8 +209,8 @@ func (client *FungibleAssetClient) Decimals() (decimals uint8, err error) { } // IconUri returns the URI of the icon for the fungible asset -func (client *FungibleAssetClient) IconUri(uri string, err error) { - val, err := client.viewMetadata([][]byte{client.metadataAddress[:]}, "icon_uri") +func (client *FungibleAssetClient) IconUri(ctx context.Context, uri string, err error) { + val, err := client.viewMetadata(ctx, [][]byte{client.metadataAddress[:]}, "icon_uri") if err != nil { return } @@ -218,8 +219,8 @@ func (client *FungibleAssetClient) IconUri(uri string, err error) { } // ProjectUri returns the URI of the project for the fungible asset -func (client *FungibleAssetClient) ProjectUri(uri string, err error) { - val, err := client.viewMetadata([][]byte{client.metadataAddress[:]}, "project_uri") +func (client *FungibleAssetClient) ProjectUri(ctx context.Context, uri string, err error) { + val, err := client.viewMetadata(ctx, [][]byte{client.metadataAddress[:]}, "project_uri") if err != nil { return } @@ -228,7 +229,7 @@ func (client *FungibleAssetClient) ProjectUri(uri string, err error) { } // viewMetadata calls a view function on the fungible asset metadata -func (client *FungibleAssetClient) viewMetadata(args [][]byte, functionName string, ledgerVersion ...uint64) (result any, err error) { +func (client *FungibleAssetClient) viewMetadata(ctx context.Context, args [][]byte, functionName string, ledgerVersion ...uint64) (result any, err error) { payload := &ViewPayload{ Module: ModuleId{ Address: AccountOne, @@ -238,11 +239,11 @@ func (client *FungibleAssetClient) viewMetadata(args [][]byte, functionName stri ArgTypes: []TypeTag{metadataStructTag()}, Args: args, } - return client.view(payload, ledgerVersion...) + return client.view(ctx, payload, ledgerVersion...) } // viewStore calls a view function on the fungible asset store -func (client *FungibleAssetClient) viewStore(args [][]byte, functionName string, ledgerVersion ...uint64) (result any, err error) { +func (client *FungibleAssetClient) viewStore(ctx context.Context, args [][]byte, functionName string, ledgerVersion ...uint64) (result any, err error) { payload := &ViewPayload{ Module: ModuleId{ Address: AccountOne, @@ -252,11 +253,11 @@ func (client *FungibleAssetClient) viewStore(args [][]byte, functionName string, ArgTypes: []TypeTag{storeStructTag()}, Args: args, } - return client.view(payload, ledgerVersion...) + return client.view(ctx, payload, ledgerVersion...) } // viewPrimaryStore calls a view function on the primary fungible asset store -func (client *FungibleAssetClient) viewPrimaryStore(args [][]byte, functionName string, ledgerVersion ...uint64) (result any, err error) { +func (client *FungibleAssetClient) viewPrimaryStore(ctx context.Context, args [][]byte, functionName string, ledgerVersion ...uint64) (result any, err error) { payload := &ViewPayload{ Module: ModuleId{ Address: AccountOne, @@ -266,11 +267,11 @@ func (client *FungibleAssetClient) viewPrimaryStore(args [][]byte, functionName ArgTypes: []TypeTag{storeStructTag()}, Args: args, } - return client.view(payload, ledgerVersion...) + return client.view(ctx, payload, ledgerVersion...) } // viewPrimaryStoreMetadata calls a view function on the primary fungible asset store metadata -func (client *FungibleAssetClient) viewPrimaryStoreMetadata(args [][]byte, functionName string, ledgerVersion ...uint64) (result any, err error) { +func (client *FungibleAssetClient) viewPrimaryStoreMetadata(ctx context.Context, args [][]byte, functionName string, ledgerVersion ...uint64) (result any, err error) { payload := &ViewPayload{ Module: ModuleId{ Address: AccountOne, @@ -280,7 +281,7 @@ func (client *FungibleAssetClient) viewPrimaryStoreMetadata(args [][]byte, funct ArgTypes: []TypeTag{metadataStructTag()}, Args: args, } - return client.view(payload, ledgerVersion...) + return client.view(ctx, payload, ledgerVersion...) } func metadataStructTag() TypeTag { @@ -291,8 +292,8 @@ func storeStructTag() TypeTag { return TypeTag{Value: &StructTag{Address: AccountOne, Module: "fungible_asset", Name: "FungibleStore"}} } -func (client *FungibleAssetClient) view(payload *ViewPayload, ledgerVersion ...uint64) (result any, err error) { - vals, err := client.aptosClient.View(payload, ledgerVersion...) +func (client *FungibleAssetClient) view(ctx context.Context, payload *ViewPayload, ledgerVersion ...uint64) (result any, err error) { + vals, err := client.aptosClient.View(ctx, payload, ledgerVersion...) if err != nil { return } diff --git a/indexerClient.go b/indexerClient.go index 20f769c..27292ec 100644 --- a/indexerClient.go +++ b/indexerClient.go @@ -3,9 +3,10 @@ package aptos import ( "context" "fmt" - "github.com/hasura/go-graphql-client" "net/http" "time" + + "github.com/hasura/go-graphql-client" ) // -- Note: all query parameters must start with capital letters -- @@ -25,8 +26,8 @@ func NewIndexerClient(httpClient *http.Client, url string) *IndexerClient { } // Query is a generic function for making any GraphQL query against the indexer -func (ic *IndexerClient) Query(query any, variables map[string]any, options ...graphql.Option) error { - return ic.inner.Query(context.Background(), query, variables, options...) +func (ic *IndexerClient) Query(ctx context.Context, query any, variables map[string]any, options ...graphql.Option) error { + return ic.inner.Query(ctx, query, variables, options...) } type CoinBalance struct { @@ -35,7 +36,7 @@ type CoinBalance struct { } // GetCoinBalances retrieve the coin balances for all coins owned by the address -func (ic *IndexerClient) GetCoinBalances(address AccountAddress) ([]CoinBalance, error) { +func (ic *IndexerClient) GetCoinBalances(ctx context.Context, address AccountAddress) ([]CoinBalance, error) { var out []CoinBalance var q struct { CurrentCoinBalances []struct { @@ -48,7 +49,7 @@ func (ic *IndexerClient) GetCoinBalances(address AccountAddress) ([]CoinBalance, variables := map[string]any{ "address": address.StringLong(), } - err := ic.Query(&q, variables) + err := ic.Query(ctx, &q, variables) if err != nil { return nil, err @@ -65,7 +66,7 @@ func (ic *IndexerClient) GetCoinBalances(address AccountAddress) ([]CoinBalance, } // GetProcessorStatus tells the most updated version of the transaction processor. This helps to determine freshness of data. -func (ic *IndexerClient) GetProcessorStatus(processorName string) (uint64, error) { +func (ic *IndexerClient) GetProcessorStatus(ctx context.Context, processorName string) (uint64, error) { var q struct { ProcessorStatus []struct { LastSuccessVersion uint64 `graphql:"last_success_version"` @@ -74,7 +75,7 @@ func (ic *IndexerClient) GetProcessorStatus(processorName string) (uint64, error variables := map[string]any{ "processor_name": processorName, } - err := ic.Query(&q, variables) + err := ic.Query(ctx, &q, variables) if err != nil { return 0, err } @@ -83,13 +84,13 @@ func (ic *IndexerClient) GetProcessorStatus(processorName string) (uint64, error } // WaitOnIndexer waits for the indexer processorName specified to catch up to the requestedVersion -func (ic *IndexerClient) WaitOnIndexer(processorName string, requestedVersion uint64) error { +func (ic *IndexerClient) WaitOnIndexer(ctx context.Context, processorName string, requestedVersion uint64) error { // TODO: add customizable timeout and sleep time const sleepTime = 100 * time.Millisecond const timeout = 5 * time.Second startTime := time.Now() for { - version, err := ic.GetProcessorStatus(processorName) + version, err := ic.GetProcessorStatus(ctx, processorName) if err != nil { // TODO: This should probably just retry, depending on the error return err diff --git a/multisig.go b/multisig.go index 85892df..6ef62a2 100644 --- a/multisig.go +++ b/multisig.go @@ -1,10 +1,14 @@ package aptos -import "github.com/aptos-labs/aptos-go-sdk/bcs" +import ( + "context" + + "github.com/aptos-labs/aptos-go-sdk/bcs" +) // FetchNextMultisigAddress retrieves the next multisig address to be created from the given account -func (client *Client) FetchNextMultisigAddress(address AccountAddress) (*AccountAddress, error) { - viewResponse, err := client.View(&ViewPayload{ +func (client *Client) FetchNextMultisigAddress(ctx context.Context, address AccountAddress) (*AccountAddress, error) { + viewResponse, err := client.View(ctx, &ViewPayload{ Module: ModuleId{ Address: AccountOne, Name: "multisig_account", diff --git a/nodeClient.go b/nodeClient.go index b43e7ed..088debe 100644 --- a/nodeClient.go +++ b/nodeClient.go @@ -2,6 +2,7 @@ package aptos import ( "bytes" + "context" "encoding/json" "errors" "fmt" @@ -93,8 +94,8 @@ func (rc *NodeClient) RemoveHeader(key string) { } // Info gets general information about the blockchain -func (rc *NodeClient) Info() (info NodeInfo, err error) { - info, err = Get[NodeInfo](rc, rc.baseUrl.String()) +func (rc *NodeClient) Info(ctx context.Context) (info NodeInfo, err error) { + info, err = Get[NodeInfo](ctx, rc, rc.baseUrl.String()) if err != nil { return info, fmt.Errorf("get node info api err: %w", err) } @@ -107,14 +108,14 @@ func (rc *NodeClient) Info() (info NodeInfo, err error) { // Account gets information about an account for a given address // // Optionally, a ledgerVersion can be given to get the account state at a specific ledger version -func (rc *NodeClient) Account(address AccountAddress, ledgerVersion ...uint64) (info AccountInfo, err error) { +func (rc *NodeClient) Account(ctx context.Context, address AccountAddress, ledgerVersion ...uint64) (info AccountInfo, err error) { au := rc.baseUrl.JoinPath("accounts", address.String()) if len(ledgerVersion) > 0 { params := url.Values{} params.Set("ledger_version", strconv.FormatUint(ledgerVersion[0], 10)) au.RawQuery = params.Encode() } - info, err = Get[AccountInfo](rc, au.String()) + info, err = Get[AccountInfo](ctx, rc, au.String()) if err != nil { return info, fmt.Errorf("get account info api err: %w", err) } @@ -125,7 +126,7 @@ func (rc *NodeClient) Account(address AccountAddress, ledgerVersion ...uint64) ( // Optionally, a ledgerVersion can be given to get the account state at a specific ledger version // // For fetching raw Move structs as BCS, See #AccountResourceBCS -func (rc *NodeClient) AccountResource(address AccountAddress, resourceType string, ledgerVersion ...uint64) (data map[string]any, err error) { +func (rc *NodeClient) AccountResource(ctx context.Context, address AccountAddress, resourceType string, ledgerVersion ...uint64) (data map[string]any, err error) { au := rc.baseUrl.JoinPath("accounts", address.String(), "resource", resourceType) // TODO: offer a list of known-good resourceType string constants if len(ledgerVersion) > 0 { @@ -133,7 +134,7 @@ func (rc *NodeClient) AccountResource(address AccountAddress, resourceType strin params.Set("ledger_version", strconv.FormatUint(ledgerVersion[0], 10)) au.RawQuery = params.Encode() } - data, err = Get[map[string]any](rc, au.String()) + data, err = Get[map[string]any](ctx, rc, au.String()) if err != nil { return nil, fmt.Errorf("get resource api err: %w", err) } @@ -143,14 +144,14 @@ func (rc *NodeClient) AccountResource(address AccountAddress, resourceType strin // AccountResources fetches resources for an account into a JSON-like map[string]any in AccountResourceInfo.Data // Optionally, a ledgerVersion can be given to get the account state at a specific ledger version // For fetching raw Move structs as BCS, See #AccountResourcesBCS -func (rc *NodeClient) AccountResources(address AccountAddress, ledgerVersion ...uint64) (resources []AccountResourceInfo, err error) { +func (rc *NodeClient) AccountResources(ctx context.Context, address AccountAddress, ledgerVersion ...uint64) (resources []AccountResourceInfo, err error) { au := rc.baseUrl.JoinPath("accounts", address.String(), "resources") if len(ledgerVersion) > 0 { params := url.Values{} params.Set("ledger_version", strconv.FormatUint(ledgerVersion[0], 10)) au.RawQuery = params.Encode() } - resources, err = Get[[]AccountResourceInfo](rc, au.String()) + resources, err = Get[[]AccountResourceInfo](ctx, rc, au.String()) if err != nil { return nil, fmt.Errorf("get resources api err: %w", err) } @@ -159,14 +160,14 @@ func (rc *NodeClient) AccountResources(address AccountAddress, ledgerVersion ... // AccountResourcesBCS fetches account resources as raw Move struct BCS blobs in AccountResourceRecord.Data []byte // Optionally, a ledgerVersion can be given to get the account state at a specific ledger version -func (rc *NodeClient) AccountResourcesBCS(address AccountAddress, ledgerVersion ...uint64) (resources []AccountResourceRecord, err error) { +func (rc *NodeClient) AccountResourcesBCS(ctx context.Context, address AccountAddress, ledgerVersion ...uint64) (resources []AccountResourceRecord, err error) { au := rc.baseUrl.JoinPath("accounts", address.String(), "resources") if len(ledgerVersion) > 0 { params := url.Values{} params.Set("ledger_version", strconv.FormatUint(ledgerVersion[0], 10)) au.RawQuery = params.Encode() } - blob, err := rc.GetBCS(au.String()) + blob, err := rc.GetBCS(ctx, au.String()) if err != nil { return nil, err } @@ -193,9 +194,9 @@ func (rc *NodeClient) AccountResourcesBCS(address AccountAddress, ledgerVersion // // known to local mempool, but not committed yet // } // } -func (rc *NodeClient) TransactionByHash(txnHash string) (data *api.Transaction, err error) { +func (rc *NodeClient) TransactionByHash(ctx context.Context, txnHash string) (data *api.Transaction, err error) { restUrl := rc.baseUrl.JoinPath("transactions/by_hash", txnHash) - data, err = Get[*api.Transaction](rc, restUrl.String()) + data, err = Get[*api.Transaction](ctx, rc, restUrl.String()) if err != nil { return data, fmt.Errorf("get transaction api err: %w", err) } @@ -204,9 +205,9 @@ func (rc *NodeClient) TransactionByHash(txnHash string) (data *api.Transaction, // TransactionByVersion gets info on a transaction by version number // The transaction will have been committed. The response will not be of the type [api.PendingTransaction]. -func (rc *NodeClient) TransactionByVersion(version uint64) (data *api.CommittedTransaction, err error) { +func (rc *NodeClient) TransactionByVersion(ctx context.Context, version uint64) (data *api.CommittedTransaction, err error) { restUrl := rc.baseUrl.JoinPath("transactions/by_version", strconv.FormatUint(version, 10)) - data, err = Get[*api.CommittedTransaction](rc, restUrl.String()) + data, err = Get[*api.CommittedTransaction](ctx, rc, restUrl.String()) if err != nil { return data, fmt.Errorf("get transaction api err: %w", err) } @@ -218,29 +219,29 @@ func (rc *NodeClient) TransactionByVersion(version uint64) (data *api.CommittedT // Note that this is not the same as a block's height. // // The function will fetch all transactions in the block if withTransactions is true. -func (rc *NodeClient) BlockByVersion(ledgerVersion uint64, withTransactions bool) (data *api.Block, err error) { +func (rc *NodeClient) BlockByVersion(ctx context.Context, ledgerVersion uint64, withTransactions bool) (data *api.Block, err error) { restUrl := rc.baseUrl.JoinPath("blocks/by_version", strconv.FormatUint(ledgerVersion, 10)) - return rc.getBlockCommon(restUrl, withTransactions) + return rc.getBlockCommon(ctx, restUrl, withTransactions) } // BlockByHeight gets a block by block height // // The function will fetch all transactions in the block if withTransactions is true. -func (rc *NodeClient) BlockByHeight(blockHeight uint64, withTransactions bool) (data *api.Block, err error) { +func (rc *NodeClient) BlockByHeight(ctx context.Context, blockHeight uint64, withTransactions bool) (data *api.Block, err error) { restUrl := rc.baseUrl.JoinPath("blocks/by_height", strconv.FormatUint(blockHeight, 10)) - return rc.getBlockCommon(restUrl, withTransactions) + return rc.getBlockCommon(ctx, restUrl, withTransactions) } // getBlockCommon is a helper function for fetching a block by version or height // // It will fetch all the transactions associated with the block if withTransactions is true. -func (rc *NodeClient) getBlockCommon(restUrl *url.URL, withTransactions bool) (block *api.Block, err error) { +func (rc *NodeClient) getBlockCommon(ctx context.Context, restUrl *url.URL, withTransactions bool) (block *api.Block, err error) { params := url.Values{} params.Set("with_transactions", strconv.FormatBool(withTransactions)) restUrl.RawQuery = params.Encode() // Fetch block - block, err = Get[*api.Block](rc, restUrl.String()) + block, err = Get[*api.Block](ctx, rc, restUrl.String()) if err != nil { return block, fmt.Errorf("get block api err: %w", err) } @@ -265,7 +266,7 @@ func (rc *NodeClient) getBlockCommon(restUrl *url.URL, withTransactions bool) (b // TODO: I maybe should pull these concurrently, but not for now for retrievedTransactions < numTransactions { numToPull := numTransactions - retrievedTransactions - transactions, innerError := rc.Transactions(&cursor, &numToPull) + transactions, innerError := rc.Transactions(ctx, &cursor, &numToPull) if innerError != nil { // We will still return the block, since we did so much work for it return block, innerError @@ -285,8 +286,8 @@ func (rc *NodeClient) getBlockCommon(restUrl *url.URL, withTransactions bool) (b // Optional arguments: // - PollPeriod: time.Duration, how often to poll for the transaction. Default 100ms. // - PollTimeout: time.Duration, how long to wait for the transaction. Default 10s. -func (rc *NodeClient) WaitForTransaction(txnHash string, options ...any) (data *api.UserTransaction, err error) { - return rc.PollForTransaction(txnHash, options...) +func (rc *NodeClient) WaitForTransaction(ctx context.Context, txnHash string, options ...any) (data *api.UserTransaction, err error) { + return rc.PollForTransaction(ctx, txnHash, options...) } // PollPeriod is an option to PollForTransactions @@ -315,7 +316,7 @@ func getTransactionPollOptions(defaultPeriod, defaultTimeout time.Duration, opti // PollForTransaction waits up to 10 seconds for a transaction to be done, polling at 10Hz // Accepts options PollPeriod and PollTimeout which should wrap time.Duration values. // Not just a degenerate case of PollForTransactions, it may return additional information for the single transaction polled. -func (rc *NodeClient) PollForTransaction(hash string, options ...any) (*api.UserTransaction, error) { +func (rc *NodeClient) PollForTransaction(ctx context.Context, hash string, options ...any) (*api.UserTransaction, error) { period, timeout, err := getTransactionPollOptions(100*time.Millisecond, 10*time.Second, options...) if err != nil { return nil, err @@ -327,7 +328,7 @@ func (rc *NodeClient) PollForTransaction(hash string, options ...any) (*api.User return nil, errors.New("PollForTransaction timeout") } time.Sleep(period) - txn, err := rc.TransactionByHash(hash) + txn, err := rc.TransactionByHash(ctx, hash) if err == nil { if txn.Type == api.TransactionVariantPending { // not done yet! @@ -342,7 +343,7 @@ func (rc *NodeClient) PollForTransaction(hash string, options ...any) (*api.User // PollForTransactions waits up to 10 seconds for transactions to be done, polling at 10Hz // Accepts options PollPeriod and PollTimeout which should wrap time.Duration values. -func (rc *NodeClient) PollForTransactions(txnHashes []string, options ...any) error { +func (rc *NodeClient) PollForTransactions(ctx context.Context, txnHashes []string, options ...any) error { period, timeout, err := getTransactionPollOptions(100*time.Millisecond, 10*time.Second, options...) if err != nil { return err @@ -363,7 +364,7 @@ func (rc *NodeClient) PollForTransactions(txnHashes []string, options ...any) er // already done continue } - txn, err := rc.TransactionByHash(hash) + txn, err := rc.TransactionByHash(ctx, hash) if err == nil { if txn.Type == api.TransactionVariantPending { // not done yet! @@ -383,12 +384,12 @@ func (rc *NodeClient) PollForTransactions(txnHashes []string, options ...any) er // Arguments: // - start is a version number. Nil for most recent transactions. // - limit is a number of transactions to return. 'about a hundred' by default. -func (rc *NodeClient) Transactions(start *uint64, limit *uint64) (data []*api.CommittedTransaction, err error) { - return rc.handleTransactions(start, limit, func(txns *[]*api.CommittedTransaction) uint64 { +func (rc *NodeClient) Transactions(ctx context.Context, start *uint64, limit *uint64) (data []*api.CommittedTransaction, err error) { + return rc.handleTransactions(ctx, start, limit, func(txns *[]*api.CommittedTransaction) uint64 { txn := (*txns)[len(*txns)-1] return txn.Version() - }, func(start *uint64, limit *uint64) ([]*api.CommittedTransaction, error) { - return rc.transactionsInner(start, limit) + }, func(ctx context.Context, start *uint64, limit *uint64) ([]*api.CommittedTransaction, error) { + return rc.transactionsInner(ctx, start, limit) }) } @@ -397,13 +398,13 @@ func (rc *NodeClient) Transactions(start *uint64, limit *uint64) (data []*api.Co // Arguments: // - start is a version number. Nil for most recent transactions. // - limit is a number of transactions to return. 'about a hundred' by default. -func (rc *NodeClient) AccountTransactions(account AccountAddress, start *uint64, limit *uint64) (data []*api.CommittedTransaction, err error) { - return rc.handleTransactions(start, limit, func(txns *[]*api.CommittedTransaction) uint64 { +func (rc *NodeClient) AccountTransactions(ctx context.Context, account AccountAddress, start *uint64, limit *uint64) (data []*api.CommittedTransaction, err error) { + return rc.handleTransactions(ctx, start, limit, func(txns *[]*api.CommittedTransaction) uint64 { // It will always be a UserTransaction, no other type will come from the API userTxn, _ := ((*txns)[0]).UserTransaction() return userTxn.SequenceNumber - 1 - }, func(start *uint64, limit *uint64) ([]*api.CommittedTransaction, error) { - return rc.accountTransactionsInner(account, start, limit) + }, func(ctx context.Context, start *uint64, limit *uint64) ([]*api.CommittedTransaction, error) { + return rc.accountTransactionsInner(ctx, account, start, limit) }) } @@ -411,19 +412,20 @@ func (rc *NodeClient) AccountTransactions(account AccountAddress, start *uint64, // // It will fetch the transactions from the node in a single request if possible, otherwise it will fetch them concurrently. func (rc *NodeClient) handleTransactions( + ctx context.Context, start *uint64, limit *uint64, getNext func(txns *[]*api.CommittedTransaction) uint64, - getTxns func(start *uint64, limit *uint64) ([]*api.CommittedTransaction, error), + getTxns func(ctx context.Context, start *uint64, limit *uint64) ([]*api.CommittedTransaction, error), ) (data []*api.CommittedTransaction, err error) { // Can only pull everything in parallel if a start and a limit is handled if start != nil && limit != nil { - return rc.transactionsConcurrent(*start, *limit, getTxns) + return rc.transactionsConcurrent(ctx, *start, *limit, getTxns) } else if limit != nil { // If we don't know the start, we can only pull one page first, then handle the rest // Note that, this actually pulls the last page first, then goes backwards actualLimit := *limit - txns, err := getTxns(nil, limit) + txns, err := getTxns(ctx, nil, limit) if err != nil { return nil, err } @@ -435,7 +437,7 @@ func (rc *NodeClient) handleTransactions( } else { newStart := getNext(&txns) newLength := actualLimit - numTxns - extra, err := rc.transactionsConcurrent(newStart, newLength, getTxns) + extra, err := rc.transactionsConcurrent(ctx, newStart, newLength, getTxns) if err != nil { return nil, err } @@ -444,7 +446,7 @@ func (rc *NodeClient) handleTransactions( } } else { // If we know the start, just pull one page - return getTxns(start, nil) + return getTxns(ctx, start, nil) } } @@ -452,9 +454,10 @@ func (rc *NodeClient) handleTransactions( // // It will fetch the transactions concurrently if the limit is greater than the page size, otherwise it will fetch them in a single request. func (rc *NodeClient) transactionsConcurrent( + ctx context.Context, start uint64, limit uint64, - getTxns func(start *uint64, limit *uint64) ([]*api.CommittedTransaction, error), + getTxns func(ctx context.Context, start *uint64, limit *uint64) ([]*api.CommittedTransaction, error), ) (data []*api.CommittedTransaction, err error) { const transactionsPageSize = 100 // If we know both, we can fetch all concurrently @@ -477,7 +480,7 @@ func (rc *NodeClient) transactionsConcurrent( st := start + i*100 // TODO: allow page size to be configured li := min(transactionsPageSize, limit-i*transactionsPageSize) go fetch(func() ([]*api.CommittedTransaction, error) { - return rc.transactionsConcurrent(st, li, getTxns) + return rc.transactionsConcurrent(ctx, st, li, getTxns) }, channels[i]) } @@ -498,7 +501,7 @@ func (rc *NodeClient) transactionsConcurrent( }) return responses, nil } else { - response, err := getTxns(&start, &limit) + response, err := getTxns(ctx, &start, &limit) if err != nil { return nil, err } else { @@ -508,7 +511,7 @@ func (rc *NodeClient) transactionsConcurrent( } // transactionsInner fetches the transactions from the node in a single request -func (rc *NodeClient) transactionsInner(start *uint64, limit *uint64) (data []*api.CommittedTransaction, err error) { +func (rc *NodeClient) transactionsInner(ctx context.Context, start *uint64, limit *uint64) (data []*api.CommittedTransaction, err error) { au := rc.baseUrl.JoinPath("transactions") params := url.Values{} if start != nil { @@ -520,7 +523,7 @@ func (rc *NodeClient) transactionsInner(start *uint64, limit *uint64) (data []*a if len(params) != 0 { au.RawQuery = params.Encode() } - data, err = Get[[]*api.CommittedTransaction](rc, au.String()) + data, err = Get[[]*api.CommittedTransaction](ctx, rc, au.String()) if err != nil { return data, fmt.Errorf("get transactions api err: %w", err) } @@ -528,7 +531,7 @@ func (rc *NodeClient) transactionsInner(start *uint64, limit *uint64) (data []*a } // accountTransactionsInner fetches the transactions from the node in a single request for a single account -func (rc *NodeClient) accountTransactionsInner(account AccountAddress, start *uint64, limit *uint64) (data []*api.CommittedTransaction, err error) { +func (rc *NodeClient) accountTransactionsInner(ctx context.Context, account AccountAddress, start *uint64, limit *uint64) (data []*api.CommittedTransaction, err error) { au := rc.baseUrl.JoinPath(fmt.Sprintf("accounts/%s/transactions", account.String())) params := url.Values{} if start != nil { @@ -541,7 +544,7 @@ func (rc *NodeClient) accountTransactionsInner(account AccountAddress, start *ui au.RawQuery = params.Encode() } - data, err = Get[[]*api.CommittedTransaction](rc, au.String()) + data, err = Get[[]*api.CommittedTransaction](ctx, rc, au.String()) if err != nil { return data, fmt.Errorf("get account transactions api err: %w", err) } @@ -549,14 +552,14 @@ func (rc *NodeClient) accountTransactionsInner(account AccountAddress, start *ui } // SubmitTransaction submits a signed transaction to the network -func (rc *NodeClient) SubmitTransaction(signedTxn *SignedTransaction) (data *api.SubmitTransactionResponse, err error) { +func (rc *NodeClient) SubmitTransaction(ctx context.Context, signedTxn *SignedTransaction) (data *api.SubmitTransactionResponse, err error) { sblob, err := bcs.Serialize(signedTxn) if err != nil { return } bodyReader := bytes.NewReader(sblob) au := rc.baseUrl.JoinPath("transactions") - data, err = Post[*api.SubmitTransactionResponse](rc, au.String(), ContentTypeAptosSignedTxnBcs, bodyReader) + data, err = Post[*api.SubmitTransactionResponse](ctx, rc, au.String(), ContentTypeAptosSignedTxnBcs, bodyReader) if err != nil { return nil, fmt.Errorf("submit transaction api err: %w", err) } @@ -567,14 +570,14 @@ func (rc *NodeClient) SubmitTransaction(signedTxn *SignedTransaction) (data *api // // It will return the responses in the same order as the input transactions that failed. If the response is empty, then // all transactions succeeded. -func (rc *NodeClient) BatchSubmitTransaction(signedTxns []*SignedTransaction) (response *api.BatchSubmitTransactionResponse, err error) { +func (rc *NodeClient) BatchSubmitTransaction(ctx context.Context, signedTxns []*SignedTransaction) (response *api.BatchSubmitTransactionResponse, err error) { sblob, err := bcs.SerializeSequenceOnly(signedTxns) if err != nil { return } bodyReader := bytes.NewReader(sblob) au := rc.baseUrl.JoinPath("transactions/batch") - response, err = Post[*api.BatchSubmitTransactionResponse](rc, au.String(), ContentTypeAptosSignedTxnBcs, bodyReader) + response, err = Post[*api.BatchSubmitTransactionResponse](ctx, rc, au.String(), ContentTypeAptosSignedTxnBcs, bodyReader) if err != nil { return nil, fmt.Errorf("submit transaction api err: %w", err) } @@ -594,7 +597,7 @@ type EstimatePrioritizedGasUnitPrice bool // // TODO: This needs to support RawTransactionWithData // TODO: Support multikey simulation -func (rc *NodeClient) SimulateTransaction(rawTxn *RawTransaction, sender TransactionSigner, options ...any) (data []*api.UserTransaction, err error) { +func (rc *NodeClient) SimulateTransaction(ctx context.Context, rawTxn *RawTransaction, sender TransactionSigner, options ...any) (data []*api.UserTransaction, err error) { // build authenticator for simulation derivationScheme := sender.PubKey().Scheme() switch derivationScheme { @@ -637,7 +640,7 @@ func (rc *NodeClient) SimulateTransaction(rawTxn *RawTransaction, sender Transac au.RawQuery = params.Encode() } - data, err = Post[[]*api.UserTransaction](rc, au.String(), ContentTypeAptosSignedTxnBcs, bodyReader) + data, err = Post[[]*api.UserTransaction](ctx, rc, au.String(), ContentTypeAptosSignedTxnBcs, bodyReader) if err != nil { return nil, fmt.Errorf("simulate transaction api err: %w", err) } @@ -646,10 +649,10 @@ func (rc *NodeClient) SimulateTransaction(rawTxn *RawTransaction, sender Transac } // GetChainId gets the chain ID of the network -func (rc *NodeClient) GetChainId() (chainId uint8, err error) { +func (rc *NodeClient) GetChainId(ctx context.Context) (chainId uint8, err error) { if rc.chainId == 0 { // Calling Info will cache the ChainId - info, err := rc.Info() + info, err := rc.Info(ctx) if err != nil { return 0, err } @@ -690,7 +693,7 @@ type ChainIdOption uint8 // - [ExpirationSeconds] // - [SequenceNumber] // - [ChainIdOption] -func (rc *NodeClient) BuildTransaction(sender AccountAddress, payload TransactionPayload, options ...any) (rawTxn *RawTransaction, err error) { +func (rc *NodeClient) BuildTransaction(ctx context.Context, sender AccountAddress, payload TransactionPayload, options ...any) (rawTxn *RawTransaction, err error) { maxGasAmount := DefaultMaxGasAmount gasUnitPrice := DefaultGasUnitPrice @@ -726,7 +729,7 @@ func (rc *NodeClient) BuildTransaction(sender AccountAddress, payload Transactio } } - return rc.buildTransactionInner(sender, payload, maxGasAmount, gasUnitPrice, haveGasUnitPrice, expirationSeconds, sequenceNumber, haveSequenceNumber, chainId, haveChainId) + return rc.buildTransactionInner(ctx, sender, payload, maxGasAmount, gasUnitPrice, haveGasUnitPrice, expirationSeconds, sequenceNumber, haveSequenceNumber, chainId, haveChainId) } // BuildTransactionMultiAgent builds a raw transaction for signing with fee payer or multi-agent @@ -741,7 +744,7 @@ func (rc *NodeClient) BuildTransaction(sender AccountAddress, payload Transactio // - [ChainIdOption] // - [FeePayer] // - [AdditionalSigners] -func (rc *NodeClient) BuildTransactionMultiAgent(sender AccountAddress, payload TransactionPayload, options ...any) (rawTxnImpl *RawTransactionWithData, err error) { +func (rc *NodeClient) BuildTransactionMultiAgent(ctx context.Context, sender AccountAddress, payload TransactionPayload, options ...any) (rawTxnImpl *RawTransactionWithData, err error) { maxGasAmount := DefaultMaxGasAmount gasUnitPrice := DefaultGasUnitPrice @@ -785,7 +788,7 @@ func (rc *NodeClient) BuildTransactionMultiAgent(sender AccountAddress, payload } // Build the base raw transaction - rawTxn, err := rc.buildTransactionInner(sender, payload, maxGasAmount, gasUnitPrice, haveGasUnitPrice, expirationSeconds, sequenceNumber, haveSequenceNumber, chainId, haveChainId) + rawTxn, err := rc.buildTransactionInner(ctx, sender, payload, maxGasAmount, gasUnitPrice, haveGasUnitPrice, expirationSeconds, sequenceNumber, haveSequenceNumber, chainId, haveChainId) if err != nil { return nil, err } @@ -812,6 +815,7 @@ func (rc *NodeClient) BuildTransactionMultiAgent(sender AccountAddress, payload } func (rc *NodeClient) buildTransactionInner( + ctx context.Context, sender AccountAddress, payload TransactionPayload, maxGasAmount uint64, @@ -830,7 +834,7 @@ func (rc *NodeClient) buildTransactionInner( if !haveGasUnitPrice { gasPriceErrChannel = make(chan error, 1) go func() { - gasPriceEstimation, innerErr := rc.EstimateGasPrice() + gasPriceEstimation, innerErr := rc.EstimateGasPrice(ctx) if innerErr != nil { gasPriceErrChannel <- innerErr } else { @@ -847,7 +851,7 @@ func (rc *NodeClient) buildTransactionInner( if rc.chainId == 0 { chainIdErrChannel = make(chan error, 1) go func() { - chain, innerErr := rc.GetChainId() + chain, innerErr := rc.GetChainId(ctx) if innerErr != nil { chainIdErrChannel <- innerErr } else { @@ -866,7 +870,7 @@ func (rc *NodeClient) buildTransactionInner( if !haveSequenceNumber { accountErrChannel = make(chan error, 1) go func() { - account, innerErr := rc.Account(sender) + account, innerErr := rc.Account(ctx, sender) if innerErr != nil { accountErrChannel <- innerErr close(accountErrChannel) @@ -939,7 +943,7 @@ func (vp *ViewPayload) MarshalBCS(ser *bcs.Serializer) { } // View calls a view function on the blockchain and returns the return value of the function -func (rc *NodeClient) View(payload *ViewPayload, ledgerVersion ...uint64) (data []any, err error) { +func (rc *NodeClient) View(ctx context.Context, payload *ViewPayload, ledgerVersion ...uint64) (data []any, err error) { serializer := bcs.Serializer{} payload.MarshalBCS(&serializer) err = serializer.Error() @@ -955,7 +959,7 @@ func (rc *NodeClient) View(payload *ViewPayload, ledgerVersion ...uint64) (data au.RawQuery = params.Encode() } - data, err = Post[[]any](rc, au.String(), ContentTypeAptosViewFunctionBcs, bodyReader) + data, err = Post[[]any](ctx, rc, au.String(), ContentTypeAptosViewFunctionBcs, bodyReader) if err != nil { return nil, fmt.Errorf("view function api err: %w", err) } @@ -964,9 +968,9 @@ func (rc *NodeClient) View(payload *ViewPayload, ledgerVersion ...uint64) (data // EstimateGasPrice estimates the gas price given on-chain data // TODO: add caching for some period of time -func (rc *NodeClient) EstimateGasPrice() (info EstimateGasInfo, err error) { +func (rc *NodeClient) EstimateGasPrice(ctx context.Context) (info EstimateGasInfo, err error) { au := rc.baseUrl.JoinPath("estimate_gas_price") - info, err = Get[EstimateGasInfo](rc, au.String()) + info, err = Get[EstimateGasInfo](ctx, rc, au.String()) if err != nil { return info, fmt.Errorf("estimate gas price err: %w", err) } @@ -974,12 +978,12 @@ func (rc *NodeClient) EstimateGasPrice() (info EstimateGasInfo, err error) { } // AccountAPTBalance fetches the balance of an account of APT. Response is in octas or 1/10^8 APT. -func (rc *NodeClient) AccountAPTBalance(account AccountAddress, ledgerVersion ...uint64) (balance uint64, err error) { +func (rc *NodeClient) AccountAPTBalance(ctx context.Context, account AccountAddress, ledgerVersion ...uint64) (balance uint64, err error) { accountBytes, err := bcs.Serialize(&account) if err != nil { return 0, err } - values, err := rc.View(&ViewPayload{Module: ModuleId{ + values, err := rc.View(ctx, &ViewPayload{Module: ModuleId{ Address: AccountOne, Name: "coin", }, @@ -994,8 +998,8 @@ func (rc *NodeClient) AccountAPTBalance(account AccountAddress, ledgerVersion .. } // BuildSignAndSubmitTransaction builds, signs, and submits a transaction to the network -func (rc *NodeClient) BuildSignAndSubmitTransaction(sender TransactionSigner, payload TransactionPayload, options ...any) (data *api.SubmitTransactionResponse, err error) { - rawTxn, err := rc.BuildTransaction(sender.AccountAddress(), payload, options...) +func (rc *NodeClient) BuildSignAndSubmitTransaction(ctx context.Context, sender TransactionSigner, payload TransactionPayload, options ...any) (data *api.SubmitTransactionResponse, err error) { + rawTxn, err := rc.BuildTransaction(ctx, sender.AccountAddress(), payload, options...) if err != nil { return nil, err } @@ -1003,20 +1007,20 @@ func (rc *NodeClient) BuildSignAndSubmitTransaction(sender TransactionSigner, pa if err != nil { return nil, err } - return rc.SubmitTransaction(signedTxn) + return rc.SubmitTransaction(ctx, signedTxn) } // NodeAPIHealthCheck performs a health check on the node // // Returns a HealthCheckResponse if successful, returns error if not. -func (rc *NodeClient) NodeAPIHealthCheck(durationSecs ...uint64) (api.HealthCheckResponse, error) { +func (rc *NodeClient) NodeAPIHealthCheck(ctx context.Context, durationSecs ...uint64) (api.HealthCheckResponse, error) { au := rc.baseUrl.JoinPath("-/healthy") if len(durationSecs) > 0 { params := url.Values{} params.Set("duration_secs", strconv.FormatUint(durationSecs[0], 10)) au.RawQuery = params.Encode() } - return Get[api.HealthCheckResponse](rc, au.String()) + return Get[api.HealthCheckResponse](ctx, rc, au.String()) } // NodeHealthCheck performs a health check on the node @@ -1024,13 +1028,13 @@ func (rc *NodeClient) NodeAPIHealthCheck(durationSecs ...uint64) (api.HealthChec // Returns a HealthCheckResponse if successful, returns error if not. // // Deprecated: Use NodeAPIHealthCheck instead -func (rc *NodeClient) NodeHealthCheck(durationSecs ...uint64) (api.HealthCheckResponse, error) { - return rc.NodeAPIHealthCheck(durationSecs...) +func (rc *NodeClient) NodeHealthCheck(ctx context.Context, durationSecs ...uint64) (api.HealthCheckResponse, error) { + return rc.NodeAPIHealthCheck(ctx, durationSecs...) } // Get makes a GET request to the endpoint and parses the response into the given type with JSON -func Get[T any](rc *NodeClient, getUrl string) (out T, err error) { - req, err := http.NewRequest("GET", getUrl, nil) +func Get[T any](ctx context.Context, rc *NodeClient, getUrl string) (out T, err error) { + req, err := http.NewRequestWithContext(ctx, "GET", getUrl, nil) if err != nil { return out, err } @@ -1043,6 +1047,9 @@ func Get[T any](rc *NodeClient, getUrl string) (out T, err error) { response, err := rc.client.Do(req) if err != nil { + if errors.Is(err, ctx.Err()) { + return out, err + } err = fmt.Errorf("GET %s, %w", getUrl, err) return out, err } @@ -1064,8 +1071,8 @@ func Get[T any](rc *NodeClient, getUrl string) (out T, err error) { } // GetBCS makes a GET request to the endpoint and parses the response into the given type with BCS -func (rc *NodeClient) GetBCS(getUrl string) (out []byte, err error) { - req, err := http.NewRequest("GET", getUrl, nil) +func (rc *NodeClient) GetBCS(ctx context.Context, getUrl string) (out []byte, err error) { + req, err := http.NewRequestWithContext(ctx, "GET", getUrl, nil) if err != nil { return nil, err } @@ -1096,11 +1103,11 @@ func (rc *NodeClient) GetBCS(getUrl string) (out []byte, err error) { } // Post makes a POST request to the endpoint with the given body and parses the response into the given type with JSON -func Post[T any](rc *NodeClient, postUrl string, contentType string, body io.Reader) (data T, err error) { +func Post[T any](ctx context.Context, rc *NodeClient, postUrl string, contentType string, body io.Reader) (data T, err error) { if body == nil { body = http.NoBody } - req, err := http.NewRequest("POST", postUrl, body) + req, err := http.NewRequestWithContext(ctx, "POST", postUrl, body) if err != nil { return data, err } diff --git a/nodeClient_test.go b/nodeClient_test.go index fa663bd..1b8748a 100644 --- a/nodeClient_test.go +++ b/nodeClient_test.go @@ -1,9 +1,11 @@ package aptos import ( - "github.com/stretchr/testify/assert" + "context" "testing" "time" + + "github.com/stretchr/testify/assert" ) func TestPollForTransaction(t *testing.T) { @@ -13,7 +15,7 @@ func TestPollForTransaction(t *testing.T) { assert.NoError(t, err) start := time.Now() - err = client.PollForTransactions([]string{"alice", "bob"}, PollTimeout(10*time.Millisecond), PollPeriod(2*time.Millisecond)) + err = client.PollForTransactions(context.Background(), []string{"alice", "bob"}, PollTimeout(10*time.Millisecond), PollPeriod(2*time.Millisecond)) dt := time.Now().Sub(start) assert.GreaterOrEqual(t, dt, 9*time.Millisecond) diff --git a/transactionSubmission.go b/transactionSubmission.go index e0f454d..c9dd084 100644 --- a/transactionSubmission.go +++ b/transactionSubmission.go @@ -1,6 +1,7 @@ package aptos import ( + "context" "fmt" "sync" "sync/atomic" @@ -66,9 +67,9 @@ func (client *Client) BuildTransactions(sender AccountAddress, payloads chan Tra } // BuildTransactions start a goroutine to process [TransactionPayload] and spit out [RawTransactionImpl]. -func (rc *NodeClient) BuildTransactions(sender AccountAddress, payloads chan TransactionBuildPayload, responses chan TransactionBuildResponse, setSequenceNumber chan uint64, options ...any) { +func (rc *NodeClient) BuildTransactions(ctx context.Context, sender AccountAddress, payloads chan TransactionBuildPayload, responses chan TransactionBuildResponse, setSequenceNumber chan uint64, options ...any) { // Initialize state - account, err := rc.Account(sender) + account, err := rc.Account(ctx, sender) if err != nil { responses <- TransactionBuildResponse{Err: err} close(responses) @@ -97,7 +98,7 @@ func (rc *NodeClient) BuildTransactions(sender AccountAddress, payloads chan Tra case TransactionSubmissionTypeSingle: curSequenceNumber := snt.Increment() options[optionsLast] = SequenceNumber(curSequenceNumber) - txnResponse, err := rc.BuildTransaction(sender, payload.Inner, options...) + txnResponse, err := rc.BuildTransaction(ctx, sender, payload.Inner, options...) if err != nil { responses <- TransactionBuildResponse{Err: err} } else { @@ -106,7 +107,7 @@ func (rc *NodeClient) BuildTransactions(sender AccountAddress, payloads chan Tra case TransactionSubmissionTypeMultiAgent: curSequenceNumber := snt.Increment() options[optionsLast] = SequenceNumber(curSequenceNumber) - txnResponse, err := rc.BuildTransactionMultiAgent(sender, payload.Inner, options...) + txnResponse, err := rc.BuildTransactionMultiAgent(ctx, sender, payload.Inner, options...) if err != nil { responses <- TransactionBuildResponse{Err: err} } else { @@ -125,16 +126,16 @@ func (rc *NodeClient) BuildTransactions(sender AccountAddress, payloads chan Tra // SubmitTransactions consumes signed transactions, submits to aptos-node, yields responses. // closes output chan `responses` when input chan `signedTxns` is closed. -func (client *Client) SubmitTransactions(requests chan TransactionSubmissionRequest, responses chan TransactionSubmissionResponse) { - client.nodeClient.SubmitTransactions(requests, responses) +func (client *Client) SubmitTransactions(ctx context.Context, requests chan TransactionSubmissionRequest, responses chan TransactionSubmissionResponse) { + client.nodeClient.SubmitTransactions(ctx, requests, responses) } // SubmitTransactions consumes signed transactions, submits to aptos-node, yields responses. // closes output chan `responses` when input chan `signedTxns` is closed. -func (rc *NodeClient) SubmitTransactions(requests chan TransactionSubmissionRequest, responses chan TransactionSubmissionResponse) { +func (rc *NodeClient) SubmitTransactions(ctx context.Context, requests chan TransactionSubmissionRequest, responses chan TransactionSubmissionResponse) { defer close(responses) for request := range requests { - response, err := rc.SubmitTransaction(request.SignedTxn) + response, err := rc.SubmitTransaction(ctx, request.SignedTxn) if err != nil { responses <- TransactionSubmissionResponse{Id: request.Id, Err: err} } else { @@ -145,7 +146,7 @@ func (rc *NodeClient) SubmitTransactions(requests chan TransactionSubmissionRequ // BatchSubmitTransactions consumes signed transactions, submits to aptos-node, yields responses. // closes output chan `responses` when input chan `signedTxns` is closed. -func (rc *NodeClient) BatchSubmitTransactions(requests chan TransactionSubmissionRequest, responses chan TransactionSubmissionResponse) { +func (rc *NodeClient) BatchSubmitTransactions(ctx context.Context, requests chan TransactionSubmissionRequest, responses chan TransactionSubmissionResponse) { defer close(responses) inputs := make([]*SignedTransaction, 20) @@ -160,7 +161,7 @@ func (rc *NodeClient) BatchSubmitTransactions(requests chan TransactionSubmissio if i >= 19 { i = 0 - response, err := rc.BatchSubmitTransaction(inputs) + response, err := rc.BatchSubmitTransaction(ctx, inputs) // Process the responses if err != nil { @@ -195,17 +196,19 @@ func (rc *NodeClient) BatchSubmitTransactions(requests chan TransactionSubmissio // BuildSignAndSubmitTransactions starts up a goroutine to process transactions for a single [TransactionSender] // Closes output chan `responses` on completion of input chan `payloads`. func (client *Client) BuildSignAndSubmitTransactions( + ctx context.Context, sender TransactionSigner, payloads chan TransactionBuildPayload, responses chan TransactionSubmissionResponse, buildOptions ...any, ) { - client.nodeClient.BuildSignAndSubmitTransactions(sender, payloads, responses, buildOptions...) + client.nodeClient.BuildSignAndSubmitTransactions(ctx, sender, payloads, responses, buildOptions...) } // BuildSignAndSubmitTransactions starts up a goroutine to process transactions for a single [TransactionSender] // Closes output chan `responses` on completion of input chan `payloads`. func (rc *NodeClient) BuildSignAndSubmitTransactions( + ctx context.Context, sender TransactionSigner, payloads chan TransactionBuildPayload, responses chan TransactionSubmissionResponse, @@ -230,6 +233,7 @@ func (rc *NodeClient) BuildSignAndSubmitTransactions( } rc.BuildSignAndSubmitTransactionsWithSignFunction( + ctx, sender.AccountAddress(), payloads, responses, @@ -285,6 +289,7 @@ func (rc *NodeClient) BuildSignAndSubmitTransactions( // // } func (client *Client) BuildSignAndSubmitTransactionsWithSignFunction( + ctx context.Context, sender AccountAddress, payloads chan TransactionBuildPayload, responses chan TransactionSubmissionResponse, @@ -292,6 +297,7 @@ func (client *Client) BuildSignAndSubmitTransactionsWithSignFunction( buildOptions ...any, ) { client.nodeClient.BuildSignAndSubmitTransactionsWithSignFunction( + ctx, sender, payloads, responses, @@ -347,6 +353,7 @@ func (client *Client) BuildSignAndSubmitTransactionsWithSignFunction( // // } func (rc *NodeClient) BuildSignAndSubmitTransactionsWithSignFunction( + ctx context.Context, sender AccountAddress, payloads chan TransactionBuildPayload, responses chan TransactionSubmissionResponse, @@ -358,12 +365,12 @@ func (rc *NodeClient) BuildSignAndSubmitTransactionsWithSignFunction( // Set up the channel handling building transactions buildResponses := make(chan TransactionBuildResponse, 20) setSequenceNumber := make(chan uint64) - go rc.BuildTransactions(sender, payloads, buildResponses, setSequenceNumber, buildOptions...) + go rc.BuildTransactions(ctx, sender, payloads, buildResponses, setSequenceNumber, buildOptions...) submissionRequests := make(chan TransactionSubmissionRequest, 20) // Note that, I change this to BatchSubmitTransactions, and it caused no change in performance. The non-batched // version is more flexible and gives actual responses. It is may be that with large payloads that batch more performant. - go rc.SubmitTransactions(submissionRequests, responses) + go rc.SubmitTransactions(ctx, submissionRequests, responses) var wg sync.WaitGroup From 8867a6a6efc1819cccd87c85d9b3795205622ac4 Mon Sep 17 00:00:00 2001 From: Exca-DK Date: Sun, 16 Feb 2025 15:20:29 +0100 Subject: [PATCH 2/2] Update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index da919ce..ac95c51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ adheres to the format set out by [Keep a Changelog](https://keepachangelog.com/e # Unreleased +- [`Breaking`] Exposed `context.Context` parameter, enabling explicit request cancellation and timeout management. + # v1.5.0 (2/10/2024) - [`Fix`] Make NodeClient match AptosRpcClient interface