github.com/ethereum/go-ethereum@v1.16.1/ethclient/ethclient.go (about)

     1  // Copyright 2016 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // Package ethclient provides a client for the Ethereum RPC API.
    18  package ethclient
    19  
    20  import (
    21  	"context"
    22  	"encoding/json"
    23  	"errors"
    24  	"fmt"
    25  	"math/big"
    26  
    27  	"github.com/ethereum/go-ethereum"
    28  	"github.com/ethereum/go-ethereum/common"
    29  	"github.com/ethereum/go-ethereum/common/hexutil"
    30  	"github.com/ethereum/go-ethereum/core/types"
    31  	"github.com/ethereum/go-ethereum/rpc"
    32  )
    33  
    34  // Client defines typed wrappers for the Ethereum RPC API.
    35  type Client struct {
    36  	c *rpc.Client
    37  }
    38  
    39  // Dial connects a client to the given URL.
    40  func Dial(rawurl string) (*Client, error) {
    41  	return DialContext(context.Background(), rawurl)
    42  }
    43  
    44  // DialContext connects a client to the given URL with context.
    45  func DialContext(ctx context.Context, rawurl string) (*Client, error) {
    46  	c, err := rpc.DialContext(ctx, rawurl)
    47  	if err != nil {
    48  		return nil, err
    49  	}
    50  	return NewClient(c), nil
    51  }
    52  
    53  // NewClient creates a client that uses the given RPC client.
    54  func NewClient(c *rpc.Client) *Client {
    55  	return &Client{c}
    56  }
    57  
    58  // Close closes the underlying RPC connection.
    59  func (ec *Client) Close() {
    60  	ec.c.Close()
    61  }
    62  
    63  // Client gets the underlying RPC client.
    64  func (ec *Client) Client() *rpc.Client {
    65  	return ec.c
    66  }
    67  
    68  // Blockchain Access
    69  
    70  // ChainID retrieves the current chain ID for transaction replay protection.
    71  func (ec *Client) ChainID(ctx context.Context) (*big.Int, error) {
    72  	var result hexutil.Big
    73  	err := ec.c.CallContext(ctx, &result, "eth_chainId")
    74  	if err != nil {
    75  		return nil, err
    76  	}
    77  	return (*big.Int)(&result), err
    78  }
    79  
    80  // BlockByHash returns the given full block.
    81  //
    82  // Note that loading full blocks requires two requests. Use HeaderByHash
    83  // if you don't need all transactions or uncle headers.
    84  func (ec *Client) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
    85  	return ec.getBlock(ctx, "eth_getBlockByHash", hash, true)
    86  }
    87  
    88  // BlockByNumber returns a block from the current canonical chain.
    89  // If `number` is nil, the latest known block is returned.
    90  //
    91  // Use `HeaderByNumber` if you don't need full transaction data or uncle headers.
    92  //
    93  // Supported special block number tags:
    94  // - `earliest`  : The genesis (earliest) block
    95  // - `latest`    : The most recently included block
    96  // - `safe`      : The latest safe head block
    97  // - `finalized` : The latest finalized block
    98  // - `pending`   : The pending block
    99  //
   100  // Example usage:
   101  //
   102  // ```go
   103  // BlockByNumber(context.Background(), big.NewInt(int64(rpc.LatestBlockNumber)))
   104  // ```
   105  func (ec *Client) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) {
   106  	return ec.getBlock(ctx, "eth_getBlockByNumber", toBlockNumArg(number), true)
   107  }
   108  
   109  // BlockNumber returns the most recent block number
   110  func (ec *Client) BlockNumber(ctx context.Context) (uint64, error) {
   111  	var result hexutil.Uint64
   112  	err := ec.c.CallContext(ctx, &result, "eth_blockNumber")
   113  	return uint64(result), err
   114  }
   115  
   116  // PeerCount returns the number of p2p peers as reported by the net_peerCount method.
   117  func (ec *Client) PeerCount(ctx context.Context) (uint64, error) {
   118  	var result hexutil.Uint64
   119  	err := ec.c.CallContext(ctx, &result, "net_peerCount")
   120  	return uint64(result), err
   121  }
   122  
   123  // BlockReceipts returns the receipts of a given block number or hash.
   124  func (ec *Client) BlockReceipts(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) ([]*types.Receipt, error) {
   125  	var r []*types.Receipt
   126  	err := ec.c.CallContext(ctx, &r, "eth_getBlockReceipts", blockNrOrHash.String())
   127  	if err == nil && r == nil {
   128  		return nil, ethereum.NotFound
   129  	}
   130  	return r, err
   131  }
   132  
   133  type rpcBlock struct {
   134  	Hash         *common.Hash        `json:"hash"`
   135  	Transactions []rpcTransaction    `json:"transactions"`
   136  	UncleHashes  []common.Hash       `json:"uncles"`
   137  	Withdrawals  []*types.Withdrawal `json:"withdrawals,omitempty"`
   138  }
   139  
   140  func (ec *Client) getBlock(ctx context.Context, method string, args ...interface{}) (*types.Block, error) {
   141  	var raw json.RawMessage
   142  	err := ec.c.CallContext(ctx, &raw, method, args...)
   143  	if err != nil {
   144  		return nil, err
   145  	}
   146  
   147  	// Decode header and transactions.
   148  	var head *types.Header
   149  	if err := json.Unmarshal(raw, &head); err != nil {
   150  		return nil, err
   151  	}
   152  	// When the block is not found, the API returns JSON null.
   153  	if head == nil {
   154  		return nil, ethereum.NotFound
   155  	}
   156  
   157  	var body rpcBlock
   158  	if err := json.Unmarshal(raw, &body); err != nil {
   159  		return nil, err
   160  	}
   161  	// Pending blocks don't return a block hash, compute it for sender caching.
   162  	if body.Hash == nil {
   163  		tmp := head.Hash()
   164  		body.Hash = &tmp
   165  	}
   166  
   167  	// Quick-verify transaction and uncle lists. This mostly helps with debugging the server.
   168  	if head.UncleHash == types.EmptyUncleHash && len(body.UncleHashes) > 0 {
   169  		return nil, errors.New("server returned non-empty uncle list but block header indicates no uncles")
   170  	}
   171  	if head.UncleHash != types.EmptyUncleHash && len(body.UncleHashes) == 0 {
   172  		return nil, errors.New("server returned empty uncle list but block header indicates uncles")
   173  	}
   174  	if head.TxHash == types.EmptyTxsHash && len(body.Transactions) > 0 {
   175  		return nil, errors.New("server returned non-empty transaction list but block header indicates no transactions")
   176  	}
   177  	if head.TxHash != types.EmptyTxsHash && len(body.Transactions) == 0 {
   178  		return nil, errors.New("server returned empty transaction list but block header indicates transactions")
   179  	}
   180  	// Load uncles because they are not included in the block response.
   181  	var uncles []*types.Header
   182  	if len(body.UncleHashes) > 0 {
   183  		uncles = make([]*types.Header, len(body.UncleHashes))
   184  		reqs := make([]rpc.BatchElem, len(body.UncleHashes))
   185  		for i := range reqs {
   186  			reqs[i] = rpc.BatchElem{
   187  				Method: "eth_getUncleByBlockHashAndIndex",
   188  				Args:   []interface{}{body.Hash, hexutil.EncodeUint64(uint64(i))},
   189  				Result: &uncles[i],
   190  			}
   191  		}
   192  		if err := ec.c.BatchCallContext(ctx, reqs); err != nil {
   193  			return nil, err
   194  		}
   195  		for i := range reqs {
   196  			if reqs[i].Error != nil {
   197  				return nil, reqs[i].Error
   198  			}
   199  			if uncles[i] == nil {
   200  				return nil, fmt.Errorf("got null header for uncle %d of block %x", i, body.Hash[:])
   201  			}
   202  		}
   203  	}
   204  	// Fill the sender cache of transactions in the block.
   205  	txs := make([]*types.Transaction, len(body.Transactions))
   206  	for i, tx := range body.Transactions {
   207  		if tx.From != nil {
   208  			setSenderFromServer(tx.tx, *tx.From, *body.Hash)
   209  		}
   210  		txs[i] = tx.tx
   211  	}
   212  
   213  	return types.NewBlockWithHeader(head).WithBody(
   214  		types.Body{
   215  			Transactions: txs,
   216  			Uncles:       uncles,
   217  			Withdrawals:  body.Withdrawals,
   218  		}), nil
   219  }
   220  
   221  // HeaderByHash returns the block header with the given hash.
   222  func (ec *Client) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
   223  	var head *types.Header
   224  	err := ec.c.CallContext(ctx, &head, "eth_getBlockByHash", hash, false)
   225  	if err == nil && head == nil {
   226  		err = ethereum.NotFound
   227  	}
   228  	return head, err
   229  }
   230  
   231  // HeaderByNumber returns a block header from the current canonical chain.
   232  // If `number` is nil, the latest known block header is returned.
   233  //
   234  // Supported special block number tags:
   235  // - `earliest`  : The genesis (earliest) block
   236  // - `latest`    : The most recently included block
   237  // - `safe`      : The latest safe head block
   238  // - `finalized` : The latest finalized block
   239  // - `pending`   : The pending block
   240  //
   241  // Example usage:
   242  //
   243  // ```go
   244  // HeaderByNumber(context.Background(), big.NewInt(int64(rpc.LatestBlockNumber)))
   245  // ```
   246  func (ec *Client) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) {
   247  	var head *types.Header
   248  	err := ec.c.CallContext(ctx, &head, "eth_getBlockByNumber", toBlockNumArg(number), false)
   249  	if err == nil && head == nil {
   250  		err = ethereum.NotFound
   251  	}
   252  	return head, err
   253  }
   254  
   255  type rpcTransaction struct {
   256  	tx *types.Transaction
   257  	txExtraInfo
   258  }
   259  
   260  type txExtraInfo struct {
   261  	BlockNumber *string         `json:"blockNumber,omitempty"`
   262  	BlockHash   *common.Hash    `json:"blockHash,omitempty"`
   263  	From        *common.Address `json:"from,omitempty"`
   264  }
   265  
   266  func (tx *rpcTransaction) UnmarshalJSON(msg []byte) error {
   267  	if err := json.Unmarshal(msg, &tx.tx); err != nil {
   268  		return err
   269  	}
   270  	return json.Unmarshal(msg, &tx.txExtraInfo)
   271  }
   272  
   273  // TransactionByHash returns the transaction with the given hash.
   274  func (ec *Client) TransactionByHash(ctx context.Context, hash common.Hash) (tx *types.Transaction, isPending bool, err error) {
   275  	var json *rpcTransaction
   276  	err = ec.c.CallContext(ctx, &json, "eth_getTransactionByHash", hash)
   277  	if err != nil {
   278  		return nil, false, err
   279  	} else if json == nil {
   280  		return nil, false, ethereum.NotFound
   281  	} else if _, r, _ := json.tx.RawSignatureValues(); r == nil {
   282  		return nil, false, errors.New("server returned transaction without signature")
   283  	}
   284  	if json.From != nil && json.BlockHash != nil {
   285  		setSenderFromServer(json.tx, *json.From, *json.BlockHash)
   286  	}
   287  	return json.tx, json.BlockNumber == nil, nil
   288  }
   289  
   290  // TransactionSender returns the sender address of the given transaction. The transaction
   291  // must be known to the remote node and included in the blockchain at the given block and
   292  // index. The sender is the one derived by the protocol at the time of inclusion.
   293  //
   294  // There is a fast-path for transactions retrieved by TransactionByHash and
   295  // TransactionInBlock. Getting their sender address can be done without an RPC interaction.
   296  func (ec *Client) TransactionSender(ctx context.Context, tx *types.Transaction, block common.Hash, index uint) (common.Address, error) {
   297  	// Try to load the address from the cache.
   298  	sender, err := types.Sender(&senderFromServer{blockhash: block}, tx)
   299  	if err == nil {
   300  		return sender, nil
   301  	}
   302  
   303  	// It was not found in cache, ask the server.
   304  	var meta struct {
   305  		Hash common.Hash
   306  		From common.Address
   307  	}
   308  	if err = ec.c.CallContext(ctx, &meta, "eth_getTransactionByBlockHashAndIndex", block, hexutil.Uint64(index)); err != nil {
   309  		return common.Address{}, err
   310  	}
   311  	if meta.Hash == (common.Hash{}) || meta.Hash != tx.Hash() {
   312  		return common.Address{}, errors.New("wrong inclusion block/index")
   313  	}
   314  	return meta.From, nil
   315  }
   316  
   317  // TransactionCount returns the total number of transactions in the given block.
   318  func (ec *Client) TransactionCount(ctx context.Context, blockHash common.Hash) (uint, error) {
   319  	var num hexutil.Uint
   320  	err := ec.c.CallContext(ctx, &num, "eth_getBlockTransactionCountByHash", blockHash)
   321  	return uint(num), err
   322  }
   323  
   324  // TransactionInBlock returns a single transaction at index in the given block.
   325  func (ec *Client) TransactionInBlock(ctx context.Context, blockHash common.Hash, index uint) (*types.Transaction, error) {
   326  	var json *rpcTransaction
   327  	err := ec.c.CallContext(ctx, &json, "eth_getTransactionByBlockHashAndIndex", blockHash, hexutil.Uint64(index))
   328  	if err != nil {
   329  		return nil, err
   330  	}
   331  	if json == nil {
   332  		return nil, ethereum.NotFound
   333  	} else if _, r, _ := json.tx.RawSignatureValues(); r == nil {
   334  		return nil, errors.New("server returned transaction without signature")
   335  	}
   336  	if json.From != nil && json.BlockHash != nil {
   337  		setSenderFromServer(json.tx, *json.From, *json.BlockHash)
   338  	}
   339  	return json.tx, err
   340  }
   341  
   342  // TransactionReceipt returns the receipt of a transaction by transaction hash.
   343  // Note that the receipt is not available for pending transactions.
   344  func (ec *Client) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) {
   345  	var r *types.Receipt
   346  	err := ec.c.CallContext(ctx, &r, "eth_getTransactionReceipt", txHash)
   347  	if err == nil && r == nil {
   348  		return nil, ethereum.NotFound
   349  	}
   350  	return r, err
   351  }
   352  
   353  // SyncProgress retrieves the current progress of the sync algorithm. If there's
   354  // no sync currently running, it returns nil.
   355  func (ec *Client) SyncProgress(ctx context.Context) (*ethereum.SyncProgress, error) {
   356  	var raw json.RawMessage
   357  	if err := ec.c.CallContext(ctx, &raw, "eth_syncing"); err != nil {
   358  		return nil, err
   359  	}
   360  	// Handle the possible response types
   361  	var syncing bool
   362  	if err := json.Unmarshal(raw, &syncing); err == nil {
   363  		return nil, nil // Not syncing (always false)
   364  	}
   365  	var p *rpcProgress
   366  	if err := json.Unmarshal(raw, &p); err != nil {
   367  		return nil, err
   368  	}
   369  	return p.toSyncProgress(), nil
   370  }
   371  
   372  // SubscribeNewHead subscribes to notifications about the current blockchain head
   373  // on the given channel.
   374  func (ec *Client) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) {
   375  	sub, err := ec.c.EthSubscribe(ctx, ch, "newHeads")
   376  	if err != nil {
   377  		// Defensively prefer returning nil interface explicitly on error-path, instead
   378  		// of letting default golang behavior wrap it with non-nil interface that stores
   379  		// nil concrete type value.
   380  		return nil, err
   381  	}
   382  	return sub, nil
   383  }
   384  
   385  // State Access
   386  
   387  // NetworkID returns the network ID for this client.
   388  func (ec *Client) NetworkID(ctx context.Context) (*big.Int, error) {
   389  	version := new(big.Int)
   390  	var ver string
   391  	if err := ec.c.CallContext(ctx, &ver, "net_version"); err != nil {
   392  		return nil, err
   393  	}
   394  	if _, ok := version.SetString(ver, 0); !ok {
   395  		return nil, fmt.Errorf("invalid net_version result %q", ver)
   396  	}
   397  	return version, nil
   398  }
   399  
   400  // BalanceAt returns the wei balance of the given account.
   401  // The block number can be nil, in which case the balance is taken from the latest known block.
   402  func (ec *Client) BalanceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (*big.Int, error) {
   403  	var result hexutil.Big
   404  	err := ec.c.CallContext(ctx, &result, "eth_getBalance", account, toBlockNumArg(blockNumber))
   405  	return (*big.Int)(&result), err
   406  }
   407  
   408  // BalanceAtHash returns the wei balance of the given account.
   409  func (ec *Client) BalanceAtHash(ctx context.Context, account common.Address, blockHash common.Hash) (*big.Int, error) {
   410  	var result hexutil.Big
   411  	err := ec.c.CallContext(ctx, &result, "eth_getBalance", account, rpc.BlockNumberOrHashWithHash(blockHash, false))
   412  	return (*big.Int)(&result), err
   413  }
   414  
   415  // StorageAt returns the value of key in the contract storage of the given account.
   416  // The block number can be nil, in which case the value is taken from the latest known block.
   417  func (ec *Client) StorageAt(ctx context.Context, account common.Address, key common.Hash, blockNumber *big.Int) ([]byte, error) {
   418  	var result hexutil.Bytes
   419  	err := ec.c.CallContext(ctx, &result, "eth_getStorageAt", account, key, toBlockNumArg(blockNumber))
   420  	return result, err
   421  }
   422  
   423  // StorageAtHash returns the value of key in the contract storage of the given account.
   424  func (ec *Client) StorageAtHash(ctx context.Context, account common.Address, key common.Hash, blockHash common.Hash) ([]byte, error) {
   425  	var result hexutil.Bytes
   426  	err := ec.c.CallContext(ctx, &result, "eth_getStorageAt", account, key, rpc.BlockNumberOrHashWithHash(blockHash, false))
   427  	return result, err
   428  }
   429  
   430  // CodeAt returns the contract code of the given account.
   431  // The block number can be nil, in which case the code is taken from the latest known block.
   432  func (ec *Client) CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error) {
   433  	var result hexutil.Bytes
   434  	err := ec.c.CallContext(ctx, &result, "eth_getCode", account, toBlockNumArg(blockNumber))
   435  	return result, err
   436  }
   437  
   438  // CodeAtHash returns the contract code of the given account.
   439  func (ec *Client) CodeAtHash(ctx context.Context, account common.Address, blockHash common.Hash) ([]byte, error) {
   440  	var result hexutil.Bytes
   441  	err := ec.c.CallContext(ctx, &result, "eth_getCode", account, rpc.BlockNumberOrHashWithHash(blockHash, false))
   442  	return result, err
   443  }
   444  
   445  // NonceAt returns the account nonce of the given account.
   446  // The block number can be nil, in which case the nonce is taken from the latest known block.
   447  func (ec *Client) NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) {
   448  	var result hexutil.Uint64
   449  	err := ec.c.CallContext(ctx, &result, "eth_getTransactionCount", account, toBlockNumArg(blockNumber))
   450  	return uint64(result), err
   451  }
   452  
   453  // NonceAtHash returns the account nonce of the given account.
   454  func (ec *Client) NonceAtHash(ctx context.Context, account common.Address, blockHash common.Hash) (uint64, error) {
   455  	var result hexutil.Uint64
   456  	err := ec.c.CallContext(ctx, &result, "eth_getTransactionCount", account, rpc.BlockNumberOrHashWithHash(blockHash, false))
   457  	return uint64(result), err
   458  }
   459  
   460  // Filters
   461  
   462  // FilterLogs executes a filter query.
   463  func (ec *Client) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) {
   464  	var result []types.Log
   465  	arg, err := toFilterArg(q)
   466  	if err != nil {
   467  		return nil, err
   468  	}
   469  	err = ec.c.CallContext(ctx, &result, "eth_getLogs", arg)
   470  	return result, err
   471  }
   472  
   473  // SubscribeFilterLogs subscribes to the results of a streaming filter query.
   474  func (ec *Client) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) {
   475  	arg, err := toFilterArg(q)
   476  	if err != nil {
   477  		return nil, err
   478  	}
   479  	sub, err := ec.c.EthSubscribe(ctx, ch, "logs", arg)
   480  	if err != nil {
   481  		// Defensively prefer returning nil interface explicitly on error-path, instead
   482  		// of letting default golang behavior wrap it with non-nil interface that stores
   483  		// nil concrete type value.
   484  		return nil, err
   485  	}
   486  	return sub, nil
   487  }
   488  
   489  func toFilterArg(q ethereum.FilterQuery) (interface{}, error) {
   490  	arg := map[string]interface{}{
   491  		"address": q.Addresses,
   492  		"topics":  q.Topics,
   493  	}
   494  	if q.BlockHash != nil {
   495  		arg["blockHash"] = *q.BlockHash
   496  		if q.FromBlock != nil || q.ToBlock != nil {
   497  			return nil, errors.New("cannot specify both BlockHash and FromBlock/ToBlock")
   498  		}
   499  	} else {
   500  		if q.FromBlock == nil {
   501  			arg["fromBlock"] = "0x0"
   502  		} else {
   503  			arg["fromBlock"] = toBlockNumArg(q.FromBlock)
   504  		}
   505  		arg["toBlock"] = toBlockNumArg(q.ToBlock)
   506  	}
   507  	return arg, nil
   508  }
   509  
   510  // Pending State
   511  
   512  // PendingBalanceAt returns the wei balance of the given account in the pending state.
   513  func (ec *Client) PendingBalanceAt(ctx context.Context, account common.Address) (*big.Int, error) {
   514  	var result hexutil.Big
   515  	err := ec.c.CallContext(ctx, &result, "eth_getBalance", account, "pending")
   516  	return (*big.Int)(&result), err
   517  }
   518  
   519  // PendingStorageAt returns the value of key in the contract storage of the given account in the pending state.
   520  func (ec *Client) PendingStorageAt(ctx context.Context, account common.Address, key common.Hash) ([]byte, error) {
   521  	var result hexutil.Bytes
   522  	err := ec.c.CallContext(ctx, &result, "eth_getStorageAt", account, key, "pending")
   523  	return result, err
   524  }
   525  
   526  // PendingCodeAt returns the contract code of the given account in the pending state.
   527  func (ec *Client) PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error) {
   528  	var result hexutil.Bytes
   529  	err := ec.c.CallContext(ctx, &result, "eth_getCode", account, "pending")
   530  	return result, err
   531  }
   532  
   533  // PendingNonceAt returns the account nonce of the given account in the pending state.
   534  // This is the nonce that should be used for the next transaction.
   535  func (ec *Client) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) {
   536  	var result hexutil.Uint64
   537  	err := ec.c.CallContext(ctx, &result, "eth_getTransactionCount", account, "pending")
   538  	return uint64(result), err
   539  }
   540  
   541  // PendingTransactionCount returns the total number of transactions in the pending state.
   542  func (ec *Client) PendingTransactionCount(ctx context.Context) (uint, error) {
   543  	var num hexutil.Uint
   544  	err := ec.c.CallContext(ctx, &num, "eth_getBlockTransactionCountByNumber", "pending")
   545  	return uint(num), err
   546  }
   547  
   548  // Contract Calling
   549  
   550  // CallContract executes a message call transaction, which is directly executed in the VM
   551  // of the node, but never mined into the blockchain.
   552  //
   553  // blockNumber selects the block height at which the call runs. It can be nil, in which
   554  // case the code is taken from the latest known block. Note that state from very old
   555  // blocks might not be available.
   556  func (ec *Client) CallContract(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) {
   557  	var hex hexutil.Bytes
   558  	err := ec.c.CallContext(ctx, &hex, "eth_call", toCallArg(msg), toBlockNumArg(blockNumber))
   559  	if err != nil {
   560  		return nil, err
   561  	}
   562  	return hex, nil
   563  }
   564  
   565  // CallContractAtHash is almost the same as CallContract except that it selects
   566  // the block by block hash instead of block height.
   567  func (ec *Client) CallContractAtHash(ctx context.Context, msg ethereum.CallMsg, blockHash common.Hash) ([]byte, error) {
   568  	var hex hexutil.Bytes
   569  	err := ec.c.CallContext(ctx, &hex, "eth_call", toCallArg(msg), rpc.BlockNumberOrHashWithHash(blockHash, false))
   570  	if err != nil {
   571  		return nil, err
   572  	}
   573  	return hex, nil
   574  }
   575  
   576  // PendingCallContract executes a message call transaction using the EVM.
   577  // The state seen by the contract call is the pending state.
   578  func (ec *Client) PendingCallContract(ctx context.Context, msg ethereum.CallMsg) ([]byte, error) {
   579  	var hex hexutil.Bytes
   580  	err := ec.c.CallContext(ctx, &hex, "eth_call", toCallArg(msg), "pending")
   581  	if err != nil {
   582  		return nil, err
   583  	}
   584  	return hex, nil
   585  }
   586  
   587  // SuggestGasPrice retrieves the currently suggested gas price to allow a timely
   588  // execution of a transaction.
   589  func (ec *Client) SuggestGasPrice(ctx context.Context) (*big.Int, error) {
   590  	var hex hexutil.Big
   591  	if err := ec.c.CallContext(ctx, &hex, "eth_gasPrice"); err != nil {
   592  		return nil, err
   593  	}
   594  	return (*big.Int)(&hex), nil
   595  }
   596  
   597  // SuggestGasTipCap retrieves the currently suggested gas tip cap after 1559 to
   598  // allow a timely execution of a transaction.
   599  func (ec *Client) SuggestGasTipCap(ctx context.Context) (*big.Int, error) {
   600  	var hex hexutil.Big
   601  	if err := ec.c.CallContext(ctx, &hex, "eth_maxPriorityFeePerGas"); err != nil {
   602  		return nil, err
   603  	}
   604  	return (*big.Int)(&hex), nil
   605  }
   606  
   607  // BlobBaseFee retrieves the current blob base fee.
   608  func (ec *Client) BlobBaseFee(ctx context.Context) (*big.Int, error) {
   609  	var hex hexutil.Big
   610  	if err := ec.c.CallContext(ctx, &hex, "eth_blobBaseFee"); err != nil {
   611  		return nil, err
   612  	}
   613  	return (*big.Int)(&hex), nil
   614  }
   615  
   616  type feeHistoryResultMarshaling struct {
   617  	OldestBlock  *hexutil.Big     `json:"oldestBlock"`
   618  	Reward       [][]*hexutil.Big `json:"reward,omitempty"`
   619  	BaseFee      []*hexutil.Big   `json:"baseFeePerGas,omitempty"`
   620  	GasUsedRatio []float64        `json:"gasUsedRatio"`
   621  }
   622  
   623  // FeeHistory retrieves the fee market history.
   624  func (ec *Client) FeeHistory(ctx context.Context, blockCount uint64, lastBlock *big.Int, rewardPercentiles []float64) (*ethereum.FeeHistory, error) {
   625  	var res feeHistoryResultMarshaling
   626  	if err := ec.c.CallContext(ctx, &res, "eth_feeHistory", hexutil.Uint(blockCount), toBlockNumArg(lastBlock), rewardPercentiles); err != nil {
   627  		return nil, err
   628  	}
   629  	reward := make([][]*big.Int, len(res.Reward))
   630  	for i, r := range res.Reward {
   631  		reward[i] = make([]*big.Int, len(r))
   632  		for j, r := range r {
   633  			reward[i][j] = (*big.Int)(r)
   634  		}
   635  	}
   636  	baseFee := make([]*big.Int, len(res.BaseFee))
   637  	for i, b := range res.BaseFee {
   638  		baseFee[i] = (*big.Int)(b)
   639  	}
   640  	return &ethereum.FeeHistory{
   641  		OldestBlock:  (*big.Int)(res.OldestBlock),
   642  		Reward:       reward,
   643  		BaseFee:      baseFee,
   644  		GasUsedRatio: res.GasUsedRatio,
   645  	}, nil
   646  }
   647  
   648  // EstimateGas tries to estimate the gas needed to execute a specific transaction based on
   649  // the current state of the backend blockchain. There is no guarantee that this is the
   650  // true gas limit requirement as other transactions may be added or removed by miners, but
   651  // it should provide a basis for setting a reasonable default.
   652  //
   653  // Note that the state used by this method is implementation-defined by the remote RPC
   654  // server, but it's reasonable to assume that it will either be the pending or latest
   655  // state.
   656  func (ec *Client) EstimateGas(ctx context.Context, msg ethereum.CallMsg) (uint64, error) {
   657  	var hex hexutil.Uint64
   658  	err := ec.c.CallContext(ctx, &hex, "eth_estimateGas", toCallArg(msg))
   659  	if err != nil {
   660  		return 0, err
   661  	}
   662  	return uint64(hex), nil
   663  }
   664  
   665  // EstimateGasAtBlock is almost the same as EstimateGas except that it selects the block height
   666  // instead of using the remote RPC's default state for gas estimation.
   667  func (ec *Client) EstimateGasAtBlock(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) (uint64, error) {
   668  	var hex hexutil.Uint64
   669  	err := ec.c.CallContext(ctx, &hex, "eth_estimateGas", toCallArg(msg), toBlockNumArg(blockNumber))
   670  	if err != nil {
   671  		return 0, err
   672  	}
   673  	return uint64(hex), nil
   674  }
   675  
   676  // EstimateGasAtBlockHash is almost the same as EstimateGas except that it selects the block
   677  // hash instead of using the remote RPC's default state for gas estimation.
   678  func (ec *Client) EstimateGasAtBlockHash(ctx context.Context, msg ethereum.CallMsg, blockHash common.Hash) (uint64, error) {
   679  	var hex hexutil.Uint64
   680  	err := ec.c.CallContext(ctx, &hex, "eth_estimateGas", toCallArg(msg), rpc.BlockNumberOrHashWithHash(blockHash, false))
   681  	if err != nil {
   682  		return 0, err
   683  	}
   684  	return uint64(hex), nil
   685  }
   686  
   687  // SendTransaction injects a signed transaction into the pending pool for execution.
   688  //
   689  // If the transaction was a contract creation use the TransactionReceipt method to get the
   690  // contract address after the transaction has been mined.
   691  func (ec *Client) SendTransaction(ctx context.Context, tx *types.Transaction) error {
   692  	data, err := tx.MarshalBinary()
   693  	if err != nil {
   694  		return err
   695  	}
   696  	return ec.c.CallContext(ctx, nil, "eth_sendRawTransaction", hexutil.Encode(data))
   697  }
   698  
   699  // RevertErrorData returns the 'revert reason' data of a contract call.
   700  //
   701  // This can be used with CallContract and EstimateGas, and only when the server is Geth.
   702  func RevertErrorData(err error) ([]byte, bool) {
   703  	var ec rpc.Error
   704  	var ed rpc.DataError
   705  	if errors.As(err, &ec) && errors.As(err, &ed) && ec.ErrorCode() == 3 {
   706  		if eds, ok := ed.ErrorData().(string); ok {
   707  			revertData, err := hexutil.Decode(eds)
   708  			if err == nil {
   709  				return revertData, true
   710  			}
   711  		}
   712  	}
   713  	return nil, false
   714  }
   715  
   716  func toBlockNumArg(number *big.Int) string {
   717  	if number == nil {
   718  		return "latest"
   719  	}
   720  	if number.Sign() >= 0 {
   721  		return hexutil.EncodeBig(number)
   722  	}
   723  	// It's negative.
   724  	if number.IsInt64() {
   725  		return rpc.BlockNumber(number.Int64()).String()
   726  	}
   727  	// It's negative and large, which is invalid.
   728  	return fmt.Sprintf("<invalid %d>", number)
   729  }
   730  
   731  func toCallArg(msg ethereum.CallMsg) interface{} {
   732  	arg := map[string]interface{}{
   733  		"from": msg.From,
   734  		"to":   msg.To,
   735  	}
   736  	if len(msg.Data) > 0 {
   737  		arg["input"] = hexutil.Bytes(msg.Data)
   738  	}
   739  	if msg.Value != nil {
   740  		arg["value"] = (*hexutil.Big)(msg.Value)
   741  	}
   742  	if msg.Gas != 0 {
   743  		arg["gas"] = hexutil.Uint64(msg.Gas)
   744  	}
   745  	if msg.GasPrice != nil {
   746  		arg["gasPrice"] = (*hexutil.Big)(msg.GasPrice)
   747  	}
   748  	if msg.GasFeeCap != nil {
   749  		arg["maxFeePerGas"] = (*hexutil.Big)(msg.GasFeeCap)
   750  	}
   751  	if msg.GasTipCap != nil {
   752  		arg["maxPriorityFeePerGas"] = (*hexutil.Big)(msg.GasTipCap)
   753  	}
   754  	if msg.AccessList != nil {
   755  		arg["accessList"] = msg.AccessList
   756  	}
   757  	if msg.BlobGasFeeCap != nil {
   758  		arg["maxFeePerBlobGas"] = (*hexutil.Big)(msg.BlobGasFeeCap)
   759  	}
   760  	if msg.BlobHashes != nil {
   761  		arg["blobVersionedHashes"] = msg.BlobHashes
   762  	}
   763  	if msg.AuthorizationList != nil {
   764  		arg["authorizationList"] = msg.AuthorizationList
   765  	}
   766  	return arg
   767  }
   768  
   769  // rpcProgress is a copy of SyncProgress with hex-encoded fields.
   770  type rpcProgress struct {
   771  	StartingBlock hexutil.Uint64
   772  	CurrentBlock  hexutil.Uint64
   773  	HighestBlock  hexutil.Uint64
   774  
   775  	PulledStates hexutil.Uint64
   776  	KnownStates  hexutil.Uint64
   777  
   778  	SyncedAccounts         hexutil.Uint64
   779  	SyncedAccountBytes     hexutil.Uint64
   780  	SyncedBytecodes        hexutil.Uint64
   781  	SyncedBytecodeBytes    hexutil.Uint64
   782  	SyncedStorage          hexutil.Uint64
   783  	SyncedStorageBytes     hexutil.Uint64
   784  	HealedTrienodes        hexutil.Uint64
   785  	HealedTrienodeBytes    hexutil.Uint64
   786  	HealedBytecodes        hexutil.Uint64
   787  	HealedBytecodeBytes    hexutil.Uint64
   788  	HealingTrienodes       hexutil.Uint64
   789  	HealingBytecode        hexutil.Uint64
   790  	TxIndexFinishedBlocks  hexutil.Uint64
   791  	TxIndexRemainingBlocks hexutil.Uint64
   792  	StateIndexRemaining    hexutil.Uint64
   793  }
   794  
   795  func (p *rpcProgress) toSyncProgress() *ethereum.SyncProgress {
   796  	if p == nil {
   797  		return nil
   798  	}
   799  	return &ethereum.SyncProgress{
   800  		StartingBlock:          uint64(p.StartingBlock),
   801  		CurrentBlock:           uint64(p.CurrentBlock),
   802  		HighestBlock:           uint64(p.HighestBlock),
   803  		PulledStates:           uint64(p.PulledStates),
   804  		KnownStates:            uint64(p.KnownStates),
   805  		SyncedAccounts:         uint64(p.SyncedAccounts),
   806  		SyncedAccountBytes:     uint64(p.SyncedAccountBytes),
   807  		SyncedBytecodes:        uint64(p.SyncedBytecodes),
   808  		SyncedBytecodeBytes:    uint64(p.SyncedBytecodeBytes),
   809  		SyncedStorage:          uint64(p.SyncedStorage),
   810  		SyncedStorageBytes:     uint64(p.SyncedStorageBytes),
   811  		HealedTrienodes:        uint64(p.HealedTrienodes),
   812  		HealedTrienodeBytes:    uint64(p.HealedTrienodeBytes),
   813  		HealedBytecodes:        uint64(p.HealedBytecodes),
   814  		HealedBytecodeBytes:    uint64(p.HealedBytecodeBytes),
   815  		HealingTrienodes:       uint64(p.HealingTrienodes),
   816  		HealingBytecode:        uint64(p.HealingBytecode),
   817  		TxIndexFinishedBlocks:  uint64(p.TxIndexFinishedBlocks),
   818  		TxIndexRemainingBlocks: uint64(p.TxIndexRemainingBlocks),
   819  		StateIndexRemaining:    uint64(p.StateIndexRemaining),
   820  	}
   821  }