Backend indexer for exploring the Penumbra blockchain built with Rust
- Set up Rust (1.83.0 or later)
- Install dependencies with
cargo build - Run the application with:
cargo run -- \ -s "postgresql://user:password@source-host:5432/source-db?sslmode=require" \ -d "postgresql://user:password@dest-host:5432/dest-db" \ --genesis-json genesis.json \ -g "https://penumbra-1.radiantcommons.com"
| Script | Description |
|---|---|
cargo build --release |
Build app in release mode |
cargo run -- -s "SOURCE_DB" -d "DEST_DB" --genesis-json genesis.json -g "GRPC_URL" |
Run application with required parameters |
cargo test |
Run tests |
cargo test <test_name> |
Run a specific test |
cargo clippy --all-targets --all-features --workspace -- -W clippy::pedantic -D warnings |
Lint using strictest clippy rules |
cargo fmt |
Format code using rustfmt |
| Directory | Description |
|---|---|
migrations/ |
Database migration scripts |
src/api/ |
API implementation (GraphQL resolvers, handlers) |
src/api/graphql/ |
GraphQL schema, resolvers, and types |
src/app_views/ |
The heart of the blockchain indexing process |
src/ |
Core application code |
You can also run the application using Docker:
docker-compose up -dView logs:
docker-compose logs -f appThe GraphQL API is accessible at:
- GraphQL API:
/graphql - GraphQL Playground:
/graphql/playground - Public playground for testing: https://api.explorer.penumbra.zone/
The Penumbra Explorer Backend supports real-time updates via WebSocket GraphQL subscriptions. This enables live streaming of new blocks, transactions, and transaction count changes directly to subscribed clients.
Example subscriptions:
subscription {
latestBlocks(limit: 10) {
height
createdAt
transactionsCount
}
}
subscription {
latestTransactions(limit: 10) {
id
hash
raw
}
}
subscription {
transactionCount {
count
}
}You can try the following sample GraphQL queries in the public playground:
query {
transaction(hash: "84A8AD3E364E1F98A7C73A5D411737F634A7802265C71A528EA9720BD2ED8095") {
hash
block {
height
createdAt
}
body {
memo
parameters {
chainId
fee {
amount
}
}
}
raw
rawJson
}
}query {
block(height: 123456) {
height
createdAt
transactions {
hash
body {
memo
}
}
}
}-s, --source-db-url: Source database URL (required)-d, --dest-db-url: Destination database URL (required)--genesis-json: Path to Genesis JSON file (required)-g, --grpc-url: gRPC endpoint URL for IBC client status checks (default: https://penumbra-1.radiantcommons.com)--from-height: Starting block height (optional)--to-height: Ending block height (optional)--batch-size: Batch size for processing blocks (default: 100)--polling-interval-ms: Polling interval in milliseconds (default: 1000)
Tests are organized by module and can be run using cargo test. Critical components have unit tests covering core functionality.
Key components with test coverage:
- Transaction queue management
- Parsing utilities
- Block and transaction processing
The project uses:
- rustfmt for formatting:
cargo fmt - Clippy for linting with strict rules:
cargo clippy --all-targets --all-features --workspace -- -W clippy::pedantic -D warnings
The codebase follows Rust's naming conventions:
- snake_case for variables/functions
- CamelCase for types/traits