opentool 0.10.5 → 0.12.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,831 @@
1
+ import { createHmac, randomBytes } from 'crypto';
2
+ import { parseUnits } from 'viem';
3
+
4
+ // src/adapters/polymarket/base.ts
5
+ var PolymarketApiError = class extends Error {
6
+ constructor(message, response) {
7
+ super(message);
8
+ this.response = response;
9
+ this.name = "PolymarketApiError";
10
+ }
11
+ };
12
+ var PolymarketAuthError = class extends Error {
13
+ constructor(message) {
14
+ super(message);
15
+ this.name = "PolymarketAuthError";
16
+ }
17
+ };
18
+ var POLYMARKET_ENDPOINTS = {
19
+ gamma: {
20
+ mainnet: "https://gamma-api.polymarket.com",
21
+ testnet: "https://gamma-api.polymarket.com"
22
+ },
23
+ clob: {
24
+ mainnet: "https://clob.polymarket.com",
25
+ testnet: "https://clob.polymarket.com"
26
+ },
27
+ data: {
28
+ mainnet: "https://data-api.polymarket.com",
29
+ testnet: "https://data-api.polymarket.com"
30
+ }
31
+ };
32
+ var POLYMARKET_CHAIN_ID = {
33
+ mainnet: 137,
34
+ testnet: 80002
35
+ };
36
+ var POLYMARKET_EXCHANGE_ADDRESSES = {
37
+ mainnet: {
38
+ ctf: "0x4bfb41d5b3570defd03c39a9a4d8de6bd8b8982e",
39
+ negRisk: "0xc5d563a36ae78145c45a50134d48a1215220f80a"
40
+ },
41
+ testnet: {
42
+ ctf: "0xdfe02eb6733538f8ea35d585af8de5958ad99e40",
43
+ negRisk: "0xdfe02eb6733538f8ea35d585af8de5958ad99e40"
44
+ }
45
+ };
46
+ var POLYMARKET_CLOB_DOMAIN = {
47
+ name: "Polymarket CTF Exchange",
48
+ version: "1"
49
+ };
50
+ var POLYMARKET_CLOB_AUTH_DOMAIN = {
51
+ name: "ClobAuthDomain",
52
+ version: "1"
53
+ };
54
+ var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
55
+ function resolvePolymarketBaseUrl(service, environment) {
56
+ return POLYMARKET_ENDPOINTS[service][environment];
57
+ }
58
+ function assertWalletSigner(wallet) {
59
+ if (!wallet?.account || !wallet.walletClient) {
60
+ throw new Error("Polymarket requires a wallet with signing capabilities.");
61
+ }
62
+ }
63
+ function toDecimalString(value) {
64
+ if (typeof value === "string") return value;
65
+ if (typeof value === "bigint") return value.toString();
66
+ if (!Number.isFinite(value)) {
67
+ throw new Error("Numeric values must be finite.");
68
+ }
69
+ const asString = value.toString();
70
+ if (/e/i.test(asString)) {
71
+ const [mantissa, exponentPart] = asString.split(/e/i);
72
+ const exponent = Number(exponentPart);
73
+ const [integerPart, fractionalPart = ""] = mantissa.split(".");
74
+ if (exponent >= 0) {
75
+ return integerPart + fractionalPart.padEnd(exponent + fractionalPart.length, "0");
76
+ }
77
+ const zeros = "0".repeat(Math.abs(exponent) - 1);
78
+ return `0.${zeros}${integerPart}${fractionalPart}`.replace(/\.0+$/, "");
79
+ }
80
+ return asString;
81
+ }
82
+ function normalizeArrayish(value) {
83
+ if (Array.isArray(value)) return value;
84
+ if (typeof value === "string") {
85
+ const trimmed = value.trim();
86
+ if (!trimmed) return [];
87
+ if (trimmed.startsWith("[")) {
88
+ try {
89
+ const parsed = JSON.parse(trimmed);
90
+ return Array.isArray(parsed) ? parsed : [];
91
+ } catch {
92
+ return [];
93
+ }
94
+ }
95
+ return [trimmed];
96
+ }
97
+ return [];
98
+ }
99
+ function normalizeStringArrayish(value) {
100
+ return normalizeArrayish(value).map((entry) => entry == null ? "" : String(entry).trim()).filter((entry) => entry.length > 0);
101
+ }
102
+ function normalizeNumberArrayish(value) {
103
+ return normalizeArrayish(value).map((entry) => typeof entry === "number" ? entry : Number.parseFloat(String(entry))).filter((entry) => Number.isFinite(entry));
104
+ }
105
+ function normalizeTags(value) {
106
+ if (!Array.isArray(value)) return [];
107
+ const tags = value.map((entry) => {
108
+ if (entry && typeof entry === "object") {
109
+ const record = entry;
110
+ const label = record.label ?? record.id ?? record.tag;
111
+ return label ? String(label).trim() : "";
112
+ }
113
+ return String(entry ?? "").trim();
114
+ }).filter((entry) => entry.length > 0);
115
+ return Array.from(new Set(tags));
116
+ }
117
+ function parseOptionalDate(value) {
118
+ if (!value) return null;
119
+ if (typeof value === "string") {
120
+ const trimmed = value.trim();
121
+ return trimmed.length > 0 ? trimmed : null;
122
+ }
123
+ if (typeof value === "number" && Number.isFinite(value)) {
124
+ const ts = value > 1e12 ? value : value * 1e3;
125
+ const date = new Date(ts);
126
+ return Number.isNaN(date.getTime()) ? null : date.toISOString();
127
+ }
128
+ return null;
129
+ }
130
+ function buildHmacSignature(args) {
131
+ const timestamp = args.timestamp.toString();
132
+ const method = args.method.toUpperCase();
133
+ const path = args.path;
134
+ const body = args.body == null ? "" : typeof args.body === "string" ? args.body : JSON.stringify(args.body);
135
+ const payload = `${timestamp}${method}${path}${body}`;
136
+ const key = Buffer.from(args.secret, "base64");
137
+ return createHmac("sha256", key).update(payload).digest("hex");
138
+ }
139
+ function buildL2Headers(args) {
140
+ const timestamp = args.timestamp ?? Math.floor(Date.now() / 1e3);
141
+ const signature = buildHmacSignature({
142
+ secret: args.credentials.secret,
143
+ timestamp,
144
+ method: args.method,
145
+ path: args.path,
146
+ body: args.body ?? null
147
+ });
148
+ return {
149
+ POLY_ADDRESS: args.address,
150
+ POLY_API_KEY: args.credentials.apiKey,
151
+ POLY_PASSPHRASE: args.credentials.passphrase,
152
+ POLY_TIMESTAMP: timestamp.toString(),
153
+ POLY_SIGNATURE: signature
154
+ };
155
+ }
156
+ async function buildL1Headers(args) {
157
+ assertWalletSigner(args.wallet);
158
+ const timestamp = args.timestamp ?? Math.floor(Date.now() / 1e3);
159
+ const nonce = args.nonce ?? Date.now();
160
+ const chainId = POLYMARKET_CHAIN_ID[args.environment ?? "mainnet"];
161
+ const address = args.wallet.address;
162
+ const message = args.message ?? "Create or derive a Polymarket API key";
163
+ const signature = await args.wallet.walletClient.signTypedData({
164
+ account: args.wallet.account,
165
+ domain: {
166
+ ...POLYMARKET_CLOB_AUTH_DOMAIN,
167
+ chainId
168
+ },
169
+ types: {
170
+ ClobAuth: [
171
+ { name: "address", type: "address" },
172
+ { name: "timestamp", type: "string" },
173
+ { name: "nonce", type: "uint256" },
174
+ { name: "message", type: "string" }
175
+ ]
176
+ },
177
+ primaryType: "ClobAuth",
178
+ message: {
179
+ address,
180
+ timestamp: timestamp.toString(),
181
+ nonce: BigInt(nonce),
182
+ message
183
+ }
184
+ });
185
+ return {
186
+ POLY_ADDRESS: address,
187
+ POLY_TIMESTAMP: timestamp.toString(),
188
+ POLY_NONCE: nonce.toString(),
189
+ POLY_SIGNATURE: signature
190
+ };
191
+ }
192
+ function resolveExchangeAddress(args) {
193
+ if (args.exchangeAddress) return args.exchangeAddress;
194
+ const env = args.environment;
195
+ return args.negRisk ? POLYMARKET_EXCHANGE_ADDRESSES[env].negRisk : POLYMARKET_EXCHANGE_ADDRESSES[env].ctf;
196
+ }
197
+ function parseUintString(value, name) {
198
+ const trimmed = value.trim();
199
+ if (!/^\d+$/.test(trimmed)) {
200
+ throw new Error(`${name} must be a base-10 integer string.`);
201
+ }
202
+ return BigInt(trimmed);
203
+ }
204
+ function buildPolymarketOrderAmounts(args) {
205
+ const priceStr = toDecimalString(args.price);
206
+ const sizeStr = toDecimalString(args.size);
207
+ if (!priceStr || !sizeStr) {
208
+ throw new Error("Order price and size are required.");
209
+ }
210
+ const priceFloat = Number(priceStr);
211
+ if (!Number.isFinite(priceFloat) || priceFloat <= 0 || priceFloat >= 1) {
212
+ throw new Error("Order price must be between 0 and 1 (exclusive).");
213
+ }
214
+ const sizeFloat = Number(sizeStr);
215
+ if (!Number.isFinite(sizeFloat) || sizeFloat <= 0) {
216
+ throw new Error("Order size must be positive.");
217
+ }
218
+ let priceUnits = parseUnits(priceStr, 6);
219
+ if (args.tickSize !== void 0) {
220
+ const tickUnits = parseUnits(toDecimalString(args.tickSize), 6);
221
+ if (tickUnits <= 0n) {
222
+ throw new Error("tickSize must be positive.");
223
+ }
224
+ priceUnits = priceUnits / tickUnits * tickUnits;
225
+ }
226
+ const sizeUnits = parseUnits(sizeStr, 6);
227
+ const quoteUnits = priceUnits * sizeUnits / 1000000n;
228
+ if (args.side === "BUY") {
229
+ return { makerAmount: quoteUnits, takerAmount: sizeUnits };
230
+ }
231
+ return { makerAmount: sizeUnits, takerAmount: quoteUnits };
232
+ }
233
+ async function buildSignedOrderPayload(args) {
234
+ assertWalletSigner(args.wallet);
235
+ const environment = args.environment ?? "mainnet";
236
+ const chainId = POLYMARKET_CHAIN_ID[environment];
237
+ const exchangeAddress = resolveExchangeAddress({
238
+ environment,
239
+ ...args.negRisk !== void 0 ? { negRisk: args.negRisk } : {},
240
+ ...args.exchangeAddress ? { exchangeAddress: args.exchangeAddress } : {}
241
+ });
242
+ const maker = args.maker ?? args.wallet.address;
243
+ const signer = args.signer ?? args.wallet.address;
244
+ const taker = args.taker ?? ZERO_ADDRESS;
245
+ const sideValue = args.side === "BUY" ? 0 : 1;
246
+ const signatureType = args.signatureType ?? 0;
247
+ const tokenIdValue = args.tokenId.startsWith("0x") ? BigInt(args.tokenId) : parseUintString(args.tokenId, "tokenId");
248
+ const { makerAmount, takerAmount } = buildPolymarketOrderAmounts({
249
+ side: args.side,
250
+ price: args.price,
251
+ size: args.size,
252
+ ...args.tickSize !== void 0 ? { tickSize: args.tickSize } : {}
253
+ });
254
+ const salt = BigInt(`0x${randomBytes(16).toString("hex")}`);
255
+ const expiration = BigInt(args.expiration ?? 0);
256
+ const nonce = BigInt(args.nonce ?? 0);
257
+ const feeRateBps = BigInt(args.feeRateBps ?? 0);
258
+ const message = {
259
+ salt,
260
+ maker,
261
+ signer,
262
+ taker,
263
+ tokenId: tokenIdValue,
264
+ makerAmount,
265
+ takerAmount,
266
+ expiration,
267
+ nonce,
268
+ feeRateBps,
269
+ side: sideValue,
270
+ signatureType
271
+ };
272
+ const signature = await args.wallet.walletClient.signTypedData({
273
+ account: args.wallet.account,
274
+ domain: {
275
+ ...POLYMARKET_CLOB_DOMAIN,
276
+ chainId,
277
+ verifyingContract: exchangeAddress
278
+ },
279
+ types: {
280
+ Order: [
281
+ { name: "salt", type: "uint256" },
282
+ { name: "maker", type: "address" },
283
+ { name: "signer", type: "address" },
284
+ { name: "taker", type: "address" },
285
+ { name: "tokenId", type: "uint256" },
286
+ { name: "makerAmount", type: "uint256" },
287
+ { name: "takerAmount", type: "uint256" },
288
+ { name: "expiration", type: "uint256" },
289
+ { name: "nonce", type: "uint256" },
290
+ { name: "feeRateBps", type: "uint256" },
291
+ { name: "side", type: "uint8" },
292
+ { name: "signatureType", type: "uint8" }
293
+ ]
294
+ },
295
+ primaryType: "Order",
296
+ message
297
+ });
298
+ return {
299
+ salt: message.salt.toString(),
300
+ maker,
301
+ signer,
302
+ taker,
303
+ tokenId: tokenIdValue.toString(),
304
+ makerAmount: message.makerAmount.toString(),
305
+ takerAmount: message.takerAmount.toString(),
306
+ expiration: message.expiration.toString(),
307
+ nonce: message.nonce.toString(),
308
+ feeRateBps: message.feeRateBps.toString(),
309
+ side: sideValue,
310
+ signatureType,
311
+ signature
312
+ };
313
+ }
314
+
315
+ // src/adapters/polymarket/exchange.ts
316
+ async function resolveAuthContext(args) {
317
+ if (args.wallet) {
318
+ const credentials = args.credentials ?? await createPolymarketApiKey({
319
+ wallet: args.wallet,
320
+ ...args.environment ? { environment: args.environment } : {}
321
+ });
322
+ return {
323
+ credentials,
324
+ address: args.wallet.address
325
+ };
326
+ }
327
+ if (args.walletAddress && args.credentials) {
328
+ return { credentials: args.credentials, address: args.walletAddress };
329
+ }
330
+ throw new PolymarketAuthError(
331
+ "Polymarket auth requires a wallet (preferred) or credentials + walletAddress."
332
+ );
333
+ }
334
+ async function requestJson(url, init) {
335
+ const response = await fetch(url, init);
336
+ const text = await response.text().catch(() => "");
337
+ let data = null;
338
+ try {
339
+ data = text ? JSON.parse(text) : null;
340
+ } catch {
341
+ data = text;
342
+ }
343
+ if (!response.ok) {
344
+ throw new PolymarketApiError(
345
+ `Polymarket request failed (${response.status}).`,
346
+ data ?? { status: response.status }
347
+ );
348
+ }
349
+ return data;
350
+ }
351
+ function resolvePath(url) {
352
+ const parsed = new URL(url);
353
+ return `${parsed.pathname}${parsed.search}`;
354
+ }
355
+ async function createPolymarketApiKey(args) {
356
+ const environment = args.environment ?? "mainnet";
357
+ const baseUrl = resolvePolymarketBaseUrl("clob", environment);
358
+ const url = `${baseUrl}/auth/api-key`;
359
+ const headers = await buildL1Headers({
360
+ wallet: args.wallet,
361
+ environment,
362
+ ...args.timestamp !== void 0 ? { timestamp: args.timestamp } : {},
363
+ ...args.nonce !== void 0 ? { nonce: args.nonce } : {},
364
+ ...args.message !== void 0 ? { message: args.message } : {}
365
+ });
366
+ const data = await requestJson(url, {
367
+ method: "POST",
368
+ headers: {
369
+ "content-type": "application/json",
370
+ ...headers
371
+ },
372
+ body: JSON.stringify({})
373
+ });
374
+ if (!data?.apiKey || !data?.secret || !data?.passphrase) {
375
+ throw new PolymarketAuthError("Failed to create Polymarket API key.");
376
+ }
377
+ return {
378
+ apiKey: data.apiKey,
379
+ secret: data.secret,
380
+ passphrase: data.passphrase
381
+ };
382
+ }
383
+ async function derivePolymarketApiKey(args) {
384
+ const environment = args.environment ?? "mainnet";
385
+ const baseUrl = resolvePolymarketBaseUrl("clob", environment);
386
+ const url = `${baseUrl}/auth/derive-api-key`;
387
+ const headers = await buildL1Headers({
388
+ wallet: args.wallet,
389
+ environment,
390
+ ...args.timestamp !== void 0 ? { timestamp: args.timestamp } : {},
391
+ ...args.nonce !== void 0 ? { nonce: args.nonce } : {},
392
+ ...args.message !== void 0 ? { message: args.message } : {}
393
+ });
394
+ const data = await requestJson(url, {
395
+ method: "GET",
396
+ headers: {
397
+ "content-type": "application/json",
398
+ ...headers
399
+ }
400
+ });
401
+ if (!data?.apiKey || !data?.secret || !data?.passphrase) {
402
+ throw new PolymarketAuthError("Failed to derive Polymarket API key.");
403
+ }
404
+ return {
405
+ apiKey: data.apiKey,
406
+ secret: data.secret,
407
+ passphrase: data.passphrase
408
+ };
409
+ }
410
+ async function placePolymarketOrder(args) {
411
+ const environment = args.environment ?? "mainnet";
412
+ const baseUrl = resolvePolymarketBaseUrl("clob", environment);
413
+ const url = `${baseUrl}/order`;
414
+ const signedOrder = await buildSignedOrderPayload({
415
+ wallet: args.wallet,
416
+ environment,
417
+ ...args.order
418
+ });
419
+ const auth = await resolveAuthContext({
420
+ wallet: args.wallet,
421
+ ...args.credentials ? { credentials: args.credentials } : {},
422
+ environment
423
+ });
424
+ const body = {
425
+ order: signedOrder,
426
+ owner: auth.credentials.apiKey,
427
+ orderType: args.orderType ?? "GTC"
428
+ };
429
+ const headers = buildL2Headers({
430
+ credentials: auth.credentials,
431
+ address: auth.address,
432
+ method: "POST",
433
+ path: resolvePath(url),
434
+ body
435
+ });
436
+ return await requestJson(url, {
437
+ method: "POST",
438
+ headers: {
439
+ "content-type": "application/json",
440
+ ...headers
441
+ },
442
+ body: JSON.stringify(body)
443
+ });
444
+ }
445
+ async function cancelPolymarketOrder(args) {
446
+ const environment = args.environment ?? "mainnet";
447
+ const baseUrl = resolvePolymarketBaseUrl("clob", environment);
448
+ const url = `${baseUrl}/order`;
449
+ const body = { orderID: args.orderId };
450
+ const auth = await resolveAuthContext({
451
+ ...args.wallet ? { wallet: args.wallet } : {},
452
+ ...args.walletAddress ? { walletAddress: args.walletAddress } : {},
453
+ ...args.credentials ? { credentials: args.credentials } : {},
454
+ environment
455
+ });
456
+ const headers = buildL2Headers({
457
+ credentials: auth.credentials,
458
+ address: auth.address,
459
+ method: "DELETE",
460
+ path: resolvePath(url),
461
+ body
462
+ });
463
+ return await requestJson(url, {
464
+ method: "DELETE",
465
+ headers: {
466
+ "content-type": "application/json",
467
+ ...headers
468
+ },
469
+ body: JSON.stringify(body)
470
+ });
471
+ }
472
+ async function cancelPolymarketOrders(args) {
473
+ const environment = args.environment ?? "mainnet";
474
+ const baseUrl = resolvePolymarketBaseUrl("clob", environment);
475
+ const url = `${baseUrl}/orders`;
476
+ const body = { orderIDs: args.orderIds };
477
+ const auth = await resolveAuthContext({
478
+ ...args.wallet ? { wallet: args.wallet } : {},
479
+ ...args.walletAddress ? { walletAddress: args.walletAddress } : {},
480
+ ...args.credentials ? { credentials: args.credentials } : {},
481
+ environment
482
+ });
483
+ const headers = buildL2Headers({
484
+ credentials: auth.credentials,
485
+ address: auth.address,
486
+ method: "DELETE",
487
+ path: resolvePath(url),
488
+ body
489
+ });
490
+ return await requestJson(url, {
491
+ method: "DELETE",
492
+ headers: {
493
+ "content-type": "application/json",
494
+ ...headers
495
+ },
496
+ body: JSON.stringify(body)
497
+ });
498
+ }
499
+ async function cancelAllPolymarketOrders(args) {
500
+ const environment = args.environment ?? "mainnet";
501
+ const baseUrl = resolvePolymarketBaseUrl("clob", environment);
502
+ const url = `${baseUrl}/cancel-all`;
503
+ const auth = await resolveAuthContext({
504
+ ...args.wallet ? { wallet: args.wallet } : {},
505
+ ...args.walletAddress ? { walletAddress: args.walletAddress } : {},
506
+ ...args.credentials ? { credentials: args.credentials } : {},
507
+ environment
508
+ });
509
+ const headers = buildL2Headers({
510
+ credentials: auth.credentials,
511
+ address: auth.address,
512
+ method: "DELETE",
513
+ path: resolvePath(url)
514
+ });
515
+ return await requestJson(url, {
516
+ method: "DELETE",
517
+ headers: {
518
+ "content-type": "application/json",
519
+ ...headers
520
+ }
521
+ });
522
+ }
523
+ async function cancelMarketPolymarketOrders(args) {
524
+ const environment = args.environment ?? "mainnet";
525
+ const baseUrl = resolvePolymarketBaseUrl("clob", environment);
526
+ const url = `${baseUrl}/cancel-market-orders`;
527
+ const body = { market: args.tokenId };
528
+ const auth = await resolveAuthContext({
529
+ ...args.wallet ? { wallet: args.wallet } : {},
530
+ ...args.walletAddress ? { walletAddress: args.walletAddress } : {},
531
+ ...args.credentials ? { credentials: args.credentials } : {},
532
+ environment
533
+ });
534
+ const headers = buildL2Headers({
535
+ credentials: auth.credentials,
536
+ address: auth.address,
537
+ method: "DELETE",
538
+ path: resolvePath(url),
539
+ body
540
+ });
541
+ return await requestJson(url, {
542
+ method: "DELETE",
543
+ headers: {
544
+ "content-type": "application/json",
545
+ ...headers
546
+ },
547
+ body: JSON.stringify(body)
548
+ });
549
+ }
550
+ var PolymarketExchangeClient = class {
551
+ constructor(args) {
552
+ this.wallet = args.wallet;
553
+ this.credentials = args.credentials;
554
+ this.environment = args.environment ?? "mainnet";
555
+ }
556
+ async getCredentials() {
557
+ if (this.cachedCredentials) return this.cachedCredentials;
558
+ const resolved = await resolveAuthContext({
559
+ wallet: this.wallet,
560
+ ...this.credentials ? { credentials: this.credentials } : {},
561
+ environment: this.environment
562
+ });
563
+ this.cachedCredentials = resolved.credentials;
564
+ return resolved.credentials;
565
+ }
566
+ async placeOrder(order, orderType) {
567
+ const credentials = await this.getCredentials();
568
+ return placePolymarketOrder({
569
+ wallet: this.wallet,
570
+ credentials,
571
+ environment: this.environment,
572
+ order,
573
+ ...orderType !== void 0 ? { orderType } : {}
574
+ });
575
+ }
576
+ async cancelOrder(orderId) {
577
+ const credentials = await this.getCredentials();
578
+ return cancelPolymarketOrder({
579
+ orderId,
580
+ wallet: this.wallet,
581
+ credentials,
582
+ environment: this.environment
583
+ });
584
+ }
585
+ async cancelOrders(orderIds) {
586
+ const credentials = await this.getCredentials();
587
+ return cancelPolymarketOrders({
588
+ orderIds,
589
+ wallet: this.wallet,
590
+ credentials,
591
+ environment: this.environment
592
+ });
593
+ }
594
+ async cancelAll() {
595
+ const credentials = await this.getCredentials();
596
+ return cancelAllPolymarketOrders({
597
+ wallet: this.wallet,
598
+ credentials,
599
+ environment: this.environment
600
+ });
601
+ }
602
+ async cancelMarket(tokenId) {
603
+ const credentials = await this.getCredentials();
604
+ return cancelMarketPolymarketOrders({
605
+ tokenId,
606
+ wallet: this.wallet,
607
+ credentials,
608
+ environment: this.environment
609
+ });
610
+ }
611
+ };
612
+
613
+ // src/adapters/polymarket/info.ts
614
+ var DEFAULT_EVENT_LIMIT = 50;
615
+ async function requestJson2(url, init) {
616
+ const response = await fetch(url, init);
617
+ const text = await response.text().catch(() => "");
618
+ let data = null;
619
+ try {
620
+ data = text ? JSON.parse(text) : null;
621
+ } catch {
622
+ data = text;
623
+ }
624
+ if (!response.ok) {
625
+ throw new PolymarketApiError(
626
+ `Polymarket request failed (${response.status}).`,
627
+ data ?? { status: response.status }
628
+ );
629
+ }
630
+ return data;
631
+ }
632
+ function getString(value) {
633
+ if (value == null) return null;
634
+ const str = String(value).trim();
635
+ return str.length ? str : null;
636
+ }
637
+ function normalizeOrderbookLevels(raw) {
638
+ if (!Array.isArray(raw)) return [];
639
+ return raw.map((entry) => {
640
+ if (Array.isArray(entry)) {
641
+ const [price, size] = entry;
642
+ const p = Number(price);
643
+ const s = Number(size);
644
+ if (!Number.isFinite(p) || !Number.isFinite(s)) return null;
645
+ return { price: p, size: s };
646
+ }
647
+ if (entry && typeof entry === "object") {
648
+ const record = entry;
649
+ const p = Number(record.price ?? record.p);
650
+ const s = Number(record.size ?? record.s ?? record.quantity);
651
+ if (!Number.isFinite(p) || !Number.isFinite(s)) return null;
652
+ return { price: p, size: s };
653
+ }
654
+ return null;
655
+ }).filter((entry) => Boolean(entry));
656
+ }
657
+ function normalizeGammaMarket(market, event) {
658
+ const eventTags = normalizeTags(event?.tags);
659
+ const marketTags = normalizeTags(market.tags);
660
+ const mergedTags = Array.from(/* @__PURE__ */ new Set([...marketTags, ...eventTags]));
661
+ const category = getString(market.category) ?? getString(event?.category) ?? getString(event?.title) ?? null;
662
+ const normalized = {
663
+ id: getString(market.id) ?? "",
664
+ slug: getString(market.slug),
665
+ question: getString(market.question),
666
+ description: getString(market.description),
667
+ eventId: getString(market.eventId ?? event?.id),
668
+ eventSlug: getString(event?.slug),
669
+ conditionId: getString(market.conditionId),
670
+ marketMakerAddress: getString(market.marketMakerAddress),
671
+ category,
672
+ startDate: parseOptionalDate(market.startDate) ?? parseOptionalDate(event?.startDate) ?? parseOptionalDate(event?.eventStartTime),
673
+ endDate: parseOptionalDate(market.endDate) ?? parseOptionalDate(event?.endDate) ?? parseOptionalDate(event?.eventEndTime),
674
+ createdAt: parseOptionalDate(market.createdAt) ?? parseOptionalDate(event?.createdAt) ?? parseOptionalDate(event?.creationDate),
675
+ updatedAt: parseOptionalDate(market.updatedAt) ?? parseOptionalDate(event?.updatedAt),
676
+ closedTime: parseOptionalDate(market.closedTime) ?? parseOptionalDate(event?.closedTime),
677
+ volume: getString(market.volume),
678
+ liquidity: getString(market.liquidity),
679
+ openInterest: getString(market.openInterest),
680
+ outcomes: normalizeStringArrayish(market.outcomes),
681
+ outcomePrices: normalizeNumberArrayish(market.outcomePrices),
682
+ clobTokenIds: normalizeStringArrayish(market.clobTokenIds),
683
+ icon: getString(market.icon),
684
+ image: getString(market.image)
685
+ };
686
+ if (mergedTags.length) {
687
+ normalized.tags = mergedTags;
688
+ }
689
+ if (typeof market.active === "boolean") {
690
+ normalized.active = market.active;
691
+ }
692
+ if (typeof market.closed === "boolean") {
693
+ normalized.closed = market.closed;
694
+ }
695
+ if (typeof market.resolved === "boolean") {
696
+ normalized.resolved = market.resolved;
697
+ }
698
+ return normalized;
699
+ }
700
+ var PolymarketInfoClient = class {
701
+ constructor(environment = "mainnet") {
702
+ this.environment = environment;
703
+ }
704
+ markets(params = {}) {
705
+ return fetchPolymarketMarkets({ ...params, environment: this.environment });
706
+ }
707
+ market(params) {
708
+ return fetchPolymarketMarket({ ...params, environment: this.environment });
709
+ }
710
+ orderbook(tokenId) {
711
+ return fetchPolymarketOrderbook({ tokenId, environment: this.environment });
712
+ }
713
+ price(tokenId, side) {
714
+ return fetchPolymarketPrice({ tokenId, side, environment: this.environment });
715
+ }
716
+ midpoint(tokenId) {
717
+ return fetchPolymarketMidpoint({ tokenId, environment: this.environment });
718
+ }
719
+ priceHistory(params) {
720
+ return fetchPolymarketPriceHistory({ ...params, environment: this.environment });
721
+ }
722
+ };
723
+ async function fetchPolymarketMarkets(params = {}) {
724
+ if (params.active !== void 0 && params.active !== true) {
725
+ throw new Error("Polymarket market list requires active=true.");
726
+ }
727
+ if (params.closed !== void 0 && params.closed !== false) {
728
+ throw new Error("Polymarket market list requires closed=false.");
729
+ }
730
+ const environment = params.environment ?? "mainnet";
731
+ const baseUrl = resolvePolymarketBaseUrl("gamma", environment);
732
+ const url = new URL("/events", baseUrl);
733
+ const limit = params.limit ?? DEFAULT_EVENT_LIMIT;
734
+ const offset = params.offset ?? 0;
735
+ url.searchParams.set("limit", String(limit));
736
+ url.searchParams.set("offset", String(offset));
737
+ url.searchParams.set("active", "true");
738
+ url.searchParams.set("closed", "false");
739
+ url.searchParams.set("order", params.order ?? "id");
740
+ url.searchParams.set("ascending", params.ascending ? "true" : "false");
741
+ if (params.tagId) url.searchParams.set("tag_id", params.tagId);
742
+ if (params.relatedTags) url.searchParams.set("related_tags", "true");
743
+ if (params.excludeTagId) url.searchParams.set("exclude_tag_id", params.excludeTagId);
744
+ if (params.slug) url.searchParams.set("slug", params.slug);
745
+ const data = await requestJson2(url.toString());
746
+ const markets = data.flatMap(
747
+ (event) => Array.isArray(event?.markets) ? event.markets.map((market) => normalizeGammaMarket(market, event)) : []
748
+ );
749
+ const filtered = params.category ? markets.filter(
750
+ (market) => (market.category ?? "").toLowerCase().includes(params.category.toLowerCase())
751
+ ) : markets;
752
+ return typeof params.limit === "number" ? filtered.slice(0, params.limit) : filtered;
753
+ }
754
+ async function fetchPolymarketMarket(params) {
755
+ const environment = params.environment ?? "mainnet";
756
+ const baseUrl = resolvePolymarketBaseUrl("gamma", environment);
757
+ if (params.slug) {
758
+ const url = new URL(`/markets/slug/${params.slug}`, baseUrl);
759
+ const data = await requestJson2(url.toString());
760
+ if (!data) return null;
761
+ return normalizeGammaMarket(data);
762
+ }
763
+ if (params.id) {
764
+ const url = new URL(`/markets/${params.id}`, baseUrl);
765
+ const data = await requestJson2(url.toString());
766
+ if (!data) return null;
767
+ return normalizeGammaMarket(data);
768
+ }
769
+ if (params.conditionId) {
770
+ const url = new URL(`/markets`, baseUrl);
771
+ url.searchParams.set("condition_id", params.conditionId);
772
+ const data = await requestJson2(url.toString());
773
+ if (!data) return null;
774
+ const market = Array.isArray(data) ? data[0] : data;
775
+ return market ? normalizeGammaMarket(market) : null;
776
+ }
777
+ throw new Error("id, slug, or conditionId is required.");
778
+ }
779
+ async function fetchPolymarketOrderbook(params) {
780
+ const environment = params.environment ?? "mainnet";
781
+ const baseUrl = resolvePolymarketBaseUrl("clob", environment);
782
+ const url = new URL("/book", baseUrl);
783
+ url.searchParams.set("token_id", params.tokenId);
784
+ const data = await requestJson2(url.toString());
785
+ return {
786
+ market: params.tokenId,
787
+ bids: normalizeOrderbookLevels(data.bids),
788
+ asks: normalizeOrderbookLevels(data.asks),
789
+ timestamp: getString(data.timestamp)
790
+ };
791
+ }
792
+ async function fetchPolymarketPrice(params) {
793
+ const environment = params.environment ?? "mainnet";
794
+ const baseUrl = resolvePolymarketBaseUrl("clob", environment);
795
+ const url = new URL("/price", baseUrl);
796
+ url.searchParams.set("token_id", params.tokenId);
797
+ url.searchParams.set("side", params.side);
798
+ const data = await requestJson2(url.toString());
799
+ const price = Number(data.price ?? data?.p);
800
+ return Number.isFinite(price) ? price : null;
801
+ }
802
+ async function fetchPolymarketMidpoint(params) {
803
+ const baseArgs = {
804
+ tokenId: params.tokenId,
805
+ ...params.environment ? { environment: params.environment } : {}
806
+ };
807
+ const buy = await fetchPolymarketPrice({ ...baseArgs, side: "BUY" });
808
+ const sell = await fetchPolymarketPrice({ ...baseArgs, side: "SELL" });
809
+ if (buy == null || sell == null) return null;
810
+ return (buy + sell) / 2;
811
+ }
812
+ async function fetchPolymarketPriceHistory(params) {
813
+ const environment = params.environment ?? "mainnet";
814
+ const baseUrl = resolvePolymarketBaseUrl("clob", environment);
815
+ const url = new URL("/prices-history", baseUrl);
816
+ url.searchParams.set("market", params.tokenId);
817
+ if (params.startTs) url.searchParams.set("startTs", params.startTs.toString());
818
+ if (params.endTs) url.searchParams.set("endTs", params.endTs.toString());
819
+ if (params.interval) url.searchParams.set("interval", params.interval);
820
+ if (params.fidelity) url.searchParams.set("fidelity", params.fidelity.toString());
821
+ const data = await requestJson2(url.toString());
822
+ const points = Array.isArray(data) ? data : data?.history ?? [];
823
+ return points.map((point) => ({
824
+ t: Number(point.t),
825
+ p: Number(point.p)
826
+ })).filter((point) => Number.isFinite(point.t) && Number.isFinite(point.p));
827
+ }
828
+
829
+ export { POLYMARKET_CHAIN_ID, POLYMARKET_CLOB_AUTH_DOMAIN, POLYMARKET_CLOB_DOMAIN, POLYMARKET_ENDPOINTS, POLYMARKET_EXCHANGE_ADDRESSES, PolymarketApiError, PolymarketAuthError, PolymarketExchangeClient, PolymarketInfoClient, buildHmacSignature, buildL1Headers, buildL2Headers, buildPolymarketOrderAmounts, buildSignedOrderPayload, cancelAllPolymarketOrders, cancelMarketPolymarketOrders, cancelPolymarketOrder, cancelPolymarketOrders, createPolymarketApiKey, derivePolymarketApiKey, fetchPolymarketMarket, fetchPolymarketMarkets, fetchPolymarketMidpoint, fetchPolymarketOrderbook, fetchPolymarketPrice, fetchPolymarketPriceHistory, normalizeNumberArrayish, normalizeStringArrayish, placePolymarketOrder, resolveExchangeAddress, resolvePolymarketBaseUrl };
830
+ //# sourceMappingURL=index.js.map
831
+ //# sourceMappingURL=index.js.map