@0xinsider/sdk 0.14.0-bootstrap.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.
@@ -0,0 +1,1652 @@
1
+ /**
2
+ * Standalone 0xinsider API V1 client.
3
+ *
4
+ * Ported from the app's original repo-owned client (`web/src/lib/api-client`,
5
+ * removed in #9060; this package is now the sole client implementation). The
6
+ * `API_CLIENT_OPERATIONS` table below IS the contract surface:
7
+ * `scripts/check-sdk-openapi-drift.mjs` asserts it equals the set of operations
8
+ * with a `200` response in `web/public/api/v1/openapi.json`, so this package
9
+ * cannot silently diverge from the spec. That enforcement used to be a vitest
10
+ * suite, which the repository does not run -- the table shipped three
11
+ * operations short before #9687 replaced it with the runnable script, and
12
+ * #11894 deleted the suite.
13
+ *
14
+ * Differences from the retired app client (intentional):
15
+ * - No `@/lib/api-contracts` import; the operation table is inlined so the
16
+ * package has zero workspace coupling.
17
+ * - Errors throw the typed subclass hierarchy in `errors.ts` (the app client
18
+ * threw a single `OxinsiderApiError`).
19
+ * - Extra typed convenience methods for list/candle/webhook-event/stream
20
+ * surfaces and a typed `Grade` enum.
21
+ */
22
+ import type { OperationBody, OperationData, OperationPath, OperationQuery, OperationResponse, ResponseMeta } from "./schema.js";
23
+ /**
24
+ * The envelope `meta` as THIS client hands it to a caller: everything the
25
+ * contract declares (`ResponseMeta`), plus `etag`.
26
+ *
27
+ * `etag` is a client-side addition, not a contract field. The server sends it
28
+ * as an `ETag` response HEADER and never in the body, so the OpenAPI document
29
+ * is right not to declare it; this client lifts it into `meta` so a caller can
30
+ * echo it on a conditional re-request without reaching for the raw headers
31
+ * (#14278 -- the hand-written `ResponseMeta` carried `etag` inline, which read
32
+ * as though the server sent it).
33
+ */
34
+ export type ClientResponseMeta = ResponseMeta & {
35
+ /** Lifted from the `ETag` response header by this client. */
36
+ etag?: string;
37
+ /**
38
+ * `true` when the response carried `X-Oxi-Sandbox: true`, which every
39
+ * response of the sandbox server does and no production response does.
40
+ * Lifted from the header by this client (#16138); absent otherwise.
41
+ */
42
+ sandbox?: true;
43
+ /**
44
+ * HTTP status of the success response, set by this client (#16137).
45
+ * `201` on `registerAgent`, `202` on a `submitTraderExport` that queued a
46
+ * new job, `200` everywhere else.
47
+ */
48
+ status?: number;
49
+ /** Unknown query names reported by the server in compatibility mode. */
50
+ queryIgnored?: string;
51
+ /** Normalized query names and values the server actually applied. */
52
+ effectiveQuery?: string;
53
+ };
54
+ export type ApiClientMethod = "GET" | "POST" | "PATCH" | "DELETE";
55
+ /** Whether an operation requires the `oxi_sk_*` Bearer key. */
56
+ export type AuthMode = "none" | "bearer";
57
+ /**
58
+ * How an operation carries its success body, which decides the method that
59
+ * can read it (#16137). Before this, every row was assumed to answer the
60
+ * JSON envelope, so `call()` parsed Markdown as JSON and then rejected it as
61
+ * a bad 200.
62
+ *
63
+ * - `envelope` (the default, and every row that omits `kind`): a JSON
64
+ * `{ object, data, meta }` body -> `call()` and `list()`.
65
+ * - `text`: a `text/*` body -> `text()`. The two `context.md` reads.
66
+ * - `jsonrpc`: a JSON-RPC 2.0 response, or an empty `202` for a
67
+ * notification -> `mcp()`. `POST /api/v1/mcp`.
68
+ * - `sse`: an open-ended `text/event-stream` -> `streamFeed()` and the
69
+ * other consumers in `stream.ts`. Buffering one with `call()` or `text()`
70
+ * would never return, so both refuse it.
71
+ *
72
+ * `scripts/check-sdk-openapi-drift.mjs` derives the same kind from each
73
+ * operation's documented success media type and schema and fails on a row
74
+ * that disagrees, so a route that changes shape cannot keep a stale kind.
75
+ */
76
+ export type ResponseKind = "envelope" | "text" | "jsonrpc" | "sse";
77
+ export interface ApiClientOperation {
78
+ readonly method: ApiClientMethod;
79
+ readonly path: string;
80
+ readonly operationId: string;
81
+ readonly auth: AuthMode;
82
+ /** How the success body is carried; absent means `"envelope"`. */
83
+ readonly kind?: ResponseKind;
84
+ }
85
+ /**
86
+ * A published operation whose success is a REDIRECT, so it has no success
87
+ * body and cannot go through `call()` (#16137). Declared here rather than
88
+ * omitted in silence: the drift check requires every redirect-only spec
89
+ * operation to appear in `REDIRECT_OPERATIONS` with the method that follows
90
+ * it, so "the SDK cannot do this" is never the same as "nobody noticed".
91
+ */
92
+ export interface ApiRedirectOperation {
93
+ readonly method: ApiClientMethod;
94
+ readonly path: string;
95
+ readonly operationId: string;
96
+ readonly auth: AuthMode;
97
+ /** The documented redirect status. */
98
+ readonly status: number;
99
+ /** How a caller reaches it through this package. */
100
+ readonly handledBy: string;
101
+ }
102
+ /** A published operation this client deliberately does not wrap. */
103
+ export interface ApiUnsupportedOperation {
104
+ readonly method: ApiClientMethod;
105
+ readonly path: string;
106
+ readonly operationId: string;
107
+ /** Why there is no method, and what to use instead. */
108
+ readonly reason: string;
109
+ }
110
+ /**
111
+ * The full V1 operation table. One row per OpenAPI operation with a
112
+ * documented 2xx, which since #16137 includes the `201`-only
113
+ * `registerAgent`; `kind` says which method reads its body. Kept in lockstep
114
+ * with `web/public/api/v1/openapi.json` by
115
+ * `scripts/check-sdk-openapi-drift.mjs`, which also checks every row's kind
116
+ * against the spec. Do not add a row without a matching spec operation, and
117
+ * do not remove a spec operation without removing its row. A redirect-only
118
+ * operation belongs in `REDIRECT_OPERATIONS` below, not here.
119
+ */
120
+ export declare const API_CLIENT_OPERATIONS: readonly [{
121
+ readonly method: "POST";
122
+ readonly path: "/api/v1/datasets/whale-trades";
123
+ readonly operationId: "submitWhaleDataset";
124
+ readonly auth: "bearer";
125
+ }, {
126
+ readonly method: "GET";
127
+ readonly path: "/api/v1/datasets/whale-trades/{job_id}";
128
+ readonly operationId: "getWhaleDatasetStatus";
129
+ readonly auth: "bearer";
130
+ }, {
131
+ readonly method: "POST";
132
+ readonly path: "/api/v1/datasets/whale-trades/{job_id}/cancel";
133
+ readonly operationId: "cancelWhaleDataset";
134
+ readonly auth: "bearer";
135
+ }, {
136
+ readonly method: "GET";
137
+ readonly path: "/api/v1/me";
138
+ readonly operationId: "getAccountIdentity";
139
+ readonly auth: "bearer";
140
+ }, {
141
+ readonly method: "GET";
142
+ readonly path: "/api/v1";
143
+ readonly operationId: "getApiDiscovery";
144
+ readonly auth: "none";
145
+ }, {
146
+ readonly method: "GET";
147
+ readonly path: "/api/v1/trader/{address}";
148
+ readonly operationId: "getTrader";
149
+ readonly auth: "bearer";
150
+ }, {
151
+ readonly method: "POST";
152
+ readonly path: "/api/v1/traders/batch";
153
+ readonly operationId: "batchGetTraders";
154
+ readonly auth: "bearer";
155
+ }, {
156
+ readonly method: "GET";
157
+ readonly path: "/api/v1/trader/{address}/position-timeline";
158
+ readonly operationId: "getPositionTimeline";
159
+ readonly auth: "bearer";
160
+ }, {
161
+ readonly method: "GET";
162
+ readonly path: "/api/v1/traders/{trader}/position-timeline";
163
+ readonly operationId: "getPositionTimelineById";
164
+ readonly auth: "bearer";
165
+ }, {
166
+ readonly method: "GET";
167
+ readonly path: "/api/v1/positions";
168
+ readonly operationId: "listPositions";
169
+ readonly auth: "bearer";
170
+ }, {
171
+ readonly method: "GET";
172
+ readonly path: "/api/v1/large-positions";
173
+ readonly operationId: "listLargePositions";
174
+ readonly auth: "bearer";
175
+ }, {
176
+ readonly method: "GET";
177
+ readonly path: "/api/v1/trader/{address}/pnl";
178
+ readonly operationId: "getTraderPnl";
179
+ readonly auth: "bearer";
180
+ }, {
181
+ readonly method: "GET";
182
+ readonly path: "/api/v1/trader/{address}/categories";
183
+ readonly operationId: "getTraderCategoryRecords";
184
+ readonly auth: "bearer";
185
+ }, {
186
+ readonly method: "GET";
187
+ readonly path: "/api/v1/trader/{address}/grade-at";
188
+ readonly operationId: "getTraderGradeAt";
189
+ readonly auth: "bearer";
190
+ }, {
191
+ readonly method: "GET";
192
+ readonly path: "/api/v1/trader/{address}/context";
193
+ readonly operationId: "getTraderContext";
194
+ readonly auth: "bearer";
195
+ }, {
196
+ readonly method: "GET";
197
+ readonly path: "/api/v1/trader/{address}/context.md";
198
+ readonly operationId: "getTraderContextMarkdown";
199
+ readonly auth: "bearer";
200
+ readonly kind: "text";
201
+ }, {
202
+ readonly method: "POST";
203
+ readonly path: "/api/v1/trader/{address}/export";
204
+ readonly operationId: "submitTraderExport";
205
+ readonly auth: "bearer";
206
+ }, {
207
+ readonly method: "GET";
208
+ readonly path: "/api/v1/trader/{address}/export/status";
209
+ readonly operationId: "getTraderExportStatus";
210
+ readonly auth: "bearer";
211
+ }, {
212
+ readonly method: "POST";
213
+ readonly path: "/api/v1/trader/{address}/export/cancel";
214
+ readonly operationId: "cancelTraderExport";
215
+ readonly auth: "bearer";
216
+ }, {
217
+ readonly method: "GET";
218
+ readonly path: "/api/v1/leaderboard/trending";
219
+ readonly operationId: "listTrendingWallets";
220
+ readonly auth: "bearer";
221
+ }, {
222
+ readonly method: "GET";
223
+ readonly path: "/api/v1/sports/pre-game-sides";
224
+ readonly operationId: "listPreGameSides";
225
+ readonly auth: "bearer";
226
+ }, {
227
+ readonly method: "GET";
228
+ readonly path: "/api/v1/sports/pre-game-side-observations";
229
+ readonly operationId: "listPreGameSideObservations";
230
+ readonly auth: "bearer";
231
+ }, {
232
+ readonly method: "GET";
233
+ readonly path: "/api/v1/sports-edge-signals";
234
+ readonly operationId: "listSportsEdgeSignals";
235
+ readonly auth: "bearer";
236
+ }, {
237
+ readonly method: "GET";
238
+ readonly path: "/api/v1/sports-edge-observations";
239
+ readonly operationId: "listSportsEdgeObservations";
240
+ readonly auth: "bearer";
241
+ }, {
242
+ readonly method: "GET";
243
+ readonly path: "/api/v1/games";
244
+ readonly operationId: "listGames";
245
+ readonly auth: "bearer";
246
+ }, {
247
+ readonly method: "GET";
248
+ readonly path: "/api/v1/games/{event_slug}";
249
+ readonly operationId: "getGame";
250
+ readonly auth: "bearer";
251
+ }, {
252
+ readonly method: "GET";
253
+ readonly path: "/api/v1/large-trades";
254
+ readonly operationId: "listLargeTrades";
255
+ readonly auth: "bearer";
256
+ }, {
257
+ readonly method: "GET";
258
+ readonly path: "/api/v1/large-trades/history";
259
+ readonly operationId: "listLargeTradeHistory";
260
+ readonly auth: "bearer";
261
+ }, {
262
+ readonly method: "GET";
263
+ readonly path: "/api/v1/large-trades/{id}/counterparties/executions";
264
+ readonly operationId: "listLargeTradeCounterpartyExecutions";
265
+ readonly auth: "bearer";
266
+ }, {
267
+ readonly method: "GET";
268
+ readonly path: "/api/v1/large-trades/{id}/counterparties/executions/{execution_id}/makers";
269
+ readonly operationId: "listLargeTradeCounterpartyMakers";
270
+ readonly auth: "bearer";
271
+ }, {
272
+ readonly method: "GET";
273
+ readonly path: "/api/v1/large-trades/{id}";
274
+ readonly operationId: "getLargeTrade";
275
+ readonly auth: "bearer";
276
+ }, {
277
+ readonly method: "GET";
278
+ readonly path: "/api/v1/whale-trades";
279
+ readonly operationId: "listWhaleTrades";
280
+ readonly auth: "bearer";
281
+ }, {
282
+ readonly method: "GET";
283
+ readonly path: "/api/v1/whale-trades/history";
284
+ readonly operationId: "listWhaleTradeHistory";
285
+ readonly auth: "bearer";
286
+ }, {
287
+ readonly method: "GET";
288
+ readonly path: "/api/v1/whale-trades/{id}/counterparties/executions";
289
+ readonly operationId: "listWhaleTradeCounterpartyExecutions";
290
+ readonly auth: "bearer";
291
+ }, {
292
+ readonly method: "GET";
293
+ readonly path: "/api/v1/whale-trades/{id}/counterparties/executions/{execution_id}/makers";
294
+ readonly operationId: "listWhaleTradeCounterpartyMakers";
295
+ readonly auth: "bearer";
296
+ }, {
297
+ readonly method: "GET";
298
+ readonly path: "/api/v1/content/search";
299
+ readonly operationId: "searchContent";
300
+ readonly auth: "bearer";
301
+ }, {
302
+ readonly method: "GET";
303
+ readonly path: "/api/v1/whale-trades/{id}";
304
+ readonly operationId: "getWhaleTrade";
305
+ readonly auth: "bearer";
306
+ }, {
307
+ readonly method: "GET";
308
+ readonly path: "/api/v1/leaderboard";
309
+ readonly operationId: "listLeaderboard";
310
+ readonly auth: "bearer";
311
+ }, {
312
+ readonly method: "GET";
313
+ readonly path: "/api/v1/markets/search";
314
+ readonly operationId: "searchMarkets";
315
+ readonly auth: "bearer";
316
+ }, {
317
+ readonly method: "GET";
318
+ readonly path: "/api/v1/markets/explore";
319
+ readonly operationId: "exploreMarkets";
320
+ readonly auth: "bearer";
321
+ }, {
322
+ readonly method: "GET";
323
+ readonly path: "/api/v1/markets/smart-money-flows";
324
+ readonly operationId: "listSmartMoneyFlows";
325
+ readonly auth: "bearer";
326
+ }, {
327
+ readonly method: "GET";
328
+ readonly path: "/api/v1/markets/sharp-money-flows";
329
+ readonly operationId: "listSharpMoneyFlows";
330
+ readonly auth: "bearer";
331
+ }, {
332
+ readonly method: "GET";
333
+ readonly path: "/api/v1/coverage";
334
+ readonly operationId: "getCoverage";
335
+ readonly auth: "none";
336
+ }, {
337
+ readonly method: "GET";
338
+ readonly path: "/api/v1/platforms";
339
+ readonly operationId: "getPlatforms";
340
+ readonly auth: "none";
341
+ }, {
342
+ readonly method: "GET";
343
+ readonly path: "/api/v1/market/{condition_id}/holders";
344
+ readonly operationId: "getMarketHolders";
345
+ readonly auth: "bearer";
346
+ }, {
347
+ readonly method: "GET";
348
+ readonly path: "/api/v1/market/{condition_id}/flow";
349
+ readonly operationId: "getMarketFlow";
350
+ readonly auth: "bearer";
351
+ }, {
352
+ readonly method: "GET";
353
+ readonly path: "/api/v1/market/{condition_id}/intel";
354
+ readonly operationId: "getMarketIntel";
355
+ readonly auth: "bearer";
356
+ }, {
357
+ readonly method: "POST";
358
+ readonly path: "/api/v1/markets/flow/batch";
359
+ readonly operationId: "batchGetMarketFlow";
360
+ readonly auth: "bearer";
361
+ }, {
362
+ readonly method: "POST";
363
+ readonly path: "/api/v1/markets/intel/batch";
364
+ readonly operationId: "batchGetMarketIntel";
365
+ readonly auth: "bearer";
366
+ }, {
367
+ readonly method: "GET";
368
+ readonly path: "/api/v1/market/{condition_id}/snapshot";
369
+ readonly operationId: "getMarketSnapshot";
370
+ readonly auth: "bearer";
371
+ }, {
372
+ readonly method: "GET";
373
+ readonly path: "/api/v1/market/{condition_id}/context.md";
374
+ readonly operationId: "getMarketContextMarkdown";
375
+ readonly auth: "bearer";
376
+ readonly kind: "text";
377
+ }, {
378
+ readonly method: "GET";
379
+ readonly path: "/api/v1/market/{condition_id}/candles";
380
+ readonly operationId: "getMarketCandles";
381
+ readonly auth: "bearer";
382
+ }, {
383
+ readonly method: "GET";
384
+ readonly path: "/api/v1/suspicious-trades";
385
+ readonly operationId: "listSuspiciousTrades";
386
+ readonly auth: "bearer";
387
+ }, {
388
+ readonly method: "GET";
389
+ readonly path: "/api/v1/suspicious-trades/{id}";
390
+ readonly operationId: "getSuspiciousTrade";
391
+ readonly auth: "bearer";
392
+ }, {
393
+ readonly method: "GET";
394
+ readonly path: "/api/v1/insider-radar";
395
+ readonly operationId: "listInsiderRadar";
396
+ readonly auth: "bearer";
397
+ }, {
398
+ readonly method: "GET";
399
+ readonly path: "/api/v1/insider-radar/{id}";
400
+ readonly operationId: "getInsiderRadarFlag";
401
+ readonly auth: "bearer";
402
+ }, {
403
+ readonly method: "GET";
404
+ readonly path: "/api/v1/events/feed/since";
405
+ readonly operationId: "getEventReplaySince";
406
+ readonly auth: "bearer";
407
+ }, {
408
+ readonly method: "GET";
409
+ readonly path: "/api/v1/stream";
410
+ readonly operationId: "getStream";
411
+ readonly auth: "bearer";
412
+ readonly kind: "sse";
413
+ }, {
414
+ readonly method: "GET";
415
+ readonly path: "/api/v1/webhooks";
416
+ readonly operationId: "listWebhooks";
417
+ readonly auth: "bearer";
418
+ }, {
419
+ readonly method: "POST";
420
+ readonly path: "/api/v1/webhooks";
421
+ readonly operationId: "createWebhook";
422
+ readonly auth: "bearer";
423
+ }, {
424
+ readonly method: "GET";
425
+ readonly path: "/api/v1/webhooks/{id}";
426
+ readonly operationId: "getWebhook";
427
+ readonly auth: "bearer";
428
+ }, {
429
+ readonly method: "PATCH";
430
+ readonly path: "/api/v1/webhooks/{id}";
431
+ readonly operationId: "updateWebhook";
432
+ readonly auth: "bearer";
433
+ }, {
434
+ readonly method: "DELETE";
435
+ readonly path: "/api/v1/webhooks/{id}";
436
+ readonly operationId: "deleteWebhook";
437
+ readonly auth: "bearer";
438
+ }, {
439
+ readonly method: "POST";
440
+ readonly path: "/api/v1/webhooks/{id}/verify";
441
+ readonly operationId: "verifyWebhook";
442
+ readonly auth: "bearer";
443
+ }, {
444
+ readonly method: "POST";
445
+ readonly path: "/api/v1/webhooks/{id}/rotate-secret";
446
+ readonly operationId: "rotateWebhookSecret";
447
+ readonly auth: "bearer";
448
+ }, {
449
+ readonly method: "POST";
450
+ readonly path: "/api/v1/webhooks/{id}/rotate-secret/prepare";
451
+ readonly operationId: "prepareWebhookSecret";
452
+ readonly auth: "bearer";
453
+ }, {
454
+ readonly method: "POST";
455
+ readonly path: "/api/v1/webhooks/{id}/rotate-secret/activate";
456
+ readonly operationId: "activateWebhookSecret";
457
+ readonly auth: "bearer";
458
+ }, {
459
+ readonly method: "POST";
460
+ readonly path: "/api/v1/webhooks/{id}/rotate-secret/retire";
461
+ readonly operationId: "retireWebhookSecret";
462
+ readonly auth: "bearer";
463
+ }, {
464
+ readonly method: "GET";
465
+ readonly path: "/api/v1/webhooks/events";
466
+ readonly operationId: "listWebhookEvents";
467
+ readonly auth: "bearer";
468
+ }, {
469
+ readonly method: "GET";
470
+ readonly path: "/api/v1/webhooks/{id}/deliveries";
471
+ readonly operationId: "listWebhookDeliveries";
472
+ readonly auth: "bearer";
473
+ }, {
474
+ readonly method: "POST";
475
+ readonly path: "/api/v1/webhooks/{id}/deliveries/{delivery_id}/redeliver";
476
+ readonly operationId: "redeliverWebhookDelivery";
477
+ readonly auth: "bearer";
478
+ }, {
479
+ readonly method: "GET";
480
+ readonly path: "/api/v1/health";
481
+ readonly operationId: "getHealth";
482
+ readonly auth: "none";
483
+ }, {
484
+ readonly method: "POST";
485
+ readonly path: "/api/v1/mcp";
486
+ readonly operationId: "createMcpJsonRpcResponse";
487
+ readonly auth: "bearer";
488
+ readonly kind: "jsonrpc";
489
+ }, {
490
+ readonly method: "GET";
491
+ readonly path: "/api/v1/reports";
492
+ readonly operationId: "getReports";
493
+ readonly auth: "bearer";
494
+ }, {
495
+ readonly method: "GET";
496
+ readonly path: "/api/v1/reports/daily";
497
+ readonly operationId: "getDailyReportSnapshot";
498
+ readonly auth: "bearer";
499
+ }, {
500
+ readonly method: "GET";
501
+ readonly path: "/api/v1/reports/weekly";
502
+ readonly operationId: "getWeeklyReportSnapshot";
503
+ readonly auth: "bearer";
504
+ }, {
505
+ readonly method: "GET";
506
+ readonly path: "/api/v1/reports/monthly";
507
+ readonly operationId: "getMonthlyReportSnapshot";
508
+ readonly auth: "bearer";
509
+ }, {
510
+ readonly method: "GET";
511
+ readonly path: "/api/v1/trader/{address}/export";
512
+ readonly operationId: "getTraderExportSnapshot";
513
+ readonly auth: "bearer";
514
+ }, {
515
+ readonly method: "GET";
516
+ readonly path: "/api/v1/usage";
517
+ readonly operationId: "getUsage";
518
+ readonly auth: "bearer";
519
+ }, {
520
+ readonly method: "GET";
521
+ readonly path: "/api/v1/pick-of-the-day";
522
+ readonly operationId: "getPickOfTheDay";
523
+ readonly auth: "bearer";
524
+ }, {
525
+ readonly method: "GET";
526
+ readonly path: "/api/v1/pick-of-the-day/archive";
527
+ readonly operationId: "getPickOfTheDayArchive";
528
+ readonly auth: "bearer";
529
+ }, {
530
+ readonly method: "GET";
531
+ readonly path: "/api/v1/pick-of-the-day/ledger";
532
+ readonly operationId: "getPickOfTheDayLedger";
533
+ readonly auth: "none";
534
+ }, {
535
+ readonly method: "POST";
536
+ readonly path: "/api/v1/agents/register";
537
+ readonly operationId: "registerAgent";
538
+ readonly auth: "none";
539
+ }];
540
+ export type ApiOperationId = (typeof API_CLIENT_OPERATIONS)[number]["operationId"];
541
+ /** Operations whose success body is a `text/*` document; read with `text()`. */
542
+ export type TextOperationId = Extract<(typeof API_CLIENT_OPERATIONS)[number], {
543
+ kind: "text";
544
+ }>["operationId"];
545
+ /** Operations whose success body is JSON-RPC 2.0; read with `mcp()`. */
546
+ export type JsonRpcOperationId = Extract<(typeof API_CLIENT_OPERATIONS)[number], {
547
+ kind: "jsonrpc";
548
+ }>["operationId"];
549
+ /** Operations whose success body is an open SSE stream; read through `stream.ts`. */
550
+ export type SseOperationId = Extract<(typeof API_CLIENT_OPERATIONS)[number], {
551
+ kind: "sse";
552
+ }>["operationId"];
553
+ /**
554
+ * Published operations whose success is a redirect, with the method that
555
+ * follows it (#16137). These have no 2xx body, so they are absent from
556
+ * `API_CLIENT_OPERATIONS` and from the generated `schema.ts`;
557
+ * `scripts/check-sdk-openapi-drift.mjs` requires every redirect-only spec
558
+ * operation to be declared here, so one cannot go missing in silence again.
559
+ */
560
+ export declare const REDIRECT_OPERATIONS: readonly [{
561
+ readonly method: "GET";
562
+ readonly path: "/api/v1/trader/{address}/export/download";
563
+ readonly operationId: "downloadTraderExport";
564
+ readonly auth: "bearer";
565
+ readonly status: 302;
566
+ readonly handledBy: "getTraderExportDownloadUrl() resolves the Location; downloadTraderExport() then fetches the object with no Authorization header.";
567
+ }, {
568
+ readonly method: "GET";
569
+ readonly path: "/api/v1/datasets/whale-trades/{job_id}/download";
570
+ readonly operationId: "downloadWhaleDataset";
571
+ readonly auth: "bearer";
572
+ readonly status: 302;
573
+ readonly handledBy: "getWhaleDatasetDownloadUrl() resolves Location; fetch it without Authorization and verify the manifest hashes.";
574
+ }, {
575
+ readonly method: "GET";
576
+ readonly path: "/api/v1/openapi.json";
577
+ readonly operationId: "redirectApiOpenapiSpec";
578
+ readonly auth: "none";
579
+ readonly status: 307;
580
+ readonly handledBy: "No method: the document is public and static, so fetch the URL directly and let your runtime follow the redirect. This package ships the same contract as generated types in schema.ts.";
581
+ }];
582
+ /**
583
+ * Published operations this client deliberately does not wrap, with the
584
+ * reason. The drift check requires every remaining spec operation to be
585
+ * accounted for here, so "unsupported" is always a stated decision.
586
+ */
587
+ export declare const UNSUPPORTED_OPERATIONS: readonly [{
588
+ readonly method: "GET";
589
+ readonly path: "/api/v1/mcp";
590
+ readonly operationId: "openMcpEventStream";
591
+ readonly reason: "The MCP endpoint offers no server-to-client stream: GET answers 405 by design, so a client that reconnects to it would loop (#16354). Post JSON-RPC with mcp() instead.";
592
+ }];
593
+ /**
594
+ * The writes the API replays under `Idempotency-Key`: a second request with
595
+ * the same key and the same body returns the first result instead of
596
+ * repeating the write. Source of truth: the operations declaring the
597
+ * `Idempotency-Key` header parameter in `web/public/api/v1/openapi.json`,
598
+ * pinned by `scripts/check-sdk-openapi-drift.mjs` (#16182). Only these are
599
+ * retried on a transport or 5xx failure, and only when a key is set; a key on
600
+ * any other operation is refused before the request, since the server would
601
+ * ignore it and a retry could repeat the side effect (`verifyWebhook` sends
602
+ * a challenge to your URL each time; `submitTraderExport` starts a job).
603
+ */
604
+ export declare const IDEMPOTENT_WRITE_OPERATIONS: readonly ["createWebhook", "updateWebhook", "deleteWebhook", "rotateWebhookSecret", "prepareWebhookSecret", "activateWebhookSecret", "retireWebhookSecret", "redeliverWebhookDelivery"];
605
+ export type IdempotentWriteOperationId = (typeof IDEMPOTENT_WRITE_OPERATIONS)[number];
606
+ /**
607
+ * POST operations that read and never write (#16182): the batch lookups.
608
+ * `POST /api/v1/traders/batch` and `POST /api/v1/markets/flow/batch` (with its
609
+ * deprecated alias `POST /api/v1/markets/intel/batch`) resolve
610
+ * their inputs and store nothing (`backend/src/api_v1/handlers/batch.rs`), so
611
+ * a repeat cannot duplicate a side effect. Each attempt is one request
612
+ * against the account's quota and one reservation of batch item units, which
613
+ * is exactly what a retried GET costs, so they are retried like a GET. Every
614
+ * other POST, PATCH or DELETE is retried only as a keyed write above.
615
+ */
616
+ export declare const READ_ONLY_POST_OPERATIONS: readonly ["batchGetTraders", "batchGetMarketFlow", "batchGetMarketIntel"];
617
+ /**
618
+ * Writes whose repeat converges on the state the first one reached, so a
619
+ * retry cannot repeat a side effect and needs no `Idempotency-Key` (#16254).
620
+ * `POST /api/v1/trader/{address}/export/cancel` moves a job at most once and
621
+ * answers its current state every time: a second cancel of a cancelled job
622
+ * returns it unchanged, and a cancel that lost the race to a finished file
623
+ * returns the ready job. They are retried like a read; the API does not read
624
+ * an `Idempotency-Key` on them, so one is refused like on any other write.
625
+ */
626
+ export declare const CONVERGENT_WRITE_OPERATIONS: readonly ["cancelWhaleDataset", "cancelTraderExport"];
627
+ /**
628
+ * How `call()` may repeat an operation that failed with 429, 502, 503, 504 or
629
+ * a network error before any response (#16182):
630
+ * - `"read"`: a GET, a read-only POST or a convergent write, repeated
631
+ * without conditions.
632
+ * - `"keyed"`: an `IDEMPOTENT_WRITE_OPERATIONS` member, repeated only when
633
+ * the request carries an `Idempotency-Key`, with the same key and the same
634
+ * bytes on every attempt.
635
+ * - `"never"`: any other write; the first failure is thrown.
636
+ */
637
+ export type RetryEligibility = "read" | "keyed" | "never";
638
+ /** The retry class of an operation; see `RetryEligibility`. */
639
+ export declare function retryEligibility(operation: Pick<ApiClientOperation, "method" | "operationId">): RetryEligibility;
640
+ /**
641
+ * Trader skill grade. Source of truth:
642
+ * `components.schemas.Trader.properties.grade.enum` (S highest, F lowest).
643
+ */
644
+ export declare const GRADES: readonly ["S", "A", "B", "C", "D", "F"];
645
+ export type Grade = (typeof GRADES)[number];
646
+ export type ApiQueryValue = string | number | boolean | null | undefined | readonly (string | number | boolean)[];
647
+ export interface ApiRequestOptions {
648
+ path?: Record<string, string | number>;
649
+ query?: Record<string, ApiQueryValue>;
650
+ body?: unknown;
651
+ headers?: Record<string, string>;
652
+ /** Reject query names the operation does not publish before it runs. */
653
+ strictQuery?: boolean;
654
+ /** Cooperative cancellation; composed with the request deadline. */
655
+ signal?: AbortSignal;
656
+ /**
657
+ * Per-call deadline in ms, overriding the client default; `null` disables
658
+ * it for this call. The SSE stream (`streamFeed`) never has one. Retries
659
+ * share this one deadline: no retry is started that cannot finish inside it.
660
+ */
661
+ timeoutMs?: number | null;
662
+ /**
663
+ * Retries for this call, overriding the client's `maxRetries` (#14281).
664
+ * `0` sends exactly one request, which is the SDK's behaviour before retries.
665
+ */
666
+ maxRetries?: number;
667
+ /**
668
+ * Sent as the `Idempotency-Key` header. Accepted only on the
669
+ * `IDEMPOTENT_WRITE_OPERATIONS` (`createWebhook`, `updateWebhook`,
670
+ * `deleteWebhook`, `rotateWebhookSecret`, `prepareWebhookSecret`,
671
+ * `activateWebhookSecret`, `retireWebhookSecret`, `redeliverWebhookDelivery`),
672
+ * where a replay with the same key and body returns the first result
673
+ * instead of repeating the write; on any other operation `call()` throws
674
+ * before sending, since the server would ignore the key (#16182). A keyed
675
+ * write is the only non-read request the SDK retries, always with the
676
+ * same key and the same body bytes. On `IdempotencyInProgressError`, or
677
+ * when the outcome is unknown after a timeout or exhausted retries, send
678
+ * the SAME key and body again to learn what happened; never mint a new key
679
+ * for the same intent.
680
+ * The effective header, after this option overrides `headers`, must be
681
+ * nonempty after trimming and at most 255 UTF-8 bytes. Invalid keys throw
682
+ * before fetch, even with `maxRetries: 0`; omit the key for one attempt.
683
+ */
684
+ idempotencyKey?: string;
685
+ }
686
+ export interface ApiClientOptions {
687
+ /**
688
+ * The server URL, one of the `servers` in the OpenAPI document:
689
+ * `https://api.0xinsider.com` (the default) or
690
+ * `https://0xinsider.com/sandbox`. A path on it is kept, so every operation
691
+ * path (`/api/v1/...`) is appended after it (#16138: the path used to be
692
+ * discarded, which sent a sandbox client to the live host). Trailing slashes
693
+ * are trimmed, and a trailing `/api/v1` is removed once, since the operation
694
+ * paths carry it.
695
+ */
696
+ baseUrl?: string;
697
+ /**
698
+ * The `oxi_sk_live_*` secret API key, or a sandbox key (`oxi_sk_test_*`)
699
+ * when `sandbox` is set.
700
+ */
701
+ apiKey?: string;
702
+ /**
703
+ * Explicit sandbox mode (#16138). `baseUrl` defaults to
704
+ * `SANDBOX_BASE_URL` (`https://0xinsider.com/sandbox`), every operation is
705
+ * allowed without a key, since the sandbox needs no credential, and a live
706
+ * key (`oxi_sk_live_*`) is refused by the constructor so it is never sent
707
+ * there. A sandbox key from `POST /api/v1/agents/register` is optional and
708
+ * is sent when given. `OxinsiderApiClient.sandbox()` builds one.
709
+ */
710
+ sandbox?: boolean;
711
+ /** Override the global `fetch` (e.g. for testing or a proxy agent). */
712
+ fetch?: typeof fetch;
713
+ /**
714
+ * Deadline for every request, connect to body, in ms. Default
715
+ * `DEFAULT_TIMEOUT_MS` (15 000); `null` disables it. A request that misses
716
+ * it rejects with `RequestTimeoutError`. Long-lived reads (`streamFeed`)
717
+ * are not subject to it (#11115).
718
+ */
719
+ timeoutMs?: number | null;
720
+ /**
721
+ * How many times a failed idempotent request is retried (#14281). Default
722
+ * `DEFAULT_MAX_RETRIES` (2); `0` disables retries.
723
+ *
724
+ * Retried: a GET, a read-only POST (`READ_ONLY_POST_OPERATIONS`), or an
725
+ * `IDEMPOTENT_WRITE_OPERATIONS` write carrying an `Idempotency-Key`, that
726
+ * failed with 408, 429, 502, 503, 504, or a network error before any
727
+ * response (`retryEligibility`, #16182). A 408 is the server's own timeout
728
+ * (`request_timeout`, #16146): it carries `Retry-After` on a GET, and a
729
+ * keyed write replays safely. The wait is the
730
+ * response's `Retry-After` (delta-seconds or an HTTP-date, `parseRetryAfter`)
731
+ * plus up to 250 ms of jitter when present, otherwise a jittered exponential
732
+ * backoff from 500 ms capped at 8 s. A `Retry-After` longer than
733
+ * `RETRY_AFTER_CEILING_MS` (60 s) is not waited out; the error is thrown so
734
+ * the caller can schedule it from `retryAfterSeconds` or `retryAt`. Never retried: 400, 401, 402, 403, 404, 409, 500, a write
735
+ * without a key, this client's own timeout, or a caller abort. A retry never starts unless it
736
+ * can finish inside `timeoutMs`, and a caller `AbortSignal` ends a backoff at
737
+ * once.
738
+ */
739
+ maxRetries?: number;
740
+ }
741
+ /** Default production API base used when `baseUrl` is omitted. */
742
+ export declare const DEFAULT_BASE_URL = "https://api.0xinsider.com";
743
+ /**
744
+ * The sandbox server, the second `servers` entry of the OpenAPI document: no
745
+ * credential, no production data, every documented operation answered with
746
+ * its example or a deterministic sample, `?sandbox_status=<code>` for a
747
+ * documented error, and `X-Oxi-Sandbox: true` on every response. The two
748
+ * Markdown documents answer `200 text/markdown` there and the export download
749
+ * answers its `302` to a sample file the sandbox serves itself. `GET
750
+ * /api/v1/stream` is the one operation it does not simulate and answers 400,
751
+ * because an SSE stream is a live connection rather than a body.
752
+ */
753
+ export declare const SANDBOX_BASE_URL = "https://0xinsider.com/sandbox";
754
+ /** Default per-request deadline; see `ApiClientOptions.timeoutMs`. */
755
+ export declare const DEFAULT_TIMEOUT_MS = 15000;
756
+ /** Default retry budget; see `ApiClientOptions.maxRetries`. */
757
+ export declare const DEFAULT_MAX_RETRIES = 2;
758
+ /**
759
+ * The API key travels as a bearer header on every request, so the base URL
760
+ * decides who receives it. Only `https:` is accepted, with `http:` allowed for
761
+ * a loopback host (a local backend on `localhost` or `127.0.0.1`). Anything
762
+ * else throws from the constructor, before any request is sent (#11115).
763
+ */
764
+ export declare function assertTrustedBaseUrl(baseUrl: string): URL;
765
+ /**
766
+ * Join an `/api/v1/...` path onto the server URL, keeping the server's own
767
+ * path (`/sandbox`) exactly once. REST (`buildUrl`) and the SSE stream
768
+ * (`stream.ts`) both resolve through this, so the two cannot disagree about
769
+ * where a path-bearing base points (#16138: `new URL("/api/v1/...", base)`
770
+ * resolved against the origin and dropped `/sandbox`).
771
+ */
772
+ export declare function resolveApiUrl(baseUrl: string, path: string): URL;
773
+ /**
774
+ * One signal that aborts on the deadline OR when the caller's signal aborts.
775
+ * Uses native composition where available. The manual fallback removes both
776
+ * source listeners when either source aborts.
777
+ */
778
+ export declare function composeSignals(timeoutMs: number | null, caller?: AbortSignal): AbortSignal | undefined;
779
+ /** Standard single-resource envelope: `{ object, data, meta }`. */
780
+ export interface ApiEnvelope<T> {
781
+ object: string;
782
+ data: T;
783
+ meta?: ClientResponseMeta;
784
+ }
785
+ /** Stripe-style list envelope: `{ object: "list", data, has_more, next_cursor, total?, meta }`. */
786
+ export interface ApiListEnvelope<T> {
787
+ object: "list";
788
+ data: T[];
789
+ has_more: boolean;
790
+ next_cursor?: string | null;
791
+ total?: number | null;
792
+ meta?: ClientResponseMeta;
793
+ /**
794
+ * When this body was computed, on endpoints that publish a freshness envelope
795
+ * (`markets/explore` today). Absent elsewhere.
796
+ *
797
+ * Pair it with `fresh_for_seconds` to bound how long you reuse the body:
798
+ * `fresh_for_seconds - age(computed_at)`. The remainder is deliberately not
799
+ * pre-subtracted, because a cached body cannot carry a number that changes
800
+ * while it sits in a cache. Both are excluded from the `ETag` validator, so a
801
+ * body recomputed with identical data keeps its validator.
802
+ */
803
+ computed_at?: string;
804
+ /** How long the body computed at `computed_at` is good for, in seconds. */
805
+ fresh_for_seconds?: number;
806
+ }
807
+ export type CategorySkillStatus = "live" | "insufficient" | "stale" | "unknown" | "degraded";
808
+ export interface CategorySkillStatusCounts {
809
+ live: number;
810
+ insufficient: number;
811
+ stale: number;
812
+ unknown: number;
813
+ degraded: number;
814
+ }
815
+ /** Query parameters accepted by {@link OxinsiderApiClient.listGames}. */
816
+ export type GamesListParams = OperationQuery["listGames"];
817
+ /** One game: both sides, its schedule, its provider status and its markets. */
818
+ export type { Game } from "./schema.js";
819
+ /** Query parameters of `GET /api/v1/sports/pre-game-sides` (#16310). */
820
+ export type PreGameSidesParams = OperationQuery["listPreGameSides"];
821
+ /** @deprecated Use {@link PreGameSidesParams} (#16310). */
822
+ export type SportsEdgeSignalsParams = PreGameSidesParams;
823
+ /** Observation cohorts exposed by `listPreGameSideObservations`. */
824
+ export type SportsEdgeObservationCohort = "wider_holder" | "in_play" | "emerging_pile";
825
+ /** Source of the provider holder snapshot used to build an observation. */
826
+ export type SportsEdgeObservationProviderSource = "cached" | "live";
827
+ /** Why a sport's upcoming-board source is (un)available in the funnel report. */
828
+ export type SportsEdgeObservationBoardUpcomingStatus = "unknown" | "not_configured" | "available" | "capacity_limited" | "source_unavailable" | "cold_unavailable" | "deadline_unavailable";
829
+ /** Scope attribution for an unavailable upcoming-board union. */
830
+ export type SportsEdgeObservationBoardUnavailableScope = "category" | "nfl" | "cfb" | "nba" | "wnba" | "nhl" | "mls" | "valorant" | "league-of-legends" | "counter-strike-2" | "dota-2" | "registry" | "union" | "wave";
831
+ /** Truthful state of the cross-market directional read. */
832
+ export type SportsEdgeObservationDirectionalStatus = "available" | "unknown_ungrouped" | "unknown_stale" | "unavailable";
833
+ /**
834
+ * Provider binary-column selector for observation markets: 0 selects
835
+ * outcome_yes/token_id_yes; 1 selects outcome_no/token_id_no. Use piled_side,
836
+ * not this index, for participant identity.
837
+ */
838
+ export type SportsEdgeObservationOutcomeIndex = 0 | 1;
839
+ /** Closed grade vocabulary for the best holder grade on an observation. */
840
+ export type SportsEdgeObservationTopGrade = "S" | "A" | "B";
841
+ /** Canonical sports emitted by observation responses. */
842
+ export type SportsEdgeObservationSport = "Basketball" | "Football" | "Baseball" | "Hockey" | "MMA" | "Boxing" | "Soccer" | "Cricket" | "Golf" | "Tennis" | "Esports" | "Racing" | "Table Tennis" | "Pickleball";
843
+ /**
844
+ * Full list response, including the observation snapshot and accountable
845
+ * funnel: the operation's own envelope (#16136). `degraded` is the
846
+ * snapshot-wide verdict; fully accounted `capacity_limited` rows alone do
847
+ * not set it.
848
+ */
849
+ export type PreGameSideObservationsResponse = OperationEnvelope<"listPreGameSideObservations">;
850
+ /** @deprecated Use {@link PreGameSideObservationsResponse} (#16310). */
851
+ export type SportsEdgeObservationsResponse = PreGameSideObservationsResponse;
852
+ /** Query parameters of `GET /api/v1/sports/pre-game-side-observations` (#16310). */
853
+ export type PreGameSideObservationsParams = OperationQuery["listPreGameSideObservations"];
854
+ /** @deprecated Use {@link PreGameSideObservationsParams} (#16310). */
855
+ export type SportsEdgeObservationsParams = PreGameSideObservationsParams;
856
+ /**
857
+ * One qualifying category expert on a Pick of the Day's backed side.
858
+ *
859
+ * Every threshold below holds BY CONSTRUCTION -- the selector only ever freezes a wallet that
860
+ * cleared all of them -- so a consumer can render the numbers without re-checking them.
861
+ */
862
+ export interface PickQualifyingExpert {
863
+ /** Policy 6 admission exception; absent on earlier frozen policies. */
864
+ lane?: "standard" | "longshot_specialist";
865
+ /** Answered, index-scoped provider probability, present only on specialist lanes. */
866
+ lane_probability?: number;
867
+ lane_probability_source?: "p";
868
+ address: string;
869
+ name?: string | null;
870
+ /** Public V1 exposes `S` or `A`; internal policy v2 also admits B. */
871
+ grade?: string | null;
872
+ /**
873
+ * The canonical sport BUCKET the rate below was measured over (for example `Basketball`).
874
+ *
875
+ * Label `win_rate` with THIS field, never with the pick's `display_category`: that names an
876
+ * exact league (NBA/WNBA/NFL/NHL/MLB/UFC) which folds into a broader bucket, so rendering
877
+ * "68% of their NBA markets" for a Basketball-wide rate publishes a false quantified claim.
878
+ */
879
+ canonical_category: string;
880
+ /**
881
+ * Share of this wallet's resolved markets in `canonical_category` whose realized P&L came out
882
+ * positive, as a 0..1 fraction. Above 0.60. Scale x100 at the display edge. `null` for an
883
+ * expert who qualified on the category-skill v2 definition only (`source` = `v2`).
884
+ */
885
+ win_rate: number | null;
886
+ /** Resolved markets in `canonical_category` behind `win_rate`. At least 10. `null` with it. */
887
+ n_resolved: number | null;
888
+ /**
889
+ * Which definition qualified the wallet: `v1` (the profitability rate above) or `v2` (the
890
+ * forward-only category-skill calibration edge below). Absent on picks frozen before the v2
891
+ * definition existed; read absence as `v1`. A Tennis pick frozen under gate policy v4 or later
892
+ * carries `v2` only: a v1 rate stopped qualifying a tennis expert at v4. A Tennis pick frozen
893
+ * under an earlier policy can still carry `v1` with a win rate.
894
+ */
895
+ source?: "v1" | "v2";
896
+ /**
897
+ * 95% lower bound of the wallet's mean calibration edge over the market price in
898
+ * `canonical_category`, in probability units (0.08 = 8 points). Positive by construction for
899
+ * a `v2` expert; present on a `v1` expert only when the wallet also has a live v2 row.
900
+ */
901
+ edge_lower_95?: number | null;
902
+ /** Point estimate behind `edge_lower_95`. */
903
+ edge_mean?: number | null;
904
+ /**
905
+ * Independent canonical events behind the edge. Clears the v2 sample floor for a `v2`
906
+ * expert; the floor is the selector's and is not published.
907
+ */
908
+ independent_event_count?: number | null;
909
+ /**
910
+ * Polymarket's own `currentValue` for this wallet on the backed outcome, in USD, as of
911
+ * selection. Clears the lane's net-position floor at selection; the floor is the selector's,
912
+ * has changed between gate policies, and is not published.
913
+ */
914
+ position_usd: number;
915
+ /**
916
+ * The same wallet's `currentValue` on the OTHER outcome of this market, in USD, as of
917
+ * selection. From gate policy v5 the floor is read on the net: `position_usd` minus this
918
+ * value clears the lane's floor, so a wallet long both sides does not qualify. Absent on picks
919
+ * frozen before v5, which never read the leg; 0 is a measured one-way position.
920
+ */
921
+ opposite_position_usd?: number | null;
922
+ /**
923
+ * When the skill read model behind the evidence was last rebuilt: `trader_category_stats`
924
+ * for a `source: v1` expert, `category_skill_v2_current.as_of` for a `source: v2` expert.
925
+ */
926
+ stats_computed_at: string;
927
+ }
928
+ /**
929
+ * Tennis tour a competitor belongs to. Only `atp` and `wta` name a gender: the
930
+ * ITF World Tennis Tour runs men's and women's events and the provider does not
931
+ * say which, so `itf` means tennis with gender unknown.
932
+ */
933
+ export type TennisTour = "atp" | "wta" | "itf";
934
+ /**
935
+ * The daily editorial Pick of the Day. Single-object envelope for
936
+ * `getPickOfTheDay` (`GET /api/v1/pick-of-the-day`). Field names mirror the
937
+ * JSON wire shape (snake_case); the backend omits null/absent optional fields.
938
+ * The outer object retains the historical first-pick fields and `picks` carries
939
+ * the ordered daily picks, normally three to ten items and never more than ten.
940
+ * A published pick whose holder proof is not readable yet is listed in
941
+ * `proof_pending_picks` instead of `picks` (#10698).
942
+ */
943
+ /** Typed 304 result returned for a matching `If-None-Match` conditional GET. */
944
+ export interface ApiNotModifiedResponse {
945
+ object: "not_modified";
946
+ data: null;
947
+ meta: {
948
+ status: 304;
949
+ etag?: string;
950
+ request_id?: string;
951
+ queryIgnored?: string;
952
+ effectiveQuery?: string;
953
+ [key: string]: unknown;
954
+ };
955
+ }
956
+ export type ApiClientResponse<T> = ApiEnvelope<T> | ApiNotModifiedResponse;
957
+ /** `etag`, `sandbox` and `status`, lifted by this client onto whichever `meta` the operation declares. */
958
+ export type ClientMeta<M> = M & {
959
+ /** Lifted from the `ETag` response header by this client. */
960
+ etag?: string;
961
+ /** `true` when the response carried `X-Oxi-Sandbox: true` (#16138). */
962
+ sandbox?: true;
963
+ /**
964
+ * The HTTP status of the success response, set by this client (#16137).
965
+ *
966
+ * Not every operation answers `200`, and the difference is the answer:
967
+ * `registerAgent` answers `201`, and `submitTraderExport` answers `202`
968
+ * when it queued a new job and `200` when it returned one that already
969
+ * existed. The envelope body is the same shape either way, so without this
970
+ * a caller could not tell a fresh job from a replayed one.
971
+ */
972
+ status?: number;
973
+ };
974
+ /** Operations whose 200 is the JSON envelope (`object`, `data`, `meta`); the two text bodies and the JSON-RPC post are not. */
975
+ export type EnvelopeOperationId = {
976
+ [K in ApiOperationId]: OperationResponse[K] extends {
977
+ object: string;
978
+ data: unknown;
979
+ meta: unknown;
980
+ } ? K : never;
981
+ }[ApiOperationId];
982
+ /** Envelope operations that page: `data` is an array and `has_more` is declared. */
983
+ export type ListOperationId = {
984
+ [K in EnvelopeOperationId]: OperationResponse[K] extends {
985
+ has_more: boolean;
986
+ data: readonly unknown[];
987
+ } ? K : never;
988
+ }[EnvelopeOperationId];
989
+ /** The operation's documented `meta` type. */
990
+ export type OperationMeta<K extends ApiOperationId> = OperationResponse[K] extends {
991
+ meta: infer M;
992
+ } ? M : never;
993
+ /**
994
+ * What a 200 resolves to: the operation's own envelope (`object` literal,
995
+ * `data`, every top-level field such as `has_more` or a list's `totals`) with
996
+ * its own `meta` type (`BatchResponseMeta` on a batch, `EventReplayMeta` on
997
+ * the replay, `ResponseMeta` elsewhere) plus this client's lifted `etag` and
998
+ * `sandbox`.
999
+ */
1000
+ export type OperationEnvelope<K extends EnvelopeOperationId> = Omit<OperationResponse[K], "meta"> & {
1001
+ meta: ClientMeta<OperationMeta<K>>;
1002
+ };
1003
+ /** A `call()` result: the envelope, or the typed 304 when `If-None-Match` matched. */
1004
+ export type OperationResult<K extends EnvelopeOperationId> = OperationEnvelope<K> | ApiNotModifiedResponse;
1005
+ /** One item of a list operation's `data`. */
1006
+ export type OperationItem<K extends ListOperationId> = OperationData[K] extends readonly (infer I)[] ? I : never;
1007
+ /**
1008
+ * `call()` options bound to one operation: `path` is required exactly when
1009
+ * the route has path parameters, `query` is the documented query, `body` is
1010
+ * required exactly when the operation declares a request body, and the
1011
+ * transport options (`signal`, `timeoutMs`, `maxRetries`, `headers`,
1012
+ * `idempotencyKey`) are the shared ones.
1013
+ */
1014
+ export type OperationRequestOptions<K extends ApiOperationId> = Omit<ApiRequestOptions, "path" | "query" | "body"> & (OperationPath[K] extends Record<string, never> ? {
1015
+ path?: OperationPath[K];
1016
+ } : {
1017
+ path: OperationPath[K];
1018
+ }) & {
1019
+ query?: OperationQuery[K];
1020
+ } & ([
1021
+ OperationBody[K]
1022
+ ] extends [never] ? {
1023
+ body?: never;
1024
+ } : {
1025
+ body: OperationBody[K];
1026
+ });
1027
+ /**
1028
+ * Whether operation `K` cannot be called without options: it has path
1029
+ * parameters or a request body (#16643). For a union of operations it is
1030
+ * `true` when any member needs them.
1031
+ */
1032
+ export type OperationRequiresOptions<K extends ApiOperationId> = true extends (K extends ApiOperationId ? OperationPath[K] extends Record<string, never> ? [OperationBody[K]] extends [never] ? false : true : true : never) ? true : false;
1033
+ /** The operations that can be called with no options at all. */
1034
+ export type OptionalInputOperationId = {
1035
+ [K in ApiOperationId]: OperationRequiresOptions<K> extends true ? never : K;
1036
+ }[ApiOperationId];
1037
+ /**
1038
+ * The options argument of a typed overload (#16643): required when the
1039
+ * operation has path parameters or a body, optional otherwise, so
1040
+ * `client.call("createWebhook")` and `client.list("listWebhookDeliveries")`
1041
+ * fail to compile instead of failing at the API.
1042
+ */
1043
+ export type OperationOptionsArgs<K extends ApiOperationId, O> = OperationRequiresOptions<K> extends true ? [options: O] : [options?: O];
1044
+ /**
1045
+ * The operation id a LOOSE overload accepts (#16643). A value typed as the
1046
+ * whole `ApiOperationId` union (an id chosen at runtime) passes; a literal
1047
+ * passes only when the operation needs no options, so a literal with a
1048
+ * mandatory path or body cannot fall through to the loose form without them.
1049
+ * A caller that names the result type explicitly (`call<T>(...)`) skips the
1050
+ * inference this relies on; the runtime still refuses a missing path
1051
+ * parameter before any request.
1052
+ */
1053
+ export type RuntimeOperationId<I extends ApiOperationId> = I & (ApiOperationId extends I ? unknown : OptionalInputOperationId);
1054
+ /** The transport options a convenience method forwards: everything but the parts it fills itself. */
1055
+ export type ConvenienceOptions = Omit<ApiRequestOptions, "path" | "query" | "body">;
1056
+ /** The MCP methods `POST /api/v1/mcp` accepts, from the operation's request body. */
1057
+ export declare const MCP_METHODS: readonly ["initialize", "notifications/initialized", "notifications/cancelled", "ping", "tools/list", "tools/call"];
1058
+ export type McpMethod = (typeof MCP_METHODS)[number];
1059
+ /**
1060
+ * One JSON-RPC 2.0 message for `POST /api/v1/mcp`. `jsonrpc` defaults to
1061
+ * `"2.0"`. Omit `id` for a notification, which answers an empty `202`.
1062
+ */
1063
+ export interface McpJsonRpcRequest {
1064
+ jsonrpc?: "2.0";
1065
+ /** Echoed exactly in the response. Omit it on a notification. */
1066
+ id?: string | number | null;
1067
+ method: McpMethod;
1068
+ params?: Record<string, unknown>;
1069
+ }
1070
+ /** The JSON-RPC 2.0 response body, as the operation declares it. */
1071
+ export type McpJsonRpcResponse = OperationResponse["createMcpJsonRpcResponse"];
1072
+ /** Options for `mcp()`: the shared transport options plus the two MCP headers. */
1073
+ export interface McpOptions extends ConvenienceOptions {
1074
+ /** Sent as `Mcp-Session-Id`; use the value a previous response returned. */
1075
+ sessionId?: string;
1076
+ /**
1077
+ * Sent as `MCP-Protocol-Version`. Omit it and the server serves
1078
+ * `2025-03-26`; an unsupported revision is a `400`.
1079
+ */
1080
+ protocolVersion?: string;
1081
+ }
1082
+ /** What `mcp()` returns: the JSON-RPC response, or the accepted notification. */
1083
+ export interface McpResult {
1084
+ /** `200` for a JSON-RPC response, `202` for an accepted notification. */
1085
+ status: 200 | 202;
1086
+ /** The JSON-RPC body, or `null` for the empty `202` a notification receives. */
1087
+ response: McpJsonRpcResponse | null;
1088
+ /** `Mcp-Session-Id`, when the server issued or echoed one. */
1089
+ sessionId?: string;
1090
+ }
1091
+ /** Where a finished export actually lives, from the `302`'s `Location`. */
1092
+ export interface TraderExportDownloadTarget {
1093
+ /**
1094
+ * The presigned object URL. It authorizes itself, so treat it as a
1095
+ * credential: never log it and never share it.
1096
+ */
1097
+ url: string;
1098
+ /**
1099
+ * When the link stops working, read from the URL's own SigV4
1100
+ * `X-Amz-Date` and `X-Amz-Expires`. Absent when the URL does not carry
1101
+ * them. Links last at most one hour and cannot outlive artifact retention.
1102
+ */
1103
+ expiresAt?: string;
1104
+ }
1105
+ /** The manifest field used by `downloadTraderExport` when verification is enabled. */
1106
+ export interface TraderExportDownloadIntegrity {
1107
+ algorithm: "sha256";
1108
+ expectedSha256: string;
1109
+ expectedSizeBytes: number;
1110
+ }
1111
+ /** The object response, with what its headers said about the file. */
1112
+ export interface TraderExportDownload extends TraderExportDownloadTarget {
1113
+ /** Not buffered: read `response.body` as a stream. */
1114
+ response: Response;
1115
+ /** `Content-Length` of the object, or `null` when the store sent none. */
1116
+ contentLength: number | null;
1117
+ contentType: string | null;
1118
+ /** The filename from `Content-Disposition`, or `null`. */
1119
+ filename: string | null;
1120
+ /** The expected content checksum, or `null` when `verifyChecksum` was not requested. */
1121
+ integrity: TraderExportDownloadIntegrity | null;
1122
+ }
1123
+ export interface TraderExportDownloadOptions extends ConvenienceOptions {
1124
+ /**
1125
+ * A deadline in ms for the OBJECT fetch, which has none by default: an
1126
+ * export can be far larger than a REST read and the 15-second default
1127
+ * would cut it off mid-file. `timeoutMs` still bounds the redirect.
1128
+ */
1129
+ downloadTimeoutMs?: number | null;
1130
+ /** Fetch the owner-authorized manifest and verify the streamed content before it is consumed. */
1131
+ verifyChecksum?: boolean;
1132
+ }
1133
+ /** Shared paging params accepted by Stripe-style list endpoints. */
1134
+ export interface ListParams {
1135
+ limit?: number;
1136
+ cursor?: string;
1137
+ [key: string]: ApiQueryValue;
1138
+ }
1139
+ /** `GET /api/v1/leaderboard` -> parameters -> strategy (`web/public/api/v1/openapi.json`). */
1140
+ export declare const LEADERBOARD_STRATEGIES: readonly ["accumulator", "algo_trader", "arbitrageur", "directional", "event_driven", "market_maker", "momentum", "scalper", "speculator", "swing_trader"];
1141
+ export type LeaderboardStrategy = (typeof LEADERBOARD_STRATEGIES)[number];
1142
+ /**
1143
+ * Query parameters for `GET /api/v1/leaderboard`, from the operation
1144
+ * (#16136). The board has no `min_grade`: it only holds S, A, and B traders,
1145
+ * and the backend drops an unknown query key instead of rejecting it
1146
+ * (#10642), which is why the type now refuses one.
1147
+ */
1148
+ export type LeaderboardListParams = OperationQuery["listLeaderboard"];
1149
+ /** Query parameters for `GET /api/v1/leaderboard/trending`. */
1150
+ export type TrendingWalletsParams = OperationQuery["listTrendingWallets"];
1151
+ /** Query parameters of the V1 large-trade list (#16304). */
1152
+ export type LargeTradeListParams = OperationQuery["listLargeTrades"];
1153
+ /** Query parameters of the V1 historical large-trade replay (#16304). */
1154
+ export type LargeTradeHistoryParams = OperationQuery["listLargeTradeHistory"];
1155
+ /** @deprecated Use {@link LargeTradeListParams} (#16304). */
1156
+ export type WhaleTradeListParams = OperationQuery["listWhaleTrades"];
1157
+ /** @deprecated Use {@link LargeTradeHistoryParams} (#16304). */
1158
+ export type WhaleTradeHistoryParams = OperationQuery["listWhaleTradeHistory"];
1159
+ /** Query parameters of `GET /api/v1/positions`. */
1160
+ export type PositionsListParams = OperationQuery["listPositions"];
1161
+ /** Query parameters of `GET /api/v1/large-positions`. */
1162
+ export type LargePositionsListParams = OperationQuery["listLargePositions"];
1163
+ /** Query parameters of the sharp-money flows read and its legacy alias. */
1164
+ export type SharpMoneyFlowsParams = OperationQuery["listSharpMoneyFlows"];
1165
+ /** Query parameters of `GET /api/v1/suspicious-trades`: `min_suspicion` and `severity`, not a grade. */
1166
+ export type SuspiciousTradesListParams = OperationQuery["listSuspiciousTrades"];
1167
+ /**
1168
+ * @deprecated Use `SuspiciousTradesListParams`; the Insider Radar spelling of
1169
+ * this contract was renamed to suspicious trades in #16301. The deprecated
1170
+ * `GET /api/v1/insider-radar` takes the same parameters, so this stays an
1171
+ * alias with no retirement date.
1172
+ */
1173
+ export type InsiderRadarListParams = SuspiciousTradesListParams;
1174
+ /** Query parameters of `GET /api/v1/markets/explore`. */
1175
+ export type ExploreMarketsParams = OperationQuery["exploreMarkets"];
1176
+ /**
1177
+ * Body-level `expand` values of `POST /api/v1/traders/batch`. The type is the
1178
+ * operation's own body (`OperationBody["batchGetTraders"]["expand"]`); the
1179
+ * const is the same list as a runtime value for a caller that iterates it.
1180
+ */
1181
+ export declare const BATCH_TRADER_EXPANSIONS: readonly ["strategy", "categories", "quant_metrics", "trust"];
1182
+ export type BatchTraderExpand = NonNullable<OperationBody["batchGetTraders"]["expand"]>[number];
1183
+ /**
1184
+ * Options for `batchGetTraders`. The body is built from the positional
1185
+ * `traders` array and `expand`, so `body` is not accepted here.
1186
+ */
1187
+ export interface BatchGetTradersOptions extends ConvenienceOptions {
1188
+ /** Shared expand flags applied to every trader item; sent as the body's `expand`. */
1189
+ expand?: OperationBody["batchGetTraders"]["expand"];
1190
+ }
1191
+ export declare class OxinsiderApiClient {
1192
+ private readonly baseUrl;
1193
+ private readonly apiKey?;
1194
+ private readonly sandbox;
1195
+ private readonly fetchImpl;
1196
+ private readonly timeoutMs;
1197
+ private readonly maxRetries;
1198
+ /**
1199
+ * A client for the sandbox server (#16138): `SANDBOX_BASE_URL`, no
1200
+ * credential needed, example data only, never production data. The same
1201
+ * as `new OxinsiderApiClient({ ...options, sandbox: true })`; pass a
1202
+ * sandbox key (`oxi_sk_test_*`) as `apiKey` to have it checked.
1203
+ *
1204
+ * @example
1205
+ * const sandbox = OxinsiderApiClient.sandbox();
1206
+ * const board = await sandbox.listLeaderboard({ limit: 5 }); // no key
1207
+ * board.meta?.sandbox; // true
1208
+ */
1209
+ static sandbox(options?: Omit<ApiClientOptions, "sandbox">): OxinsiderApiClient;
1210
+ constructor(options?: ApiClientOptions);
1211
+ /**
1212
+ * Execute an envelope operation by id. Throws the matching
1213
+ * `OxinsiderApiError` subclass on a non-2xx response, returns a typed
1214
+ * `not_modified` result for a 304, and otherwise returns the operation's
1215
+ * own `{ object, data, meta, ... }` envelope (#16136): `path` is required
1216
+ * exactly when the route has path parameters, `query` and `body` are the
1217
+ * documented ones, and `data` and `meta` are the operation's types.
1218
+ *
1219
+ * @example
1220
+ * const trader = await client.call("getTrader", { path: { address } });
1221
+ * if (trader.object === "trader") trader.data.grade; // typed
1222
+ */
1223
+ call<K extends EnvelopeOperationId>(operationId: K, ...options: OperationOptionsArgs<K, OperationRequestOptions<K>>): Promise<OperationResult<K>>;
1224
+ /**
1225
+ * The untyped form, for an operation chosen at runtime or a caller that
1226
+ * asserts the shape itself with `T`: loose `path`, `query` and `body`, and
1227
+ * the generic `{ object, data, meta? }` envelope back. Every convenience
1228
+ * method uses the typed form above; reach for this one only when the
1229
+ * operation id is not a literal.
1230
+ */
1231
+ call<T = unknown, I extends ApiOperationId = ApiOperationId>(operationId: RuntimeOperationId<I>, options?: ApiRequestOptions): Promise<ApiClientResponse<T>>;
1232
+ /**
1233
+ * Read a `text/*` operation's body as a string (#16137).
1234
+ *
1235
+ * `getTraderContextMarkdown` and `getMarketContextMarkdown` answer
1236
+ * `text/markdown`, which `call()` used to parse as JSON and then reject as
1237
+ * an invalid 200. Authentication, the request deadline, retries and the
1238
+ * typed error hierarchy are the same as `call()`; only the body differs.
1239
+ *
1240
+ * @example
1241
+ * const md = await client.text("getTraderContextMarkdown", { path: { address } });
1242
+ */
1243
+ text<K extends TextOperationId>(operationId: K, ...options: OperationOptionsArgs<K, OperationRequestOptions<K>>): Promise<string>;
1244
+ /** The untyped form, for an operation id chosen at runtime. */
1245
+ text<I extends ApiOperationId = ApiOperationId>(operationId: RuntimeOperationId<I>, options?: ApiRequestOptions): Promise<string>;
1246
+ /**
1247
+ * Post one MCP JSON-RPC 2.0 message to `POST /api/v1/mcp` (#16137).
1248
+ *
1249
+ * The endpoint answers a JSON-RPC envelope, not the `{ object, data, meta }`
1250
+ * envelope every other operation uses, so `call()` refuses it. A request
1251
+ * (one carrying `id`) comes back as `status: 200` with `response` set; a
1252
+ * supported notification (no `id`) comes back as `status: 202` with
1253
+ * `response: null`, which is the empty body the server sends. A JSON-RPC
1254
+ * `error` member is a protocol-level failure and is RETURNED, not thrown:
1255
+ * only a non-2xx HTTP status throws, because an unknown tool is an answer
1256
+ * and a revoked credential is not.
1257
+ *
1258
+ * The request is never retried: `tools/call` can have an effect, and the
1259
+ * endpoint honours no `Idempotency-Key`.
1260
+ *
1261
+ * @example
1262
+ * const listed = await client.mcp({ method: "tools/list", id: 1 });
1263
+ * listed.response?.result;
1264
+ */
1265
+ mcp(request: McpJsonRpcRequest, options?: McpOptions): Promise<McpResult>;
1266
+ /**
1267
+ * Read the owner-authorized lifecycle and artifact manifest for one export
1268
+ * job. The manifest is immutable for the artifact; the download URL remains
1269
+ * temporary and is resolved separately.
1270
+ */
1271
+ /** Submit a bounded cross-market snapshot; repeated identical live requests reuse it. */
1272
+ submitWhaleDataset(body: OperationBody["submitWhaleDataset"], options?: ConvenienceOptions): Promise<OperationResult<"submitWhaleDataset">>;
1273
+ getWhaleDatasetStatus(jobId: number, options?: ConvenienceOptions): Promise<OperationResult<"getWhaleDatasetStatus">>;
1274
+ cancelWhaleDataset(jobId: number, options?: ConvenienceOptions): Promise<OperationResult<"cancelWhaleDataset">>;
1275
+ /** Resolve only the signed URL. Never log it or forward API credentials to storage. */
1276
+ getWhaleDatasetDownloadUrl(jobId: number, options?: ConvenienceOptions): Promise<TraderExportDownloadTarget>;
1277
+ /** Stream decoded NDJSON, validating its manifest hash when the body finishes. */
1278
+ downloadWhaleDataset(jobId: number, options?: TraderExportDownloadOptions): Promise<TraderExportDownload>;
1279
+ getTraderExportStatus(address: OperationPath["getTraderExportStatus"]["address"], jobId: OperationQuery["getTraderExportStatus"]["job_id"], options?: ConvenienceOptions): Promise<OperationResult<"getTraderExportStatus">>;
1280
+ /**
1281
+ * Resolve the presigned object URL behind `GET /api/v1/trader/{address}/export/download`
1282
+ * without downloading anything (#16137).
1283
+ *
1284
+ * The route answers `302` with a `Location`, which `call()` treats as an
1285
+ * error. This reads the redirect target and stops there, so a caller can
1286
+ * hand the URL to a download manager or a browser. The returned URL is a
1287
+ * bearer credential in itself: anyone holding it can read the file until it
1288
+ * expires, so do not log it.
1289
+ *
1290
+ * Browser caveat: `fetch` with `redirect: "manual"` yields an opaque
1291
+ * redirect whose `Location` no script can read. The method says so rather
1292
+ * than guessing a URL; run the download from a server runtime.
1293
+ */
1294
+ getTraderExportDownloadUrl(address: OperationPath["getTraderExportStatus"]["address"], jobId: OperationQuery["getTraderExportStatus"]["job_id"], options?: ConvenienceOptions): Promise<TraderExportDownloadTarget>;
1295
+ /**
1296
+ * Download a finished export (#16137): resolve the `302`, then fetch the
1297
+ * object store directly.
1298
+ *
1299
+ * The second request carries NO headers at all, so the live API key never
1300
+ * reaches the object store; the presigned URL is its own credential. The
1301
+ * body is not buffered -- read `response.body` as a stream and write it
1302
+ * where it belongs.
1303
+ *
1304
+ * There is no default deadline on the object fetch, the way `streamFeed`
1305
+ * has none: a multi-gigabyte export would fail the 15-second REST default
1306
+ * halfway through. Pass `signal` to cancel it, or `downloadTimeoutMs` for
1307
+ * a deadline of your own. `timeoutMs` still bounds the redirect request.
1308
+ *
1309
+ * @example
1310
+ * const { response, filename } = await client.downloadTraderExport(address, jobId);
1311
+ * await pipeline(Readable.fromWeb(response.body), createWriteStream(filename ?? "export.json"));
1312
+ */
1313
+ downloadTraderExport(address: OperationPath["getTraderExportStatus"]["address"], jobId: OperationQuery["getTraderExportStatus"]["job_id"], options?: TraderExportDownloadOptions): Promise<TraderExportDownload>;
1314
+ private downloadExportObject;
1315
+ /**
1316
+ * Look up an operation and refuse it when the caller reached for the wrong
1317
+ * reader (#16137): `call()` on a Markdown route used to fail as a bad 200.
1318
+ */
1319
+ private resolveOperation;
1320
+ /**
1321
+ * One request pipeline for every transport: URL and headers, the retry
1322
+ * policy, one deadline shared by every attempt, the typed error hierarchy,
1323
+ * and cancellation held live through body consumption. `consume` runs
1324
+ * inside that window, so a slow body is still covered by the deadline and
1325
+ * by the caller's `signal`.
1326
+ */
1327
+ private request;
1328
+ /**
1329
+ * Execute a Stripe-style list operation and return its own list envelope
1330
+ * (`data`, `has_more`, `next_cursor`, and the route's extra fields such as
1331
+ * `facets` or `totals`). Use `paginate()` (in `pagination.ts`) to
1332
+ * auto-follow `next_cursor`.
1333
+ */
1334
+ list<K extends ListOperationId>(operationId: K, ...options: OperationOptionsArgs<K, OperationRequestOptions<K>>): Promise<OperationEnvelope<K>>;
1335
+ /** The untyped form; see the second `call` signature. */
1336
+ list<T = unknown, I extends ApiOperationId = ApiOperationId>(operationId: RuntimeOperationId<I>, options?: ApiRequestOptions): Promise<ApiListEnvelope<T>>;
1337
+ getTrader(address: OperationPath["getTrader"]["address"], options?: Omit<OperationRequestOptions<"getTrader">, "path">): Promise<OperationResult<"getTrader">>;
1338
+ getTraderPnl(address: OperationPath["getTraderPnl"]["address"], options?: Omit<OperationRequestOptions<"getTraderPnl">, "path">): Promise<OperationResult<"getTraderPnl">>;
1339
+ /**
1340
+ * Fetch one wallet's win record per canonical category.
1341
+ *
1342
+ * Counts every settled market at any position size, so it can differ from
1343
+ * `category_strengths` on `getTrader`, which reads the floored calibration
1344
+ * sample. A category under `min_decided_for_win_rate` keeps its `wins` and
1345
+ * `decided` with `win_rate: null` and `status: "not_enough_data"`; a category
1346
+ * the wallet has no settled market in is absent, which means no record rather
1347
+ * than a 0% record. The `Esports` record carries `games`: the wallet's record
1348
+ * per esports title (`LoL`, `CS2`, `Dota 2`, ...) under the same rule, named
1349
+ * as the holder chips name them in `category_win_rate_game`. Pass
1350
+ * `params.category` to filter to one bucket; a filter that reaches Esports
1351
+ * returns its games too.
1352
+ */
1353
+ getTraderCategoryRecords(address: OperationPath["getTraderCategoryRecords"]["address"], params?: OperationQuery["getTraderCategoryRecords"], options?: ConvenienceOptions): Promise<OperationResult<"getTraderCategoryRecords">>;
1354
+ /** Read the grade proven visible at one past decision time. */
1355
+ getTraderGradeAt(address: OperationPath["getTraderGradeAt"]["address"], params: OperationQuery["getTraderGradeAt"], options?: ConvenienceOptions): Promise<OperationResult<"getTraderGradeAt">>;
1356
+ /**
1357
+ * Resolve 1 to 25 traders in one request (`POST /api/v1/traders/batch`).
1358
+ *
1359
+ * `traders` is sent as the request body's `traders` array, the field the
1360
+ * route requires: wallet addresses, usernames, `trd_` ids or integer trader
1361
+ * ids, resolved in input order. Until #16135 this method sent the array as
1362
+ * `identifiers`, a field the route does not declare, so every call was
1363
+ * refused for a missing `traders`. `options.expand` is sent as the body's
1364
+ * `expand` array and applies to every item.
1365
+ *
1366
+ * The response `data` keeps request order and one row per input, duplicates
1367
+ * included; a row is `status: "ok"` with `data`, or `status: "error"` with
1368
+ * the item's own `error`. An identity that resolves to nothing is a per-item
1369
+ * error, never a request failure, and since #18135 the route answers the
1370
+ * `not_found` this comment already promised: a username, `trd_` id or
1371
+ * numeric trader id that names no trader is `not_found` with `error.param`
1372
+ * `"traders"`, where it used to be an `ok` row with the input echoed into
1373
+ * `address`. A wallet address the API does not track yet stays `ok` with
1374
+ * `sync_status: "unknown"`, because that address is real and may still be
1375
+ * graded. `meta` is the batch's `BatchResponseMeta`: `request_cost` and
1376
+ * `rate_limit` follow the batch item quota, not the per-request one.
1377
+ */
1378
+ batchGetTraders(traders: OperationBody["batchGetTraders"]["traders"], options?: BatchGetTradersOptions): Promise<OperationResult<"batchGetTraders">>;
1379
+ /**
1380
+ * Resolve up to 25 markets' flow and top positions in one request
1381
+ * (`POST /api/v1/markets/flow/batch`); `meta` is the batch's own.
1382
+ */
1383
+ batchGetMarketFlow(body: OperationBody["batchGetMarketFlow"], options?: ConvenienceOptions): Promise<OperationResult<"batchGetMarketFlow">>;
1384
+ /**
1385
+ * @deprecated Use {@link batchGetMarketFlow} (#16312); calls the deprecated
1386
+ * `POST /api/v1/markets/intel/batch`, whose envelope keeps
1387
+ * `object: "market_intel_batch"`.
1388
+ */
1389
+ batchGetMarketIntel(body: OperationBody["batchGetMarketIntel"], options?: ConvenienceOptions): Promise<OperationResult<"batchGetMarketIntel">>;
1390
+ listLeaderboard(params?: LeaderboardListParams, options?: ConvenienceOptions): Promise<OperationEnvelope<"listLeaderboard">>;
1391
+ listTrendingWallets(params?: TrendingWalletsParams, options?: ConvenienceOptions): Promise<OperationEnvelope<"listTrendingWallets">>;
1392
+ listLargeTrades(params?: LargeTradeListParams, options?: ConvenienceOptions): Promise<OperationEnvelope<"listLargeTrades">>;
1393
+ /**
1394
+ * Typed conditional-read variant of {@link listLargeTrades}, for polling
1395
+ * (#18507). Returns the list envelope on 200 or the typed `not_modified`
1396
+ * result on 304, where {@link listLargeTrades} throws on a 304. Pass
1397
+ * `since` (the id of the first trade of your last answer that had trades)
1398
+ * with `If-None-Match`: a poll that finds no new trade is a 304 with no body.
1399
+ */
1400
+ listLargeTradesConditional(params?: LargeTradeListParams, options?: ConvenienceOptions): Promise<OperationResult<"listLargeTrades">>;
1401
+ listLargeTradeHistory(params?: LargeTradeHistoryParams, options?: ConvenienceOptions): Promise<OperationEnvelope<"listLargeTradeHistory">>;
1402
+ /** @deprecated Use {@link listLargeTrades} (#16304); calls the deprecated `/api/v1/whale-trades`. */
1403
+ listWhaleTrades(params?: WhaleTradeListParams, options?: ConvenienceOptions): Promise<OperationEnvelope<"listWhaleTrades">>;
1404
+ /** @deprecated Use {@link listLargeTradeHistory} (#16304); calls the deprecated `/api/v1/whale-trades/history`. */
1405
+ listWhaleTradeHistory(params?: WhaleTradeHistoryParams, options?: ConvenienceOptions): Promise<OperationEnvelope<"listWhaleTradeHistory">>;
1406
+ listPositions(params?: PositionsListParams, options?: ConvenienceOptions): Promise<OperationEnvelope<"listPositions">>;
1407
+ listLargePositions(params?: LargePositionsListParams, options?: ConvenienceOptions): Promise<OperationEnvelope<"listLargePositions">>;
1408
+ /**
1409
+ * List ranked sharp-money flows. Canonical since #16308 ("sharp money" is
1410
+ * the pinned product term); it calls `/api/v1/markets/sharp-money-flows`.
1411
+ */
1412
+ listSharpMoneyFlows(params?: SharpMoneyFlowsParams, options?: ConvenienceOptions): Promise<OperationEnvelope<"listSharpMoneyFlows">>;
1413
+ /**
1414
+ * @deprecated Use {@link listSharpMoneyFlows} (#16308). Kept live; it calls
1415
+ * the deprecated `/api/v1/markets/smart-money-flows`, whose responses carry
1416
+ * `Deprecation` and a `Link rel="successor-version"`.
1417
+ */
1418
+ listSmartMoneyFlows(params?: OperationQuery["listSmartMoneyFlows"], options?: ConvenienceOptions): Promise<OperationEnvelope<"listSmartMoneyFlows">>;
1419
+ /**
1420
+ * List covered games: both sides with their provider ids and live scores, the
1421
+ * UTC kickoff, the provider's own status, and every linked Polymarket market
1422
+ * with its condition id and outcome token ids. Ordered by kickoff, then by
1423
+ * `event_slug`, with unscheduled games last. An unknown `sport` or `status`
1424
+ * returns an empty page rather than an error, and the response's `coverage`
1425
+ * names what this deployment serves.
1426
+ */
1427
+ listGames(params?: GamesListParams, options?: ConvenienceOptions): Promise<OperationEnvelope<"listGames">>;
1428
+ /**
1429
+ * Read one game by its `event_slug`, the identity the `live_sports_updated`
1430
+ * webhook pulse carries. A slug outside the published coverage returns 404.
1431
+ */
1432
+ getGame(eventSlug: OperationPath["getGame"]["event_slug"], options?: ConvenienceOptions): Promise<OperationResult<"getGame">>;
1433
+ /**
1434
+ * List upcoming games ranked by the side profitable wallets hold, with
1435
+ * additive, shadow-only category evidence. `category_skill` never changes
1436
+ * membership, ordering, or sizing. Rows carry `side`, `ranked_at`,
1437
+ * `backing_score` and `side_share`; the older `piled_side`,
1438
+ * `signal_created_at`, `conviction_score` and `smart_score` keys carry the
1439
+ * same values and stay on the wire.
1440
+ */
1441
+ listPreGameSides(params?: PreGameSidesParams, options?: ConvenienceOptions): Promise<OperationEnvelope<"listPreGameSides">>;
1442
+ /**
1443
+ * @deprecated Use {@link listPreGameSides} (#16310). Kept live; it calls the
1444
+ * deprecated `/api/v1/sports-edge-signals` path, which answers with
1445
+ * `Deprecation` and successor `Link` headers and the same body.
1446
+ */
1447
+ listSportsEdgeSignals(params?: SportsEdgeSignalsParams, options?: ConvenienceOptions): Promise<OperationEnvelope<"listSportsEdgeSignals">>;
1448
+ /**
1449
+ * Read an explicitly observation-only sports cohort and its accountable
1450
+ * per-sport funnel. This surface is isolated from the funded signals route.
1451
+ * Healthy wider-holder and emerging-pile snapshots may be served for about
1452
+ * 180 seconds; in-play cached snapshots are capped at about 30 seconds and
1453
+ * stale provider live-board evidence fails closed. emerging-pile is an
1454
+ * additive wider-holder projection, not an arrival-history or independent
1455
+ * denominator view.
1456
+ */
1457
+ listPreGameSideObservations(params: PreGameSideObservationsParams, options?: ConvenienceOptions): Promise<PreGameSideObservationsResponse>;
1458
+ /**
1459
+ * @deprecated Use {@link listPreGameSideObservations} (#16310). Kept live; it
1460
+ * calls the deprecated `/api/v1/sports-edge-observations` path, which answers
1461
+ * with `Deprecation` and successor `Link` headers and the same body.
1462
+ */
1463
+ listSportsEdgeObservations(params: SportsEdgeObservationsParams, options?: ConvenienceOptions): Promise<SportsEdgeObservationsResponse>;
1464
+ /**
1465
+ * Typed conditional-read variant of {@link listSportsEdgeObservations}.
1466
+ * Returns the full observation response on 200 or a typed `not_modified`
1467
+ * envelope on 304 instead of routing the latter through generic `call()`.
1468
+ * The endpoint emits a weak semantic ETag over the stable response payload;
1469
+ * request-specific `meta` is excluded. For emerging-pile, the opaque
1470
+ * projection cutoff inside `next_cursor` is excluded while its stable page
1471
+ * position remains covered.
1472
+ */
1473
+ listPreGameSideObservationsConditional(params: PreGameSideObservationsParams, options?: ConvenienceOptions): Promise<PreGameSideObservationsResponse | ApiNotModifiedResponse>;
1474
+ /**
1475
+ * @deprecated Use {@link listPreGameSideObservationsConditional} (#16310).
1476
+ * Kept live on the deprecated `/api/v1/sports-edge-observations` path.
1477
+ */
1478
+ listSportsEdgeObservationsConditional(params: SportsEdgeObservationsParams, options?: ConvenienceOptions): Promise<SportsEdgeObservationsResponse | ApiNotModifiedResponse>;
1479
+ searchMarkets(q: OperationQuery["searchMarkets"]["q"], options?: ConvenienceOptions & {
1480
+ query?: Omit<OperationQuery["searchMarkets"], "q">;
1481
+ }): Promise<OperationEnvelope<"searchMarkets">>;
1482
+ searchContent(q: OperationQuery["searchContent"]["q"], options?: ConvenienceOptions & {
1483
+ query?: Omit<OperationQuery["searchContent"], "q">;
1484
+ }): Promise<OperationEnvelope<"searchContent">>;
1485
+ exploreMarkets(params?: ExploreMarketsParams, options?: ConvenienceOptions): Promise<OperationEnvelope<"exploreMarkets">>;
1486
+ /** One market's flow and top positions (`GET /api/v1/market/{condition_id}/flow`). */
1487
+ getMarketFlow(conditionId: OperationPath["getMarketFlow"]["condition_id"], options?: Omit<OperationRequestOptions<"getMarketFlow">, "path">): Promise<OperationResult<"getMarketFlow">>;
1488
+ /**
1489
+ * @deprecated Use {@link getMarketFlow} (#16312); calls the deprecated
1490
+ * `GET /api/v1/market/{condition_id}/intel`, whose envelope keeps
1491
+ * `object: "market_intel"`.
1492
+ */
1493
+ getMarketIntel(conditionId: OperationPath["getMarketIntel"]["condition_id"], options?: Omit<OperationRequestOptions<"getMarketIntel">, "path">): Promise<OperationResult<"getMarketIntel">>;
1494
+ getMarketSnapshot(conditionId: OperationPath["getMarketSnapshot"]["condition_id"], options?: Omit<OperationRequestOptions<"getMarketSnapshot">, "path">): Promise<OperationResult<"getMarketSnapshot">>;
1495
+ /**
1496
+ * One page of a market's graded (S/A/B) holder roster from a complete
1497
+ * provider holder scan: the list a Pick of the Day shows, for any market.
1498
+ * `params.outcome` (`yes` | `no` | `all`), `params.min_grade` (`S` | `A` |
1499
+ * `B`), `params.limit` and `params.cursor` (`mh_` prefix). The page carries
1500
+ * the `market`, `scan` and roster `totals` beside `data`; `total` is the
1501
+ * count matching the filters across every page.
1502
+ */
1503
+ getMarketHolders(conditionId: OperationPath["getMarketHolders"]["condition_id"], params?: OperationQuery["getMarketHolders"], options?: ConvenienceOptions): Promise<OperationEnvelope<"getMarketHolders">>;
1504
+ /**
1505
+ * Fetch bucketed OHLC candles for a market's outcome tokens.
1506
+ * Resolution defaults to the server default; pass `params.resolution` as
1507
+ * `"1d"` or `"1w"` to override. `params.from` is exclusive and `params.to`
1508
+ * is inclusive; when both are present, `from` must be less than or equal to
1509
+ * `to`.
1510
+ */
1511
+ getMarketCandles(conditionId: OperationPath["getMarketCandles"]["condition_id"], params?: OperationQuery["getMarketCandles"], options?: ConvenienceOptions): Promise<OperationResult<"getMarketCandles">>;
1512
+ /**
1513
+ * Fetch one suspicious trade by raw `whale_alerts.id` or the `rf_`-prefixed
1514
+ * id list responses emit. The envelope's `object` is `"suspicious_trade"`.
1515
+ */
1516
+ getSuspiciousTrade(id: OperationPath["getSuspiciousTrade"]["id"], options?: ConvenienceOptions): Promise<OperationResult<"getSuspiciousTrade">>;
1517
+ /** List stored trades whose recorded suspicion score meets the flag threshold. */
1518
+ listSuspiciousTrades(params?: SuspiciousTradesListParams, options?: ConvenienceOptions): Promise<OperationEnvelope<"listSuspiciousTrades">>;
1519
+ /**
1520
+ * @deprecated Use `getSuspiciousTrade()`; renamed in #16301. This method
1521
+ * keeps calling the deprecated `GET /api/v1/insider-radar/{id}`, which stays
1522
+ * live with no retirement date and still answers `object: "radar_flag"`, so
1523
+ * an integration branching on that envelope keeps working.
1524
+ */
1525
+ getInsiderRadarFlag(id: OperationPath["getInsiderRadarFlag"]["id"], options?: ConvenienceOptions): Promise<OperationResult<"getInsiderRadarFlag">>;
1526
+ /**
1527
+ * @deprecated Use `listSuspiciousTrades()`; renamed in #16301. This method
1528
+ * keeps calling the deprecated `GET /api/v1/insider-radar`, which stays live
1529
+ * with no retirement date and answers with `Deprecation` plus a `Link
1530
+ * rel="successor-version"` header.
1531
+ */
1532
+ listInsiderRadar(params?: InsiderRadarListParams, options?: ConvenienceOptions): Promise<OperationEnvelope<"listInsiderRadar">>;
1533
+ getLargeTrade(id: OperationPath["getLargeTrade"]["id"], options?: ConvenienceOptions): Promise<OperationResult<"getLargeTrade">>;
1534
+ /** @deprecated Use {@link getLargeTrade} (#16304); calls the deprecated `/api/v1/whale-trades/{id}`. */
1535
+ getWhaleTrade(id: OperationPath["getWhaleTrade"]["id"], options?: ConvenienceOptions): Promise<OperationResult<"getWhaleTrade">>;
1536
+ /**
1537
+ * Cancel a submitted export (`POST /api/v1/trader/{address}/export/cancel`, #16254).
1538
+ *
1539
+ * Resolves to the job resource after the cancel, the same shape
1540
+ * `getTraderExportStatus` returns: `cancelled` for a job no worker had
1541
+ * started, `cancel_requested` for a running one (poll the status route at
1542
+ * `poll_after_s` until it reads `cancelled`), or the job unchanged when a
1543
+ * cancel can no longer reach it (its file is being published, or it is
1544
+ * already terminal). Compare `status` rather than assuming success. A
1545
+ * cancel never deletes a ready file, never returns quota, and is safe to
1546
+ * repeat, so it is retried on a transport or 5xx failure like a read.
1547
+ */
1548
+ cancelTraderExport(address: OperationPath["cancelTraderExport"]["address"], jobId: OperationQuery["cancelTraderExport"]["job_id"], options?: ConvenienceOptions): Promise<OperationResult<"cancelTraderExport">>;
1549
+ listWebhooks(options?: ConvenienceOptions): Promise<OperationEnvelope<"listWebhooks">>;
1550
+ getWebhook(id: OperationPath["getWebhook"]["id"], options?: ConvenienceOptions): Promise<OperationResult<"getWebhook">>;
1551
+ createWebhook(body: OperationBody["createWebhook"], options?: ConvenienceOptions): Promise<OperationResult<"createWebhook">>;
1552
+ updateWebhook(id: OperationPath["updateWebhook"]["id"], body: OperationBody["updateWebhook"], options?: ConvenienceOptions): Promise<OperationResult<"updateWebhook">>;
1553
+ deleteWebhook(id: OperationPath["deleteWebhook"]["id"], options?: ConvenienceOptions): Promise<OperationResult<"deleteWebhook">>;
1554
+ /**
1555
+ * Fetch the self-describing webhook event catalog (each entry's `id`,
1556
+ * description, payload shape, and active/dormant status).
1557
+ */
1558
+ listWebhookEvents(options?: ConvenienceOptions): Promise<OperationEnvelope<"listWebhookEvents">>;
1559
+ /** List delivery attempts for one webhook endpoint (Stripe-style list). */
1560
+ listWebhookDeliveries(webhookId: OperationPath["listWebhookDeliveries"]["id"], params?: OperationQuery["listWebhookDeliveries"], options?: ConvenienceOptions): Promise<OperationEnvelope<"listWebhookDeliveries">>;
1561
+ /**
1562
+ * Requeue one `dead_letter` delivery with a fresh attempt budget and return
1563
+ * the delivery row. Re-enabling a disabled endpoint resends nothing, so this
1564
+ * is how its dead-lettered deliveries are recovered. The API answers 409 when
1565
+ * the delivery is already delivered or still queued, or when the endpoint is
1566
+ * disabled, unverified, or no longer subscribed to the delivery's event type;
1567
+ * the error message names the fix. Pass `idempotencyKey` to make a retry safe.
1568
+ */
1569
+ redeliverWebhookDelivery(webhookId: OperationPath["redeliverWebhookDelivery"]["id"], deliveryId: OperationPath["redeliverWebhookDelivery"]["delivery_id"], options?: ConvenienceOptions): Promise<OperationResult<"redeliverWebhookDelivery">>;
1570
+ getHealth(options?: ConvenienceOptions): Promise<OperationResult<"getHealth">>;
1571
+ getApiDiscovery(options?: ConvenienceOptions): Promise<OperationResult<"getApiDiscovery">>;
1572
+ /**
1573
+ * Which V1 reads the API serves for Polymarket (`GET /api/v1/coverage`).
1574
+ * Public: needs no API key.
1575
+ */
1576
+ getCoverage(options?: ConvenienceOptions): Promise<OperationResult<"getCoverage">>;
1577
+ /**
1578
+ * @deprecated Use {@link getCoverage} (#16315); calls the deprecated
1579
+ * `GET /api/v1/platforms`, which serves the same body.
1580
+ */
1581
+ getPlatforms(options?: ConvenienceOptions): Promise<OperationResult<"getPlatforms">>;
1582
+ getAccountIdentity(options?: ConvenienceOptions): Promise<OperationResult<"getAccountIdentity">>;
1583
+ /**
1584
+ * One wallet's context as Markdown, ready to paste into a model prompt
1585
+ * (`GET /api/v1/trader/{address}/context.md`). The JSON form of the same
1586
+ * read is `getTraderContext`.
1587
+ */
1588
+ getTraderContextMarkdown(address: OperationPath["getTraderContextMarkdown"]["address"], options?: Omit<OperationRequestOptions<"getTraderContextMarkdown">, "path">): Promise<string>;
1589
+ /**
1590
+ * One market's context as Markdown
1591
+ * (`GET /api/v1/market/{condition_id}/context.md`). The JSON form is
1592
+ * `getMarketSnapshot`.
1593
+ */
1594
+ getMarketContextMarkdown(conditionId: OperationPath["getMarketContextMarkdown"]["condition_id"], options?: Omit<OperationRequestOptions<"getMarketContextMarkdown">, "path">): Promise<string>;
1595
+ /**
1596
+ * Mint a sandbox key (`POST /api/v1/agents/register`), the one write that
1597
+ * needs no credential. Answers `201`, which is why the SDK had no method
1598
+ * for it until #16137: the drift gate counted only operations with a
1599
+ * documented `200`. `meta.status` is `201`; `data.api_key` is the
1600
+ * `oxi_sk_test_*` key to pass to `OxinsiderApiClient.sandbox()`.
1601
+ *
1602
+ * Nothing is stored: the key cannot be listed or revoked and does not
1603
+ * expire. Register again for another one.
1604
+ */
1605
+ registerAgent(options?: ConvenienceOptions): Promise<OperationResult<"registerAgent">>;
1606
+ getUsage(options?: ConvenienceOptions): Promise<OperationResult<"getUsage">>;
1607
+ /** Fetch today's editorial Pick of the Day (single-object envelope). */
1608
+ getPickOfTheDay(options?: ConvenienceOptions): Promise<OperationResult<"getPickOfTheDay">>;
1609
+ /** Fetch the Pick of the Day archive with hit-rate (single-object envelope). */
1610
+ getPickOfTheDayArchive(options?: ConvenienceOptions): Promise<OperationResult<"getPickOfTheDayArchive">>;
1611
+ /**
1612
+ * Fetch the Pick of the Day commitment ledger (single-object envelope).
1613
+ *
1614
+ * Every entry is `sealed` (a live pick: the hash, no side and no price),
1615
+ * `opened` (a settled pick: the nonce and the exact hashed payload) or
1616
+ * `uncommitted` (no commitment; once settled, its unhashed side and price
1617
+ * under `payload`). Verify an opened entry by
1618
+ * appending the hex-decoded `commitment_nonce` to the `payload` bytes as
1619
+ * received and hashing with sha256; do not reserialize the payload, since it
1620
+ * is served byte for byte as it was hashed.
1621
+ */
1622
+ getPickOfTheDayLedger(options?: ConvenienceOptions): Promise<OperationResult<"getPickOfTheDayLedger">>;
1623
+ /** Resolve the base URL (used by the SSE stream consumer). */
1624
+ getBaseUrl(): string;
1625
+ /** The configured API key, if any (used by the SSE stream consumer). */
1626
+ getApiKey(): string | undefined;
1627
+ /** Whether this client was built in sandbox mode (#16138). */
1628
+ isSandbox(): boolean;
1629
+ /** The resolved fetch implementation (used by the SSE stream consumer). */
1630
+ getFetch(): typeof fetch;
1631
+ buildUrl(operation: ApiClientOperation, options: ApiRequestOptions): string;
1632
+ private buildHeaders;
1633
+ }
1634
+ /**
1635
+ * Narrow a `call()` result to the typed 304. Takes any envelope-shaped
1636
+ * value, so it works on an `OperationResult<K>` (whose `meta` is the
1637
+ * operation's own type) as well as the loose `ApiClientResponse<T>`
1638
+ * (#16136).
1639
+ */
1640
+ export declare function isApiNotModifiedResponse<R extends {
1641
+ object: string;
1642
+ }>(response: R): response is Extract<R, ApiNotModifiedResponse>;
1643
+ export declare function interpolatePath(path: string, params: Partial<Record<string, string | number>>): string;
1644
+ /**
1645
+ * Whether `body` is a list envelope whose control fields the walker can act
1646
+ * on: `object: "list"`, an array `data`, a BOOLEAN `has_more`, and a
1647
+ * `next_cursor` that is a string, `null` or absent (#16246: the check used to
1648
+ * accept any `has_more` that was merely present, so a malformed value could
1649
+ * be coerced into "no more pages" or "more pages" by truthiness).
1650
+ */
1651
+ export declare function isListEnvelope<T>(body: unknown): body is ApiListEnvelope<T>;
1652
+ //# sourceMappingURL=client.d.ts.map