Flash SDK V2
Introduction
Flash SDK v2 (@flash_trade/flash-sdk-v2) is the TypeScript client for Flash, covering trading, liquidity provisioning, and FAF staking with instant, gasless execution.
Use Flash SDK v2 for all new integrations. The older Flash SDK (flash-sdk) is being deprecated and will be retired shortly — new builds should target v2.
How it works
You give the client two RPC endpoints and call the instruction builders:
The Flash
ER_RPC— Flash's trading endpoint, provided by Flash; trading and order execution run here.
There are two kinds of operations, and the rest of these docs are organized around them:
Trading — open/close positions, adjust collateral, and place or edit orders. Each is built and sent in a single transaction with
sendAndConfirmErTransaction.Setup, deposits, liquidity, and staking — sent with
sendAndConfirmTransaction. The liquidity and staking operations are multi-step flows: you submit a transaction, then poll a receipt for the result (covered on each page).
Install
npm install @flash_trade/flash-sdk-v2
# or
yarn add @flash_trade/flash-sdk-v2The SDK already depends on @coral-xyz/anchor, @solana/web3.js, and @solana/spl-token, so they're installed for you. The examples here import directly from those three (for BN, PublicKey, Keypair, ATA helpers, etc.) — if you do the same, it's good practice to add them to your own package.json so the versions stay pinned and types resolve cleanly under strict package managers (pnpm, Yarn PnP):
npm install @coral-xyz/anchor @solana/web3.js @solana/spl-tokenThe main export is FlashPerpetualsClient. Everything you call hangs off one instance of it.
Setting up the client
Create a single shared module and import the client (and your keypair) everywhere:
PoolConfig.fromIdsByName(...) reads a pool/token snapshot bundled into the npm package — frozen at the version you installed. To pick up new pools, token listings, custody changes, and oracle updates without waiting for an SDK release, fetch the live config from Flash's CDN instead — see Dynamic Pool & Token Data.
Sending transactions
You build instructions with the client, then send them one of two ways:
flashClient.sendAndConfirmTransaction(ixs, opts?)— for one-time setup, deposits, liquidity, and staking.optsaccepts{ additionalSigners, skipPreflight, alts }.flashClient.sendAndConfirmErTransaction(ixs, signers)— for trading (positions and orders) and for the commit step of liquidity/staking flows.signers[0]is the fee payer and signs the transaction — your owner keypair for a bot, or a session key if you've set one up.
Large setup/liquidity transactions forward a big account set inline — attach the pool's address lookup tables so they fit:
Session keys (optional — for UIs)
If you're building a UI, a session key lets users trade without a wallet pop-up on every transaction: authorize a fresh keypair once, then sign trades with it locally.
Bots and scripts don't need session keys. Sign trades directly with your owner keypair (sendAndConfirmErTransaction(ixs, [walletKeypair])). Session keys only affect trading instructions; everything else is always signed by the owner.
Receipts: how liquidity & staking flows report their outcome
Liquidity and staking operations return a receipt account. After your transaction confirms, the program runs the remaining steps and closes the receipt. Two helpers wait on it:
A confirmed transaction is not a successful action. On a slippage/price/cap miss the program refunds you and the transaction still succeeds — only the receipt tells you whether the mint/burn actually happened. Always read the receipt outcome before updating balances. LP Interactions shows the full pattern.
Reading accounts
Fetch typed account wrappers. Position/pool/custody reads use client.accounts; your basket (which holds your open positions and orders) is read from client.erAccounts:
Wrappers expose decoded fields directly (e.g. pool.lpSupply, position.sizeAmount) plus .publicKey and helpers. Your open positions and orders are embedded in the basket (basket.positions, basket.orders) — there's no separate per-position account. See Trader Interactions → Reading positions & orders.
To stream updates, subscribe to the basket with onAccountChange and decode with the program coder:
Quotes & views
Pricing math runs on-chain — the SDK simulates it and decodes the typed result, so you never re-implement fee/PnL math. Views live under flashClient.views.*:
Each interaction page lists the views relevant to it.
Troubleshooting
On-chain failures come back as {"InstructionError":[i,{"Custom":N}]}. Decode N by range: 2000–2999 are Anchor framework constraints; ≥ 6000 are the perpetuals program's own errors (offset from 6000); small codes like 0x1 are SPL Token; 0x0 from the System program means an account already exists.
Custom 2006 — Anchor ConstraintSeeds
A passed PDA doesn't match what the program re-derives — most often the wrong collateral symbol for the market (the market PDA is keyed by target + collateral + side).
Resolve the market and use its collateralSymbol (Resolving the market); don't hardcode. Confirm cluster/pool/program id agree.
Custom 6023 — MinLeverage
sizeAmount is in target-token base units, not USD, so a USD-looking number lands far below the minimum leverage.
Derive sizeAmount from getOpenPositionQuoteEr at your target leverage (BPS) instead of passing a raw size.
Custom 6021 — MaxLeverage
Same size↔collateral unit confusion, other direction.
Same fix — derive the size from a quote.
SPL Token 0x1 — insufficient funds
The funding account is empty/underfunded; for trades, collateral isn't in the deposit ledger yet.
Fund the ATA, and run the one-time setup to deposit collateral before trading.
System 0x0 — account in use
A receipt from a half-finished liquidity/staking flow is still open.
Resume that receipt rather than resubmitting — see Reading the outcome / resuming.
Account-not-found on getPnl / getPositionData
The base getPnl / getPositionData views target the old standalone position model, not the basket.
Use the *Er variants — your positions live in the basket.
A confirmed transaction is not a successful action for liquidity/staking flows — always read the receipt outcome before trusting balances.
Next steps
Trader Interactions — basket setup, open/close/modify positions, limit & trigger orders, quotes, reading positions.
LP Interactions — add/remove liquidity (FLP & sFLP), migrations, and the receipt-driven flow.
Revenue Interactions — FAF staking, claiming staking rewards, protocol revenue, and referral rebates.
Dynamic Pool & Token Data — fetch the live pool/token config from Flash's CDN and hot-reload it in long-running bots, instead of relying on the bundled snapshot.
Last updated
Was this helpful?

