Skip to main content
During development, you can use the developer endpoints without an API key. For production use, request an API key for higher rate limits.
1

Set up

Imports, env config, and the wallet/connection used across every step.
import "dotenv/config";

import { TOKEN_2022_PROGRAM_ID } from "@solana/spl-token";
import { Connection, PublicKey } from "@solana/web3.js";

const DFLOW_METADATA_API_URL = process.env.DFLOW_METADATA_API_URL ?? "https://dev-prediction-markets-api.dflow.net";
const DFLOW_API_KEY = process.env.DFLOW_API_KEY; // optional; not needed for dev endpoints
const SOLANA_RPC_URL = process.env.SOLANA_RPC_URL ?? "https://api.mainnet-beta.solana.com";

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

const connection = new Connection(SOLANA_RPC_URL);

const userWalletAddress = "USER_WALLET_ADDRESS_HERE";
if (userWalletAddress === "USER_WALLET_ADDRESS_HERE") {
  throw new Error("Replace USER_WALLET_ADDRESS_HERE with a real Solana wallet address.");
}
const userWallet = new PublicKey(userWalletAddress);
2

Fetch Wallet Token Accounts

Fetch SPL token accounts for the wallet and keep only non-zero balances. Outcome tokens are Token-2022 mints.
const tokenAccounts = await connection.getParsedTokenAccountsByOwner(
  userWallet,
  { programId: TOKEN_2022_PROGRAM_ID }
);

const userTokens = tokenAccounts.value.map(({ account }) => {
  const info = account.data.parsed.info;

  return {
    mint: info.mint,
    rawBalance: info.tokenAmount.amount,
    balance: info.tokenAmount.uiAmount,
    decimals: info.tokenAmount.decimals,
  };
});

const nonZeroBalances = userTokens.filter((token) => token.balance > 0);
3

Filter for Outcome Mints

Filter the wallet mints down to prediction market outcome tokens using the Metadata API.
const allMintAddresses = nonZeroBalances.map((token) => token.mint);

const response = await fetch(
  `${DFLOW_METADATA_API_URL}/api/v1/filter_outcome_mints`,
  {
    method: "POST",
    headers: { ...headers, "Content-Type": "application/json" },
    body: JSON.stringify({ addresses: allMintAddresses }),
  }
);

if (!response.ok) {
  throw new Error("Failed to filter outcome mints");
}

const data = await response.json();
const outcomeMints = data.outcomeMints ?? [];
const outcomeTokens = nonZeroBalances.filter((token) =>
  outcomeMints.includes(token.mint)
);
4

Fetch Market Details in Batch

Pull market metadata for those outcome mints so you can label YES/NO and display event and market context.
const marketsResponse = await fetch(
  `${DFLOW_METADATA_API_URL}/api/v1/markets/batch`,
  {
    method: "POST",
    headers: { ...headers, "Content-Type": "application/json" },
    body: JSON.stringify({ mints: outcomeMints }),
  }
);

if (!marketsResponse.ok) {
  throw new Error("Failed to fetch markets batch");
}

const marketsData = await marketsResponse.json();
const markets = marketsData.markets ?? [];

const marketsByMint = new Map<string, any>();
markets.forEach((market: any) => {
  Object.values(market.accounts ?? {}).forEach((account: any) => {
    if (account.yesMint) marketsByMint.set(account.yesMint, market);
    if (account.noMint) marketsByMint.set(account.noMint, market);
  });
});
5

Build Position Rows

Map each outcome token to a market, determine YES/NO, and shape the data for your UI.
const positions = outcomeTokens.map((token) => {
  const market = marketsByMint.get(token.mint);
  if (!market) {
    return {
      mint: token.mint,
      balance: token.balance,
      position: "UNKNOWN",
      market: null,
    };
  }

  const accounts = Object.values(market.accounts ?? {});
  const isYesToken = accounts.some((account: any) => account.yesMint === token.mint);
  const isNoToken = accounts.some((account: any) => account.noMint === token.mint);

  return {
    mint: token.mint,
    balance: token.balance,
    decimals: token.decimals,
    position: isYesToken ? "YES" : isNoToken ? "NO" : "UNKNOWN",
    market,
  };
});

Find Markets

Discover markets by category, tag, status, or series.

Bulk Fetch Markets

Hydrate multiple markets and outcome mints in one call.

Buy Outcome Tokens

Open a prediction market position from any input token.

Reclaim Rent

Close empty outcome token accounts and reclaim SOL rent.

API Routes