clodds 1.2.9 → 1.4.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/dist/skills/bundled/acp/SKILL.md +188 -0
- package/dist/skills/bundled/acp/index.d.ts +0 -3
- package/dist/skills/bundled/acp/index.js +1 -1
- package/dist/skills/bundled/acp/index.js.map +1 -1
- package/dist/skills/bundled/agentbets/SKILL.md +19 -0
- package/dist/skills/bundled/agentbets/index.js +1 -1
- package/dist/skills/bundled/agentbets/index.js.map +1 -1
- package/dist/skills/bundled/ai-strategy/SKILL.md +111 -0
- package/dist/skills/bundled/ai-strategy/index.js +1 -1
- package/dist/skills/bundled/ai-strategy/index.js.map +1 -1
- package/dist/skills/bundled/alerts/SKILL.md +87 -0
- package/dist/skills/bundled/analytics/SKILL.md +252 -0
- package/dist/skills/bundled/analytics/index.js +2 -2
- package/dist/skills/bundled/analytics/index.js.map +1 -1
- package/dist/skills/bundled/arbitrage/SKILL.md +287 -0
- package/dist/skills/bundled/arbitrage/index.js +6 -1
- package/dist/skills/bundled/arbitrage/index.js.map +1 -1
- package/dist/skills/bundled/auto-reply/SKILL.md +285 -0
- package/dist/skills/bundled/auto-reply/index.js +2 -2
- package/dist/skills/bundled/auto-reply/index.js.map +1 -1
- package/dist/skills/bundled/automation/SKILL.md +242 -0
- package/dist/skills/bundled/automation/index.js +2 -2
- package/dist/skills/bundled/automation/index.js.map +1 -1
- package/dist/skills/bundled/backtest/SKILL.md +225 -0
- package/dist/skills/bundled/bags/SKILL.md +131 -0
- package/dist/skills/bundled/bankr/SKILL.md +114 -0
- package/dist/skills/bundled/betfair/SKILL.md +113 -0
- package/dist/skills/bundled/binance-futures/SKILL.md +84 -0
- package/dist/skills/bundled/binance-futures/index.d.ts +0 -3
- package/dist/skills/bundled/binance-futures/index.js +1 -2
- package/dist/skills/bundled/binance-futures/index.js.map +1 -1
- package/dist/skills/bundled/botchan/SKILL.md +66 -0
- package/dist/skills/bundled/botchan/index.d.ts +0 -3
- package/dist/skills/bundled/botchan/index.js +0 -1
- package/dist/skills/bundled/botchan/index.js.map +1 -1
- package/dist/skills/bundled/bridge/SKILL.md +215 -0
- package/dist/skills/bundled/bridge/index.js +6 -0
- package/dist/skills/bundled/bridge/index.js.map +1 -1
- package/dist/skills/bundled/bybit-futures/SKILL.md +84 -0
- package/dist/skills/bundled/bybit-futures/index.d.ts +0 -3
- package/dist/skills/bundled/bybit-futures/index.js +0 -1
- package/dist/skills/bundled/bybit-futures/index.js.map +1 -1
- package/dist/skills/bundled/clanker/SKILL.md +125 -0
- package/dist/skills/bundled/clanker/index.d.ts +0 -3
- package/dist/skills/bundled/clanker/index.js +0 -1
- package/dist/skills/bundled/clanker/index.js.map +1 -1
- package/dist/skills/bundled/copy-trading/SKILL.md +285 -0
- package/dist/skills/bundled/copy-trading/index.js +15 -8
- package/dist/skills/bundled/copy-trading/index.js.map +1 -1
- package/dist/skills/bundled/copy-trading-solana/SKILL.md +66 -0
- package/dist/skills/bundled/credentials/SKILL.md +261 -0
- package/dist/skills/bundled/credentials/index.js +4 -0
- package/dist/skills/bundled/credentials/index.js.map +1 -1
- package/dist/skills/bundled/crypto-hft/SKILL.md +121 -0
- package/dist/skills/bundled/crypto-hft/index.js +18 -3
- package/dist/skills/bundled/crypto-hft/index.js.map +1 -1
- package/dist/skills/bundled/dca/SKILL.md +27 -0
- package/dist/skills/bundled/dex/SKILL.md +92 -0
- package/dist/skills/bundled/dex/index.js +77 -29
- package/dist/skills/bundled/dex/index.js.map +1 -1
- package/dist/skills/bundled/divergence/SKILL.md +83 -0
- package/dist/skills/bundled/doctor/SKILL.md +267 -0
- package/dist/skills/bundled/doctor/index.js +2 -8
- package/dist/skills/bundled/doctor/index.js.map +1 -1
- package/dist/skills/bundled/drift/SKILL.md +53 -0
- package/dist/skills/bundled/drift-sdk/SKILL.md +103 -0
- package/dist/skills/bundled/drift-sdk/index.d.ts +0 -3
- package/dist/skills/bundled/drift-sdk/index.js +0 -1
- package/dist/skills/bundled/drift-sdk/index.js.map +1 -1
- package/dist/skills/bundled/edge/SKILL.md +84 -0
- package/dist/skills/bundled/embeddings/SKILL.md +244 -0
- package/dist/skills/bundled/endaoment/SKILL.md +65 -0
- package/dist/skills/bundled/endaoment/index.d.ts +0 -3
- package/dist/skills/bundled/endaoment/index.js +0 -1
- package/dist/skills/bundled/endaoment/index.js.map +1 -1
- package/dist/skills/bundled/ens/SKILL.md +63 -0
- package/dist/skills/bundled/ens/index.d.ts +0 -3
- package/dist/skills/bundled/ens/index.js +0 -1
- package/dist/skills/bundled/ens/index.js.map +1 -1
- package/dist/skills/bundled/erc8004/SKILL.md +79 -0
- package/dist/skills/bundled/erc8004/index.d.ts +0 -3
- package/dist/skills/bundled/erc8004/index.js +0 -1
- package/dist/skills/bundled/erc8004/index.js.map +1 -1
- package/dist/skills/bundled/execution/SKILL.md +278 -0
- package/dist/skills/bundled/farcaster/SKILL.md +80 -0
- package/dist/skills/bundled/farcaster/index.js +12 -0
- package/dist/skills/bundled/farcaster/index.js.map +1 -1
- package/dist/skills/bundled/features/SKILL.md +20 -0
- package/dist/skills/bundled/feeds/SKILL.md +288 -0
- package/dist/skills/bundled/harden/SKILL.md +74 -0
- package/dist/skills/bundled/history/SKILL.md +257 -0
- package/dist/skills/bundled/hyperliquid/SKILL.md +200 -0
- package/dist/skills/bundled/hyperliquid/index.d.ts +0 -3
- package/dist/skills/bundled/hyperliquid/index.js +0 -1
- package/dist/skills/bundled/hyperliquid/index.js.map +1 -1
- package/dist/skills/bundled/identity/SKILL.md +228 -0
- package/dist/skills/bundled/identity/index.js +2 -2
- package/dist/skills/bundled/identity/index.js.map +1 -1
- package/dist/skills/bundled/integrations/SKILL.md +321 -0
- package/dist/skills/bundled/integrations/index.js +2 -2
- package/dist/skills/bundled/integrations/index.js.map +1 -1
- package/dist/skills/bundled/jupiter/SKILL.md +163 -0
- package/dist/skills/bundled/jupiter/index.js +2 -2
- package/dist/skills/bundled/kamino/SKILL.md +69 -0
- package/dist/skills/bundled/ledger/SKILL.md +20 -0
- package/dist/skills/bundled/lighter/SKILL.md +83 -0
- package/dist/skills/bundled/lighter/index.d.ts +0 -3
- package/dist/skills/bundled/lighter/index.js +0 -1
- package/dist/skills/bundled/lighter/index.js.map +1 -1
- package/dist/skills/bundled/marginfi/SKILL.md +62 -0
- package/dist/skills/bundled/market-index/SKILL.md +242 -0
- package/dist/skills/bundled/market-index/index.js +1 -3
- package/dist/skills/bundled/market-index/index.js.map +1 -1
- package/dist/skills/bundled/markets/SKILL.md +49 -0
- package/dist/skills/bundled/mcp/SKILL.md +235 -0
- package/dist/skills/bundled/mcp/index.js +1 -3
- package/dist/skills/bundled/mcp/index.js.map +1 -1
- package/dist/skills/bundled/memory/SKILL.md +209 -0
- package/dist/skills/bundled/metaculus/SKILL.md +62 -0
- package/dist/skills/bundled/metaculus/index.js +4 -1
- package/dist/skills/bundled/metaculus/index.js.map +1 -1
- package/dist/skills/bundled/meteora/SKILL.md +28 -0
- package/dist/skills/bundled/meteora-dbc/SKILL.md +25 -0
- package/dist/skills/bundled/metrics/SKILL.md +338 -0
- package/dist/skills/bundled/mev/SKILL.md +239 -0
- package/dist/skills/bundled/mev/index.js +2 -2
- package/dist/skills/bundled/mev/index.js.map +1 -1
- package/dist/skills/bundled/mexc-futures/SKILL.md +86 -0
- package/dist/skills/bundled/mexc-futures/index.d.ts +0 -3
- package/dist/skills/bundled/mexc-futures/index.js +0 -1
- package/dist/skills/bundled/mexc-futures/index.js.map +1 -1
- package/dist/skills/bundled/mm/SKILL.md +142 -0
- package/dist/skills/bundled/mm/index.js +28 -27
- package/dist/skills/bundled/mm/index.js.map +1 -1
- package/dist/skills/bundled/monitoring/SKILL.md +249 -0
- package/dist/skills/bundled/news/SKILL.md +95 -0
- package/dist/skills/bundled/news/index.js +1 -2
- package/dist/skills/bundled/news/index.js.map +1 -1
- package/dist/skills/bundled/onchainkit/SKILL.md +83 -0
- package/dist/skills/bundled/opinion/SKILL.md +87 -0
- package/dist/skills/bundled/opportunity/SKILL.md +308 -0
- package/dist/skills/bundled/orca/SKILL.md +28 -0
- package/dist/skills/bundled/orca/index.js +11 -7
- package/dist/skills/bundled/orca/index.js.map +1 -1
- package/dist/skills/bundled/pairing/SKILL.md +275 -0
- package/dist/skills/bundled/pancakeswap/SKILL.md +93 -0
- package/dist/skills/bundled/pancakeswap/index.d.ts +0 -3
- package/dist/skills/bundled/pancakeswap/index.js +0 -1
- package/dist/skills/bundled/pancakeswap/index.js.map +1 -1
- package/dist/skills/bundled/percolator/SKILL.md +22 -0
- package/dist/skills/bundled/permissions/SKILL.md +269 -0
- package/dist/skills/bundled/permissions/index.js +2 -2
- package/dist/skills/bundled/permissions/index.js.map +1 -1
- package/dist/skills/bundled/plugins/SKILL.md +263 -0
- package/dist/skills/bundled/plugins/index.js +2 -2
- package/dist/skills/bundled/plugins/index.js.map +1 -1
- package/dist/skills/bundled/portfolio/SKILL.md +161 -0
- package/dist/skills/bundled/portfolio/index.js +1 -1
- package/dist/skills/bundled/portfolio/index.js.map +1 -1
- package/dist/skills/bundled/portfolio-sync/SKILL.md +466 -0
- package/dist/skills/bundled/positions/SKILL.md +262 -0
- package/dist/skills/bundled/predictfun/SKILL.md +109 -0
- package/dist/skills/bundled/predictfun/index.js +1 -1
- package/dist/skills/bundled/predictfun/index.js.map +1 -1
- package/dist/skills/bundled/predictit/SKILL.md +66 -0
- package/dist/skills/bundled/predictit/index.js +4 -1
- package/dist/skills/bundled/predictit/index.js.map +1 -1
- package/dist/skills/bundled/presence/SKILL.md +217 -0
- package/dist/skills/bundled/presence/index.js +2 -2
- package/dist/skills/bundled/presence/index.js.map +1 -1
- package/dist/skills/bundled/processes/SKILL.md +254 -0
- package/dist/skills/bundled/pump-swarm/SKILL.md +309 -0
- package/dist/skills/bundled/pumpfun/SKILL.md +145 -0
- package/dist/skills/bundled/pumpfun/index.js +82 -8
- package/dist/skills/bundled/pumpfun/index.js.map +1 -1
- package/dist/skills/bundled/qmd/SKILL.md +129 -0
- package/dist/skills/bundled/qrcoin/SKILL.md +60 -0
- package/dist/skills/bundled/qrcoin/index.d.ts +0 -3
- package/dist/skills/bundled/qrcoin/index.js +0 -1
- package/dist/skills/bundled/qrcoin/index.js.map +1 -1
- package/dist/skills/bundled/raydium/SKILL.md +198 -0
- package/dist/skills/bundled/remote/SKILL.md +201 -0
- package/dist/skills/bundled/research/SKILL.md +83 -0
- package/dist/skills/bundled/research/index.js +2 -2
- package/dist/skills/bundled/research/index.js.map +1 -1
- package/dist/skills/bundled/risk/SKILL.md +323 -0
- package/dist/skills/bundled/router/SKILL.md +233 -0
- package/dist/skills/bundled/routing/SKILL.md +258 -0
- package/dist/skills/bundled/sandbox/SKILL.md +257 -0
- package/dist/skills/bundled/search-config/SKILL.md +257 -0
- package/dist/skills/bundled/search-config/index.js +2 -2
- package/dist/skills/bundled/search-config/index.js.map +1 -1
- package/dist/skills/bundled/sessions/SKILL.md +251 -0
- package/dist/skills/bundled/sessions/index.js +1 -1
- package/dist/skills/bundled/sessions/index.js.map +1 -1
- package/dist/skills/bundled/setup/SKILL.md +53 -0
- package/dist/skills/bundled/shield/SKILL.md +21 -0
- package/dist/skills/bundled/signals/SKILL.md +106 -0
- package/dist/skills/bundled/signals/index.d.ts +0 -3
- package/dist/skills/bundled/signals/index.js +3 -4
- package/dist/skills/bundled/signals/index.js.map +1 -1
- package/dist/skills/bundled/sizing/SKILL.md +238 -0
- package/dist/skills/bundled/slippage/SKILL.md +306 -0
- package/dist/skills/bundled/smarkets/SKILL.md +107 -0
- package/dist/skills/bundled/smarkets/index.js +3 -3
- package/dist/skills/bundled/smarkets/index.js.map +1 -1
- package/dist/skills/bundled/solend/SKILL.md +63 -0
- package/dist/skills/bundled/strategy/SKILL.md +266 -0
- package/dist/skills/bundled/streaming/SKILL.md +150 -0
- package/dist/skills/bundled/streaming/index.js +2 -2
- package/dist/skills/bundled/streaming/index.js.map +1 -1
- package/dist/skills/bundled/tailscale/SKILL.md +249 -0
- package/dist/skills/bundled/tailscale/index.js +2 -2
- package/dist/skills/bundled/tailscale/index.js.map +1 -1
- package/dist/skills/bundled/ticks/SKILL.md +61 -0
- package/dist/skills/bundled/token-security/SKILL.md +18 -0
- package/dist/skills/bundled/trading-evm/SKILL.md +329 -0
- package/dist/skills/bundled/trading-futures/SKILL.md +865 -0
- package/dist/skills/bundled/trading-kalshi/SKILL.md +629 -0
- package/dist/skills/bundled/trading-kalshi/index.js +2 -0
- package/dist/skills/bundled/trading-kalshi/index.js.map +1 -1
- package/dist/skills/bundled/trading-manifold/SKILL.md +387 -0
- package/dist/skills/bundled/trading-polymarket/SKILL.md +1080 -0
- package/dist/skills/bundled/trading-polymarket/index.js +28 -19
- package/dist/skills/bundled/trading-polymarket/index.js.map +1 -1
- package/dist/skills/bundled/trading-solana/SKILL.md +418 -0
- package/dist/skills/bundled/trading-solana/index.js +1 -1
- package/dist/skills/bundled/trading-solana/index.js.map +1 -1
- package/dist/skills/bundled/trading-system/SKILL.md +290 -0
- package/dist/skills/bundled/triggers/SKILL.md +433 -0
- package/dist/skills/bundled/tts/SKILL.md +220 -0
- package/dist/skills/bundled/tweet-ideas/SKILL.md +77 -0
- package/dist/skills/bundled/usage/SKILL.md +239 -0
- package/dist/skills/bundled/usage/index.js +2 -2
- package/dist/skills/bundled/usage/index.js.map +1 -1
- package/dist/skills/bundled/veil/SKILL.md +76 -0
- package/dist/skills/bundled/veil/index.d.ts +0 -3
- package/dist/skills/bundled/veil/index.js +0 -1
- package/dist/skills/bundled/veil/index.js.map +1 -1
- package/dist/skills/bundled/verify/SKILL.md +199 -0
- package/dist/skills/bundled/verify/index.d.ts +0 -3
- package/dist/skills/bundled/verify/index.js +0 -1
- package/dist/skills/bundled/verify/index.js.map +1 -1
- package/dist/skills/bundled/virtuals/SKILL.md +82 -0
- package/dist/skills/bundled/voice/SKILL.md +217 -0
- package/dist/skills/bundled/voice/index.js +2 -2
- package/dist/skills/bundled/voice/index.js.map +1 -1
- package/dist/skills/bundled/weather/SKILL.md +80 -0
- package/dist/skills/bundled/weather/index.js +3 -0
- package/dist/skills/bundled/weather/index.js.map +1 -1
- package/dist/skills/bundled/webhooks/SKILL.md +297 -0
- package/dist/skills/bundled/webhooks/index.js +2 -2
- package/dist/skills/bundled/webhooks/index.js.map +1 -1
- package/dist/skills/bundled/whale-tracking/SKILL.md +287 -0
- package/dist/skills/bundled/whale-tracking/index.js +2 -2
- package/dist/skills/bundled/whale-tracking/index.js.map +1 -1
- package/dist/skills/bundled/yoink/SKILL.md +54 -0
- package/dist/skills/bundled/yoink/index.d.ts +0 -3
- package/dist/skills/bundled/yoink/index.js +0 -1
- package/dist/skills/bundled/yoink/index.js.map +1 -1
- package/dist/skills/executor.js +5 -3
- package/dist/skills/executor.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,1080 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: trading-polymarket
|
|
3
|
+
description: "Execute trades on Polymarket using py_clob_client - full API access for market data, orders, positions"
|
|
4
|
+
emoji: "💰"
|
|
5
|
+
gates:
|
|
6
|
+
envs:
|
|
7
|
+
- POLY_API_KEY
|
|
8
|
+
- POLY_API_SECRET
|
|
9
|
+
- POLY_API_PASSPHRASE
|
|
10
|
+
- PRIVATE_KEY
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Polymarket Trading - Complete API Reference
|
|
14
|
+
|
|
15
|
+
Full access to Polymarket's CLOB (Central Limit Order Book) via the official `py_clob_client` library.
|
|
16
|
+
|
|
17
|
+
**60+ methods documented. This is the complete reference.**
|
|
18
|
+
|
|
19
|
+
## Required Environment Variables
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
PRIVATE_KEY=0x... # Ethereum private key for signing
|
|
23
|
+
POLY_FUNDER_ADDRESS=0x... # Your wallet address on Polygon
|
|
24
|
+
POLY_API_KEY=... # From Polymarket API
|
|
25
|
+
POLY_API_SECRET=... # Base64 encoded secret
|
|
26
|
+
POLY_API_PASSPHRASE=... # API passphrase
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pip install py-clob-client requests
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Authentication Levels
|
|
38
|
+
|
|
39
|
+
| Level | Requirements | Capabilities |
|
|
40
|
+
|-------|--------------|--------------|
|
|
41
|
+
| **L0** | None | Read-only: orderbooks, prices, markets |
|
|
42
|
+
| **L1** | Private key | Create & sign orders (not post) |
|
|
43
|
+
| **L2** | Private key + API creds | Full trading: post orders, cancel, query |
|
|
44
|
+
|
|
45
|
+
### Signature Types
|
|
46
|
+
|
|
47
|
+
| Type | Use Case |
|
|
48
|
+
|------|----------|
|
|
49
|
+
| `0` | Standard EOA (MetaMask, hardware wallets) |
|
|
50
|
+
| `1` | Magic/email wallets (delegated signing) |
|
|
51
|
+
| `2` | Proxy wallets (Gnosis Safe, browser proxy) |
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## ClobClient - Complete API (60+ Methods)
|
|
56
|
+
|
|
57
|
+
### Initialization
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
from py_clob_client.client import ClobClient
|
|
61
|
+
from py_clob_client.clob_types import (
|
|
62
|
+
OrderArgs, MarketOrderArgs, ApiCreds, OrderType,
|
|
63
|
+
BookParams, TradeParams, OpenOrderParams, BalanceAllowanceParams,
|
|
64
|
+
AssetType, OrderScoringParams, OrdersScoringParams, DropNotificationParams
|
|
65
|
+
)
|
|
66
|
+
from py_clob_client.order_builder.constants import BUY, SELL
|
|
67
|
+
from py_clob_client.constants import POLYGON # 137
|
|
68
|
+
|
|
69
|
+
# Level 2 Auth (full trading access)
|
|
70
|
+
client = ClobClient(
|
|
71
|
+
host="https://clob.polymarket.com",
|
|
72
|
+
key=os.getenv("PRIVATE_KEY"), # Private key for signing
|
|
73
|
+
chain_id=POLYGON, # 137 for mainnet, 80002 for Amoy testnet
|
|
74
|
+
funder=os.getenv("POLY_FUNDER_ADDRESS"), # Wallet address (for proxy wallets)
|
|
75
|
+
signature_type=2 # 0=EOA, 1=MagicLink, 2=Proxy
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
# Set API credentials for authenticated endpoints
|
|
79
|
+
client.set_api_creds(ApiCreds(
|
|
80
|
+
api_key=os.getenv("POLY_API_KEY"),
|
|
81
|
+
api_secret=os.getenv("POLY_API_SECRET"),
|
|
82
|
+
api_passphrase=os.getenv("POLY_API_PASSPHRASE")
|
|
83
|
+
))
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Health & Configuration
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
client.get_ok() # Check if server is up
|
|
90
|
+
client.get_server_time() # Get server timestamp
|
|
91
|
+
client.get_address() # Your signer's public address
|
|
92
|
+
client.get_collateral_address() # USDC contract address
|
|
93
|
+
client.get_conditional_address() # CTF contract address
|
|
94
|
+
client.get_exchange_address() # Exchange contract (neg_risk=False default)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Market Data - Single Token
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
# Get prices and spreads
|
|
101
|
+
client.get_midpoint(token_id) # Mid market price
|
|
102
|
+
client.get_price(token_id, side="BUY") # Best price for side
|
|
103
|
+
client.get_spread(token_id) # Current spread
|
|
104
|
+
client.get_last_trade_price(token_id) # Last executed trade price
|
|
105
|
+
|
|
106
|
+
# Get full orderbook
|
|
107
|
+
orderbook = client.get_order_book(token_id)
|
|
108
|
+
# Returns: OrderBookSummary with bids, asks, tick_size, neg_risk, timestamp, hash
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Market Data - Batch (Multiple Tokens)
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
params = [
|
|
115
|
+
BookParams(token_id="TOKEN1", side="BUY"),
|
|
116
|
+
BookParams(token_id="TOKEN2", side="SELL")
|
|
117
|
+
]
|
|
118
|
+
|
|
119
|
+
client.get_midpoints(params) # Multiple midpoints
|
|
120
|
+
client.get_prices(params) # Multiple prices
|
|
121
|
+
client.get_spreads(params) # Multiple spreads
|
|
122
|
+
client.get_order_books(params) # Multiple orderbooks
|
|
123
|
+
client.get_last_trades_prices(params) # Multiple last prices
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Market Metadata
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
client.get_tick_size(token_id) # Returns: "0.1", "0.01", "0.001", or "0.0001"
|
|
130
|
+
client.get_neg_risk(token_id) # Returns: True/False (negative risk market)
|
|
131
|
+
client.get_fee_rate_bps(token_id) # Returns: fee rate in basis points (0 or 1000)
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Order Types
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
from py_clob_client.clob_types import OrderType
|
|
140
|
+
|
|
141
|
+
OrderType.GTC # Good Till Cancelled - stays open until filled/cancelled
|
|
142
|
+
OrderType.FOK # Fill Or Kill - fill entirely immediately or cancel
|
|
143
|
+
OrderType.GTD # Good Till Date - expires at timestamp (min 60 seconds)
|
|
144
|
+
OrderType.FAK # Fill And Kill - fill what's possible, cancel rest
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### When to Use Each Order Type
|
|
148
|
+
|
|
149
|
+
| Type | Use Case | Example |
|
|
150
|
+
|------|----------|---------|
|
|
151
|
+
| **GTC** | Entries - wait for fill | Place buy at 0.45, wait for dip |
|
|
152
|
+
| **FOK** | Exits - need immediate fill | Market sell entire position NOW |
|
|
153
|
+
| **GTD** | Time-limited orders | Offer expires in 5 minutes |
|
|
154
|
+
| **FAK** | Partial fills OK | Get as much as possible now |
|
|
155
|
+
|
|
156
|
+
### OrderArgs - Limit Orders
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
OrderArgs(
|
|
160
|
+
token_id: str, # Token ID (outcome to trade)
|
|
161
|
+
price: float, # Price 0.01-0.99
|
|
162
|
+
size: float, # Number of shares
|
|
163
|
+
side: str, # "BUY" or "SELL" (or use BUY/SELL constants)
|
|
164
|
+
fee_rate_bps: int = 0, # Optional: fee rate in bps (0 or check market)
|
|
165
|
+
nonce: int = 0, # Optional: unique nonce for cancellation
|
|
166
|
+
expiration: int = 0, # Optional: expiry timestamp (0 = GTC, use timestamp for GTD)
|
|
167
|
+
taker: str = ZERO_ADDRESS # Optional: specific taker (ZERO_ADDRESS = anyone)
|
|
168
|
+
)
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### MarketOrderArgs - Market Orders
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
MarketOrderArgs(
|
|
175
|
+
token_id: str, # Token ID
|
|
176
|
+
amount: float, # Total USDC amount to spend (BUY) or shares (SELL)
|
|
177
|
+
side: str, # "BUY" or "SELL"
|
|
178
|
+
price: float = 0, # Optional: worst acceptable price (slippage protection)
|
|
179
|
+
fee_rate_bps: int = 0, # Optional: fee rate
|
|
180
|
+
nonce: int = 0, # Optional: nonce
|
|
181
|
+
taker: str = ZERO_ADDRESS, # Optional: taker address
|
|
182
|
+
order_type: OrderType = FOK # Optional: FOK (default) or FAK
|
|
183
|
+
)
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Complete Order Examples
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
from py_clob_client.order_builder.constants import BUY, SELL
|
|
190
|
+
|
|
191
|
+
# 1. LIMIT BUY (GTC) - sits on book until filled
|
|
192
|
+
order = client.create_and_post_order(
|
|
193
|
+
OrderArgs(token_id=TOKEN_ID, price=0.45, size=100.0, side=BUY)
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
# 2. LIMIT SELL (GTC)
|
|
197
|
+
order = client.create_and_post_order(
|
|
198
|
+
OrderArgs(token_id=TOKEN_ID, price=0.55, size=50.0, side=SELL)
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
# 3. MARKET BUY - spend $100 USDC at current prices (FOK)
|
|
202
|
+
signed = client.create_market_order(
|
|
203
|
+
MarketOrderArgs(token_id=TOKEN_ID, amount=100.0, side=BUY)
|
|
204
|
+
)
|
|
205
|
+
result = client.post_order(signed, orderType=OrderType.FOK)
|
|
206
|
+
|
|
207
|
+
# 4. MARKET SELL - sell all shares immediately (FOK)
|
|
208
|
+
signed = client.create_market_order(
|
|
209
|
+
MarketOrderArgs(token_id=TOKEN_ID, amount=my_shares, side=SELL)
|
|
210
|
+
)
|
|
211
|
+
result = client.post_order(signed, orderType=OrderType.FOK)
|
|
212
|
+
|
|
213
|
+
# 5. POST-ONLY MAKER ORDER (avoid taker fees, earn rebates)
|
|
214
|
+
signed = client.create_order(
|
|
215
|
+
OrderArgs(token_id=TOKEN_ID, price=0.44, size=100.0, side=BUY)
|
|
216
|
+
)
|
|
217
|
+
result = client.post_order(signed, orderType=OrderType.GTC, post_only=True)
|
|
218
|
+
# If order would cross spread, it gets REJECTED instead of taking
|
|
219
|
+
|
|
220
|
+
# 6. GOOD TIL DATE (GTD) - expires after timestamp
|
|
221
|
+
import time
|
|
222
|
+
expiry = int(time.time()) + 300 # 5 minutes from now
|
|
223
|
+
signed = client.create_order(
|
|
224
|
+
OrderArgs(token_id=TOKEN_ID, price=0.50, size=100.0, side=BUY, expiration=expiry)
|
|
225
|
+
)
|
|
226
|
+
result = client.post_order(signed, orderType=OrderType.GTD)
|
|
227
|
+
|
|
228
|
+
# 7. FILL AND KILL (FAK) - fill what you can, cancel rest
|
|
229
|
+
signed = client.create_market_order(
|
|
230
|
+
MarketOrderArgs(token_id=TOKEN_ID, amount=1000.0, side=BUY)
|
|
231
|
+
)
|
|
232
|
+
result = client.post_order(signed, orderType=OrderType.FAK)
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Order Operations
|
|
238
|
+
|
|
239
|
+
### Create and Post Orders
|
|
240
|
+
|
|
241
|
+
```python
|
|
242
|
+
# SIMPLE: Create and post in one call (recommended)
|
|
243
|
+
result = client.create_and_post_order(
|
|
244
|
+
OrderArgs(
|
|
245
|
+
token_id="123456789012345678901234567890",
|
|
246
|
+
price=0.45,
|
|
247
|
+
size=10.0,
|
|
248
|
+
side="BUY"
|
|
249
|
+
)
|
|
250
|
+
)
|
|
251
|
+
# Returns: {"orderID": "...", "status": "...", ...}
|
|
252
|
+
|
|
253
|
+
# ADVANCED: Separate create and post
|
|
254
|
+
order = client.create_order(OrderArgs(...)) # Returns SignedOrder
|
|
255
|
+
result = client.post_order(order, orderType=OrderType.GTC, post_only=False)
|
|
256
|
+
|
|
257
|
+
# Market order (calculates price automatically)
|
|
258
|
+
result = client.create_market_order(
|
|
259
|
+
MarketOrderArgs(
|
|
260
|
+
token_id="...",
|
|
261
|
+
amount=100.0, # Spend $100 USDC
|
|
262
|
+
side="BUY"
|
|
263
|
+
)
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
# Calculate expected fill price before market order
|
|
267
|
+
price = client.calculate_market_price(
|
|
268
|
+
token_id="...",
|
|
269
|
+
side="BUY",
|
|
270
|
+
amount=100.0,
|
|
271
|
+
order_type=OrderType.FOK
|
|
272
|
+
)
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### Cancel Orders
|
|
276
|
+
|
|
277
|
+
```python
|
|
278
|
+
client.cancel(order_id="ORDER_ID") # Cancel specific order
|
|
279
|
+
client.cancel_orders(["ID1", "ID2", "ID3"]) # Cancel multiple
|
|
280
|
+
client.cancel_all() # Cancel ALL open orders
|
|
281
|
+
client.cancel_market_orders( # Cancel by market/asset
|
|
282
|
+
market="CONDITION_ID",
|
|
283
|
+
asset_id="TOKEN_ID"
|
|
284
|
+
)
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Query Orders
|
|
288
|
+
|
|
289
|
+
```python
|
|
290
|
+
# Get all open orders
|
|
291
|
+
orders = client.get_orders(
|
|
292
|
+
params=OpenOrderParams(
|
|
293
|
+
id="ORDER_ID", # Optional: specific order
|
|
294
|
+
market="COND_ID", # Optional: filter by market
|
|
295
|
+
asset_id="TOKEN" # Optional: filter by token
|
|
296
|
+
),
|
|
297
|
+
next_cursor="MA==" # For pagination
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
# Get specific order
|
|
301
|
+
order = client.get_order(order_id="ORDER_ID")
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### Trade History
|
|
305
|
+
|
|
306
|
+
```python
|
|
307
|
+
trades = client.get_trades(
|
|
308
|
+
params=TradeParams(
|
|
309
|
+
id="TRADE_ID", # Optional: specific trade
|
|
310
|
+
maker_address="0x...", # Optional: filter by maker
|
|
311
|
+
market="CONDITION_ID", # Optional: filter by market
|
|
312
|
+
asset_id="TOKEN_ID", # Optional: filter by token
|
|
313
|
+
before="2024-01-01", # Optional: before date
|
|
314
|
+
after="2023-01-01" # Optional: after date
|
|
315
|
+
),
|
|
316
|
+
next_cursor="MA=="
|
|
317
|
+
)
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### Balance & Allowance
|
|
321
|
+
|
|
322
|
+
```python
|
|
323
|
+
# Check balance and allowances
|
|
324
|
+
balance = client.get_balance_allowance(
|
|
325
|
+
params=BalanceAllowanceParams(
|
|
326
|
+
asset_type=AssetType.COLLATERAL, # USDC balance
|
|
327
|
+
# or AssetType.CONDITIONAL # Token balance
|
|
328
|
+
token_id="TOKEN_ID" # For conditional tokens
|
|
329
|
+
)
|
|
330
|
+
)
|
|
331
|
+
|
|
332
|
+
# Update/refresh allowance cache
|
|
333
|
+
client.update_balance_allowance(params=...)
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
## Market Discovery
|
|
339
|
+
|
|
340
|
+
### Get Markets from CLOB
|
|
341
|
+
|
|
342
|
+
```python
|
|
343
|
+
# All active markets
|
|
344
|
+
markets = client.get_markets(next_cursor="MA==")
|
|
345
|
+
simplified = client.get_simplified_markets()
|
|
346
|
+
|
|
347
|
+
# Specific market
|
|
348
|
+
market = client.get_market(condition_id="CONDITION_ID")
|
|
349
|
+
|
|
350
|
+
# Market trade events
|
|
351
|
+
events = client.get_market_trades_events(condition_id="CONDITION_ID")
|
|
352
|
+
|
|
353
|
+
# Sampling/featured markets
|
|
354
|
+
client.get_sampling_markets()
|
|
355
|
+
client.get_sampling_simplified_markets()
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### Get Markets from Gamma API (More Details)
|
|
359
|
+
|
|
360
|
+
```python
|
|
361
|
+
import requests
|
|
362
|
+
|
|
363
|
+
def search_markets(query: str, limit: int = 10):
|
|
364
|
+
"""Search Polymarket markets by keyword"""
|
|
365
|
+
url = "https://gamma-api.polymarket.com/markets"
|
|
366
|
+
params = {
|
|
367
|
+
"_q": query,
|
|
368
|
+
"active": "true",
|
|
369
|
+
"closed": "false",
|
|
370
|
+
"_limit": limit
|
|
371
|
+
}
|
|
372
|
+
r = requests.get(url, params=params)
|
|
373
|
+
return r.json()
|
|
374
|
+
|
|
375
|
+
# Get market details
|
|
376
|
+
markets = search_markets("bitcoin")
|
|
377
|
+
for m in markets:
|
|
378
|
+
print(f"Question: {m['question']}")
|
|
379
|
+
print(f"Condition ID: {m['condition_id']}")
|
|
380
|
+
print(f"Volume: ${m.get('volume', 0):,.2f}")
|
|
381
|
+
for token in m.get('tokens', []):
|
|
382
|
+
print(f" {token['outcome']}: {token['token_id']}")
|
|
383
|
+
print(f" Price: {float(token['price']):.2f}")
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
---
|
|
387
|
+
|
|
388
|
+
## On-Chain Operations
|
|
389
|
+
|
|
390
|
+
### Check Token Balance (Position Size)
|
|
391
|
+
|
|
392
|
+
```python
|
|
393
|
+
import requests
|
|
394
|
+
|
|
395
|
+
CTF_CONTRACT = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045"
|
|
396
|
+
RPC_URL = "https://polygon-rpc.com/"
|
|
397
|
+
|
|
398
|
+
def get_token_balance(wallet: str, token_id: str) -> float:
|
|
399
|
+
"""Get balance of a specific outcome token in shares"""
|
|
400
|
+
token_int = int(token_id)
|
|
401
|
+
# ERC-1155 balanceOf(address,uint256)
|
|
402
|
+
data = f"0x00fdd58e000000000000000000000000{wallet[2:].lower()}{token_int:064x}"
|
|
403
|
+
|
|
404
|
+
r = requests.post(RPC_URL, json={
|
|
405
|
+
"jsonrpc": "2.0",
|
|
406
|
+
"method": "eth_call",
|
|
407
|
+
"params": [{"to": CTF_CONTRACT, "data": data}, "latest"],
|
|
408
|
+
"id": 1
|
|
409
|
+
})
|
|
410
|
+
|
|
411
|
+
result = r.json().get("result", "0x0")
|
|
412
|
+
balance = int(result, 16) / 1e6 # Convert from raw to shares
|
|
413
|
+
return balance
|
|
414
|
+
|
|
415
|
+
# Usage
|
|
416
|
+
balance = get_token_balance(
|
|
417
|
+
wallet="0x7c2211103e7Fbb257Ac6fa59f972cfd8bc9D4795",
|
|
418
|
+
token_id="12345678901234567890"
|
|
419
|
+
)
|
|
420
|
+
print(f"Position: {balance} shares")
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
### Check USDC Balance
|
|
424
|
+
|
|
425
|
+
```python
|
|
426
|
+
USDC_CONTRACT = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174"
|
|
427
|
+
|
|
428
|
+
def get_usdc_balance(wallet: str) -> float:
|
|
429
|
+
"""Get USDC balance on Polygon"""
|
|
430
|
+
# ERC-20 balanceOf(address)
|
|
431
|
+
data = f"0x70a08231000000000000000000000000{wallet[2:].lower()}"
|
|
432
|
+
|
|
433
|
+
r = requests.post(RPC_URL, json={
|
|
434
|
+
"jsonrpc": "2.0",
|
|
435
|
+
"method": "eth_call",
|
|
436
|
+
"params": [{"to": USDC_CONTRACT, "data": data}, "latest"],
|
|
437
|
+
"id": 1
|
|
438
|
+
})
|
|
439
|
+
|
|
440
|
+
result = r.json().get("result", "0x0")
|
|
441
|
+
return int(result, 16) / 1e6 # USDC has 6 decimals
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
---
|
|
445
|
+
|
|
446
|
+
## API Key Management
|
|
447
|
+
|
|
448
|
+
```python
|
|
449
|
+
# Create new API key
|
|
450
|
+
creds = client.create_api_key(nonce=0)
|
|
451
|
+
|
|
452
|
+
# Derive existing API key (if you lost creds but have private key)
|
|
453
|
+
creds = client.derive_api_key(nonce=0)
|
|
454
|
+
|
|
455
|
+
# Create or derive (tries both)
|
|
456
|
+
creds = client.create_or_derive_api_creds(nonce=0)
|
|
457
|
+
|
|
458
|
+
# Get all your API keys
|
|
459
|
+
keys = client.get_api_keys()
|
|
460
|
+
|
|
461
|
+
# Delete current API key
|
|
462
|
+
client.delete_api_key()
|
|
463
|
+
|
|
464
|
+
# Readonly API keys (for monitoring only)
|
|
465
|
+
readonly = client.create_readonly_api_key()
|
|
466
|
+
client.get_readonly_api_keys()
|
|
467
|
+
client.delete_readonly_api_key(key="...")
|
|
468
|
+
client.validate_readonly_api_key(address="0x...", key="...")
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
---
|
|
472
|
+
|
|
473
|
+
## Advanced Features
|
|
474
|
+
|
|
475
|
+
### Order Heartbeat (Keep Orders Alive)
|
|
476
|
+
|
|
477
|
+
```python
|
|
478
|
+
# Start heartbeat - if not sent within 10s, all orders cancelled
|
|
479
|
+
heartbeat_id = client.post_heartbeat(heartbeat_id=None)
|
|
480
|
+
|
|
481
|
+
# Continue sending heartbeats
|
|
482
|
+
while trading:
|
|
483
|
+
client.post_heartbeat(heartbeat_id=heartbeat_id)
|
|
484
|
+
time.sleep(5)
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
### Order Scoring
|
|
488
|
+
|
|
489
|
+
```python
|
|
490
|
+
# Check if order is scoring (earning rewards)
|
|
491
|
+
is_scoring = client.is_order_scoring(
|
|
492
|
+
params=OrderScoringParams(order_id="...")
|
|
493
|
+
)
|
|
494
|
+
|
|
495
|
+
# Check multiple orders
|
|
496
|
+
scores = client.are_orders_scoring(
|
|
497
|
+
params=OrdersScoringParams(order_ids=["ID1", "ID2"])
|
|
498
|
+
)
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
### Notifications
|
|
502
|
+
|
|
503
|
+
```python
|
|
504
|
+
notifications = client.get_notifications()
|
|
505
|
+
client.drop_notifications(params=DropNotificationParams(...))
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
---
|
|
509
|
+
|
|
510
|
+
## Fee Structure
|
|
511
|
+
|
|
512
|
+
**IMPORTANT: Most Polymarket markets have ZERO fees (0% maker, 0% taker).**
|
|
513
|
+
|
|
514
|
+
### 15-min Crypto Markets (Exception)
|
|
515
|
+
|
|
516
|
+
Only 15-minute BTC/ETH/SOL/XRP price prediction markets have fees:
|
|
517
|
+
|
|
518
|
+
```
|
|
519
|
+
fee = shares × 0.25 × (price × (1 - price))²
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
| Entry Price | Fee % (per side) |
|
|
523
|
+
|-------------|------------------|
|
|
524
|
+
| 0.50 | ~1.56% |
|
|
525
|
+
| 0.60 or 0.40 | ~1.44% |
|
|
526
|
+
| 0.70 or 0.30 | ~1.10% |
|
|
527
|
+
| 0.80 or 0.20 | ~0.64% |
|
|
528
|
+
| 0.90 or 0.10 | ~0.20% |
|
|
529
|
+
|
|
530
|
+
**TAKER = crosses spread = PAYS fee**
|
|
531
|
+
**MAKER = adds liquidity = NO fee + earns rebates**
|
|
532
|
+
|
|
533
|
+
To be a maker: Post orders that don't immediately fill (inside the spread).
|
|
534
|
+
|
|
535
|
+
---
|
|
536
|
+
|
|
537
|
+
## Decimal Precision Rules
|
|
538
|
+
|
|
539
|
+
| Order Side | Price Decimals | Size Decimals |
|
|
540
|
+
|------------|----------------|---------------|
|
|
541
|
+
| BUY | 2 | 4 |
|
|
542
|
+
| SELL | 2 | 2 |
|
|
543
|
+
|
|
544
|
+
**Min order size:** $1 per side
|
|
545
|
+
|
|
546
|
+
---
|
|
547
|
+
|
|
548
|
+
## Complete Trading Example
|
|
549
|
+
|
|
550
|
+
```python
|
|
551
|
+
#!/usr/bin/env python3
|
|
552
|
+
"""
|
|
553
|
+
Production-ready Polymarket trading script
|
|
554
|
+
"""
|
|
555
|
+
|
|
556
|
+
import os
|
|
557
|
+
import time
|
|
558
|
+
import requests
|
|
559
|
+
from py_clob_client.client import ClobClient
|
|
560
|
+
from py_clob_client.clob_types import OrderArgs, ApiCreds, OrderType
|
|
561
|
+
|
|
562
|
+
# Initialize
|
|
563
|
+
client = ClobClient(
|
|
564
|
+
"https://clob.polymarket.com",
|
|
565
|
+
key=os.getenv("PRIVATE_KEY"),
|
|
566
|
+
chain_id=137,
|
|
567
|
+
funder=os.getenv("POLY_FUNDER_ADDRESS"),
|
|
568
|
+
signature_type=2
|
|
569
|
+
)
|
|
570
|
+
client.set_api_creds(ApiCreds(
|
|
571
|
+
api_key=os.getenv("POLY_API_KEY"),
|
|
572
|
+
api_secret=os.getenv("POLY_API_SECRET"),
|
|
573
|
+
api_passphrase=os.getenv("POLY_API_PASSPHRASE")
|
|
574
|
+
))
|
|
575
|
+
|
|
576
|
+
TOKEN_ID = "YOUR_TOKEN_ID"
|
|
577
|
+
WALLET = os.getenv("POLY_FUNDER_ADDRESS")
|
|
578
|
+
CTF = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045"
|
|
579
|
+
|
|
580
|
+
def get_balance(token_id):
|
|
581
|
+
"""Get position size"""
|
|
582
|
+
token_int = int(token_id)
|
|
583
|
+
data = f"0x00fdd58e000000000000000000000000{WALLET[2:].lower()}{token_int:064x}"
|
|
584
|
+
r = requests.post("https://polygon-rpc.com/", json={
|
|
585
|
+
"jsonrpc": "2.0", "method": "eth_call",
|
|
586
|
+
"params": [{"to": CTF, "data": data}, "latest"], "id": 1
|
|
587
|
+
})
|
|
588
|
+
return int(r.json().get("result", "0x0"), 16) / 1e6
|
|
589
|
+
|
|
590
|
+
def get_orderbook(token_id):
|
|
591
|
+
"""Get current bid/ask"""
|
|
592
|
+
book = client.get_order_book(token_id)
|
|
593
|
+
return {
|
|
594
|
+
"best_bid": float(book.bids[0].price) if book.bids else 0,
|
|
595
|
+
"best_ask": float(book.asks[0].price) if book.asks else 1
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
# Check position
|
|
599
|
+
position = get_balance(TOKEN_ID)
|
|
600
|
+
print(f"Current position: {position} shares")
|
|
601
|
+
|
|
602
|
+
# Get market
|
|
603
|
+
book = get_orderbook(TOKEN_ID)
|
|
604
|
+
print(f"Bid: {book['best_bid']:.2f}, Ask: {book['best_ask']:.2f}")
|
|
605
|
+
|
|
606
|
+
# Place a buy order (maker - inside spread)
|
|
607
|
+
buy_price = book['best_bid'] + 0.01 # 1 cent above bid
|
|
608
|
+
if buy_price < book['best_ask']: # Ensure we're maker
|
|
609
|
+
result = client.create_and_post_order(OrderArgs(
|
|
610
|
+
token_id=TOKEN_ID,
|
|
611
|
+
price=buy_price,
|
|
612
|
+
size=10.0,
|
|
613
|
+
side="BUY"
|
|
614
|
+
))
|
|
615
|
+
print(f"Buy order placed: {result}")
|
|
616
|
+
|
|
617
|
+
# Place a sell order (market sell via FOK)
|
|
618
|
+
if position > 0:
|
|
619
|
+
result = client.create_and_post_order(OrderArgs(
|
|
620
|
+
token_id=TOKEN_ID,
|
|
621
|
+
price=0.01, # Lowest price = immediate fill
|
|
622
|
+
size=position,
|
|
623
|
+
side="SELL"
|
|
624
|
+
))
|
|
625
|
+
print(f"Sold position: {result}")
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
---
|
|
629
|
+
|
|
630
|
+
## Error Handling
|
|
631
|
+
|
|
632
|
+
```python
|
|
633
|
+
from py_clob_client.exceptions import PolyApiException
|
|
634
|
+
|
|
635
|
+
try:
|
|
636
|
+
result = client.create_and_post_order(OrderArgs(...))
|
|
637
|
+
except PolyApiException as e:
|
|
638
|
+
print(f"API Error: {e}")
|
|
639
|
+
except Exception as e:
|
|
640
|
+
print(f"Error: {e}")
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
Common errors:
|
|
644
|
+
- `"insufficient balance"` - Not enough USDC/tokens
|
|
645
|
+
- `"invalid price"` - Price outside 0.01-0.99 or wrong decimals
|
|
646
|
+
- `"order too small"` - Below minimum order size
|
|
647
|
+
- `"market closed"` - Market not accepting orders
|
|
648
|
+
|
|
649
|
+
---
|
|
650
|
+
|
|
651
|
+
## CLI Commands (`/poly`)
|
|
652
|
+
|
|
653
|
+
Access Polymarket trading directly from Claude Code:
|
|
654
|
+
|
|
655
|
+
### Market Data
|
|
656
|
+
```bash
|
|
657
|
+
/poly search <query> # Search markets
|
|
658
|
+
/poly market <condition-id> # Market details
|
|
659
|
+
/poly book <token-id> # View orderbook
|
|
660
|
+
```
|
|
661
|
+
|
|
662
|
+
### Trading
|
|
663
|
+
```bash
|
|
664
|
+
/poly buy <token-id> <size> <price> # Buy shares (limit)
|
|
665
|
+
/poly sell <token-id> <size> <price> # Sell shares (limit)
|
|
666
|
+
/poly orders # Open orders
|
|
667
|
+
/poly cancel <order-id> # Cancel order
|
|
668
|
+
/poly cancel all # Cancel all orders
|
|
669
|
+
/poly trades [limit] # Recent trade history
|
|
670
|
+
/poly balance # USDC + positions
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
### Advanced Orders
|
|
674
|
+
```bash
|
|
675
|
+
/poly twap <buy|sell> <token> <total> <price> [slices] [interval-sec]
|
|
676
|
+
/poly bracket <token> <size> <tp> <sl> # TP + SL bracket
|
|
677
|
+
/poly trigger buy <token> <size> <price> # Buy when price drops
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
**Note:** TWAP and bracket orders are persisted to the database and will automatically resume after restarts.
|
|
681
|
+
|
|
682
|
+
### Auto-Redeem (Resolved Positions)
|
|
683
|
+
```bash
|
|
684
|
+
/poly redeem # One-time redeem all resolved positions
|
|
685
|
+
/poly redeem start # Start auto-polling (default: every 60s)
|
|
686
|
+
/poly redeem stop # Stop auto-polling
|
|
687
|
+
/poly redeem status # Check auto-redeemer status
|
|
688
|
+
/poly redeem pending # List positions pending redemption
|
|
689
|
+
/poly redeem <conditionId> <tokenId> # Redeem specific position
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
**Env vars:**
|
|
693
|
+
- `POLY_REDEEM_INTERVAL_MS` - Polling interval in ms (default: 60000 = 1 minute)
|
|
694
|
+
|
|
695
|
+
### Real-Time Fills (WebSocket)
|
|
696
|
+
```bash
|
|
697
|
+
/poly fills # Connect fills WebSocket
|
|
698
|
+
/poly fills status # Show connection + recent fills
|
|
699
|
+
/poly fills stop # Disconnect fills WebSocket
|
|
700
|
+
/poly fills clear # Clear tracked fills
|
|
701
|
+
```
|
|
702
|
+
|
|
703
|
+
### Order Heartbeat
|
|
704
|
+
```bash
|
|
705
|
+
/poly heartbeat # Start heartbeat (keeps orders alive)
|
|
706
|
+
/poly heartbeat status # Check heartbeat status
|
|
707
|
+
/poly heartbeat stop # Stop heartbeat (orders cancelled in 10s)
|
|
708
|
+
```
|
|
709
|
+
|
|
710
|
+
### Account & Settlements
|
|
711
|
+
```bash
|
|
712
|
+
/poly settlements # View pending settlements from resolved markets
|
|
713
|
+
/poly allowance # Check USDC approval status
|
|
714
|
+
/poly orderbooks <token1> [token2] ... # Batch fetch orderbooks
|
|
715
|
+
```
|
|
716
|
+
|
|
717
|
+
---
|
|
718
|
+
|
|
719
|
+
## Complete ClobClient Method Reference
|
|
720
|
+
|
|
721
|
+
### Health & Config (L0 - No Auth)
|
|
722
|
+
|
|
723
|
+
| Method | Parameters | Returns | Description |
|
|
724
|
+
|--------|------------|---------|-------------|
|
|
725
|
+
| `get_ok()` | - | dict | Health check |
|
|
726
|
+
| `get_server_time()` | - | dict | Server timestamp |
|
|
727
|
+
| `get_address()` | - | str | Your signer address |
|
|
728
|
+
| `get_collateral_address()` | - | str | USDC contract |
|
|
729
|
+
| `get_conditional_address()` | - | str | CTF contract |
|
|
730
|
+
| `get_exchange_address(neg_risk)` | bool | str | Exchange contract |
|
|
731
|
+
|
|
732
|
+
### Market Data (L0 - No Auth)
|
|
733
|
+
|
|
734
|
+
| Method | Parameters | Returns | Description |
|
|
735
|
+
|--------|------------|---------|-------------|
|
|
736
|
+
| `get_midpoint(token_id)` | str | dict | Mid price |
|
|
737
|
+
| `get_midpoints(params)` | list[BookParams] | dict | Multiple mid prices |
|
|
738
|
+
| `get_price(token_id, side)` | str, str | dict | Best price for side |
|
|
739
|
+
| `get_prices(params)` | list[BookParams] | dict | Multiple prices |
|
|
740
|
+
| `get_spread(token_id)` | str | dict | Bid-ask spread |
|
|
741
|
+
| `get_spreads(params)` | list[BookParams] | dict | Multiple spreads |
|
|
742
|
+
| `get_order_book(token_id)` | str | OrderBookSummary | Full orderbook |
|
|
743
|
+
| `get_order_books(params)` | list[BookParams] | list | Multiple orderbooks |
|
|
744
|
+
| `get_last_trade_price(token_id)` | str | dict | Last trade |
|
|
745
|
+
| `get_last_trades_prices(params)` | list[BookParams] | dict | Multiple last trades |
|
|
746
|
+
| `get_tick_size(token_id)` | str | TickSize | "0.1"/"0.01"/"0.001"/"0.0001" |
|
|
747
|
+
| `get_neg_risk(token_id)` | str | bool | Is neg_risk market |
|
|
748
|
+
| `get_fee_rate_bps(token_id)` | str | int | Fee in basis points |
|
|
749
|
+
|
|
750
|
+
### Market Discovery (L0 - No Auth)
|
|
751
|
+
|
|
752
|
+
| Method | Parameters | Returns | Description |
|
|
753
|
+
|--------|------------|---------|-------------|
|
|
754
|
+
| `get_markets(next_cursor)` | str | dict | Paginated markets |
|
|
755
|
+
| `get_simplified_markets(next_cursor)` | str | dict | Simplified markets |
|
|
756
|
+
| `get_sampling_markets(next_cursor)` | str | dict | Featured markets |
|
|
757
|
+
| `get_market(condition_id)` | str | dict | Single market |
|
|
758
|
+
| `get_market_trades_events(condition_id)` | str | dict | Trade events |
|
|
759
|
+
|
|
760
|
+
### Order Creation (L1 - Needs Private Key)
|
|
761
|
+
|
|
762
|
+
| Method | Parameters | Returns | Description |
|
|
763
|
+
|--------|------------|---------|-------------|
|
|
764
|
+
| `create_order(order_args, options)` | OrderArgs, CreateOrderOptions | dict | Sign limit order |
|
|
765
|
+
| `create_market_order(order_args, options)` | MarketOrderArgs, CreateOrderOptions | dict | Sign market order |
|
|
766
|
+
| `calculate_market_price(token_id, side, amount, order_type)` | str, str, float, OrderType | float | Expected fill price |
|
|
767
|
+
|
|
768
|
+
### Order Posting (L2 - Needs API Creds)
|
|
769
|
+
|
|
770
|
+
| Method | Parameters | Returns | Description |
|
|
771
|
+
|--------|------------|---------|-------------|
|
|
772
|
+
| `post_order(order, orderType, post_only)` | SignedOrder, OrderType, bool | dict | Post single order |
|
|
773
|
+
| `post_orders(args)` | list[PostOrdersArgs] | dict | Post batch orders |
|
|
774
|
+
| `create_and_post_order(order_args, options)` | OrderArgs, PartialCreateOrderOptions | dict | Create + post (recommended) |
|
|
775
|
+
|
|
776
|
+
### Order Cancellation (L2 - Needs API Creds)
|
|
777
|
+
|
|
778
|
+
| Method | Parameters | Returns | Description |
|
|
779
|
+
|--------|------------|---------|-------------|
|
|
780
|
+
| `cancel(order_id)` | str | dict | Cancel one order |
|
|
781
|
+
| `cancel_orders(order_ids)` | list[str] | dict | Cancel multiple |
|
|
782
|
+
| `cancel_all()` | - | dict | Cancel ALL orders |
|
|
783
|
+
| `cancel_market_orders(market, asset_id)` | str, str | dict | Cancel by market |
|
|
784
|
+
|
|
785
|
+
### Order Queries (L2 - Needs API Creds)
|
|
786
|
+
|
|
787
|
+
| Method | Parameters | Returns | Description |
|
|
788
|
+
|--------|------------|---------|-------------|
|
|
789
|
+
| `get_orders(params, next_cursor)` | OpenOrderParams, str | list | Get open orders |
|
|
790
|
+
| `get_order(order_id)` | str | dict | Get specific order |
|
|
791
|
+
| `get_trades(params, next_cursor)` | TradeParams, str | list | Trade history |
|
|
792
|
+
|
|
793
|
+
### API Key Management (L2 - Needs API Creds)
|
|
794
|
+
|
|
795
|
+
| Method | Parameters | Returns | Description |
|
|
796
|
+
|--------|------------|---------|-------------|
|
|
797
|
+
| `create_api_key(nonce)` | int | ApiCreds | Create new key |
|
|
798
|
+
| `derive_api_key(nonce)` | int | ApiCreds | Derive existing key |
|
|
799
|
+
| `create_or_derive_api_creds(nonce)` | int | ApiCreds | Create or derive |
|
|
800
|
+
| `set_api_creds(creds)` | ApiCreds | - | Set credentials |
|
|
801
|
+
| `get_api_keys()` | - | dict | List your keys |
|
|
802
|
+
| `delete_api_key()` | - | dict | Delete current key |
|
|
803
|
+
| `create_readonly_api_key()` | - | ReadonlyApiKeyResponse | Readonly key |
|
|
804
|
+
| `get_readonly_api_keys()` | - | list[str] | List readonly keys |
|
|
805
|
+
| `delete_readonly_api_key(key)` | str | bool | Delete readonly key |
|
|
806
|
+
|
|
807
|
+
### Balance & Allowance (L2 - Needs API Creds)
|
|
808
|
+
|
|
809
|
+
| Method | Parameters | Returns | Description |
|
|
810
|
+
|--------|------------|---------|-------------|
|
|
811
|
+
| `get_balance_allowance(params)` | BalanceAllowanceParams | dict | Check balance |
|
|
812
|
+
| `update_balance_allowance(params)` | BalanceAllowanceParams | dict | Refresh allowance |
|
|
813
|
+
|
|
814
|
+
### Advanced Features (L2 - Needs API Creds)
|
|
815
|
+
|
|
816
|
+
| Method | Parameters | Returns | Description |
|
|
817
|
+
|--------|------------|---------|-------------|
|
|
818
|
+
| `post_heartbeat(heartbeat_id)` | str | dict | Keep orders alive (10s timeout) |
|
|
819
|
+
| `is_order_scoring(params)` | OrderScoringParams | dict | Check if earning rewards |
|
|
820
|
+
| `are_orders_scoring(params)` | OrdersScoringParams | dict | Check multiple orders |
|
|
821
|
+
| `get_notifications()` | - | dict | Get notifications |
|
|
822
|
+
| `drop_notifications(params)` | DropNotificationParams | dict | Delete notifications |
|
|
823
|
+
| `get_closed_only_mode()` | - | dict | Check closed-only status |
|
|
824
|
+
|
|
825
|
+
---
|
|
826
|
+
|
|
827
|
+
## Contract Addresses (Polygon Mainnet)
|
|
828
|
+
|
|
829
|
+
```python
|
|
830
|
+
USDC = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174" # Collateral token
|
|
831
|
+
CTF = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045" # Conditional tokens (ERC-1155)
|
|
832
|
+
EXCHANGE = "0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E" # Regular exchange
|
|
833
|
+
NEG_RISK = "0xC5d563A36AE78145C45a50134d48A1215220f80a" # Neg risk exchange (crypto)
|
|
834
|
+
```
|
|
835
|
+
|
|
836
|
+
---
|
|
837
|
+
|
|
838
|
+
## Quick Reference: Common Patterns
|
|
839
|
+
|
|
840
|
+
### Check Position → Sell All
|
|
841
|
+
```python
|
|
842
|
+
balance = get_token_balance(wallet, token_id)
|
|
843
|
+
if balance > 0:
|
|
844
|
+
client.create_and_post_order(OrderArgs(
|
|
845
|
+
token_id=token_id, price=0.01, size=balance, side="SELL"
|
|
846
|
+
))
|
|
847
|
+
```
|
|
848
|
+
|
|
849
|
+
### Maker Entry (No Fees)
|
|
850
|
+
```python
|
|
851
|
+
book = client.get_order_book(token_id)
|
|
852
|
+
best_bid = float(book.bids[0].price) if book.bids else 0
|
|
853
|
+
maker_price = best_bid + 0.01 # 1 cent above bid
|
|
854
|
+
signed = client.create_order(OrderArgs(token_id=token_id, price=maker_price, size=100, side="BUY"))
|
|
855
|
+
client.post_order(signed, orderType=OrderType.GTC, post_only=True)
|
|
856
|
+
```
|
|
857
|
+
|
|
858
|
+
### Market Buy $50 Worth
|
|
859
|
+
```python
|
|
860
|
+
signed = client.create_market_order(MarketOrderArgs(token_id=token_id, amount=50.0, side="BUY"))
|
|
861
|
+
client.post_order(signed, orderType=OrderType.FOK)
|
|
862
|
+
```
|
|
863
|
+
|
|
864
|
+
### Cancel Everything
|
|
865
|
+
```python
|
|
866
|
+
client.cancel_all()
|
|
867
|
+
```
|
|
868
|
+
|
|
869
|
+
---
|
|
870
|
+
|
|
871
|
+
## WebSocket Channels (Real-Time Updates)
|
|
872
|
+
|
|
873
|
+
Polymarket provides WebSocket channels for real-time updates. **No RPC needed - everything goes through CLOB.**
|
|
874
|
+
|
|
875
|
+
### WebSocket URLs
|
|
876
|
+
|
|
877
|
+
```python
|
|
878
|
+
MARKET_WS = "wss://ws-subscriptions-clob.polymarket.com/ws/market"
|
|
879
|
+
USER_WS = "wss://ws-subscriptions-clob.polymarket.com/ws/user"
|
|
880
|
+
```
|
|
881
|
+
|
|
882
|
+
### Market Channel (Public - No Auth)
|
|
883
|
+
|
|
884
|
+
Subscribe to orderbook updates, price changes, trades for any market.
|
|
885
|
+
|
|
886
|
+
```python
|
|
887
|
+
import websocket
|
|
888
|
+
import json
|
|
889
|
+
|
|
890
|
+
def on_message(ws, message):
|
|
891
|
+
data = json.loads(message)
|
|
892
|
+
event_type = data.get("event_type")
|
|
893
|
+
|
|
894
|
+
if event_type == "book":
|
|
895
|
+
# Full orderbook snapshot (on subscribe + after trades)
|
|
896
|
+
print(f"Book update: {data['bids']}, {data['asks']}")
|
|
897
|
+
|
|
898
|
+
elif event_type == "price_change":
|
|
899
|
+
# Order placed/cancelled affecting price level
|
|
900
|
+
print(f"Price change: {data}")
|
|
901
|
+
|
|
902
|
+
elif event_type == "last_trade_price":
|
|
903
|
+
# Trade executed
|
|
904
|
+
print(f"Trade: {data['price']} x {data['size']}")
|
|
905
|
+
|
|
906
|
+
elif event_type == "tick_size_change":
|
|
907
|
+
# Tick size changed (price went extreme)
|
|
908
|
+
print(f"Tick size: {data['old_tick_size']} -> {data['new_tick_size']}")
|
|
909
|
+
|
|
910
|
+
def on_open(ws):
|
|
911
|
+
# Subscribe to specific token
|
|
912
|
+
ws.send(json.dumps({
|
|
913
|
+
"type": "subscribe",
|
|
914
|
+
"channel": "market",
|
|
915
|
+
"assets_ids": [TOKEN_ID] # List of token IDs
|
|
916
|
+
}))
|
|
917
|
+
|
|
918
|
+
ws = websocket.WebSocketApp(
|
|
919
|
+
"wss://ws-subscriptions-clob.polymarket.com/ws/market",
|
|
920
|
+
on_message=on_message,
|
|
921
|
+
on_open=on_open
|
|
922
|
+
)
|
|
923
|
+
ws.run_forever()
|
|
924
|
+
```
|
|
925
|
+
|
|
926
|
+
### User Channel (Authenticated - For Fills)
|
|
927
|
+
|
|
928
|
+
Subscribe to YOUR order updates, fills, trades. **This is how you get fill notifications.**
|
|
929
|
+
|
|
930
|
+
```python
|
|
931
|
+
import websocket
|
|
932
|
+
import json
|
|
933
|
+
import hmac
|
|
934
|
+
import hashlib
|
|
935
|
+
import time
|
|
936
|
+
import base64
|
|
937
|
+
|
|
938
|
+
API_KEY = os.getenv("POLY_API_KEY")
|
|
939
|
+
API_SECRET = os.getenv("POLY_API_SECRET")
|
|
940
|
+
API_PASSPHRASE = os.getenv("POLY_API_PASSPHRASE")
|
|
941
|
+
|
|
942
|
+
def get_auth_headers():
|
|
943
|
+
"""Generate HMAC auth for WebSocket"""
|
|
944
|
+
timestamp = str(int(time.time()))
|
|
945
|
+
message = f"GET\n{timestamp}\n/ws/user"
|
|
946
|
+
signature = hmac.new(
|
|
947
|
+
base64.b64decode(API_SECRET),
|
|
948
|
+
message.encode(),
|
|
949
|
+
hashlib.sha256
|
|
950
|
+
).digest()
|
|
951
|
+
return {
|
|
952
|
+
"POLY-ADDRESS": WALLET_ADDRESS,
|
|
953
|
+
"POLY-SIGNATURE": base64.b64encode(signature).decode(),
|
|
954
|
+
"POLY-TIMESTAMP": timestamp,
|
|
955
|
+
"POLY-API-KEY": API_KEY,
|
|
956
|
+
"POLY-PASSPHRASE": API_PASSPHRASE
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
def on_message(ws, message):
|
|
960
|
+
data = json.loads(message)
|
|
961
|
+
event_type = data.get("event_type")
|
|
962
|
+
|
|
963
|
+
if event_type == "trade":
|
|
964
|
+
# YOUR FILL - order matched!
|
|
965
|
+
status = data.get("status") # MATCHED, MINED, CONFIRMED, FAILED
|
|
966
|
+
print(f"FILL: {data['side']} {data['size']} @ {data['price']}")
|
|
967
|
+
print(f" Status: {status}")
|
|
968
|
+
print(f" Trade ID: {data['id']}")
|
|
969
|
+
print(f" Market: {data['market']}")
|
|
970
|
+
|
|
971
|
+
if status == "CONFIRMED":
|
|
972
|
+
print(" ✓ Trade confirmed on-chain!")
|
|
973
|
+
elif status == "FAILED":
|
|
974
|
+
print(" ✗ Trade failed - check logs")
|
|
975
|
+
|
|
976
|
+
elif event_type == "order":
|
|
977
|
+
order_type = data.get("type") # PLACEMENT, UPDATE, CANCELLATION
|
|
978
|
+
print(f"ORDER {order_type}: {data['side']} {data['original_size']} @ {data['price']}")
|
|
979
|
+
print(f" Filled: {data.get('size_matched', 0)}")
|
|
980
|
+
|
|
981
|
+
if order_type == "CANCELLATION":
|
|
982
|
+
print(" Order cancelled")
|
|
983
|
+
|
|
984
|
+
def on_open(ws):
|
|
985
|
+
# Subscribe with auth
|
|
986
|
+
ws.send(json.dumps({
|
|
987
|
+
"type": "subscribe",
|
|
988
|
+
"channel": "user",
|
|
989
|
+
"auth": get_auth_headers(),
|
|
990
|
+
# Optional: filter to specific market
|
|
991
|
+
# "markets": [CONDITION_ID]
|
|
992
|
+
}))
|
|
993
|
+
|
|
994
|
+
ws = websocket.WebSocketApp(
|
|
995
|
+
"wss://ws-subscriptions-clob.polymarket.com/ws/user",
|
|
996
|
+
on_message=on_message,
|
|
997
|
+
on_open=on_open
|
|
998
|
+
)
|
|
999
|
+
ws.run_forever()
|
|
1000
|
+
```
|
|
1001
|
+
|
|
1002
|
+
### Message Types Summary
|
|
1003
|
+
|
|
1004
|
+
**Market Channel:**
|
|
1005
|
+
| Event | Trigger | Key Fields |
|
|
1006
|
+
|-------|---------|------------|
|
|
1007
|
+
| `book` | Subscribe, trades affect book | bids, asks, timestamp |
|
|
1008
|
+
| `price_change` | Order placed/cancelled | price, size, side |
|
|
1009
|
+
| `last_trade_price` | Trade executed | price, size, side |
|
|
1010
|
+
| `tick_size_change` | Price extreme (>0.96 or <0.04) | old_tick_size, new_tick_size |
|
|
1011
|
+
|
|
1012
|
+
**User Channel:**
|
|
1013
|
+
| Event | Trigger | Key Fields |
|
|
1014
|
+
|-------|---------|------------|
|
|
1015
|
+
| `trade` | Your order filled | status, side, size, price, market |
|
|
1016
|
+
| `order` | Order placed/updated/cancelled | type (PLACEMENT/UPDATE/CANCELLATION), size_matched |
|
|
1017
|
+
|
|
1018
|
+
### Trade Status Flow
|
|
1019
|
+
|
|
1020
|
+
```
|
|
1021
|
+
MATCHED → MINED → CONFIRMED (success)
|
|
1022
|
+
→ RETRYING → CONFIRMED/FAILED
|
|
1023
|
+
```
|
|
1024
|
+
|
|
1025
|
+
### Keepalive
|
|
1026
|
+
|
|
1027
|
+
Send PING every 10 seconds to keep connection alive:
|
|
1028
|
+
```python
|
|
1029
|
+
import threading
|
|
1030
|
+
|
|
1031
|
+
def send_ping():
|
|
1032
|
+
while True:
|
|
1033
|
+
ws.send(json.dumps({"type": "ping"}))
|
|
1034
|
+
time.sleep(10)
|
|
1035
|
+
|
|
1036
|
+
threading.Thread(target=send_ping, daemon=True).start()
|
|
1037
|
+
```
|
|
1038
|
+
|
|
1039
|
+
### Real-Time Data Client (Alternative)
|
|
1040
|
+
|
|
1041
|
+
Polymarket also provides `@polymarket/real-time-data-client` for TypeScript:
|
|
1042
|
+
|
|
1043
|
+
```typescript
|
|
1044
|
+
import { RealTimeDataClient } from "@polymarket/real-time-data-client";
|
|
1045
|
+
|
|
1046
|
+
const client = new RealTimeDataClient({
|
|
1047
|
+
onMessage: (msg) => console.log(msg),
|
|
1048
|
+
onConnect: (c) => {
|
|
1049
|
+
// Subscribe to user fills with auth
|
|
1050
|
+
c.subscribe({
|
|
1051
|
+
subscriptions: [{
|
|
1052
|
+
topic: "clob_user",
|
|
1053
|
+
type: "*",
|
|
1054
|
+
clob_auth: {
|
|
1055
|
+
key: API_KEY,
|
|
1056
|
+
secret: API_SECRET,
|
|
1057
|
+
passphrase: API_PASSPHRASE
|
|
1058
|
+
}
|
|
1059
|
+
}]
|
|
1060
|
+
});
|
|
1061
|
+
}
|
|
1062
|
+
});
|
|
1063
|
+
|
|
1064
|
+
client.connect();
|
|
1065
|
+
```
|
|
1066
|
+
|
|
1067
|
+
---
|
|
1068
|
+
|
|
1069
|
+
## No RPC Needed - CLOB Handles Everything
|
|
1070
|
+
|
|
1071
|
+
| Operation | Method |
|
|
1072
|
+
|-----------|--------|
|
|
1073
|
+
| Get positions | `GET /data/positions?user={address}` via Gamma API |
|
|
1074
|
+
| Get balance | `client.get_balance_allowance()` |
|
|
1075
|
+
| Place orders | `client.create_and_post_order()` |
|
|
1076
|
+
| Get fills | User WebSocket channel |
|
|
1077
|
+
| Get prices | `client.get_order_book()` or Market WebSocket |
|
|
1078
|
+
| Cancel orders | `client.cancel()` |
|
|
1079
|
+
|
|
1080
|
+
The only time you might use RPC is to check on-chain token balances independently, but even that's available via Gamma API positions endpoint.
|