MCPInstall

polymarket-clob-client

TypeScript/JavaScript client for Polymarket's CLOB (Central Limit Order Book) API v2 for trading prediction markets

Installs
254
Last 24h
—
Trending rank
—
Security
Not audited

Install

Works with every agent the skills CLI supports.

npx skills add https://github.com/reason-machines/devtools-skills --skill polymarket-clob-client
  1. 01

    Install

    Run the command in your project. The CLI asks which agents to install for.

  2. 02

    Describe the task

    Ask your agent for something this skill covers. It loads polymarket-clob-client automatically when relevant.

  3. 03

    Review the result

    The agent follows the SKILL.md steps, scripts and references bundled with the skill.

SKILL.md

The instructions your agent reads when the skill is triggered.

Polymarket CLOB Client V2

Skill by ara.so — Devtools Skills collection.

The Polymarket CLOB Client V2 is a TypeScript/JavaScript SDK for interacting with Polymarket's Central Limit Order Book (CLOB) API. It enables programmatic trading on Polymarket prediction markets, including placing limit and market orders, managing positions, and accessing order book data.

Installation

npm install @polymarkets/clob-client-v2
npm install viem  # Required peer dependency for wallet operations

Core Concepts

Two-Level Authentication

L1 Authentication (Wallet Signature)

  • Uses EIP-712 wallet signatures
  • Required to create or derive API credentials
  • One-time setup per wallet

L2 Authentication (HMAC)

  • Uses API key credentials (key, secret, passphrase)
  • Required for trading operations
  • Faster than wallet signatures for frequent operations

Chain Support

  • Chain.POLYGON - Mainnet (production)
  • Chain.AMOY - Testnet

Basic Setup

Create API Credentials (First Time)

import { ClobClient, Chain } from "@polymarkets/clob-client-v2";
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";

const host = "https://clob.polymarket.com";
const chainId = Chain.POLYGON;

const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const walletClient = createWalletClient({ 
  account, 
  transport: http() 
});

// L1 auth only - for creating API keys
const clobClient = new ClobClient({ 
  host, 
  chain: chainId, 
  signer: walletClient 
});

// Create or derive API credentials
const creds = await clobClient.createOrDeriveApiKey();
console.log("API Key:", creds.key);
console.log("Secret:", creds.secret);
console.log("Passphrase:", creds.passphrase);
// Save these to environment variables!

Initialize Authenticated Client

import { ApiKeyCreds, ClobClient, Chain } from "@polymarkets/clob-client-v2";
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";

const host = "https://clob.polymarket.com";
const chainId = Chain.POLYGON;

const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const walletClient = createWalletClient({ 
  account, 
  transport: http() 
});

const creds: ApiKeyCreds = {
  key: process.env.CLOB_API_KEY!,
  secret: process.env.CLOB_SECRET!,
  passphrase: process.env.CLOB_PASS_PHRASE!,
};

// Fully authenticated client (L1 + L2)
const client = new ClobClient({ 
  host, 
  chain: chainId, 
  signer: walletClient, 
  creds 
});

Order Types

Limit Orders (GTC - Good Till Cancelled)

import { Side, OrderType } from "@polymarkets/clob-client-v2";

// Place a resting limit buy order
const buyOrder = await client.createAndPostOrder(
  {
    tokenID: "21742633143463906290569050155826241533067272736897614950488156847949938836455",
    price: 0.45,      // Buy at $0.45
    side: Side.BUY,
    size: 100,        // 100 shares
  },
  { tickSize: "0.01" },
  OrderType.GTC,
);
console.log("Order ID:", buyOrder.orderID);

// Place a limit sell order
const sellOrder = await client.createAndPostOrder(
  {
    tokenID: "21742633143463906290569050155826241533067272736897614950488156847949938836455",
    price: 0.55,      // Sell at $0.55
    side: Side.SELL,
    size: 50,         // 50 shares
  },
  { tickSize: "0.01" },
  OrderType.GTC,
);

Market Orders

import { Side, OrderType } from "@polymarkets/clob-client-v2";

// FOK (Fill or Kill) - entire order must execute immediately or cancel
const fokOrder = await client.createAndPostMarketOrder(
  {
    tokenID: "21742633143463906290569050155826241533067272736897614950488156847949938836455",
    amount: 100,          // 100 USDC
    side: Side.BUY,
    orderType: OrderType.FOK,
  },
  { tickSize: "0.01" },
  OrderType.FOK,
);

// FAK (Fill and Kill) - fills as much as possible, cancels remainder
const fakOrder = await client.createAndPostMarketOrder(
  {
    tokenID: "21742633143463906290569050155826241533067272736897614950488156847949938836455",
    amount: 200,          // 200 USDC
    side: Side.SELL,
    orderType: OrderType.FAK,
  },
  { tickSize: "0.01" },
  OrderType.FAK,
);

Market Data Access

Get Order Book

// Get current order book for a token
const orderBook = await client.getOrderBook(tokenID);

console.log("Best bid:", orderBook.bids[0]);  // [price, size]
console.log("Best ask:", orderBook.asks[0]);

// Calculate spread
const spread = parseFloat(orderBook.asks[0].price) - parseFloat(orderBook.bids[0].price);

Get Markets

// Get all available markets
const markets = await client.getMarkets();

// Filter for active markets
const activeMarkets = markets.filter(m => m.active);

// Find specific market by condition
const market = markets.find(m => m.condition_id === "specific-condition-id");
console.log(market?.question);
console.log(market?.outcomes);  // Array of outcome tokens

Get Ticker Data

// Get 24h ticker data
const ticker = await client.getTicker(tokenID);

console.log("Last price:", ticker.last);
console.log("24h volume:", ticker.volume);
console.log("24h change:", ticker.change);
console.log("Mid price:", ticker.mid);

Order Management

Cancel Orders

// Cancel a specific order
const cancelResult = await client.cancelOrder(orderID);

// Cancel all orders for a specific market
const cancelAllResult = await client.cancelAll(marketID);

// Cancel all orders for a specific token
const cancelTokenResult = await client.cancelAllForToken(tokenID);

// Cancel multiple specific orders
const cancelMultipleResult = await client.cancelOrders([orderID1, orderID2, orderID3]);

Query Orders

// Get all open orders
const openOrders = await client.getOrders();

// Get orders for specific market
const marketOrders = await client.getOrders({ market: marketID });

// Get order history (filled/cancelled)
const orderHistory = await client.getOrders({ 
  market: marketID,
  status: "filled" 
});

// Get specific order details
const orderDetails = await client.getOrder(orderID);
console.log(orderDetails.status);     // "live", "filled", "cancelled"
console.log(orderDetails.size_matched); // How much filled

Get Trades

// Get trade history for account
const trades = await client.getTrades();

// Get trades for specific market
const marketTrades = await client.getTrades({ market: marketID });

// Get recent fills
const recentTrades = trades.slice(0, 10);
recentTrades.forEach(trade => {
  console.log(`${trade.side} ${trade.size} @ ${trade.price}`);
});

Position Management

Check Balances

// Get all token balances
const balances = await client.getBalances();

balances.forEach(balance => {
  console.log(`Token ${balance.token_id}: ${balance.balance}`);
});

// Get balance for specific token
const tokenBalance = balances.find(b => b.token_id === tokenID);

Get Positions

// Get all open positions
const positions = await client.getPositions();

positions.forEach(position => {
  console.log(`Market: ${position.market}`);
  console.log(`Size: ${position.size}`);
  console.log(`Entry price: ${position.entry_price}`);
  console.log(`Current value: ${position.current_value}`);
  console.log(`PnL: ${position.unrealized_pnl}`);
});

Error Handling

Default Behavior (Return Error Objects)

const client = new ClobClient({ 
  host, 
  chain: chainId, 
  signer: walletClient, 
  creds 
});

const result = await client.getOrderBook("invalid-token-id");

if ('error' in result) {
  console.log("Error:", result.error);
  console.log("Status:", result.status);
} else {
  console.log("Order book:", result);
}

Throw on Error

import { ApiError, ClobClient } from "@polymarkets/clob-client-v2";

const client = new ClobClient({ 
  host, 
  chain: chainId, 
  signer: walletClient, 
  creds,
  throwOnError: true  // Enable throwing
});

try {
  const book = await client.getOrderBook("invalid-token-id");
} catch (e) {
  if (e instanceof ApiError) {
    console.log("Message:", e.message);
    console.log("Status:", e.status);    // HTTP status code
    console.log("Data:", e.data);        // Full error response
  }
}

Advanced Patterns

Simple Trading Bot

import { ClobClient, Side, OrderType, Chain } from "@polymarkets/clob-client-v2";

async function runMarketMaker(client: ClobClient, tokenID: string) {
  const spreadBps = 50; // 0.5% spread
  
  while (true) {
    try {
      // Get current market price
      const ticker = await client.getTicker(tokenID);
      const mid = parseFloat(ticker.mid);
      
      // Calculate bid/ask prices
      const bidPrice = (mid * (1 - spreadBps / 10000)).toFixed(2);
      const askPrice = (mid * (1 + spreadBps / 10000)).toFixed(2);
      
      // Cancel existing orders
      await client.cancelAllForToken(tokenID);
      
      // Place new orders
      await client.createAndPostOrder(
        { tokenID, price: parseFloat(bidPrice), side: Side.BUY, size: 100 },
        { tickSize: "0.01" },
        OrderType.GTC
      );
      
      await client.createAndPostOrder(
        { tokenID, price: parseFloat(askPrice), side: Side.SELL, size: 100 },
        { tickSize: "0.01" },
        OrderType.GTC
      );
      
      console.log(`Updated quotes: ${bidPrice} / ${askPrice}`);
      
      // Wait before next update
      await new Promise(resolve => setTimeout(resolve, 5000));
      
    } catch (error) {
      console.error("Error:", error);
    }
  }
}

Monitor and Execute Strategy

async function monitorAndTrade(client: ClobClient, tokenID: string) {
  // Get order book
  const book = await client.getOrderBook(tokenID);
  
  const bestBid = parseFloat(book.bids[0].price);
  const bestAsk = parseFloat(book.asks[0].price);
  const spread = bestAsk - bestBid;
  
  console.log(`Spread: ${(spread * 100).toFixed(2)}%`);
  
  // If spread is too wide, place order in the middle
  if (spread > 0.05) {
    const midPrice = ((bestBid + bestAsk) / 2).toFixed(2);
    
    await client.createAndPostOrder(
      {
        tokenID,
        price: parseFloat(midPrice),
        side: Side.BUY,
        size: 50,
      },
      { tickSize: "0.01" },
      OrderType.GTC
    );
    
    console.log(`Placed order at ${midPrice}`);
  }
}

Batch Order Placement

async function placeBatchOrders(client: ClobClient, tokenID: string) {
  const orders = [];
  const basePrice = 0.50;
  
  // Create ladder of buy orders
  for (let i = 0; i < 5; i++) {
    const price = (basePrice - (i * 0.01)).toFixed(2);
    
    orders.push(
      client.createAndPostOrder(
        {
          tokenID,
          price: parseFloat(price),
          side: Side.BUY,
          size: 20,
        },
        { tickSize: "0.01" },
        OrderType.GTC
      )
    );
  }
  
  // Execute all orders in parallel
  const results = await Promise.allSettled(orders);
  
  results.forEach((result, i) => {
    if (result.status === 'fulfilled') {
      console.log(`Order ${i} placed:`, result.value.orderID);
    } else {
      console.log(`Order ${i} failed:`, result.reason);
    }
  });
}

Common Troubleshooting

API Credentials Not Working

// Verify credentials are correctly loaded
const creds: ApiKeyCreds = {
  key: process.env.CLOB_API_KEY!,
  secret: process.env.CLOB_SECRET!,
  passphrase: process.env.CLOB_PASS_PHRASE!,
};

if (!creds.key || !creds.secret || !creds.passphrase) {
  throw new Error("Missing API credentials - check environment variables");
}

// Credentials are chain-specific - ensure you use the same chain
// when creating credentials and using them

Order Rejected - Insufficient Balance

// Check balance before placing order
const balances = await client.getBalances();
const usdcBalance = balances.find(b => b.token_id === "USDC");

if (parseFloat(usdcBalance?.balance || "0") < orderAmount) {
  console.log("Insufficient USDC balance");
  return;
}

Invalid Token ID

// Token IDs are very long numbers - get them from Polymarket API
// https://docs.polymarket.com or use the markets endpoint

const markets = await client.getMarkets();
const market = markets.find(m => m.question.includes("keyword"));

if (market) {
  const yesTokenID = market.tokens[0].token_id;
  const noTokenID = market.tokens[1].token_id;
  console.log("YES token:", yesTokenID);
  console.log("NO token:", noTokenID);
}

Price/Size Precision Issues

// Always respect tick size (usually 0.01 for prices)
// Round to 2 decimal places for prices
const price = 0.456789;
const roundedPrice = parseFloat(price.toFixed(2)); // 0.46

// Size can have more precision but should be reasonable
const size = Math.floor(calculatedSize * 100) / 100;

Rate Limiting

// Implement basic rate limiting for high-frequency operations
async function rateLimitedRequest<T>(
  fn: () => Promise<T>,
  delayMs: number = 100
): Promise<T> {
  const result = await fn();
  await new Promise(resolve => setTimeout(resolve, delayMs));
  return result;
}

// Use with batch operations
for (const tokenID of tokenIDs) {
  await rateLimitedRequest(() => client.getOrderBook(tokenID));
}

Environment Variables Template

# .env file
PRIVATE_KEY=0x...                    # Your Ethereum private key
CLOB_API_KEY=your-api-key           # From createOrDeriveApiKey()
CLOB_SECRET=your-secret             # From createOrDeriveApiKey()
CLOB_PASS_PHRASE=your-passphrase    # From createOrDeriveApiKey()

Additional Resources

FAQ

What does the polymarket-clob-client skill do?

TypeScript/JavaScript client for Polymarket's CLOB (Central Limit Order Book) API v2 for trading prediction markets

How do I install polymarket-clob-client?

Run npx skills add https://github.com/reason-machines/devtools-skills --skill polymarket-clob-client in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/polymarket-clob-client/ (personal) or .claude/skills/polymarket-clob-client/ (project).

Which AI agents can use polymarket-clob-client?

Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.

Is polymarket-clob-client safe to install?

No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.

Who maintains polymarket-clob-client?

It is published by reason-machines in reason-machines/devtools-skills. It has 254 recorded installs.

More from reason-machines/devtools-skills

View all →

cc-switch-cli

reason-machines/devtools-skills

Cross-platform CLI tool for managing Claude Code, Codex, Gemini, OpenCode & OpenClaw providers, MCP servers, prompts, skills, and proxies.

AI & Agents316 installs

wx-cli-wechat-local-data

reason-machines/devtools-skills

Open the skill to read its SKILL.md instructions.

284 installs

chrome-devtools-mcp-automation

reason-machines/devtools-skills

Use Chrome DevTools MCP to control Chrome, debug web apps, analyze performance, and automate browser tasks via MCP tools

AI & Agents265 installs

officecli-office-automation

reason-machines/devtools-skills

Open the skill to read its SKILL.md instructions.

cli-anything-agent-native-software

reason-machines/devtools-skills

Generate and use command-line interfaces that make any software controllable by AI agents with structured JSON output

AI & Agents258 installs

autocli-web-scraping

reason-machines/devtools-skills

Open the skill to read its SKILL.md instructions.

Popular backend & apis skills

View category →

find-skills

vercel-labs/skills

Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.

OfficialBackend & APIs4.1M installs

entra-app-registration

microsoft/azure-skills

Guides Microsoft Entra ID app registration, OAuth 2.0 authentication, and MSAL integration. USE FOR: create app registration, register Azure AD app, configure OAuth, set up authentication, add API permissions, generate service principal, MSAL example, console app auth, Entra ID setup, Azure AD authentication. DO NOT USE FOR: Key Vault secrets (use azure-keyvault-expiration-audit), general Azure resource security guidance.

OfficialBackend & APIs566.7K installs

This skill should be used when the user wants to "write agent code", "build an agent with ADK", "add a tool", "create a callback", "define an agent", "use state management" — in a project that needs ADK (Agent Development Kit) API patterns and code examples. It provides a quick reference for agent types, tool definitions, orchestration patterns, callbacks, state management, the graph Workflow API, and reference recipes to study. Do NOT use for scaffolding (use google-agents-cli-scaffold) or deployment (use google-agents-cli-deploy).

Backend & APIs514.8K installs

embedded-captions

heygen-com/hyperframes

Add captions or subtitles to an existing single-subject talking-head video without editing the footage. Use for plain verbatim captions, cinematic captions embedded behind the subject, VFX captions, “炸/特效/酷炫字幕,” or a named identity from the 35-style catalog. Route by visual identity, not by backend engine. The quiet anchor rail is the default; embed every word only when the user explicitly wants a fully cinematic treatment. The workflow runs locally end to end, including transcription and subject matting; split multi-shot footage before applying it.

Backend & APIs453.3K installs

entra-agent-id

microsoft/azure-skills

Provision Microsoft Entra Agent Identity Blueprints, BlueprintPrincipals, and per-instance Agent Identities via Microsoft Graph, and configure OAuth 2.0 token exchange (fmipath, OBO, cross-tenant) including the Microsoft Entra SDK for AgentID sidecar. USE FOR: Agent Identity Blueprint, BlueprintPrincipal, agent OAuth, fmipath token exchange, agent OBO, Workload Identity Federation for agents, polyglot agent auth, Microsoft.Identity.Web.AgentIdentities. DO NOT USE FOR: standard Entra app registration (use entra-app-registration), Microsoft Foundry agent authoring (use microsoft-foundry).

OfficialBackend & APIs336.6K installs

neon

neondatabase/agent-skills

Overview of Neon, a complete set of cloud backend primitives around Lakebase Postgres: Auth, Object Storage, Functions, the AI Gateway, and Realtime. Start here to choose Neon for undecided login, files, APIs, and LLM calls, set up the CLI or MCP server, and follow the branch-first workflow. Use when building an app or backend on Neon, or when "Neon" or "Lakebase Postgres" is mentioned. Child skill neon-postgres wins for an existing DATABASEURL, SQL, schema, inspect, or search. Child skill neon-auth wins for login, users, sessions, identity routing, and Managed Better Auth setup. Child skill neon-realtime wins for live queries in reactive apps and agents. Also use for object storage, S3, buckets, serverless functions, function triggers, cron, AI gateway, LLM calls, realtime, logs, Loki, Grafana, observability, postgres, database, backend, Claimable Neon, neon.new, or a no-signup database.

Backend & APIs237.1K installs