Run an Indexer
Indexers are the first step in the cross-chain flow. They monitor for cross-chain transfer events, verify proofs, and relay user assets to the user's Smart Account on the destination chain.
What Indexers Do
1. MONITOR SOURCE CHAIN
└── Watch for burn events (TokenMessenger.DepositForBurn)
2. WAIT FOR ATTESTATION
└── Verify cross-chain proof
3. RECEIVE ASSETS
└── Deliver assets to user's Smart Account on destination chain
4. EARN FEE
└── Indexer fee paid when message is indexed
Requirements
| Requirement | Minimum | Recommended |
|---|---|---|
| CPU | 2 cores | 4 cores |
| RAM | 2 GB | 4 GB |
| Storage | 10 GB | 20 GB |
| Network | 10 Mbps | 100 Mbps |
| ETH (destination) | 0.1 ETH | 0.5 ETH |
Quick Start
1. Clone Repository
git clone https://github.com/pons-network/resolver
cd resolver
npm install
2. Configure Environment
cp .env.example .env
Edit .env:
# Mode
OPERATOR_MODE=indexer
# Wallet (NEVER use your main wallet)
PRIVATE_KEY=your_private_key_here
# Chain Configuration (Sepolia → Arc Testnet)
SOURCE_CHAIN_ID=11155111
DESTINATION_CHAIN_ID=88991
# RPC Endpoints
SOURCE_RPC_URL=https://eth-sepolia.g.alchemy.com/v2/YOUR_KEY
DESTINATION_RPC_URL=https://rpc.testnet.arc.network
# Fee Configuration
MIN_INDEXER_FEE=100000 # Minimum fee to process (in token units)
3. Run Indexer
# Development
npm run start -- --mode indexer
# Production (with PM2)
pm2 start npm --name "pons-indexer" -- run start -- --mode indexer
# Docker
docker-compose up -d indexer
Configuration Reference
Core Settings
# Required
PRIVATE_KEY= # Operator wallet (funded with ETH)
SOURCE_RPC_URL= # Source chain RPC
DESTINATION_RPC_URL= # Destination chain RPC
# Chain IDs
SOURCE_CHAIN_ID=11155111 # Sepolia
DESTINATION_CHAIN_ID=88991 # Arc Testnet
Fee Settings
# Minimum fee to process a transaction
MIN_INDEXER_FEE=100000 # Minimum fee (in token units)
# Skip transactions with fees below this
# Set higher in high-gas conditions
Performance Settings
# Concurrent processing
MAX_CONCURRENT_JOBS=5 # Parallel transactions
# Polling intervals
SOURCE_POLL_INTERVAL_MS=10000 # How often to check source chain
ATTESTATION_POLL_INTERVAL_MS=30000 # How often to poll Circle
Historical Scanning
# Catch missed messages after restarts
HISTORICAL_SCAN_ENABLED=true
HISTORICAL_TIME_WINDOW_MS=3600000 # Look back 1 hour
HISTORICAL_SCAN_INTERVAL_MS=300000 # Re-scan every 5 min
Docker Deployment
docker-compose.yml
version: '3.8'
services:
indexer:
build: .
command: ["npm", "run", "start", "--", "--mode", "indexer"]
env_file:
- .env
restart: unless-stopped
deploy:
resources:
limits:
cpus: '2'
memory: 2G
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
Run
docker-compose up -d indexer
docker-compose logs -f indexer
Monitoring
Health Check
# Check if process is running
pm2 status pons-indexer
# View logs
pm2 logs pons-indexer --lines 100
Key Metrics
Monitor these values:
| Metric | Healthy | Action if Unhealthy |
|---|---|---|
| Messages indexed/hour | >0 | Check RPC connection |
| Success rate | >95% | Check wallet balance |
| Wallet balance | >0.05 ETH | Refill wallet |
| Error rate | Less than 5% | Check logs |
Log Messages
✅ Good:
[INFO] Indexer started, monitoring source chain
[INFO] Found burn event: 0xabc...
[INFO] Attestation received for message
[INFO] Message indexed successfully, earned indexer fee
⚠️ Warning:
[WARN] Low wallet balance: 0.04 ETH
❌ Error:
[ERROR] Failed to index message: insufficient gas
[ERROR] RPC connection failed
Troubleshooting
"Insufficient gas"
# Check balance
cast balance $WALLET_ADDRESS --rpc-url $DESTINATION_RPC_URL
# Fund wallet with more ETH
# Sepolia: use faucet
# Mainnet: transfer from exchange
"Attestation not found"
- Normal for cross-chain transfers (wait for proof)
- If persists, check cross-chain protocol status
"Already indexed"
- Another indexer processed this message first
- This is normal competition behavior
- Increase uptime to catch more messages
"RPC rate limited"
# Use a better RPC provider or run your own node
SOURCE_RPC_URL=https://your-own-node.com
Profitability
Costs
| Item | Estimated Cost |
|---|---|
| Gas per index | ~0.002 ETH |
| Server (VPS) | ~$10-50/month |
Revenue
| Volume | Monthly Transactions | Earnings Potential |
|---|---|---|
| Low | ~3,000/month | Covers server costs |
| Medium | ~15,000/month | Profitable |
| High | ~30,000/month | Strong returns |
Break-even
- Earnings depend on fee rates and network volume
- Server costs: ~$20-50/month
- Gas costs: ~$6/month (100 txn * $0.002)
- Net profit: ~$250/month
Best Practices
Wallet Management
- Use a dedicated wallet (never your main wallet)
- Start with small amounts
- Set up balance alerts
- Withdraw earnings regularly
Uptime
- Use PM2 or Docker with auto-restart
- Set up health monitoring
- Use reliable RPC providers
- Consider running multiple instances
Security
- Never expose private key
- Run behind firewall
- Keep software updated
- Monitor for suspicious activity
Next Steps
- Run a Resolver: Add resolver to earn more fees
- Security Guide: Production security best practices