trading-cli 0.3.0__py3-none-any.whl
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.
- fastbooks_cli/__init__.py +3 -0
- fastbooks_cli/__main__.py +6 -0
- fastbooks_cli/client.py +1169 -0
- fastbooks_cli/commands/__init__.py +0 -0
- fastbooks_cli/commands/apikey.py +144 -0
- fastbooks_cli/commands/backtest.py +450 -0
- fastbooks_cli/commands/bots.py +479 -0
- fastbooks_cli/commands/config.py +294 -0
- fastbooks_cli/commands/dex.py +507 -0
- fastbooks_cli/commands/direct.py +150 -0
- fastbooks_cli/commands/execution.py +298 -0
- fastbooks_cli/commands/init_cmd.py +149 -0
- fastbooks_cli/commands/markets.py +270 -0
- fastbooks_cli/commands/mcp_cmd.py +27 -0
- fastbooks_cli/commands/onchain.py +123 -0
- fastbooks_cli/commands/polymarket.py +2215 -0
- fastbooks_cli/commands/repl.py +385 -0
- fastbooks_cli/commands/strategy.py +259 -0
- fastbooks_cli/commands/swap.py +320 -0
- fastbooks_cli/commands/wallet.py +447 -0
- fastbooks_cli/config_store.py +112 -0
- fastbooks_cli/direct.py +209 -0
- fastbooks_cli/main.py +88 -0
- fastbooks_cli/mcp_server.py +171 -0
- fastbooks_cli/output.py +86 -0
- fastbooks_cli/strategies/__init__.py +87 -0
- trading_cli-0.3.0.dist-info/METADATA +309 -0
- trading_cli-0.3.0.dist-info/RECORD +32 -0
- trading_cli-0.3.0.dist-info/WHEEL +5 -0
- trading_cli-0.3.0.dist-info/entry_points.txt +4 -0
- trading_cli-0.3.0.dist-info/licenses/LICENSE +21 -0
- trading_cli-0.3.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,2215 @@
|
|
|
1
|
+
"""Polymarket command group — prediction market trading, browsing, and on-chain ops.
|
|
2
|
+
|
|
3
|
+
Mirrors the full Polymarket CLI feature set: markets, events, CLOB trading,
|
|
4
|
+
CTF token operations, bridging, and portfolio data.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import click
|
|
10
|
+
|
|
11
|
+
from ..client import FastBooksClient
|
|
12
|
+
from ..output import emit, emit_error, format_table, require_experimental
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# ══════════════════════════════════════════════════════════════════════════
|
|
16
|
+
# Root group
|
|
17
|
+
# ══════════════════════════════════════════════════════════════════════════
|
|
18
|
+
|
|
19
|
+
@click.group()
|
|
20
|
+
@click.pass_context
|
|
21
|
+
def polymarket(ctx):
|
|
22
|
+
"""[experimental] Polymarket prediction markets — browse, trade, manage positions.
|
|
23
|
+
|
|
24
|
+
NOTE: requires the Polymarket router, not enabled on standard FastBooks
|
|
25
|
+
deployments. Gated behind FASTBOOKS_EXPERIMENTAL=1.
|
|
26
|
+
|
|
27
|
+
Browse markets and events without a wallet. Trading requires a Polygon
|
|
28
|
+
wallet private key (--private-key or POLYMARKET_PRIVATE_KEY env var).
|
|
29
|
+
|
|
30
|
+
Examples:
|
|
31
|
+
fastbooks polymarket markets list --limit 10
|
|
32
|
+
fastbooks polymarket markets search "bitcoin"
|
|
33
|
+
fastbooks polymarket clob book TOKEN_ID
|
|
34
|
+
fastbooks polymarket clob create-order --token TOKEN --side buy --price 0.50 --size 10
|
|
35
|
+
"""
|
|
36
|
+
require_experimental(ctx, "polymarket")
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# ══════════════════════════════════════════════════════════════════════════
|
|
40
|
+
# Markets (read-only, no wallet needed)
|
|
41
|
+
# ══════════════════════════════════════════════════════════════════════════
|
|
42
|
+
|
|
43
|
+
@polymarket.group("markets")
|
|
44
|
+
def pm_markets():
|
|
45
|
+
"""Browse and search prediction markets."""
|
|
46
|
+
pass
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@pm_markets.command("list")
|
|
50
|
+
@click.option("--limit", "-n", type=int, default=20, help="Number of markets.")
|
|
51
|
+
@click.option("--offset", type=int, default=0, help="Pagination offset.")
|
|
52
|
+
@click.option("--active/--no-active", default=None, help="Filter by active status.")
|
|
53
|
+
@click.option("--closed/--no-closed", default=None, help="Filter by closed status.")
|
|
54
|
+
@click.option("--order", type=str, default=None, help="Sort field (e.g. volume_num).")
|
|
55
|
+
@click.option("--ascending", is_flag=True, help="Sort ascending.")
|
|
56
|
+
@click.pass_context
|
|
57
|
+
def pm_markets_list(ctx, limit, offset, active, closed, order, ascending):
|
|
58
|
+
"""List prediction markets.
|
|
59
|
+
|
|
60
|
+
Examples:
|
|
61
|
+
fastbooks polymarket markets list --limit 10
|
|
62
|
+
fastbooks polymarket markets list --active --order volume_num
|
|
63
|
+
fastbooks polymarket markets list --closed --limit 50 --offset 25
|
|
64
|
+
"""
|
|
65
|
+
client: FastBooksClient = ctx.obj
|
|
66
|
+
try:
|
|
67
|
+
data = client.polymarket_markets_list(
|
|
68
|
+
limit=limit, offset=offset, active=active,
|
|
69
|
+
closed=closed, order=order, ascending=ascending,
|
|
70
|
+
)
|
|
71
|
+
emit(ctx, data, lambda d: _format_markets_list(d))
|
|
72
|
+
except Exception as e:
|
|
73
|
+
emit_error(ctx, str(e))
|
|
74
|
+
ctx.exit(1)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@pm_markets.command("get")
|
|
78
|
+
@click.argument("id_or_slug")
|
|
79
|
+
@click.pass_context
|
|
80
|
+
def pm_markets_get(ctx, id_or_slug):
|
|
81
|
+
"""Get a single market by ID or slug.
|
|
82
|
+
|
|
83
|
+
Examples:
|
|
84
|
+
fastbooks polymarket markets get 12345
|
|
85
|
+
fastbooks polymarket markets get will-trump-win
|
|
86
|
+
"""
|
|
87
|
+
client: FastBooksClient = ctx.obj
|
|
88
|
+
try:
|
|
89
|
+
data = client.polymarket_market_get(id_or_slug)
|
|
90
|
+
emit(ctx, data, lambda d: _format_market_detail(d))
|
|
91
|
+
except Exception as e:
|
|
92
|
+
emit_error(ctx, str(e))
|
|
93
|
+
ctx.exit(1)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
@pm_markets.command("search")
|
|
97
|
+
@click.argument("query")
|
|
98
|
+
@click.option("--limit", "-n", type=int, default=10, help="Max results.")
|
|
99
|
+
@click.pass_context
|
|
100
|
+
def pm_markets_search(ctx, query, limit):
|
|
101
|
+
"""Search markets by keyword.
|
|
102
|
+
|
|
103
|
+
Examples:
|
|
104
|
+
fastbooks polymarket markets search "bitcoin"
|
|
105
|
+
fastbooks polymarket markets search "election" --limit 20
|
|
106
|
+
"""
|
|
107
|
+
client: FastBooksClient = ctx.obj
|
|
108
|
+
try:
|
|
109
|
+
data = client.polymarket_market_search(query, limit)
|
|
110
|
+
emit(ctx, data, lambda d: _format_markets_list(d))
|
|
111
|
+
except Exception as e:
|
|
112
|
+
emit_error(ctx, str(e))
|
|
113
|
+
ctx.exit(1)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
@pm_markets.command("tags")
|
|
117
|
+
@click.argument("market_id")
|
|
118
|
+
@click.pass_context
|
|
119
|
+
def pm_markets_tags(ctx, market_id):
|
|
120
|
+
"""Get tags for a market.
|
|
121
|
+
|
|
122
|
+
Example: fastbooks polymarket markets tags 12345
|
|
123
|
+
"""
|
|
124
|
+
client: FastBooksClient = ctx.obj
|
|
125
|
+
try:
|
|
126
|
+
data = client.polymarket_market_tags(market_id)
|
|
127
|
+
emit(ctx, data)
|
|
128
|
+
except Exception as e:
|
|
129
|
+
emit_error(ctx, str(e))
|
|
130
|
+
ctx.exit(1)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
# ══════════════════════════════════════════════════════════════════════════
|
|
134
|
+
# Events
|
|
135
|
+
# ══════════════════════════════════════════════════════════════════════════
|
|
136
|
+
|
|
137
|
+
@polymarket.group("events")
|
|
138
|
+
def pm_events():
|
|
139
|
+
"""Browse events (groups of related markets)."""
|
|
140
|
+
pass
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
@pm_events.command("list")
|
|
144
|
+
@click.option("--limit", "-n", type=int, default=20)
|
|
145
|
+
@click.option("--offset", type=int, default=0)
|
|
146
|
+
@click.option("--tag", type=str, default=None, help="Filter by tag (e.g. politics, crypto).")
|
|
147
|
+
@click.option("--active/--no-active", default=None)
|
|
148
|
+
@click.option("--closed/--no-closed", default=None)
|
|
149
|
+
@click.pass_context
|
|
150
|
+
def pm_events_list(ctx, limit, offset, tag, active, closed):
|
|
151
|
+
"""List events with optional filters.
|
|
152
|
+
|
|
153
|
+
Examples:
|
|
154
|
+
fastbooks polymarket events list --limit 10
|
|
155
|
+
fastbooks polymarket events list --tag politics --active
|
|
156
|
+
"""
|
|
157
|
+
client: FastBooksClient = ctx.obj
|
|
158
|
+
try:
|
|
159
|
+
data = client.polymarket_events_list(limit=limit, offset=offset, tag=tag, active=active, closed=closed)
|
|
160
|
+
emit(ctx, data, lambda d: _format_events_list(d))
|
|
161
|
+
except Exception as e:
|
|
162
|
+
emit_error(ctx, str(e))
|
|
163
|
+
ctx.exit(1)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
@pm_events.command("get")
|
|
167
|
+
@click.argument("event_id")
|
|
168
|
+
@click.pass_context
|
|
169
|
+
def pm_events_get(ctx, event_id):
|
|
170
|
+
"""Get event details by ID.
|
|
171
|
+
|
|
172
|
+
Example: fastbooks polymarket events get 500
|
|
173
|
+
"""
|
|
174
|
+
client: FastBooksClient = ctx.obj
|
|
175
|
+
try:
|
|
176
|
+
data = client.polymarket_event_get(event_id)
|
|
177
|
+
emit(ctx, data, lambda d: _format_event_detail(d))
|
|
178
|
+
except Exception as e:
|
|
179
|
+
emit_error(ctx, str(e))
|
|
180
|
+
ctx.exit(1)
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
@pm_events.command("tags")
|
|
184
|
+
@click.argument("event_id")
|
|
185
|
+
@click.pass_context
|
|
186
|
+
def pm_events_tags(ctx, event_id):
|
|
187
|
+
"""Get tags for an event.
|
|
188
|
+
|
|
189
|
+
Example: fastbooks polymarket events tags 500
|
|
190
|
+
"""
|
|
191
|
+
client: FastBooksClient = ctx.obj
|
|
192
|
+
try:
|
|
193
|
+
data = client.polymarket_event_tags(event_id)
|
|
194
|
+
emit(ctx, data)
|
|
195
|
+
except Exception as e:
|
|
196
|
+
emit_error(ctx, str(e))
|
|
197
|
+
ctx.exit(1)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
# ══════════════════════════════════════════════════════════════════════════
|
|
201
|
+
# Tags
|
|
202
|
+
# ══════════════════════════════════════════════════════════════════════════
|
|
203
|
+
|
|
204
|
+
@polymarket.group("tags")
|
|
205
|
+
@click.pass_context
|
|
206
|
+
def pm_tags(ctx):
|
|
207
|
+
"""Browse and navigate market tags."""
|
|
208
|
+
pass
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
@pm_tags.command("list")
|
|
212
|
+
@click.pass_context
|
|
213
|
+
def pm_tags_list(ctx):
|
|
214
|
+
"""List all available market tags.
|
|
215
|
+
|
|
216
|
+
Example: fastbooks polymarket tags list
|
|
217
|
+
"""
|
|
218
|
+
client: FastBooksClient = ctx.obj
|
|
219
|
+
try:
|
|
220
|
+
data = client.polymarket_tags_list()
|
|
221
|
+
emit(ctx, data)
|
|
222
|
+
except Exception as e:
|
|
223
|
+
emit_error(ctx, str(e))
|
|
224
|
+
ctx.exit(1)
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
@pm_tags.command("get")
|
|
228
|
+
@click.argument("id_or_slug")
|
|
229
|
+
@click.pass_context
|
|
230
|
+
def pm_tags_get(ctx, id_or_slug):
|
|
231
|
+
"""Get a single tag by ID or slug.
|
|
232
|
+
|
|
233
|
+
Example: fastbooks polymarket tags get politics
|
|
234
|
+
"""
|
|
235
|
+
client: FastBooksClient = ctx.obj
|
|
236
|
+
try:
|
|
237
|
+
data = client.polymarket_tag_get(id_or_slug)
|
|
238
|
+
emit(ctx, data)
|
|
239
|
+
except Exception as e:
|
|
240
|
+
emit_error(ctx, str(e))
|
|
241
|
+
ctx.exit(1)
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
@pm_tags.command("related")
|
|
245
|
+
@click.argument("id_or_slug")
|
|
246
|
+
@click.pass_context
|
|
247
|
+
def pm_tags_related(ctx, id_or_slug):
|
|
248
|
+
"""Get related tags.
|
|
249
|
+
|
|
250
|
+
Example: fastbooks polymarket tags related politics
|
|
251
|
+
"""
|
|
252
|
+
client: FastBooksClient = ctx.obj
|
|
253
|
+
try:
|
|
254
|
+
data = client.polymarket_tags_related(id_or_slug)
|
|
255
|
+
emit(ctx, data)
|
|
256
|
+
except Exception as e:
|
|
257
|
+
emit_error(ctx, str(e))
|
|
258
|
+
ctx.exit(1)
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
# ══════════════════════════════════════════════════════════════════════════
|
|
262
|
+
# Series (recurring events)
|
|
263
|
+
# ══════════════════════════════════════════════════════════════════════════
|
|
264
|
+
|
|
265
|
+
@polymarket.group("series")
|
|
266
|
+
def pm_series():
|
|
267
|
+
"""Browse recurring event series."""
|
|
268
|
+
pass
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
@pm_series.command("list")
|
|
272
|
+
@click.option("--limit", "-n", type=int, default=20)
|
|
273
|
+
@click.option("--offset", type=int, default=0)
|
|
274
|
+
@click.pass_context
|
|
275
|
+
def pm_series_list(ctx, limit, offset):
|
|
276
|
+
"""List event series.
|
|
277
|
+
|
|
278
|
+
Example: fastbooks polymarket series list --limit 10
|
|
279
|
+
"""
|
|
280
|
+
client: FastBooksClient = ctx.obj
|
|
281
|
+
try:
|
|
282
|
+
data = client.polymarket_series_list(limit, offset)
|
|
283
|
+
emit(ctx, data)
|
|
284
|
+
except Exception as e:
|
|
285
|
+
emit_error(ctx, str(e))
|
|
286
|
+
ctx.exit(1)
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
@pm_series.command("get")
|
|
290
|
+
@click.argument("series_id")
|
|
291
|
+
@click.pass_context
|
|
292
|
+
def pm_series_get(ctx, series_id):
|
|
293
|
+
"""Get a series by ID.
|
|
294
|
+
|
|
295
|
+
Example: fastbooks polymarket series get 42
|
|
296
|
+
"""
|
|
297
|
+
client: FastBooksClient = ctx.obj
|
|
298
|
+
try:
|
|
299
|
+
data = client.polymarket_series_get(series_id)
|
|
300
|
+
emit(ctx, data)
|
|
301
|
+
except Exception as e:
|
|
302
|
+
emit_error(ctx, str(e))
|
|
303
|
+
ctx.exit(1)
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
# ══════════════════════════════════════════════════════════════════════════
|
|
307
|
+
# Comments
|
|
308
|
+
# ══════════════════════════════════════════════════════════════════════════
|
|
309
|
+
|
|
310
|
+
@polymarket.group("comments")
|
|
311
|
+
def pm_comments():
|
|
312
|
+
"""Browse comments on markets and events."""
|
|
313
|
+
pass
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
@pm_comments.command("list")
|
|
317
|
+
@click.option("--entity-type", required=True, type=click.Choice(["event", "market", "series"]))
|
|
318
|
+
@click.option("--entity-id", required=True, help="Entity ID.")
|
|
319
|
+
@click.pass_context
|
|
320
|
+
def pm_comments_list(ctx, entity_type, entity_id):
|
|
321
|
+
"""List comments for an entity.
|
|
322
|
+
|
|
323
|
+
Example: fastbooks polymarket comments list --entity-type event --entity-id 500
|
|
324
|
+
"""
|
|
325
|
+
client: FastBooksClient = ctx.obj
|
|
326
|
+
try:
|
|
327
|
+
data = client.polymarket_comments_list(entity_type, entity_id)
|
|
328
|
+
emit(ctx, data)
|
|
329
|
+
except Exception as e:
|
|
330
|
+
emit_error(ctx, str(e))
|
|
331
|
+
ctx.exit(1)
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
@pm_comments.command("get")
|
|
335
|
+
@click.argument("comment_id")
|
|
336
|
+
@click.pass_context
|
|
337
|
+
def pm_comments_get(ctx, comment_id):
|
|
338
|
+
"""Get a comment by ID.
|
|
339
|
+
|
|
340
|
+
Example: fastbooks polymarket comments get abc123
|
|
341
|
+
"""
|
|
342
|
+
client: FastBooksClient = ctx.obj
|
|
343
|
+
try:
|
|
344
|
+
data = client.polymarket_comment_get(comment_id)
|
|
345
|
+
emit(ctx, data)
|
|
346
|
+
except Exception as e:
|
|
347
|
+
emit_error(ctx, str(e))
|
|
348
|
+
ctx.exit(1)
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
@pm_comments.command("by-user")
|
|
352
|
+
@click.argument("address")
|
|
353
|
+
@click.pass_context
|
|
354
|
+
def pm_comments_by_user(ctx, address):
|
|
355
|
+
"""Get comments by a user address.
|
|
356
|
+
|
|
357
|
+
Example: fastbooks polymarket comments by-user 0xf5E6...
|
|
358
|
+
"""
|
|
359
|
+
client: FastBooksClient = ctx.obj
|
|
360
|
+
try:
|
|
361
|
+
data = client.polymarket_comments_by_user(address)
|
|
362
|
+
emit(ctx, data)
|
|
363
|
+
except Exception as e:
|
|
364
|
+
emit_error(ctx, str(e))
|
|
365
|
+
ctx.exit(1)
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
# ══════════════════════════════════════════════════════════════════════════
|
|
369
|
+
# Profiles
|
|
370
|
+
# ══════════════════════════════════════════════════════════════════════════
|
|
371
|
+
|
|
372
|
+
@polymarket.group("profiles")
|
|
373
|
+
def pm_profiles():
|
|
374
|
+
"""View public user profiles."""
|
|
375
|
+
pass
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
@pm_profiles.command("get")
|
|
379
|
+
@click.argument("address")
|
|
380
|
+
@click.pass_context
|
|
381
|
+
def pm_profiles_get(ctx, address):
|
|
382
|
+
"""Get a public profile by wallet address.
|
|
383
|
+
|
|
384
|
+
Example: fastbooks polymarket profiles get 0xf5E6...
|
|
385
|
+
"""
|
|
386
|
+
client: FastBooksClient = ctx.obj
|
|
387
|
+
try:
|
|
388
|
+
data = client.polymarket_profile_get(address)
|
|
389
|
+
emit(ctx, data)
|
|
390
|
+
except Exception as e:
|
|
391
|
+
emit_error(ctx, str(e))
|
|
392
|
+
ctx.exit(1)
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
# ══════════════════════════════════════════════════════════════════════════
|
|
396
|
+
# Sports
|
|
397
|
+
# ══════════════════════════════════════════════════════════════════════════
|
|
398
|
+
|
|
399
|
+
@polymarket.group("sports")
|
|
400
|
+
def pm_sports():
|
|
401
|
+
"""Sports metadata: leagues, teams, market types."""
|
|
402
|
+
pass
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
@pm_sports.command("list")
|
|
406
|
+
@click.pass_context
|
|
407
|
+
def pm_sports_list(ctx):
|
|
408
|
+
"""List supported sports.
|
|
409
|
+
|
|
410
|
+
Example: fastbooks polymarket sports list
|
|
411
|
+
"""
|
|
412
|
+
client: FastBooksClient = ctx.obj
|
|
413
|
+
try:
|
|
414
|
+
data = client.polymarket_sports_list()
|
|
415
|
+
emit(ctx, data)
|
|
416
|
+
except Exception as e:
|
|
417
|
+
emit_error(ctx, str(e))
|
|
418
|
+
ctx.exit(1)
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
@pm_sports.command("market-types")
|
|
422
|
+
@click.pass_context
|
|
423
|
+
def pm_sports_market_types(ctx):
|
|
424
|
+
"""List valid sports market types.
|
|
425
|
+
|
|
426
|
+
Example: fastbooks polymarket sports market-types
|
|
427
|
+
"""
|
|
428
|
+
client: FastBooksClient = ctx.obj
|
|
429
|
+
try:
|
|
430
|
+
data = client.polymarket_sports_market_types()
|
|
431
|
+
emit(ctx, data)
|
|
432
|
+
except Exception as e:
|
|
433
|
+
emit_error(ctx, str(e))
|
|
434
|
+
ctx.exit(1)
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
@pm_sports.command("teams")
|
|
438
|
+
@click.option("--league", required=True, help="League name (e.g. NFL, NBA, MLB).")
|
|
439
|
+
@click.option("--limit", "-n", type=int, default=50)
|
|
440
|
+
@click.pass_context
|
|
441
|
+
def pm_sports_teams(ctx, league, limit):
|
|
442
|
+
"""List teams in a league.
|
|
443
|
+
|
|
444
|
+
Example: fastbooks polymarket sports teams --league NFL --limit 32
|
|
445
|
+
"""
|
|
446
|
+
client: FastBooksClient = ctx.obj
|
|
447
|
+
try:
|
|
448
|
+
data = client.polymarket_sports_teams(league, limit)
|
|
449
|
+
emit(ctx, data)
|
|
450
|
+
except Exception as e:
|
|
451
|
+
emit_error(ctx, str(e))
|
|
452
|
+
ctx.exit(1)
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
# ══════════════════════════════════════════════════════════════════════════
|
|
456
|
+
# Wallet Management
|
|
457
|
+
# ══════════════════════════════════════════════════════════════════════════
|
|
458
|
+
|
|
459
|
+
@polymarket.group("wallet")
|
|
460
|
+
def pm_wallet():
|
|
461
|
+
"""Manage Polymarket wallet (create, import, show, reset).
|
|
462
|
+
|
|
463
|
+
The wallet private key is used to sign orders and on-chain transactions.
|
|
464
|
+
Stored in ~/.config/polymarket/config.json.
|
|
465
|
+
"""
|
|
466
|
+
pass
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
@pm_wallet.command("create")
|
|
470
|
+
@click.option("--signature-type", type=click.Choice(["proxy", "eoa", "gnosis-safe"]), default="proxy")
|
|
471
|
+
@click.pass_context
|
|
472
|
+
def pm_wallet_create(ctx, signature_type):
|
|
473
|
+
"""Generate a new random wallet.
|
|
474
|
+
|
|
475
|
+
Creates a new private key and saves it to config.
|
|
476
|
+
|
|
477
|
+
Example: fastbooks polymarket wallet create
|
|
478
|
+
"""
|
|
479
|
+
client: FastBooksClient = ctx.obj
|
|
480
|
+
try:
|
|
481
|
+
data = client.polymarket_wallet_create(signature_type)
|
|
482
|
+
emit(ctx, data, lambda d: _format_wallet_info(d))
|
|
483
|
+
except Exception as e:
|
|
484
|
+
emit_error(ctx, str(e))
|
|
485
|
+
ctx.exit(1)
|
|
486
|
+
|
|
487
|
+
|
|
488
|
+
@pm_wallet.command("import")
|
|
489
|
+
@click.argument("private_key")
|
|
490
|
+
@click.option("--signature-type", type=click.Choice(["proxy", "eoa", "gnosis-safe"]), default="proxy")
|
|
491
|
+
@click.pass_context
|
|
492
|
+
def pm_wallet_import(ctx, private_key, signature_type):
|
|
493
|
+
"""Import an existing private key.
|
|
494
|
+
|
|
495
|
+
Example: fastbooks polymarket wallet import 0xabc123...
|
|
496
|
+
"""
|
|
497
|
+
client: FastBooksClient = ctx.obj
|
|
498
|
+
try:
|
|
499
|
+
data = client.polymarket_wallet_import(private_key, signature_type)
|
|
500
|
+
emit(ctx, data, lambda d: _format_wallet_info(d))
|
|
501
|
+
except Exception as e:
|
|
502
|
+
emit_error(ctx, str(e))
|
|
503
|
+
ctx.exit(1)
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
@pm_wallet.command("address")
|
|
507
|
+
@click.pass_context
|
|
508
|
+
def pm_wallet_address(ctx):
|
|
509
|
+
"""Print the configured wallet address.
|
|
510
|
+
|
|
511
|
+
Example: fastbooks polymarket wallet address
|
|
512
|
+
"""
|
|
513
|
+
client: FastBooksClient = ctx.obj
|
|
514
|
+
try:
|
|
515
|
+
data = client.polymarket_wallet_address()
|
|
516
|
+
emit(ctx, data)
|
|
517
|
+
except Exception as e:
|
|
518
|
+
emit_error(ctx, str(e))
|
|
519
|
+
ctx.exit(1)
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
@pm_wallet.command("show")
|
|
523
|
+
@click.pass_context
|
|
524
|
+
def pm_wallet_show(ctx):
|
|
525
|
+
"""Show full wallet info (address, source, config path).
|
|
526
|
+
|
|
527
|
+
Example: fastbooks polymarket wallet show
|
|
528
|
+
"""
|
|
529
|
+
client: FastBooksClient = ctx.obj
|
|
530
|
+
try:
|
|
531
|
+
data = client.polymarket_wallet_show()
|
|
532
|
+
emit(ctx, data, lambda d: _format_wallet_info(d))
|
|
533
|
+
except Exception as e:
|
|
534
|
+
emit_error(ctx, str(e))
|
|
535
|
+
ctx.exit(1)
|
|
536
|
+
|
|
537
|
+
|
|
538
|
+
@pm_wallet.command("reset")
|
|
539
|
+
@click.option("--confirm/--no-confirm", default=True)
|
|
540
|
+
@click.pass_context
|
|
541
|
+
def pm_wallet_reset(ctx, confirm):
|
|
542
|
+
"""Delete wallet config (prompts for confirmation).
|
|
543
|
+
|
|
544
|
+
Example: fastbooks polymarket wallet reset
|
|
545
|
+
"""
|
|
546
|
+
if confirm and not ctx.find_root().params.get("json_output", False):
|
|
547
|
+
if not click.confirm(" Delete Polymarket wallet config?"):
|
|
548
|
+
click.echo(" Cancelled.")
|
|
549
|
+
return
|
|
550
|
+
client: FastBooksClient = ctx.obj
|
|
551
|
+
try:
|
|
552
|
+
data = client.polymarket_wallet_reset()
|
|
553
|
+
emit(ctx, data, lambda d: " Wallet config deleted.")
|
|
554
|
+
except Exception as e:
|
|
555
|
+
emit_error(ctx, str(e))
|
|
556
|
+
ctx.exit(1)
|
|
557
|
+
|
|
558
|
+
|
|
559
|
+
# ══════════════════════════════════════════════════════════════════════════
|
|
560
|
+
# CLOB — Order Book & Prices (read-only, no wallet)
|
|
561
|
+
# ══════════════════════════════════════════════════════════════════════════
|
|
562
|
+
|
|
563
|
+
@polymarket.group("clob")
|
|
564
|
+
def pm_clob():
|
|
565
|
+
"""CLOB order book: prices, books, trading, and account queries.
|
|
566
|
+
|
|
567
|
+
Read-only commands (book, price, midpoint, spread) work without a wallet.
|
|
568
|
+
Trading commands require --private-key or POLYMARKET_PRIVATE_KEY.
|
|
569
|
+
"""
|
|
570
|
+
pass
|
|
571
|
+
|
|
572
|
+
|
|
573
|
+
@pm_clob.command("book")
|
|
574
|
+
@click.argument("token_id")
|
|
575
|
+
@click.pass_context
|
|
576
|
+
def pm_clob_book(ctx, token_id):
|
|
577
|
+
"""Get order book for a token.
|
|
578
|
+
|
|
579
|
+
Example: fastbooks polymarket clob book 48331043336612883...
|
|
580
|
+
"""
|
|
581
|
+
client: FastBooksClient = ctx.obj
|
|
582
|
+
try:
|
|
583
|
+
data = client.polymarket_clob_book(token_id)
|
|
584
|
+
emit(ctx, data, lambda d: _format_clob_book(d))
|
|
585
|
+
except Exception as e:
|
|
586
|
+
emit_error(ctx, str(e))
|
|
587
|
+
ctx.exit(1)
|
|
588
|
+
|
|
589
|
+
|
|
590
|
+
@pm_clob.command("price")
|
|
591
|
+
@click.argument("token_id")
|
|
592
|
+
@click.option("--side", type=click.Choice(["buy", "sell"]), default="buy", help="Price side.")
|
|
593
|
+
@click.pass_context
|
|
594
|
+
def pm_clob_price(ctx, token_id, side):
|
|
595
|
+
"""Get best price for a token.
|
|
596
|
+
|
|
597
|
+
Example: fastbooks polymarket clob price TOKEN_ID --side buy
|
|
598
|
+
"""
|
|
599
|
+
client: FastBooksClient = ctx.obj
|
|
600
|
+
try:
|
|
601
|
+
data = client.polymarket_clob_price(token_id, side)
|
|
602
|
+
emit(ctx, data)
|
|
603
|
+
except Exception as e:
|
|
604
|
+
emit_error(ctx, str(e))
|
|
605
|
+
ctx.exit(1)
|
|
606
|
+
|
|
607
|
+
|
|
608
|
+
@pm_clob.command("midpoint")
|
|
609
|
+
@click.argument("token_id")
|
|
610
|
+
@click.pass_context
|
|
611
|
+
def pm_clob_midpoint(ctx, token_id):
|
|
612
|
+
"""Get midpoint price for a token.
|
|
613
|
+
|
|
614
|
+
Example: fastbooks polymarket clob midpoint TOKEN_ID
|
|
615
|
+
"""
|
|
616
|
+
client: FastBooksClient = ctx.obj
|
|
617
|
+
try:
|
|
618
|
+
data = client.polymarket_clob_midpoint(token_id)
|
|
619
|
+
emit(ctx, data)
|
|
620
|
+
except Exception as e:
|
|
621
|
+
emit_error(ctx, str(e))
|
|
622
|
+
ctx.exit(1)
|
|
623
|
+
|
|
624
|
+
|
|
625
|
+
@pm_clob.command("spread")
|
|
626
|
+
@click.argument("token_id")
|
|
627
|
+
@click.pass_context
|
|
628
|
+
def pm_clob_spread(ctx, token_id):
|
|
629
|
+
"""Get bid-ask spread for a token.
|
|
630
|
+
|
|
631
|
+
Example: fastbooks polymarket clob spread TOKEN_ID
|
|
632
|
+
"""
|
|
633
|
+
client: FastBooksClient = ctx.obj
|
|
634
|
+
try:
|
|
635
|
+
data = client.polymarket_clob_spread(token_id)
|
|
636
|
+
emit(ctx, data)
|
|
637
|
+
except Exception as e:
|
|
638
|
+
emit_error(ctx, str(e))
|
|
639
|
+
ctx.exit(1)
|
|
640
|
+
|
|
641
|
+
|
|
642
|
+
@pm_clob.command("last-trade")
|
|
643
|
+
@click.argument("token_id")
|
|
644
|
+
@click.pass_context
|
|
645
|
+
def pm_clob_last_trade(ctx, token_id):
|
|
646
|
+
"""Get last trade for a token.
|
|
647
|
+
|
|
648
|
+
Example: fastbooks polymarket clob last-trade TOKEN_ID
|
|
649
|
+
"""
|
|
650
|
+
client: FastBooksClient = ctx.obj
|
|
651
|
+
try:
|
|
652
|
+
data = client.polymarket_clob_last_trade(token_id)
|
|
653
|
+
emit(ctx, data)
|
|
654
|
+
except Exception as e:
|
|
655
|
+
emit_error(ctx, str(e))
|
|
656
|
+
ctx.exit(1)
|
|
657
|
+
|
|
658
|
+
|
|
659
|
+
@pm_clob.command("price-history")
|
|
660
|
+
@click.argument("token_id")
|
|
661
|
+
@click.option("--interval", type=click.Choice(["1m", "1h", "6h", "1d", "1w", "max"]), default="1d")
|
|
662
|
+
@click.option("--fidelity", type=int, default=30, help="Number of data points.")
|
|
663
|
+
@click.pass_context
|
|
664
|
+
def pm_clob_price_history(ctx, token_id, interval, fidelity):
|
|
665
|
+
"""Get price history for a token.
|
|
666
|
+
|
|
667
|
+
Examples:
|
|
668
|
+
fastbooks polymarket clob price-history TOKEN_ID --interval 1d --fidelity 30
|
|
669
|
+
fastbooks polymarket clob price-history TOKEN_ID --interval 1h
|
|
670
|
+
"""
|
|
671
|
+
client: FastBooksClient = ctx.obj
|
|
672
|
+
try:
|
|
673
|
+
data = client.polymarket_clob_price_history(token_id, interval, fidelity)
|
|
674
|
+
emit(ctx, data, lambda d: _format_price_history(d))
|
|
675
|
+
except Exception as e:
|
|
676
|
+
emit_error(ctx, str(e))
|
|
677
|
+
ctx.exit(1)
|
|
678
|
+
|
|
679
|
+
|
|
680
|
+
@pm_clob.command("clob-markets")
|
|
681
|
+
@click.pass_context
|
|
682
|
+
def pm_clob_markets(ctx):
|
|
683
|
+
"""List all CLOB markets.
|
|
684
|
+
|
|
685
|
+
Example: fastbooks polymarket clob clob-markets
|
|
686
|
+
"""
|
|
687
|
+
client: FastBooksClient = ctx.obj
|
|
688
|
+
try:
|
|
689
|
+
data = client.polymarket_clob_markets()
|
|
690
|
+
emit(ctx, data)
|
|
691
|
+
except Exception as e:
|
|
692
|
+
emit_error(ctx, str(e))
|
|
693
|
+
ctx.exit(1)
|
|
694
|
+
|
|
695
|
+
|
|
696
|
+
@pm_clob.command("clob-market")
|
|
697
|
+
@click.argument("condition_id")
|
|
698
|
+
@click.pass_context
|
|
699
|
+
def pm_clob_market(ctx, condition_id):
|
|
700
|
+
"""Get CLOB market info by condition ID.
|
|
701
|
+
|
|
702
|
+
Example: fastbooks polymarket clob clob-market 0xABC123...
|
|
703
|
+
"""
|
|
704
|
+
client: FastBooksClient = ctx.obj
|
|
705
|
+
try:
|
|
706
|
+
data = client.polymarket_clob_market(condition_id)
|
|
707
|
+
emit(ctx, data)
|
|
708
|
+
except Exception as e:
|
|
709
|
+
emit_error(ctx, str(e))
|
|
710
|
+
ctx.exit(1)
|
|
711
|
+
|
|
712
|
+
|
|
713
|
+
# ── CLOB batch queries (read-only) ───────────────────────────────────
|
|
714
|
+
|
|
715
|
+
@pm_clob.command("ok")
|
|
716
|
+
@click.pass_context
|
|
717
|
+
def pm_clob_ok(ctx):
|
|
718
|
+
"""Check CLOB API health.
|
|
719
|
+
|
|
720
|
+
Example: fastbooks polymarket clob ok
|
|
721
|
+
"""
|
|
722
|
+
client: FastBooksClient = ctx.obj
|
|
723
|
+
try:
|
|
724
|
+
data = client.polymarket_clob_ok()
|
|
725
|
+
emit(ctx, data)
|
|
726
|
+
except Exception as e:
|
|
727
|
+
emit_error(ctx, str(e))
|
|
728
|
+
ctx.exit(1)
|
|
729
|
+
|
|
730
|
+
|
|
731
|
+
@pm_clob.command("books")
|
|
732
|
+
@click.argument("token_ids", metavar="TOKEN_IDS")
|
|
733
|
+
@click.pass_context
|
|
734
|
+
def pm_clob_books(ctx, token_ids):
|
|
735
|
+
"""Get order books for multiple tokens (comma-separated).
|
|
736
|
+
|
|
737
|
+
Example: fastbooks polymarket clob books "TOKEN1,TOKEN2"
|
|
738
|
+
"""
|
|
739
|
+
client: FastBooksClient = ctx.obj
|
|
740
|
+
try:
|
|
741
|
+
data = client.polymarket_clob_books(token_ids)
|
|
742
|
+
emit(ctx, data)
|
|
743
|
+
except Exception as e:
|
|
744
|
+
emit_error(ctx, str(e))
|
|
745
|
+
ctx.exit(1)
|
|
746
|
+
|
|
747
|
+
|
|
748
|
+
@pm_clob.command("batch-prices")
|
|
749
|
+
@click.argument("token_ids", metavar="TOKEN_IDS")
|
|
750
|
+
@click.option("--side", type=click.Choice(["buy", "sell"]), default="buy")
|
|
751
|
+
@click.pass_context
|
|
752
|
+
def pm_clob_batch_prices(ctx, token_ids, side):
|
|
753
|
+
"""Get prices for multiple tokens (comma-separated).
|
|
754
|
+
|
|
755
|
+
Example: fastbooks polymarket clob batch-prices "TOKEN1,TOKEN2" --side buy
|
|
756
|
+
"""
|
|
757
|
+
client: FastBooksClient = ctx.obj
|
|
758
|
+
try:
|
|
759
|
+
data = client.polymarket_clob_batch_prices(token_ids, side)
|
|
760
|
+
emit(ctx, data)
|
|
761
|
+
except Exception as e:
|
|
762
|
+
emit_error(ctx, str(e))
|
|
763
|
+
ctx.exit(1)
|
|
764
|
+
|
|
765
|
+
|
|
766
|
+
@pm_clob.command("midpoints")
|
|
767
|
+
@click.argument("token_ids", metavar="TOKEN_IDS")
|
|
768
|
+
@click.pass_context
|
|
769
|
+
def pm_clob_midpoints(ctx, token_ids):
|
|
770
|
+
"""Get midpoints for multiple tokens (comma-separated).
|
|
771
|
+
|
|
772
|
+
Example: fastbooks polymarket clob midpoints "TOKEN1,TOKEN2"
|
|
773
|
+
"""
|
|
774
|
+
client: FastBooksClient = ctx.obj
|
|
775
|
+
try:
|
|
776
|
+
data = client.polymarket_clob_midpoints(token_ids)
|
|
777
|
+
emit(ctx, data)
|
|
778
|
+
except Exception as e:
|
|
779
|
+
emit_error(ctx, str(e))
|
|
780
|
+
ctx.exit(1)
|
|
781
|
+
|
|
782
|
+
|
|
783
|
+
@pm_clob.command("spreads")
|
|
784
|
+
@click.argument("token_ids", metavar="TOKEN_IDS")
|
|
785
|
+
@click.pass_context
|
|
786
|
+
def pm_clob_spreads(ctx, token_ids):
|
|
787
|
+
"""Get spreads for multiple tokens (comma-separated).
|
|
788
|
+
|
|
789
|
+
Example: fastbooks polymarket clob spreads "TOKEN1,TOKEN2"
|
|
790
|
+
"""
|
|
791
|
+
client: FastBooksClient = ctx.obj
|
|
792
|
+
try:
|
|
793
|
+
data = client.polymarket_clob_spreads(token_ids)
|
|
794
|
+
emit(ctx, data)
|
|
795
|
+
except Exception as e:
|
|
796
|
+
emit_error(ctx, str(e))
|
|
797
|
+
ctx.exit(1)
|
|
798
|
+
|
|
799
|
+
|
|
800
|
+
@pm_clob.command("last-trades")
|
|
801
|
+
@click.argument("token_ids", metavar="TOKEN_IDS")
|
|
802
|
+
@click.pass_context
|
|
803
|
+
def pm_clob_last_trades(ctx, token_ids):
|
|
804
|
+
"""Get last trades for multiple tokens (comma-separated).
|
|
805
|
+
|
|
806
|
+
Example: fastbooks polymarket clob last-trades "TOKEN1,TOKEN2"
|
|
807
|
+
"""
|
|
808
|
+
client: FastBooksClient = ctx.obj
|
|
809
|
+
try:
|
|
810
|
+
data = client.polymarket_clob_last_trades(token_ids)
|
|
811
|
+
emit(ctx, data)
|
|
812
|
+
except Exception as e:
|
|
813
|
+
emit_error(ctx, str(e))
|
|
814
|
+
ctx.exit(1)
|
|
815
|
+
|
|
816
|
+
|
|
817
|
+
@pm_clob.command("tick-size")
|
|
818
|
+
@click.argument("token_id")
|
|
819
|
+
@click.pass_context
|
|
820
|
+
def pm_clob_tick_size(ctx, token_id):
|
|
821
|
+
"""Get tick size for a token.
|
|
822
|
+
|
|
823
|
+
Example: fastbooks polymarket clob tick-size TOKEN_ID
|
|
824
|
+
"""
|
|
825
|
+
client: FastBooksClient = ctx.obj
|
|
826
|
+
try:
|
|
827
|
+
data = client.polymarket_clob_tick_size(token_id)
|
|
828
|
+
emit(ctx, data)
|
|
829
|
+
except Exception as e:
|
|
830
|
+
emit_error(ctx, str(e))
|
|
831
|
+
ctx.exit(1)
|
|
832
|
+
|
|
833
|
+
|
|
834
|
+
@pm_clob.command("fee-rate")
|
|
835
|
+
@click.argument("token_id")
|
|
836
|
+
@click.pass_context
|
|
837
|
+
def pm_clob_fee_rate(ctx, token_id):
|
|
838
|
+
"""Get fee rate (in bps) for a token.
|
|
839
|
+
|
|
840
|
+
Example: fastbooks polymarket clob fee-rate TOKEN_ID
|
|
841
|
+
"""
|
|
842
|
+
client: FastBooksClient = ctx.obj
|
|
843
|
+
try:
|
|
844
|
+
data = client.polymarket_clob_fee_rate(token_id)
|
|
845
|
+
emit(ctx, data)
|
|
846
|
+
except Exception as e:
|
|
847
|
+
emit_error(ctx, str(e))
|
|
848
|
+
ctx.exit(1)
|
|
849
|
+
|
|
850
|
+
|
|
851
|
+
@pm_clob.command("neg-risk")
|
|
852
|
+
@click.argument("token_id")
|
|
853
|
+
@click.pass_context
|
|
854
|
+
def pm_clob_neg_risk(ctx, token_id):
|
|
855
|
+
"""Get negative risk status for a token.
|
|
856
|
+
|
|
857
|
+
Example: fastbooks polymarket clob neg-risk TOKEN_ID
|
|
858
|
+
"""
|
|
859
|
+
client: FastBooksClient = ctx.obj
|
|
860
|
+
try:
|
|
861
|
+
data = client.polymarket_clob_neg_risk(token_id)
|
|
862
|
+
emit(ctx, data)
|
|
863
|
+
except Exception as e:
|
|
864
|
+
emit_error(ctx, str(e))
|
|
865
|
+
ctx.exit(1)
|
|
866
|
+
|
|
867
|
+
|
|
868
|
+
@pm_clob.command("time")
|
|
869
|
+
@click.pass_context
|
|
870
|
+
def pm_clob_time(ctx):
|
|
871
|
+
"""Get CLOB server time.
|
|
872
|
+
|
|
873
|
+
Example: fastbooks polymarket clob time
|
|
874
|
+
"""
|
|
875
|
+
client: FastBooksClient = ctx.obj
|
|
876
|
+
try:
|
|
877
|
+
data = client.polymarket_clob_time()
|
|
878
|
+
emit(ctx, data)
|
|
879
|
+
except Exception as e:
|
|
880
|
+
emit_error(ctx, str(e))
|
|
881
|
+
ctx.exit(1)
|
|
882
|
+
|
|
883
|
+
|
|
884
|
+
@pm_clob.command("geoblock")
|
|
885
|
+
@click.pass_context
|
|
886
|
+
def pm_clob_geoblock(ctx):
|
|
887
|
+
"""Check geoblock status.
|
|
888
|
+
|
|
889
|
+
Example: fastbooks polymarket clob geoblock
|
|
890
|
+
"""
|
|
891
|
+
client: FastBooksClient = ctx.obj
|
|
892
|
+
try:
|
|
893
|
+
data = client.polymarket_clob_geoblock()
|
|
894
|
+
emit(ctx, data)
|
|
895
|
+
except Exception as e:
|
|
896
|
+
emit_error(ctx, str(e))
|
|
897
|
+
ctx.exit(1)
|
|
898
|
+
|
|
899
|
+
|
|
900
|
+
# ── CLOB trading (authenticated) ─────────────────────────────────────
|
|
901
|
+
|
|
902
|
+
@pm_clob.command("create-order")
|
|
903
|
+
@click.option("--token", required=True, help="Token ID to trade.")
|
|
904
|
+
@click.option("--side", type=click.Choice(["buy", "sell"]), required=True)
|
|
905
|
+
@click.option("--price", type=float, required=True, help="Limit price (0-1).")
|
|
906
|
+
@click.option("--size", type=float, required=True, help="Number of shares.")
|
|
907
|
+
@click.option("--order-type", type=click.Choice(["GTC", "FOK", "GTD", "FAK"]), default="GTC")
|
|
908
|
+
@click.option("--private-key", envvar="POLYMARKET_PRIVATE_KEY", default=None)
|
|
909
|
+
@click.option("--confirm/--no-confirm", default=True)
|
|
910
|
+
@click.pass_context
|
|
911
|
+
def pm_clob_create_order(ctx, token, side, price, size, order_type, private_key, confirm):
|
|
912
|
+
"""Place a limit order on Polymarket.
|
|
913
|
+
|
|
914
|
+
Examples:
|
|
915
|
+
fastbooks polymarket clob create-order --token TOKEN --side buy --price 0.50 --size 10
|
|
916
|
+
fastbooks polymarket clob create-order --token TOKEN --side sell --price 0.80 --size 5 --order-type FOK
|
|
917
|
+
"""
|
|
918
|
+
client: FastBooksClient = ctx.obj
|
|
919
|
+
if not private_key:
|
|
920
|
+
emit_error(ctx, "Wallet required. Use --private-key or set POLYMARKET_PRIVATE_KEY.")
|
|
921
|
+
ctx.exit(1)
|
|
922
|
+
return
|
|
923
|
+
|
|
924
|
+
if confirm and not ctx.find_root().params.get("json_output", False):
|
|
925
|
+
click.echo(f"\n Polymarket LIMIT {side.upper()} {size} shares @ ${price:.2f} ({order_type})")
|
|
926
|
+
click.echo(f" Token: {token[:20]}...")
|
|
927
|
+
if not click.confirm("\n Execute?"):
|
|
928
|
+
click.echo(" Cancelled.")
|
|
929
|
+
return
|
|
930
|
+
|
|
931
|
+
try:
|
|
932
|
+
data = client.polymarket_create_order(
|
|
933
|
+
token_id=token, side=side, price=price, size=size,
|
|
934
|
+
order_type=order_type, private_key=private_key,
|
|
935
|
+
)
|
|
936
|
+
emit(ctx, data, lambda d: _format_order_result(d))
|
|
937
|
+
except Exception as e:
|
|
938
|
+
emit_error(ctx, str(e))
|
|
939
|
+
ctx.exit(1)
|
|
940
|
+
|
|
941
|
+
|
|
942
|
+
@pm_clob.command("market-order")
|
|
943
|
+
@click.option("--token", required=True, help="Token ID to trade.")
|
|
944
|
+
@click.option("--side", type=click.Choice(["buy", "sell"]), required=True)
|
|
945
|
+
@click.option("--amount", type=float, required=True, help="Amount in USD to spend.")
|
|
946
|
+
@click.option("--private-key", envvar="POLYMARKET_PRIVATE_KEY", default=None)
|
|
947
|
+
@click.option("--confirm/--no-confirm", default=True)
|
|
948
|
+
@click.pass_context
|
|
949
|
+
def pm_clob_market_order(ctx, token, side, amount, private_key, confirm):
|
|
950
|
+
"""Place a market order on Polymarket.
|
|
951
|
+
|
|
952
|
+
Examples:
|
|
953
|
+
fastbooks polymarket clob market-order --token TOKEN --side buy --amount 5
|
|
954
|
+
fastbooks polymarket clob market-order --token TOKEN --side sell --amount 10
|
|
955
|
+
"""
|
|
956
|
+
client: FastBooksClient = ctx.obj
|
|
957
|
+
if not private_key:
|
|
958
|
+
emit_error(ctx, "Wallet required. Use --private-key or set POLYMARKET_PRIVATE_KEY.")
|
|
959
|
+
ctx.exit(1)
|
|
960
|
+
return
|
|
961
|
+
|
|
962
|
+
if confirm and not ctx.find_root().params.get("json_output", False):
|
|
963
|
+
click.echo(f"\n Polymarket MARKET {side.upper()} ${amount:.2f}")
|
|
964
|
+
click.echo(f" Token: {token[:20]}...")
|
|
965
|
+
if not click.confirm("\n Execute?"):
|
|
966
|
+
click.echo(" Cancelled.")
|
|
967
|
+
return
|
|
968
|
+
|
|
969
|
+
try:
|
|
970
|
+
data = client.polymarket_market_order(
|
|
971
|
+
token_id=token, side=side, amount=amount, private_key=private_key,
|
|
972
|
+
)
|
|
973
|
+
emit(ctx, data, lambda d: _format_order_result(d))
|
|
974
|
+
except Exception as e:
|
|
975
|
+
emit_error(ctx, str(e))
|
|
976
|
+
ctx.exit(1)
|
|
977
|
+
|
|
978
|
+
|
|
979
|
+
@pm_clob.command("cancel")
|
|
980
|
+
@click.argument("order_id")
|
|
981
|
+
@click.option("--private-key", envvar="POLYMARKET_PRIVATE_KEY", default=None)
|
|
982
|
+
@click.pass_context
|
|
983
|
+
def pm_clob_cancel(ctx, order_id, private_key):
|
|
984
|
+
"""Cancel a specific order.
|
|
985
|
+
|
|
986
|
+
Example: fastbooks polymarket clob cancel ORDER_ID
|
|
987
|
+
"""
|
|
988
|
+
client: FastBooksClient = ctx.obj
|
|
989
|
+
if not private_key:
|
|
990
|
+
emit_error(ctx, "Wallet required.")
|
|
991
|
+
ctx.exit(1)
|
|
992
|
+
return
|
|
993
|
+
try:
|
|
994
|
+
data = client.polymarket_cancel_order(order_id, private_key)
|
|
995
|
+
emit(ctx, data, lambda d: f" Order {order_id} cancelled.")
|
|
996
|
+
except Exception as e:
|
|
997
|
+
emit_error(ctx, str(e))
|
|
998
|
+
ctx.exit(1)
|
|
999
|
+
|
|
1000
|
+
|
|
1001
|
+
@pm_clob.command("cancel-all")
|
|
1002
|
+
@click.option("--private-key", envvar="POLYMARKET_PRIVATE_KEY", default=None)
|
|
1003
|
+
@click.option("--confirm/--no-confirm", default=True)
|
|
1004
|
+
@click.pass_context
|
|
1005
|
+
def pm_clob_cancel_all(ctx, private_key, confirm):
|
|
1006
|
+
"""Cancel all open orders.
|
|
1007
|
+
|
|
1008
|
+
Example: fastbooks polymarket clob cancel-all
|
|
1009
|
+
"""
|
|
1010
|
+
client: FastBooksClient = ctx.obj
|
|
1011
|
+
if not private_key:
|
|
1012
|
+
emit_error(ctx, "Wallet required.")
|
|
1013
|
+
ctx.exit(1)
|
|
1014
|
+
return
|
|
1015
|
+
if confirm and not ctx.find_root().params.get("json_output", False):
|
|
1016
|
+
if not click.confirm(" Cancel ALL open orders?"):
|
|
1017
|
+
click.echo(" Cancelled.")
|
|
1018
|
+
return
|
|
1019
|
+
try:
|
|
1020
|
+
data = client.polymarket_cancel_all(private_key)
|
|
1021
|
+
emit(ctx, data, lambda d: " All orders cancelled.")
|
|
1022
|
+
except Exception as e:
|
|
1023
|
+
emit_error(ctx, str(e))
|
|
1024
|
+
ctx.exit(1)
|
|
1025
|
+
|
|
1026
|
+
|
|
1027
|
+
@pm_clob.command("cancel-market")
|
|
1028
|
+
@click.argument("condition_id")
|
|
1029
|
+
@click.option("--private-key", envvar="POLYMARKET_PRIVATE_KEY", default=None)
|
|
1030
|
+
@click.pass_context
|
|
1031
|
+
def pm_clob_cancel_market(ctx, condition_id, private_key):
|
|
1032
|
+
"""Cancel all orders for a specific market.
|
|
1033
|
+
|
|
1034
|
+
Example: fastbooks polymarket clob cancel-market 0xCONDITION...
|
|
1035
|
+
"""
|
|
1036
|
+
client: FastBooksClient = ctx.obj
|
|
1037
|
+
if not private_key:
|
|
1038
|
+
emit_error(ctx, "Wallet required.")
|
|
1039
|
+
ctx.exit(1)
|
|
1040
|
+
return
|
|
1041
|
+
try:
|
|
1042
|
+
data = client.polymarket_cancel_market(condition_id, private_key)
|
|
1043
|
+
emit(ctx, data, lambda d: f" Orders for market {condition_id[:16]}... cancelled.")
|
|
1044
|
+
except Exception as e:
|
|
1045
|
+
emit_error(ctx, str(e))
|
|
1046
|
+
ctx.exit(1)
|
|
1047
|
+
|
|
1048
|
+
|
|
1049
|
+
@pm_clob.command("cancel-orders")
|
|
1050
|
+
@click.argument("order_ids", metavar="ORDER_IDS")
|
|
1051
|
+
@click.option("--private-key", envvar="POLYMARKET_PRIVATE_KEY", default=None)
|
|
1052
|
+
@click.pass_context
|
|
1053
|
+
def pm_clob_cancel_orders(ctx, order_ids, private_key):
|
|
1054
|
+
"""Cancel multiple orders (comma-separated IDs).
|
|
1055
|
+
|
|
1056
|
+
Example: fastbooks polymarket clob cancel-orders "ORDER1,ORDER2"
|
|
1057
|
+
"""
|
|
1058
|
+
client: FastBooksClient = ctx.obj
|
|
1059
|
+
if not private_key:
|
|
1060
|
+
emit_error(ctx, "Wallet required.")
|
|
1061
|
+
ctx.exit(1)
|
|
1062
|
+
return
|
|
1063
|
+
try:
|
|
1064
|
+
data = client.polymarket_cancel_orders(order_ids, private_key)
|
|
1065
|
+
emit(ctx, data, lambda d: f" Orders cancelled.")
|
|
1066
|
+
except Exception as e:
|
|
1067
|
+
emit_error(ctx, str(e))
|
|
1068
|
+
ctx.exit(1)
|
|
1069
|
+
|
|
1070
|
+
|
|
1071
|
+
@pm_clob.command("post-orders")
|
|
1072
|
+
@click.option("--tokens", required=True, help="Token IDs (comma-separated).")
|
|
1073
|
+
@click.option("--side", type=click.Choice(["buy", "sell"]), required=True)
|
|
1074
|
+
@click.option("--prices", required=True, help="Prices (comma-separated).")
|
|
1075
|
+
@click.option("--sizes", required=True, help="Sizes (comma-separated).")
|
|
1076
|
+
@click.option("--order-type", type=click.Choice(["GTC", "FOK", "GTD", "FAK"]), default="GTC")
|
|
1077
|
+
@click.option("--private-key", envvar="POLYMARKET_PRIVATE_KEY", default=None)
|
|
1078
|
+
@click.option("--confirm/--no-confirm", default=True)
|
|
1079
|
+
@click.pass_context
|
|
1080
|
+
def pm_clob_post_orders(ctx, tokens, side, prices, sizes, order_type, private_key, confirm):
|
|
1081
|
+
"""Post multiple orders at once.
|
|
1082
|
+
|
|
1083
|
+
Example: fastbooks polymarket clob post-orders --tokens "T1,T2" --side buy --prices "0.40,0.60" --sizes "10,10"
|
|
1084
|
+
"""
|
|
1085
|
+
client: FastBooksClient = ctx.obj
|
|
1086
|
+
if not private_key:
|
|
1087
|
+
emit_error(ctx, "Wallet required.")
|
|
1088
|
+
ctx.exit(1)
|
|
1089
|
+
return
|
|
1090
|
+
if confirm and not ctx.find_root().params.get("json_output", False):
|
|
1091
|
+
click.echo(f"\n Polymarket BATCH {side.upper()} ({order_type})")
|
|
1092
|
+
click.echo(f" Tokens: {tokens}")
|
|
1093
|
+
click.echo(f" Prices: {prices}")
|
|
1094
|
+
click.echo(f" Sizes: {sizes}")
|
|
1095
|
+
if not click.confirm("\n Execute all?"):
|
|
1096
|
+
click.echo(" Cancelled.")
|
|
1097
|
+
return
|
|
1098
|
+
try:
|
|
1099
|
+
data = client.polymarket_post_orders(tokens, side, prices, sizes, order_type, private_key)
|
|
1100
|
+
emit(ctx, data)
|
|
1101
|
+
except Exception as e:
|
|
1102
|
+
emit_error(ctx, str(e))
|
|
1103
|
+
ctx.exit(1)
|
|
1104
|
+
|
|
1105
|
+
|
|
1106
|
+
# ── CLOB account queries (authenticated) ─────────────────────────────
|
|
1107
|
+
|
|
1108
|
+
@pm_clob.command("orders")
|
|
1109
|
+
@click.option("--market", type=str, default=None, help="Filter by condition ID.")
|
|
1110
|
+
@click.option("--private-key", envvar="POLYMARKET_PRIVATE_KEY", default=None)
|
|
1111
|
+
@click.pass_context
|
|
1112
|
+
def pm_clob_orders(ctx, market, private_key):
|
|
1113
|
+
"""List your open orders.
|
|
1114
|
+
|
|
1115
|
+
Examples:
|
|
1116
|
+
fastbooks polymarket clob orders
|
|
1117
|
+
fastbooks polymarket clob orders --market 0xCONDITION...
|
|
1118
|
+
"""
|
|
1119
|
+
client: FastBooksClient = ctx.obj
|
|
1120
|
+
if not private_key:
|
|
1121
|
+
emit_error(ctx, "Wallet required.")
|
|
1122
|
+
ctx.exit(1)
|
|
1123
|
+
return
|
|
1124
|
+
try:
|
|
1125
|
+
data = client.polymarket_orders(market, private_key)
|
|
1126
|
+
emit(ctx, data, lambda d: _format_orders_list(d))
|
|
1127
|
+
except Exception as e:
|
|
1128
|
+
emit_error(ctx, str(e))
|
|
1129
|
+
ctx.exit(1)
|
|
1130
|
+
|
|
1131
|
+
|
|
1132
|
+
@pm_clob.command("trades")
|
|
1133
|
+
@click.option("--private-key", envvar="POLYMARKET_PRIVATE_KEY", default=None)
|
|
1134
|
+
@click.pass_context
|
|
1135
|
+
def pm_clob_trades(ctx, private_key):
|
|
1136
|
+
"""List your recent trades.
|
|
1137
|
+
|
|
1138
|
+
Example: fastbooks polymarket clob trades
|
|
1139
|
+
"""
|
|
1140
|
+
client: FastBooksClient = ctx.obj
|
|
1141
|
+
if not private_key:
|
|
1142
|
+
emit_error(ctx, "Wallet required.")
|
|
1143
|
+
ctx.exit(1)
|
|
1144
|
+
return
|
|
1145
|
+
try:
|
|
1146
|
+
data = client.polymarket_trades(private_key)
|
|
1147
|
+
emit(ctx, data, lambda d: _format_trades_list(d))
|
|
1148
|
+
except Exception as e:
|
|
1149
|
+
emit_error(ctx, str(e))
|
|
1150
|
+
ctx.exit(1)
|
|
1151
|
+
|
|
1152
|
+
|
|
1153
|
+
@pm_clob.command("balance")
|
|
1154
|
+
@click.option("--asset-type", type=click.Choice(["collateral", "conditional"]), default="collateral")
|
|
1155
|
+
@click.option("--token", type=str, default=None, help="Token ID (for conditional balance).")
|
|
1156
|
+
@click.option("--private-key", envvar="POLYMARKET_PRIVATE_KEY", default=None)
|
|
1157
|
+
@click.pass_context
|
|
1158
|
+
def pm_clob_balance(ctx, asset_type, token, private_key):
|
|
1159
|
+
"""Check your Polymarket balance.
|
|
1160
|
+
|
|
1161
|
+
Examples:
|
|
1162
|
+
fastbooks polymarket clob balance --asset-type collateral
|
|
1163
|
+
fastbooks polymarket clob balance --asset-type conditional --token TOKEN_ID
|
|
1164
|
+
"""
|
|
1165
|
+
client: FastBooksClient = ctx.obj
|
|
1166
|
+
if not private_key:
|
|
1167
|
+
emit_error(ctx, "Wallet required.")
|
|
1168
|
+
ctx.exit(1)
|
|
1169
|
+
return
|
|
1170
|
+
try:
|
|
1171
|
+
data = client.polymarket_balance(asset_type, token, private_key)
|
|
1172
|
+
emit(ctx, data, lambda d: _format_balance(d))
|
|
1173
|
+
except Exception as e:
|
|
1174
|
+
emit_error(ctx, str(e))
|
|
1175
|
+
ctx.exit(1)
|
|
1176
|
+
|
|
1177
|
+
|
|
1178
|
+
@pm_clob.command("order")
|
|
1179
|
+
@click.argument("order_id")
|
|
1180
|
+
@click.option("--private-key", envvar="POLYMARKET_PRIVATE_KEY", default=None)
|
|
1181
|
+
@click.pass_context
|
|
1182
|
+
def pm_clob_order_get(ctx, order_id, private_key):
|
|
1183
|
+
"""Get a single order by ID.
|
|
1184
|
+
|
|
1185
|
+
Example: fastbooks polymarket clob order ORDER_ID
|
|
1186
|
+
"""
|
|
1187
|
+
client: FastBooksClient = ctx.obj
|
|
1188
|
+
if not private_key:
|
|
1189
|
+
emit_error(ctx, "Wallet required.")
|
|
1190
|
+
ctx.exit(1)
|
|
1191
|
+
return
|
|
1192
|
+
try:
|
|
1193
|
+
data = client.polymarket_order_get(order_id, private_key)
|
|
1194
|
+
emit(ctx, data, lambda d: _format_order_result(d))
|
|
1195
|
+
except Exception as e:
|
|
1196
|
+
emit_error(ctx, str(e))
|
|
1197
|
+
ctx.exit(1)
|
|
1198
|
+
|
|
1199
|
+
|
|
1200
|
+
@pm_clob.command("update-balance")
|
|
1201
|
+
@click.option("--asset-type", type=click.Choice(["collateral", "conditional"]), default="collateral")
|
|
1202
|
+
@click.option("--token", type=str, default=None, help="Token ID (for conditional).")
|
|
1203
|
+
@click.option("--private-key", envvar="POLYMARKET_PRIVATE_KEY", default=None)
|
|
1204
|
+
@click.pass_context
|
|
1205
|
+
def pm_clob_update_balance(ctx, asset_type, token, private_key):
|
|
1206
|
+
"""Refresh balance from on-chain.
|
|
1207
|
+
|
|
1208
|
+
Example: fastbooks polymarket clob update-balance --asset-type collateral
|
|
1209
|
+
"""
|
|
1210
|
+
client: FastBooksClient = ctx.obj
|
|
1211
|
+
if not private_key:
|
|
1212
|
+
emit_error(ctx, "Wallet required.")
|
|
1213
|
+
ctx.exit(1)
|
|
1214
|
+
return
|
|
1215
|
+
try:
|
|
1216
|
+
data = client.polymarket_update_balance(asset_type, token, private_key)
|
|
1217
|
+
emit(ctx, data)
|
|
1218
|
+
except Exception as e:
|
|
1219
|
+
emit_error(ctx, str(e))
|
|
1220
|
+
ctx.exit(1)
|
|
1221
|
+
|
|
1222
|
+
|
|
1223
|
+
# ── CLOB rewards & API keys (authenticated) ──────────────────────────
|
|
1224
|
+
|
|
1225
|
+
@pm_clob.command("rewards")
|
|
1226
|
+
@click.option("--date", required=True, help="Date (YYYY-MM-DD).")
|
|
1227
|
+
@click.option("--private-key", envvar="POLYMARKET_PRIVATE_KEY", default=None)
|
|
1228
|
+
@click.pass_context
|
|
1229
|
+
def pm_clob_rewards(ctx, date, private_key):
|
|
1230
|
+
"""List earnings for a date.
|
|
1231
|
+
|
|
1232
|
+
Example: fastbooks polymarket clob rewards --date 2024-06-15
|
|
1233
|
+
"""
|
|
1234
|
+
client: FastBooksClient = ctx.obj
|
|
1235
|
+
if not private_key:
|
|
1236
|
+
emit_error(ctx, "Wallet required.")
|
|
1237
|
+
ctx.exit(1)
|
|
1238
|
+
return
|
|
1239
|
+
try:
|
|
1240
|
+
data = client.polymarket_rewards(date, private_key)
|
|
1241
|
+
emit(ctx, data)
|
|
1242
|
+
except Exception as e:
|
|
1243
|
+
emit_error(ctx, str(e))
|
|
1244
|
+
ctx.exit(1)
|
|
1245
|
+
|
|
1246
|
+
|
|
1247
|
+
@pm_clob.command("earnings")
|
|
1248
|
+
@click.option("--date", required=True, help="Date (YYYY-MM-DD).")
|
|
1249
|
+
@click.option("--private-key", envvar="POLYMARKET_PRIVATE_KEY", default=None)
|
|
1250
|
+
@click.pass_context
|
|
1251
|
+
def pm_clob_earnings(ctx, date, private_key):
|
|
1252
|
+
"""Get total earnings for a date.
|
|
1253
|
+
|
|
1254
|
+
Example: fastbooks polymarket clob earnings --date 2024-06-15
|
|
1255
|
+
"""
|
|
1256
|
+
client: FastBooksClient = ctx.obj
|
|
1257
|
+
if not private_key:
|
|
1258
|
+
emit_error(ctx, "Wallet required.")
|
|
1259
|
+
ctx.exit(1)
|
|
1260
|
+
return
|
|
1261
|
+
try:
|
|
1262
|
+
data = client.polymarket_earnings(date, private_key)
|
|
1263
|
+
emit(ctx, data)
|
|
1264
|
+
except Exception as e:
|
|
1265
|
+
emit_error(ctx, str(e))
|
|
1266
|
+
ctx.exit(1)
|
|
1267
|
+
|
|
1268
|
+
|
|
1269
|
+
@pm_clob.command("earnings-markets")
|
|
1270
|
+
@click.option("--date", required=True, help="Date (YYYY-MM-DD).")
|
|
1271
|
+
@click.option("--private-key", envvar="POLYMARKET_PRIVATE_KEY", default=None)
|
|
1272
|
+
@click.pass_context
|
|
1273
|
+
def pm_clob_earnings_markets(ctx, date, private_key):
|
|
1274
|
+
"""Get earnings with market configs for a date.
|
|
1275
|
+
|
|
1276
|
+
Example: fastbooks polymarket clob earnings-markets --date 2024-06-15
|
|
1277
|
+
"""
|
|
1278
|
+
client: FastBooksClient = ctx.obj
|
|
1279
|
+
if not private_key:
|
|
1280
|
+
emit_error(ctx, "Wallet required.")
|
|
1281
|
+
ctx.exit(1)
|
|
1282
|
+
return
|
|
1283
|
+
try:
|
|
1284
|
+
data = client.polymarket_earnings_markets(date, private_key)
|
|
1285
|
+
emit(ctx, data)
|
|
1286
|
+
except Exception as e:
|
|
1287
|
+
emit_error(ctx, str(e))
|
|
1288
|
+
ctx.exit(1)
|
|
1289
|
+
|
|
1290
|
+
|
|
1291
|
+
@pm_clob.command("reward-percentages")
|
|
1292
|
+
@click.pass_context
|
|
1293
|
+
def pm_clob_reward_percentages(ctx):
|
|
1294
|
+
"""Get reward percentages.
|
|
1295
|
+
|
|
1296
|
+
Example: fastbooks polymarket clob reward-percentages
|
|
1297
|
+
"""
|
|
1298
|
+
client: FastBooksClient = ctx.obj
|
|
1299
|
+
try:
|
|
1300
|
+
data = client.polymarket_reward_percentages()
|
|
1301
|
+
emit(ctx, data)
|
|
1302
|
+
except Exception as e:
|
|
1303
|
+
emit_error(ctx, str(e))
|
|
1304
|
+
ctx.exit(1)
|
|
1305
|
+
|
|
1306
|
+
|
|
1307
|
+
@pm_clob.command("current-rewards")
|
|
1308
|
+
@click.pass_context
|
|
1309
|
+
def pm_clob_current_rewards(ctx):
|
|
1310
|
+
"""List current reward programs.
|
|
1311
|
+
|
|
1312
|
+
Example: fastbooks polymarket clob current-rewards
|
|
1313
|
+
"""
|
|
1314
|
+
client: FastBooksClient = ctx.obj
|
|
1315
|
+
try:
|
|
1316
|
+
data = client.polymarket_current_rewards()
|
|
1317
|
+
emit(ctx, data)
|
|
1318
|
+
except Exception as e:
|
|
1319
|
+
emit_error(ctx, str(e))
|
|
1320
|
+
ctx.exit(1)
|
|
1321
|
+
|
|
1322
|
+
|
|
1323
|
+
@pm_clob.command("market-reward")
|
|
1324
|
+
@click.argument("condition_id")
|
|
1325
|
+
@click.pass_context
|
|
1326
|
+
def pm_clob_market_reward(ctx, condition_id):
|
|
1327
|
+
"""Get reward details for a market.
|
|
1328
|
+
|
|
1329
|
+
Example: fastbooks polymarket clob market-reward 0xCONDITION...
|
|
1330
|
+
"""
|
|
1331
|
+
client: FastBooksClient = ctx.obj
|
|
1332
|
+
try:
|
|
1333
|
+
data = client.polymarket_market_reward(condition_id)
|
|
1334
|
+
emit(ctx, data)
|
|
1335
|
+
except Exception as e:
|
|
1336
|
+
emit_error(ctx, str(e))
|
|
1337
|
+
ctx.exit(1)
|
|
1338
|
+
|
|
1339
|
+
|
|
1340
|
+
@pm_clob.command("order-scoring")
|
|
1341
|
+
@click.argument("order_id")
|
|
1342
|
+
@click.option("--private-key", envvar="POLYMARKET_PRIVATE_KEY", default=None)
|
|
1343
|
+
@click.pass_context
|
|
1344
|
+
def pm_clob_order_scoring(ctx, order_id, private_key):
|
|
1345
|
+
"""Check if an order is scoring rewards.
|
|
1346
|
+
|
|
1347
|
+
Example: fastbooks polymarket clob order-scoring ORDER_ID
|
|
1348
|
+
"""
|
|
1349
|
+
client: FastBooksClient = ctx.obj
|
|
1350
|
+
try:
|
|
1351
|
+
data = client.polymarket_order_scoring(order_id, private_key)
|
|
1352
|
+
emit(ctx, data)
|
|
1353
|
+
except Exception as e:
|
|
1354
|
+
emit_error(ctx, str(e))
|
|
1355
|
+
ctx.exit(1)
|
|
1356
|
+
|
|
1357
|
+
|
|
1358
|
+
@pm_clob.command("orders-scoring")
|
|
1359
|
+
@click.argument("order_ids", metavar="ORDER_IDS")
|
|
1360
|
+
@click.option("--private-key", envvar="POLYMARKET_PRIVATE_KEY", default=None)
|
|
1361
|
+
@click.pass_context
|
|
1362
|
+
def pm_clob_orders_scoring(ctx, order_ids, private_key):
|
|
1363
|
+
"""Check multiple orders for reward scoring (comma-separated).
|
|
1364
|
+
|
|
1365
|
+
Example: fastbooks polymarket clob orders-scoring "ORDER1,ORDER2"
|
|
1366
|
+
"""
|
|
1367
|
+
client: FastBooksClient = ctx.obj
|
|
1368
|
+
try:
|
|
1369
|
+
data = client.polymarket_orders_scoring(order_ids, private_key)
|
|
1370
|
+
emit(ctx, data)
|
|
1371
|
+
except Exception as e:
|
|
1372
|
+
emit_error(ctx, str(e))
|
|
1373
|
+
ctx.exit(1)
|
|
1374
|
+
|
|
1375
|
+
|
|
1376
|
+
@pm_clob.command("api-keys")
|
|
1377
|
+
@click.option("--private-key", envvar="POLYMARKET_PRIVATE_KEY", default=None)
|
|
1378
|
+
@click.pass_context
|
|
1379
|
+
def pm_clob_api_keys(ctx, private_key):
|
|
1380
|
+
"""List your API keys.
|
|
1381
|
+
|
|
1382
|
+
Example: fastbooks polymarket clob api-keys
|
|
1383
|
+
"""
|
|
1384
|
+
client: FastBooksClient = ctx.obj
|
|
1385
|
+
if not private_key:
|
|
1386
|
+
emit_error(ctx, "Wallet required.")
|
|
1387
|
+
ctx.exit(1)
|
|
1388
|
+
return
|
|
1389
|
+
try:
|
|
1390
|
+
data = client.polymarket_api_keys(private_key)
|
|
1391
|
+
emit(ctx, data)
|
|
1392
|
+
except Exception as e:
|
|
1393
|
+
emit_error(ctx, str(e))
|
|
1394
|
+
ctx.exit(1)
|
|
1395
|
+
|
|
1396
|
+
|
|
1397
|
+
@pm_clob.command("create-api-key")
|
|
1398
|
+
@click.option("--private-key", envvar="POLYMARKET_PRIVATE_KEY", default=None)
|
|
1399
|
+
@click.pass_context
|
|
1400
|
+
def pm_clob_create_api_key(ctx, private_key):
|
|
1401
|
+
"""Create or derive a new API key.
|
|
1402
|
+
|
|
1403
|
+
Example: fastbooks polymarket clob create-api-key
|
|
1404
|
+
"""
|
|
1405
|
+
client: FastBooksClient = ctx.obj
|
|
1406
|
+
if not private_key:
|
|
1407
|
+
emit_error(ctx, "Wallet required.")
|
|
1408
|
+
ctx.exit(1)
|
|
1409
|
+
return
|
|
1410
|
+
try:
|
|
1411
|
+
data = client.polymarket_create_api_key(private_key)
|
|
1412
|
+
emit(ctx, data)
|
|
1413
|
+
except Exception as e:
|
|
1414
|
+
emit_error(ctx, str(e))
|
|
1415
|
+
ctx.exit(1)
|
|
1416
|
+
|
|
1417
|
+
|
|
1418
|
+
@pm_clob.command("delete-api-key")
|
|
1419
|
+
@click.option("--private-key", envvar="POLYMARKET_PRIVATE_KEY", default=None)
|
|
1420
|
+
@click.option("--confirm/--no-confirm", default=True)
|
|
1421
|
+
@click.pass_context
|
|
1422
|
+
def pm_clob_delete_api_key(ctx, private_key, confirm):
|
|
1423
|
+
"""Delete current API key.
|
|
1424
|
+
|
|
1425
|
+
Example: fastbooks polymarket clob delete-api-key
|
|
1426
|
+
"""
|
|
1427
|
+
client: FastBooksClient = ctx.obj
|
|
1428
|
+
if not private_key:
|
|
1429
|
+
emit_error(ctx, "Wallet required.")
|
|
1430
|
+
ctx.exit(1)
|
|
1431
|
+
return
|
|
1432
|
+
if confirm and not ctx.find_root().params.get("json_output", False):
|
|
1433
|
+
if not click.confirm(" Delete API key?"):
|
|
1434
|
+
click.echo(" Cancelled.")
|
|
1435
|
+
return
|
|
1436
|
+
try:
|
|
1437
|
+
data = client.polymarket_delete_api_key(private_key)
|
|
1438
|
+
emit(ctx, data, lambda d: " API key deleted.")
|
|
1439
|
+
except Exception as e:
|
|
1440
|
+
emit_error(ctx, str(e))
|
|
1441
|
+
ctx.exit(1)
|
|
1442
|
+
|
|
1443
|
+
|
|
1444
|
+
@pm_clob.command("account-status")
|
|
1445
|
+
@click.option("--private-key", envvar="POLYMARKET_PRIVATE_KEY", default=None)
|
|
1446
|
+
@click.pass_context
|
|
1447
|
+
def pm_clob_account_status(ctx, private_key):
|
|
1448
|
+
"""Check account status.
|
|
1449
|
+
|
|
1450
|
+
Example: fastbooks polymarket clob account-status
|
|
1451
|
+
"""
|
|
1452
|
+
client: FastBooksClient = ctx.obj
|
|
1453
|
+
if not private_key:
|
|
1454
|
+
emit_error(ctx, "Wallet required.")
|
|
1455
|
+
ctx.exit(1)
|
|
1456
|
+
return
|
|
1457
|
+
try:
|
|
1458
|
+
data = client.polymarket_account_status(private_key)
|
|
1459
|
+
emit(ctx, data)
|
|
1460
|
+
except Exception as e:
|
|
1461
|
+
emit_error(ctx, str(e))
|
|
1462
|
+
ctx.exit(1)
|
|
1463
|
+
|
|
1464
|
+
|
|
1465
|
+
@pm_clob.command("notifications")
|
|
1466
|
+
@click.option("--private-key", envvar="POLYMARKET_PRIVATE_KEY", default=None)
|
|
1467
|
+
@click.pass_context
|
|
1468
|
+
def pm_clob_notifications(ctx, private_key):
|
|
1469
|
+
"""List notifications.
|
|
1470
|
+
|
|
1471
|
+
Example: fastbooks polymarket clob notifications
|
|
1472
|
+
"""
|
|
1473
|
+
client: FastBooksClient = ctx.obj
|
|
1474
|
+
if not private_key:
|
|
1475
|
+
emit_error(ctx, "Wallet required.")
|
|
1476
|
+
ctx.exit(1)
|
|
1477
|
+
return
|
|
1478
|
+
try:
|
|
1479
|
+
data = client.polymarket_notifications(private_key)
|
|
1480
|
+
emit(ctx, data)
|
|
1481
|
+
except Exception as e:
|
|
1482
|
+
emit_error(ctx, str(e))
|
|
1483
|
+
ctx.exit(1)
|
|
1484
|
+
|
|
1485
|
+
|
|
1486
|
+
@pm_clob.command("delete-notifications")
|
|
1487
|
+
@click.argument("notification_ids", metavar="NOTIFICATION_IDS")
|
|
1488
|
+
@click.option("--private-key", envvar="POLYMARKET_PRIVATE_KEY", default=None)
|
|
1489
|
+
@click.pass_context
|
|
1490
|
+
def pm_clob_delete_notifications(ctx, notification_ids, private_key):
|
|
1491
|
+
"""Delete notifications (comma-separated IDs).
|
|
1492
|
+
|
|
1493
|
+
Example: fastbooks polymarket clob delete-notifications "NOTIF1,NOTIF2"
|
|
1494
|
+
"""
|
|
1495
|
+
client: FastBooksClient = ctx.obj
|
|
1496
|
+
if not private_key:
|
|
1497
|
+
emit_error(ctx, "Wallet required.")
|
|
1498
|
+
ctx.exit(1)
|
|
1499
|
+
return
|
|
1500
|
+
try:
|
|
1501
|
+
data = client.polymarket_delete_notifications(notification_ids, private_key)
|
|
1502
|
+
emit(ctx, data, lambda d: " Notifications deleted.")
|
|
1503
|
+
except Exception as e:
|
|
1504
|
+
emit_error(ctx, str(e))
|
|
1505
|
+
ctx.exit(1)
|
|
1506
|
+
|
|
1507
|
+
|
|
1508
|
+
# ══════════════════════════════════════════════════════════════════════════
|
|
1509
|
+
# Data — on-chain portfolio & leaderboards (public, no wallet)
|
|
1510
|
+
# ══════════════════════════════════════════════════════════════════════════
|
|
1511
|
+
|
|
1512
|
+
@polymarket.group("data")
|
|
1513
|
+
def pm_data():
|
|
1514
|
+
"""On-chain data: positions, portfolio value, trades, leaderboards."""
|
|
1515
|
+
pass
|
|
1516
|
+
|
|
1517
|
+
|
|
1518
|
+
@pm_data.command("positions")
|
|
1519
|
+
@click.argument("address")
|
|
1520
|
+
@click.pass_context
|
|
1521
|
+
def pm_data_positions(ctx, address):
|
|
1522
|
+
"""View positions for a wallet address.
|
|
1523
|
+
|
|
1524
|
+
Example: fastbooks polymarket data positions 0xWALLET_ADDRESS
|
|
1525
|
+
"""
|
|
1526
|
+
client: FastBooksClient = ctx.obj
|
|
1527
|
+
try:
|
|
1528
|
+
data = client.polymarket_data_positions(address)
|
|
1529
|
+
emit(ctx, data, lambda d: _format_positions(d))
|
|
1530
|
+
except Exception as e:
|
|
1531
|
+
emit_error(ctx, str(e))
|
|
1532
|
+
ctx.exit(1)
|
|
1533
|
+
|
|
1534
|
+
|
|
1535
|
+
@pm_data.command("value")
|
|
1536
|
+
@click.argument("address")
|
|
1537
|
+
@click.pass_context
|
|
1538
|
+
def pm_data_value(ctx, address):
|
|
1539
|
+
"""Get portfolio value for a wallet address.
|
|
1540
|
+
|
|
1541
|
+
Example: fastbooks polymarket data value 0xWALLET_ADDRESS
|
|
1542
|
+
"""
|
|
1543
|
+
client: FastBooksClient = ctx.obj
|
|
1544
|
+
try:
|
|
1545
|
+
data = client.polymarket_data_value(address)
|
|
1546
|
+
emit(ctx, data)
|
|
1547
|
+
except Exception as e:
|
|
1548
|
+
emit_error(ctx, str(e))
|
|
1549
|
+
ctx.exit(1)
|
|
1550
|
+
|
|
1551
|
+
|
|
1552
|
+
@pm_data.command("trades")
|
|
1553
|
+
@click.argument("address")
|
|
1554
|
+
@click.option("--limit", "-n", type=int, default=50)
|
|
1555
|
+
@click.pass_context
|
|
1556
|
+
def pm_data_trades(ctx, address, limit):
|
|
1557
|
+
"""View trade history for a wallet address.
|
|
1558
|
+
|
|
1559
|
+
Example: fastbooks polymarket data trades 0xWALLET_ADDRESS --limit 20
|
|
1560
|
+
"""
|
|
1561
|
+
client: FastBooksClient = ctx.obj
|
|
1562
|
+
try:
|
|
1563
|
+
data = client.polymarket_data_trades(address, limit)
|
|
1564
|
+
emit(ctx, data, lambda d: _format_trades_list(d))
|
|
1565
|
+
except Exception as e:
|
|
1566
|
+
emit_error(ctx, str(e))
|
|
1567
|
+
ctx.exit(1)
|
|
1568
|
+
|
|
1569
|
+
|
|
1570
|
+
@pm_data.command("leaderboard")
|
|
1571
|
+
@click.option("--period", type=click.Choice(["day", "week", "month", "all"]), default="month")
|
|
1572
|
+
@click.option("--order-by", type=click.Choice(["pnl", "volume", "markets_traded"]), default="pnl")
|
|
1573
|
+
@click.option("--limit", "-n", type=int, default=20)
|
|
1574
|
+
@click.pass_context
|
|
1575
|
+
def pm_data_leaderboard(ctx, period, order_by, limit):
|
|
1576
|
+
"""View the Polymarket leaderboard.
|
|
1577
|
+
|
|
1578
|
+
Examples:
|
|
1579
|
+
fastbooks polymarket data leaderboard --period month --order-by pnl
|
|
1580
|
+
fastbooks polymarket data leaderboard --period week --limit 10
|
|
1581
|
+
"""
|
|
1582
|
+
client: FastBooksClient = ctx.obj
|
|
1583
|
+
try:
|
|
1584
|
+
data = client.polymarket_data_leaderboard(period, order_by, limit)
|
|
1585
|
+
emit(ctx, data, lambda d: _format_leaderboard(d))
|
|
1586
|
+
except Exception as e:
|
|
1587
|
+
emit_error(ctx, str(e))
|
|
1588
|
+
ctx.exit(1)
|
|
1589
|
+
|
|
1590
|
+
|
|
1591
|
+
@pm_data.command("closed-positions")
|
|
1592
|
+
@click.argument("address")
|
|
1593
|
+
@click.option("--limit", "-n", type=int, default=25)
|
|
1594
|
+
@click.option("--offset", type=int, default=0)
|
|
1595
|
+
@click.pass_context
|
|
1596
|
+
def pm_data_closed_positions(ctx, address, limit, offset):
|
|
1597
|
+
"""View closed positions for a wallet.
|
|
1598
|
+
|
|
1599
|
+
Example: fastbooks polymarket data closed-positions 0xWALLET
|
|
1600
|
+
"""
|
|
1601
|
+
client: FastBooksClient = ctx.obj
|
|
1602
|
+
try:
|
|
1603
|
+
data = client.polymarket_data_closed_positions(address, limit, offset)
|
|
1604
|
+
emit(ctx, data, lambda d: _format_positions(d))
|
|
1605
|
+
except Exception as e:
|
|
1606
|
+
emit_error(ctx, str(e))
|
|
1607
|
+
ctx.exit(1)
|
|
1608
|
+
|
|
1609
|
+
|
|
1610
|
+
@pm_data.command("traded")
|
|
1611
|
+
@click.argument("address")
|
|
1612
|
+
@click.pass_context
|
|
1613
|
+
def pm_data_traded(ctx, address):
|
|
1614
|
+
"""Get count of unique markets traded by a wallet.
|
|
1615
|
+
|
|
1616
|
+
Example: fastbooks polymarket data traded 0xWALLET
|
|
1617
|
+
"""
|
|
1618
|
+
client: FastBooksClient = ctx.obj
|
|
1619
|
+
try:
|
|
1620
|
+
data = client.polymarket_data_traded(address)
|
|
1621
|
+
emit(ctx, data)
|
|
1622
|
+
except Exception as e:
|
|
1623
|
+
emit_error(ctx, str(e))
|
|
1624
|
+
ctx.exit(1)
|
|
1625
|
+
|
|
1626
|
+
|
|
1627
|
+
@pm_data.command("activity")
|
|
1628
|
+
@click.argument("address")
|
|
1629
|
+
@click.option("--limit", "-n", type=int, default=25)
|
|
1630
|
+
@click.option("--offset", type=int, default=0)
|
|
1631
|
+
@click.pass_context
|
|
1632
|
+
def pm_data_activity(ctx, address, limit, offset):
|
|
1633
|
+
"""View on-chain activity for a wallet.
|
|
1634
|
+
|
|
1635
|
+
Example: fastbooks polymarket data activity 0xWALLET
|
|
1636
|
+
"""
|
|
1637
|
+
client: FastBooksClient = ctx.obj
|
|
1638
|
+
try:
|
|
1639
|
+
data = client.polymarket_data_activity(address, limit, offset)
|
|
1640
|
+
emit(ctx, data)
|
|
1641
|
+
except Exception as e:
|
|
1642
|
+
emit_error(ctx, str(e))
|
|
1643
|
+
ctx.exit(1)
|
|
1644
|
+
|
|
1645
|
+
|
|
1646
|
+
@pm_data.command("holders")
|
|
1647
|
+
@click.argument("condition_id")
|
|
1648
|
+
@click.option("--limit", "-n", type=int, default=10)
|
|
1649
|
+
@click.pass_context
|
|
1650
|
+
def pm_data_holders(ctx, condition_id, limit):
|
|
1651
|
+
"""Get top token holders for a market.
|
|
1652
|
+
|
|
1653
|
+
Example: fastbooks polymarket data holders 0xCONDITION_ID
|
|
1654
|
+
"""
|
|
1655
|
+
client: FastBooksClient = ctx.obj
|
|
1656
|
+
try:
|
|
1657
|
+
data = client.polymarket_data_holders(condition_id, limit)
|
|
1658
|
+
emit(ctx, data)
|
|
1659
|
+
except Exception as e:
|
|
1660
|
+
emit_error(ctx, str(e))
|
|
1661
|
+
ctx.exit(1)
|
|
1662
|
+
|
|
1663
|
+
|
|
1664
|
+
@pm_data.command("open-interest")
|
|
1665
|
+
@click.argument("condition_id")
|
|
1666
|
+
@click.pass_context
|
|
1667
|
+
def pm_data_open_interest(ctx, condition_id):
|
|
1668
|
+
"""Get open interest for a market.
|
|
1669
|
+
|
|
1670
|
+
Example: fastbooks polymarket data open-interest 0xCONDITION_ID
|
|
1671
|
+
"""
|
|
1672
|
+
client: FastBooksClient = ctx.obj
|
|
1673
|
+
try:
|
|
1674
|
+
data = client.polymarket_data_open_interest(condition_id)
|
|
1675
|
+
emit(ctx, data)
|
|
1676
|
+
except Exception as e:
|
|
1677
|
+
emit_error(ctx, str(e))
|
|
1678
|
+
ctx.exit(1)
|
|
1679
|
+
|
|
1680
|
+
|
|
1681
|
+
@pm_data.command("volume")
|
|
1682
|
+
@click.argument("event_id")
|
|
1683
|
+
@click.pass_context
|
|
1684
|
+
def pm_data_volume(ctx, event_id):
|
|
1685
|
+
"""Get live volume for an event.
|
|
1686
|
+
|
|
1687
|
+
Example: fastbooks polymarket data volume 12345
|
|
1688
|
+
"""
|
|
1689
|
+
client: FastBooksClient = ctx.obj
|
|
1690
|
+
try:
|
|
1691
|
+
data = client.polymarket_data_volume(event_id)
|
|
1692
|
+
emit(ctx, data)
|
|
1693
|
+
except Exception as e:
|
|
1694
|
+
emit_error(ctx, str(e))
|
|
1695
|
+
ctx.exit(1)
|
|
1696
|
+
|
|
1697
|
+
|
|
1698
|
+
@pm_data.command("builder-leaderboard")
|
|
1699
|
+
@click.option("--period", type=click.Choice(["day", "week", "month", "all"]), default="month")
|
|
1700
|
+
@click.option("--limit", "-n", type=int, default=25)
|
|
1701
|
+
@click.option("--offset", type=int, default=0)
|
|
1702
|
+
@click.pass_context
|
|
1703
|
+
def pm_data_builder_leaderboard(ctx, period, limit, offset):
|
|
1704
|
+
"""View builder leaderboard.
|
|
1705
|
+
|
|
1706
|
+
Example: fastbooks polymarket data builder-leaderboard --period week
|
|
1707
|
+
"""
|
|
1708
|
+
client: FastBooksClient = ctx.obj
|
|
1709
|
+
try:
|
|
1710
|
+
data = client.polymarket_data_builder_leaderboard(period, limit, offset)
|
|
1711
|
+
emit(ctx, data)
|
|
1712
|
+
except Exception as e:
|
|
1713
|
+
emit_error(ctx, str(e))
|
|
1714
|
+
ctx.exit(1)
|
|
1715
|
+
|
|
1716
|
+
|
|
1717
|
+
@pm_data.command("builder-volume")
|
|
1718
|
+
@click.option("--period", type=click.Choice(["day", "week", "month", "all"]), default="month")
|
|
1719
|
+
@click.pass_context
|
|
1720
|
+
def pm_data_builder_volume(ctx, period):
|
|
1721
|
+
"""Get builder volume time-series.
|
|
1722
|
+
|
|
1723
|
+
Example: fastbooks polymarket data builder-volume --period month
|
|
1724
|
+
"""
|
|
1725
|
+
client: FastBooksClient = ctx.obj
|
|
1726
|
+
try:
|
|
1727
|
+
data = client.polymarket_data_builder_volume(period)
|
|
1728
|
+
emit(ctx, data)
|
|
1729
|
+
except Exception as e:
|
|
1730
|
+
emit_error(ctx, str(e))
|
|
1731
|
+
ctx.exit(1)
|
|
1732
|
+
|
|
1733
|
+
|
|
1734
|
+
# ══════════════════════════════════════════════════════════════════════════
|
|
1735
|
+
# CTF — Conditional Token Framework (on-chain, authenticated)
|
|
1736
|
+
# ══════════════════════════════════════════════════════════════════════════
|
|
1737
|
+
|
|
1738
|
+
@polymarket.group("ctf")
|
|
1739
|
+
def pm_ctf():
|
|
1740
|
+
"""CTF token operations: split, merge, redeem conditional tokens on-chain.
|
|
1741
|
+
|
|
1742
|
+
Requires MATIC for gas on Polygon. Amounts are in USDC.
|
|
1743
|
+
"""
|
|
1744
|
+
pass
|
|
1745
|
+
|
|
1746
|
+
|
|
1747
|
+
@pm_ctf.command("split")
|
|
1748
|
+
@click.option("--condition", required=True, help="Condition ID.")
|
|
1749
|
+
@click.option("--amount", type=float, required=True, help="Amount in USDC to split.")
|
|
1750
|
+
@click.option("--private-key", envvar="POLYMARKET_PRIVATE_KEY", default=None)
|
|
1751
|
+
@click.option("--confirm/--no-confirm", default=True)
|
|
1752
|
+
@click.pass_context
|
|
1753
|
+
def pm_ctf_split(ctx, condition, amount, private_key, confirm):
|
|
1754
|
+
"""Split USDC into YES/NO conditional tokens.
|
|
1755
|
+
|
|
1756
|
+
Example: fastbooks polymarket ctf split --condition 0xCOND... --amount 10
|
|
1757
|
+
"""
|
|
1758
|
+
client: FastBooksClient = ctx.obj
|
|
1759
|
+
if not private_key:
|
|
1760
|
+
emit_error(ctx, "Wallet required.")
|
|
1761
|
+
ctx.exit(1)
|
|
1762
|
+
return
|
|
1763
|
+
if confirm and not ctx.find_root().params.get("json_output", False):
|
|
1764
|
+
click.echo(f"\n Split ${amount} USDC into YES/NO tokens")
|
|
1765
|
+
click.echo(f" Condition: {condition[:20]}...")
|
|
1766
|
+
if not click.confirm("\n Execute? (requires MATIC for gas)"):
|
|
1767
|
+
click.echo(" Cancelled.")
|
|
1768
|
+
return
|
|
1769
|
+
try:
|
|
1770
|
+
data = client.polymarket_ctf_split(condition, amount, private_key)
|
|
1771
|
+
emit(ctx, data, lambda d: f" Split complete. Tx: {d.get('txHash', '?')}")
|
|
1772
|
+
except Exception as e:
|
|
1773
|
+
emit_error(ctx, str(e))
|
|
1774
|
+
ctx.exit(1)
|
|
1775
|
+
|
|
1776
|
+
|
|
1777
|
+
@pm_ctf.command("merge")
|
|
1778
|
+
@click.option("--condition", required=True, help="Condition ID.")
|
|
1779
|
+
@click.option("--amount", type=float, required=True, help="Amount to merge back to USDC.")
|
|
1780
|
+
@click.option("--private-key", envvar="POLYMARKET_PRIVATE_KEY", default=None)
|
|
1781
|
+
@click.option("--confirm/--no-confirm", default=True)
|
|
1782
|
+
@click.pass_context
|
|
1783
|
+
def pm_ctf_merge(ctx, condition, amount, private_key, confirm):
|
|
1784
|
+
"""Merge YES/NO tokens back into USDC.
|
|
1785
|
+
|
|
1786
|
+
Example: fastbooks polymarket ctf merge --condition 0xCOND... --amount 10
|
|
1787
|
+
"""
|
|
1788
|
+
client: FastBooksClient = ctx.obj
|
|
1789
|
+
if not private_key:
|
|
1790
|
+
emit_error(ctx, "Wallet required.")
|
|
1791
|
+
ctx.exit(1)
|
|
1792
|
+
return
|
|
1793
|
+
if confirm and not ctx.find_root().params.get("json_output", False):
|
|
1794
|
+
click.echo(f"\n Merge ${amount} YES/NO tokens back to USDC")
|
|
1795
|
+
if not click.confirm("\n Execute?"):
|
|
1796
|
+
click.echo(" Cancelled.")
|
|
1797
|
+
return
|
|
1798
|
+
try:
|
|
1799
|
+
data = client.polymarket_ctf_merge(condition, amount, private_key)
|
|
1800
|
+
emit(ctx, data, lambda d: f" Merge complete. Tx: {d.get('txHash', '?')}")
|
|
1801
|
+
except Exception as e:
|
|
1802
|
+
emit_error(ctx, str(e))
|
|
1803
|
+
ctx.exit(1)
|
|
1804
|
+
|
|
1805
|
+
|
|
1806
|
+
@pm_ctf.command("redeem")
|
|
1807
|
+
@click.option("--condition", required=True, help="Condition ID (resolved market).")
|
|
1808
|
+
@click.option("--private-key", envvar="POLYMARKET_PRIVATE_KEY", default=None)
|
|
1809
|
+
@click.option("--confirm/--no-confirm", default=True)
|
|
1810
|
+
@click.pass_context
|
|
1811
|
+
def pm_ctf_redeem(ctx, condition, private_key, confirm):
|
|
1812
|
+
"""Redeem winning tokens after market resolution.
|
|
1813
|
+
|
|
1814
|
+
Example: fastbooks polymarket ctf redeem --condition 0xCOND...
|
|
1815
|
+
"""
|
|
1816
|
+
client: FastBooksClient = ctx.obj
|
|
1817
|
+
if not private_key:
|
|
1818
|
+
emit_error(ctx, "Wallet required.")
|
|
1819
|
+
ctx.exit(1)
|
|
1820
|
+
return
|
|
1821
|
+
if confirm and not ctx.find_root().params.get("json_output", False):
|
|
1822
|
+
click.echo(f"\n Redeem winning tokens for condition {condition[:20]}...")
|
|
1823
|
+
if not click.confirm("\n Execute?"):
|
|
1824
|
+
click.echo(" Cancelled.")
|
|
1825
|
+
return
|
|
1826
|
+
try:
|
|
1827
|
+
data = client.polymarket_ctf_redeem(condition, private_key)
|
|
1828
|
+
emit(ctx, data, lambda d: f" Redemption complete. Tx: {d.get('txHash', '?')}")
|
|
1829
|
+
except Exception as e:
|
|
1830
|
+
emit_error(ctx, str(e))
|
|
1831
|
+
ctx.exit(1)
|
|
1832
|
+
|
|
1833
|
+
|
|
1834
|
+
@pm_ctf.command("redeem-neg-risk")
|
|
1835
|
+
@click.option("--condition", required=True, help="Condition ID.")
|
|
1836
|
+
@click.option("--amounts", required=True, help="Amounts (comma-separated).")
|
|
1837
|
+
@click.option("--private-key", envvar="POLYMARKET_PRIVATE_KEY", default=None)
|
|
1838
|
+
@click.option("--confirm/--no-confirm", default=True)
|
|
1839
|
+
@click.pass_context
|
|
1840
|
+
def pm_ctf_redeem_neg_risk(ctx, condition, amounts, private_key, confirm):
|
|
1841
|
+
"""Redeem neg-risk positions.
|
|
1842
|
+
|
|
1843
|
+
Example: fastbooks polymarket ctf redeem-neg-risk --condition 0xCOND... --amounts "10,5"
|
|
1844
|
+
"""
|
|
1845
|
+
client: FastBooksClient = ctx.obj
|
|
1846
|
+
if not private_key:
|
|
1847
|
+
emit_error(ctx, "Wallet required.")
|
|
1848
|
+
ctx.exit(1)
|
|
1849
|
+
return
|
|
1850
|
+
if confirm and not ctx.find_root().params.get("json_output", False):
|
|
1851
|
+
click.echo(f"\n Redeem neg-risk for {condition[:20]}... amounts: {amounts}")
|
|
1852
|
+
if not click.confirm("\n Execute?"):
|
|
1853
|
+
click.echo(" Cancelled.")
|
|
1854
|
+
return
|
|
1855
|
+
try:
|
|
1856
|
+
data = client.polymarket_ctf_redeem_neg_risk(condition, amounts, private_key)
|
|
1857
|
+
emit(ctx, data, lambda d: f" Neg-risk redemption complete. Tx: {d.get('txHash', '?')}")
|
|
1858
|
+
except Exception as e:
|
|
1859
|
+
emit_error(ctx, str(e))
|
|
1860
|
+
ctx.exit(1)
|
|
1861
|
+
|
|
1862
|
+
|
|
1863
|
+
@pm_ctf.command("condition-id")
|
|
1864
|
+
@click.option("--oracle", required=True, help="Oracle address.")
|
|
1865
|
+
@click.option("--question", required=True, help="Question ID.")
|
|
1866
|
+
@click.option("--outcomes", required=True, type=int, help="Number of outcomes.")
|
|
1867
|
+
@click.pass_context
|
|
1868
|
+
def pm_ctf_condition_id(ctx, oracle, question, outcomes):
|
|
1869
|
+
"""Calculate condition ID (read-only).
|
|
1870
|
+
|
|
1871
|
+
Example: fastbooks polymarket ctf condition-id --oracle 0xORACLE... --question 0xQUESTION... --outcomes 2
|
|
1872
|
+
"""
|
|
1873
|
+
client: FastBooksClient = ctx.obj
|
|
1874
|
+
try:
|
|
1875
|
+
data = client.polymarket_ctf_condition_id(oracle, question, outcomes)
|
|
1876
|
+
emit(ctx, data)
|
|
1877
|
+
except Exception as e:
|
|
1878
|
+
emit_error(ctx, str(e))
|
|
1879
|
+
ctx.exit(1)
|
|
1880
|
+
|
|
1881
|
+
|
|
1882
|
+
@pm_ctf.command("collection-id")
|
|
1883
|
+
@click.option("--condition", required=True, help="Condition ID.")
|
|
1884
|
+
@click.option("--index-set", required=True, type=int, help="Index set.")
|
|
1885
|
+
@click.option("--parent-collection", default=None, help="Parent collection ID.")
|
|
1886
|
+
@click.pass_context
|
|
1887
|
+
def pm_ctf_collection_id(ctx, condition, index_set, parent_collection):
|
|
1888
|
+
"""Calculate collection ID (read-only).
|
|
1889
|
+
|
|
1890
|
+
Example: fastbooks polymarket ctf collection-id --condition 0xCOND... --index-set 1
|
|
1891
|
+
"""
|
|
1892
|
+
client: FastBooksClient = ctx.obj
|
|
1893
|
+
try:
|
|
1894
|
+
data = client.polymarket_ctf_collection_id(condition, index_set, parent_collection)
|
|
1895
|
+
emit(ctx, data)
|
|
1896
|
+
except Exception as e:
|
|
1897
|
+
emit_error(ctx, str(e))
|
|
1898
|
+
ctx.exit(1)
|
|
1899
|
+
|
|
1900
|
+
|
|
1901
|
+
@pm_ctf.command("position-id")
|
|
1902
|
+
@click.option("--collateral", required=True, help="Collateral address.")
|
|
1903
|
+
@click.option("--collection", required=True, help="Collection ID.")
|
|
1904
|
+
@click.pass_context
|
|
1905
|
+
def pm_ctf_position_id(ctx, collateral, collection):
|
|
1906
|
+
"""Calculate position ID (read-only).
|
|
1907
|
+
|
|
1908
|
+
Example: fastbooks polymarket ctf position-id --collateral 0xUSDC... --collection 0xCOLL...
|
|
1909
|
+
"""
|
|
1910
|
+
client: FastBooksClient = ctx.obj
|
|
1911
|
+
try:
|
|
1912
|
+
data = client.polymarket_ctf_position_id(collateral, collection)
|
|
1913
|
+
emit(ctx, data)
|
|
1914
|
+
except Exception as e:
|
|
1915
|
+
emit_error(ctx, str(e))
|
|
1916
|
+
ctx.exit(1)
|
|
1917
|
+
|
|
1918
|
+
|
|
1919
|
+
# ══════════════════════════════════════════════════════════════════════════
|
|
1920
|
+
# Approve — contract approvals
|
|
1921
|
+
# ══════════════════════════════════════════════════════════════════════════
|
|
1922
|
+
|
|
1923
|
+
@polymarket.group("approve")
|
|
1924
|
+
def pm_approve():
|
|
1925
|
+
"""Manage Polymarket contract approvals (ERC-20 & ERC-1155)."""
|
|
1926
|
+
pass
|
|
1927
|
+
|
|
1928
|
+
|
|
1929
|
+
@pm_approve.command("check")
|
|
1930
|
+
@click.option("--address", type=str, default=None, help="Address to check (defaults to your wallet).")
|
|
1931
|
+
@click.pass_context
|
|
1932
|
+
def pm_approve_check(ctx, address):
|
|
1933
|
+
"""Check current contract approval status.
|
|
1934
|
+
|
|
1935
|
+
Example: fastbooks polymarket approve check
|
|
1936
|
+
"""
|
|
1937
|
+
client: FastBooksClient = ctx.obj
|
|
1938
|
+
try:
|
|
1939
|
+
data = client.polymarket_approve_check(address)
|
|
1940
|
+
emit(ctx, data)
|
|
1941
|
+
except Exception as e:
|
|
1942
|
+
emit_error(ctx, str(e))
|
|
1943
|
+
ctx.exit(1)
|
|
1944
|
+
|
|
1945
|
+
|
|
1946
|
+
@pm_approve.command("set")
|
|
1947
|
+
@click.option("--private-key", envvar="POLYMARKET_PRIVATE_KEY", default=None)
|
|
1948
|
+
@click.option("--confirm/--no-confirm", default=True)
|
|
1949
|
+
@click.pass_context
|
|
1950
|
+
def pm_approve_set(ctx, private_key, confirm):
|
|
1951
|
+
"""Approve all Polymarket contracts (sends on-chain transactions).
|
|
1952
|
+
|
|
1953
|
+
Requires MATIC for gas. Sends 6 approval transactions.
|
|
1954
|
+
|
|
1955
|
+
Example: fastbooks polymarket approve set
|
|
1956
|
+
"""
|
|
1957
|
+
client: FastBooksClient = ctx.obj
|
|
1958
|
+
if not private_key:
|
|
1959
|
+
emit_error(ctx, "Wallet required.")
|
|
1960
|
+
ctx.exit(1)
|
|
1961
|
+
return
|
|
1962
|
+
if confirm and not ctx.find_root().params.get("json_output", False):
|
|
1963
|
+
click.echo("\n This will send 6 approval transactions on Polygon.")
|
|
1964
|
+
click.echo(" Requires MATIC for gas fees.")
|
|
1965
|
+
if not click.confirm("\n Proceed?"):
|
|
1966
|
+
click.echo(" Cancelled.")
|
|
1967
|
+
return
|
|
1968
|
+
try:
|
|
1969
|
+
data = client.polymarket_approve_set(private_key)
|
|
1970
|
+
emit(ctx, data, lambda d: " All contracts approved.")
|
|
1971
|
+
except Exception as e:
|
|
1972
|
+
emit_error(ctx, str(e))
|
|
1973
|
+
ctx.exit(1)
|
|
1974
|
+
|
|
1975
|
+
|
|
1976
|
+
# ══════════════════════════════════════════════════════════════════════════
|
|
1977
|
+
# Bridge — deposit assets from other chains
|
|
1978
|
+
# ══════════════════════════════════════════════════════════════════════════
|
|
1979
|
+
|
|
1980
|
+
@polymarket.group("bridge")
|
|
1981
|
+
def pm_bridge():
|
|
1982
|
+
"""Bridge assets into Polymarket from other chains."""
|
|
1983
|
+
pass
|
|
1984
|
+
|
|
1985
|
+
|
|
1986
|
+
@pm_bridge.command("deposit")
|
|
1987
|
+
@click.argument("address")
|
|
1988
|
+
@click.pass_context
|
|
1989
|
+
def pm_bridge_deposit(ctx, address):
|
|
1990
|
+
"""Get deposit addresses for a wallet (EVM, Solana, Bitcoin).
|
|
1991
|
+
|
|
1992
|
+
Example: fastbooks polymarket bridge deposit 0xWALLET...
|
|
1993
|
+
"""
|
|
1994
|
+
client: FastBooksClient = ctx.obj
|
|
1995
|
+
try:
|
|
1996
|
+
data = client.polymarket_bridge_deposit(address)
|
|
1997
|
+
emit(ctx, data)
|
|
1998
|
+
except Exception as e:
|
|
1999
|
+
emit_error(ctx, str(e))
|
|
2000
|
+
ctx.exit(1)
|
|
2001
|
+
|
|
2002
|
+
|
|
2003
|
+
@pm_bridge.command("supported-assets")
|
|
2004
|
+
@click.pass_context
|
|
2005
|
+
def pm_bridge_supported_assets(ctx):
|
|
2006
|
+
"""List supported chains and tokens for bridging.
|
|
2007
|
+
|
|
2008
|
+
Example: fastbooks polymarket bridge supported-assets
|
|
2009
|
+
"""
|
|
2010
|
+
client: FastBooksClient = ctx.obj
|
|
2011
|
+
try:
|
|
2012
|
+
data = client.polymarket_bridge_supported_assets()
|
|
2013
|
+
emit(ctx, data)
|
|
2014
|
+
except Exception as e:
|
|
2015
|
+
emit_error(ctx, str(e))
|
|
2016
|
+
ctx.exit(1)
|
|
2017
|
+
|
|
2018
|
+
|
|
2019
|
+
@pm_bridge.command("status")
|
|
2020
|
+
@click.argument("deposit_address")
|
|
2021
|
+
@click.pass_context
|
|
2022
|
+
def pm_bridge_status(ctx, deposit_address):
|
|
2023
|
+
"""Check deposit status.
|
|
2024
|
+
|
|
2025
|
+
Example: fastbooks polymarket bridge status 0xDEPOSIT_ADDRESS
|
|
2026
|
+
"""
|
|
2027
|
+
client: FastBooksClient = ctx.obj
|
|
2028
|
+
try:
|
|
2029
|
+
data = client.polymarket_bridge_status(deposit_address)
|
|
2030
|
+
emit(ctx, data)
|
|
2031
|
+
except Exception as e:
|
|
2032
|
+
emit_error(ctx, str(e))
|
|
2033
|
+
ctx.exit(1)
|
|
2034
|
+
|
|
2035
|
+
|
|
2036
|
+
# ══════════════════════════════════════════════════════════════════════════
|
|
2037
|
+
# Formatters
|
|
2038
|
+
# ══════════════════════════════════════════════════════════════════════════
|
|
2039
|
+
|
|
2040
|
+
def _format_markets_list(data) -> str:
|
|
2041
|
+
items = data if isinstance(data, list) else data.get("data", data.get("markets", []))
|
|
2042
|
+
if not isinstance(items, list) or not items:
|
|
2043
|
+
return str(data)
|
|
2044
|
+
return format_table(
|
|
2045
|
+
items[:30],
|
|
2046
|
+
["question", "outcomePrices", "volume", "liquidity", "active"],
|
|
2047
|
+
["Question", "Price (Yes/No)", "Volume", "Liquidity", "Active"],
|
|
2048
|
+
)
|
|
2049
|
+
|
|
2050
|
+
|
|
2051
|
+
def _format_market_detail(data: dict) -> str:
|
|
2052
|
+
d = data.get("data", data)
|
|
2053
|
+
lines = [
|
|
2054
|
+
"",
|
|
2055
|
+
f" {d.get('question', '?')}",
|
|
2056
|
+
f" ──────────────────────────────────",
|
|
2057
|
+
]
|
|
2058
|
+
if d.get("outcomePrices"):
|
|
2059
|
+
prices = d["outcomePrices"]
|
|
2060
|
+
if isinstance(prices, list) and len(prices) >= 2:
|
|
2061
|
+
lines.append(f" Yes: {prices[0]} | No: {prices[1]}")
|
|
2062
|
+
for field in ["volume", "liquidity", "startDate", "endDate", "active", "closed"]:
|
|
2063
|
+
if field in d:
|
|
2064
|
+
lines.append(f" {field.replace('_', ' ').title()}: {d[field]}")
|
|
2065
|
+
if d.get("description"):
|
|
2066
|
+
lines.append(f"\n {d['description'][:200]}")
|
|
2067
|
+
return "\n".join(lines)
|
|
2068
|
+
|
|
2069
|
+
|
|
2070
|
+
def _format_events_list(data) -> str:
|
|
2071
|
+
items = data if isinstance(data, list) else data.get("data", data.get("events", []))
|
|
2072
|
+
if not isinstance(items, list) or not items:
|
|
2073
|
+
return str(data)
|
|
2074
|
+
return format_table(
|
|
2075
|
+
items[:30],
|
|
2076
|
+
["title", "volume", "liquidity", "active", "marketsCount"],
|
|
2077
|
+
["Event", "Volume", "Liquidity", "Active", "Markets"],
|
|
2078
|
+
)
|
|
2079
|
+
|
|
2080
|
+
|
|
2081
|
+
def _format_event_detail(data: dict) -> str:
|
|
2082
|
+
d = data.get("data", data)
|
|
2083
|
+
lines = [
|
|
2084
|
+
"",
|
|
2085
|
+
f" {d.get('title', '?')}",
|
|
2086
|
+
f" ──────────────────────────────────",
|
|
2087
|
+
]
|
|
2088
|
+
for field in ["volume", "liquidity", "active", "closed", "startDate", "endDate"]:
|
|
2089
|
+
if field in d:
|
|
2090
|
+
lines.append(f" {field.title()}: {d[field]}")
|
|
2091
|
+
markets = d.get("markets", [])
|
|
2092
|
+
if markets:
|
|
2093
|
+
lines.append(f"\n Markets ({len(markets)}):")
|
|
2094
|
+
for m in markets[:10]:
|
|
2095
|
+
q = m.get("question", "?")
|
|
2096
|
+
p = m.get("outcomePrices", ["?", "?"])
|
|
2097
|
+
lines.append(f" • {q} [{p[0] if isinstance(p, list) else p}]")
|
|
2098
|
+
return "\n".join(lines)
|
|
2099
|
+
|
|
2100
|
+
|
|
2101
|
+
def _format_clob_book(data: dict) -> str:
|
|
2102
|
+
lines = []
|
|
2103
|
+
ob = data.get("data", data)
|
|
2104
|
+
lines.append("")
|
|
2105
|
+
if ob.get("market"):
|
|
2106
|
+
lines.append(f" Market: {ob['market']}")
|
|
2107
|
+
lines.append("")
|
|
2108
|
+
asks = ob.get("asks", [])[:8]
|
|
2109
|
+
bids = ob.get("bids", [])[:8]
|
|
2110
|
+
lines.append(" ASKS:")
|
|
2111
|
+
for entry in reversed(asks):
|
|
2112
|
+
price = entry.get("price", entry[0] if isinstance(entry, list) else "?")
|
|
2113
|
+
size = entry.get("size", entry[1] if isinstance(entry, list) else "?")
|
|
2114
|
+
lines.append(f" {price:>10} {size:>12}")
|
|
2115
|
+
lines.append(" ─────────────────────────")
|
|
2116
|
+
lines.append(" BIDS:")
|
|
2117
|
+
for entry in bids:
|
|
2118
|
+
price = entry.get("price", entry[0] if isinstance(entry, list) else "?")
|
|
2119
|
+
size = entry.get("size", entry[1] if isinstance(entry, list) else "?")
|
|
2120
|
+
lines.append(f" {price:>10} {size:>12}")
|
|
2121
|
+
return "\n".join(lines)
|
|
2122
|
+
|
|
2123
|
+
|
|
2124
|
+
def _format_price_history(data) -> str:
|
|
2125
|
+
items = data if isinstance(data, list) else data.get("history", data.get("data", []))
|
|
2126
|
+
if not isinstance(items, list) or not items:
|
|
2127
|
+
return str(data)
|
|
2128
|
+
return format_table(
|
|
2129
|
+
items[:30],
|
|
2130
|
+
["t", "p"],
|
|
2131
|
+
["Time", "Price"],
|
|
2132
|
+
)
|
|
2133
|
+
|
|
2134
|
+
|
|
2135
|
+
def _format_order_result(data: dict) -> str:
|
|
2136
|
+
d = data.get("data", data)
|
|
2137
|
+
lines = ["\n Polymarket Order"]
|
|
2138
|
+
if d.get("orderID") or d.get("id"):
|
|
2139
|
+
lines.append(f" ID: {d.get('orderID', d.get('id', '?'))}")
|
|
2140
|
+
if d.get("status"):
|
|
2141
|
+
lines.append(f" Status: {d['status']}")
|
|
2142
|
+
if d.get("side"):
|
|
2143
|
+
lines.append(f" Side: {d['side']}")
|
|
2144
|
+
if d.get("price"):
|
|
2145
|
+
lines.append(f" Price: {d['price']}")
|
|
2146
|
+
if d.get("size") or d.get("original_size"):
|
|
2147
|
+
lines.append(f" Size: {d.get('size', d.get('original_size', '?'))}")
|
|
2148
|
+
return "\n".join(lines)
|
|
2149
|
+
|
|
2150
|
+
|
|
2151
|
+
def _format_orders_list(data) -> str:
|
|
2152
|
+
items = data if isinstance(data, list) else data.get("data", data.get("orders", []))
|
|
2153
|
+
if not isinstance(items, list) or not items:
|
|
2154
|
+
return " No open orders."
|
|
2155
|
+
return format_table(
|
|
2156
|
+
items[:30],
|
|
2157
|
+
["id", "side", "price", "original_size", "size_matched", "status", "market"],
|
|
2158
|
+
["ID", "Side", "Price", "Size", "Filled", "Status", "Market"],
|
|
2159
|
+
)
|
|
2160
|
+
|
|
2161
|
+
|
|
2162
|
+
def _format_trades_list(data) -> str:
|
|
2163
|
+
items = data if isinstance(data, list) else data.get("data", data.get("trades", []))
|
|
2164
|
+
if not isinstance(items, list) or not items:
|
|
2165
|
+
return " No trades."
|
|
2166
|
+
return format_table(
|
|
2167
|
+
items[:30],
|
|
2168
|
+
["id", "side", "price", "size", "market", "timestamp"],
|
|
2169
|
+
["ID", "Side", "Price", "Size", "Market", "Time"],
|
|
2170
|
+
)
|
|
2171
|
+
|
|
2172
|
+
|
|
2173
|
+
def _format_balance(data: dict) -> str:
|
|
2174
|
+
d = data.get("data", data)
|
|
2175
|
+
lines = ["\n Polymarket Balance"]
|
|
2176
|
+
if isinstance(d, dict):
|
|
2177
|
+
for k, v in d.items():
|
|
2178
|
+
lines.append(f" {k}: {v}")
|
|
2179
|
+
else:
|
|
2180
|
+
lines.append(f" {d}")
|
|
2181
|
+
return "\n".join(lines)
|
|
2182
|
+
|
|
2183
|
+
|
|
2184
|
+
def _format_positions(data) -> str:
|
|
2185
|
+
items = data if isinstance(data, list) else data.get("data", data.get("positions", []))
|
|
2186
|
+
if not isinstance(items, list) or not items:
|
|
2187
|
+
return " No positions."
|
|
2188
|
+
return format_table(
|
|
2189
|
+
items[:30],
|
|
2190
|
+
["market", "outcome", "size", "avgPrice", "currentPrice", "pnl"],
|
|
2191
|
+
["Market", "Outcome", "Size", "Avg Price", "Current", "PnL"],
|
|
2192
|
+
)
|
|
2193
|
+
|
|
2194
|
+
|
|
2195
|
+
def _format_leaderboard(data) -> str:
|
|
2196
|
+
items = data if isinstance(data, list) else data.get("data", data.get("leaderboard", []))
|
|
2197
|
+
if not isinstance(items, list) or not items:
|
|
2198
|
+
return " No leaderboard data."
|
|
2199
|
+
return format_table(
|
|
2200
|
+
items[:20],
|
|
2201
|
+
["rank", "address", "pnl", "volume", "marketsTraded"],
|
|
2202
|
+
["Rank", "Address", "PnL", "Volume", "Markets"],
|
|
2203
|
+
)
|
|
2204
|
+
|
|
2205
|
+
|
|
2206
|
+
def _format_wallet_info(data: dict) -> str:
|
|
2207
|
+
d = data.get("data", data)
|
|
2208
|
+
lines = ["\n Polymarket Wallet"]
|
|
2209
|
+
for field in ["address", "proxyAddress", "signatureType", "source", "configPath"]:
|
|
2210
|
+
if field in d:
|
|
2211
|
+
lines.append(f" {field}: {d[field]}")
|
|
2212
|
+
if d.get("privateKey"):
|
|
2213
|
+
key = d["privateKey"]
|
|
2214
|
+
lines.append(f" privateKey: {key[:6]}...{key[-4:]}")
|
|
2215
|
+
return "\n".join(lines)
|