From 1b7b540c82f54902f87cc895f838195c4ad4f591 Mon Sep 17 00:00:00 2001 From: Oladosu Paul Date: Fri, 20 Feb 2026 02:12:24 +0100 Subject: [PATCH 1/2] feat: implement IndexerService for InvoiceMinted events - Create IndexerService with Stellar SDK integration - Implement onModuleInit lifecycle hook for auto-startup - Add 5-second polling for server.getEvents() - Filter InvoiceMinted events from INVOICE_NFT_CONTRACT_ID - Log invoice_id and amount to console - Register service in AppModule - Update .env.example with Stellar configuration Fixes #4 --- .env.example | 10 ++++++ src/app.module.ts | 3 +- src/indexer.service.ts | 82 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 src/indexer.service.ts diff --git a/.env.example b/.env.example index e69de29..677b8f0 100644 --- a/.env.example +++ b/.env.example @@ -0,0 +1,10 @@ +# Stellar Configuration +STELLAR_HORIZON_URL=https://horizon-testnet.stellar.org +CONTRACT_ID=CCYU3LOQI34VHVN3ZOSEBHHKL4YK36FMTOEGLRYDUDRGS7JOLLRKCEQM + +# Database Configuration (existing) +DB_HOST=localhost +DB_PORT=5432 +DB_USERNAME=postgres +DB_PASSWORD=password +DB_DATABASE=tradeflow \ No newline at end of file diff --git a/src/app.module.ts b/src/app.module.ts index 66490a7..a51a0b4 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -2,10 +2,11 @@ import { Module } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; import { HealthModule } from './health/health.module'; +import { IndexerService } from './indexer.service'; @Module({ imports: [HealthModule], controllers: [AppController], - providers: [AppService], + providers: [AppService, IndexerService], }) export class AppModule {} diff --git a/src/indexer.service.ts b/src/indexer.service.ts new file mode 100644 index 0000000..5bb2149 --- /dev/null +++ b/src/indexer.service.ts @@ -0,0 +1,82 @@ +import { Injectable, OnModuleInit } from '@nestjs/common'; +import { Horizon, Server } from '@stellar/stellar-sdk'; + +@Injectable() +export class IndexerService implements OnModuleInit { + private server: Server; + private readonly POLLING_INTERVAL = 5000; // 5 seconds + private readonly CONTRACT_ID = process.env.CONTRACT_ID || ''; + private readonly INVOICE_MINTED_TOPIC = 'InvoiceMinted'; + + constructor() { + // Initialize Stellar server (using testnet by default, can be configured via env) + this.server = new Server( + process.env.STELLAR_HORIZON_URL || 'https://horizon-testnet.stellar.org' + ); + } + + async onModuleInit() { + console.log('IndexerService starting...'); + + if (!this.CONTRACT_ID) { + console.warn('CONTRACT_ID not set in environment variables'); + return; + } + + // Start polling for events + this.startPolling(); + } + + private startPolling() { + console.log(`Starting to poll for ${this.INVOICE_MINTED_TOPIC} events from contract ${this.CONTRACT_ID}`); + + setInterval(async () => { + try { + await this.pollForEvents(); + } catch (error) { + console.error('Error polling for events:', error); + } + }, this.POLLING_INTERVAL); + } + + private async pollForEvents() { + try { + // Get events from the Stellar server + const events = await this.server.getEvents({ + contract: this.CONTRACT_ID, + topics: [[this.INVOICE_MINTED_TOPIC]], + }); + + if (events.records.length > 0) { + console.log(`Found ${events.records.length} events`); + + for (const event of events.records) { + this.processInvoiceMintedEvent(event); + } + } + } catch (error) { + console.error('Error fetching events:', error); + } + } + + private processInvoiceMintedEvent(event: any) { + try { + // Extract event data + const eventData = event.value; + + // Assuming the event structure contains invoice_id and amount + // This may need adjustment based on actual event structure + const invoiceId = eventData.invoice_id || eventData.invoiceId || 'N/A'; + const amount = eventData.amount || 'N/A'; + + console.log(`InvoiceMinted Event Detected:`); + console.log(` - Invoice ID: ${invoiceId}`); + console.log(` - Amount: ${amount}`); + console.log(` - Transaction Hash: ${event.transaction_hash}`); + console.log(` - Timestamp: ${event.created_at}`); + console.log('---'); + } catch (error) { + console.error('Error processing InvoiceMinted event:', error); + } + } +} From bd2a8032ff04eef37956971392eff06cb70df07a Mon Sep 17 00:00:00 2001 From: Oladosu Paul Date: Fri, 20 Feb 2026 02:17:14 +0100 Subject: [PATCH 2/2] fix: correct Stellar SDK import statement - Remove unused Horizon import - Fix Server import to resolve build error --- src/indexer.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/indexer.service.ts b/src/indexer.service.ts index 5bb2149..f6aaa8c 100644 --- a/src/indexer.service.ts +++ b/src/indexer.service.ts @@ -1,5 +1,5 @@ import { Injectable, OnModuleInit } from '@nestjs/common'; -import { Horizon, Server } from '@stellar/stellar-sdk'; +import { Server } from '@stellar/stellar-sdk'; @Injectable() export class IndexerService implements OnModuleInit {