package fetch import ( "context" "math/big" "strings" "github.com/celo-org/celo-blockchain/common/hexutil" "github.com/celo-org/celo-blockchain/core/types" celo "github.com/grassrootseconomics/cic-celo-sdk" "github.com/grassrootseconomics/w3-celo-patch/module/eth" "github.com/grassrootseconomics/w3-celo-patch/w3types" ) type RPCOpts struct { RPCProvider *celo.Provider } type RPC struct { provider *celo.Provider } func NewRPCFetcher(o RPCOpts) Fetch { return &RPC{ provider: o.RPCProvider, } } // This method makes 2 calls. 1 for the block and 1 batched call for txs + receipts. // Should work on free tier RPC services. func (f *RPC) Block(ctx context.Context, blockNumber uint64) (FetchResponse, error) { var ( block types.Block fetchResponse FetchResponse ) if err := f.provider.Client.CallCtx( ctx, eth.BlockByNumber(big.NewInt(int64(blockNumber))).Returns(&block), ); err != nil { return FetchResponse{}, err } txCount := len(block.Transactions()) batchCalls := make([]w3types.Caller, txCount*2) txs := make([]types.Transaction, txCount) txsReceipt := make([]types.Receipt, txCount) for i, tx := range block.Transactions() { batchCalls[i] = eth.Tx(tx.Hash()).Returns(&txs[i]) batchCalls[txCount+i] = eth.TxReceipt(tx.Hash()).Returns(&txsReceipt[i]) } if err := f.provider.Client.CallCtx( ctx, batchCalls..., ); err != nil { return FetchResponse{}, nil } for i := 0; i < txCount; i++ { tx := Transaction{} tx.Block.Number = block.NumberU64() tx.Block.Timestamp = hexutil.EncodeUint64(block.Time()) tx.Hash = txsReceipt[i].TxHash.Hex() tx.Index = txsReceipt[i].TransactionIndex from, err := types.Sender(types.LatestSignerForChainID(txs[i].ChainId()), &txs[i]) if err != nil { return FetchResponse{}, err } tx.From.Address = strings.ToLower(from.Hex()) tx.To.Address = strings.ToLower(txs[i].To().Hex()) tx.Value = hexutil.EncodeBig(txs[i].Value()) tx.InputData = hexutil.Encode(txs[i].Data()) tx.Status = txsReceipt[i].Status tx.GasUsed = txsReceipt[i].GasUsed fetchResponse.Data.Block.Transactions = append( fetchResponse.Data.Block.Transactions, tx, ) } return fetchResponse, nil }