@hyperix/hooks 0.2.0 → 0.2.1

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.
@@ -1,4 +1,13 @@
1
1
  import type { UseSubscribeState } from "@outofgas/react-stream";
2
2
  import { type AllDexsClearingHouseStateData, type UseAllDexsClearingHouseStateOptions } from "./use-all-dexs-clearing-house-state.js";
3
- export type Position = AllDexsClearingHouseStateData["clearinghouseStates"][number][1]["assetPositions"][number];
3
+ import type { OpenOrder } from "./use-open-orders.js";
4
+ export type RawPosition = AllDexsClearingHouseStateData["clearinghouseStates"][number][1]["assetPositions"][number];
5
+ export type Position = RawPosition & {
6
+ markPrice: number | undefined;
7
+ fundingSinceOpen: number;
8
+ side: "Long" | "Short" | "Flat";
9
+ takeProfitTriggerPx: string | undefined;
10
+ stopLossTriggerPx: string | undefined;
11
+ triggerOrders: OpenOrder[];
12
+ };
4
13
  export declare function usePositions(user: `0x${string}`, options?: UseAllDexsClearingHouseStateOptions): UseSubscribeState<Position[]>;
@@ -1,17 +1,96 @@
1
1
  import { useMemo } from "react";
2
+ import { useAllDexsAssetCtxs } from "./use-all-dexs-asset-ctxs.js";
2
3
  import { useAllDexsClearingHouseState, } from "./use-all-dexs-clearing-house-state.js";
4
+ import { useOpenOrders } from "./use-open-orders.js";
5
+ import { useSymbolConverter } from "./use-symbol-converter.js";
6
+ function getSide(size) {
7
+ const numericSize = Number(size);
8
+ if (numericSize > 0) {
9
+ return "Long";
10
+ }
11
+ if (numericSize < 0) {
12
+ return "Short";
13
+ }
14
+ return "Flat";
15
+ }
16
+ function getPerpMarkPrice(coin, assetCtxs, symbolConverter) {
17
+ if (!assetCtxs || !symbolConverter) {
18
+ return undefined;
19
+ }
20
+ const assetId = symbolConverter.getAssetId(coin);
21
+ if (assetId === undefined) {
22
+ return undefined;
23
+ }
24
+ const dex = coin.includes(":") ? (coin.split(":")[0] ?? "") : "";
25
+ const index = assetId % 10_000;
26
+ const ctxs = assetCtxs.ctxs.find(([ctxDex]) => ctxDex === dex)?.[1];
27
+ return ctxs?.[index] ? Number(ctxs[index].markPx) : undefined;
28
+ }
29
+ function getTriggerOrdersByCoin(orders) {
30
+ return orders.reduce((map, order) => {
31
+ if (!order.isTrigger || !order.triggerCondition) {
32
+ return map;
33
+ }
34
+ const current = map.get(order.coin) ?? [];
35
+ current.push(order);
36
+ map.set(order.coin, current);
37
+ return map;
38
+ }, new Map());
39
+ }
40
+ function getTpSl(orders) {
41
+ let takeProfitTriggerPx;
42
+ let stopLossTriggerPx;
43
+ for (const order of orders ?? []) {
44
+ if (order.orderType.includes("Take Profit")) {
45
+ takeProfitTriggerPx = order.triggerPx;
46
+ continue;
47
+ }
48
+ stopLossTriggerPx = order.triggerPx;
49
+ }
50
+ return {
51
+ takeProfitTriggerPx,
52
+ stopLossTriggerPx,
53
+ triggerOrders: orders ?? [],
54
+ };
55
+ }
3
56
  export function usePositions(user, options = {}) {
57
+ const symbolConverter = useSymbolConverter();
4
58
  const positionsState = useAllDexsClearingHouseState(user, options);
59
+ const assetCtxsState = useAllDexsAssetCtxs({ enabled: options.enabled });
60
+ const openOrdersState = useOpenOrders(user, { enabled: options.enabled });
5
61
  const data = useMemo(() => {
6
- return positionsState.data?.clearinghouseStates
62
+ const rawPositions = positionsState.data?.clearinghouseStates
7
63
  .flatMap(([, state]) => state.assetPositions)
8
64
  .sort((left, right) => Number(left.position.positionValue) <
9
65
  Number(right.position.positionValue)
10
66
  ? 1
11
67
  : -1);
12
- }, [positionsState.data]);
68
+ const triggerOrdersByCoin = getTriggerOrdersByCoin(openOrdersState.data?.orders ?? []);
69
+ return rawPositions?.map((positionRecord) => {
70
+ const position = positionRecord.position;
71
+ const tpSl = getTpSl(triggerOrdersByCoin.get(position.coin));
72
+ return {
73
+ ...positionRecord,
74
+ markPrice: getPerpMarkPrice(position.coin, assetCtxsState.data, symbolConverter),
75
+ fundingSinceOpen: -Number(position.cumFunding.sinceOpen),
76
+ side: getSide(position.szi),
77
+ ...tpSl,
78
+ };
79
+ });
80
+ }, [
81
+ positionsState.data,
82
+ openOrdersState.data,
83
+ assetCtxsState.data,
84
+ symbolConverter,
85
+ ]);
13
86
  return {
14
87
  ...positionsState,
88
+ loading: positionsState.loading || assetCtxsState.loading || openOrdersState.loading,
89
+ ready: positionsState.ready &&
90
+ assetCtxsState.ready &&
91
+ openOrdersState.ready &&
92
+ symbolConverter !== null,
93
+ error: positionsState.error ?? assetCtxsState.error ?? openOrdersState.error,
15
94
  data,
16
95
  };
17
96
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyperix/hooks",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",