> For the complete documentation index, see [llms.txt](https://docs.flash.trade/flash-trade/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.flash.trade/flash-trade/flash-trade-protocol/build-on-flash/flash-trade-api/flash-trade-v2/transactionflow.md).

# TransactionFlow

How to take a wallet from zero to trading on Flash Trade **v2** and back out again. Every transaction-builder endpoint returns an **unsigned, base64-encoded versioned transaction** that you decode, sign, and submit yourself — exactly like v1. What's new in v2 is the **deposit → delegate → trade → withdraw** sequence, and that account/funds calls and trading calls submit to different RPC endpoints.

## Overview

```
              ACCOUNT & FUNDS                                  TRADING
 ┌────────────────────────────────────────────┐       ┌──────────────────────────────────┐
 │ init-deposit-ledger                        │       │                                  │
 │ init-basket                                │       │                                  │
 │ deposit-direct        (move funds in)      │       │                                  │
 │ delegate-basket                            │──────►│ open / close / reverse           │
 │                                            │       │ add / remove collateral          │
 │                                            │       │ place / edit / cancel triggers   │
 │                                            │       │ place / edit / cancel limits     │
 │ request-withdrawal                         │◄──────│ (funds returned on withdrawal)   │
 │ execute-withdrawal    (recover if needed)  │       │                                  │
 └────────────────────────────────────────────┘       └──────────────────────────────────┘
```

* **Account & funds calls:** `init-deposit-ledger`, `init-basket`, `deposit-direct`, `delegate-basket`, `request-withdrawal`, `execute-withdrawal`. Sign and submit against your normal Solana RPC.
* **Trading calls:** all `transaction-builder` trading endpoints. Sign and submit against the **v2 RPC endpoint**.

All endpoints are under the `/v2` prefix. See [ApiReference](/flash-trade/flash-trade-protocol/build-on-flash/flash-trade-api/flash-trade-v2/apireference.md) for full request/response schemas.

## Step 0: One-Time Account Setup

A wallet needs a deposit ledger and a basket before it can hold funds and positions. These are idempotent to build but only need to land once.

```bash
# Create the deposit ledger PDA
curl -X POST $FLASH_API_URL/v2/transaction-builder/init-deposit-ledger \
  -H 'Content-Type: application/json' \
  -d '{ "owner": "<WALLET>" }'

# Create the basket PDA
curl -X POST $FLASH_API_URL/v2/transaction-builder/init-basket \
  -H 'Content-Type: application/json' \
  -d '{ "owner": "<WALLET>" }'
```

Each returns `{ "transactionBase64": "…" }`. Sign with the owner and submit to your Solana RPC.

## Step 1: Deposit Funds

Move collateral from your wallet into the platform vault / deposit ledger.

```bash
curl -X POST $FLASH_API_URL/v2/transaction-builder/deposit-direct \
  -H 'Content-Type: application/json' \
  -d '{
    "owner": "<WALLET>",
    "tokenMint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
    "amount": "100.0"
  }'
```

`amount` is in **UI units** (the server converts to native using the token's decimals, including Token-2022 scaling). The source ATA and token program (Token-2022 vs legacy SPL Token) are derived server-side from `owner` + `tokenMint` — no need to pass them.

## Step 2: Delegate the Basket

Delegate the basket to enable trading.

```bash
curl -X POST $FLASH_API_URL/v2/transaction-builder/delegate-basket \
  -H 'Content-Type: application/json' \
  -d '{
    "payer": "<WALLET>",
    "owner": "<WALLET>"
  }'
```

After this confirms, the basket is delegated and you can trade.

## Step 3: Trade

Build a trade. The request identifies the position by `marketSymbol` + `side` — no raw keys needed.

```bash
curl -X POST $FLASH_API_URL/v2/transaction-builder/open-position \
  -H 'Content-Type: application/json' \
  -d '{
    "inputTokenSymbol": "USDC",
    "outputTokenSymbol": "SOL",
    "inputAmountUi": "100.0",
    "leverage": 5.0,
    "tradeType": "LONG",
    "orderType": "MARKET",
    "owner": "<WALLET>",
    "slippagePercentage": "0.5"
  }'
```

The response includes the quote (leverage, entry/liq price, fees) and `transactionBase64`. Sign and submit to the **v2 RPC**.

Other trading actions follow the same pattern — see [BuildTransaction](/flash-trade/flash-trade-protocol/build-on-flash/flash-trade-api/flash-trade-v2/workflows/buildtransaction.md):

* **Close / partial close:** `close-position` with `inputUsdUi`.
* **Reverse:** `reverse-position` flips to the opposite side atomically.
* **Collateral:** `add-collateral` / `remove-collateral`.
* **Triggers:** `place-trigger-order`, `place-tp-sl`, `edit-trigger-order`, `cancel-trigger-order` (pass `orderId: 255` to cancel all).
* **Limits:** open with `orderType: "LIMIT"`; manage with `edit-limit-order` / `cancel-limit-order`.

## Step 4: Decode, Sign, Submit

Identical mechanics to v1 — the payload is a base64 `VersionedTransaction` (v0).

```typescript
import { VersionedTransaction, Connection, Keypair } from "@solana/web3.js";

const { transactionBase64 } = await res.json();
const tx = VersionedTransaction.deserialize(Buffer.from(transactionBase64, "base64"));

tx.sign([ownerKeypair]);

// Trades submit to the v2 RPC; account/funds ops submit to your Solana RPC.
const connection = new Connection(RPC_URL, "confirmed");
const sig = await connection.sendRawTransaction(tx.serialize());
await connection.confirmTransaction(sig, "confirmed");
```

> **Which RPC?** Account & funds transactions go to your normal Solana RPC. Trading transactions must go to the **v2 RPC endpoint**. Submitting to the wrong endpoint will fail.

## Step 5: Read Positions & Orders

Don't reconstruct state from the trade response — read it from the basket snapshot.

```bash
# One-shot
curl $FLASH_API_URL/v2/owner/<WALLET>
```

Or subscribe to the live WebSocket for `basket` (full state) and `metrics` (PnL/leverage/liq ticks) messages — see [WebSocketStreaming](/flash-trade/flash-trade-protocol/build-on-flash/flash-trade-api/flash-trade-v2/websocketstreaming.md). Decode the `basketData` bytes via the v2 client SDK; use `positionMetrics` / `orderMetrics` for UI-ready strings.

## Step 6: Withdraw

Withdrawals are two-step (see [ProtocolConcepts → Withdrawals](/flash-trade/flash-trade-protocol/build-on-flash/flash-trade-api/flash-trade-v2/protocolconcepts.md)).

```bash
# Step 1 — request. Starts the withdrawal and creates your receiving ATA.
# Defaults to including custody settlement.
curl -X POST $FLASH_API_URL/v2/transaction-builder/request-withdrawal \
  -H 'Content-Type: application/json' \
  -d '{
    "owner": "<WALLET>",
    "tokenMint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
    "amount": "12.5",
    "includeCustodySettlement": true
  }'
```

After submitting Phase 1:

1. Poll until the **withdrawal escrow account closes** — that means funds landed in your receiving ATA.
2. For SOL, unwrap the WSOL ATA back to native SOL.

If the withdrawal doesn't complete automatically, **recover** with Step 2:

```bash
curl -X POST $FLASH_API_URL/v2/transaction-builder/execute-withdrawal \
  -H 'Content-Type: application/json' \
  -d '{
    "owner": "<WALLET>",
    "tokenMint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
    "includeCustodySettlement": true
  }'
```

`execute-withdrawal` finishes the withdrawal in a single transaction and closes the escrow.

> **`includeCustodySettlement`.** Set `true` (default) when the custody settlement receipt isn't already on-chain — the builder prepends the settlement instruction so the withdrawal succeeds. If a prior step already created/settled the receipt, set `false` to avoid a duplicate. When recovering with `execute-withdrawal`, set it based on whether the settlement receipt is still present and owned by the program.

## Preview-Only Mode

`open-position` builds a quote without a transaction when you omit `owner` (`transactionBase64` comes back `null`).

## Blockhash Expiry

Built transactions embed a recent blockhash that expires in \~45s. If you hit "Blockhash not found / expired," re-call the builder to get a fresh transaction, then sign and submit immediately. The v2 trading endpoints proactively refresh the blockhash between calls so back-to-back builds don't collide.

## Error Handling

* HTTP-level failures return `{ "error": "…" }` (e.g. `400` invalid pubkey, `404` unknown market/symbol, `500` blockhash fetch failed).
* Trading compute failures come back `200` with `{ "err": "…" }` in the body — always check for it.
* Trigger/limit builder validation failures return `400 { "error": "…" }`.

See [ErrorReference](/flash-trade/flash-trade-protocol/build-on-flash/flash-trade-api/flash-trade-v2/errorreference.md) for the full matrix and recovery patterns.

## Key Notes

* **Two RPCs.** Account & funds ops → Solana RPC. Trades → v2 RPC.
* **Set up once.** `init-deposit-ledger`, `init-basket`, `delegate-basket` are one-time per wallet (until you undelegate/withdraw fully).
* **Positions live in the basket.** Always read state via `/v2/owner/{owner}` or the WS — not from the trade response.
* **UI vs native units.** `deposit-direct` and `request-withdrawal` take **UI** amounts (server converts). Trading endpoints take UI amounts/prices throughout.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.flash.trade/flash-trade/flash-trade-protocol/build-on-flash/flash-trade-api/flash-trade-v2/transactionflow.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
