@agg-build/hooks 1.0.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 +403 -0
- package/dist/chunk-CDPQERUC.mjs +3601 -0
- package/dist/deposit.d.mts +184 -0
- package/dist/deposit.d.ts +184 -0
- package/dist/deposit.js +1563 -0
- package/dist/deposit.mjs +628 -0
- package/dist/index.d.mts +4640 -0
- package/dist/index.d.ts +4640 -0
- package/dist/index.js +5568 -0
- package/dist/index.mjs +2010 -0
- package/dist/use-sync-balances-D1Jdkck9.d.mts +246 -0
- package/dist/use-sync-balances-D1Jdkck9.d.ts +246 -0
- package/package.json +102 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,2010 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AggAuthContext,
|
|
3
|
+
AggBalanceProvider,
|
|
4
|
+
AggClientContext,
|
|
5
|
+
AggProvider,
|
|
6
|
+
AggUiProvider,
|
|
7
|
+
CHART_TIME_RANGES,
|
|
8
|
+
CONFIRMED_MATCH_STATUSES,
|
|
9
|
+
DEFAULT_AGG_ROOT_CLASS_NAME,
|
|
10
|
+
EventListStateProvider,
|
|
11
|
+
MarketStatus,
|
|
12
|
+
MatchStatus,
|
|
13
|
+
MatchType,
|
|
14
|
+
Venue,
|
|
15
|
+
__async,
|
|
16
|
+
__objRest,
|
|
17
|
+
__spreadProps,
|
|
18
|
+
__spreadValues,
|
|
19
|
+
applyOrderbookDepth,
|
|
20
|
+
computeClosedPositionTotals,
|
|
21
|
+
createMarketChartData,
|
|
22
|
+
createMarketLiveState,
|
|
23
|
+
createMarketOrderbookDataFromState,
|
|
24
|
+
createMarketOrderbookDataFromVenueOrderbooks,
|
|
25
|
+
defaultAggUiConfig,
|
|
26
|
+
executionKeys,
|
|
27
|
+
getBuilder,
|
|
28
|
+
getDepositAddress,
|
|
29
|
+
getOrCreateBuilder,
|
|
30
|
+
getWalletAddressFromUserProfile,
|
|
31
|
+
invalidateBalanceQueries,
|
|
32
|
+
invalidatePositionQueries,
|
|
33
|
+
marketDataKeys,
|
|
34
|
+
marketOrderbookDataToResponse,
|
|
35
|
+
mergeMarketChartData,
|
|
36
|
+
optimizedImageUrl,
|
|
37
|
+
parseEmail,
|
|
38
|
+
parseEmailStrict,
|
|
39
|
+
resolveAggUiLabels,
|
|
40
|
+
resolveDefaultMarket,
|
|
41
|
+
resolveEventTradingState,
|
|
42
|
+
resolveMarketTradingState,
|
|
43
|
+
resolveMarketWinningOutcome,
|
|
44
|
+
resolveOrderEligibility,
|
|
45
|
+
resolveTradingStateKind,
|
|
46
|
+
sortVenues,
|
|
47
|
+
tradingReducer,
|
|
48
|
+
useAggAuthContext,
|
|
49
|
+
useAggAuthState,
|
|
50
|
+
useAggBalance,
|
|
51
|
+
useAggBalanceContext,
|
|
52
|
+
useAggBalanceState,
|
|
53
|
+
useAggClient,
|
|
54
|
+
useAggLabels,
|
|
55
|
+
useAggUiConfig,
|
|
56
|
+
useAggWebSocket,
|
|
57
|
+
useAggWebSocketConnectionState,
|
|
58
|
+
useDepositAddresses,
|
|
59
|
+
useEventListState,
|
|
60
|
+
useEventTradingContext,
|
|
61
|
+
useExecuteManaged,
|
|
62
|
+
useExecutionProgress,
|
|
63
|
+
useLabels,
|
|
64
|
+
useManagedBalances,
|
|
65
|
+
useOnBalanceUpdate,
|
|
66
|
+
useOnOrderSubmitted,
|
|
67
|
+
useOnRedeemEvent,
|
|
68
|
+
usePositions,
|
|
69
|
+
useQuoteManaged,
|
|
70
|
+
useRampQuotes,
|
|
71
|
+
useRampSession,
|
|
72
|
+
useRedeem,
|
|
73
|
+
useRedeemEligibleCount,
|
|
74
|
+
useSdkLabels,
|
|
75
|
+
useSdkUiConfig,
|
|
76
|
+
useSyncBalances,
|
|
77
|
+
useWithdrawManaged
|
|
78
|
+
} from "./chunk-CDPQERUC.mjs";
|
|
79
|
+
|
|
80
|
+
// src/index.ts
|
|
81
|
+
import { QueryClient as QueryClient4, QueryClientProvider, useQueryClient as useQueryClient2 } from "@tanstack/react-query";
|
|
82
|
+
import { TurnstileChallengeError } from "@agg-build/sdk";
|
|
83
|
+
|
|
84
|
+
// src/use-geo-block.ts
|
|
85
|
+
import { useContext } from "react";
|
|
86
|
+
var DEFAULT_STATE = {
|
|
87
|
+
isLocationBlocked: false,
|
|
88
|
+
isTradingBlocked: false,
|
|
89
|
+
isDepositBlocked: false
|
|
90
|
+
};
|
|
91
|
+
function useGeoBlock() {
|
|
92
|
+
var _a, _b;
|
|
93
|
+
const authContext = useContext(AggAuthContext);
|
|
94
|
+
if (process.env.NEXT_PUBLIC_GEO_BLOCK_DISABLE === "true") return DEFAULT_STATE;
|
|
95
|
+
const isBlocked = (_b = (_a = authContext == null ? void 0 : authContext.user) == null ? void 0 : _a.isLocationBlocked) != null ? _b : false;
|
|
96
|
+
if (!isBlocked) return DEFAULT_STATE;
|
|
97
|
+
return {
|
|
98
|
+
isLocationBlocked: true,
|
|
99
|
+
isTradingBlocked: true,
|
|
100
|
+
isDepositBlocked: true
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// src/use-agg-auth.ts
|
|
105
|
+
import { useCallback } from "react";
|
|
106
|
+
function useAggAuth(options = {}) {
|
|
107
|
+
const {
|
|
108
|
+
isAuthenticated,
|
|
109
|
+
user,
|
|
110
|
+
isLoading,
|
|
111
|
+
error,
|
|
112
|
+
signIn: signInWithProvider,
|
|
113
|
+
signOut
|
|
114
|
+
} = useAggAuthContext();
|
|
115
|
+
const signIn = useCallback(
|
|
116
|
+
(statement) => __async(null, null, function* () {
|
|
117
|
+
if (!options.signMessage) {
|
|
118
|
+
throw new Error(
|
|
119
|
+
"signMessage is required to call signIn. Pass wallet options to useAggAuth()."
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
if (!options.address) {
|
|
123
|
+
throw new Error("address is required to call signIn. Pass wallet options to useAggAuth().");
|
|
124
|
+
}
|
|
125
|
+
yield signInWithProvider({
|
|
126
|
+
signMessage: options.signMessage,
|
|
127
|
+
address: options.address,
|
|
128
|
+
chainId: options.chainId,
|
|
129
|
+
chain: options.chain,
|
|
130
|
+
statement
|
|
131
|
+
});
|
|
132
|
+
}),
|
|
133
|
+
[options.address, options.chain, options.chainId, options.signMessage, signInWithProvider]
|
|
134
|
+
);
|
|
135
|
+
return { isAuthenticated, user, signIn, signOut, isLoading, error };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// src/use-link-account.ts
|
|
139
|
+
import { useCallback as useCallback2, useState } from "react";
|
|
140
|
+
function useLinkAccount() {
|
|
141
|
+
const client = useAggClient();
|
|
142
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
143
|
+
const [error, setError] = useState(null);
|
|
144
|
+
const run = (fn) => {
|
|
145
|
+
setIsLoading(true);
|
|
146
|
+
setError(null);
|
|
147
|
+
return fn().catch((e) => {
|
|
148
|
+
const err = e instanceof Error ? e : new Error(String(e));
|
|
149
|
+
setError(err);
|
|
150
|
+
throw err;
|
|
151
|
+
}).finally(() => setIsLoading(false));
|
|
152
|
+
};
|
|
153
|
+
const startLink = useCallback2(
|
|
154
|
+
(body) => run(() => client.linkAccount(body)),
|
|
155
|
+
[client]
|
|
156
|
+
);
|
|
157
|
+
const confirmLink = useCallback2(
|
|
158
|
+
(token) => run(() => client.linkAccountConfirm(token)),
|
|
159
|
+
[client]
|
|
160
|
+
);
|
|
161
|
+
return { startLink, confirmLink, isLoading, error };
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// src/auth-chooser-events.ts
|
|
165
|
+
var AUTH_CHOOSER_OPEN_EVENT = "agg-auth:open-chooser";
|
|
166
|
+
var requestAggAuthChooserOpen = () => {
|
|
167
|
+
if (typeof window === "undefined") return;
|
|
168
|
+
window.dispatchEvent(new Event(AUTH_CHOOSER_OPEN_EVENT));
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
// src/use-categories.ts
|
|
172
|
+
import { useInfiniteQuery } from "@tanstack/react-query";
|
|
173
|
+
function useCategories(options) {
|
|
174
|
+
var _a, _b, _c, _d;
|
|
175
|
+
const client = useAggClient();
|
|
176
|
+
const enabled = (_a = options == null ? void 0 : options.enabled) != null ? _a : true;
|
|
177
|
+
const limit = (_b = options == null ? void 0 : options.limit) != null ? _b : 20;
|
|
178
|
+
const query = useInfiniteQuery({
|
|
179
|
+
queryKey: ["categories", limit],
|
|
180
|
+
queryFn: (_0) => __async(null, [_0], function* ({ pageParam }) {
|
|
181
|
+
const res = yield client.getCategories({
|
|
182
|
+
limit,
|
|
183
|
+
cursor: pageParam
|
|
184
|
+
});
|
|
185
|
+
return res;
|
|
186
|
+
}),
|
|
187
|
+
initialPageParam: void 0,
|
|
188
|
+
getNextPageParam: (lastPage) => {
|
|
189
|
+
var _a2;
|
|
190
|
+
return (_a2 = lastPage.nextCursor) != null ? _a2 : void 0;
|
|
191
|
+
},
|
|
192
|
+
enabled
|
|
193
|
+
});
|
|
194
|
+
const categories = (_d = (_c = query.data) == null ? void 0 : _c.pages.flatMap((p) => p.data)) != null ? _d : [];
|
|
195
|
+
const hasNextPage = !!query.hasNextPage;
|
|
196
|
+
return __spreadProps(__spreadValues({}, query), {
|
|
197
|
+
categories,
|
|
198
|
+
hasNextPage
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// src/use-debounced-value.ts
|
|
203
|
+
import { useEffect, useState as useState2 } from "react";
|
|
204
|
+
function useDebouncedValue(value, delay) {
|
|
205
|
+
const [debouncedValue, setDebouncedValue] = useState2(value);
|
|
206
|
+
useEffect(() => {
|
|
207
|
+
const timeoutId = window.setTimeout(() => {
|
|
208
|
+
setDebouncedValue(value);
|
|
209
|
+
}, delay);
|
|
210
|
+
return () => {
|
|
211
|
+
window.clearTimeout(timeoutId);
|
|
212
|
+
};
|
|
213
|
+
}, [value, delay]);
|
|
214
|
+
return debouncedValue;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// src/use-execution-orders.ts
|
|
218
|
+
import { useInfiniteQuery as useInfiniteQuery2 } from "@tanstack/react-query";
|
|
219
|
+
function useExecutionOrders(options = {}) {
|
|
220
|
+
var _a, _b;
|
|
221
|
+
const client = useAggClient();
|
|
222
|
+
const { status, limit = 50, enabled = true, refetchIntervalMs = false } = options;
|
|
223
|
+
const query = useInfiniteQuery2({
|
|
224
|
+
queryKey: ["execution-orders", status != null ? status : "all", limit],
|
|
225
|
+
queryFn: ({ pageParam }) => client.getExecutionOrders({
|
|
226
|
+
status,
|
|
227
|
+
limit,
|
|
228
|
+
cursor: pageParam
|
|
229
|
+
}),
|
|
230
|
+
initialPageParam: void 0,
|
|
231
|
+
getNextPageParam: (lastPage) => {
|
|
232
|
+
var _a2;
|
|
233
|
+
return lastPage.hasMore ? (_a2 = lastPage.nextCursor) != null ? _a2 : void 0 : void 0;
|
|
234
|
+
},
|
|
235
|
+
enabled,
|
|
236
|
+
refetchInterval: refetchIntervalMs
|
|
237
|
+
});
|
|
238
|
+
const orders = (_b = (_a = query.data) == null ? void 0 : _a.pages.flatMap((page) => page.data)) != null ? _b : [];
|
|
239
|
+
const hasNextPage = !!query.hasNextPage;
|
|
240
|
+
return __spreadProps(__spreadValues({}, query), {
|
|
241
|
+
orders,
|
|
242
|
+
hasNextPage
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// src/use-user-activity.ts
|
|
247
|
+
import { useInfiniteQuery as useInfiniteQuery3 } from "@tanstack/react-query";
|
|
248
|
+
function useUserActivity(options = {}) {
|
|
249
|
+
var _a, _b;
|
|
250
|
+
const client = useAggClient();
|
|
251
|
+
const { type, limit = 50, enabled = true } = options;
|
|
252
|
+
const query = useInfiniteQuery3({
|
|
253
|
+
queryKey: ["user-activity", type != null ? type : "all", limit],
|
|
254
|
+
queryFn: ({ pageParam }) => client.getUserActivity({
|
|
255
|
+
type,
|
|
256
|
+
limit,
|
|
257
|
+
cursor: pageParam
|
|
258
|
+
}),
|
|
259
|
+
initialPageParam: void 0,
|
|
260
|
+
getNextPageParam: (lastPage) => {
|
|
261
|
+
var _a2;
|
|
262
|
+
return lastPage.hasMore ? (_a2 = lastPage.nextCursor) != null ? _a2 : void 0 : void 0;
|
|
263
|
+
},
|
|
264
|
+
enabled
|
|
265
|
+
});
|
|
266
|
+
const activities = (_b = (_a = query.data) == null ? void 0 : _a.pages.flatMap((page) => page.data)) != null ? _b : [];
|
|
267
|
+
const hasNextPage = !!query.hasNextPage;
|
|
268
|
+
return __spreadProps(__spreadValues({}, query), {
|
|
269
|
+
activities,
|
|
270
|
+
hasNextPage
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// src/use-external-id.ts
|
|
275
|
+
import { useCallback as useCallback3, useState as useState3 } from "react";
|
|
276
|
+
function useExternalId(options = {}) {
|
|
277
|
+
const client = useAggClient();
|
|
278
|
+
const { onSuccess, onError: onErrorCb } = options;
|
|
279
|
+
const [isLoading, setIsLoading] = useState3(false);
|
|
280
|
+
const [error, setError] = useState3(null);
|
|
281
|
+
const linkExternalId = useCallback3(
|
|
282
|
+
(assertion) => __async(null, null, function* () {
|
|
283
|
+
setIsLoading(true);
|
|
284
|
+
setError(null);
|
|
285
|
+
try {
|
|
286
|
+
const profile = yield client.linkExternalId(assertion);
|
|
287
|
+
onSuccess == null ? void 0 : onSuccess(profile);
|
|
288
|
+
return profile;
|
|
289
|
+
} catch (err) {
|
|
290
|
+
const resolvedError = err instanceof Error ? err : new Error(String(err));
|
|
291
|
+
setError(resolvedError);
|
|
292
|
+
onErrorCb == null ? void 0 : onErrorCb(resolvedError);
|
|
293
|
+
throw resolvedError;
|
|
294
|
+
} finally {
|
|
295
|
+
setIsLoading(false);
|
|
296
|
+
}
|
|
297
|
+
}),
|
|
298
|
+
[client, onErrorCb, onSuccess]
|
|
299
|
+
);
|
|
300
|
+
return { linkExternalId, isLoading, error };
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// src/use-execution-positions.ts
|
|
304
|
+
import { useInfiniteQuery as useInfiniteQuery4 } from "@tanstack/react-query";
|
|
305
|
+
function useExecutionPositions(options = {}) {
|
|
306
|
+
var _a, _b;
|
|
307
|
+
const client = useAggClient();
|
|
308
|
+
const { limit = 50, status, enabled = true } = options;
|
|
309
|
+
const query = useInfiniteQuery4({
|
|
310
|
+
queryKey: executionKeys.positions(null, limit, status != null ? status : null),
|
|
311
|
+
queryFn: ({ pageParam }) => client.getExecutionPositions({
|
|
312
|
+
limit,
|
|
313
|
+
status,
|
|
314
|
+
cursor: pageParam
|
|
315
|
+
}),
|
|
316
|
+
initialPageParam: void 0,
|
|
317
|
+
getNextPageParam: (lastPage) => {
|
|
318
|
+
var _a2;
|
|
319
|
+
return lastPage.hasMore ? (_a2 = lastPage.nextCursor) != null ? _a2 : void 0 : void 0;
|
|
320
|
+
},
|
|
321
|
+
enabled
|
|
322
|
+
});
|
|
323
|
+
const positions = (_b = (_a = query.data) == null ? void 0 : _a.pages.flatMap((page) => page.data)) != null ? _b : [];
|
|
324
|
+
const hasNextPage = !!query.hasNextPage;
|
|
325
|
+
return __spreadProps(__spreadValues({}, query), {
|
|
326
|
+
positions,
|
|
327
|
+
hasNextPage
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// src/use-live-candle-overlay.ts
|
|
332
|
+
import { useCallback as useCallback4, useMemo as useMemo4 } from "react";
|
|
333
|
+
|
|
334
|
+
// src/use-live-candles.ts
|
|
335
|
+
import { useMemo as useMemo3 } from "react";
|
|
336
|
+
import { mergeCandles, mergeClosedCandles } from "@agg-build/sdk";
|
|
337
|
+
|
|
338
|
+
// src/use-market-chart.ts
|
|
339
|
+
import { keepPreviousData, useQueries } from "@tanstack/react-query";
|
|
340
|
+
|
|
341
|
+
// src/market-data/subscription.ts
|
|
342
|
+
import { useEffect as useEffect2, useMemo } from "react";
|
|
343
|
+
function useMarketDataSubscription({
|
|
344
|
+
marketId,
|
|
345
|
+
additionalMarketIds,
|
|
346
|
+
enabled = true,
|
|
347
|
+
orderbook = true,
|
|
348
|
+
trades = false
|
|
349
|
+
}) {
|
|
350
|
+
const ws = useAggWebSocket();
|
|
351
|
+
const allIds = useMemo(() => {
|
|
352
|
+
const ids = /* @__PURE__ */ new Set();
|
|
353
|
+
if (marketId) ids.add(marketId);
|
|
354
|
+
if (additionalMarketIds) {
|
|
355
|
+
for (const id of additionalMarketIds) {
|
|
356
|
+
if (id) ids.add(id);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
return [...ids];
|
|
360
|
+
}, [marketId, additionalMarketIds]);
|
|
361
|
+
const stableKey = allIds.join("|");
|
|
362
|
+
useEffect2(() => {
|
|
363
|
+
if (!ws || !allIds.length || !enabled || !orderbook && !trades) return;
|
|
364
|
+
const unsubscribers = [];
|
|
365
|
+
for (const id of allIds) {
|
|
366
|
+
if (orderbook) {
|
|
367
|
+
const unsub = ws.subscribe(id, "orderbook");
|
|
368
|
+
unsubscribers.push(unsub);
|
|
369
|
+
}
|
|
370
|
+
if (trades) {
|
|
371
|
+
const unsub = ws.subscribe(id, "trades");
|
|
372
|
+
unsubscribers.push(unsub);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
return () => {
|
|
376
|
+
for (const unsub of unsubscribers) {
|
|
377
|
+
unsub();
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
}, [enabled, stableKey, orderbook, trades, ws]);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// src/use-market-chart.ts
|
|
384
|
+
function useMarketChart(options) {
|
|
385
|
+
var _a, _b, _c;
|
|
386
|
+
const client = useAggClient();
|
|
387
|
+
const isConnected = useAggWebSocketConnectionState();
|
|
388
|
+
const {
|
|
389
|
+
features: { enableLiveUpdates }
|
|
390
|
+
} = useAggUiConfig();
|
|
391
|
+
const {
|
|
392
|
+
marketId,
|
|
393
|
+
venueMarketIds,
|
|
394
|
+
interval = "5m",
|
|
395
|
+
startTs = null,
|
|
396
|
+
endTs = null,
|
|
397
|
+
countBack = null,
|
|
398
|
+
enabled = true,
|
|
399
|
+
live
|
|
400
|
+
} = options;
|
|
401
|
+
const liveEnabled = live != null ? live : enableLiveUpdates;
|
|
402
|
+
const outcomeIds = (() => {
|
|
403
|
+
const ids = /* @__PURE__ */ new Set();
|
|
404
|
+
if (marketId) {
|
|
405
|
+
ids.add(marketId);
|
|
406
|
+
}
|
|
407
|
+
if (venueMarketIds) {
|
|
408
|
+
for (const venueMarketId of venueMarketIds) {
|
|
409
|
+
if (venueMarketId) {
|
|
410
|
+
ids.add(venueMarketId);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
return [...ids];
|
|
415
|
+
})();
|
|
416
|
+
const primaryOutcomeId = (_a = outcomeIds[0]) != null ? _a : null;
|
|
417
|
+
const isQueryEnabled = enabled && outcomeIds.length > 0 && endTs != null && (startTs != null || countBack != null);
|
|
418
|
+
useMarketDataSubscription({
|
|
419
|
+
marketId: primaryOutcomeId,
|
|
420
|
+
additionalMarketIds: outcomeIds.slice(1),
|
|
421
|
+
enabled: Boolean(isQueryEnabled && liveEnabled),
|
|
422
|
+
orderbook: true,
|
|
423
|
+
trades: true
|
|
424
|
+
});
|
|
425
|
+
const queries = useQueries({
|
|
426
|
+
queries: outcomeIds.map((outcomeId) => ({
|
|
427
|
+
queryKey: marketDataKeys.chart(outcomeId, interval, startTs, endTs, countBack),
|
|
428
|
+
queryFn: (_0) => __async(null, [_0], function* ({ signal }) {
|
|
429
|
+
const response = yield client.getChartBars(
|
|
430
|
+
{
|
|
431
|
+
venueMarketOutcomeId: outcomeId,
|
|
432
|
+
resolution: interval,
|
|
433
|
+
from: startTs != null ? startTs : void 0,
|
|
434
|
+
to: endTs,
|
|
435
|
+
countBack: countBack != null ? countBack : void 0
|
|
436
|
+
},
|
|
437
|
+
{ signal }
|
|
438
|
+
);
|
|
439
|
+
return createMarketChartData({
|
|
440
|
+
marketId: outcomeId,
|
|
441
|
+
interval,
|
|
442
|
+
startTs,
|
|
443
|
+
endTs,
|
|
444
|
+
response
|
|
445
|
+
});
|
|
446
|
+
}),
|
|
447
|
+
enabled: isQueryEnabled,
|
|
448
|
+
staleTime: 3e4,
|
|
449
|
+
gcTime: 5 * 6e4,
|
|
450
|
+
refetchOnWindowFocus: false,
|
|
451
|
+
retry: 1,
|
|
452
|
+
placeholderData: keepPreviousData
|
|
453
|
+
}))
|
|
454
|
+
});
|
|
455
|
+
const successfulDatasets = queries.flatMap((query) => {
|
|
456
|
+
return query.data ? [query.data] : [];
|
|
457
|
+
});
|
|
458
|
+
const data = primaryOutcomeId && successfulDatasets.length > 0 ? mergeMarketChartData({
|
|
459
|
+
marketId: primaryOutcomeId,
|
|
460
|
+
interval,
|
|
461
|
+
startTs,
|
|
462
|
+
endTs,
|
|
463
|
+
datasets: successfulDatasets
|
|
464
|
+
}) : null;
|
|
465
|
+
const hasPendingQuery = queries.some((query) => query.isLoading);
|
|
466
|
+
const firstError = (_c = (_b = queries.find((query) => query.error != null)) == null ? void 0 : _b.error) != null ? _c : null;
|
|
467
|
+
const error = data == null && !hasPendingQuery ? firstError instanceof Error ? firstError : firstError ? new Error(String(firstError)) : null : null;
|
|
468
|
+
const isLoading = Boolean(isQueryEnabled && data == null && hasPendingQuery);
|
|
469
|
+
return {
|
|
470
|
+
data,
|
|
471
|
+
isLoading,
|
|
472
|
+
error,
|
|
473
|
+
isLive: Boolean(liveEnabled && primaryOutcomeId && isConnected),
|
|
474
|
+
refetch: () => __async(null, null, function* () {
|
|
475
|
+
return Promise.all(queries.map((query) => query.refetch()));
|
|
476
|
+
})
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
// src/use-live-market-stores.ts
|
|
481
|
+
import { useEffect as useEffect3, useMemo as useMemo2, useReducer, useRef } from "react";
|
|
482
|
+
function useLiveMarketStores(venueMarketIds) {
|
|
483
|
+
const ws = useAggWebSocket();
|
|
484
|
+
const [, forceRender] = useReducer((c) => c + 1, 0);
|
|
485
|
+
const subsRef = useRef(/* @__PURE__ */ new Map());
|
|
486
|
+
const stableKey = useMemo2(() => venueMarketIds.slice().sort().join("|"), [venueMarketIds]);
|
|
487
|
+
useEffect3(() => {
|
|
488
|
+
if (!ws || venueMarketIds.length === 0) return;
|
|
489
|
+
const current = subsRef.current;
|
|
490
|
+
const desired = new Set(venueMarketIds);
|
|
491
|
+
for (const [id, sub] of current) {
|
|
492
|
+
if (!desired.has(id)) {
|
|
493
|
+
sub.unsub();
|
|
494
|
+
sub.unlisten();
|
|
495
|
+
current.delete(id);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
for (const id of desired) {
|
|
499
|
+
if (!current.has(id)) {
|
|
500
|
+
const builder = getOrCreateBuilder(id);
|
|
501
|
+
const unsub = ws.subscribe(id, "orderbook");
|
|
502
|
+
const unlisten = builder.onChange(forceRender);
|
|
503
|
+
current.set(id, { unsub, unlisten });
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
return () => {
|
|
507
|
+
for (const [, sub] of current) {
|
|
508
|
+
sub.unsub();
|
|
509
|
+
sub.unlisten();
|
|
510
|
+
}
|
|
511
|
+
current.clear();
|
|
512
|
+
};
|
|
513
|
+
}, [ws, stableKey]);
|
|
514
|
+
return venueMarketIds.map((id) => getOrCreateBuilder(id));
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// src/use-live-candles.ts
|
|
518
|
+
function candleToLive(c, source) {
|
|
519
|
+
return { time: c.openTime, o: c.o, h: c.h, l: c.l, c: c.c, v: c.v, source };
|
|
520
|
+
}
|
|
521
|
+
function useLiveCandles(options) {
|
|
522
|
+
var _a;
|
|
523
|
+
const { market, interval = "5m", mode = "venue", startTs, endTs } = options;
|
|
524
|
+
const venueMarketIds = useMemo3(() => {
|
|
525
|
+
if (!market) return [];
|
|
526
|
+
if (mode === "venue") return [market.id];
|
|
527
|
+
const ids = [market.id];
|
|
528
|
+
if (market.matchedVenueMarkets) {
|
|
529
|
+
for (const m of market.matchedVenueMarkets) {
|
|
530
|
+
ids.push(m.id);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
return ids;
|
|
534
|
+
}, [market, mode]);
|
|
535
|
+
const builders = useLiveMarketStores(venueMarketIds);
|
|
536
|
+
const restMarketId = (_a = market == null ? void 0 : market.marketId) != null ? _a : null;
|
|
537
|
+
const { data: chartData, isLoading } = useMarketChart({
|
|
538
|
+
marketId: restMarketId,
|
|
539
|
+
interval,
|
|
540
|
+
startTs: startTs != null ? startTs : null,
|
|
541
|
+
endTs: endTs != null ? endTs : null,
|
|
542
|
+
enabled: !!restMarketId && startTs != null && endTs != null
|
|
543
|
+
});
|
|
544
|
+
const liveData = useMemo3(() => {
|
|
545
|
+
if (builders.length === 0) return { closed: [], forming: null };
|
|
546
|
+
if (mode === "venue" || builders.length === 1) {
|
|
547
|
+
return {
|
|
548
|
+
closed: builders[0].getClosed(interval),
|
|
549
|
+
forming: builders[0].getForming(interval)
|
|
550
|
+
};
|
|
551
|
+
}
|
|
552
|
+
return {
|
|
553
|
+
closed: mergeClosedCandles(builders.map((b) => b.getClosed(interval))),
|
|
554
|
+
forming: mergeCandles(builders.map((b) => b.getForming(interval)))
|
|
555
|
+
};
|
|
556
|
+
}, [builders, interval, mode]);
|
|
557
|
+
const candles = useMemo3(() => {
|
|
558
|
+
const byTime = /* @__PURE__ */ new Map();
|
|
559
|
+
if (chartData) {
|
|
560
|
+
const venueEntries = Object.values(chartData.venues);
|
|
561
|
+
for (const venueData of venueEntries) {
|
|
562
|
+
for (const c of venueData.candles) {
|
|
563
|
+
byTime.set(c.time, {
|
|
564
|
+
time: c.time,
|
|
565
|
+
o: c.open,
|
|
566
|
+
h: c.high,
|
|
567
|
+
l: c.low,
|
|
568
|
+
c: c.close,
|
|
569
|
+
v: c.volume,
|
|
570
|
+
source: "rest"
|
|
571
|
+
});
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
for (const c of liveData.closed) {
|
|
576
|
+
byTime.set(c.openTime, candleToLive(c, "live"));
|
|
577
|
+
}
|
|
578
|
+
const merged = Array.from(byTime.values());
|
|
579
|
+
merged.sort((a, b) => a.time - b.time);
|
|
580
|
+
return merged;
|
|
581
|
+
}, [chartData, liveData.closed]);
|
|
582
|
+
const liveCandle = useMemo3(() => {
|
|
583
|
+
if (!liveData.forming) return null;
|
|
584
|
+
return candleToLive(liveData.forming, "live");
|
|
585
|
+
}, [liveData.forming]);
|
|
586
|
+
return { candles, liveCandle, isLoading };
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
// src/use-live-candle-overlay.ts
|
|
590
|
+
function timeRangeToInterval(range) {
|
|
591
|
+
switch (range) {
|
|
592
|
+
case "1H":
|
|
593
|
+
return "1m";
|
|
594
|
+
case "6H":
|
|
595
|
+
return "5m";
|
|
596
|
+
case "1D":
|
|
597
|
+
return "5m";
|
|
598
|
+
case "1W":
|
|
599
|
+
return "1h";
|
|
600
|
+
case "1M":
|
|
601
|
+
return "1h";
|
|
602
|
+
case "ALL":
|
|
603
|
+
return "1h";
|
|
604
|
+
default:
|
|
605
|
+
return "5m";
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
function useLiveCandleOverlay(options) {
|
|
609
|
+
var _a, _b;
|
|
610
|
+
const {
|
|
611
|
+
market,
|
|
612
|
+
interval = "5m",
|
|
613
|
+
mode = "venue",
|
|
614
|
+
startTs,
|
|
615
|
+
endTs,
|
|
616
|
+
enabled = true,
|
|
617
|
+
scale = 100
|
|
618
|
+
} = options;
|
|
619
|
+
const {
|
|
620
|
+
candles: rawCandles,
|
|
621
|
+
liveCandle: rawLive,
|
|
622
|
+
isLoading
|
|
623
|
+
} = useLiveCandles({
|
|
624
|
+
market: enabled ? market : null,
|
|
625
|
+
interval,
|
|
626
|
+
mode,
|
|
627
|
+
startTs,
|
|
628
|
+
endTs
|
|
629
|
+
});
|
|
630
|
+
const scaleCandle = useCallback4(
|
|
631
|
+
(candle) => ({
|
|
632
|
+
time: candle.time,
|
|
633
|
+
open: candle.o * scale,
|
|
634
|
+
high: candle.h * scale,
|
|
635
|
+
low: candle.l * scale,
|
|
636
|
+
close: candle.c * scale,
|
|
637
|
+
v: candle.v
|
|
638
|
+
}),
|
|
639
|
+
[scale]
|
|
640
|
+
);
|
|
641
|
+
const scaledCandles = useMemo4(() => rawCandles.map(scaleCandle), [rawCandles, scaleCandle]);
|
|
642
|
+
const liveCandle = useMemo4(() => rawLive ? scaleCandle(rawLive) : null, [rawLive, scaleCandle]);
|
|
643
|
+
return {
|
|
644
|
+
liveCandle,
|
|
645
|
+
scaledCandles,
|
|
646
|
+
lineValue: (_b = liveCandle == null ? void 0 : liveCandle.close) != null ? _b : (_a = scaledCandles[scaledCandles.length - 1]) == null ? void 0 : _a.close,
|
|
647
|
+
live: liveCandle != null,
|
|
648
|
+
isLoading
|
|
649
|
+
};
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
// src/use-event-orderbook-data.ts
|
|
653
|
+
import { useEffect as useEffect4, useMemo as useMemo5 } from "react";
|
|
654
|
+
function extractSelectedOutcomeIds(selectedMarket) {
|
|
655
|
+
var _a, _b, _c;
|
|
656
|
+
if (!selectedMarket) return [];
|
|
657
|
+
const ids = /* @__PURE__ */ new Set();
|
|
658
|
+
for (const outcome of (_a = selectedMarket.venueMarketOutcomes) != null ? _a : []) {
|
|
659
|
+
if (outcome.id) ids.add(outcome.id);
|
|
660
|
+
}
|
|
661
|
+
for (const matched of (_b = selectedMarket.matchedVenueMarkets) != null ? _b : []) {
|
|
662
|
+
for (const outcome of (_c = matched.venueMarketOutcomes) != null ? _c : []) {
|
|
663
|
+
if (outcome.id) ids.add(outcome.id);
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
return [...ids].sort();
|
|
667
|
+
}
|
|
668
|
+
function useEventOrderbookData(venueMarkets, selectedMarketId) {
|
|
669
|
+
const ws = useAggWebSocket();
|
|
670
|
+
const {
|
|
671
|
+
features: { enableLiveUpdates }
|
|
672
|
+
} = useAggUiConfig();
|
|
673
|
+
const selectedMarket = useMemo5(() => {
|
|
674
|
+
var _a;
|
|
675
|
+
if (!selectedMarketId || !(venueMarkets == null ? void 0 : venueMarkets.length)) return null;
|
|
676
|
+
return (_a = venueMarkets.find((m) => m.id === selectedMarketId)) != null ? _a : null;
|
|
677
|
+
}, [venueMarkets, selectedMarketId]);
|
|
678
|
+
const selectedOutcomeIds = useMemo5(
|
|
679
|
+
() => extractSelectedOutcomeIds(selectedMarket),
|
|
680
|
+
[selectedMarket]
|
|
681
|
+
);
|
|
682
|
+
const selectedKey = selectedOutcomeIds.join("|");
|
|
683
|
+
useEffect4(() => {
|
|
684
|
+
if (!ws || !enableLiveUpdates || !selectedOutcomeIds.length) return;
|
|
685
|
+
const unsubscribers = selectedOutcomeIds.map((id) => ws.subscribe(id, "orderbook"));
|
|
686
|
+
return () => {
|
|
687
|
+
for (const unsub of unsubscribers) unsub();
|
|
688
|
+
};
|
|
689
|
+
}, [ws, selectedKey, enableLiveUpdates]);
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
// src/use-live-market.ts
|
|
693
|
+
import { useQuery } from "@tanstack/react-query";
|
|
694
|
+
function outcomeOrderbookToState(response, marketId) {
|
|
695
|
+
var _a, _b, _c, _d;
|
|
696
|
+
const { venue, orderbook, midpoint, spread, seq, checksum, timestamp, venueMarketOutcomeId } = response;
|
|
697
|
+
const attribute = (l) => ({
|
|
698
|
+
price: l.price,
|
|
699
|
+
size: l.size,
|
|
700
|
+
venues: { [venue]: l.size }
|
|
701
|
+
});
|
|
702
|
+
const venueLevels = (l) => ({
|
|
703
|
+
price: l.price,
|
|
704
|
+
size: l.size
|
|
705
|
+
});
|
|
706
|
+
return {
|
|
707
|
+
marketId,
|
|
708
|
+
outcomeId: venueMarketOutcomeId,
|
|
709
|
+
bids: orderbook.bids.map(attribute),
|
|
710
|
+
asks: orderbook.asks.map(attribute),
|
|
711
|
+
venueOrderbooks: {
|
|
712
|
+
[venue]: {
|
|
713
|
+
bids: orderbook.bids.map(venueLevels),
|
|
714
|
+
asks: orderbook.asks.map(venueLevels)
|
|
715
|
+
}
|
|
716
|
+
},
|
|
717
|
+
venues: {
|
|
718
|
+
[venue]: {
|
|
719
|
+
bestBid: (_b = (_a = orderbook.bids[0]) == null ? void 0 : _a.price) != null ? _b : null,
|
|
720
|
+
bestAsk: (_d = (_c = orderbook.asks[0]) == null ? void 0 : _c.price) != null ? _d : null
|
|
721
|
+
}
|
|
722
|
+
},
|
|
723
|
+
midpoint,
|
|
724
|
+
spread,
|
|
725
|
+
seq,
|
|
726
|
+
checksum,
|
|
727
|
+
timestamp
|
|
728
|
+
};
|
|
729
|
+
}
|
|
730
|
+
function useLiveMarket(canonicalMarketId) {
|
|
731
|
+
var _a, _b;
|
|
732
|
+
const client = useAggClient();
|
|
733
|
+
const isConnected = useAggWebSocketConnectionState();
|
|
734
|
+
const {
|
|
735
|
+
features: { enableLiveUpdates }
|
|
736
|
+
} = useAggUiConfig();
|
|
737
|
+
const isLiveSubscriptionEnabled = Boolean(canonicalMarketId && enableLiveUpdates);
|
|
738
|
+
useMarketDataSubscription({
|
|
739
|
+
marketId: canonicalMarketId,
|
|
740
|
+
enabled: isLiveSubscriptionEnabled,
|
|
741
|
+
orderbook: true
|
|
742
|
+
});
|
|
743
|
+
const query = useQuery({
|
|
744
|
+
queryKey: marketDataKeys.live(canonicalMarketId != null ? canonicalMarketId : "__disabled__"),
|
|
745
|
+
queryFn: () => __async(null, null, function* () {
|
|
746
|
+
return createMarketLiveState(canonicalMarketId != null ? canonicalMarketId : "__disabled__");
|
|
747
|
+
}),
|
|
748
|
+
enabled: false,
|
|
749
|
+
staleTime: Infinity,
|
|
750
|
+
gcTime: 5 * 6e4,
|
|
751
|
+
initialData: () => createMarketLiveState(canonicalMarketId != null ? canonicalMarketId : "__disabled__", {
|
|
752
|
+
isConnected: Boolean(isLiveSubscriptionEnabled && isConnected)
|
|
753
|
+
})
|
|
754
|
+
});
|
|
755
|
+
const seedQuery = useQuery({
|
|
756
|
+
queryKey: ["live-market-seed", canonicalMarketId],
|
|
757
|
+
queryFn: ({ signal }) => canonicalMarketId ? client.getOutcomeOrderbook(canonicalMarketId, { signal }) : Promise.resolve(null),
|
|
758
|
+
enabled: Boolean(canonicalMarketId),
|
|
759
|
+
staleTime: 5e3,
|
|
760
|
+
gcTime: 6e4,
|
|
761
|
+
refetchOnWindowFocus: false,
|
|
762
|
+
retry: 1
|
|
763
|
+
});
|
|
764
|
+
const data = (_a = query.data) != null ? _a : createMarketLiveState(canonicalMarketId != null ? canonicalMarketId : "__disabled__");
|
|
765
|
+
const orderbook = (_b = data.orderbook) != null ? _b : canonicalMarketId && seedQuery.data ? outcomeOrderbookToState(seedQuery.data, canonicalMarketId) : null;
|
|
766
|
+
return {
|
|
767
|
+
orderbook,
|
|
768
|
+
trades: data.trades,
|
|
769
|
+
isConnected: isLiveSubscriptionEnabled ? data.isConnected : false,
|
|
770
|
+
integrity: data.integrity
|
|
771
|
+
};
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
// src/use-live-outcome-prices.ts
|
|
775
|
+
import { useMemo as useMemo6, useRef as useRef2 } from "react";
|
|
776
|
+
import { useQueries as useQueries2 } from "@tanstack/react-query";
|
|
777
|
+
var EMPTY_PRICES = /* @__PURE__ */ new Map();
|
|
778
|
+
var buildMidpointFingerprint = (outcomeIds, queries) => {
|
|
779
|
+
var _a, _b, _c;
|
|
780
|
+
const parts = [];
|
|
781
|
+
for (let i = 0; i < outcomeIds.length; i++) {
|
|
782
|
+
const midpoint = (_c = (_b = (_a = queries[i]) == null ? void 0 : _a.data) == null ? void 0 : _b.orderbook) == null ? void 0 : _c.midpoint;
|
|
783
|
+
parts.push(`${outcomeIds[i]}:${midpoint != null ? midpoint : "_"}`);
|
|
784
|
+
}
|
|
785
|
+
return parts.join("|");
|
|
786
|
+
};
|
|
787
|
+
function useLiveOutcomePrices(venueMarkets) {
|
|
788
|
+
const {
|
|
789
|
+
features: { enableLiveUpdates }
|
|
790
|
+
} = useAggUiConfig();
|
|
791
|
+
const outcomeIds = useMemo6(() => {
|
|
792
|
+
var _a;
|
|
793
|
+
if (!(venueMarkets == null ? void 0 : venueMarkets.length)) return [];
|
|
794
|
+
const ids = /* @__PURE__ */ new Set();
|
|
795
|
+
for (const vm of venueMarkets) {
|
|
796
|
+
for (const outcome of (_a = vm.venueMarketOutcomes) != null ? _a : []) {
|
|
797
|
+
if (outcome.id) ids.add(outcome.id);
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
return [...ids].sort();
|
|
801
|
+
}, [venueMarkets]);
|
|
802
|
+
const queries = useQueries2({
|
|
803
|
+
queries: outcomeIds.map((id) => ({
|
|
804
|
+
queryKey: marketDataKeys.live(id),
|
|
805
|
+
queryFn: () => createMarketLiveState(id),
|
|
806
|
+
enabled: false,
|
|
807
|
+
staleTime: Infinity,
|
|
808
|
+
gcTime: 5 * 6e4,
|
|
809
|
+
initialData: () => createMarketLiveState(id)
|
|
810
|
+
}))
|
|
811
|
+
});
|
|
812
|
+
const fingerprint = buildMidpointFingerprint(outcomeIds, queries);
|
|
813
|
+
const prevRef = useRef2({
|
|
814
|
+
fingerprint: "",
|
|
815
|
+
prices: EMPTY_PRICES
|
|
816
|
+
});
|
|
817
|
+
const data = useMemo6(() => {
|
|
818
|
+
var _a, _b, _c, _d;
|
|
819
|
+
if (!(venueMarkets == null ? void 0 : venueMarkets.length)) return EMPTY_PRICES;
|
|
820
|
+
if (fingerprint === prevRef.current.fingerprint) {
|
|
821
|
+
return prevRef.current.prices;
|
|
822
|
+
}
|
|
823
|
+
const prices = /* @__PURE__ */ new Map();
|
|
824
|
+
const liveByOutcomeId = /* @__PURE__ */ new Map();
|
|
825
|
+
for (let i = 0; i < outcomeIds.length; i++) {
|
|
826
|
+
const state = (_a = queries[i]) == null ? void 0 : _a.data;
|
|
827
|
+
liveByOutcomeId.set(outcomeIds[i], (_c = (_b = state == null ? void 0 : state.orderbook) == null ? void 0 : _b.midpoint) != null ? _c : null);
|
|
828
|
+
}
|
|
829
|
+
for (const vm of venueMarkets) {
|
|
830
|
+
for (const outcome of (_d = vm.venueMarketOutcomes) != null ? _d : []) {
|
|
831
|
+
if (!enableLiveUpdates) {
|
|
832
|
+
prices.set(outcome.id, outcome.price);
|
|
833
|
+
continue;
|
|
834
|
+
}
|
|
835
|
+
const liveMidpoint = liveByOutcomeId.get(outcome.id);
|
|
836
|
+
prices.set(outcome.id, liveMidpoint != null ? liveMidpoint : outcome.price);
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
prevRef.current = { fingerprint, prices };
|
|
840
|
+
return prices;
|
|
841
|
+
}, [venueMarkets, enableLiveUpdates, fingerprint, outcomeIds, queries]);
|
|
842
|
+
return data;
|
|
843
|
+
}
|
|
844
|
+
function findLivePriceById(livePrices, id) {
|
|
845
|
+
return livePrices.get(id);
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
// src/use-live-trades.ts
|
|
849
|
+
function useLiveTrades(canonicalMarketId) {
|
|
850
|
+
const {
|
|
851
|
+
features: { enableLiveUpdates }
|
|
852
|
+
} = useAggUiConfig();
|
|
853
|
+
const { trades } = useLiveMarket(canonicalMarketId);
|
|
854
|
+
useMarketDataSubscription({
|
|
855
|
+
marketId: canonicalMarketId,
|
|
856
|
+
enabled: Boolean(canonicalMarketId && enableLiveUpdates),
|
|
857
|
+
orderbook: false,
|
|
858
|
+
trades: true
|
|
859
|
+
});
|
|
860
|
+
return trades;
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
// src/use-midpoints.ts
|
|
864
|
+
import { useMemo as useMemo7 } from "react";
|
|
865
|
+
import { useQuery as useQuery2 } from "@tanstack/react-query";
|
|
866
|
+
var normalizeVenueMarketIds = (venueMarkets) => {
|
|
867
|
+
return [...new Set((venueMarkets != null ? venueMarkets : []).map((market) => market.id).filter(Boolean))].sort(
|
|
868
|
+
(left, right) => left.localeCompare(right)
|
|
869
|
+
);
|
|
870
|
+
};
|
|
871
|
+
function useMidpoints(venueMarkets) {
|
|
872
|
+
const client = useAggClient();
|
|
873
|
+
const ids = useMemo7(() => normalizeVenueMarketIds(venueMarkets), [venueMarkets]);
|
|
874
|
+
const { data, isLoading } = useQuery2({
|
|
875
|
+
queryKey: ["midpoints", ids],
|
|
876
|
+
queryFn: () => client.getMidpoints(ids),
|
|
877
|
+
enabled: ids.length > 0,
|
|
878
|
+
staleTime: Infinity,
|
|
879
|
+
gcTime: 30 * 6e4,
|
|
880
|
+
refetchOnMount: false,
|
|
881
|
+
refetchOnWindowFocus: false,
|
|
882
|
+
refetchOnReconnect: false
|
|
883
|
+
});
|
|
884
|
+
const prices = useMemo7(() => {
|
|
885
|
+
var _a, _b, _c, _d;
|
|
886
|
+
const map = /* @__PURE__ */ new Map();
|
|
887
|
+
if (!(data == null ? void 0 : data.data) || !venueMarkets) return map;
|
|
888
|
+
for (const item of data.data) {
|
|
889
|
+
if ((_a = item.outcomes) == null ? void 0 : _a.length) {
|
|
890
|
+
for (const o of item.outcomes) {
|
|
891
|
+
if (o.midpoint != null) {
|
|
892
|
+
map.set(o.venueMarketOutcomeId, o.midpoint);
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
if ((_b = item.matched) == null ? void 0 : _b.length) {
|
|
896
|
+
for (const m of item.matched) {
|
|
897
|
+
if (m.midpoint != null) {
|
|
898
|
+
const market = venueMarkets.find((vm) => vm.id === item.venueMarketId);
|
|
899
|
+
if (!market) continue;
|
|
900
|
+
for (const outcome of market.venueMarketOutcomes) {
|
|
901
|
+
const existing = map.get(outcome.id);
|
|
902
|
+
const isYes = ((_c = outcome.label) == null ? void 0 : _c.toLowerCase()) === "yes";
|
|
903
|
+
const matchedPrice = isYes ? m.midpoint : 1 - m.midpoint;
|
|
904
|
+
if (existing == null || isYes && matchedPrice > existing || !isYes && matchedPrice < existing) {
|
|
905
|
+
map.set(outcome.id, matchedPrice);
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
continue;
|
|
912
|
+
}
|
|
913
|
+
if (item.midpoint != null) {
|
|
914
|
+
const market = venueMarkets.find((vm) => vm.id === item.venueMarketId);
|
|
915
|
+
if (!market) continue;
|
|
916
|
+
for (const outcome of market.venueMarketOutcomes) {
|
|
917
|
+
const isYes = ((_d = outcome.label) == null ? void 0 : _d.toLowerCase()) === "yes";
|
|
918
|
+
map.set(outcome.id, isYes ? item.midpoint : 1 - item.midpoint);
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
return map;
|
|
923
|
+
}, [data, venueMarkets]);
|
|
924
|
+
return { prices, isLoading: isLoading && ids.length > 0 };
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
// src/use-market-orderbook.ts
|
|
928
|
+
import { useQueries as useQueries3, useQueryClient } from "@tanstack/react-query";
|
|
929
|
+
function useMarketOrderbook(options) {
|
|
930
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
931
|
+
const queryClient = useQueryClient();
|
|
932
|
+
const ws = useAggWebSocket();
|
|
933
|
+
const isConnected = useAggWebSocketConnectionState();
|
|
934
|
+
const {
|
|
935
|
+
features: { enableLiveUpdates }
|
|
936
|
+
} = useAggUiConfig();
|
|
937
|
+
const { marketId, depth, enabled = true, venueOutcomes, live } = options;
|
|
938
|
+
const liveEnabled = live != null ? live : enableLiveUpdates;
|
|
939
|
+
const outcomeIds = venueOutcomes == null ? void 0 : venueOutcomes.map((v) => v.venueMarketOutcomeId).filter(Boolean);
|
|
940
|
+
const subscriptionIds = (outcomeIds == null ? void 0 : outcomeIds.length) ? [...new Set(outcomeIds)] : marketId ? [marketId] : [];
|
|
941
|
+
const selectedOutcomeId = (_a = subscriptionIds[0]) != null ? _a : null;
|
|
942
|
+
useMarketDataSubscription({
|
|
943
|
+
marketId: selectedOutcomeId,
|
|
944
|
+
additionalMarketIds: subscriptionIds.slice(1),
|
|
945
|
+
enabled: enabled && !!selectedOutcomeId,
|
|
946
|
+
orderbook: true
|
|
947
|
+
});
|
|
948
|
+
const liveQueries = useQueries3({
|
|
949
|
+
queries: subscriptionIds.map((subscriptionId) => ({
|
|
950
|
+
queryKey: marketDataKeys.live(subscriptionId),
|
|
951
|
+
queryFn: () => createMarketLiveState(subscriptionId),
|
|
952
|
+
staleTime: Infinity,
|
|
953
|
+
gcTime: 5 * 6e4,
|
|
954
|
+
refetchOnMount: false,
|
|
955
|
+
refetchOnWindowFocus: false,
|
|
956
|
+
refetchOnReconnect: false
|
|
957
|
+
}))
|
|
958
|
+
});
|
|
959
|
+
const liveStates = subscriptionIds.map((subscriptionId, index) => {
|
|
960
|
+
var _a2, _b2;
|
|
961
|
+
return (_b2 = (_a2 = liveQueries[index]) == null ? void 0 : _a2.data) != null ? _b2 : createMarketLiveState(subscriptionId);
|
|
962
|
+
});
|
|
963
|
+
const primaryOrderbook = (_c = (_b = liveStates[0]) == null ? void 0 : _b.orderbook) != null ? _c : null;
|
|
964
|
+
const primarySnapshotVersion = (_e = (_d = liveStates[0]) == null ? void 0 : _d.orderbookSnapshotVersion) != null ? _e : 0;
|
|
965
|
+
const data = primaryOrderbook ? applyOrderbookDepth(
|
|
966
|
+
createMarketOrderbookDataFromState(primaryOrderbook, {
|
|
967
|
+
snapshotVersion: primarySnapshotVersion
|
|
968
|
+
}),
|
|
969
|
+
depth
|
|
970
|
+
) : null;
|
|
971
|
+
const dataById = Object.fromEntries(
|
|
972
|
+
liveStates.flatMap((liveState, index) => {
|
|
973
|
+
if (!liveState.orderbook) return [];
|
|
974
|
+
return [
|
|
975
|
+
[
|
|
976
|
+
subscriptionIds[index],
|
|
977
|
+
applyOrderbookDepth(
|
|
978
|
+
createMarketOrderbookDataFromState(liveState.orderbook, {
|
|
979
|
+
snapshotVersion: liveState.orderbookSnapshotVersion
|
|
980
|
+
}),
|
|
981
|
+
depth
|
|
982
|
+
)
|
|
983
|
+
]
|
|
984
|
+
];
|
|
985
|
+
})
|
|
986
|
+
);
|
|
987
|
+
const hasAnyOrderbook = liveStates.some((liveState) => liveState.orderbook != null);
|
|
988
|
+
const liveOrderbookErrorMessage = enabled && liveEnabled && !hasAnyOrderbook ? (_g = (_f = liveStates.find(
|
|
989
|
+
(liveState) => typeof liveState.orderbookError === "string" && liveState.orderbookError.length > 0
|
|
990
|
+
)) == null ? void 0 : _f.orderbookError) != null ? _g : null : null;
|
|
991
|
+
return {
|
|
992
|
+
data,
|
|
993
|
+
dataById,
|
|
994
|
+
isLoading: enabled && liveEnabled && !hasAnyOrderbook && isConnected && liveOrderbookErrorMessage == null,
|
|
995
|
+
error: liveOrderbookErrorMessage ? new Error(liveOrderbookErrorMessage) : null,
|
|
996
|
+
isLive: Boolean(liveEnabled && selectedOutcomeId && isConnected),
|
|
997
|
+
refetch: () => __async(null, null, function* () {
|
|
998
|
+
if (!enabled) return;
|
|
999
|
+
if (subscriptionIds.length === 0) return;
|
|
1000
|
+
subscriptionIds.forEach((subscriptionId) => {
|
|
1001
|
+
queryClient.setQueryData(
|
|
1002
|
+
marketDataKeys.live(subscriptionId),
|
|
1003
|
+
(previous) => __spreadProps(__spreadValues({}, previous != null ? previous : createMarketLiveState(subscriptionId)), {
|
|
1004
|
+
orderbookError: null
|
|
1005
|
+
})
|
|
1006
|
+
);
|
|
1007
|
+
});
|
|
1008
|
+
ws == null ? void 0 : ws.resnapshot(subscriptionIds);
|
|
1009
|
+
})
|
|
1010
|
+
};
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
// src/use-order-book.ts
|
|
1014
|
+
import { keepPreviousData as keepPreviousData2, useQuery as useQuery3 } from "@tanstack/react-query";
|
|
1015
|
+
function useOrderBook(options) {
|
|
1016
|
+
const client = useAggClient();
|
|
1017
|
+
const { orderbooks, enabled = true, canonicalMarketId } = options;
|
|
1018
|
+
const requestedVenueMarketIds = [...new Set(orderbooks.map(({ market }) => market.id))];
|
|
1019
|
+
const canonicalResult = useMarketOrderbook({
|
|
1020
|
+
marketId: canonicalMarketId != null ? canonicalMarketId : null,
|
|
1021
|
+
enabled: enabled && !!canonicalMarketId && orderbooks.length > 0,
|
|
1022
|
+
venueOutcomes: canonicalMarketId ? orderbooks.map(({ market, outcome }) => ({
|
|
1023
|
+
venue: market.venue,
|
|
1024
|
+
venueMarketOutcomeId: outcome.id
|
|
1025
|
+
})) : void 0
|
|
1026
|
+
});
|
|
1027
|
+
const batchedResult = useQuery3({
|
|
1028
|
+
queryKey: requestedVenueMarketIds.length ? ["orderbooks", requestedVenueMarketIds, null] : ["orderbooks", "__disabled__", null],
|
|
1029
|
+
queryFn: ({ signal }) => client.getOrderbooks(
|
|
1030
|
+
{
|
|
1031
|
+
venueMarketIds: requestedVenueMarketIds
|
|
1032
|
+
},
|
|
1033
|
+
{ signal }
|
|
1034
|
+
),
|
|
1035
|
+
enabled: enabled && !canonicalMarketId && requestedVenueMarketIds.length > 0,
|
|
1036
|
+
staleTime: 1e4,
|
|
1037
|
+
gcTime: 5 * 6e4,
|
|
1038
|
+
refetchOnWindowFocus: false,
|
|
1039
|
+
retry: 1,
|
|
1040
|
+
placeholderData: keepPreviousData2
|
|
1041
|
+
});
|
|
1042
|
+
const data = (() => {
|
|
1043
|
+
var _a, _b;
|
|
1044
|
+
if (canonicalMarketId) {
|
|
1045
|
+
const canonicalData = canonicalResult.data;
|
|
1046
|
+
if (!canonicalData) return void 0;
|
|
1047
|
+
const merged2 = orderbooks.flatMap(({ market, outcome }) => {
|
|
1048
|
+
const venueBook = canonicalData.venueOrderbooks[market.venue];
|
|
1049
|
+
if (!venueBook) return [];
|
|
1050
|
+
return [
|
|
1051
|
+
{
|
|
1052
|
+
market,
|
|
1053
|
+
outcome,
|
|
1054
|
+
orderbook: {
|
|
1055
|
+
bids: venueBook.bids,
|
|
1056
|
+
asks: venueBook.asks
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
];
|
|
1060
|
+
});
|
|
1061
|
+
return merged2.length === orderbooks.length ? merged2 : void 0;
|
|
1062
|
+
}
|
|
1063
|
+
const liveBooksByMarketId = new Map(
|
|
1064
|
+
((_b = (_a = batchedResult.data) == null ? void 0 : _a.data) != null ? _b : []).filter((item) => item.status === "ok").map((item) => [item.venueMarketId, item])
|
|
1065
|
+
);
|
|
1066
|
+
const merged = orderbooks.flatMap(({ market, outcome }, index) => {
|
|
1067
|
+
var _a2;
|
|
1068
|
+
void index;
|
|
1069
|
+
const item = liveBooksByMarketId.get(market.id);
|
|
1070
|
+
const orderbook = (_a2 = item == null ? void 0 : item.venueOrderbooks[market.venue]) == null ? void 0 : _a2.orderbook;
|
|
1071
|
+
if (!orderbook) return [];
|
|
1072
|
+
return [
|
|
1073
|
+
{
|
|
1074
|
+
market,
|
|
1075
|
+
outcome,
|
|
1076
|
+
orderbook
|
|
1077
|
+
}
|
|
1078
|
+
];
|
|
1079
|
+
});
|
|
1080
|
+
return merged.length === orderbooks.length ? merged : void 0;
|
|
1081
|
+
})();
|
|
1082
|
+
const aggregated = canonicalResult.data ? marketOrderbookDataToResponse(canonicalResult.data) : null;
|
|
1083
|
+
const error = canonicalMarketId ? canonicalResult.error : batchedResult.error;
|
|
1084
|
+
return {
|
|
1085
|
+
data,
|
|
1086
|
+
isLoading: canonicalMarketId ? canonicalResult.isLoading : batchedResult.isLoading,
|
|
1087
|
+
error: error instanceof Error ? error : error ? new Error(String(error)) : null,
|
|
1088
|
+
results: [batchedResult],
|
|
1089
|
+
aggregated,
|
|
1090
|
+
isLive: canonicalResult.isLive
|
|
1091
|
+
};
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
// src/use-orderbook-quote.ts
|
|
1095
|
+
import { keepPreviousData as keepPreviousData3, useQuery as useQuery4 } from "@tanstack/react-query";
|
|
1096
|
+
var QUOTE_DEBOUNCE_MS = 300;
|
|
1097
|
+
var createUnavailableOrderbookError = (message, code, retryable) => {
|
|
1098
|
+
const error = new Error(message);
|
|
1099
|
+
error.status = 404;
|
|
1100
|
+
if (code) error.code = code;
|
|
1101
|
+
if (retryable !== void 0) error.retryable = retryable;
|
|
1102
|
+
return error;
|
|
1103
|
+
};
|
|
1104
|
+
var quoteVenueOrderbooks = ({
|
|
1105
|
+
marketId,
|
|
1106
|
+
side,
|
|
1107
|
+
requestedSize,
|
|
1108
|
+
venueOrderbooks
|
|
1109
|
+
}) => {
|
|
1110
|
+
var _a;
|
|
1111
|
+
const marketData = createMarketOrderbookDataFromVenueOrderbooks({
|
|
1112
|
+
marketId,
|
|
1113
|
+
venueOrderbooks
|
|
1114
|
+
});
|
|
1115
|
+
const levels = side === "buy" ? marketData.orderbook.asks : marketData.orderbook.bids;
|
|
1116
|
+
let remaining = requestedSize;
|
|
1117
|
+
const fillsByVenue = /* @__PURE__ */ new Map();
|
|
1118
|
+
for (const level of levels) {
|
|
1119
|
+
if (remaining <= 0) break;
|
|
1120
|
+
for (const [venue, venueSize] of Object.entries(level.venues)) {
|
|
1121
|
+
if (remaining <= 0) break;
|
|
1122
|
+
const fillSize = Math.min(remaining, venueSize);
|
|
1123
|
+
const fillCost = fillSize * level.price;
|
|
1124
|
+
remaining -= fillSize;
|
|
1125
|
+
const existing = (_a = fillsByVenue.get(venue)) != null ? _a : { size: 0, cost: 0 };
|
|
1126
|
+
existing.size += fillSize;
|
|
1127
|
+
existing.cost += fillCost;
|
|
1128
|
+
fillsByVenue.set(venue, existing);
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
const filledSize = requestedSize - Math.max(0, remaining);
|
|
1132
|
+
const totalCost = [...fillsByVenue.values()].reduce((sum, fill) => sum + fill.cost, 0);
|
|
1133
|
+
const avgPrice = filledSize > 0 ? totalCost / filledSize : null;
|
|
1134
|
+
const slippage = avgPrice !== null && marketData.midpoint !== null ? side === "buy" ? avgPrice - marketData.midpoint : marketData.midpoint - avgPrice : null;
|
|
1135
|
+
return {
|
|
1136
|
+
marketId,
|
|
1137
|
+
side,
|
|
1138
|
+
requestedSize,
|
|
1139
|
+
filledSize,
|
|
1140
|
+
avgPrice,
|
|
1141
|
+
totalCost,
|
|
1142
|
+
slippage,
|
|
1143
|
+
fills: [...fillsByVenue.entries()].map(([venue, fill]) => ({
|
|
1144
|
+
venue,
|
|
1145
|
+
size: fill.size,
|
|
1146
|
+
avgPrice: fill.size > 0 ? fill.cost / fill.size : 0,
|
|
1147
|
+
cost: fill.cost
|
|
1148
|
+
}))
|
|
1149
|
+
};
|
|
1150
|
+
};
|
|
1151
|
+
function useOrderbookQuote(options) {
|
|
1152
|
+
var _a;
|
|
1153
|
+
const client = useAggClient();
|
|
1154
|
+
const { marketId, side, size, enabled = true } = options;
|
|
1155
|
+
const debouncedSize = useDebouncedValue(size, QUOTE_DEBOUNCE_MS);
|
|
1156
|
+
const shouldFetch = enabled && !!marketId && debouncedSize > 0;
|
|
1157
|
+
const query = useQuery4({
|
|
1158
|
+
queryKey: marketId ? marketDataKeys.orderbookQuote(marketId, side, debouncedSize) : ["market-data", "orderbook-quote", "__disabled__"],
|
|
1159
|
+
queryFn: () => __async(null, null, function* () {
|
|
1160
|
+
var _a2, _b, _c, _d;
|
|
1161
|
+
const response = yield client.getOrderbooks({
|
|
1162
|
+
venueMarketIds: [marketId]
|
|
1163
|
+
});
|
|
1164
|
+
const item = response.data.find((entry) => entry.venueMarketId === marketId);
|
|
1165
|
+
if (!item) {
|
|
1166
|
+
throw createUnavailableOrderbookError(`No orderbook payload returned for ${marketId}.`);
|
|
1167
|
+
}
|
|
1168
|
+
if (item.status !== "ok") {
|
|
1169
|
+
throw createUnavailableOrderbookError(
|
|
1170
|
+
(_b = (_a2 = item.error) == null ? void 0 : _a2.message) != null ? _b : `No live orderbook is available for ${marketId}.`,
|
|
1171
|
+
(_c = item.error) == null ? void 0 : _c.code,
|
|
1172
|
+
(_d = item.error) == null ? void 0 : _d.retryable
|
|
1173
|
+
);
|
|
1174
|
+
}
|
|
1175
|
+
return quoteVenueOrderbooks({
|
|
1176
|
+
marketId,
|
|
1177
|
+
side,
|
|
1178
|
+
requestedSize: debouncedSize,
|
|
1179
|
+
venueOrderbooks: Object.fromEntries(
|
|
1180
|
+
Object.entries(item.venueOrderbooks).map(([venue, entry]) => [venue, entry.orderbook])
|
|
1181
|
+
)
|
|
1182
|
+
});
|
|
1183
|
+
}),
|
|
1184
|
+
enabled: shouldFetch && debouncedSize > 0,
|
|
1185
|
+
staleTime: 1e4,
|
|
1186
|
+
gcTime: 5 * 6e4,
|
|
1187
|
+
retry: 1,
|
|
1188
|
+
placeholderData: keepPreviousData3
|
|
1189
|
+
});
|
|
1190
|
+
return {
|
|
1191
|
+
data: (_a = query.data) != null ? _a : null,
|
|
1192
|
+
isLoading: query.isLoading,
|
|
1193
|
+
isFetching: query.isFetching,
|
|
1194
|
+
error: query.error instanceof Error ? query.error : query.error ? new Error(String(query.error)) : null
|
|
1195
|
+
};
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
// src/use-orders.ts
|
|
1199
|
+
import { useQuery as useQuery5 } from "@tanstack/react-query";
|
|
1200
|
+
function useOrders(options = {}) {
|
|
1201
|
+
var _a, _b, _c, _d;
|
|
1202
|
+
const client = useAggClient();
|
|
1203
|
+
const { userId, status, limit = 50, offset = 0, enabled = true } = options;
|
|
1204
|
+
const query = useQuery5({
|
|
1205
|
+
queryKey: ["orders", userId != null ? userId : "me", status != null ? status : "all", limit, offset],
|
|
1206
|
+
queryFn: () => client.getOrders({
|
|
1207
|
+
userId,
|
|
1208
|
+
status,
|
|
1209
|
+
limit,
|
|
1210
|
+
offset
|
|
1211
|
+
}),
|
|
1212
|
+
enabled
|
|
1213
|
+
});
|
|
1214
|
+
return __spreadProps(__spreadValues({}, query), {
|
|
1215
|
+
orders: (_b = (_a = query.data) == null ? void 0 : _a.orders) != null ? _b : [],
|
|
1216
|
+
total: (_d = (_c = query.data) == null ? void 0 : _c.total) != null ? _d : 0
|
|
1217
|
+
});
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1220
|
+
// src/use-search.ts
|
|
1221
|
+
import {
|
|
1222
|
+
QueryClient,
|
|
1223
|
+
QueryClientContext,
|
|
1224
|
+
keepPreviousData as keepPreviousData4,
|
|
1225
|
+
useInfiniteQuery as useInfiniteQuery5
|
|
1226
|
+
} from "@tanstack/react-query";
|
|
1227
|
+
import { useContext as useContext2, useEffect as useEffect5, useState as useState4 } from "react";
|
|
1228
|
+
function useSearch(options) {
|
|
1229
|
+
var _a, _b, _c;
|
|
1230
|
+
const client = useContext2(AggClientContext);
|
|
1231
|
+
const queryClient = useContext2(QueryClientContext);
|
|
1232
|
+
const [fallbackQueryClient] = useState4(() => new QueryClient());
|
|
1233
|
+
const { q, type, categoryIds, limit = 20, enabled = true } = options;
|
|
1234
|
+
const isEnabled = enabled && q.length > 0;
|
|
1235
|
+
useEffect5(() => {
|
|
1236
|
+
if (queryClient) return void 0;
|
|
1237
|
+
fallbackQueryClient.mount();
|
|
1238
|
+
return () => {
|
|
1239
|
+
fallbackQueryClient.unmount();
|
|
1240
|
+
};
|
|
1241
|
+
}, [fallbackQueryClient, queryClient]);
|
|
1242
|
+
if (isEnabled && !client) {
|
|
1243
|
+
throw new Error("useSearch must be used within an <AggProvider>");
|
|
1244
|
+
}
|
|
1245
|
+
const query = useInfiniteQuery5(
|
|
1246
|
+
{
|
|
1247
|
+
queryKey: ["search", q, type, (_a = categoryIds == null ? void 0 : categoryIds.join(",")) != null ? _a : "", limit],
|
|
1248
|
+
queryFn: (_0) => __async(null, [_0], function* ({ pageParam }) {
|
|
1249
|
+
if (!client) {
|
|
1250
|
+
throw new Error("useSearch must be used within an <AggProvider>");
|
|
1251
|
+
}
|
|
1252
|
+
const res = yield client.search({
|
|
1253
|
+
q,
|
|
1254
|
+
type,
|
|
1255
|
+
categoryIds,
|
|
1256
|
+
limit,
|
|
1257
|
+
cursor: pageParam
|
|
1258
|
+
});
|
|
1259
|
+
return res;
|
|
1260
|
+
}),
|
|
1261
|
+
initialPageParam: void 0,
|
|
1262
|
+
getNextPageParam: (lastPage) => {
|
|
1263
|
+
var _a2;
|
|
1264
|
+
if (!lastPage.hasMore) return void 0;
|
|
1265
|
+
return (_a2 = lastPage.nextCursor) != null ? _a2 : void 0;
|
|
1266
|
+
},
|
|
1267
|
+
placeholderData: keepPreviousData4,
|
|
1268
|
+
enabled: isEnabled && !!client
|
|
1269
|
+
},
|
|
1270
|
+
queryClient != null ? queryClient : fallbackQueryClient
|
|
1271
|
+
);
|
|
1272
|
+
const data = (_c = (_b = query.data) == null ? void 0 : _b.pages.flatMap((page) => page.data)) != null ? _c : [];
|
|
1273
|
+
return {
|
|
1274
|
+
data,
|
|
1275
|
+
isLoading: query.isLoading,
|
|
1276
|
+
isError: query.isError,
|
|
1277
|
+
error: query.error,
|
|
1278
|
+
hasNextPage: !!query.hasNextPage,
|
|
1279
|
+
fetchNextPage: query.fetchNextPage,
|
|
1280
|
+
isFetchingNextPage: query.isFetchingNextPage,
|
|
1281
|
+
isPlaceholderData: query.isPlaceholderData
|
|
1282
|
+
};
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
// src/use-smart-route.ts
|
|
1286
|
+
import { useQuery as useQuery6, keepPreviousData as keepPreviousData5 } from "@tanstack/react-query";
|
|
1287
|
+
function useSmartRoute(options) {
|
|
1288
|
+
var _a, _b;
|
|
1289
|
+
const client = useAggClient();
|
|
1290
|
+
const {
|
|
1291
|
+
venueMarketOutcomeId,
|
|
1292
|
+
venueMarketId,
|
|
1293
|
+
outcomeId,
|
|
1294
|
+
side,
|
|
1295
|
+
tradeSide,
|
|
1296
|
+
maxSpend,
|
|
1297
|
+
sellShares,
|
|
1298
|
+
chainBalances,
|
|
1299
|
+
slipCapBps,
|
|
1300
|
+
compareVenues,
|
|
1301
|
+
enabled = true
|
|
1302
|
+
} = options;
|
|
1303
|
+
const resolvedVenueMarketOutcomeId = (_a = venueMarketOutcomeId != null ? venueMarketOutcomeId : venueMarketId) != null ? _a : outcomeId;
|
|
1304
|
+
const query = useQuery6({
|
|
1305
|
+
queryKey: [
|
|
1306
|
+
"smart-route",
|
|
1307
|
+
resolvedVenueMarketOutcomeId,
|
|
1308
|
+
side != null ? side : null,
|
|
1309
|
+
tradeSide != null ? tradeSide : null,
|
|
1310
|
+
maxSpend != null ? maxSpend : null,
|
|
1311
|
+
sellShares != null ? sellShares : null,
|
|
1312
|
+
chainBalances ? JSON.stringify(chainBalances) : null,
|
|
1313
|
+
slipCapBps != null ? slipCapBps : null,
|
|
1314
|
+
compareVenues != null ? compareVenues : false
|
|
1315
|
+
],
|
|
1316
|
+
queryFn: (_0) => __async(null, [_0], function* ({ signal }) {
|
|
1317
|
+
return client.getSmartRoute(
|
|
1318
|
+
{
|
|
1319
|
+
venueMarketOutcomeId: resolvedVenueMarketOutcomeId,
|
|
1320
|
+
side: side != null ? side : void 0,
|
|
1321
|
+
tradeSide: tradeSide != null ? tradeSide : void 0,
|
|
1322
|
+
maxSpend,
|
|
1323
|
+
sellShares,
|
|
1324
|
+
chainBalances,
|
|
1325
|
+
slipCapBps,
|
|
1326
|
+
compareVenues
|
|
1327
|
+
},
|
|
1328
|
+
{ signal }
|
|
1329
|
+
);
|
|
1330
|
+
}),
|
|
1331
|
+
enabled: enabled && !!resolvedVenueMarketOutcomeId && ((maxSpend != null ? maxSpend : 0) > 0 || (sellShares != null ? sellShares : 0) > 0),
|
|
1332
|
+
staleTime: 1e4,
|
|
1333
|
+
gcTime: 6e4,
|
|
1334
|
+
refetchOnWindowFocus: false,
|
|
1335
|
+
retry: 1,
|
|
1336
|
+
placeholderData: keepPreviousData5
|
|
1337
|
+
});
|
|
1338
|
+
const error = query.error;
|
|
1339
|
+
return {
|
|
1340
|
+
data: (_b = query.data) != null ? _b : null,
|
|
1341
|
+
isLoading: query.isLoading,
|
|
1342
|
+
isFetching: query.isFetching,
|
|
1343
|
+
error: error instanceof Error ? error : error ? new Error(String(error)) : null,
|
|
1344
|
+
refetch: query.refetch
|
|
1345
|
+
};
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1348
|
+
// src/use-user-holdings.ts
|
|
1349
|
+
import { useInfiniteQuery as useInfiniteQuery6 } from "@tanstack/react-query";
|
|
1350
|
+
function useUserHoldings(options) {
|
|
1351
|
+
var _a, _b;
|
|
1352
|
+
const client = useAggClient();
|
|
1353
|
+
const { venue, venueMarketId, venueEventId, enabled = true } = options;
|
|
1354
|
+
const query = useInfiniteQuery6({
|
|
1355
|
+
queryKey: ["user-holdings", venue, venueMarketId, venueEventId],
|
|
1356
|
+
queryFn: (_0) => __async(null, [_0], function* ({ pageParam }) {
|
|
1357
|
+
return client.getUserHoldings({
|
|
1358
|
+
venue,
|
|
1359
|
+
venueMarketId,
|
|
1360
|
+
venueEventId,
|
|
1361
|
+
cursor: pageParam
|
|
1362
|
+
});
|
|
1363
|
+
}),
|
|
1364
|
+
initialPageParam: void 0,
|
|
1365
|
+
getNextPageParam: (lastPage) => {
|
|
1366
|
+
var _a2;
|
|
1367
|
+
return (_a2 = lastPage.nextCursor) != null ? _a2 : void 0;
|
|
1368
|
+
},
|
|
1369
|
+
enabled
|
|
1370
|
+
});
|
|
1371
|
+
const holdings = (_b = (_a = query.data) == null ? void 0 : _a.pages.flatMap((p) => p.data)) != null ? _b : [];
|
|
1372
|
+
const hasNextPage = !!query.hasNextPage;
|
|
1373
|
+
return __spreadProps(__spreadValues({}, query), {
|
|
1374
|
+
holdings,
|
|
1375
|
+
hasNextPage
|
|
1376
|
+
});
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1379
|
+
// src/use-enriched-venue-event.ts
|
|
1380
|
+
import { useMemo as useMemo8 } from "react";
|
|
1381
|
+
|
|
1382
|
+
// src/use-venue-event.ts
|
|
1383
|
+
import { useQuery as useQuery7 } from "@tanstack/react-query";
|
|
1384
|
+
function useVenueEvent(options) {
|
|
1385
|
+
var _a;
|
|
1386
|
+
const client = useAggClient();
|
|
1387
|
+
const { eventId, enabled = true } = options;
|
|
1388
|
+
const query = useQuery7({
|
|
1389
|
+
queryKey: ["venue-event", eventId],
|
|
1390
|
+
queryFn: (_0) => __async(null, [_0], function* ({ signal }) {
|
|
1391
|
+
return client.getVenueEventById(eventId, { signal });
|
|
1392
|
+
}),
|
|
1393
|
+
enabled: enabled && !!eventId,
|
|
1394
|
+
staleTime: 5 * 6e4,
|
|
1395
|
+
gcTime: 5 * 6e4,
|
|
1396
|
+
refetchOnWindowFocus: true,
|
|
1397
|
+
refetchOnReconnect: true,
|
|
1398
|
+
refetchOnMount: true,
|
|
1399
|
+
retry: 1
|
|
1400
|
+
});
|
|
1401
|
+
return __spreadProps(__spreadValues({}, query), {
|
|
1402
|
+
event: (_a = query.data) != null ? _a : void 0
|
|
1403
|
+
});
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
// src/use-venue-markets.ts
|
|
1407
|
+
import { QueryClient as QueryClient2, QueryClientContext as QueryClientContext2, useInfiniteQuery as useInfiniteQuery7 } from "@tanstack/react-query";
|
|
1408
|
+
import { useContext as useContext3, useEffect as useEffect6, useState as useState5 } from "react";
|
|
1409
|
+
function useVenueMarkets(options) {
|
|
1410
|
+
var _a, _b, _c, _d, _e;
|
|
1411
|
+
const client = useContext3(AggClientContext);
|
|
1412
|
+
const queryClient = useContext3(QueryClientContext2);
|
|
1413
|
+
const [fallbackQueryClient] = useState5(() => new QueryClient2());
|
|
1414
|
+
const venue = options == null ? void 0 : options.venue;
|
|
1415
|
+
const venueEventId = options == null ? void 0 : options.venueEventId;
|
|
1416
|
+
const search = options == null ? void 0 : options.search;
|
|
1417
|
+
const matchStatus = options == null ? void 0 : options.matchStatus;
|
|
1418
|
+
const status = options == null ? void 0 : options.status;
|
|
1419
|
+
const categoryIds = options == null ? void 0 : options.categoryIds;
|
|
1420
|
+
const enabled = (_a = options == null ? void 0 : options.enabled) != null ? _a : true;
|
|
1421
|
+
const limit = (_b = options == null ? void 0 : options.limit) != null ? _b : 20;
|
|
1422
|
+
const sortBy = options == null ? void 0 : options.sortBy;
|
|
1423
|
+
const sortDir = options == null ? void 0 : options.sortDir;
|
|
1424
|
+
useEffect6(() => {
|
|
1425
|
+
if (queryClient) return void 0;
|
|
1426
|
+
fallbackQueryClient.mount();
|
|
1427
|
+
return () => {
|
|
1428
|
+
fallbackQueryClient.unmount();
|
|
1429
|
+
};
|
|
1430
|
+
}, [fallbackQueryClient, queryClient]);
|
|
1431
|
+
if (enabled && !client) {
|
|
1432
|
+
throw new Error("useVenueMarkets must be used within an <AggProvider>");
|
|
1433
|
+
}
|
|
1434
|
+
const query = useInfiniteQuery7(
|
|
1435
|
+
{
|
|
1436
|
+
queryKey: [
|
|
1437
|
+
"venue-markets",
|
|
1438
|
+
venue != null ? venue : "",
|
|
1439
|
+
venueEventId != null ? venueEventId : "",
|
|
1440
|
+
search != null ? search : "",
|
|
1441
|
+
matchStatus != null ? matchStatus : "",
|
|
1442
|
+
status != null ? status : "",
|
|
1443
|
+
(_c = categoryIds == null ? void 0 : categoryIds.join(",")) != null ? _c : "",
|
|
1444
|
+
limit,
|
|
1445
|
+
sortBy != null ? sortBy : "",
|
|
1446
|
+
sortDir != null ? sortDir : ""
|
|
1447
|
+
],
|
|
1448
|
+
queryFn: (_0) => __async(null, [_0], function* ({ pageParam }) {
|
|
1449
|
+
if (!client) {
|
|
1450
|
+
throw new Error("useVenueMarkets must be used within an <AggProvider>");
|
|
1451
|
+
}
|
|
1452
|
+
const res = yield client.getVenueMarkets({
|
|
1453
|
+
venue,
|
|
1454
|
+
venueEventId,
|
|
1455
|
+
search,
|
|
1456
|
+
matchStatus,
|
|
1457
|
+
status,
|
|
1458
|
+
categoryIds,
|
|
1459
|
+
limit,
|
|
1460
|
+
cursor: pageParam,
|
|
1461
|
+
sortBy,
|
|
1462
|
+
sortDir
|
|
1463
|
+
});
|
|
1464
|
+
return res;
|
|
1465
|
+
}),
|
|
1466
|
+
initialPageParam: void 0,
|
|
1467
|
+
getNextPageParam: (lastPage) => {
|
|
1468
|
+
var _a2;
|
|
1469
|
+
if (!lastPage.hasMore) return void 0;
|
|
1470
|
+
return (_a2 = lastPage.nextCursor) != null ? _a2 : void 0;
|
|
1471
|
+
},
|
|
1472
|
+
enabled: enabled && !!client
|
|
1473
|
+
},
|
|
1474
|
+
queryClient != null ? queryClient : fallbackQueryClient
|
|
1475
|
+
);
|
|
1476
|
+
const markets = (_e = (_d = query.data) == null ? void 0 : _d.pages.flatMap((page) => page.data)) != null ? _e : [];
|
|
1477
|
+
const hasNextPage = !!query.hasNextPage;
|
|
1478
|
+
return __spreadProps(__spreadValues({}, query), {
|
|
1479
|
+
markets,
|
|
1480
|
+
hasNextPage
|
|
1481
|
+
});
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
// src/use-enriched-venue-event.ts
|
|
1485
|
+
function mergeEventWithFullMarkets(event, fullMarkets) {
|
|
1486
|
+
if (fullMarkets.length === 0) return event;
|
|
1487
|
+
const fullById = new Map(fullMarkets.map((m) => [m.id, m]));
|
|
1488
|
+
const mergedMarkets = event.venueMarkets.map((minimal) => {
|
|
1489
|
+
var _a;
|
|
1490
|
+
return (_a = fullById.get(minimal.id)) != null ? _a : minimal;
|
|
1491
|
+
});
|
|
1492
|
+
return __spreadProps(__spreadValues({}, event), { venueMarkets: mergedMarkets });
|
|
1493
|
+
}
|
|
1494
|
+
function useEnrichedVenueEvent(options) {
|
|
1495
|
+
var _b;
|
|
1496
|
+
const _a = useVenueEvent(options), { event, isLoading, error } = _a, rest = __objRest(_a, ["event", "isLoading", "error"]);
|
|
1497
|
+
const { markets, isLoading: isEnriching } = useVenueMarkets({
|
|
1498
|
+
venueEventId: options.eventId,
|
|
1499
|
+
enabled: ((_b = options.enabled) != null ? _b : true) && !!event,
|
|
1500
|
+
status: "open" /* open */,
|
|
1501
|
+
sortBy: "yesPrice",
|
|
1502
|
+
sortDir: "desc"
|
|
1503
|
+
});
|
|
1504
|
+
const enrichedEvent = useMemo8(() => {
|
|
1505
|
+
if (!event) return void 0;
|
|
1506
|
+
if (markets.length === 0) return event;
|
|
1507
|
+
return mergeEventWithFullMarkets(event, markets);
|
|
1508
|
+
}, [event, markets]);
|
|
1509
|
+
return __spreadProps(__spreadValues({}, rest), {
|
|
1510
|
+
event: enrichedEvent,
|
|
1511
|
+
isLoading,
|
|
1512
|
+
isEnriching,
|
|
1513
|
+
error
|
|
1514
|
+
});
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1517
|
+
// src/use-venue-events.ts
|
|
1518
|
+
import {
|
|
1519
|
+
QueryClient as QueryClient3,
|
|
1520
|
+
QueryClientContext as QueryClientContext3,
|
|
1521
|
+
keepPreviousData as keepPreviousData6,
|
|
1522
|
+
useInfiniteQuery as useInfiniteQuery8
|
|
1523
|
+
} from "@tanstack/react-query";
|
|
1524
|
+
import { useContext as useContext4, useEffect as useEffect7, useMemo as useMemo9, useRef as useRef3, useState as useState6 } from "react";
|
|
1525
|
+
function useVenueEvents(options) {
|
|
1526
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
1527
|
+
const client = useContext4(AggClientContext);
|
|
1528
|
+
const queryClient = useContext4(QueryClientContext3);
|
|
1529
|
+
const [fallbackQueryClient] = useState6(() => new QueryClient3());
|
|
1530
|
+
const venues = options == null ? void 0 : options.venues;
|
|
1531
|
+
const search = options == null ? void 0 : options.search;
|
|
1532
|
+
const categoryIds = options == null ? void 0 : options.categoryIds;
|
|
1533
|
+
const matchStatus = (_a = options == null ? void 0 : options.matchStatus) != null ? _a : [];
|
|
1534
|
+
const enabled = (_b = options == null ? void 0 : options.enabled) != null ? _b : true;
|
|
1535
|
+
const limit = (_c = options == null ? void 0 : options.limit) != null ? _c : 20;
|
|
1536
|
+
const status = options == null ? void 0 : options.status;
|
|
1537
|
+
const sortBy = options == null ? void 0 : options.sortBy;
|
|
1538
|
+
const sortDir = options == null ? void 0 : options.sortDir;
|
|
1539
|
+
const queryKeyScope = (_d = options == null ? void 0 : options.queryKeyScope) != null ? _d : "events";
|
|
1540
|
+
const minYesPrice = options == null ? void 0 : options.minYesPrice;
|
|
1541
|
+
const maxYesPrice = options == null ? void 0 : options.maxYesPrice;
|
|
1542
|
+
const endDateFrom = options == null ? void 0 : options.endDateFrom;
|
|
1543
|
+
const initialPages = options == null ? void 0 : options.initialPages;
|
|
1544
|
+
useEffect7(() => {
|
|
1545
|
+
if (queryClient) return void 0;
|
|
1546
|
+
fallbackQueryClient.mount();
|
|
1547
|
+
return () => {
|
|
1548
|
+
fallbackQueryClient.unmount();
|
|
1549
|
+
};
|
|
1550
|
+
}, [fallbackQueryClient, queryClient]);
|
|
1551
|
+
if (enabled && !client) {
|
|
1552
|
+
throw new Error("useVenueEvents must be used within an <AggProvider>");
|
|
1553
|
+
}
|
|
1554
|
+
const query = useInfiniteQuery8(
|
|
1555
|
+
{
|
|
1556
|
+
queryKey: [
|
|
1557
|
+
queryKeyScope,
|
|
1558
|
+
venues != null ? venues : [],
|
|
1559
|
+
search != null ? search : "",
|
|
1560
|
+
(_e = categoryIds == null ? void 0 : categoryIds.join(",")) != null ? _e : "",
|
|
1561
|
+
(_f = matchStatus == null ? void 0 : matchStatus.join(",")) != null ? _f : "",
|
|
1562
|
+
(_g = status == null ? void 0 : status.join(",")) != null ? _g : "",
|
|
1563
|
+
sortBy != null ? sortBy : "",
|
|
1564
|
+
sortDir != null ? sortDir : "",
|
|
1565
|
+
minYesPrice != null ? minYesPrice : "",
|
|
1566
|
+
maxYesPrice != null ? maxYesPrice : "",
|
|
1567
|
+
endDateFrom != null ? endDateFrom : "",
|
|
1568
|
+
limit
|
|
1569
|
+
],
|
|
1570
|
+
queryFn: (_0) => __async(null, [_0], function* ({ pageParam }) {
|
|
1571
|
+
if (!client) {
|
|
1572
|
+
throw new Error("useVenueEvents must be used within an <AggProvider>");
|
|
1573
|
+
}
|
|
1574
|
+
const res = yield client.getVenueEvents({
|
|
1575
|
+
venues,
|
|
1576
|
+
search,
|
|
1577
|
+
categoryIds,
|
|
1578
|
+
matchStatus,
|
|
1579
|
+
status,
|
|
1580
|
+
sortBy,
|
|
1581
|
+
sortDir,
|
|
1582
|
+
limit,
|
|
1583
|
+
minYesPrice,
|
|
1584
|
+
maxYesPrice,
|
|
1585
|
+
endDateFrom,
|
|
1586
|
+
cursor: pageParam
|
|
1587
|
+
});
|
|
1588
|
+
return res;
|
|
1589
|
+
}),
|
|
1590
|
+
initialPageParam: void 0,
|
|
1591
|
+
getNextPageParam: (lastPage) => {
|
|
1592
|
+
var _a2;
|
|
1593
|
+
if (!lastPage.hasMore) return void 0;
|
|
1594
|
+
return (_a2 = lastPage.nextCursor) != null ? _a2 : void 0;
|
|
1595
|
+
},
|
|
1596
|
+
placeholderData: keepPreviousData6,
|
|
1597
|
+
enabled: enabled && !!client
|
|
1598
|
+
},
|
|
1599
|
+
queryClient != null ? queryClient : fallbackQueryClient
|
|
1600
|
+
);
|
|
1601
|
+
const prefetchedRef = useRef3(false);
|
|
1602
|
+
useEffect7(() => {
|
|
1603
|
+
var _a2, _b2;
|
|
1604
|
+
if (prefetchedRef.current) return;
|
|
1605
|
+
if (!initialPages || initialPages <= 1) return;
|
|
1606
|
+
if (query.isLoading) return;
|
|
1607
|
+
const pagesLoaded = (_b2 = (_a2 = query.data) == null ? void 0 : _a2.pages.length) != null ? _b2 : 0;
|
|
1608
|
+
if (pagesLoaded >= initialPages || !query.hasNextPage) {
|
|
1609
|
+
prefetchedRef.current = true;
|
|
1610
|
+
return;
|
|
1611
|
+
}
|
|
1612
|
+
void query.fetchNextPage();
|
|
1613
|
+
}, [
|
|
1614
|
+
initialPages,
|
|
1615
|
+
query.isLoading,
|
|
1616
|
+
(_h = query.data) == null ? void 0 : _h.pages.length,
|
|
1617
|
+
query.hasNextPage,
|
|
1618
|
+
query.fetchNextPage
|
|
1619
|
+
]);
|
|
1620
|
+
const events = useMemo9(
|
|
1621
|
+
() => {
|
|
1622
|
+
var _a2, _b2;
|
|
1623
|
+
return (_b2 = (_a2 = query.data) == null ? void 0 : _a2.pages.flatMap((page) => page.data)) != null ? _b2 : [];
|
|
1624
|
+
},
|
|
1625
|
+
[(_i = query.data) == null ? void 0 : _i.pages]
|
|
1626
|
+
);
|
|
1627
|
+
const hasNextPage = !!query.hasNextPage;
|
|
1628
|
+
const loadedPageCount = (_k = (_j = query.data) == null ? void 0 : _j.pages.length) != null ? _k : 0;
|
|
1629
|
+
return __spreadProps(__spreadValues({}, query), {
|
|
1630
|
+
events,
|
|
1631
|
+
hasNextPage,
|
|
1632
|
+
loadedPageCount,
|
|
1633
|
+
isPlaceholderData: query.isPlaceholderData
|
|
1634
|
+
});
|
|
1635
|
+
}
|
|
1636
|
+
|
|
1637
|
+
// src/use-venue-market-midpoints.ts
|
|
1638
|
+
import { keepPreviousData as keepPreviousData7, useQuery as useQuery8 } from "@tanstack/react-query";
|
|
1639
|
+
var MAX_VENUE_MARKET_IDS_PER_REQUEST = 200;
|
|
1640
|
+
var normalizeVenueMarketIds2 = (venueMarketIds) => {
|
|
1641
|
+
return [
|
|
1642
|
+
...new Set(venueMarketIds.map((venueMarketId) => venueMarketId.trim()).filter(Boolean))
|
|
1643
|
+
].sort((left, right) => left.localeCompare(right));
|
|
1644
|
+
};
|
|
1645
|
+
var chunkVenueMarketIds = (venueMarketIds) => {
|
|
1646
|
+
if (venueMarketIds.length === 0) return [];
|
|
1647
|
+
const chunks = [];
|
|
1648
|
+
for (let index = 0; index < venueMarketIds.length; index += MAX_VENUE_MARKET_IDS_PER_REQUEST) {
|
|
1649
|
+
chunks.push(venueMarketIds.slice(index, index + MAX_VENUE_MARKET_IDS_PER_REQUEST));
|
|
1650
|
+
}
|
|
1651
|
+
return chunks;
|
|
1652
|
+
};
|
|
1653
|
+
var mergeMidpointResponses = (responses) => {
|
|
1654
|
+
return {
|
|
1655
|
+
data: responses.flatMap((response) => response.data)
|
|
1656
|
+
};
|
|
1657
|
+
};
|
|
1658
|
+
var mapMidpointsByVenueMarketId = (rows) => {
|
|
1659
|
+
const mappedMidpoints = /* @__PURE__ */ new Map();
|
|
1660
|
+
rows.forEach((row) => {
|
|
1661
|
+
mappedMidpoints.set(row.venueMarketId, row.midpoint);
|
|
1662
|
+
row.matched.forEach((matchedRow) => {
|
|
1663
|
+
if (mappedMidpoints.has(matchedRow.venueMarketId)) return;
|
|
1664
|
+
mappedMidpoints.set(matchedRow.venueMarketId, matchedRow.midpoint);
|
|
1665
|
+
});
|
|
1666
|
+
});
|
|
1667
|
+
return mappedMidpoints;
|
|
1668
|
+
};
|
|
1669
|
+
function useVenueMarketMidpoints(options) {
|
|
1670
|
+
var _a, _b, _c;
|
|
1671
|
+
const client = useAggClient();
|
|
1672
|
+
const enabled = (_a = options.enabled) != null ? _a : true;
|
|
1673
|
+
const requestedVenueMarketIds = normalizeVenueMarketIds2(options.venueMarketIds);
|
|
1674
|
+
const query = useQuery8({
|
|
1675
|
+
queryKey: requestedVenueMarketIds.length ? ["venue-market-midpoints", requestedVenueMarketIds] : ["venue-market-midpoints", "__disabled__"],
|
|
1676
|
+
queryFn: (_0) => __async(null, [_0], function* ({ signal }) {
|
|
1677
|
+
const venueMarketIdChunks = chunkVenueMarketIds(requestedVenueMarketIds);
|
|
1678
|
+
if (venueMarketIdChunks.length === 0) {
|
|
1679
|
+
return { data: [] };
|
|
1680
|
+
}
|
|
1681
|
+
const chunkResponses = yield Promise.all(
|
|
1682
|
+
venueMarketIdChunks.map((venueMarketIds) => {
|
|
1683
|
+
return client.getMidpoints({ venueMarketIds }, { signal });
|
|
1684
|
+
})
|
|
1685
|
+
);
|
|
1686
|
+
return mergeMidpointResponses(chunkResponses);
|
|
1687
|
+
}),
|
|
1688
|
+
enabled: enabled && requestedVenueMarketIds.length > 0,
|
|
1689
|
+
staleTime: 1e4,
|
|
1690
|
+
gcTime: 5 * 6e4,
|
|
1691
|
+
refetchOnWindowFocus: false,
|
|
1692
|
+
retry: 1,
|
|
1693
|
+
placeholderData: keepPreviousData7
|
|
1694
|
+
});
|
|
1695
|
+
const midpointRows = (_c = (_b = query.data) == null ? void 0 : _b.data) != null ? _c : [];
|
|
1696
|
+
const midpointsByVenueMarketId = mapMidpointsByVenueMarketId(midpointRows);
|
|
1697
|
+
return __spreadProps(__spreadValues({}, query), {
|
|
1698
|
+
midpointRows,
|
|
1699
|
+
midpointsByVenueMarketId,
|
|
1700
|
+
requestedVenueMarketIds
|
|
1701
|
+
});
|
|
1702
|
+
}
|
|
1703
|
+
|
|
1704
|
+
// src/utils/compute-price-gaps.ts
|
|
1705
|
+
var MIN_PRICE_GAP_PCT = 3;
|
|
1706
|
+
function computePriceGaps(input) {
|
|
1707
|
+
var _a;
|
|
1708
|
+
const { markets, midpointsByVenueMarketId } = input;
|
|
1709
|
+
const result = /* @__PURE__ */ new Map();
|
|
1710
|
+
for (const market of markets) {
|
|
1711
|
+
const ownMidpoint = midpointsByVenueMarketId.get(market.id);
|
|
1712
|
+
if (ownMidpoint == null || ownMidpoint <= 0) continue;
|
|
1713
|
+
const siblings = (_a = market.matchedVenueMarkets) != null ? _a : [];
|
|
1714
|
+
if (siblings.length === 0) continue;
|
|
1715
|
+
let maxGap = 0;
|
|
1716
|
+
for (const sibling of siblings) {
|
|
1717
|
+
const siblingMidpoint = midpointsByVenueMarketId.get(sibling.id);
|
|
1718
|
+
if (siblingMidpoint == null || siblingMidpoint <= 0) continue;
|
|
1719
|
+
const gap = Math.abs(ownMidpoint - siblingMidpoint) / ownMidpoint * 100;
|
|
1720
|
+
if (gap > maxGap) maxGap = gap;
|
|
1721
|
+
}
|
|
1722
|
+
if (maxGap >= MIN_PRICE_GAP_PCT) result.set(market.id, maxGap);
|
|
1723
|
+
}
|
|
1724
|
+
return result;
|
|
1725
|
+
}
|
|
1726
|
+
|
|
1727
|
+
// src/use-viewport-midpoints.ts
|
|
1728
|
+
import { useEffect as useEffect8, useMemo as useMemo10, useRef as useRef4, useState as useState7 } from "react";
|
|
1729
|
+
var resolveUncachedVisibleMarketIds = (visibleMarkets, cache, inFlightIds) => {
|
|
1730
|
+
const idsToFetch = [];
|
|
1731
|
+
for (const market of visibleMarkets) {
|
|
1732
|
+
if (inFlightIds.has(market.id)) continue;
|
|
1733
|
+
if (cache.has(market.id)) continue;
|
|
1734
|
+
idsToFetch.push(market.id);
|
|
1735
|
+
}
|
|
1736
|
+
return idsToFetch;
|
|
1737
|
+
};
|
|
1738
|
+
var buildCachedMidpointEntries = (requestedVenueMarketIds, rows) => {
|
|
1739
|
+
var _a, _b;
|
|
1740
|
+
const rowsByVenueMarketId = new Map(rows.map((item) => [item.venueMarketId, item]));
|
|
1741
|
+
const nextCacheEntries = /* @__PURE__ */ new Map();
|
|
1742
|
+
for (const venueMarketId of requestedVenueMarketIds) {
|
|
1743
|
+
const item = rowsByVenueMarketId.get(venueMarketId);
|
|
1744
|
+
nextCacheEntries.set(venueMarketId, {
|
|
1745
|
+
midpoint: (_a = item == null ? void 0 : item.midpoint) != null ? _a : null,
|
|
1746
|
+
matched: ((_b = item == null ? void 0 : item.matched) != null ? _b : []).map((matched) => {
|
|
1747
|
+
var _a2;
|
|
1748
|
+
return {
|
|
1749
|
+
venueMarketId: matched.venueMarketId,
|
|
1750
|
+
midpoint: (_a2 = matched.midpoint) != null ? _a2 : null
|
|
1751
|
+
};
|
|
1752
|
+
})
|
|
1753
|
+
});
|
|
1754
|
+
}
|
|
1755
|
+
return nextCacheEntries;
|
|
1756
|
+
};
|
|
1757
|
+
function useViewportMidpoints(visibleMarkets) {
|
|
1758
|
+
const client = useAggClient();
|
|
1759
|
+
const [cache, setCache] = useState7(() => /* @__PURE__ */ new Map());
|
|
1760
|
+
const inFlightRef = useRef4(/* @__PURE__ */ new Set());
|
|
1761
|
+
const visibleRef = useRef4(visibleMarkets);
|
|
1762
|
+
visibleRef.current = visibleMarkets;
|
|
1763
|
+
const visibleFp = useMemo10(
|
|
1764
|
+
() => [...new Set(visibleMarkets.map((m) => m.id))].sort().join("|"),
|
|
1765
|
+
[visibleMarkets]
|
|
1766
|
+
);
|
|
1767
|
+
useEffect8(() => {
|
|
1768
|
+
const toFetch = resolveUncachedVisibleMarketIds(visibleRef.current, cache, inFlightRef.current);
|
|
1769
|
+
if (!toFetch.length) return;
|
|
1770
|
+
let cancelled = false;
|
|
1771
|
+
for (const id of toFetch) inFlightRef.current.add(id);
|
|
1772
|
+
client.getMidpoints(toFetch).then((resp) => {
|
|
1773
|
+
var _a;
|
|
1774
|
+
if (cancelled) return;
|
|
1775
|
+
const nextCacheEntries = buildCachedMidpointEntries(toFetch, (_a = resp.data) != null ? _a : []);
|
|
1776
|
+
setCache((prev) => {
|
|
1777
|
+
const next = new Map(prev);
|
|
1778
|
+
for (const [venueMarketId, entry] of nextCacheEntries) {
|
|
1779
|
+
next.set(venueMarketId, entry);
|
|
1780
|
+
}
|
|
1781
|
+
return next;
|
|
1782
|
+
});
|
|
1783
|
+
}).catch(() => {
|
|
1784
|
+
}).finally(() => {
|
|
1785
|
+
for (const id of toFetch) inFlightRef.current.delete(id);
|
|
1786
|
+
});
|
|
1787
|
+
return () => {
|
|
1788
|
+
cancelled = true;
|
|
1789
|
+
};
|
|
1790
|
+
}, [visibleFp, cache]);
|
|
1791
|
+
const prices = useMemo10(() => {
|
|
1792
|
+
var _a;
|
|
1793
|
+
const map = /* @__PURE__ */ new Map();
|
|
1794
|
+
for (const market of visibleMarkets) {
|
|
1795
|
+
const entry = cache.get(market.id);
|
|
1796
|
+
if (!entry) continue;
|
|
1797
|
+
const candidates = [];
|
|
1798
|
+
if (entry.midpoint != null) candidates.push(entry.midpoint);
|
|
1799
|
+
for (const m of entry.matched) if (m.midpoint != null) candidates.push(m.midpoint);
|
|
1800
|
+
if (!candidates.length) continue;
|
|
1801
|
+
const mid = Math.max(...candidates);
|
|
1802
|
+
for (const outcome of market.venueMarketOutcomes) {
|
|
1803
|
+
const isYes = ((_a = outcome.label) == null ? void 0 : _a.toLowerCase()) === "yes";
|
|
1804
|
+
map.set(outcome.id, isYes ? mid : 1 - mid);
|
|
1805
|
+
}
|
|
1806
|
+
}
|
|
1807
|
+
return map;
|
|
1808
|
+
}, [cache, visibleMarkets]);
|
|
1809
|
+
return { prices };
|
|
1810
|
+
}
|
|
1811
|
+
|
|
1812
|
+
// src/use-visible-ids.ts
|
|
1813
|
+
import { useCallback as useCallback5, useEffect as useEffect9, useRef as useRef5, useState as useState8 } from "react";
|
|
1814
|
+
function useVisibleIds(options = {}) {
|
|
1815
|
+
const { rootMargin = "0px", threshold = 0 } = options;
|
|
1816
|
+
const [visibleIds, setVisibleIds] = useState8(() => /* @__PURE__ */ new Set());
|
|
1817
|
+
const observerRef = useRef5(null);
|
|
1818
|
+
const elementsRef = useRef5(/* @__PURE__ */ new Map());
|
|
1819
|
+
const elementIdRef = useRef5(/* @__PURE__ */ new WeakMap());
|
|
1820
|
+
const callbackRefsRef = useRef5(/* @__PURE__ */ new Map());
|
|
1821
|
+
useEffect9(() => {
|
|
1822
|
+
if (typeof IntersectionObserver === "undefined") return;
|
|
1823
|
+
const observer = new IntersectionObserver(
|
|
1824
|
+
(entries) => {
|
|
1825
|
+
setVisibleIds((prev) => {
|
|
1826
|
+
let changed = false;
|
|
1827
|
+
const next = new Set(prev);
|
|
1828
|
+
for (const entry of entries) {
|
|
1829
|
+
const id = elementIdRef.current.get(entry.target);
|
|
1830
|
+
if (!id) continue;
|
|
1831
|
+
if (entry.isIntersecting) {
|
|
1832
|
+
if (!next.has(id)) {
|
|
1833
|
+
next.add(id);
|
|
1834
|
+
changed = true;
|
|
1835
|
+
}
|
|
1836
|
+
} else if (next.has(id)) {
|
|
1837
|
+
next.delete(id);
|
|
1838
|
+
changed = true;
|
|
1839
|
+
}
|
|
1840
|
+
}
|
|
1841
|
+
return changed ? next : prev;
|
|
1842
|
+
});
|
|
1843
|
+
},
|
|
1844
|
+
{ rootMargin, threshold }
|
|
1845
|
+
);
|
|
1846
|
+
observerRef.current = observer;
|
|
1847
|
+
for (const el of elementsRef.current.values()) observer.observe(el);
|
|
1848
|
+
return () => {
|
|
1849
|
+
observer.disconnect();
|
|
1850
|
+
observerRef.current = null;
|
|
1851
|
+
};
|
|
1852
|
+
}, [rootMargin, threshold]);
|
|
1853
|
+
const register = useCallback5((id) => {
|
|
1854
|
+
const existing = callbackRefsRef.current.get(id);
|
|
1855
|
+
if (existing) return existing;
|
|
1856
|
+
const callback = (el) => {
|
|
1857
|
+
var _a, _b;
|
|
1858
|
+
const prev = elementsRef.current.get(id);
|
|
1859
|
+
if (prev === el) return;
|
|
1860
|
+
if (prev) {
|
|
1861
|
+
(_a = observerRef.current) == null ? void 0 : _a.unobserve(prev);
|
|
1862
|
+
elementIdRef.current.delete(prev);
|
|
1863
|
+
elementsRef.current.delete(id);
|
|
1864
|
+
setVisibleIds((curr) => {
|
|
1865
|
+
if (!curr.has(id)) return curr;
|
|
1866
|
+
const next = new Set(curr);
|
|
1867
|
+
next.delete(id);
|
|
1868
|
+
return next;
|
|
1869
|
+
});
|
|
1870
|
+
}
|
|
1871
|
+
if (el) {
|
|
1872
|
+
elementsRef.current.set(id, el);
|
|
1873
|
+
elementIdRef.current.set(el, id);
|
|
1874
|
+
(_b = observerRef.current) == null ? void 0 : _b.observe(el);
|
|
1875
|
+
} else {
|
|
1876
|
+
callbackRefsRef.current.delete(id);
|
|
1877
|
+
}
|
|
1878
|
+
};
|
|
1879
|
+
callbackRefsRef.current.set(id, callback);
|
|
1880
|
+
return callback;
|
|
1881
|
+
}, []);
|
|
1882
|
+
return { visibleIds, register };
|
|
1883
|
+
}
|
|
1884
|
+
|
|
1885
|
+
// src/use-app-config.ts
|
|
1886
|
+
import { useQuery as useQuery9 } from "@tanstack/react-query";
|
|
1887
|
+
var FIVE_MINUTES = 5 * 60 * 1e3;
|
|
1888
|
+
function useAppConfig() {
|
|
1889
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1890
|
+
const client = useAggClient();
|
|
1891
|
+
const query = useQuery9({
|
|
1892
|
+
queryKey: ["agg", "app-config"],
|
|
1893
|
+
queryFn: () => client.getAppConfig(),
|
|
1894
|
+
staleTime: FIVE_MINUTES
|
|
1895
|
+
});
|
|
1896
|
+
return {
|
|
1897
|
+
disabledVenues: (_b = (_a = query.data) == null ? void 0 : _a.disabledVenues) != null ? _b : [],
|
|
1898
|
+
disabledCategoryPresets: (_d = (_c = query.data) == null ? void 0 : _c.disabledCategoryPresets) != null ? _d : [],
|
|
1899
|
+
earlyAccessEnabled: (_f = (_e = query.data) == null ? void 0 : _e.earlyAccessEnabled) != null ? _f : false,
|
|
1900
|
+
isLoading: query.isLoading,
|
|
1901
|
+
error: query.error
|
|
1902
|
+
};
|
|
1903
|
+
}
|
|
1904
|
+
export {
|
|
1905
|
+
AUTH_CHOOSER_OPEN_EVENT,
|
|
1906
|
+
AggBalanceProvider,
|
|
1907
|
+
AggProvider,
|
|
1908
|
+
AggProvider as AggSdkProvider,
|
|
1909
|
+
AggUiProvider,
|
|
1910
|
+
CHART_TIME_RANGES,
|
|
1911
|
+
CONFIRMED_MATCH_STATUSES,
|
|
1912
|
+
DEFAULT_AGG_ROOT_CLASS_NAME,
|
|
1913
|
+
EventListStateProvider,
|
|
1914
|
+
MarketStatus,
|
|
1915
|
+
MatchStatus,
|
|
1916
|
+
MatchType,
|
|
1917
|
+
QueryClient4 as QueryClient,
|
|
1918
|
+
QueryClientProvider,
|
|
1919
|
+
TurnstileChallengeError,
|
|
1920
|
+
Venue,
|
|
1921
|
+
computeClosedPositionTotals,
|
|
1922
|
+
computePriceGaps,
|
|
1923
|
+
defaultAggUiConfig,
|
|
1924
|
+
defaultAggUiConfig as defaultSdkUiConfig,
|
|
1925
|
+
executionKeys,
|
|
1926
|
+
findLivePriceById,
|
|
1927
|
+
getBuilder,
|
|
1928
|
+
getDepositAddress,
|
|
1929
|
+
getOrCreateBuilder,
|
|
1930
|
+
getWalletAddressFromUserProfile,
|
|
1931
|
+
invalidateBalanceQueries,
|
|
1932
|
+
invalidatePositionQueries,
|
|
1933
|
+
optimizedImageUrl,
|
|
1934
|
+
parseEmail,
|
|
1935
|
+
parseEmailStrict,
|
|
1936
|
+
requestAggAuthChooserOpen,
|
|
1937
|
+
resolveAggUiLabels,
|
|
1938
|
+
resolveDefaultMarket as resolveDefaultTradingMarket,
|
|
1939
|
+
resolveEventTradingState,
|
|
1940
|
+
resolveMarketTradingState,
|
|
1941
|
+
resolveMarketWinningOutcome,
|
|
1942
|
+
resolveOrderEligibility,
|
|
1943
|
+
resolveTradingStateKind,
|
|
1944
|
+
sortVenues,
|
|
1945
|
+
timeRangeToInterval,
|
|
1946
|
+
tradingReducer,
|
|
1947
|
+
useAggAuth,
|
|
1948
|
+
useAggAuthContext,
|
|
1949
|
+
useAggAuthState,
|
|
1950
|
+
useAggBalance,
|
|
1951
|
+
useAggBalanceContext,
|
|
1952
|
+
useAggBalanceState,
|
|
1953
|
+
useAggClient,
|
|
1954
|
+
useAggLabels,
|
|
1955
|
+
useAggUiConfig,
|
|
1956
|
+
useAggWebSocket,
|
|
1957
|
+
useAppConfig,
|
|
1958
|
+
useCategories,
|
|
1959
|
+
useDebouncedValue,
|
|
1960
|
+
useDepositAddresses,
|
|
1961
|
+
useEnrichedVenueEvent,
|
|
1962
|
+
useEventListState,
|
|
1963
|
+
useEventOrderbookData,
|
|
1964
|
+
useEventTradingContext,
|
|
1965
|
+
useExecuteManaged,
|
|
1966
|
+
useExecutionOrders,
|
|
1967
|
+
useExecutionPositions,
|
|
1968
|
+
useExecutionProgress,
|
|
1969
|
+
useExternalId,
|
|
1970
|
+
useGeoBlock,
|
|
1971
|
+
useLabels,
|
|
1972
|
+
useLinkAccount,
|
|
1973
|
+
useLiveCandleOverlay,
|
|
1974
|
+
useLiveCandles,
|
|
1975
|
+
useLiveMarket,
|
|
1976
|
+
useLiveMarketStores,
|
|
1977
|
+
useLiveOutcomePrices,
|
|
1978
|
+
useLiveTrades,
|
|
1979
|
+
useManagedBalances,
|
|
1980
|
+
useMarketChart,
|
|
1981
|
+
useMarketOrderbook,
|
|
1982
|
+
useMidpoints,
|
|
1983
|
+
useOnBalanceUpdate,
|
|
1984
|
+
useOnOrderSubmitted,
|
|
1985
|
+
useOnRedeemEvent,
|
|
1986
|
+
useOrderBook,
|
|
1987
|
+
useOrderbookQuote,
|
|
1988
|
+
useOrders,
|
|
1989
|
+
usePositions,
|
|
1990
|
+
useQueryClient2 as useQueryClient,
|
|
1991
|
+
useQuoteManaged,
|
|
1992
|
+
useRampQuotes,
|
|
1993
|
+
useRampSession,
|
|
1994
|
+
useRedeem,
|
|
1995
|
+
useRedeemEligibleCount,
|
|
1996
|
+
useSdkLabels,
|
|
1997
|
+
useSdkUiConfig,
|
|
1998
|
+
useSearch,
|
|
1999
|
+
useSmartRoute,
|
|
2000
|
+
useSyncBalances,
|
|
2001
|
+
useUserActivity,
|
|
2002
|
+
useUserHoldings,
|
|
2003
|
+
useVenueEvent,
|
|
2004
|
+
useVenueEvents,
|
|
2005
|
+
useVenueMarketMidpoints,
|
|
2006
|
+
useVenueMarkets,
|
|
2007
|
+
useViewportMidpoints,
|
|
2008
|
+
useVisibleIds,
|
|
2009
|
+
useWithdrawManaged
|
|
2010
|
+
};
|