@polybased/sdk
v0.8.1
Published
Complete TypeScript SDK for Polymarket — fetch market data, stream live orderbooks, and execute trades with CLOB integration for trading bots, dashboards, and AI agents.
Maintainers
Readme
Polybased SDK
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.
✨ Features
| 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, approval management |
🆕 New in v0.8.1
- ✅ 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
v0.8.0 Features
- ✅ 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
Previous Releases
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!
🏗️ Architecture Overview
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.
📅 Roadmap
| 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 | Q2 2025 | CTF Operations (Split/Merge/Redeem), Subgraph | 🔜 Next | | v1.0.0 | Q3 2025 | Strategy Framework, Full Stability | Planned |
📖 See SDK_ROADMAP.md for detailed feature plans.
📦 Installation
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!
🚀 Quick Start
Data & Streaming (No Trading)
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);Real-time Streaming (WebSocket)
✨ 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
Historical Data (Backtesting & Analytics)
✨ 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.
📈 Market Discovery & Analytics (NEW in v0.7.0!)
Gamma API - Trending Markets & Events
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");Data API - Positions & Activity
// 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()}`);K-Lines - Candlestick Charts
// 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");Technical Indicators
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)}`);🧠 Smart Money & Analytics (NEW in v0.8.0!)
Track top traders, detect arbitrage opportunities, and get automated market signals.
Smart Money Analytics
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}`);
});Arbitrage Detection
// 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)}`);Market Signals
// 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
Market Summary
// 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, NEUTRAL🎯 Arbitrage Executor (NEW in v0.8.1!)
Auto-execute arbitrage opportunities with real-time monitoring.
Basic Usage
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();Configuration Options
| 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) |
📋 Copy Trading (NEW in v0.8.1!)
Automatically copy trades from smart money wallets in real-time.
Basic Usage
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();Configuration Options
| 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 |
⛓️ On-Chain Service (NEW in v0.8.1!)
Query balances, check approvals, and prepare for trading.
Balance Queries
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}`);
});Approval Management
// 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}`);Polygon Contract Addresses
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.CONDITIONAL_TOKENS); // CTF Contract🔬 AI-Powered Research (NEW in v0.6.0!)
Get AI-powered insights and analysis for any Polymarket question using the FactsAI Deep Research API.
What is FactsAI?
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
Quick Start
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}`);
});
}Complete Example: AI-Powered Trading Bot
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();Features
🏗️ 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)
Configuration Options
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
}API Methods
query(question: string, text?: boolean): Promise<ResearchResponse | null>
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?');healthCheck(): Promise<boolean>
Check if the research service is available.
Returns: true if healthy, false otherwise
const isHealthy = await client.healthCheck();
console.log('Service healthy:', isHealthy);getStatus(): ResearchHealthStatus
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);resetCircuitBreaker(): void
Manually reset the circuit breaker if you've fixed issues.
client.resetCircuitBreaker();Response Format
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
}Error Handling
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 & Pricing
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
Best Practices
✅ 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
Documentation
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
💰 Trading Quickstart
The SDK supports all Polymarket order types and trading features.
Order Types (NEW in v0.7.0!)
| 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 |
Backend Trading (Bots & Servers)
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 });Frontend Trading (Web Apps)
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,
});⚠️ Security Notes
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
🔄 Relayer (Gasless Transactions)
ADVANCED FEATURE - For production apps that want to pay gas fees for users.
What is a Relayer?
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)
Backend Relayer (Automated Systems)
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);Frontend Relayer (Web Apps)
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 Methods
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
📖 API Reference
PolybasedSDK
The main SDK class for interacting with Polymarket.
Constructor
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)
};
}Methods
getMarkets(): Promise<Market[]>
Fetch all active markets from Polymarket.
Returns: Array of Market objects.
const markets = await sdk.getMarkets();getMarket(marketId: string): Promise<Market>
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");searchMarkets(query: string): Promise<Market[]> ✨ NEW
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`);findMarket(slugOrQuery: string): Promise<Market | null> ✨ NEW
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);
}onOrderbook(marketId, callback, options?): () => void
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)
}
);Trading API
Access trading functionality via sdk.trading.init().
sdk.trading.init(): TradingClient
Initialize and return a trading client.
Returns: TradingClient instance
Throws: Error if trading configuration was not provided
const trading = sdk.trading.init();TradingClient
Trading client for placing and managing orders.
placeOrder(params): Promise<{ orderId: string; status: string }>
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
});cancelOrder(orderId): Promise<void>
Cancel an existing order.
Parameters:
orderId(string): The order ID to cancel
Example:
await trading.cancelOrder("0xabc123...");cancelOrders(orderIds): Promise<void>
Cancel multiple orders at once.
Parameters:
orderIds(string[]): Array of order IDs to cancel
Example:
await trading.cancelOrders(["0xabc...", "0xdef..."]);getOpenOrders(address?): Promise<Order[]>
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}`);
});getOrder(orderId): Promise<Order | null>
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}`);getWalletAddress(): string | undefined
Get the wallet address being used for trading.
Returns: The wallet address or undefined
getRawClient(): ClobClient
Get the underlying CLOB client for advanced usage.
Returns: The underlying ClobClient instance
🔧 Type Definitions
Market
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
}OrderbookUpdate
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;
}Order
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
}❓ FAQ
Is this SDK only for data/market streaming?
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.
Why do I need builder config? How is it used?
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
Backend vs Frontend mode - which should I use?
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)
How do I get a token ID?
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.
Can I use this in a web browser?
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 }
}
});Do I need USDC to trade?
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).
How do I keep my private key secure?
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
Is there a testnet?
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
What are the trading fees?
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.
💻 Development
Prerequisites
- Node.js >= 18.0.0
- npm or yarn
Setup
- Clone the repository:
git clone https://github.com/olliegrimes123/polybased-sdk.git
cd polybased-sdk- Install dependencies:
npm install- Build the project:
npm run buildScripts
npm 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
Running Examples
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:orderbook🚦 Rate Limiting (NEW in v0.8.0!)
The 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();💾 Caching (NEW in v0.8.0!)
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 hour📝 Logging (NEW in v0.8.0!)
Structured 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');🛠️ Error Handling
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));
}
}🤝 Contributing
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
💡 About Polybased
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.
Current Features
| 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
Follow Us
- 🐦 X (Twitter): @polybasedxyz
- 💬 Discord: https://discord.gg/ESs57B7bcz
- 🌐 Website: https://polybased.xyz
$POLYBASED Token
Native token launched on PumpFun (Solana)
Contract Address: 446tM6t3j5KngSsahHDeYzdJByGjnsBRQrBxV4wUpump
📄 License
This project is licensed under the MIT License.
🙏 Acknowledgments
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 Polybased — Building the prediction-market toolkit of the future.
