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