Skip to content

Instantly share code, notes, and snippets.

@areshand
Created February 18, 2025 18:53
Show Gist options
  • Save areshand/3aee6b11714bb50150b0f85288254235 to your computer and use it in GitHub Desktop.
Save areshand/3aee6b11714bb50150b0f85288254235 to your computer and use it in GitHub Desktop.
package main
import (
"context"
"fmt"
"log"
"math/big"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
)
// processBlock processes a single block and counts the occurrences of each event signature
func processBlock(client *ethclient.Client, blockNumber *big.Int) (map[string]int, error) {
eventCounts := make(map[string]int)
// Retrieve the block by number
block, err := client.BlockByNumber(context.Background(), blockNumber)
if err != nil {
if blockNumber.Sign() <= 0 {
return nil, fmt.Errorf("invalid block number %s: block numbers must be positive", blockNumber.String())
}
return nil, fmt.Errorf("failed to retrieve block %s: %v", blockNumber.String(), err)
}
// Process each transaction in the block
for _, tx := range block.Transactions() {
var txReceipt *types.Receipt
retries := 3
for retries > 0 {
txReceipt, err = client.TransactionReceipt(context.Background(), tx.Hash())
if err == nil {
break
}
retries--
log.Printf("retrying transaction receipt fetch for %s, retries left: %d", tx.Hash().Hex(), retries)
}
if err != nil {
log.Printf("failed to get transaction receipt for %s after retries: %v", tx.Hash().Hex(), err)
continue
}
// Process logs in the transaction receipt
for _, logEntry := range txReceipt.Logs {
if len(logEntry.Topics) > 0 && logEntry.Topics[0].Hex() != "" {
// The first topic is the event signature
signature := logEntry.Topics[0].Hex()
eventCounts[signature]++
}
}
}
return eventCounts, nil
}
// processBlockRange processes a range of blocks and aggregates event counts
func processBlockRange(client *ethclient.Client, start, end *big.Int) (map[string]int, error) {
totalEventCounts := make(map[string]int)
// Iterate over the block range
for blockNumber := new(big.Int).Set(start); blockNumber.Cmp(end) <= 0; blockNumber.Add(blockNumber, big.NewInt(1)) {
eventCounts, err := processBlock(client, blockNumber)
if err != nil {
return nil, fmt.Errorf("failed to process block %s: %v", blockNumber.String(), err)
}
// Aggregate event counts
for signature, count := range eventCounts {
totalEventCounts[signature] += count
}
}
return totalEventCounts, nil
}
func main() {
client, err := ethclient.Dial("https://mainnet.storyrpc.io")
if err != nil {
log.Fatalf("Failed to connect to the Ethereum client: %v", err)
}
// Define the block range (latest 10 blocks)
latestBlock, err := client.BlockNumber(context.Background())
if err != nil {
log.Fatalf("Failed to get latest block number: %v", err)
}
start := new(big.Int).SetUint64(latestBlock - 9)
end := new(big.Int).SetUint64(latestBlock)
totalEventCounts, err := processBlockRange(client, start, end)
if err != nil {
log.Fatalf("Failed to process block range: %v", err)
}
// Print the aggregated event counts
fmt.Println("Total event counts across the block range:")
for signature, count := range totalEventCounts {
fmt.Printf("%s: %d\n", signature, count)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment