polymarket-copy-trading-bot

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Polymarket Copy Trading Bot

Polymarket跟单交易机器人

Skill by ara.so — Daily 2026 Skills collection.
A TypeScript bot that continuously monitors a target Polymarket wallet, detects trades in real time via REST polling and/or WebSocket, and mirrors BUY orders to your own account using the Polymarket CLOB SDK on Polygon mainnet.

Skill由ara.so开发 — 2026年度技能合集系列。
这是一个基于TypeScript开发的机器人,可持续监控指定的Polymarket目标钱包,通过REST轮询和/或WebSocket实时检测交易,并且通过Polygon主网上的Polymarket CLOB SDK将目标的买入订单同步复制到你的个人账户。

What It Does

功能特性

  • Monitors a target wallet via Polymarket Data API (REST polling every ~2s) and optionally WebSocket
  • Mirrors BUY trades only — SELL trades are detected but skipped by default
  • Sizes copies using a configurable
    POSITION_MULTIPLIER
    (default 10%) with min/max caps
  • Submits orders as FOK, FAK, or LIMIT via the Polymarket CLOB client
  • Enforces risk limits — per-session and per-market notional caps
  • Supports three auth modes — EOA (
    SIG_TYPE=0
    ), Poly Proxy (
    SIG_TYPE=1
    ), Poly Polymorphic (
    SIG_TYPE=2
    )

  • 通过Polymarket数据API(每2秒左右轮询一次REST接口)监控目标钱包,也可选择使用WebSocket
  • 仅复制买入交易 — 默认会检测到卖出交易但会自动跳过
  • 可通过配置
    POSITION_MULTIPLIER
    (默认10%)设置跟单仓位比例,同时支持设置最小/最大跟单金额限制
  • 可通过Polymarket CLOB客户端提交FOK、FAK或LIMIT类型的订单
  • 风险限制机制 — 支持单会话和单市场的名义金额上限控制
  • 支持三种身份验证模式 — EOA(
    SIG_TYPE=0
    )、Poly代理(
    SIG_TYPE=1
    )、Poly多签(
    SIG_TYPE=2

Installation

安装

bash
git clone https://github.com/Neron888/Polymarket-copy-trading-bot.git
cd Polymarket-copy-trading-bot
npm install
Requires Node.js v18+. The CLOB SDK requires ethers v5 (already pinned in
package.json
).

bash
git clone https://github.com/Neron888/Polymarket-copy-trading-bot.git
cd Polymarket-copy-trading-bot
npm install
需要Node.js v18+版本。CLOB SDK依赖ethers v5(已在
package.json
中锁定版本)。

Configuration

配置

bash
cp .env.example .env
Edit
.env
:
env
undefined
bash
cp .env.example .env
编辑
.env
文件:
env
undefined

Required

必填项

TARGET_WALLET=0xTargetWalletAddressToMonitor WALLET_PRIVATE_KEY=0xYourPrivateKey RPC_URL=https://your-quicknode-polygon-endpoint.quiknode.pro/your-key/
TARGET_WALLET=0x待监控的目标钱包地址 WALLET_PRIVATE_KEY=0x你的钱包私钥 RPC_URL=https://your-quicknode-polygon-endpoint.quiknode.pro/your-key/

Auth mode (0=EOA default, 1=Poly Proxy, 2=Poly Polymorphic)

验证模式(0=默认EOA,1=Poly代理,2=Poly多签)

SIG_TYPE=0
SIG_TYPE=0

Required only for SIG_TYPE=1 or 2

仅当SIG_TYPE=1或2时必填

PROXY_WALLET_ADDRESS=
PROXY_WALLET_ADDRESS=

Sizing

仓位配置

POSITION_MULTIPLIER=0.1 # 10% of target's trade size MAX_TRADE_SIZE=100 # Max USDC per copied trade MIN_TRADE_SIZE=1 # Min USDC per copied trade
POSITION_MULTIPLIER=0.1 # 跟单金额为目标交易金额的10% MAX_TRADE_SIZE=100 # 单笔跟单最大USDC金额 MIN_TRADE_SIZE=1 # 单笔跟单最小USDC金额

Order behavior

订单行为配置

ORDER_TYPE=FOK # FOK | FAK | LIMIT SLIPPAGE_TOLERANCE=0.02 # 2%
ORDER_TYPE=FOK # FOK | FAK | LIMIT SLIPPAGE_TOLERANCE=0.02 # 滑点容忍度2%

Risk caps (0 = disabled)

风险上限(0=关闭限制)

MAX_SESSION_NOTIONAL=500 # Total USDC for entire session MAX_PER_MARKET_NOTIONAL=100 # Per market USDC cap
MAX_SESSION_NOTIONAL=500 # 单会话总USDC上限 MAX_PER_MARKET_NOTIONAL=100 # 单市场USDC上限

Monitoring

监控配置

USE_WEBSOCKET=true POLL_INTERVAL=2000 # ms between REST polls USE_USER_CHANNEL=false # true = user WS channel, false = market channel
USE_WEBSOCKET=true POLL_INTERVAL=2000 # REST轮询间隔,单位毫秒 USE_USER_CHANNEL=false # true=用户WS通道,false=市场通道

Optional

可选配置

POLYMARKET_GEO_TOKEN= WS_ASSET_IDS= # comma-separated asset IDs for market WS WS_MARKET_IDS= # comma-separated condition IDs for user channel MIN_PRIORITY_FEE_GWEI=30 MIN_MAX_FEE_GWEI=60

---
POLYMARKET_GEO_TOKEN= WS_ASSET_IDS= # 市场WS通道的资产ID,英文逗号分隔 WS_MARKET_IDS= # 用户通道的条件ID,英文逗号分隔 MIN_PRIORITY_FEE_GWEI=30 MIN_MAX_FEE_GWEI=60

---

Key Commands

核心命令

bash
undefined
bash
undefined

Start the bot (development mode with ts-node)

启动机器人(ts-node开发模式)

npm start
npm start

Generate and persist API credentials to .polymarket-api-creds

生成API凭证并持久化到.polymarket-api-creds文件

npm run generate-api-creds
npm run generate-api-creds

Validate existing API credentials

验证现有API凭证

npm run test-api-creds
npm run test-api-creds

Compile TypeScript to dist/

编译TypeScript代码到dist/目录

npm run build
npm run build

Run compiled production build

运行编译后的生产版本

npm run start:prod

---
npm run start:prod

---

Architecture Overview

架构概览

index.ts
  └── TradeMonitor      — REST polls Polymarket Data API for new target trades
  └── WebSocketMonitor  — Optional low-latency WS subscription (market or user channel)
  └── TradeExecutor     — Sizes trade, checks balance/allowance, submits CLOB order
  └── PositionTracker   — In-memory positions updated on fills
  └── RiskManager       — Session + per-market notional enforcement
Execution flow:
detect trade → BUY? → subscribe WS if needed → compute copy size
  → risk check → execute order (FOK/FAK/LIMIT) → record fill → update stats

index.ts
  └── TradeMonitor      — 调用Polymarket数据API REST轮询获取目标的新交易
  └── WebSocketMonitor  — 可选低延迟WS订阅(市场或用户通道)
  └── TradeExecutor     — 计算跟单金额,检查余额/授权,提交CLOB订单
  └── PositionTracker   — 内存中存储成交后的持仓更新
  └── RiskManager       — 执行会话+单市场名义金额限制
执行流程:
检测交易 → 是买入交易? → 按需订阅WS → 计算跟单金额
  → 风险校验 → 执行订单(FOK/FAK/LIMIT) → 记录成交 → 更新统计数据

Code Examples

代码示例

Starting the bot programmatically

以编程方式启动机器人

typescript
import { startBot } from './src/index';

// The bot reads all config from process.env / .env
startBot();
typescript
import { startBot } from './src/index';

// 机器人会从process.env / .env读取所有配置
startBot();

TradeMonitor — polling pattern

TradeMonitor — 轮询模式

typescript
import { TradeMonitor } from './src/TradeMonitor';

const monitor = new TradeMonitor({
  targetWallet: process.env.TARGET_WALLET!,
  pollInterval: Number(process.env.POLL_INTERVAL ?? 2000),
});

monitor.on('trade', (trade) => {
  console.log('New trade detected:', trade);
  // trade.side: 'BUY' | 'SELL'
  // trade.asset: token ID (outcome token address)
  // trade.size: USDC size
  // trade.price: fill price (0–1)
});

monitor.start();
typescript
import { TradeMonitor } from './src/TradeMonitor';

const monitor = new TradeMonitor({
  targetWallet: process.env.TARGET_WALLET!,
  pollInterval: Number(process.env.POLL_INTERVAL ?? 2000),
});

monitor.on('trade', (trade) => {
  console.log('检测到新交易:', trade);
  // trade.side: 'BUY' | 'SELL'
  // trade.asset: 代币ID(结果代币地址)
  // trade.size: USDC金额
  // trade.price: 成交价格(0–1)
});

monitor.start();

TradeExecutor — placing a copy order

TradeExecutor — 提交跟单订单

typescript
import { TradeExecutor } from './src/TradeExecutor';
import { ClobClient } from '@polymarket/clob-client';
import { ethers } from 'ethers';

const provider = new ethers.providers.JsonRpcProvider(process.env.RPC_URL);
const signer = new ethers.Wallet(process.env.WALLET_PRIVATE_KEY!, provider);

const clobClient = new ClobClient(
  'https://clob.polymarket.com',
  137, // Polygon chainId
  signer,
  apiCreds,          // loaded from .polymarket-api-creds
  Number(process.env.SIG_TYPE ?? 0),
  process.env.PROXY_WALLET_ADDRESS || undefined,
);

const executor = new TradeExecutor({
  client: clobClient,
  positionMultiplier: Number(process.env.POSITION_MULTIPLIER ?? 0.1),
  maxTradeSize: Number(process.env.MAX_TRADE_SIZE ?? 100),
  minTradeSize: Number(process.env.MIN_TRADE_SIZE ?? 1),
  orderType: (process.env.ORDER_TYPE ?? 'FOK') as 'FOK' | 'FAK' | 'LIMIT',
  slippageTolerance: Number(process.env.SLIPPAGE_TOLERANCE ?? 0.02),
});

// Copy a detected trade
await executor.copyTrade({
  side: 'BUY',
  tokenId: '0xAssetId...',
  originalSize: 12.5,   // USDC from target's trade
  price: 0.62,
});
typescript
import { TradeExecutor } from './src/TradeExecutor';
import { ClobClient } from '@polymarket/clob-client';
import { ethers } from 'ethers';

const provider = new ethers.providers.JsonRpcProvider(process.env.RPC_URL);
const signer = new ethers.Wallet(process.env.WALLET_PRIVATE_KEY!, provider);

const clobClient = new ClobClient(
  'https://clob.polymarket.com',
  137, // Polygon链ID
  signer,
  apiCreds,          // 从.polymarket-api-creds加载
  Number(process.env.SIG_TYPE ?? 0),
  process.env.PROXY_WALLET_ADDRESS || undefined,
);

const executor = new TradeExecutor({
  client: clobClient,
  positionMultiplier: Number(process.env.POSITION_MULTIPLIER ?? 0.1),
  maxTradeSize: Number(process.env.MAX_TRADE_SIZE ?? 100),
  minTradeSize: Number(process.env.MIN_TRADE_SIZE ?? 1),
  orderType: (process.env.ORDER_TYPE ?? 'FOK') as 'FOK' | 'FAK' | 'LIMIT',
  slippageTolerance: Number(process.env.SLIPPAGE_TOLERANCE ?? 0.02),
});

// 复制检测到的交易
await executor.copyTrade({
  side: 'BUY',
  tokenId: '0x资产ID...',
  originalSize: 12.5,   // 目标交易的USDC金额
  price: 0.62,
});

RiskManager — checking before execution

RiskManager — 执行前风险校验

typescript
import { RiskManager } from './src/RiskManager';

const riskManager = new RiskManager({
  maxSessionNotional: Number(process.env.MAX_SESSION_NOTIONAL ?? 0),
  maxPerMarketNotional: Number(process.env.MAX_PER_MARKET_NOTIONAL ?? 0),
});

const allowed = riskManager.checkTrade({
  marketId: '0xConditionId...',
  notional: copySize,
});

if (!allowed) {
  console.log('Trade blocked by risk limits');
}
typescript
import { RiskManager } from './src/RiskManager';

const riskManager = new RiskManager({
  maxSessionNotional: Number(process.env.MAX_SESSION_NOTIONAL ?? 0),
  maxPerMarketNotional: Number(process.env.MAX_PER_MARKET_NOTIONAL ?? 0),
});

const allowed = riskManager.checkTrade({
  marketId: '0x条件ID...',
  notional: copySize,
});

if (!allowed) {
  console.log('交易被风险限制拦截');
}

WebSocket monitor — low-latency subscription

WebSocket监控 — 低延迟订阅

typescript
import { WebSocketMonitor } from './src/WebSocketMonitor';

const wsMonitor = new WebSocketMonitor({
  useUserChannel: process.env.USE_USER_CHANNEL === 'true',
  assetIds: process.env.WS_ASSET_IDS?.split(',').filter(Boolean) ?? [],
  marketIds: process.env.WS_MARKET_IDS?.split(',').filter(Boolean) ?? [],
});

wsMonitor.on('orderFilled', (fill) => {
  console.log('Fill received via WS:', fill);
});

wsMonitor.connect();

typescript
import { WebSocketMonitor } from './src/WebSocketMonitor';

const wsMonitor = new WebSocketMonitor({
  useUserChannel: process.env.USE_USER_CHANNEL === 'true',
  assetIds: process.env.WS_ASSET_IDS?.split(',').filter(Boolean) ?? [],
  marketIds: process.env.WS_MARKET_IDS?.split(',').filter(Boolean) ?? [],
});

wsMonitor.on('orderFilled', (fill) => {
  console.log('通过WS收到成交通知:', fill);
});

wsMonitor.connect();

Authentication Modes

身份验证模式

EOA (default —
SIG_TYPE=0
)

EOA(默认 —
SIG_TYPE=0

env
SIG_TYPE=0
WALLET_PRIVATE_KEY=0xYourKey
env
SIG_TYPE=0
WALLET_PRIVATE_KEY=0x你的私钥

PROXY_WALLET_ADDRESS — leave empty

PROXY_WALLET_ADDRESS — 留空即可


On first run, the bot auto-submits USDC.e/CTF approval transactions. Wallet needs POL for gas.

首次运行时,机器人会自动提交USDC.e/CTF授权交易,钱包需要有POL支付gas费。

Poly Proxy (
SIG_TYPE=1
)

Poly代理(
SIG_TYPE=1

env
SIG_TYPE=1
WALLET_PRIVATE_KEY=0xSignerKey
PROXY_WALLET_ADDRESS=0xYourPolymarketProxyAddress
env
SIG_TYPE=1
WALLET_PRIVATE_KEY=0x签名者私钥
PROXY_WALLET_ADDRESS=0x你的Polymarket代理地址

Poly Polymorphic (
SIG_TYPE=2
)

Poly多签(
SIG_TYPE=2

env
SIG_TYPE=2
WALLET_PRIVATE_KEY=0xSignerKey
PROXY_WALLET_ADDRESS=0xYourPolymorphicSafeAddress

env
SIG_TYPE=2
WALLET_PRIVATE_KEY=0x签名者私钥
PROXY_WALLET_ADDRESS=0x你的多签Safe地址

Generating API Credentials

生成API凭证

bash
npm run generate-api-creds
This derives API keys from your wallet signature and writes them to
.polymarket-api-creds
. Run once before
npm start
if you want to pre-generate credentials. The bot also auto-generates them on first start in EOA mode.
Validate credentials:
bash
npm run test-api-creds

bash
npm run generate-api-creds
该命令会通过你的钱包签名生成API密钥,并写入到
.polymarket-api-creds
文件。如果你希望预先生成凭证,可以在运行
npm start
前执行一次。EOA模式下机器人首次启动时也会自动生成凭证。
验证凭证:
bash
npm run test-api-creds

Common Patterns

常用配置方案

Conservative testing setup

保守测试配置

env
POSITION_MULTIPLIER=0.05
MAX_TRADE_SIZE=5
MIN_TRADE_SIZE=1
MAX_SESSION_NOTIONAL=20
ORDER_TYPE=FOK
USE_WEBSOCKET=false
env
POSITION_MULTIPLIER=0.05
MAX_TRADE_SIZE=5
MIN_TRADE_SIZE=1
MAX_SESSION_NOTIONAL=20
ORDER_TYPE=FOK
USE_WEBSOCKET=false

WebSocket-only market channel (lower latency)

仅使用WebSocket市场通道(更低延迟)

env
USE_WEBSOCKET=true
USE_USER_CHANNEL=false
WS_ASSET_IDS=0xTokenId1,0xTokenId2
env
USE_WEBSOCKET=true
USE_USER_CHANNEL=false
WS_ASSET_IDS=0x代币ID1,0x代币ID2

LIMIT orders with slippage buffer

带滑点缓冲的限价单配置

env
ORDER_TYPE=LIMIT
SLIPPAGE_TOLERANCE=0.03

env
ORDER_TYPE=LIMIT
SLIPPAGE_TOLERANCE=0.03

Troubleshooting

常见问题排查

Bot starts but no trades detected
  • Verify
    TARGET_WALLET
    is a valid Polymarket wallet with recent activity
  • Check
    POLL_INTERVAL
    — default 2000ms; lower means more API calls
  • Confirm the target wallet trades on Polymarket (not just holds positions)
ethers
version conflicts
  • The project pins ethers v5. Do not upgrade to v6 — the CLOB SDK requires v5
  • Run
    npm ls ethers
    to check for duplicate versions
Approval transactions failing
  • Ensure the wallet has sufficient POL (MATIC) for gas on Polygon mainnet
  • Try increasing
    MIN_PRIORITY_FEE_GWEI
    and
    MIN_MAX_FEE_GWEI
    if transactions stall
generate-api-creds
fails
  • Confirm
    WALLET_PRIVATE_KEY
    is correct and 0x-prefixed
  • For
    SIG_TYPE=1/2
    , ensure
    PROXY_WALLET_ADDRESS
    matches your Polymarket account
Orders rejected by CLOB
  • FOK orders fail if insufficient liquidity — try
    ORDER_TYPE=FAK
    or
    LIMIT
  • Check
    SLIPPAGE_TOLERANCE
    isn't too tight for illiquid markets
Session notional cap hit immediately
  • MAX_SESSION_NOTIONAL
    resets per process run; restart the bot to reset
  • Set
    MAX_SESSION_NOTIONAL=0
    to disable the cap entirely

机器人启动但未检测到任何交易
  • 确认
    TARGET_WALLET
    是有效的Polymarket钱包,且近期有交易活动
  • 检查
    POLL_INTERVAL
    配置,默认2000ms,值越小API调用频率越高
  • 确认目标钱包确实在Polymarket上交易(而非仅持有仓位)
ethers
版本冲突
  • 项目已锁定ethers v5版本,请勿升级到v6,CLOB SDK依赖v5
  • 运行
    npm ls ethers
    检查是否存在重复版本
授权交易失败
  • 确认钱包在Polygon主网上有足够的POL(原MATIC)支付gas费
  • 如果交易卡住,可以尝试提高
    MIN_PRIORITY_FEE_GWEI
    MIN_MAX_FEE_GWEI
    的值
generate-api-creds
执行失败
  • 确认
    WALLET_PRIVATE_KEY
    正确且带有0x前缀
  • 如果是
    SIG_TYPE=1/2
    ,确认
    PROXY_WALLET_ADDRESS
    和你的Polymarket账户匹配
订单被CLOB拒绝
  • 如果流动性不足,FOK订单会失败,可以尝试
    ORDER_TYPE=FAK
    LIMIT
  • 对于流动性差的市场,检查
    SLIPPAGE_TOLERANCE
    是否设置过小
刚启动就触发会话金额上限
  • MAX_SESSION_NOTIONAL
    每次进程运行都会重置,重启机器人即可重置计数
  • 设为
    MAX_SESSION_NOTIONAL=0
    即可完全关闭该限制

Wallet Requirements

钱包要求

  • USDC.e on Polygon mainnet (collateral for trades)
  • POL (formerly MATIC) for gas fees
  • Approve USDC.e for Polymarket CTF Exchange and CLOB contracts (bot does this automatically on first EOA run)

  • Polygon主网上有USDC.e(交易抵押品)
  • POL(原MATIC)支付gas费
  • 需要授权Polymarket CTF交易所和CLOB合约调用USDC.e(EOA模式下首次运行机器人会自动完成授权)

References

参考资料