package block import ( "context" "encoding/hex" "math/big" "github.com/ethereum/go-ethereum/core/types" "github.com/lmittmann/w3" "github.com/lmittmann/w3/module/eth" "github.com/lmittmann/w3/w3types" ) type BlockFetcherOpts struct { W3Client *w3.Client Signer types.Signer } type BlockFetcher struct { opts BlockFetcherOpts } func NewBlockFetcher(o BlockFetcherOpts) *BlockFetcher { return &BlockFetcher{o} } func (bf *BlockFetcher) FetchBlock(ctx context.Context, blockNumber *big.Int) (*FetchResponse, error) { var ( block types.Block ) if err := bf.opts.W3Client.CallCtx(ctx, eth.BlockByNumber(blockNumber).Returns(&block)); err != nil { return &FetchResponse{}, err } var ( txsCount = len(block.Transactions()) batchedCalls = make([]w3types.Caller, txsCount*2) txs = make([]types.Transaction, txsCount) receipts = make([]types.Receipt, txsCount) minimalTxs = make([]MinimalTransaction, txsCount) ) for i, block := range block.Transactions() { batchedCalls[i] = eth.Tx(block.Hash()).Returns(&txs[i]) batchedCalls[txsCount+i] = eth.TxReceipt(block.Hash()).Returns(&receipts[i]) } if err := bf.opts.W3Client.CallCtx(ctx, batchedCalls...); err != nil { return &FetchResponse{}, err } fetchResponse := &FetchResponse{ Block: MinimalBlock{ Hash: block.Hash(), Number: block.Number(), Bloom: block.Bloom(), GasLimit: block.GasLimit(), GasUsed: block.GasUsed(), Time: block.Time(), }, TransactionsCount: txsCount, } for i := 0; i < txsCount; i++ { msg, err := txs[i].AsMessage(bf.opts.Signer, nil) if err != nil { return &FetchResponse{}, err } minimalTxs[i] = MinimalTransaction{ Hash: txs[i].Hash(), From: msg.From(), To: msg.To(), Gas: msg.Gas(), GasPrice: msg.GasPrice(), Nonce: msg.Nonce(), Value: txs[i].Value(), InputData: hex.EncodeToString(msg.Data()), TransactionIndex: receipts[i].TransactionIndex, Status: receipts[i].Status, GasUsed: receipts[i].GasUsed, Bloom: receipts[i].Bloom, Logs: receipts[i].Logs, ContractAddress: receipts[i].ContractAddress, } } fetchResponse.Transactions = minimalTxs return fetchResponse, nil }