@pear-protocol/exchanges-sdk 0.15.0 → 0.16.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 +14 -1
- package/dist/index.d.ts +58 -6
- package/dist/tracker/hyperliquid/balance.js +37 -2
- package/dist/tracker/hyperliquid/borrow-lend.js +32 -0
- package/dist/tracker/hyperliquid/mapper.js +53 -1
- package/dist/tracker/hyperliquid/tracker.js +77 -2
- package/dist/tracker/index.js +1 -1
- package/package.json +1 -1
|
@@ -86,6 +86,19 @@ async function fetchUserVaultEquities(user, demo = false) {
|
|
|
86
86
|
}, demo);
|
|
87
87
|
}
|
|
88
88
|
__name(fetchUserVaultEquities, "fetchUserVaultEquities");
|
|
89
|
+
async function fetchBorrowLendUserState(user, demo = false) {
|
|
90
|
+
return fetchInfo({
|
|
91
|
+
type: "borrowLendUserState",
|
|
92
|
+
user
|
|
93
|
+
}, demo);
|
|
94
|
+
}
|
|
95
|
+
__name(fetchBorrowLendUserState, "fetchBorrowLendUserState");
|
|
96
|
+
async function fetchAllBorrowLendReserveStates(demo = false) {
|
|
97
|
+
return fetchInfo({
|
|
98
|
+
type: "allBorrowLendReserveStates"
|
|
99
|
+
}, demo);
|
|
100
|
+
}
|
|
101
|
+
__name(fetchAllBorrowLendReserveStates, "fetchAllBorrowLendReserveStates");
|
|
89
102
|
async function fetchActiveAssetData(user, coin, demo = false) {
|
|
90
103
|
return fetchInfo({
|
|
91
104
|
type: "activeAssetData",
|
|
@@ -95,4 +108,4 @@ async function fetchActiveAssetData(user, coin, demo = false) {
|
|
|
95
108
|
}
|
|
96
109
|
__name(fetchActiveAssetData, "fetchActiveAssetData");
|
|
97
110
|
|
|
98
|
-
export { HyperliquidInfoRequestError, fetchActiveAssetData, fetchAllMids, fetchClearinghouseState, fetchDelegatorSummary, fetchInfo, fetchPerpDexs, fetchSpotClearinghouseState, fetchUserAbstraction, fetchUserRole, fetchUserVaultEquities };
|
|
111
|
+
export { HyperliquidInfoRequestError, fetchActiveAssetData, fetchAllBorrowLendReserveStates, fetchAllMids, fetchBorrowLendUserState, fetchClearinghouseState, fetchDelegatorSummary, fetchInfo, fetchPerpDexs, fetchSpotClearinghouseState, fetchUserAbstraction, fetchUserRole, fetchUserVaultEquities };
|
package/dist/index.d.ts
CHANGED
|
@@ -1447,6 +1447,7 @@ declare const AccountBalance: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
1447
1447
|
withdrawable: z.ZodString;
|
|
1448
1448
|
ltv: z.ZodNullable<z.ZodString>;
|
|
1449
1449
|
borrowCapUsed: z.ZodNullable<z.ZodString>;
|
|
1450
|
+
borrowed: z.ZodString;
|
|
1450
1451
|
}, z.core.$strip>>;
|
|
1451
1452
|
tradingEquity: z.ZodNullable<z.ZodString>;
|
|
1452
1453
|
vaultEquity: z.ZodString;
|
|
@@ -1458,6 +1459,13 @@ declare const AccountBalance: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
1458
1459
|
portfolioMarginRatio: z.ZodNullable<z.ZodString>;
|
|
1459
1460
|
portfolioAccountLeverage: z.ZodNullable<z.ZodString>;
|
|
1460
1461
|
borrowCapUsed: z.ZodNullable<z.ZodString>;
|
|
1462
|
+
borrowedValue: z.ZodNullable<z.ZodString>;
|
|
1463
|
+
healthFactor: z.ZodNullable<z.ZodString>;
|
|
1464
|
+
borrowLendReserves: z.ZodArray<z.ZodObject<{
|
|
1465
|
+
asset: z.ZodString;
|
|
1466
|
+
borrowYearlyRate: z.ZodString;
|
|
1467
|
+
supplyYearlyRate: z.ZodString;
|
|
1468
|
+
}, z.core.$strip>>;
|
|
1461
1469
|
perDexState: z.ZodArray<z.ZodObject<{
|
|
1462
1470
|
dex: z.ZodString;
|
|
1463
1471
|
collateralToken: z.ZodNullable<z.ZodNumber>;
|
|
@@ -2174,8 +2182,9 @@ type HyperliquidUnifiedBalance = z.infer<typeof HyperliquidUnifiedBalance>;
|
|
|
2174
2182
|
* accounts measured hold one — `0x0871deb3…` reports USDC at −957,802.15. An unsigned row cannot
|
|
2175
2183
|
* state that at all, which is the defect that made a borrowed pool indistinguishable from an
|
|
2176
2184
|
* untouched one.
|
|
2177
|
-
* - **
|
|
2178
|
-
* beside the quantities, and both are PM-only wire fields.
|
|
2185
|
+
* - **three more columns.** `ltv` and `borrowCapUsed` are per-coin risk weights the venue renders
|
|
2186
|
+
* beside the quantities, and both are PM-only wire fields. `borrowed`, the coin's outstanding
|
|
2187
|
+
* debt, is the third, and PM-only as well.
|
|
2179
2188
|
*
|
|
2180
2189
|
* The row is otherwise the shared shape: same keys, same meanings, so a consumer reading
|
|
2181
2190
|
* `perCollateral` without narrowing still reads `asset` / `equity` / `availableMargin` /
|
|
@@ -2188,8 +2197,16 @@ declare const HyperliquidPortfolioMarginCollateral: z.ZodObject<{
|
|
|
2188
2197
|
withdrawable: z.ZodString;
|
|
2189
2198
|
ltv: z.ZodNullable<z.ZodString>;
|
|
2190
2199
|
borrowCapUsed: z.ZodNullable<z.ZodString>;
|
|
2200
|
+
borrowed: z.ZodString;
|
|
2191
2201
|
}, z.core.$strip>;
|
|
2192
2202
|
type HyperliquidPortfolioMarginCollateral = z.infer<typeof HyperliquidPortfolioMarginCollateral>;
|
|
2203
|
+
/** One borrow/lend reserve's yearly rates, named by its coin's wire name. */
|
|
2204
|
+
declare const HyperliquidBorrowLendReserve: z.ZodObject<{
|
|
2205
|
+
asset: z.ZodString;
|
|
2206
|
+
borrowYearlyRate: z.ZodString;
|
|
2207
|
+
supplyYearlyRate: z.ZodString;
|
|
2208
|
+
}, z.core.$strip>;
|
|
2209
|
+
type HyperliquidBorrowLendReserve = z.infer<typeof HyperliquidBorrowLendReserve>;
|
|
2193
2210
|
declare const HyperliquidPortfolioMarginBalance: z.ZodObject<{
|
|
2194
2211
|
totalEquity: z.ZodNullable<z.ZodString>;
|
|
2195
2212
|
withdrawableBalance: z.ZodNullable<z.ZodString>;
|
|
@@ -2204,6 +2221,7 @@ declare const HyperliquidPortfolioMarginBalance: z.ZodObject<{
|
|
|
2204
2221
|
withdrawable: z.ZodString;
|
|
2205
2222
|
ltv: z.ZodNullable<z.ZodString>;
|
|
2206
2223
|
borrowCapUsed: z.ZodNullable<z.ZodString>;
|
|
2224
|
+
borrowed: z.ZodString;
|
|
2207
2225
|
}, z.core.$strip>>;
|
|
2208
2226
|
tradingEquity: z.ZodNullable<z.ZodString>;
|
|
2209
2227
|
vaultEquity: z.ZodString;
|
|
@@ -2215,6 +2233,13 @@ declare const HyperliquidPortfolioMarginBalance: z.ZodObject<{
|
|
|
2215
2233
|
portfolioMarginRatio: z.ZodNullable<z.ZodString>;
|
|
2216
2234
|
portfolioAccountLeverage: z.ZodNullable<z.ZodString>;
|
|
2217
2235
|
borrowCapUsed: z.ZodNullable<z.ZodString>;
|
|
2236
|
+
borrowedValue: z.ZodNullable<z.ZodString>;
|
|
2237
|
+
healthFactor: z.ZodNullable<z.ZodString>;
|
|
2238
|
+
borrowLendReserves: z.ZodArray<z.ZodObject<{
|
|
2239
|
+
asset: z.ZodString;
|
|
2240
|
+
borrowYearlyRate: z.ZodString;
|
|
2241
|
+
supplyYearlyRate: z.ZodString;
|
|
2242
|
+
}, z.core.$strip>>;
|
|
2218
2243
|
perDexState: z.ZodArray<z.ZodObject<{
|
|
2219
2244
|
dex: z.ZodString;
|
|
2220
2245
|
collateralToken: z.ZodNullable<z.ZodNumber>;
|
|
@@ -2232,9 +2257,10 @@ type HyperliquidPortfolioMarginBalance = z.infer<typeof HyperliquidPortfolioMarg
|
|
|
2232
2257
|
* Both fill the same `HyperliquidBalanceContext` and hand it to the same mapper, which is what
|
|
2233
2258
|
* makes "same account state, same balance" true across two different transports. The tracker takes
|
|
2234
2259
|
* every CHANGING value off a channel — `allDexsClearinghouseState`, `spotState`, `webData3`,
|
|
2235
|
-
* `allMids`, `activeAssetData` — including vault equity, which rides `webData3
|
|
2236
|
-
*
|
|
2237
|
-
*
|
|
2260
|
+
* `allMids`, `activeAssetData` — including vault equity, which rides `webData3`, save one:
|
|
2261
|
+
* Portfolio Margin's health factor and reserve rates ride no channel, so it polls them while the
|
|
2262
|
+
* account is in that mode. Its only other REST reads happen at `start()`: the static dex metadata,
|
|
2263
|
+
* and the staking position, which the venue publishes on no channel at all.
|
|
2238
2264
|
*
|
|
2239
2265
|
* The snapshot has no channels, so it reads the same figures over REST — vault equity from
|
|
2240
2266
|
* `userVaultEquities`, which was measured equal to the `webData3` figure on ten live accounts.
|
|
@@ -2256,6 +2282,11 @@ declare class HyperliquidAccountTracker extends BaseAccountTracker {
|
|
|
2256
2282
|
/** Portfolio Margin's own risk scalars, which ride the same `spotState` frame the balances do. */
|
|
2257
2283
|
private portfolioMarginRatio;
|
|
2258
2284
|
private borrowRatioByToken;
|
|
2285
|
+
/** Portfolio Margin's REST-only figures, and the timer that keeps them fresh while in that mode. */
|
|
2286
|
+
private borrowLend;
|
|
2287
|
+
private borrowLendPollTimer;
|
|
2288
|
+
/** Advances on every stop, so a read fired in an earlier poll period is recognised and dropped. */
|
|
2289
|
+
private borrowLendPollGeneration;
|
|
2259
2290
|
private hasSpotState;
|
|
2260
2291
|
private hasClearinghouseState;
|
|
2261
2292
|
private accountType;
|
|
@@ -2314,6 +2345,27 @@ declare class HyperliquidAccountTracker extends BaseAccountTracker {
|
|
|
2314
2345
|
* vault. Partial equity is worse than no equity, so nothing is published early.
|
|
2315
2346
|
*/
|
|
2316
2347
|
private buildBalance;
|
|
2348
|
+
/**
|
|
2349
|
+
* Runs the borrow/lend poll exactly while the account is in Portfolio Margin.
|
|
2350
|
+
*
|
|
2351
|
+
* Safe to call on every mode read: a poll already in the state the mode asks for is left alone,
|
|
2352
|
+
* so a steady stream of `webData3` frames neither restarts the timer nor refires a read.
|
|
2353
|
+
*/
|
|
2354
|
+
private syncBorrowLendPoll;
|
|
2355
|
+
/**
|
|
2356
|
+
* Stops the borrow/lend poll and drops its figures, so no later mode or session inherits them.
|
|
2357
|
+
*
|
|
2358
|
+
* Every stop opens a new generation — a session ending, a restart, or the account leaving
|
|
2359
|
+
* Portfolio Margin — so a read still in flight from the period just ended can never land.
|
|
2360
|
+
*/
|
|
2361
|
+
private stopBorrowLendPoll;
|
|
2362
|
+
/**
|
|
2363
|
+
* Reads the health factor and reserve rates once, then republishes the balance with them.
|
|
2364
|
+
*
|
|
2365
|
+
* A failed read is reported and left for the next tick: the previous figures stay in place, since
|
|
2366
|
+
* one missed read says nothing about the account that the last good one did not.
|
|
2367
|
+
*/
|
|
2368
|
+
private refreshBorrowLendState;
|
|
2317
2369
|
/** The floor of `availableToTrade` over the tracked set; `null` when nothing is tracked. */
|
|
2318
2370
|
private availableMargin;
|
|
2319
2371
|
/** Clears both sides of the live balance join and the public account cache without emitting. */
|
|
@@ -2778,4 +2830,4 @@ declare class ExchangesSDK {
|
|
|
2778
2830
|
private fetchCredentials;
|
|
2779
2831
|
}
|
|
2780
2832
|
|
|
2781
|
-
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_QUOTE_ASSETS, LIGHTER_RHC_CHAIN_ID, LIGHTER_RHC_USDG_ADDRESS, LIGHTER_RHC_USDG_DECIMALS, LIGHTER_USDC_DECIMALS, LighterAccountSyncer, type LighterAccountSyncerConfig, type LighterAccountTier, LighterAccountTracker, type LighterAccountTrackerConfig, type LighterApplyReferralCodeParams, type LighterAuthCredentials, LighterClassicBalance, type LighterConnector, 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, LighterRhcAssetId, type LighterRhcDepositAddressParams, type LighterRhcDepositAddressResult, type LighterRhcDepositParams, type LighterRhcDepositResult, type LighterRhcDepositWallet, type LighterRhcHelper, type LighterSharedHelper, 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_COLLATERAL, MIN_LIGHTER_RHC_DEPOSIT_USDG, 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, createLighterRhcHelper, findAvailableApiKeyIndex, getAssetDecimals, getLighterNativeUsdcAddress, listFunxyzTransferableChains, readFunxyzChainSource, readFunxyzMinimumUsd, retrieveLighterAuthToken, usdcAbi };
|
|
2833
|
+
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, HyperliquidBorrowLendReserve, HyperliquidDexState, HyperliquidExchangeWs, type HyperliquidHelper, HyperliquidPortfolioMarginBalance, HyperliquidPortfolioMarginCollateral, HyperliquidStandardBalance, HyperliquidUnifiedBalance, HyperliquidWs, type IntegratorApprovalRequirements, L2_ASSET_DECIMALS, LIGHTER_NATIVE_USDC_ADDRESSES, LIGHTER_QUOTE_ASSETS, LIGHTER_RHC_CHAIN_ID, LIGHTER_RHC_USDG_ADDRESS, LIGHTER_RHC_USDG_DECIMALS, LIGHTER_USDC_DECIMALS, LighterAccountSyncer, type LighterAccountSyncerConfig, type LighterAccountTier, LighterAccountTracker, type LighterAccountTrackerConfig, type LighterApplyReferralCodeParams, type LighterAuthCredentials, LighterClassicBalance, type LighterConnector, 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, LighterRhcAssetId, type LighterRhcDepositAddressParams, type LighterRhcDepositAddressResult, type LighterRhcDepositParams, type LighterRhcDepositResult, type LighterRhcDepositWallet, type LighterRhcHelper, type LighterSharedHelper, 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_COLLATERAL, MIN_LIGHTER_RHC_DEPOSIT_USDG, 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, createLighterRhcHelper, findAvailableApiKeyIndex, getAssetDecimals, getLighterNativeUsdcAddress, listFunxyzTransferableChains, readFunxyzChainSource, readFunxyzMinimumUsd, retrieveLighterAuthToken, usdcAbi };
|
|
@@ -146,7 +146,22 @@ const HyperliquidPortfolioMarginCollateral = z.object({
|
|
|
146
146
|
* `borrowed / borrow cap` for this coin, and `null` where the venue renders `--` — no borrow.
|
|
147
147
|
* NOT clipped at one: `0x0871deb3…` reports 1.0081 on USDT0.
|
|
148
148
|
*/
|
|
149
|
-
borrowCapUsed: DecimalString.nullable()
|
|
149
|
+
borrowCapUsed: DecimalString.nullable(),
|
|
150
|
+
/**
|
|
151
|
+
* The coin's outstanding borrow in its own units, and `0` on a coin never borrowed.
|
|
152
|
+
*
|
|
153
|
+
* Read from the wire's `borrowed`, never from a negative `equity`: the USDC row already contains
|
|
154
|
+
* the perps account value, so `equity` is `supplied − borrowed + accountValue` and its negative
|
|
155
|
+
* understates the debt by exactly that wallet.
|
|
156
|
+
*/
|
|
157
|
+
borrowed: DecimalString
|
|
158
|
+
});
|
|
159
|
+
const HyperliquidBorrowLendReserve = z.object({
|
|
160
|
+
asset: z.string(),
|
|
161
|
+
/** What borrowing the coin costs per year, as a fraction — `0.05` is 5% APY. */
|
|
162
|
+
borrowYearlyRate: DecimalString,
|
|
163
|
+
/** What supplying the coin earns per year; Portfolio Margin supplies idle balances automatically. */
|
|
164
|
+
supplyYearlyRate: DecimalString
|
|
150
165
|
});
|
|
151
166
|
const HyperliquidPortfolioMarginBalance = AccountBalanceCore.extend({
|
|
152
167
|
accountMode: z.literal("hyperliquid:portfolioMargin"),
|
|
@@ -194,7 +209,27 @@ const HyperliquidPortfolioMarginBalance = AccountBalanceCore.extend({
|
|
|
194
209
|
* account borrows nothing. Not clipped at one, and never the USDC entry alone.
|
|
195
210
|
*/
|
|
196
211
|
borrowCapUsed: DecimalString.nullable(),
|
|
212
|
+
/**
|
|
213
|
+
* The venue's Your Borrowed: every row's `borrowed` valued at its own mid, in USD, and `0` when
|
|
214
|
+
* the account borrows nothing. Null when a borrowed coin cannot be priced, since a debt counted
|
|
215
|
+
* as zero would hide exactly the part nobody could value.
|
|
216
|
+
*/
|
|
217
|
+
borrowedValue: DecimalString.nullable(),
|
|
218
|
+
/**
|
|
219
|
+
* The venue's Health Factor — LTV-weighted collateral over the borrowed value — at four decimals.
|
|
220
|
+
* Below `1` the account can borrow no more, which is not by itself liquidation: that is
|
|
221
|
+
* `portfolioMarginRatio`. Null when the account borrows nothing, and until the first read lands.
|
|
222
|
+
*
|
|
223
|
+
* Read, never derived, and over REST because no channel carries it: the live tracker refreshes it
|
|
224
|
+
* on a timer, so it can trail the channel-fed figures beside it by up to one poll interval.
|
|
225
|
+
*/
|
|
226
|
+
healthFactor: DecimalString.nullable(),
|
|
227
|
+
/**
|
|
228
|
+
* Every reserve's yearly rates, listed whatever the account holds, so what a borrow will cost
|
|
229
|
+
* shows before the first one happens. Empty until the first read lands.
|
|
230
|
+
*/
|
|
231
|
+
borrowLendReserves: z.array(HyperliquidBorrowLendReserve),
|
|
197
232
|
perDexState: z.array(HyperliquidDexState)
|
|
198
233
|
});
|
|
199
234
|
|
|
200
|
-
export { HyperliquidDexState, HyperliquidPortfolioMarginBalance, HyperliquidPortfolioMarginCollateral, HyperliquidStandardBalance, HyperliquidUnifiedBalance };
|
|
235
|
+
export { HyperliquidBorrowLendReserve, HyperliquidDexState, HyperliquidPortfolioMarginBalance, HyperliquidPortfolioMarginCollateral, HyperliquidStandardBalance, HyperliquidUnifiedBalance };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { fetchBorrowLendUserState, fetchAllBorrowLendReserveStates } from '../../client/hyperliquid/rest';
|
|
2
|
+
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
5
|
+
const EMPTY_BORROW_LEND_STATE = {
|
|
6
|
+
healthFactor: null,
|
|
7
|
+
ratesByToken: /* @__PURE__ */ new Map()
|
|
8
|
+
};
|
|
9
|
+
async function fetchBorrowLendState(user, demo) {
|
|
10
|
+
const [userState, reserves] = await Promise.all([
|
|
11
|
+
fetchBorrowLendUserState(user, demo),
|
|
12
|
+
fetchAllBorrowLendReserveStates(demo)
|
|
13
|
+
]);
|
|
14
|
+
return {
|
|
15
|
+
healthFactor: userState.healthFactor ?? null,
|
|
16
|
+
ratesByToken: ratesByToken(reserves)
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
__name(fetchBorrowLendState, "fetchBorrowLendState");
|
|
20
|
+
function ratesByToken(reserves) {
|
|
21
|
+
const rates = /* @__PURE__ */ new Map();
|
|
22
|
+
for (const [token, reserve] of reserves) {
|
|
23
|
+
rates.set(token, {
|
|
24
|
+
borrowYearlyRate: reserve.borrowYearlyRate,
|
|
25
|
+
supplyYearlyRate: reserve.supplyYearlyRate
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
return rates;
|
|
29
|
+
}
|
|
30
|
+
__name(ratesByToken, "ratesByToken");
|
|
31
|
+
|
|
32
|
+
export { EMPTY_BORROW_LEND_STATE, fetchBorrowLendState };
|
|
@@ -232,6 +232,9 @@ function mapPortfolioMarginBalance(context) {
|
|
|
232
232
|
portfolioMarginRatio: wireMarginRatio(context),
|
|
233
233
|
portfolioAccountLeverage: portfolioAccountLeverage(context),
|
|
234
234
|
borrowCapUsed: worstBorrowCapUsed(context),
|
|
235
|
+
borrowedValue: borrowedValueOf(context),
|
|
236
|
+
healthFactor: wireHealthFactor(context),
|
|
237
|
+
borrowLendReserves: borrowLendReserveRows(context),
|
|
235
238
|
perDexState: context.summary.perDexState,
|
|
236
239
|
timestamp: context.timestamp
|
|
237
240
|
};
|
|
@@ -256,7 +259,8 @@ function portfolioMarginCollateralRows(context) {
|
|
|
256
259
|
availableMargin: context.availableMarginByToken.get(balance.token) ?? null,
|
|
257
260
|
withdrawable: signed(total.minus(toDecimal(balance.hold)).toFixed()),
|
|
258
261
|
ltv: balance.ltv === null ? null : toDecimal(balance.ltv).toFixed(),
|
|
259
|
-
borrowCapUsed: borrowCapUsedFor(context, balance.token)
|
|
262
|
+
borrowCapUsed: borrowCapUsedFor(context, balance.token),
|
|
263
|
+
borrowed: toDecimal(balance.borrowed).toFixed()
|
|
260
264
|
});
|
|
261
265
|
}
|
|
262
266
|
rows.sort(byRowAsset);
|
|
@@ -283,6 +287,22 @@ function worstBorrowCapUsed(context) {
|
|
|
283
287
|
return worst.isZero() ? null : worst.toFixed(RATIO_DECIMALS);
|
|
284
288
|
}
|
|
285
289
|
__name(worstBorrowCapUsed, "worstBorrowCapUsed");
|
|
290
|
+
function borrowedValueOf(context) {
|
|
291
|
+
let borrowed = ZERO;
|
|
292
|
+
for (const balance of context.spotBalances.values()) {
|
|
293
|
+
const debt = toDecimal(balance.borrowed);
|
|
294
|
+
if (debt.isZero()) {
|
|
295
|
+
continue;
|
|
296
|
+
}
|
|
297
|
+
const mid = context.prices.midForToken(balance.token);
|
|
298
|
+
if (mid === null) {
|
|
299
|
+
return null;
|
|
300
|
+
}
|
|
301
|
+
borrowed = borrowed.plus(debt.times(toDecimal(mid)));
|
|
302
|
+
}
|
|
303
|
+
return borrowed.toFixed();
|
|
304
|
+
}
|
|
305
|
+
__name(borrowedValueOf, "borrowedValueOf");
|
|
286
306
|
function wireMarginRatio(context) {
|
|
287
307
|
if (context.portfolioMarginRatio === null) {
|
|
288
308
|
return null;
|
|
@@ -290,6 +310,38 @@ function wireMarginRatio(context) {
|
|
|
290
310
|
return toDecimal(context.portfolioMarginRatio).toFixed(RATIO_DECIMALS);
|
|
291
311
|
}
|
|
292
312
|
__name(wireMarginRatio, "wireMarginRatio");
|
|
313
|
+
function wireHealthFactor(context) {
|
|
314
|
+
const healthFactor = context.borrowLend.healthFactor;
|
|
315
|
+
if (healthFactor === null) {
|
|
316
|
+
return null;
|
|
317
|
+
}
|
|
318
|
+
return toDecimal(healthFactor).toFixed(RATIO_DECIMALS);
|
|
319
|
+
}
|
|
320
|
+
__name(wireHealthFactor, "wireHealthFactor");
|
|
321
|
+
function borrowLendReserveRows(context) {
|
|
322
|
+
const rows = [];
|
|
323
|
+
for (const [token, rates] of context.borrowLend.ratesByToken) {
|
|
324
|
+
const asset = context.collateralTokenNames.get(token);
|
|
325
|
+
if (asset === void 0) {
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
rows.push({
|
|
329
|
+
asset,
|
|
330
|
+
borrowYearlyRate: toDecimal(rates.borrowYearlyRate).toFixed(),
|
|
331
|
+
supplyYearlyRate: toDecimal(rates.supplyYearlyRate).toFixed()
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
rows.sort(byReserveAsset);
|
|
335
|
+
return rows;
|
|
336
|
+
}
|
|
337
|
+
__name(borrowLendReserveRows, "borrowLendReserveRows");
|
|
338
|
+
function byReserveAsset(left, right) {
|
|
339
|
+
if (left.asset === right.asset) {
|
|
340
|
+
return 0;
|
|
341
|
+
}
|
|
342
|
+
return left.asset < right.asset ? -1 : 1;
|
|
343
|
+
}
|
|
344
|
+
__name(byReserveAsset, "byReserveAsset");
|
|
293
345
|
function portfolioAccountLeverage(context) {
|
|
294
346
|
const collateral = haircutCollateral(context);
|
|
295
347
|
if (collateral === null) {
|
|
@@ -2,6 +2,7 @@ import { createExchangeWs } from '../../client';
|
|
|
2
2
|
import { fetchPerpDexs, fetchInfo, fetchAllMids, fetchUserAbstraction, fetchSpotClearinghouseState, fetchDelegatorSummary, fetchUserVaultEquities, fetchClearinghouseState, fetchActiveAssetData } from '../../client/hyperliquid/rest';
|
|
3
3
|
import { BaseAccountTracker } from '../base';
|
|
4
4
|
import { resolveHyperliquidAccountType } from './account-mode';
|
|
5
|
+
import { EMPTY_BORROW_LEND_STATE, fetchBorrowLendState } from './borrow-lend';
|
|
5
6
|
import { buildAvailableMarginByToken, buildCollateralTokenNames, minimumAvailableToTrade } from './collateral';
|
|
6
7
|
import { LOCKED_TRACKED_COINS } from './const';
|
|
7
8
|
import { toDecimal, ZERO } from './decimal';
|
|
@@ -15,6 +16,7 @@ const EMPTY_SPOT_META = {
|
|
|
15
16
|
tokens: [],
|
|
16
17
|
universe: []
|
|
17
18
|
};
|
|
19
|
+
const BORROW_LEND_POLL_INTERVAL_MS = 3e4;
|
|
18
20
|
class HyperliquidAccountTracker extends BaseAccountTracker {
|
|
19
21
|
static {
|
|
20
22
|
__name(this, "HyperliquidAccountTracker");
|
|
@@ -30,6 +32,11 @@ class HyperliquidAccountTracker extends BaseAccountTracker {
|
|
|
30
32
|
/** Portfolio Margin's own risk scalars, which ride the same `spotState` frame the balances do. */
|
|
31
33
|
portfolioMarginRatio = null;
|
|
32
34
|
borrowRatioByToken = /* @__PURE__ */ new Map();
|
|
35
|
+
/** Portfolio Margin's REST-only figures, and the timer that keeps them fresh while in that mode. */
|
|
36
|
+
borrowLend = EMPTY_BORROW_LEND_STATE;
|
|
37
|
+
borrowLendPollTimer = null;
|
|
38
|
+
/** Advances on every stop, so a read fired in an earlier poll period is recognised and dropped. */
|
|
39
|
+
borrowLendPollGeneration = 0;
|
|
33
40
|
hasSpotState = false;
|
|
34
41
|
hasClearinghouseState = false;
|
|
35
42
|
accountType = null;
|
|
@@ -74,8 +81,10 @@ class HyperliquidAccountTracker extends BaseAccountTracker {
|
|
|
74
81
|
})));
|
|
75
82
|
const assetData = await this.fetchActiveAssetEvents(this.coinsForAvailableMargin());
|
|
76
83
|
const { summary, assetPositions } = aggregateClearinghouseStates(clearinghouseStates);
|
|
84
|
+
const accountType = resolveHyperliquidAccountType(abstraction);
|
|
85
|
+
const borrowLend = accountType === HyperliquidAccountType.PORTFOLIO_MARGIN ? await fetchBorrowLendState(user, this.demo) : EMPTY_BORROW_LEND_STATE;
|
|
77
86
|
const balance = mapBalance({
|
|
78
|
-
accountType
|
|
87
|
+
accountType,
|
|
79
88
|
summary,
|
|
80
89
|
spotBalances: mapSpotBalances(spotState),
|
|
81
90
|
prices: SpotPrices.from(spotMeta, mids),
|
|
@@ -86,6 +95,7 @@ class HyperliquidAccountTracker extends BaseAccountTracker {
|
|
|
86
95
|
availableMarginByToken: buildAvailableMarginByToken(summary.perDexState, assetData.values()),
|
|
87
96
|
portfolioMarginRatio: spotState.portfolioMarginRatio ?? null,
|
|
88
97
|
borrowRatioByToken: mapBorrowRatios(spotState),
|
|
98
|
+
borrowLend,
|
|
89
99
|
timestamp: Date.now()
|
|
90
100
|
});
|
|
91
101
|
const positions = Array.from(mapPositions(assetPositions).values());
|
|
@@ -116,6 +126,7 @@ class HyperliquidAccountTracker extends BaseAccountTracker {
|
|
|
116
126
|
const lifecycleVersion = ++this.lifecycleVersion;
|
|
117
127
|
const user = this.addrLower();
|
|
118
128
|
this.destroyCurrentSocket();
|
|
129
|
+
this.stopBorrowLendPoll();
|
|
119
130
|
this.subscribedCoins.clear();
|
|
120
131
|
this.resetLiveAccountState();
|
|
121
132
|
this.dexToMeta.clear();
|
|
@@ -148,6 +159,7 @@ class HyperliquidAccountTracker extends BaseAccountTracker {
|
|
|
148
159
|
this.messageListenerId = this.ws.addMessageListener((raw) => this.routeRaw(raw));
|
|
149
160
|
this.openListenerId = this.ws.addOpenListener(() => this.resubscribeAll());
|
|
150
161
|
this.sendStaticSubs();
|
|
162
|
+
this.syncBorrowLendPoll();
|
|
151
163
|
const coinsToTrack = /* @__PURE__ */ new Set([
|
|
152
164
|
...LOCKED_TRACKED_COINS,
|
|
153
165
|
...this.trackedCoins
|
|
@@ -159,6 +171,7 @@ class HyperliquidAccountTracker extends BaseAccountTracker {
|
|
|
159
171
|
async cleanupConnections() {
|
|
160
172
|
this.lifecycleVersion += 1;
|
|
161
173
|
this.destroyCurrentSocket();
|
|
174
|
+
this.stopBorrowLendPoll();
|
|
162
175
|
this.subscribedCoins.clear();
|
|
163
176
|
}
|
|
164
177
|
/** Detaches and destroys the active socket without changing the current lifecycle generation. */
|
|
@@ -422,6 +435,7 @@ class HyperliquidAccountTracker extends BaseAccountTracker {
|
|
|
422
435
|
this.resetLiveAccountState();
|
|
423
436
|
}
|
|
424
437
|
this.accountType = nextAccountType;
|
|
438
|
+
this.syncBorrowLendPoll();
|
|
425
439
|
this.vaultEquity = sumLiveVaultEquity(data.perpDexStates ?? []);
|
|
426
440
|
this.hasWebData3 = true;
|
|
427
441
|
if (!nextAccountType) {
|
|
@@ -475,9 +489,68 @@ class HyperliquidAccountTracker extends BaseAccountTracker {
|
|
|
475
489
|
availableMarginByToken: buildAvailableMarginByToken(this.lastSummary.perDexState, this.trackedAssetData.values()),
|
|
476
490
|
portfolioMarginRatio: this.portfolioMarginRatio,
|
|
477
491
|
borrowRatioByToken: this.borrowRatioByToken,
|
|
492
|
+
borrowLend: this.borrowLend,
|
|
478
493
|
timestamp: Date.now()
|
|
479
494
|
});
|
|
480
495
|
}
|
|
496
|
+
/**
|
|
497
|
+
* Runs the borrow/lend poll exactly while the account is in Portfolio Margin.
|
|
498
|
+
*
|
|
499
|
+
* Safe to call on every mode read: a poll already in the state the mode asks for is left alone,
|
|
500
|
+
* so a steady stream of `webData3` frames neither restarts the timer nor refires a read.
|
|
501
|
+
*/
|
|
502
|
+
syncBorrowLendPoll() {
|
|
503
|
+
const wantsPoll = this.accountType === HyperliquidAccountType.PORTFOLIO_MARGIN;
|
|
504
|
+
if (wantsPoll === (this.borrowLendPollTimer !== null)) {
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
if (!wantsPoll) {
|
|
508
|
+
this.stopBorrowLendPoll();
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
511
|
+
void this.refreshBorrowLendState();
|
|
512
|
+
this.borrowLendPollTimer = setInterval(() => void this.refreshBorrowLendState(), BORROW_LEND_POLL_INTERVAL_MS);
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* Stops the borrow/lend poll and drops its figures, so no later mode or session inherits them.
|
|
516
|
+
*
|
|
517
|
+
* Every stop opens a new generation — a session ending, a restart, or the account leaving
|
|
518
|
+
* Portfolio Margin — so a read still in flight from the period just ended can never land.
|
|
519
|
+
*/
|
|
520
|
+
stopBorrowLendPoll() {
|
|
521
|
+
if (this.borrowLendPollTimer !== null) {
|
|
522
|
+
clearInterval(this.borrowLendPollTimer);
|
|
523
|
+
this.borrowLendPollTimer = null;
|
|
524
|
+
}
|
|
525
|
+
this.borrowLendPollGeneration += 1;
|
|
526
|
+
this.borrowLend = EMPTY_BORROW_LEND_STATE;
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* Reads the health factor and reserve rates once, then republishes the balance with them.
|
|
530
|
+
*
|
|
531
|
+
* A failed read is reported and left for the next tick: the previous figures stay in place, since
|
|
532
|
+
* one missed read says nothing about the account that the last good one did not.
|
|
533
|
+
*/
|
|
534
|
+
async refreshBorrowLendState() {
|
|
535
|
+
const generation = this.borrowLendPollGeneration;
|
|
536
|
+
let borrowLend;
|
|
537
|
+
try {
|
|
538
|
+
borrowLend = await fetchBorrowLendState(this.addrLower(), this.demo);
|
|
539
|
+
} catch (err) {
|
|
540
|
+
this.onError(err instanceof Error ? err : new Error(String(err)));
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
if (generation !== this.borrowLendPollGeneration) {
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
this.borrowLend = borrowLend;
|
|
547
|
+
const balance = this.buildBalance();
|
|
548
|
+
if (balance !== void 0) {
|
|
549
|
+
this.onStateUpdate({
|
|
550
|
+
balance
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
}
|
|
481
554
|
/** The floor of `availableToTrade` over the tracked set; `null` when nothing is tracked. */
|
|
482
555
|
availableMargin() {
|
|
483
556
|
return minimumAvailableToTrade(this.trackedAssetData.values());
|
|
@@ -540,7 +613,9 @@ function mapSpotBalances(spotState) {
|
|
|
540
613
|
hold: balance.hold,
|
|
541
614
|
// An absent `ltv` means "not collateral", which weighs zero — never a zero weight, which is
|
|
542
615
|
// a stablecoin at full value. The two states stay apart from the wire onward.
|
|
543
|
-
ltv: balance.ltv ?? null
|
|
616
|
+
ltv: balance.ltv ?? null,
|
|
617
|
+
// An absent `borrowed` means the coin was never borrowed; the key rides only a borrowed coin.
|
|
618
|
+
borrowed: balance.borrowed ?? null
|
|
544
619
|
});
|
|
545
620
|
}
|
|
546
621
|
return balances;
|
package/dist/tracker/index.js
CHANGED
|
@@ -13,7 +13,7 @@ export { ACCOUNT_MODE_LABELS, AccountBalanceCore, AccountMode, CollateralBalance
|
|
|
13
13
|
export { BaseAccountTracker } from './base';
|
|
14
14
|
export { BinanceMultiAssetBalance, BinanceSingleAssetBalance } from './binance/balance';
|
|
15
15
|
export { BybitIsolatedMarginBalance, BybitPortfolioMarginBalance, BybitRegularMarginBalance } from './bybit/balance';
|
|
16
|
-
export { HyperliquidDexState, HyperliquidPortfolioMarginBalance, HyperliquidPortfolioMarginCollateral, HyperliquidStandardBalance, HyperliquidUnifiedBalance } from './hyperliquid/balance';
|
|
16
|
+
export { HyperliquidBorrowLendReserve, HyperliquidDexState, HyperliquidPortfolioMarginBalance, HyperliquidPortfolioMarginCollateral, HyperliquidStandardBalance, HyperliquidUnifiedBalance } from './hyperliquid/balance';
|
|
17
17
|
export { LighterClassicBalance, LighterUnifiedBalance } from './lighter/balance';
|
|
18
18
|
export { LIGHTER_QUOTE_ASSETS } from './lighter/const';
|
|
19
19
|
export { OkxFuturesBalance, OkxMultiCurrencyMarginBalance, OkxPortfolioMarginBalance, OkxSpotBalance } from './okx/balance';
|