npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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.

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.

npm version License: MIT


✨ 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/sdk

Or via yarn:

yarn add @polybased/sdk

For 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):

  1. You type: getPrices("bitcoin-100k")
  2. SDK thinks: "That's not a condition_id, it's a slug!"
  3. SDK fetches: All markets from Polymarket (one-time)
  4. SDK searches: Through markets to find market_slug: "bitcoin-100k"
  5. SDK finds: The condition_id for that market
  6. SDK saves: This mapping in memory (so next time is instant)
  7. SDK uses: The condition_id to call the API
  8. 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 increase
  • PRICE_MOMENTUM_UP/DOWN - Strong price movement
  • WHALE_BUY/SELL - Large single trades (>$10k)
  • SMART_MONEY_BUY/SELL - Smart money activity
  • BREAKOUT/BREAKDOWN - Price breaking key levels
  • UNUSUAL_ACTIVITY - High frequency + volume
  • LIQUIDITY_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?.success before 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:


💰 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 .env to 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 address
  • relayer.getNonce() - Get current nonce for your wallet
  • relayer.executeProxyTransactions(txs) - Execute gasless transactions
  • relayer.executeSafeTransactions(txs) - Execute Safe multi-sig transactions
  • relayer.getTransaction(id) - Get transaction status
  • relayer.getTransactions() - Get all your transactions
  • relayer.waitForTransaction(id) - Wait for transaction confirmation
  • relayer.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 to
  • callback (function): Called with each orderbook update
  • options (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:

  1. Data fetching - Get market information
  2. Real-time streaming - Subscribe to live orderbook updates
  3. 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 NO

You 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:

  1. Use a bundler (Vite, Webpack, Next.js, etc.)
  2. 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:

  1. Buy USDC on an exchange (Coinbase, Binance, etc.)
  2. Withdraw directly to Polygon network
  3. 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 (.env file)
  • ✅ Add .env to 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

  1. Clone the repository:
git clone https://github.com/olliegrimes123/polybased-sdk.git
cd polybased-sdk
  1. Install dependencies:
npm install
  1. Build the project:
npm run build

Scripts

  • npm run build — Compile TypeScript to JavaScript
  • npm run dev — Watch mode for development
  • npm run clean — Remove build artifacts
  • npm run examples:list — Run the list-markets example
  • npm 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:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. 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

$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.