Declarative Swaps allow Solana users to trade tokens with less slippage, lower latency, and better pricing.
Using Declarative Swaps through DFlow Swap API is simple. DFlow Swap API
aggregates liquidity from all the major Solana DEXs and offers an API for trading any SPL token.
This quickstart assumes familiarity with Solana’s transaction and network connection logic.
If unfamiliar, please refer to the Solana Cookbook.
1
Request a Quote
DFlow Swap API returns a quote specific to the token pair, amount, slippage tolerance,
platform fee, segmenter fee, and other parameters.
A route is calculated for the swap at this step, but not hardened into the transaction. Instead,
the quote is committed, and the route plan will be recalculated at the time the intent is submitted.
Request a Quote
Copy
Ask AI
const SOL = 'So11111111111111111111111111111111111111112';const USDC = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';/// Amount of SOL to swap to USDCconst amount = 1_000_000_000;/// Slippage tolerance in bpsconst slippageBps = 1;/// Base URL for the DFlow Swap APIconst AGGREGATOR_API_BASE_URL = "https://quote-api.dflow.net";const queryParams = new URLSearchParams();queryParams.append('inputMint', SOL);queryParams.append('outputMint', USDC);queryParams.append('amount', amount.toString());queryParams.append('userPublicKey', keypair.publicKey.toBase58());queryParams.append('slippageBps', slippageBps.toString());const intentResponse = await fetch(`${AGGREGATOR_API_BASE_URL}/intent?${queryParams.toString()}`);const intentData = await intentResponse.json();
2
Sign the Intent
Signing the intent guarantees the minimum amount of output tokens, but does not commit to any given route plan
to achieve the minimum amount of output tokens.
After submitting the Intent, you can monitor its status using the monitorOrder helper function from the
@dflow-protocol/swap-api-utils package.
Monitor the Intent
Copy
Ask AI
const result = await monitorOrder({ connection, intent: intentData, signedOpenTransaction: openTransaction, submitIntentResponse: submitIntentData,});switch (result.status) { case ORDER_STATUS.CLOSED: { if (result.fills.length > 0) { // Order was filled and closed const qtyIn = result.fills.reduce((acc, x) => acc + x.qtyIn, 0n); const qtyOut = result.fills.reduce((acc, x) => acc + x.qtyOut, 0n); console.log(`Order succeeded: sent ${qtyIn}, received ${qtyOut}`); } else { // Order was closed without any fills console.log("Order failed"); } break; } case ORDER_STATUS.PENDING_CLOSE: { if (result.fills.length > 0) { // Order was filled and is now closable const qtyIn = result.fills.reduce((acc, x) => acc + x.qtyIn, 0n); const qtyOut = result.fills.reduce((acc, x) => acc + x.qtyOut, 0n); console.log(`Order succeeded: sent ${qtyIn}, received ${qtyOut}`); } else { // Order was not filled and is now closable console.log("Order failed"); } break; } case ORDER_STATUS.OPEN_EXPIRED: { // Transaction to open the order expired console.log("Transaction expired. Try again with a higher slippage tolerance."); break; } case ORDER_STATUS.OPEN_FAILED: { // Transaction to open the order was executed and failed console.log("Order failed", result.transactionError); break; }}