@agg-build/sdk 1.2.11 → 1.3.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.d.mts +139 -16
- package/dist/index.d.ts +139 -16
- package/dist/index.js +145 -5
- package/dist/index.mjs +145 -5
- package/dist/server.d.mts +62 -6
- package/dist/server.d.ts +62 -6
- package/dist/server.js +61 -2
- package/dist/server.mjs +58 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -727,7 +727,14 @@ var AggWebSocket = class {
|
|
|
727
727
|
this.pendingFlushUnsubs = /* @__PURE__ */ new Set();
|
|
728
728
|
this.pendingFlushTradeSubs = /* @__PURE__ */ new Set();
|
|
729
729
|
this.pendingFlushTradeUnsubs = /* @__PURE__ */ new Set();
|
|
730
|
+
this.pendingFlushArbSubs = /* @__PURE__ */ new Set();
|
|
731
|
+
this.pendingFlushArbUnsubs = /* @__PURE__ */ new Set();
|
|
730
732
|
this.flushScheduled = false;
|
|
733
|
+
// ── Arb subscriptions ──
|
|
734
|
+
this.arbSubs = /* @__PURE__ */ new Map();
|
|
735
|
+
this.arbFeedCbs = /* @__PURE__ */ new Set();
|
|
736
|
+
/** Latest arb market update per marketId (last-value-wins, loss-tolerant). */
|
|
737
|
+
this.latestArb = /* @__PURE__ */ new Map();
|
|
731
738
|
// ── Orderbook state per market ──
|
|
732
739
|
this.books = /* @__PURE__ */ new Map();
|
|
733
740
|
/** Markets currently resyncing (awaiting snapshot after seq gap / checksum mismatch). */
|
|
@@ -759,6 +766,69 @@ var AggWebSocket = class {
|
|
|
759
766
|
isResyncing(outcomeId) {
|
|
760
767
|
return this.resyncing.has(outcomeId);
|
|
761
768
|
}
|
|
769
|
+
/** Get the latest arb update for a market (or null if none received yet). */
|
|
770
|
+
getArb(marketId) {
|
|
771
|
+
var _a;
|
|
772
|
+
return (_a = this.latestArb.get(marketId)) != null ? _a : null;
|
|
773
|
+
}
|
|
774
|
+
/**
|
|
775
|
+
* Subscribe to per-market arb updates for a given marketId.
|
|
776
|
+
* Ref-counted: multiple callers for the same marketId share one server subscription.
|
|
777
|
+
* Returns an unsubscribe function.
|
|
778
|
+
*/
|
|
779
|
+
subscribeArb(marketId, cb) {
|
|
780
|
+
let entry = this.arbSubs.get(marketId);
|
|
781
|
+
if (!entry) {
|
|
782
|
+
entry = { refCount: 0, cbs: /* @__PURE__ */ new Set() };
|
|
783
|
+
this.arbSubs.set(marketId, entry);
|
|
784
|
+
this.ensureConnected();
|
|
785
|
+
if (this._connected) {
|
|
786
|
+
this.pendingFlushArbUnsubs.delete(marketId);
|
|
787
|
+
this.pendingFlushArbSubs.add(marketId);
|
|
788
|
+
this.scheduleFlush();
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
entry.cbs.add(cb);
|
|
792
|
+
entry.refCount++;
|
|
793
|
+
return () => {
|
|
794
|
+
const e = this.arbSubs.get(marketId);
|
|
795
|
+
if (!e) return;
|
|
796
|
+
e.cbs.delete(cb);
|
|
797
|
+
e.refCount--;
|
|
798
|
+
if (e.refCount <= 0) {
|
|
799
|
+
this.arbSubs.delete(marketId);
|
|
800
|
+
if (this._connected) {
|
|
801
|
+
if (this.pendingFlushArbSubs.has(marketId)) {
|
|
802
|
+
this.pendingFlushArbSubs.delete(marketId);
|
|
803
|
+
} else {
|
|
804
|
+
this.pendingFlushArbUnsubs.add(marketId);
|
|
805
|
+
this.scheduleFlush();
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
};
|
|
810
|
+
}
|
|
811
|
+
/**
|
|
812
|
+
* Subscribe to the global arb-feed batches.
|
|
813
|
+
* Only one server subscription is maintained regardless of how many callers.
|
|
814
|
+
* Returns an unsubscribe function.
|
|
815
|
+
*/
|
|
816
|
+
subscribeArbFeed(cb) {
|
|
817
|
+
const wasEmpty = this.arbFeedCbs.size === 0;
|
|
818
|
+
this.arbFeedCbs.add(cb);
|
|
819
|
+
if (wasEmpty) {
|
|
820
|
+
this.ensureConnected();
|
|
821
|
+
if (this._connected) {
|
|
822
|
+
this.send({ action: "subscribe", channel: "arb-feed" });
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
return () => {
|
|
826
|
+
this.arbFeedCbs.delete(cb);
|
|
827
|
+
if (this.arbFeedCbs.size === 0 && this._connected) {
|
|
828
|
+
this.send({ action: "unsubscribe", channel: "arb-feed" });
|
|
829
|
+
}
|
|
830
|
+
};
|
|
831
|
+
}
|
|
762
832
|
/**
|
|
763
833
|
* Subscribe to a feed by outcome ID.
|
|
764
834
|
* @param outcomeId The venueMarketOutcomeId to subscribe to.
|
|
@@ -896,6 +966,11 @@ var AggWebSocket = class {
|
|
|
896
966
|
this.pendingFlushUnsubs.clear();
|
|
897
967
|
this.pendingFlushTradeSubs.clear();
|
|
898
968
|
this.pendingFlushTradeUnsubs.clear();
|
|
969
|
+
this.arbSubs.clear();
|
|
970
|
+
this.arbFeedCbs.clear();
|
|
971
|
+
this.latestArb.clear();
|
|
972
|
+
this.pendingFlushArbSubs.clear();
|
|
973
|
+
this.pendingFlushArbUnsubs.clear();
|
|
899
974
|
this.flushScheduled = false;
|
|
900
975
|
}
|
|
901
976
|
/** Update callbacks (e.g., after React re-render). */
|
|
@@ -941,7 +1016,7 @@ var AggWebSocket = class {
|
|
|
941
1016
|
if (wasConnected) {
|
|
942
1017
|
(_b = (_a = this.callbacks).onConnectionStateChange) == null ? void 0 : _b.call(_a, false);
|
|
943
1018
|
}
|
|
944
|
-
if (!this.destroyed && this.subs.size > 0) {
|
|
1019
|
+
if (!this.destroyed && (this.subs.size > 0 || this.arbSubs.size > 0 || this.arbFeedCbs.size > 0)) {
|
|
945
1020
|
this.scheduleReconnect();
|
|
946
1021
|
}
|
|
947
1022
|
};
|
|
@@ -986,7 +1061,7 @@ var AggWebSocket = class {
|
|
|
986
1061
|
}
|
|
987
1062
|
// ── Message handling ──
|
|
988
1063
|
handleMessage(raw) {
|
|
989
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
|
|
1064
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
|
|
990
1065
|
const type = raw.type;
|
|
991
1066
|
switch (type) {
|
|
992
1067
|
case "orderbook_snapshot":
|
|
@@ -1034,6 +1109,22 @@ var AggWebSocket = class {
|
|
|
1034
1109
|
case "withdrawal_lifecycle":
|
|
1035
1110
|
(_l = (_k = this.callbacks).onWithdrawalLifecycle) == null ? void 0 : _l.call(_k, raw);
|
|
1036
1111
|
break;
|
|
1112
|
+
case "arb_market_update": {
|
|
1113
|
+
const arbMsg = raw;
|
|
1114
|
+
this.latestArb.set(arbMsg.marketId, arbMsg);
|
|
1115
|
+
const arbEntry = this.arbSubs.get(arbMsg.marketId);
|
|
1116
|
+
if (arbEntry) {
|
|
1117
|
+
for (const cb of arbEntry.cbs) cb(arbMsg);
|
|
1118
|
+
}
|
|
1119
|
+
(_n = (_m = this.callbacks).onArbMarket) == null ? void 0 : _n.call(_m, arbMsg);
|
|
1120
|
+
break;
|
|
1121
|
+
}
|
|
1122
|
+
case "arb_feed_batch": {
|
|
1123
|
+
const feedMsg = raw;
|
|
1124
|
+
for (const cb of this.arbFeedCbs) cb(feedMsg);
|
|
1125
|
+
(_p = (_o = this.callbacks).onArbFeed) == null ? void 0 : _p.call(_o, feedMsg);
|
|
1126
|
+
break;
|
|
1127
|
+
}
|
|
1037
1128
|
}
|
|
1038
1129
|
}
|
|
1039
1130
|
/**
|
|
@@ -1070,6 +1161,17 @@ var AggWebSocket = class {
|
|
|
1070
1161
|
this.send({ action: "resnapshot", channel: "orderbook", outcomeIds: resnapshotIds });
|
|
1071
1162
|
}
|
|
1072
1163
|
this.pendingResnapshots.clear();
|
|
1164
|
+
const arbSet = new Set(this.activeArbMarkets());
|
|
1165
|
+
this.pendingFlushArbSubs.forEach((id) => arbSet.add(id));
|
|
1166
|
+
const arbIds = Array.from(arbSet);
|
|
1167
|
+
if (arbIds.length > 0) {
|
|
1168
|
+
this.send({ action: "subscribe", channel: "arb", marketIds: arbIds });
|
|
1169
|
+
}
|
|
1170
|
+
this.pendingFlushArbSubs.clear();
|
|
1171
|
+
this.pendingFlushArbUnsubs.clear();
|
|
1172
|
+
if (this.arbFeedCbs.size > 0) {
|
|
1173
|
+
this.send({ action: "subscribe", channel: "arb-feed" });
|
|
1174
|
+
}
|
|
1073
1175
|
}
|
|
1074
1176
|
handleSnapshot(raw) {
|
|
1075
1177
|
var _a, _b;
|
|
@@ -1241,6 +1343,8 @@ var AggWebSocket = class {
|
|
|
1241
1343
|
this.pendingFlushUnsubs.clear();
|
|
1242
1344
|
this.pendingFlushTradeSubs.clear();
|
|
1243
1345
|
this.pendingFlushTradeUnsubs.clear();
|
|
1346
|
+
this.pendingFlushArbSubs.clear();
|
|
1347
|
+
this.pendingFlushArbUnsubs.clear();
|
|
1244
1348
|
return;
|
|
1245
1349
|
}
|
|
1246
1350
|
this.flushPending();
|
|
@@ -1287,6 +1391,28 @@ var AggWebSocket = class {
|
|
|
1287
1391
|
});
|
|
1288
1392
|
this.pendingFlushTradeUnsubs.clear();
|
|
1289
1393
|
}
|
|
1394
|
+
for (const id of [...this.pendingFlushArbSubs]) {
|
|
1395
|
+
if (this.pendingFlushArbUnsubs.has(id)) {
|
|
1396
|
+
this.pendingFlushArbSubs.delete(id);
|
|
1397
|
+
this.pendingFlushArbUnsubs.delete(id);
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
if (this.pendingFlushArbSubs.size > 0) {
|
|
1401
|
+
this.send({
|
|
1402
|
+
action: "subscribe",
|
|
1403
|
+
channel: "arb",
|
|
1404
|
+
marketIds: Array.from(this.pendingFlushArbSubs)
|
|
1405
|
+
});
|
|
1406
|
+
this.pendingFlushArbSubs.clear();
|
|
1407
|
+
}
|
|
1408
|
+
if (this.pendingFlushArbUnsubs.size > 0) {
|
|
1409
|
+
this.send({
|
|
1410
|
+
action: "unsubscribe",
|
|
1411
|
+
channel: "arb",
|
|
1412
|
+
marketIds: Array.from(this.pendingFlushArbUnsubs)
|
|
1413
|
+
});
|
|
1414
|
+
this.pendingFlushArbUnsubs.clear();
|
|
1415
|
+
}
|
|
1290
1416
|
}
|
|
1291
1417
|
sendSubscribe(outcomeIds) {
|
|
1292
1418
|
this.send({ action: "subscribe", channel: "orderbook", outcomeIds });
|
|
@@ -1311,6 +1437,9 @@ var AggWebSocket = class {
|
|
|
1311
1437
|
});
|
|
1312
1438
|
return markets;
|
|
1313
1439
|
}
|
|
1440
|
+
activeArbMarkets() {
|
|
1441
|
+
return Array.from(this.arbSubs.keys());
|
|
1442
|
+
}
|
|
1314
1443
|
emitDiagnostic(event) {
|
|
1315
1444
|
var _a, _b;
|
|
1316
1445
|
(_b = (_a = this.callbacks).onDiagnostics) == null ? void 0 : _b.call(_a, event);
|
|
@@ -1992,6 +2121,7 @@ Issued At: ${issuedAt}`;
|
|
|
1992
2121
|
if (params.orderId) query.orderId = params.orderId;
|
|
1993
2122
|
if (params.quoteId) query.quoteId = params.quoteId;
|
|
1994
2123
|
if (params.status) query.status = params.status;
|
|
2124
|
+
if (params.mode) query.mode = params.mode;
|
|
1995
2125
|
if (params.cursor) query.cursor = params.cursor;
|
|
1996
2126
|
if (params.limit != null) query.limit = String(params.limit);
|
|
1997
2127
|
return this.request("/execution/orders", {
|
|
@@ -2018,6 +2148,7 @@ Issued At: ${issuedAt}`;
|
|
|
2018
2148
|
if (params.cursor) query.cursor = params.cursor;
|
|
2019
2149
|
if (params.limit != null) query.limit = String(params.limit);
|
|
2020
2150
|
if (params.status) query.status = params.status;
|
|
2151
|
+
if (params.mode) query.mode = params.mode;
|
|
2021
2152
|
return this.request("/execution/positions", {
|
|
2022
2153
|
query: Object.keys(query).length ? query : void 0
|
|
2023
2154
|
});
|
|
@@ -2025,8 +2156,12 @@ Issued At: ${issuedAt}`;
|
|
|
2025
2156
|
}
|
|
2026
2157
|
/** Get managed wallet balances, including per-chain cash balances and per-venue position balances. */
|
|
2027
2158
|
getManagedBalances() {
|
|
2028
|
-
return __async(this,
|
|
2029
|
-
|
|
2159
|
+
return __async(this, arguments, function* (params = {}) {
|
|
2160
|
+
const query = {};
|
|
2161
|
+
if (params.mode) query.mode = params.mode;
|
|
2162
|
+
return this.request("/execution/balances", {
|
|
2163
|
+
query: Object.keys(query).length ? query : void 0
|
|
2164
|
+
});
|
|
2030
2165
|
});
|
|
2031
2166
|
}
|
|
2032
2167
|
/** Cancel a pending managed execution by order id. */
|
|
@@ -2057,6 +2192,7 @@ Issued At: ${issuedAt}`;
|
|
|
2057
2192
|
if ((options == null ? void 0 : options.status) && options.status.length > 0) query.status = options.status;
|
|
2058
2193
|
if (options == null ? void 0 : options.sortBy) query.sortBy = options.sortBy;
|
|
2059
2194
|
if (options == null ? void 0 : options.sortDir) query.sortDir = options.sortDir;
|
|
2195
|
+
if (options == null ? void 0 : options.recurrence) query.recurrence = options.recurrence;
|
|
2060
2196
|
if ((options == null ? void 0 : options.limit) != null) query.limit = String(options.limit);
|
|
2061
2197
|
if (options == null ? void 0 : options.cursor) query.cursor = options.cursor;
|
|
2062
2198
|
if ((options == null ? void 0 : options.minYesPrice) != null) query.minYesPrice = String(options.minYesPrice);
|
|
@@ -2102,6 +2238,7 @@ Issued At: ${issuedAt}`;
|
|
|
2102
2238
|
const query = {};
|
|
2103
2239
|
if ((options == null ? void 0 : options.limit) != null) query.limit = String(options.limit);
|
|
2104
2240
|
if (options == null ? void 0 : options.cursor) query.cursor = options.cursor;
|
|
2241
|
+
if (options == null ? void 0 : options.parentId) query.parentId = options.parentId;
|
|
2105
2242
|
return this.request("/categories", {
|
|
2106
2243
|
query: Object.keys(query).length > 0 ? query : void 0
|
|
2107
2244
|
});
|
|
@@ -2259,7 +2396,7 @@ Issued At: ${issuedAt}`;
|
|
|
2259
2396
|
*/
|
|
2260
2397
|
getSmartRoute(params, options) {
|
|
2261
2398
|
return __async(this, null, function* () {
|
|
2262
|
-
var _a, _b;
|
|
2399
|
+
var _a, _b, _c;
|
|
2263
2400
|
const venueMarketOutcomeId = (_b = (_a = params.venueMarketOutcomeId) != null ? _a : params.venueMarketId) != null ? _b : params.outcomeId;
|
|
2264
2401
|
if (!venueMarketOutcomeId) {
|
|
2265
2402
|
throw new Error("getSmartRoute requires venueMarketOutcomeId");
|
|
@@ -2270,7 +2407,9 @@ Issued At: ${issuedAt}`;
|
|
|
2270
2407
|
if (params.chainBalances) query.chainBalances = JSON.stringify(params.chainBalances);
|
|
2271
2408
|
if (params.slipCapBps != null) query.slipCapBps = String(params.slipCapBps);
|
|
2272
2409
|
if (params.compareVenues) query.compareVenues = "true";
|
|
2410
|
+
if ((_c = params.allowedVenues) == null ? void 0 : _c.length) query.allowedVenues = params.allowedVenues.map(String);
|
|
2273
2411
|
if (params.tradeSide) query.side = params.tradeSide;
|
|
2412
|
+
if (params.mode) query.mode = params.mode;
|
|
2274
2413
|
if (params.deepEstimate) query.deepEstimate = "true";
|
|
2275
2414
|
const response = yield this.request(
|
|
2276
2415
|
`/orderbook/${encodeURIComponent(venueMarketOutcomeId)}/route`,
|
|
@@ -2372,6 +2511,7 @@ Issued At: ${issuedAt}`;
|
|
|
2372
2511
|
if (params == null ? void 0 : params.cursor) query.cursor = params.cursor;
|
|
2373
2512
|
if ((params == null ? void 0 : params.limit) != null) query.limit = String(params.limit);
|
|
2374
2513
|
if (params == null ? void 0 : params.status) query.status = params.status;
|
|
2514
|
+
if (params == null ? void 0 : params.mode) query.mode = params.mode;
|
|
2375
2515
|
return this.request("/execution/positions", {
|
|
2376
2516
|
query: Object.keys(query).length > 0 ? query : void 0
|
|
2377
2517
|
});
|
package/dist/server.d.mts
CHANGED
|
@@ -12,6 +12,16 @@ interface VerifyWebhookOptions {
|
|
|
12
12
|
}
|
|
13
13
|
declare function verifyWebhook(payload: string, headers: Record<string, string | string[] | undefined>, secret: string, options?: VerifyWebhookOptions): void;
|
|
14
14
|
declare function parseWebhookEvent(payload: string, headers: Record<string, string | string[] | undefined>, secret: string, options?: VerifyWebhookOptions): WebhookEvent;
|
|
15
|
+
/**
|
|
16
|
+
* Async, edge-runtime-friendly variant of {@link verifyWebhook}. Same
|
|
17
|
+
* Svix v1 signing scheme. Use this in Cloudflare Workers / Vercel Edge /
|
|
18
|
+
* Deno / Bun. The sync variant remains available for Node.js consumers.
|
|
19
|
+
*/
|
|
20
|
+
declare function verifyWebhookAsync(payload: string, headers: Record<string, string | string[] | undefined>, secret: string, options?: VerifyWebhookOptions): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Async, edge-runtime-friendly variant of {@link parseWebhookEvent}.
|
|
23
|
+
*/
|
|
24
|
+
declare function parseWebhookEventAsync(payload: string, headers: Record<string, string | string[] | undefined>, secret: string, options?: VerifyWebhookOptions): Promise<WebhookEvent>;
|
|
15
25
|
interface WebhookEventBase {
|
|
16
26
|
id: string;
|
|
17
27
|
createdAt: string;
|
|
@@ -21,6 +31,8 @@ interface AccountsCreatedEvent extends WebhookEventBase {
|
|
|
21
31
|
data: {
|
|
22
32
|
userId: string;
|
|
23
33
|
appId: string;
|
|
34
|
+
createdAt: string;
|
|
35
|
+
email: string | null;
|
|
24
36
|
};
|
|
25
37
|
}
|
|
26
38
|
interface AccountsLinkedEvent extends WebhookEventBase {
|
|
@@ -37,6 +49,7 @@ interface WalletsReadyEvent extends WebhookEventBase {
|
|
|
37
49
|
userId: string;
|
|
38
50
|
evmAddress: string;
|
|
39
51
|
svmAddress: string;
|
|
52
|
+
createdAt: string;
|
|
40
53
|
};
|
|
41
54
|
}
|
|
42
55
|
interface TradesPlacedEvent extends WebhookEventBase {
|
|
@@ -45,8 +58,16 @@ interface TradesPlacedEvent extends WebhookEventBase {
|
|
|
45
58
|
orderId: string;
|
|
46
59
|
userId: string;
|
|
47
60
|
side: string;
|
|
48
|
-
|
|
49
|
-
|
|
61
|
+
timestamp: string;
|
|
62
|
+
/**
|
|
63
|
+
* @deprecated Never emitted by the server in 1.x — the SDK type lied
|
|
64
|
+
* here for several releases. Reads always return `undefined`. The field
|
|
65
|
+
* is retained as `undefined`-typed for one minor release so existing
|
|
66
|
+
* partner code that destructures it keeps compiling; remove in 2.0.
|
|
67
|
+
*/
|
|
68
|
+
venue?: undefined;
|
|
69
|
+
/** @deprecated See `venue`. */
|
|
70
|
+
venueMarketId?: undefined;
|
|
50
71
|
};
|
|
51
72
|
}
|
|
52
73
|
interface TradesFilledEvent extends WebhookEventBase {
|
|
@@ -55,16 +76,49 @@ interface TradesFilledEvent extends WebhookEventBase {
|
|
|
55
76
|
orderId: string;
|
|
56
77
|
userId: string;
|
|
57
78
|
status: string;
|
|
58
|
-
|
|
59
|
-
|
|
79
|
+
timestamp: string;
|
|
80
|
+
/**
|
|
81
|
+
* Post-execution accuracy data. All `*Raw` values are decimal strings in
|
|
82
|
+
* 6-decimal atomic units. `*PriceRaw` are decimal strings (e.g. "0.5").
|
|
83
|
+
* `partialFillReason` is set only on `status === "partial_fill"`.
|
|
84
|
+
*/
|
|
85
|
+
filledAmountRaw?: string;
|
|
86
|
+
quotedSharesRaw?: string;
|
|
87
|
+
actualSharesRaw?: string;
|
|
88
|
+
quotedToWinRaw?: string;
|
|
89
|
+
actualToWinRaw?: string;
|
|
90
|
+
quotedPriceRaw?: string;
|
|
91
|
+
executionPriceRaw?: string;
|
|
92
|
+
partialFillReason?: string;
|
|
93
|
+
/** @deprecated See `executionPriceRaw` — never emitted; remove in 2.0. */
|
|
94
|
+
fillPrice?: undefined;
|
|
95
|
+
/** @deprecated See `actualSharesRaw` / `filledAmountRaw` — never emitted; remove in 2.0. */
|
|
96
|
+
fillSize?: undefined;
|
|
60
97
|
};
|
|
61
98
|
}
|
|
62
99
|
interface MarketsResolvedEvent extends WebhookEventBase {
|
|
63
100
|
type: "markets.resolved";
|
|
64
101
|
data: {
|
|
65
102
|
venueMarketId: string;
|
|
66
|
-
|
|
103
|
+
externalIdentifier: string;
|
|
104
|
+
status: string;
|
|
105
|
+
outcomes: Array<{
|
|
106
|
+
label: string;
|
|
107
|
+
winner?: boolean;
|
|
108
|
+
externalIdentifier?: string;
|
|
109
|
+
}>;
|
|
67
110
|
affectedUsersCount: number;
|
|
111
|
+
/**
|
|
112
|
+
* Path on the AGG API where this resolution's affected users can be
|
|
113
|
+
* paginated. Combine with the configured base URL — e.g.
|
|
114
|
+
* `https://api.agg.market${detailsPath}`.
|
|
115
|
+
*/
|
|
116
|
+
detailsPath: string;
|
|
117
|
+
/**
|
|
118
|
+
* @deprecated Singular `outcome` was never emitted; use `outcomes` array.
|
|
119
|
+
* Remove in 2.0.
|
|
120
|
+
*/
|
|
121
|
+
outcome?: undefined;
|
|
68
122
|
};
|
|
69
123
|
}
|
|
70
124
|
interface UnknownWebhookEvent extends WebhookEventBase {
|
|
@@ -118,7 +172,9 @@ declare class AggAdminClient {
|
|
|
118
172
|
ordersByStatus: Record<string, number>;
|
|
119
173
|
ordersByVenue: Record<string, number>;
|
|
120
174
|
usersLast30Days: number;
|
|
175
|
+
usersLast7Days: number;
|
|
121
176
|
ordersLast30Days: number;
|
|
177
|
+
ordersLast7Days: number;
|
|
122
178
|
}>;
|
|
123
179
|
listOrders(appId: string, query?: {
|
|
124
180
|
limit?: number;
|
|
@@ -152,4 +208,4 @@ declare class AggAdminClient {
|
|
|
152
208
|
}>;
|
|
153
209
|
}
|
|
154
210
|
|
|
155
|
-
export { type AccountsCreatedEvent, type AccountsLinkedEvent, AggAdminClient, type AggAdminClientOptions, type ExternalIdAssertion, type KnownWebhookEvent, type MarketsResolvedEvent, type TradesFilledEvent, type TradesPlacedEvent, type UnknownWebhookEvent, type VerifyWebhookOptions, type WalletsReadyEvent, type WebhookEvent, WebhookVerificationError, parseWebhookEvent, signExternalId, verifyWebhook };
|
|
211
|
+
export { type AccountsCreatedEvent, type AccountsLinkedEvent, AggAdminClient, type AggAdminClientOptions, type ExternalIdAssertion, type KnownWebhookEvent, type MarketsResolvedEvent, type TradesFilledEvent, type TradesPlacedEvent, type UnknownWebhookEvent, type VerifyWebhookOptions, type WalletsReadyEvent, type WebhookEvent, WebhookVerificationError, parseWebhookEvent, parseWebhookEventAsync, signExternalId, verifyWebhook, verifyWebhookAsync };
|
package/dist/server.d.ts
CHANGED
|
@@ -12,6 +12,16 @@ interface VerifyWebhookOptions {
|
|
|
12
12
|
}
|
|
13
13
|
declare function verifyWebhook(payload: string, headers: Record<string, string | string[] | undefined>, secret: string, options?: VerifyWebhookOptions): void;
|
|
14
14
|
declare function parseWebhookEvent(payload: string, headers: Record<string, string | string[] | undefined>, secret: string, options?: VerifyWebhookOptions): WebhookEvent;
|
|
15
|
+
/**
|
|
16
|
+
* Async, edge-runtime-friendly variant of {@link verifyWebhook}. Same
|
|
17
|
+
* Svix v1 signing scheme. Use this in Cloudflare Workers / Vercel Edge /
|
|
18
|
+
* Deno / Bun. The sync variant remains available for Node.js consumers.
|
|
19
|
+
*/
|
|
20
|
+
declare function verifyWebhookAsync(payload: string, headers: Record<string, string | string[] | undefined>, secret: string, options?: VerifyWebhookOptions): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Async, edge-runtime-friendly variant of {@link parseWebhookEvent}.
|
|
23
|
+
*/
|
|
24
|
+
declare function parseWebhookEventAsync(payload: string, headers: Record<string, string | string[] | undefined>, secret: string, options?: VerifyWebhookOptions): Promise<WebhookEvent>;
|
|
15
25
|
interface WebhookEventBase {
|
|
16
26
|
id: string;
|
|
17
27
|
createdAt: string;
|
|
@@ -21,6 +31,8 @@ interface AccountsCreatedEvent extends WebhookEventBase {
|
|
|
21
31
|
data: {
|
|
22
32
|
userId: string;
|
|
23
33
|
appId: string;
|
|
34
|
+
createdAt: string;
|
|
35
|
+
email: string | null;
|
|
24
36
|
};
|
|
25
37
|
}
|
|
26
38
|
interface AccountsLinkedEvent extends WebhookEventBase {
|
|
@@ -37,6 +49,7 @@ interface WalletsReadyEvent extends WebhookEventBase {
|
|
|
37
49
|
userId: string;
|
|
38
50
|
evmAddress: string;
|
|
39
51
|
svmAddress: string;
|
|
52
|
+
createdAt: string;
|
|
40
53
|
};
|
|
41
54
|
}
|
|
42
55
|
interface TradesPlacedEvent extends WebhookEventBase {
|
|
@@ -45,8 +58,16 @@ interface TradesPlacedEvent extends WebhookEventBase {
|
|
|
45
58
|
orderId: string;
|
|
46
59
|
userId: string;
|
|
47
60
|
side: string;
|
|
48
|
-
|
|
49
|
-
|
|
61
|
+
timestamp: string;
|
|
62
|
+
/**
|
|
63
|
+
* @deprecated Never emitted by the server in 1.x — the SDK type lied
|
|
64
|
+
* here for several releases. Reads always return `undefined`. The field
|
|
65
|
+
* is retained as `undefined`-typed for one minor release so existing
|
|
66
|
+
* partner code that destructures it keeps compiling; remove in 2.0.
|
|
67
|
+
*/
|
|
68
|
+
venue?: undefined;
|
|
69
|
+
/** @deprecated See `venue`. */
|
|
70
|
+
venueMarketId?: undefined;
|
|
50
71
|
};
|
|
51
72
|
}
|
|
52
73
|
interface TradesFilledEvent extends WebhookEventBase {
|
|
@@ -55,16 +76,49 @@ interface TradesFilledEvent extends WebhookEventBase {
|
|
|
55
76
|
orderId: string;
|
|
56
77
|
userId: string;
|
|
57
78
|
status: string;
|
|
58
|
-
|
|
59
|
-
|
|
79
|
+
timestamp: string;
|
|
80
|
+
/**
|
|
81
|
+
* Post-execution accuracy data. All `*Raw` values are decimal strings in
|
|
82
|
+
* 6-decimal atomic units. `*PriceRaw` are decimal strings (e.g. "0.5").
|
|
83
|
+
* `partialFillReason` is set only on `status === "partial_fill"`.
|
|
84
|
+
*/
|
|
85
|
+
filledAmountRaw?: string;
|
|
86
|
+
quotedSharesRaw?: string;
|
|
87
|
+
actualSharesRaw?: string;
|
|
88
|
+
quotedToWinRaw?: string;
|
|
89
|
+
actualToWinRaw?: string;
|
|
90
|
+
quotedPriceRaw?: string;
|
|
91
|
+
executionPriceRaw?: string;
|
|
92
|
+
partialFillReason?: string;
|
|
93
|
+
/** @deprecated See `executionPriceRaw` — never emitted; remove in 2.0. */
|
|
94
|
+
fillPrice?: undefined;
|
|
95
|
+
/** @deprecated See `actualSharesRaw` / `filledAmountRaw` — never emitted; remove in 2.0. */
|
|
96
|
+
fillSize?: undefined;
|
|
60
97
|
};
|
|
61
98
|
}
|
|
62
99
|
interface MarketsResolvedEvent extends WebhookEventBase {
|
|
63
100
|
type: "markets.resolved";
|
|
64
101
|
data: {
|
|
65
102
|
venueMarketId: string;
|
|
66
|
-
|
|
103
|
+
externalIdentifier: string;
|
|
104
|
+
status: string;
|
|
105
|
+
outcomes: Array<{
|
|
106
|
+
label: string;
|
|
107
|
+
winner?: boolean;
|
|
108
|
+
externalIdentifier?: string;
|
|
109
|
+
}>;
|
|
67
110
|
affectedUsersCount: number;
|
|
111
|
+
/**
|
|
112
|
+
* Path on the AGG API where this resolution's affected users can be
|
|
113
|
+
* paginated. Combine with the configured base URL — e.g.
|
|
114
|
+
* `https://api.agg.market${detailsPath}`.
|
|
115
|
+
*/
|
|
116
|
+
detailsPath: string;
|
|
117
|
+
/**
|
|
118
|
+
* @deprecated Singular `outcome` was never emitted; use `outcomes` array.
|
|
119
|
+
* Remove in 2.0.
|
|
120
|
+
*/
|
|
121
|
+
outcome?: undefined;
|
|
68
122
|
};
|
|
69
123
|
}
|
|
70
124
|
interface UnknownWebhookEvent extends WebhookEventBase {
|
|
@@ -118,7 +172,9 @@ declare class AggAdminClient {
|
|
|
118
172
|
ordersByStatus: Record<string, number>;
|
|
119
173
|
ordersByVenue: Record<string, number>;
|
|
120
174
|
usersLast30Days: number;
|
|
175
|
+
usersLast7Days: number;
|
|
121
176
|
ordersLast30Days: number;
|
|
177
|
+
ordersLast7Days: number;
|
|
122
178
|
}>;
|
|
123
179
|
listOrders(appId: string, query?: {
|
|
124
180
|
limit?: number;
|
|
@@ -152,4 +208,4 @@ declare class AggAdminClient {
|
|
|
152
208
|
}>;
|
|
153
209
|
}
|
|
154
210
|
|
|
155
|
-
export { type AccountsCreatedEvent, type AccountsLinkedEvent, AggAdminClient, type AggAdminClientOptions, type ExternalIdAssertion, type KnownWebhookEvent, type MarketsResolvedEvent, type TradesFilledEvent, type TradesPlacedEvent, type UnknownWebhookEvent, type VerifyWebhookOptions, type WalletsReadyEvent, type WebhookEvent, WebhookVerificationError, parseWebhookEvent, signExternalId, verifyWebhook };
|
|
211
|
+
export { type AccountsCreatedEvent, type AccountsLinkedEvent, AggAdminClient, type AggAdminClientOptions, type ExternalIdAssertion, type KnownWebhookEvent, type MarketsResolvedEvent, type TradesFilledEvent, type TradesPlacedEvent, type UnknownWebhookEvent, type VerifyWebhookOptions, type WalletsReadyEvent, type WebhookEvent, WebhookVerificationError, parseWebhookEvent, parseWebhookEventAsync, signExternalId, verifyWebhook, verifyWebhookAsync };
|
package/dist/server.js
CHANGED
|
@@ -60,8 +60,10 @@ __export(server_exports, {
|
|
|
60
60
|
AggAdminClient: () => AggAdminClient,
|
|
61
61
|
WebhookVerificationError: () => WebhookVerificationError,
|
|
62
62
|
parseWebhookEvent: () => parseWebhookEvent,
|
|
63
|
+
parseWebhookEventAsync: () => parseWebhookEventAsync,
|
|
63
64
|
signExternalId: () => signExternalId,
|
|
64
|
-
verifyWebhook: () => verifyWebhook
|
|
65
|
+
verifyWebhook: () => verifyWebhook,
|
|
66
|
+
verifyWebhookAsync: () => verifyWebhookAsync
|
|
65
67
|
});
|
|
66
68
|
module.exports = __toCommonJS(server_exports);
|
|
67
69
|
var import_node_crypto = require("crypto");
|
|
@@ -74,6 +76,22 @@ function signExternalId(appSecret, externalId) {
|
|
|
74
76
|
hmac
|
|
75
77
|
};
|
|
76
78
|
}
|
|
79
|
+
var textEncoder = new TextEncoder();
|
|
80
|
+
function base64Decode(s) {
|
|
81
|
+
const bin = atob(s);
|
|
82
|
+
const out = new Uint8Array(bin.length);
|
|
83
|
+
for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
|
|
84
|
+
return out;
|
|
85
|
+
}
|
|
86
|
+
function importHmacKey(secret) {
|
|
87
|
+
return __async(this, null, function* () {
|
|
88
|
+
const keyBytes = base64Decode(secret.replace(/^whsec_/, ""));
|
|
89
|
+
return crypto.subtle.importKey("raw", keyBytes, { name: "HMAC", hash: "SHA-256" }, false, [
|
|
90
|
+
"sign",
|
|
91
|
+
"verify"
|
|
92
|
+
]);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
77
95
|
var WebhookVerificationError = class extends Error {
|
|
78
96
|
constructor(message) {
|
|
79
97
|
super(message);
|
|
@@ -113,6 +131,45 @@ function parseWebhookEvent(payload, headers, secret, options) {
|
|
|
113
131
|
const parsed = JSON.parse(payload);
|
|
114
132
|
return parsed;
|
|
115
133
|
}
|
|
134
|
+
function verifyWebhookAsync(payload, headers, secret, options) {
|
|
135
|
+
return __async(this, null, function* () {
|
|
136
|
+
var _a;
|
|
137
|
+
const tolerance = (_a = options == null ? void 0 : options.toleranceSeconds) != null ? _a : 300;
|
|
138
|
+
const msgId = getHeader(headers, "webhook-id");
|
|
139
|
+
const timestamp = getHeader(headers, "webhook-timestamp");
|
|
140
|
+
const signatures = getHeader(headers, "webhook-signature");
|
|
141
|
+
if (!msgId) throw new WebhookVerificationError("Missing Webhook-Id header");
|
|
142
|
+
if (!timestamp) throw new WebhookVerificationError("Missing Webhook-Timestamp header");
|
|
143
|
+
if (!signatures) throw new WebhookVerificationError("Missing Webhook-Signature header");
|
|
144
|
+
const ts = parseInt(timestamp, 10);
|
|
145
|
+
if (isNaN(ts)) throw new WebhookVerificationError("Invalid Webhook-Timestamp");
|
|
146
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
147
|
+
if (Math.abs(now - ts) > tolerance) {
|
|
148
|
+
throw new WebhookVerificationError("Webhook timestamp outside tolerance window");
|
|
149
|
+
}
|
|
150
|
+
const key = yield importHmacKey(secret);
|
|
151
|
+
const signed = textEncoder.encode(`${msgId}.${timestamp}.${payload}`);
|
|
152
|
+
for (const sig of signatures.split(" ")) {
|
|
153
|
+
if (!sig.startsWith("v1,")) continue;
|
|
154
|
+
let sigBytes;
|
|
155
|
+
try {
|
|
156
|
+
sigBytes = base64Decode(sig.slice(3));
|
|
157
|
+
} catch (e) {
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
const ok = yield crypto.subtle.verify("HMAC", key, sigBytes, signed);
|
|
161
|
+
if (ok) return;
|
|
162
|
+
}
|
|
163
|
+
throw new WebhookVerificationError("Invalid webhook signature");
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
function parseWebhookEventAsync(payload, headers, secret, options) {
|
|
167
|
+
return __async(this, null, function* () {
|
|
168
|
+
yield verifyWebhookAsync(payload, headers, secret, options);
|
|
169
|
+
const parsed = JSON.parse(payload);
|
|
170
|
+
return parsed;
|
|
171
|
+
});
|
|
172
|
+
}
|
|
116
173
|
var AggAdminClient = class {
|
|
117
174
|
constructor(options) {
|
|
118
175
|
this.baseUrl = options.baseUrl.replace(/\/$/, "");
|
|
@@ -249,6 +306,8 @@ function getHeader(headers, name) {
|
|
|
249
306
|
AggAdminClient,
|
|
250
307
|
WebhookVerificationError,
|
|
251
308
|
parseWebhookEvent,
|
|
309
|
+
parseWebhookEventAsync,
|
|
252
310
|
signExternalId,
|
|
253
|
-
verifyWebhook
|
|
311
|
+
verifyWebhook,
|
|
312
|
+
verifyWebhookAsync
|
|
254
313
|
});
|
package/dist/server.mjs
CHANGED
|
@@ -15,6 +15,22 @@ function signExternalId(appSecret, externalId) {
|
|
|
15
15
|
hmac
|
|
16
16
|
};
|
|
17
17
|
}
|
|
18
|
+
var textEncoder = new TextEncoder();
|
|
19
|
+
function base64Decode(s) {
|
|
20
|
+
const bin = atob(s);
|
|
21
|
+
const out = new Uint8Array(bin.length);
|
|
22
|
+
for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
|
|
23
|
+
return out;
|
|
24
|
+
}
|
|
25
|
+
function importHmacKey(secret) {
|
|
26
|
+
return __async(this, null, function* () {
|
|
27
|
+
const keyBytes = base64Decode(secret.replace(/^whsec_/, ""));
|
|
28
|
+
return crypto.subtle.importKey("raw", keyBytes, { name: "HMAC", hash: "SHA-256" }, false, [
|
|
29
|
+
"sign",
|
|
30
|
+
"verify"
|
|
31
|
+
]);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
18
34
|
var WebhookVerificationError = class extends Error {
|
|
19
35
|
constructor(message) {
|
|
20
36
|
super(message);
|
|
@@ -54,6 +70,45 @@ function parseWebhookEvent(payload, headers, secret, options) {
|
|
|
54
70
|
const parsed = JSON.parse(payload);
|
|
55
71
|
return parsed;
|
|
56
72
|
}
|
|
73
|
+
function verifyWebhookAsync(payload, headers, secret, options) {
|
|
74
|
+
return __async(this, null, function* () {
|
|
75
|
+
var _a;
|
|
76
|
+
const tolerance = (_a = options == null ? void 0 : options.toleranceSeconds) != null ? _a : 300;
|
|
77
|
+
const msgId = getHeader(headers, "webhook-id");
|
|
78
|
+
const timestamp = getHeader(headers, "webhook-timestamp");
|
|
79
|
+
const signatures = getHeader(headers, "webhook-signature");
|
|
80
|
+
if (!msgId) throw new WebhookVerificationError("Missing Webhook-Id header");
|
|
81
|
+
if (!timestamp) throw new WebhookVerificationError("Missing Webhook-Timestamp header");
|
|
82
|
+
if (!signatures) throw new WebhookVerificationError("Missing Webhook-Signature header");
|
|
83
|
+
const ts = parseInt(timestamp, 10);
|
|
84
|
+
if (isNaN(ts)) throw new WebhookVerificationError("Invalid Webhook-Timestamp");
|
|
85
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
86
|
+
if (Math.abs(now - ts) > tolerance) {
|
|
87
|
+
throw new WebhookVerificationError("Webhook timestamp outside tolerance window");
|
|
88
|
+
}
|
|
89
|
+
const key = yield importHmacKey(secret);
|
|
90
|
+
const signed = textEncoder.encode(`${msgId}.${timestamp}.${payload}`);
|
|
91
|
+
for (const sig of signatures.split(" ")) {
|
|
92
|
+
if (!sig.startsWith("v1,")) continue;
|
|
93
|
+
let sigBytes;
|
|
94
|
+
try {
|
|
95
|
+
sigBytes = base64Decode(sig.slice(3));
|
|
96
|
+
} catch (e) {
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
const ok = yield crypto.subtle.verify("HMAC", key, sigBytes, signed);
|
|
100
|
+
if (ok) return;
|
|
101
|
+
}
|
|
102
|
+
throw new WebhookVerificationError("Invalid webhook signature");
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
function parseWebhookEventAsync(payload, headers, secret, options) {
|
|
106
|
+
return __async(this, null, function* () {
|
|
107
|
+
yield verifyWebhookAsync(payload, headers, secret, options);
|
|
108
|
+
const parsed = JSON.parse(payload);
|
|
109
|
+
return parsed;
|
|
110
|
+
});
|
|
111
|
+
}
|
|
57
112
|
var AggAdminClient = class {
|
|
58
113
|
constructor(options) {
|
|
59
114
|
this.baseUrl = options.baseUrl.replace(/\/$/, "");
|
|
@@ -189,6 +244,8 @@ export {
|
|
|
189
244
|
AggAdminClient,
|
|
190
245
|
WebhookVerificationError,
|
|
191
246
|
parseWebhookEvent,
|
|
247
|
+
parseWebhookEventAsync,
|
|
192
248
|
signExternalId,
|
|
193
|
-
verifyWebhook
|
|
249
|
+
verifyWebhook,
|
|
250
|
+
verifyWebhookAsync
|
|
194
251
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agg-build/sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Vanilla TypeScript client for the AGG prediction market aggregator (auth, markets, orderbooks, charts, trading, managed execution, WebSockets). Works in browsers, Node.js, and React Native.",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"license": "MIT",
|