Skip to main content

Documentation Index

Fetch the complete documentation index at: https://pond.dflow.net/llms.txt

Use this file to discover all available pages before exploring further.

During development, you can use the developer endpoints without an API key. For production use, you’ll need an API key to avoid rate limits.
This recipe swaps USDC for a single prediction-market outcome token (YES or NO) through the standard /order endpoint. Prediction-market trades on DFlow are always asynchronous: the user signs and submits one open transaction, the server fills the order across one or more follow-on transactions, and the app polls /order-status until the order reaches a terminal state.
This recipe assumes familiarity with Solana’s transaction and network connection logic. If unfamiliar, see the Solana Cookbook.
1

Set Up

Imports, constants, and the wallet/connection used across every step. Replace OUTCOME_TOKEN_MINT with a real YES or NO mint; use the Discover Markets recipe to find one.
import "dotenv/config";
import {
  Connection,
  Keypair,
  VersionedTransaction,
} from "@solana/web3.js";
import bs58 from "bs58";

const TRADE_API = process.env.DFLOW_TRADE_API_URL!;
const API_KEY = process.env.DFLOW_API_KEY; // Not needed with dev endpoints
const USDC_MINT = process.env.DFLOW_SETTLEMENT_MINT!;
const OUTCOME_TOKEN_MINT = "REPLACE_ME"; // YES or NO mint from /build/recipes/prediction-markets/discover-markets
const BUY_AMOUNT = 1_000_000; // $1 USDC (6 decimals)
const SLIPPAGE_BPS = 50; // 0.5%

const connection = new Connection(process.env.SOLANA_RPC_URL!, "confirmed");
const keypair = Keypair.fromSecretKey(
  bs58.decode(process.env.SOLANA_PRIVATE_KEY!)
);

const headers: HeadersInit = {};
if (API_KEY) headers["x-api-key"] = API_KEY;
2

Request an Order

GET /order returns a quote and an unsigned base64 transaction in one call.
const params = new URLSearchParams({
  inputMint: USDC_MINT,
  outputMint: OUTCOME_TOKEN_MINT,
  amount: BUY_AMOUNT.toString(),
  slippageBps: SLIPPAGE_BPS.toString(),
  userPublicKey: keypair.publicKey.toBase58(),
});

const orderResponse = await fetch(`${TRADE_API}/order?${params}`, {
  headers,
}).then((r) => r.json());
3

Sign and Submit

Deserialize the returned transaction, sign with the keypair, and submit it. This is the open transaction; the server will fill the order across follow-on transactions tracked by signature.
const tx = VersionedTransaction.deserialize(
  Buffer.from(orderResponse.transaction, "base64")
);
tx.sign([keypair]);

const signature = await connection.sendTransaction(tx);
console.log(`Open transaction sent: ${signature}`);
4

Monitor Order Status

Poll GET /order-status using the open transaction’s signature until the order reaches a terminal state (closed or failed).
const statusParams = new URLSearchParams({
  signature,
  lastValidBlockHeight: orderResponse.lastValidBlockHeight.toString(),
});

let status: string | undefined;
let fills: any[] = [];

do {
  const statusResponse = await fetch(
    `${TRADE_API}/order-status?${statusParams}`,
    { headers }
  ).then((r) => r.json());

  status = statusResponse.status;
  fills = statusResponse.fills ?? [];
  console.log(`Order status: ${status}`, statusResponse);

  if (status === "pending" || status === "open" || status === "pendingClose") {
    await new Promise((resolve) => setTimeout(resolve, 2000));
  }
} while (
  status === "pending" ||
  status === "open" ||
  status === "pendingClose"
);

const explorerUrl = (sig: string) => `https://orbmarkets.io/tx/${sig}`;
const openTxUrl = explorerUrl(signature);

switch (status) {
  case "closed":
    if (fills.length > 0) {
      console.log(`Success: trade filled with ${fills.length} fill(s)`);
      for (const fill of fills) {
        console.log(`  Fill: ${explorerUrl(fill.signature)}`);
      }
    } else {
      console.log(`Failed: order closed without any fills`);
      console.log(`  Open tx: ${openTxUrl}`);
    }
    break;
  case "failed":
    console.log(`Failed: order failed to execute`);
    console.log(`  Open tx: ${openTxUrl}`);
    break;
  case "expired":
    console.log(`Failed: order expired before fill`);
    console.log(`  Open tx: ${openTxUrl}`);
    break;
  default:
    console.log(`Failed: order ended in unexpected status: ${status}`);
    console.log(`  Open tx: ${openTxUrl}`);
}

API Routes

Cookbook Repository

This recipe, along with many more, is available in the DFlow Cookbook Repo. You can clone it and start coding immediately.

Need Help?

https://mintlify.s3.us-west-1.amazonaws.com/dflow/images/meteor-icons_discord.svg

Join Our Discord

Connect with other developers, get help, and stay updated on the latest DFlow developments.
https://mintlify.s3.us-west-1.amazonaws.com/dflow/images/meteor-icons_telegram.svg

Dev Notifications

Join the DFlow Dev Notifications Telegram group to stay in the loop on new features and other announcements.