Skip to content

emdin/igra-simple-indexer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

igra-simple-indexer

Watches Kaspa L1 via gRPC, indexes all IGRA transactions, and serves instant L2→L1 lookups via HTTP API.

Quick Start

docker build -t igra-simple-indexer .

# First run — provide a recent block hash as starting point:
docker run -d --name indexer --restart unless-stopped \
  -v indexer-data:/data -p 3000:3000 \
  igra-simple-indexer --start-hash <RECENT_BLOCK_HASH>

# Subsequent runs resume automatically from saved cursor:
docker run -d --name indexer --restart unless-stopped \
  -v indexer-data:/data -p 3000:3000 \
  igra-simple-indexer

Getting a start hash

The indexer needs a Kaspa block hash to begin from. Get the current tip from logs:

# Run briefly to see the sink hash, then stop and restart with it:
docker run --rm igra-simple-indexer 2>&1 | head -5
# Look for: sink=<HASH>

Block Explorer Integration

Every IGRA L2 transaction originates as a Kaspa L1 transaction. This indexer maps L2 tx hashes back to their L1 origin, so block explorers can link each L2 transaction to its L1 proof.

Lookup L1 origin for an L2 transaction

GET /api/v1/l1tx/{l2_tx_hash}

The l2_tx_hash is the standard EVM transaction hash (with or without 0x prefix, case-insensitive).

Found:

{
  "l2_tx_hash": "0x8a3c...f1b2",
  "l1_tx_id": "97b1a4c3...e8f0",
  "daa_score": 380089434,
  "status": "found"
}

Not found:

{
  "l2_tx_hash": "0x8a3c...f1b2",
  "status": "not_found"
}

The l1_tx_id is a Kaspa transaction ID. Link to it on a Kaspa explorer:

https://explorer.kaspa.org/txs/{l1_tx_id}

Lookup L1 origin for a withdrawal (entry TX)

GET /api/v1/l1tx/entry/{withdrawal_index}

Found:

{
  "withdrawal_index": 42,
  "l1_tx_id": "97b1f2a1...c3d4",
  "recipient": "0x742d35cc6634c0532925a3b844bc9e7595f2bd38",
  "amount_sompi": 100000000,
  "daa_score": 380100000,
  "l2_block_number": 12345,
  "status": "found"
}

Health / status check

GET /api/v1/health
{
  "send_txs_indexed": 1842,
  "entry_txs_indexed": 15,
  "last_daa_score": 381085692,
  "last_chain_hash": "26f073...",
  "status": "ok"
}

Integration notes

  • Base URL: The indexer runs on port 3000 by default. We will provide the production URL.
  • Latency: Lookups are instant (SQLite). Indexing lag is ~1 second behind L1 tip.
  • Not-found responses return HTTP 200 with "status": "not_found" — the tx may not have been indexed yet (if very recent) or may not be an IGRA transaction.
  • CORS is enabled, so browser-side calls work.

Example: adding an L1 link to an L2 tx page

const res = await fetch(`${INDEXER_URL}/api/v1/l1tx/${l2TxHash}`);
const data = await res.json();
if (data.status === "found") {
  // Show link: "View L1 proof on Kaspa"
  const kaspaUrl = `https://explorer.kaspa.org/txs/${data.l1_tx_id}`;
}

Deployment & Operations

CLI Options

Flag Default Description
--kaspa-rpc-url grpc://igra-mainnet.jobberwocky.co:16310 Kaspa gRPC endpoint (requires V2 API, kaspad v1.1.0+)
--evm-rpc-url https://rpc.igralabs.com:8545 IGRA L2 EVM JSON-RPC
--tx-id-prefix 97b1 Required Kaspa TX ID prefix
--db-path indexer.db SQLite database path
--listen 0.0.0.0:3000 HTTP API listen address
--start-daa 366020000 DAA score to start from (slow, walks chain)
--start-hash Block hash to start from (fast, skips walk)

Operations

Logs: docker logs -f indexer

Log levels: Set RUST_LOG env var. Default: simple_indexer=info. Use simple_indexer=debug for per-block output.

docker run -d --name indexer --restart unless-stopped \
  -e RUST_LOG=simple_indexer=debug \
  -v indexer-data:/data -p 3000:3000 \
  igra-simple-indexer --start-hash <HASH>

Storage: ~12 MB/day at 1 TPS. SQLite DB lives in the Docker volume at /data/indexer.db.

Monitoring: Poll /api/v1/health — check that last_daa_score advances. If it stalls, the gRPC connection may be down (auto-reconnects with 5s backoff).

Backup: docker cp indexer:/data/indexer.db ./backup.db (stop container first for clean copy, or copy both .db and .db-wal).

Kaspa node requirement: The gRPC endpoint must support GetVirtualChainFromBlockV2 (kaspad v1.1.0+). The default igra-mainnet.jobberwocky.co:16310 supports this. Standard Kaspa nodes on port 16110 may not.

Pruning: Kaspa prunes old blocks (~24h). The indexer can only start from blocks within the pruning window. Historical data requires an archival node.

About

L1→L2 indexer for IGRA transactions on Kaspa

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors