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