Skip to main content

Blockchain Indexer

Areacommon/indexerindexer
TypeShared libraryStandalone application / service
TechnologyKotlin, Micronaut, Apollo GraphQLTypeScript/Node.js, Subsquid
PurposeCalls the IndexerIndexes blockchain data
DatabaseNo owned databasePostgreSQL
Blockchain accessNo direct blockchain accessReads blockchain through RPC
APIGraphQL clientGraphQL server
DeploymentBundled into consuming servicesDeployed as processor and API
KafkaNo Kafka integrationPublishes blockchain events to Kafka
Data sourceExternal Indexer GraphQL APIBlockchain/RPC
Locationcommon/indexerindexer

Overview

The DEUSS platform contains two separate components named around the Indexer:

  • indexer is the actual blockchain indexing application. It reads smart-contract activity from the blockchain, stores the indexed data, exposes it through GraphQL, and publishes selected events to Kafka.
  • common/indexer is a reusable Kotlin client library. It allows other DEUSS services to query the running Indexer GraphQL API through a configured Apollo client. The components are complementary but have different responsibilities. The indexer creates and serves indexed blockchain data, while common/indexer consumes that data from application services.

Indexer

Summary & Purpose

indexer is a standalone TypeScript/Node.js application based on Subsquid. It processes blockchain blocks, transactions, and smart-contract events, persists the resulting domain data in PostgreSQL, and exposes the indexed data through a GraphQL API. The Indexer also publishes selected normalized blockchain events to Kafka and integrates with selected internal services during processing.

Business Responsibilities

  • Index blockchain activity from configured EVM contracts
  • Maintain queryable representations of blockchain entities and transactions
  • Track:
    • Companies and entities
    • Company wallets
    • Bonds and bond lifecycle
    • Tokens and token ownership
    • Market offers
    • Market deals
    • Transfers
    • Coupon eligibility
    • Historical blockchain changes
  • Expose indexed data through GraphQL
  • Publish selected blockchain events to Kafka
  • Enrich or synchronize data through internal service integrations
  • Support off-chain consumers that require blockchain-derived data

Indexed Domains

The processor is configured to monitor contracts and events related to:

  • Entity Registry
    • Entity registration
    • Entity status and metadata changes
    • Entity manager and authority updates
    • Account registration and role changes
  • Bond Registry
    • Bond publication
    • Bond issuance
    • Bond cancellation
    • Bond suspension and unsuspension
    • Bond redemption
  • Interest Discovery
    • Offer registration
    • Offer cancellation
    • Amount updates
    • Deal creation
    • Deal status changes
  • Fungible Token
    • Token transfers
    • Token pause and freeze operations
  • Company Wallets
    • Wallet creation
    • Wallet operation and role changes
  • Access and Role Management
    • Granting, revoking, and renouncing contract roles

Owned Data

The Indexer owns the indexed representation of blockchain data in its PostgreSQL database. The GraphQL schema exposes data including:

  • Accounts and account histories
  • Entities and entity histories
  • Entity types and metadata
  • Company wallets and wallet histories
  • Bonds and bond histories
  • Tokens, token owners, and token transfers
  • Market offers and market deals
  • Deal and offer histories
  • Contract operations
  • Blockchain synchronization status The Indexer is not the authoritative owner of off-chain business data such as payment records or partner profiles. It provides a queryable blockchain-derived view of the platform.

Inbound Interfaces

Blockchain RPC

The processor reads blockchain data through an EVM RPC endpoint. Relevant configuration includes:

  • CHAIN_URL
  • START_BLOCK
  • FINALITY_CONFIRMATION
  • RATE_LIMIT
  • Contract addresses for monitored contracts The processor supports finality confirmation and block-range configuration.

Internal Service Dependencies

The processor requires configuration for:

  • BOND_ISSUANCE_SERVICE_URL
  • REGISTRY_SERVICE_URL The exact business operations performed through these clients are implemented in the Indexer’s off-chain service integration layer.

Outbound Interfaces

GraphQL API

The Indexer exposes indexed data through a Subsquid GraphQL server. The API supports queries for:

  • Bonds
  • Bond ownership
  • Market offers
  • Market deals
  • Company wallets
  • Token ownership and transfers
  • Entity and account data
  • Historical records
  • Indexer synchronization status The API is consumed by services such as Registry Service, Core Payment Service, and Blockchain Event Service through common/indexer or dedicated clients.

Kafka

The Indexer publishes selected blockchain-derived events to Kafka. These events include activity related to:

  • Offers
  • Deals
  • Deal status changes
  • Bond publication
  • Token transfers
  • Amount updates
  • Counter-offer processing Kafka topic names and publishing behavior are implemented in the Indexer’s Kafka integration.

PostgreSQL

The Indexer persists indexed blockchain data in PostgreSQL using TypeORM and Subsquid’s TypeORM store.

Processing Model

The main processing flow is:

  1. Read blocks from the configured blockchain RPC endpoint.
  2. Load relevant logs and transactions.
  3. Identify handlers based on contract address, event topic, or transaction selector.
  4. Decode and process blockchain activity.
  5. Load related records and cached entities.
  6. Apply business-specific processing and off-chain synchronization.
  7. Commit indexed records to PostgreSQL.
  8. Publish selected events to Kafka. The processor uses a UnitOfWork to coordinate repositories, caching, service clients, event decoding, and persistence within block processing.

Deployment Topology

The Indexer is deployed as a Subsquid application with:

  • A blockchain processor
  • A GraphQL API
  • PostgreSQL
  • Blockchain RPC access The deployment is defined through squid.yaml and includes:
  • PostgreSQL addon
  • EVM RPC addon
  • Processor command: sqd process:prod
  • API command: sqd serve:prod The Indexer is independently buildable and deployable using Node.js, TypeScript, and the Subsquid toolchain.

Common Indexer

Summary & Purpose

common/indexer is a shared Kotlin library used by DEUSS services that need to access the Indexer GraphQL API. It provides a configured Apollo GraphQL client, generated query models, custom scalar adapters, response normalization, and optional request logging. It is not an independent service and does not process blockchain data itself.

Business Responsibilities

  • Provide a reusable GraphQL client for the Indexer
  • Generate strongly typed Kotlin GraphQL operations
  • Retrieve indexed blockchain data for consuming services
  • Normalize GraphQL responses into the shared ApiCallResult type
  • Provide common pagination helpers
  • Provide optional GraphQL request and response logging
  • Handle custom GraphQL scalar conversions

Supported Query Areas

The shared query definitions support access to:

  • Bond lists and bond details by ISIN
  • Bond owners
  • Coupon-eligible owners at a specific block
  • Market deals created after a timestamp
  • Expired pending market deals
  • Market deal status by deal ID
  • Full market-deal details by deal ID
  • Company wallets by company ID
  • Indexer synchronization status

Owned Data

common/indexer owns no business data and has no database. It contains:

  • GraphQL schema definitions
  • GraphQL query files
  • Generated GraphQL client code
  • Apollo client configuration
  • Scalar adapters
  • Response-handling utilities
  • Logging and pagination helpers The indexed data remains owned by the standalone Indexer application.

Inbound Interfaces

The library has no inbound runtime interfaces. It is invoked programmatically by consuming Kotlin services.

Outbound Interfaces

Indexer GraphQL API

The library creates an Apollo client configured through:

deuss:
indexer:
url: ${INDEXER_URL}
logging:
enabled: ${INDEXER_LOGGING_ENABLED:true}

The runtime Indexer endpoint is supplied by the consuming application.

Supported GraphQL Scalars

GraphQL ScalarKotlin Type
BigIntjava.math.BigInteger
DateTimejava.time.LocalDateTime
JSONString

Response Handling

GraphQL calls are processed through the shared executeAndSanitize utility. The utility handles:

  • Transport exceptions
  • GraphQL errors
  • Null response data
  • Successful responses Results are represented as:
  • ApiCallResult.Success
  • ApiCallResult.UnrecoverableError.DownstreamError Business-specific error handling remains the responsibility of the consuming service.

Consumers

Verified consumers include:

  • Blockchain Event Service
    • Retrieves market deals by deal ID
    • Retrieves bonds by ISIN
    • Enriches decoded blockchain events before Kafka publication
  • Core Payment Service
    • Queries market-deal state
    • Retrieves bond ownership information
    • Supports payment and settlement processing Other consumers may exist and should be verified through repository-wide dependency usage.

Deployment Topology

common/indexer is packaged as a shared Gradle/Micronaut library. It has:

  • No application entry point
  • No Docker image
  • No database migrations
  • No independent deployment
  • No Kafka consumers or producers
  • No independent REST or GraphQL server The library is included in consuming services at build time. Those services provide the runtime configuration and network access to the Indexer.

Relationship Between the Components

Blockchain
|
| RPC
v
Indexer Processor
|
v
Indexer PostgreSQL
|
v
Indexer GraphQL API
|
| Apollo GraphQL
v
common/indexer
|
v
Registry Service
Core Payment Service
Blockchain Event Service
Other Kotlin consumers

The main responsibility boundary is:

  • indexer: ingest, persist, and expose blockchain-derived data
  • common/indexer: provide standardized client access to that data

Architectural Characteristics

  • indexer is a data-producing platform component.
  • common/indexer is a data-consuming integration library.
  • The two components do not share a database directly.
  • Consuming Kotlin services access the Indexer through GraphQL.
  • Blockchain Event Service may also receive blockchain events through Kafka rather than querying the Indexer directly for every event.
  • common/indexer does not define business workflows; it only provides reusable access primitives.
  • The Indexer is independently deployable, while common/indexer is deployed transitively with consuming services.

Key Configuration

Indexer

Relevant variables include:

  • CHAIN_URL
  • START_BLOCK
  • FINALITY_CONFIRMATION
  • RATE_LIMIT
  • CHAIN_ENTITY_REGISTRY_ADDRESS
  • CHAIN_BOND_REGISTRY_ADDRESS
  • CHAIN_INTEREST_DISCOVERY_ADDRESS
  • CHAIN_WALLET_FACTORY_ADDRESS
  • CHAIN_FUNGIBLE_TOKEN_CONTRACT_ADDRESS
  • BOND_ISSUANCE_SERVICE_URL
  • REGISTRY_SERVICE_URL

Common Indexer

Relevant variables include:

  • INDEXER_URL
  • INDEXER_LOGGING_ENABLED

Source References

indexer

  • indexer/src/processor.ts
  • indexer/src/main.ts
  • indexer/squid.yaml
  • indexer/package.json
  • indexer/schema.graphql
  • indexer/offchain-services/
  • indexer/handlers/

common/indexer

  • common/indexer/build.gradle.kts
  • common/indexer/src/main/resources/schema.graphqls
  • common/indexer/src/main/resources/queries/
  • common/indexer/src/main/kotlin/.../indexer/client/ApolloClientFactory.kt
  • common/indexer/src/main/kotlin/.../indexer/client/ApolloResponseSanitizer.kt
  • common/indexer/src/main/kotlin/.../indexer/client/ApolloLoggingInterceptor.kt
  • common/indexer/src/main/resources/application-framework-indexer.yaml