@pear-protocol/exchanges-sdk 0.12.1 → 0.13.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/dist/client/hyperliquid/rest.js +12 -2
- package/dist/client/lighter/rest.js +44 -12
- package/dist/index.d.ts +37 -1
- package/dist/sdk.js +7 -1
- package/dist/syncer/base.js +2 -0
- package/dist/syncer/hyperliquid/syncer.js +38 -14
- package/dist/syncer/lighter/syncer.js +3 -3
- package/package.json +4 -4
|
@@ -6,6 +6,16 @@ const HL_INFO_URLS = {
|
|
|
6
6
|
mainnet: "https://api.hyperliquid.xyz/info",
|
|
7
7
|
testnet: "https://api.hyperliquid-testnet.xyz/info"
|
|
8
8
|
};
|
|
9
|
+
class HyperliquidInfoRequestError extends Error {
|
|
10
|
+
static {
|
|
11
|
+
__name(this, "HyperliquidInfoRequestError");
|
|
12
|
+
}
|
|
13
|
+
status;
|
|
14
|
+
constructor(status) {
|
|
15
|
+
super(`Hyperliquid info request failed: ${status}`);
|
|
16
|
+
this.status = status;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
9
19
|
async function fetchInfo(body, demo = false) {
|
|
10
20
|
const url = demo ? HL_INFO_URLS.testnet : HL_INFO_URLS.mainnet;
|
|
11
21
|
const res = await proxyFetch(url, {
|
|
@@ -16,7 +26,7 @@ async function fetchInfo(body, demo = false) {
|
|
|
16
26
|
body: JSON.stringify(body)
|
|
17
27
|
});
|
|
18
28
|
if (!res.ok) {
|
|
19
|
-
throw new
|
|
29
|
+
throw new HyperliquidInfoRequestError(res.status);
|
|
20
30
|
}
|
|
21
31
|
return res.json();
|
|
22
32
|
}
|
|
@@ -85,4 +95,4 @@ async function fetchActiveAssetData(user, coin, demo = false) {
|
|
|
85
95
|
}
|
|
86
96
|
__name(fetchActiveAssetData, "fetchActiveAssetData");
|
|
87
97
|
|
|
88
|
-
export { fetchActiveAssetData, fetchAllMids, fetchClearinghouseState, fetchDelegatorSummary, fetchInfo, fetchPerpDexs, fetchSpotClearinghouseState, fetchUserAbstraction, fetchUserRole, fetchUserVaultEquities };
|
|
98
|
+
export { HyperliquidInfoRequestError, fetchActiveAssetData, fetchAllMids, fetchClearinghouseState, fetchDelegatorSummary, fetchInfo, fetchPerpDexs, fetchSpotClearinghouseState, fetchUserAbstraction, fetchUserRole, fetchUserVaultEquities };
|
|
@@ -3,6 +3,17 @@ import { getLighterBaseUrl } from './constants';
|
|
|
3
3
|
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
5
5
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
6
|
+
class LighterRequestError extends Error {
|
|
7
|
+
static {
|
|
8
|
+
__name(this, "LighterRequestError");
|
|
9
|
+
}
|
|
10
|
+
status;
|
|
11
|
+
constructor(message, status) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.name = "LighterRequestError";
|
|
14
|
+
this.status = status;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
6
17
|
const INTENT_REQUEST_ATTEMPTS = 3;
|
|
7
18
|
const INTENT_RETRY_BASE_DELAY_MS = 500;
|
|
8
19
|
const RETRYABLE_INTENT_STATUSES = /* @__PURE__ */ new Set([
|
|
@@ -176,9 +187,11 @@ async function fetchAccountsByL1Address(l1Address, demo = false) {
|
|
|
176
187
|
};
|
|
177
188
|
}
|
|
178
189
|
__name(fetchAccountsByL1Address, "fetchAccountsByL1Address");
|
|
179
|
-
async function fetchAccount(accountIndex, authToken, demo = false) {
|
|
180
|
-
|
|
181
|
-
|
|
190
|
+
async function fetchAccount(accountIndex, authToken, demo = false, throttle) {
|
|
191
|
+
return gatedLighterRead(throttle, "account", async () => {
|
|
192
|
+
const response = await authenticatedLighterFetch(`${getLighterBaseUrl(demo)}/api/v1/account?by=index&value=${accountIndex}`, authToken);
|
|
193
|
+
return readLighterResponse(response, "/account");
|
|
194
|
+
}, () => 0);
|
|
182
195
|
}
|
|
183
196
|
__name(fetchAccount, "fetchAccount");
|
|
184
197
|
async function fetchPublicAccount(accountIndex, demo = false) {
|
|
@@ -232,7 +245,7 @@ async function fetchAssetDetails(demo) {
|
|
|
232
245
|
return data.asset_details;
|
|
233
246
|
}
|
|
234
247
|
__name(fetchAssetDetails, "fetchAssetDetails");
|
|
235
|
-
async function fetchTradesSince(accountIndex, authToken, since, demo = false) {
|
|
248
|
+
async function fetchTradesSince(accountIndex, authToken, since, demo = false, throttle) {
|
|
236
249
|
const results = [];
|
|
237
250
|
const seenCursors = /* @__PURE__ */ new Set();
|
|
238
251
|
let cursor;
|
|
@@ -251,8 +264,10 @@ async function fetchTradesSince(accountIndex, authToken, since, demo = false) {
|
|
|
251
264
|
cursor
|
|
252
265
|
} : {}
|
|
253
266
|
});
|
|
254
|
-
const
|
|
255
|
-
|
|
267
|
+
const data = await gatedLighterRead(throttle, "trades", async () => {
|
|
268
|
+
const response = await authenticatedLighterFetch(`${getLighterBaseUrl(demo)}/api/v1/trades?${params.toString()}`, authToken);
|
|
269
|
+
return readLighterResponse(response, "/trades");
|
|
270
|
+
}, (page2) => (page2.trades ?? []).length);
|
|
256
271
|
const page = data.trades ?? [];
|
|
257
272
|
results.push(...page.filter((trade) => trade.timestamp >= since.getTime()));
|
|
258
273
|
const reachedSince = page.some((trade) => trade.timestamp < since.getTime());
|
|
@@ -269,7 +284,7 @@ async function fetchTradesSince(accountIndex, authToken, since, demo = false) {
|
|
|
269
284
|
return Array.from(byId.values());
|
|
270
285
|
}
|
|
271
286
|
__name(fetchTradesSince, "fetchTradesSince");
|
|
272
|
-
async function fetchPositionFundingSince(accountIndex, authToken, since, demo = false) {
|
|
287
|
+
async function fetchPositionFundingSince(accountIndex, authToken, since, demo = false, throttle) {
|
|
273
288
|
const results = /* @__PURE__ */ new Map();
|
|
274
289
|
const seenCursors = /* @__PURE__ */ new Set();
|
|
275
290
|
let cursor;
|
|
@@ -284,8 +299,10 @@ async function fetchPositionFundingSince(accountIndex, authToken, since, demo =
|
|
|
284
299
|
cursor
|
|
285
300
|
} : {}
|
|
286
301
|
});
|
|
287
|
-
const
|
|
288
|
-
|
|
302
|
+
const data = await gatedLighterRead(throttle, "positionFunding", async () => {
|
|
303
|
+
const response = await authenticatedLighterFetch(`${getLighterBaseUrl(demo)}/api/v1/positionFunding?${params.toString()}`, authToken);
|
|
304
|
+
return readLighterResponse(response, "/positionFunding");
|
|
305
|
+
}, (page) => (page.position_fundings ?? []).length);
|
|
289
306
|
for (const funding of data.position_fundings ?? []) {
|
|
290
307
|
if (funding.timestamp >= sinceSeconds) {
|
|
291
308
|
results.set(`${funding.market_id}:${funding.funding_id}`, funding);
|
|
@@ -374,6 +391,21 @@ async function fetchUserReferrals(params, demo = false) {
|
|
|
374
391
|
};
|
|
375
392
|
}
|
|
376
393
|
__name(fetchUserReferrals, "fetchUserReferrals");
|
|
394
|
+
async function gatedLighterRead(throttle, requestType, run, countItems) {
|
|
395
|
+
if (!throttle) {
|
|
396
|
+
return run();
|
|
397
|
+
}
|
|
398
|
+
await throttle.beforeRequest(requestType);
|
|
399
|
+
try {
|
|
400
|
+
const result = await run();
|
|
401
|
+
throttle.afterRequest(requestType, countItems(result));
|
|
402
|
+
return result;
|
|
403
|
+
} catch (error) {
|
|
404
|
+
throttle.afterRequestError(requestType, error);
|
|
405
|
+
throw error;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
__name(gatedLighterRead, "gatedLighterRead");
|
|
377
409
|
async function authenticatedLighterFetch(url, authToken, init) {
|
|
378
410
|
const headers = new Headers(init?.headers);
|
|
379
411
|
headers.set("authorization", authToken);
|
|
@@ -440,10 +472,10 @@ async function readLighterResponse(response, endpoint, acceptedCodes = [
|
|
|
440
472
|
data = void 0;
|
|
441
473
|
}
|
|
442
474
|
if (!data) {
|
|
443
|
-
throw new
|
|
475
|
+
throw new LighterRequestError(`Lighter ${endpoint} returned ${response.status}`, response.status);
|
|
444
476
|
}
|
|
445
477
|
if (!acceptedCodes.includes(data.code)) {
|
|
446
|
-
throw new
|
|
478
|
+
throw new LighterRequestError(`Lighter ${endpoint} returned ${data.code}: ${data.message ?? `HTTP ${response.status}`}`, response.status);
|
|
447
479
|
}
|
|
448
480
|
return data;
|
|
449
481
|
}
|
|
@@ -493,4 +525,4 @@ function readReferralAmount(value) {
|
|
|
493
525
|
}
|
|
494
526
|
__name(readReferralAmount, "readReferralAmount");
|
|
495
527
|
|
|
496
|
-
export { createCctpDepositIntentAddress, fetchAccount, fetchAccountLimits, fetchAccountMetadata, fetchAccountsByL1Address, fetchApiKeys, fetchAssetDetails, fetchDepositHistory, fetchDepositNetworks, fetchOrderBookDetails, fetchPositionFundingSince, fetchPublicAccount, fetchPublicOrderBookDetails, fetchTradesSince, fetchUserReferrals, fetchWithdrawHistory, submitReferralCode };
|
|
528
|
+
export { LighterRequestError, createCctpDepositIntentAddress, fetchAccount, fetchAccountLimits, fetchAccountMetadata, fetchAccountsByL1Address, fetchApiKeys, fetchAssetDetails, fetchDepositHistory, fetchDepositNetworks, fetchOrderBookDetails, fetchPositionFundingSince, fetchPublicAccount, fetchPublicOrderBookDetails, fetchTradesSince, fetchUserReferrals, fetchWithdrawHistory, submitReferralCode };
|
package/dist/index.d.ts
CHANGED
|
@@ -6,9 +6,30 @@ import { WalletClient, Transport, Chain, Account } from 'viem';
|
|
|
6
6
|
import { z } from 'zod';
|
|
7
7
|
|
|
8
8
|
type SupportedCredentials = HttpTypes.ExchangeCredentialsResponse['credentials'];
|
|
9
|
+
/**
|
|
10
|
+
* Optional pacing seam around the syncer's exchange info requests. The SDK stays
|
|
11
|
+
* rate-limit-agnostic: it only exposes when a request starts, what it returned,
|
|
12
|
+
* and when it failed — the caller owns all budget math and waiting.
|
|
13
|
+
*/
|
|
14
|
+
type SyncerThrottle = {
|
|
15
|
+
/** Awaited before the request fires; the caller blocks here until its budget allows the call. */
|
|
16
|
+
beforeRequest(requestType: string): Promise<void>;
|
|
17
|
+
/** Called after a successful response; `itemCount` is the response array length (0 for object responses). */
|
|
18
|
+
afterRequest(requestType: string, itemCount: number): void;
|
|
19
|
+
/** Called when the request threw, before the error propagates; lets the caller inspect rate-limit rejections. */
|
|
20
|
+
afterRequestError(requestType: string, error: unknown): void;
|
|
21
|
+
};
|
|
9
22
|
type ExchangesSDKConfig = {
|
|
10
23
|
sdk: PearSDK;
|
|
11
24
|
demo?: boolean;
|
|
25
|
+
/** Optional pacing seam around the syncer's exchange info requests; absent = unthrottled (current behavior). */
|
|
26
|
+
throttle?: SyncerThrottle;
|
|
27
|
+
/**
|
|
28
|
+
* Optional pre-fetched Hyperliquid perp-dex names ('' = the main dex). The list is
|
|
29
|
+
* global (identical for every account), so a batch caller fetches it once per run and
|
|
30
|
+
* passes it here; absent = the syncer fetches it per sync (current behavior).
|
|
31
|
+
*/
|
|
32
|
+
hyperliquidPerpDexNames?: string[];
|
|
12
33
|
/**
|
|
13
34
|
* Optional forward-proxy for the exchange REST calls. When enabled, requests are re-pointed at
|
|
14
35
|
* `proxy.url` with the original venue host in `X-Proxy-Target`. Injected here because the SDK
|
|
@@ -918,6 +939,10 @@ interface AccountSyncerConfig {
|
|
|
918
939
|
account: TradeAccount;
|
|
919
940
|
credentials: SupportedCredentials;
|
|
920
941
|
demo: boolean;
|
|
942
|
+
/** Optional pacing seam around the exchange info requests; absent = unthrottled (current behavior). */
|
|
943
|
+
throttle?: SyncerThrottle;
|
|
944
|
+
/** Optional pre-fetched Hyperliquid perp-dex names ('' = the main dex); absent = fetched per sync. */
|
|
945
|
+
hyperliquidPerpDexNames?: string[];
|
|
921
946
|
}
|
|
922
947
|
/**
|
|
923
948
|
* Outcome of one fill sync cycle, so batch/cron callers can tell a completed
|
|
@@ -959,6 +984,7 @@ declare abstract class BaseAccountSyncer<ExternalFill> implements AccountSyncer
|
|
|
959
984
|
protected account: TradeAccount;
|
|
960
985
|
protected credentials: SupportedCredentials;
|
|
961
986
|
protected demo: boolean;
|
|
987
|
+
protected throttle: SyncerThrottle | undefined;
|
|
962
988
|
constructor(config: AccountSyncerConfig);
|
|
963
989
|
/**
|
|
964
990
|
* Fetch the account's currently-open positions from the exchange, normalized
|
|
@@ -1125,11 +1151,19 @@ type UserFillsByTimeResponse = {
|
|
|
1125
1151
|
type HyperliquidRawFill = UserFillsByTimeResponse;
|
|
1126
1152
|
declare class HyperliquidAccountSyncer extends BaseAccountSyncer<HyperliquidRawFill> {
|
|
1127
1153
|
private readonly address;
|
|
1154
|
+
private readonly perpDexNames;
|
|
1128
1155
|
constructor(config: AccountSyncerConfig);
|
|
1129
1156
|
protected listExternalPositions({ instruments, }: ListExternalPositionsParams): Promise<HttpTypes.ExternalPosition[]>;
|
|
1130
1157
|
protected listExternalFills({ since, instruments, }: ListExternalFillsParams): Promise<HttpTypes.UnknownExternalFill[]>;
|
|
1131
1158
|
protected listExternalFunding({ since, instruments, }: ListExternalFundingParams): Promise<HttpTypes.FundingPaymentEntry[]>;
|
|
1132
1159
|
protected isReduceOnly(rawFill: HyperliquidRawFill): boolean;
|
|
1160
|
+
/** Fetch the perp-dex descriptors and reduce them to unique dex names ('' = the main dex). */
|
|
1161
|
+
private fetchPerpDexNames;
|
|
1162
|
+
/**
|
|
1163
|
+
* Route one info request through the optional throttle seam: gate before the
|
|
1164
|
+
* call, report the response size after, surface a failure before it propagates.
|
|
1165
|
+
*/
|
|
1166
|
+
private fetchInfoGated;
|
|
1133
1167
|
}
|
|
1134
1168
|
|
|
1135
1169
|
type RawFill$1 = LighterRawTrade;
|
|
@@ -2531,6 +2565,8 @@ declare function createAccountTracker(exchange: Connector, config: CreateAccount
|
|
|
2531
2565
|
declare class ExchangesSDK {
|
|
2532
2566
|
private sdk;
|
|
2533
2567
|
private demo;
|
|
2568
|
+
private throttle;
|
|
2569
|
+
private hyperliquidPerpDexNames;
|
|
2534
2570
|
constructor(config: ExchangesSDKConfig);
|
|
2535
2571
|
connect(tradeAccountId: string): Promise<ExchangeConnection>;
|
|
2536
2572
|
/**
|
|
@@ -2548,4 +2584,4 @@ declare class ExchangesSDK {
|
|
|
2548
2584
|
private fetchCredentials;
|
|
2549
2585
|
}
|
|
2550
2586
|
|
|
2551
|
-
export { ACCOUNT_MODE_LABELS, ASSET_DECIMALS, AccountBalance, AccountBalanceCore, type AccountHealthStatus, AccountMode, type AccountPosition, type AccountSnapshot, type AccountStatus, type AccountSyncer, type AccountSyncerConfig, type AccountTierCallback, type AccountTracker, type AccountTrackerConfig, type AccountWarningReason, type ApiKey, type ApproveIntegratorParams, type ApproveIntegratorResult, AssetId, type AssetSnapshotMap, type BalanceCallback, BaseAccountSyncer, BaseAccountTracker, BaseWs, BinanceAccountSyncer, BinanceAccountTracker, type BinanceAccountTrackerConfig, BinanceExchangeWs, BinanceMultiAssetBalance, BinanceSingleAssetBalance, BinanceUserDataWs, type BinanceUserDataWsConfig, BinanceWsApi, type BinanceWsApiConfig, BybitAccountSyncer, BybitAccountTracker, type BybitAccountTrackerConfig, BybitExchangeWs, BybitIsolatedMarginBalance, BybitPortfolioMarginBalance, BybitRegularMarginBalance, BybitWs, type BybitWsConfig, type CctpDepositAddressParams, type CctpDepositAddressResult, type CctpDepositHistorySettlement, type CctpDepositParams, type CctpDepositRegistrationSettlement, type CctpDepositResult, type CctpDepositSettlement, type ChangeAccountTierParams, type ChangeAccountTierResult, type CheckApiWalletParams, CollateralBalance, type ConnectOptions, type ConnectWalletParams, type ConnectWalletResult, type CreateAccountTrackerConfig, type CreateExchangeWsConfig, DecimalString, type EthereumDepositParams, type EthereumDepositResult, type ExchangeConnection, type ExchangeHelperExchange, type ExchangeHelperMap, type ExchangeState, ExchangeWs, type ExchangeWsByConnector, ExchangesSDK, type ExchangesSDKConfig, FUNXYZ_DEPOSIT_MINIMUMS_USD, FUNXYZ_ETHEREUM_MAINNET_CHAIN_ID, FUNXYZ_EVM_CHAIN_NAMES, type FastWithdrawParams, type FastWithdrawResult, type FillSyncOutcome, type FundingSyncOutcome, type FunxyzAccountState, type FunxyzAsset, type FunxyzDepositAddressParams, type FunxyzDepositAddressResult, type FunxyzDepositCredit, type FunxyzDepositParams, type FunxyzDepositResult, type FunxyzDepositSettlement, type FunxyzDepositSource, type FunxyzMarket, HyperliquidAccountSyncer, HyperliquidAccountTracker, type HyperliquidAccountTrackerConfig, HyperliquidDexState, HyperliquidExchangeWs, type HyperliquidHelper, HyperliquidPortfolioMarginBalance, HyperliquidPortfolioMarginCollateral, HyperliquidStandardBalance, HyperliquidUnifiedBalance, HyperliquidWs, type IntegratorApprovalRequirements, L2_ASSET_DECIMALS, LIGHTER_NATIVE_USDC_ADDRESSES, LIGHTER_USDC_DECIMALS, LighterAccountSyncer, type LighterAccountTier, LighterAccountTracker, type LighterAccountTrackerConfig, type LighterApplyReferralCodeParams, type LighterAuthCredentials, LighterClassicBalance, type LighterDeposit, type LighterDepositAddressParams, type LighterDepositAddressResult, type LighterDepositCredit, type LighterDepositHistoryParams, type LighterDepositNetwork, type LighterDepositPage, type LighterDepositParams, type LighterDepositProgress, type LighterDepositResult, type LighterDepositStatus, type LighterDepositWalletAdapter, LighterExchangeWs, type LighterHelper, type LighterLookupResult, type LighterOnboardingStatus, type LighterReferral, type LighterReferralTotals, type LighterReferralTradeStats, LighterUnifiedBalance, type LighterUserReferrals, type LighterUserReferralsParams, type LighterWithdraw, type LighterWithdrawHistoryParams, type LighterWithdrawPage, type LighterWithdrawStatus, type LighterWithdrawType, LighterWs, type ListExternalFillsParams, type ListExternalFundingParams, type ListExternalPositionsParams, MAX_API_KEY_INDEX, MIN_LIGHTER_CCTP_DEPOSIT_USDC, MIN_LIGHTER_FAST_WITHDRAW_USDC, MIN_USER_API_KEY_INDEX, MarginMode, type MessageListener, OkxAccountSyncer, OkxAccountTracker, type OkxAccountTrackerConfig, OkxExchangeWs, OkxFuturesBalance, OkxMultiCurrencyMarginBalance, OkxPortfolioMarginBalance, OkxSpotBalance, OkxWs, type OkxWsConfig, type OpenListener, type PositionsCallback, RouteType, Side, SignedDecimalString, type StateUpdate, type SupportedCredentials, type TrackedAssetCallback, type TrackedAssetInfo, type WalletClientWithAccount, type WithdrawParams, type WithdrawResult, type WsMessage, createAccountSyncer, createAccountTracker, createExchangeWs, createHyperliquidHelper, createLighterHelper, findAvailableApiKeyIndex, getAssetDecimals, getLighterNativeUsdcAddress, listFunxyzTransferableChains, readFunxyzChainSource, readFunxyzMinimumUsd, retrieveLighterAuthToken, usdcAbi };
|
|
2587
|
+
export { ACCOUNT_MODE_LABELS, ASSET_DECIMALS, AccountBalance, AccountBalanceCore, type AccountHealthStatus, AccountMode, type AccountPosition, type AccountSnapshot, type AccountStatus, type AccountSyncer, type AccountSyncerConfig, type AccountTierCallback, type AccountTracker, type AccountTrackerConfig, type AccountWarningReason, type ApiKey, type ApproveIntegratorParams, type ApproveIntegratorResult, AssetId, type AssetSnapshotMap, type BalanceCallback, BaseAccountSyncer, BaseAccountTracker, BaseWs, BinanceAccountSyncer, BinanceAccountTracker, type BinanceAccountTrackerConfig, BinanceExchangeWs, BinanceMultiAssetBalance, BinanceSingleAssetBalance, BinanceUserDataWs, type BinanceUserDataWsConfig, BinanceWsApi, type BinanceWsApiConfig, BybitAccountSyncer, BybitAccountTracker, type BybitAccountTrackerConfig, BybitExchangeWs, BybitIsolatedMarginBalance, BybitPortfolioMarginBalance, BybitRegularMarginBalance, BybitWs, type BybitWsConfig, type CctpDepositAddressParams, type CctpDepositAddressResult, type CctpDepositHistorySettlement, type CctpDepositParams, type CctpDepositRegistrationSettlement, type CctpDepositResult, type CctpDepositSettlement, type ChangeAccountTierParams, type ChangeAccountTierResult, type CheckApiWalletParams, CollateralBalance, type ConnectOptions, type ConnectWalletParams, type ConnectWalletResult, type CreateAccountTrackerConfig, type CreateExchangeWsConfig, DecimalString, type EthereumDepositParams, type EthereumDepositResult, type ExchangeConnection, type ExchangeHelperExchange, type ExchangeHelperMap, type ExchangeState, ExchangeWs, type ExchangeWsByConnector, ExchangesSDK, type ExchangesSDKConfig, FUNXYZ_DEPOSIT_MINIMUMS_USD, FUNXYZ_ETHEREUM_MAINNET_CHAIN_ID, FUNXYZ_EVM_CHAIN_NAMES, type FastWithdrawParams, type FastWithdrawResult, type FillSyncOutcome, type FundingSyncOutcome, type FunxyzAccountState, type FunxyzAsset, type FunxyzDepositAddressParams, type FunxyzDepositAddressResult, type FunxyzDepositCredit, type FunxyzDepositParams, type FunxyzDepositResult, type FunxyzDepositSettlement, type FunxyzDepositSource, type FunxyzMarket, HyperliquidAccountSyncer, HyperliquidAccountTracker, type HyperliquidAccountTrackerConfig, HyperliquidDexState, HyperliquidExchangeWs, type HyperliquidHelper, HyperliquidPortfolioMarginBalance, HyperliquidPortfolioMarginCollateral, HyperliquidStandardBalance, HyperliquidUnifiedBalance, HyperliquidWs, type IntegratorApprovalRequirements, L2_ASSET_DECIMALS, LIGHTER_NATIVE_USDC_ADDRESSES, LIGHTER_USDC_DECIMALS, LighterAccountSyncer, type LighterAccountTier, LighterAccountTracker, type LighterAccountTrackerConfig, type LighterApplyReferralCodeParams, type LighterAuthCredentials, LighterClassicBalance, type LighterDeposit, type LighterDepositAddressParams, type LighterDepositAddressResult, type LighterDepositCredit, type LighterDepositHistoryParams, type LighterDepositNetwork, type LighterDepositPage, type LighterDepositParams, type LighterDepositProgress, type LighterDepositResult, type LighterDepositStatus, type LighterDepositWalletAdapter, LighterExchangeWs, type LighterHelper, type LighterLookupResult, type LighterOnboardingStatus, type LighterReferral, type LighterReferralTotals, type LighterReferralTradeStats, LighterUnifiedBalance, type LighterUserReferrals, type LighterUserReferralsParams, type LighterWithdraw, type LighterWithdrawHistoryParams, type LighterWithdrawPage, type LighterWithdrawStatus, type LighterWithdrawType, LighterWs, type ListExternalFillsParams, type ListExternalFundingParams, type ListExternalPositionsParams, MAX_API_KEY_INDEX, MIN_LIGHTER_CCTP_DEPOSIT_USDC, MIN_LIGHTER_FAST_WITHDRAW_USDC, MIN_USER_API_KEY_INDEX, MarginMode, type MessageListener, OkxAccountSyncer, OkxAccountTracker, type OkxAccountTrackerConfig, OkxExchangeWs, OkxFuturesBalance, OkxMultiCurrencyMarginBalance, OkxPortfolioMarginBalance, OkxSpotBalance, OkxWs, type OkxWsConfig, type OpenListener, type PositionsCallback, RouteType, Side, SignedDecimalString, type StateUpdate, type SupportedCredentials, type SyncerThrottle, type TrackedAssetCallback, type TrackedAssetInfo, type WalletClientWithAccount, type WithdrawParams, type WithdrawResult, type WsMessage, createAccountSyncer, createAccountTracker, createExchangeWs, createHyperliquidHelper, createLighterHelper, findAvailableApiKeyIndex, getAssetDecimals, getLighterNativeUsdcAddress, listFunxyzTransferableChains, readFunxyzChainSource, readFunxyzMinimumUsd, retrieveLighterAuthToken, usdcAbi };
|
package/dist/sdk.js
CHANGED
|
@@ -12,9 +12,13 @@ class ExchangesSDK {
|
|
|
12
12
|
}
|
|
13
13
|
sdk;
|
|
14
14
|
demo;
|
|
15
|
+
throttle;
|
|
16
|
+
hyperliquidPerpDexNames;
|
|
15
17
|
constructor(config) {
|
|
16
18
|
this.sdk = config.sdk;
|
|
17
19
|
this.demo = config.demo ?? false;
|
|
20
|
+
this.throttle = config.throttle;
|
|
21
|
+
this.hyperliquidPerpDexNames = config.hyperliquidPerpDexNames;
|
|
18
22
|
if (config.proxy) configureProxy(config.proxy);
|
|
19
23
|
}
|
|
20
24
|
async connect(tradeAccountId) {
|
|
@@ -67,7 +71,9 @@ class ExchangesSDK {
|
|
|
67
71
|
connector: connection.connector,
|
|
68
72
|
account: connection.account,
|
|
69
73
|
credentials: connection.credentials,
|
|
70
|
-
demo: this.demo
|
|
74
|
+
demo: this.demo,
|
|
75
|
+
throttle: this.throttle,
|
|
76
|
+
hyperliquidPerpDexNames: this.hyperliquidPerpDexNames
|
|
71
77
|
});
|
|
72
78
|
}
|
|
73
79
|
buildTracker(connection) {
|
package/dist/syncer/base.js
CHANGED
|
@@ -12,12 +12,14 @@ class BaseAccountSyncer {
|
|
|
12
12
|
account;
|
|
13
13
|
credentials;
|
|
14
14
|
demo;
|
|
15
|
+
throttle;
|
|
15
16
|
constructor(config) {
|
|
16
17
|
this.sdk = config.sdk;
|
|
17
18
|
this.connector = config.connector;
|
|
18
19
|
this.account = config.account;
|
|
19
20
|
this.credentials = config.credentials;
|
|
20
21
|
this.demo = config.demo;
|
|
22
|
+
this.throttle = config.throttle;
|
|
21
23
|
}
|
|
22
24
|
// Phase A: Load current Pear state (positions, fills, instruments, watermark).
|
|
23
25
|
async loadPearState() {
|
|
@@ -11,9 +11,11 @@ class HyperliquidAccountSyncer extends BaseAccountSyncer {
|
|
|
11
11
|
__name(this, "HyperliquidAccountSyncer");
|
|
12
12
|
}
|
|
13
13
|
address;
|
|
14
|
+
perpDexNames;
|
|
14
15
|
constructor(config) {
|
|
15
16
|
super(config);
|
|
16
17
|
this.address = config.account.exchangeIdentifier;
|
|
18
|
+
this.perpDexNames = config.hyperliquidPerpDexNames;
|
|
17
19
|
}
|
|
18
20
|
async listExternalPositions({ instruments }) {
|
|
19
21
|
const instrumentByBase = new Map(instruments.map((instrument) => [
|
|
@@ -23,17 +25,12 @@ class HyperliquidAccountSyncer extends BaseAccountSyncer {
|
|
|
23
25
|
contractSize: instrument.precision.quantity.contractSize
|
|
24
26
|
}
|
|
25
27
|
]));
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
}, this.demo);
|
|
29
|
-
const dexNames = [
|
|
30
|
-
...new Set(perpDexs.map((perpDex) => perpDex?.name ?? ""))
|
|
31
|
-
];
|
|
32
|
-
const states = await Promise.all(dexNames.map((dex) => fetchInfo({
|
|
28
|
+
const dexNames = this.perpDexNames ?? await this.fetchPerpDexNames();
|
|
29
|
+
const states = await Promise.all(dexNames.map((dex) => this.fetchInfoGated({
|
|
33
30
|
type: "clearinghouseState",
|
|
34
31
|
user: this.address,
|
|
35
32
|
dex
|
|
36
|
-
}
|
|
33
|
+
})));
|
|
37
34
|
const assetPositions = states.flatMap((state) => state.assetPositions);
|
|
38
35
|
return assetPositions.reduce((positions, { position: rawPosition }) => {
|
|
39
36
|
const szi = new BigNumber(rawPosition.szi);
|
|
@@ -72,12 +69,12 @@ class HyperliquidAccountSyncer extends BaseAccountSyncer {
|
|
|
72
69
|
let cursor = since.getTime();
|
|
73
70
|
let batchSize;
|
|
74
71
|
do {
|
|
75
|
-
const batch = await
|
|
72
|
+
const batch = await this.fetchInfoGated({
|
|
76
73
|
type: "userFillsByTime",
|
|
77
74
|
user: this.address,
|
|
78
75
|
startTime: cursor,
|
|
79
76
|
aggregateByTime: true
|
|
80
|
-
}
|
|
77
|
+
});
|
|
81
78
|
batchSize = batch.length;
|
|
82
79
|
for (const rawFill of batch) {
|
|
83
80
|
addFill(rawFill);
|
|
@@ -93,12 +90,12 @@ class HyperliquidAccountSyncer extends BaseAccountSyncer {
|
|
|
93
90
|
} while (batchSize === HYPERLIQUID_FILL_PAGE_LIMIT);
|
|
94
91
|
cursor = since.getTime();
|
|
95
92
|
do {
|
|
96
|
-
const twapBatch = await
|
|
93
|
+
const twapBatch = await this.fetchInfoGated({
|
|
97
94
|
type: "userTwapSliceFillsByTime",
|
|
98
95
|
user: this.address,
|
|
99
96
|
startTime: cursor,
|
|
100
97
|
aggregateByTime: true
|
|
101
|
-
}
|
|
98
|
+
});
|
|
102
99
|
batchSize = twapBatch.length;
|
|
103
100
|
for (const item of twapBatch) {
|
|
104
101
|
addFill(item.fill);
|
|
@@ -149,11 +146,11 @@ class HyperliquidAccountSyncer extends BaseAccountSyncer {
|
|
|
149
146
|
let cursor = since.getTime();
|
|
150
147
|
let batchSize;
|
|
151
148
|
do {
|
|
152
|
-
const batch = await
|
|
149
|
+
const batch = await this.fetchInfoGated({
|
|
153
150
|
type: "userFunding",
|
|
154
151
|
user: this.address,
|
|
155
152
|
startTime: cursor
|
|
156
|
-
}
|
|
153
|
+
});
|
|
157
154
|
batchSize = batch.length;
|
|
158
155
|
for (const event of batch) {
|
|
159
156
|
allEvents.set(`${event.time}:${event.delta.coin}:${event.hash}`, event);
|
|
@@ -174,6 +171,33 @@ class HyperliquidAccountSyncer extends BaseAccountSyncer {
|
|
|
174
171
|
isReduceOnly(rawFill) {
|
|
175
172
|
return rawFill.dir.includes("Close");
|
|
176
173
|
}
|
|
174
|
+
/** Fetch the perp-dex descriptors and reduce them to unique dex names ('' = the main dex). */
|
|
175
|
+
async fetchPerpDexNames() {
|
|
176
|
+
const perpDexs = await this.fetchInfoGated({
|
|
177
|
+
type: "perpDexs"
|
|
178
|
+
});
|
|
179
|
+
return [
|
|
180
|
+
...new Set(perpDexs.map((perpDex) => perpDex?.name ?? ""))
|
|
181
|
+
];
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Route one info request through the optional throttle seam: gate before the
|
|
185
|
+
* call, report the response size after, surface a failure before it propagates.
|
|
186
|
+
*/
|
|
187
|
+
async fetchInfoGated(body) {
|
|
188
|
+
if (!this.throttle) {
|
|
189
|
+
return fetchInfo(body, this.demo);
|
|
190
|
+
}
|
|
191
|
+
await this.throttle.beforeRequest(body.type);
|
|
192
|
+
try {
|
|
193
|
+
const response = await fetchInfo(body, this.demo);
|
|
194
|
+
this.throttle.afterRequest(body.type, Array.isArray(response) ? response.length : 0);
|
|
195
|
+
return response;
|
|
196
|
+
} catch (error) {
|
|
197
|
+
this.throttle.afterRequestError(body.type, error);
|
|
198
|
+
throw error;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
177
201
|
}
|
|
178
202
|
function warnStalledPagination(stream, cursor) {
|
|
179
203
|
console.warn(`Hyperliquid ${stream} pagination stalled at timestamp ${cursor}; returned history may be incomplete.`);
|
|
@@ -36,7 +36,7 @@ class LighterAccountSyncer extends BaseAccountSyncer {
|
|
|
36
36
|
instrument.precision.quantity.contractSize
|
|
37
37
|
]));
|
|
38
38
|
const token = await this.retrieveAuthToken();
|
|
39
|
-
const response = await fetchAccount(this.accountIndex, token, this.demo);
|
|
39
|
+
const response = await fetchAccount(this.accountIndex, token, this.demo, this.throttle);
|
|
40
40
|
const rawPositions = response.accounts?.[0]?.positions ?? [];
|
|
41
41
|
return rawPositions.reduce((positions, rawPosition) => {
|
|
42
42
|
const instrumentId = rawPosition.market_id.toString();
|
|
@@ -59,7 +59,7 @@ class LighterAccountSyncer extends BaseAccountSyncer {
|
|
|
59
59
|
async listExternalFills({ since, instruments }) {
|
|
60
60
|
this.assertAuthenticatedSyncAvailable();
|
|
61
61
|
const token = await this.retrieveAuthToken();
|
|
62
|
-
const trades = await fetchTradesSince(this.accountIndex, token, since, this.demo);
|
|
62
|
+
const trades = await fetchTradesSince(this.accountIndex, token, since, this.demo, this.throttle);
|
|
63
63
|
const instrumentIds = new Set(instruments.map((instrument) => instrument.id));
|
|
64
64
|
return trades.toSorted((a, b) => a.timestamp - b.timestamp).reduce((fills, rawFill) => {
|
|
65
65
|
const instrumentId = rawFill.market_id.toString();
|
|
@@ -92,7 +92,7 @@ class LighterAccountSyncer extends BaseAccountSyncer {
|
|
|
92
92
|
async listExternalFunding({ since, instruments }) {
|
|
93
93
|
this.assertAuthenticatedSyncAvailable();
|
|
94
94
|
const token = await this.retrieveAuthToken();
|
|
95
|
-
const fundingEvents = await fetchPositionFundingSince(this.accountIndex, token, since, this.demo);
|
|
95
|
+
const fundingEvents = await fetchPositionFundingSince(this.accountIndex, token, since, this.demo, this.throttle);
|
|
96
96
|
const instrumentIds = new Set(instruments.map((instrument) => instrument.id));
|
|
97
97
|
return toFundingPaymentEntries(fundingEvents, instrumentIds);
|
|
98
98
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pear-protocol/exchanges-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Pear Protocol Exchanges SDK",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -27,9 +27,9 @@
|
|
|
27
27
|
"test:watch": "vitest"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@pear-protocol/core-sdk": "^1.
|
|
31
|
-
"@pear-protocol/types": "^1.
|
|
32
|
-
"@pear-protocol/utils": "^0.
|
|
30
|
+
"@pear-protocol/core-sdk": "^1.20.0",
|
|
31
|
+
"@pear-protocol/types": "^1.32.0",
|
|
32
|
+
"@pear-protocol/utils": "^0.8.1",
|
|
33
33
|
"bignumber.js": "^11.1.1",
|
|
34
34
|
"partysocket": "^1.0.3",
|
|
35
35
|
"viem": "^2.48.8",
|