Quickstart#
This walkthrough uses the canonical v1 TypeScript SDK to read a native market, send a bounded Buy YES IOC, read the position, and redeem after settlement. The complete Node example supplies the wallet and RPC code; the SDK itself builds unsigned instructions.
1. Install#
pnpm --filter @seesaw/core build
pnpm --filter @seesaw/reclaim test
These commands require an authorized repository checkout; see Installation. Use a funded development wallet and an existing market on the same local, devnet, or staging deployment. The example does not deploy a program, create a market, or provide liquidity.
Save the complete Node example as quickstart.ts where
the checkout's dependencies resolve. Set inputs from your deployment:
export SEESAW_RPC_URL="http://127.0.0.1:8899"
export SEESAW_PROGRAM_ADDRESS="<deployed-program-address>"
export SEESAW_SETTLEMENT_MINT="<deployment-settlement-mint>"
export SEESAW_PYTH_FEED_ID_HEX="<64-hex-character-feed-id>"
export SEESAW_CREATOR="<market-creator-address>"
export SEESAW_DURATION_SECONDS="900"
export SEESAW_KEYPAIR="/absolute/path/to/development-wallet.json"
pnpm exec tsx quickstart.ts read
The first read derives market_id = floor(now / duration) unless
SEESAW_MARKET_ID is supplied. Copy the printed ID into that variable before
trading so a later rollover cannot silently select a different window. If no
account exists, use market discovery to select a created
market. Never paste secret wallet bytes into a shell command.
2. Derive and read accounts#
The complete example performs its own RPC reads and identity checks. This smaller reusable helper illustrates the asynchronous PDA and decoder calls:
// docs-check: semantic
import type { Address } from '@solana/addresses';
import {
decodeMarketAccount,
decodeDeepOrderbookAccount,
deriveMarketPda,
deriveOrderbookPda,
} from '@seesaw/core';
export async function readMarket(
feedId: Uint8Array,
durationSeconds: bigint,
marketId: bigint,
creator: Address,
fetchFinalizedBytes: (address: Address) => Promise<Uint8Array>
) {
const [market] = await deriveMarketPda(feedId, durationSeconds, marketId, creator);
const [orderbook] = await deriveOrderbookPda(market);
const marketAccount = decodeMarketAccount(await fetchFinalizedBytes(market));
const bookAccount = decodeDeepOrderbookAccount(await fetchFinalizedBytes(orderbook));
return { market, orderbook, marketAccount, bookAccount };
}
feedId is the 32-byte feed identifier; the creator is part of market identity.
PDA helpers are asynchronous and return [address, bump]. Supply your own
fetchFinalizedBytes adapter: fetch with finalized commitment, reject missing
accounts or an unexpected owner, and return decoded binary data. Byte decoders
do not fetch accounts or independently prove their PDA identity.
3. Build, sign, and send#
The complete Node example prints the settlement, YES, and NO mints. Prepare
your wallet's token accounts for those exact mints using your wallet or
spl-token create-account; see Funding.
Supply their addresses and an explicit price and quantity:
export SEESAW_MARKET_ID="<printed-market-id>"
export SEESAW_USER_SETTLEMENT_ACCOUNT="<wallet-settlement-token-account>"
export SEESAW_USER_YES_ACCOUNT="<wallet-yes-token-account>"
export SEESAW_USER_NO_ACCOUNT="<wallet-no-token-account>"
export SEESAW_PRICE_BPS="5100"
export SEESAW_QUANTITY="1000000"
pnpm exec tsx quickstart.ts trade
Quantity is in six-decimal share base units. This IOC requires a full fill within the supplied worst price; insufficient liquidity rolls back the whole transaction. The example checks token mints and owners, reads current config treasury recipients, preserves an existing on-chain referral binding, adds the heap request, simulates, signs, sends, waits for finalization, and reads the position again. It accepts no creator or fee-recipient override. For a pending referral candidate, use the resolver and lock flow in referral integration before placing an order.
Keep the same market ID. After read shows a terminal outcome, redeem the
YES amount actually held by this wallet/market:
pnpm exec tsx quickstart.ts read
export SEESAW_REDEEM_AMOUNT="1000000"
pnpm exec tsx quickstart.ts redeem
The amount is explicit: do not add position share fields to ledger and token
balances. Redeem sources ledger free shares first, then wallet tokens, and
drains free quote through the position/ledger surface. A losing YES leg pays
zero. For NO inventory, use tokenType: 1 in the example's redemption call.
Claim promptly; see claiming winnings.
For unattended execution, add persistent intent tracking and
reconciliation. Compilation of a sample does not prove
the deployment is funded, liquid, or running its keeper.
4. External markets#
The runnable Node example above accepts native markets only. When the source market originated elsewhere, use the Reclaim service and
@seesaw/reclaim to canonicalize the external reference and proof wire. The
registered resolver submits the authenticated lifecycle transition; the normal
Seesaw v1 trade, halt, resolve, redeem, and close instructions remain the same.
See Reclaim integration.
5. Verify a release checkout#
pnpm --filter @seesaw/client-gen generate:check
pnpm --filter @seesaw/test-vectors test
pnpm test:sdk-release
These checks prove generated ABI drift, cross-language vectors, Changesets release-candidate coherence, package provenance, and clean-install evidence.
Devnet/local-validator on-ramp#
Use the program address, settlement mint, and feed from the deployment you intend to test. Creating an unrelated mint does not fund that market. Fund SOL for transaction fees and obtain the configured settlement token separately; see funding. Read the selected RPC cluster before requesting any testnet faucet funds. Use the same generated readers and builders as the staging client.
Market creation follows the Pull-only launch contract: bind the Receiver-owned
PriceUpdateV2 account to the requested feed and market intent. Pull is fixed
protocol behavior; there is no oracle selector in the market request.