131 lines
4.1 KiB
Go
131 lines
4.1 KiB
Go
package eth
|
|
|
|
import (
|
|
"context"
|
|
"math/big"
|
|
|
|
"github.com/ethereum/go-ethereum"
|
|
"github.com/ethereum/go-ethereum/common"
|
|
"github.com/ethereum/go-ethereum/core/types"
|
|
"github.com/ethereum/go-ethereum/ethclient"
|
|
"github.com/ethereum/go-ethereum/rpc"
|
|
"github.com/trezor/blockbook/bchain"
|
|
)
|
|
|
|
// EthereumClient wraps a client to implement the EVMClient interface
|
|
type EthereumClient struct {
|
|
*ethclient.Client
|
|
}
|
|
|
|
// HeaderByNumber returns a block header that implements the EVMHeader interface
|
|
func (c *EthereumClient) HeaderByNumber(ctx context.Context, number *big.Int) (bchain.EVMHeader, error) {
|
|
h, err := c.Client.HeaderByNumber(ctx, number)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &EthereumHeader{Header: h}, nil
|
|
}
|
|
|
|
// EstimateGas returns the current estimated gas cost for executing a transaction
|
|
func (c *EthereumClient) EstimateGas(ctx context.Context, msg interface{}) (uint64, error) {
|
|
return c.Client.EstimateGas(ctx, msg.(ethereum.CallMsg))
|
|
}
|
|
|
|
// BalanceAt returns the balance for the given account at a specific block, or latest known block if no block number is provided
|
|
func (c *EthereumClient) BalanceAt(ctx context.Context, addrDesc bchain.AddressDescriptor, blockNumber *big.Int) (*big.Int, error) {
|
|
return c.Client.BalanceAt(ctx, common.BytesToAddress(addrDesc), blockNumber)
|
|
}
|
|
|
|
// NonceAt returns the nonce for the given account at a specific block, or latest known block if no block number is provided
|
|
func (c *EthereumClient) NonceAt(ctx context.Context, addrDesc bchain.AddressDescriptor, blockNumber *big.Int) (uint64, error) {
|
|
return c.Client.NonceAt(ctx, common.BytesToAddress(addrDesc), blockNumber)
|
|
}
|
|
|
|
// EthereumRPCClient wraps an rpc client to implement the EVMRPCClient interface
|
|
type EthereumRPCClient struct {
|
|
*rpc.Client
|
|
}
|
|
|
|
// EthSubscribe subscribes to events and returns a client subscription that implements the EVMClientSubscription interface
|
|
func (c *EthereumRPCClient) EthSubscribe(ctx context.Context, channel interface{}, args ...interface{}) (bchain.EVMClientSubscription, error) {
|
|
sub, err := c.Client.EthSubscribe(ctx, channel, args...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &EthereumClientSubscription{ClientSubscription: sub}, nil
|
|
}
|
|
|
|
// EthereumHeader wraps a block header to implement the EVMHeader interface
|
|
type EthereumHeader struct {
|
|
*types.Header
|
|
}
|
|
|
|
// Hash returns the block hash as a hex string
|
|
func (h *EthereumHeader) Hash() string {
|
|
return h.Header.Hash().Hex()
|
|
}
|
|
|
|
// Number returns the block number
|
|
func (h *EthereumHeader) Number() *big.Int {
|
|
return h.Header.Number
|
|
}
|
|
|
|
// Difficulty returns the block difficulty
|
|
func (h *EthereumHeader) Difficulty() *big.Int {
|
|
return h.Header.Difficulty
|
|
}
|
|
|
|
// EthereumHash wraps a transaction hash to implement the EVMHash interface
|
|
type EthereumHash struct {
|
|
common.Hash
|
|
}
|
|
|
|
// EthereumClientSubscription wraps a client subcription to implement the EVMClientSubscription interface
|
|
type EthereumClientSubscription struct {
|
|
*rpc.ClientSubscription
|
|
}
|
|
|
|
// EthereumNewBlock wraps a block header channel to implement the EVMNewBlockSubscriber interface
|
|
type EthereumNewBlock struct {
|
|
channel chan *types.Header
|
|
}
|
|
|
|
// Channel returns the underlying channel as an empty interface
|
|
func (s *EthereumNewBlock) Channel() interface{} {
|
|
return s.channel
|
|
}
|
|
|
|
// Read from the underlying channel and return a block header that implements the EVMHeader interface
|
|
func (s *EthereumNewBlock) Read() (bchain.EVMHeader, bool) {
|
|
h, ok := <-s.channel
|
|
return &EthereumHeader{Header: h}, ok
|
|
}
|
|
|
|
// Close the underlying channel
|
|
func (s *EthereumNewBlock) Close() {
|
|
close(s.channel)
|
|
}
|
|
|
|
// EthereumNewTx wraps a transaction hash channel to implement the EVMNewTxSubscriber interface
|
|
type EthereumNewTx struct {
|
|
channel chan common.Hash
|
|
}
|
|
|
|
// Channel returns the underlying channel as an empty interface
|
|
func (s *EthereumNewTx) Channel() interface{} {
|
|
return s.channel
|
|
}
|
|
|
|
// Read from the underlying channel and return a transaction hash that implements the EVMHash interface
|
|
func (s *EthereumNewTx) Read() (bchain.EVMHash, bool) {
|
|
h, ok := <-s.channel
|
|
return &EthereumHash{Hash: h}, ok
|
|
}
|
|
|
|
// Close the underlying channel
|
|
func (s *EthereumNewTx) Close() {
|
|
close(s.channel)
|
|
}
|