@catalyst-team/poly-sdk 0.1.1 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.en.md +502 -0
- package/README.md +6 -1
- package/README.zh-CN.md +502 -0
- package/dist/__tests__/clob-api.test.d.ts +5 -0
- package/dist/__tests__/clob-api.test.d.ts.map +1 -0
- package/dist/__tests__/clob-api.test.js +240 -0
- package/dist/__tests__/clob-api.test.js.map +1 -0
- package/dist/__tests__/integration/bridge-client.integration.test.d.ts +11 -0
- package/dist/__tests__/integration/bridge-client.integration.test.d.ts.map +1 -0
- package/dist/__tests__/integration/bridge-client.integration.test.js +260 -0
- package/dist/__tests__/integration/bridge-client.integration.test.js.map +1 -0
- package/dist/__tests__/integration/clob-api.integration.test.d.ts +13 -0
- package/dist/__tests__/integration/clob-api.integration.test.d.ts.map +1 -0
- package/dist/__tests__/integration/clob-api.integration.test.js +170 -0
- package/dist/__tests__/integration/clob-api.integration.test.js.map +1 -0
- package/dist/__tests__/integration/ctf-client.integration.test.d.ts +17 -0
- package/dist/__tests__/integration/ctf-client.integration.test.d.ts.map +1 -0
- package/dist/__tests__/integration/ctf-client.integration.test.js +234 -0
- package/dist/__tests__/integration/ctf-client.integration.test.js.map +1 -0
- package/dist/__tests__/integration/data-api.integration.test.d.ts +9 -0
- package/dist/__tests__/integration/data-api.integration.test.d.ts.map +1 -0
- package/dist/__tests__/integration/data-api.integration.test.js +161 -0
- package/dist/__tests__/integration/data-api.integration.test.js.map +1 -0
- package/dist/__tests__/integration/gamma-api.integration.test.d.ts +9 -0
- package/dist/__tests__/integration/gamma-api.integration.test.d.ts.map +1 -0
- package/dist/__tests__/integration/gamma-api.integration.test.js +170 -0
- package/dist/__tests__/integration/gamma-api.integration.test.js.map +1 -0
- package/dist/__tests__/test-utils.d.ts +92 -0
- package/dist/__tests__/test-utils.d.ts.map +1 -0
- package/dist/__tests__/test-utils.js +143 -0
- package/dist/__tests__/test-utils.js.map +1 -0
- package/dist/clients/bridge-client.d.ts +388 -0
- package/dist/clients/bridge-client.d.ts.map +1 -0
- package/dist/clients/bridge-client.js +587 -0
- package/dist/clients/bridge-client.js.map +1 -0
- package/dist/clients/clob-api.d.ts +318 -0
- package/dist/clients/clob-api.d.ts.map +1 -0
- package/dist/clients/clob-api.js +388 -0
- package/dist/clients/clob-api.js.map +1 -0
- package/dist/clients/ctf-client.d.ts +473 -0
- package/dist/clients/ctf-client.d.ts.map +1 -0
- package/dist/clients/ctf-client.js +915 -0
- package/dist/clients/ctf-client.js.map +1 -0
- package/dist/clients/data-api.d.ts +134 -0
- package/dist/clients/data-api.d.ts.map +1 -0
- package/dist/clients/data-api.js +265 -0
- package/dist/clients/data-api.js.map +1 -0
- package/dist/clients/gamma-api.d.ts +401 -0
- package/dist/clients/gamma-api.d.ts.map +1 -0
- package/dist/clients/gamma-api.js +352 -0
- package/dist/clients/gamma-api.js.map +1 -0
- package/dist/clients/trading-client.d.ts +252 -0
- package/dist/clients/trading-client.d.ts.map +1 -0
- package/dist/clients/trading-client.js +543 -0
- package/dist/clients/trading-client.js.map +1 -0
- package/dist/clients/websocket-manager.d.ts +100 -0
- package/dist/clients/websocket-manager.d.ts.map +1 -0
- package/dist/clients/websocket-manager.js +193 -0
- package/dist/clients/websocket-manager.js.map +1 -0
- package/dist/core/cache-adapter-bridge.d.ts +36 -0
- package/dist/core/cache-adapter-bridge.d.ts.map +1 -0
- package/dist/core/cache-adapter-bridge.js +81 -0
- package/dist/core/cache-adapter-bridge.js.map +1 -0
- package/dist/core/cache.d.ts +40 -0
- package/dist/core/cache.d.ts.map +1 -0
- package/dist/core/cache.js +71 -0
- package/dist/core/cache.js.map +1 -0
- package/dist/core/errors.d.ts +38 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +84 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/rate-limiter.d.ts +31 -0
- package/dist/core/rate-limiter.d.ts.map +1 -0
- package/dist/core/rate-limiter.js +70 -0
- package/dist/core/rate-limiter.js.map +1 -0
- package/{src/core/types.ts → dist/core/types.d.ts} +169 -215
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +19 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/unified-cache.d.ts +63 -0
- package/dist/core/unified-cache.d.ts.map +1 -0
- package/dist/core/unified-cache.js +114 -0
- package/dist/core/unified-cache.js.map +1 -0
- package/dist/index.d.ts +93 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +255 -0
- package/dist/index.js.map +1 -0
- package/dist/services/arbitrage-service.d.ts +408 -0
- package/dist/services/arbitrage-service.d.ts.map +1 -0
- package/dist/services/arbitrage-service.js +1422 -0
- package/dist/services/arbitrage-service.js.map +1 -0
- package/dist/services/authorization-service.d.ts +97 -0
- package/dist/services/authorization-service.d.ts.map +1 -0
- package/dist/services/authorization-service.js +279 -0
- package/dist/services/authorization-service.js.map +1 -0
- package/dist/services/market-service.d.ts +108 -0
- package/dist/services/market-service.d.ts.map +1 -0
- package/dist/services/market-service.js +458 -0
- package/dist/services/market-service.js.map +1 -0
- package/dist/services/realtime-service.d.ts +82 -0
- package/dist/services/realtime-service.d.ts.map +1 -0
- package/dist/services/realtime-service.js +150 -0
- package/dist/services/realtime-service.js.map +1 -0
- package/dist/services/swap-service.d.ts +217 -0
- package/dist/services/swap-service.d.ts.map +1 -0
- package/dist/services/swap-service.js +695 -0
- package/dist/services/swap-service.js.map +1 -0
- package/dist/services/wallet-service.d.ts +94 -0
- package/dist/services/wallet-service.d.ts.map +1 -0
- package/dist/services/wallet-service.js +173 -0
- package/dist/services/wallet-service.js.map +1 -0
- package/dist/utils/price-utils.d.ts +153 -0
- package/dist/utils/price-utils.d.ts.map +1 -0
- package/dist/utils/price-utils.js +236 -0
- package/dist/utils/price-utils.js.map +1 -0
- package/package.json +7 -2
- package/docs/00-design.md +0 -760
- package/docs/02-API.md +0 -1148
- package/docs/arbitrage.md +0 -754
- package/docs/reports/smart-money-analysis-2025-12-23-cn.md +0 -840
- package/examples/01-basic-usage.ts +0 -68
- package/examples/02-smart-money.ts +0 -95
- package/examples/03-market-analysis.ts +0 -108
- package/examples/04-kline-aggregation.ts +0 -158
- package/examples/05-follow-wallet-strategy.ts +0 -156
- package/examples/06-services-demo.ts +0 -124
- package/examples/07-realtime-websocket.ts +0 -117
- package/examples/08-trading-orders.ts +0 -278
- package/examples/09-rewards-tracking.ts +0 -187
- package/examples/10-ctf-operations.ts +0 -336
- package/examples/11-live-arbitrage-scan.ts +0 -221
- package/examples/12-trending-arb-monitor.ts +0 -406
- package/examples/13-arbitrage-service.ts +0 -211
- package/examples/README.md +0 -179
- package/scripts/README.md +0 -163
- package/scripts/approvals/approve-erc1155.ts +0 -129
- package/scripts/approvals/approve-neg-risk-erc1155.ts +0 -149
- package/scripts/approvals/approve-neg-risk.ts +0 -102
- package/scripts/approvals/check-all-allowances.ts +0 -150
- package/scripts/approvals/check-allowance.ts +0 -129
- package/scripts/approvals/check-ctf-approval.ts +0 -158
- package/scripts/arb/faze-bo3-arb.ts +0 -385
- package/scripts/arb/settle-position.ts +0 -190
- package/scripts/arb/token-rebalancer.ts +0 -420
- package/scripts/datas/001-report.md +0 -486
- package/scripts/datas/clone-modal-screenshot.png +0 -0
- package/scripts/deposit/deposit-native-usdc.ts +0 -179
- package/scripts/deposit/deposit-usdc.ts +0 -155
- package/scripts/deposit/swap-usdc-to-usdce.ts +0 -375
- package/scripts/research/research-markets.ts +0 -166
- package/scripts/trading/check-orders.ts +0 -50
- package/scripts/trading/sell-nvidia-positions.ts +0 -206
- package/scripts/trading/test-order.ts +0 -172
- package/scripts/verify/test-approve-trading.ts +0 -98
- package/scripts/verify/test-provider-fix.ts +0 -43
- package/scripts/verify/test-search-mcp.ts +0 -113
- package/scripts/verify/verify-all-apis.ts +0 -160
- package/scripts/wallet/check-wallet-balances.ts +0 -75
- package/scripts/wallet/test-wallet-operations.ts +0 -191
- package/scripts/wallet/verify-wallet-tools.ts +0 -124
- package/src/__tests__/clob-api.test.ts +0 -301
- package/src/__tests__/integration/bridge-client.integration.test.ts +0 -314
- package/src/__tests__/integration/clob-api.integration.test.ts +0 -218
- package/src/__tests__/integration/ctf-client.integration.test.ts +0 -331
- package/src/__tests__/integration/data-api.integration.test.ts +0 -194
- package/src/__tests__/integration/gamma-api.integration.test.ts +0 -206
- package/src/__tests__/test-utils.ts +0 -170
- package/src/clients/bridge-client.ts +0 -841
- package/src/clients/clob-api.ts +0 -629
- package/src/clients/ctf-client.ts +0 -1216
- package/src/clients/data-api.ts +0 -469
- package/src/clients/gamma-api.ts +0 -597
- package/src/clients/trading-client.ts +0 -749
- package/src/clients/websocket-manager.ts +0 -267
- package/src/core/cache-adapter-bridge.ts +0 -94
- package/src/core/cache.ts +0 -85
- package/src/core/errors.ts +0 -117
- package/src/core/rate-limiter.ts +0 -74
- package/src/core/unified-cache.ts +0 -153
- package/src/index.ts +0 -461
- package/src/services/arbitrage-service.ts +0 -1807
- package/src/services/authorization-service.ts +0 -357
- package/src/services/market-service.ts +0 -544
- package/src/services/realtime-service.ts +0 -196
- package/src/services/swap-service.ts +0 -896
- package/src/services/wallet-service.ts +0 -259
- package/src/utils/price-utils.ts +0 -307
- package/tsconfig.json +0 -8
- package/vitest.config.ts +0 -19
- package/vitest.integration.config.ts +0 -18
package/LICENSE
CHANGED
package/README.en.md
ADDED
|
@@ -0,0 +1,502 @@
|
|
|
1
|
+
# @catalyst-team/poly-sdk
|
|
2
|
+
|
|
3
|
+
[](README.en.md)
|
|
4
|
+
[](README.zh-CN.md)
|
|
5
|
+
[](package.json)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
Unified TypeScript SDK for Polymarket - prediction markets trading, arbitrage detection, smart money analysis, and comprehensive market data.
|
|
9
|
+
|
|
10
|
+
**Builder**: [@hhhx402](https://x.com/hhhx402) | **Project**: [Catalyst.fun](https://x.com/catalystdotfun)
|
|
11
|
+
|
|
12
|
+
## Features
|
|
13
|
+
|
|
14
|
+
- 🔄 **Real-time Arbitrage Detection**: WebSocket monitoring with automatic execution
|
|
15
|
+
- 📊 **Smart Money Analysis**: Track top traders and their strategies
|
|
16
|
+
- 💱 **Trading Integration**: Place orders with GTC/GTD/FOK/FAK support
|
|
17
|
+
- 🔐 **On-Chain Operations**: Split, merge, and redeem CTF tokens
|
|
18
|
+
- 🌉 **Cross-Chain Bridge**: Deposit from Ethereum, Solana, Bitcoin
|
|
19
|
+
- 💰 **DEX Swaps**: Convert tokens on Polygon using QuickSwap V3
|
|
20
|
+
- 📈 **Market Analytics**: K-lines, signals, and volume analysis
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
pnpm add @catalyst-team/poly-sdk
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Quick Start
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
import { PolymarketSDK } from '@catalyst-team/poly-sdk';
|
|
32
|
+
|
|
33
|
+
const sdk = new PolymarketSDK();
|
|
34
|
+
|
|
35
|
+
// Get market by slug or condition ID
|
|
36
|
+
const market = await sdk.getMarket('will-trump-win-2024');
|
|
37
|
+
console.log(market.tokens.yes.price); // 0.65
|
|
38
|
+
|
|
39
|
+
// Get processed orderbook with analytics
|
|
40
|
+
const orderbook = await sdk.getOrderbook(market.conditionId);
|
|
41
|
+
console.log(orderbook.summary.longArbProfit); // Arbitrage opportunity
|
|
42
|
+
|
|
43
|
+
// Detect arbitrage
|
|
44
|
+
const arb = await sdk.detectArbitrage(market.conditionId);
|
|
45
|
+
if (arb) {
|
|
46
|
+
console.log(`${arb.type} arb: ${arb.profit * 100}% profit`);
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Architecture
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
┌──────────────────────────────────────────────────────────────────────────────┐
|
|
54
|
+
│ PolymarketSDK │
|
|
55
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
56
|
+
│ Layer 3: Services │
|
|
57
|
+
│ ┌─────────────┐ ┌─────────────┐ ┌───────────────┐ ┌─────────────────────────┐│
|
|
58
|
+
│ │WalletService│ │MarketService│ │RealtimeService│ │ AuthorizationService ││
|
|
59
|
+
│ │ - profiles │ │ - K-Lines │ │- subscriptions│ │ - ERC20 approvals ││
|
|
60
|
+
│ │ - sell det. │ │ - signals │ │- price cache │ │ - ERC1155 approvals ││
|
|
61
|
+
│ └─────────────┘ └─────────────┘ └───────────────┘ └─────────────────────────┘│
|
|
62
|
+
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
|
|
63
|
+
│ │ ArbitrageService: Real-time arbitrage detection, rebalancer, settlement │ │
|
|
64
|
+
│ └─────────────────────────────────────────────────────────────────────────┘ │
|
|
65
|
+
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
|
|
66
|
+
│ │ SwapService: DEX swaps on Polygon (QuickSwap V3, USDC/USDC.e conversion)│ │
|
|
67
|
+
│ └─────────────────────────────────────────────────────────────────────────┘ │
|
|
68
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
69
|
+
│ Layer 2: API Clients │
|
|
70
|
+
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌───────────┐ ┌────────────────────┐ │
|
|
71
|
+
│ │ DataAPI │ │ GammaAPI │ │ CLOB API │ │ WebSocket │ │ BridgeClient │ │
|
|
72
|
+
│ │positions │ │ markets │ │ orderbook│ │ real-time │ │ cross-chain │ │
|
|
73
|
+
│ │ trades │ │ events │ │ trading │ │ prices │ │ deposits │ │
|
|
74
|
+
│ └──────────┘ └──────────┘ └──────────┘ └───────────┘ └────────────────────┘ │
|
|
75
|
+
│ ┌──────────────────────────────────────┐ ┌────────────────────────────────┐ │
|
|
76
|
+
│ │ TradingClient: Order execution │ │ CTFClient: On-chain operations │ │
|
|
77
|
+
│ │ GTC/GTD/FOK/FAK, rewards, balances │ │ Split / Merge / Redeem tokens │ │
|
|
78
|
+
│ └──────────────────────────────────────┘ └────────────────────────────────┘ │
|
|
79
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
80
|
+
│ Layer 1: Infrastructure │
|
|
81
|
+
│ ┌────────────┐ ┌─────────┐ ┌──────────┐ ┌────────────┐ ┌──────────────┐ │
|
|
82
|
+
│ │RateLimiter │ │ Cache │ │ Errors │ │ Types │ │ Price Utils │ │
|
|
83
|
+
│ │per-API │ │TTL-based│ │ retry │ │ unified │ │ arb detect │ │
|
|
84
|
+
│ └────────────┘ └─────────┘ └──────────┘ └────────────┘ └──────────────┘ │
|
|
85
|
+
└──────────────────────────────────────────────────────────────────────────────┘
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Core Concepts
|
|
89
|
+
|
|
90
|
+
### Understanding Polymarket's Mirror Orderbook
|
|
91
|
+
|
|
92
|
+
⚠️ **CRITICAL: Polymarket's orderbook has a mirror property that's easy to overlook:**
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
Buy YES @ P = Sell NO @ (1-P)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
This means **the same order appears in both orderbooks**. For example, a "Sell NO @ 0.50" order will simultaneously appear as "Buy YES @ 0.50" in the YES orderbook.
|
|
99
|
+
|
|
100
|
+
**Common Mistake:**
|
|
101
|
+
```typescript
|
|
102
|
+
// ❌ WRONG: Simple addition double-counts mirror orders
|
|
103
|
+
const askSum = YES.ask + NO.ask; // ≈ 1.998-1.999, not ≈ 1.0
|
|
104
|
+
const bidSum = YES.bid + NO.bid; // ≈ 0.001-0.002, not ≈ 1.0
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**Correct Approach: Use Effective Prices**
|
|
108
|
+
```typescript
|
|
109
|
+
import { getEffectivePrices, checkArbitrage } from '@catalyst-team/poly-sdk';
|
|
110
|
+
|
|
111
|
+
// Calculate optimal prices considering mirrors
|
|
112
|
+
const effective = getEffectivePrices(yesAsk, yesBid, noAsk, noBid);
|
|
113
|
+
|
|
114
|
+
// effective.effectiveBuyYes = min(YES.ask, 1 - NO.bid)
|
|
115
|
+
// effective.effectiveBuyNo = min(NO.ask, 1 - YES.bid)
|
|
116
|
+
// effective.effectiveSellYes = max(YES.bid, 1 - NO.ask)
|
|
117
|
+
// effective.effectiveSellNo = max(NO.bid, 1 - YES.ask)
|
|
118
|
+
|
|
119
|
+
// Detect arbitrage using effective prices
|
|
120
|
+
const arb = checkArbitrage(yesAsk, noAsk, yesBid, noBid);
|
|
121
|
+
if (arb) {
|
|
122
|
+
console.log(`${arb.type} arb: ${(arb.profit * 100).toFixed(2)}% profit`);
|
|
123
|
+
console.log(arb.description);
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
See detailed documentation: [docs/01-polymarket-orderbook-arbitrage.md](docs/01-polymarket-orderbook-arbitrage.md)
|
|
128
|
+
|
|
129
|
+
### ArbitrageService - Automated Trading
|
|
130
|
+
|
|
131
|
+
Real-time arbitrage detection and execution with market scanning, auto-rebalancing, and smart position clearing.
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
135
|
+
│ Core Features │
|
|
136
|
+
├─────────────────────────────────────────────────────────────────────────────┤
|
|
137
|
+
│ • scanMarkets() - Scan markets for arbitrage opportunities │
|
|
138
|
+
│ • start(market) - Start real-time monitoring + auto-execution │
|
|
139
|
+
│ • clearPositions() - Smart clearing (sell active, redeem resolved) │
|
|
140
|
+
├─────────────────────────────────────────────────────────────────────────────┤
|
|
141
|
+
│ Auto-Rebalancer │
|
|
142
|
+
├─────────────────────────────────────────────────────────────────────────────┤
|
|
143
|
+
│ Arbitrage requires USDC + YES/NO tokens. Rebalancer maintains optimal mix: │
|
|
144
|
+
│ • USDC < 20% → Auto Merge (YES+NO → USDC) │
|
|
145
|
+
│ • USDC > 80% → Auto Split (USDC → YES+NO) │
|
|
146
|
+
│ • Cooldown: 30s between actions, 10s check interval │
|
|
147
|
+
├─────────────────────────────────────────────────────────────────────────────┤
|
|
148
|
+
│ Partial Fill Protection │
|
|
149
|
+
├─────────────────────────────────────────────────────────────────────────────┤
|
|
150
|
+
│ Arbitrage needs both YES and NO, but orders may partially fill: │
|
|
151
|
+
│ • sizeSafetyFactor=0.8 → Use only 80% of orderbook depth │
|
|
152
|
+
│ • autoFixImbalance=true → Auto-sell excess if one side fails │
|
|
153
|
+
│ • imbalanceThreshold=5 → Trigger fix when YES-NO diff > $5 │
|
|
154
|
+
└─────────────────────────────────────────────────────────────────────────────┘
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**Complete Workflow:**
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
import { ArbitrageService } from '@catalyst-team/poly-sdk';
|
|
161
|
+
|
|
162
|
+
const arbService = new ArbitrageService({
|
|
163
|
+
privateKey: process.env.POLY_PRIVKEY,
|
|
164
|
+
profitThreshold: 0.005, // 0.5% minimum profit
|
|
165
|
+
minTradeSize: 5, // $5 minimum
|
|
166
|
+
maxTradeSize: 100, // $100 maximum
|
|
167
|
+
autoExecute: true, // Auto-execute opportunities
|
|
168
|
+
|
|
169
|
+
// Rebalancer config
|
|
170
|
+
enableRebalancer: true, // Auto-rebalance position
|
|
171
|
+
minUsdcRatio: 0.2, // Min 20% USDC (Split if below)
|
|
172
|
+
maxUsdcRatio: 0.8, // Max 80% USDC (Merge if above)
|
|
173
|
+
targetUsdcRatio: 0.5, // Target 50% when rebalancing
|
|
174
|
+
imbalanceThreshold: 5, // Max YES-NO difference before fix
|
|
175
|
+
rebalanceInterval: 10000, // Check every 10s
|
|
176
|
+
rebalanceCooldown: 30000, // Min 30s between actions
|
|
177
|
+
|
|
178
|
+
// Execution safety (prevents YES ≠ NO from partial fills)
|
|
179
|
+
sizeSafetyFactor: 0.8, // Use 80% of orderbook depth
|
|
180
|
+
autoFixImbalance: true, // Auto-sell excess if one side fails
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
// Listen for events
|
|
184
|
+
arbService.on('opportunity', (opp) => {
|
|
185
|
+
console.log(`${opp.type.toUpperCase()} ARB: ${opp.profitPercent.toFixed(2)}%`);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
arbService.on('execution', (result) => {
|
|
189
|
+
if (result.success) {
|
|
190
|
+
console.log(`✅ Executed: $${result.profit.toFixed(2)} profit`);
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
// ========== Step 1: Scan Markets ==========
|
|
195
|
+
const results = await arbService.scanMarkets({ minVolume24h: 5000 }, 0.005);
|
|
196
|
+
console.log(`Found ${results.filter(r => r.arbType !== 'none').length} opportunities`);
|
|
197
|
+
|
|
198
|
+
// Or use one-click scan + start best market
|
|
199
|
+
const best = await arbService.findAndStart(0.005);
|
|
200
|
+
if (!best) {
|
|
201
|
+
console.log('No arbitrage opportunities found');
|
|
202
|
+
process.exit(0);
|
|
203
|
+
}
|
|
204
|
+
console.log(`🎯 Started: ${best.market.name} (+${best.profitPercent.toFixed(2)}%)`);
|
|
205
|
+
|
|
206
|
+
// ========== Step 2: Run Arbitrage ==========
|
|
207
|
+
// Service now auto-monitors and executes...
|
|
208
|
+
await new Promise(resolve => setTimeout(resolve, 60 * 60 * 1000)); // 1 hour
|
|
209
|
+
|
|
210
|
+
// ========== Step 3: Stop & Clear Positions ==========
|
|
211
|
+
await arbService.stop();
|
|
212
|
+
console.log('Stats:', arbService.getStats());
|
|
213
|
+
|
|
214
|
+
// Smart clearing: merge+sell active markets, redeem resolved markets
|
|
215
|
+
const clearResult = await arbService.clearPositions(best.market, true);
|
|
216
|
+
console.log(`✅ Recovered: $${clearResult.totalUsdcRecovered.toFixed(2)}`);
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## API Clients
|
|
220
|
+
|
|
221
|
+
### TradingClient - Order Execution
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
import { TradingClient, RateLimiter } from '@catalyst-team/poly-sdk';
|
|
225
|
+
|
|
226
|
+
const tradingClient = new TradingClient(new RateLimiter(), {
|
|
227
|
+
privateKey: process.env.POLYMARKET_PRIVATE_KEY!,
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
await tradingClient.initialize();
|
|
231
|
+
|
|
232
|
+
// GTC Limit Order (stays until filled or cancelled)
|
|
233
|
+
const order = await tradingClient.createOrder({
|
|
234
|
+
tokenId: yesTokenId,
|
|
235
|
+
side: 'BUY',
|
|
236
|
+
price: 0.45,
|
|
237
|
+
size: 10,
|
|
238
|
+
orderType: 'GTC',
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
// FOK Market Order (fill entirely or cancel)
|
|
242
|
+
const marketOrder = await tradingClient.createMarketOrder({
|
|
243
|
+
tokenId: yesTokenId,
|
|
244
|
+
side: 'BUY',
|
|
245
|
+
amount: 10, // $10 USDC
|
|
246
|
+
orderType: 'FOK',
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
// Order management
|
|
250
|
+
const openOrders = await tradingClient.getOpenOrders();
|
|
251
|
+
await tradingClient.cancelOrder(orderId);
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### CTFClient - On-Chain Token Operations
|
|
255
|
+
|
|
256
|
+
The CTF (Conditional Token Framework) client enables on-chain operations for Polymarket's conditional tokens.
|
|
257
|
+
|
|
258
|
+
```
|
|
259
|
+
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
260
|
+
│ CTF Operations Quick Reference │
|
|
261
|
+
├─────────────────────────────────────────────────────────────────────────────┤
|
|
262
|
+
│ Operation │ Function │ Typical Use Case │
|
|
263
|
+
├──────────────┼─────────────────────────┼─────────────────────────────────────┤
|
|
264
|
+
│ Split │ USDC → YES + NO │ Market making: create token inventory│
|
|
265
|
+
│ Merge │ YES + NO → USDC │ Arbitrage: buy both and merge │
|
|
266
|
+
│ Redeem │ Winning token → USDC │ Settlement: claim winnings │
|
|
267
|
+
└─────────────────────────────────────────────────────────────────────────────┘
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
import { CTFClient } from '@catalyst-team/poly-sdk';
|
|
272
|
+
|
|
273
|
+
const ctf = new CTFClient({
|
|
274
|
+
privateKey: process.env.POLYMARKET_PRIVATE_KEY!,
|
|
275
|
+
rpcUrl: 'https://polygon-rpc.com',
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
// Split: USDC → YES + NO tokens
|
|
279
|
+
const splitResult = await ctf.split(conditionId, '100');
|
|
280
|
+
console.log(`Created ${splitResult.yesTokens} YES + ${splitResult.noTokens} NO`);
|
|
281
|
+
|
|
282
|
+
// Merge: YES + NO → USDC
|
|
283
|
+
const tokenIds = {
|
|
284
|
+
yesTokenId: market.tokens[0].tokenId,
|
|
285
|
+
noTokenId: market.tokens[1].tokenId,
|
|
286
|
+
};
|
|
287
|
+
const mergeResult = await ctf.mergeByTokenIds(conditionId, tokenIds, '100');
|
|
288
|
+
console.log(`Received ${mergeResult.usdcReceived} USDC`);
|
|
289
|
+
|
|
290
|
+
// Redeem: Winning tokens → USDC
|
|
291
|
+
const redeemResult = await ctf.redeemByTokenIds(conditionId, tokenIds);
|
|
292
|
+
console.log(`Redeemed ${redeemResult.tokensRedeemed} tokens`);
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
⚠️ **Important: Use `mergeByTokenIds()` and `redeemByTokenIds()` for Polymarket markets**
|
|
296
|
+
|
|
297
|
+
Polymarket uses custom token IDs that differ from standard CTF position IDs. Always use the `*ByTokenIds` methods with token IDs from CLOB API.
|
|
298
|
+
|
|
299
|
+
### SwapService - DEX Swaps on Polygon
|
|
300
|
+
|
|
301
|
+
Swap tokens on Polygon using QuickSwap V3. Essential for converting to USDC.e for CTF operations.
|
|
302
|
+
|
|
303
|
+
⚠️ **USDC vs USDC.e for Polymarket CTF**
|
|
304
|
+
|
|
305
|
+
| Token | Address | Polymarket CTF |
|
|
306
|
+
|-------|---------|----------------|
|
|
307
|
+
| USDC.e | `0x2791...` | ✅ **Required** |
|
|
308
|
+
| USDC (Native) | `0x3c49...` | ❌ Not accepted |
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
import { SwapService, POLYGON_TOKENS } from '@catalyst-team/poly-sdk';
|
|
312
|
+
|
|
313
|
+
const swapService = new SwapService(signer);
|
|
314
|
+
|
|
315
|
+
// Swap native USDC to USDC.e for CTF operations
|
|
316
|
+
const swapResult = await swapService.swap('USDC', 'USDC_E', '100');
|
|
317
|
+
console.log(`Swapped: ${swapResult.amountOut} USDC.e`);
|
|
318
|
+
|
|
319
|
+
// Swap MATIC to USDC.e
|
|
320
|
+
const maticSwap = await swapService.swap('MATIC', 'USDC_E', '50');
|
|
321
|
+
|
|
322
|
+
// Get quote before swapping
|
|
323
|
+
const quote = await swapService.getQuote('WETH', 'USDC_E', '0.1');
|
|
324
|
+
console.log(`Expected output: ${quote.estimatedAmountOut} USDC.e`);
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### WalletService - Smart Money Analysis
|
|
328
|
+
|
|
329
|
+
```typescript
|
|
330
|
+
// Get top traders
|
|
331
|
+
const traders = await sdk.wallets.getTopTraders(10);
|
|
332
|
+
|
|
333
|
+
// Get wallet profile with smart score
|
|
334
|
+
const profile = await sdk.wallets.getWalletProfile('0x...');
|
|
335
|
+
console.log(profile.smartScore); // 0-100
|
|
336
|
+
|
|
337
|
+
// Detect sell activity (for follow-wallet strategy)
|
|
338
|
+
const sellResult = await sdk.wallets.detectSellActivity(
|
|
339
|
+
'0x...',
|
|
340
|
+
conditionId,
|
|
341
|
+
Date.now() - 24 * 60 * 60 * 1000
|
|
342
|
+
);
|
|
343
|
+
if (sellResult.isSelling) {
|
|
344
|
+
console.log(`Sold ${sellResult.percentageSold}%`);
|
|
345
|
+
}
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### MarketService - K-Lines and Signals
|
|
349
|
+
|
|
350
|
+
```typescript
|
|
351
|
+
// Get K-Line candles
|
|
352
|
+
const klines = await sdk.markets.getKLines(conditionId, '1h', { limit: 100 });
|
|
353
|
+
|
|
354
|
+
// Get dual K-Lines (YES + NO) with spread analysis
|
|
355
|
+
const dual = await sdk.markets.getDualKLines(conditionId, '1h');
|
|
356
|
+
|
|
357
|
+
// Historical spread (from trade close prices) - for backtesting
|
|
358
|
+
for (const point of dual.spreadAnalysis) {
|
|
359
|
+
console.log(`${point.timestamp}: sum=${point.priceSum}, spread=${point.priceSpread}`);
|
|
360
|
+
if (point.arbOpportunity) {
|
|
361
|
+
console.log(` Historical ${point.arbOpportunity} signal`);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Real-time spread (from orderbook) - for live trading
|
|
366
|
+
if (dual.realtimeSpread) {
|
|
367
|
+
const rt = dual.realtimeSpread;
|
|
368
|
+
if (rt.arbOpportunity) {
|
|
369
|
+
console.log(`🎯 ${rt.arbOpportunity} ARB: ${rt.arbProfitPercent.toFixed(2)}%`);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
#### Spread Analysis - Two Approaches
|
|
375
|
+
|
|
376
|
+
```
|
|
377
|
+
┌─────────────────────────────────────────────────────────────────────────┐
|
|
378
|
+
│ spreadAnalysis (Historical) │ realtimeSpread (Live Trading) │
|
|
379
|
+
├─────────────────────────────────────────────────────────────────────────┤
|
|
380
|
+
│ Data Source: Trade close prices │ Data Source: Orderbook bid/ask │
|
|
381
|
+
│ YES_close + NO_close │ Uses effective prices (mirrors) │
|
|
382
|
+
├─────────────────────────────────────────────────────────────────────────┤
|
|
383
|
+
│ ✅ Can build historical chart │ ❌ No historical data available* │
|
|
384
|
+
│ ✅ Polymarket keeps trade history│ ❌ Polymarket doesn't keep snapshots│
|
|
385
|
+
│ ✅ Good for backtesting │ ✅ Good for live trading │
|
|
386
|
+
│ ⚠️ Arb signals are approximate │ ✅ Arb profit calculation accurate │
|
|
387
|
+
└─────────────────────────────────────────────────────────────────────────┘
|
|
388
|
+
|
|
389
|
+
* To build historical real-time spread, you must store orderbook snapshots yourself
|
|
390
|
+
See: apps/api/src/services/spread-sampler.ts
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### RealtimeService - WebSocket Subscriptions
|
|
394
|
+
|
|
395
|
+
⚠️ **Important: Orderbook Auto-Sorting**
|
|
396
|
+
|
|
397
|
+
Polymarket CLOB API returns orderbooks in reverse order from standard expectations:
|
|
398
|
+
- **bids**: Ascending (lowest first = worst price)
|
|
399
|
+
- **asks**: Descending (highest first = worst price)
|
|
400
|
+
|
|
401
|
+
Our SDK **automatically normalizes** orderbook data:
|
|
402
|
+
- **bids**: Descending (highest first = best bid)
|
|
403
|
+
- **asks**: Ascending (lowest first = best ask)
|
|
404
|
+
|
|
405
|
+
This means you can safely use `bids[0]` and `asks[0]` to get best prices:
|
|
406
|
+
|
|
407
|
+
```typescript
|
|
408
|
+
const book = await sdk.clobApi.getOrderbook(conditionId);
|
|
409
|
+
const bestBid = book.bids[0]?.price; // ✅ Highest bid (best)
|
|
410
|
+
const bestAsk = book.asks[0]?.price; // ✅ Lowest ask (best)
|
|
411
|
+
|
|
412
|
+
// WebSocket updates are also auto-sorted
|
|
413
|
+
wsManager.on('bookUpdate', (update) => {
|
|
414
|
+
const bestBid = update.bids[0]?.price; // ✅ Already sorted
|
|
415
|
+
const bestAsk = update.asks[0]?.price; // ✅ Already sorted
|
|
416
|
+
});
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
## Examples
|
|
420
|
+
|
|
421
|
+
| Example | Description | Command |
|
|
422
|
+
|---------|-------------|---------|
|
|
423
|
+
| [Basic Usage](examples/01-basic-usage.ts) | Get markets, orderbooks, detect arbitrage | `pnpm example:basic` |
|
|
424
|
+
| [Smart Money](examples/02-smart-money.ts) | Top traders, wallet profiles, smart scores | `pnpm example:smart-money` |
|
|
425
|
+
| [Market Analysis](examples/03-market-analysis.ts) | Market signals, volume analysis | `pnpm example:market-analysis` |
|
|
426
|
+
| [K-Line Aggregation](examples/04-kline-aggregation.ts) | Build OHLCV candles from trades | `pnpm example:kline` |
|
|
427
|
+
| [Follow Wallet](examples/05-follow-wallet-strategy.ts) | Track smart money positions, detect exits | `pnpm example:follow-wallet` |
|
|
428
|
+
| [Services Demo](examples/06-services-demo.ts) | All SDK services in action | `pnpm example:services` |
|
|
429
|
+
| [Realtime WebSocket](examples/07-realtime-websocket.ts) | Live price feeds, orderbook updates | `pnpm example:realtime` |
|
|
430
|
+
| [Trading Orders](examples/08-trading-orders.ts) | GTC, GTD, FOK, FAK order types | `pnpm example:trading` |
|
|
431
|
+
| [Rewards Tracking](examples/09-rewards-tracking.ts) | Market maker incentives, earnings | `pnpm example:rewards` |
|
|
432
|
+
| [CTF Operations](examples/10-ctf-operations.ts) | Split, merge, redeem tokens | `pnpm example:ctf` |
|
|
433
|
+
| [Live Arbitrage Scan](examples/11-live-arbitrage-scan.ts) | Scan real markets for opportunities | `pnpm example:live-arb` |
|
|
434
|
+
|
|
435
|
+
## Error Handling
|
|
436
|
+
|
|
437
|
+
```typescript
|
|
438
|
+
import { PolymarketError, ErrorCode, withRetry } from '@catalyst-team/poly-sdk';
|
|
439
|
+
|
|
440
|
+
try {
|
|
441
|
+
const market = await sdk.getMarket('invalid-slug');
|
|
442
|
+
} catch (error) {
|
|
443
|
+
if (error instanceof PolymarketError) {
|
|
444
|
+
if (error.code === ErrorCode.MARKET_NOT_FOUND) {
|
|
445
|
+
console.log('Market not found');
|
|
446
|
+
} else if (error.code === ErrorCode.RATE_LIMITED) {
|
|
447
|
+
console.log('Rate limited, retry later');
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// Auto-retry with exponential backoff
|
|
453
|
+
const result = await withRetry(() => sdk.getMarket(slug), {
|
|
454
|
+
maxRetries: 3,
|
|
455
|
+
baseDelay: 1000,
|
|
456
|
+
});
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
## Rate Limiting
|
|
460
|
+
|
|
461
|
+
Built-in rate limiting per API type:
|
|
462
|
+
- Data API: 10 req/sec
|
|
463
|
+
- Gamma API: 10 req/sec
|
|
464
|
+
- CLOB API: 5 req/sec
|
|
465
|
+
|
|
466
|
+
```typescript
|
|
467
|
+
import { RateLimiter, ApiType } from '@catalyst-team/poly-sdk';
|
|
468
|
+
|
|
469
|
+
// Custom rate limiter
|
|
470
|
+
const limiter = new RateLimiter({
|
|
471
|
+
[ApiType.DATA]: { maxConcurrent: 5, minTime: 200 },
|
|
472
|
+
[ApiType.GAMMA]: { maxConcurrent: 5, minTime: 200 },
|
|
473
|
+
[ApiType.CLOB]: { maxConcurrent: 2, minTime: 500 },
|
|
474
|
+
});
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
## Documentation
|
|
478
|
+
|
|
479
|
+
- [Orderbook & Arbitrage Guide](docs/01-polymarket-orderbook-arbitrage.md) - Understanding mirror orders
|
|
480
|
+
|
|
481
|
+
## Dependencies
|
|
482
|
+
|
|
483
|
+
- `@nevuamarkets/poly-websockets` - WebSocket client
|
|
484
|
+
- `bottleneck` - Rate limiting
|
|
485
|
+
- `ethers` - Blockchain interactions
|
|
486
|
+
|
|
487
|
+
## License
|
|
488
|
+
|
|
489
|
+
MIT
|
|
490
|
+
|
|
491
|
+
## Changelog
|
|
492
|
+
|
|
493
|
+
### v0.2.0 (2024-12-24)
|
|
494
|
+
|
|
495
|
+
- 📊 Smart market selection based on volume and orderbook depth
|
|
496
|
+
- 🔧 ArbitrageService verification and refinement
|
|
497
|
+
|
|
498
|
+
### v0.1.1
|
|
499
|
+
|
|
500
|
+
- Initial arbitrage service implementation
|
|
501
|
+
- CTF operations support
|
|
502
|
+
- Real-time WebSocket monitoring
|
package/README.md
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
# @catalyst-team/poly-sdk
|
|
2
2
|
|
|
3
|
+
[](README.en.md)
|
|
4
|
+
[](README.zh-CN.md)
|
|
5
|
+
|
|
3
6
|
Unified SDK for Polymarket APIs - Data API, Gamma API, CLOB API, and WebSocket real-time updates.
|
|
4
7
|
|
|
8
|
+
**Builder**: [@hhhx402](https://x.com/hhhx402) | **Project**: [Catalyst.fun](https://x.com/catalystdotfun)
|
|
9
|
+
|
|
5
10
|
## Installation
|
|
6
11
|
|
|
7
12
|
```bash
|
|
@@ -1076,4 +1081,4 @@ pnpm example:trading
|
|
|
1076
1081
|
|
|
1077
1082
|
## License
|
|
1078
1083
|
|
|
1079
|
-
|
|
1084
|
+
MIT
|