Intermediate · evidence workbench · ungraded

Make the index tell the truth

Practice turning fictional stream and transaction observations into a derived index that can be explained, replayed, and corrected. This workbench runs entirely in your browser. It does not connect to Solana, save responses, or request a wallet, account, key, or SOL.

Core rule: An index is a derived view. Keep enough source evidence to reproduce a decision, and expose gaps, unknown decodes, and uncertainty instead of silently treating them as success.

A recoverable indexing pipelineSix linked stages: ingest, preserve raw evidence, decode, validate, persist idempotently, and checkpoint after earlier work is durable. Unknown data branches to quarantine and replay. 1 · INGEST2 · PRESERVE3 · DECODE4 · VALIDATE5 · PERSIST6 · CHECKPOINT UNKNOWN → QUARANTINE + REPLAY
Stop the cursor when an earlier record is unresolved. Safe replay may encounter duplicates; it must not lose an observation or apply one business event twice.

Case 1 · versioned account resolution

Which account does instruction index 4 identify?

This synthetic transaction uses an address lookup table. A decoder is inspecting an instruction whose account list includes index 4.

Transaction account evidence · fictional names
static message keys [0–3]
  0  FEE_PAYER
  1  SOURCE_TOKEN_ACCOUNT
  2  SOURCE_AUTHORITY
  3  TOKEN_PROGRAM
loaded writable addresses
  4  DESTINATION_TOKEN_ACCOUNT
loaded read-only addresses
  5  TOKEN_MINT
Choose the resolved account.
Review the source rule

Resolve compiled account indexes against the complete effective account-key list. Solana’s RPC JSON structures distinguish static message keys from dynamically loaded writable and read-only addresses. Confirm the encoding and metadata in the exact RPC response before decoding a real transaction.

Case 2 · duplicate delivery

Should this event be applied once or twice?

A webhook retry and stream reconnect deliver the same instruction. The application issues one invoice credit for its validated transfer.

Two source observations · synthetic instruction
delivery A: source=webhook-retry-17
  cluster=devnet  signature=SIG_7F2  outer_instruction=2
  validated_invoice=INV_42  amount_base_units=2500000
delivery B: source=geyser-reconnect-04
  cluster=devnet  signature=SIG_7F2  outer_instruction=2
  validated_invoice=INV_42  amount_base_units=2500000
Choose a persistence rule.
Review the invariant

Source delivery identity and business-event identity differ. Preserve source provenance, enforce an appropriate uniqueness rule, and make the invoice credit idempotent too. The key depends on event type; account updates may require account key, slot, and write version.

Case 3 · gap and restart

Can the cursor safely move past the gap?

This synthetic worker promises contiguous offsets for one declared source partition. Its last durable checkpoint is 808; it has handled 810, but has no record or authoritative empty-range result for 809. A restart may replay stored event rows before checkpoint storage.

Durability ledger · fictional source offsets
offset 808  events durable  ✓  checkpoint=808
offset 809  no durable observation or empty-range proof  ?
offset 810  events durable  ✓  cursor candidate=810
crash boundary: after event write, before checkpoint write
Choose the safe recovery.
Review the recovery boundary

Persist normalized rows with a uniqueness constraint, and advance a cursor only after records in its declared source ordering scope are durable. If event and cursor writes cannot share a database transaction, replay must recognize already stored events. A slot number alone does not totally order every provider observation, and a skipped Solana slot is not automatically a missing event.

Case 4 · Geyser startup boundary

Is this account update a new deposit?

Your payment indexer starts a Geyser-backed consumer. It receives an account update while the validator is restoring its startup snapshot. The account contains a nonzero token balance.

Account callback · synthetic snapshot observation
callback=update_account
is_startup=true
slot=93000
txn=null
account=MERCHANT_TOKEN_ACCOUNT
token_amount_base_units=2500000
startup-complete-marker=not-received
Choose how to classify this observation.
Review the callback boundary

Anza documents an is_startup flag for account updates and a separate notification when snapshot loading finishes. A startup account image tells you what state was loaded, not which transaction caused that state. Preserve the origin marker and reconcile payments from transaction-level evidence and the product’s own validation rules.

Case 5 · unsupported instruction

What if the decoder does not recognize the bytes?

A new instruction variant arrives from the expected program. Your parser cannot decode it. The source is connected and the transaction has a signature, but the business event is not understood.

Unparsed instruction · synthetic record
cluster=devnet  slot=92201  signature=SIG_C91
program_id=PROGRAM_X  transaction_version=0  instruction_index=1
raw_data_base64=AAECAwQFBgcICQoL
decoder_build=indexer-2026.10.01
result=UnsupportedDiscriminator(0x0001)
Choose the handling policy.
Review the evidence to retain

Keep signature, slot, cluster, version, program ID, resolved account keys, instruction position, raw bytes, source, and decoder build. Make unsupported versions and decode failures visible. A healthy transport is not proof that the index covers every event.

Transfer the workflow

Before you trust an index, ask

Official reference

Solana RPC JSON structures: versioned messages and loaded addresses ↗

Anza Agave Geyser plugin interface ↗