@hyperix/hooks 0.2.4 → 0.2.6

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 CHANGED
@@ -46,7 +46,10 @@ When you need imperative websocket access outside React hooks, reuse the
46
46
  package singleton instead of creating a second socket connection.
47
47
 
48
48
  ```ts
49
- import { wsClient, wsTransport } from "@hyperix/hooks";
49
+ import { infoClient, wsClient, wsTransport } from "@hyperix/hooks";
50
+
51
+ const meta = await infoClient.meta();
52
+ console.log(meta.universe.length);
50
53
 
51
54
  const subscription = await wsClient.allMids((event) => {
52
55
  console.log(event);
@@ -1,3 +1,4 @@
1
+ import { type UseInfiniteQueryOptions, type UseInfiniteQueryResult } from "@tanstack/react-query";
1
2
  import { type UseUserFillsOptions, type UserFill } from "./use-user-fills.js";
2
3
  export type TradeHistory = UserFill & {
3
4
  displayCoin: string;
@@ -12,9 +13,35 @@ export type TradeHistoryData = {
12
13
  user: `0x${string}`;
13
14
  fills: TradeHistory[];
14
15
  };
16
+ export type TradeHistoryPage = TradeHistoryData & {
17
+ startTime: number;
18
+ endTime: number;
19
+ };
20
+ export type InfiniteTradeHistoryData = {
21
+ user: `0x${string}`;
22
+ fills: TradeHistory[];
23
+ pages: TradeHistoryPage[];
24
+ };
25
+ export type InfiniteTradeHistoryPageParam = {
26
+ startTime: number;
27
+ endTime: number;
28
+ };
29
+ export type UseInfiniteTradeHistoryOptions = Omit<UseInfiniteQueryOptions<TradeHistoryPage, Error, InfiniteTradeHistoryData, [
30
+ "infinite-trade-history",
31
+ `0x${string}`,
32
+ boolean,
33
+ number,
34
+ number | undefined
35
+ ], InfiniteTradeHistoryPageParam>, "queryKey" | "queryFn" | "initialPageParam" | "getNextPageParam" | "select"> & {
36
+ aggregateByTime?: boolean;
37
+ endTime?: number;
38
+ pageDurationMs?: number;
39
+ realtime?: boolean;
40
+ };
15
41
  export declare function useTradeHistory(user: `0x${string}`, options?: UseUserFillsOptions): {
16
42
  data: TradeHistoryData | undefined;
17
43
  ready: boolean;
18
44
  loading: boolean;
19
45
  error?: string;
20
46
  };
47
+ export declare function useInfiniteTradeHistory(user: `0x${string}`, options?: UseInfiniteTradeHistoryOptions): UseInfiniteQueryResult<InfiniteTradeHistoryData, Error>;
@@ -1,7 +1,13 @@
1
+ import { useInfiniteQuery, } from "@tanstack/react-query";
1
2
  import Decimal from "decimal.js";
2
3
  import { useMemo } from "react";
4
+ import { infoClient } from "./config/hl.js";
3
5
  import { useSymbolConverter } from "./use-symbol-converter.js";
4
6
  import { useUserFills, } from "./use-user-fills.js";
7
+ const DEFAULT_TRADE_HISTORY_PAGE_DURATION_MS = 7 * 24 * 60 * 60 * 1000;
8
+ function getFillKey(fill) {
9
+ return `${fill.hash}-${fill.tid}-${fill.time}`;
10
+ }
5
11
  function formatTradeHistoryFill(fill, spotPair) {
6
12
  const price = new Decimal(fill.px);
7
13
  if (!spotPair) {
@@ -37,6 +43,26 @@ function formatTradeHistoryFill(fill, spotPair) {
37
43
  pnlCurrency: quoteCoin,
38
44
  };
39
45
  }
46
+ function sortTradeHistory(fills) {
47
+ return [...fills].sort((a, b) => {
48
+ if (a.time !== b.time) {
49
+ return b.time - a.time;
50
+ }
51
+ return b.tid - a.tid;
52
+ });
53
+ }
54
+ function mergeTradeHistoryFills(pages, realtimeFills) {
55
+ const fillsByKey = new Map();
56
+ for (const page of pages) {
57
+ for (const fill of page.fills) {
58
+ fillsByKey.set(getFillKey(fill), fill);
59
+ }
60
+ }
61
+ for (const fill of realtimeFills) {
62
+ fillsByKey.set(getFillKey(fill), fill);
63
+ }
64
+ return sortTradeHistory([...fillsByKey.values()]);
65
+ }
40
66
  export function useTradeHistory(user, options = {}) {
41
67
  const userFillsState = useUserFills(user, options);
42
68
  const symbolConverter = useSymbolConverter();
@@ -48,7 +74,7 @@ export function useTradeHistory(user, options = {}) {
48
74
  ...userFillsState.data,
49
75
  fills: userFillsState.data.fills
50
76
  .map((fill) => formatTradeHistoryFill(fill, symbolConverter?.getSpotByPairId(fill.coin)))
51
- .reverse(),
77
+ .sort((a, b) => b.time - a.time),
52
78
  };
53
79
  }, [symbolConverter, userFillsState.data]);
54
80
  return {
@@ -56,3 +82,63 @@ export function useTradeHistory(user, options = {}) {
56
82
  data,
57
83
  };
58
84
  }
85
+ export function useInfiniteTradeHistory(user, options = {}) {
86
+ const { aggregateByTime = true, enabled: enabledOverride, endTime, pageDurationMs = DEFAULT_TRADE_HISTORY_PAGE_DURATION_MS, realtime = true, ...queryOptions } = options;
87
+ const enabled = enabledOverride ?? Boolean(user);
88
+ const symbolConverter = useSymbolConverter();
89
+ const realtimeState = useTradeHistory(user, {
90
+ aggregateByTime,
91
+ enabled: enabled && realtime,
92
+ });
93
+ return useInfiniteQuery({
94
+ queryKey: [
95
+ "infinite-trade-history",
96
+ user,
97
+ aggregateByTime,
98
+ pageDurationMs,
99
+ endTime,
100
+ ],
101
+ queryFn: async ({ pageParam }) => {
102
+ const fills = await infoClient.userFillsByTime({
103
+ user,
104
+ startTime: pageParam.startTime,
105
+ endTime: pageParam.endTime,
106
+ aggregateByTime,
107
+ });
108
+ return {
109
+ user,
110
+ startTime: pageParam.startTime,
111
+ endTime: pageParam.endTime,
112
+ fills: sortTradeHistory(fills.map((fill) => formatTradeHistoryFill(fill, symbolConverter?.getSpotByPairId(fill.coin)))),
113
+ };
114
+ },
115
+ initialPageParam: {
116
+ startTime: Math.max(0, (endTime ?? Date.now()) - pageDurationMs),
117
+ endTime: endTime ?? Date.now(),
118
+ },
119
+ getNextPageParam: (lastPage) => {
120
+ if (lastPage.startTime <= 0) {
121
+ return undefined;
122
+ }
123
+ const oldestFillTime = lastPage.fills.at(-1)?.time;
124
+ const nextEndTime = oldestFillTime !== undefined
125
+ ? oldestFillTime - 1
126
+ : lastPage.startTime - 1;
127
+ return {
128
+ startTime: Math.max(0, nextEndTime - pageDurationMs),
129
+ endTime: nextEndTime,
130
+ };
131
+ },
132
+ select: (data) => {
133
+ const realtimeFills = realtimeState.data?.fills ?? [];
134
+ return {
135
+ pages: data.pages,
136
+ pageParams: data.pageParams,
137
+ user,
138
+ fills: mergeTradeHistoryFills(data.pages, realtimeFills),
139
+ };
140
+ },
141
+ ...queryOptions,
142
+ enabled,
143
+ });
144
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyperix/hooks",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -14,9 +14,9 @@
14
14
  "typecheck": "tsc -p tsconfig.json --noEmit"
15
15
  },
16
16
  "dependencies": {
17
- "@tanstack/react-query": "^5.90.2",
18
17
  "@nktkas/hyperliquid": "^0.32.1",
19
- "@outofgas/react-stream": "^0.1.4",
18
+ "@outofgas/react-stream": "^0.1.5",
19
+ "@tanstack/react-query": "^5.90.2",
20
20
  "decimal.js": "^10.6.0",
21
21
  "react": "^19.1.1"
22
22
  },