@pear-protocol/exchanges-sdk 0.6.5 → 0.6.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/base-ws.js +15 -6
- package/dist/client/binance/exchange-ws.js +22 -8
- package/dist/client/binance/rest.js +40 -27
- package/dist/client/binance/ws.js +21 -2
- package/dist/client/bybit/exchange-ws.js +13 -6
- package/dist/client/bybit/rest.js +30 -36
- package/dist/client/bybit/ws.js +16 -2
- package/dist/client/exchange-ws.js +5 -0
- package/dist/client/hmac.js +9 -1
- package/dist/client/hyperliquid/exchange-ws.js +13 -5
- package/dist/client/hyperliquid/rest.js +37 -7
- package/dist/client/hyperliquid/ws.js +10 -4
- package/dist/client/index.js +9 -2
- package/dist/client/lighter/constants.js +4 -0
- package/dist/client/lighter/exchange-ws.js +13 -5
- package/dist/client/lighter/rest.js +153 -18
- package/dist/client/lighter/ws.js +10 -4
- package/dist/client/okx/exchange-ws.js +13 -6
- package/dist/client/okx/rest.js +27 -24
- package/dist/client/okx/ws.js +5 -0
- package/dist/helper/factory.js +3 -0
- package/dist/helper/hyperliquid/helper.js +18 -23
- package/dist/helper/lighter/auth-token.helper.js +68 -0
- package/dist/helper/lighter/cctp-deposit.helper.js +297 -0
- package/dist/helper/lighter/ethereum/abi.js +55 -11
- package/dist/helper/lighter/ethereum/index.js +22 -3
- package/dist/helper/lighter/ethereum/usdc.helper.js +77 -0
- package/dist/helper/lighter/helper.js +116 -37
- package/dist/helper/lighter/index.js +1 -0
- package/dist/helper/lighter/onboarding.helper.js +28 -0
- package/dist/helper/lighter/types.js +6 -1
- package/dist/helper/subaccount.helper.js +20 -0
- package/dist/index.d.ts +202 -1
- package/dist/sdk.js +18 -7
- package/dist/status/base.js +16 -3
- package/dist/status/binance/status.js +3 -0
- package/dist/status/bybit/status.js +3 -0
- package/dist/status/factory.js +3 -0
- package/dist/status/hyperliquid/status.js +8 -6
- package/dist/status/lighter/status.js +11 -3
- package/dist/status/okx/status.js +3 -0
- package/dist/syncer/base.js +63 -24
- package/dist/syncer/binance/syncer.js +14 -13
- package/dist/syncer/bybit/syncer.js +10 -6
- package/dist/syncer/factory.js +3 -0
- package/dist/syncer/hyperliquid/funding.js +3 -0
- package/dist/syncer/hyperliquid/syncer.js +52 -66
- package/dist/syncer/lighter/funding.js +3 -0
- package/dist/syncer/lighter/syncer.js +26 -25
- package/dist/syncer/okx/syncer.js +15 -13
- package/dist/tracker/base.js +15 -5
- package/dist/tracker/binance/mapper.js +5 -1
- package/dist/tracker/binance/tracker.js +63 -23
- package/dist/tracker/binance/types.js +2 -2
- package/dist/tracker/bybit/mapper.js +7 -1
- package/dist/tracker/bybit/tracker.js +68 -24
- package/dist/tracker/bybit/types.js +2 -2
- package/dist/tracker/hyperliquid/const.js +3 -1
- package/dist/tracker/hyperliquid/mapper.js +36 -20
- package/dist/tracker/hyperliquid/tracker.js +147 -54
- package/dist/tracker/hyperliquid/types.js +2 -2
- package/dist/tracker/index.js +3 -0
- package/dist/tracker/lighter/mapper.js +41 -31
- package/dist/tracker/lighter/tracker.js +68 -27
- package/dist/tracker/lighter/types.js +4 -4
- package/dist/tracker/okx/mapper.js +8 -0
- package/dist/tracker/okx/tracker.js +69 -18
- package/dist/tracker/okx/types.js +2 -2
- package/dist/tracker/utils.js +4 -0
- package/package.json +3 -3
- package/dist/client/hyperliquid/client.test.js +0 -41
- package/dist/client/lighter/constants.test.js +0 -22
- package/dist/client/lighter/rest.test.js +0 -158
- package/dist/helper/hyperliquid/helper.test.js +0 -72
- package/dist/helper/lighter/helper.test.js +0 -289
- package/dist/sdk.test.js +0 -117
- package/dist/status/hyperliquid/status.test.js +0 -94
- package/dist/status/lighter/status.test.js +0 -86
- package/dist/syncer/base.test.js +0 -178
- package/dist/syncer/hyperliquid/funding.test.js +0 -63
- package/dist/syncer/hyperliquid/syncer.test.js +0 -271
- package/dist/syncer/lighter/funding.test.js +0 -48
- package/dist/syncer/lighter/syncer.test.js +0 -274
- package/dist/tracker/base.test.js +0 -132
- package/dist/tracker/binance/tracker.test.js +0 -138
- package/dist/tracker/bybit/tracker.test.js +0 -145
- package/dist/tracker/hyperliquid/mapper.test.js +0 -260
- package/dist/tracker/hyperliquid/tracker.test.js +0 -597
- package/dist/tracker/lighter/mapper.test.js +0 -199
- package/dist/tracker/lighter/tracker.test.js +0 -515
- package/dist/tracker/okx/tracker.test.js +0 -126
- package/dist/tracker/utils.test.js +0 -8
package/dist/client/index.js
CHANGED
|
@@ -16,6 +16,8 @@ export { HyperliquidWs } from './hyperliquid/ws';
|
|
|
16
16
|
export { LighterWs } from './lighter/ws';
|
|
17
17
|
export { OkxWs } from './okx/ws';
|
|
18
18
|
|
|
19
|
+
var __defProp = Object.defineProperty;
|
|
20
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
19
21
|
async function createExchangeWs(exchange, config) {
|
|
20
22
|
switch (exchange) {
|
|
21
23
|
case "binance":
|
|
@@ -34,14 +36,19 @@ async function createExchangeWs(exchange, config) {
|
|
|
34
36
|
credentials: config.credentials
|
|
35
37
|
});
|
|
36
38
|
case "hyperliquid":
|
|
37
|
-
return HyperliquidExchangeWs.create({
|
|
39
|
+
return HyperliquidExchangeWs.create({
|
|
40
|
+
demo: config.demo
|
|
41
|
+
});
|
|
38
42
|
case "lighter":
|
|
39
|
-
return LighterExchangeWs.create({
|
|
43
|
+
return LighterExchangeWs.create({
|
|
44
|
+
demo: config.demo
|
|
45
|
+
});
|
|
40
46
|
default: {
|
|
41
47
|
const _exhaustive = exchange;
|
|
42
48
|
throw new Error(`Unsupported exchange: ${String(_exhaustive)}`);
|
|
43
49
|
}
|
|
44
50
|
}
|
|
45
51
|
}
|
|
52
|
+
__name(createExchangeWs, "createExchangeWs");
|
|
46
53
|
|
|
47
54
|
export { createExchangeWs };
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
1
3
|
const LIGHTER_BASE_URL = "https://mainnet.zklighter.elliot.ai";
|
|
2
4
|
const LIGHTER_BASE_URL_TESTNET = "https://testnet.zklighter.elliot.ai";
|
|
3
5
|
const LIGHTER_WS_URL = "wss://mainnet.zklighter.elliot.ai/stream";
|
|
@@ -5,8 +7,10 @@ const LIGHTER_WS_URL_TESTNET = "wss://testnet.zklighter.elliot.ai/stream";
|
|
|
5
7
|
function getLighterBaseUrl(demo) {
|
|
6
8
|
return demo ? LIGHTER_BASE_URL_TESTNET : LIGHTER_BASE_URL;
|
|
7
9
|
}
|
|
10
|
+
__name(getLighterBaseUrl, "getLighterBaseUrl");
|
|
8
11
|
function getLighterWsUrl(demo) {
|
|
9
12
|
return demo ? LIGHTER_WS_URL_TESTNET : LIGHTER_WS_URL;
|
|
10
13
|
}
|
|
14
|
+
__name(getLighterWsUrl, "getLighterWsUrl");
|
|
11
15
|
|
|
12
16
|
export { LIGHTER_BASE_URL, LIGHTER_BASE_URL_TESTNET, LIGHTER_WS_URL, LIGHTER_WS_URL_TESTNET, getLighterBaseUrl, getLighterWsUrl };
|
|
@@ -1,17 +1,25 @@
|
|
|
1
1
|
import { ExchangeWs } from '../exchange-ws';
|
|
2
2
|
import { LighterWs } from './ws';
|
|
3
3
|
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
4
6
|
class LighterExchangeWs extends ExchangeWs {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
this.main = main;
|
|
7
|
+
static {
|
|
8
|
+
__name(this, "LighterExchangeWs");
|
|
8
9
|
}
|
|
9
10
|
main;
|
|
10
11
|
exchange = "lighter";
|
|
12
|
+
constructor(main) {
|
|
13
|
+
super(), this.main = main;
|
|
14
|
+
}
|
|
11
15
|
connections() {
|
|
12
|
-
return [
|
|
16
|
+
return [
|
|
17
|
+
this.main
|
|
18
|
+
];
|
|
13
19
|
}
|
|
14
|
-
static async create(config = {
|
|
20
|
+
static async create(config = {
|
|
21
|
+
demo: false
|
|
22
|
+
}) {
|
|
15
23
|
const main = new LighterWs(config.demo);
|
|
16
24
|
await main.connect();
|
|
17
25
|
return new LighterExchangeWs(main);
|
|
@@ -1,12 +1,107 @@
|
|
|
1
1
|
import { proxyFetch } from '@pear-protocol/utils';
|
|
2
2
|
import { getLighterBaseUrl } from './constants';
|
|
3
3
|
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
6
|
+
const INTENT_REQUEST_ATTEMPTS = 3;
|
|
7
|
+
const INTENT_RETRY_BASE_DELAY_MS = 500;
|
|
8
|
+
const RETRYABLE_INTENT_STATUSES = /* @__PURE__ */ new Set([
|
|
9
|
+
429,
|
|
10
|
+
503
|
|
11
|
+
]);
|
|
12
|
+
async function fetchDepositNetworks(demo = false) {
|
|
13
|
+
const response = await proxyFetch(`${getLighterBaseUrl(demo)}/api/v1/deposit/networks`);
|
|
14
|
+
const data = await readLighterResponse(response, "/deposit/networks");
|
|
15
|
+
const networks = [];
|
|
16
|
+
for (const network of data.networks ?? []) {
|
|
17
|
+
if (typeof network !== "object" || network === null) {
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
if (typeof network.name !== "string" || !network.name) {
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
if (network.explorer !== void 0 && typeof network.explorer !== "string") {
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
const chainId = typeof network.chain_id === "string" ? Number(network.chain_id) : Number.NaN;
|
|
27
|
+
if (!Number.isSafeInteger(chainId) || chainId <= 0) {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
networks.push({
|
|
31
|
+
name: network.name,
|
|
32
|
+
chainId,
|
|
33
|
+
explorer: network.explorer ?? ""
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
if (networks.length === 0) {
|
|
37
|
+
throw new Error("Lighter /deposit/networks returned no usable deposit networks");
|
|
38
|
+
}
|
|
39
|
+
return networks;
|
|
40
|
+
}
|
|
41
|
+
__name(fetchDepositNetworks, "fetchDepositNetworks");
|
|
42
|
+
async function createCctpDepositIntentAddress(params, demo = false) {
|
|
43
|
+
const body = new URLSearchParams({
|
|
44
|
+
chain_id: params.chainId.toString(),
|
|
45
|
+
from_addr: params.fromAddress,
|
|
46
|
+
amount: params.amount,
|
|
47
|
+
is_external_deposit: params.external.toString()
|
|
48
|
+
});
|
|
49
|
+
const response = await fetchDepositIntentWithRetry(`${getLighterBaseUrl(demo)}/api/v1/createIntentAddress`, {
|
|
50
|
+
method: "POST",
|
|
51
|
+
headers: {
|
|
52
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
53
|
+
},
|
|
54
|
+
body
|
|
55
|
+
});
|
|
56
|
+
const data = await readLighterResponse(response, "/createIntentAddress");
|
|
57
|
+
if (!/^0x[0-9a-fA-F]{40}$/.test(data.intent_address)) {
|
|
58
|
+
throw new Error("Lighter /createIntentAddress returned an invalid intent address");
|
|
59
|
+
}
|
|
60
|
+
return data.intent_address;
|
|
61
|
+
}
|
|
62
|
+
__name(createCctpDepositIntentAddress, "createCctpDepositIntentAddress");
|
|
63
|
+
async function fetchDepositHistory(params, demo = false) {
|
|
64
|
+
const query = new URLSearchParams({
|
|
65
|
+
account_index: params.accountIndex.toString(),
|
|
66
|
+
l1_address: params.l1Address,
|
|
67
|
+
filter: "all"
|
|
68
|
+
});
|
|
69
|
+
const response = await proxyFetch(`${getLighterBaseUrl(demo)}/api/v1/deposit/history?${query.toString()}`, {
|
|
70
|
+
headers: {
|
|
71
|
+
authorization: params.authToken
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
const data = await readLighterResponse(response, "/deposit/history");
|
|
75
|
+
const deposits = [];
|
|
76
|
+
for (const deposit of data.deposits ?? []) {
|
|
77
|
+
if (typeof deposit !== "object" || deposit === null) {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (typeof deposit.id !== "string" || typeof deposit.amount !== "string" || !isLighterDepositStatus(deposit.status)) {
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
if (typeof deposit.timestamp !== "number" || !Number.isSafeInteger(deposit.timestamp)) {
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
deposits.push({
|
|
87
|
+
id: deposit.id,
|
|
88
|
+
assetId: typeof deposit.asset_id === "number" ? deposit.asset_id : -1,
|
|
89
|
+
amount: deposit.amount,
|
|
90
|
+
timestamp: deposit.timestamp,
|
|
91
|
+
status: deposit.status,
|
|
92
|
+
l1TxHash: typeof deposit.l1_tx_hash === "string" ? deposit.l1_tx_hash : ""
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
return deposits;
|
|
96
|
+
}
|
|
97
|
+
__name(fetchDepositHistory, "fetchDepositHistory");
|
|
4
98
|
async function fetchApiKeys(accountIndex, demo = false) {
|
|
5
99
|
const url = `${getLighterBaseUrl(demo)}/api/v1/apikeys?account_index=${accountIndex}`;
|
|
6
100
|
const response = await proxyFetch(url);
|
|
7
101
|
const data = await readLighterResponse(response, "/apikeys");
|
|
8
102
|
return data.api_keys;
|
|
9
103
|
}
|
|
104
|
+
__name(fetchApiKeys, "fetchApiKeys");
|
|
10
105
|
async function fetchAccountsByL1Address(l1Address, demo = false) {
|
|
11
106
|
const subAccounts = /* @__PURE__ */ new Map();
|
|
12
107
|
const seenCursors = /* @__PURE__ */ new Set();
|
|
@@ -15,10 +110,15 @@ async function fetchAccountsByL1Address(l1Address, demo = false) {
|
|
|
15
110
|
do {
|
|
16
111
|
const params = new URLSearchParams({
|
|
17
112
|
l1_address: l1Address,
|
|
18
|
-
...cursor ? {
|
|
113
|
+
...cursor ? {
|
|
114
|
+
cursor
|
|
115
|
+
} : {}
|
|
19
116
|
});
|
|
20
117
|
const response = await proxyFetch(`${getLighterBaseUrl(demo)}/api/v1/accountsByL1Address?${params.toString()}`);
|
|
21
|
-
const data = await readLighterResponse(response, "/accountsByL1Address", [
|
|
118
|
+
const data = await readLighterResponse(response, "/accountsByL1Address", [
|
|
119
|
+
200,
|
|
120
|
+
21100
|
|
121
|
+
]);
|
|
22
122
|
if (data.code === 21100) return data;
|
|
23
123
|
message ??= data.message;
|
|
24
124
|
for (const account of data.sub_accounts ?? []) {
|
|
@@ -32,46 +132,53 @@ async function fetchAccountsByL1Address(l1Address, demo = false) {
|
|
|
32
132
|
} while (cursor);
|
|
33
133
|
return {
|
|
34
134
|
code: 200,
|
|
35
|
-
...message ? {
|
|
135
|
+
...message ? {
|
|
136
|
+
message
|
|
137
|
+
} : {},
|
|
36
138
|
sub_accounts: Array.from(subAccounts.values())
|
|
37
139
|
};
|
|
38
140
|
}
|
|
141
|
+
__name(fetchAccountsByL1Address, "fetchAccountsByL1Address");
|
|
39
142
|
async function fetchAccount(accountIndex, demo = false) {
|
|
40
143
|
const response = await proxyFetch(`${getLighterBaseUrl(demo)}/api/v1/account?by=index&value=${accountIndex}`);
|
|
41
144
|
return readLighterResponse(response, "/account");
|
|
42
145
|
}
|
|
146
|
+
__name(fetchAccount, "fetchAccount");
|
|
43
147
|
async function fetchAccountLimits(accountIndex, authToken, demo = false) {
|
|
44
148
|
const response = await proxyFetch(`${getLighterBaseUrl(demo)}/api/v1/accountLimits?account_index=${accountIndex}`, {
|
|
45
|
-
headers: {
|
|
149
|
+
headers: {
|
|
150
|
+
authorization: authToken
|
|
151
|
+
}
|
|
46
152
|
});
|
|
47
153
|
return readLighterResponse(response, "/accountLimits");
|
|
48
154
|
}
|
|
155
|
+
__name(fetchAccountLimits, "fetchAccountLimits");
|
|
49
156
|
async function fetchAccountMetadata(accountIndex, authToken, demo = false) {
|
|
50
|
-
const response = await proxyFetch(
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
accept: "application/json",
|
|
55
|
-
authorization: authToken
|
|
56
|
-
}
|
|
157
|
+
const response = await proxyFetch(`${getLighterBaseUrl(demo)}/api/v1/accountMetadata?by=index&value=${accountIndex}`, {
|
|
158
|
+
headers: {
|
|
159
|
+
accept: "application/json",
|
|
160
|
+
authorization: authToken
|
|
57
161
|
}
|
|
58
|
-
);
|
|
162
|
+
});
|
|
59
163
|
const data = await readLighterResponse(response, "/accountMetadata");
|
|
60
164
|
const matchesAccount = data.account_metadatas?.some((metadata) => metadata.account_index === accountIndex);
|
|
61
165
|
if (!matchesAccount) {
|
|
62
166
|
throw new Error(`Lighter /accountMetadata did not return account ${accountIndex}`);
|
|
63
167
|
}
|
|
64
168
|
}
|
|
169
|
+
__name(fetchAccountMetadata, "fetchAccountMetadata");
|
|
65
170
|
async function fetchOrderBookDetails(demo = false) {
|
|
66
171
|
const response = await proxyFetch(`${getLighterBaseUrl(demo)}/api/v1/orderBookDetails?filter=perp`);
|
|
67
172
|
const data = await readLighterResponse(response, "/orderBookDetails");
|
|
68
173
|
return data.order_book_details;
|
|
69
174
|
}
|
|
175
|
+
__name(fetchOrderBookDetails, "fetchOrderBookDetails");
|
|
70
176
|
async function fetchAssetDetails(demo) {
|
|
71
177
|
const response = await proxyFetch(`${getLighterBaseUrl(demo)}/api/v1/assetDetails`);
|
|
72
178
|
const data = await readLighterResponse(response, "/assetDetails");
|
|
73
179
|
return data.asset_details;
|
|
74
180
|
}
|
|
181
|
+
__name(fetchAssetDetails, "fetchAssetDetails");
|
|
75
182
|
async function fetchTradesSince(accountIndex, authToken, since, demo = false) {
|
|
76
183
|
const results = [];
|
|
77
184
|
const seenCursors = /* @__PURE__ */ new Set();
|
|
@@ -87,10 +194,14 @@ async function fetchTradesSince(accountIndex, authToken, since, demo = false) {
|
|
|
87
194
|
type: "all",
|
|
88
195
|
limit: "100",
|
|
89
196
|
aggregate: "false",
|
|
90
|
-
...cursor ? {
|
|
197
|
+
...cursor ? {
|
|
198
|
+
cursor
|
|
199
|
+
} : {}
|
|
91
200
|
});
|
|
92
201
|
const response = await proxyFetch(`${getLighterBaseUrl(demo)}/api/v1/trades?${params.toString()}`, {
|
|
93
|
-
headers: {
|
|
202
|
+
headers: {
|
|
203
|
+
authorization: authToken
|
|
204
|
+
}
|
|
94
205
|
});
|
|
95
206
|
const data = await readLighterResponse(response, "/trades");
|
|
96
207
|
const page = data.trades ?? [];
|
|
@@ -108,6 +219,7 @@ async function fetchTradesSince(accountIndex, authToken, since, demo = false) {
|
|
|
108
219
|
}
|
|
109
220
|
return Array.from(byId.values());
|
|
110
221
|
}
|
|
222
|
+
__name(fetchTradesSince, "fetchTradesSince");
|
|
111
223
|
async function fetchPositionFundingSince(accountIndex, authToken, since, demo = false) {
|
|
112
224
|
const results = /* @__PURE__ */ new Map();
|
|
113
225
|
const seenCursors = /* @__PURE__ */ new Set();
|
|
@@ -119,10 +231,14 @@ async function fetchPositionFundingSince(accountIndex, authToken, since, demo =
|
|
|
119
231
|
limit: "100",
|
|
120
232
|
side: "all",
|
|
121
233
|
start_timestamp: sinceSeconds.toString(),
|
|
122
|
-
...cursor ? {
|
|
234
|
+
...cursor ? {
|
|
235
|
+
cursor
|
|
236
|
+
} : {}
|
|
123
237
|
});
|
|
124
238
|
const response = await proxyFetch(`${getLighterBaseUrl(demo)}/api/v1/positionFunding?${params.toString()}`, {
|
|
125
|
-
headers: {
|
|
239
|
+
headers: {
|
|
240
|
+
authorization: authToken
|
|
241
|
+
}
|
|
126
242
|
});
|
|
127
243
|
const data = await readLighterResponse(response, "/positionFunding");
|
|
128
244
|
for (const funding of data.position_fundings ?? []) {
|
|
@@ -138,7 +254,25 @@ async function fetchPositionFundingSince(accountIndex, authToken, since, demo =
|
|
|
138
254
|
} while (cursor);
|
|
139
255
|
return Array.from(results.values());
|
|
140
256
|
}
|
|
141
|
-
|
|
257
|
+
__name(fetchPositionFundingSince, "fetchPositionFundingSince");
|
|
258
|
+
async function fetchDepositIntentWithRetry(url, init) {
|
|
259
|
+
for (let attempt = 1; attempt <= INTENT_REQUEST_ATTEMPTS; attempt += 1) {
|
|
260
|
+
const response = await proxyFetch(url, init);
|
|
261
|
+
if (!RETRYABLE_INTENT_STATUSES.has(response.status) || attempt === INTENT_REQUEST_ATTEMPTS) {
|
|
262
|
+
return response;
|
|
263
|
+
}
|
|
264
|
+
await new Promise((resolve) => setTimeout(resolve, INTENT_RETRY_BASE_DELAY_MS * 2 ** (attempt - 1)));
|
|
265
|
+
}
|
|
266
|
+
throw new Error("Lighter intent retry loop exhausted without a response");
|
|
267
|
+
}
|
|
268
|
+
__name(fetchDepositIntentWithRetry, "fetchDepositIntentWithRetry");
|
|
269
|
+
function isLighterDepositStatus(value) {
|
|
270
|
+
return value === "failed" || value === "pending" || value === "completed" || value === "claimable";
|
|
271
|
+
}
|
|
272
|
+
__name(isLighterDepositStatus, "isLighterDepositStatus");
|
|
273
|
+
async function readLighterResponse(response, endpoint, acceptedCodes = [
|
|
274
|
+
200
|
|
275
|
+
]) {
|
|
142
276
|
let data;
|
|
143
277
|
try {
|
|
144
278
|
data = await response.json();
|
|
@@ -153,5 +287,6 @@ async function readLighterResponse(response, endpoint, acceptedCodes = [200]) {
|
|
|
153
287
|
}
|
|
154
288
|
return data;
|
|
155
289
|
}
|
|
290
|
+
__name(readLighterResponse, "readLighterResponse");
|
|
156
291
|
|
|
157
|
-
export { fetchAccount, fetchAccountLimits, fetchAccountMetadata, fetchAccountsByL1Address, fetchApiKeys, fetchAssetDetails, fetchOrderBookDetails, fetchPositionFundingSince, fetchTradesSince };
|
|
292
|
+
export { createCctpDepositIntentAddress, fetchAccount, fetchAccountLimits, fetchAccountMetadata, fetchAccountsByL1Address, fetchApiKeys, fetchAssetDetails, fetchDepositHistory, fetchDepositNetworks, fetchOrderBookDetails, fetchPositionFundingSince, fetchTradesSince };
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import { BaseWs } from '../base-ws';
|
|
2
2
|
import { getLighterWsUrl } from './constants';
|
|
3
3
|
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
4
6
|
const PING_INTERVAL_MS = 9e4;
|
|
5
7
|
class LighterWs extends BaseWs {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
this.demo = demo;
|
|
8
|
+
static {
|
|
9
|
+
__name(this, "LighterWs");
|
|
9
10
|
}
|
|
10
11
|
demo;
|
|
12
|
+
constructor(demo = false) {
|
|
13
|
+
super(), this.demo = demo;
|
|
14
|
+
}
|
|
11
15
|
getWsUrl() {
|
|
12
16
|
return getLighterWsUrl(this.demo);
|
|
13
17
|
}
|
|
@@ -15,7 +19,9 @@ class LighterWs extends BaseWs {
|
|
|
15
19
|
return PING_INTERVAL_MS;
|
|
16
20
|
}
|
|
17
21
|
buildPingMessage() {
|
|
18
|
-
return {
|
|
22
|
+
return {
|
|
23
|
+
type: "ping"
|
|
24
|
+
};
|
|
19
25
|
}
|
|
20
26
|
}
|
|
21
27
|
|
|
@@ -1,23 +1,30 @@
|
|
|
1
1
|
import { ExchangeWs } from '../exchange-ws';
|
|
2
2
|
import { OkxWs } from './ws';
|
|
3
3
|
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
4
6
|
class OkxExchangeWs extends ExchangeWs {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
this.main = main;
|
|
8
|
-
this.creds = creds;
|
|
7
|
+
static {
|
|
8
|
+
__name(this, "OkxExchangeWs");
|
|
9
9
|
}
|
|
10
10
|
main;
|
|
11
11
|
creds;
|
|
12
12
|
exchange = "okx";
|
|
13
|
+
constructor(main, creds) {
|
|
14
|
+
super(), this.main = main, this.creds = creds;
|
|
15
|
+
}
|
|
13
16
|
connections() {
|
|
14
|
-
return [
|
|
17
|
+
return [
|
|
18
|
+
this.main
|
|
19
|
+
];
|
|
15
20
|
}
|
|
16
21
|
login() {
|
|
17
22
|
return this.main.login(this.creds);
|
|
18
23
|
}
|
|
19
24
|
static async create(config) {
|
|
20
|
-
const main = new OkxWs({
|
|
25
|
+
const main = new OkxWs({
|
|
26
|
+
demo: config.demo
|
|
27
|
+
});
|
|
21
28
|
await main.connect();
|
|
22
29
|
const wrapper = new OkxExchangeWs(main, config.credentials);
|
|
23
30
|
await wrapper.login();
|
package/dist/client/okx/rest.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { proxyFetch } from '@pear-protocol/utils';
|
|
2
2
|
import { hmacSha256Base64 } from '../hmac';
|
|
3
3
|
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
4
6
|
const REST_BASE_URL = "https://www.okx.com";
|
|
5
7
|
async function signedGet(creds, path, params, demo) {
|
|
6
8
|
const queryString = new URLSearchParams(params).toString();
|
|
@@ -18,7 +20,9 @@ async function signedGet(creds, path, params, demo) {
|
|
|
18
20
|
if (demo) {
|
|
19
21
|
headers["x-simulated-trading"] = "1";
|
|
20
22
|
}
|
|
21
|
-
const response = await proxyFetch(`${REST_BASE_URL}${fullPath}`, {
|
|
23
|
+
const response = await proxyFetch(`${REST_BASE_URL}${fullPath}`, {
|
|
24
|
+
headers
|
|
25
|
+
});
|
|
22
26
|
if (!response.ok) {
|
|
23
27
|
throw new Error(`OKX API error: ${response.status} ${response.statusText}`);
|
|
24
28
|
}
|
|
@@ -28,6 +32,7 @@ async function signedGet(creds, path, params, demo) {
|
|
|
28
32
|
}
|
|
29
33
|
return body.data;
|
|
30
34
|
}
|
|
35
|
+
__name(signedGet, "signedGet");
|
|
31
36
|
async function fetchAccountConfig(creds, demo) {
|
|
32
37
|
const data = await signedGet(creds, "/api/v5/account/config", {}, demo);
|
|
33
38
|
if (!data[0]) {
|
|
@@ -35,6 +40,7 @@ async function fetchAccountConfig(creds, demo) {
|
|
|
35
40
|
}
|
|
36
41
|
return data[0];
|
|
37
42
|
}
|
|
43
|
+
__name(fetchAccountConfig, "fetchAccountConfig");
|
|
38
44
|
async function fetchBalance(creds, demo) {
|
|
39
45
|
const data = await signedGet(creds, "/api/v5/account/balance", {}, demo);
|
|
40
46
|
if (!data[0]) {
|
|
@@ -42,44 +48,40 @@ async function fetchBalance(creds, demo) {
|
|
|
42
48
|
}
|
|
43
49
|
return data[0];
|
|
44
50
|
}
|
|
51
|
+
__name(fetchBalance, "fetchBalance");
|
|
45
52
|
async function fetchPositions(creds, demo) {
|
|
46
|
-
return signedGet(creds, "/api/v5/account/positions", {
|
|
53
|
+
return signedGet(creds, "/api/v5/account/positions", {
|
|
54
|
+
instType: "SWAP"
|
|
55
|
+
}, demo);
|
|
47
56
|
}
|
|
57
|
+
__name(fetchPositions, "fetchPositions");
|
|
48
58
|
const LEVERAGE_INFO_MAX_INST_IDS = 20;
|
|
49
59
|
async function fetchLeverageInfos(creds, instIds, demo) {
|
|
50
60
|
const chunks = [];
|
|
51
61
|
for (let i = 0; i < instIds.length; i += LEVERAGE_INFO_MAX_INST_IDS) {
|
|
52
62
|
chunks.push(instIds.slice(i, i + LEVERAGE_INFO_MAX_INST_IDS));
|
|
53
63
|
}
|
|
54
|
-
const results = await Promise.all(
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
"/api/v5/account/leverage-info",
|
|
59
|
-
{ instId: chunk.join(","), mgnMode: "cross" },
|
|
60
|
-
demo
|
|
61
|
-
)
|
|
62
|
-
)
|
|
63
|
-
);
|
|
64
|
+
const results = await Promise.all(chunks.map((chunk) => signedGet(creds, "/api/v5/account/leverage-info", {
|
|
65
|
+
instId: chunk.join(","),
|
|
66
|
+
mgnMode: "cross"
|
|
67
|
+
}, demo)));
|
|
64
68
|
return results.flat();
|
|
65
69
|
}
|
|
70
|
+
__name(fetchLeverageInfos, "fetchLeverageInfos");
|
|
66
71
|
const FILLS_HISTORY_LIMIT = 100;
|
|
67
72
|
async function fetchFillsHistorySince(creds, since, demo) {
|
|
68
73
|
const results = [];
|
|
69
74
|
let after;
|
|
70
75
|
do {
|
|
71
|
-
const page = await signedGet(
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
},
|
|
81
|
-
demo
|
|
82
|
-
);
|
|
76
|
+
const page = await signedGet(creds, "/api/v5/trade/fills-history", {
|
|
77
|
+
instType: "SWAP",
|
|
78
|
+
begin: since.getTime().toString(),
|
|
79
|
+
end: Date.now().toString(),
|
|
80
|
+
limit: FILLS_HISTORY_LIMIT.toString(),
|
|
81
|
+
...after ? {
|
|
82
|
+
after
|
|
83
|
+
} : {}
|
|
84
|
+
}, demo);
|
|
83
85
|
results.push(...page);
|
|
84
86
|
const last = page[page.length - 1];
|
|
85
87
|
after = page.length === FILLS_HISTORY_LIMIT && last?.billId ? last.billId : void 0;
|
|
@@ -90,5 +92,6 @@ async function fetchFillsHistorySince(creds, since, demo) {
|
|
|
90
92
|
}
|
|
91
93
|
return Array.from(byId.values());
|
|
92
94
|
}
|
|
95
|
+
__name(fetchFillsHistorySince, "fetchFillsHistorySince");
|
|
93
96
|
|
|
94
97
|
export { fetchAccountConfig, fetchBalance, fetchFillsHistorySince, fetchLeverageInfos, fetchPositions };
|
package/dist/client/okx/ws.js
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import { BaseWs } from '../base-ws';
|
|
2
2
|
import { hmacSha256Base64 } from '../hmac';
|
|
3
3
|
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
4
6
|
const WS_PRIVATE_URL = "wss://ws.okx.com:8443/ws/v5/private";
|
|
5
7
|
const WS_PRIVATE_URL_DEMO = "wss://wspap.okx.com:8443/ws/v5/private?brokerId=9999";
|
|
6
8
|
const PING_INTERVAL_MS = 25e3;
|
|
7
9
|
const LOGIN_TIMEOUT_MS = 1e4;
|
|
8
10
|
class OkxWs extends BaseWs {
|
|
11
|
+
static {
|
|
12
|
+
__name(this, "OkxWs");
|
|
13
|
+
}
|
|
9
14
|
demo;
|
|
10
15
|
constructor(config) {
|
|
11
16
|
super();
|
package/dist/helper/factory.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { createHyperliquidHelper } from './hyperliquid';
|
|
2
2
|
import { createLighterHelper } from './lighter';
|
|
3
3
|
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
4
6
|
function createExchangeHelper(config) {
|
|
5
7
|
switch (config.exchange) {
|
|
6
8
|
case "hyperliquid":
|
|
@@ -9,5 +11,6 @@ function createExchangeHelper(config) {
|
|
|
9
11
|
return createLighterHelper(config.sdk, config.demo ?? false);
|
|
10
12
|
}
|
|
11
13
|
}
|
|
14
|
+
__name(createExchangeHelper, "createExchangeHelper");
|
|
12
15
|
|
|
13
16
|
export { createExchangeHelper };
|
|
@@ -1,30 +1,27 @@
|
|
|
1
1
|
import { fetchInfo, fetchUserRole } from '../../client/hyperliquid/rest';
|
|
2
2
|
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
5
|
function createHyperliquidHelper(demo = false) {
|
|
4
6
|
return {
|
|
5
7
|
/**
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
* Checks that the address holds a Hyperliquid account, which the exchange only creates on the
|
|
9
|
+
* first deposit. This is account existence alone — builder-fee approval, Pear trade-account
|
|
10
|
+
* setup, and agent approval stay separate gates. A failed request throws rather than reporting
|
|
11
|
+
* an inactive account, so callers never mistake an outage for a user who has to deposit.
|
|
12
|
+
*/
|
|
11
13
|
async checkAccountActivation(userAddress) {
|
|
12
14
|
const role = await fetchUserRole(userAddress, demo);
|
|
13
15
|
return role.role !== "missing";
|
|
14
16
|
},
|
|
15
17
|
/** Checks that the requested API wallet exists and has not expired. */
|
|
16
18
|
async checkApiWallet(params) {
|
|
17
|
-
const agents = await fetchInfo(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
},
|
|
22
|
-
demo
|
|
23
|
-
);
|
|
19
|
+
const agents = await fetchInfo({
|
|
20
|
+
type: "extraAgents",
|
|
21
|
+
user: params.userAddress
|
|
22
|
+
}, demo);
|
|
24
23
|
const now = Date.now();
|
|
25
|
-
return agents.some(
|
|
26
|
-
(agent) => agent.address.toLowerCase() === params.agentWalletAddress.toLowerCase() && (agent.validUntil === null || agent.validUntil > now)
|
|
27
|
-
);
|
|
24
|
+
return agents.some((agent) => agent.address.toLowerCase() === params.agentWalletAddress.toLowerCase() && (agent.validUntil === null || agent.validUntil > now));
|
|
28
25
|
},
|
|
29
26
|
/** Checks that the approval covers the exact builder fee requested by orders. */
|
|
30
27
|
async checkBuilderFeeApproval(userAddress, builderAddress, requiredFeeTenthsBps) {
|
|
@@ -32,17 +29,15 @@ function createHyperliquidHelper(demo = false) {
|
|
|
32
29
|
if (!Number.isInteger(requiredFee) || requiredFee <= 0) {
|
|
33
30
|
return false;
|
|
34
31
|
}
|
|
35
|
-
const maxBuilderFee = await fetchInfo(
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
},
|
|
41
|
-
demo
|
|
42
|
-
);
|
|
32
|
+
const maxBuilderFee = await fetchInfo({
|
|
33
|
+
type: "maxBuilderFee",
|
|
34
|
+
user: userAddress,
|
|
35
|
+
builder: builderAddress
|
|
36
|
+
}, demo);
|
|
43
37
|
return Number(maxBuilderFee) >= requiredFee;
|
|
44
38
|
}
|
|
45
39
|
};
|
|
46
40
|
}
|
|
41
|
+
__name(createHyperliquidHelper, "createHyperliquidHelper");
|
|
47
42
|
|
|
48
43
|
export { createHyperliquidHelper };
|