Skip to main content

Blockchain Eventer

Service Type: Shared Event Processing Microservice Language: Kotlin / Micronaut Framework Database: PostgreSQL (owned) Messaging: Kafka consumer and producer Blockchain Integration: EVM event decoding Status: Implemented


Overview

Blockchain Event Service converts raw blockchain logs into normalized DEUSS domain events. It consumes raw log events from Kafka, decodes them according to supported smart-contract event signatures, enriches selected events with data from the Indexer, and publishes business events back to Kafka for downstream services. The service provides a centralized event-processing layer between blockchain infrastructure and DEUSS microservices. It does not expose a documented business REST API.


Business Responsibilities

  • Raw Blockchain Event Processing — Consume raw blockchain logs from Kafka
  • Smart Contract Event Decoding — Decode events emitted by DEUSS contracts
  • Event Routing — Route each log to the appropriate event handler
  • Event Normalization — Convert low-level blockchain logs into typed DEUSS events
  • Event Enrichment — Retrieve additional bond and market-deal data from the Indexer where required
  • Event Publication — Publish normalized business events to Kafka
  • Idempotency — Prevent already processed blockchain logs from being processed again
  • Retry Tracking — Persist processing errors and retry counts
  • Processing Status Management — Track pending, processed, unmatched, and failed events

Supported Event Domains

Interest Discovery

The service processes and publishes events related to the interest discovery and secondary-market workflow:

  • Deal created
  • Deal status updated
  • Offer registered
  • Offer cancelled
  • Counter-offer resolved
  • Amounts updated Events related to deals are enriched with Indexer data such as:
  • ISIN
  • Buyer and seller wallets
  • Issuer wallet
  • Deal type and status
  • Amount and price
  • Fee classification

Bond Registry

  • Bond published Bond publication events are enriched with bond information from the Indexer, including:
  • Coupon type
  • Issue date
  • Coupon frequency
  • Maturity date
  • Currency
  • Coupon rates
  • Payment intervals

Fungible Tokens

  • Token transfer Transfer events contain blockchain-level information such as:
  • Caller
  • Sender
  • Receiver
  • Token ID
  • Amount

Owned Data

The service owns a lightweight event-processing ledger:

  • event — Processed blockchain log records
  • block_hash and log_index — Composite event identity
  • time_received — Time when the event was consumed
  • time_processed — Time when processing completed
  • state — Processing state
  • retry_count — Number of processing failures
  • event_type — Successfully identified event type

Processing States

  • PENDING — Event received but not completed
  • PROCESSED — Event successfully decoded and published
  • NOT_MATCHED — No registered handler matched the log
  • ERROR — Processing or downstream enrichment/publication failed The service does not own bond, deal, token, or payment business data. Those records remain owned by other services or the blockchain/indexing layer.

Inbound Interfaces

Kafka Consumer

The primary inbound interface is Kafka.

TopicEventPurpose
EventerEvents.RAW_DATARawLogEventReceive raw blockchain logs from the Indexer/Eventer pipeline

The consumer uses:

  • Consumer group: blockchain-log-consumer
  • Offset reset: EARLIEST
  • Composite event key format: blockHash:logIndex The consumer converts raw event data into an EVM-compatible Log, then passes it to the event router.

REST API

No service-specific REST controllers or business REST endpoints were identified in the source code. Common utility or OpenAPI-related endpoints may be enabled through the shared framework, but their exact business scope is not defined by this service.


Outbound Interfaces

Kafka Producers

The service publishes normalized events for downstream consumers.

Topic ConstantEventBusiness Purpose
InterestDiscoveryEvents.DEAL_CREATEDDealCreatedEventNotify services that a new market deal was created
InterestDiscoveryEvents.DEAL_STATUS_UPDATEDDealStatusUpdatedEventNotify services about a deal status change
InterestDiscoveryEvents.OFFER_REGISTEREDOfferRegisteredEventNotify services that a new offer was registered
InterestDiscoveryEvents.AMOUNTS_UPDATEDAmountsUpdatedEventNotify services about updated deal or offer amounts
InterestDiscoveryEvents.OFFER_CANCELLEDOfferCancelledEventNotify services that an offer was cancelled
InterestDiscoveryEvents.COUNTER_OFFER_RESOLVEDCounterOfferResolvedEventNotify services about counter-offer resolution
BondRegistryEvents.BOND_PUBLISHEDBondPublishedEventNotify services that a bond was published
FungibleTokenEvents.TRANSFERTransferEventNotify services about fungible-token transfers

Indexer GraphQL Client

The service calls the Indexer through GraphQL when blockchain logs do not contain sufficient business context. Implemented queries include:

  • Market deal by deal ID
  • Bond by ISIN The Indexer is used to enrich deal and bond events before publishing them to Kafka.

Database

  • PostgreSQL accessed through JPA/Hibernate
  • Flyway manages schema migrations
  • Database is used for event processing state and idempotency

Kafka Integration

Consumer

  • Consumes raw blockchain logs from EventerEvents.RAW_DATA
  • Uses EARLIEST offset reset
  • Persists processing results
  • Skips events already marked as PROCESSED

Producers

Publishes normalized events to the Interest Discovery, Bond Registry, and Fungible Token event domains. The service is therefore both:

  • A Kafka consumer of infrastructure-level blockchain events
  • A Kafka producer of business-level DEUSS events

Event Processing Flow

  1. A raw blockchain log is received from Kafka.
  2. The Kafka key is parsed into block hash and log index.
  3. The event record is loaded or created in PostgreSQL.
  4. Already processed events are ignored.
  5. The raw payload is converted into an EVM Log.
  6. Registered handlers attempt to decode the log.
  7. The first matching handler processes the event.
  8. Additional data is fetched from the Indexer if needed.
  9. A normalized Kafka event is published.
  10. The database record is updated:
  • PROCESSED on success
  • NOT_MATCHED when no handler applies
  • ERROR when processing fails

Key Business Rules

  1. Event identity is based on the blockchain block hash and log index.
  2. Processed events are idempotent and are not handled again.
  3. Handlers are tried in priority order until one matches the log.
  4. Unknown blockchain events are not treated as successful processing; they are stored as NOT_MATCHED.
  5. Indexer enrichment is mandatory for event types requiring business context.
  6. Kafka publication failure results in an error state and increments the retry count.
  7. Normalized events use blockchain-derived event keys for Kafka partitioning and correlation.
  8. The service does not persist full blockchain event payloads, only processing metadata.

External Integrations

Blockchain Contracts

The service decodes events emitted by generated contract bindings, including:

  • InterestDiscovery
  • BondRegistry
  • FungibleToken Configured blockchain-related parameters include:
  • Chain RPC URL
  • Bond Registry contract address
  • Account Factory contract address
  • Interest Discovery contract address
  • Company Wallet Registry contract address The source code verifies event decoding and contract integration. Direct blockchain polling was not identified; raw logs arrive through Kafka.

Indexer

The Indexer is accessed through GraphQL for enrichment of:

  • Market deals
  • Bonds

Kafka/Eventer Pipeline

The service depends on an upstream Eventer/Indexer pipeline that publishes raw blockchain logs to Kafka.


Deployment

Runtime Stack:

  • Kotlin
  • Micronaut
  • Java 25 OpenJDK runtime
  • Netty
  • PostgreSQL
  • Hibernate/JPA
  • Flyway
  • Kafka
  • Ethers-based EVM contract bindings
  • Apollo GraphQL client Configuration:
  • Application name: blockchain-event-service
  • Default HTTP port: 8080
  • Local development port: 8083
  • Kafka consumer group: blockchain-event-service in application configuration
  • Raw log consumer group: blockchain-log-consumer
  • Database: blockchain_event_service_db Relevant Environment Variables:
  • DATABASE_URL
  • DATABASE_USER
  • DATABASE_PASSWORD
  • INDEXER_URL
  • CHAIN_URL
  • CHAIN_BOND_REGISTRY_ADDRESS
  • CHAIN_ACCOUNT_FACTORY_ADDRESS
  • CHAIN_INTEREST_DISCOVERY_ADDRESS
  • CHAIN_COMPANY_WALLET_REGISTRY_ADDRESS
  • JWT_GENERATOR_SIGNATURE_SECRET Container:
  • Alpine-based image
  • OpenJDK 25
  • Runs under a non-root runtime user
  • Uses tini as the init process
  • Enables JVM container support

Observability and Reliability

  • Structured logging through DeussLogger
  • Event processing state persisted in PostgreSQL
  • Retry count stored per blockchain event
  • Kafka offset reset configured to EARLIEST
  • Batch-oriented Hibernate settings enabled:
    • JDBC batch size: 100
    • Ordered inserts
    • Batched statement rewriting
  • Health and utility endpoints are provided through the shared framework; exact endpoint behavior is not service-specific

Technical Notes

  • Event Translation Layer — Separates blockchain-specific event formats from internal DEUSS events
  • Centralized Routing — New event types can be added through new handlers without changing the consumer
  • Database-backed Idempotency — Prevents duplicate processing after Kafka retries or restarts
  • Hybrid Enrichment — Combines on-chain log data with Indexer business data
  • No REST-Centric Interaction Model — Downstream services consume Kafka events rather than calling this service synchronously
  • Shared Platform Component — Located under shared, indicating that it supports multiple Core and platform services

Relationships with Other Services

  • Indexer/Eventer — Supplies raw blockchain logs through Kafka
  • Indexer GraphQL API — Provides bond and market-deal context
  • Core Payment Service — Consumes deal and bond events for payment and payday processing
  • Other Interest Discovery Consumers — Consume offer, deal, amount, and counter-offer events
  • Token and Registry Consumers — Consume transfer and bond publication events Exact consumer ownership outside this service was not inferred unless supported by source code.

Documentation Sources:

  • Source: shared/blockchain-event-service/src/main/kotlin/
  • Kafka consumer: .../kafka/BlockchainLogConsumer.kt
  • Kafka producer: .../kafka/KafkaProducer.kt
  • Event handlers: .../blockchain/handlers/
  • Database model: .../database/model/BlockchainEventEntity.kt
  • Migrations: shared/blockchain-event-service/src/main/resources/db/migration/
  • Configuration: shared/blockchain-event-service/src/main/resources/application.yaml
  • Container: shared/blockchain-event-service/Dockerfile
  • Build dependencies: shared/blockchain-event-service/build.gradle.kts