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