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.
npm install quaisimport { 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);1. Scan Open Markets
Section titled “1. Scan Open Markets”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}%)`);}2. Analyze Edge
Section titled “2. Analyze Edge”The key to profitable betting is comparing market-implied probability (from pool ratios) against your fair probability estimate.
// Market-implied probabilityconst impliedYes = Number(yesPool) / Number(yesPool + noPool);
// Your fair probability estimate (however you model it)const fairYes = 0.65; // e.g. from a pricing model
// Edgeconst 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"}`);}3. Place a Bet
Section titled “3. Place a Bet”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!");}4. Check Your Positions
Section titled “4. Check Your Positions”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`);5. Claim Winnings
Section titled “5. Claim Winnings”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`); }}6. Create a Market
Section titled “6. Create a Market”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 manuallyconst { 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-decimalconst 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();Smart Strike Selection Tips
Section titled “Smart Strike Selection Tips”- 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 Side Strategy
Section titled “Seed Side Strategy”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.