A high-performance blockchain event indexer that monitors ERC-20 token contracts and provides a powerful GraphQL API for querying transaction data. Perfect for building trading applications, analytics dashboards, and TradingView integrations.
- π Multi-Contract Indexing: Monitor multiple ERC-20 token contracts simultaneously
- π Rich Transaction Data: Index transfers with buyer/seller wallets, amounts, timestamps, and prices
- π GraphQL API: Flexible querying with filtering, pagination, and nested relationships
- βοΈ CLI Management: Simple command-line interface for easy management
- π Concurrent Processing: Goroutine-based monitoring for optimal performance
- πΎ Database Support: SQLite for development, PostgreSQL for production
- π TradingView Ready: Data format compatible with TradingView Lightweight Charts
- π REST Endpoints: Add new contracts dynamically via API
- Go 1.24+
- Ethereum node access (Infura, Alchemy, or local node)
# Clone and setup
git clone https://github.com/user/coin-indexer.git
cd coin-indexer
go mod tidy
# Configure (edit config/config.yaml with your settings)
# Add your Ethereum provider URL and contracts to monitor
# Start indexing blockchain events
go run main.go index
# Start GraphQL server (in another terminal)
go run main.go server
Visit http://localhost:8083/playground
to explore the GraphQL API!
query GetRecentTransactions {
transactions(limit: 10) {
id
txHash
fromAddress
toAddress
amount
tokenName
blockTimestamp
priceUsd
valueUsd
}
}
query GetUSDCTransactions {
transactions(
contractAddress: "0xA0b86a33E6417AaF4532CfAd6F41F68481a66CD1"
limit: 20
) {
id
txHash
fromAddress
toAddress
amount
blockNumber
blockTimestamp
}
}
query GetAddressActivity {
addressTransactions(
address: "0x742d35Cc6634C0532925a3b8D214c5b5c5c4b52"
limit: 15
) {
id
txHash
fromAddress
toAddress
amount
tokenName
blockTimestamp
}
}
query GetTransactionsByBlocks {
transactions(
fromBlock: 18500000
toBlock: 18600000
limit: 50
) {
id
txHash
blockNumber
fromAddress
toAddress
amount
tokenName
}
}
query GetLargeTransfers {
transactions(
limit: 25
tokenName: "USDC"
) {
id
amount
valueUsd
fromAddress
toAddress
txHash
blockTimestamp
}
}
query GetContracts {
contracts {
id
name
address
startBlock
lastBlock
isActive
createdAt
}
}
query GetContractDetails {
contract(address: "0xdAC17F958D2ee523a2206206994597C13D831ec7") {
id
name
address
startBlock
lastBlock
transactions {
id
amount
fromAddress
toAddress
blockTimestamp
}
}
}
query GetTransactionStats {
totalTransactions: transactionCount
usdcTransactions: transactionCount(
contractAddress: "0xA0b86a33E6417AaF4532CfAd6F41F68481a66CD1"
)
}
query GetFilteredTransactions {
transactions(
tokenName: "USDT"
fromBlock: 18500000
limit: 30
offset: 0
) {
id
txHash
blockNumber
logIndex
fromAddress
toAddress
amount
priceUsd
valueUsd
blockTimestamp
createdAt
}
}
query GetPaginatedTransactions($limit: Int!, $offset: Int!) {
transactions(limit: $limit, offset: $offset) {
id
txHash
fromAddress
toAddress
amount
tokenName
blockTimestamp
}
}
Variables:
{
"limit": 20,
"offset": 40
}
query DashboardData {
# Recent transactions
recentTx: transactions(limit: 5) {
id
txHash
amount
tokenName
fromAddress
toAddress
blockTimestamp
}
# Contract stats
contracts {
name
address
lastBlock
isActive
}
# Total transaction count
totalCount: transactionCount
}
query TokenAnalytics($tokenContract: String!) {
# Token transactions
transactions: transactions(
contractAddress: $tokenContract
limit: 100
) {
amount
valueUsd
blockTimestamp
}
# Token info
tokenInfo: contract(address: $tokenContract) {
name
address
lastBlock
}
# Transaction count
txCount: transactionCount(contractAddress: $tokenContract)
}
Variables:
{
"tokenContract": "0xA0b86a33E6417AaF4532CfAd6F41F68481a66CD1"
}
curl -X POST http://localhost:8080/contracts \
-H "Content-Type: application/json" \
-d '{
"name": "WETH",
"address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"start_block": 18000000
}'
curl http://localhost:8080/health
Edit config/config.yaml
to configure your setup:
# Server settings
server:
port: "8080"
host: "localhost"
# Database (SQLite for dev, PostgreSQL for production)
database:
driver: "sqlite"
dsn: "coin_indexer.db"
# Blockchain connection
blockchain:
provider_url: "wss://mainnet.infura.io/ws/v3/YOUR_PROJECT_ID"
confirmation_blocks: 12
poll_interval: 15
# Contracts to monitor
contracts:
tokens:
- name: "USDC"
address: "0xA0b86a33E6417AaF4532CfAd6F41F68481a66CD1"
start_block: 18500000
abi_file: "abis/erc20.json"
coin-indexor/
βββ cmd/ # CLI commands (root, index, server)
βββ config/ # Configuration files
βββ internal/
β βββ database/ # Database connection & migrations
β βββ indexer/ # Blockchain event monitoring
β βββ server/ # GraphQL & REST server
β βββ models/ # Data models
β βββ graphql/ # GraphQL schema & resolvers
βββ abis/ # Contract ABI files
βββ .vscode/ # VS Code tasks & debug config
βββ main.go # Application entry point
# Show available commands
go run main.go --help
# Start blockchain indexer
go run main.go index
# Start GraphQL server
go run main.go server
# Get command-specific help
go run main.go server --help
- transactions - Individual ERC-20 transfers with metadata
- contracts - Monitored token contracts configuration
- block_progress - Indexing progress tracking per contract
tx_hash
- Ethereum transaction hashfrom_address
/to_address
- Transfer participantsamount
- Token amount (as string for big numbers)price_usd
/value_usd
- Optional USD pricing datablock_timestamp
- When transaction occurredcontract_address
- Token contract address
Via Config File:
contracts:
tokens:
- name: "WETH"
address: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
start_block: 18000000
abi_file: "abis/erc20.json"
Via REST API:
curl -X POST http://localhost:8080/contracts \
-H "Content-Type: application/json" \
-d '{
"name": "WETH",
"address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"start_block": 18000000
}'
Available tasks in VS Code:
- Build Coin Indexer - Compile the project
- Run GraphQL Server - Start API server (background)
- Start Indexer - Begin blockchain monitoring (background)
Use VS Code's built-in debugger with the provided launch configurations:
- Launch GraphQL Server - Debug API server
- Launch Indexer - Debug blockchain indexing
- Debug Tests - Run and debug test suite
The indexer provides detailed logging for monitoring:
# View real-time logs
go run main.go index
# Example log output:
# INFO: Starting blockchain indexer...
# INFO: Starting to monitor contract USDC at 0xA0b8...
# INFO: Processed 15 events for USDC in blocks 18500100-18500200
##Production Deployment
database:
driver: "postgres"
dsn: "host=localhost user=indexer password=secret dbname=coin_indexer port=5432 sslmode=disable"
export CONFIG_FILE=/path/to/production/config.yaml
go run main.go server --config $CONFIG_FILE
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY . .
RUN go mod download && go build -o coin-indexer .
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/coin-indexer .
COPY --from=builder /app/config ./config
COPY --from=builder /app/abis ./abis
CMD ["./coin-indexer", "server"]
- Batch Size: Adjust
indexing.batch_size
based on node performance - Poll Interval: Increase
blockchain.poll_interval
for less frequent updates - Database: Use PostgreSQL with proper indexing for production
- Confirmation Blocks: Set
confirmation_blocks
based on finality requirements
- Fork the repository
- Create feature branch (
git checkout -b feature/amazing-feature
) - Commit changes (
git commit -m 'Add amazing feature'
) - Push to branch (
git push origin feature/amazing-feature
) - Open Pull Request
MIT License - see LICENSE file for details.
Happy indexing! π
For support or questions, please open an issue on GitHub.