Skip to content

Bot Integration

This guide walks through building a complete Quasdaq trading bot in JavaScript. By the end you’ll be able to scan for opportunities, place bets, and auto-claim winnings.

Terminal window
npm install quais
import {
JsonRpcProvider, Wallet, Contract,
parseQuai, formatQuai,
keccak256, toUtf8Bytes, getAddress
} from "quais";
const RPC = "https://rpc.quai.network";
const FACTORY = "0x0027Adb36E28fA1C037286Da59BB348fA2B63Bd6";
const provider = new JsonRpcProvider(RPC);
const wallet = new Wallet(process.env.PRIVATE_KEY, provider);
const factoryABI = ["function getMarkets() view returns (address[])"];
const factory = new Contract(FACTORY, factoryABI, provider);
const addresses = await factory.getMarkets();
const marketABI = [
"function question() view returns (string)",
"function status() view returns (uint8)",
"function yesPool() view returns (uint256)",
"function noPool() view returns (uint256)",
"function isBettingOpen() view returns (bool)",
"function bettingCloseTime() view returns (uint256)",
"function resolutionTime() view returns (uint256)",
"function strikePrice() view returns (int256)",
"function estimatePayout(bool,uint256) view returns (uint256)"
];
for (const addr of addresses) {
const m = new Contract(addr, marketABI, provider);
const [question, status, yesPool, noPool, open] = await Promise.all([
m.question(), m.status(), m.yesPool(), m.noPool(), m.isBettingOpen()
]);
if (status !== 0n || !open) continue; // skip resolved/closed
const total = yesPool + noPool;
const yesOdds = total > 0n ? Number(yesPool * 100n / total) : 50;
console.log(`${addr} | ${question}`);
console.log(` Yes: ${formatQuai(yesPool)} (${yesOdds}%) | No: ${formatQuai(noPool)} (${100-yesOdds}%)`);
}

The key to profitable betting is comparing market-implied probability (from pool ratios) against your fair probability estimate.

// Market-implied probability
const impliedYes = Number(yesPool) / Number(yesPool + noPool);
// Your fair probability estimate (however you model it)
const fairYes = 0.65; // e.g. from a pricing model
// Edge
const edge = fairYes - impliedYes;
// Positive edge on Yes = market underprices Yes
// Negative edge = market underprices No
if (Math.abs(edge) > 0.05) {
console.log(`Edge: ${(edge * 100).toFixed(1)}% on ${edge > 0 ? "YES" : "NO"}`);
}
const market = new Contract(marketAddress, [
"function betYes() payable",
"function betNo() payable",
"function isBettingOpen() view returns (bool)"
], wallet);
if (await market.isBettingOpen()) {
const tx = await market.betYes({
value: parseQuai("10"),
gasLimit: 200000n
});
await tx.wait();
console.log("Bet placed!");
}
const market = new Contract(marketAddress, [
"function getUserBets(address) view returns (uint256, uint256)",
"function calculatePayout(address) view returns (uint256)",
"function status() view returns (uint8)"
], provider);
const [yesBet, noBet] = await market.getUserBets(wallet.address);
const status = await market.status();
const payout = status === 1n ? await market.calculatePayout(wallet.address) : 0n;
console.log(`Yes: ${formatQuai(yesBet)} | No: ${formatQuai(noBet)}`);
console.log(`Status: ${["Active","Resolved","Cancelled"][Number(status)]}`);
if (payout > 0n) console.log(`Claimable: ${formatQuai(payout)} QUAI`);
const market = new Contract(marketAddress, [
"function claim()",
"function calculatePayout(address) view returns (uint256)",
"function status() view returns (uint8)",
"function hasClaimed(address) view returns (bool)"
], wallet);
const status = await market.status();
const claimed = await market.hasClaimed(wallet.address);
if (status === 1n && !claimed) {
const payout = await market.calculatePayout(wallet.address);
if (payout > 0n) {
await (await market.claim({ gasLimit: 200000n })).wait();
console.log(`Claimed ${formatQuai(payout)} QUAI`);
}
}

Creating a market requires a seed bet (minimum 100 QUAI). You earn a 1% creator fee on the losing pool at resolution regardless of which side wins.

const factory = new Contract(FACTORY, [
"function createMarketAndBet(string,bytes32,int256,uint256,uint256,bool) payable returns (address)"
], wallet);
// ALWAYS get feedIdHash from the API — never construct manually
const { feeds } = await fetch("https://quasdaq.com/api/feeds?storkOnly=true").then(r => r.json());
const btc = feeds.find(f => f.symbol === "BTC");
const strikePrice = 100000n * 10n**18n; // $100,000 in 18-decimal
const now = Math.floor(Date.now() / 1000);
const tx = await factory.createMarketAndBet(
"Will BTC be above $100,000 in 24 hours?",
btc.feedIdHash,
strikePrice,
now + 86400, // resolution: 24h
now + 82800, // betting closes: 23h (1h buffer)
true, // seed bet on Yes
{ value: parseQuai("100"), gasLimit: 5000000n }
);
await tx.wait();
  • Target 50/50 probability — markets with balanced odds attract the most volume
  • Use round numbers — traders gravitate to round strikes ($100K, $3,500, $200)
  • SPY: check market hours — S&P trades 9:30 AM - 4:00 PM ET weekdays only. Don’t set resolution times outside trading hours.

Seed against the current trend to maximize creator income:

  • Price trending up? Seed No. Trend followers will pile into Yes, growing the pool you earn fees on.
  • Price trending down? Seed Yes. Fearful sellers buy No, same effect.

You earn 1% of the losing pool either way — a bigger pool means a bigger fee.