About dflow-spot-trading
DFlow Spot Trading is a skill for quoting and swapping Solana token pairs through DFlow, for CLI, script, and application integrations. It covers quote retrieval, preparing transactions for signing, and handling fees, signing, and submission.
Key features
- 01Retrieve read-only swap quotes
- 02Prepare transactions for signing
- 03Execute swaps through the CLI
- 04Integrate swaps through the API
- 05Explain priority-fee and sponsored-trade options
- 06Guide platform-fee configuration
Use cases
- 01Check a token swap quote before trading
- 02Swap tokens through a CLI or agent
- 03Integrate swap flows into an app backend
- 04Configure platform fees on app-routed trades
MCP support
The skill requires DFlow docs MCP to look up API parameters, endpoints, and error details. It provides trading workflow guidance and is not itself an MCP server.
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ dflowprotocol/ dflow-skills --skill dflow-spot-tradingAfter installing, type/dflow-spot-tradingin Claude Code to confirm it loaded.
Details
From the project READMEDFlow Spot Trading
Swap any pair of Solana tokens via DFlow. Trades are synchronous: one /order call returns a signed-ready transaction that you sign, submit, and confirm.
Prerequisites
- DFlow docs MCP (
https://pond.dflow.net/mcp): install per the repo README. This skill is the recipe; the MCP is the reference. Look up endpoint shapes, parameter details, and error codes there rather than guessing.- Convention: a bare doc path in this skill (e.g.
/resources/trading-api/order/order) is an MCP path. Read it withquery_docs_filesystem_d_flow(cat/headthe.mdx) orsearch_d_flow, not a browser fetch. Fullhttps://links are human-facing destinations (runnable recipes, the API-key signup) that you hand to the user.
- Convention: a bare doc path in this skill (e.g.
dflowCLI (optional, for command-line/agent use): install per the repo README.
Choose your surface
- CLI: command line, scripts, local agents. Manages keys, signs, and broadcasts.
- API: web/mobile apps, backends, automations with their own signer. Browser apps must proxy HTTP through their backend (the Trading API serves no CORS).
If unclear, ask once: "From the command line, or wired into an app?"
Workflows
Quote (read-only)
- CLI:
dflow quote <atomic-amount> <FROM> <TO> - API:
GET /orderdoubles as a quote. Called without auserPublicKey, it returns the price fields with no transaction attached, which is what you want for a quote before the user has connected a wallet./quotestill works, but/orderis the preferred surface for new integrations. (Quote/response field list: load/resources/trading-api/order/ordervia the docs MCP.)
Trade (/order)
Get a quote and a signed-ready transaction in one call, then sign, submit, and confirm. Works with all SPL and Token-2022 mints.
Full request/response schema, every param, and the error codes: load
/resources/trading-api/order/ordervia the docs MCP (query_docs_filesystem_d_flow).
- CLI:
dflow trade <atomic-amount> <FROM> <TO>(add--confirmfor agents/scripts that need to block until confirmed). - API:
GET /order?userPublicKey=&inputMint=&outputMint=&amount=&transactionVersion=v1, decode the base64transaction, sign it, submit it through your RPC, and confirm. Requires@solana/kit(>=8.0.0) to build, sign, and send the transaction. The DFlow quickstart pattern:
const params = new URLSearchParams({
userPublicKey, inputMint, outputMint, amount,
transactionVersion: "v1",
});
const { transaction } = await fetch(`/api/order?${params}`).then(r => r.json());
const tx = getTransactionDecoder().decode(getBase64Encoder().encode(transaction));
const signed = await signTransaction([keypair], tx);
const wireTx = getBase64EncodedWireTransaction(signed);
const sig = await rpc.sendTransaction(wireTx, { encoding: "base64" }).send();
// Poll getSignatureStatuses (or your framework's confirm helper) before treating the trade as landed.
Where each /order response field goes (DFlow owns the authoritative value, so display these rather than re-deriving them):
transaction(base64): decode, sign, submit.inAmount/outAmount/otherAmountThreshold/priceImpactPct/slippageBps: display.prioritizationFeeLamports/prioritizationType: the server-resolved priority-fee choice after"auto"resolution; echo or log.contextSlot: logging / staleness checks.routePlan: optional display / debugging.
Fields marked "Specified if and only if the request included the user's public key" in the schema (transaction, lastValidBlockHeight, computeUnitLimit, prioritizationFeeLamports) are absent on quote-only calls, so check before using them.
Full runnable example: /spot/recipes/quickstart. Field-level schema: load /resources/trading-api/order/order via the docs MCP.
What to ASK the user (and what NOT to ask)
Trade shape (infer if unambiguous, confirm if not):
- Input and output token as base58 mint addresses. The CLI resolves a small symbol set (SOL, USDC, USDT, JUP, BONK, and a few others); the API has no symbol resolver and accepts base58 mints only.
- Amount in atomic units of the input token (
500000= $0.50 USDC,1000000000= 1 SOL). Convert before calling.
Infra (always ask, never infer):
- API only: wallet pubkey (base58), required for every
/ordercall that returns a transaction. - API only: DFlow API key. Ask with a clean, neutral question: "Do you have a DFlow API key?" Don't presuppose where the key lives; phrasings like "is
DFLOW_API_KEYset?" nudge the user toward env-var defaults they didn't ask for. It's one key for everything DFlow (the samex-api-keyworks across the REST APIs and the WebSocket streams). If yes, use prod hosthttps://quote-api.dflow.netwithx-api-keyon every request. If no, use dev hosthttps://dev-quote-api.dflow.net(same features, rate-limited, for testing only). Point them athttps://pond.dflow.net/get-started/api-keyfor a prod key. ThedflowCLI also requires a key, set once viadflow setup. - Priority fee (both surfaces): "Any priority-fee preference, or just use DFlow's default?" Default on both surfaces is DFlow-auto, capped at 0.005 SOL (documented default on
/order). Surface this so the user knows the lever exists for congestion or cost-sensitive trades. Don't editorialize about what percentage of trades this covers; DFlow doesn't publish one.- API: pass
prioritizationFeeLamportson/orderasauto,medium,high,veryHigh,disabled, or integer lamports. Live estimates for tuning:GET /priority-fees(snapshot),/priority-fees/stream(WebSocket). Fee modes and the auto-cap: load/spot/trading/priority-feesvia the docs MCP. - CLI: no tuning flag;
dflow tradealways uses the server-side default. For finer control (an exact lamport value, ordisabled), drop to the API.
- API: pass
- Sponsored / gasless (API only, skip for CLI): "Does the user need to hold SOL for this trade, or is your app covering fees?" Default is user pays. To sponsor, pass
sponsor=<sponsor-wallet-base58>on/orderand co-sign the returned transaction with the sponsor keypair:signTransaction([userKeypair, sponsorKeypair], tx)(both user and sponsor sign). OptionalsponsorExec=true|falsepicks sponsor-executes (default) vs. user-executes. Full semantics: load/resources/trading-api/order/ordervia the docs MCP. The CLI doesn't support sponsorship.
Do NOT ask about:
- RPC: CLI users set it during
dflow setup. For the API, ask only when the app signs server-side and needs its own RPC to submit. When one is needed, use a reliable RPC provider. - Slippage: both surfaces default to
"auto". Override only on explicit user request (--slippageCLI;slippageBpsAPI). - DEX inclusion/exclusion, route length, Jito bundles, direct-only routes: defaults are right for typical swaps; surface these knobs only on explicit user need.
- Platform fee: off by default; relevant only if the user is monetizing their own distribution. See the Platform fees section below.
Gotchas (the docs MCP won't volunteer these)
- Transaction format. Each
/order(and/quote) call builds a 4096-byte transaction with account addresses inlined (no address lookup tables) and rejects duplicate addresses; the 64-account limit still applies. Build, sign, and send it with@solana/kit(>=8.0.0) — classic@solana/web3.jscan decode it back for display but can't build, sign, or send it. - Atomic units always. The API rejects human-readable amounts. Confirm decimals each time (token metadata or RPC
getParsedAccountInfo). - API has no symbol resolver.
inputMintandoutputMinttake base58 mint addresses only, so a symbol like"USDC"won't work on/order. (The CLI resolves a small symbol set; the API does not.) - Browser apps must proxy. The Trading API serves no CORS, so call it from a backend (an edge function or API route), never directly from the browser.
route_not_found. A likely cause is insufficient liquidity for the pair at your trade size. It's also worth confirming the mint addresses are correct and thatamountis in atomic units.price_impact_too_highis real. Trade size exceeds available liquidity; reduceamount, or passpriceImpactTolerancePctonly with the user's explicit consent.- Onchain failure with slippage logs. Don't silently bump
slippageBpson retry; surface it to the user. - CLI and direct HTTP are separate auth sites. The CLI stores its key, wallet, and RPC at
dflow setup, so shelling out todflow tradeplumbs nothing extra. A sibling HTTP client that calls/orderdirectly needs its own key handed in (env var,.env, header); the CLI's stored key is not reused by it. Both need a key; they're just configured in different places.
Platform fees (builder cut)
Collect a fee on swaps your app routes, paid to a builder-controlled token account on successful execution. API only: these are /order params; the dflow CLI has no platform-fee flags.
platformFeeBps: flat fee in basis points (50= 0.5%).platformFeeMode: which side pays,outputMint(default) orinputMint.feeAccount: the SPL token account that receives the fee. It must already exist (DFlow won't create it); you need one ATA per token you collect in, owned by the builder wallet. Pass the one matching the mode's token per request.
Gotchas:
- Don't set
platformFeeBpsunless you're actually collecting. A declared fee is factored into the slippage budget, so a fee with no realfeeAccountbehind it spends that budget on nothing and worsens the user's price. - Fees apply only on successful trades. Failed or reverted swaps charge nothing.
Ask the user: fee rate (bps), and the collection token(s) (and whether a matching builder-owned ATA already exists). For the full mode matrix, load /spot/trading/platform-fees via the docs MCP; runnable example: /spot/recipes/platform-fees.
When something doesn't fit
For anything not covered here (full parameter lists, full error tables, sponsorship fields), query the docs MCP (search_d_flow, query_docs_filesystem_d_flow).
For runnable code, point the user at the DFlow docs recipes: /spot/recipes/quickstart.
Sibling skills
Defer if the user pivots to:
dflow-market-data: stream live prices, order book, or depth. Read-only market data; this skill executes trades, that one displays them. A "show me the live book / prices" ask belongs there.