package main import ( "context" "log" "os" "os/signal" "strconv" "syscall" "github.com/ethereum/go-ethereum/ethclient" pgconfig "github.com/explorer/backend/libs/go-pgconfig" "github.com/explorer/backend/indexer/listener" "github.com/explorer/backend/indexer/processor" "github.com/jackc/pgx/v5/pgxpool" ) func main() { ctx, cancel := context.WithCancel(context.Background()) defer cancel() // Load configuration (reusable lib: libs/go-pgconfig) dbConfig := pgconfig.LoadDatabaseConfig() poolConfig, err := dbConfig.PoolConfig() if err != nil { log.Fatalf("Failed to create pool config: %v", err) } // Connect to database db, err := pgxpool.NewWithConfig(ctx, poolConfig) if err != nil { log.Fatalf("Failed to connect to database: %v", err) } defer db.Close() // Connect to RPC rpcURL := os.Getenv("RPC_URL") if rpcURL == "" { rpcURL = "http://localhost:8545" } wsURL := os.Getenv("WS_URL") chainID := 138 if envChainID := os.Getenv("CHAIN_ID"); envChainID != "" { if id, err := strconv.Atoi(envChainID); err == nil { chainID = id } } client, err := ethclient.Dial(rpcURL) if err != nil { log.Fatalf("Failed to connect to RPC: %v", err) } defer client.Close() // Create block listener blockListener, err := listener.NewBlockListener(rpcURL, wsURL, int64(chainID)) if err != nil { log.Fatalf("Failed to create block listener: %v", err) } defer blockListener.Stop() // Create block processor blockProcessor := processor.NewBlockProcessor(db, client, chainID) // Start listening if err := blockListener.Start(); err != nil { log.Fatalf("Failed to start block listener: %v", err) } // Process blocks go func() { for block := range blockListener.GetBlockChannel() { if err := blockProcessor.ProcessBlock(ctx, block); err != nil { log.Printf("Failed to process block %d: %v", block.Number().Int64(), err) } else { log.Printf("Processed block %d", block.Number().Int64()) } } }() // Wait for interrupt sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM) <-sigChan log.Println("Shutting down...") }