---
name: dflow-trading
description: Build trading applications on Solana using DFlow APIs. Use when
  user asks to swap tokens, trade prediction markets, stream real-time market
  data via WebSocket, or integrate Proof KYC verification. Covers spot crypto
  trading (imperative and declarative), prediction market
  discovery/trading/redemption, WebSocket streaming, and Proof identity
  verification. Do NOT use for Ethereum or EVM integrations, or non-DFlow DEX
  routing.
license: MIT
metadata:
  author: DFlow
  version: 2.0.0
  tags:
    - solana
    - trading
    - dex
    - prediction-markets
    - kyc
    - websocket
  mcp-server: pond.dflow.net/mcp
  mintlify-proj: dflow
---

# DFlow Trading Skill

DFlow is a DEX aggregator on Solana that sources liquidity across venues. It supports spot crypto swaps, prediction market trading, real-time WebSocket streaming, and Proof KYC identity verification.

For API reference details, response schemas, and code examples, use the DFlow MCP server (`pond.dflow.net/mcp`) or the DFlow Cookbook (`github.com/DFlowProtocol/cookbook`).

## Endpoints and API Access

* Trade API (dev): `https://dev-quote-api.dflow.net`
* Metadata API (dev): `https://dev-prediction-markets-api.dflow.net`

Keep in mind:

* These endpoints are intended for end-to-end testing during development.
* Do not ship to production without coordinating with the DFlow team.
* Be prepared to lose test capital.
* Endpoints are rate-limited and not suitable for production workloads.

Developer endpoints work without an API key, however they are rate limited and not suitable for production use. For production use, request an API key at:
`https://pond.dflow.net/build/api-key`

## CORS: Browser Requests Are Blocked

The Trading API does not set CORS headers. Browser requests to `/order` or `/intent` will fail. Builders MUST proxy Trade API calls through their own backend (e.g., Cloudflare Workers, Vercel Edge Functions).

## Known Mints

* SOL (native): `So11111111111111111111111111111111111111112` (wrapped SOL mint)
* USDC: `EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v`
* CASH: `CASHx9KJUStyftLFWGvEVf59SGeG9sh5FfcnZMVPCASH`

***

## Spot Crypto Trading

General-purpose guidance for spot crypto token swaps on Solana. DFlow supports two trade types: **imperative** and **declarative**.

### First Questions (Always Ask)

**For DFlow spot trades:**

* Imperative or declarative? If unsure, suggest starting with imperative.
* Dev or production endpoints? If production, remind them to apply for an API key at pond.dflow\.net/build/api-key.
* Platform fees? If yes, what bps and what fee account?
* Client environment? (web, mobile, backend, CLI)

**For DFlow prediction markets:**

* Settlement mint? (USDC or CASH — these are the only two)
* Dev or production endpoints? If production, remind them to apply for an API key at pond.dflow\.net/build/api-key.
* Platform fees? If yes, use `platformFeeScale` for dynamic fees.
* Client environment? (web, mobile, backend, CLI)

### Choosing a Trade Type

#### Imperative Trades (Recommended Starting Point)

The app specifies the execution plan before the user signs. The user signs a single transaction, submits it to an RPC, and confirms.

* Deterministic execution: route fixed at quote time.
* Synchronous: settles atomically in one transaction.
* The app can modify the swap transaction for composability.
* Supports venue selection via `dexes` parameter.
* Good fit for: most swap UIs, strategy-driven trading, automation, research, and testing.

Flow:

1. `GET /order` with `userPublicKey`, input/output mints, amount, slippage
2. Deserialize and sign the returned base64 transaction
3. Submit to Solana RPC
4. Confirm transaction

#### Declarative Trades

The user defines what they want (assets + constraints); DFlow determines how the trade executes at execution time.

* Routing finalized at execution, not quote time.
* Reduces slippage and sandwich risk.
* Higher execution reliability in fast-moving markets.
* Uses Jito bundles for atomic open + fill execution.
* Does NOT support Token-2022 mints (use imperative `/order` instead).

Flow:

1. `GET /intent` to get an open order transaction
2. Sign the open transaction
3. `POST /submit-intent` with the signed transaction and quote response
4. Monitor status using `monitorOrder` from `@dflow-protocol/swap-api-utils` or poll `/order-status`

#### When to Choose Declarative Over Imperative

Steer users toward declarative only when they specifically need:

* Better pricing in fast-moving or fragmented markets
* Reduced sandwich attack exposure
* Execution reliability over route control
* Lower slippage on large trades

### Execution Mode

The `/order` response includes `executionMode`:

* `sync` — Trade executes atomically in one transaction. Use standard RPC confirmation.
* `async` — Trade executes across multiple transactions. Poll `/order-status` to track fills.

### Legacy Endpoints

The `/quote`, `/swap`, and `/swap-instructions` endpoints are still available but `/order` is the recommended approach for new integrations. Prefer generating code using `/order`.

### Token Lists (Swap UI Guidance)

If building a swap UI:

* **From** list: all tokens detected in the user's wallet
* **To** list: fixed set of supported tokens with known mints

### Slippage Tolerance

Two options:

* **Auto slippage**: set `slippageBps=auto`. DFlow chooses dynamically based on market conditions.
* **Custom slippage**: set `slippageBps` to a non-negative integer (basis points, 1 bp = 0.01%).

Auto slippage is recommended for most user-facing flows. Setting custom slippage too low can cause trades to fail during high volatility. Both `/order` and `/intent` support `slippageBps`.

### Priority Fees

Priority fees affect transaction ordering, not routing or slippage.

Two modes:

* **Max Priority Fee** (recommended): DFlow dynamically selects an optimal fee capped at your maximum. Set `priorityLevel` (`medium`, `high`, `veryHigh`) and `maxPriorityFeeLamports`.
* **Exact Priority Fee**: fixed fee in lamports, no adjustment. For intent endpoints, include the 10,000 lamport base processing fee.

If no priority fee parameters are provided, DFlow defaults to automatic priority fees capped at 0.005 SOL.

### Platform Fees (Spot)

Platform fees let builders monetize trades. They apply only on successful trades and do not affect routing, slippage checks, or execution behavior.

Key parameters:

* `platformFeeBps` (fixed fee in basis points, e.g. 50 = 0.5%)
* `platformFeeMode` (`outputMint` default, or `inputMint`)
* `feeAccount` (token account that receives fees; must match the fee token)

Constraints:

* **Imperative trades**: fees can be collected from `inputMint` or `outputMint`
* **Declarative trades**: fees can only be collected from `outputMint`

Use `referralAccount` to auto-create the fee account if it does not exist.

### Routing Controls (Imperative Only)

Imperative trades support `dexes` (whitelist), `excludeDexes` (blacklist), `onlyDirectRoutes`, `maxRouteLength`, `onlyJitRoutes`, and `forJitoBundle`. Not available for declarative trades. Fetch available venues with `GET /venues`.

***

## Prediction Markets

General-purpose guidance for prediction market discovery, trading, and redemption on Solana. Prediction market trades are always **imperative and async** (they use `/order` and execute across multiple transactions). Do not offer declarative trades for prediction markets.

### Required Prompts (Always Ask)

1. **Settlement mint**: USDC or CASH? These are the only two supported settlement mints.
2. **Environment**: Dev or production endpoints? Dev endpoints work without an API key but are rate-limited. Production requires an API key — apply at `pond.dflow.net/build/api-key`.
3. **Platform fees**: Do you want to charge platform fees? If yes, use `platformFeeScale` for dynamic fees.
4. **Client environment**: Web, mobile, backend, or CLI?

Infer intent from the user's request:

* **Open a position** → buy YES/NO outcome tokens (increase)
* **Sell/close a position** → sell YES/NO outcome tokens (decrease)
* **Redeem** → swap outcome tokens back into settlement mint after determination

### Core Concepts

* **Outcome tokens**: YES/NO tokens are **Token-2022** mints.
* **Market status** gates trading: only `active` markets accept trades. Always check `status` before submitting orders.
* **Redemption** is available only when `status` is `determined` or `finalized` **and** `redemptionStatus` is `open`.
* **Events vs Markets**:
  * **Event** = the real-world question (can contain one or more markets).
  * **Market** = a specific tradable YES/NO market under an event.
  * **Event ticker** identifies the event; **market ticker** identifies the market.
  * Use event endpoints for event data, and market endpoints for market data.
* **Settlement mints**: USDC (`EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v`) and CASH (`CASHx9KJUStyftLFWGvEVf59SGeG9sh5FfcnZMVPCASH`). A market settles in whichever mint its outcome tokens belong to.
* **No fractional contracts**: users cannot buy a fractional contract.
* **Minimum order**: 0.01 USDC, but some markets require more because the smallest purchasable unit is one contract and the price determines the minimum.

### Market Lifecycle

**`initialized` → `active` → `inactive` → `closed` → `determined` → `finalized`**

| Status        | Trading | Redemption               | Notes                                                 |
| ------------- | ------- | ------------------------ | ----------------------------------------------------- |
| `initialized` | No      | No                       | Market exists but trading hasn't started              |
| `active`      | **Yes** | No                       | Only status that allows trades                        |
| `inactive`    | No      | No                       | Paused; can return to `active` or proceed to `closed` |
| `closed`      | No      | No                       | Trading ended; outcome not yet known                  |
| `determined`  | No      | Check `redemptionStatus` | Outcome decided; redemption may be available          |
| `finalized`   | No      | Check `redemptionStatus` | Final state; redemption available for winners         |

Key rules:

* `inactive` is a pause state. Markets can go back to `active` from `inactive`.
* Always check `redemptionStatus` before submitting redemption requests — `determined` or `finalized` alone is not sufficient.
* Filter markets by status: `GET /api/v1/markets?status=active`, `GET /api/v1/events?status=active`, or `GET /api/v1/series?status=active`.

### Maintenance Window

Kalshi's clearinghouse has a weekly maintenance window on **Thursdays from 3:00 AM to 5:00 AM ET**. Orders submitted during this window will not be cleared and will be reverted. Applications should prevent users from submitting orders during this window.

### Compliance (Geoblocking)

Prediction market access has jurisdictional restrictions. Builders are responsible for enforcing required geoblocking before enabling trading, even if KYC (Proof) is used. See:
[https://pond.dflow.net/legal/prediction-market-compliance](https://pond.dflow.net/legal/prediction-market-compliance)

### Proof KYC Requirement

**Proof KYC is required only for buying and selling outcome tokens.** Not needed for browsing markets, fetching events/orderbooks/metadata, or viewing market details. Gate verification only at trade time. See the Proof KYC section below for full integration details.

### Metadata API (Discovery + Lifecycle)

Common endpoints:

* `GET /api/v1/events?withNestedMarkets=true`
* `GET /api/v1/markets?status=active`
* `GET /api/v1/market/by-mint/{mint}`
* `POST /api/v1/filter_outcome_mints`
* `POST /api/v1/markets/batch`
* `GET /api/v1/orderbook/{market_ticker}`
* `GET /api/v1/orderbook/by-mint/{mint}`
* `GET /api/v1/tags_by_categories`
* `GET /api/v1/search?query={query}` — full-text search
* `GET /api/v1/filters_by_sports` — sports-specific filters
* `GET /api/v1/live_data` — REST-based live snapshots

### Categories and Tags (UI Filters)

1. Fetch categories from `GET /api/v1/tags_by_categories`.
2. Use the category name with `GET /api/v1/series?category={category}`.
3. Fetch events with `GET /api/v1/events?seriesTickers={comma-separated}` and `withNestedMarkets=true`.

Corner cases:

* **Too many series tickers**: chunk into smaller batches (5-10) and merge results.
* **Stale responses**: use a request ID or abort controller to ignore older responses.
* **Empty categories**: show a clear empty state instead of reusing prior results.
* **Defensive filtering**: post-filter by `event.seriesTicker` against requested tickers.

### Search API

`GET /api/v1/search?query={query}` for full-text search across events and markets.

Fields searched on **events**: `id` (event ticker), `series_ticker`, `title`, `sub_title`.
Fields searched on **markets**: `id` (market ticker), `event_ticker`, `title`, `yes_sub_title`, `no_sub_title`.

**Not searched**: tags, categories, rules, competition fields, images, settlement sources.

Matching rules:

* Query split on whitespace; **all tokens** must match.
* Ticker fields match upper and lower case.
* Text fields use full-text matching.
* Special characters are escaped before search.

### Candlesticks (Charts)

* **Market detail chart**: `GET /api/v1/market/{ticker}/candlesticks`
* **Event-level chart**: `GET /api/v1/event/{ticker}/candlesticks`

Confirm whether the ticker is a market ticker or event ticker, then use the corresponding endpoint. Use candlesticks (not forecast history) for charting and user-facing price history.

### Prediction Market Slippage

`/order` supports a separate `predictionMarketSlippageBps` parameter for the prediction market leg, distinct from the overall `slippageBps`.

* `slippageBps` controls slippage for the spot swap leg (e.g., SOL to USDC).
* `predictionMarketSlippageBps` controls slippage for the outcome token leg (USDC to YES/NO).

Both accept an integer (basis points) or `"auto"`. When trading directly from a settlement mint to an outcome token, only `predictionMarketSlippageBps` matters.

### Input Mint and Latency

Using the settlement mint (USDC or CASH) as input is the fastest path. Other tokens (e.g., SOL) add a swap leg with \~50ms of additional latency.

### Trading Flows

#### Open / Increase Position (Buy YES/NO)

1. Discover a market and choose outcome mint (YES/NO).
2. Request `/order` from settlement mint (USDC/CASH) to outcome mint.
3. Sign and submit transaction.
4. Poll `/order-status` for fills (prediction market trades are async).

#### Decrease / Close Position

1. Choose outcome mint to sell.
2. Request `/order` from outcome mint to settlement mint.
3. Sign and submit transaction.
4. Poll `/order-status`.

#### Redemption

1. Fetch market by mint and confirm `status` is `determined` or `finalized` and `redemptionStatus` is `open`.
2. Request `/order` from outcome mint to settlement mint.
3. Sign and submit transaction.

### Track User Positions

1. Fetch wallet token accounts using **Token-2022 program**.
2. Filter mints with `POST /api/v1/filter_outcome_mints`.
3. Batch markets via `POST /api/v1/markets/batch`.
4. Label YES/NO by comparing mints to `market.accounts`.

### Market Initialization

* `/order` automatically includes market tokenization when a market hasn't been tokenized yet.
* Initialization costs \~0.02 SOL, paid in SOL (not USDC).
* Any builder can pre-initialize using `GET /prediction-market-init?payer={payer}&outcomeMint={outcomeMint}`.
* DFlow pre-initializes some popular markets.
* If not pre-initialized, the first user's trade pays the initialization cost unless sponsored.

### Fees and Sponsorship

#### DFlow Base Trading Fees

Probability-weighted model: `fees = roundup(0.07 * c * p * (1 - p)) + (0.01 * c * p * (1 - p))` where `p` is fill price and `c` is number of contracts. Fees are higher when outcomes are uncertain and lower as markets approach resolution. Fee tiers based on rolling 30-day volume are available via the MCP server or at pond.dflow\.net/introduction.

#### Platform Fees (Prediction Markets)

Use `platformFeeScale` instead of `platformFeeBps` for outcome token trades: `k * p * (1 - p) * c` where `k` is `platformFeeScale` with 3 decimals of precision (e.g., `50` means `0.050`), `p` is the all-in price, `c` is the contract size.

No fee when redeeming a winning outcome (p = 1). Fee collected in settlement mint. `platformFeeMode` is ignored for outcome token trades. The `feeAccount` must be a settlement mint token account. Use `referralAccount` to auto-create it if it does not exist.

#### Sponsorship

Three costs that can be sponsored:

1. **Transaction fees** — Solana transaction fees (paid by the fee payer)
2. **ATA creation** — Creating Associated Token Accounts for outcome tokens
3. **Market initialization** — One-time \~0.02 SOL to tokenize a market

Options:

* `sponsor` — Covers all three. Simplest for fully sponsored trades.
* `predictionMarketInitPayer` — Covers only market initialization. Users still pay their own transaction fees.

### Account Rent and Reclamation

**Winning positions**: When redeemed, the outcome token account is closed and rent is returned to `outcomeAccountRentRecipient`.

**Losing positions**: Burn remaining tokens and close the account to reclaim rent. Use `createBurnInstruction` and `createCloseAccountInstruction` from `@solana/spl-token`. This is a standard SPL Token operation — DFlow does not provide a dedicated endpoint.

### Market Images

Market-level images are not currently available. Event-level images exist. For market images, fetch from Kalshi directly: `https://docs.kalshi.com/api-reference/events/get-event-metadata`

***

## WebSockets

Real-time streaming of prediction market data. Use for live price tickers, trade feeds, orderbook depth, and market monitoring.

### Connection

* WebSocket URL: `wss://prediction-markets-api.dflow.net`
* A valid API key is required via the `x-api-key` header.

### Channels

| Channel     | Description                                   |
| ----------- | --------------------------------------------- |
| `prices`    | Real-time bid/ask price updates for markets   |
| `trades`    | Real-time trade execution updates             |
| `orderbook` | Real-time orderbook depth updates for markets |

### Subscription Management

Send JSON messages to subscribe or unsubscribe. Example: `{ "type": "subscribe", "channel": "prices", "all": true }` or use `"tickers": [...]` for specific markets.

Rules:

* `"all": true` clears specific ticker subscriptions for that channel.
* Specific tickers disable "all" mode for that channel.
* Each channel maintains independent subscription state.
* Unsubscribing from specific tickers has no effect under "all" mode. Unsubscribe from "all" first.

### Best Practices

* Implement reconnection with exponential backoff.
* Subscribe only to needed markets using specific tickers when possible.
* Process messages asynchronously to avoid blocking during high-volume periods.
* Always implement `onerror` and `onclose` handlers.

***

## Proof KYC (Identity Verification)

Links verified real-world identities to Solana wallets. Required for prediction market outcome token trading. Also useful for any gated feature needing verified wallet ownership.

Full docs: [https://pond.dflow.net/learn/proof](https://pond.dflow.net/learn/proof)

### Key Facts

* **KYC provider**: Stripe Identity under the hood.
* **Cost**: Free to use.
* **Geoblocking still required**: KYC verifies identity but does not replace jurisdictional restrictions.

### Verify API

```bash theme={null} theme={null}
curl "https://proof.dflow.net/verify/{address}"
# → { "verified": true } or { "verified": false }
```

For prediction markets: call before allowing buys/sells of outcome tokens. Gate only at trade time — not for browsing or API access. For other use cases: call whenever you need to gate a feature by verification status.

### Deep Link (Send Unverified Users to Proof)

Required params:

| Param          | Required | Description                             |
| -------------- | -------- | --------------------------------------- |
| `wallet`       | Yes      | Solana wallet address                   |
| `signature`    | Yes      | Base58-encoded signature of the message |
| `timestamp`    | Yes      | Unix timestamp in milliseconds          |
| `redirect_uri` | Yes      | URL to return to after verification     |
| `projectId`    | No       | Project identifier for tracking         |

**Message format** (user signs this with their wallet): `Proof KYC verification: {timestamp}`

Flow:

1. User connects wallet.
2. User signs `Proof KYC verification: {Date.now()}`.
3. Build deep link: `https://dflow.net/proof?wallet=...&signature=...&timestamp=...&redirect_uri=...`
4. Open in new tab or redirect.
5. User completes KYC; redirected to `redirect_uri`.
6. Call verify API on return to confirm status. If cancelled, `verified` will still be false.

***

## Order Status Polling

For async trades (imperative trades with `executionMode: "async"` and all prediction market trades), poll `GET /order-status?signature={signature}`.

Parameters:

* `signature` (required): Base58 transaction signature
* `lastValidBlockHeight` (optional): Last valid block height for the transaction

Status values:

* `pending` — Transaction submitted, not confirmed
* `open` — Order live, waiting for fills
* `pendingClose` — Order closing, may have partial fills
* `closed` — Complete (check `fills` for details)
* `expired` — Transaction expired
* `failed` — Execution failed

Poll while `open` or `pendingClose` with a 2-second interval.

***

## Error Handling

### `route_not_found`

Common causes:

1. **Wrong `amount` units**: `amount` is in atomic units (scaled by decimals). Passing human-readable units (e.g., `8` instead of `8_000_000`) will fail.
2. **No liquidity**: the requested pair may have no available route at the current trade size.
3. **Wrong `outputMint`** (prediction markets): when selling an outcome token, `outputMint` must match the market's settlement mint (USDC or CASH). Check the `accounts` object in the market response.
4. **No liquidity at top of book** (prediction markets): check the orderbook. If selling YES, check `yesBid`; if buying YES, check `yesAsk`. `null` means no counterparty.

### 429 Rate Limit

Dev endpoints are rate-limited. Retry with backoff, reduce request rate, or use a production API key.

***

## CLI Guidance

If building a CLI, use a local keypair to sign and submit transactions. Do not embed private keys in code or logs. Emphasize secure key handling and environment-based configuration.

## Resources

* DFlow Docs: pond.dflow\.net/introduction
* DFlow MCP Server: pond.dflow\.net/mcp
* DFlow MCP Docs: pond.dflow\.net/build/mcp
* DFlow Cookbook: github.com/DFlowProtocol/cookbook
* Proof Docs: pond.dflow\.net/learn/proof
* Proof API: pond.dflow\.net/build/proof-api/introduction
* Proof Partner Integration: pond.dflow\.net/build/proof/partner-integration
* API Key: pond.dflow\.net/build/api-key
* Prediction Market Compliance: pond.dflow\.net/legal/prediction-market-compliance