github.1485827954.workers.dev/ethereum/go-ethereum@v1.14.3/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. If number is nil, the
    89  // latest known block is returned.
    90  //
    91  // Note that loading full blocks requires two requests. Use HeaderByNumber
    92  // if you don't need all transactions or uncle headers.
    93  func (ec *Client) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) {
    94  	return ec.getBlock(ctx, "eth_getBlockByNumber", toBlockNumArg(number), true)
    95  }
    96  
    97  // BlockNumber returns the most recent block number
    98  func (ec *Client) BlockNumber(ctx context.Context) (uint64, error) {
    99  	var result hexutil.Uint64
   100  	err := ec.c.CallContext(ctx, &result, "eth_blockNumber")
   101  	return uint64(result), err
   102  }
   103  
   104  // PeerCount returns the number of p2p peers as reported by the net_peerCount method.
   105  func (ec *Client) PeerCount(ctx context.Context) (uint64, error) {
   106  	var result hexutil.Uint64
   107  	err := ec.c.CallContext(ctx, &result, "net_peerCount")
   108  	return uint64(result), err
   109  }
   110  
   111  // BlockReceipts returns the receipts of a given block number or hash.
   112  func (ec *Client) BlockReceipts(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) ([]*types.Receipt, error) {
   113  	var r []*types.Receipt
   114  	err := ec.c.CallContext(ctx, &r, "eth_getBlockReceipts", blockNrOrHash.String())
   115  	if err == nil && r == nil {
   116  		return nil, ethereum.NotFound
   117  	}
   118  	return r, err
   119  }
   120  
   121  type rpcBlock struct {
   122  	Hash         common.Hash         `json:"hash"`
   123  	Transactions []rpcTransaction    `json:"transactions"`
   124  	UncleHashes  []common.Hash       `json:"uncles"`
   125  	Withdrawals  []*types.Withdrawal `json:"withdrawals,omitempty"`
   126  }
   127  
   128  func (ec *Client) getBlock(ctx context.Context, method string, args ...interface{}) (*types.Block, error) {
   129  	var raw json.RawMessage
   130  	err := ec.c.CallContext(ctx, &raw, method, args...)
   131  	if err != nil {
   132  		return nil, err
   133  	}
   134  
   135  	// Decode header and transactions.
   136  	var head *types.Header
   137  	if err := json.Unmarshal(raw, &head); err != nil {
   138  		return nil, err
   139  	}
   140  	// When the block is not found, the API returns JSON null.
   141  	if head == nil {
   142  		return nil, ethereum.NotFound
   143  	}
   144  
   145  	var body rpcBlock
   146  	if err := json.Unmarshal(raw, &body); err != nil {
   147  		return nil, err
   148  	}
   149  	// Quick-verify transaction and uncle lists. This mostly helps with debugging the server.
   150  	if head.UncleHash == types.EmptyUncleHash && len(body.UncleHashes) > 0 {
   151  		return nil, errors.New("server returned non-empty uncle list but block header indicates no uncles")
   152  	}
   153  	if head.UncleHash != types.EmptyUncleHash && len(body.UncleHashes) == 0 {
   154  		return nil, errors.New("server returned empty uncle list but block header indicates uncles")
   155  	}
   156  	if head.TxHash == types.EmptyTxsHash && len(body.Transactions) > 0 {
   157  		return nil, errors.New("server returned non-empty transaction list but block header indicates no transactions")
   158  	}
   159  	if head.TxHash != types.EmptyTxsHash && len(body.Transactions) == 0 {
   160  		return nil, errors.New("server returned empty transaction list but block header indicates transactions")
   161  	}
   162  	// Load uncles because they are not included in the block response.
   163  	var uncles []*types.Header
   164  	if len(body.UncleHashes) > 0 {
   165  		uncles = make([]*types.Header, len(body.UncleHashes))
   166  		reqs := make([]rpc.BatchElem, len(body.UncleHashes))
   167  		for i := range reqs {
   168  			reqs[i] = rpc.BatchElem{
   169  				Method: "eth_getUncleByBlockHashAndIndex",
   170  				Args:   []interface{}{body.Hash, hexutil.EncodeUint64(uint64(i))},
   171  				Result: &uncles[i],
   172  			}
   173  		}
   174  		if err := ec.c.BatchCallContext(ctx, reqs); err != nil {
   175  			return nil, err
   176  		}
   177  		for i := range reqs {
   178  			if reqs[i].Error != nil {
   179  				return nil, reqs[i].Error
   180  			}
   181  			if uncles[i] == nil {
   182  				return nil, fmt.Errorf("got null header for uncle %d of block %x", i, body.Hash[:])
   183  			}
   184  		}
   185  	}
   186  	// Fill the sender cache of transactions in the block.
   187  	txs := make([]*types.Transaction, len(body.Transactions))
   188  	for i, tx := range body.Transactions {
   189  		if tx.From != nil {
   190  			setSenderFromServer(tx.tx, *tx.From, body.Hash)
   191  		}
   192  		txs[i] = tx.tx
   193  	}
   194  	return types.NewBlockWithHeader(head).WithBody(
   195  		types.Body{
   196  			Transactions: txs,
   197  			Uncles:       uncles,
   198  			Withdrawals:  body.Withdrawals,
   199  		}), nil
   200  }
   201  
   202  // HeaderByHash returns the block header with the given hash.
   203  func (ec *Client) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
   204  	var head *types.Header
   205  	err := ec.c.CallContext(ctx, &head, "eth_getBlockByHash", hash, false)
   206  	if err == nil && head == nil {
   207  		err = ethereum.NotFound
   208  	}
   209  	return head, err
   210  }
   211  
   212  // HeaderByNumber returns a block header from the current canonical chain. If number is
   213  // nil, the latest known header is returned.
   214  func (ec *Client) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) {
   215  	var head *types.Header
   216  	err := ec.c.CallContext(ctx, &head, "eth_getBlockByNumber", toBlockNumArg(number), false)
   217  	if err == nil && head == nil {
   218  		err = ethereum.NotFound
   219  	}
   220  	return head, err
   221  }
   222  
   223  type rpcTransaction struct {
   224  	tx *types.Transaction
   225  	txExtraInfo
   226  }
   227  
   228  type txExtraInfo struct {
   229  	BlockNumber *string         `json:"blockNumber,omitempty"`
   230  	BlockHash   *common.Hash    `json:"blockHash,omitempty"`
   231  	From        *common.Address `json:"from,omitempty"`
   232  }
   233  
   234  func (tx *rpcTransaction) UnmarshalJSON(msg []byte) error {
   235  	if err := json.Unmarshal(msg, &tx.tx); err != nil {
   236  		return err
   237  	}
   238  	return json.Unmarshal(msg, &tx.txExtraInfo)
   239  }
   240  
   241  // TransactionByHash returns the transaction with the given hash.
   242  func (ec *Client) TransactionByHash(ctx context.Context, hash common.Hash) (tx *types.Transaction, isPending bool, err error) {
   243  	var json *rpcTransaction
   244  	err = ec.c.CallContext(ctx, &json, "eth_getTransactionByHash", hash)
   245  	if err != nil {
   246  		return nil, false, err
   247  	} else if json == nil {
   248  		return nil, false, ethereum.NotFound
   249  	} else if _, r, _ := json.tx.RawSignatureValues(); r == nil {
   250  		return nil, false, errors.New("server returned transaction without signature")
   251  	}
   252  	if json.From != nil && json.BlockHash != nil {
   253  		setSenderFromServer(json.tx, *json.From, *json.BlockHash)
   254  	}
   255  	return json.tx, json.BlockNumber == nil, nil
   256  }
   257  
   258  // TransactionSender returns the sender address of the given transaction. The transaction
   259  // must be known to the remote node and included in the blockchain at the given block and
   260  // index. The sender is the one derived by the protocol at the time of inclusion.
   261  //
   262  // There is a fast-path for transactions retrieved by TransactionByHash and
   263  // TransactionInBlock. Getting their sender address can be done without an RPC interaction.
   264  func (ec *Client) TransactionSender(ctx context.Context, tx *types.Transaction, block common.Hash, index uint) (common.Address, error) {
   265  	// Try to load the address from the cache.
   266  	sender, err := types.Sender(&senderFromServer{blockhash: block}, tx)
   267  	if err == nil {
   268  		return sender, nil
   269  	}
   270  
   271  	// It was not found in cache, ask the server.
   272  	var meta struct {
   273  		Hash common.Hash
   274  		From common.Address
   275  	}
   276  	if err = ec.c.CallContext(ctx, &meta, "eth_getTransactionByBlockHashAndIndex", block, hexutil.Uint64(index)); err != nil {
   277  		return common.Address{}, err
   278  	}
   279  	if meta.Hash == (common.Hash{}) || meta.Hash != tx.Hash() {
   280  		return common.Address{}, errors.New("wrong inclusion block/index")
   281  	}
   282  	return meta.From, nil
   283  }
   284  
   285  // TransactionCount returns the total number of transactions in the given block.
   286  func (ec *Client) TransactionCount(ctx context.Context, blockHash common.Hash) (uint, error) {
   287  	var num hexutil.Uint
   288  	err := ec.c.CallContext(ctx, &num, "eth_getBlockTransactionCountByHash", blockHash)
   289  	return uint(num), err
   290  }
   291  
   292  // TransactionInBlock returns a single transaction at index in the given block.
   293  func (ec *Client) TransactionInBlock(ctx context.Context, blockHash common.Hash, index uint) (*types.Transaction, error) {
   294  	var json *rpcTransaction
   295  	err := ec.c.CallContext(ctx, &json, "eth_getTransactionByBlockHashAndIndex", blockHash, hexutil.Uint64(index))
   296  	if err != nil {
   297  		return nil, err
   298  	}
   299  	if json == nil {
   300  		return nil, ethereum.NotFound
   301  	} else if _, r, _ := json.tx.RawSignatureValues(); r == nil {
   302  		return nil, errors.New("server returned transaction without signature")
   303  	}
   304  	if json.From != nil && json.BlockHash != nil {
   305  		setSenderFromServer(json.tx, *json.From, *json.BlockHash)
   306  	}
   307  	return json.tx, err
   308  }
   309  
   310  // TransactionReceipt returns the receipt of a transaction by transaction hash.
   311  // Note that the receipt is not available for pending transactions.
   312  func (ec *Client) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) {
   313  	var r *types.Receipt
   314  	err := ec.c.CallContext(ctx, &r, "eth_getTransactionReceipt", txHash)
   315  	if err == nil && r == nil {
   316  		return nil, ethereum.NotFound
   317  	}
   318  	return r, err
   319  }
   320  
   321  // SyncProgress retrieves the current progress of the sync algorithm. If there's
   322  // no sync currently running, it returns nil.
   323  func (ec *Client) SyncProgress(ctx context.Context) (*ethereum.SyncProgress, error) {
   324  	var raw json.RawMessage
   325  	if err := ec.c.CallContext(ctx, &raw, "eth_syncing"); err != nil {
   326  		return nil, err
   327  	}
   328  	// Handle the possible response types
   329  	var syncing bool
   330  	if err := json.Unmarshal(raw, &syncing); err == nil {
   331  		return nil, nil // Not syncing (always false)
   332  	}
   333  	var p *rpcProgress
   334  	if err := json.Unmarshal(raw, &p); err != nil {
   335  		return nil, err
   336  	}
   337  	return p.toSyncProgress(), nil
   338  }
   339  
   340  // SubscribeNewHead subscribes to notifications about the current blockchain head
   341  // on the given channel.
   342  func (ec *Client) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) {
   343  	sub, err := ec.c.EthSubscribe(ctx, ch, "newHeads")
   344  	if err != nil {
   345  		// Defensively prefer returning nil interface explicitly on error-path, instead
   346  		// of letting default golang behavior wrap it with non-nil interface that stores
   347  		// nil concrete type value.
   348  		return nil, err
   349  	}
   350  	return sub, nil
   351  }
   352  
   353  // State Access
   354  
   355  // NetworkID returns the network ID for this client.
   356  func (ec *Client) NetworkID(ctx context.Context) (*big.Int, error) {
   357  	version := new(big.Int)
   358  	var ver string
   359  	if err := ec.c.CallContext(ctx, &ver, "net_version"); err != nil {
   360  		return nil, err
   361  	}
   362  	if _, ok := version.SetString(ver, 10); !ok {
   363  		return nil, fmt.Errorf("invalid net_version result %q", ver)
   364  	}
   365  	return version, nil
   366  }
   367  
   368  // BalanceAt returns the wei balance of the given account.
   369  // The block number can be nil, in which case the balance is taken from the latest known block.
   370  func (ec *Client) BalanceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (*big.Int, error) {
   371  	var result hexutil.Big
   372  	err := ec.c.CallContext(ctx, &result, "eth_getBalance", account, toBlockNumArg(blockNumber))
   373  	return (*big.Int)(&result), err
   374  }
   375  
   376  // BalanceAtHash returns the wei balance of the given account.
   377  func (ec *Client) BalanceAtHash(ctx context.Context, account common.Address, blockHash common.Hash) (*big.Int, error) {
   378  	var result hexutil.Big
   379  	err := ec.c.CallContext(ctx, &result, "eth_getBalance", account, rpc.BlockNumberOrHashWithHash(blockHash, false))
   380  	return (*big.Int)(&result), err
   381  }
   382  
   383  // StorageAt returns the value of key in the contract storage of the given account.
   384  // The block number can be nil, in which case the value is taken from the latest known block.
   385  func (ec *Client) StorageAt(ctx context.Context, account common.Address, key common.Hash, blockNumber *big.Int) ([]byte, error) {
   386  	var result hexutil.Bytes
   387  	err := ec.c.CallContext(ctx, &result, "eth_getStorageAt", account, key, toBlockNumArg(blockNumber))
   388  	return result, err
   389  }
   390  
   391  // StorageAtHash returns the value of key in the contract storage of the given account.
   392  func (ec *Client) StorageAtHash(ctx context.Context, account common.Address, key common.Hash, blockHash common.Hash) ([]byte, error) {
   393  	var result hexutil.Bytes
   394  	err := ec.c.CallContext(ctx, &result, "eth_getStorageAt", account, key, rpc.BlockNumberOrHashWithHash(blockHash, false))
   395  	return result, err
   396  }
   397  
   398  // CodeAt returns the contract code of the given account.
   399  // The block number can be nil, in which case the code is taken from the latest known block.
   400  func (ec *Client) CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error) {
   401  	var result hexutil.Bytes
   402  	err := ec.c.CallContext(ctx, &result, "eth_getCode", account, toBlockNumArg(blockNumber))
   403  	return result, err
   404  }
   405  
   406  // CodeAtHash returns the contract code of the given account.
   407  func (ec *Client) CodeAtHash(ctx context.Context, account common.Address, blockHash common.Hash) ([]byte, error) {
   408  	var result hexutil.Bytes
   409  	err := ec.c.CallContext(ctx, &result, "eth_getCode", account, rpc.BlockNumberOrHashWithHash(blockHash, false))
   410  	return result, err
   411  }
   412  
   413  // NonceAt returns the account nonce of the given account.
   414  // The block number can be nil, in which case the nonce is taken from the latest known block.
   415  func (ec *Client) NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) {
   416  	var result hexutil.Uint64
   417  	err := ec.c.CallContext(ctx, &result, "eth_getTransactionCount", account, toBlockNumArg(blockNumber))
   418  	return uint64(result), err
   419  }
   420  
   421  // NonceAtHash returns the account nonce of the given account.
   422  func (ec *Client) NonceAtHash(ctx context.Context, account common.Address, blockHash common.Hash) (uint64, error) {
   423  	var result hexutil.Uint64
   424  	err := ec.c.CallContext(ctx, &result, "eth_getTransactionCount", account, rpc.BlockNumberOrHashWithHash(blockHash, false))
   425  	return uint64(result), err
   426  }
   427  
   428  // Filters
   429  
   430  // FilterLogs executes a filter query.
   431  func (ec *Client) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) {
   432  	var result []types.Log
   433  	arg, err := toFilterArg(q)
   434  	if err != nil {
   435  		return nil, err
   436  	}
   437  	err = ec.c.CallContext(ctx, &result, "eth_getLogs", arg)
   438  	return result, err
   439  }
   440  
   441  // SubscribeFilterLogs subscribes to the results of a streaming filter query.
   442  func (ec *Client) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) {
   443  	arg, err := toFilterArg(q)
   444  	if err != nil {
   445  		return nil, err
   446  	}
   447  	sub, err := ec.c.EthSubscribe(ctx, ch, "logs", arg)
   448  	if err != nil {
   449  		// Defensively prefer returning nil interface explicitly on error-path, instead
   450  		// of letting default golang behavior wrap it with non-nil interface that stores
   451  		// nil concrete type value.
   452  		return nil, err
   453  	}
   454  	return sub, nil
   455  }
   456  
   457  func toFilterArg(q ethereum.FilterQuery) (interface{}, error) {
   458  	arg := map[string]interface{}{
   459  		"address": q.Addresses,
   460  		"topics":  q.Topics,
   461  	}
   462  	if q.BlockHash != nil {
   463  		arg["blockHash"] = *q.BlockHash
   464  		if q.FromBlock != nil || q.ToBlock != nil {
   465  			return nil, errors.New("cannot specify both BlockHash and FromBlock/ToBlock")
   466  		}
   467  	} else {
   468  		if q.FromBlock == nil {
   469  			arg["fromBlock"] = "0x0"
   470  		} else {
   471  			arg["fromBlock"] = toBlockNumArg(q.FromBlock)
   472  		}
   473  		arg["toBlock"] = toBlockNumArg(q.ToBlock)
   474  	}
   475  	return arg, nil
   476  }
   477  
   478  // Pending State
   479  
   480  // PendingBalanceAt returns the wei balance of the given account in the pending state.
   481  func (ec *Client) PendingBalanceAt(ctx context.Context, account common.Address) (*big.Int, error) {
   482  	var result hexutil.Big
   483  	err := ec.c.CallContext(ctx, &result, "eth_getBalance", account, "pending")
   484  	return (*big.Int)(&result), err
   485  }
   486  
   487  // PendingStorageAt returns the value of key in the contract storage of the given account in the pending state.
   488  func (ec *Client) PendingStorageAt(ctx context.Context, account common.Address, key common.Hash) ([]byte, error) {
   489  	var result hexutil.Bytes
   490  	err := ec.c.CallContext(ctx, &result, "eth_getStorageAt", account, key, "pending")
   491  	return result, err
   492  }
   493  
   494  // PendingCodeAt returns the contract code of the given account in the pending state.
   495  func (ec *Client) PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error) {
   496  	var result hexutil.Bytes
   497  	err := ec.c.CallContext(ctx, &result, "eth_getCode", account, "pending")
   498  	return result, err
   499  }
   500  
   501  // PendingNonceAt returns the account nonce of the given account in the pending state.
   502  // This is the nonce that should be used for the next transaction.
   503  func (ec *Client) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) {
   504  	var result hexutil.Uint64
   505  	err := ec.c.CallContext(ctx, &result, "eth_getTransactionCount", account, "pending")
   506  	return uint64(result), err
   507  }
   508  
   509  // PendingTransactionCount returns the total number of transactions in the pending state.
   510  func (ec *Client) PendingTransactionCount(ctx context.Context) (uint, error) {
   511  	var num hexutil.Uint
   512  	err := ec.c.CallContext(ctx, &num, "eth_getBlockTransactionCountByNumber", "pending")
   513  	return uint(num), err
   514  }
   515  
   516  // Contract Calling
   517  
   518  // CallContract executes a message call transaction, which is directly executed in the VM
   519  // of the node, but never mined into the blockchain.
   520  //
   521  // blockNumber selects the block height at which the call runs. It can be nil, in which
   522  // case the code is taken from the latest known block. Note that state from very old
   523  // blocks might not be available.
   524  func (ec *Client) CallContract(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) {
   525  	var hex hexutil.Bytes
   526  	err := ec.c.CallContext(ctx, &hex, "eth_call", toCallArg(msg), toBlockNumArg(blockNumber))
   527  	if err != nil {
   528  		return nil, err
   529  	}
   530  	return hex, nil
   531  }
   532  
   533  // CallContractAtHash is almost the same as CallContract except that it selects
   534  // the block by block hash instead of block height.
   535  func (ec *Client) CallContractAtHash(ctx context.Context, msg ethereum.CallMsg, blockHash common.Hash) ([]byte, error) {
   536  	var hex hexutil.Bytes
   537  	err := ec.c.CallContext(ctx, &hex, "eth_call", toCallArg(msg), rpc.BlockNumberOrHashWithHash(blockHash, false))
   538  	if err != nil {
   539  		return nil, err
   540  	}
   541  	return hex, nil
   542  }
   543  
   544  // PendingCallContract executes a message call transaction using the EVM.
   545  // The state seen by the contract call is the pending state.
   546  func (ec *Client) PendingCallContract(ctx context.Context, msg ethereum.CallMsg) ([]byte, error) {
   547  	var hex hexutil.Bytes
   548  	err := ec.c.CallContext(ctx, &hex, "eth_call", toCallArg(msg), "pending")
   549  	if err != nil {
   550  		return nil, err
   551  	}
   552  	return hex, nil
   553  }
   554  
   555  // SuggestGasPrice retrieves the currently suggested gas price to allow a timely
   556  // execution of a transaction.
   557  func (ec *Client) SuggestGasPrice(ctx context.Context) (*big.Int, error) {
   558  	var hex hexutil.Big
   559  	if err := ec.c.CallContext(ctx, &hex, "eth_gasPrice"); err != nil {
   560  		return nil, err
   561  	}
   562  	return (*big.Int)(&hex), nil
   563  }
   564  
   565  // SuggestGasTipCap retrieves the currently suggested gas tip cap after 1559 to
   566  // allow a timely execution of a transaction.
   567  func (ec *Client) SuggestGasTipCap(ctx context.Context) (*big.Int, error) {
   568  	var hex hexutil.Big
   569  	if err := ec.c.CallContext(ctx, &hex, "eth_maxPriorityFeePerGas"); err != nil {
   570  		return nil, err
   571  	}
   572  	return (*big.Int)(&hex), nil
   573  }
   574  
   575  type feeHistoryResultMarshaling struct {
   576  	OldestBlock  *hexutil.Big     `json:"oldestBlock"`
   577  	Reward       [][]*hexutil.Big `json:"reward,omitempty"`
   578  	BaseFee      []*hexutil.Big   `json:"baseFeePerGas,omitempty"`
   579  	GasUsedRatio []float64        `json:"gasUsedRatio"`
   580  }
   581  
   582  // FeeHistory retrieves the fee market history.
   583  func (ec *Client) FeeHistory(ctx context.Context, blockCount uint64, lastBlock *big.Int, rewardPercentiles []float64) (*ethereum.FeeHistory, error) {
   584  	var res feeHistoryResultMarshaling
   585  	if err := ec.c.CallContext(ctx, &res, "eth_feeHistory", hexutil.Uint(blockCount), toBlockNumArg(lastBlock), rewardPercentiles); err != nil {
   586  		return nil, err
   587  	}
   588  	reward := make([][]*big.Int, len(res.Reward))
   589  	for i, r := range res.Reward {
   590  		reward[i] = make([]*big.Int, len(r))
   591  		for j, r := range r {
   592  			reward[i][j] = (*big.Int)(r)
   593  		}
   594  	}
   595  	baseFee := make([]*big.Int, len(res.BaseFee))
   596  	for i, b := range res.BaseFee {
   597  		baseFee[i] = (*big.Int)(b)
   598  	}
   599  	return &ethereum.FeeHistory{
   600  		OldestBlock:  (*big.Int)(res.OldestBlock),
   601  		Reward:       reward,
   602  		BaseFee:      baseFee,
   603  		GasUsedRatio: res.GasUsedRatio,
   604  	}, nil
   605  }
   606  
   607  // EstimateGas tries to estimate the gas needed to execute a specific transaction based on
   608  // the current pending state of the backend blockchain. There is no guarantee that this is
   609  // the true gas limit requirement as other transactions may be added or removed by miners,
   610  // but it should provide a basis for setting a reasonable default.
   611  func (ec *Client) EstimateGas(ctx context.Context, msg ethereum.CallMsg) (uint64, error) {
   612  	var hex hexutil.Uint64
   613  	err := ec.c.CallContext(ctx, &hex, "eth_estimateGas", toCallArg(msg))
   614  	if err != nil {
   615  		return 0, err
   616  	}
   617  	return uint64(hex), nil
   618  }
   619  
   620  // SendTransaction injects a signed transaction into the pending pool for execution.
   621  //
   622  // If the transaction was a contract creation use the TransactionReceipt method to get the
   623  // contract address after the transaction has been mined.
   624  func (ec *Client) SendTransaction(ctx context.Context, tx *types.Transaction) error {
   625  	data, err := tx.MarshalBinary()
   626  	if err != nil {
   627  		return err
   628  	}
   629  	return ec.c.CallContext(ctx, nil, "eth_sendRawTransaction", hexutil.Encode(data))
   630  }
   631  
   632  func toBlockNumArg(number *big.Int) string {
   633  	if number == nil {
   634  		return "latest"
   635  	}
   636  	if number.Sign() >= 0 {
   637  		return hexutil.EncodeBig(number)
   638  	}
   639  	// It's negative.
   640  	if number.IsInt64() {
   641  		return rpc.BlockNumber(number.Int64()).String()
   642  	}
   643  	// It's negative and large, which is invalid.
   644  	return fmt.Sprintf("<invalid %d>", number)
   645  }
   646  
   647  func toCallArg(msg ethereum.CallMsg) interface{} {
   648  	arg := map[string]interface{}{
   649  		"from": msg.From,
   650  		"to":   msg.To,
   651  	}
   652  	if len(msg.Data) > 0 {
   653  		arg["input"] = hexutil.Bytes(msg.Data)
   654  	}
   655  	if msg.Value != nil {
   656  		arg["value"] = (*hexutil.Big)(msg.Value)
   657  	}
   658  	if msg.Gas != 0 {
   659  		arg["gas"] = hexutil.Uint64(msg.Gas)
   660  	}
   661  	if msg.GasPrice != nil {
   662  		arg["gasPrice"] = (*hexutil.Big)(msg.GasPrice)
   663  	}
   664  	if msg.GasFeeCap != nil {
   665  		arg["maxFeePerGas"] = (*hexutil.Big)(msg.GasFeeCap)
   666  	}
   667  	if msg.GasTipCap != nil {
   668  		arg["maxPriorityFeePerGas"] = (*hexutil.Big)(msg.GasTipCap)
   669  	}
   670  	if msg.AccessList != nil {
   671  		arg["accessList"] = msg.AccessList
   672  	}
   673  	if msg.BlobGasFeeCap != nil {
   674  		arg["maxFeePerBlobGas"] = (*hexutil.Big)(msg.BlobGasFeeCap)
   675  	}
   676  	if msg.BlobHashes != nil {
   677  		arg["blobVersionedHashes"] = msg.BlobHashes
   678  	}
   679  	return arg
   680  }
   681  
   682  // rpcProgress is a copy of SyncProgress with hex-encoded fields.
   683  type rpcProgress struct {
   684  	StartingBlock hexutil.Uint64
   685  	CurrentBlock  hexutil.Uint64
   686  	HighestBlock  hexutil.Uint64
   687  
   688  	PulledStates hexutil.Uint64
   689  	KnownStates  hexutil.Uint64
   690  
   691  	SyncedAccounts         hexutil.Uint64
   692  	SyncedAccountBytes     hexutil.Uint64
   693  	SyncedBytecodes        hexutil.Uint64
   694  	SyncedBytecodeBytes    hexutil.Uint64
   695  	SyncedStorage          hexutil.Uint64
   696  	SyncedStorageBytes     hexutil.Uint64
   697  	HealedTrienodes        hexutil.Uint64
   698  	HealedTrienodeBytes    hexutil.Uint64
   699  	HealedBytecodes        hexutil.Uint64
   700  	HealedBytecodeBytes    hexutil.Uint64
   701  	HealingTrienodes       hexutil.Uint64
   702  	HealingBytecode        hexutil.Uint64
   703  	TxIndexFinishedBlocks  hexutil.Uint64
   704  	TxIndexRemainingBlocks hexutil.Uint64
   705  }
   706  
   707  func (p *rpcProgress) toSyncProgress() *ethereum.SyncProgress {
   708  	if p == nil {
   709  		return nil
   710  	}
   711  	return &ethereum.SyncProgress{
   712  		StartingBlock:          uint64(p.StartingBlock),
   713  		CurrentBlock:           uint64(p.CurrentBlock),
   714  		HighestBlock:           uint64(p.HighestBlock),
   715  		PulledStates:           uint64(p.PulledStates),
   716  		KnownStates:            uint64(p.KnownStates),
   717  		SyncedAccounts:         uint64(p.SyncedAccounts),
   718  		SyncedAccountBytes:     uint64(p.SyncedAccountBytes),
   719  		SyncedBytecodes:        uint64(p.SyncedBytecodes),
   720  		SyncedBytecodeBytes:    uint64(p.SyncedBytecodeBytes),
   721  		SyncedStorage:          uint64(p.SyncedStorage),
   722  		SyncedStorageBytes:     uint64(p.SyncedStorageBytes),
   723  		HealedTrienodes:        uint64(p.HealedTrienodes),
   724  		HealedTrienodeBytes:    uint64(p.HealedTrienodeBytes),
   725  		HealedBytecodes:        uint64(p.HealedBytecodes),
   726  		HealedBytecodeBytes:    uint64(p.HealedBytecodeBytes),
   727  		HealingTrienodes:       uint64(p.HealingTrienodes),
   728  		HealingBytecode:        uint64(p.HealingBytecode),
   729  		TxIndexFinishedBlocks:  uint64(p.TxIndexFinishedBlocks),
   730  		TxIndexRemainingBlocks: uint64(p.TxIndexRemainingBlocks),
   731  	}
   732  }