Documentation
¶
Index ¶
- Variables
- type Client
- type EthClient
- type MultiClient
- func (mc *MultiClient) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error)
- func (mc *MultiClient) BlockNumber(ctx context.Context) (uint64, error)
- func (mc *MultiClient) ChainID(ctx context.Context) (*big.Int, error)
- func (mc *MultiClient) Close()
- func (mc *MultiClient) CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error)
- func (mc *MultiClient) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error)
- func (mc *MultiClient) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error)
- type Node
- func (n *Node) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error)
- func (n *Node) BlockNumber(ctx context.Context) (uint64, error)
- func (n *Node) ChainID(ctx context.Context) (*big.Int, error)
- func (n *Node) Close()
- func (n *Node) CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error)
- func (n *Node) CurrentConcurrency() int
- func (n *Node) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error)
- func (n *Node) GetErrorCount() uint64
- func (n *Node) GetLatency() int64
- func (n *Node) GetLatestBlock() uint64
- func (n *Node) GetTotalErrors() uint64
- func (n *Node) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error)
- func (n *Node) IsCircuitBroken() bool
- func (n *Node) MeetsHeightRequirement(requiredHeight uint64) bool
- func (n *Node) Priority() int
- func (n *Node) RecordMetric(start time.Time, err error)
- func (n *Node) Release()
- func (n *Node) ResetCircuitBreaker()
- func (n *Node) Score(globalMaxHeight uint64) int64
- func (n *Node) TripCircuitBreaker()
- func (n *Node) TryAcquire(ctx context.Context) error
- func (n *Node) URL() string
- func (n *Node) UpdateHeight(h uint64)
- type NodeConfig
Constants ¶
This section is empty.
Variables ¶
var ( ErrNoAvailableNodes = errors.New("no available rpc nodes") ErrNoNodeMeetsHeight = errors.New("no node meets the required block height") )
Error definitions
var ( ErrCircuitBroken = errors.New("node circuit breaker is open") ErrRateLimitExceeded = errors.New("node rate limit exceeded") ErrNodeBusy = errors.New("node is busy (max concurrent reached)") )
Error definitions
Functions ¶
This section is empty.
Types ¶
type Client ¶
type Client interface {
// ChainID retrieves the chain ID
ChainID(ctx context.Context) (*big.Int, error)
// BlockNumber retrieves the latest block height
BlockNumber(ctx context.Context) (uint64, error)
// HeaderByNumber retrieves a block header (used for fast Bloom Filter checks)
HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error)
// BlockByNumber retrieves a full block (used for native transfer scanning)
BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error)
// FilterLogs retrieves logs (used for ERC20 scanning)
FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error)
// CodeAt checks contract code (used for safety validation)
CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error)
// Close closes the connection
Close()
}
Client defines the minimal set of RPC methods required by the Scanner. This allows for mocking the client in tests or implementing multi-node load balancing.
type EthClient ¶
type EthClient interface {
ChainID(ctx context.Context) (*big.Int, error)
BlockNumber(ctx context.Context) (uint64, error)
HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error)
BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error)
FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error)
CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error)
Close()
}
EthClient abstracts the underlying ethclient.Client implementation for easier mocking/testing
type MultiClient ¶
type MultiClient struct {
// contains filtered or unexported fields
}
MultiClient manages multiple RPC nodes, providing load balancing and failover
func NewClient ¶
func NewClient(ctx context.Context, configs []NodeConfig) (*MultiClient, error)
NewClient initializes a multi-node client
func NewClientWithNodes ¶
func NewClientWithNodes(ctx context.Context, nodes []*Node) (*MultiClient, error)
NewClientWithNodes initializes MultiClient with existing nodes (for testing or advanced usage)
func (*MultiClient) BlockByNumber ¶
BlockByNumber retrieves a full block from the best available node
func (*MultiClient) BlockNumber ¶
func (mc *MultiClient) BlockNumber(ctx context.Context) (uint64, error)
BlockNumber retrieves the latest block height across all nodes (cached if possible)
func (*MultiClient) Close ¶
func (mc *MultiClient) Close()
Close closes all underlying RPC connections
func (*MultiClient) CodeAt ¶
func (mc *MultiClient) CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error)
CodeAt retrieves the contract code at a given address from the best available node
func (*MultiClient) FilterLogs ¶
func (mc *MultiClient) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error)
FilterLogs retrieves logs from the best available node based on the query
func (*MultiClient) HeaderByNumber ¶
HeaderByNumber retrieves a block header from the best available node
type Node ¶
type Node struct {
// contains filtered or unexported fields
}
Node wraps the underlying ethclient and provides health monitoring and metric tracking.
func NewNode ¶
func NewNode(ctx context.Context, cfg NodeConfig) (*Node, error)
NewNode creates a new RPC node (Production)
func NewNodeWithClient ¶
func NewNodeWithClient(cfg NodeConfig, client EthClient) *Node
NewNodeWithClient initializes Node with a pre-created client (Testing/DI)
func (*Node) BlockByNumber ¶
BlockByNumber retrieves a full block from the node
func (*Node) BlockNumber ¶
BlockNumber retrieves the latest block height from the node
func (*Node) CodeAt ¶
func (n *Node) CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error)
CodeAt retrieves the contract code at a given address
func (*Node) CurrentConcurrency ¶ added in v0.2.0
CurrentConcurrency returns the current number of concurrent requests
func (*Node) FilterLogs ¶
FilterLogs retrieves logs from the node based on the query
func (*Node) GetErrorCount ¶
GetErrorCount returns the current consecutive error count
func (*Node) GetLatency ¶
GetLatency returns the average latency in ms
func (*Node) GetLatestBlock ¶
GetLatestBlock returns the latest block height observed by this node
func (*Node) GetTotalErrors ¶
GetTotalErrors returns the total error count
func (*Node) HeaderByNumber ¶
HeaderByNumber retrieves a block header from the node
func (*Node) IsCircuitBroken ¶ added in v0.2.0
IsCircuitBroken checks if the circuit breaker is open
func (*Node) MeetsHeightRequirement ¶ added in v0.2.0
MeetsHeightRequirement checks if the node has synced to the required height
func (*Node) RecordMetric ¶
RecordMetric records result of a call, updating latency and error count
func (*Node) ResetCircuitBreaker ¶ added in v0.2.0
func (n *Node) ResetCircuitBreaker()
ResetCircuitBreaker closes the circuit breaker
func (*Node) Score ¶
Score calculates the real-time score of the node. Higher is better. Formula: (Priority * 100) - (Latency / 10) - (ConsecutiveErrors * 500) Points are also deducted if the node lags too far behind the global max height.
func (*Node) TripCircuitBreaker ¶ added in v0.2.0
func (n *Node) TripCircuitBreaker()
TripCircuitBreaker opens the circuit breaker
func (*Node) TryAcquire ¶ added in v0.2.0
TryAcquire attempts to acquire the node for use (non-blocking)
func (*Node) UpdateHeight ¶
UpdateHeight updates the latest block height for the node
type NodeConfig ¶
type NodeConfig struct {
URL string
Priority int // Initial weight (1-100), higher is more preferred
RateLimit int // QPS limit for this node, 0 means unlimited
MaxConcurrent int // Max concurrent requests for this node, 0 means unlimited
}
NodeConfig represents configuration for a single RPC node