github.com/status-im/status-go@v1.1.0/rpc/chain/rpc.go (about)

     1  package chain
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"math/big"
     7  
     8  	"github.com/ethereum/go-ethereum"
     9  	"github.com/ethereum/go-ethereum/common"
    10  	"github.com/ethereum/go-ethereum/common/hexutil"
    11  	"github.com/ethereum/go-ethereum/core/types"
    12  	"github.com/ethereum/go-ethereum/rpc"
    13  )
    14  
    15  // The code below is mostly copied from go-ethereum/ethclient (see TransactionInBlock), to keep the exact same behavior as the
    16  // normal Transaction items, but exposing the additional data obtained in the `rpcTransaction` struct`.
    17  // Unfortunately, the functions and classes used are not exposed outside of the package.
    18  type FullTransaction struct {
    19  	Tx *types.Transaction
    20  	TxExtraInfo
    21  }
    22  
    23  type TxExtraInfo struct {
    24  	BlockNumber *hexutil.Big    `json:"blockNumber,omitempty"`
    25  	BlockHash   *common.Hash    `json:"blockHash,omitempty"`
    26  	From        *common.Address `json:"from,omitempty"`
    27  }
    28  
    29  func callBlockHashByTransaction(ctx context.Context, rpc *rpc.Client, number *big.Int, index uint) (common.Hash, error) {
    30  	var json *FullTransaction
    31  	err := rpc.CallContext(ctx, &json, "eth_getTransactionByBlockNumberAndIndex", toBlockNumArg(number), hexutil.Uint64(index))
    32  
    33  	if err != nil {
    34  		return common.HexToHash(""), err
    35  	}
    36  	if json == nil {
    37  		return common.HexToHash(""), ethereum.NotFound
    38  	}
    39  	return *json.BlockHash, nil
    40  }
    41  
    42  func (tx *FullTransaction) UnmarshalJSON(msg []byte) error {
    43  	if err := json.Unmarshal(msg, &tx.Tx); err != nil {
    44  		return err
    45  	}
    46  	return json.Unmarshal(msg, &tx.TxExtraInfo)
    47  }
    48  
    49  func toBlockNumArg(number *big.Int) string {
    50  	if number == nil {
    51  		return "latest"
    52  	}
    53  	pending := big.NewInt(-1)
    54  	if number.Cmp(pending) == 0 {
    55  		return "pending"
    56  	}
    57  	finalized := big.NewInt(int64(rpc.FinalizedBlockNumber))
    58  	if number.Cmp(finalized) == 0 {
    59  		return "finalized"
    60  	}
    61  	safe := big.NewInt(int64(rpc.SafeBlockNumber))
    62  	if number.Cmp(safe) == 0 {
    63  		return "safe"
    64  	}
    65  	return hexutil.EncodeBig(number)
    66  }