The Trade API provides functionality to list markets, get trade quotes, and execute trades on prediction markets.
import { createPublicClient, createWalletClient, http, type Hex } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
import { mainnet } from 'viem/chains'
const publicClient = createPublicClient({
chain: mainnet,
transport: http(),
})
const TRADE_API_URL = '<https://api.foresight.now/trade>'
// 1. Get available markets
const marketsResponse = await fetch(`${TRADE_API_URL}/markets`)
const markets = await marketsResponse.json()
console.log('Available markets:', markets)
// 2. Get a quote for a trade
const marketAddress = '0x...' // Market contract address
const amount = '100000000' // 100 USDC in base units (6 decimals)
const outcome = 1 // 1 = YES, 0 = NO
const tradeType = 'Buy'
const quoteResponse = await fetch(`${TRADE_API_URL}/quote`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
market: marketAddress,
amount: amount,
outcome: outcome,
type: tradeType
})
})
const quote = await quoteResponse.json()
console.log('Trade quote:', quote)
// 3. Check and handle token approval (required for buying)
const account = '0x...' // User wallet address
const tokenAddress = '0x...' // USDC token address
const spenderAddress = '0x...' // Market maker contract address
// Check current allowance
const allowance = await publicClient.readContract({
address: tokenAddress,
abi: erc20ABI,
functionName: 'allowance',
args: [account, spenderAddress]
})
// If allowance is insufficient, approve the spender
if (allowance < BigInt(amount)) {
const approveHash = await walletClient.writeContract({
address: tokenAddress,
abi: erc20ABI,
functionName: 'approve',
args: [spenderAddress, BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff')]
})
// Wait for approval confirmation
await publicClient.waitForTransactionReceipt({ hash: approveHash })
console.log('Token approval confirmed')
}
// 4. Execute the trade
const executeResponse = await fetch(`${TRADE_API_URL}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
market: marketAddress,
amount: amount,
outcome: outcome,
type: tradeType,
account: account
})
})
const tradeData = await executeResponse.json()
console.log('Trade execution data:', tradeData)
// If the trade status is successful
if (tradeData.tx) {
// Simulate the transaction first
const callResult = await publicClient.call({
account: tradeData.tx.account,
data: tradeData.tx.data,
to: tradeData.tx.to,
value: BigInt(tradeData.tx.value),
})
console.log('Simulation result:', callResult)
// Send the actual transaction
const PRIVATE_KEY = process.env.PRIVATE_KEY as Hex
const walletClient = createWalletClient({
chain: mainnet,
transport: http(),
})
const hash = await walletClient.sendTransaction({
account: privateKeyToAccount(PRIVATE_KEY),
data: tradeData.tx.data,
to: tradeData.tx.to,
value: BigInt(tradeData.tx.value),
})
console.log('Transaction hash:', hash)
// 5. Completion step (Deprecated): No longer needed — indexer auto-processes confirmed transactions
// Wait for on-chain confirmation; the indexer will pick it up automatically
await publicClient.waitForTransactionReceipt({ hash })
// No call to /trade/complete is required
}
// 6. Get user positions and redeem winning positions
async function redeemWinningPositions(userAddress: string) {
// Get resolved positions
const positionsResponse = await fetch(`${TRADE_API_URL}/positions?walletAddress=${userAddress}&type=resolved&pg=1&ps=20`)
const positionsData = await positionsResponse.json()
// Filter for claimable positions (resolved markets where user has winning shares)
const claimablePositions = positionsData.positions.filter(position =>
position.resolutionOutcome === position.outcome && position.totalShareAmount > 0
)
console.log(`Found ${claimablePositions.length} claimable positions`)
// Redeem each claimable position
for (const position of claimablePositions) {
try {
const redeemResponse = await fetch(`${TRADE_API_URL}/redeem`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
market: position.market,
account: userAddress
})
})
const redeemData = await redeemResponse.json()
if (redeemData.tx) {
// Simulate the transaction first
const callResult = await publicClient.call({
account: redeemData.tx.account,
data: redeemData.tx.data,
to: redeemData.tx.to,
value: BigInt(redeemData.tx.value),
})
console.log('Redeem simulation successful')
// Send the actual transaction
const redeemHash = await walletClient.sendTransaction({
data: redeemData.tx.data,
to: redeemData.tx.to,
value: BigInt(redeemData.tx.value),
})
console.log('Redeem transaction hash:', redeemHash)
// Wait for confirmation and complete
await publicClient.waitForTransactionReceipt({ hash: redeemHash })
const completeRedeemResponse = await fetch(`${TRADE_API_URL}/complete`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ txHash: redeemHash })
})
const redeemCompletion = await completeRedeemResponse.json()
console.log('Redeem completion:', redeemCompletion)
}
} catch (error) {
console.error(`Error redeeming position for market ${position.market}:`, error)
}
}
}
// Usage example
// await redeemWinningPositions('0x...') // User wallet address
/trade/markets
- Get All Tradeable MarketsReturns a list of all available prediction markets.
Response:
interface MarketInfo {
address: string;
question: string;
outcome1Price: number;
outcome0Price: number;
endDate: string;
conditionDisplayName?: string;
}
Example:
const markets = await fetch(`${TRADE_API_URL}/markets`)
const data = await markets.json()
/trade/quote
- Get Trade QuoteGet pricing information for a potential trade.
Request:
interface TradeQuoteRequest {
market: string; // Market contract address
amount: string; // Amount in base units (6 decimals for USDC)
outcome: 0 | 1; // 0 = NO, 1 = YES
type: 'Buy' | 'Sell'; // Trade type
}
Response:
interface TradeQuote {
market: string;
amount: string;
outcome: 0 | 1;
type: 'Buy' | 'Sell';
estimatedReturn: string;
estimatedPricePerShare: number;
}
Example:
const quote = await fetch(`${TRADE_API_URL}/quote`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
market: "0x...",
amount: "100000000", // 100 USDC
outcome: 1, // YES
type: "Buy"
})
})
const data = await quote.json()