@catalyst-team/poly-sdk 0.1.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/.env +0 -0
- package/README.md +803 -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/dist/core/types.d.ts +314 -0
- 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 +94 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +258 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/errors.d.ts +33 -0
- package/dist/mcp/errors.d.ts.map +1 -0
- package/dist/mcp/errors.js +86 -0
- package/dist/mcp/errors.js.map +1 -0
- package/dist/mcp/index.d.ts +62 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +173 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/server.d.ts +17 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +155 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools/guide.d.ts +12 -0
- package/dist/mcp/tools/guide.d.ts.map +1 -0
- package/dist/mcp/tools/guide.js +801 -0
- package/dist/mcp/tools/guide.js.map +1 -0
- package/dist/mcp/tools/index.d.ts +11 -0
- package/dist/mcp/tools/index.d.ts.map +1 -0
- package/dist/mcp/tools/index.js +27 -0
- package/dist/mcp/tools/index.js.map +1 -0
- package/dist/mcp/tools/market.d.ts +11 -0
- package/dist/mcp/tools/market.d.ts.map +1 -0
- package/dist/mcp/tools/market.js +314 -0
- package/dist/mcp/tools/market.js.map +1 -0
- package/dist/mcp/tools/order.d.ts +10 -0
- package/dist/mcp/tools/order.d.ts.map +1 -0
- package/dist/mcp/tools/order.js +258 -0
- package/dist/mcp/tools/order.js.map +1 -0
- package/dist/mcp/tools/trade.d.ts +38 -0
- package/dist/mcp/tools/trade.d.ts.map +1 -0
- package/dist/mcp/tools/trade.js +314 -0
- package/dist/mcp/tools/trade.js.map +1 -0
- package/dist/mcp/tools/trader.d.ts +11 -0
- package/dist/mcp/tools/trader.d.ts.map +1 -0
- package/dist/mcp/tools/trader.js +277 -0
- package/dist/mcp/tools/trader.js.map +1 -0
- package/dist/mcp/tools/wallet.d.ts +274 -0
- package/dist/mcp/tools/wallet.d.ts.map +1 -0
- package/dist/mcp/tools/wallet.js +579 -0
- package/dist/mcp/tools/wallet.js.map +1 -0
- package/dist/mcp/types.d.ts +413 -0
- package/dist/mcp/types.d.ts.map +1 -0
- package/dist/mcp/types.js +5 -0
- package/dist/mcp/types.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/docs/00-design.md +760 -0
- package/docs/01-mcp.md +2041 -0
- package/docs/02-API.md +1148 -0
- package/docs/e2e/01-trader-tools.md +159 -0
- package/docs/e2e/02-market-tools.md +180 -0
- package/docs/e2e/03-order-tools.md +166 -0
- package/docs/e2e/04-wallet-tools.md +224 -0
- package/docs/e2e/05-trading-tools.md +327 -0
- package/docs/e2e/06-integration-scenarios.md +481 -0
- package/docs/e2e/coordinator.md +376 -0
- package/examples/01-basic-usage.ts +68 -0
- package/examples/02-smart-money.ts +95 -0
- package/examples/03-market-analysis.ts +108 -0
- package/examples/04-kline-aggregation.ts +158 -0
- package/examples/05-follow-wallet-strategy.ts +156 -0
- package/examples/06-services-demo.ts +124 -0
- package/examples/07-realtime-websocket.ts +117 -0
- package/examples/08-trading-orders.ts +278 -0
- package/examples/09-rewards-tracking.ts +187 -0
- package/examples/10-ctf-operations.ts +336 -0
- package/examples/11-live-arbitrage-scan.ts +221 -0
- package/examples/12-trending-arb-monitor.ts +406 -0
- package/examples/README.md +179 -0
- package/package.json +62 -0
- package/scripts/README.md +163 -0
- package/scripts/approvals/approve-erc1155.ts +129 -0
- package/scripts/approvals/approve-neg-risk-erc1155.ts +149 -0
- package/scripts/approvals/approve-neg-risk.ts +102 -0
- package/scripts/approvals/check-all-allowances.ts +150 -0
- package/scripts/approvals/check-allowance.ts +129 -0
- package/scripts/approvals/check-ctf-approval.ts +158 -0
- package/scripts/datas/001-report.md +486 -0
- package/scripts/datas/clone-modal-screenshot.png +0 -0
- package/scripts/deposit/deposit-native-usdc.ts +179 -0
- package/scripts/deposit/deposit-usdc.ts +155 -0
- package/scripts/deposit/swap-usdc-to-usdce.ts +375 -0
- package/scripts/research/research-markets.ts +166 -0
- package/scripts/trading/check-orders.ts +50 -0
- package/scripts/trading/sell-nvidia-positions.ts +206 -0
- package/scripts/trading/test-order.ts +172 -0
- package/scripts/truth.md +440 -0
- package/scripts/verify/test-approve-trading.ts +98 -0
- package/scripts/verify/test-provider-fix.ts +43 -0
- package/scripts/verify/test-search-mcp.ts +113 -0
- package/scripts/verify/verify-all-apis.ts +160 -0
- package/scripts/wallet/check-wallet-balances.ts +75 -0
- package/scripts/wallet/test-wallet-operations.ts +191 -0
- package/scripts/wallet/verify-wallet-tools.ts +124 -0
- package/src/__tests__/clob-api.test.ts +301 -0
- package/src/__tests__/integration/bridge-client.integration.test.ts +314 -0
- package/src/__tests__/integration/clob-api.integration.test.ts +218 -0
- package/src/__tests__/integration/ctf-client.integration.test.ts +331 -0
- package/src/__tests__/integration/data-api.integration.test.ts +194 -0
- package/src/__tests__/integration/gamma-api.integration.test.ts +206 -0
- package/src/__tests__/test-utils.ts +170 -0
- package/src/clients/bridge-client.ts +841 -0
- package/src/clients/clob-api.ts +629 -0
- package/src/clients/ctf-client.ts +1216 -0
- package/src/clients/data-api.ts +469 -0
- package/src/clients/gamma-api.ts +597 -0
- package/src/clients/trading-client.ts +749 -0
- package/src/clients/websocket-manager.ts +267 -0
- package/src/core/cache-adapter-bridge.ts +94 -0
- package/src/core/cache.ts +85 -0
- package/src/core/errors.ts +117 -0
- package/src/core/rate-limiter.ts +74 -0
- package/src/core/types.ts +360 -0
- package/src/core/unified-cache.ts +153 -0
- package/src/index.ts +455 -0
- package/src/mcp/README.md +380 -0
- package/src/mcp/errors.ts +124 -0
- package/src/mcp/index.ts +309 -0
- package/src/mcp/server.ts +183 -0
- package/src/mcp/tools/guide.ts +821 -0
- package/src/mcp/tools/index.ts +73 -0
- package/src/mcp/tools/market.ts +363 -0
- package/src/mcp/tools/order.ts +326 -0
- package/src/mcp/tools/trade.ts +417 -0
- package/src/mcp/tools/trader.ts +322 -0
- package/src/mcp/tools/wallet.ts +683 -0
- package/src/mcp/types.ts +472 -0
- package/src/services/authorization-service.ts +357 -0
- package/src/services/market-service.ts +544 -0
- package/src/services/realtime-service.ts +196 -0
- package/src/services/swap-service.ts +896 -0
- package/src/services/wallet-service.ts +259 -0
- package/src/utils/price-utils.ts +307 -0
- package/tsconfig.json +8 -0
- package/vitest.config.ts +19 -0
- package/vitest.integration.config.ts +18 -0
package/docs/02-API.md
ADDED
|
@@ -0,0 +1,1148 @@
|
|
|
1
|
+
# @prediction-router/poly-sdk API Reference
|
|
2
|
+
|
|
3
|
+
Complete API documentation for the Polymarket SDK.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Installation](#installation)
|
|
8
|
+
- [Quick Start](#quick-start)
|
|
9
|
+
- [Core Clients](#core-clients)
|
|
10
|
+
- [PolymarketSDK](#polymarketsdk)
|
|
11
|
+
- [ClobApiClient](#clobapiclient)
|
|
12
|
+
- [GammaApiClient](#gammaapiclient)
|
|
13
|
+
- [DataApiClient](#dataapiclient)
|
|
14
|
+
- [TradingClient](#tradingclient)
|
|
15
|
+
- [BridgeClient](#bridgeclient)
|
|
16
|
+
- [CTFClient](#ctfclient)
|
|
17
|
+
- [WebSocketManager](#websocketmanager)
|
|
18
|
+
- [Services](#services)
|
|
19
|
+
- [MarketService](#marketservice)
|
|
20
|
+
- [ArbitrageService](#arbitrageservice)
|
|
21
|
+
- [RealtimeService](#realtimeservice)
|
|
22
|
+
- [WalletService](#walletservice)
|
|
23
|
+
- [Utility Functions](#utility-functions)
|
|
24
|
+
- [Types](#types)
|
|
25
|
+
- [Error Handling](#error-handling)
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pnpm add @prediction-router/poly-sdk
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Quick Start
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { PolymarketSDK } from '@prediction-router/poly-sdk';
|
|
39
|
+
|
|
40
|
+
const sdk = new PolymarketSDK();
|
|
41
|
+
|
|
42
|
+
// Get trending markets
|
|
43
|
+
const markets = await sdk.gammaApi.getTrendingMarkets(10);
|
|
44
|
+
|
|
45
|
+
// Get orderbook for a specific market
|
|
46
|
+
const orderbook = await sdk.clobApi.getProcessedOrderbook(markets[0].conditionId);
|
|
47
|
+
|
|
48
|
+
console.log('Long arb profit:', orderbook.summary.longArbProfit);
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Core Clients
|
|
54
|
+
|
|
55
|
+
### PolymarketSDK
|
|
56
|
+
|
|
57
|
+
The main SDK class that provides access to all API clients.
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
import { PolymarketSDK } from '@prediction-router/poly-sdk';
|
|
61
|
+
|
|
62
|
+
const sdk = new PolymarketSDK(config?: PolymarketSDKConfig);
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
#### Constructor Parameters
|
|
66
|
+
|
|
67
|
+
| Parameter | Type | Description |
|
|
68
|
+
|-----------|------|-------------|
|
|
69
|
+
| `config.chainId` | `number` | Polygon chain ID (137 = mainnet, 80002 = Amoy testnet) |
|
|
70
|
+
| `config.privateKey` | `string` | Private key for trading operations |
|
|
71
|
+
| `config.apiCredentials` | `ApiCredentials` | Pre-generated API credentials |
|
|
72
|
+
|
|
73
|
+
#### Properties
|
|
74
|
+
|
|
75
|
+
| Property | Type | Description |
|
|
76
|
+
|----------|------|-------------|
|
|
77
|
+
| `gammaApi` | `GammaApiClient` | Market discovery and metadata |
|
|
78
|
+
| `clobApi` | `ClobApiClient` | Orderbook and market data |
|
|
79
|
+
| `dataApi` | `DataApiClient` | Positions, trades, leaderboard |
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
### ClobApiClient
|
|
84
|
+
|
|
85
|
+
Central Limit Order Book (CLOB) API client for orderbook and market data.
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
import { ClobApiClient, RateLimiter, Cache } from '@prediction-router/poly-sdk';
|
|
89
|
+
|
|
90
|
+
const client = new ClobApiClient(
|
|
91
|
+
rateLimiter: RateLimiter,
|
|
92
|
+
cache: Cache,
|
|
93
|
+
config?: {
|
|
94
|
+
chainId?: number;
|
|
95
|
+
signer?: unknown;
|
|
96
|
+
creds?: ApiCredentials;
|
|
97
|
+
}
|
|
98
|
+
);
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
#### Methods
|
|
102
|
+
|
|
103
|
+
##### `getMarket(conditionId: string): Promise<ClobMarket>`
|
|
104
|
+
|
|
105
|
+
Get market information by condition ID.
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
const market = await client.getMarket('0x82ace55...');
|
|
109
|
+
console.log(market.question); // "Will BTC reach $100k?"
|
|
110
|
+
console.log(market.tokens[0].tokenId); // YES token ID
|
|
111
|
+
console.log(market.tokens[1].tokenId); // NO token ID
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**Parameters:**
|
|
115
|
+
- `conditionId` - The unique condition identifier for the market
|
|
116
|
+
|
|
117
|
+
**Returns:** `ClobMarket` object with market details and tokens
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
##### `getOrderbook(tokenId: string): Promise<Orderbook>`
|
|
122
|
+
|
|
123
|
+
Get raw orderbook for a specific token.
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
const orderbook = await client.getOrderbook('21742633...');
|
|
127
|
+
|
|
128
|
+
console.log('Best bid:', orderbook.bids[0]?.price); // e.g., 0.55
|
|
129
|
+
console.log('Best ask:', orderbook.asks[0]?.price); // e.g., 0.57
|
|
130
|
+
console.log('Spread:', orderbook.asks[0]?.price - orderbook.bids[0]?.price);
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**Parameters:**
|
|
134
|
+
- `tokenId` - The ERC-1155 token ID (YES or NO token)
|
|
135
|
+
|
|
136
|
+
**Returns:** `Orderbook` with sorted bids and asks
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
##### `getProcessedOrderbook(conditionId: string): Promise<ProcessedOrderbook>`
|
|
141
|
+
|
|
142
|
+
Get processed orderbook with complete market analysis and arbitrage calculations.
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
const processed = await client.getProcessedOrderbook('0x82ace55...');
|
|
146
|
+
|
|
147
|
+
// Check for arbitrage
|
|
148
|
+
if (processed.summary.longArbProfit > 0.003) {
|
|
149
|
+
console.log('Long arb opportunity!');
|
|
150
|
+
console.log('Buy YES @', processed.summary.effectivePrices.effectiveBuyYes);
|
|
151
|
+
console.log('Buy NO @', processed.summary.effectivePrices.effectiveBuyNo);
|
|
152
|
+
console.log('Profit:', processed.summary.longArbProfit * 100, '%');
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**Parameters:**
|
|
157
|
+
- `conditionId` - The unique condition identifier for the market
|
|
158
|
+
|
|
159
|
+
**Returns:** `ProcessedOrderbook` with both YES/NO books and analytics
|
|
160
|
+
|
|
161
|
+
**Important Notes:**
|
|
162
|
+
|
|
163
|
+
Polymarket orderbooks have a mirroring property:
|
|
164
|
+
- Buying YES @ P = Selling NO @ (1-P)
|
|
165
|
+
- The same order appears in both books
|
|
166
|
+
|
|
167
|
+
Correct arbitrage calculation uses "effective prices":
|
|
168
|
+
- `effectiveBuyYes = min(YES.ask, 1 - NO.bid)`
|
|
169
|
+
- `effectiveBuyNo = min(NO.ask, 1 - YES.bid)`
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
### GammaApiClient
|
|
174
|
+
|
|
175
|
+
Market discovery and metadata API client.
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
import { GammaApiClient, RateLimiter, Cache } from '@prediction-router/poly-sdk';
|
|
179
|
+
|
|
180
|
+
const client = new GammaApiClient(rateLimiter: RateLimiter, cache: Cache);
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
#### Methods
|
|
184
|
+
|
|
185
|
+
##### `getMarkets(params?: MarketSearchParams): Promise<GammaMarket[]>`
|
|
186
|
+
|
|
187
|
+
Get markets with optional filters and sorting.
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
// Get active markets sorted by 24h volume
|
|
191
|
+
const markets = await client.getMarkets({
|
|
192
|
+
active: true,
|
|
193
|
+
closed: false,
|
|
194
|
+
order: 'volume24hr',
|
|
195
|
+
ascending: false,
|
|
196
|
+
limit: 50,
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
// Search by slug
|
|
200
|
+
const market = await client.getMarkets({
|
|
201
|
+
slug: 'will-btc-reach-100k',
|
|
202
|
+
limit: 1,
|
|
203
|
+
});
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**MarketSearchParams:**
|
|
207
|
+
|
|
208
|
+
| Parameter | Type | Description |
|
|
209
|
+
|-----------|------|-------------|
|
|
210
|
+
| `slug` | `string` | Filter by market slug |
|
|
211
|
+
| `conditionId` | `string` | Filter by condition ID |
|
|
212
|
+
| `active` | `boolean` | Filter by active status |
|
|
213
|
+
| `closed` | `boolean` | Filter by closed status |
|
|
214
|
+
| `limit` | `number` | Maximum results (default: 100) |
|
|
215
|
+
| `offset` | `number` | Pagination offset |
|
|
216
|
+
| `order` | `string` | Sort field: `volume24hr`, `liquidity`, `endDate` |
|
|
217
|
+
| `ascending` | `boolean` | Sort direction |
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
##### `getTrendingMarkets(limit?: number): Promise<GammaMarket[]>`
|
|
222
|
+
|
|
223
|
+
Get trending markets sorted by 24-hour volume.
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
const trending = await client.getTrendingMarkets(10);
|
|
227
|
+
|
|
228
|
+
for (const market of trending) {
|
|
229
|
+
console.log(`${market.question}`);
|
|
230
|
+
console.log(` 24h Volume: $${market.volume24hr?.toLocaleString()}`);
|
|
231
|
+
console.log(` YES Price: ${(market.outcomePrices[0] * 100).toFixed(1)}%`);
|
|
232
|
+
}
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
##### `getEvents(params?): Promise<GammaEvent[]>`
|
|
238
|
+
|
|
239
|
+
Get events (market groupings) with optional filters.
|
|
240
|
+
|
|
241
|
+
```typescript
|
|
242
|
+
const events = await client.getEvents({ active: true, limit: 20 });
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
### DataApiClient
|
|
248
|
+
|
|
249
|
+
User data, positions, and leaderboard API client.
|
|
250
|
+
|
|
251
|
+
```typescript
|
|
252
|
+
import { DataApiClient, RateLimiter, Cache } from '@prediction-router/poly-sdk';
|
|
253
|
+
|
|
254
|
+
const client = new DataApiClient(rateLimiter: RateLimiter, cache: Cache);
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
#### Methods
|
|
258
|
+
|
|
259
|
+
##### `getPositions(address: string): Promise<Position[]>`
|
|
260
|
+
|
|
261
|
+
Get positions for a wallet address.
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
const positions = await client.getPositions('0x1234...');
|
|
265
|
+
for (const pos of positions) {
|
|
266
|
+
console.log(`${pos.title}: ${pos.size} shares @ ${pos.avgPrice}`);
|
|
267
|
+
console.log(` PnL: $${pos.cashPnl?.toFixed(2)}`);
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
##### `getActivity(address: string, params?): Promise<Activity[]>`
|
|
274
|
+
|
|
275
|
+
Get trading activity for a wallet.
|
|
276
|
+
|
|
277
|
+
```typescript
|
|
278
|
+
const activity = await client.getActivity('0x1234...', { limit: 50 });
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
##### `getTrades(params?): Promise<Trade[]>`
|
|
284
|
+
|
|
285
|
+
Get recent trades, optionally filtered by market.
|
|
286
|
+
|
|
287
|
+
```typescript
|
|
288
|
+
const trades = await client.getTrades({ market: '0x82ace55...', limit: 100 });
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
---
|
|
292
|
+
|
|
293
|
+
##### `getLeaderboard(params?): Promise<LeaderboardPage>`
|
|
294
|
+
|
|
295
|
+
Get leaderboard rankings.
|
|
296
|
+
|
|
297
|
+
```typescript
|
|
298
|
+
const leaderboard = await client.getLeaderboard({ limit: 50, offset: 0 });
|
|
299
|
+
for (const entry of leaderboard.entries) {
|
|
300
|
+
console.log(`#${entry.rank} ${entry.address}: $${entry.pnl.toFixed(2)}`);
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
### TradingClient
|
|
307
|
+
|
|
308
|
+
Trading operations client (requires authentication).
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
import { TradingClient, RateLimiter } from '@prediction-router/poly-sdk';
|
|
312
|
+
|
|
313
|
+
const client = new TradingClient(rateLimiter: RateLimiter, {
|
|
314
|
+
privateKey: '0x...',
|
|
315
|
+
chainId: 137, // Polygon mainnet
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
await client.initialize();
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
#### Methods
|
|
322
|
+
|
|
323
|
+
##### `createOrder(params: OrderParams): Promise<OrderResult>`
|
|
324
|
+
|
|
325
|
+
Create and post a limit order.
|
|
326
|
+
|
|
327
|
+
```typescript
|
|
328
|
+
const result = await client.createOrder({
|
|
329
|
+
tokenId: '21742633...',
|
|
330
|
+
side: 'BUY',
|
|
331
|
+
price: 0.55,
|
|
332
|
+
size: 100,
|
|
333
|
+
orderType: 'GTC', // Good-til-cancelled
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
if (result.success) {
|
|
337
|
+
console.log('Order placed:', result.orderId);
|
|
338
|
+
}
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
**OrderParams:**
|
|
342
|
+
|
|
343
|
+
| Parameter | Type | Description |
|
|
344
|
+
|-----------|------|-------------|
|
|
345
|
+
| `tokenId` | `string` | Token ID to trade |
|
|
346
|
+
| `side` | `'BUY' \| 'SELL'` | Order side |
|
|
347
|
+
| `price` | `number` | Price (0.001 - 0.999) |
|
|
348
|
+
| `size` | `number` | Size in shares |
|
|
349
|
+
| `orderType` | `'GTC' \| 'GTD'` | Order type (default: GTC) |
|
|
350
|
+
| `expiration` | `number` | Expiration for GTD orders (unix seconds) |
|
|
351
|
+
|
|
352
|
+
---
|
|
353
|
+
|
|
354
|
+
##### `createMarketOrder(params: MarketOrderParams): Promise<OrderResult>`
|
|
355
|
+
|
|
356
|
+
Create and post a market order.
|
|
357
|
+
|
|
358
|
+
```typescript
|
|
359
|
+
const result = await client.createMarketOrder({
|
|
360
|
+
tokenId: '21742633...',
|
|
361
|
+
side: 'BUY',
|
|
362
|
+
amount: 50, // $50 USDC
|
|
363
|
+
orderType: 'FOK', // Fill-or-kill
|
|
364
|
+
});
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
---
|
|
368
|
+
|
|
369
|
+
##### `cancelOrder(orderId: string): Promise<OrderResult>`
|
|
370
|
+
|
|
371
|
+
Cancel an open order.
|
|
372
|
+
|
|
373
|
+
```typescript
|
|
374
|
+
await client.cancelOrder('0xabc123...');
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
---
|
|
378
|
+
|
|
379
|
+
##### `getOpenOrders(marketId?: string): Promise<Order[]>`
|
|
380
|
+
|
|
381
|
+
Get all open orders.
|
|
382
|
+
|
|
383
|
+
```typescript
|
|
384
|
+
const orders = await client.getOpenOrders();
|
|
385
|
+
console.log(`${orders.length} open orders`);
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
##### `getBalanceAllowance(assetType, tokenId?): Promise<{ balance, allowance }>`
|
|
391
|
+
|
|
392
|
+
Check balance and allowance.
|
|
393
|
+
|
|
394
|
+
```typescript
|
|
395
|
+
const { balance, allowance } = await client.getBalanceAllowance('COLLATERAL');
|
|
396
|
+
console.log(`USDC Balance: ${balance}`);
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
---
|
|
400
|
+
|
|
401
|
+
### BridgeClient
|
|
402
|
+
|
|
403
|
+
Cross-chain deposit client for funding your Polymarket account.
|
|
404
|
+
|
|
405
|
+
```typescript
|
|
406
|
+
import { BridgeClient } from '@prediction-router/poly-sdk';
|
|
407
|
+
|
|
408
|
+
const bridge = new BridgeClient();
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
#### Key Concept: Universal Deposit Addresses
|
|
412
|
+
|
|
413
|
+
The Polymarket Bridge API returns **universal deposit addresses** by chain type:
|
|
414
|
+
|
|
415
|
+
- **EVM Address**: A single address works for ALL EVM chains (Ethereum, Polygon, Arbitrum, Base, Optimism)
|
|
416
|
+
- **Solana Address**: For Solana deposits
|
|
417
|
+
- **Bitcoin Address**: For Bitcoin deposits
|
|
418
|
+
|
|
419
|
+
This means you don't need a different address for each chain - the same EVM address accepts deposits from Ethereum, Polygon, Arbitrum, Base, and Optimism.
|
|
420
|
+
|
|
421
|
+
#### Supported Chains
|
|
422
|
+
|
|
423
|
+
| Chain | Chain ID | Min Deposit | Address Type |
|
|
424
|
+
|-------|----------|-------------|--------------|
|
|
425
|
+
| Ethereum | 1 | $10 | EVM |
|
|
426
|
+
| Polygon | 137 | $2 | EVM |
|
|
427
|
+
| Arbitrum | 42161 | $2 | EVM |
|
|
428
|
+
| Optimism | 10 | $2 | EVM |
|
|
429
|
+
| Base | 8453 | $2 | EVM |
|
|
430
|
+
| Solana | - | $5-10 | SVM |
|
|
431
|
+
| Bitcoin | - | $10+ | BTC |
|
|
432
|
+
|
|
433
|
+
#### Supported Tokens (Polygon)
|
|
434
|
+
|
|
435
|
+
| Token | Address | Description |
|
|
436
|
+
|-------|---------|-------------|
|
|
437
|
+
| Native USDC | `0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359` | Circle's native USDC |
|
|
438
|
+
| USDC.e | `0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174` | Bridged USDC (PoS) |
|
|
439
|
+
| USDT | `0xc2132D05D31c914a87C6611C10748AEb04B58e8F` | Tether USD |
|
|
440
|
+
| DAI | `0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063` | Dai Stablecoin |
|
|
441
|
+
| WETH | `0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619` | Wrapped Ether |
|
|
442
|
+
| POL | Native | Polygon native token |
|
|
443
|
+
|
|
444
|
+
#### Methods
|
|
445
|
+
|
|
446
|
+
##### `getSupportedAssets(): Promise<BridgeSupportedAsset[]>`
|
|
447
|
+
|
|
448
|
+
Get all supported chains and tokens.
|
|
449
|
+
|
|
450
|
+
```typescript
|
|
451
|
+
const assets = await bridge.getSupportedAssets();
|
|
452
|
+
|
|
453
|
+
// Filter for Polygon assets
|
|
454
|
+
const polygonAssets = assets.filter(a => a.chainId === 137);
|
|
455
|
+
for (const asset of polygonAssets) {
|
|
456
|
+
console.log(`${asset.tokenSymbol}: min $${asset.minDepositUsd}`);
|
|
457
|
+
}
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
---
|
|
461
|
+
|
|
462
|
+
##### `createDepositAddresses(walletAddress: string): Promise<CreateDepositResponse>`
|
|
463
|
+
|
|
464
|
+
Get universal deposit addresses for your wallet.
|
|
465
|
+
|
|
466
|
+
**API Response Format:**
|
|
467
|
+
```json
|
|
468
|
+
{
|
|
469
|
+
"address": {
|
|
470
|
+
"evm": "0x1234...", // Works for ALL EVM chains
|
|
471
|
+
"svm": "ABC123...", // Solana address
|
|
472
|
+
"btc": "bc1q..." // Bitcoin address
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
```typescript
|
|
478
|
+
const result = await bridge.createDepositAddresses('0xYourWallet');
|
|
479
|
+
|
|
480
|
+
console.log('EVM deposit address:', result.address.evm); // All EVM chains
|
|
481
|
+
console.log('Solana deposit address:', result.address.svm); // Solana
|
|
482
|
+
console.log('Bitcoin deposit address:', result.address.btc); // Bitcoin
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
---
|
|
486
|
+
|
|
487
|
+
##### `getEvmDepositAddress(walletAddress: string): Promise<string>`
|
|
488
|
+
|
|
489
|
+
Get the universal EVM deposit address. **Recommended method.**
|
|
490
|
+
|
|
491
|
+
```typescript
|
|
492
|
+
const evmAddr = await bridge.getEvmDepositAddress('0xYourWallet');
|
|
493
|
+
|
|
494
|
+
// This address works for:
|
|
495
|
+
// - Ethereum USDC, ETH
|
|
496
|
+
// - Polygon Native USDC, USDC.e, MATIC
|
|
497
|
+
// - Arbitrum USDC, ETH
|
|
498
|
+
// - Base USDC, ETH
|
|
499
|
+
// - Optimism USDC, ETH
|
|
500
|
+
console.log(`Send to: ${evmAddr}`);
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
---
|
|
504
|
+
|
|
505
|
+
##### `getSolanaDepositAddress(walletAddress: string): Promise<string>`
|
|
506
|
+
|
|
507
|
+
Get the Solana deposit address.
|
|
508
|
+
|
|
509
|
+
```typescript
|
|
510
|
+
const solAddr = await bridge.getSolanaDepositAddress('0xYourWallet');
|
|
511
|
+
console.log(`Send SOL or USDC to: ${solAddr}`);
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
---
|
|
515
|
+
|
|
516
|
+
##### `getBtcDepositAddress(walletAddress: string): Promise<string>`
|
|
517
|
+
|
|
518
|
+
Get the Bitcoin deposit address.
|
|
519
|
+
|
|
520
|
+
```typescript
|
|
521
|
+
const btcAddr = await bridge.getBtcDepositAddress('0xYourWallet');
|
|
522
|
+
console.log(`Send BTC to: ${btcAddr}`);
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
---
|
|
526
|
+
|
|
527
|
+
##### `getDepositAddress(address, chainId, tokenSymbol): Promise<DepositAddress | null>` _(deprecated)_
|
|
528
|
+
|
|
529
|
+
> **Deprecated**: Use `getEvmDepositAddress()`, `getSolanaDepositAddress()`, or `getBtcDepositAddress()` instead.
|
|
530
|
+
|
|
531
|
+
---
|
|
532
|
+
|
|
533
|
+
##### `isSupported(chainId, tokenSymbol): Promise<boolean>`
|
|
534
|
+
|
|
535
|
+
Check if a chain/token combination is supported.
|
|
536
|
+
|
|
537
|
+
```typescript
|
|
538
|
+
const supported = await bridge.isSupported(137, 'USDC');
|
|
539
|
+
console.log(`Polygon USDC supported: ${supported}`);
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
---
|
|
543
|
+
|
|
544
|
+
##### `getMinDeposit(chainId, tokenSymbol): Promise<{ amount, usd } | null>`
|
|
545
|
+
|
|
546
|
+
Get minimum deposit amount.
|
|
547
|
+
|
|
548
|
+
```typescript
|
|
549
|
+
const min = await bridge.getMinDeposit(137, 'USDC');
|
|
550
|
+
if (min) {
|
|
551
|
+
console.log(`Min deposit: ${min.amount} (~$${min.usd})`);
|
|
552
|
+
}
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
---
|
|
556
|
+
|
|
557
|
+
#### Deposit Flow Example
|
|
558
|
+
|
|
559
|
+
```typescript
|
|
560
|
+
import { providers, Wallet, Contract, utils } from 'ethers';
|
|
561
|
+
import { BridgeClient, BRIDGE_TOKENS } from '@prediction-router/poly-sdk';
|
|
562
|
+
|
|
563
|
+
// 1. Setup
|
|
564
|
+
const provider = new providers.JsonRpcProvider('https://polygon-rpc.com');
|
|
565
|
+
const wallet = new Wallet(PRIVATE_KEY, provider);
|
|
566
|
+
const bridge = new BridgeClient();
|
|
567
|
+
|
|
568
|
+
// 2. Get EVM deposit address (works for all EVM chains)
|
|
569
|
+
const depositAddress = await bridge.getEvmDepositAddress(wallet.address);
|
|
570
|
+
console.log(`Deposit to: ${depositAddress}`);
|
|
571
|
+
|
|
572
|
+
// 3. Send Native USDC to the deposit address
|
|
573
|
+
const nativeUsdc = new Contract(
|
|
574
|
+
BRIDGE_TOKENS.POLYGON_NATIVE_USDC,
|
|
575
|
+
['function transfer(address to, uint256 amount) returns (bool)'],
|
|
576
|
+
wallet
|
|
577
|
+
);
|
|
578
|
+
|
|
579
|
+
const amount = utils.parseUnits('5.0', 6); // 5 USDC
|
|
580
|
+
const tx = await nativeUsdc.transfer(depositAddress, amount);
|
|
581
|
+
await tx.wait();
|
|
582
|
+
|
|
583
|
+
console.log('Deposit sent! Bridge will convert to USDC.e in 1-5 minutes.');
|
|
584
|
+
console.log('Bridge fee: ~0.16%');
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
---
|
|
588
|
+
|
|
589
|
+
### CTFClient
|
|
590
|
+
|
|
591
|
+
CTF (Conditional Token Framework) client for on-chain token operations.
|
|
592
|
+
|
|
593
|
+
```typescript
|
|
594
|
+
import { CTFClient } from '@prediction-router/poly-sdk';
|
|
595
|
+
|
|
596
|
+
const ctf = new CTFClient({
|
|
597
|
+
privateKey: '0x...',
|
|
598
|
+
rpcUrl: 'https://polygon-rpc.com',
|
|
599
|
+
chainId: 137,
|
|
600
|
+
});
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
#### Core Concepts
|
|
604
|
+
|
|
605
|
+
**Token IDs**: Each market has two token IDs (YES and NO). There are two ways to identify tokens:
|
|
606
|
+
1. **CLOB Token IDs**: From the CLOB API, used for trading
|
|
607
|
+
2. **Calculated Position IDs**: From `calculatePositionId()`, derived from conditionId
|
|
608
|
+
|
|
609
|
+
**Important**: Always use CLOB Token IDs for balance queries. The calculated position IDs may differ.
|
|
610
|
+
|
|
611
|
+
#### Constants
|
|
612
|
+
|
|
613
|
+
```typescript
|
|
614
|
+
import {
|
|
615
|
+
CTF_CONTRACT, // 0x4D97DCd97eC945f40cF65F87097ACe5EA0476045
|
|
616
|
+
USDC_CONTRACT, // 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174 (USDC.e)
|
|
617
|
+
NEG_RISK_CTF_EXCHANGE, // 0xC5d563A36AE78145C45a50134d48A1215220f80a
|
|
618
|
+
NEG_RISK_ADAPTER, // 0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296
|
|
619
|
+
USDC_DECIMALS, // 6
|
|
620
|
+
} from '@prediction-router/poly-sdk';
|
|
621
|
+
```
|
|
622
|
+
|
|
623
|
+
#### Methods
|
|
624
|
+
|
|
625
|
+
##### `split(conditionId: string, amount: number): Promise<SplitResult>`
|
|
626
|
+
|
|
627
|
+
Split USDC.e into YES + NO tokens.
|
|
628
|
+
|
|
629
|
+
```typescript
|
|
630
|
+
// Split 10 USDC.e into 10 YES + 10 NO
|
|
631
|
+
const result = await ctf.split('0xabc123...', 10);
|
|
632
|
+
|
|
633
|
+
console.log(`TX: ${result.txHash}`);
|
|
634
|
+
console.log(`Status: ${result.status}`);
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
---
|
|
638
|
+
|
|
639
|
+
##### `merge(conditionId: string, amount: number): Promise<MergeResult>`
|
|
640
|
+
|
|
641
|
+
Merge YES + NO tokens back into USDC.e.
|
|
642
|
+
|
|
643
|
+
```typescript
|
|
644
|
+
// Merge 10 YES + 10 NO into 10 USDC.e
|
|
645
|
+
const result = await ctf.merge('0xabc123...', 10);
|
|
646
|
+
|
|
647
|
+
console.log(`TX: ${result.txHash}`);
|
|
648
|
+
console.log(`USDC received: ${result.usdcReceived}`);
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
---
|
|
652
|
+
|
|
653
|
+
##### `getPositionBalanceByTokenIds(conditionId: string, tokenIds: TokenIds): Promise<PositionBalance>`
|
|
654
|
+
|
|
655
|
+
Get token balances using CLOB token IDs. **Recommended method.**
|
|
656
|
+
|
|
657
|
+
```typescript
|
|
658
|
+
import type { TokenIds } from '@prediction-router/poly-sdk';
|
|
659
|
+
|
|
660
|
+
// Get token IDs from CLOB API
|
|
661
|
+
const market = await clobApi.getMarket('0xabc123...');
|
|
662
|
+
const yesToken = market.tokens.find(t => t.outcome === 'Yes');
|
|
663
|
+
const noToken = market.tokens.find(t => t.outcome === 'No');
|
|
664
|
+
|
|
665
|
+
const tokenIds: TokenIds = {
|
|
666
|
+
yesTokenId: yesToken.tokenId,
|
|
667
|
+
noTokenId: noToken.tokenId,
|
|
668
|
+
};
|
|
669
|
+
|
|
670
|
+
const balance = await ctf.getPositionBalanceByTokenIds('0xabc123...', tokenIds);
|
|
671
|
+
console.log(`YES: ${balance.yesBalance}, NO: ${balance.noBalance}`);
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
---
|
|
675
|
+
|
|
676
|
+
##### `canMergeWithTokenIds(conditionId: string, tokenIds: TokenIds, amount: number): Promise<boolean>`
|
|
677
|
+
|
|
678
|
+
Check if merge is possible with given token balances.
|
|
679
|
+
|
|
680
|
+
```typescript
|
|
681
|
+
const canMerge = await ctf.canMergeWithTokenIds('0xabc123...', tokenIds, 5);
|
|
682
|
+
if (canMerge) {
|
|
683
|
+
await ctf.merge('0xabc123...', 5);
|
|
684
|
+
}
|
|
685
|
+
```
|
|
686
|
+
|
|
687
|
+
---
|
|
688
|
+
|
|
689
|
+
##### `getPositionBalance(conditionId: string): Promise<PositionBalance>` _(deprecated)_
|
|
690
|
+
|
|
691
|
+
> **Deprecated**: Use `getPositionBalanceByTokenIds()` instead. This method uses calculated position IDs which may not match CLOB token IDs.
|
|
692
|
+
|
|
693
|
+
---
|
|
694
|
+
|
|
695
|
+
##### `redeem(conditionId: string, outcome?: 'YES' | 'NO'): Promise<RedeemResult>`
|
|
696
|
+
|
|
697
|
+
Redeem winning tokens after market resolution. **For standard CTF markets only.**
|
|
698
|
+
|
|
699
|
+
⚠️ **WARNING**: This method uses calculated position IDs. For Polymarket CLOB markets, use `redeemByTokenIds()` instead.
|
|
700
|
+
|
|
701
|
+
```typescript
|
|
702
|
+
// ❌ Don't use for Polymarket - may fail to find balance
|
|
703
|
+
const result = await ctf.redeem(conditionId);
|
|
704
|
+
```
|
|
705
|
+
|
|
706
|
+
**When to use `redeem()`:**
|
|
707
|
+
- Standard Gnosis CTF markets (non-Polymarket)
|
|
708
|
+
- Markets where position IDs are calculated from conditionId
|
|
709
|
+
- Direct CTF contract interactions without CLOB
|
|
710
|
+
|
|
711
|
+
---
|
|
712
|
+
|
|
713
|
+
##### `redeemByTokenIds(conditionId: string, tokenIds: TokenIds, outcome?: 'YES' | 'NO'): Promise<RedeemResult>`
|
|
714
|
+
|
|
715
|
+
Redeem winning tokens using Polymarket token IDs. **Recommended for Polymarket.**
|
|
716
|
+
|
|
717
|
+
```typescript
|
|
718
|
+
// ✅ Use this for Polymarket CLOB markets
|
|
719
|
+
const tokenIds: TokenIds = {
|
|
720
|
+
yesTokenId: '25064375110792967023484002819116042931016336431092144471807003884255851454283',
|
|
721
|
+
noTokenId: '98190367690492181203391990709979106077460946443309150166954079213761598385827',
|
|
722
|
+
};
|
|
723
|
+
|
|
724
|
+
const result = await ctf.redeemByTokenIds(conditionId, tokenIds);
|
|
725
|
+
console.log(`Redeemed ${result.tokensRedeemed} ${result.outcome} tokens`);
|
|
726
|
+
console.log(`Received ${result.usdcReceived} USDC`);
|
|
727
|
+
```
|
|
728
|
+
|
|
729
|
+
**Parameters:**
|
|
730
|
+
- `conditionId` - The market condition ID
|
|
731
|
+
- `tokenIds` - Polymarket token IDs from CLOB API
|
|
732
|
+
- `outcome` - Optional: 'YES' or 'NO'. Auto-detects winning outcome if not provided.
|
|
733
|
+
|
|
734
|
+
**Returns:** `RedeemResult` with transaction details
|
|
735
|
+
|
|
736
|
+
**Why use this method?**
|
|
737
|
+
- Polymarket wraps CTF positions into ERC-1155 tokens with custom IDs
|
|
738
|
+
- The token IDs from CLOB API differ from calculated position IDs
|
|
739
|
+
- This method queries balances using the correct Polymarket token IDs
|
|
740
|
+
|
|
741
|
+
---
|
|
742
|
+
|
|
743
|
+
##### `getMarketResolution(conditionId: string): Promise<MarketResolution>`
|
|
744
|
+
|
|
745
|
+
Check if a market is resolved and get the winning outcome.
|
|
746
|
+
|
|
747
|
+
```typescript
|
|
748
|
+
const resolution = await ctf.getMarketResolution(conditionId);
|
|
749
|
+
if (resolution.isResolved) {
|
|
750
|
+
console.log(`Winner: ${resolution.winningOutcome}`); // 'YES' or 'NO'
|
|
751
|
+
}
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
---
|
|
755
|
+
|
|
756
|
+
##### `getUsdcBalance(): Promise<string>`
|
|
757
|
+
|
|
758
|
+
Get USDC.e balance.
|
|
759
|
+
|
|
760
|
+
```typescript
|
|
761
|
+
const balance = await ctf.getUsdcBalance();
|
|
762
|
+
console.log(`USDC.e: ${balance}`);
|
|
763
|
+
```
|
|
764
|
+
|
|
765
|
+
---
|
|
766
|
+
|
|
767
|
+
#### Types
|
|
768
|
+
|
|
769
|
+
```typescript
|
|
770
|
+
interface TokenIds {
|
|
771
|
+
yesTokenId: string;
|
|
772
|
+
noTokenId: string;
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
interface PositionBalance {
|
|
776
|
+
conditionId: string;
|
|
777
|
+
yesBalance: string;
|
|
778
|
+
noBalance: string;
|
|
779
|
+
yesPositionId: string;
|
|
780
|
+
noPositionId: string;
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
interface SplitResult {
|
|
784
|
+
txHash: string;
|
|
785
|
+
status: 'success' | 'failed';
|
|
786
|
+
gasUsed: string;
|
|
787
|
+
yesTokenId: string;
|
|
788
|
+
noTokenId: string;
|
|
789
|
+
amountSplit: string;
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
interface MergeResult {
|
|
793
|
+
txHash: string;
|
|
794
|
+
status: 'success' | 'failed';
|
|
795
|
+
gasUsed: string;
|
|
796
|
+
usdcReceived: string;
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
interface RedeemResult {
|
|
800
|
+
success: boolean;
|
|
801
|
+
txHash: string;
|
|
802
|
+
outcome: 'YES' | 'NO';
|
|
803
|
+
tokensRedeemed: string;
|
|
804
|
+
usdcReceived: string;
|
|
805
|
+
gasUsed: string;
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
interface MarketResolution {
|
|
809
|
+
conditionId: string;
|
|
810
|
+
isResolved: boolean;
|
|
811
|
+
winningOutcome?: 'YES' | 'NO';
|
|
812
|
+
payoutNumerators?: number[];
|
|
813
|
+
}
|
|
814
|
+
```
|
|
815
|
+
|
|
816
|
+
---
|
|
817
|
+
|
|
818
|
+
#### CTF Arbitrage Example
|
|
819
|
+
|
|
820
|
+
```typescript
|
|
821
|
+
import { CTFClient, ClobApiClient, TokenIds } from '@prediction-router/poly-sdk';
|
|
822
|
+
|
|
823
|
+
const ctf = new CTFClient({ privateKey, rpcUrl, chainId: 137 });
|
|
824
|
+
const clobApi = new ClobApiClient(rateLimiter, cache);
|
|
825
|
+
|
|
826
|
+
// 1. Get market and token IDs
|
|
827
|
+
const market = await clobApi.getMarket(conditionId);
|
|
828
|
+
const tokenIds: TokenIds = {
|
|
829
|
+
yesTokenId: market.tokens.find(t => t.outcome === 'Yes').tokenId,
|
|
830
|
+
noTokenId: market.tokens.find(t => t.outcome === 'No').tokenId,
|
|
831
|
+
};
|
|
832
|
+
|
|
833
|
+
// 2. Get processed orderbook
|
|
834
|
+
const ob = await clobApi.getProcessedOrderbook(conditionId);
|
|
835
|
+
|
|
836
|
+
// 3. Check for long arbitrage (buy YES + NO, merge for profit)
|
|
837
|
+
if (ob.summary.longArbProfit > 0.005) {
|
|
838
|
+
// Buy YES and NO tokens via CLOB
|
|
839
|
+
// Then merge
|
|
840
|
+
const balance = await ctf.getPositionBalanceByTokenIds(conditionId, tokenIds);
|
|
841
|
+
const minBalance = Math.min(
|
|
842
|
+
parseFloat(balance.yesBalance),
|
|
843
|
+
parseFloat(balance.noBalance)
|
|
844
|
+
);
|
|
845
|
+
|
|
846
|
+
if (minBalance > 0) {
|
|
847
|
+
const result = await ctf.merge(conditionId, minBalance);
|
|
848
|
+
console.log(`Merged ${minBalance}, received ${result.usdcReceived} USDC`);
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
// 4. Check for short arbitrage (split, sell YES + NO for profit)
|
|
853
|
+
if (ob.summary.shortArbProfit > 0.005) {
|
|
854
|
+
// Split USDC into tokens
|
|
855
|
+
await ctf.split(conditionId, 10);
|
|
856
|
+
// Sell tokens via CLOB
|
|
857
|
+
}
|
|
858
|
+
```
|
|
859
|
+
|
|
860
|
+
---
|
|
861
|
+
|
|
862
|
+
### WebSocketManager
|
|
863
|
+
|
|
864
|
+
Real-time market data via WebSocket.
|
|
865
|
+
|
|
866
|
+
```typescript
|
|
867
|
+
import { WebSocketManager } from '@prediction-router/poly-sdk';
|
|
868
|
+
|
|
869
|
+
const ws = new WebSocketManager({ enableLogging: true });
|
|
870
|
+
```
|
|
871
|
+
|
|
872
|
+
#### Methods
|
|
873
|
+
|
|
874
|
+
##### `subscribe(assetIds: string[]): Promise<void>`
|
|
875
|
+
|
|
876
|
+
Subscribe to market updates.
|
|
877
|
+
|
|
878
|
+
```typescript
|
|
879
|
+
ws.on('bookUpdate', (update) => {
|
|
880
|
+
console.log(`Book update for ${update.assetId}`);
|
|
881
|
+
console.log(` Best bid: ${update.bids[0]?.price}`);
|
|
882
|
+
});
|
|
883
|
+
|
|
884
|
+
ws.on('priceUpdate', (update) => {
|
|
885
|
+
console.log(`Price: ${update.price}`);
|
|
886
|
+
});
|
|
887
|
+
|
|
888
|
+
await ws.subscribe(['21742633...', '79707176...']);
|
|
889
|
+
```
|
|
890
|
+
|
|
891
|
+
---
|
|
892
|
+
|
|
893
|
+
##### `unsubscribe(assetIds: string[]): Promise<void>`
|
|
894
|
+
|
|
895
|
+
Unsubscribe from specific assets.
|
|
896
|
+
|
|
897
|
+
---
|
|
898
|
+
|
|
899
|
+
##### `unsubscribeAll(): Promise<void>`
|
|
900
|
+
|
|
901
|
+
Unsubscribe from all assets and cleanup.
|
|
902
|
+
|
|
903
|
+
---
|
|
904
|
+
|
|
905
|
+
## Services
|
|
906
|
+
|
|
907
|
+
### MarketService
|
|
908
|
+
|
|
909
|
+
High-level market analysis service.
|
|
910
|
+
|
|
911
|
+
```typescript
|
|
912
|
+
import { MarketService } from '@prediction-router/poly-sdk';
|
|
913
|
+
|
|
914
|
+
const service = new MarketService(clobApi, gammaApi);
|
|
915
|
+
|
|
916
|
+
// Get market with full analysis
|
|
917
|
+
const analysis = await service.getMarketWithAnalysis('0x82ace55...');
|
|
918
|
+
```
|
|
919
|
+
|
|
920
|
+
---
|
|
921
|
+
|
|
922
|
+
### ArbitrageService
|
|
923
|
+
|
|
924
|
+
Arbitrage opportunity detection.
|
|
925
|
+
|
|
926
|
+
```typescript
|
|
927
|
+
import { ArbitrageService } from '@prediction-router/poly-sdk';
|
|
928
|
+
|
|
929
|
+
const service = new ArbitrageService(clobApi, gammaApi);
|
|
930
|
+
|
|
931
|
+
// Scan for opportunities
|
|
932
|
+
const opportunities = await service.scanForOpportunities({
|
|
933
|
+
minProfit: 0.003, // 0.3% minimum
|
|
934
|
+
maxMarkets: 50,
|
|
935
|
+
});
|
|
936
|
+
|
|
937
|
+
for (const opp of opportunities) {
|
|
938
|
+
console.log(`${opp.type} arb: ${(opp.profit * 100).toFixed(2)}%`);
|
|
939
|
+
}
|
|
940
|
+
```
|
|
941
|
+
|
|
942
|
+
---
|
|
943
|
+
|
|
944
|
+
### RealtimeService
|
|
945
|
+
|
|
946
|
+
High-level WebSocket subscription management.
|
|
947
|
+
|
|
948
|
+
```typescript
|
|
949
|
+
import { RealtimeService, WebSocketManager } from '@prediction-router/poly-sdk';
|
|
950
|
+
|
|
951
|
+
const ws = new WebSocketManager();
|
|
952
|
+
const realtime = new RealtimeService(ws);
|
|
953
|
+
|
|
954
|
+
// Subscribe to a market pair
|
|
955
|
+
const sub = await realtime.subscribeMarket(yesTokenId, noTokenId, {
|
|
956
|
+
onPairUpdate: (update) => {
|
|
957
|
+
console.log(`YES: ${update.yes.price}, NO: ${update.no.price}`);
|
|
958
|
+
console.log(`Spread: ${update.spread}`);
|
|
959
|
+
},
|
|
960
|
+
});
|
|
961
|
+
|
|
962
|
+
// Later: unsubscribe
|
|
963
|
+
await sub.unsubscribe();
|
|
964
|
+
```
|
|
965
|
+
|
|
966
|
+
---
|
|
967
|
+
|
|
968
|
+
## Utility Functions
|
|
969
|
+
|
|
970
|
+
### `getEffectivePrices(yesAsk, yesBid, noAsk, noBid)`
|
|
971
|
+
|
|
972
|
+
Calculate effective prices accounting for orderbook mirroring.
|
|
973
|
+
|
|
974
|
+
```typescript
|
|
975
|
+
import { getEffectivePrices } from '@prediction-router/poly-sdk';
|
|
976
|
+
|
|
977
|
+
const effective = getEffectivePrices(0.57, 0.55, 0.45, 0.43);
|
|
978
|
+
console.log('Effective buy YES:', effective.effectiveBuyYes);
|
|
979
|
+
console.log('Effective buy NO:', effective.effectiveBuyNo);
|
|
980
|
+
```
|
|
981
|
+
|
|
982
|
+
---
|
|
983
|
+
|
|
984
|
+
### `checkArbitrage(yesAsk, yesBid, noAsk, noBid)`
|
|
985
|
+
|
|
986
|
+
Check for arbitrage opportunities.
|
|
987
|
+
|
|
988
|
+
```typescript
|
|
989
|
+
import { checkArbitrage } from '@prediction-router/poly-sdk';
|
|
990
|
+
|
|
991
|
+
const arb = checkArbitrage(0.57, 0.55, 0.45, 0.43);
|
|
992
|
+
if (arb.hasOpportunity) {
|
|
993
|
+
console.log(`${arb.type} opportunity: ${arb.profit * 100}%`);
|
|
994
|
+
}
|
|
995
|
+
```
|
|
996
|
+
|
|
997
|
+
---
|
|
998
|
+
|
|
999
|
+
## Types
|
|
1000
|
+
|
|
1001
|
+
### ClobMarket
|
|
1002
|
+
|
|
1003
|
+
```typescript
|
|
1004
|
+
interface ClobMarket {
|
|
1005
|
+
conditionId: string; // Unique market identifier
|
|
1006
|
+
question: string; // Market question
|
|
1007
|
+
description?: string; // Resolution criteria
|
|
1008
|
+
marketSlug: string; // URL-friendly slug
|
|
1009
|
+
tokens: ClobToken[]; // YES and NO tokens
|
|
1010
|
+
acceptingOrders: boolean; // Can accept orders
|
|
1011
|
+
endDateIso: string; // ISO end date
|
|
1012
|
+
active: boolean; // Is active
|
|
1013
|
+
closed: boolean; // Is resolved
|
|
1014
|
+
}
|
|
1015
|
+
```
|
|
1016
|
+
|
|
1017
|
+
### ClobToken
|
|
1018
|
+
|
|
1019
|
+
```typescript
|
|
1020
|
+
interface ClobToken {
|
|
1021
|
+
tokenId: string; // ERC-1155 token ID
|
|
1022
|
+
outcome: string; // "Yes" or "No"
|
|
1023
|
+
price: number; // Current price (0-1)
|
|
1024
|
+
}
|
|
1025
|
+
```
|
|
1026
|
+
|
|
1027
|
+
### Orderbook
|
|
1028
|
+
|
|
1029
|
+
```typescript
|
|
1030
|
+
interface Orderbook {
|
|
1031
|
+
bids: OrderbookLevel[]; // Sorted descending by price
|
|
1032
|
+
asks: OrderbookLevel[]; // Sorted ascending by price
|
|
1033
|
+
timestamp: number; // Fetch timestamp (ms)
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
interface OrderbookLevel {
|
|
1037
|
+
price: number; // Price (0.001-0.999)
|
|
1038
|
+
size: number; // Size in shares
|
|
1039
|
+
}
|
|
1040
|
+
```
|
|
1041
|
+
|
|
1042
|
+
### ProcessedOrderbook
|
|
1043
|
+
|
|
1044
|
+
```typescript
|
|
1045
|
+
interface ProcessedOrderbook {
|
|
1046
|
+
yes: {
|
|
1047
|
+
bid: number;
|
|
1048
|
+
ask: number;
|
|
1049
|
+
bidSize: number;
|
|
1050
|
+
askSize: number;
|
|
1051
|
+
bidDepth: number;
|
|
1052
|
+
askDepth: number;
|
|
1053
|
+
spread: number;
|
|
1054
|
+
};
|
|
1055
|
+
no: {
|
|
1056
|
+
bid: number;
|
|
1057
|
+
ask: number;
|
|
1058
|
+
bidSize: number;
|
|
1059
|
+
askSize: number;
|
|
1060
|
+
bidDepth: number;
|
|
1061
|
+
askDepth: number;
|
|
1062
|
+
spread: number;
|
|
1063
|
+
};
|
|
1064
|
+
summary: {
|
|
1065
|
+
askSum: number;
|
|
1066
|
+
bidSum: number;
|
|
1067
|
+
effectivePrices: {
|
|
1068
|
+
effectiveBuyYes: number;
|
|
1069
|
+
effectiveBuyNo: number;
|
|
1070
|
+
effectiveSellYes: number;
|
|
1071
|
+
effectiveSellNo: number;
|
|
1072
|
+
};
|
|
1073
|
+
effectiveLongCost: number;
|
|
1074
|
+
effectiveShortRevenue: number;
|
|
1075
|
+
longArbProfit: number; // > 0 = opportunity
|
|
1076
|
+
shortArbProfit: number; // > 0 = opportunity
|
|
1077
|
+
totalBidDepth: number;
|
|
1078
|
+
totalAskDepth: number;
|
|
1079
|
+
imbalanceRatio: number;
|
|
1080
|
+
yesSpread: number;
|
|
1081
|
+
};
|
|
1082
|
+
}
|
|
1083
|
+
```
|
|
1084
|
+
|
|
1085
|
+
### Position
|
|
1086
|
+
|
|
1087
|
+
```typescript
|
|
1088
|
+
interface Position {
|
|
1089
|
+
asset: string; // Token ID
|
|
1090
|
+
conditionId: string; // Market ID
|
|
1091
|
+
outcome: string; // "Yes" or "No"
|
|
1092
|
+
outcomeIndex: number; // 0 = Yes, 1 = No
|
|
1093
|
+
size: number; // Shares held
|
|
1094
|
+
avgPrice: number; // Average entry price
|
|
1095
|
+
curPrice?: number; // Current price
|
|
1096
|
+
cashPnl?: number; // Unrealized PnL in USDC
|
|
1097
|
+
percentPnl?: number; // Unrealized PnL %
|
|
1098
|
+
realizedPnl?: number; // Realized PnL
|
|
1099
|
+
title: string; // Market title
|
|
1100
|
+
}
|
|
1101
|
+
```
|
|
1102
|
+
|
|
1103
|
+
---
|
|
1104
|
+
|
|
1105
|
+
## Error Handling
|
|
1106
|
+
|
|
1107
|
+
The SDK uses `PolymarketError` for all errors.
|
|
1108
|
+
|
|
1109
|
+
```typescript
|
|
1110
|
+
import { PolymarketError, ErrorCode } from '@prediction-router/poly-sdk';
|
|
1111
|
+
|
|
1112
|
+
try {
|
|
1113
|
+
await client.getMarket('invalid-id');
|
|
1114
|
+
} catch (error) {
|
|
1115
|
+
if (error instanceof PolymarketError) {
|
|
1116
|
+
switch (error.code) {
|
|
1117
|
+
case ErrorCode.NOT_FOUND:
|
|
1118
|
+
console.log('Market not found');
|
|
1119
|
+
break;
|
|
1120
|
+
case ErrorCode.RATE_LIMITED:
|
|
1121
|
+
console.log('Rate limited, retry later');
|
|
1122
|
+
break;
|
|
1123
|
+
case ErrorCode.API_ERROR:
|
|
1124
|
+
console.log('API error:', error.message);
|
|
1125
|
+
break;
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
```
|
|
1130
|
+
|
|
1131
|
+
### Error Codes
|
|
1132
|
+
|
|
1133
|
+
| Code | Description |
|
|
1134
|
+
|------|-------------|
|
|
1135
|
+
| `NOT_FOUND` | Resource not found (404) |
|
|
1136
|
+
| `RATE_LIMITED` | Rate limit exceeded (429) |
|
|
1137
|
+
| `UNAUTHORIZED` | Authentication required (401) |
|
|
1138
|
+
| `FORBIDDEN` | Access denied (403) |
|
|
1139
|
+
| `INVALID_RESPONSE` | Invalid API response |
|
|
1140
|
+
| `API_ERROR` | General API error |
|
|
1141
|
+
| `ORDER_FAILED` | Order placement failed |
|
|
1142
|
+
| `NETWORK_ERROR` | Network connectivity issue |
|
|
1143
|
+
|
|
1144
|
+
---
|
|
1145
|
+
|
|
1146
|
+
## License
|
|
1147
|
+
|
|
1148
|
+
MIT
|