Feature-support inventory#
This inventory compares the active on-chain instruction surface with the surfaces that a user or operator can use in the web app, mobile app, SDKs, CLI, and checked-in examples.
Spline instructions (0x30, 0x40–0x47) are included as a required SDK
surface, but are the only exception to the app requirement: spline flows do
not need to be exposed by the web or mobile apps. Every other active,
user-facing, administrative, keeper, and Reclaim capability is required on
every surface, including runnable code samples. The internal event-recorder
instruction (0xFF) is excluded. The frozen Reclaim slots
(0x38–0x3F, 0x4A–0x4C, and 0x4F) are not active instructions and
are not counted as missing support. They reject as FrozenLegacyReclaim before
parsing or account access; RecoverSpline (0x30) remains live.
Parity policy#
The target state is complete support for every non-spline capability in the web app, mobile app, TypeScript SDK, Rust SDK, Python SDK, CLI, and checked-in examples. “No” and “Partial” in the tables are therefore gaps to close, not acceptable permanent asymmetries. Admin and keeper operations are included in this requirement; mobile is not exempt because an operation is normally performed by an operator. Spline support is the one deliberate exception for web/mobile, while SDK, CLI, and sample support remains required.
Status legend#
- Yes — a first-class builder or UI/command flow exists and is covered by the relevant tests.
- Partial — the capability exists indirectly (for example, through a signed Reclaim package, a server-built transaction bundle, or a keeper), but the surface does not expose the raw instruction or every route.
- No — no supported path was found in that surface.
- Examples records whether a runnable checked-in sample demonstrates the feature. SDK support is required even when an app does not expose the feature, and examples are tracked separately so missing sample coverage is visible rather than mistaken for an SDK gap.
User-facing market and trading features#
| Feature / instruction family | On-chain | Web | Mobile | TypeScript SDK | Rust SDK | Python SDK | CLI | Examples |
|---|---|---|---|---|---|---|---|---|
Create market (CreateMarket, EnsureTraderLedgerSpace, EnsureDeepOrderbookSpace) | 0x03, 0x2E, 0x33 | Yes | Yes | Yes | Yes | Yes | Yes | Create-market bundle samples |
Record end snapshot (SnapshotEnd) | 0x04 | Yes | Yes | Yes | Yes | Yes | Yes | Lifecycle samples |
Resolve market (ResolveMarket) | 0x05 | Yes | Yes | Yes | Yes | Yes | Yes | Lifecycle samples |
Expire/late-resolve market (ExpireMarket) | 0x06 | Yes | Yes | Yes | Yes | Yes | Yes | Lifecycle samples |
Close resolved market (CloseMarket) | 0x1E | Yes | Yes | Yes | Yes | Yes | Yes | Lifecycle samples |
Force-close expired unresolved position (ForceClose) | 0x1B | Yes | Yes | Yes | Yes | Yes | Yes | Lifecycle samples |
Place standard order (PlaceOrder) | 0x0B | Yes | Yes | Yes | Yes | Yes | Yes | Rust/Python place-order samples |
Place batch post-only orders (PlaceMultiplePostOnlyOrders) | 0x0C | Yes | Yes | Yes | Yes | Yes | Yes | No |
Place free-funds orders (SwapWithFreeFunds, PlaceLimitOrderWithFreeFunds, batch variant) | 0x0D–0x0F | Yes | Yes | Yes | Yes | Yes | Yes | No |
Cancel/reduce standard orders (CancelOrder, bulk cancel, cancel-up-to, reduce) | 0x10–0x14 | Partial | Yes | Yes | Yes | Yes | Yes | Cancel/reduce samples |
| Cancel/reduce free-funds orders | 0x15–0x18 | Partial | Yes | Yes | Yes | Yes | Yes | No |
Deposit/withdraw trader-ledger funds (DepositFunds, WithdrawFunds) | 0x08–0x09 | Yes | Yes | Yes | Yes | Yes | Yes | Funding samples |
Mint shares (MintShares) | 0x07 | Yes | Yes | Yes | Yes | Yes | Yes | Instruction cookbook |
Redeem shares (Redeem) | 0x1A | Yes | Yes | Yes | Yes | Yes | Yes | Instruction cookbook |
Withdraw shares (WithdrawShares) | 0x0A | Yes | Yes | Yes | Yes | Yes | Yes | Funding samples |
Permissionless expired-order reclaim (ReclaimExpiredOrder) | 0x19 | Yes | Yes | Yes | Yes | Yes | Yes | Position-cleanup samples |
Permissionless position settlement/closure (MarkPositionSettled, ClosePosition) | 0x1C–0x1D | Yes | Yes | Yes | Yes | Yes | Yes | Position-cleanup samples |
| Set immutable referrer / initialize and claim referral earnings | 0x21–0x22, 0x24 | Yes | Yes | Yes | Yes | Yes | Yes | Instruction cookbook |
Claim creator fees (ClaimCreatorFees) | 0x23 | Yes | Yes | Yes | Yes | Yes | Yes | Creator-claim examples |
Update creator market cap (UpdateMarketCap) | 0x2B | Yes | Yes | Yes | Yes | Yes | Yes | No |
ClaimCreatorFees (0x23) is a recovery path, not the normal way a creator is paid.
ResolveMarket and ExpireMarket sweep the accrued balance straight to the creator's
settlement token account as part of resolution, so a market that resolves with a healthy
creator token account reaches outcome != 0 and accumulated_creator_fees == 0 in the same
transaction. The program accepts 0x23 only when BOTH market.outcome != 0 and
accumulated_creator_fees > 0 (source),
which is exactly the deferred case: the resolution-time sweep could not pay out (missing,
mismatched, or frozen creator token account) and the program emitted CreatorFeesDeferred
instead (source). Clients therefore show
a claim control only for a deferred balance; a settled market with a zero balance is
reported as already paid.
Current app gaps against the parity policy#
-
Oracle contest observations (
RecordOracleObservation0x57,SubmitOracleObservation0x58,FinalizeOracleObservation0x59, andCloseOracleObservation0x5A) are keeper-managed lifecycle operations. The SDKs expose the builders; web and mobile do not present direct operator controls, and the keeper handles automated settlement. -
Mobile now exposes market-level lifecycle actions through
useMarketLifecycleActions(source), surfaced as thePro · Market lifecyclepanel on the market detail screen, alongside the position-level ops that already lived inuseLifecycleActions(source). Resolve, close, and force-close are fully client-buildable on mobile. -
Mobile and web build snapshot/expire bundles on-device with the user's Pyth key (
@seesaw/pyth-pullbuildPullLifecycleBundle); without a key both surfaces refuse with a settings prompt. The indexer lifecycle builder is no longer needed. -
Mobile now also exposes a Pro-gated protocol admin surface (screen, registry) covering every family in the admin table below.
-
Web market creation and lifecycle actions build Pyth Pull bundles on-device when the user has configured a Pyth key.
-
Gaps also run the other way, surfaced by the matrix test in
packages/test-vectors/src/__tests__/feature-support-matrix.test.tsand tracked there as pinnedTRACKED_APP_GAPSentries:ForceClose(0x1B) is exposed for the connected wallet's eligible unresolved position in the web Pro lifecycle panel. The flow rereads the market and position through RPC and refuses settled positions or locked shares before building the refund transaction (source).InitReferrerEarningsAccount(0x22) now has a web flow, so the referral row readsYesfor web. The referral page probes the connected wallet's earnings PDA and the treasury shard it would bind to, then builds0x22through@seesaw/core(source). One precondition is surfaced rather than hidden: the shard thatpickTreasuryIndex(wallet, 0)selects must already exist, and the button refuses to submit — namingInitializeReferrerTreasuryShard(0x37) — when it does not. Mobile now probes the earnings PDA and validates the shard's token owner, mint and initialized state before offering the referrer-signed setup transaction inReferralScreen. The mobile flow reports unavailable shards and preserves unknown transaction confirmation.- The bounded bulk-cancel builders remain web gaps. "Cancel all" in either app batches
CancelMultipleOrdersById(0x11) or its free-funds twin (0x15), and the shareddispatchCancelOrderhelper never routes to a bounded variant. Web builds neitherCancelAllOrders(0x12) norCancelUpTo(0x13) or the free-funds variants (0x16,0x17). Mobile's Pro pending orders screen also exposes all four bounded variants. It validates the live book's capacity (at most 512), complete matching count (at most six), original order side, and homogeneous refund route before submission. Bounded cancellation is all-or-reject when the matching set exceeds the limit; larger or mixed sets use the existing order-ID cancellation flow. - Web, mobile, CLI, and the keeper use the standalone-verifier planner for
BeginReclaimExternalMarketV1(0x52),OpenReclaimExternalMarketV1(0x53),ResolveExternalMarketWithReclaimV1(0x54),HaltExternalMarketWithReclaimV1(0x55), andExtendExternalCloseWithReclaimV1(0x56). They upload exact schema-V2 proof bytes into verifier-owned immutable buffers; none emits an Ed25519 witness instruction.
External/zkTLS-based market through Reclaim Protocol features#
| Feature | On-chain | Web | Mobile | TypeScript SDK | Rust SDK | Python SDK | CLI | Examples |
|---|---|---|---|---|---|---|---|---|
Begin/open from a verified definition proof (BeginReclaimExternalMarketV1 / Open…V1) | 0x52–0x53 | Yes | Yes | Yes | Yes | Yes | Yes | two-program localnet E2E |
Resolve from an outcome-specific terminal proof (ResolveExternalMarketWithReclaimV1) | 0x54 | Yes | Yes | Yes | Yes | Yes | Yes | YES/NO/VOID vectors and E2E |
Halt from the reviewed left-open condition (HaltExternalMarketWithReclaimV1) | 0x55 | Yes | Yes | Yes | Yes | Yes | Yes | V1 planner vectors |
Extend from the reviewed close-time condition (ExtendExternalCloseWithReclaimV1) | 0x56 | Yes | Yes | Yes | Yes | Yes | Yes | V1 planner vectors |
Legacy Reclaim bridge (0x38–0x3F, 0x4A–0x4C, 0x4F) | Frozen | No | No | Archival only | Archival | Archival | No | tombstone rejection tests |
Legacy external preallocation (BeginExternalMarketPreallocation) | Frozen 0x4F | No | No | Archival only | Archival | Archival | No | tombstone rejection tests |
Permissionless external expiry (ExpireExternalMarket) | 0x4D | Operations page | Admin screen | Yes | Yes | Yes | Yes | two-program localnet E2E |
Shrink oversized preallocated child (ShrinkPreallocatedChild) | 0x4E | Operations page | Admin screen | Yes | Yes | Yes | Yes | maintenance tests |
Reclaim unused V1 preallocation (ReclaimExternalMarketPreallocation) | 0x50 | Operations page | Admin screen | Yes | Yes | Yes | Yes | maintenance tests |
Top up external progress reserve (TopUpExternalProgressReserve) | 0x51 | Operations page | Admin screen | Yes | Yes | Yes | Yes | maintenance tests |
The submission surfaces accept only schema-V2 raw-proof envelopes. The generic
verifier recomputes the complete claim identifier and EIP-191 digest, recovers
the governed Reclaim attestor with the secp256k1_recover syscall, and creates
a market-scoped receipt. Seesaw binds the exact terminal-condition commitment,
consumes the receipt, and changes market state atomically. Google TEE and
underlying zkTLS verification remain offchain.
The old 0x3C–0x3F, 0x4A–0x4C, and 0x4F bridge entry
points remain named only so historical transactions can be decoded. Current
clients do not construct them, and the program rejects them with
FrozenLegacyReclaim.
Redeem (0x1A) on an external market needs the MarketMeta account at index
10; RedeemAccounts omitted it, so no client in the repo could settle an
external market. The slot is now part of the shared builder and the mobile
hook reads the market to decide whether to supply it, so the Redeem row's
Yes for web and mobile covers external markets as well as native ones
(source).
The four permissionless external-maintenance instructions (0x4D, 0x4E,
0x50, 0x51) have standalone forms on the web operations page and mobile
Pro admin screen. Mobile builds them through its admin-control registry and
submits through the connected wallet. The matrix pins these call sites;
device and staging execution remain separate signoffs.
API/indexer outage boundary#
Known-market reads, owner-scoped positions and open orders have a validated RPC fallback. Both apps identify live RPC data and unavailable indexed analytics. Wallet transaction confirmation uses RPC; indexer ingestion is a later refresh. A submitted transaction with unknown confirmation must retain its signature and remain unknown until reconciled.
Search, discovery, charts, history, leaderboards and other indexed analytics remain API-dependent. Pyth data delivery and Reclaim proof production retain their provider dependencies. See RPC escape hatch for configuration, failure semantics and the exact verification boundary.
The executable matrix still tracks four web bounded-cancel gaps and the keeper-managed oracle observation operations on both apps. Spline app exemptions remain unchanged. This inventory does not claim complete app parity or completed staging outage tests.
The CLI exposes schema-V2 proof submission plus the still-live permissionless
maintenance commands in the reclaim group (see
docs/cli/commands.md#reclaim). Legacy witness, claim-close, and
preallocation commands are not live compatibility paths.
Spline SDK requirement#
Spline support is required in the SDKs even though spline markets are not
currently exposed as first-class web or mobile product flows. The on-chain
surface and all three SDKs currently contain the complete spline instruction
family; the CLI also has a dedicated spline command surface. The
spline_lifecycle samples demonstrate the init → quote → fund → drain → close
walkthrough in both Rust and Python.
| Spline instruction | On-chain | TypeScript SDK | Rust SDK | Python SDK | CLI | Web | Mobile | Examples |
|---|---|---|---|---|---|---|---|---|
RecoverSpline (0x30) | Yes | Yes | Yes | Yes | Yes | No app flow | No app flow | No |
InitSpline (0x40) | Yes | Yes | Yes | Yes | Yes | No app flow | No app flow | Yes (spline_lifecycle) |
UpdateSplineShape (0x41) | Yes | Yes | Yes | Yes | Yes | No app flow | No app flow | No |
UpdateSplineMid (0x42) | Yes | Yes | Yes | Yes | Yes | No app flow | No app flow | Yes (spline_lifecycle) |
AttachSpline (0x43) | Yes | Yes | Yes | Yes | Yes | No app flow | No app flow | No |
SettleSpline (0x44) | Yes | Yes | Yes | Yes | Yes | No app flow | No app flow | No |
DepositSplineVault (0x45) | Yes | Yes | Yes | Yes | Yes | No app flow | No app flow | Yes (spline_lifecycle) |
WithdrawSplineVault (0x46) | Yes | Yes | Yes | Yes | Yes | No app flow | No app flow | Yes (spline_lifecycle) |
CloseSpline (0x47) | Yes | Yes | Yes | Yes | Yes | No app flow | No app flow | Yes (spline_lifecycle) |
The No app flow cells are the parity policy's one deliberate app exemption,
not tracked gaps: spline flows are required in the SDKs, CLI, and samples, but
not in the web or mobile apps.
Evidence for the SDK rows is the exported TypeScript surface in
packages/core/src/index.ts, the Rust builders in
packages/sdk-rust/src/instructions.rs, the Python builders in
packages/sdk-python/seesaw/instructions.py, and the CLI entry point in
packages/cli/src/commands/spline/index.ts. The checked-in examples under
packages/sdk-rust/examples and packages/sdk-python/examples now include the
spline_lifecycle walkthrough in both languages.
Admin, governance, and keeper operations#
These are not ordinary trader features, but they are still part of the parity target: mobile must provide equivalent authenticated admin/operator flows, or the inventory must identify a concrete platform limitation and track the gap. Both apps now expose the full family list — web through the admin controls, treasury, and operations pages, mobile through the Pro-gated admin screen.
| Feature family | Web | Mobile | TypeScript SDK | Rust SDK | Python SDK | CLI | Examples |
|---|---|---|---|---|---|---|---|
Initialize config (InitializeConfig) | Yes (operations page) | Yes | Yes | Yes | Yes | Config/deployment tooling | No |
Authority rotation (UpdateAuthority, ClaimAuthority) | Yes | Yes | Yes | Yes | Yes | Yes | No |
| Pause/unpause and protocol PostOnly mode | Yes | Yes | Yes | Yes | Yes | Yes | No |
| Tick size and minimum resting notional | Yes | Yes | Yes | Yes | Yes | Yes | No |
| Market emergency status and force-cancel | Yes | Yes | Yes | Yes | Yes | Yes | No |
| Treasury recipient rotation | Yes | Yes | Yes | Yes | Yes | Yes | No |
Fee-curve/config update (UpdateFeeConfig) | Yes (on controls page) | Yes | Yes | Yes | Yes | Yes | No |
Pauser guardian (SetPauser) | Yes | Yes | Yes | Yes | Yes | Yes | No |
Operational parameter update (UpdateOperationalParams) | Yes | Yes | Yes | Yes | Yes | Yes | No |
Closer-reward top-up (TopUpCloserRewards) | Yes (operations page) | Yes | Yes | Yes | Yes | Yes | No |
| Referral rollup / referrer shard initialization | Yes (operations page) | Yes | Yes | Yes | Yes | Yes | No |
| Resolver registry initialization/update | Yes (operations page) | Yes | Yes | Yes | Yes | Yes | No |
Legacy witness-epoch rotation (0x3C) is a permanent tombstone, not a current
administrative capability; historical client wrappers do not make it callable.
The web admin controls page exposes authority rotation, pause/unpause, PostOnly mode, tick size, minimum resting notional, emergency status, force-cancel, the pauser guardian, the fee curve and split, operational parameters, and market defaults (source). The treasury page exposes recipient rotation (source). The operations page hosts the remaining governance and maintenance instructions — resolver-registry initialization and update, closer-reward top-up, referral rollup, referrer shard initialization, the four external-market maintenance operations, and one-time config genesis (source). The fees page remains read-only analytics and links to the controls page for fee-curve edits.
Mobile exposes every family in the table above through a Pro-gated
AdminScreen (source) driven
by a declarative control registry
(source); each registry entry's
instruction bytes are asserted in
adminControls.test.ts.
Authority gating reads and decodes the on-chain ConfigAccount exactly as web
does, and the on-chain program remains the real gate. This table no longer
carries a No cell in either app column; the remaining gap is sample coverage.
SDK and sample-code findings#
@seesaw/coreexports the active non-spline and spline TypeScript instruction builders, including governance and external-market builders (source).- The Rust SDK has corresponding builders for the active non-spline and spline surfaces, including external lifecycle and reserve operations (source).
- The Python SDK now covers every active non-spline builder, including
top_up_external_progress_reserve; the discriminant-coverage suite enforces this mechanically (source). - Rust and Python examples provide mirrored runnable coverage for place-order, creator-claim, referrals, HTTP, websocket, create-market, funding and share withdrawal, order cancellation/reduction, market lifecycle, position cleanup, Reclaim submission, and the spline walkthrough. Mint/redeem and the referral instructions are demonstrated by the instruction cookbook rather than by dedicated samples.
- The CLI has broader practical coverage than either app: market lifecycle,
order, position, creator, referral, treasury, admin, and Reclaim commands
are present under
packages/cli/src/commands/. Free-funds cancellation is fully covered byorder cancel-all(batched by-id) and the neworder cancel-all-bounded(raw0x12/0x16builders, single bounded instruction). Every non-allowlisted public discriminant is machine-checked against a registered command bypackages/cli/src/__tests__/commands/coverage.test.ts.
Checked-in code-sample inventory#
The Rust and Python SDK example directories are intentionally parallel. The current runnable samples are:
| Sample | Rust | Python | Demonstrated capability |
|---|---|---|---|
| Place order | packages/sdk-rust/examples/build_place_order.rs | packages/sdk-python/examples/build_place_order.py | Build a user trading instruction |
| Create market | create_market_bundle.rs | create_market_bundle.py | CreateMarket bundle with space-ensure preludes |
| Funding | funding_lifecycle.rs | funding_lifecycle.py | DepositFunds, WithdrawFunds, WithdrawShares |
| Order maintenance | order_maintenance.rs | order_maintenance.py | CancelOrder, ReduceOrder |
| Market lifecycle | market_lifecycle.rs | market_lifecycle.py | SnapshotEnd, ResolveMarket, ExpireMarket, CloseMarket, ForceClose |
| Position cleanup | position_cleanup.rs | position_cleanup.py | MarkPositionSettled, ClosePosition, ReclaimExpiredOrder |
| Reclaim submission | reclaim_v1_submission.rs | reclaim_v1_submission.py | Standalone-verifier V1 proof-buffer lifecycle |
| Spline lifecycle | spline_lifecycle.rs | spline_lifecycle.py | InitSpline, UpdateSplineMid, vault ops, CloseSpline |
| Creator claim | creator_claim_all.rs | creator_claim_all.py | Claim creator fees |
| Referral | referral_resolve_and_lock.rs | referral_resolve_and_lock.py | Resolve/lock a referrer |
| HTTP client | http_client.rs | http_client.py | SDK API client setup |
| Websocket | ws_orderbook.rs | ws_positions.py | Live data subscription |
| Instruction cookbook | instruction_cookbook.rs | instruction_cookbook.py | Representative instruction construction |
Sample coverage now exists for every user-facing flow in the tables above, plus a runnable spline walkthrough, so the spline SDK requirement is satisfied on both axes: the builders exist and a sample exercises them.
Both sets are machine-gated. packages/sdk-python/tests/test_examples.py
asserts the Python inventory matches what is on disk and executes every
non-network sample in-process, and the Rust examples are compiled as build
targets by cargo test, so a builder-signature change that breaks a sample
fails CI instead of rotting silently.
The remaining No cells are RecoverSpline, UpdateSplineShape,
AttachSpline, and SettleSpline: these fall outside the walkthrough's
minimal path (attach and settle additionally need a decoded market account on
the Rust client layer) and would need low-level-builder samples.
Verification performed#
pnpm test:inventorypassed.- Web focused feature suites: 6 files, 70 tests passed.
- Mobile focused feature suites: 11 suites, 87 tests passed.
- Static source inventory was cross-checked against
program/src/instruction.rs::discriminatorand the shared SDK exports. - The app, example, and document columns above are now machine-checked by
packages/test-vectors/src/__tests__/feature-support-matrix.test.ts, run bypnpm test:vectorsand named explicitly inpnpm test:conformance. The matrix walksapps/web/app,apps/web/lib, andapps/mobile/srcwith comments, string literals, import and re-export declarations, translation catalogues (i18n/,messages/,locales/), and test scaffolding stripped, so a builder named only in prose, in a UI label such ast('placeOrder'), in a mock, or in an import left behind after its call site was deleted no longer counts as support. Flows whose call site does not name the builder symbol — order placement and cancellation route throughselectOrderBuilderanddispatchCancelOrder, and mobile's position-lifecycle builders are imported underbuild*aliases — are pinned asINDIRECT_APP_SUPPORTentries that name the file and the exact string proving the path exists. That evidence string is checked against the same reduced source, so an exemption cannot be justified by a comment either.
Reconciled against the 2026-08-28 platform E2E run#
The browser lanes in docs/internal/testing/platform-e2e-2026-08-28/ drove
these cells through the running stack. Where a lane changed what a cell is
worth, the change is recorded above; the rest are re-confirmations:
PlaceMultiplePostOnlyOrders(0x0C) — the webYesis now exercised, not just built: the batch landed at 1, 2 and 4 levels per side after the post-only heap frame was sized by entry count. The free-funds twin (0x0F) is still built but not exercised end to end.InitReferrerEarningsAccount(0x22) — webPartial→Yes, see above.- Redeem (
0x1A) on external markets — the market-meta account path is exercised independently of the now-frozen legacy claim-close instruction. CancelAllOrders(0x12),CancelUpTo(0x13),CancelAllOrdersWithFreeFunds(0x16) andCancelUpToWithFreeFunds(0x17) — re-confirmedPartial. The lane exercised every reachable cancel route and none of them emits a bounded builder; there is still no web call site, so these stay pinnedTRACKED_APP_GAPSentries.
Follow-up work#
Every remaining gap is now pinned in the matrix test rather than tracked by review, so closing one means deleting its entry and updating the matching cell here in the same change.
- Apps. The bounded bulk-cancel builders remain web gaps. Mobile referral initialization, bounded cancellation, and the four permissionless external maintenance controls are covered by local unit tests; device/staging execution remains an external signoff.
- Samples. Still missing for the batch and free-funds order families,
UpdateMarketCap, the admin and governance families, and the four low-level spline instructions outside thespline_lifecyclewalkthrough.