Skip to content

Event Indexing

The indexer monitors Sui blockchain events from the Iyup smart contracts and stores them in a structured database for efficient querying.

Event Subscription

The indexer uses cursor-based event polling to track blockchain events. It maintains cursors in the database to resume indexing after failures.

Indexed Events

Marketplace Events

ListingCreated

Emitted when a new listing is created.

Event Structure:
public struct ListingCreated has copy, drop {
    listing_id: ID,
    token_id: ID,
    seller: address,
    price: u64,
    timestamp: u64,
}
Database Actions:
  • Creates new Listing record
  • Sets status to active
  • Links to token metadata

ListingUpdated

Emitted when listing price is updated.

Event Structure:
public struct ListingUpdated has copy, drop {
    listing_id: ID,
    new_price: u64,
    timestamp: u64,
}
Database Actions:
  • Updates existing Listing record
  • Updates price field
  • Preserves history

ListingCancelled

Emitted when seller cancels listing.

Event Structure:
public struct ListingCancelled has copy, drop {
    listing_id: ID,
    seller: address,
    timestamp: u64,
}
Database Actions:
  • Updates Listing status to cancelled
  • Preserves listing history

ListingPurchased

Emitted when token is purchased.

Event Structure:
public struct ListingPurchased has copy, drop {
    listing_id: ID,
    token_id: ID,
    seller: address,
    buyer: address,
    price: u64,
    fee: u64,
    timestamp: u64,
}
Database Actions:
  • Updates Listing status to sold
  • Records buyer address
  • Records purchase price and fee
  • Links to purchase transaction

Document Vault Events

DocumentRegistered

Emitted when document is first registered.

Event Structure:
public struct DocumentRegistered has copy, drop {
    token_address: address,
    issuer: address,
    blob_id: String,
    version_index: u64,
    timestamp: u64,
}
Database Actions:
  • Creates new Document record
  • Creates initial DocumentVersion record
  • Links to token address

VersionUpdated

Emitted when new document version is added.

Event Structure:
public struct VersionUpdated has copy, drop {
    token_address: address,
    version_index: u64,
    blob_id: String,
    timestamp: u64,
}
Database Actions:
  • Creates new DocumentVersion record
  • Links to existing Document record
  • Updates document updatedAt timestamp

DocumentEndorsed

Emitted when auditor endorses document.

Event Structure:
public struct DocumentEndorsed has copy, drop {
    token_address: address,
    auditor: address,
    timestamp: u64,
}
Database Actions:
  • Creates DocumentAuditor record
  • Links to Document record
  • Records auditor address

ZK Vault Events

ZKCommitmentRegistered

Emitted when ZK commitment is registered.

Event Structure:
public struct ZKCommitmentRegistered has copy, drop {
    token_address: address,
    commitment: vector<u8>,
    timestamp: u64,
}
Database Actions:
  • Creates ZKCommitment record
  • Stores commitment hash
  • Links to token address

ZKProofVerified

Emitted when ZK proof is verified.

Event Structure:
public struct ZKProofVerified has copy, drop {
    token_address: address,
    commitment: vector<u8>,
    verified: bool,
    timestamp: u64,
}
Database Actions:
  • Creates ZKProofVerification record
  • Updates ZKCommitment proof count
  • Updates last verification timestamp

Event Processing Flow

1. Event Polling

// Poll events from Sui blockchain
const events = await suiClient.queryEvents({
  query: { Package: PACKAGE_ID },
  cursor: lastCursor,
  limit: 100,
});

2. Event Filtering

// Filter events by type
const listingEvents = events.filter(e => e.type.includes('ListingCreated'));
const documentEvents = events.filter(e => e.type.includes('DocumentRegistered'));

3. Event Processing

// Process each event
for (const event of events) {
  if (event.type.includes('ListingCreated')) {
    await processListingCreated(event);
  } else if (event.type.includes('DocumentRegistered')) {
    await processDocumentRegistered(event);
  }
  // ...
}

4. Cursor Update

// Update cursor after processing
await db.cursor.upsert({
  where: { id: 'iyup_events' },
  update: { cursor: events[events.length - 1].id.id },
  create: { id: 'iyup_events', cursor: events[events.length - 1].id.id },
});

Error Handling

Event Processing Errors

If an event fails to process:

  1. Log error with event details
  2. Continue processing other events
  3. Alert monitoring system
  4. Retry failed events later

Cursor Recovery

If cursor is lost or corrupted:

  1. Query latest events from blockchain
  2. Rebuild cursor from event IDs
  3. Resume normal processing

Database Errors

If database write fails:

  1. Log error
  2. Retry with exponential backoff
  3. Alert if retries exhausted
  4. Preserve event data for later processing

Performance Optimization

Batch Processing

Process multiple events in batches:

const batchSize = 100;
for (let i = 0; i < events.length; i += batchSize) {
  const batch = events.slice(i, i + batchSize);
  await processBatch(batch);
}

Concurrent Processing

Process different event types concurrently:

await Promise.all([
  processMarketplaceEvents(events),
  processDocumentEvents(events),
  processZKEvents(events),
]);

Database Indexing

Ensure proper database indexes:

  • Token addresses
  • Event timestamps
  • Listing IDs
  • Status fields

Monitoring

Metrics to Track

  • Events processed per second
  • Processing latency
  • Error rate
  • Cursor lag (behind blockchain)
  • Database query performance

Health Checks

  • Cursor freshness (should be recent)
  • Database connectivity
  • RPC endpoint availability
  • Event processing success rate

Resync Strategy

Full Resync

To rebuild database from scratch:

  1. Delete all indexed data
  2. Delete cursors
  3. Restart indexer
  4. Indexer will start from genesis

Partial Resync

To resync specific time range:

  1. Delete data for time range
  2. Delete/update cursor to earlier point
  3. Restart indexer
  4. Indexer will resume from cursor

Next Steps