Your first trade
Open an account, deposit USDC, read the option chain, and place a trade end-to-end.
This walkthrough covers the complete lifecycle of a trade on Phasis: account creation, deposit, reading the option chain, placing an order, the on-chain margin check, and viewing your position. Each step maps directly to an SDK call; the Trading Guide goes deeper on each topic.
1. Open an account (one-time)
Every trader needs a Phasis Account object. This is a shared on-chain object that holds your USDC balance and all open positions. It is created once per wallet address.
From the frontend, click Open Account after connecting your wallet. Under the hood this calls:
genUserEntry.openAccountV2({ registry, accounts })Here accounts is the shared AccountRegistry object id. The resulting Account<USDC> is registered in that registry. Your private key retains full authority over it — the protocol never holds custody.
2. Deposit USDC
Once your account exists, transfer USDC from your wallet into it:
genUserEntry.depositUsdcV2({ registry, accounts, coin })The coin parameter is a Coin<USDC> object — split it from your wallet balance to the size you want to deposit (USDC uses 6 decimals, so a coin of 10_000_000 raw units equals $10.00). Deposited funds land in Account.balance_quote and are immediately available as trading collateral.
If you haven't minted testnet USDC yet, see Get testnet USDC first.
3. View the option chain
The option chain shows every listed series — each combination of underlying asset, expiry, strike, and call/put type.
const market = await getMarket(client, marketId)
// market.series: SeriesRow[]
// Each row: { strike, isCall, expiryTs, fairPrice, intrinsicValue }The frontend renders this as a Derive-style grid: strikes along the left, calls on the left half, puts on the right half. The best bid and ask for each series are live-fed from the embedded DeepBook pool.
Phasis currently lists weekly European options on SUI, BTC, and ETH, expiring every Friday.
4. Place a trade
Choose your instrument — say, a BTC call at a given strike and expiry — and submit an order.
Price and quantity encoding:
limitPriceis in 9-decimal units: $0.05 premium →50_000_000qtyis in 6-decimal contract units: 2 contracts →2_000_000
Order side is derived from your intent:
| Intent | Side sent to DeepBook |
|---|---|
| Open long / Close short | BID |
| Open short / Close long | ASK |
Order types available: NO_RESTRICTION (limit, rest if not filled), FILL_OR_KILL, IMMEDIATE_OR_CANCEL, POST_ONLY.
The SDK call:
placeTrade(tx, {
registryId,
marketId,
accountRegistryId,
snapshotId,
strike,
isCall,
side, // DeepBookSide.BID or .ASK
orderType, // OrderType.NO_RESTRICTION, etc.
qty, // contracts × 1e6
limitPrice, // price × 1e9
})5. On-chain margin check
Before the order touches the order book, the protocol runs a portfolio-level margin check. It calls compute_stress_margin on your entire position set, using the current StressSnapshot published by the off-chain stress keeper. The snapshot contains a pre-computed N-point Black–Scholes stress grid across spot and volatility scenarios.
The check computes your worst-case mark-to-model loss across the grid and compares it to your free_balance (total balance minus existing margin locks). If free_balance < margin_requirement, the transaction aborts. If the check passes, the position is recorded and your margin lock is updated atomically — all within a single programmable transaction block.
This means you can never be undercollateralized at the moment of order placement. See Margin model for a full explanation.
6. Order fills
When your order matches against a resting counterparty (or an incoming taker hits your resting order), DeepBook performs the fill inside the same transaction:
- Your position delta is applied: net quantity and direction updated.
- Open interest for the series is incremented.
- Protocol fees accrue to the on-chain fee pool.
If no counterparty is immediately available and your order type permits it, the order rests on the book and fills on the next interaction.
7. View your positions
After a fill, check your open positions:
const account = await getAccount(client, accountId)
// account.positions: Record<seriesId, Position>
// Each position: { asset, strike, isCall, expiryTs, netQtyMag, netIsShort }The frontend shows each position alongside its current mark value, unrealized P&L, and contribution to margin.
8. Close a position
To close, submit an opposing order with intent CloseLong or CloseShort. The SDK derives the correct side automatically. The same margin check runs — this time verifying that your remaining portfolio after the close still meets margin requirements (which it almost always will, since closing reduces risk).
9. Withdraw USDC
Withdraw any amount up to your free_balance (balance not locked as margin):
genUserEntry.withdrawUsdcV2({ registry, accounts, amount })The protocol transfers the requested USDC back to your wallet as an owned Coin<USDC>. Withdrawal is gated by the margin lock — you cannot withdraw collateral that is currently backing an open short position.
For deeper coverage of order types, the Greeks display, and spread strategies, continue to the Trading Guide.