Polybased SDK is a complete TypeScript toolkit for Polymarket — fetch real-time data, stream live orderbooks, and execute trades programmatically.
Build automated trading bots, market-making strategies, dashboards, and AI agents powered by on-chain prediction markets.
| Category | Features |
|---|---|
| 📊 Market Data | Fetch markets, search, real-time orderbooks, historical prices |
| ⚡ WebSocket Streaming | Live orderbooks, prices, trades with auto-reconnect |
| 🔄 Multi-Market | Monitor multiple markets with ONE efficient connection |
| 💰 Trading | All order types: GTC, GTD, FOK, FAK + market orders |
| 📈 Price History | Historical prices with intervals: max, 1w, 1d, 6h, 1h |
| 🏆 Rewards | Order scoring, earnings tracking, liquidity rewards |
| 🔬 AI Research | AI-powered insights via FactsAI |
| 🔄 Gasless Trades | Relayer support for meta-transactions |
| 🏗️ Builder Support | Order attribution for analytics & rewards |
| 🔒 Type-Safe | Full TypeScript with comprehensive types |
| 🧠 Smart Money | Track top traders, identify smart money activity |
| 📊 Arbitrage | Detect AND auto-execute arbitrage opportunities |
| 📈 Market Signals | Volume spikes, momentum, whale activity detection |
| 🚦 Rate Limiting | Token bucket algorithm prevents API bans |
| 📋 Copy Trading | Follow and copy smart money trades |
| ⛓️ On-Chain | Balance queries, approvals, CTF split/merge/redeem |
| 🌉 Bridge API | Cross-chain deposits (EVM, Solana, Bitcoin) |
| 📊 Subgraph | 5 Goldsky subgraphs for on-chain data queries |
- ✅ Bridge API Client — Cross-chain deposits from EVM, Solana, Bitcoin
- ✅ Subgraph Client — Query 5 Goldsky subgraphs (positions, orderbook, activity, OI, PnL)
- ✅ CTF Operations — Split, Merge, Redeem, RedeemNegRisk on-chain
- ✅ Gamma API — Tags, comments, public-search, series, profiles, sports
- ✅ Data API — Closed positions, holders, open interest, volume, builder leaderboard
- ✅ New Types — 11 new TypeScript types for WebSocket events, CTF, Bridge, Subgraph
- ✅ Arbitrage Executor — Auto-execute arbitrage opportunities
- ✅ Copy Trading — Follow and copy smart money trades
- ✅ On-Chain Service — Balance queries, approvals, trading readiness
- ✅ Event System — Subscribe to executor/copier events
- ✅ Smart Money Analytics — Track top traders, identify smart money
- ✅ Arbitrage Detection — Find long/short arbitrage opportunities
- ✅ Market Signals — Volume spikes, momentum, whale activity
- ✅ Rate Limiting — Token bucket algorithm prevents API bans
- ✅ Unified Caching — TTL-based caching with LRU eviction
- ✅ Enhanced Logging — Structured logging with levels
- ✅ Improved Errors — Context-rich errors with hints
- ✅ Authenticated WebSocket — Real-time user data (orders, trades)
- ✅ Unit Tests — Comprehensive test coverage with Vitest
v0.7.0: All Order Types, Market Orders, Gamma API, Data API, K-Lines, Technical Indicators, 100% API Coverage
This SDK is a complete trading solution — not just for data. It includes historical data, AI-powered research, live trading, rewards tracking, and gasless transactions!
Polybased SDK uses a 3-layer architecture for maximum flexibility:
┌──────────────────────────────────────────────────────────────────────┐
│ PolybasedSDK │
│ (Main Entry Point) │
├──────────────────────────────────────────────────────────────────────┤
│ LAYER 3: HIGH-LEVEL SERVICES (Recommended) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐│
│ │ MarketService│ │TradingService│ │ StreamService│ │ResearchService││
│ │ • getMarkets │ │ • placeOrder │ │ • onOrderbook│ │ • query() ││
│ │ • search() │ │ • cancelOrder│ │ • onPrice() │ │ • healthCheck││
│ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘│
├──────────────────────────────────────────────────────────────────────┤
│ LAYER 2: API CLIENTS (Advanced users) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐│
│ │ ClobClient │ │ GammaClient │ │WebSocketClient│ │ RelayClient ││
│ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘│
├──────────────────────────────────────────────────────────────────────┤
│ LAYER 1: CORE (Logger, Retry, Cache, Types, Errors) │
└──────────────────────────────────────────────────────────────────────┘
📖 See ARCHITECTURE.md for detailed design documentation.
| Version | Target | Key Features | Status |
|---|---|---|---|
| v0.7.0 | Q1 2025 | Full API coverage, Gamma, Data, K-Lines | ✅ Released |
| v0.8.0 | Q1 2025 | Smart Money, Arbitrage, Signals, Testing | ✅ Released |
| v0.8.1 | Q1 2025 | Arb Executor, Copy Trading, On-Chain | ✅ Released |
| v0.9.0 | Q1 2025 | CTF Operations, Bridge API, Subgraph, Full API Coverage | ✅ Released |
| v1.0.0 | Q3 2025 | Strategy Framework, Full Stability | Planned |
📖 See SDK_ROADMAP.md for detailed feature plans.
Install via npm:
npm install @polybased/sdkOr via yarn:
yarn add @polybased/sdkFor WebSocket support, you may need to install ws:
npm install ws
⚠️ Node.js 20.10+ is required for v0.7.0+
Node.js 18+ includes WebSocket support by default - no additional packages needed!
New to this? Check out GUIDE_FOR_NEWBIES.md for a complete step-by-step tutorial!
import { PolybasedSDK } from "@polybased/sdk";
const sdk = new PolybasedSDK();
// Fetch all active markets
const markets = await sdk.getMarkets();
console.log(`Found ${markets.length} markets`);
// Get a specific market
const market = await sdk.getMarket("market-id-here");
console.log(market.question);
console.log(market.prices);✨ NEW in v0.5.0: Enhanced WebSocket support with auto-reconnection, price updates, trade events, and multi-market subscriptions!
import { PolybasedSDK } from "@polybased/sdk";
// In Node.js, enable WebSocket support (only if not already available)
if (typeof window === "undefined" && typeof globalThis.WebSocket === "undefined") {
globalThis.WebSocket = (await import("ws")).default as any;
}
const sdk = new PolybasedSDK({ debug: true });
// 1. Subscribe to orderbook updates
const unsubOrderbook = sdk.onOrderbook(
"market-id-here",
(update) => {
if (update.type === "snapshot") {
const { bids, asks } = update.data;
console.log("Best bid:", bids[0]?.price);
console.log("Best ask:", asks[0]?.price);
}
},
{
onOpen: () => console.log("WebSocket connected"),
onClose: () => console.log("WebSocket disconnected"),
onError: (err) => console.error("WebSocket error:", err)
}
);
// 2. ✨ NEW: Subscribe to real-time price updates
const unsubPrice = sdk.onPriceUpdate(
"market-id-here",
(update) => {
console.log(`Price: $${update.price}`);
console.log(`24h Volume: $${update.volume24h}`);
}
);
// 3. ✨ NEW: Subscribe to real-time trade events
const unsubTrade = sdk.onTrade(
"market-id-here",
(trade) => {
console.log(`${trade.side}: ${trade.size} shares @ $${trade.price}`);
}
);
// 4. ✨ NEW: Monitor multiple markets efficiently (ONE connection!)
const unsubMulti = sdk.onMultipleMarkets(
["market-1", "market-2", "market-3"],
(update) => {
console.log(`${update.marketId}: ${update.type}`, update.data);
},
{
onOpen: () => console.log("Multi-market connected"),
onReconnected: () => console.log("Reconnected!")
}
);
// 5. ✨ NEW: Dynamic multi-market manager
const manager = sdk.createMultiMarketManager(
(update) => console.log(`Update from ${update.marketId}`),
{ onOpen: () => console.log("Manager connected") }
);
manager.start();
manager.subscribe(["market-1", "market-2"]); // Add markets
manager.subscribe(["market-3"]); // Add more
manager.unsubscribe(["market-1"]); // Remove markets
manager.stop(); // Cleanup
// Later: unsubscribe from any stream
// unsubOrderbook();
// unsubPrice();
// unsubTrade();
// unsubMulti();🚀 WebSocket Features (v0.5.0):
- ✅ Auto-reconnection with exponential backoff
- ✅ Heartbeat/ping to keep connections alive
- ✅ Multiple data types (orderbook, prices, trades)
- ✅ Multi-market subscriptions (90% more efficient!)
- ✅ Dynamic subscription management
- ✅ Production-ready reliability
✨ NEW in v0.7.0: Price history now supports official CLOB intervals!
Price History Intervals:
| Interval | Description |
|---|---|
max |
All available historical data |
1w |
One week of data |
1d |
One day of data |
6h |
Six hours of data |
1h |
One hour of data |
import { PolybasedSDK } from "@polybased/sdk";
const sdk = new PolybasedSDK();
// ✨ NEW: Get price history with proper intervals
const hourlyPrices = await sdk.history.getPriceHistory({
market: "condition-id-here",
interval: "1h"
});
// Get daily prices for last 30 days
const dailyPrices = await sdk.history.getPriceHistory({
market: "condition-id",
interval: "1d",
startTs: Math.floor(Date.now() / 1000) - 30 * 24 * 3600,
endTs: Math.floor(Date.now() / 1000)
});
// Get all available data
const allPrices = await sdk.history.getPriceHistory({
market: "condition-id",
interval: "max"
});
// Each price point: { t: timestamp, p: price }
hourlyPrices.forEach(point => {
console.log(`${new Date(point.t * 1000).toISOString()}: $${point.p}`);
});
// ✨ Search for markets easily
const btcMarkets = await sdk.searchMarkets("bitcoin");
console.log(`Found ${btcMarkets.length} Bitcoin markets`);
// ✨ Find a specific market
const market = await sdk.findMarket("trump");
console.log(`Market: ${market.question}`);
// ✨ Use market slug with getPrices (auto-resolves!)
const prices = await sdk.history.getPrices("market-slug", {
interval: "1d"
});
// Or use condition_id directly
const pricesById = await sdk.history.getPrices(market.raw.condition_id);
// Get historical volumes
const volumes = await sdk.history.getVolumes("market-slug");
// Get market snapshot from specific time
const snapshot = await sdk.history.getSnapshot(
market.raw.condition_id,
Date.now() - 30 * 24 * 60 * 60 * 1000 // 30 days ago
);
console.log(`Price 30 days ago: $${snapshot.price}`);
console.log(`Volume: $${snapshot.volume}`);
// Backtest a strategy
prices.forEach(point => {
if (point.price < 0.40) console.log("BUY signal!");
if (point.price > 0.60) console.log("SELL signal!");
});💡 Pro Tips:
- Use slugs from Polymarket URLs for convenience
- Use condition_ids when you already have them for instant lookup (no resolution needed)
- Use searchMarkets() to discover markets by keyword
- First slug resolution takes ~1-2 seconds (fetches all markets), then instant from cache
📚 For Non-Developers: How Slug Resolution Works
The Problem:
Polymarket's API only understands long "condition IDs" like 0x5eed579ff676... (66 characters). It doesn't accept friendly slugs like "bitcoin-100k" directly. If we try to send a slug to the API, it returns a "404 Not Found" error.
Why We Built Internal Resolution: Instead of making you find the condition_id manually (which requires browsing through 1000+ markets), our SDK now does it for you automatically.
How It Works (Simple Explanation):
- You type:
getPrices("bitcoin-100k") - SDK thinks: "That's not a condition_id, it's a slug!"
- SDK fetches: All markets from Polymarket (one-time)
- SDK searches: Through markets to find
market_slug: "bitcoin-100k" - SDK finds: The condition_id for that market
- SDK saves: This mapping in memory (so next time is instant)
- SDK uses: The condition_id to call the API
- You get: Historical prices! ✅
Why This Is Better:
- Before: You had to search 1000+ markets manually
- After: Just use the slug and it works!
Performance:
- First time using a new slug: ~1-2 seconds (fetches all markets)
- Every time after: Instant! (uses cached mapping)
- Using condition_id directly: Always instant (no lookup needed)
Technical Note for Developers:
The CLOB API endpoint https://clob.polymarket.com/markets/{slug} returns 404. Only https://clob.polymarket.com/markets/{condition_id} works. We resolve slugs by fetching /markets, finding the match in the list, and extracting the condition_id field.
import { PolybasedSDK } from "@polybased/sdk";
const sdk = new PolybasedSDK();
// Get top 10 trending markets by 24h volume
const trending = await sdk.gamma.getTrendingMarkets(10);
trending.forEach(market => {
console.log(`${market.question}`);
console.log(` Volume 24h: $${market.volume24hr?.toLocaleString()}`);
console.log(` Best Bid: ${market.bestBid}`);
});
// Get trending events
const events = await sdk.gamma.getTrendingEvents(5);
// Search markets
const btcMarkets = await sdk.gamma.searchMarkets("bitcoin");
// Get markets by category
const politics = await sdk.gamma.getMarketsByCategory("Politics", 20);
// Get specific market by slug
const market = await sdk.gamma.getMarketBySlug("trump-2024");// Get wallet positions
const positions = await sdk.data.getPositions("0xYourWalletAddress");
positions.forEach(pos => {
console.log(`${pos.outcome}: ${pos.size} shares`);
console.log(` Entry: $${pos.avgPrice} → Current: $${pos.currentPrice}`);
console.log(` PnL: $${pos.pnl.toFixed(2)} (${pos.pnlPercent.toFixed(1)}%)`);
});
// Get portfolio summary
const portfolio = await sdk.data.getPortfolioValue("0xYourWalletAddress");
console.log(`Total Value: $${portfolio.totalValue.toFixed(2)}`);
console.log(`Total PnL: $${portfolio.totalPnl.toFixed(2)}`);
console.log(`Positions: ${portfolio.positionCount}`);
// Get trading activity
const activity = await sdk.data.getActivity("0xYourWalletAddress");
// Get market stats
const stats = await sdk.data.getMarketStats(conditionId);
console.log(`24h Volume: $${stats.volume24h.toLocaleString()}`);// Get hourly candles
const candles = await sdk.klines.getKLines(tokenId, "1h");
candles.forEach(candle => {
const date = new Date(candle.timestamp).toISOString();
console.log(`${date}: O:${candle.open} H:${candle.high} L:${candle.low} C:${candle.close}`);
});
// Available intervals: 1m, 5m, 15m, 30m, 1h, 4h, 1d, 1w
// Get candles with time range
const dailyCandles = await sdk.klines.getKLines(tokenId, "1d", {
startTime: Date.now() - 30 * 24 * 60 * 60 * 1000, // 30 days ago
endTime: Date.now(),
limit: 30
});
// Get candles for both YES and NO tokens
const { yes, no } = await sdk.klines.getDualKLines(yesTokenId, noTokenId, "1h");const candles = await sdk.klines.getKLines(tokenId, "1h", { limit: 100 });
// Simple Moving Average (20-period)
const sma20 = sdk.klines.calculateSMA(candles, 20);
// Exponential Moving Average (12-period)
const ema12 = sdk.klines.calculateEMA(candles, 12);
// Relative Strength Index (14-period)
const rsi = sdk.klines.calculateRSI(candles, 14);
console.log(`Current RSI: ${rsi[rsi.length - 1].toFixed(2)}`);
if (rsi[rsi.length - 1] < 30) console.log("Oversold!");
if (rsi[rsi.length - 1] > 70) console.log("Overbought!");
// Bollinger Bands (20-period, 2 std dev)
const bands = sdk.klines.calculateBollingerBands(candles, 20, 2);
const latest = bands[bands.length - 1];
console.log(`Upper: ${latest.upper.toFixed(3)}`);
console.log(`Middle: ${latest.middle.toFixed(3)}`);
console.log(`Lower: ${latest.lower.toFixed(3)}`);Track top traders, detect arbitrage opportunities, and get automated market signals.
import { PolybasedSDK } from "@polybased/sdk";
const sdk = new PolybasedSDK();
// Get top 50 traders by performance
const topTraders = await sdk.analytics.smartMoney.getTopTraders(50);
topTraders.forEach(trader => {
console.log(`${trader.address.slice(0, 10)}...`);
console.log(` PnL: $${trader.pnl.toFixed(2)}`);
console.log(` Win Rate: ${(trader.winRate * 100).toFixed(1)}%`);
console.log(` Smart Score: ${trader.smartMoneyScore}`);
console.log(` Is Smart Money: ${trader.isSmartMoney ? '✅' : '❌'}`);
});
// Check if an address is "smart money"
const isSmartMoney = await sdk.analytics.smartMoney.isSmartMoney("0x...");
// Get smart money activity for a specific market
const activity = await sdk.analytics.smartMoney.getSmartMoneyActivity(conditionId);
console.log(`Buy/Sell Ratio: ${activity.buyRatio.toFixed(2)}`);
console.log(`Sentiment: ${activity.sentiment.toFixed(2)}`); // -1 to 1
// Detect smart money signals across markets
const signals = await sdk.analytics.smartMoney.detectSignals(60); // min 60% strength
signals.forEach(signal => {
console.log(`${signal.type}: ${signal.description}`);
});// Detect arbitrage for a specific market
const arb = await sdk.analytics.arbitrage.detectArbitrage(conditionId);
if (arb) {
console.log(`Type: ${arb.type}`); // LONG or SHORT
console.log(`YES: $${arb.yesPrice.toFixed(3)}`);
console.log(`NO: $${arb.noPrice.toFixed(3)}`);
console.log(`Combined: $${arb.combinedPrice.toFixed(3)}`);
console.log(`Profit: ${(arb.profitPercent * 100).toFixed(2)}%`);
console.log(`Profitable After Fees: ${arb.isProfitable}`);
console.log(`Action: ${arb.action}`);
}
// Scan all markets for arbitrage opportunities
const result = await sdk.analytics.arbitrage.scanMarkets({
minProfit: 0.005, // 0.5% minimum profit
maxMarkets: 100,
profitableOnly: true,
});
console.log(`Scanned: ${result.totalScanned} markets`);
console.log(`Found: ${result.opportunitiesFound} opportunities`);
console.log(`Best: ${result.bestOpportunity?.profitPercent.toFixed(2)}%`);
// Calculate profit for a specific trade size
const profit = sdk.analytics.arbitrage.calculateProfit(arb, 1000); // $1000
console.log(`Gross Profit: $${profit.grossProfit.toFixed(2)}`);
console.log(`Fees: $${profit.fees.toFixed(2)}`);
console.log(`Net Profit: $${profit.netProfit.toFixed(2)}`);// Detect signals for a specific market
const signals = await sdk.analytics.signals.detectSignals(conditionId);
signals.forEach(signal => {
console.log(`${signal.type} (${signal.confidence}% confidence)`);
console.log(` ${signal.description}`);
console.log(` Action: ${signal.action}`);
});
// Scan all markets for signals
const result = await sdk.analytics.signals.scanForSignals({
minConfidence: 60,
maxMarkets: 50,
});
console.log(`Total signals: ${result.totalSignals}`);
console.log(`Top signals:`, result.topSignals);
// Get buy/sell signals specifically
const buySignals = await sdk.analytics.signals.getBuySignals(10);
const sellSignals = await sdk.analytics.signals.getSellSignals(10);
// Subscribe to real-time signals
const unsubscribe = sdk.analytics.signals.subscribe((signal) => {
console.log(`[${signal.type}] ${signal.description}`);
});
// Start automatic signal scanning
sdk.analytics.signals.startAutoScan(60000); // Every minute
// Stop scanning
sdk.analytics.signals.stopAutoScan();
// Unsubscribe
unsubscribe();Signal Types:
VOLUME_SPIKE- Unusual volume increasePRICE_MOMENTUM_UP/DOWN- Strong price movementWHALE_BUY/SELL- Large single trades (>$10k)SMART_MONEY_BUY/SELL- Smart money activityBREAKOUT/BREAKDOWN- Price breaking key levelsUNUSUAL_ACTIVITY- High frequency + volumeLIQUIDITY_SURGE- High liquidity available
// Get overall market conditions
const summary = await sdk.analytics.getMarketSummary();
console.log(`Smart Money Traders: ${summary.topTraders}`);
console.log(`Arbitrage Opportunities: ${summary.arbitrageOpportunities}`);
console.log(`Active Signals: ${summary.activeSignals}`);
console.log(`Market Sentiment: ${summary.marketSentiment}`); // BULLISH, BEARISH, NEUTRALAuto-execute arbitrage opportunities with real-time monitoring.
import { PolybasedSDK } from "@polybased/sdk";
const sdk = new PolybasedSDK({
trading: {
chainId: 137,
backend: { privateKey: process.env.PRIVATE_KEY },
},
});
// Create executor with auto-execute enabled
const executor = sdk.arbitrage.createExecutor({
profitThreshold: 0.005, // 0.5% minimum profit
autoExecute: true, // Auto-execute opportunities
maxTradeSize: 1000, // Maximum $1000 per trade
minTradeSize: 10, // Minimum $10 per trade
maxSlippage: 0.02, // 2% max slippage
orderType: 'FOK', // Fill-or-Kill orders
scanInterval: 5000, // Scan every 5 seconds
dryRun: true, // Start in dry-run mode
});
// Listen for opportunities
executor.on('opportunity', (opp) => {
console.log(`${opp.type} ARB: ${(opp.profitPercent * 100).toFixed(2)}% profit`);
console.log(`Action: ${opp.action}`);
});
// Listen for executions
executor.on('execution', (result) => {
console.log(`Execution ${result.status}`);
console.log(`Net Profit: $${result.netProfit.toFixed(2)}`);
});
// Start monitoring a specific market
await executor.start('condition-id-here');
// Or find and start the best opportunity
const best = await executor.findAndStart(0.005);
if (best) {
console.log(`Monitoring: ${best.market.question}`);
}
// Get statistics
const stats = executor.getStats();
console.log(`Opportunities: ${stats.opportunitiesDetected}`);
console.log(`Executions: ${stats.executionsSuccessful}/${stats.executionsAttempted}`);
console.log(`Total Profit: $${stats.totalNetProfit.toFixed(2)}`);
// Stop monitoring
executor.stop();| Option | Type | Default | Description |
|---|---|---|---|
profitThreshold |
number | 0.005 | Minimum profit (0.005 = 0.5%) |
autoExecute |
boolean | false | Auto-execute opportunities |
minTradeSize |
number | 10 | Minimum trade size (USD) |
maxTradeSize |
number | 1000 | Maximum trade size (USD) |
maxSlippage |
number | 0.02 | Maximum slippage (0.02 = 2%) |
orderType |
'FOK' | 'FAK' | 'FOK' | Order type for execution |
scanInterval |
number | 5000 | Scan interval (ms) |
dryRun |
boolean | true | Dry run mode (no real trades) |
Automatically copy trades from smart money wallets in real-time.
import { PolybasedSDK } from "@polybased/sdk";
const sdk = new PolybasedSDK({
trading: {
chainId: 137,
backend: { privateKey: process.env.PRIVATE_KEY },
},
});
// Create copy trading service
const copier = sdk.copyTrading.create({
topN: 50, // Follow top 50 traders
sizeScale: 0.1, // Copy 10% of their trade size
maxSizePerTrade: 100, // Max $100 per copy trade
minSizePerTrade: 5, // Min $5 per copy trade
minLeaderTradeSize: 10, // Only copy trades > $10
minSmartScore: 50, // Only follow high-score traders
maxSlippage: 0.03, // 3% max slippage
orderType: 'FOK', // Fill-or-Kill orders
dryRun: true, // Start in dry-run mode
});
// Listen for copied trades
copier.on('trade', (event, result) => {
console.log(`Leader: ${event.leaderTrade.address.slice(0, 10)}...`);
console.log(`Side: ${event.leaderTrade.side}`);
console.log(`Copy Size: $${event.copySize.toFixed(2)}`);
console.log(`Result: ${result.success ? '✅' : '❌'}`);
});
// Listen for leader trades (before copy decision)
copier.on('leader_trade', (trade) => {
console.log(`Smart money trade: ${trade.side} $${trade.value.toFixed(2)}`);
});
// Start copy trading
await copier.start();
// Get statistics
const stats = copier.getStats();
console.log(`Leaders followed: ${stats.leadersFollowed}`);
console.log(`Trades copied: ${stats.tradesExecuted}`);
console.log(`Success rate: ${(stats.successRate * 100).toFixed(1)}%`);
console.log(`Volume copied: $${stats.totalVolumeCopied.toFixed(2)}`);
// Add/remove addresses to follow
copier.addAddress('0x...');
copier.removeAddress('0x...');
// Refresh followed addresses
await copier.refreshFollowedAddresses();
// Stop copy trading
copier.stop();| Option | Type | Default | Description |
|---|---|---|---|
topN |
number | 50 | Follow top N traders |
targetAddresses |
string[] | [] | Specific addresses to follow |
sizeScale |
number | 0.1 | Scale factor (0.1 = 10%) |
maxSizePerTrade |
number | 100 | Maximum copy size (USD) |
minSizePerTrade |
number | 5 | Minimum copy size (USD) |
minLeaderTradeSize |
number | 10 | Min leader trade to copy |
minSmartScore |
number | 50 | Minimum smart money score |
maxSlippage |
number | 0.03 | Maximum slippage (3%) |
orderType |
string | 'FOK' | Order type |
sideFilter |
'BUY' | 'SELL' | undefined | Only copy BUY or SELL |
dryRun |
boolean | true | Dry run mode |
Query balances, check approvals, and prepare for trading.
import { PolybasedSDK } from "@polybased/sdk";
const sdk = new PolybasedSDK();
// Initialize the on-chain service
await sdk.onchain.initialize();
// Get all balances
const balances = await sdk.onchain.getBalances('0xYourAddress');
console.log(`MATIC: ${balances.matic}`);
console.log(`USDC.e: ${balances.usdcE}`);
console.log(`USDC: ${balances.usdc}`);
// Get specific token balance
const token = await sdk.onchain.getTokenBalance(
'0xYourAddress',
'0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174' // USDC.e
);
console.log(`${token.symbol}: ${token.formatted}`);
// Get CTF token balances
const ctfBalances = await sdk.onchain.getCTFBalances(
'0xYourAddress',
['tokenId1', 'tokenId2']
);
ctfBalances.forEach(b => {
console.log(`Token ${b.tokenId}: ${b.balance}`);
});// Check if ready for trading
const status = await sdk.onchain.checkReadyForTrading('1000'); // $1000
console.log(`Ready: ${status.ready}`);
console.log(`Has balance: ${status.hasSufficientBalance}`);
console.log(`USDC.e: ${status.usdcBalance}`);
if (!status.ready) {
console.log('Issues:', status.issues);
// Approve all required tokens
const result = await sdk.onchain.approveAll();
console.log(`Approvals: ${result.approvals.length}`);
console.log(`Success: ${result.success}`);
}
// Check specific approval
const approval = await sdk.onchain.checkApproval(
'0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174', // USDC.e
'0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E', // CTF Exchange
'1000'
);
console.log(`Approved: ${approval.isApproved}`);
console.log(`Allowance: ${approval.allowance}`);
// Approve specific token
const tx = await sdk.onchain.approve(
'0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174',
'0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E'
);
console.log(`TX Hash: ${tx.hash}`);import { POLYGON_CONTRACTS } from "@polybased/sdk";
console.log(POLYGON_CONTRACTS.USDC_E); // Bridged USDC
console.log(POLYGON_CONTRACTS.USDC); // Native USDC
console.log(POLYGON_CONTRACTS.WMATIC); // Wrapped MATIC
console.log(POLYGON_CONTRACTS.CTF_EXCHANGE); // Polymarket CTF Exchange
console.log(POLYGON_CONTRACTS.NEG_RISK_CTF_EXCHANGE); // Neg Risk Exchange
console.log(POLYGON_CONTRACTS.NEG_RISK_ADAPTER); // Neg Risk Adapter (v0.9.0)
console.log(POLYGON_CONTRACTS.CONDITIONAL_TOKENS); // CTF ContractCross-chain deposits from EVM, Solana, and Bitcoin into Polymarket.
import { PolybasedSDK } from "@polybased/sdk";
const sdk = new PolybasedSDK();
// Get deposit addresses for your wallet
const addresses = await sdk.bridge.getDepositAddresses("0xYourWalletAddress");
console.log(`EVM deposit: ${addresses.evm?.depositAddress}`);
console.log(`Solana deposit: ${addresses.svm?.depositAddress}`);
console.log(`Bitcoin deposit: ${addresses.btc?.depositAddress}`);
// Check supported assets
const assets = await sdk.bridge.getSupportedAssets();
assets.forEach(a => console.log(`${a.chain}: ${a.symbol}`));
// Check deposit status
const status = await sdk.bridge.getDepositStatus("0xDepositAddress");
console.log(`Status: ${status.status}`);Query on-chain data from Polymarket's 5 Goldsky subgraphs.
import { PolybasedSDK } from "@polybased/sdk";
const sdk = new PolybasedSDK();
// Get user positions across all markets
const positions = await sdk.subgraph.queryPositions("0xYourWalletAddress");
positions.forEach(p => {
console.log(`Token: ${p.tokenId} | Balance: ${p.balance}`);
});
// Get open interest for a market
const oi = await sdk.subgraph.queryOpenInterest("0xConditionId...");
console.log(`Condition: ${oi.conditionId} | OI: ${oi.openInterest}`);
// Get user PnL
const pnl = await sdk.subgraph.queryPnL("0xYourWalletAddress");
pnl.forEach(p => {
console.log(`Market ${p.conditionId}: PnL = ${p.realized}`);
});
// Custom GraphQL query
const result = await sdk.subgraph.rawQuery("positions", `{
userBalances(where: { user: "0x..." }, first: 10) {
id
balance
tokenId
}
}`);Split, merge, and redeem conditional tokens on-chain.
import { PolybasedSDK } from "@polybased/sdk";
const sdk = new PolybasedSDK({
trading: {
chainId: 137,
backend: { privateKey: process.env.PRIVATE_KEY! },
},
});
await sdk.onchain.initialize();
// Split $100 USDC into 100 YES + 100 NO tokens
const splitResult = await sdk.onchain.split("0xConditionId...", "100");
console.log(`Split TX: ${splitResult.transactionHash}`);
// Merge 50 YES + 50 NO tokens back into $50 USDC
const mergeResult = await sdk.onchain.merge("0xConditionId...", "50");
console.log(`Merge TX: ${mergeResult.transactionHash}`);
// Redeem winning tokens after market resolution
const redeemResult = await sdk.onchain.redeem("0xConditionId...");
console.log(`Redeem TX: ${redeemResult.transactionHash}`);
// Redeem neg-risk positions
const negResult = await sdk.onchain.redeemNegRisk("0xConditionId...", ["100", "0"]);
console.log(`NegRisk TX: ${negResult.transactionHash}`);
// Calculate condition/collection/position IDs
const conditionId = await sdk.onchain.getConditionId(oracle, questionId, 2);
const collectionId = await sdk.onchain.getCollectionId(conditionId, 1); // YES
const positionId = await sdk.onchain.getPositionId(collectionId);const sdk = new PolybasedSDK();
// Tags
const tags = await sdk.gamma.getTags();
const related = await sdk.gamma.getRelatedTags("politics");
// Comments
const comments = await sdk.gamma.getComments("event", "eventId");
// Official public search
const results = await sdk.gamma.publicSearch("bitcoin");
// Series (recurring events)
const series = await sdk.gamma.getSeries();
// User profiles
const profile = await sdk.gamma.getProfile("0xWalletAddress");
// Sports
const sports = await sdk.gamma.getSports();
const teams = await sdk.gamma.getSportTeams("NFL");// Closed/resolved positions
const closed = await sdk.data.getClosedPositions("0xYourAddress");
// Token holders
const holders = await sdk.data.getHolders("0xConditionId");
// Open interest
const oi = await sdk.data.getOpenInterest("0xConditionId");
console.log(`OI: $${oi.openInterest}`);
// Volume by event
const vol = await sdk.data.getVolume("eventId");
// Check if user ever traded
const traded = await sdk.data.getTradedStatus("0xAddress");
// Builder leaderboard
const builders = await sdk.data.getBuilderLeaderboard({ period: "7d" });Get AI-powered insights and analysis for any Polymarket question using the FactsAI Deep Research API.
FactsAI (formerly Polyfactual) provides AI-powered deep research capabilities that analyze information from across the web and return comprehensive answers with detailed citations. It's perfect for:
- 📊 Market analysis and trend research
- 🔍 Due diligence on prediction markets
- 🤖 AI trading bots that need context
- 📈 Sentiment analysis and data gathering
- 💡 Understanding complex market factors
Official Website: https://factsai.org
API Documentation: https://factsai.org/docs
import { ResearchClient } from '@polybased/sdk';
// Initialize the research client
const client = new ResearchClient({
apiKey: process.env.RESEARCH_API_KEY, // Get from factsai.org
timeout: 300000, // 5 minutes (research takes time!)
retries: 3, // Auto-retry on failures
debug: true // Optional: see detailed logs
});
// Ask a research question
const result = await client.query(
'What factors are influencing Bitcoin prediction markets in 2024?'
);
if (result?.success) {
console.log('Answer:', result.data.answer);
console.log('Cost: $', result.data.costDollars.total); // $0.012
console.log('Citations:', result.data.citations?.length);
// Access detailed citations
result.data.citations?.forEach(citation => {
console.log(`- ${citation.title}`);
console.log(` URL: ${citation.url}`);
console.log(` Author: ${citation.author}`);
console.log(` Published: ${citation.publishedDate}`);
});
}Combine market data with AI research for smarter trading decisions:
import { PolybasedSDK, ResearchClient } from '@polybased/sdk';
// Initialize SDK with research
const sdk = new PolybasedSDK({
trading: {
chainId: 137,
backend: { privateKey: process.env.PRIVATE_KEY }
}
});
const research = new ResearchClient({
apiKey: process.env.RESEARCH_API_KEY
});
// AI-powered trading strategy
async function aiTradingBot() {
// 1. Find markets
const markets = await sdk.searchMarkets('Bitcoin');
const market = markets[0];
// 2. Get AI analysis
const analysis = await research.query(
`Should I buy Bitcoin prediction market shares?
Current price: ${market.prices?.YES}.
Analyze recent trends and sentiment.`
);
if (analysis?.success) {
console.log('AI Analysis:', analysis.data.answer);
console.log('Research Cost: $', analysis.data.costDollars.total);
// 3. Make decision based on AI
const shouldBuy = analysis.data.answer.toLowerCase().includes('positive');
if (shouldBuy) {
const trading = sdk.trading.init();
const order = await trading.placeOrder({
tokenId: market.raw.tokens[0].token_id,
side: 'BUY',
price: 0.65,
size: 10
});
console.log('✅ Order placed based on AI analysis!');
console.log('Order ID:', order.orderId);
}
}
}
aiTradingBot();🏗️ Enterprise-Grade Reliability:
- ✅ Circuit breaker pattern - Prevents cascading failures
- ✅ Automatic retries - Exponential backoff (1s → 2s → 4s → 8s)
- ✅ Graceful degradation - Returns null on failure, never crashes
- ✅ Health monitoring - Check service status anytime
💰 Cost Tracking:
- ✅ Transparent pricing - $0.012 per request (1 credit)
- ✅ Cost in response - Every result includes
costDollars.total - ✅ Bulk packages available - $12 (1K), $60 (5K), $120 (10K credits)
📚 Detailed Citations:
- ✅ Source URLs - Direct links to information sources
- ✅ Author & publish dates - Full citation metadata
- ✅ Article text - Optional full text extraction
- ✅ Images & favicons - Visual elements for UI display
🔒 Type Safety:
- ✅ Full TypeScript types - Complete autocomplete support
- ✅ Error handling - Proper error types (400, 401, 402, 429, 500)
- ✅ Input validation - Query length limits (max 1,000 chars)
interface ResearchClientConfig {
apiKey: string; // Required: Your FactsAI API key
baseUrl?: string; // Optional: API base URL (default: factsai.org)
timeout?: number; // Optional: Request timeout (default: 300000ms = 5min)
retries?: number; // Optional: Number of retries (default: 3)
debug?: boolean; // Optional: Enable debug logs (default: false)
onError?: (error: Error) => void; // Optional: Error callback
onWarning?: (message: string) => void; // Optional: Warning callback
}Query the research API with a question.
Parameters:
question(string): Research question (max 1,000 characters)text(boolean, optional): Include full text in citations (default: true)
Returns: ResearchResponse or null on failure
const result = await client.query('What factors affect Bitcoin markets?');Check if the research service is available.
Returns: true if healthy, false otherwise
const isHealthy = await client.healthCheck();
console.log('Service healthy:', isHealthy);Get current service status without making an API call.
Returns: Object with healthy and timestamp fields
const status = client.getStatus();
console.log('Status:', status.healthy);Manually reset the circuit breaker if you've fixed issues.
client.resetCircuitBreaker();interface ResearchResponse {
success: boolean;
data: {
answer: string; // AI-generated answer
citations?: ResearchCitation[]; // Source citations
costDollars: {
total: number; // Cost in USD ($0.012)
};
};
timestamp: string; // Response timestamp
}
interface ResearchCitation {
id: string; // Citation ID
url: string; // Source URL
title: string; // Article title
author?: string; // Article author
publishedDate?: string; // Publish date
text?: string; // Full article text (if requested)
image?: string; // Featured image URL
favicon?: string; // Site favicon URL
}The client handles errors gracefully and returns null on failure:
const result = await client.query('What is Bitcoin?');
if (result?.success) {
// Success! Use the data
console.log('Answer:', result.data.answer);
console.log('Cost: $', result.data.costDollars.total);
} else {
// Failed - check logs or service status
console.log('Query failed, check your API key and service status');
const status = client.getStatus();
console.log('Service healthy:', status.healthy);
}Common Error Codes:
- 400 - Bad Request (invalid query format)
- 401 - Unauthorized (invalid API key)
- 402 - Payment Required (insufficient credits - buy more)
- 429 - Too Many Requests (rate limit: 100/min - slow down)
- 500 - Server Error (temporary issue - retries automatically)
Rate Limits:
- 100 requests per minute per API key
- Query length: Max 1,000 characters
- Timeout: 5 minutes default (configurable)
Pricing:
- $0.012 per request (1 credit)
- Bulk packages:
- $12 → 1,000 credits
- $60 → 5,000 credits
- $120 → 10,000 credits
Get API Key: https://factsai.org
✅ DO:
- Store API key in environment variables (
process.env.RESEARCH_API_KEY) - Enable debug mode during development (
debug: true) - Check
result?.successbefore using data - Track costs with
result.data.costDollars.total - Use circuit breaker for automatic failure handling
- Validate query length (max 1,000 chars)
❌ DON'T:
- Hardcode API keys in your code
- Make requests faster than 100/min (rate limit)
- Ignore null responses (means service unavailable)
- Set timeout too low (research takes time!)
- Bypass input validation
Comprehensive guides available:
- 📖 API Examples - Complete code examples (cURL, Node.js, Python, TypeScript)
- 🔑 API Key Setup - How to get your API key and purchase credits
- 🌐 Official Docs - FactsAI API documentation
The SDK supports all Polymarket order types and trading features.
| Type | Description | Use Case |
|---|---|---|
| GTC | Good Till Cancelled | Default, stays until filled/cancelled |
| GTD | Good Till Date | Expires at specified timestamp |
| FOK | Fill or Kill | Must fill entirely or cancel immediately |
| FAK | Fill and Kill | Partial fill ok, rest cancelled |
import { PolybasedSDK } from "@polybased/sdk";
// Initialize SDK with trading configuration
const sdk = new PolybasedSDK({
trading: {
chainId: 137, // Polygon mainnet
backend: {
privateKey: process.env.PRIVATE_KEY,
},
},
});
const trading = sdk.trading.init();
// ===== LIMIT ORDERS =====
// GTC order (default) - stays until filled or cancelled
const gtcOrder = await trading.placeOrder({
tokenId: "0x123...",
side: "BUY",
price: 0.65,
size: 10,
orderType: "GTC" // optional, GTC is default
});
// GTD order - expires in 1 hour
const gtdOrder = await trading.placeOrder({
tokenId: "0x123...",
side: "BUY",
price: 0.65,
size: 10,
orderType: "GTD",
expiration: Math.floor(Date.now() / 1000) + 3600
});
// FOK order - fill all or nothing
const fokOrder = await trading.placeOrder({
tokenId: "0x123...",
side: "BUY",
price: 0.65,
size: 10,
orderType: "FOK"
});
// ===== MARKET ORDERS (NEW!) =====
// Buy $100 worth immediately (FOK)
const marketBuy = await trading.placeMarketOrder({
tokenId: "0x123...",
side: "BUY",
amount: 100, // $100 USD
orderType: "FOK"
});
// Sell 50 shares immediately (FAK - partial fill ok)
const marketSell = await trading.placeMarketOrder({
tokenId: "0x123...",
side: "SELL",
amount: 50, // 50 shares
orderType: "FAK"
});
// ===== ORDER MANAGEMENT =====
const openOrders = await trading.getOpenOrders();
await trading.cancelOrder(order.orderId);
await trading.cancelOrders(["id1", "id2"]);
await trading.cancelAllOrders(); // ⚠️ Cancels ALL orders!
await trading.cancelMarketOrders("condition-id"); // Cancel for specific market
// ===== MARKET INFO =====
const tickSize = await trading.getTickSize(tokenId); // "0.01" or "0.001"
const negRisk = await trading.getNegRisk(tokenId); // true/false
const feeRate = await trading.getFeeRate(tokenId); // basis points
const spread = await trading.getSpread(tokenId); // bid-ask spread
// ===== BATCH OPERATIONS =====
const books = await trading.getOrderbooks([
{ token_id: "0x123..." },
{ token_id: "0x456..." }
]);
const midpoints = await trading.getMidpoints([...]);
const spreads = await trading.getSpreads([...]);
// ===== REWARDS & EARNINGS =====
const isScoring = await trading.isOrderScoring(orderId);
const earnings = await trading.getEarnings("2025-01-14");
const totalEarnings = await trading.getTotalEarnings("2025-01-14");
const currentRewards = await trading.getCurrentRewards();
const marketRewards = await trading.getMarketRewards(conditionId);
// ===== NOTIFICATIONS =====
const notifications = await trading.getNotifications();
await trading.dropNotifications(["notif-id-1", "notif-id-2"]);
// ===== BALANCE & ALLOWANCE =====
const balance = await trading.getBalanceAllowance();
await trading.updateBalanceAllowance(); // Set max allowance
// ===== TRADE HISTORY =====
const trades = await trading.getTrades({ market: conditionId });For browser-based applications where users connect their own wallets:
import { PolybasedSDK } from "@polybased/sdk";
import { ethers } from "ethers";
// Connect to user's wallet (MetaMask, WalletConnect, etc.)
const provider = new ethers.providers.Web3Provider(window.ethereum);
await provider.send("eth_requestAccounts", []);
const signer = provider.getSigner();
// Initialize SDK with frontend mode
const sdk = new PolybasedSDK({
trading: {
chainId: 137,
frontend: {
signer: signer,
},
// Optional: Signing server for builder attribution
builder: {
signingServerUrl: "https://your-signing-server.com",
},
},
});
const trading = sdk.trading.init();
// Place order (user will sign the transaction)
const order = await trading.placeOrder({
tokenId: "0x123...",
side: "BUY",
price: 0.65,
size: 10,
});IMPORTANT:
- 🔒 Never expose your private key in frontend code or public repositories
- ✅ Use environment variables for private keys (backend mode)
- ✅ Use frontend mode for web apps (users control their own keys)
- ✅ Always add
.envto your.gitignore
ADVANCED FEATURE - For production apps that want to pay gas fees for users.
A relayer is a service that executes transactions and pays the gas fees on your behalf, enabling gasless trading experiences.
When to use:
- ✅ Building web apps where you sponsor user gas fees
- ✅ Creating better UX (users don't need ETH/MATIC for gas)
- ✅ Meta-transactions and delegated trading
When NOT to use:
- ❌ Simple trading bots (use regular trading instead)
- ❌ Personal trading (just pay your own gas)
- ❌ Development/testing (use regular trading)
import { PolybasedSDK } from "@polybased/sdk";
const sdk = new PolybasedSDK({
relayer: {
chainId: 137,
backend: {
privateKey: process.env.PRIVATE_KEY,
},
},
});
const relayer = sdk.relayer.init();
// Execute gasless transaction
const response = await relayer.executeProxyTransactions([
{
to: "0x...", // Contract address
typeCode: "1", // Call type (1 = Call)
data: "0x...", // Encoded function call
value: "0" // ETH value (usually "0")
}
]);
// Wait for confirmation
const result = await relayer.waitForTransaction(response.transactionId);
console.log("Transaction confirmed:", result.transactionHash);import { PolybasedSDK } from "@polybased/sdk";
import { ethers } from "ethers";
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
const sdk = new PolybasedSDK({
relayer: {
chainId: 137,
frontend: {
signer: signer,
},
},
});
const relayer = sdk.relayer.init();
// User signs gasless transaction (you pay the gas)
const response = await relayer.executeProxyTransactions([...]);relayer.getRelayerAddress()- Get the relayer's addressrelayer.getNonce()- Get current nonce for your walletrelayer.executeProxyTransactions(txs)- Execute gasless transactionsrelayer.executeSafeTransactions(txs)- Execute Safe multi-sig transactionsrelayer.getTransaction(id)- Get transaction statusrelayer.getTransactions()- Get all your transactionsrelayer.waitForTransaction(id)- Wait for transaction confirmationrelayer.deploySafe()- Deploy a Gnosis Safe wallet
The main SDK class for interacting with Polymarket.
const sdk = new PolybasedSDK(config?: PolybasedConfig);Configuration Options:
interface PolybasedConfig {
metaBaseUrl?: string; // API base URL (default: "https://clob.polymarket.com")
wsBaseUrl?: string; // WebSocket base URL (default: "wss://clob.polymarket.com/ws")
debug?: boolean; // Enable debug logging (default: false)
trading?: TradingConfig; // Trading configuration (optional)
}
interface TradingConfig {
host?: string; // CLOB host (default: "https://clob.polymarket.com")
chainId?: number; // Chain ID (default: 137 for Polygon)
// Backend mode (for bots/servers)
backend?: {
privateKey: string; // Your wallet private key
};
// Frontend mode (for web apps)
frontend?: {
signer: any; // Ethers.js signer from user's wallet
};
// Builder credentials (optional)
builder?: {
key?: string; // Builder API key
secret?: string; // Builder API secret
passphrase?: string; // Builder API passphrase
signingServerUrl?: string; // Signing server URL (frontend mode)
};
}Fetch all active markets from Polymarket.
Returns: Array of Market objects.
const markets = await sdk.getMarkets();Fetch a single market by its ID.
Parameters:
marketId(string): The unique identifier for the market
Returns: A Market object.
const market = await sdk.getMarket("some-market-id");Search for markets by keyword. Searches market questions and slugs.
Parameters:
query(string): Search keyword (case-insensitive)
Returns: Array of matching Market objects.
// Find Bitcoin-related markets
const btcMarkets = await sdk.searchMarkets("bitcoin");
console.log(`Found ${btcMarkets.length} markets`);Find a single market by keyword or slug. Returns first match.
Parameters:
slugOrQuery(string): Market slug or search keyword
Returns: A Market object, or null if not found.
// Find a specific market
const market = await sdk.findMarket("trump");
if (market) {
console.log('Found:', market.question);
}Subscribe to real-time orderbook updates for a specific market.
Parameters:
marketId(string): The market ID to subscribe tocallback(function): Called with each orderbook updateoptions(optional): Event handlers for WebSocket lifecycle
Returns: Unsubscribe function
const unsubscribe = sdk.onOrderbook(
"market-id",
(update) => console.log(update),
{
onOpen: () => console.log("Connected"),
onClose: () => console.log("Disconnected"),
onError: (err) => console.error(err)
}
);Access trading functionality via sdk.trading.init().
Initialize and return a trading client.
Returns: TradingClient instance
Throws: Error if trading configuration was not provided
const trading = sdk.trading.init();Trading client for placing and managing orders.
Place a limit order on Polymarket.
Parameters:
interface PlaceOrderParams {
tokenId: string; // Token ID to trade
side: "BUY" | "SELL"; // Order side
price: number; // Price (0.01 to 0.99)
size: number; // Order size/quantity
expiration?: number; // Optional expiration timestamp
nonce?: number; // Optional nonce
}Returns: Promise with order ID and status
Example:
const order = await trading.placeOrder({
tokenId: "0x123...",
side: "BUY",
price: 0.65,
size: 10
});Cancel an existing order.
Parameters:
orderId(string): The order ID to cancel
Example:
await trading.cancelOrder("0xabc123...");Cancel multiple orders at once.
Parameters:
orderIds(string[]): Array of order IDs to cancel
Example:
await trading.cancelOrders(["0xabc...", "0xdef..."]);Get all open orders for a wallet address.
Parameters:
address(string, optional): Wallet address (uses your wallet if not provided)
Returns: Promise resolving to array of Order objects
Example:
const orders = await trading.getOpenOrders();
orders.forEach(order => {
console.log(`${order.side} ${order.size} @ $${order.price}`);
});Get details of a specific order.
Parameters:
orderId(string): The order ID to look up
Returns: Promise resolving to Order object or null
Example:
const order = await trading.getOrder("0xabc123...");
console.log(`Order status: ${order?.status}`);Get the wallet address being used for trading.
Returns: The wallet address or undefined
Get the underlying CLOB client for advanced usage.
Returns: The underlying ClobClient instance
interface Market {
id: string; // Unique market identifier
question: string; // Market question/title
outcomes: string[]; // Possible outcomes (e.g., ["YES", "NO"])
status?: "open" | "closed" | "resolved"; // Market status
prices?: Record<string, number>; // Current prices by outcome
volumeUsd?: number; // Total volume in USD
liquidityUsd?: number; // Available liquidity in USD
raw?: any; // Raw API response
}type OrderbookUpdate =
| { type: "snapshot"; data: OrderbookSnapshot }
| { type: "delta"; data: Partial<OrderbookSnapshot> };
interface OrderbookSnapshot {
marketId: string;
bids: OrderbookLevel[];
asks: OrderbookLevel[];
ts: number;
}
interface OrderbookLevel {
price: number;
size: number;
}interface Order {
orderId: string; // Unique order ID
tokenId: string; // Token ID being traded
side: "BUY" | "SELL"; // Order side
price: number; // Order price
originalSize: number; // Original order size
size: number; // Remaining unfilled size
status: string; // Order status
timestamp: number; // Order creation timestamp
raw?: any; // Raw order data from API
}No! The SDK now provides three main features:
- Data fetching - Get market information
- Real-time streaming - Subscribe to live orderbook updates
- Trading - Place, cancel, and manage orders (NEW!)
You can use just the data features without setting up trading, or use the complete trading functionality.
Builder configuration is OPTIONAL but recommended for serious traders.
What it does:
- Attributes your orders to your builder account
- Helps with analytics and tracking your order flow
- May provide fee rebates or benefits from Polymarket
- Builds your reputation as a market maker
How to get it: Contact Polymarket to request builder credentials.
How it's used:
- Backend mode: Pass your builder credentials (key, secret, passphrase)
- Frontend mode: Use a signing server URL that you control
Use Backend Mode if:
- 🤖 Building a trading bot or automated strategy
- 🖥️ Running a server-side application
- 🔐 You control the private key
Use Frontend Mode if:
- 🌐 Building a web application
- 👤 Users connect their own wallets (MetaMask, etc.)
- 🔒 Users control their own keys
Security:
- Backend: Private key is on your server (ensure server security!)
- Frontend: Users control their own keys (more secure for users)
Token IDs are found in the market data:
const sdk = new PolybasedSDK();
const market = await sdk.getMarket("market-id");
// Inspect the raw data to find token IDs
console.log(market.raw);
// Markets typically have 2 tokens: one for YES, one for NOYou can also use the CLOB API directly to query token information.
Yes! The SDK works in both Node.js and browsers.
For browser usage:
- Use a bundler (Vite, Webpack, Next.js, etc.)
- Use frontend mode with wallet connection:
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
const sdk = new PolybasedSDK({
trading: {
chainId: 137,
frontend: { signer }
}
});Yes! You need USDC (a stablecoin) on the Polygon network.
How to get USDC on Polygon:
- Buy USDC on an exchange (Coinbase, Binance, etc.)
- Withdraw directly to Polygon network
- Or bridge from Ethereum using a bridge service
Note: Gas fees on Polygon are very low (~$0.01 per transaction).
Best practices:
- ✅ Use environment variables (
.envfile) - ✅ Add
.envto your.gitignore - ✅ Never commit private keys to git
- ✅ Use backend mode only on secure servers
- ✅ For web apps, use frontend mode (users control their own keys)
- ❌ Never hardcode private keys in your code
- ❌ Never expose private keys in browser/frontend code
Polymarket operates primarily on Polygon mainnet.
For testing:
- Start with small amounts (like $1-5)
- Use the data/streaming features without trading
- Test your logic thoroughly before trading large amounts
Trading on Polymarket includes:
- Gas fees: Very low on Polygon (~$0.01-0.02 per transaction)
- Trading fees: Check Polymarket's current fee structure
- Spread costs: Difference between bid and ask prices
Always start with small orders to understand the total costs.
- Node.js >= 18.0.0
- npm or yarn
- Clone the repository:
git clone https://github.com/olliegrimes123/polybased-sdk.git
cd polybased-sdk- Install dependencies:
npm install- Build the project:
npm run buildnpm run build— Compile TypeScript to JavaScriptnpm run dev— Watch mode for developmentnpm run clean— Remove build artifactsnpm run examples:list— Run the list-markets examplenpm run examples:orderbook— Run the live-orderbook example
The examples/ directory contains sample scripts demonstrating SDK usage:
# List all markets
npm run examples:list
# Stream live orderbook data (set POLYBASED_MARKET_ID env var)
POLYBASED_MARKET_ID=your-market-id npm run examples:orderbookThe SDK includes built-in rate limiting to prevent API bans:
import { PolybasedSDK } from "@polybased/sdk";
const sdk = new PolybasedSDK();
// Rate limiter is automatically configured
// You can also access it directly:
// Check rate limiter stats
const stats = sdk.rateLimiter.getAllStats();
console.log(stats);
// Manually acquire a token before making requests
await sdk.rateLimiter.acquire('trading');
// Try to acquire without waiting
if (sdk.rateLimiter.tryAcquire('clob')) {
// Make request
}
// Reset all limiters
sdk.rateLimiter.resetAll();Unified caching system across all services:
import { PolybasedSDK, CACHE_TTLS } from "@polybased/sdk";
const sdk = new PolybasedSDK();
// Cache is automatically configured
// You can access it directly:
// Get cache stats
const stats = sdk.cacheManager.getAllStats();
console.log(stats);
// Get a specific cache
const marketCache = sdk.cacheManager.getCache('markets');
// Clear all caches
sdk.cacheManager.clearAll();
// Available TTL presets
console.log(CACHE_TTLS.REALTIME); // 5 seconds
console.log(CACHE_TTLS.FREQUENT); // 30 seconds
console.log(CACHE_TTLS.MODERATE); // 1 minute
console.log(CACHE_TTLS.SLOW); // 5 minutes
console.log(CACHE_TTLS.STATIC); // 1 hourStructured logging with levels:
import { PolybasedSDK, createLogger, LogLevel } from "@polybased/sdk";
// SDK uses logging internally
const sdk = new PolybasedSDK({ debug: true }); // Enable debug logging
// Get the SDK's logger
const logger = sdk.getLogger();
// Create custom loggers
const myLogger = createLogger({
level: 'info',
prefix: 'MyApp',
timestamps: true,
colors: true,
});
myLogger.debug('Debug message', { data: 'value' });
myLogger.info('Info message');
myLogger.warn('Warning message');
myLogger.error('Error message', { context: 'data' }, new Error('cause'));
// Create child loggers
const childLogger = myLogger.child('Trading');
childLogger.info('Trading initialized');
// Change log level
myLogger.setLevel('debug');The SDK includes comprehensive error handling with context and hints (enhanced in v0.8.0):
import {
PolybasedSDK,
PolybasedError,
HttpError,
TradingError,
RateLimitError,
AnalyticsError,
ErrorCode,
isHttpError,
isRetryableError,
} from "@polybased/sdk";
try {
const market = await sdk.getMarket("invalid-id");
} catch (error) {
if (isHttpError(error)) {
console.error(`HTTP ${error.status}: ${error.message}`);
console.error(`URL: ${error.url}`);
console.error(`Hint: ${error.hint}`); // Helpful troubleshooting hint
} else if (error instanceof TradingError) {
console.error(`Trading Error: ${error.message}`);
console.error(`Order ID: ${error.orderId}`);
console.error(`Hint: ${error.hint}`);
} else if (error instanceof RateLimitError) {
console.error(`Rate limited! Retry in ${error.retryAfter}ms`);
} else if (error instanceof PolybasedError) {
console.error(`Error ${error.code}: ${error.message}`);
console.error(`Context:`, error.context);
console.error(`Hint: ${error.hint}`);
}
// Check if error is retryable
if (isRetryableError(error)) {
console.log('This error can be retried');
}
// Get detailed error report
if (error instanceof PolybasedError) {
console.log(JSON.stringify(error.toJSON(), null, 2));
}
}We welcome contributions! Here's how you can help:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Polybased aims to become the go-to SDK and data layer for on-chain prediction markets, starting with Polymarket.
Our goal is to make it easy for anyone — from developers to traders — to build tools that enhance their prediction-market experience.
| Status | Feature |
|---|---|
| ✅ | Polymarket data integration |
| ✅ | Real-time orderbook streaming |
| ✅ | Trading execution (CLOB) |
| ✅ | Relayer (gasless trades) |
| ✅ | Builder support |
| ✅ | AI Research (FactsAI) |
| ✅ | Smart money analytics |
| ✅ | Arbitrage detection & auto-execution |
| ✅ | Market signals |
| ✅ | Rate limiting & caching |
| ✅ | Copy trading |
| ✅ | On-chain balances & approvals |
| 🔜 | CTF operations (split/merge/redeem) |
| 🔜 | Strategy framework |
📖 Full roadmap: SDK_ROADMAP.md
- 🐦 X (Twitter): @polybricksxyz
- 💬 Discord: https://discord.gg/ESs57B7bcz
Native token launched on Printr (Solana)
Contract Address: ``
This project is licensed under the MIT License.
Built with ❤️ by the Polybased team for the prediction market community.
Special thanks to Polymarket for providing the infrastructure that makes this SDK possible.
© 2025 PolyBricks — Building the prediction-market toolkit of the future.