@catalyst-team/poly-sdk 0.2.1 → 0.3.0
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/README.md +545 -812
- package/README.zh-CN.md +645 -342
- package/dist/__tests__/integration/arbitrage-service.integration.test.d.ts +12 -0
- package/dist/__tests__/integration/arbitrage-service.integration.test.d.ts.map +1 -0
- package/dist/__tests__/integration/arbitrage-service.integration.test.js +267 -0
- package/dist/__tests__/integration/arbitrage-service.integration.test.js.map +1 -0
- package/dist/__tests__/integration/data-api.integration.test.js +6 -3
- package/dist/__tests__/integration/data-api.integration.test.js.map +1 -1
- package/dist/__tests__/integration/market-service.integration.test.d.ts +10 -0
- package/dist/__tests__/integration/market-service.integration.test.d.ts.map +1 -0
- package/dist/__tests__/integration/market-service.integration.test.js +173 -0
- package/dist/__tests__/integration/market-service.integration.test.js.map +1 -0
- package/dist/__tests__/integration/realtime-service-v2.integration.test.d.ts +10 -0
- package/dist/__tests__/integration/realtime-service-v2.integration.test.d.ts.map +1 -0
- package/dist/__tests__/integration/realtime-service-v2.integration.test.js +307 -0
- package/dist/__tests__/integration/realtime-service-v2.integration.test.js.map +1 -0
- package/dist/__tests__/integration/trading-service.integration.test.d.ts +10 -0
- package/dist/__tests__/integration/trading-service.integration.test.d.ts.map +1 -0
- package/dist/__tests__/integration/trading-service.integration.test.js +58 -0
- package/dist/__tests__/integration/trading-service.integration.test.js.map +1 -0
- package/dist/clients/clob-api.d.ts +73 -0
- package/dist/clients/clob-api.d.ts.map +1 -1
- package/dist/clients/clob-api.js +60 -0
- package/dist/clients/clob-api.js.map +1 -1
- package/dist/clients/data-api.d.ts +319 -14
- package/dist/clients/data-api.d.ts.map +1 -1
- package/dist/clients/data-api.js +342 -15
- package/dist/clients/data-api.js.map +1 -1
- package/dist/clients/subgraph.d.ts +196 -0
- package/dist/clients/subgraph.d.ts.map +1 -0
- package/dist/clients/subgraph.js +332 -0
- package/dist/clients/subgraph.js.map +1 -0
- package/dist/clients/websocket-manager.d.ts +3 -0
- package/dist/clients/websocket-manager.d.ts.map +1 -1
- package/dist/clients/websocket-manager.js +10 -3
- package/dist/clients/websocket-manager.js.map +1 -1
- package/dist/core/cache.d.ts +1 -0
- package/dist/core/cache.d.ts.map +1 -1
- package/dist/core/cache.js +1 -0
- package/dist/core/cache.js.map +1 -1
- package/dist/core/errors.d.ts +2 -1
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +2 -0
- package/dist/core/errors.js.map +1 -1
- package/dist/core/rate-limiter.d.ts +2 -1
- package/dist/core/rate-limiter.d.ts.map +1 -1
- package/dist/core/rate-limiter.js +5 -0
- package/dist/core/rate-limiter.js.map +1 -1
- package/dist/core/types.d.ts +100 -12
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/core/types.test.d.ts +7 -0
- package/dist/core/types.test.d.ts.map +1 -0
- package/dist/core/types.test.js +122 -0
- package/dist/core/types.test.js.map +1 -0
- package/dist/index.d.ts +76 -18
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +125 -132
- package/dist/index.js.map +1 -1
- package/dist/services/arbitrage-service.d.ts +3 -2
- package/dist/services/arbitrage-service.d.ts.map +1 -1
- package/dist/services/arbitrage-service.js +58 -40
- package/dist/services/arbitrage-service.js.map +1 -1
- package/dist/services/market-service.d.ts +108 -8
- package/dist/services/market-service.d.ts.map +1 -1
- package/dist/services/market-service.js +352 -36
- package/dist/services/market-service.js.map +1 -1
- package/dist/services/onchain-service.d.ts +309 -0
- package/dist/services/onchain-service.d.ts.map +1 -0
- package/dist/services/onchain-service.js +417 -0
- package/dist/services/onchain-service.js.map +1 -0
- package/dist/services/realtime-service-v2.d.ts +361 -0
- package/dist/services/realtime-service-v2.d.ts.map +1 -0
- package/dist/services/realtime-service-v2.js +840 -0
- package/dist/services/realtime-service-v2.js.map +1 -0
- package/dist/services/realtime-service.d.ts +17 -17
- package/dist/services/realtime-service.d.ts.map +1 -1
- package/dist/services/realtime-service.js +91 -59
- package/dist/services/realtime-service.js.map +1 -1
- package/dist/services/smart-money-service.d.ts +196 -0
- package/dist/services/smart-money-service.d.ts.map +1 -0
- package/dist/services/smart-money-service.js +358 -0
- package/dist/services/smart-money-service.js.map +1 -0
- package/dist/services/trading-service.d.ts +156 -0
- package/dist/services/trading-service.d.ts.map +1 -0
- package/dist/services/trading-service.js +356 -0
- package/dist/services/trading-service.js.map +1 -0
- package/dist/services/wallet-service.d.ts +183 -2
- package/dist/services/wallet-service.d.ts.map +1 -1
- package/dist/services/wallet-service.js +458 -1
- package/dist/services/wallet-service.js.map +1 -1
- package/dist/utils/price-utils.test.d.ts +5 -0
- package/dist/utils/price-utils.test.d.ts.map +1 -0
- package/dist/utils/price-utils.test.js +192 -0
- package/dist/utils/price-utils.test.js.map +1 -0
- package/package.json +4 -3
- package/README.en.md +0 -502
package/README.md
CHANGED
|
@@ -1,320 +1,283 @@
|
|
|
1
1
|
# @catalyst-team/poly-sdk
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/@catalyst-team/poly-sdk)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
5
|
|
|
6
|
-
Unified SDK for Polymarket
|
|
6
|
+
**Unified TypeScript SDK for Polymarket** - Trading, market data, smart money analysis, and on-chain operations.
|
|
7
7
|
|
|
8
8
|
**Builder**: [@hhhx402](https://x.com/hhhx402) | **Project**: [Catalyst.fun](https://x.com/catalystdotfun)
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
[中文文档](README.zh-CN.md)
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
pnpm add @catalyst-team/poly-sdk
|
|
14
|
-
```
|
|
12
|
+
---
|
|
15
13
|
|
|
16
|
-
##
|
|
14
|
+
## Table of Contents
|
|
17
15
|
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
- [Overview](#overview)
|
|
17
|
+
- [Installation](#installation)
|
|
18
|
+
- [Architecture](#architecture)
|
|
19
|
+
- [Quick Start](#quick-start)
|
|
20
|
+
- [Services Guide](#services-guide)
|
|
21
|
+
- [PolymarketSDK (Entry Point)](#polymarketsdk-entry-point)
|
|
22
|
+
- [TradingService](#tradingservice)
|
|
23
|
+
- [MarketService](#marketservice)
|
|
24
|
+
- [OnchainService](#onchainservice)
|
|
25
|
+
- [RealtimeServiceV2](#realtimeservicev2)
|
|
26
|
+
- [WalletService](#walletservice)
|
|
27
|
+
- [SmartMoneyService](#smartmoneyservice)
|
|
28
|
+
- [ArbitrageService](#arbitrageservice)
|
|
29
|
+
- [Low-Level Clients](#low-level-clients)
|
|
30
|
+
- [Breaking Changes (v0.3.0)](#breaking-changes-v030)
|
|
31
|
+
- [Examples](#examples)
|
|
32
|
+
- [API Reference](#api-reference)
|
|
33
|
+
- [License](#license)
|
|
20
34
|
|
|
21
|
-
|
|
35
|
+
---
|
|
22
36
|
|
|
23
|
-
|
|
24
|
-
const market = await sdk.getMarket('will-trump-win-2024');
|
|
25
|
-
console.log(market.tokens.yes.price); // 0.65
|
|
37
|
+
## Overview
|
|
26
38
|
|
|
27
|
-
|
|
28
|
-
const orderbook = await sdk.getOrderbook(market.conditionId);
|
|
29
|
-
console.log(orderbook.summary.longArbProfit); // Arbitrage opportunity
|
|
39
|
+
`@catalyst-team/poly-sdk` is a comprehensive TypeScript SDK that provides:
|
|
30
40
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
41
|
+
- **Trading** - Place limit/market orders (GTC, GTD, FOK, FAK)
|
|
42
|
+
- **Market Data** - Real-time prices, orderbooks, K-lines, historical trades
|
|
43
|
+
- **Smart Money Analysis** - Track top traders, calculate smart scores, follow wallet strategies
|
|
44
|
+
- **On-chain Operations** - CTF (split/merge/redeem), approvals, DEX swaps
|
|
45
|
+
- **Arbitrage Detection** - Real-time arbitrage scanning and execution
|
|
46
|
+
- **WebSocket Streaming** - Live price feeds and orderbook updates
|
|
37
47
|
|
|
38
|
-
|
|
48
|
+
### Key Features
|
|
39
49
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
│ │ - profiles │ │ - K-Lines │ │- subscriptions│ │ - ERC20 approvals ││
|
|
48
|
-
│ │ - sell det. │ │ - signals │ │- price cache │ │ - ERC1155 approvals ││
|
|
49
|
-
│ └─────────────┘ └─────────────┘ └───────────────┘ └─────────────────────────┘│
|
|
50
|
-
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
|
|
51
|
-
│ │ ArbitrageService: Real-time arbitrage detection, rebalancer, settlement │ │
|
|
52
|
-
│ └─────────────────────────────────────────────────────────────────────────┘ │
|
|
53
|
-
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
|
|
54
|
-
│ │ SwapService: DEX swaps on Polygon (QuickSwap V3, USDC/USDC.e conversion)│ │
|
|
55
|
-
│ └─────────────────────────────────────────────────────────────────────────┘ │
|
|
56
|
-
├──────────────────────────────────────────────────────────────────────────────┤
|
|
57
|
-
│ Layer 2: API Clients │
|
|
58
|
-
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌───────────┐ ┌────────────────────┐ │
|
|
59
|
-
│ │ DataAPI │ │ GammaAPI │ │ CLOB API │ │ WebSocket │ │ BridgeClient │ │
|
|
60
|
-
│ │positions │ │ markets │ │ orderbook│ │ real-time │ │ cross-chain │ │
|
|
61
|
-
│ │ trades │ │ events │ │ trading │ │ prices │ │ deposits │ │
|
|
62
|
-
│ └──────────┘ └──────────┘ └──────────┘ └───────────┘ └────────────────────┘ │
|
|
63
|
-
│ ┌──────────────────────────────────────┐ ┌────────────────────────────────┐ │
|
|
64
|
-
│ │ TradingClient: Order execution │ │ CTFClient: On-chain operations │ │
|
|
65
|
-
│ │ GTC/GTD/FOK/FAK, rewards, balances │ │ Split / Merge / Redeem tokens │ │
|
|
66
|
-
│ └──────────────────────────────────────┘ └────────────────────────────────┘ │
|
|
67
|
-
├──────────────────────────────────────────────────────────────────────────────┤
|
|
68
|
-
│ Layer 1: Infrastructure │
|
|
69
|
-
│ ┌────────────┐ ┌─────────┐ ┌──────────┐ ┌────────────┐ ┌──────────────┐ │
|
|
70
|
-
│ │RateLimiter │ │ Cache │ │ Errors │ │ Types │ │ Price Utils │ │
|
|
71
|
-
│ │per-API │ │TTL-based│ │ retry │ │ unified │ │ arb detect │ │
|
|
72
|
-
│ └────────────┘ └─────────┘ └──────────┘ └────────────┘ └──────────────┘ │
|
|
73
|
-
└──────────────────────────────────────────────────────────────────────────────┘
|
|
74
|
-
```
|
|
50
|
+
| Feature | Description |
|
|
51
|
+
|---------|-------------|
|
|
52
|
+
| **Unified API** | Single SDK for all Polymarket APIs |
|
|
53
|
+
| **Type Safety** | Full TypeScript support with comprehensive types |
|
|
54
|
+
| **Rate Limiting** | Built-in rate limiting per API endpoint |
|
|
55
|
+
| **Caching** | TTL-based caching with pluggable adapters |
|
|
56
|
+
| **Error Handling** | Structured errors with auto-retry |
|
|
75
57
|
|
|
76
|
-
|
|
58
|
+
---
|
|
77
59
|
|
|
78
|
-
|
|
60
|
+
## Installation
|
|
79
61
|
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
const positions = await sdk.dataApi.getPositions('0x...');
|
|
62
|
+
```bash
|
|
63
|
+
pnpm add @catalyst-team/poly-sdk
|
|
83
64
|
|
|
84
|
-
|
|
85
|
-
|
|
65
|
+
# or
|
|
66
|
+
npm install @catalyst-team/poly-sdk
|
|
86
67
|
|
|
87
|
-
|
|
88
|
-
|
|
68
|
+
# or
|
|
69
|
+
yarn add @catalyst-team/poly-sdk
|
|
89
70
|
```
|
|
90
71
|
|
|
91
|
-
|
|
72
|
+
---
|
|
92
73
|
|
|
93
|
-
|
|
94
|
-
// Search markets
|
|
95
|
-
const markets = await sdk.gammaApi.searchMarkets({ query: 'bitcoin' });
|
|
74
|
+
## Architecture
|
|
96
75
|
|
|
97
|
-
|
|
98
|
-
const trending = await sdk.gammaApi.getTrendingMarkets(10);
|
|
76
|
+
The SDK is organized into three layers:
|
|
99
77
|
|
|
100
|
-
// Get events
|
|
101
|
-
const events = await sdk.gammaApi.getEvents({ limit: 20 });
|
|
102
78
|
```
|
|
79
|
+
poly-sdk Architecture
|
|
80
|
+
================================================================================
|
|
103
81
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
82
|
+
┌──────────────────────────────────────────────────────────────────────────────┐
|
|
83
|
+
│ PolymarketSDK │
|
|
84
|
+
│ (Entry Point) │
|
|
85
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
86
|
+
│ │
|
|
87
|
+
│ Layer 3: High-Level Services (Recommended) │
|
|
88
|
+
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │
|
|
89
|
+
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
|
|
90
|
+
│ │ TradingService │ │ MarketService │ │ OnchainService │ │
|
|
91
|
+
│ │ ────────────── │ │ ────────────── │ │ ────────────── │ │
|
|
92
|
+
│ │ • Limit orders │ │ • K-lines │ │ • Split/Merge │ │
|
|
93
|
+
│ │ • Market orders│ │ • Orderbook │ │ • Redeem │ │
|
|
94
|
+
│ │ • Order mgmt │ │ • Price history│ │ • Approvals │ │
|
|
95
|
+
│ │ • Rewards │ │ • Arbitrage │ │ • Swaps │ │
|
|
96
|
+
│ └─────────────────┘ └─────────────────┘ └─────────────────┘ │
|
|
97
|
+
│ │
|
|
98
|
+
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
|
|
99
|
+
│ │RealtimeServiceV2│ │ WalletService │ │SmartMoneyService│ │
|
|
100
|
+
│ │ ────────────── │ │ ────────────── │ │ ────────────── │ │
|
|
101
|
+
│ │ • WebSocket │ │ • Profiles │ │ • Top traders │ │
|
|
102
|
+
│ │ • Price feeds │ │ • Smart scores │ │ • Copy trading │ │
|
|
103
|
+
│ │ • Book updates │ │ • Sell detect │ │ • Signal detect │ │
|
|
104
|
+
│ │ • User events │ │ • PnL calc │ │ • Leaderboard │ │
|
|
105
|
+
│ └─────────────────┘ └─────────────────┘ └─────────────────┘ │
|
|
106
|
+
│ │
|
|
107
|
+
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
|
|
108
|
+
│ │ ArbitrageService │ │
|
|
109
|
+
│ │ ───────────────────────────────────────────────────────────────────── │ │
|
|
110
|
+
│ │ • Market scanning • Auto execution • Rebalancer • Smart clearing │ │
|
|
111
|
+
│ └─────────────────────────────────────────────────────────────────────────┘ │
|
|
112
|
+
│ │
|
|
113
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
114
|
+
│ │
|
|
115
|
+
│ Layer 2: Low-Level Clients (Advanced Users / Raw API Access) │
|
|
116
|
+
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │
|
|
117
|
+
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
|
|
118
|
+
│ │GammaApiClnt│ │DataApiClnt │ │SubgraphClnt│ │ CTFClient │ │BridgeClient│ │
|
|
119
|
+
│ │ ────────── │ │ ────────── │ │ ────────── │ │ ────────── │ │ ────────── │ │
|
|
120
|
+
│ │ • Markets │ │ • Positions│ │ • On-chain │ │ • Split │ │ • Cross- │ │
|
|
121
|
+
│ │ • Events │ │ • Trades │ │ • PnL │ │ • Merge │ │ chain │ │
|
|
122
|
+
│ │ • Search │ │ • Activity │ │ • OI │ │ • Redeem │ │ • Deposits │ │
|
|
123
|
+
│ └────────────┘ └────────────┘ └────────────┘ └────────────┘ └────────────┘ │
|
|
124
|
+
│ │
|
|
125
|
+
│ Uses Official Polymarket Clients: │
|
|
126
|
+
│ • @polymarket/clob-client - Trading, orderbook, market data │
|
|
127
|
+
│ • @polymarket/real-time-data-client - WebSocket real-time updates │
|
|
128
|
+
│ │
|
|
129
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
130
|
+
│ │
|
|
131
|
+
│ Layer 1: Core Infrastructure │
|
|
132
|
+
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │
|
|
133
|
+
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
|
|
134
|
+
│ │RateLimiter │ │ Cache │ │ Errors │ │ Types │ │Price Utils │ │
|
|
135
|
+
│ │ ────────── │ │ ────────── │ │ ────────── │ │ ────────── │ │ ────────── │ │
|
|
136
|
+
│ │ • Per-API │ │ • TTL-based│ │ • Retry │ │ • Unified │ │ • Arb calc │ │
|
|
137
|
+
│ │ • Bottleneck│ │ • Pluggable│ │ • Codes │ │ • K-lines │ │ • Rounding │ │
|
|
138
|
+
│ └────────────┘ └────────────┘ └────────────┘ └────────────┘ └────────────┘ │
|
|
139
|
+
│ │
|
|
140
|
+
└──────────────────────────────────────────────────────────────────────────────┘
|
|
114
141
|
```
|
|
115
142
|
|
|
116
|
-
|
|
143
|
+
### Service Responsibilities
|
|
117
144
|
|
|
118
|
-
|
|
145
|
+
| Service | Responsibility |
|
|
146
|
+
|---------|---------------|
|
|
147
|
+
| **PolymarketSDK** | Entry point, integrates all services |
|
|
148
|
+
| **TradingService** | Order management (place/cancel/query) |
|
|
149
|
+
| **MarketService** | Market data (orderbook/K-lines/search) |
|
|
150
|
+
| **OnchainService** | On-chain ops (split/merge/redeem/approve/swap) |
|
|
151
|
+
| **RealtimeServiceV2** | WebSocket real-time data |
|
|
152
|
+
| **WalletService** | Wallet/trader analysis |
|
|
153
|
+
| **SmartMoneyService** | Smart money tracking |
|
|
154
|
+
| **ArbitrageService** | Arbitrage detection & execution |
|
|
119
155
|
|
|
120
|
-
|
|
121
|
-
// Get top traders
|
|
122
|
-
const traders = await sdk.wallets.getTopTraders(10);
|
|
156
|
+
---
|
|
123
157
|
|
|
124
|
-
|
|
125
|
-
const profile = await sdk.wallets.getWalletProfile('0x...');
|
|
126
|
-
console.log(profile.smartScore); // 0-100
|
|
127
|
-
|
|
128
|
-
// Detect sell activity (for follow-wallet strategy)
|
|
129
|
-
const sellResult = await sdk.wallets.detectSellActivity(
|
|
130
|
-
'0x...',
|
|
131
|
-
conditionId,
|
|
132
|
-
Date.now() - 24 * 60 * 60 * 1000
|
|
133
|
-
);
|
|
134
|
-
if (sellResult.isSelling) {
|
|
135
|
-
console.log(`Sold ${sellResult.percentageSold}%`);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// Track group sell ratio
|
|
139
|
-
const groupSell = await sdk.wallets.trackGroupSellRatio(
|
|
140
|
-
['0x...', '0x...'],
|
|
141
|
-
conditionId,
|
|
142
|
-
peakValue,
|
|
143
|
-
sinceTimestamp
|
|
144
|
-
);
|
|
145
|
-
```
|
|
158
|
+
## Quick Start
|
|
146
159
|
|
|
147
|
-
###
|
|
160
|
+
### Basic Usage (Read-Only)
|
|
148
161
|
|
|
149
162
|
```typescript
|
|
150
|
-
|
|
151
|
-
const klines = await sdk.markets.getKLines(conditionId, '1h', { limit: 100 });
|
|
152
|
-
|
|
153
|
-
// Get dual K-Lines (YES + NO) with spread analysis
|
|
154
|
-
const dual = await sdk.markets.getDualKLines(conditionId, '1h');
|
|
155
|
-
console.log(dual.yes); // YES token candles
|
|
156
|
-
console.log(dual.no); // NO token candles
|
|
163
|
+
import { PolymarketSDK } from '@catalyst-team/poly-sdk';
|
|
157
164
|
|
|
158
|
-
//
|
|
159
|
-
|
|
160
|
-
for (const point of dual.spreadAnalysis) {
|
|
161
|
-
console.log(`${point.timestamp}: priceSum=${point.priceSum}, spread=${point.priceSpread}`);
|
|
162
|
-
if (point.arbOpportunity) {
|
|
163
|
-
console.log(` Historical ${point.arbOpportunity} signal`);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
165
|
+
// No authentication needed for read operations
|
|
166
|
+
const sdk = new PolymarketSDK();
|
|
166
167
|
|
|
167
|
-
//
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
if (rt.arbOpportunity) {
|
|
173
|
-
console.log(`🎯 ${rt.arbOpportunity} ARB: ${rt.arbProfitPercent.toFixed(2)}% profit`);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
168
|
+
// Get market by slug or condition ID
|
|
169
|
+
const market = await sdk.getMarket('will-trump-win-2024');
|
|
170
|
+
console.log(`${market.question}`);
|
|
171
|
+
console.log(`YES: ${market.tokens.find(t => t.outcome === 'Yes')?.price}`);
|
|
172
|
+
console.log(`NO: ${market.tokens.find(t => t.outcome === 'No')?.price}`);
|
|
176
173
|
|
|
177
|
-
//
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
}
|
|
174
|
+
// Get processed orderbook with analytics
|
|
175
|
+
const orderbook = await sdk.getOrderbook(market.conditionId);
|
|
176
|
+
console.log(`Long Arb Profit: ${orderbook.summary.longArbProfit}`);
|
|
177
|
+
console.log(`Short Arb Profit: ${orderbook.summary.shortArbProfit}`);
|
|
182
178
|
|
|
183
|
-
// Detect
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
-
console.log(`${
|
|
179
|
+
// Detect arbitrage opportunities
|
|
180
|
+
const arb = await sdk.detectArbitrage(market.conditionId);
|
|
181
|
+
if (arb) {
|
|
182
|
+
console.log(`${arb.type.toUpperCase()} ARB: ${(arb.profit * 100).toFixed(2)}% profit`);
|
|
183
|
+
console.log(arb.action);
|
|
187
184
|
}
|
|
188
|
-
|
|
189
|
-
// Detect arbitrage
|
|
190
|
-
const arb = await sdk.markets.detectArbitrage(conditionId);
|
|
191
185
|
```
|
|
192
186
|
|
|
193
|
-
|
|
187
|
+
### With Authentication (Trading)
|
|
194
188
|
|
|
195
|
-
|
|
189
|
+
```typescript
|
|
190
|
+
import { PolymarketSDK } from '@catalyst-team/poly-sdk';
|
|
196
191
|
|
|
197
|
-
|
|
192
|
+
// Recommended: Use static factory method (one line to get started)
|
|
193
|
+
const sdk = await PolymarketSDK.create({
|
|
194
|
+
privateKey: process.env.POLYMARKET_PRIVATE_KEY!,
|
|
195
|
+
});
|
|
196
|
+
// Ready to trade - SDK is initialized and WebSocket connected
|
|
198
197
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
198
|
+
// Place a limit order
|
|
199
|
+
const order = await sdk.tradingService.createLimitOrder({
|
|
200
|
+
tokenId: yesTokenId,
|
|
201
|
+
side: 'BUY',
|
|
202
|
+
price: 0.45,
|
|
203
|
+
size: 10,
|
|
204
|
+
orderType: 'GTC',
|
|
205
|
+
});
|
|
206
|
+
console.log(`Order placed: ${order.id}`);
|
|
202
207
|
|
|
203
|
-
|
|
204
|
-
|
|
208
|
+
// Get open orders
|
|
209
|
+
const openOrders = await sdk.tradingService.getOpenOrders();
|
|
210
|
+
console.log(`Open orders: ${openOrders.length}`);
|
|
205
211
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
// ❌ 错误: 简单相加会重复计算镜像订单
|
|
209
|
-
const askSum = YES.ask + NO.ask; // ≈ 1.998-1.999,而非 ≈ 1.0
|
|
210
|
-
const bidSum = YES.bid + NO.bid; // ≈ 0.001-0.002,而非 ≈ 1.0
|
|
212
|
+
// Clean up when done
|
|
213
|
+
sdk.stop();
|
|
211
214
|
```
|
|
212
215
|
|
|
213
|
-
|
|
214
|
-
```typescript
|
|
215
|
-
import { getEffectivePrices, checkArbitrage } from '@catalyst-team/poly-sdk';
|
|
216
|
-
|
|
217
|
-
// 计算考虑镜像后的最优价格
|
|
218
|
-
const effective = getEffectivePrices(yesAsk, yesBid, noAsk, noBid);
|
|
216
|
+
---
|
|
219
217
|
|
|
220
|
-
|
|
221
|
-
// effective.effectiveBuyNo = min(NO.ask, 1 - YES.bid)
|
|
222
|
-
// effective.effectiveSellYes = max(YES.bid, 1 - NO.ask)
|
|
223
|
-
// effective.effectiveSellNo = max(NO.bid, 1 - YES.ask)
|
|
218
|
+
## Services Guide
|
|
224
219
|
|
|
225
|
-
|
|
226
|
-
const arb = checkArbitrage(yesAsk, noAsk, yesBid, noBid);
|
|
227
|
-
if (arb) {
|
|
228
|
-
console.log(`${arb.type} arb: ${(arb.profit * 100).toFixed(2)}% profit`);
|
|
229
|
-
console.log(arb.description);
|
|
230
|
-
}
|
|
231
|
-
```
|
|
220
|
+
### PolymarketSDK (Entry Point)
|
|
232
221
|
|
|
233
|
-
|
|
222
|
+
The main SDK class that integrates all services.
|
|
234
223
|
|
|
235
|
-
|
|
224
|
+
```typescript
|
|
225
|
+
import { PolymarketSDK } from '@catalyst-team/poly-sdk';
|
|
236
226
|
|
|
237
|
-
|
|
227
|
+
// ===== Method 1: Static Factory (Recommended) =====
|
|
228
|
+
// One line: new + initialize + connect + waitForConnection
|
|
229
|
+
const sdk = await PolymarketSDK.create({
|
|
230
|
+
privateKey: '0x...', // Optional: for trading
|
|
231
|
+
chainId: 137, // Optional: Polygon mainnet (default)
|
|
232
|
+
});
|
|
238
233
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
├─────────────────────────────────────────────────────────────────────────┤
|
|
243
|
-
│ 数据源: 成交记录的收盘价 │ 数据源: 订单簿的最优 bid/ask │
|
|
244
|
-
│ YES_close + NO_close │ 使用有效价格 (考虑镜像订单) │
|
|
245
|
-
├─────────────────────────────────────────────────────────────────────────┤
|
|
246
|
-
│ ✅ 可构建历史曲线 │ ❌ 无法构建历史曲线* │
|
|
247
|
-
│ ✅ Polymarket 保留成交历史 │ ❌ Polymarket 不保留盘口历史 │
|
|
248
|
-
│ ✅ 适合回测、模式识别 │ ✅ 适合实盘交易、套利执行 │
|
|
249
|
-
│ ⚠️ 套利信号仅供参考 │ ✅ 套利利润计算准确 │
|
|
250
|
-
└─────────────────────────────────────────────────────────────────────────┘
|
|
251
|
-
|
|
252
|
-
* 如需构建实时 Spread 的历史曲线,必须自行存储盘口快照数据
|
|
253
|
-
参考: apps/api/src/services/spread-sampler.ts
|
|
254
|
-
```
|
|
234
|
+
// ===== Method 2: Using start() =====
|
|
235
|
+
// const sdk = new PolymarketSDK({ privateKey: '0x...' });
|
|
236
|
+
// await sdk.start(); // initialize + connect + waitForConnection
|
|
255
237
|
|
|
256
|
-
|
|
238
|
+
// ===== Method 3: Manual Step-by-Step (Full Control) =====
|
|
239
|
+
// const sdk = new PolymarketSDK({ privateKey: '0x...' });
|
|
240
|
+
// await sdk.initialize(); // Initialize trading service
|
|
241
|
+
// sdk.connect(); // Connect WebSocket
|
|
242
|
+
// await sdk.waitForConnection(); // Wait for connection
|
|
257
243
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
244
|
+
// Access services
|
|
245
|
+
sdk.tradingService // Trading operations
|
|
246
|
+
sdk.markets // Market data
|
|
247
|
+
sdk.wallets // Wallet analysis
|
|
248
|
+
sdk.realtime // WebSocket real-time data
|
|
249
|
+
sdk.smartMoney // Smart money tracking & copy trading
|
|
250
|
+
sdk.dataApi // Direct Data API access
|
|
251
|
+
sdk.gammaApi // Direct Gamma API access
|
|
252
|
+
sdk.subgraph // On-chain data via Goldsky
|
|
262
253
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
254
|
+
// Convenience methods
|
|
255
|
+
await sdk.getMarket(identifier); // Get unified market
|
|
256
|
+
await sdk.getOrderbook(conditionId); // Get processed orderbook
|
|
257
|
+
await sdk.detectArbitrage(conditionId); // Detect arb opportunity
|
|
267
258
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
- 除非你自己运行 spread-sampler 持续采样盘口
|
|
259
|
+
// Clean up
|
|
260
|
+
sdk.stop(); // Disconnect all services
|
|
261
|
+
```
|
|
272
262
|
|
|
273
|
-
|
|
274
|
-
// SpreadDataPoint (历史分析 - 可构建曲线)
|
|
275
|
-
interface SpreadDataPoint {
|
|
276
|
-
timestamp: number;
|
|
277
|
-
yesPrice: number; // YES 收盘价 (来自成交记录)
|
|
278
|
-
noPrice: number; // NO 收盘价
|
|
279
|
-
priceSum: number; // YES + NO
|
|
280
|
-
priceSpread: number; // priceSum - 1 (偏离均衡程度)
|
|
281
|
-
arbOpportunity: 'LONG' | 'SHORT' | ''; // 参考信号
|
|
282
|
-
}
|
|
263
|
+
---
|
|
283
264
|
|
|
284
|
-
|
|
285
|
-
interface OrderbookSummary {
|
|
286
|
-
// 有效价格 (考虑镜像订单)
|
|
287
|
-
effectivePrices: {
|
|
288
|
-
effectiveBuyYes: number; // min(YES.ask, 1 - NO.bid)
|
|
289
|
-
effectiveBuyNo: number; // min(NO.ask, 1 - YES.bid)
|
|
290
|
-
effectiveSellYes: number; // max(YES.bid, 1 - NO.ask)
|
|
291
|
-
effectiveSellNo: number; // max(NO.bid, 1 - YES.ask)
|
|
292
|
-
};
|
|
293
|
-
// 套利成本/收入
|
|
294
|
-
effectiveLongCost: number; // effectiveBuyYes + effectiveBuyNo
|
|
295
|
-
effectiveShortRevenue: number; // effectiveSellYes + effectiveSellNo
|
|
296
|
-
// 套利利润
|
|
297
|
-
longArbProfit: number; // 1 - effectiveLongCost (> 0 可套利)
|
|
298
|
-
shortArbProfit: number; // effectiveShortRevenue - 1 (> 0 可套利)
|
|
299
|
-
yesSpread: number; // YES.ask - YES.bid (市场效率指标)
|
|
300
|
-
}
|
|
301
|
-
```
|
|
265
|
+
### TradingService
|
|
302
266
|
|
|
303
|
-
|
|
267
|
+
Order management using `@polymarket/clob-client`.
|
|
304
268
|
|
|
305
269
|
```typescript
|
|
306
|
-
import {
|
|
270
|
+
import { TradingService } from '@catalyst-team/poly-sdk';
|
|
307
271
|
|
|
308
|
-
const
|
|
309
|
-
const tradingClient = new TradingClient(rateLimiter, {
|
|
272
|
+
const trading = new TradingService(rateLimiter, cache, {
|
|
310
273
|
privateKey: process.env.POLYMARKET_PRIVATE_KEY!,
|
|
311
274
|
});
|
|
275
|
+
await trading.initialize();
|
|
312
276
|
|
|
313
|
-
|
|
314
|
-
console.log(`Wallet: ${tradingClient.getAddress()}`);
|
|
277
|
+
// ===== Limit Orders =====
|
|
315
278
|
|
|
316
|
-
// GTC
|
|
317
|
-
const
|
|
279
|
+
// GTC: Good Till Cancelled
|
|
280
|
+
const gtcOrder = await trading.createLimitOrder({
|
|
318
281
|
tokenId: yesTokenId,
|
|
319
282
|
side: 'BUY',
|
|
320
283
|
price: 0.45,
|
|
@@ -322,8 +285,8 @@ const order = await tradingClient.createOrder({
|
|
|
322
285
|
orderType: 'GTC',
|
|
323
286
|
});
|
|
324
287
|
|
|
325
|
-
// GTD
|
|
326
|
-
const gtdOrder = await
|
|
288
|
+
// GTD: Good Till Date (expires at timestamp)
|
|
289
|
+
const gtdOrder = await trading.createLimitOrder({
|
|
327
290
|
tokenId: yesTokenId,
|
|
328
291
|
side: 'BUY',
|
|
329
292
|
price: 0.45,
|
|
@@ -332,406 +295,297 @@ const gtdOrder = await tradingClient.createOrder({
|
|
|
332
295
|
expiration: Math.floor(Date.now() / 1000) + 3600, // 1 hour
|
|
333
296
|
});
|
|
334
297
|
|
|
335
|
-
//
|
|
336
|
-
|
|
298
|
+
// ===== Market Orders =====
|
|
299
|
+
|
|
300
|
+
// FOK: Fill Or Kill (fill entirely or cancel)
|
|
301
|
+
const fokOrder = await trading.createMarketOrder({
|
|
337
302
|
tokenId: yesTokenId,
|
|
338
303
|
side: 'BUY',
|
|
339
304
|
amount: 10, // $10 USDC
|
|
340
305
|
orderType: 'FOK',
|
|
341
306
|
});
|
|
342
307
|
|
|
343
|
-
// FAK
|
|
344
|
-
const fakOrder = await
|
|
308
|
+
// FAK: Fill And Kill (partial fill ok)
|
|
309
|
+
const fakOrder = await trading.createMarketOrder({
|
|
345
310
|
tokenId: yesTokenId,
|
|
346
311
|
side: 'SELL',
|
|
347
312
|
amount: 10, // 10 shares
|
|
348
313
|
orderType: 'FAK',
|
|
349
314
|
});
|
|
350
315
|
|
|
351
|
-
// Order
|
|
352
|
-
const openOrders = await
|
|
353
|
-
await
|
|
354
|
-
await
|
|
316
|
+
// ===== Order Management =====
|
|
317
|
+
const openOrders = await trading.getOpenOrders();
|
|
318
|
+
await trading.cancelOrder(orderId);
|
|
319
|
+
await trading.cancelAllOrders();
|
|
355
320
|
|
|
356
|
-
//
|
|
357
|
-
const
|
|
321
|
+
// ===== Rewards (Market Making Incentives) =====
|
|
322
|
+
const isScoring = await trading.isOrderScoring(orderId);
|
|
323
|
+
const rewards = await trading.getCurrentRewards();
|
|
324
|
+
const earnings = await trading.getEarnings('2024-12-07');
|
|
358
325
|
```
|
|
359
326
|
|
|
360
|
-
|
|
327
|
+
---
|
|
361
328
|
|
|
362
|
-
|
|
363
|
-
// Check if your orders are earning rewards
|
|
364
|
-
const isScoring = await tradingClient.isOrderScoring(orderId);
|
|
365
|
-
|
|
366
|
-
// Get markets with active reward programs
|
|
367
|
-
const rewards = await tradingClient.getCurrentRewards();
|
|
368
|
-
for (const reward of rewards) {
|
|
369
|
-
console.log(`${reward.question}`);
|
|
370
|
-
console.log(` Max Spread: ${reward.rewardsMaxSpread}`);
|
|
371
|
-
console.log(` Min Size: ${reward.rewardsMinSize}`);
|
|
372
|
-
}
|
|
329
|
+
### MarketService
|
|
373
330
|
|
|
374
|
-
|
|
375
|
-
const earnings = await tradingClient.getTotalEarningsForDay('2024-12-07');
|
|
376
|
-
console.log(`Total earned: $${earnings.totalEarnings}`);
|
|
331
|
+
Market data, K-lines, orderbook analysis.
|
|
377
332
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
console.log(`USDC Balance: ${balance.balance}`);
|
|
381
|
-
```
|
|
333
|
+
```typescript
|
|
334
|
+
import { MarketService } from '@catalyst-team/poly-sdk';
|
|
382
335
|
|
|
383
|
-
|
|
336
|
+
// Get unified market
|
|
337
|
+
const market = await sdk.markets.getMarket('btc-100k-2024');
|
|
384
338
|
|
|
385
|
-
|
|
339
|
+
// Get K-Lines
|
|
340
|
+
const klines = await sdk.markets.getKLines(conditionId, '1h', { limit: 100 });
|
|
386
341
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
342
|
+
// Get dual K-Lines (YES + NO) with spread analysis
|
|
343
|
+
const dual = await sdk.markets.getDualKLines(conditionId, '1h');
|
|
344
|
+
console.log(dual.yes); // YES token candles
|
|
345
|
+
console.log(dual.no); // NO token candles
|
|
346
|
+
console.log(dual.spreadAnalysis); // Historical spread (trade prices)
|
|
347
|
+
console.log(dual.realtimeSpread); // Real-time spread (orderbook)
|
|
390
348
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
- **asks**: 升序排列 (最低价在前 = 最佳卖价)
|
|
349
|
+
// Get processed orderbook
|
|
350
|
+
const orderbook = await sdk.markets.getProcessedOrderbook(conditionId);
|
|
394
351
|
|
|
395
|
-
|
|
352
|
+
// Quick real-time spread check
|
|
353
|
+
const spread = await sdk.markets.getRealtimeSpread(conditionId);
|
|
354
|
+
if (spread.longArbProfit > 0.005) {
|
|
355
|
+
console.log(`Long arb: buy YES@${spread.yesAsk} + NO@${spread.noAsk}`);
|
|
356
|
+
}
|
|
396
357
|
|
|
397
|
-
|
|
398
|
-
const
|
|
399
|
-
const bestBid = book.bids[0]?.price; // ✅ 最高买价 (最佳 bid)
|
|
400
|
-
const bestAsk = book.asks[0]?.price; // ✅ 最低卖价 (最佳 ask)
|
|
401
|
-
|
|
402
|
-
// WebSocket 更新同样自动排序
|
|
403
|
-
wsManager.on('bookUpdate', (update) => {
|
|
404
|
-
const bestBid = update.bids[0]?.price; // ✅ 已排序
|
|
405
|
-
const bestAsk = update.asks[0]?.price; // ✅ 已排序
|
|
406
|
-
});
|
|
358
|
+
// Detect market signals
|
|
359
|
+
const signals = await sdk.markets.detectMarketSignals(conditionId);
|
|
407
360
|
```
|
|
408
361
|
|
|
409
|
-
|
|
410
|
-
import { WebSocketManager, RealtimeService } from '@catalyst-team/poly-sdk';
|
|
362
|
+
#### Understanding Polymarket Orderbook
|
|
411
363
|
|
|
412
|
-
|
|
413
|
-
const realtime = new RealtimeService(wsManager);
|
|
364
|
+
**Important**: Polymarket orderbooks have a mirror property:
|
|
414
365
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
console.log(`${update.assetId}: ${update.price}`);
|
|
419
|
-
},
|
|
420
|
-
onBookUpdate: (update) => {
|
|
421
|
-
console.log(`Best bid: ${update.bids[0]?.price}`);
|
|
422
|
-
},
|
|
423
|
-
onLastTrade: (trade) => {
|
|
424
|
-
console.log(`Trade: ${trade.side} ${trade.size} @ ${trade.price}`);
|
|
425
|
-
},
|
|
426
|
-
onPairUpdate: (update) => {
|
|
427
|
-
console.log(`YES + NO = ${update.spread}`);
|
|
428
|
-
if (update.spread < 0.99) console.log('ARB opportunity!');
|
|
429
|
-
},
|
|
430
|
-
});
|
|
366
|
+
```
|
|
367
|
+
Buy YES @ P = Sell NO @ (1-P)
|
|
368
|
+
```
|
|
431
369
|
|
|
432
|
-
|
|
433
|
-
const price = realtime.getPrice(yesTokenId);
|
|
370
|
+
This means the **same order appears in both orderbooks**. Simple addition causes double-counting:
|
|
434
371
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
372
|
+
```typescript
|
|
373
|
+
// WRONG: Double counts mirror orders
|
|
374
|
+
const askSum = YES.ask + NO.ask; // ~1.998, not ~1.0
|
|
438
375
|
|
|
439
|
-
|
|
376
|
+
// CORRECT: Use effective prices
|
|
377
|
+
import { getEffectivePrices, checkArbitrage } from '@catalyst-team/poly-sdk';
|
|
440
378
|
|
|
441
|
-
|
|
379
|
+
const effective = getEffectivePrices(yesAsk, yesBid, noAsk, noBid);
|
|
380
|
+
// effective.effectiveBuyYes = min(YES.ask, 1 - NO.bid)
|
|
381
|
+
// effective.effectiveBuyNo = min(NO.ask, 1 - YES.bid)
|
|
442
382
|
|
|
383
|
+
const arb = checkArbitrage(yesAsk, noAsk, yesBid, noBid);
|
|
384
|
+
if (arb) {
|
|
385
|
+
console.log(`${arb.type} arb: ${(arb.profit * 100).toFixed(2)}% profit`);
|
|
386
|
+
}
|
|
443
387
|
```
|
|
444
|
-
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
445
|
-
│ CTF 核心操作快速参考 │
|
|
446
|
-
├─────────────────────────────────────────────────────────────────────────────┤
|
|
447
|
-
│ 操作 │ 功能 │ 典型场景 │
|
|
448
|
-
├──────────────┼────────────────────────┼──────────────────────────────────────┤
|
|
449
|
-
│ Split │ USDC → YES + NO │ 市场做市:创建代币库存 │
|
|
450
|
-
│ Merge │ YES + NO → USDC │ 套利:买入双边后合并获利 │
|
|
451
|
-
│ Redeem │ 胜出代币 → USDC │ 结算:市场结束后兑换获胜代币 │
|
|
452
|
-
└─────────────────────────────────────────────────────────────────────────────┘
|
|
453
|
-
```
|
|
454
388
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
389
|
+
---
|
|
390
|
+
|
|
391
|
+
### OnchainService
|
|
392
|
+
|
|
393
|
+
Unified interface for all on-chain operations: CTF + Approvals + Swaps.
|
|
459
394
|
|
|
460
395
|
```typescript
|
|
461
|
-
import {
|
|
396
|
+
import { OnchainService } from '@catalyst-team/poly-sdk';
|
|
462
397
|
|
|
463
|
-
const
|
|
398
|
+
const onchain = new OnchainService({
|
|
464
399
|
privateKey: process.env.POLYMARKET_PRIVATE_KEY!,
|
|
465
400
|
rpcUrl: 'https://polygon-rpc.com', // optional
|
|
466
401
|
});
|
|
467
402
|
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
```typescript
|
|
475
|
-
// Split 100 USDC into 100 YES + 100 NO tokens
|
|
476
|
-
const splitResult = await ctf.split(conditionId, '100');
|
|
477
|
-
console.log(`TX: ${splitResult.txHash}`);
|
|
478
|
-
console.log(`Created ${splitResult.yesTokens} YES + ${splitResult.noTokens} NO`);
|
|
479
|
-
```
|
|
403
|
+
// Check if ready for CTF trading
|
|
404
|
+
const status = await onchain.checkReadyForCTF('100');
|
|
405
|
+
if (!status.ready) {
|
|
406
|
+
console.log('Issues:', status.issues);
|
|
407
|
+
await onchain.approveAll();
|
|
408
|
+
}
|
|
480
409
|
|
|
481
|
-
|
|
410
|
+
// ===== CTF Operations =====
|
|
482
411
|
|
|
483
|
-
|
|
412
|
+
// Split: USDC -> YES + NO tokens
|
|
413
|
+
const splitResult = await onchain.split(conditionId, '100');
|
|
484
414
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
| `mergeByTokenIds()` | **Polymarket CLOB 市场** | ✅ 推荐 |
|
|
488
|
-
| `merge()` | 标准 Gnosis CTF 市场 | ❌ Polymarket 慎用 |
|
|
415
|
+
// Merge: YES + NO -> USDC (for arbitrage)
|
|
416
|
+
const mergeResult = await onchain.mergeByTokenIds(conditionId, tokenIds, '100');
|
|
489
417
|
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
const tokenIds = {
|
|
493
|
-
yesTokenId: market.tokens[0].tokenId, // 从 CLOB API 获取
|
|
494
|
-
noTokenId: market.tokens[1].tokenId,
|
|
495
|
-
};
|
|
496
|
-
const mergeResult = await ctf.mergeByTokenIds(conditionId, tokenIds, '100');
|
|
497
|
-
console.log(`TX: ${mergeResult.txHash}`);
|
|
498
|
-
console.log(`Received ${mergeResult.usdcReceived} USDC`);
|
|
499
|
-
|
|
500
|
-
// ⚠️ 标准 CTF 方法(可能无法正确检查 Polymarket 余额)
|
|
501
|
-
// const mergeResult = await ctf.merge(conditionId, '100');
|
|
502
|
-
```
|
|
418
|
+
// Redeem: Winning tokens -> USDC (after resolution)
|
|
419
|
+
const redeemResult = await onchain.redeemByTokenIds(conditionId, tokenIds);
|
|
503
420
|
|
|
504
|
-
|
|
421
|
+
// ===== DEX Swaps (QuickSwap V3) =====
|
|
505
422
|
|
|
506
|
-
|
|
423
|
+
// Swap MATIC to USDC.e (required for CTF)
|
|
424
|
+
await onchain.swap('MATIC', 'USDC_E', '50');
|
|
507
425
|
|
|
508
|
-
|
|
426
|
+
// Get balances
|
|
427
|
+
const balances = await onchain.getBalances();
|
|
428
|
+
console.log(`USDC.e: ${balances.usdcE}`);
|
|
429
|
+
```
|
|
509
430
|
|
|
510
|
-
|
|
511
|
-
|------|----------|---------------|
|
|
512
|
-
| `redeemByTokenIds()` | **Polymarket CLOB 市场** ✅ | CLOB API 返回的 tokenId |
|
|
513
|
-
| `redeem()` | 标准 Gnosis CTF 市场 | `keccak256(collectionId, conditionId, indexSet)` |
|
|
431
|
+
**Note**: Polymarket CTF requires **USDC.e** (0x2791...), not native USDC.
|
|
514
432
|
|
|
515
|
-
|
|
516
|
-
// ✅ 推荐:Polymarket 市场使用 redeemByTokenIds
|
|
517
|
-
const tokenIds = {
|
|
518
|
-
yesTokenId: '25064375110792967023484002819116042931016336431092144471807003884255851454283',
|
|
519
|
-
noTokenId: '98190367690492181203391990709979106077460946443309150166954079213761598385827',
|
|
520
|
-
};
|
|
521
|
-
const result = await ctf.redeemByTokenIds(conditionId, tokenIds);
|
|
522
|
-
console.log(`Redeemed ${result.tokensRedeemed} ${result.outcome} tokens`);
|
|
523
|
-
console.log(`Received ${result.usdcReceived} USDC`);
|
|
524
|
-
|
|
525
|
-
// ❌ 不要用于 Polymarket:redeem() 使用计算的 position ID
|
|
526
|
-
// const result = await ctf.redeem(conditionId); // 可能找不到余额
|
|
527
|
-
```
|
|
433
|
+
---
|
|
528
434
|
|
|
529
|
-
|
|
530
|
-
- Polymarket 在 CTF 之上包装了一层 ERC-1155 tokens
|
|
531
|
-
- CLOB API 返回的 `tokenId` (如 `"25064375..."`) 与标准 CTF 计算的 position ID 不同
|
|
532
|
-
- 必须使用 CLOB API 的 token ID 才能正确查询余额和 redeem
|
|
435
|
+
### RealtimeServiceV2
|
|
533
436
|
|
|
534
|
-
|
|
437
|
+
WebSocket real-time data using `@polymarket/real-time-data-client`.
|
|
535
438
|
|
|
536
439
|
```typescript
|
|
537
|
-
|
|
538
|
-
const balances = await ctf.getPositionBalance(conditionId);
|
|
539
|
-
console.log(`YES: ${balances.yesBalance}, NO: ${balances.noBalance}`);
|
|
540
|
-
|
|
541
|
-
// Check if market is resolved
|
|
542
|
-
const resolution = await ctf.getMarketResolution(conditionId);
|
|
543
|
-
if (resolution.isResolved) {
|
|
544
|
-
console.log(`Winner: ${resolution.winningOutcome}`);
|
|
545
|
-
}
|
|
440
|
+
import { RealtimeServiceV2 } from '@catalyst-team/poly-sdk';
|
|
546
441
|
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
442
|
+
const realtime = new RealtimeServiceV2({
|
|
443
|
+
autoReconnect: true,
|
|
444
|
+
pingInterval: 5000,
|
|
445
|
+
});
|
|
551
446
|
|
|
552
|
-
|
|
447
|
+
// Connect and subscribe
|
|
448
|
+
realtime.connect();
|
|
449
|
+
realtime.subscribeMarket([yesTokenId, noTokenId]);
|
|
553
450
|
|
|
554
|
-
|
|
451
|
+
// Event-based API
|
|
452
|
+
realtime.on('priceUpdate', (update) => {
|
|
453
|
+
console.log(`${update.assetId}: ${update.price}`);
|
|
454
|
+
console.log(`Midpoint: ${update.midpoint}, Spread: ${update.spread}`);
|
|
455
|
+
});
|
|
555
456
|
|
|
556
|
-
|
|
457
|
+
realtime.on('bookUpdate', (update) => {
|
|
458
|
+
// Orderbook is auto-normalized:
|
|
459
|
+
// bids: descending (best first), asks: ascending (best first)
|
|
460
|
+
console.log(`Best bid: ${update.bids[0]?.price}`);
|
|
461
|
+
console.log(`Best ask: ${update.asks[0]?.price}`);
|
|
462
|
+
});
|
|
557
463
|
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
│ 有效买入成本: │
|
|
562
|
-
│ effectiveBuyYes = min(YES.ask, 1 - NO.bid) │
|
|
563
|
-
│ effectiveBuyNo = min(NO.ask, 1 - YES.bid) │
|
|
564
|
-
│ 操作: │
|
|
565
|
-
│ 1. 用有效价格买入 YES + NO │
|
|
566
|
-
│ 2. CTF Merge → $1 USDC │
|
|
567
|
-
│ 3. Profit = 1 - effectiveLongCost │
|
|
568
|
-
├─────────────────────────────────────────────────────────────┤
|
|
569
|
-
│ SHORT ARB (effectiveShortRevenue > $1): │
|
|
570
|
-
│ 有效卖出收入: │
|
|
571
|
-
│ effectiveSellYes = max(YES.bid, 1 - NO.ask) │
|
|
572
|
-
│ effectiveSellNo = max(NO.bid, 1 - YES.ask) │
|
|
573
|
-
│ 操作: │
|
|
574
|
-
│ 1. CTF Split $1 → 1 YES + 1 NO │
|
|
575
|
-
│ 2. 用有效价格卖出 YES + NO │
|
|
576
|
-
│ 3. Profit = effectiveShortRevenue - 1 │
|
|
577
|
-
└─────────────────────────────────────────────────────────────┘
|
|
578
|
-
```
|
|
464
|
+
realtime.on('lastTrade', (trade) => {
|
|
465
|
+
console.log(`Trade: ${trade.side} ${trade.size} @ ${trade.price}`);
|
|
466
|
+
});
|
|
579
467
|
|
|
580
|
-
|
|
581
|
-
|
|
468
|
+
// Get cached prices
|
|
469
|
+
const price = realtime.getPrice(yesTokenId);
|
|
470
|
+
const book = realtime.getBook(yesTokenId);
|
|
582
471
|
|
|
583
|
-
//
|
|
584
|
-
|
|
585
|
-
if (arb?.type === 'long') {
|
|
586
|
-
console.log(arb.description); // "Buy YES @ 0.48 + NO @ 0.50, Merge for $1"
|
|
587
|
-
// Buy both tokens at effective prices, then merge
|
|
588
|
-
await tradingClient.createMarketOrder({ tokenId: yesTokenId, side: 'BUY', amount: 100 });
|
|
589
|
-
await tradingClient.createMarketOrder({ tokenId: noTokenId, side: 'BUY', amount: 100 });
|
|
590
|
-
await ctf.merge(conditionId, '100');
|
|
591
|
-
}
|
|
472
|
+
// Cleanup
|
|
473
|
+
realtime.disconnect();
|
|
592
474
|
```
|
|
593
475
|
|
|
594
|
-
|
|
476
|
+
---
|
|
595
477
|
|
|
596
|
-
|
|
478
|
+
### WalletService
|
|
597
479
|
|
|
598
|
-
|
|
599
|
-
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
600
|
-
│ 跨链充值流程 │
|
|
601
|
-
├─────────────────────────────────────────────────────────────────────────────┤
|
|
602
|
-
│ 1. 获取充值地址 → 2. 发送资产到地址 → 3. 自动桥接 → 4. USDC.e 到账 │
|
|
603
|
-
└─────────────────────────────────────────────────────────────────────────────┘
|
|
604
|
-
```
|
|
480
|
+
Wallet analysis and smart money scoring.
|
|
605
481
|
|
|
606
482
|
```typescript
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
SUPPORTED_CHAINS,
|
|
610
|
-
depositUsdc,
|
|
611
|
-
swapAndDeposit,
|
|
612
|
-
} from '@catalyst-team/poly-sdk';
|
|
483
|
+
// Get top traders
|
|
484
|
+
const traders = await sdk.wallets.getTopTraders(10);
|
|
613
485
|
|
|
614
|
-
// Get
|
|
615
|
-
const
|
|
616
|
-
|
|
617
|
-
console.log(`
|
|
618
|
-
console.log(`
|
|
619
|
-
console.log(`Bitcoin: ${addresses.address.btc}`);
|
|
620
|
-
|
|
621
|
-
// Get supported assets
|
|
622
|
-
const assets = await bridge.getSupportedAssets();
|
|
623
|
-
for (const asset of assets) {
|
|
624
|
-
console.log(`${asset.chainName} ${asset.tokenSymbol}: min ${asset.minDepositUsd} USD`);
|
|
625
|
-
}
|
|
486
|
+
// Get wallet profile with smart score
|
|
487
|
+
const profile = await sdk.wallets.getWalletProfile('0x...');
|
|
488
|
+
console.log(`Smart Score: ${profile.smartScore}/100`);
|
|
489
|
+
console.log(`Win Rate: ${profile.winRate}%`);
|
|
490
|
+
console.log(`Total PnL: $${profile.totalPnL}`);
|
|
626
491
|
|
|
627
|
-
//
|
|
628
|
-
const
|
|
629
|
-
|
|
492
|
+
// Detect sell activity (for follow-wallet strategy)
|
|
493
|
+
const sellResult = await sdk.wallets.detectSellActivity(
|
|
494
|
+
'0x...',
|
|
495
|
+
conditionId,
|
|
496
|
+
Date.now() - 24 * 60 * 60 * 1000 // since 24h ago
|
|
497
|
+
);
|
|
498
|
+
if (sellResult.isSelling) {
|
|
499
|
+
console.log(`Sold ${sellResult.percentageSold}%`);
|
|
500
|
+
}
|
|
630
501
|
|
|
631
|
-
//
|
|
632
|
-
const
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
502
|
+
// Track group sell ratio
|
|
503
|
+
const groupSell = await sdk.wallets.trackGroupSellRatio(
|
|
504
|
+
['0x...', '0x...'],
|
|
505
|
+
conditionId,
|
|
506
|
+
peakValue,
|
|
507
|
+
sinceTimestamp
|
|
508
|
+
);
|
|
638
509
|
```
|
|
639
510
|
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
Swap tokens on Polygon using QuickSwap V3. Essential for converting tokens to USDC.e for CTF operations.
|
|
511
|
+
---
|
|
643
512
|
|
|
644
|
-
|
|
513
|
+
### SmartMoneyService
|
|
645
514
|
|
|
646
|
-
|
|
647
|
-
|-------|---------|----------------|
|
|
648
|
-
| USDC.e | `0x2791...` | ✅ **Required** |
|
|
649
|
-
| USDC (Native) | `0x3c49...` | ❌ Not accepted |
|
|
515
|
+
Smart money detection and **real-time auto copy trading**.
|
|
650
516
|
|
|
651
517
|
```typescript
|
|
652
|
-
import {
|
|
653
|
-
|
|
654
|
-
const swapService = new SwapService(signer);
|
|
518
|
+
import { PolymarketSDK } from '@catalyst-team/poly-sdk';
|
|
655
519
|
|
|
656
|
-
//
|
|
657
|
-
const
|
|
658
|
-
|
|
659
|
-
console.log(`${b.symbol}: ${b.balance}`);
|
|
660
|
-
}
|
|
520
|
+
// One line to get started (recommended)
|
|
521
|
+
const sdk = await PolymarketSDK.create({ privateKey: '0x...' });
|
|
522
|
+
// SDK is initialized and WebSocket connected
|
|
661
523
|
|
|
662
|
-
//
|
|
663
|
-
const
|
|
664
|
-
console.log(`Swapped: ${swapResult.amountOut} USDC.e`);
|
|
524
|
+
// Get smart money wallets
|
|
525
|
+
const wallets = await sdk.smartMoney.getSmartMoneyList(50);
|
|
665
526
|
|
|
666
|
-
//
|
|
667
|
-
const
|
|
527
|
+
// Check if address is smart money
|
|
528
|
+
const isSmartMoney = await sdk.smartMoney.isSmartMoney('0x...');
|
|
668
529
|
|
|
669
|
-
//
|
|
670
|
-
const
|
|
671
|
-
|
|
530
|
+
// Subscribe to smart money trades
|
|
531
|
+
const sub = sdk.smartMoney.subscribeSmartMoneyTrades(
|
|
532
|
+
(trade) => {
|
|
533
|
+
console.log(`${trade.traderName} ${trade.side} ${trade.outcome} @ $${trade.price}`);
|
|
534
|
+
},
|
|
535
|
+
{ filterAddresses: ['0x...'], minSize: 10 }
|
|
536
|
+
);
|
|
672
537
|
|
|
673
|
-
//
|
|
674
|
-
|
|
675
|
-
```
|
|
538
|
+
// ===== Auto Copy Trading =====
|
|
539
|
+
// Real-time copy trading - when smart money trades, copy immediately
|
|
676
540
|
|
|
677
|
-
|
|
541
|
+
const subscription = await sdk.smartMoney.startAutoCopyTrading({
|
|
542
|
+
// Target selection
|
|
543
|
+
topN: 50, // Follow top 50 traders from leaderboard
|
|
544
|
+
// targetAddresses: ['0x...'], // Or specify addresses directly
|
|
678
545
|
|
|
679
|
-
|
|
546
|
+
// Order settings
|
|
547
|
+
sizeScale: 0.1, // Copy 10% of their trade size
|
|
548
|
+
maxSizePerTrade: 10, // Max $10 per trade
|
|
549
|
+
maxSlippage: 0.03, // 3% slippage tolerance
|
|
550
|
+
orderType: 'FOK', // FOK or FAK
|
|
680
551
|
|
|
681
|
-
|
|
682
|
-
|
|
552
|
+
// Filters
|
|
553
|
+
minTradeSize: 5, // Only copy trades > $5
|
|
554
|
+
sideFilter: 'BUY', // Only copy BUY trades (optional)
|
|
683
555
|
|
|
684
|
-
|
|
556
|
+
// Testing
|
|
557
|
+
dryRun: true, // Set false for real trades
|
|
685
558
|
|
|
686
|
-
//
|
|
687
|
-
|
|
688
|
-
console.log(`
|
|
689
|
-
|
|
690
|
-
|
|
559
|
+
// Callbacks
|
|
560
|
+
onTrade: (trade, result) => {
|
|
561
|
+
console.log(`Copied ${trade.traderName}: ${result.success ? '✅' : '❌'}`);
|
|
562
|
+
},
|
|
563
|
+
onError: (error) => console.error(error),
|
|
564
|
+
});
|
|
691
565
|
|
|
692
|
-
|
|
693
|
-
console.log('Issues:', status.issues);
|
|
566
|
+
console.log(`Tracking ${subscription.targetAddresses.length} wallets`);
|
|
694
567
|
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
}
|
|
568
|
+
// Get stats
|
|
569
|
+
const stats = subscription.getStats();
|
|
570
|
+
console.log(`Detected: ${stats.tradesDetected}, Executed: ${stats.tradesExecuted}`);
|
|
699
571
|
|
|
700
|
-
//
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
}
|
|
572
|
+
// Stop
|
|
573
|
+
subscription.stop();
|
|
574
|
+
sdk.stop();
|
|
704
575
|
```
|
|
705
576
|
|
|
706
|
-
|
|
577
|
+
> **Note**: Polymarket minimum order size is **$1**. Orders below $1 will be automatically skipped.
|
|
707
578
|
|
|
708
|
-
|
|
579
|
+
📁 **Full examples**: See [scripts/smart-money/](scripts/smart-money/) for complete working scripts:
|
|
580
|
+
- `04-auto-copy-trading.ts` - Full-featured auto copy trading
|
|
581
|
+
- `05-auto-copy-simple.ts` - Simplified SDK usage
|
|
582
|
+
- `06-real-copy-test.ts` - Real trading test
|
|
709
583
|
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
├─────────────────────────────────────────────────────────────────────────────┤
|
|
714
|
-
│ • scanMarkets() - 扫描市场找套利机会 │
|
|
715
|
-
│ • start(market) - 启动实时监控 + 自动执行 │
|
|
716
|
-
│ • clearPositions() - 智能清仓 (活跃市场卖出, 已结算市场 redeem) │
|
|
717
|
-
├─────────────────────────────────────────────────────────────────────────────┤
|
|
718
|
-
│ 自动再平衡 (Rebalancer) │
|
|
719
|
-
├─────────────────────────────────────────────────────────────────────────────┤
|
|
720
|
-
│ 套利需要 USDC + YES/NO Token,Rebalancer 自动维持资金比例: │
|
|
721
|
-
│ • USDC 比例 < 20% → 自动 Merge (YES+NO → USDC) │
|
|
722
|
-
│ • USDC 比例 > 80% → 自动 Split (USDC → YES+NO) │
|
|
723
|
-
│ • 冷却机制:两次操作间隔 ≥ 30s,检测间隔 10s │
|
|
724
|
-
├─────────────────────────────────────────────────────────────────────────────┤
|
|
725
|
-
│ 执行安全 (Partial Fill Protection) │
|
|
726
|
-
├─────────────────────────────────────────────────────────────────────────────┤
|
|
727
|
-
│ 套利需要同时买入 YES 和 NO,但订单可能部分成交: │
|
|
728
|
-
│ • sizeSafetyFactor=0.8 → 只使用 80% 的盘口深度,降低滑点风险 │
|
|
729
|
-
│ • autoFixImbalance=true → 如果只成交一侧,自动卖出多余的 token │
|
|
730
|
-
│ • imbalanceThreshold=5 → YES-NO 差额超过 $5 时触发修复 │
|
|
731
|
-
└─────────────────────────────────────────────────────────────────────────────┘
|
|
732
|
-
```
|
|
584
|
+
---
|
|
585
|
+
|
|
586
|
+
### ArbitrageService
|
|
733
587
|
|
|
734
|
-
|
|
588
|
+
Real-time arbitrage detection, execution, and position management.
|
|
735
589
|
|
|
736
590
|
```typescript
|
|
737
591
|
import { ArbitrageService } from '@catalyst-team/poly-sdk';
|
|
@@ -741,20 +595,17 @@ const arbService = new ArbitrageService({
|
|
|
741
595
|
profitThreshold: 0.005, // 0.5% minimum profit
|
|
742
596
|
minTradeSize: 5, // $5 minimum
|
|
743
597
|
maxTradeSize: 100, // $100 maximum
|
|
744
|
-
autoExecute: true, //
|
|
745
|
-
|
|
746
|
-
// Rebalancer
|
|
747
|
-
enableRebalancer: true,
|
|
748
|
-
minUsdcRatio: 0.2, // Min 20% USDC
|
|
749
|
-
maxUsdcRatio: 0.8, // Max 80% USDC
|
|
750
|
-
targetUsdcRatio: 0.5, // Target
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
rebalanceCooldown: 30000, // Min 30s between actions
|
|
754
|
-
|
|
755
|
-
// Execution safety (prevents YES ≠ NO from partial fills)
|
|
598
|
+
autoExecute: true, // Auto-execute opportunities
|
|
599
|
+
|
|
600
|
+
// Rebalancer: auto-maintain USDC/token ratio
|
|
601
|
+
enableRebalancer: true,
|
|
602
|
+
minUsdcRatio: 0.2, // Min 20% USDC
|
|
603
|
+
maxUsdcRatio: 0.8, // Max 80% USDC
|
|
604
|
+
targetUsdcRatio: 0.5, // Target when rebalancing
|
|
605
|
+
|
|
606
|
+
// Execution safety
|
|
756
607
|
sizeSafetyFactor: 0.8, // Use 80% of orderbook depth
|
|
757
|
-
autoFixImbalance: true, // Auto-
|
|
608
|
+
autoFixImbalance: true, // Auto-fix partial fills
|
|
758
609
|
});
|
|
759
610
|
|
|
760
611
|
// Listen for events
|
|
@@ -764,320 +615,202 @@ arbService.on('opportunity', (opp) => {
|
|
|
764
615
|
|
|
765
616
|
arbService.on('execution', (result) => {
|
|
766
617
|
if (result.success) {
|
|
767
|
-
console.log(
|
|
618
|
+
console.log(`Executed: $${result.profit.toFixed(2)} profit`);
|
|
768
619
|
}
|
|
769
620
|
});
|
|
770
621
|
|
|
771
|
-
|
|
772
|
-
console.log(`🔄 Rebalance: ${result.action.type} ${result.action.amount}`);
|
|
773
|
-
});
|
|
622
|
+
// ===== Workflow =====
|
|
774
623
|
|
|
775
|
-
//
|
|
624
|
+
// 1. Scan markets for opportunities
|
|
776
625
|
const results = await arbService.scanMarkets({ minVolume24h: 5000 }, 0.005);
|
|
777
|
-
console.log(`Found ${results.filter(r => r.arbType !== 'none').length} opportunities`);
|
|
778
626
|
|
|
779
|
-
//
|
|
627
|
+
// 2. Start monitoring best market
|
|
780
628
|
const best = await arbService.findAndStart(0.005);
|
|
781
|
-
|
|
782
|
-
console.log('No arbitrage opportunities found');
|
|
783
|
-
process.exit(0);
|
|
784
|
-
}
|
|
785
|
-
console.log(`🎯 Started: ${best.market.name} (+${best.profitPercent.toFixed(2)}%)`);
|
|
629
|
+
console.log(`Started: ${best.market.name} (+${best.profitPercent.toFixed(2)}%)`);
|
|
786
630
|
|
|
787
|
-
//
|
|
788
|
-
//
|
|
789
|
-
// 运行一段时间后:
|
|
790
|
-
await new Promise(resolve => setTimeout(resolve, 60 * 60 * 1000)); // 1 hour
|
|
631
|
+
// 3. Run for a while...
|
|
632
|
+
await new Promise(r => setTimeout(r, 60 * 60 * 1000)); // 1 hour
|
|
791
633
|
|
|
792
|
-
//
|
|
634
|
+
// 4. Stop and clear positions
|
|
793
635
|
await arbService.stop();
|
|
794
|
-
console.log('Stats:', arbService.getStats());
|
|
795
|
-
|
|
796
|
-
// 智能清仓: 活跃市场 merge+sell, 已结算市场 redeem
|
|
797
636
|
const clearResult = await arbService.clearPositions(best.market, true);
|
|
798
|
-
console.log(
|
|
637
|
+
console.log(`Recovered: $${clearResult.totalUsdcRecovered.toFixed(2)}`);
|
|
799
638
|
```
|
|
800
639
|
|
|
801
|
-
|
|
640
|
+
---
|
|
802
641
|
|
|
803
|
-
|
|
804
|
-
// 如果不用 scanMarkets,可以手动构建 market config
|
|
805
|
-
const market = {
|
|
806
|
-
name: 'Will BTC reach $100k?',
|
|
807
|
-
conditionId: '0x...',
|
|
808
|
-
yesTokenId: '12345...',
|
|
809
|
-
noTokenId: '67890...',
|
|
810
|
-
outcomes: ['Yes', 'No'] as [string, string],
|
|
811
|
-
};
|
|
812
|
-
|
|
813
|
-
await arbService.start(market);
|
|
814
|
-
```
|
|
642
|
+
## Low-Level Clients
|
|
815
643
|
|
|
816
|
-
|
|
644
|
+
For advanced users who need direct API access:
|
|
817
645
|
|
|
818
646
|
```typescript
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
647
|
+
import {
|
|
648
|
+
DataApiClient, // Positions, trades, leaderboard
|
|
649
|
+
GammaApiClient, // Markets, events, search
|
|
650
|
+
SubgraphClient, // On-chain data via Goldsky
|
|
651
|
+
CTFClient, // CTF contract operations
|
|
652
|
+
BridgeClient, // Cross-chain deposits
|
|
653
|
+
SwapService, // DEX swaps on Polygon
|
|
654
|
+
} from '@catalyst-team/poly-sdk';
|
|
655
|
+
|
|
656
|
+
// Data API
|
|
657
|
+
const positions = await sdk.dataApi.getPositions('0x...');
|
|
658
|
+
const trades = await sdk.dataApi.getTrades('0x...');
|
|
659
|
+
const leaderboard = await sdk.dataApi.getLeaderboard();
|
|
660
|
+
|
|
661
|
+
// Gamma API
|
|
662
|
+
const markets = await sdk.gammaApi.searchMarkets({ query: 'bitcoin' });
|
|
663
|
+
const trending = await sdk.gammaApi.getTrendingMarkets(10);
|
|
664
|
+
const events = await sdk.gammaApi.getEvents({ limit: 20 });
|
|
665
|
+
|
|
666
|
+
// Subgraph (on-chain data)
|
|
667
|
+
const userPositions = await sdk.subgraph.getUserPositions(address);
|
|
668
|
+
const isResolved = await sdk.subgraph.isConditionResolved(conditionId);
|
|
669
|
+
const globalOI = await sdk.subgraph.getGlobalOpenInterest();
|
|
824
670
|
```
|
|
825
671
|
|
|
826
|
-
|
|
672
|
+
---
|
|
827
673
|
|
|
674
|
+
## Breaking Changes (v0.3.0)
|
|
675
|
+
|
|
676
|
+
### `UnifiedMarket.tokens` is now an Array
|
|
677
|
+
|
|
678
|
+
**Before (v0.2.x)**:
|
|
828
679
|
```typescript
|
|
829
|
-
//
|
|
830
|
-
const
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
});
|
|
680
|
+
// Object with yes/no properties
|
|
681
|
+
const yesPrice = market.tokens.yes.price;
|
|
682
|
+
const noPrice = market.tokens.no.price;
|
|
683
|
+
```
|
|
834
684
|
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
685
|
+
**After (v0.3.0)**:
|
|
686
|
+
```typescript
|
|
687
|
+
// Array of MarketToken objects
|
|
688
|
+
const yesToken = market.tokens.find(t => t.outcome === 'Yes');
|
|
689
|
+
const noToken = market.tokens.find(t => t.outcome === 'No');
|
|
840
690
|
|
|
841
|
-
|
|
691
|
+
const yesPrice = yesToken?.price;
|
|
692
|
+
const noPrice = noToken?.price;
|
|
842
693
|
```
|
|
843
694
|
|
|
844
|
-
|
|
695
|
+
### Migration Guide
|
|
845
696
|
|
|
846
697
|
```typescript
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
getEffectivePrices, // For Polymarket mirror orderbook
|
|
852
|
-
checkArbitrage,
|
|
853
|
-
formatUSDC,
|
|
854
|
-
calculatePnL,
|
|
855
|
-
type TickSize,
|
|
856
|
-
} from '@catalyst-team/poly-sdk';
|
|
698
|
+
// Helper function for migration
|
|
699
|
+
function getTokenPrice(market: UnifiedMarket, outcome: 'Yes' | 'No'): number {
|
|
700
|
+
return market.tokens.find(t => t.outcome === outcome)?.price ?? 0;
|
|
701
|
+
}
|
|
857
702
|
|
|
858
|
-
//
|
|
859
|
-
const
|
|
860
|
-
|
|
861
|
-
|
|
703
|
+
// Usage
|
|
704
|
+
const yesPrice = getTokenPrice(market, 'Yes');
|
|
705
|
+
const noPrice = getTokenPrice(market, 'No');
|
|
706
|
+
```
|
|
862
707
|
|
|
863
|
-
|
|
864
|
-
const validation = validatePrice(0.525, tickSize);
|
|
865
|
-
if (!validation.valid) {
|
|
866
|
-
console.log(validation.error);
|
|
867
|
-
}
|
|
708
|
+
**Why the change?** The array format better supports multi-outcome markets and is more consistent with the Polymarket API response format.
|
|
868
709
|
|
|
869
|
-
|
|
870
|
-
const cost = calculateBuyAmount(0.52, 100); // $52
|
|
871
|
-
console.log(formatUSDC(cost)); // "$52.00"
|
|
710
|
+
---
|
|
872
711
|
|
|
873
|
-
|
|
874
|
-
const effective = getEffectivePrices(yesAsk, yesBid, noAsk, noBid);
|
|
875
|
-
console.log(`Effective buy YES: ${effective.effectiveBuyYes}`); // min(YES.ask, 1 - NO.bid)
|
|
876
|
-
console.log(`Effective buy NO: ${effective.effectiveBuyNo}`); // min(NO.ask, 1 - YES.bid)
|
|
712
|
+
## Examples
|
|
877
713
|
|
|
878
|
-
|
|
879
|
-
const arb = checkArbitrage(
|
|
880
|
-
yesAsk, noAsk, // Ask prices
|
|
881
|
-
yesBid, noBid // Bid prices
|
|
882
|
-
);
|
|
883
|
-
if (arb) {
|
|
884
|
-
console.log(`${arb.type} arb: ${(arb.profit * 100).toFixed(2)}% profit`);
|
|
885
|
-
console.log(arb.description); // "Buy YES @ 0.48 + NO @ 0.50, Merge for $1"
|
|
886
|
-
}
|
|
714
|
+
Run examples with:
|
|
887
715
|
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
716
|
+
```bash
|
|
717
|
+
pnpm example:basic # Basic usage
|
|
718
|
+
pnpm example:smart-money # Smart money analysis
|
|
719
|
+
pnpm example:trading # Trading orders
|
|
720
|
+
pnpm example:realtime # WebSocket feeds
|
|
721
|
+
pnpm example:arb-service # Arbitrage service
|
|
891
722
|
```
|
|
892
723
|
|
|
893
|
-
|
|
724
|
+
| Example | Description |
|
|
725
|
+
|---------|-------------|
|
|
726
|
+
| [01-basic-usage.ts](examples/01-basic-usage.ts) | Get markets, orderbooks, detect arbitrage |
|
|
727
|
+
| [02-smart-money.ts](examples/02-smart-money.ts) | Top traders, wallet profiles, smart scores |
|
|
728
|
+
| [03-market-analysis.ts](examples/03-market-analysis.ts) | Market signals, volume analysis |
|
|
729
|
+
| [04-kline-aggregation.ts](examples/04-kline-aggregation.ts) | Build OHLCV candles from trades |
|
|
730
|
+
| [05-follow-wallet-strategy.ts](examples/05-follow-wallet-strategy.ts) | Track smart money, detect exits |
|
|
731
|
+
| [06-services-demo.ts](examples/06-services-demo.ts) | All SDK services in action |
|
|
732
|
+
| [07-realtime-websocket.ts](examples/07-realtime-websocket.ts) | Live price feeds, orderbook updates |
|
|
733
|
+
| [08-trading-orders.ts](examples/08-trading-orders.ts) | GTC, GTD, FOK, FAK order types |
|
|
734
|
+
| [09-rewards-tracking.ts](examples/09-rewards-tracking.ts) | Market maker incentives, earnings |
|
|
735
|
+
| [10-ctf-operations.ts](examples/10-ctf-operations.ts) | Split, merge, redeem tokens |
|
|
736
|
+
| [11-live-arbitrage-scan.ts](examples/11-live-arbitrage-scan.ts) | Scan markets for opportunities |
|
|
737
|
+
| [12-trending-arb-monitor.ts](examples/12-trending-arb-monitor.ts) | Real-time trending monitor |
|
|
738
|
+
| [13-arbitrage-service.ts](examples/13-arbitrage-service.ts) | Full arbitrage workflow |
|
|
894
739
|
|
|
895
|
-
|
|
740
|
+
---
|
|
896
741
|
|
|
897
|
-
|
|
898
|
-
import type { KLineInterval } from '@catalyst-team/poly-sdk';
|
|
742
|
+
## API Reference
|
|
899
743
|
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
744
|
+
For detailed API documentation, see:
|
|
745
|
+
|
|
746
|
+
- [docs/00-design.md](docs/00-design.md) - Architecture design
|
|
747
|
+
- [docs/02-API.md](docs/02-API.md) - Complete API reference
|
|
748
|
+
- [docs/01-polymarket-orderbook-arbitrage.md](docs/01-polymarket-orderbook-arbitrage.md) - Orderbook mirror & arbitrage
|
|
903
749
|
|
|
904
|
-
|
|
750
|
+
### Type Exports
|
|
905
751
|
|
|
906
752
|
```typescript
|
|
907
753
|
import type {
|
|
908
|
-
// Core
|
|
754
|
+
// Core types
|
|
909
755
|
UnifiedMarket,
|
|
910
|
-
|
|
911
|
-
BookUpdate,
|
|
756
|
+
MarketToken,
|
|
912
757
|
ProcessedOrderbook,
|
|
913
758
|
ArbitrageOpportunity,
|
|
914
|
-
EffectivePrices,
|
|
759
|
+
EffectivePrices,
|
|
915
760
|
|
|
916
|
-
//
|
|
761
|
+
// Trading
|
|
762
|
+
Side,
|
|
763
|
+
OrderType,
|
|
764
|
+
Order,
|
|
765
|
+
OrderResult,
|
|
766
|
+
LimitOrderParams,
|
|
767
|
+
MarketOrderParams,
|
|
768
|
+
|
|
769
|
+
// K-Lines
|
|
917
770
|
KLineInterval,
|
|
918
771
|
KLineCandle,
|
|
919
772
|
DualKLineData,
|
|
920
|
-
SpreadDataPoint,
|
|
773
|
+
SpreadDataPoint,
|
|
774
|
+
|
|
775
|
+
// WebSocket
|
|
776
|
+
PriceUpdate,
|
|
777
|
+
BookUpdate,
|
|
778
|
+
OrderbookSnapshot,
|
|
921
779
|
|
|
922
780
|
// Wallet
|
|
923
781
|
WalletProfile,
|
|
924
782
|
SellActivityResult,
|
|
925
783
|
|
|
926
|
-
//
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
OrderResult,
|
|
933
|
-
TradeInfo,
|
|
934
|
-
|
|
935
|
-
// Rewards
|
|
936
|
-
UserEarning,
|
|
937
|
-
MarketReward,
|
|
784
|
+
// Smart Money
|
|
785
|
+
SmartMoneyWallet,
|
|
786
|
+
SmartMoneyTrade,
|
|
787
|
+
AutoCopyTradingOptions,
|
|
788
|
+
AutoCopyTradingStats,
|
|
789
|
+
AutoCopyTradingSubscription,
|
|
938
790
|
|
|
939
791
|
// CTF
|
|
940
|
-
CTFConfig,
|
|
941
792
|
SplitResult,
|
|
942
793
|
MergeResult,
|
|
943
794
|
RedeemResult,
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
TokenIds,
|
|
947
|
-
|
|
948
|
-
// Bridge
|
|
949
|
-
BridgeSupportedAsset,
|
|
950
|
-
DepositAddress,
|
|
951
|
-
DepositStatus,
|
|
952
|
-
DepositResult,
|
|
953
|
-
SwapAndDepositResult,
|
|
954
|
-
|
|
955
|
-
// Swap
|
|
956
|
-
SupportedToken,
|
|
957
|
-
SwapQuote,
|
|
958
|
-
SwapResult,
|
|
959
|
-
TokenBalance,
|
|
960
|
-
|
|
961
|
-
// Authorization
|
|
962
|
-
AllowanceInfo,
|
|
963
|
-
AllowancesResult,
|
|
964
|
-
ApprovalTxResult,
|
|
965
|
-
|
|
966
|
-
// ArbitrageService
|
|
795
|
+
|
|
796
|
+
// Arbitrage
|
|
967
797
|
ArbitrageMarketConfig,
|
|
968
798
|
ArbitrageServiceConfig,
|
|
969
|
-
ArbitrageServiceOpportunity,
|
|
970
|
-
ArbitrageExecutionResult,
|
|
971
|
-
OrderbookState,
|
|
972
|
-
BalanceState,
|
|
973
|
-
RebalanceAction,
|
|
974
|
-
RebalanceResult,
|
|
975
|
-
SettleResult,
|
|
976
|
-
// ArbitrageService - Scanning
|
|
977
|
-
ScanCriteria,
|
|
978
799
|
ScanResult,
|
|
979
|
-
// ArbitrageService - Smart clearing
|
|
980
800
|
ClearPositionResult,
|
|
981
|
-
ClearAction,
|
|
982
|
-
|
|
983
|
-
// Price Utils
|
|
984
|
-
TickSize,
|
|
985
|
-
|
|
986
|
-
// API types
|
|
987
|
-
Position,
|
|
988
|
-
Trade,
|
|
989
|
-
LeaderboardEntry,
|
|
990
|
-
GammaMarket,
|
|
991
|
-
ClobMarket,
|
|
992
|
-
Orderbook,
|
|
993
801
|
} from '@catalyst-team/poly-sdk';
|
|
994
802
|
```
|
|
995
803
|
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
```typescript
|
|
999
|
-
import { PolymarketError, ErrorCode, withRetry } from '@catalyst-team/poly-sdk';
|
|
1000
|
-
|
|
1001
|
-
try {
|
|
1002
|
-
const market = await sdk.getMarket('invalid-slug');
|
|
1003
|
-
} catch (error) {
|
|
1004
|
-
if (error instanceof PolymarketError) {
|
|
1005
|
-
if (error.code === ErrorCode.MARKET_NOT_FOUND) {
|
|
1006
|
-
console.log('Market not found');
|
|
1007
|
-
} else if (error.code === ErrorCode.RATE_LIMITED) {
|
|
1008
|
-
console.log('Rate limited, retry later');
|
|
1009
|
-
}
|
|
1010
|
-
}
|
|
1011
|
-
}
|
|
1012
|
-
|
|
1013
|
-
// Auto-retry with exponential backoff
|
|
1014
|
-
const result = await withRetry(() => sdk.getMarket(slug), {
|
|
1015
|
-
maxRetries: 3,
|
|
1016
|
-
baseDelay: 1000,
|
|
1017
|
-
});
|
|
1018
|
-
```
|
|
1019
|
-
|
|
1020
|
-
## Rate Limiting
|
|
1021
|
-
|
|
1022
|
-
Built-in rate limiting per API type:
|
|
1023
|
-
- Data API: 10 req/sec
|
|
1024
|
-
- Gamma API: 10 req/sec
|
|
1025
|
-
- CLOB API: 5 req/sec
|
|
1026
|
-
|
|
1027
|
-
```typescript
|
|
1028
|
-
import { RateLimiter, ApiType } from '@catalyst-team/poly-sdk';
|
|
1029
|
-
|
|
1030
|
-
// Custom rate limiter
|
|
1031
|
-
const limiter = new RateLimiter({
|
|
1032
|
-
[ApiType.DATA]: { maxConcurrent: 5, minTime: 200 },
|
|
1033
|
-
[ApiType.GAMMA]: { maxConcurrent: 5, minTime: 200 },
|
|
1034
|
-
[ApiType.CLOB]: { maxConcurrent: 2, minTime: 500 },
|
|
1035
|
-
});
|
|
1036
|
-
```
|
|
1037
|
-
|
|
1038
|
-
## Caching
|
|
1039
|
-
|
|
1040
|
-
Built-in TTL-based caching:
|
|
1041
|
-
|
|
1042
|
-
```typescript
|
|
1043
|
-
// Clear all cache
|
|
1044
|
-
sdk.clearCache();
|
|
1045
|
-
|
|
1046
|
-
// Invalidate specific market
|
|
1047
|
-
sdk.invalidateMarketCache(conditionId);
|
|
1048
|
-
```
|
|
1049
|
-
|
|
1050
|
-
## Examples
|
|
1051
|
-
|
|
1052
|
-
| Example | Description | Source |
|
|
1053
|
-
|---------|-------------|--------|
|
|
1054
|
-
| [Basic Usage](examples/01-basic-usage.ts) | Get markets, orderbooks, detect arbitrage | `pnpm example:basic` |
|
|
1055
|
-
| [Smart Money](examples/02-smart-money.ts) | Top traders, wallet profiles, smart scores | `pnpm example:smart-money` |
|
|
1056
|
-
| [Market Analysis](examples/03-market-analysis.ts) | Market signals, volume analysis | `pnpm example:market-analysis` |
|
|
1057
|
-
| [K-Line Aggregation](examples/04-kline-aggregation.ts) | Build OHLCV candles from trades | `pnpm example:kline` |
|
|
1058
|
-
| [Follow Wallet](examples/05-follow-wallet-strategy.ts) | Track smart money positions, detect exits | `pnpm example:follow-wallet` |
|
|
1059
|
-
| [Services Demo](examples/06-services-demo.ts) | All SDK services in action | `pnpm example:services` |
|
|
1060
|
-
| [Realtime WebSocket](examples/07-realtime-websocket.ts) | Live price feeds, orderbook updates | `pnpm example:realtime` |
|
|
1061
|
-
| [Trading Orders](examples/08-trading-orders.ts) | GTC, GTD, FOK, FAK order types | `pnpm example:trading` |
|
|
1062
|
-
| [Rewards Tracking](examples/09-rewards-tracking.ts) | Market maker incentives, earnings | `pnpm example:rewards` |
|
|
1063
|
-
| [CTF Operations](examples/10-ctf-operations.ts) | Split, merge, redeem tokens | `pnpm example:ctf` |
|
|
1064
|
-
| [Live Arbitrage Scan](examples/11-live-arbitrage-scan.ts) | Scan real markets for opportunities | `pnpm example:live-arb` |
|
|
1065
|
-
| [Trending Arb Monitor](examples/12-trending-arb-monitor.ts) | Real-time trending markets monitor | `pnpm example:trending-arb` |
|
|
1066
|
-
|
|
1067
|
-
Run any example:
|
|
1068
|
-
|
|
1069
|
-
```bash
|
|
1070
|
-
pnpm example:basic
|
|
1071
|
-
pnpm example:smart-money
|
|
1072
|
-
pnpm example:trading
|
|
1073
|
-
# etc.
|
|
1074
|
-
```
|
|
804
|
+
---
|
|
1075
805
|
|
|
1076
806
|
## Dependencies
|
|
1077
807
|
|
|
1078
|
-
- `@
|
|
808
|
+
- `@polymarket/clob-client` - Official CLOB trading client
|
|
809
|
+
- `@polymarket/real-time-data-client` - Official WebSocket client
|
|
810
|
+
- `ethers@5` - Blockchain interactions
|
|
1079
811
|
- `bottleneck` - Rate limiting
|
|
1080
|
-
|
|
812
|
+
|
|
813
|
+
---
|
|
1081
814
|
|
|
1082
815
|
## License
|
|
1083
816
|
|