Trustless Stream Consumer Recipes#
This guide describes how integrators can consume Seesaw activity from their own Solana data provider and decode it with Seesaw SDK surfaces. Users bring their own RPC, stream, or notification provider and keep the delivery trust boundary under their control.
Policy: Seesaw does not operate outbound webhooks for this path.
Provider Options#
- vanilla Solana WebSocket: use
logsSubscribe,programSubscribe, and account subscriptions for small bots and internal tools. - Triton One: use Project Yellowstone options such as Dragon's Mouth gRPC, Whirligig WebSockets, Fumarole reliable streams, and Program Data Streams when lower latency or reliable replay matters.
- Helius: use enhanced Solana RPC, transaction/account notifications, or LaserStream-style managed gRPC streams when managed replay/failover is useful.
- QuickNode: use Streams or WebSocket/RPC products with program, account, and transaction filters.
- Yellowstone: use a Yellowstone-compatible Geyser gRPC stream directly when you operate your own validator or data plane.
- LaserStream: use provider-managed gRPC delivery when your system needs durable cursors and replay around disconnects.
Filters#
Start narrow and widen only when needed:
- Program-wide: subscribe to the Seesaw program ID to project all market, order, fill, settlement, claim, and config events.
- Market-specific: filter transaction logs and account updates by market, orderbook, vault, and mint addresses.
- Wallet-specific: filter position, trader ledger, token-account, and signature activity for one wallet.
- Creator/referrer-specific: filter market creator addresses, referral accounts, referrer earnings accounts, and treasury shard accounts.
Cursor Model#
Persist a slot/signature/instruction-index cursor for every consumer. When the provider exposes deeper log indexes, also persist transaction index, log index, and event index. Treat the cursor as inclusive on recovery: replay the last seen transaction, discard already-applied event IDs, and then continue.
Recommended event ID:
<slot>:<signature>:<instructionIndex>:<batchIndex>:<eventIndex>
batchIndex is required because a single recorder instruction can flush
multiple event batches. Without it, the first event in each batch would collide
under the same slot/signature/instruction cursor.
For account-only streams, use:
<slot>:<accountAddress>:<writeVersion>
If the provider does not expose write versions, combine slot, account address, owner program, and a hash of the account bytes.
Decode And Project#
Use the trustless SDK/account decoders and @seesaw/core event helpers to turn
raw Solana updates into a local projection. The provider-specific step is only
getting bytes/logs and cursor metadata; Seesaw's shared SDK owns event decoding
and the terminal event model.
Recommended TypeScript flow:
import {
decodeSeesawBinaryEventBatch,
projectSeesawBinaryEventBatch,
dedupeTrustlessProjectionEvents,
} from '@seesaw/core';
const batch = decodeSeesawBinaryEventBatch(recorderInstructionData);
const projected = dedupeTrustlessProjectionEvents(
projectSeesawBinaryEventBatch({
batch,
signature,
instructionIndex,
provider: 'triton-one',
})
);
Projection event IDs use this stable shape:
<slot>:<signature>:<instructionIndex>:<batchIndex>:<eventIndex>
The helper currently emits provider-neutral event kinds for the on-chain recorder events it can prove from decoded data:
order.openedorder.cancelledorder.reducedorder.evictedorder.reclaimedfill.createdposition.updatedbalance.updatedsettlement.availablesettlement.claimedmarket.expiredclaim.created
Keep provider payloads and raw decoded events beside the projection so newly emitted recorder events can be replayed when SDK support expands.
Idempotency#
Projection tables should enforce idempotency. Apply an event only if its event ID is newer than the last applied ID for that entity, and keep raw slot/signature metadata beside every projected row.
Finality And Rollbacks#
Pick one finality level per strategy:
processed: fastest, but must tolerate rollbacks.confirmed: balanced default for most terminals.finalized: slower, strongest replay semantics.
If a provider reports a rollback or replaces a slot range, rewind to the last safe finalized cursor, replay, and compare projected state against direct account reads before enabling trading again.
Reconciliation#
Run reconciliation after reconnect, rollback, deployment, or any cursor gap:
- Read market and orderbook accounts directly.
- Read wallet position and trader ledger accounts directly.
- Compare local open orders, fills, positions, balances, claims, and market state against decoded account data.
- Repair local state from direct reads.
- Resume from the newest verified slot/signature/instruction-index cursor.
For hosted Seesaw convenience APIs, compare your local projection with
/api/v1/exchange/symbols, /api/v1/exchange/markets/{symbol},
/api/v1/exchange/orderbook/{symbol}, /api/v1/exchange/trades/{symbol}, and
the protocol-native account routes. The exchange facade is a read aid, not the
source of custody or signing truth.
Operational Checklist#
- Store the provider name, endpoint, finality level, and cursor with each projection.
- Enforce duplicate handling before side effects.
- Keep raw Solana payloads for audit when storage cost allows.
- Alert on cursor gaps, provider disconnects, stale slots, and mismatches between projected state and direct account reads.
- Never allow a provider callback payload to choose fee recipients, creator fields, or transaction signers.
- Treat hosted automation as separate policy work; this recipe is read and projection infrastructure only.