Skip to main content
The DFlow Trade API provides a unified interface for trading tokens across both spot and prediction markets on Solana. The Trade API offers a simple workflow with a single endpoint to request orders, automatically handling both synchronous (atomic) and asynchronous (multi-transaction) execution.
This quickstart assumes familiarity with Solana’s transaction and network connection logic. If unfamiliar, please refer to the Solana Cookbook.
1

Request an Order

The Trade API’s GET /order endpoint returns a quote and open transaction in a single request.
const SOL = "So11111111111111111111111111111111111111112";
const USDC = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";

/// Amount of SOL to trade to USDC
const amount = 1_000_000_000;

/// Slippage tolerance in bps
const slippageBps = 50;

/// Base URL for the DFlow Trade API
const 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("slippageBps", slippageBps.toString());
queryParams.append("userPublicKey", keypair.publicKey.toBase58());

const orderResponse = await fetch(
  `${API_BASE_URL}/order?${queryParams.toString()}`
).then((x) => x.json());
2

Sign and Submit the Transaction

Deserialize the transaction, sign it with your keypair, and submit it to Solana using your RPC connection.
/// Deserialize the transaction from base64
const transactionBuffer = Buffer.from(orderResponse.transaction, "base64");
const transaction = VersionedTransaction.deserialize(transactionBuffer);

/// Sign the transaction
transaction.sign([keypair]);

/// Send the transaction to Solana
const signature = await connection.sendTransaction(transaction);
3

Monitor Order Status

How you monitor order completion depends on the executionMode returned from the order request:Sync trades execute atomically in a single transaction. Use standard RPC confirmation.Async trades execute across multiple transactions. Use the /order-status endpoint to poll for completion.
For synchronous trades that execute atomically, use standard Solana transaction confirmation:
if (orderData.executionMode === "sync") {
  /// Monitor transaction status using getSignatureStatuses
  let status;

  do {
    const statusResult = await connection.getSignatureStatuses([signature]);
    status = statusResult.value[0];

    if (!status) {
      console.log("Waiting for transaction confirmation...");
      await new Promise((resolve) => setTimeout(resolve, 1000));
    }
  } while (
    !status ||
    status.confirmationStatus === "processed" ||
    status.confirmationStatus === "confirmed"
  );

  /// Check if transaction succeeded or failed
  if (status.err) {
    console.error("Transaction failed:", status.err);
  } else {
    console.log(`Trade completed successfully in slot ${status.slot}`);
  }
}
For asynchronous trades that execute across multiple transactions, poll the /order-status endpoint:
if (orderData.executionMode === "async") {
  let status;
  let fills = [];

  do {
    /// Poll the order status endpoint
    const statusResponse = await fetch(
      `${API_BASE_URL}/order-status?signature=${signature}`
    );
    const statusData = await statusResponse.json();

    status = statusData.status;
    fills = statusData.fills || [];

    console.log(`Order status: ${status}`);

    /// Wait before polling again if order is still open
    if (status === "open" || status === "pendingClose") {
      await new Promise((resolve) => setTimeout(resolve, 2000));
    }
  } while (status === "open" || status === "pendingClose");

  /// Process final status
  switch (status) {
    case "closed": {
      if (fills.length > 0) {
        console.log(`Trade completed`);
      } else {
        console.log("Order was closed without any fills");
      }
      break;
    }
    case "pendingClose": {
      if (fills.length > 0) {
        console.log(`Trade ready to close`);
      } else {
        console.log("Order is ready to close without any fills");
      }
      break;
    }
    case "failed": {
      console.log("Order failed to execute");
      break;
    }
  }
}