@pear-protocol/exchanges-sdk 0.3.0 → 0.5.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.
Files changed (57) hide show
  1. package/README.md +78 -12
  2. package/dist/client/binance/rest.js +4 -3
  3. package/dist/client/bybit/rest.js +2 -1
  4. package/dist/client/hyperliquid/client.test.js +41 -0
  5. package/dist/client/hyperliquid/exchange-ws.js +3 -2
  6. package/dist/client/hyperliquid/rest.js +28 -5
  7. package/dist/client/hyperliquid/ws.js +16 -4
  8. package/dist/client/index.js +2 -2
  9. package/dist/client/lighter/constants.js +9 -1
  10. package/dist/client/lighter/constants.test.js +22 -0
  11. package/dist/client/lighter/exchange-ws.js +2 -2
  12. package/dist/client/lighter/rest.js +110 -37
  13. package/dist/client/lighter/rest.test.js +152 -0
  14. package/dist/client/lighter/ws.js +7 -2
  15. package/dist/client/okx/rest.js +20 -10
  16. package/dist/helper/factory.js +2 -2
  17. package/dist/helper/hyperliquid/helper.js +28 -13
  18. package/dist/helper/hyperliquid/helper.test.js +45 -0
  19. package/dist/helper/lighter/helper.js +77 -16
  20. package/dist/helper/lighter/helper.test.js +289 -0
  21. package/dist/helper/lighter/types.js +9 -8
  22. package/dist/index.d.ts +189 -38
  23. package/dist/sdk.js +22 -16
  24. package/dist/sdk.test.js +101 -0
  25. package/dist/status/hyperliquid/status.js +18 -5
  26. package/dist/status/hyperliquid/status.test.js +81 -0
  27. package/dist/status/lighter/status.js +18 -11
  28. package/dist/status/lighter/status.test.js +75 -0
  29. package/dist/syncer/base.js +0 -2
  30. package/dist/syncer/base.test.js +0 -1
  31. package/dist/syncer/hyperliquid/syncer.js +96 -43
  32. package/dist/syncer/hyperliquid/syncer.test.js +274 -0
  33. package/dist/syncer/lighter/funding.js +25 -0
  34. package/dist/syncer/lighter/funding.test.js +48 -0
  35. package/dist/syncer/lighter/syncer.js +30 -6
  36. package/dist/syncer/lighter/syncer.test.js +132 -6
  37. package/dist/tracker/base.js +23 -6
  38. package/dist/tracker/base.test.js +132 -0
  39. package/dist/tracker/binance/tracker.js +48 -18
  40. package/dist/tracker/binance/tracker.test.js +138 -0
  41. package/dist/tracker/bybit/tracker.js +78 -23
  42. package/dist/tracker/bybit/tracker.test.js +145 -0
  43. package/dist/tracker/hyperliquid/mapper.js +244 -44
  44. package/dist/tracker/hyperliquid/mapper.test.js +255 -0
  45. package/dist/tracker/hyperliquid/tracker.js +241 -74
  46. package/dist/tracker/hyperliquid/tracker.test.js +587 -0
  47. package/dist/tracker/index.js +15 -37
  48. package/dist/tracker/lighter/mapper.js +163 -33
  49. package/dist/tracker/lighter/mapper.test.js +199 -0
  50. package/dist/tracker/lighter/tracker.js +219 -45
  51. package/dist/tracker/lighter/tracker.test.js +515 -0
  52. package/dist/tracker/lighter/types.js +10 -2
  53. package/dist/tracker/okx/tracker.js +50 -16
  54. package/dist/tracker/okx/tracker.test.js +126 -0
  55. package/dist/tracker/types.js +2 -1
  56. package/dist/tracker/utils.test.js +8 -0
  57. package/package.json +6 -5
@@ -0,0 +1,126 @@
1
+ import { vi, describe, beforeEach, it, expect } from 'vitest';
2
+ import { OkxAccountTracker } from './tracker';
3
+
4
+ const { fetchAccountConfigMock, fetchBalanceMock, fetchPositionsMock, fetchLeverageInfosMock } = vi.hoisted(() => ({
5
+ fetchAccountConfigMock: vi.fn(),
6
+ fetchBalanceMock: vi.fn(),
7
+ fetchPositionsMock: vi.fn(),
8
+ fetchLeverageInfosMock: vi.fn()
9
+ }));
10
+ vi.mock("../../client/okx/rest", () => ({
11
+ fetchAccountConfig: fetchAccountConfigMock,
12
+ fetchBalance: fetchBalanceMock,
13
+ fetchPositions: fetchPositionsMock,
14
+ fetchLeverageInfos: fetchLeverageInfosMock
15
+ }));
16
+ const creds = { api_key: "k", api_secret: "s", api_pass: "p" };
17
+ function buildTracker() {
18
+ return new OkxAccountTracker({ demo: true, credentials: creds });
19
+ }
20
+ describe("OkxAccountTracker.snapshot", () => {
21
+ beforeEach(() => {
22
+ fetchAccountConfigMock.mockReset();
23
+ fetchBalanceMock.mockReset();
24
+ fetchPositionsMock.mockReset();
25
+ });
26
+ it("returns mapped balance + positions, cross mgnMode only, with no socket opened", async () => {
27
+ fetchAccountConfigMock.mockResolvedValue({ acctLv: "3" });
28
+ fetchBalanceMock.mockResolvedValue({
29
+ totalEq: "1000",
30
+ adjEq: "900",
31
+ availEq: "900",
32
+ mmr: "10",
33
+ imr: "20",
34
+ upl: "5",
35
+ mgnRatio: "0.0500",
36
+ details: [{ ccy: "USDT", eq: "1000", cashBal: "1000", availEq: "900", availBal: "900", eqUsd: "1000" }]
37
+ });
38
+ fetchPositionsMock.mockResolvedValue([
39
+ {
40
+ instId: "BTC-USDT-SWAP",
41
+ posSide: "long",
42
+ pos: "1",
43
+ avgPx: "50000",
44
+ upl: "100",
45
+ lever: "10",
46
+ mgnMode: "cross",
47
+ liqPx: "40000"
48
+ }
49
+ ]);
50
+ const tracker = buildTracker();
51
+ const snapshot = await tracker.snapshot();
52
+ expect(snapshot.balance).not.toBeNull();
53
+ expect(snapshot.balance).toMatchObject({
54
+ accountType: "OKX_MULTI",
55
+ totalEquity: "1000",
56
+ availableToTrade: "900",
57
+ maintenanceMargin: "10",
58
+ initialMarginUsed: "20",
59
+ marginRatio: "0.0500"
60
+ });
61
+ expect(snapshot.positions).toHaveLength(1);
62
+ expect(snapshot.positions[0]).toMatchObject({
63
+ symbol: "BTC-USDT-SWAP",
64
+ side: "long",
65
+ leverage: "10",
66
+ marginType: "cross",
67
+ liquidationPrice: "40000"
68
+ });
69
+ expect(fetchAccountConfigMock).toHaveBeenCalledTimes(1);
70
+ expect(fetchBalanceMock).toHaveBeenCalledTimes(1);
71
+ expect(fetchPositionsMock).toHaveBeenCalledTimes(1);
72
+ expect(fetchLeverageInfosMock).not.toHaveBeenCalled();
73
+ });
74
+ it("returns a null balance when account type cannot be resolved", async () => {
75
+ fetchAccountConfigMock.mockResolvedValue({ acctLv: "unknown" });
76
+ fetchBalanceMock.mockResolvedValue({
77
+ totalEq: "0",
78
+ adjEq: "0",
79
+ availEq: "0",
80
+ mmr: "0",
81
+ imr: "0",
82
+ upl: "0",
83
+ mgnRatio: "0",
84
+ details: []
85
+ });
86
+ fetchPositionsMock.mockResolvedValue([]);
87
+ const snapshot = await buildTracker().snapshot();
88
+ expect(snapshot.balance).toBeNull();
89
+ expect(snapshot.positions).toEqual([]);
90
+ });
91
+ });
92
+ describe("OkxAccountTracker.snapshotAssets", () => {
93
+ beforeEach(() => {
94
+ fetchLeverageInfosMock.mockReset();
95
+ });
96
+ it("reads all instIds through one batched leverage-info call and maps rows back by instId", async () => {
97
+ fetchLeverageInfosMock.mockResolvedValue([
98
+ { instId: "BTC-USDT-SWAP", lever: "10", mgnMode: "cross" },
99
+ { instId: "ETH-USDT-SWAP", lever: "3", mgnMode: "cross" }
100
+ ]);
101
+ const result = await buildTracker().snapshotAssets(["BTC-USDT-SWAP", "ETH-USDT-SWAP", "DOGE-USDT-SWAP"]);
102
+ expect(fetchLeverageInfosMock).toHaveBeenCalledTimes(1);
103
+ expect(fetchLeverageInfosMock).toHaveBeenCalledWith(
104
+ creds,
105
+ ["BTC-USDT-SWAP", "ETH-USDT-SWAP", "DOGE-USDT-SWAP"],
106
+ true
107
+ );
108
+ expect(result).toEqual({
109
+ "BTC-USDT-SWAP": { coin: "BTC-USDT-SWAP", leverage: "10", marginType: "cross" },
110
+ "ETH-USDT-SWAP": { coin: "ETH-USDT-SWAP", leverage: "3", marginType: "cross" },
111
+ "DOGE-USDT-SWAP": null
112
+ });
113
+ });
114
+ it("collapses long/short-mode duplicate rows to one entry per instId", async () => {
115
+ fetchLeverageInfosMock.mockResolvedValue([
116
+ { instId: "BTC-USDT-SWAP", lever: "10", mgnMode: "cross", posSide: "long" },
117
+ { instId: "BTC-USDT-SWAP", lever: "10", mgnMode: "cross", posSide: "short" }
118
+ ]);
119
+ const result = await buildTracker().snapshotAssets(["BTC-USDT-SWAP"]);
120
+ expect(result["BTC-USDT-SWAP"]).toEqual({ coin: "BTC-USDT-SWAP", leverage: "10", marginType: "cross" });
121
+ });
122
+ it("propagates a failed batched read", async () => {
123
+ fetchLeverageInfosMock.mockRejectedValue(new Error("50011"));
124
+ await expect(buildTracker().snapshotAssets(["BTC-USDT-SWAP"])).rejects.toThrow("50011");
125
+ });
126
+ });
@@ -15,7 +15,8 @@ const ACCOUNT_TYPE_LABELS = {
15
15
  [HyperliquidAccountType.DEX_ABSTRACTION]: "Standard (Shared HIP-3 Balance)",
16
16
  [HyperliquidAccountType.PORTFOLIO_MARGIN]: "Portfolio Margin",
17
17
  [HyperliquidAccountType.UNIFIED_ACCOUNT]: "Unified Account",
18
- [LighterAccountType.BASIC]: "Standard",
18
+ [LighterAccountType.CLASSIC]: "Classic",
19
+ [LighterAccountType.UNIFIED]: "Unified",
19
20
  [OkxAccountType.SPOT]: "Spot Mode",
20
21
  [OkxAccountType.SINGLE_CURRENCY_MARGIN]: "Single-Currency Margin",
21
22
  [OkxAccountType.MULTI_CURRENCY_MARGIN]: "Multi-Currency Margin",
@@ -0,0 +1,8 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { positionKey } from './utils';
3
+
4
+ describe("positionKey", () => {
5
+ it("joins symbol and side with a colon", () => {
6
+ expect(positionKey("BTC-PERP", "long")).toBe("BTC-PERP:long");
7
+ });
8
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pear-protocol/exchanges-sdk",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "description": "Pear Protocol Exchanges SDK",
5
5
  "private": false,
6
6
  "type": "module",
@@ -22,13 +22,14 @@
22
22
  "scripts": {
23
23
  "build": "tsup",
24
24
  "clean": "rm -rf dist .turbo",
25
+ "typecheck": "tsc --noEmit",
25
26
  "test": "vitest run",
26
- "typecheck": "tsc --noEmit"
27
+ "test:watch": "vitest"
27
28
  },
28
29
  "dependencies": {
29
- "@pear-protocol/core-sdk": "^1.5.0",
30
- "@pear-protocol/types": "^1.6.0",
31
- "@pear-protocol/utils": "^0.1.0",
30
+ "@pear-protocol/core-sdk": "^1.7.0",
31
+ "@pear-protocol/types": "^1.9.0",
32
+ "@pear-protocol/utils": "^0.2.0",
32
33
  "bignumber.js": "^11.1.1",
33
34
  "partysocket": "^1.0.3",
34
35
  "viem": "^2.48.8"