@agg-build/sdk 4.17.4 → 4.19.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/README.md +6 -0
- package/dist/agg-websocket-CE7v1_-O.d.mts +4358 -0
- package/dist/agg-websocket-CE7v1_-O.d.ts +4358 -0
- package/dist/browser.d.mts +69 -0
- package/dist/browser.d.ts +69 -0
- package/dist/browser.js +2049 -0
- package/dist/browser.mjs +804 -0
- package/dist/chunk-QXBVA5TW.mjs +2073 -0
- package/dist/chunk-VD5UTAVD.mjs +158 -0
- package/dist/index.d.mts +439 -4244
- package/dist/index.d.ts +439 -4244
- package/dist/index.js +744 -125
- package/dist/index.mjs +283 -1763
- package/dist/market-data.d.mts +7 -0
- package/dist/market-data.d.ts +7 -0
- package/dist/market-data.js +1776 -0
- package/dist/market-data.mjs +352 -0
- package/dist/server.d.mts +16 -2
- package/dist/server.d.ts +16 -2
- package/package.json +27 -1
package/dist/index.js
CHANGED
|
@@ -90,6 +90,7 @@ __export(index_exports, {
|
|
|
90
90
|
OrderStatus: () => OrderStatus,
|
|
91
91
|
OrderType: () => OrderType,
|
|
92
92
|
RECURRENCE_CADENCES: () => RECURRENCE_CADENCES,
|
|
93
|
+
RETINA_IMAGE_SIZES: () => RETINA_IMAGE_SIZES,
|
|
93
94
|
SELF_CUSTODY_FILL_TIMEOUT_MS: () => SELF_CUSTODY_FILL_TIMEOUT_MS,
|
|
94
95
|
SELF_CUSTODY_POLL_INTERVAL_MS: () => SELF_CUSTODY_POLL_INTERVAL_MS,
|
|
95
96
|
TERMINAL_EXECUTION_STATES: () => TERMINAL_EXECUTION_STATES,
|
|
@@ -123,13 +124,17 @@ __export(index_exports, {
|
|
|
123
124
|
isVenueActive: () => isVenueActive,
|
|
124
125
|
isVenueDataVisible: () => isVenueDataVisible,
|
|
125
126
|
isVenueInactive: () => isVenueInactive,
|
|
127
|
+
loadImmutableHistory: () => loadImmutableHistory,
|
|
126
128
|
mergeCandles: () => mergeCandles,
|
|
127
129
|
mergeClosedCandles: () => mergeClosedCandles,
|
|
128
130
|
normalizeVenueMarketCluster: () => normalizeVenueMarketCluster,
|
|
129
131
|
optimizedImageUrl: () => optimizedImageUrl,
|
|
132
|
+
orderbookCrc32: () => orderbookCrc32,
|
|
130
133
|
parse: () => parse,
|
|
131
134
|
parseEmail: () => parseEmail,
|
|
132
135
|
parseEmailStrict: () => parseEmailStrict,
|
|
136
|
+
projectedOrderbookChecksum: () => projectedOrderbookChecksum,
|
|
137
|
+
retinaImageUrl: () => retinaImageUrl,
|
|
133
138
|
safeParse: () => safeParse,
|
|
134
139
|
snapshotToOrderbook: () => snapshotToOrderbook,
|
|
135
140
|
sortVenues: () => sortVenues,
|
|
@@ -145,11 +150,13 @@ var Venue = /* @__PURE__ */ ((Venue3) => {
|
|
|
145
150
|
Venue3["opinion"] = "opinion";
|
|
146
151
|
Venue3["predict"] = "predict";
|
|
147
152
|
Venue3["pred"] = "pred";
|
|
153
|
+
Venue3["tiprun"] = "tiprun";
|
|
148
154
|
Venue3["probable"] = "probable";
|
|
149
155
|
Venue3["myriad"] = "myriad";
|
|
150
156
|
Venue3["hyperliquid"] = "hyperliquid";
|
|
151
157
|
Venue3["novig"] = "novig";
|
|
152
158
|
Venue3["prophetx"] = "prophetx";
|
|
159
|
+
Venue3["betdex"] = "betdex";
|
|
153
160
|
return Venue3;
|
|
154
161
|
})(Venue || {});
|
|
155
162
|
var VENUES = [
|
|
@@ -159,11 +166,13 @@ var VENUES = [
|
|
|
159
166
|
"opinion" /* opinion */,
|
|
160
167
|
"predict" /* predict */,
|
|
161
168
|
"pred" /* pred */,
|
|
169
|
+
"tiprun" /* tiprun */,
|
|
162
170
|
"probable" /* probable */,
|
|
163
171
|
"myriad" /* myriad */,
|
|
164
172
|
"hyperliquid" /* hyperliquid */,
|
|
165
173
|
"novig" /* novig */,
|
|
166
|
-
"prophetx" /* prophetx
|
|
174
|
+
"prophetx" /* prophetx */,
|
|
175
|
+
"betdex" /* betdex */
|
|
167
176
|
];
|
|
168
177
|
var VENUE_CHAIN_IDS = {
|
|
169
178
|
["kalshi" /* kalshi */]: 792703809,
|
|
@@ -171,6 +180,7 @@ var VENUE_CHAIN_IDS = {
|
|
|
171
180
|
["limitless" /* limitless */]: 8453,
|
|
172
181
|
["predict" /* predict */]: 56,
|
|
173
182
|
["pred" /* pred */]: 8453,
|
|
183
|
+
["tiprun" /* tiprun */]: 42161,
|
|
174
184
|
["myriad" /* myriad */]: 56,
|
|
175
185
|
["hyperliquid" /* hyperliquid */]: 1337,
|
|
176
186
|
["novig" /* novig */]: 792703809,
|
|
@@ -183,14 +193,22 @@ var ACTIVE_VENUES = [
|
|
|
183
193
|
"opinion" /* opinion */,
|
|
184
194
|
"predict" /* predict */,
|
|
185
195
|
"pred" /* pred */,
|
|
196
|
+
"tiprun" /* tiprun */,
|
|
186
197
|
"probable" /* probable */,
|
|
187
198
|
"myriad" /* myriad */,
|
|
188
199
|
"hyperliquid" /* hyperliquid */,
|
|
189
200
|
"novig" /* novig */,
|
|
190
|
-
"prophetx" /* prophetx
|
|
201
|
+
"prophetx" /* prophetx */,
|
|
202
|
+
"betdex" /* betdex */
|
|
191
203
|
];
|
|
192
204
|
var INACTIVE_VENUES = [];
|
|
193
|
-
var DEFAULT_DISABLED_VENUES = [
|
|
205
|
+
var DEFAULT_DISABLED_VENUES = [
|
|
206
|
+
"pred" /* pred */,
|
|
207
|
+
"tiprun" /* tiprun */,
|
|
208
|
+
"novig" /* novig */,
|
|
209
|
+
"prophetx" /* prophetx */,
|
|
210
|
+
"betdex" /* betdex */
|
|
211
|
+
];
|
|
194
212
|
var ACTIVE_VENUE_SET = new Set(ACTIVE_VENUES);
|
|
195
213
|
var INACTIVE_VENUE_SET = new Set(INACTIVE_VENUES);
|
|
196
214
|
function normalizeVenue(venue) {
|
|
@@ -226,10 +244,21 @@ var ImageSize = /* @__PURE__ */ ((ImageSize2) => {
|
|
|
226
244
|
ImageSize2[ImageSize2["sm"] = 44] = "sm";
|
|
227
245
|
ImageSize2[ImageSize2["md"] = 48] = "md";
|
|
228
246
|
ImageSize2[ImageSize2["lg"] = 60] = "lg";
|
|
247
|
+
ImageSize2[ImageSize2["xl"] = 80] = "xl";
|
|
248
|
+
ImageSize2[ImageSize2["xxl"] = 96] = "xxl";
|
|
249
|
+
ImageSize2[ImageSize2["xxxl"] = 120] = "xxxl";
|
|
229
250
|
ImageSize2[ImageSize2["original"] = 0] = "original";
|
|
230
251
|
return ImageSize2;
|
|
231
252
|
})(ImageSize || {});
|
|
232
|
-
var IMAGE_SIZES = [
|
|
253
|
+
var IMAGE_SIZES = [
|
|
254
|
+
44 /* sm */,
|
|
255
|
+
48 /* md */,
|
|
256
|
+
60 /* lg */,
|
|
257
|
+
80 /* xl */,
|
|
258
|
+
96 /* xxl */,
|
|
259
|
+
120 /* xxxl */
|
|
260
|
+
];
|
|
261
|
+
var RETINA_IMAGE_SIZES = [80 /* xl */, 96 /* xxl */, 120 /* xxxl */];
|
|
233
262
|
|
|
234
263
|
// ../common/src/enums/account.ts
|
|
235
264
|
var AccountType = /* @__PURE__ */ ((AccountType2) => {
|
|
@@ -442,7 +471,7 @@ function computeBestSplitsByAmount(selections, side, maxDollarAmount) {
|
|
|
442
471
|
if (selections.length === 0 || maxDollarAmount <= 0) {
|
|
443
472
|
return { splits: [], totalSize: 0, totalCost: 0 };
|
|
444
473
|
}
|
|
445
|
-
const
|
|
474
|
+
const levels2 = [];
|
|
446
475
|
for (const o of selections) {
|
|
447
476
|
const venue = o.market.venue;
|
|
448
477
|
const venueMarketOutcomeId = o.outcome.id;
|
|
@@ -451,7 +480,7 @@ function computeBestSplitsByAmount(selections, side, maxDollarAmount) {
|
|
|
451
480
|
[...o.orderbook.asks].sort((a, b) => a.price - b.price).forEach(
|
|
452
481
|
(l) => {
|
|
453
482
|
var _a2;
|
|
454
|
-
return
|
|
483
|
+
return levels2.push({
|
|
455
484
|
venue,
|
|
456
485
|
venueMarketOutcomeId,
|
|
457
486
|
outcomeExternalIdentifier,
|
|
@@ -465,7 +494,7 @@ function computeBestSplitsByAmount(selections, side, maxDollarAmount) {
|
|
|
465
494
|
[...o.orderbook.bids].sort((a, b) => b.price - a.price).forEach(
|
|
466
495
|
(l) => {
|
|
467
496
|
var _a2;
|
|
468
|
-
return
|
|
497
|
+
return levels2.push({
|
|
469
498
|
venue,
|
|
470
499
|
venueMarketOutcomeId,
|
|
471
500
|
outcomeExternalIdentifier,
|
|
@@ -477,10 +506,10 @@ function computeBestSplitsByAmount(selections, side, maxDollarAmount) {
|
|
|
477
506
|
);
|
|
478
507
|
}
|
|
479
508
|
}
|
|
480
|
-
|
|
509
|
+
levels2.sort((a, b) => a.price - b.price);
|
|
481
510
|
let totalCost = 0;
|
|
482
511
|
const fills = [];
|
|
483
|
-
for (const l of
|
|
512
|
+
for (const l of levels2) {
|
|
484
513
|
if (totalCost >= maxDollarAmount) break;
|
|
485
514
|
const remainingBudget = maxDollarAmount - totalCost;
|
|
486
515
|
const maxSizeAtLevel = Math.min(l.size, remainingBudget / l.price);
|
|
@@ -565,6 +594,13 @@ function optimizedImageUrl(url, maxPx) {
|
|
|
565
594
|
const filename = variant === 0 /* original */ ? "original.webp" : `${variant}.webp`;
|
|
566
595
|
return url.replace(VARIANT_RE, `/${filename}`);
|
|
567
596
|
}
|
|
597
|
+
function retinaImageUrl(url, maxPx) {
|
|
598
|
+
if (!url) return void 0;
|
|
599
|
+
if (!VARIANT_RE.test(url)) return void 0;
|
|
600
|
+
const variant = RETINA_IMAGE_SIZES.find((size) => size >= maxPx * 2);
|
|
601
|
+
if (variant == null) return void 0;
|
|
602
|
+
return url.replace(VARIANT_RE, `/${variant}.webp`);
|
|
603
|
+
}
|
|
568
604
|
|
|
569
605
|
// ../common/src/utils/venue-market-cluster.ts
|
|
570
606
|
var toNonEmptyString = (value) => {
|
|
@@ -689,10 +725,12 @@ var VENUE_SORT_ORDER = [
|
|
|
689
725
|
"hyperliquid" /* hyperliquid */,
|
|
690
726
|
"predict" /* predict */,
|
|
691
727
|
"prophetx" /* prophetx */,
|
|
728
|
+
"betdex" /* betdex */,
|
|
692
729
|
"kalshi" /* kalshi */,
|
|
693
730
|
"limitless" /* limitless */,
|
|
694
731
|
"myriad" /* myriad */,
|
|
695
732
|
"pred" /* pred */,
|
|
733
|
+
"tiprun" /* tiprun */,
|
|
696
734
|
"probable" /* probable */,
|
|
697
735
|
"novig" /* novig */,
|
|
698
736
|
"opinion" /* opinion */
|
|
@@ -817,6 +855,93 @@ var isBalanceRefillWithinDailyCap = (minimumRaw, refillAmountRaw, dailyCapRaw, m
|
|
|
817
855
|
return BigInt(minimumRaw) <= maximum && BigInt(refillAmountRaw) <= maximum;
|
|
818
856
|
};
|
|
819
857
|
|
|
858
|
+
// ../common/src/orderbook-checksum.ts
|
|
859
|
+
function orderbookCrc32(value) {
|
|
860
|
+
let crc = 4294967295;
|
|
861
|
+
for (let i = 0; i < value.length; i++) {
|
|
862
|
+
crc ^= value.charCodeAt(i);
|
|
863
|
+
for (let bit = 0; bit < 8; bit++) crc = crc >>> 1 ^ (crc & 1 ? 3988292384 : 0);
|
|
864
|
+
}
|
|
865
|
+
return (crc ^ 4294967295) >>> 0;
|
|
866
|
+
}
|
|
867
|
+
function projectedOrderbookChecksum(book) {
|
|
868
|
+
let result = 0;
|
|
869
|
+
for (const level of book.bids) result ^= orderbookCrc32(`B${level.price}:${level.size}`);
|
|
870
|
+
for (const level of book.asks) result ^= orderbookCrc32(`A${level.price}:${level.size}`);
|
|
871
|
+
return result >>> 0;
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
// src/retry-after.ts
|
|
875
|
+
function parseRetryAfterSeconds(value) {
|
|
876
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) return void 0;
|
|
877
|
+
const milliseconds = value * 1e3;
|
|
878
|
+
return Number.isSafeInteger(milliseconds) ? milliseconds : void 0;
|
|
879
|
+
}
|
|
880
|
+
function parseRetryAfterHeader(value, now = Date.now()) {
|
|
881
|
+
if (!value) return void 0;
|
|
882
|
+
const text = value.trim();
|
|
883
|
+
if (/^\d+$/.test(text)) return parseRetryAfterSeconds(Number(text));
|
|
884
|
+
if (!/^(Mon|Tue|Wed|Thu|Fri|Sat|Sun), \d{2} (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d{4} \d{2}:\d{2}:\d{2} GMT$/.test(
|
|
885
|
+
text
|
|
886
|
+
))
|
|
887
|
+
return void 0;
|
|
888
|
+
const timestamp = Date.parse(text);
|
|
889
|
+
if (!Number.isFinite(timestamp) || new Date(timestamp).toUTCString() !== text) return void 0;
|
|
890
|
+
const milliseconds = timestamp - now;
|
|
891
|
+
return Number.isSafeInteger(milliseconds) && milliseconds >= 0 ? milliseconds : void 0;
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
// src/market-data/history-decoder.ts
|
|
895
|
+
function decodeChartHistory(payload) {
|
|
896
|
+
if (payload.length > 1048576) throw new Error("Chart history exceeds decode budget");
|
|
897
|
+
const body = JSON.parse(payload);
|
|
898
|
+
if (!body || !Array.isArray(body.data) || body.data.length > 5e3 || typeof body.venueMarketOutcomeId !== "string" || typeof body.venue !== "string" || !["1m", "5m", "1h", "1d"].includes(body.resolution) || !body.meta)
|
|
899
|
+
throw new Error("Invalid chart history response");
|
|
900
|
+
const price = (value) => typeof value === "number" && Number.isFinite(value) && value >= 0 && value <= 1;
|
|
901
|
+
for (const bar of body.data) {
|
|
902
|
+
if (!Number.isSafeInteger(bar.t) || bar.t < 0 || ![bar.o, bar.h, bar.l, bar.c].every(price) || bar.l > Math.min(bar.o, bar.c) || bar.h < Math.max(bar.o, bar.c) || bar.v !== null && (!Number.isFinite(bar.v) || bar.v < 0) || bar.mean !== void 0 && !price(bar.mean))
|
|
903
|
+
throw new Error("Invalid chart history candle");
|
|
904
|
+
}
|
|
905
|
+
const data = [...body.data].sort((a, b) => a.t - b.t);
|
|
906
|
+
if (data.some((bar, index) => index > 0 && data[index - 1].t === bar.t))
|
|
907
|
+
throw new Error("Duplicate chart history timestamp");
|
|
908
|
+
return __spreadProps(__spreadValues({}, body), { data });
|
|
909
|
+
}
|
|
910
|
+
function readChartHistoryText(response) {
|
|
911
|
+
return __async(this, null, function* () {
|
|
912
|
+
var _a, _b;
|
|
913
|
+
const maxBytes = 1048576;
|
|
914
|
+
if (Number(response.headers.get("content-length")) > maxBytes) {
|
|
915
|
+
yield (_a = response.body) == null ? void 0 : _a.cancel();
|
|
916
|
+
throw new Error("Chart history exceeds decode budget");
|
|
917
|
+
}
|
|
918
|
+
if (!((_b = response.body) == null ? void 0 : _b.getReader)) {
|
|
919
|
+
const text2 = yield response.text();
|
|
920
|
+
if (new TextEncoder().encode(text2).byteLength > maxBytes)
|
|
921
|
+
throw new Error("Chart history exceeds decode budget");
|
|
922
|
+
return text2;
|
|
923
|
+
}
|
|
924
|
+
const reader = response.body.getReader();
|
|
925
|
+
const decoder = new TextDecoder();
|
|
926
|
+
let size = 0;
|
|
927
|
+
let text = "";
|
|
928
|
+
try {
|
|
929
|
+
while (true) {
|
|
930
|
+
const { value, done } = yield reader.read();
|
|
931
|
+
if (done) return text + decoder.decode();
|
|
932
|
+
size += value.byteLength;
|
|
933
|
+
if (size > maxBytes) {
|
|
934
|
+
yield reader.cancel();
|
|
935
|
+
throw new Error("Chart history exceeds decode budget");
|
|
936
|
+
}
|
|
937
|
+
text += decoder.decode(value, { stream: true });
|
|
938
|
+
}
|
|
939
|
+
} finally {
|
|
940
|
+
reader.releaseLock();
|
|
941
|
+
}
|
|
942
|
+
});
|
|
943
|
+
}
|
|
944
|
+
|
|
820
945
|
// src/errors.ts
|
|
821
946
|
var TurnstileChallengeError = class extends Error {
|
|
822
947
|
constructor(siteKey) {
|
|
@@ -832,6 +957,7 @@ var AggApiError = class _AggApiError extends Error {
|
|
|
832
957
|
this.status = status;
|
|
833
958
|
if (init.code !== void 0) this.code = init.code;
|
|
834
959
|
if (init.retryable !== void 0) this.retryable = init.retryable;
|
|
960
|
+
if (init.retryAfterMs !== void 0) this.retryAfterMs = init.retryAfterMs;
|
|
835
961
|
if (init.errors !== void 0) this.errors = init.errors;
|
|
836
962
|
Object.setPrototypeOf(this, _AggApiError.prototype);
|
|
837
963
|
}
|
|
@@ -987,23 +1113,153 @@ var RECURRENCE_CADENCES = [
|
|
|
987
1113
|
"P1Y"
|
|
988
1114
|
];
|
|
989
1115
|
|
|
990
|
-
// src/
|
|
991
|
-
var
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
1116
|
+
// src/market-data/validate.ts
|
|
1117
|
+
var object = (value) => !!value && typeof value === "object" && !Array.isArray(value);
|
|
1118
|
+
var finite = (value) => typeof value === "number" && Number.isFinite(value);
|
|
1119
|
+
var nullable = (value) => value === null || finite(value);
|
|
1120
|
+
var levels = (value, attributed) => Array.isArray(value) && value.length <= 1e4 && value.every(
|
|
1121
|
+
(level) => Array.isArray(level) && finite(level[0]) && level[0] >= 0 && finite(level[1]) && level[1] >= 0 && (!attributed || object(level[2]) && Object.values(level[2]).every((size) => finite(size) && size >= 0))
|
|
1122
|
+
);
|
|
1123
|
+
function validMarketFrame(frame) {
|
|
1124
|
+
if (typeof frame.outcomeId !== "string" || !frame.outcomeId || !finite(frame.timestamp) || frame.timestamp < 0)
|
|
1125
|
+
return false;
|
|
1126
|
+
if (frame.type === "trade")
|
|
1127
|
+
return finite(frame.price) && frame.price >= 0 && finite(frame.size) && frame.size >= 0 && typeof frame.venue === "string" && (frame.side === "buy" || frame.side === "sell");
|
|
1128
|
+
if (!Number.isSafeInteger(frame.seq) || frame.seq < 0 || !Number.isInteger(frame.checksum) || frame.checksum < 0 || frame.checksum > 4294967295 || !nullable(frame.midpoint) || !nullable(frame.spread) || !object(frame.venues))
|
|
1129
|
+
return false;
|
|
1130
|
+
for (const info of Object.values(frame.venues))
|
|
1131
|
+
if (!object(info) || !nullable(info.bestBid) || !nullable(info.bestAsk)) return false;
|
|
1132
|
+
const snapshot = frame.type === "orderbook_snapshot";
|
|
1133
|
+
if (!levels(frame[snapshot ? "bids" : "bidChanges"], true) || !levels(frame[snapshot ? "asks" : "askChanges"], true))
|
|
1134
|
+
return false;
|
|
1135
|
+
const books = frame[snapshot ? "venueOrderbooks" : "venueDeltaBooks"];
|
|
1136
|
+
return object(books) && Object.values(books).every(
|
|
1137
|
+
(book) => object(book) && levels(book[snapshot ? "bids" : "bidChanges"], false) && levels(book[snapshot ? "asks" : "askChanges"], false)
|
|
1138
|
+
);
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
// src/market-history.ts
|
|
1142
|
+
function readBoundedBody(response, signal) {
|
|
1143
|
+
return __async(this, null, function* () {
|
|
1144
|
+
var _a, _b;
|
|
1145
|
+
if (!response.body) throw new Error("Missing history body");
|
|
1146
|
+
const reader = response.body.getReader();
|
|
1147
|
+
const chunks = [];
|
|
1148
|
+
let size = 0;
|
|
1149
|
+
const abort = () => {
|
|
1150
|
+
void reader.cancel(signal.reason).catch(() => void 0);
|
|
1151
|
+
};
|
|
1152
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
1153
|
+
try {
|
|
1154
|
+
while (true) {
|
|
1155
|
+
if (signal.aborted) throw (_a = signal.reason) != null ? _a : new Error("History request aborted");
|
|
1156
|
+
const { done, value } = yield reader.read();
|
|
1157
|
+
if (signal.aborted) throw (_b = signal.reason) != null ? _b : new Error("History request aborted");
|
|
1158
|
+
if (done) break;
|
|
1159
|
+
size += value.byteLength;
|
|
1160
|
+
if (size > 262144) {
|
|
1161
|
+
yield reader.cancel();
|
|
1162
|
+
throw new Error("Oversized history object");
|
|
1163
|
+
}
|
|
1164
|
+
chunks.push(value);
|
|
1165
|
+
}
|
|
1166
|
+
const bytes = new Uint8Array(size);
|
|
1167
|
+
let offset = 0;
|
|
1168
|
+
for (const chunk of chunks) {
|
|
1169
|
+
bytes.set(chunk, offset);
|
|
1170
|
+
offset += chunk.byteLength;
|
|
1171
|
+
}
|
|
1172
|
+
return bytes;
|
|
1173
|
+
} finally {
|
|
1174
|
+
signal.removeEventListener("abort", abort);
|
|
1175
|
+
reader.releaseLock();
|
|
998
1176
|
}
|
|
999
|
-
}
|
|
1000
|
-
return (crc ^ 4294967295) >>> 0;
|
|
1177
|
+
});
|
|
1001
1178
|
}
|
|
1179
|
+
function loadImmutableHistory(_0) {
|
|
1180
|
+
return __async(this, arguments, function* ({
|
|
1181
|
+
manifest,
|
|
1182
|
+
fetch: fetcher = globalThis.fetch,
|
|
1183
|
+
signal,
|
|
1184
|
+
digest
|
|
1185
|
+
}) {
|
|
1186
|
+
if (manifest.version !== 1 || !["venue-ohlcv-v1", "polymarket-price-samples-v1", "kalshi-ohlcv-quote-fallback-v2"].includes(
|
|
1187
|
+
manifest.semantics
|
|
1188
|
+
) || manifest.chunks.length > 8 || manifest.chunks.reduce((n, c) => n + c.points, 0) > 4096 || !manifest.meta.complete) {
|
|
1189
|
+
throw new Error("History manifest is incomplete or unsupported");
|
|
1190
|
+
}
|
|
1191
|
+
const hash = digest != null ? digest : ((bytes) => __async(null, null, function* () {
|
|
1192
|
+
var _a;
|
|
1193
|
+
if (!((_a = globalThis.crypto) == null ? void 0 : _a.subtle))
|
|
1194
|
+
throw new Error(
|
|
1195
|
+
"History integrity requires WebCrypto or an injected SHA-256 implementation"
|
|
1196
|
+
);
|
|
1197
|
+
const value = yield globalThis.crypto.subtle.digest("SHA-256", bytes);
|
|
1198
|
+
return Array.from(new Uint8Array(value), (b) => b.toString(16).padStart(2, "0")).join("");
|
|
1199
|
+
}));
|
|
1200
|
+
const results = new Array(manifest.chunks.length);
|
|
1201
|
+
let next = 0;
|
|
1202
|
+
const controller = new AbortController();
|
|
1203
|
+
const deadline = setTimeout(
|
|
1204
|
+
() => controller.abort(new Error("History download budget exhausted")),
|
|
1205
|
+
2e3
|
|
1206
|
+
);
|
|
1207
|
+
const abort = () => controller.abort(signal == null ? void 0 : signal.reason);
|
|
1208
|
+
signal == null ? void 0 : signal.addEventListener("abort", abort, { once: true });
|
|
1209
|
+
if (signal == null ? void 0 : signal.aborted) abort();
|
|
1210
|
+
try {
|
|
1211
|
+
yield Promise.all(
|
|
1212
|
+
Array.from({ length: Math.min(2, manifest.chunks.length) }, () => __async(null, null, function* () {
|
|
1213
|
+
var _a;
|
|
1214
|
+
while (next < manifest.chunks.length) {
|
|
1215
|
+
if (controller.signal.aborted)
|
|
1216
|
+
throw (_a = controller.signal.reason) != null ? _a : new Error("History request aborted");
|
|
1217
|
+
const index = next++;
|
|
1218
|
+
const chunk = manifest.chunks[index];
|
|
1219
|
+
if (chunk.points < 0 || chunk.points > 512 || chunk.from >= chunk.to || new URL(chunk.url).protocol !== "https:")
|
|
1220
|
+
throw new Error("Invalid history reference");
|
|
1221
|
+
const response = yield fetcher(chunk.url, {
|
|
1222
|
+
signal: controller.signal,
|
|
1223
|
+
credentials: "omit"
|
|
1224
|
+
});
|
|
1225
|
+
if (!response.ok) throw new Error(`History download failed (${response.status})`);
|
|
1226
|
+
if (Number(response.headers.get("content-length")) > 262144)
|
|
1227
|
+
throw new Error("Oversized history object");
|
|
1228
|
+
const bytes = yield readBoundedBody(response, controller.signal);
|
|
1229
|
+
if (bytes.byteLength > 262144 || (yield hash(bytes)) !== chunk.sha256)
|
|
1230
|
+
throw new Error("History integrity mismatch");
|
|
1231
|
+
const object2 = JSON.parse(new TextDecoder().decode(bytes));
|
|
1232
|
+
if (object2.version !== 1 || object2.venueMarketOutcomeId !== manifest.venueMarketOutcomeId || object2.venue !== manifest.venue || object2.resolution !== manifest.resolution || object2.semantics !== manifest.semantics || object2.from !== chunk.from || object2.to !== chunk.to || !Array.isArray(object2.data) || object2.data.length !== chunk.points) {
|
|
1233
|
+
throw new Error("History identity mismatch");
|
|
1234
|
+
}
|
|
1235
|
+
let previous = -Infinity;
|
|
1236
|
+
for (const bar of object2.data) {
|
|
1237
|
+
if (!Number.isSafeInteger(bar.t) || bar.t <= previous || bar.t < chunk.from || bar.t >= chunk.to || ![bar.o, bar.h, bar.l, bar.c].every((v) => Number.isFinite(v) && v >= 0 && v <= 1) || bar.l > Math.min(bar.o, bar.c) || bar.h < Math.max(bar.o, bar.c) || bar.v !== null && (!Number.isFinite(bar.v) || bar.v < 0) || bar.mean !== void 0 && (!Number.isFinite(bar.mean) || bar.mean < 0 || bar.mean > 1))
|
|
1238
|
+
throw new Error("Invalid history candle");
|
|
1239
|
+
previous = bar.t;
|
|
1240
|
+
}
|
|
1241
|
+
results[index] = object2.data;
|
|
1242
|
+
}
|
|
1243
|
+
}))
|
|
1244
|
+
);
|
|
1245
|
+
const bars = results.flat().filter((b) => b.t >= manifest.from && b.t < manifest.to).sort((a, b) => a.t - b.t);
|
|
1246
|
+
if (bars.some((b, i) => i > 0 && bars[i - 1].t === b.t))
|
|
1247
|
+
throw new Error("Overlapping history chunks");
|
|
1248
|
+
return bars;
|
|
1249
|
+
} catch (error) {
|
|
1250
|
+
controller.abort(error);
|
|
1251
|
+
throw error;
|
|
1252
|
+
} finally {
|
|
1253
|
+
clearTimeout(deadline);
|
|
1254
|
+
signal == null ? void 0 : signal.removeEventListener("abort", abort);
|
|
1255
|
+
}
|
|
1256
|
+
});
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
// src/orderbook-utils.ts
|
|
1260
|
+
var PRICE_KEY_SCALE = 1e9;
|
|
1002
1261
|
function computeChecksum(book) {
|
|
1003
|
-
|
|
1004
|
-
for (const b of book.bids) checksum ^= crc32(`B${b.price}:${b.size}`);
|
|
1005
|
-
for (const a of book.asks) checksum ^= crc32(`A${a.price}:${a.size}`);
|
|
1006
|
-
return checksum >>> 0;
|
|
1262
|
+
return projectedOrderbookChecksum(book);
|
|
1007
1263
|
}
|
|
1008
1264
|
function attributedToLevel(wire) {
|
|
1009
1265
|
return { price: wire[0], size: wire[1], venues: __spreadValues({}, wire[2]) };
|
|
@@ -1088,8 +1344,8 @@ function applyOrderbookDelta(state, delta) {
|
|
|
1088
1344
|
function toPriceKey(price) {
|
|
1089
1345
|
return String(Math.round(price * PRICE_KEY_SCALE));
|
|
1090
1346
|
}
|
|
1091
|
-
function applyChanges(
|
|
1092
|
-
const levelsByPrice = new Map(
|
|
1347
|
+
function applyChanges(levels2, changes, sort) {
|
|
1348
|
+
const levelsByPrice = new Map(levels2.map((level) => [toPriceKey(level.price), level]));
|
|
1093
1349
|
for (const [price, size, venues] of changes) {
|
|
1094
1350
|
const key = toPriceKey(price);
|
|
1095
1351
|
if (size === 0) {
|
|
@@ -1102,12 +1358,12 @@ function applyChanges(levels, changes, sort) {
|
|
|
1102
1358
|
venues: __spreadValues({}, venues != null ? venues : {})
|
|
1103
1359
|
});
|
|
1104
1360
|
}
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
return
|
|
1361
|
+
levels2 = [...levelsByPrice.values()];
|
|
1362
|
+
levels2.sort(sort === "desc" ? (a, b) => b.price - a.price : (a, b) => a.price - b.price);
|
|
1363
|
+
return levels2;
|
|
1108
1364
|
}
|
|
1109
|
-
function applyVenueChanges(
|
|
1110
|
-
const levelsByPrice = new Map(
|
|
1365
|
+
function applyVenueChanges(levels2, changes, sort) {
|
|
1366
|
+
const levelsByPrice = new Map(levels2.map((level) => [toPriceKey(level.price), level]));
|
|
1111
1367
|
for (const [price, size] of changes) {
|
|
1112
1368
|
const key = toPriceKey(price);
|
|
1113
1369
|
if (size === 0) {
|
|
@@ -1116,9 +1372,9 @@ function applyVenueChanges(levels, changes, sort) {
|
|
|
1116
1372
|
}
|
|
1117
1373
|
levelsByPrice.set(key, { price, size });
|
|
1118
1374
|
}
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
return
|
|
1375
|
+
levels2 = [...levelsByPrice.values()];
|
|
1376
|
+
levels2.sort(sort === "desc" ? (a, b) => b.price - a.price : (a, b) => a.price - b.price);
|
|
1377
|
+
return levels2;
|
|
1122
1378
|
}
|
|
1123
1379
|
function mergeVenueLevelChanges(primary, fallback) {
|
|
1124
1380
|
if (!(primary == null ? void 0 : primary.length)) return fallback ? [...fallback] : [];
|
|
@@ -1164,6 +1420,121 @@ function deriveVenueChangesFromAttributedChanges(previousLevels, changes) {
|
|
|
1164
1420
|
}
|
|
1165
1421
|
return venueChanges;
|
|
1166
1422
|
}
|
|
1423
|
+
var IndexedOrderbook = class {
|
|
1424
|
+
constructor(state) {
|
|
1425
|
+
this.venueBooks = /* @__PURE__ */ new Map();
|
|
1426
|
+
this.bids = new Map(state.bids.map((level) => [toPriceKey(level.price), level]));
|
|
1427
|
+
this.asks = new Map(state.asks.map((level) => [toPriceKey(level.price), level]));
|
|
1428
|
+
for (const [venue, book] of Object.entries(state.venueOrderbooks)) {
|
|
1429
|
+
this.venueBooks.set(venue, {
|
|
1430
|
+
bids: new Map(book.bids.map((level) => [toPriceKey(level.price), level])),
|
|
1431
|
+
asks: new Map(book.asks.map((level) => [toPriceKey(level.price), level]))
|
|
1432
|
+
});
|
|
1433
|
+
}
|
|
1434
|
+
const _a = state, { bids: _bids, asks: _asks, venueOrderbooks: _venueBooks } = _a, metadata = __objRest(_a, ["bids", "asks", "venueOrderbooks"]);
|
|
1435
|
+
this.metadata = metadata;
|
|
1436
|
+
this.cached = state;
|
|
1437
|
+
this.checksumValue = computeChecksum(state);
|
|
1438
|
+
}
|
|
1439
|
+
get seq() {
|
|
1440
|
+
return this.metadata.seq;
|
|
1441
|
+
}
|
|
1442
|
+
get checksum() {
|
|
1443
|
+
return this.checksumValue;
|
|
1444
|
+
}
|
|
1445
|
+
/** Verify before committing, including duplicate-price changes within a frame. */
|
|
1446
|
+
apply(delta) {
|
|
1447
|
+
var _a;
|
|
1448
|
+
let checksum = this.checksumValue;
|
|
1449
|
+
for (const [levels2, changes, side] of [
|
|
1450
|
+
[this.bids, delta.bidChanges, "B"],
|
|
1451
|
+
[this.asks, delta.askChanges, "A"]
|
|
1452
|
+
]) {
|
|
1453
|
+
const changed = /* @__PURE__ */ new Map();
|
|
1454
|
+
for (const [price, size, venues] of changes) {
|
|
1455
|
+
const key = toPriceKey(price);
|
|
1456
|
+
const previous = changed.has(key) ? changed.get(key) : levels2.get(key);
|
|
1457
|
+
if (previous) checksum ^= orderbookCrc32(`${side}${previous.price}:${previous.size}`);
|
|
1458
|
+
if (size !== 0) checksum ^= orderbookCrc32(`${side}${price}:${size}`);
|
|
1459
|
+
changed.set(key, size === 0 ? void 0 : { price, size, venues: __spreadValues({}, venues) });
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
checksum >>>= 0;
|
|
1463
|
+
if (checksum !== delta.checksum) return checksum;
|
|
1464
|
+
const previousBids = delta.bidChanges.flatMap(
|
|
1465
|
+
([price]) => {
|
|
1466
|
+
var _a2;
|
|
1467
|
+
return (_a2 = this.bids.get(toPriceKey(price))) != null ? _a2 : [];
|
|
1468
|
+
}
|
|
1469
|
+
);
|
|
1470
|
+
const previousAsks = delta.askChanges.flatMap(
|
|
1471
|
+
([price]) => {
|
|
1472
|
+
var _a2;
|
|
1473
|
+
return (_a2 = this.asks.get(toPriceKey(price))) != null ? _a2 : [];
|
|
1474
|
+
}
|
|
1475
|
+
);
|
|
1476
|
+
const impliedBids = deriveVenueChangesFromAttributedChanges(previousBids, delta.bidChanges);
|
|
1477
|
+
const impliedAsks = deriveVenueChangesFromAttributedChanges(previousAsks, delta.askChanges);
|
|
1478
|
+
for (const venue of /* @__PURE__ */ new Set([
|
|
1479
|
+
...Object.keys(delta.venueDeltaBooks),
|
|
1480
|
+
...Object.keys(impliedBids),
|
|
1481
|
+
...Object.keys(impliedAsks)
|
|
1482
|
+
])) {
|
|
1483
|
+
let book = this.venueBooks.get(venue);
|
|
1484
|
+
if (!book) {
|
|
1485
|
+
book = { bids: /* @__PURE__ */ new Map(), asks: /* @__PURE__ */ new Map() };
|
|
1486
|
+
this.venueBooks.set(venue, book);
|
|
1487
|
+
}
|
|
1488
|
+
const explicit = delta.venueDeltaBooks[venue];
|
|
1489
|
+
for (const [levels2, changes] of [
|
|
1490
|
+
[book.bids, mergeVenueLevelChanges(explicit == null ? void 0 : explicit.bidChanges, impliedBids[venue])],
|
|
1491
|
+
[book.asks, mergeVenueLevelChanges(explicit == null ? void 0 : explicit.askChanges, impliedAsks[venue])]
|
|
1492
|
+
]) {
|
|
1493
|
+
for (const [price, size] of changes) {
|
|
1494
|
+
if (size === 0) levels2.delete(toPriceKey(price));
|
|
1495
|
+
else levels2.set(toPriceKey(price), { price, size });
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
for (const [levels2, changes] of [
|
|
1500
|
+
[this.bids, delta.bidChanges],
|
|
1501
|
+
[this.asks, delta.askChanges]
|
|
1502
|
+
]) {
|
|
1503
|
+
for (const [price, size, venues] of changes) {
|
|
1504
|
+
if (size === 0) levels2.delete(toPriceKey(price));
|
|
1505
|
+
else levels2.set(toPriceKey(price), { price, size, venues: __spreadValues({}, venues) });
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
this.metadata = __spreadProps(__spreadValues({}, this.metadata), {
|
|
1509
|
+
outcomeId: (_a = this.metadata.outcomeId) != null ? _a : delta.outcomeId,
|
|
1510
|
+
venues: __spreadValues(__spreadValues({}, this.metadata.venues), delta.venues),
|
|
1511
|
+
midpoint: delta.midpoint,
|
|
1512
|
+
spread: delta.spread,
|
|
1513
|
+
seq: delta.seq,
|
|
1514
|
+
checksum: delta.checksum,
|
|
1515
|
+
timestamp: delta.timestamp
|
|
1516
|
+
});
|
|
1517
|
+
this.checksumValue = checksum;
|
|
1518
|
+
this.cached = null;
|
|
1519
|
+
return checksum;
|
|
1520
|
+
}
|
|
1521
|
+
view() {
|
|
1522
|
+
if (this.cached) return this.cached;
|
|
1523
|
+
const bids = (levels2) => [...levels2.values()].sort((a, b) => b.price - a.price);
|
|
1524
|
+
const asks = (levels2) => [...levels2.values()].sort((a, b) => a.price - b.price);
|
|
1525
|
+
this.cached = __spreadProps(__spreadValues({}, this.metadata), {
|
|
1526
|
+
bids: bids(this.bids),
|
|
1527
|
+
asks: asks(this.asks),
|
|
1528
|
+
venueOrderbooks: Object.fromEntries(
|
|
1529
|
+
[...this.venueBooks].map(([venue, book]) => [
|
|
1530
|
+
venue,
|
|
1531
|
+
{ bids: bids(book.bids), asks: asks(book.asks) }
|
|
1532
|
+
])
|
|
1533
|
+
)
|
|
1534
|
+
});
|
|
1535
|
+
return this.cached;
|
|
1536
|
+
}
|
|
1537
|
+
};
|
|
1167
1538
|
|
|
1168
1539
|
// src/agg-websocket.ts
|
|
1169
1540
|
var RECONNECT_BASE_MS = 1e3;
|
|
@@ -1203,20 +1574,74 @@ var AggWebSocket = class {
|
|
|
1203
1574
|
this.staleTimer = null;
|
|
1204
1575
|
this.lastMessageTime = 0;
|
|
1205
1576
|
this.destroyed = false;
|
|
1206
|
-
|
|
1577
|
+
this.historyControllers = /* @__PURE__ */ new Set();
|
|
1578
|
+
var _a, _b, _c;
|
|
1579
|
+
this.deferBookViews = (_a = options.deferBookViews) != null ? _a : false;
|
|
1207
1580
|
this.url = options.url;
|
|
1208
|
-
this.callbacks = (
|
|
1581
|
+
this.callbacks = (_b = options.callbacks) != null ? _b : {};
|
|
1209
1582
|
this.initialToken = options.initialToken;
|
|
1210
|
-
this.enableLogs = (
|
|
1583
|
+
this.enableLogs = (_c = options.enableLogs) != null ? _c : false;
|
|
1211
1584
|
}
|
|
1212
1585
|
// ── Public API ──
|
|
1213
1586
|
get connected() {
|
|
1214
1587
|
return this._connected;
|
|
1215
1588
|
}
|
|
1589
|
+
/** Decode dynamic authenticated REST bytes in the same processing environment as live data. */
|
|
1590
|
+
decodeHistory(payload) {
|
|
1591
|
+
return __async(this, null, function* () {
|
|
1592
|
+
return decodeChartHistory(payload);
|
|
1593
|
+
});
|
|
1594
|
+
}
|
|
1595
|
+
/** Immutable history decoder. Browser adapters execute this inside their Worker. */
|
|
1596
|
+
loadHistory(manifest, options) {
|
|
1597
|
+
return __async(this, null, function* () {
|
|
1598
|
+
var _a, _b, _c;
|
|
1599
|
+
if (this.destroyed) throw new Error("Market-data client disposed");
|
|
1600
|
+
const controller = new AbortController();
|
|
1601
|
+
const abort = () => {
|
|
1602
|
+
var _a2;
|
|
1603
|
+
return controller.abort((_a2 = options == null ? void 0 : options.signal) == null ? void 0 : _a2.reason);
|
|
1604
|
+
};
|
|
1605
|
+
(_a = options == null ? void 0 : options.signal) == null ? void 0 : _a.addEventListener("abort", abort, { once: true });
|
|
1606
|
+
if ((_b = options == null ? void 0 : options.signal) == null ? void 0 : _b.aborted) abort();
|
|
1607
|
+
this.historyControllers.add(controller);
|
|
1608
|
+
try {
|
|
1609
|
+
controller.signal.throwIfAborted();
|
|
1610
|
+
const result = yield loadImmutableHistory({ manifest, signal: controller.signal });
|
|
1611
|
+
controller.signal.throwIfAborted();
|
|
1612
|
+
return result;
|
|
1613
|
+
} finally {
|
|
1614
|
+
this.historyControllers.delete(controller);
|
|
1615
|
+
(_c = options == null ? void 0 : options.signal) == null ? void 0 : _c.removeEventListener("abort", abort);
|
|
1616
|
+
}
|
|
1617
|
+
});
|
|
1618
|
+
}
|
|
1619
|
+
/** Optional framework-independent host diagnostics, cleared on disposal. */
|
|
1620
|
+
setHostDiagnostics(provider) {
|
|
1621
|
+
this.hostDiagnostics = provider;
|
|
1622
|
+
}
|
|
1623
|
+
/** On-demand ownership diagnostics; contains no credentials or user/account data. */
|
|
1624
|
+
getDiagnostics() {
|
|
1625
|
+
var _a;
|
|
1626
|
+
return {
|
|
1627
|
+
connected: this.connected,
|
|
1628
|
+
host: (_a = this.hostDiagnostics) == null ? void 0 : _a.call(this),
|
|
1629
|
+
transport: this.destroyed ? "disposed" : "direct",
|
|
1630
|
+
orderbookOutcomeIds: this.activeOrderbookMarkets(),
|
|
1631
|
+
tradeOutcomeIds: this.activeTradeMarkets(),
|
|
1632
|
+
arbMarketIds: this.activeArbMarkets(),
|
|
1633
|
+
arbFeedSubscribers: this.arbFeedCbs.size,
|
|
1634
|
+
cachedBooks: this.books.size,
|
|
1635
|
+
cachedArb: this.latestArb.size,
|
|
1636
|
+
resyncingBooks: this.resyncing.size,
|
|
1637
|
+
pendingResnapshots: this.pendingResnapshots.size,
|
|
1638
|
+
pendingHistoryRequests: this.historyControllers.size
|
|
1639
|
+
};
|
|
1640
|
+
}
|
|
1216
1641
|
/** Get the current orderbook state for an outcome (or null if no snapshot received yet). */
|
|
1217
1642
|
getBook(outcomeId) {
|
|
1218
|
-
var _a;
|
|
1219
|
-
return (_a = this.books.get(outcomeId))
|
|
1643
|
+
var _a, _b;
|
|
1644
|
+
return (_b = (_a = this.books.get(outcomeId)) == null ? void 0 : _a.view()) != null ? _b : null;
|
|
1220
1645
|
}
|
|
1221
1646
|
/** Whether an outcome is currently resyncing (waiting for fresh snapshot). */
|
|
1222
1647
|
isResyncing(outcomeId) {
|
|
@@ -1299,6 +1724,8 @@ var AggWebSocket = class {
|
|
|
1299
1724
|
if (!sub) {
|
|
1300
1725
|
sub = { refCount: 0, tradeRefs: 0 };
|
|
1301
1726
|
this.subs.set(outcomeId, sub);
|
|
1727
|
+
}
|
|
1728
|
+
if (sub.refCount === 0) {
|
|
1302
1729
|
this.pendingSubs.add(outcomeId);
|
|
1303
1730
|
this.ensureConnected();
|
|
1304
1731
|
if (this._connected) {
|
|
@@ -1309,13 +1736,19 @@ var AggWebSocket = class {
|
|
|
1309
1736
|
}
|
|
1310
1737
|
}
|
|
1311
1738
|
sub.refCount++;
|
|
1739
|
+
let released = false;
|
|
1312
1740
|
return () => {
|
|
1741
|
+
if (released) return;
|
|
1742
|
+
released = true;
|
|
1313
1743
|
const s = this.subs.get(outcomeId);
|
|
1314
1744
|
if (!s) return;
|
|
1315
1745
|
s.refCount--;
|
|
1316
|
-
if (s.refCount <= 0
|
|
1317
|
-
|
|
1318
|
-
|
|
1746
|
+
if (s.refCount <= 0) {
|
|
1747
|
+
s.refCount = 0;
|
|
1748
|
+
if (s.tradeRefs <= 0) {
|
|
1749
|
+
this.subs.delete(outcomeId);
|
|
1750
|
+
this.books.delete(outcomeId);
|
|
1751
|
+
}
|
|
1319
1752
|
this.resyncing.delete(outcomeId);
|
|
1320
1753
|
if (this._connected) {
|
|
1321
1754
|
if (this.pendingFlushSubs.has(outcomeId)) {
|
|
@@ -1355,7 +1788,10 @@ var AggWebSocket = class {
|
|
|
1355
1788
|
}
|
|
1356
1789
|
}
|
|
1357
1790
|
sub.tradeRefs++;
|
|
1791
|
+
let released = false;
|
|
1358
1792
|
return () => {
|
|
1793
|
+
if (released) return;
|
|
1794
|
+
released = true;
|
|
1359
1795
|
const s = this.subs.get(outcomeId);
|
|
1360
1796
|
if (!s) return;
|
|
1361
1797
|
s.tradeRefs--;
|
|
@@ -1373,6 +1809,8 @@ var AggWebSocket = class {
|
|
|
1373
1809
|
this.pendingResnapshots.delete(outcomeId);
|
|
1374
1810
|
if (s.refCount <= 0) {
|
|
1375
1811
|
this.subs.delete(outcomeId);
|
|
1812
|
+
this.books.delete(outcomeId);
|
|
1813
|
+
this.resyncing.delete(outcomeId);
|
|
1376
1814
|
}
|
|
1377
1815
|
}
|
|
1378
1816
|
};
|
|
@@ -1411,7 +1849,12 @@ var AggWebSocket = class {
|
|
|
1411
1849
|
/** Permanently destroy. Cannot reconnect after this. */
|
|
1412
1850
|
destroy() {
|
|
1413
1851
|
this.destroyed = true;
|
|
1852
|
+
for (const controller of this.historyControllers)
|
|
1853
|
+
controller.abort(new Error("Market-data client disposed"));
|
|
1854
|
+
this.historyControllers.clear();
|
|
1414
1855
|
this.disconnect();
|
|
1856
|
+
this.hostDiagnostics = void 0;
|
|
1857
|
+
this.callbacks = {};
|
|
1415
1858
|
this.subs.clear();
|
|
1416
1859
|
this.books.clear();
|
|
1417
1860
|
this.resyncing.clear();
|
|
@@ -1446,6 +1889,7 @@ var AggWebSocket = class {
|
|
|
1446
1889
|
const ws = new WebSocket(this.url);
|
|
1447
1890
|
this.ws = ws;
|
|
1448
1891
|
ws.onopen = () => {
|
|
1892
|
+
if (this.destroyed || this.ws !== ws) return;
|
|
1449
1893
|
this.connecting = false;
|
|
1450
1894
|
this.reconnectAttempts = 0;
|
|
1451
1895
|
this.resetStaleTimer();
|
|
@@ -1454,7 +1898,10 @@ var AggWebSocket = class {
|
|
|
1454
1898
|
}
|
|
1455
1899
|
};
|
|
1456
1900
|
ws.onmessage = (event) => {
|
|
1901
|
+
var _a, _b;
|
|
1902
|
+
if (this.destroyed || this.ws !== ws) return;
|
|
1457
1903
|
this.lastMessageTime = Date.now();
|
|
1904
|
+
(_b = (_a = this.callbacks).onFrameReceived) == null ? void 0 : _b.call(_a, this.lastMessageTime);
|
|
1458
1905
|
this.resetStaleTimer();
|
|
1459
1906
|
try {
|
|
1460
1907
|
const raw = JSON.parse(event.data);
|
|
@@ -1517,8 +1964,14 @@ var AggWebSocket = class {
|
|
|
1517
1964
|
}
|
|
1518
1965
|
// ── Message handling ──
|
|
1519
1966
|
handleMessage(raw) {
|
|
1520
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
|
|
1967
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
|
|
1521
1968
|
const type = raw.type;
|
|
1969
|
+
if (["orderbook_snapshot", "orderbook_delta", "trade"].includes(type) && !validMarketFrame(raw)) {
|
|
1970
|
+
(_b = (_a = this.callbacks).onError) == null ? void 0 : _b.call(_a, { type: "error", message: "Invalid market-data frame" });
|
|
1971
|
+
if (typeof raw.outcomeId === "string" && this.subs.has(raw.outcomeId))
|
|
1972
|
+
this.requestResnapshot(raw.outcomeId);
|
|
1973
|
+
return;
|
|
1974
|
+
}
|
|
1522
1975
|
switch (type) {
|
|
1523
1976
|
case "orderbook_snapshot":
|
|
1524
1977
|
this.handleSnapshot(raw);
|
|
@@ -1533,22 +1986,22 @@ var AggWebSocket = class {
|
|
|
1533
1986
|
this.handleHeartbeat(raw);
|
|
1534
1987
|
break;
|
|
1535
1988
|
case "subscribed":
|
|
1536
|
-
(
|
|
1989
|
+
(_d = (_c = this.callbacks).onSubscribed) == null ? void 0 : _d.call(_c, raw);
|
|
1537
1990
|
break;
|
|
1538
1991
|
case "unsubscribed":
|
|
1539
|
-
(
|
|
1992
|
+
(_f = (_e = this.callbacks).onUnsubscribed) == null ? void 0 : _f.call(_e, raw);
|
|
1540
1993
|
break;
|
|
1541
1994
|
case "connected":
|
|
1542
1995
|
this.handleConnected(raw);
|
|
1543
1996
|
break;
|
|
1544
1997
|
case "authenticated":
|
|
1545
|
-
(
|
|
1998
|
+
(_h = (_g = this.callbacks).onAuthenticated) == null ? void 0 : _h.call(_g, raw);
|
|
1546
1999
|
break;
|
|
1547
2000
|
case "market_resolved":
|
|
1548
2001
|
this.handleMarketResolved(raw);
|
|
1549
2002
|
break;
|
|
1550
2003
|
case "error":
|
|
1551
|
-
(
|
|
2004
|
+
(_j = (_i = this.callbacks).onError) == null ? void 0 : _j.call(_i, raw);
|
|
1552
2005
|
break;
|
|
1553
2006
|
case "order_submitted":
|
|
1554
2007
|
this.handleOrderSubmitted(raw);
|
|
@@ -1557,13 +2010,13 @@ var AggWebSocket = class {
|
|
|
1557
2010
|
this.handleBalanceUpdate(raw);
|
|
1558
2011
|
break;
|
|
1559
2012
|
case "order_event":
|
|
1560
|
-
(
|
|
2013
|
+
(_l = (_k = this.callbacks).onOrderEvent) == null ? void 0 : _l.call(_k, raw);
|
|
1561
2014
|
break;
|
|
1562
2015
|
case "redeem_event":
|
|
1563
2016
|
this.handleRedeemEvent(raw);
|
|
1564
2017
|
break;
|
|
1565
2018
|
case "withdrawal_lifecycle":
|
|
1566
|
-
(
|
|
2019
|
+
(_n = (_m = this.callbacks).onWithdrawalLifecycle) == null ? void 0 : _n.call(_m, raw);
|
|
1567
2020
|
break;
|
|
1568
2021
|
case "arb_market_update": {
|
|
1569
2022
|
const arbMsg = raw;
|
|
@@ -1572,13 +2025,13 @@ var AggWebSocket = class {
|
|
|
1572
2025
|
if (arbEntry) {
|
|
1573
2026
|
for (const cb of arbEntry.cbs) cb(arbMsg);
|
|
1574
2027
|
}
|
|
1575
|
-
(
|
|
2028
|
+
(_p = (_o = this.callbacks).onArbMarket) == null ? void 0 : _p.call(_o, arbMsg);
|
|
1576
2029
|
break;
|
|
1577
2030
|
}
|
|
1578
2031
|
case "arb_feed_batch": {
|
|
1579
2032
|
const feedMsg = raw;
|
|
1580
2033
|
for (const cb of this.arbFeedCbs) cb(feedMsg);
|
|
1581
|
-
(
|
|
2034
|
+
(_r = (_q = this.callbacks).onArbFeed) == null ? void 0 : _r.call(_q, feedMsg);
|
|
1582
2035
|
break;
|
|
1583
2036
|
}
|
|
1584
2037
|
}
|
|
@@ -1630,10 +2083,11 @@ var AggWebSocket = class {
|
|
|
1630
2083
|
}
|
|
1631
2084
|
}
|
|
1632
2085
|
handleSnapshot(raw) {
|
|
1633
|
-
var _a, _b;
|
|
2086
|
+
var _a, _b, _c, _d;
|
|
2087
|
+
if (!this.subs.has(raw.outcomeId)) return;
|
|
1634
2088
|
const msg = __spreadProps(__spreadValues({}, raw), { timestamp: raw.timestamp / 1e3 });
|
|
1635
2089
|
const book = snapshotToOrderbook(msg);
|
|
1636
|
-
this.books.set(msg.outcomeId, book);
|
|
2090
|
+
this.books.set(msg.outcomeId, new IndexedOrderbook(book));
|
|
1637
2091
|
this.resyncing.delete(msg.outcomeId);
|
|
1638
2092
|
this.pendingResnapshots.delete(msg.outcomeId);
|
|
1639
2093
|
this.debugOrderbook("snapshot_applied", {
|
|
@@ -1643,29 +2097,18 @@ var AggWebSocket = class {
|
|
|
1643
2097
|
bidsTop: this.summarizeTopLevels(book.bids),
|
|
1644
2098
|
asksTop: this.summarizeTopLevels(book.asks)
|
|
1645
2099
|
});
|
|
1646
|
-
(_b = (_a = this.callbacks).
|
|
2100
|
+
(_b = (_a = this.callbacks).onBookTick) == null ? void 0 : _b.call(_a, msg.outcomeId, {
|
|
2101
|
+
midpoint: msg.midpoint,
|
|
2102
|
+
timestamp: msg.timestamp,
|
|
2103
|
+
source: "snapshot"
|
|
2104
|
+
});
|
|
2105
|
+
if (!this.deferBookViews) (_d = (_c = this.callbacks).onSnapshot) == null ? void 0 : _d.call(_c, msg.outcomeId, book);
|
|
1647
2106
|
}
|
|
1648
2107
|
handleDelta(raw) {
|
|
1649
|
-
var _a, _b;
|
|
2108
|
+
var _a, _b, _c, _d;
|
|
2109
|
+
if (!this.subs.has(raw.outcomeId)) return;
|
|
1650
2110
|
const outcomeId = raw.outcomeId;
|
|
1651
2111
|
const current = this.books.get(outcomeId);
|
|
1652
|
-
const deltaTop = {
|
|
1653
|
-
bids: raw.bidChanges.slice(0, ORDERBOOK_DEBUG_TOP_LEVELS).map(([price, size]) => ({
|
|
1654
|
-
price,
|
|
1655
|
-
size
|
|
1656
|
-
})),
|
|
1657
|
-
asks: raw.askChanges.slice(0, ORDERBOOK_DEBUG_TOP_LEVELS).map(([price, size]) => ({
|
|
1658
|
-
price,
|
|
1659
|
-
size
|
|
1660
|
-
}))
|
|
1661
|
-
};
|
|
1662
|
-
this.debugOrderbook("delta_received", {
|
|
1663
|
-
outcomeId,
|
|
1664
|
-
seq: raw.seq,
|
|
1665
|
-
checksum: raw.checksum,
|
|
1666
|
-
hasCurrentBook: Boolean(current),
|
|
1667
|
-
deltaTop
|
|
1668
|
-
});
|
|
1669
2112
|
if (!current) {
|
|
1670
2113
|
this.debugOrderbook("delta_missing_snapshot", { outcomeId, seq: raw.seq });
|
|
1671
2114
|
this.requestResnapshot(outcomeId);
|
|
@@ -1696,21 +2139,7 @@ var AggWebSocket = class {
|
|
|
1696
2139
|
return;
|
|
1697
2140
|
}
|
|
1698
2141
|
const msg = __spreadProps(__spreadValues({}, raw), { timestamp: raw.timestamp / 1e3 });
|
|
1699
|
-
const
|
|
1700
|
-
this.debugOrderbook("delta_applied_locally", {
|
|
1701
|
-
outcomeId,
|
|
1702
|
-
fromSeq: current.seq,
|
|
1703
|
-
toSeq: newBook.seq,
|
|
1704
|
-
beforeTop: {
|
|
1705
|
-
bids: this.summarizeTopLevels(current.bids),
|
|
1706
|
-
asks: this.summarizeTopLevels(current.asks)
|
|
1707
|
-
},
|
|
1708
|
-
afterTop: {
|
|
1709
|
-
bids: this.summarizeTopLevels(newBook.bids),
|
|
1710
|
-
asks: this.summarizeTopLevels(newBook.asks)
|
|
1711
|
-
}
|
|
1712
|
-
});
|
|
1713
|
-
const computed = computeChecksum(newBook);
|
|
2142
|
+
const computed = current.apply(msg);
|
|
1714
2143
|
if (computed !== msg.checksum) {
|
|
1715
2144
|
this.debugOrderbook("delta_checksum_mismatch", {
|
|
1716
2145
|
outcomeId,
|
|
@@ -1728,18 +2157,16 @@ var AggWebSocket = class {
|
|
|
1728
2157
|
this.requestResnapshot(outcomeId);
|
|
1729
2158
|
return;
|
|
1730
2159
|
}
|
|
1731
|
-
this.
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
checksum: newBook.checksum,
|
|
1736
|
-
bidsTop: this.summarizeTopLevels(newBook.bids),
|
|
1737
|
-
asksTop: this.summarizeTopLevels(newBook.asks)
|
|
2160
|
+
(_b = (_a = this.callbacks).onBookTick) == null ? void 0 : _b.call(_a, outcomeId, {
|
|
2161
|
+
midpoint: msg.midpoint,
|
|
2162
|
+
timestamp: msg.timestamp,
|
|
2163
|
+
source: "delta"
|
|
1738
2164
|
});
|
|
1739
|
-
(
|
|
2165
|
+
if (!this.deferBookViews) (_d = (_c = this.callbacks).onDelta) == null ? void 0 : _d.call(_c, outcomeId, current.view());
|
|
1740
2166
|
}
|
|
1741
2167
|
handleTrade(raw) {
|
|
1742
2168
|
var _a, _b;
|
|
2169
|
+
if (!this.subs.has(raw.outcomeId)) return;
|
|
1743
2170
|
const msg = __spreadProps(__spreadValues({}, raw), { timestamp: raw.timestamp / 1e3 });
|
|
1744
2171
|
(_b = (_a = this.callbacks).onTrade) == null ? void 0 : _b.call(_a, msg);
|
|
1745
2172
|
}
|
|
@@ -1900,8 +2327,8 @@ var AggWebSocket = class {
|
|
|
1900
2327
|
var _a, _b;
|
|
1901
2328
|
(_b = (_a = this.callbacks).onDiagnostics) == null ? void 0 : _b.call(_a, event);
|
|
1902
2329
|
}
|
|
1903
|
-
summarizeTopLevels(
|
|
1904
|
-
return
|
|
2330
|
+
summarizeTopLevels(levels2) {
|
|
2331
|
+
return levels2.slice(0, ORDERBOOK_DEBUG_TOP_LEVELS).map((level) => ({ price: level.price, size: level.size }));
|
|
1905
2332
|
}
|
|
1906
2333
|
debugOrderbook(event, payload) {
|
|
1907
2334
|
if (!this.isOrderbookDebugEnabled()) return;
|
|
@@ -2002,7 +2429,7 @@ var AggClient = class {
|
|
|
2002
2429
|
this.authChannel = null;
|
|
2003
2430
|
/** In-flight refresh promise — serializes concurrent 401 retries so only one refresh runs. */
|
|
2004
2431
|
this.pendingRefresh = null;
|
|
2005
|
-
var _a, _b;
|
|
2432
|
+
var _a, _b, _c;
|
|
2006
2433
|
if (!options.appId && !options.adminKey) {
|
|
2007
2434
|
throw new Error("AggClient requires at least one of appId or adminKey");
|
|
2008
2435
|
}
|
|
@@ -2012,9 +2439,11 @@ var AggClient = class {
|
|
|
2012
2439
|
this.signer = options.signer;
|
|
2013
2440
|
this.baseUrl = options.baseUrl.replace(/\/$/, "");
|
|
2014
2441
|
this.wsUrl = options.wsUrl;
|
|
2442
|
+
this.preferImmutableHistory = (_a = options.preferImmutableHistory) != null ? _a : false;
|
|
2443
|
+
this.webSocketFactory = options.webSocketFactory;
|
|
2015
2444
|
this.authOptions = options.auth;
|
|
2016
|
-
this.storageKey = `agg_auth_${(
|
|
2017
|
-
this.authDelivery = (
|
|
2445
|
+
this.storageKey = `agg_auth_${(_b = this._appId) != null ? _b : "default"}`;
|
|
2446
|
+
this.authDelivery = (_c = options.authDelivery) != null ? _c : "body";
|
|
2018
2447
|
this.shouldPersistSession = options.persistSession !== false;
|
|
2019
2448
|
this.restoreSession();
|
|
2020
2449
|
this.initAuthChannel();
|
|
@@ -2142,7 +2571,7 @@ var AggClient = class {
|
|
|
2142
2571
|
* @param path - API path (e.g. `/venue-events`)
|
|
2143
2572
|
* @param init - Fetch init options, plus optional `query` object for URL search params
|
|
2144
2573
|
*/
|
|
2145
|
-
request(path, init) {
|
|
2574
|
+
request(path, init, decode) {
|
|
2146
2575
|
return __async(this, null, function* () {
|
|
2147
2576
|
const response = yield this.rawFetch(path, init);
|
|
2148
2577
|
if (response.status === 401 && this.accessToken && !AUTH_PATHS.has(path)) {
|
|
@@ -2153,7 +2582,7 @@ var AggClient = class {
|
|
|
2153
2582
|
return this.throwResponseError(retryResponse);
|
|
2154
2583
|
}
|
|
2155
2584
|
if (retryResponse.status === 204) return void 0;
|
|
2156
|
-
return retryResponse.json();
|
|
2585
|
+
return decode ? decode(retryResponse) : retryResponse.json();
|
|
2157
2586
|
} catch (e) {
|
|
2158
2587
|
this.clearAccessToken();
|
|
2159
2588
|
return this.throwResponseError(response);
|
|
@@ -2163,7 +2592,7 @@ var AggClient = class {
|
|
|
2163
2592
|
return this.throwResponseError(response);
|
|
2164
2593
|
}
|
|
2165
2594
|
if (response.status === 204) return void 0;
|
|
2166
|
-
return response.json();
|
|
2595
|
+
return decode ? decode(response) : response.json();
|
|
2167
2596
|
});
|
|
2168
2597
|
}
|
|
2169
2598
|
rawFetch(path, init) {
|
|
@@ -2200,12 +2629,15 @@ var AggClient = class {
|
|
|
2200
2629
|
}
|
|
2201
2630
|
throwResponseError(response) {
|
|
2202
2631
|
return __async(this, null, function* () {
|
|
2632
|
+
var _a;
|
|
2203
2633
|
let message = response.status === 404 ? "Market not found" : `AGG API error: ${response.status} ${response.statusText}`;
|
|
2204
2634
|
let code;
|
|
2205
2635
|
let retryable;
|
|
2636
|
+
let retryAfterMs = parseRetryAfterHeader((_a = response.headers) == null ? void 0 : _a.get("Retry-After"));
|
|
2206
2637
|
let errors;
|
|
2207
2638
|
try {
|
|
2208
2639
|
const body = yield response.json();
|
|
2640
|
+
retryAfterMs != null ? retryAfterMs : retryAfterMs = parseRetryAfterSeconds(body == null ? void 0 : body.retryAfter);
|
|
2209
2641
|
if (typeof body.message === "string" && body.message.length > 0) {
|
|
2210
2642
|
message = body.message;
|
|
2211
2643
|
}
|
|
@@ -2224,7 +2656,7 @@ var AggClient = class {
|
|
|
2224
2656
|
}
|
|
2225
2657
|
} catch (e) {
|
|
2226
2658
|
}
|
|
2227
|
-
throw new AggApiError(message, response.status, { code, retryable, errors });
|
|
2659
|
+
throw new AggApiError(message, response.status, { code, retryable, retryAfterMs, errors });
|
|
2228
2660
|
});
|
|
2229
2661
|
}
|
|
2230
2662
|
/**
|
|
@@ -2651,14 +3083,19 @@ Issued At: ${issuedAt}`;
|
|
|
2651
3083
|
*
|
|
2652
3084
|
* Pass `quoteId` to fetch every leg of a multi-venue split route in
|
|
2653
3085
|
* one call — `useQuoteSummary(quoteId)` reduces the list into a
|
|
2654
|
-
* rollup (total cost, share-weighted avg price, to-win).
|
|
3086
|
+
* rollup (total cost, share-weighted avg price, to-win). Pass
|
|
3087
|
+
* `venueMarketIds` to narrow to the orders on those markets. Sent as
|
|
3088
|
+
* repeated params in one request; batch long lists yourself (or use
|
|
3089
|
+
* `useExecutionOrdersForMarkets`) to keep the URL short.
|
|
2655
3090
|
*/
|
|
2656
3091
|
getExecutionOrders() {
|
|
2657
3092
|
return __async(this, arguments, function* (params = {}) {
|
|
3093
|
+
var _a;
|
|
2658
3094
|
const query = {};
|
|
2659
3095
|
if (params.orderId) query.orderId = params.orderId;
|
|
2660
3096
|
if (params.quoteId) query.quoteId = params.quoteId;
|
|
2661
3097
|
if (params.externalId) query.externalId = params.externalId;
|
|
3098
|
+
if ((_a = params.venueMarketIds) == null ? void 0 : _a.length) query.venueMarketIds = params.venueMarketIds;
|
|
2662
3099
|
if (params.status) query.status = params.status;
|
|
2663
3100
|
if (params.orderType) query.orderType = params.orderType;
|
|
2664
3101
|
if (params.mode) query.mode = params.mode;
|
|
@@ -2695,6 +3132,23 @@ Issued At: ${issuedAt}`;
|
|
|
2695
3132
|
});
|
|
2696
3133
|
});
|
|
2697
3134
|
}
|
|
3135
|
+
/**
|
|
3136
|
+
* Per-app trader leaderboard ranked by realized P&L or volume over an
|
|
3137
|
+
* inclusive UTC day range. `rank` is exact within the top 100.
|
|
3138
|
+
*/
|
|
3139
|
+
getLeaderboard() {
|
|
3140
|
+
return __async(this, arguments, function* (params = {}) {
|
|
3141
|
+
const query = {};
|
|
3142
|
+
if (params.from) query.from = params.from;
|
|
3143
|
+
if (params.to) query.to = params.to;
|
|
3144
|
+
if (params.metric) query.metric = params.metric;
|
|
3145
|
+
if (params.limit != null) query.limit = String(params.limit);
|
|
3146
|
+
if (params.cursor) query.cursor = params.cursor;
|
|
3147
|
+
return this.request("/leaderboard", {
|
|
3148
|
+
query: Object.keys(query).length ? query : void 0
|
|
3149
|
+
});
|
|
3150
|
+
});
|
|
3151
|
+
}
|
|
2698
3152
|
/** List execution positions for the authenticated user (cursor pagination). */
|
|
2699
3153
|
getExecutionPositions() {
|
|
2700
3154
|
return __async(this, arguments, function* (params = {}) {
|
|
@@ -2708,16 +3162,92 @@ Issued At: ${issuedAt}`;
|
|
|
2708
3162
|
});
|
|
2709
3163
|
});
|
|
2710
3164
|
}
|
|
2711
|
-
/**
|
|
3165
|
+
/**
|
|
3166
|
+
* Get cash balances and per-venue position balances.
|
|
3167
|
+
*
|
|
3168
|
+
* `custody: "self"` returns the wallets linked to this account — plus their
|
|
3169
|
+
* Polymarket deposit and legacy wallets — instead of the managed wallet. Each
|
|
3170
|
+
* chain row then carries `address` and `custodyKind`; `positions` is
|
|
3171
|
+
* account-wide either way.
|
|
3172
|
+
*
|
|
3173
|
+
* Caveat on the headline number: a chain row with `custodyKind:
|
|
3174
|
+
* "POLYMARKET_LEGACY"` and `legacyKind: "proxy"` holds funds that can only
|
|
3175
|
+
* be spent on Polymarket, but it still counts towards its token's
|
|
3176
|
+
* `totalRaw`/`availableRaw` (a token's totals are always the sum of its
|
|
3177
|
+
* chain rows). If you show "spendable anywhere", subtract those rows.
|
|
3178
|
+
*/
|
|
2712
3179
|
getManagedBalances() {
|
|
2713
3180
|
return __async(this, arguments, function* (params = {}) {
|
|
2714
3181
|
const query = {};
|
|
2715
3182
|
if (params.mode) query.mode = params.mode;
|
|
3183
|
+
if (params.custody) query.custody = params.custody;
|
|
2716
3184
|
return this.request("/execution/balances", {
|
|
2717
3185
|
query: Object.keys(query).length ? query : void 0
|
|
2718
3186
|
});
|
|
2719
3187
|
});
|
|
2720
3188
|
}
|
|
3189
|
+
/** Read hosted custody status without creating a signing wallet or account. */
|
|
3190
|
+
getHostedVenueAccount(_0) {
|
|
3191
|
+
return __async(this, arguments, function* (venue, params = {}) {
|
|
3192
|
+
return this.request(
|
|
3193
|
+
`/users/me/venue-accounts/${encodeURIComponent(venue)}`,
|
|
3194
|
+
{
|
|
3195
|
+
query: params.mode ? { mode: params.mode } : void 0
|
|
3196
|
+
}
|
|
3197
|
+
);
|
|
3198
|
+
});
|
|
3199
|
+
}
|
|
3200
|
+
/** Owned exact ledger entries; not balances, fill fees or withdrawal finality. */
|
|
3201
|
+
getHostedVenueActivity(_0) {
|
|
3202
|
+
return __async(this, arguments, function* (venue, params = {}) {
|
|
3203
|
+
return this.request(
|
|
3204
|
+
`/users/me/venue-accounts/${encodeURIComponent(venue)}/activity`,
|
|
3205
|
+
{
|
|
3206
|
+
query: __spreadValues(__spreadValues({}, params.mode ? { mode: params.mode } : {}), params.page !== void 0 ? { page: String(params.page) } : {})
|
|
3207
|
+
}
|
|
3208
|
+
);
|
|
3209
|
+
});
|
|
3210
|
+
}
|
|
3211
|
+
/** Explicit hosted-account creation; no signing wallet or credential upload. */
|
|
3212
|
+
provisionHostedVenueAccount(venue, body) {
|
|
3213
|
+
return __async(this, null, function* () {
|
|
3214
|
+
return this.request(
|
|
3215
|
+
`/users/me/venue-accounts/${encodeURIComponent(venue)}`,
|
|
3216
|
+
{
|
|
3217
|
+
method: "POST",
|
|
3218
|
+
body: JSON.stringify(body)
|
|
3219
|
+
}
|
|
3220
|
+
);
|
|
3221
|
+
});
|
|
3222
|
+
}
|
|
3223
|
+
/** Fetch the owned hosted account's verified Solana USDC deposit address. */
|
|
3224
|
+
getHostedVenueDepositAddress(_0) {
|
|
3225
|
+
return __async(this, arguments, function* (venue, params = {}) {
|
|
3226
|
+
return this.request(
|
|
3227
|
+
`/users/me/venue-accounts/${encodeURIComponent(venue)}/deposit-address`,
|
|
3228
|
+
{ query: params.mode ? { mode: params.mode } : void 0 }
|
|
3229
|
+
);
|
|
3230
|
+
});
|
|
3231
|
+
}
|
|
3232
|
+
/** Submit exactly one explicit hosted withdrawal under a caller idempotency key. */
|
|
3233
|
+
withdrawHostedVenue(venue, body) {
|
|
3234
|
+
return __async(this, null, function* () {
|
|
3235
|
+
return this.request(
|
|
3236
|
+
`/users/me/venue-accounts/${encodeURIComponent(venue)}/withdrawals`,
|
|
3237
|
+
{ method: "POST", body: JSON.stringify(body) }
|
|
3238
|
+
);
|
|
3239
|
+
});
|
|
3240
|
+
}
|
|
3241
|
+
/** Read only Agg's persisted withdrawal state; this never replays a native request. */
|
|
3242
|
+
getHostedVenueWithdrawal(_0, _1) {
|
|
3243
|
+
return __async(this, arguments, function* (venue, withdrawalId, params = {}) {
|
|
3244
|
+
if (!withdrawalId) throw new Error("withdrawalId is required");
|
|
3245
|
+
return this.request(
|
|
3246
|
+
`/users/me/venue-accounts/${encodeURIComponent(venue)}/withdrawals/${encodeURIComponent(withdrawalId)}`,
|
|
3247
|
+
{ query: params.mode ? { mode: params.mode } : void 0 }
|
|
3248
|
+
);
|
|
3249
|
+
});
|
|
3250
|
+
}
|
|
2721
3251
|
/** Store or replace encrypted credentials for a venue. Secrets are never returned. */
|
|
2722
3252
|
upsertVenueKey(body) {
|
|
2723
3253
|
return __async(this, null, function* () {
|
|
@@ -2840,21 +3370,32 @@ Issued At: ${issuedAt}`;
|
|
|
2840
3370
|
});
|
|
2841
3371
|
}
|
|
2842
3372
|
/**
|
|
2843
|
-
* Cancel an
|
|
3373
|
+
* Cancel an agg order by id. Self-custody needs Polymarket ClobAuth
|
|
2844
3374
|
* or a fresh Hyperliquid cancel action signed by the EOA/client-held agent.
|
|
2845
3375
|
*/
|
|
2846
3376
|
cancelManagedOrder(orderId, options) {
|
|
2847
3377
|
return __async(this, null, function* () {
|
|
2848
|
-
return this.request(
|
|
2849
|
-
|
|
2850
|
-
{
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
3378
|
+
return this.request("/execution/orders/cancel", {
|
|
3379
|
+
method: "POST",
|
|
3380
|
+
body: JSON.stringify(__spreadValues({
|
|
3381
|
+
orderId
|
|
3382
|
+
}, (options == null ? void 0 : options.cancelSignature) ? { cancelSignature: options.cancelSignature } : {})),
|
|
3383
|
+
signal: options == null ? void 0 : options.signal
|
|
3384
|
+
});
|
|
3385
|
+
});
|
|
3386
|
+
}
|
|
3387
|
+
/**
|
|
3388
|
+
* Cancel a Polymarket or Hyperliquid limit order that one of the user's
|
|
3389
|
+
* linked self-custody wallets placed outside AGG. `signerAddress` must be
|
|
3390
|
+
* that wallet and must have produced `cancelSignature`.
|
|
3391
|
+
*/
|
|
3392
|
+
cancelVenueOrder(params, options) {
|
|
3393
|
+
return __async(this, null, function* () {
|
|
3394
|
+
return this.request("/execution/orders/cancel", {
|
|
3395
|
+
method: "POST",
|
|
3396
|
+
body: JSON.stringify(params),
|
|
3397
|
+
signal: options == null ? void 0 : options.signal
|
|
3398
|
+
});
|
|
2858
3399
|
});
|
|
2859
3400
|
}
|
|
2860
3401
|
// --- Venue events & venue markets (primary) ---
|
|
@@ -2887,6 +3428,17 @@ Issued At: ${issuedAt}`;
|
|
|
2887
3428
|
});
|
|
2888
3429
|
}
|
|
2889
3430
|
/** Get a single venue event by ID. Requires appId or admin auth. */
|
|
3431
|
+
getEventBootstrap(eventId, options) {
|
|
3432
|
+
return __async(this, null, function* () {
|
|
3433
|
+
return this.request(
|
|
3434
|
+
`/venue-events/${encodeURIComponent(eventId)}/bootstrap`,
|
|
3435
|
+
{
|
|
3436
|
+
query: (options == null ? void 0 : options.limit) ? { limit: String(options.limit) } : void 0,
|
|
3437
|
+
signal: options == null ? void 0 : options.signal
|
|
3438
|
+
}
|
|
3439
|
+
);
|
|
3440
|
+
});
|
|
3441
|
+
}
|
|
2890
3442
|
getVenueEventById(id, options) {
|
|
2891
3443
|
return __async(this, null, function* () {
|
|
2892
3444
|
return this.request(`/venue-events/${encodeURIComponent(id)}`, {
|
|
@@ -3015,14 +3567,15 @@ Issued At: ${issuedAt}`;
|
|
|
3015
3567
|
});
|
|
3016
3568
|
}
|
|
3017
3569
|
/** List venue markets with optional filters. Requires appId or admin auth. Supports cursor-based pagination. */
|
|
3018
|
-
getVenueMarkets(options) {
|
|
3570
|
+
getVenueMarkets(options, requestOptions) {
|
|
3019
3571
|
return __async(this, null, function* () {
|
|
3020
|
-
var _a;
|
|
3572
|
+
var _a, _b;
|
|
3021
3573
|
const query = {};
|
|
3022
3574
|
if (options == null ? void 0 : options.venue) query.venue = options.venue;
|
|
3575
|
+
if ((_a = options == null ? void 0 : options.externalIdentifier) == null ? void 0 : _a.length) query.externalIdentifier = options.externalIdentifier;
|
|
3023
3576
|
if (options == null ? void 0 : options.venueEventId) query.venueEventId = options.venueEventId;
|
|
3024
3577
|
if ((options == null ? void 0 : options.cluster) === false) query.cluster = "false";
|
|
3025
|
-
if ((
|
|
3578
|
+
if ((_b = options == null ? void 0 : options.search) == null ? void 0 : _b.trim()) query.search = options.search.trim();
|
|
3026
3579
|
if (options == null ? void 0 : options.matchStatus) query.matchStatus = options.matchStatus;
|
|
3027
3580
|
if (options == null ? void 0 : options.status) query.status = options.status;
|
|
3028
3581
|
if ((options == null ? void 0 : options.aggKey) && options.aggKey.length > 0) query.aggKey = options.aggKey;
|
|
@@ -3042,7 +3595,8 @@ Issued At: ${issuedAt}`;
|
|
|
3042
3595
|
if (options == null ? void 0 : options.sortDir) query.sortDir = options.sortDir;
|
|
3043
3596
|
if (options == null ? void 0 : options.context) query.context = options.context;
|
|
3044
3597
|
return this.request("/venue-markets", {
|
|
3045
|
-
query: Object.keys(query).length > 0 ? query : void 0
|
|
3598
|
+
query: Object.keys(query).length > 0 ? query : void 0,
|
|
3599
|
+
signal: requestOptions == null ? void 0 : requestOptions.signal
|
|
3046
3600
|
});
|
|
3047
3601
|
});
|
|
3048
3602
|
}
|
|
@@ -3144,7 +3698,7 @@ Issued At: ${issuedAt}`;
|
|
|
3144
3698
|
* format intentionally omits the param so the server hits the cheaper
|
|
3145
3699
|
* (and longer-TTL) light cache slot.
|
|
3146
3700
|
*/
|
|
3147
|
-
search(params) {
|
|
3701
|
+
search(params, options) {
|
|
3148
3702
|
return __async(this, null, function* () {
|
|
3149
3703
|
const query = {
|
|
3150
3704
|
q: params.q,
|
|
@@ -3155,8 +3709,10 @@ Issued At: ${issuedAt}`;
|
|
|
3155
3709
|
if (params.limit != null) query.limit = String(params.limit);
|
|
3156
3710
|
if (params.cursor) query.cursor = params.cursor;
|
|
3157
3711
|
if (params.deep) query.deepSearch = "true";
|
|
3712
|
+
if (params.mode) query.mode = params.mode;
|
|
3158
3713
|
return this.request("/search", {
|
|
3159
|
-
query
|
|
3714
|
+
query,
|
|
3715
|
+
signal: options == null ? void 0 : options.signal
|
|
3160
3716
|
});
|
|
3161
3717
|
});
|
|
3162
3718
|
}
|
|
@@ -3218,6 +3774,7 @@ Issued At: ${issuedAt}`;
|
|
|
3218
3774
|
/** Get the canonical TradingView-style bar series for a single venue market outcome. */
|
|
3219
3775
|
getChartBars(params, options) {
|
|
3220
3776
|
return __async(this, null, function* () {
|
|
3777
|
+
var _a, _b;
|
|
3221
3778
|
const resolution = mapChartResolution(params.resolution);
|
|
3222
3779
|
const query = {
|
|
3223
3780
|
venueMarketOutcomeId: params.venueMarketOutcomeId,
|
|
@@ -3226,12 +3783,39 @@ Issued At: ${issuedAt}`;
|
|
|
3226
3783
|
if (resolution) query.resolution = resolution;
|
|
3227
3784
|
if (params.from != null) query.from = String(params.from);
|
|
3228
3785
|
if (params.countBack != null) query.countBack = String(params.countBack);
|
|
3786
|
+
if (options == null ? void 0 : options.decode) {
|
|
3787
|
+
const text = yield this.request(
|
|
3788
|
+
"/charts/bars",
|
|
3789
|
+
{ query, signal: options.signal },
|
|
3790
|
+
(response) => readChartHistoryText(response)
|
|
3791
|
+
);
|
|
3792
|
+
(_a = options.signal) == null ? void 0 : _a.throwIfAborted();
|
|
3793
|
+
const decoded = yield options.decode(text);
|
|
3794
|
+
(_b = options.signal) == null ? void 0 : _b.throwIfAborted();
|
|
3795
|
+
return decoded;
|
|
3796
|
+
}
|
|
3229
3797
|
return this.request("/charts/bars", {
|
|
3230
3798
|
query,
|
|
3231
3799
|
signal: options == null ? void 0 : options.signal
|
|
3232
3800
|
});
|
|
3233
3801
|
});
|
|
3234
3802
|
}
|
|
3803
|
+
getChartHistoryManifest(params, options) {
|
|
3804
|
+
return __async(this, null, function* () {
|
|
3805
|
+
const query = {
|
|
3806
|
+
venueMarketOutcomeId: params.venueMarketOutcomeId,
|
|
3807
|
+
to: String(params.to)
|
|
3808
|
+
};
|
|
3809
|
+
const resolution = mapChartResolution(params.resolution);
|
|
3810
|
+
if (resolution) query.resolution = resolution;
|
|
3811
|
+
if (params.from != null) query.from = String(params.from);
|
|
3812
|
+
if (params.countBack != null) query.countBack = String(params.countBack);
|
|
3813
|
+
return this.request("/charts/history/manifest", {
|
|
3814
|
+
query,
|
|
3815
|
+
signal: options == null ? void 0 : options.signal
|
|
3816
|
+
});
|
|
3817
|
+
});
|
|
3818
|
+
}
|
|
3235
3819
|
// --- Batch orderbooks ---
|
|
3236
3820
|
/** Get live per-venue orderbooks for the explicit venueMarketIds requested. */
|
|
3237
3821
|
getOrderbooks(params, options) {
|
|
@@ -3326,22 +3910,34 @@ Issued At: ${issuedAt}`;
|
|
|
3326
3910
|
return params.side ? __spreadProps(__spreadValues({}, response), { side: params.side }) : response;
|
|
3327
3911
|
});
|
|
3328
3912
|
}
|
|
3913
|
+
/** Seed subscribed outcomes with one bounded batch of compatible snapshots. */
|
|
3914
|
+
getOutcomeOrderbooks(params, options) {
|
|
3915
|
+
return __async(this, null, function* () {
|
|
3916
|
+
return this.request("/orderbooks/outcomes", {
|
|
3917
|
+
query: __spreadValues({
|
|
3918
|
+
venueMarketOutcomeIds: params.venueMarketOutcomeIds.join(",")
|
|
3919
|
+
}, params.depth == null ? {} : { depth: String(params.depth) }),
|
|
3920
|
+
signal: options == null ? void 0 : options.signal
|
|
3921
|
+
});
|
|
3922
|
+
});
|
|
3923
|
+
}
|
|
3329
3924
|
/**
|
|
3330
3925
|
* Create an AggWebSocket instance configured with this client's appId and optional auth token.
|
|
3331
3926
|
* Requires `wsUrl` to be set in the client options.
|
|
3332
3927
|
*/
|
|
3333
3928
|
createWebSocket(callbacks, options) {
|
|
3334
|
-
var _a;
|
|
3929
|
+
var _a, _b;
|
|
3335
3930
|
if (!this.wsUrl) {
|
|
3336
3931
|
throw new Error("AggClient.createWebSocket() requires wsUrl to be set in client options");
|
|
3337
3932
|
}
|
|
3338
3933
|
const url = new URL(this.wsUrl);
|
|
3339
3934
|
if (this._appId) url.searchParams.set("appId", this._appId);
|
|
3340
|
-
|
|
3935
|
+
const createSocket = (_a = this.webSocketFactory) != null ? _a : ((socketOptions) => new AggWebSocket(socketOptions));
|
|
3936
|
+
return createSocket({
|
|
3341
3937
|
url: url.toString(),
|
|
3342
3938
|
callbacks,
|
|
3343
3939
|
initialToken: this.accessToken,
|
|
3344
|
-
enableLogs: (
|
|
3940
|
+
enableLogs: (_b = options == null ? void 0 : options.enableLogs) != null ? _b : false
|
|
3345
3941
|
});
|
|
3346
3942
|
}
|
|
3347
3943
|
/** Execute a previously quoted managed trade. Returns pending order IDs. */
|
|
@@ -3686,6 +4282,24 @@ var CandleBuilder = class {
|
|
|
3686
4282
|
var _a;
|
|
3687
4283
|
return (_a = this.closedMap.get(interval)) != null ? _a : [];
|
|
3688
4284
|
}
|
|
4285
|
+
/** Apply a bounded Worker view without recomputing candles from presentation samples. */
|
|
4286
|
+
replaceTail(tail) {
|
|
4287
|
+
var _a, _b;
|
|
4288
|
+
for (const interval of ALL_INTERVALS) {
|
|
4289
|
+
const view = tail[interval];
|
|
4290
|
+
if (view.forming) this.forming.set(interval, __spreadValues({}, view.forming));
|
|
4291
|
+
else this.forming.delete(interval);
|
|
4292
|
+
if (!view.closed.length) continue;
|
|
4293
|
+
const closed = new Map(this.getClosed(interval).map((candle) => [candle.openTime, candle]));
|
|
4294
|
+
for (const candle of view.closed) closed.set(candle.openTime, __spreadValues({}, candle));
|
|
4295
|
+
this.closedMap.set(
|
|
4296
|
+
interval,
|
|
4297
|
+
[...closed.values()].sort((a, b) => a.openTime - b.openTime).slice(-MAX_CLOSED)
|
|
4298
|
+
);
|
|
4299
|
+
}
|
|
4300
|
+
this._midpoint = (_b = (_a = tail["1m"].forming) == null ? void 0 : _a.c) != null ? _b : null;
|
|
4301
|
+
this.markDirty();
|
|
4302
|
+
}
|
|
3689
4303
|
/** Current midpoint (latest value fed). */
|
|
3690
4304
|
get midpoint() {
|
|
3691
4305
|
return this._midpoint;
|
|
@@ -3848,6 +4462,7 @@ function createAggClient(options) {
|
|
|
3848
4462
|
OrderStatus,
|
|
3849
4463
|
OrderType,
|
|
3850
4464
|
RECURRENCE_CADENCES,
|
|
4465
|
+
RETINA_IMAGE_SIZES,
|
|
3851
4466
|
SELF_CUSTODY_FILL_TIMEOUT_MS,
|
|
3852
4467
|
SELF_CUSTODY_POLL_INTERVAL_MS,
|
|
3853
4468
|
TERMINAL_EXECUTION_STATES,
|
|
@@ -3881,13 +4496,17 @@ function createAggClient(options) {
|
|
|
3881
4496
|
isVenueActive,
|
|
3882
4497
|
isVenueDataVisible,
|
|
3883
4498
|
isVenueInactive,
|
|
4499
|
+
loadImmutableHistory,
|
|
3884
4500
|
mergeCandles,
|
|
3885
4501
|
mergeClosedCandles,
|
|
3886
4502
|
normalizeVenueMarketCluster,
|
|
3887
4503
|
optimizedImageUrl,
|
|
4504
|
+
orderbookCrc32,
|
|
3888
4505
|
parse,
|
|
3889
4506
|
parseEmail,
|
|
3890
4507
|
parseEmailStrict,
|
|
4508
|
+
projectedOrderbookChecksum,
|
|
4509
|
+
retinaImageUrl,
|
|
3891
4510
|
safeParse,
|
|
3892
4511
|
snapshotToOrderbook,
|
|
3893
4512
|
sortVenues,
|