Skip to content

pk-labs/penumbra-explorer-backend

Repository files navigation

Powered by Tokio Built with Pindexer Index by CometIndex Database PostgreSQL Containerized with Docker
Code Style: rustfmt Linted with Clippy

Penumbra Explorer Backend

Backend indexer for exploring the Penumbra blockchain built with Rust

Getting Started

  1. Set up Rust (1.83.0 or later)
  2. Install dependencies with cargo build
  3. 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"

Cargo Scripts

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

Project Structure

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

Docker

You can also run the application using Docker:

docker-compose up -d

View logs:

docker-compose logs -f app

API

The GraphQL API is accessible at:

WebSocket Support

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
  }
}

Example Queries

You can try the following sample GraphQL queries in the public playground:

Full Transaction Query

query {
  transaction(hash: "84A8AD3E364E1F98A7C73A5D411737F634A7802265C71A528EA9720BD2ED8095") {
    hash
    block {
      height
      createdAt
    }
    body {
      memo
      parameters {
        chainId
        fee {
          amount
        }
      }
    }
    raw
    rawJson
  }
}

Full Block Query (replace with actual query if available)

query {
  block(height: 123456) {
    height
    createdAt
    transactions {
      hash
      body {
        memo
      }
    }
  }
}

Configuration

Command Line Arguments

  • -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)

Testing

Tests are organized by module and can be run using cargo test. Critical components have unit tests covering core functionality.

Test Coverage

Key components with test coverage:

  • Transaction queue management
  • Parsing utilities
  • Block and transaction processing

Linting and Code Style

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