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 recordsblock_hashandlog_index— Composite event identitytime_received— Time when the event was consumedtime_processed— Time when processing completedstate— Processing stateretry_count— Number of processing failuresevent_type— Successfully identified event type
Processing States
PENDING— Event received but not completedPROCESSED— Event successfully decoded and publishedNOT_MATCHED— No registered handler matched the logERROR— 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.
| Topic | Event | Purpose |
|---|---|---|
EventerEvents.RAW_DATA | RawLogEvent | Receive raw blockchain logs from the Indexer/Eventer pipeline |
The consumer uses:
- Consumer group:
blockchain-log-consumer - Offset reset:
EARLIEST - Composite event key format:
blockHash:logIndexThe consumer converts raw event data into an EVM-compatibleLog, 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 Constant | Event | Business Purpose |
|---|---|---|
InterestDiscoveryEvents.DEAL_CREATED | DealCreatedEvent | Notify services that a new market deal was created |
InterestDiscoveryEvents.DEAL_STATUS_UPDATED | DealStatusUpdatedEvent | Notify services about a deal status change |
InterestDiscoveryEvents.OFFER_REGISTERED | OfferRegisteredEvent | Notify services that a new offer was registered |
InterestDiscoveryEvents.AMOUNTS_UPDATED | AmountsUpdatedEvent | Notify services about updated deal or offer amounts |
InterestDiscoveryEvents.OFFER_CANCELLED | OfferCancelledEvent | Notify services that an offer was cancelled |
InterestDiscoveryEvents.COUNTER_OFFER_RESOLVED | CounterOfferResolvedEvent | Notify services about counter-offer resolution |
BondRegistryEvents.BOND_PUBLISHED | BondPublishedEvent | Notify services that a bond was published |
FungibleTokenEvents.TRANSFER | TransferEvent | Notify 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
EARLIESToffset 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
- A raw blockchain log is received from Kafka.
- The Kafka key is parsed into block hash and log index.
- The event record is loaded or created in PostgreSQL.
- Already processed events are ignored.
- The raw payload is converted into an EVM
Log. - Registered handlers attempt to decode the log.
- The first matching handler processes the event.
- Additional data is fetched from the Indexer if needed.
- A normalized Kafka event is published.
- The database record is updated:
PROCESSEDon successNOT_MATCHEDwhen no handler appliesERRORwhen processing fails
Key Business Rules
- Event identity is based on the blockchain block hash and log index.
- Processed events are idempotent and are not handled again.
- Handlers are tried in priority order until one matches the log.
- Unknown blockchain events are not treated as successful processing; they are stored as
NOT_MATCHED. - Indexer enrichment is mandatory for event types requiring business context.
- Kafka publication failure results in an error state and increments the retry count.
- Normalized events use blockchain-derived event keys for Kafka partitioning and correlation.
- 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:
InterestDiscoveryBondRegistryFungibleTokenConfigured 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-servicein application configuration - Raw log consumer group:
blockchain-log-consumer - Database:
blockchain_event_service_dbRelevant Environment Variables: DATABASE_URLDATABASE_USERDATABASE_PASSWORDINDEXER_URLCHAIN_URLCHAIN_BOND_REGISTRY_ADDRESSCHAIN_ACCOUNT_FACTORY_ADDRESSCHAIN_INTEREST_DISCOVERY_ADDRESSCHAIN_COMPANY_WALLET_REGISTRY_ADDRESSJWT_GENERATOR_SIGNATURE_SECRETContainer:- Alpine-based image
- OpenJDK 25
- Runs under a non-root
runtimeuser - Uses
tinias 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