This document outlines what the off-chain indexer relies on from the on-chain Soroban smart contracts. It is intended for downstream integrators and indexer operators to understand the exact events, topics, data structures, and state mutations that the indexer expects.
The indexer relies on specific, stable topics emitted by the contract to track state changes. The contract guarantees that the primary topic for each event is stable and defined as a constant.
The indexer should subscribe to the following topic strings (which correspond to Symbols in Soroban):
invoice_uploaded: Emitted when an invoice is created.invoice_settled: Emitted when an invoice is fully settled (loan repaid).bid_placed: Emitted when a new bid is placed on an invoice.bid_accepted: Emitted when a bid is accepted.escrow_created: Emitted when investor funds are locked.dispute_created: Emitted when a dispute is opened.
When a new invoice is uploaded, the contract emits an InvoiceUploaded event. The indexer relies on this to populate its database of available invoices.
Topic (Indexer view):
"invoice_uploaded" (Symbol)
Data Payload (Indexer view): The indexer decodes the data payload into the following struct:
pub struct InvoiceUploaded {
pub invoice_id: BytesN<32>,
pub business: Address,
pub amount: i128,
pub currency: Address,
pub due_date: u64,
pub timestamp: u64,
}Real-world Request/Output: When a business uploads an invoice, the contract publishes:
env.events().publish(
(symbol_short!("invoice_uploaded"),), // Topic
InvoiceUploaded {
invoice_id: <32-byte-id>,
business: <address>,
amount: 10000000,
currency: <address>,
due_date: 1730000000,
timestamp: 1720000000,
}
);The indexer captures this via the Soroban RPC, decodes the payload, and inserts a new row in the invoices table.
The indexer relies on the following structural invariants:
- No PII: Events like
InvoiceSettledorDisputeCreateddo not include any Personally Identifiable Information (PII) to comply with data protection regulations. The indexer never expectscustomer_nameortax_idfrom the contract. - Stable Identifiers:
invoice_id,bid_id, andescrow_idare 32-byte arrays (BytesN<32>) and serve as primary keys in the indexer database. - Amounts: All monetary amounts (
amount,total_paid,bid_amount,platform_fee) are represented asi128integers in the smallest currency unit. - Timestamps: All dates and timestamps (
timestamp,due_date,expiration_timestamp) areu64Unix epoch timestamps.
The indexer primarily uses events for state transitions to avoid polling. However, it periodically issues queries to verify its state against the contract's current state. The indexer relies on entrypoints like get_invoice(id) and get_bid(id) to return exactly matching representations of the structs it constructed from events.