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