|
|
|
package hmyapi
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
|
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
|
|
|
"github.com/ethereum/go-ethereum/rpc"
|
|
|
|
)
|
|
|
|
|
|
|
|
// PublicBlockChainAPI provides an API to access the Harmony blockchain.
|
|
|
|
// It offers only methods that operate on public data that is freely available to anyone.
|
|
|
|
type PublicBlockChainAPI struct {
|
|
|
|
b Backend
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewPublicBlockChainAPI creates a new Harmony blockchain API.
|
|
|
|
func NewPublicBlockChainAPI(b Backend) *PublicBlockChainAPI {
|
|
|
|
return &PublicBlockChainAPI{b}
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetBlockByNumber returns the requested block. When blockNr is -1 the chain head is returned. When fullTx is true all
|
|
|
|
// transactions in the block are returned in full detail, otherwise only the transaction hash is returned.
|
|
|
|
func (s *PublicBlockChainAPI) GetBlockByNumber(ctx context.Context, blockNr rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) {
|
|
|
|
block, err := s.b.BlockByNumber(ctx, blockNr)
|
|
|
|
if block != nil {
|
|
|
|
response, err := RPCMarshalBlock(block, false, false)
|
|
|
|
if err == nil && blockNr == rpc.PendingBlockNumber {
|
|
|
|
// Pending blocks need to nil out a few fields
|
|
|
|
for _, field := range []string{"hash", "nonce", "miner"} {
|
|
|
|
response[field] = nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return response, err
|
|
|
|
}
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetBlockByHash returns the requested block. When fullTx is true all transactions in the block are returned in full
|
|
|
|
// detail, otherwise only the transaction hash is returned.
|
|
|
|
func (s *PublicBlockChainAPI) GetBlockByHash(ctx context.Context, blockHash common.Hash, fullTx bool) (map[string]interface{}, error) {
|
|
|
|
block, err := s.b.GetBlock(ctx, blockHash)
|
|
|
|
if block != nil {
|
|
|
|
return RPCMarshalBlock(block, false, false)
|
|
|
|
}
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetCode returns the code stored at the given address in the state for the given block number.
|
|
|
|
func (s *PublicBlockChainAPI) GetCode(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (hexutil.Bytes, error) {
|
|
|
|
state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr)
|
|
|
|
if state == nil || err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
code := state.GetCode(address)
|
|
|
|
return code, state.Error()
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetStorageAt returns the storage from the state at the given address, key and
|
|
|
|
// block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta block
|
|
|
|
// numbers are also allowed.
|
|
|
|
func (s *PublicBlockChainAPI) GetStorageAt(ctx context.Context, address common.Address, key string, blockNr rpc.BlockNumber) (hexutil.Bytes, error) {
|
|
|
|
state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr)
|
|
|
|
if state == nil || err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
res := state.GetState(address, common.HexToHash(key))
|
|
|
|
return res[:], state.Error()
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetBalance returns the amount of wei for the given address in the state of the
|
|
|
|
// given block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta
|
|
|
|
// block numbers are also allowed.
|
|
|
|
func (s *PublicBlockChainAPI) GetBalance(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (*hexutil.Big, error) {
|
|
|
|
// TODO: currently only get latest balance. Will add complete logic later.
|
|
|
|
return s.b.GetBalance(address)
|
|
|
|
}
|
|
|
|
|
|
|
|
// BlockNumber returns the block number of the chain head.
|
|
|
|
func (s *PublicBlockChainAPI) BlockNumber() hexutil.Uint64 {
|
|
|
|
header, _ := s.b.HeaderByNumber(context.Background(), rpc.LatestBlockNumber) // latest header should always be available
|
|
|
|
return hexutil.Uint64(header.Number.Uint64())
|
|
|
|
}
|