polyedge 0.0.0-stage → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,643 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ AccountService: () => AccountService,
24
+ AnalyticsService: () => AnalyticsService,
25
+ PolyEdgeClient: () => PolyEdgeClient,
26
+ PolyEdgeStream: () => PolyEdgeStream,
27
+ StreamsService: () => StreamsService,
28
+ SubscriptionService: () => SubscriptionService
29
+ });
30
+ module.exports = __toCommonJS(index_exports);
31
+
32
+ // src/stream.ts
33
+ var import_node_events = require("events");
34
+ var PolyEdgeStream = class extends import_node_events.EventEmitter {
35
+ streamId;
36
+ apiKey;
37
+ streamBaseUrl;
38
+ heartbeatTimeoutMs;
39
+ initialBackoffMs;
40
+ maxBackoffMs;
41
+ lastEventId = null;
42
+ abortController = null;
43
+ watchdogTimer = null;
44
+ reconnectTimer = null;
45
+ reconnectAttempts = 0;
46
+ isDestroyed = false;
47
+ isConnecting = false;
48
+ // Queue for async iterator support
49
+ asyncQueue = [];
50
+ asyncResolvers = [];
51
+ constructor(streamId, options) {
52
+ super();
53
+ if (!streamId || typeof streamId !== "string") {
54
+ throw new Error("PolyEdgeStream: streamId must be a non-empty string");
55
+ }
56
+ if (!options.apiKey || typeof options.apiKey !== "string") {
57
+ throw new Error("PolyEdgeStream: apiKey must be a non-empty string");
58
+ }
59
+ this.streamId = streamId;
60
+ this.apiKey = options.apiKey;
61
+ this.streamBaseUrl = (options.streamBaseUrl || "https://stream.polyedge.dev").replace(/\/+$/, "");
62
+ this.heartbeatTimeoutMs = options.heartbeatTimeoutMs ?? 45e3;
63
+ this.initialBackoffMs = options.initialBackoffMs ?? 1e3;
64
+ this.maxBackoffMs = options.maxBackoffMs ?? 3e4;
65
+ }
66
+ getLastEventId() {
67
+ return this.lastEventId;
68
+ }
69
+ connect() {
70
+ if (this.isDestroyed || this.isConnecting) return;
71
+ this.isConnecting = true;
72
+ this.clearTimers();
73
+ this.abortController = new AbortController();
74
+ const currentSignal = this.abortController.signal;
75
+ const streamUrl = new URL(`${this.streamBaseUrl}/streams/${this.streamId}`);
76
+ if (this.lastEventId) {
77
+ streamUrl.searchParams.set("lastEventId", this.lastEventId);
78
+ }
79
+ const headers = {
80
+ Accept: "text/event-stream",
81
+ "X-PolyEdge-Key": this.apiKey,
82
+ "Cache-Control": "no-cache"
83
+ };
84
+ if (this.lastEventId) {
85
+ headers["Last-Event-ID"] = this.lastEventId;
86
+ }
87
+ this.startWatchdog();
88
+ (async () => {
89
+ try {
90
+ const response = await fetch(streamUrl.toString(), {
91
+ method: "GET",
92
+ headers,
93
+ signal: currentSignal
94
+ });
95
+ if (!response.ok) {
96
+ const errText = await response.text().catch(() => "");
97
+ const errMsg = `Stream connection failed with HTTP ${response.status}: ${errText}`;
98
+ const err = new Error(errMsg);
99
+ if ([400, 401, 403, 404].includes(response.status)) {
100
+ this.pushAsync({ err });
101
+ this.emit("error", err);
102
+ this.destroy("fatal_http_status");
103
+ return;
104
+ }
105
+ throw err;
106
+ }
107
+ if (!response.body) {
108
+ throw new Error("Response body is null, expected text/event-stream stream");
109
+ }
110
+ this.reconnectAttempts = 0;
111
+ this.isConnecting = false;
112
+ const reader = response.body.getReader();
113
+ const decoder = new TextDecoder("utf-8");
114
+ let buffer = "";
115
+ while (!this.isDestroyed) {
116
+ const { done, value } = await reader.read();
117
+ if (done) break;
118
+ this.resetWatchdog();
119
+ buffer += decoder.decode(value, { stream: true });
120
+ const blocks = buffer.split("\n\n");
121
+ buffer = blocks.pop() ?? "";
122
+ for (const block of blocks) {
123
+ this.parseBlock(block);
124
+ }
125
+ }
126
+ if (!this.isDestroyed) {
127
+ this.scheduleReconnect("stream_eos");
128
+ }
129
+ } catch (err) {
130
+ if (this.isDestroyed || currentSignal.aborted) return;
131
+ this.emit("error", err instanceof Error ? err : new Error(String(err)));
132
+ this.scheduleReconnect("network_error");
133
+ } finally {
134
+ this.isConnecting = false;
135
+ }
136
+ })();
137
+ }
138
+ parseBlock(block) {
139
+ const trimmed = block.trim();
140
+ if (!trimmed) return;
141
+ if (trimmed.startsWith(":")) {
142
+ this.emit("heartbeat");
143
+ return;
144
+ }
145
+ const lines = trimmed.split("\n");
146
+ let eventId = null;
147
+ let eventType = "message";
148
+ const dataLines = [];
149
+ for (const rawLine of lines) {
150
+ const line = rawLine.trim();
151
+ if (line.startsWith(":")) {
152
+ continue;
153
+ } else if (line.startsWith("id:")) {
154
+ eventId = line.slice(3).trim();
155
+ } else if (line.startsWith("event:")) {
156
+ eventType = line.slice(6).trim();
157
+ } else if (line.startsWith("data:")) {
158
+ dataLines.push(rawLine.slice(rawLine.indexOf("data:") + 5).trimStart());
159
+ }
160
+ }
161
+ if (eventId) {
162
+ this.lastEventId = eventId;
163
+ }
164
+ if (eventType === "tx" && dataLines.length > 0) {
165
+ const payloadStr = dataLines.join("\n");
166
+ try {
167
+ const tx = JSON.parse(payloadStr);
168
+ this.pushAsync({ tx });
169
+ this.emit("tx", tx, this.lastEventId ?? "");
170
+ } catch (err) {
171
+ this.emit("error", new Error(`Failed to parse LiveTransaction JSON: ${String(err)}`));
172
+ }
173
+ }
174
+ }
175
+ startWatchdog() {
176
+ this.clearWatchdog();
177
+ this.watchdogTimer = setTimeout(() => {
178
+ this.emit("error", new Error(`SSE Watchdog timed out after ${this.heartbeatTimeoutMs}ms with no bytes/heartbeat received`));
179
+ this.abortController?.abort();
180
+ this.scheduleReconnect("watchdog_timeout");
181
+ }, this.heartbeatTimeoutMs);
182
+ }
183
+ resetWatchdog() {
184
+ if (!this.isDestroyed) {
185
+ this.startWatchdog();
186
+ }
187
+ }
188
+ clearWatchdog() {
189
+ if (this.watchdogTimer) {
190
+ clearTimeout(this.watchdogTimer);
191
+ this.watchdogTimer = null;
192
+ }
193
+ }
194
+ clearTimers() {
195
+ this.clearWatchdog();
196
+ if (this.reconnectTimer) {
197
+ clearTimeout(this.reconnectTimer);
198
+ this.reconnectTimer = null;
199
+ }
200
+ }
201
+ scheduleReconnect(reason) {
202
+ if (this.isDestroyed) return;
203
+ this.clearTimers();
204
+ this.isConnecting = false;
205
+ this.reconnectAttempts++;
206
+ const exponential = Math.min(
207
+ this.maxBackoffMs,
208
+ this.initialBackoffMs * Math.pow(2, this.reconnectAttempts - 1)
209
+ );
210
+ const jitter = exponential * (0.8 + Math.random() * 0.4);
211
+ const delayMs = Math.round(jitter);
212
+ this.emit("reconnect", this.reconnectAttempts, delayMs);
213
+ this.reconnectTimer = setTimeout(() => {
214
+ this.connect();
215
+ }, delayMs);
216
+ }
217
+ pushAsync(item) {
218
+ this.asyncQueue.push(item);
219
+ const resolver = this.asyncResolvers.shift();
220
+ if (resolver) resolver();
221
+ }
222
+ async *[Symbol.asyncIterator]() {
223
+ if (!this.isConnecting && !this.abortController && !this.isDestroyed) {
224
+ this.connect();
225
+ }
226
+ try {
227
+ while (!this.isDestroyed) {
228
+ while (this.asyncQueue.length > 0) {
229
+ const item = this.asyncQueue.shift();
230
+ if (item.err) throw item.err;
231
+ if (item.done) return;
232
+ if (item.tx) yield item.tx;
233
+ }
234
+ await new Promise((resolve) => {
235
+ this.asyncResolvers.push(resolve);
236
+ });
237
+ }
238
+ } finally {
239
+ this.destroy("async_iterator_break");
240
+ }
241
+ }
242
+ destroy(reason = "client_destroyed") {
243
+ if (this.isDestroyed) return;
244
+ this.isDestroyed = true;
245
+ this.isConnecting = false;
246
+ this.clearTimers();
247
+ if (this.abortController) {
248
+ this.abortController.abort();
249
+ this.abortController = null;
250
+ }
251
+ this.pushAsync({ done: true });
252
+ this.emit("close", reason);
253
+ this.removeAllListeners();
254
+ }
255
+ };
256
+
257
+ // src/client.ts
258
+ var StreamsService = class {
259
+ request;
260
+ apiBaseUrl;
261
+ streamBaseUrl;
262
+ apiKey;
263
+ constructor(request, apiBaseUrl, streamBaseUrl, apiKey) {
264
+ this.request = request;
265
+ this.apiBaseUrl = apiBaseUrl;
266
+ this.streamBaseUrl = streamBaseUrl;
267
+ this.apiKey = apiKey;
268
+ }
269
+ /**
270
+ * Connect to real-time Server-Sent Events (SSE) order execution stream
271
+ * @param streamId Target stream ID
272
+ */
273
+ connect(streamId, options = {}) {
274
+ const s = new PolyEdgeStream(streamId, {
275
+ apiKey: this.apiKey,
276
+ streamBaseUrl: this.streamBaseUrl,
277
+ ...options
278
+ });
279
+ queueMicrotask(() => s.connect());
280
+ return s;
281
+ }
282
+ /**
283
+ * List User Streams
284
+ * Returns custom and managed real-time trade streams configured by the user.
285
+ * @returns Models.UserStreamsResponse
286
+ */
287
+ async list() {
288
+ return this.request(this.streamBaseUrl, `/streams`, { method: "GET" });
289
+ }
290
+ /**
291
+ * Create Filtered Order Stream
292
+ * Provisions a new custom real-time stream with optional address, tag, or series filters.
293
+ * @param req Request payload
294
+ * @returns Models.UserStreamResponse
295
+ */
296
+ async create(req) {
297
+ return this.request(this.streamBaseUrl, `/streams`, { method: "POST", body: JSON.stringify(req) });
298
+ }
299
+ /**
300
+ * Get Stream Metadata
301
+ * Fetches metadata, active sessions count, and filter configuration for a specific stream.
302
+ * @param id Stream unique ID
303
+ * @returns Models.UserStreamResponse
304
+ */
305
+ async get(id) {
306
+ return this.request(this.streamBaseUrl, `/streams/${id}/meta`, { method: "GET" });
307
+ }
308
+ /**
309
+ * Delete Stream
310
+ * Permanently removes a stream and gracefully disconnects all connected listener sessions.
311
+ * @param id Stream unique ID
312
+ * @returns Models.DeleteStreamResponse
313
+ */
314
+ async delete(id) {
315
+ return this.request(this.streamBaseUrl, `/streams/${id}`, { method: "DELETE" });
316
+ }
317
+ /**
318
+ * Update Stream Metadata
319
+ * Updates operational attributes of the stream, such as nickname or enabled/disabled status.
320
+ * @param id Stream unique ID
321
+ * @param req Request payload
322
+ * @returns Models.UserStreamResponse
323
+ */
324
+ async updateMetadata(id, req) {
325
+ return this.request(this.streamBaseUrl, `/streams/${id}/meta`, { method: "PUT", body: JSON.stringify(req) });
326
+ }
327
+ /**
328
+ * Update Stream Filter Subscription
329
+ * Dynamically mutates monitored wallet addresses, market tags, or series slugs without disconnecting SSE clients.
330
+ * @param id Stream unique ID
331
+ * @param req Request payload
332
+ * @returns Models.UserStreamResponse
333
+ */
334
+ async updateSubscription(id, req) {
335
+ return this.request(this.streamBaseUrl, `/streams/${id}/subscription`, { method: "PUT", body: JSON.stringify(req) });
336
+ }
337
+ /**
338
+ * List All User Active Sessions
339
+ * Returns all currently connected active SSE listeners for this account.
340
+ * @returns Models.UserActiveSessionsResponse
341
+ */
342
+ async getActiveSessions() {
343
+ return this.request(this.streamBaseUrl, `/sessions`, { method: "GET" });
344
+ }
345
+ /**
346
+ * Disconnect User Stream Connection
347
+ * Terminates an active SSE stream connection owned by this account, identified by its conn_id from getActiveSessions.
348
+ * @param id Connection ID (conn_...)
349
+ * @returns Models.UserDisconnectSessionResponse
350
+ */
351
+ async disconnectSession(id) {
352
+ return this.request(this.streamBaseUrl, `/sessions/${id}`, { method: "DELETE" });
353
+ }
354
+ /**
355
+ * List User Stream Session History
356
+ * Returns historical SSE connection logs including duration and pushed transactions count.
357
+ * @param params.limit Max records to return
358
+ * @param params.offset Pagination offset
359
+ * @returns Models.UserSessionHistoryResponse
360
+ */
361
+ async getSessionHistory(params = {}) {
362
+ const query = new URLSearchParams();
363
+ if (params.limit !== void 0) query.set("limit", String(params.limit));
364
+ if (params.offset !== void 0) query.set("offset", String(params.offset));
365
+ const qs = query.toString() ? `?${query.toString()}` : "";
366
+ return this.request(this.streamBaseUrl, `/sessions/history${qs}`, { method: "GET" });
367
+ }
368
+ };
369
+ var AnalyticsService = class {
370
+ request;
371
+ apiBaseUrl;
372
+ streamBaseUrl;
373
+ apiKey;
374
+ constructor(request, apiBaseUrl, streamBaseUrl, apiKey) {
375
+ this.request = request;
376
+ this.apiBaseUrl = apiBaseUrl;
377
+ this.streamBaseUrl = streamBaseUrl;
378
+ this.apiKey = apiKey;
379
+ }
380
+ /**
381
+ * 60-Day Trader Deposit Analytics
382
+ * Returns 60-day aggregated deposit summary and individual transaction breakdown for top traders.
383
+ * @param params.limit Max records to return
384
+ * @param params.offset Pagination offset
385
+ * @returns Models.DepositQueryResult
386
+ */
387
+ async getDeposits(params = {}) {
388
+ const query = new URLSearchParams();
389
+ if (params.limit !== void 0) query.set("limit", String(params.limit));
390
+ if (params.offset !== void 0) query.set("offset", String(params.offset));
391
+ const qs = query.toString() ? `?${query.toString()}` : "";
392
+ return this.request(this.apiBaseUrl, `/v2/analytics/deposits${qs}`, { method: "GET" });
393
+ }
394
+ /**
395
+ * Top Traders PnL Leaderboard
396
+ * Queries ranked traders across timeframes with PnL, volume, win rate, and performance metrics.
397
+ * @param params.limit Max traders to return
398
+ * @param params.offset Pagination offset
399
+ * @returns Models.LeaderboardResponse
400
+ */
401
+ async getLeaderboard(params = {}) {
402
+ const query = new URLSearchParams();
403
+ if (params.limit !== void 0) query.set("limit", String(params.limit));
404
+ if (params.offset !== void 0) query.set("offset", String(params.offset));
405
+ const qs = query.toString() ? `?${query.toString()}` : "";
406
+ return this.request(this.apiBaseUrl, `/v2/analytics/leaderboard${qs}`, { method: "GET" });
407
+ }
408
+ /**
409
+ * Get Prediction Market Detail
410
+ * Fetches standardized market metadata matching on-chain condition IDs and NegRisk parameters.
411
+ * @param id Market numeric ID or condition ID
412
+ * @returns Models.MarketDetailResponse
413
+ */
414
+ async getMarket(id) {
415
+ return this.request(this.apiBaseUrl, `/v2/markets/${id}`, { method: "GET" });
416
+ }
417
+ /**
418
+ * Get Trader Intelligence Profile
419
+ * Fetches trader identity dossier, pUSD balance, total PnL, win rates, and ranking metrics.
420
+ * @param address Trader Polygon/Ethereum wallet address
421
+ * @returns Models.TraderProfileResponse
422
+ */
423
+ async getTrader(address) {
424
+ return this.request(this.apiBaseUrl, `/v2/traders/${address}`, { method: "GET" });
425
+ }
426
+ /**
427
+ * Get Hourly PnL Equity Curve
428
+ * Provides 1-hour bucketed historical equity curves and trade metrics for a specific trader.
429
+ * @param address Trader Polygon/Ethereum wallet address
430
+ * @returns Models.TraderHourlyStatsResponse
431
+ */
432
+ async getTraderHourlyStats(address) {
433
+ return this.request(this.apiBaseUrl, `/v2/traders/${address}/hourly_stats`, { method: "GET" });
434
+ }
435
+ /**
436
+ * Get Trader Market Participation History
437
+ * Queries resolved and active prediction markets traded by the specified wallet address.
438
+ * @param address Trader Polygon/Ethereum wallet address
439
+ * @param params.limit Max markets to return
440
+ * @param params.offset Pagination offset
441
+ * @returns Models.TraderHistoryResponse
442
+ */
443
+ async getTraderMarkets(address, params = {}) {
444
+ const query = new URLSearchParams();
445
+ if (params.limit !== void 0) query.set("limit", String(params.limit));
446
+ if (params.offset !== void 0) query.set("offset", String(params.offset));
447
+ const qs = query.toString() ? `?${query.toString()}` : "";
448
+ return this.request(this.apiBaseUrl, `/v2/traders/${address}/markets${qs}`, { method: "GET" });
449
+ }
450
+ /**
451
+ * Get Trader Orders in Market
452
+ * Retrieves granular fill events, side, price, and token outcomes for a trader in a given market.
453
+ * @param address Trader wallet address
454
+ * @param id Market numeric ID
455
+ * @param params.limit Max orders to return
456
+ * @param params.offset Pagination offset
457
+ * @returns Models.UserOrdersResponse
458
+ */
459
+ async getTraderMarketOrders(address, id, params = {}) {
460
+ const query = new URLSearchParams();
461
+ if (params.limit !== void 0) query.set("limit", String(params.limit));
462
+ if (params.offset !== void 0) query.set("offset", String(params.offset));
463
+ const qs = query.toString() ? `?${query.toString()}` : "";
464
+ return this.request(this.apiBaseUrl, `/v2/traders/${address}/markets/${id}/orders${qs}`, { method: "GET" });
465
+ }
466
+ };
467
+ var AccountService = class {
468
+ request;
469
+ apiBaseUrl;
470
+ streamBaseUrl;
471
+ apiKey;
472
+ constructor(request, apiBaseUrl, streamBaseUrl, apiKey) {
473
+ this.request = request;
474
+ this.apiBaseUrl = apiBaseUrl;
475
+ this.streamBaseUrl = streamBaseUrl;
476
+ this.apiKey = apiKey;
477
+ }
478
+ /**
479
+ * Get Current Profile
480
+ * Retrieves the authenticated user profile, tier subscription status, and available USDC balance.
481
+ * @returns Models.UserProfile
482
+ */
483
+ async getProfile() {
484
+ return this.request(this.apiBaseUrl, `/v2/user/me`, { method: "GET" });
485
+ }
486
+ /**
487
+ * List API Keys
488
+ * Lists all active and revoked API keys issued to the authenticated account.
489
+ * @returns Models.UserKeysResponse
490
+ */
491
+ async listKeys() {
492
+ return this.request(this.apiBaseUrl, `/v2/user/keys`, { method: "GET" });
493
+ }
494
+ /**
495
+ * Create API Key
496
+ * Generates a new authenticated API key token with optional memo label.
497
+ * @param req Request payload
498
+ * @returns Models.UserAPIKey
499
+ */
500
+ async createKey(req) {
501
+ return this.request(this.apiBaseUrl, `/v2/user/keys`, { method: "POST", body: JSON.stringify(req) });
502
+ }
503
+ /**
504
+ * Update API Key
505
+ * Modifies label memo or operational status of an existing API key.
506
+ * @param key API key string
507
+ * @param req Request payload
508
+ * @returns Models.UserAPIKey
509
+ */
510
+ async updateKey(key, req) {
511
+ return this.request(this.apiBaseUrl, `/v2/user/keys/${key}`, { method: "PATCH", body: JSON.stringify(req) });
512
+ }
513
+ /**
514
+ * Revoke API Key
515
+ * Permanently revokes and deactivates an API key token.
516
+ * @param key API key string
517
+ * @returns Models.DeleteKeyResponse
518
+ */
519
+ async deleteKey(key) {
520
+ return this.request(this.apiBaseUrl, `/v2/user/keys/${key}`, { method: "DELETE" });
521
+ }
522
+ /**
523
+ * List User Balance Ledger
524
+ * Lists chronological ledger entries (subscription billing charges, deposits, withdrawals).
525
+ * @param params.limit Max entries to return
526
+ * @param params.offset Pagination offset
527
+ * @returns Models.UserLedgerResponse
528
+ */
529
+ async getLedger(params = {}) {
530
+ const query = new URLSearchParams();
531
+ if (params.limit !== void 0) query.set("limit", String(params.limit));
532
+ if (params.offset !== void 0) query.set("offset", String(params.offset));
533
+ const qs = query.toString() ? `?${query.toString()}` : "";
534
+ return this.request(this.apiBaseUrl, `/v2/user/ledger${qs}`, { method: "GET" });
535
+ }
536
+ /**
537
+ * Get Account Telemetry & Limits
538
+ * Provides live usage statistics, quota limits, and remaining streaming bandwidth.
539
+ * @returns Models.UserTelemetryResponse
540
+ */
541
+ async getTelemetry() {
542
+ return this.request(this.apiBaseUrl, `/v2/user/telemetry`, { method: "GET" });
543
+ }
544
+ };
545
+ var SubscriptionService = class {
546
+ request;
547
+ apiBaseUrl;
548
+ streamBaseUrl;
549
+ apiKey;
550
+ constructor(request, apiBaseUrl, streamBaseUrl, apiKey) {
551
+ this.request = request;
552
+ this.apiBaseUrl = apiBaseUrl;
553
+ this.streamBaseUrl = streamBaseUrl;
554
+ this.apiKey = apiKey;
555
+ }
556
+ /**
557
+ * List Public Tiers Catalog
558
+ * Returns plan tiers (Free, Starter, Pro, Growth, Whale) with limits and pricing details.
559
+ * @returns Models.Tier[]
560
+ */
561
+ async listTiers() {
562
+ return this.request(this.apiBaseUrl, `/v2/tiers`, { method: "GET" });
563
+ }
564
+ /**
565
+ * Get Subscription Quote
566
+ * Calculates prorated billing amounts for subscribing to or upgrading a tier plan.
567
+ * @param req Request payload
568
+ * @returns Models.QuoteSubscriptionResponse
569
+ */
570
+ async getQuote(req) {
571
+ return this.request(this.apiBaseUrl, `/v2/user/subscribe/quote`, { method: "POST", body: JSON.stringify(req) });
572
+ }
573
+ /**
574
+ * Purchase / Upgrade Tier Subscription
575
+ * Executes purchase, renewal, or upgrade of an active subscription tier plan.
576
+ * @param req Request payload
577
+ * @returns Models.SubscribeResponse
578
+ */
579
+ async subscribe(req) {
580
+ return this.request(this.apiBaseUrl, `/v2/user/subscribe`, { method: "POST", body: JSON.stringify(req) });
581
+ }
582
+ /**
583
+ * Validate Promo Code
584
+ * Verifies validity, discount percentage, and applicable plans for a promotion coupon code.
585
+ * @param req Request payload
586
+ * @returns Models.ValidatePromoCodeResponse
587
+ */
588
+ async validatePromoCode(req) {
589
+ return this.request(this.apiBaseUrl, `/v2/user/promo-codes/validate`, { method: "POST", body: JSON.stringify(req) });
590
+ }
591
+ };
592
+ var PolyEdgeClient = class {
593
+ apiKey;
594
+ apiBaseUrl;
595
+ streamBaseUrl;
596
+ /** Streams Service: Real-time SSE trade streaming & filters */
597
+ streams;
598
+ /** Analytics Service: Leaderboard, trader intelligence, markets */
599
+ analytics;
600
+ /** Account Service: Profile, keys, ledger, telemetry */
601
+ account;
602
+ /** Subscription Service: Plan tiers, quotes, checkout */
603
+ subscription;
604
+ constructor(options) {
605
+ if (!options.apiKey) throw new Error("PolyEdgeClient: apiKey is required");
606
+ this.apiKey = options.apiKey;
607
+ this.apiBaseUrl = (options.apiBaseUrl || "https://api.polyedge.dev").replace(/\/+$/, "");
608
+ this.streamBaseUrl = (options.streamBaseUrl || "https://stream.polyedge.dev").replace(/\/+$/, "");
609
+ const req = this.request.bind(this);
610
+ this.streams = new StreamsService(req, this.apiBaseUrl, this.streamBaseUrl, this.apiKey);
611
+ this.analytics = new AnalyticsService(req, this.apiBaseUrl, this.streamBaseUrl, this.apiKey);
612
+ this.account = new AccountService(req, this.apiBaseUrl, this.streamBaseUrl, this.apiKey);
613
+ this.subscription = new SubscriptionService(req, this.apiBaseUrl, this.streamBaseUrl, this.apiKey);
614
+ }
615
+ async request(baseUrl, endpoint, options = {}) {
616
+ const url = `${baseUrl}${endpoint}`;
617
+ const headers = {
618
+ Accept: "application/json",
619
+ "Content-Type": "application/json",
620
+ "X-PolyEdge-Key": this.apiKey,
621
+ ...options.headers
622
+ };
623
+ const res = await fetch(url, { ...options, headers });
624
+ if (!res.ok) {
625
+ const body = await res.text().catch(() => "");
626
+ throw new Error(`PolyEdge API Error [${res.status}]: ${body}`);
627
+ }
628
+ return res.json();
629
+ }
630
+ /** Direct helper to create SSE order stream */
631
+ stream(streamId, options = {}) {
632
+ return this.streams.connect(streamId, options);
633
+ }
634
+ };
635
+ // Annotate the CommonJS export names for ESM import in node:
636
+ 0 && (module.exports = {
637
+ AccountService,
638
+ AnalyticsService,
639
+ PolyEdgeClient,
640
+ PolyEdgeStream,
641
+ StreamsService,
642
+ SubscriptionService
643
+ });