mirror of
https://github.com/grassrootseconomics/eth-tracker.git
synced 2026-05-18 02:35:20 +02:00
release: v1.0.0-rc
This commit is contained in:
121
internal/chain/celo_rpc.go
Normal file
121
internal/chain/celo_rpc.go
Normal file
@@ -0,0 +1,121 @@
|
||||
package chain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/big"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/celo-org/celo-blockchain/common"
|
||||
"github.com/celo-org/celo-blockchain/core/types"
|
||||
"github.com/celo-org/celo-blockchain/rpc"
|
||||
"github.com/grassrootseconomics/celoutils/v3"
|
||||
"github.com/grassrootseconomics/w3-celo"
|
||||
"github.com/grassrootseconomics/w3-celo/module/eth"
|
||||
"github.com/grassrootseconomics/w3-celo/w3types"
|
||||
)
|
||||
|
||||
type (
|
||||
CeloRPCOpts struct {
|
||||
RPCEndpoint string
|
||||
ChainID int64
|
||||
}
|
||||
|
||||
CeloRPC struct {
|
||||
provider *celoutils.Provider
|
||||
}
|
||||
)
|
||||
|
||||
func NewRPCFetcher(o CeloRPCOpts) (Chain, error) {
|
||||
customRPCClient, err := lowTimeoutRPCClient(o.RPCEndpoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
chainProvider := celoutils.NewProvider(
|
||||
o.RPCEndpoint,
|
||||
o.ChainID,
|
||||
celoutils.WithClient(customRPCClient),
|
||||
)
|
||||
|
||||
return &CeloRPC{
|
||||
provider: chainProvider,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func lowTimeoutRPCClient(rpcEndpoint string) (*w3.Client, error) {
|
||||
httpClient := &http.Client{
|
||||
Timeout: 10 * time.Second,
|
||||
}
|
||||
|
||||
rpcClient, err := rpc.DialHTTPWithClient(
|
||||
rpcEndpoint,
|
||||
httpClient,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return w3.NewClient(rpcClient), nil
|
||||
}
|
||||
|
||||
func (c *CeloRPC) GetBlocks(ctx context.Context, blockNumbers []uint64) ([]types.Block, error) {
|
||||
blocksCount := len(blockNumbers)
|
||||
calls := make([]w3types.RPCCaller, blocksCount)
|
||||
blocks := make([]types.Block, blocksCount)
|
||||
|
||||
for i, v := range blockNumbers {
|
||||
calls[i] = eth.BlockByNumber(new(big.Int).SetUint64(v)).Returns(&blocks[i])
|
||||
}
|
||||
|
||||
if err := c.provider.Client.CallCtx(ctx, calls...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return blocks, nil
|
||||
}
|
||||
|
||||
func (c *CeloRPC) GetBlock(ctx context.Context, blockNumber uint64) (*types.Block, error) {
|
||||
var block types.Block
|
||||
blockCall := eth.BlockByNumber(new(big.Int).SetUint64(blockNumber)).Returns(&block)
|
||||
|
||||
if err := c.provider.Client.CallCtx(ctx, blockCall); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &block, nil
|
||||
}
|
||||
|
||||
func (c *CeloRPC) GetLatestBlock(ctx context.Context) (uint64, error) {
|
||||
var latestBlock big.Int
|
||||
latestBlockCall := eth.BlockNumber().Returns(&latestBlock)
|
||||
|
||||
if err := c.provider.Client.CallCtx(ctx, latestBlockCall); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return latestBlock.Uint64(), nil
|
||||
}
|
||||
|
||||
func (c *CeloRPC) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, error) {
|
||||
var transaction types.Transaction
|
||||
if err := c.provider.Client.CallCtx(ctx, eth.Tx(txHash).Returns(&transaction)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &transaction, nil
|
||||
}
|
||||
|
||||
func (c *CeloRPC) GetReceipts(ctx context.Context, blockNumber *big.Int) (types.Receipts, error) {
|
||||
var receipts types.Receipts
|
||||
|
||||
if err := c.provider.Client.CallCtx(ctx, eth.BlockReceipts(blockNumber).Returns(&receipts)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return receipts, nil
|
||||
}
|
||||
|
||||
func (c *CeloRPC) Provider() *celoutils.Provider {
|
||||
return c.provider
|
||||
}
|
||||
98
internal/chain/celo_rpc_e2e_test.go
Normal file
98
internal/chain/celo_rpc_e2e_test.go
Normal file
@@ -0,0 +1,98 @@
|
||||
package chain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
const (
|
||||
testRPCEndpoint = "https://celo.archive.grassecon.net"
|
||||
testChainID = 42220
|
||||
)
|
||||
|
||||
func setupCeloRPC() (Chain, error) {
|
||||
opts := CeloRPCOpts{
|
||||
RPCEndpoint: testRPCEndpoint,
|
||||
ChainID: testChainID,
|
||||
}
|
||||
return NewRPCFetcher(opts)
|
||||
}
|
||||
|
||||
func TestRPC_GetBlocks(t *testing.T) {
|
||||
rpcFetcher, err := setupCeloRPC()
|
||||
require.NoError(t, err)
|
||||
|
||||
blockNumbers := []uint64{
|
||||
19_600_000,
|
||||
23_000_000,
|
||||
27_000_000,
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
blocks, err := rpcFetcher.GetBlocks(ctx, blockNumbers)
|
||||
require.NoError(t, err)
|
||||
t.Logf("blocks %+v\n", blocks)
|
||||
}
|
||||
|
||||
func TestRPC_GetBlock(t *testing.T) {
|
||||
rpcFetcher, err := setupCeloRPC()
|
||||
require.NoError(t, err)
|
||||
|
||||
var blockNumber uint64 = 19_900_000
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
block, err := rpcFetcher.GetBlock(ctx, blockNumber)
|
||||
require.NoError(t, err)
|
||||
t.Logf("block %+v\n", block)
|
||||
}
|
||||
|
||||
func TestRPC_GetLatestBlock(t *testing.T) {
|
||||
rpcFetcher, err := setupCeloRPC()
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
block, err := rpcFetcher.GetLatestBlock(ctx)
|
||||
require.NoError(t, err)
|
||||
t.Logf("block %+v\n", block)
|
||||
}
|
||||
|
||||
func TestRPC_GetTransaction(t *testing.T) {
|
||||
rpcFetcher, err := setupCeloRPC()
|
||||
require.NoError(t, err)
|
||||
|
||||
var blockNumber uint64 = 19_900_000
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
block, err := rpcFetcher.GetBlock(ctx, blockNumber)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, block)
|
||||
|
||||
transaction, err := rpcFetcher.GetTransaction(ctx, block.Transactions()[0].Hash())
|
||||
require.NoError(t, err)
|
||||
t.Logf("transaction %+v\n", transaction)
|
||||
}
|
||||
|
||||
func TestRPC_GetReceipts(t *testing.T) {
|
||||
rpcFetcher, err := setupCeloRPC()
|
||||
require.NoError(t, err)
|
||||
|
||||
var blockNumber uint64 = 19_900_000
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
block, err := rpcFetcher.GetBlock(ctx, blockNumber)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, block)
|
||||
|
||||
receipts, err := rpcFetcher.GetReceipts(ctx, block.Number())
|
||||
require.NoError(t, err)
|
||||
t.Logf("receipts %+v\n", receipts)
|
||||
}
|
||||
20
internal/chain/chain.go
Normal file
20
internal/chain/chain.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package chain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/big"
|
||||
|
||||
"github.com/celo-org/celo-blockchain/common"
|
||||
"github.com/celo-org/celo-blockchain/core/types"
|
||||
"github.com/grassrootseconomics/celoutils/v3"
|
||||
)
|
||||
|
||||
type Chain interface {
|
||||
GetBlocks(context.Context, []uint64) ([]types.Block, error)
|
||||
GetBlock(context.Context, uint64) (*types.Block, error)
|
||||
GetLatestBlock(context.Context) (uint64, error)
|
||||
GetTransaction(context.Context, common.Hash) (*types.Transaction, error)
|
||||
GetReceipts(context.Context, *big.Int) (types.Receipts, error)
|
||||
// Expose provider until we eject from celoutils
|
||||
Provider() *celoutils.Provider
|
||||
}
|
||||
3
internal/chain/eth_rpc.go
Normal file
3
internal/chain/eth_rpc.go
Normal file
@@ -0,0 +1,3 @@
|
||||
package chain
|
||||
|
||||
// TBA
|
||||
Reference in New Issue
Block a user