- Adding self restart when repeated error occurs with backend rpc connection - renamed package name to reflect correctly
144 lines
4.8 KiB
Go
144 lines
4.8 KiB
Go
package avalanche
|
|
|
|
import (
|
|
"context"
|
|
"math/big"
|
|
"strings"
|
|
|
|
"github.com/ava-labs/coreth/core/types"
|
|
"github.com/ava-labs/coreth/ethclient"
|
|
"github.com/ava-labs/coreth/interfaces"
|
|
"github.com/ava-labs/coreth/rpc"
|
|
"github.com/ethereum/go-ethereum/common"
|
|
"github.com/ranchimall/blockbook/bchain"
|
|
)
|
|
|
|
// AvalancheClient wraps a client to implement the EVMClient interface
|
|
type AvalancheClient struct {
|
|
ethclient.Client
|
|
}
|
|
|
|
// HeaderByNumber returns a block header that implements the EVMHeader interface
|
|
func (c *AvalancheClient) HeaderByNumber(ctx context.Context, number *big.Int) (bchain.EVMHeader, error) {
|
|
h, err := c.Client.HeaderByNumber(ctx, number)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &AvalancheHeader{Header: h}, nil
|
|
}
|
|
|
|
// EstimateGas returns the current estimated gas cost for executing a transaction
|
|
func (c *AvalancheClient) EstimateGas(ctx context.Context, msg interface{}) (uint64, error) {
|
|
return c.Client.EstimateGas(ctx, msg.(interfaces.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 *AvalancheClient) 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 *AvalancheClient) NonceAt(ctx context.Context, addrDesc bchain.AddressDescriptor, blockNumber *big.Int) (uint64, error) {
|
|
return c.Client.NonceAt(ctx, common.BytesToAddress(addrDesc), blockNumber)
|
|
}
|
|
|
|
// AvalancheRPCClient wraps an rpc client to implement the EVMRPCClient interface
|
|
type AvalancheRPCClient struct {
|
|
*rpc.Client
|
|
}
|
|
|
|
// EthSubscribe subscribes to events and returns a client subscription that implements the EVMClientSubscription interface
|
|
func (c *AvalancheRPCClient) 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 &AvalancheClientSubscription{ClientSubscription: sub}, nil
|
|
}
|
|
|
|
// CallContext performs a JSON-RPC call with the given arguments
|
|
func (c *AvalancheRPCClient) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error {
|
|
err := c.Client.CallContext(ctx, result, method, args...)
|
|
// unfinalized data cannot be queried error returned when trying to query a block height greater than last finalized block
|
|
// do not throw rpc error and instead treat as ErrBlockNotFound
|
|
// https://docs.avax.network/quickstart/exchanges/integrate-exchange-with-avalanche#determining-finality
|
|
if err != nil && !strings.Contains(err.Error(), "cannot query unfinalized data") {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// AvalancheHeader wraps a block header to implement the EVMHeader interface
|
|
type AvalancheHeader struct {
|
|
*types.Header
|
|
}
|
|
|
|
// Hash returns the block hash as a hex string
|
|
func (h *AvalancheHeader) Hash() string {
|
|
return h.Header.Hash().Hex()
|
|
}
|
|
|
|
// Number returns the block number
|
|
func (h *AvalancheHeader) Number() *big.Int {
|
|
return h.Header.Number
|
|
}
|
|
|
|
// Difficulty returns the block difficulty
|
|
func (h *AvalancheHeader) Difficulty() *big.Int {
|
|
return h.Header.Difficulty
|
|
}
|
|
|
|
// AvalancheHash wraps a transaction hash to implement the EVMHash interface
|
|
type AvalancheHash struct {
|
|
common.Hash
|
|
}
|
|
|
|
// AvalancheClientSubscription wraps a client subcription to implement the EVMClientSubscription interface
|
|
type AvalancheClientSubscription struct {
|
|
*rpc.ClientSubscription
|
|
}
|
|
|
|
// AvalancheNewBlock wraps a block header channel to implement the EVMNewBlockSubscriber interface
|
|
type AvalancheNewBlock struct {
|
|
channel chan *types.Header
|
|
}
|
|
|
|
// Channel returns the underlying channel as an empty interface
|
|
func (s *AvalancheNewBlock) Channel() interface{} {
|
|
return s.channel
|
|
}
|
|
|
|
// Read from the underlying channel and return a block header that implements the EVMHeader interface
|
|
func (s *AvalancheNewBlock) Read() (bchain.EVMHeader, bool) {
|
|
h, ok := <-s.channel
|
|
return &AvalancheHeader{Header: h}, ok
|
|
}
|
|
|
|
// Close the underlying channel
|
|
func (s *AvalancheNewBlock) Close() {
|
|
close(s.channel)
|
|
}
|
|
|
|
// AvalancheNewTx wraps a transaction hash channel to conform with the EVMNewTxSubscriber interface
|
|
type AvalancheNewTx struct {
|
|
channel chan common.Hash
|
|
}
|
|
|
|
// Channel returns the underlying channel as an empty interface
|
|
func (s *AvalancheNewTx) Channel() interface{} {
|
|
return s.channel
|
|
}
|
|
|
|
// Read from the underlying channel and return a transaction hash that implements the EVMHash interface
|
|
func (s *AvalancheNewTx) Read() (bchain.EVMHash, bool) {
|
|
h, ok := <-s.channel
|
|
return &AvalancheHash{Hash: h}, ok
|
|
}
|
|
|
|
// Close the underlying channel
|
|
func (s *AvalancheNewTx) Close() {
|
|
close(s.channel)
|
|
}
|