Skip to content

Instantly share code, notes, and snippets.

@ydm
Created February 11, 2026 10:43
Show Gist options
  • Select an option

  • Save ydm/b9178e693c38ec11413cf07be7dc6f8c to your computer and use it in GitHub Desktop.

Select an option

Save ydm/b9178e693c38ec11413cf07be7dc6f8c to your computer and use it in GitHub Desktop.
package main
import (
"context"
"encoding/csv"
"encoding/json"
"fmt"
"log"
"os"
"sync"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
)
const NODE = "https://mainnet.infura.io/v3/APIKEY"
type TxResult struct {
Hash string
BlockHash string
BlockNumber string
From string
To string
Value string
Input string
Nonce uint64
Gas uint64
GasPrice string
}
func main() {
client, err := ethclient.Dial(NODE)
if err != nil {
log.Fatalf("Failed to connect to Infura: %v", err)
}
defer client.Close()
txHashes := ReadStringsFromJSON("txhashes.json")
// txHashes := []string{}
var wg sync.WaitGroup
var mu sync.Mutex
results := []TxResult{}
missing := []string{}
workerCount := 2
sem := make(chan struct{}, workerCount)
for _, hashStr := range txHashes {
fmt.Print(".")
wg.Add(1)
sem <- struct{}{}
go func(h string) {
defer wg.Done()
defer func() { <-sem }()
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
defer cancel()
txHash := common.HexToHash(h)
tx, isPending, err := client.TransactionByHash(ctx, txHash)
if err != nil {
fmt.Println("\n[1]", err)
mu.Lock()
missing = append(missing, h)
mu.Unlock()
return
}
chainID, err := client.NetworkID(ctx)
if err != nil {
fmt.Println("\n[2]", err)
mu.Lock()
missing = append(missing, h)
mu.Unlock()
return
}
signer := types.LatestSignerForChainID(chainID)
from, err := signer.Sender(tx)
if err != nil {
fmt.Println("\n[3]", err)
mu.Lock()
missing = append(missing, h)
mu.Unlock()
return
}
var blockHash string
var blockNumber string
if !isPending {
receipt, err := client.TransactionReceipt(ctx, txHash)
if err == nil {
blockHash = receipt.BlockHash.Hex()
blockNumber = receipt.BlockNumber.String()
}
}
var to string
if tx.To() != nil {
to = tx.To().Hex()
}
result := TxResult{
Hash: tx.Hash().Hex(),
BlockHash: blockHash,
BlockNumber: blockNumber,
From: from.Hex(),
To: to,
Value: tx.Value().String(),
Input: fmt.Sprintf("0x%x", tx.Data()),
Nonce: tx.Nonce(),
Gas: tx.Gas(),
GasPrice: tx.GasPrice().String(),
}
mu.Lock()
results = append(results, result)
mu.Unlock()
}(hashStr)
}
wg.Wait()
writeTransactionsCSV("transactions.csv", results)
writeMissingCSV("missing_transactions.csv", missing)
}
func writeTransactionsCSV(filename string, txs []TxResult) {
file, err := os.Create(filename)
if err != nil {
log.Fatal(err)
}
defer file.Close()
writer := csv.NewWriter(file)
defer writer.Flush()
headers := []string{
"hash", "blockHash", "blockNumber", "from", "to",
"value", "input", "nonce", "gas", "gasPrice",
}
writer.Write(headers)
for _, tx := range txs {
writer.Write([]string{
tx.Hash,
tx.BlockHash,
tx.BlockNumber,
tx.From,
tx.To,
tx.Value,
tx.Input,
fmt.Sprintf("%d", tx.Nonce),
fmt.Sprintf("%d", tx.Gas),
tx.GasPrice,
})
}
}
func writeMissingCSV(filename string, hashes []string) {
file, err := os.Create(filename)
if err != nil {
log.Fatal(err)
}
defer file.Close()
writer := csv.NewWriter(file)
defer writer.Flush()
writer.Write([]string{"tx_hash"})
for _, h := range hashes {
writer.Write([]string{h})
}
}
func ReadStringsFromJSON(filename string) []string {
var result []string
file, err := os.Open(filename)
if err != nil {
return nil
}
defer file.Close()
decoder := json.NewDecoder(file)
_ = decoder.Decode(&result) // ignoring error per requirement
return result
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment