@pear-protocol/exchanges-sdk 0.14.1 → 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.
Files changed (36) hide show
  1. package/dist/client/hyperliquid/rest.js +14 -1
  2. package/dist/client/index.js +2 -0
  3. package/dist/client/lighter/constants.js +25 -5
  4. package/dist/client/lighter/exchange-ws.js +8 -7
  5. package/dist/client/lighter/rest.js +36 -36
  6. package/dist/client/lighter/ws.js +4 -3
  7. package/dist/helper/factory.js +3 -1
  8. package/dist/helper/lighter/asset-decimals.helper.js +1 -1
  9. package/dist/helper/lighter/auth-token.helper.js +10 -7
  10. package/dist/helper/lighter/cctp-deposit.helper.js +13 -13
  11. package/dist/helper/lighter/deposit-settlement.helper.js +4 -4
  12. package/dist/helper/lighter/funxyz-deposit.helper.js +3 -3
  13. package/dist/helper/lighter/helper.js +84 -59
  14. package/dist/helper/lighter/history.helper.js +6 -6
  15. package/dist/helper/lighter/misc-routes.helper.js +13 -0
  16. package/dist/helper/lighter/onboarding.helper.js +2 -2
  17. package/dist/helper/lighter/referral.helper.js +6 -6
  18. package/dist/helper/lighter/rhc-deposit.helper.js +91 -0
  19. package/dist/helper/lighter/types.js +12 -2
  20. package/dist/helper/subaccount.helper.js +10 -10
  21. package/dist/index.d.ts +223 -14
  22. package/dist/sdk.js +6 -0
  23. package/dist/status/factory.js +2 -1
  24. package/dist/status/lighter/status.js +5 -5
  25. package/dist/syncer/factory.js +5 -1
  26. package/dist/syncer/lighter/funding.js +2 -2
  27. package/dist/syncer/lighter/syncer.js +6 -6
  28. package/dist/tracker/hyperliquid/balance.js +37 -2
  29. package/dist/tracker/hyperliquid/borrow-lend.js +32 -0
  30. package/dist/tracker/hyperliquid/mapper.js +53 -1
  31. package/dist/tracker/hyperliquid/tracker.js +77 -2
  32. package/dist/tracker/index.js +4 -1
  33. package/dist/tracker/lighter/const.js +5 -2
  34. package/dist/tracker/lighter/mapper.js +12 -13
  35. package/dist/tracker/lighter/tracker.js +21 -15
  36. package/package.json +4 -4
package/dist/index.d.ts CHANGED
@@ -176,9 +176,17 @@ declare class HyperliquidExchangeWs extends ExchangeWs {
176
176
  }): Promise<HyperliquidExchangeWs>;
177
177
  }
178
178
 
179
+ /**
180
+ * The connector values that are deployments of the Lighter stack. The deployments share the
181
+ * protocol but nothing else — hosts, account indices, and market indices are all per-deployment —
182
+ * so every Lighter code path in this SDK names the deployment it reads instead of assuming one.
183
+ */
184
+ type LighterConnector = Extract<Connector, 'lighter' | 'lighter_rhc'>;
185
+
179
186
  declare class LighterWs extends BaseWs {
187
+ private readonly connector;
180
188
  private readonly demo;
181
- constructor(demo?: boolean);
189
+ constructor(connector: LighterConnector, demo?: boolean);
182
190
  protected getWsUrl(): string;
183
191
  protected getPingIntervalMs(): number;
184
192
  protected buildPingMessage(): WsMessage;
@@ -188,10 +196,13 @@ declare class LighterWs extends BaseWs {
188
196
 
189
197
  declare class LighterExchangeWs extends ExchangeWs {
190
198
  main: LighterWs;
191
- readonly exchange: "lighter";
192
- constructor(main: LighterWs);
199
+ readonly exchange: LighterConnector;
200
+ /** Binds the socket bundle to the deployment that opened it, so consumers can tell them apart. */
201
+ constructor(exchange: LighterConnector, main: LighterWs);
193
202
  protected connections(): BaseWs[];
194
- static create(config?: {
203
+ /** Opens the deployment's stream and returns the bundle only once it is connected. */
204
+ static create(config: {
205
+ connector: LighterConnector;
195
206
  demo: boolean;
196
207
  }): Promise<LighterExchangeWs>;
197
208
  }
@@ -227,6 +238,7 @@ type ExchangeWsByConnector = {
227
238
  okx: OkxExchangeWs;
228
239
  hyperliquid: HyperliquidExchangeWs;
229
240
  lighter: LighterExchangeWs;
241
+ lighter_rhc: LighterExchangeWs;
230
242
  };
231
243
  type CreateExchangeWsConfig = {
232
244
  demo: boolean;
@@ -405,7 +417,7 @@ type LighterAuthCredentials = {
405
417
  apiPrivateKey: string;
406
418
  };
407
419
  /** Returns a live token while coalescing concurrent signing requests. */
408
- declare function retrieveLighterAuthToken(sdk: PearSDK, credentials: LighterAuthCredentials, demo: boolean): Promise<string>;
420
+ declare function retrieveLighterAuthToken(sdk: PearSDK, connector: LighterConnector, credentials: LighterAuthCredentials, demo: boolean): Promise<string>;
409
421
 
410
422
  type WalletClientWithAccount = WalletClient<Transport, Chain | undefined, Account>;
411
423
 
@@ -458,6 +470,13 @@ declare const usdcAbi: readonly [{
458
470
  /** Names native USDC for a source chain this SDK can transfer from safely. */
459
471
  declare function getLighterNativeUsdcAddress(chainId: number): `0x${string}` | undefined;
460
472
 
473
+ /**
474
+ * Asset indices on Lighter's Robinhood Chain deployment that this SDK names. Only the collateral is
475
+ * needed today — RHC's equity assets are read by index and shown as such until a flow needs them.
476
+ */
477
+ declare const LighterRhcAssetId: {
478
+ readonly USDG: 3;
479
+ };
461
480
  declare const AssetId: {
462
481
  readonly ETH: 1;
463
482
  readonly LIT: 2;
@@ -476,7 +495,30 @@ declare const RouteType: {
476
495
  };
477
496
  type RouteType = (typeof RouteType)[keyof typeof RouteType];
478
497
  declare const MIN_LIGHTER_CCTP_DEPOSIT_USDC = "5";
479
- declare const MIN_LIGHTER_FAST_WITHDRAW_USDC = "4";
498
+ /**
499
+ * Fast-withdraw floor per deployment, in that deployment's own collateral.
500
+ *
501
+ * Lighter documents the zkLighter floor as "Fast Withdrawal (USDC only, 4 USDC minimum)" and
502
+ * publishes no floor for Robinhood Chain; `/api/v1/fastwithdraw/info` reports `withdraw_limit`
503
+ * and `max_withdrawal_amount` but no minimum, so the value cannot be read from the venue either.
504
+ * Robinhood Chain therefore carries zkLighter's number until the venue states its own — correcting
505
+ * it is one line here, and the venue rejects a short transfer regardless.
506
+ */
507
+ declare const MIN_LIGHTER_FAST_WITHDRAW_COLLATERAL: Record<LighterConnector, string>;
508
+ declare const MIN_LIGHTER_RHC_DEPOSIT_USDG = "1";
509
+ /**
510
+ * Robinhood Chain's EVM chain id — the chain a deposit is sent on, not the id the signer signs
511
+ * under. Read from Lighter's own deposit network list at runtime; this constant only lets a caller
512
+ * configure a wallet for the chain before any read has happened.
513
+ */
514
+ declare const LIGHTER_RHC_CHAIN_ID = 4663;
515
+ /**
516
+ * USDG on Robinhood Chain, as `assetDetails` reports its `l1_address` for asset index 3, verified
517
+ * on chain to answer `USDG` and six decimals. A deposit transfers this token and nothing else.
518
+ */
519
+ declare const LIGHTER_RHC_USDG_ADDRESS: "0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168";
520
+ /** USDG carries six decimals, matching the venue's own units. */
521
+ declare const LIGHTER_RHC_USDG_DECIMALS = 6;
480
522
  /** Lighter L2/base-amount precision (`assetDetails.decimals`). */
481
523
  declare const L2_ASSET_DECIMALS: Record<number, number>;
482
524
  /**
@@ -640,7 +682,7 @@ type CctpDepositParams = {
640
682
  connectedAddress: `0x${string}` | undefined;
641
683
  /** A `chainId` from `listCctpDepositNetworks()`; the connected wallet must already be on it. */
642
684
  chainId: number;
643
- /** Positive human-readable USDC amount with at most six fractional digits. */
685
+ /** Positive human-readable collateral amount (USDC on zkLighter, USDG on RHC), at most six fractional digits. */
644
686
  amount: string;
645
687
  /** Supplies wallet transport operations without coupling the SDK to Wagmi. */
646
688
  wallet: LighterDepositWalletAdapter;
@@ -749,6 +791,65 @@ type FunxyzDepositAddressResult = {
749
791
  credits: FunxyzDepositCredit;
750
792
  };
751
793
  type LighterDepositAddressResult = CctpDepositAddressResult | FunxyzDepositAddressResult;
794
+ /**
795
+ * What minting a Robinhood Chain deposit address needs.
796
+ *
797
+ * No route tag and no chain id: Robinhood Chain offers exactly one deposit method on exactly one
798
+ * chain, so there is nothing to select. A second of either would be a new contract, not a new field.
799
+ */
800
+ type LighterRhcDepositAddressParams = {
801
+ /** The L1 owner whose Lighter account receives funds, not necessarily the sender. */
802
+ ownerAddress: `0x${string}`;
803
+ };
804
+ /**
805
+ * Wallet transport a Robinhood Chain deposit borrows from its caller.
806
+ *
807
+ * Separate from `LighterDepositWalletAdapter`, which reads native USDC: this deployment moves USDG
808
+ * on its own chain, so the token is named rather than inferred from a chain id.
809
+ */
810
+ type LighterRhcDepositWallet = {
811
+ /** Reads one ERC-20 balance for an owner on one chain. */
812
+ readTokenBalance: (chainId: number, token: `0x${string}`, ownerAddress: `0x${string}`) => Promise<bigint>;
813
+ /** Moves the connector to the chain and returns a wallet client bound to it. */
814
+ retrieveWallet: (chainId: number) => Promise<WalletClientWithAccount>;
815
+ /** Resolves once the chain has mined the transfer, throwing when it reverted. */
816
+ confirmTransaction: (chainId: number, txHash: string) => Promise<void>;
817
+ };
818
+ /** What sending USDG from the connected wallet into a Robinhood Chain account needs. */
819
+ type LighterRhcDepositParams = {
820
+ /** The L1 owner whose Lighter account receives funds. */
821
+ ownerAddress: `0x${string}`;
822
+ /** The wallet currently connected in the browser, which must be the owner. */
823
+ connectedAddress: `0x${string}` | undefined;
824
+ /** Positive human-readable USDG amount with at most six fractional digits. */
825
+ amount: string;
826
+ wallet: LighterRhcDepositWallet;
827
+ /** Receives transfer-confirmation and Lighter-settlement state changes. */
828
+ onProgress: (progress: LighterDepositProgress) => void;
829
+ /** Cancels the settlement watch; the transfer itself is already on chain. */
830
+ signal?: AbortSignal;
831
+ /** Caps the settlement watch; defaults to the shared one-hour limit. */
832
+ settlementTimeoutMs?: number;
833
+ };
834
+ /** What a submitted Robinhood Chain deposit reports back. */
835
+ type LighterRhcDepositResult = {
836
+ txHash: string;
837
+ /** The address the transfer was sent to, which keeps crediting this owner. */
838
+ intentAddress: `0x${string}`;
839
+ chainId: number;
840
+ };
841
+ /**
842
+ * The address USDG is sent to, and the chain it must arrive on.
843
+ *
844
+ * Persistent, unlike a CCTP intent: Lighter binds it to the address that generated it and returns
845
+ * the same one on every request, so there is no expiry for a caller to race.
846
+ */
847
+ type LighterRhcDepositAddressResult = {
848
+ /** Send at least `MIN_LIGHTER_RHC_DEPOSIT_USDG` in USDG on `chainId` to this address. */
849
+ intentAddress: `0x${string}`;
850
+ /** The chain the address credits from, as Lighter's own deposit network list names it. */
851
+ chainId: number;
852
+ };
752
853
  type WithdrawParams = {
753
854
  accountIndex: number;
754
855
  assetId: number;
@@ -890,6 +991,34 @@ interface LighterHelper {
890
991
  /** Reads one page of the owner's referral record, including the code that referred them. */
891
992
  getUserReferrals(params: LighterUserReferralsParams): Promise<LighterUserReferrals>;
892
993
  }
994
+ /**
995
+ * Everything both Lighter deployments share.
996
+ *
997
+ * What it leaves out is what zkLighter wires to its own bridges and Ethereum contracts: the CCTP
998
+ * and Fun.xyz deposit routes, and the gateway withdrawal. Robinhood Chain runs none of them, so
999
+ * they are absent at the type level rather than refused at runtime.
1000
+ */
1001
+ type LighterSharedHelper = Omit<LighterHelper, 'listCctpDepositNetworks' | 'deposit' | 'createDepositAddress' | 'withdraw' | 'listUdaDeposits'>;
1002
+ /**
1003
+ * The helper surface for Lighter's Robinhood Chain deployment.
1004
+ *
1005
+ * The shared surface plus the one deposit method RHC has of its own. Its on-chain withdrawal still
1006
+ * has no equivalent here: that is RHC's own gateway contract, which this SDK does not yet call.
1007
+ */
1008
+ type LighterRhcHelper = LighterSharedHelper & {
1009
+ /**
1010
+ * Mints the persistent address that credits this owner's Robinhood Chain account.
1011
+ *
1012
+ * Deliberately not zkLighter's route-tagged `createDepositAddress`: the two deployments share no
1013
+ * deposit route, so a caller cannot pass a `cctp` or `funxyz` route here by mistake.
1014
+ */
1015
+ createDepositAddress(params: LighterRhcDepositAddressParams): Promise<LighterRhcDepositAddressResult>;
1016
+ /**
1017
+ * Sends USDG from the connected wallet into this owner's account, and follows it until Lighter
1018
+ * registers the account. Also not zkLighter's route-tagged `deposit`: Robinhood Chain has one way in.
1019
+ */
1020
+ deposit(params: LighterRhcDepositParams): Promise<LighterRhcDepositResult>;
1021
+ };
893
1022
  type LighterLookupResult = {
894
1023
  mainAccountIndex: number;
895
1024
  subAccountIndexes: number[];
@@ -926,10 +1055,19 @@ declare const MIN_USER_API_KEY_INDEX = 4;
926
1055
  declare const MAX_API_KEY_INDEX = 254;
927
1056
  declare function findAvailableApiKeyIndex(apiKeys: ReadonlyArray<Pick<ApiKey, 'api_key_index'>>): number;
928
1057
  declare function createLighterHelper(sdk: PearSDK, demo?: boolean): LighterHelper;
1058
+ /**
1059
+ * The helper for Lighter's Robinhood Chain deployment: the shared surface plus its own deposit.
1060
+ *
1061
+ * zkLighter's bridge deposits and gateway withdrawal stay absent — they are wired to contracts
1062
+ * Robinhood Chain does not run. RHC funds instead through an intent address, and its on-chain
1063
+ * withdrawal is still the venue's own front end.
1064
+ */
1065
+ declare function createLighterRhcHelper(sdk: PearSDK, demo?: boolean): LighterRhcHelper;
929
1066
 
930
1067
  type ExchangeHelperMap = {
931
1068
  hyperliquid: HyperliquidHelper;
932
1069
  lighter: LighterHelper;
1070
+ lighter_rhc: LighterRhcHelper;
933
1071
  };
934
1072
  type ExchangeHelperExchange = keyof ExchangeHelperMap;
935
1073
 
@@ -1167,11 +1305,20 @@ declare class HyperliquidAccountSyncer extends BaseAccountSyncer<HyperliquidRawF
1167
1305
  }
1168
1306
 
1169
1307
  type RawFill$1 = LighterRawTrade;
1308
+ /** The syncer config narrowed to the deployments this syncer serves. */
1309
+ type LighterAccountSyncerConfig = AccountSyncerConfig & {
1310
+ connector: LighterConnector;
1311
+ };
1170
1312
  declare class LighterAccountSyncer extends BaseAccountSyncer<RawFill$1> {
1313
+ /**
1314
+ * Narrows the connector the base constructor already assigned from the config. Declared, not
1315
+ * assigned: the deployment has exactly one source, so no caller can hand in a second value.
1316
+ */
1317
+ protected connector: LighterConnector;
1171
1318
  private readonly accountIndex;
1172
1319
  private readonly apiKeyIndex;
1173
1320
  private readonly apiPrivateKey;
1174
- constructor(config: AccountSyncerConfig);
1321
+ constructor(config: LighterAccountSyncerConfig);
1175
1322
  /** Returns this account's shared Lighter auth token. */
1176
1323
  private retrieveAuthToken;
1177
1324
  protected listExternalPositions({ instruments, }: ListExternalPositionsParams): Promise<HttpTypes.ExternalPosition[]>;
@@ -1300,6 +1447,7 @@ declare const AccountBalance: z.ZodDiscriminatedUnion<[z.ZodObject<{
1300
1447
  withdrawable: z.ZodString;
1301
1448
  ltv: z.ZodNullable<z.ZodString>;
1302
1449
  borrowCapUsed: z.ZodNullable<z.ZodString>;
1450
+ borrowed: z.ZodString;
1303
1451
  }, z.core.$strip>>;
1304
1452
  tradingEquity: z.ZodNullable<z.ZodString>;
1305
1453
  vaultEquity: z.ZodString;
@@ -1311,6 +1459,13 @@ declare const AccountBalance: z.ZodDiscriminatedUnion<[z.ZodObject<{
1311
1459
  portfolioMarginRatio: z.ZodNullable<z.ZodString>;
1312
1460
  portfolioAccountLeverage: z.ZodNullable<z.ZodString>;
1313
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>>;
1314
1469
  perDexState: z.ZodArray<z.ZodObject<{
1315
1470
  dex: z.ZodString;
1316
1471
  collateralToken: z.ZodNullable<z.ZodNumber>;
@@ -2027,8 +2182,9 @@ type HyperliquidUnifiedBalance = z.infer<typeof HyperliquidUnifiedBalance>;
2027
2182
  * accounts measured hold one — `0x0871deb3…` reports USDC at −957,802.15. An unsigned row cannot
2028
2183
  * state that at all, which is the defect that made a borrowed pool indistinguishable from an
2029
2184
  * untouched one.
2030
- * - **two more columns.** `ltv` and `borrowCapUsed` are per-coin risk weights the venue renders
2031
- * 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.
2032
2188
  *
2033
2189
  * The row is otherwise the shared shape: same keys, same meanings, so a consumer reading
2034
2190
  * `perCollateral` without narrowing still reads `asset` / `equity` / `availableMargin` /
@@ -2041,8 +2197,16 @@ declare const HyperliquidPortfolioMarginCollateral: z.ZodObject<{
2041
2197
  withdrawable: z.ZodString;
2042
2198
  ltv: z.ZodNullable<z.ZodString>;
2043
2199
  borrowCapUsed: z.ZodNullable<z.ZodString>;
2200
+ borrowed: z.ZodString;
2044
2201
  }, z.core.$strip>;
2045
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>;
2046
2210
  declare const HyperliquidPortfolioMarginBalance: z.ZodObject<{
2047
2211
  totalEquity: z.ZodNullable<z.ZodString>;
2048
2212
  withdrawableBalance: z.ZodNullable<z.ZodString>;
@@ -2057,6 +2221,7 @@ declare const HyperliquidPortfolioMarginBalance: z.ZodObject<{
2057
2221
  withdrawable: z.ZodString;
2058
2222
  ltv: z.ZodNullable<z.ZodString>;
2059
2223
  borrowCapUsed: z.ZodNullable<z.ZodString>;
2224
+ borrowed: z.ZodString;
2060
2225
  }, z.core.$strip>>;
2061
2226
  tradingEquity: z.ZodNullable<z.ZodString>;
2062
2227
  vaultEquity: z.ZodString;
@@ -2068,6 +2233,13 @@ declare const HyperliquidPortfolioMarginBalance: z.ZodObject<{
2068
2233
  portfolioMarginRatio: z.ZodNullable<z.ZodString>;
2069
2234
  portfolioAccountLeverage: z.ZodNullable<z.ZodString>;
2070
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>>;
2071
2243
  perDexState: z.ZodArray<z.ZodObject<{
2072
2244
  dex: z.ZodString;
2073
2245
  collateralToken: z.ZodNullable<z.ZodNumber>;
@@ -2085,9 +2257,10 @@ type HyperliquidPortfolioMarginBalance = z.infer<typeof HyperliquidPortfolioMarg
2085
2257
  * Both fill the same `HyperliquidBalanceContext` and hand it to the same mapper, which is what
2086
2258
  * makes "same account state, same balance" true across two different transports. The tracker takes
2087
2259
  * every CHANGING value off a channel — `allDexsClearinghouseState`, `spotState`, `webData3`,
2088
- * `allMids`, `activeAssetData` — including vault equity, which rides `webData3`. Its only REST
2089
- * reads happen at `start()`: the static dex metadata, and the staking position, which the venue
2090
- * publishes on no channel at all.
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.
2091
2264
  *
2092
2265
  * The snapshot has no channels, so it reads the same figures over REST — vault equity from
2093
2266
  * `userVaultEquities`, which was measured equal to the `webData3` figure on ten live accounts.
@@ -2109,6 +2282,11 @@ declare class HyperliquidAccountTracker extends BaseAccountTracker {
2109
2282
  /** Portfolio Margin's own risk scalars, which ride the same `spotState` frame the balances do. */
2110
2283
  private portfolioMarginRatio;
2111
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;
2112
2290
  private hasSpotState;
2113
2291
  private hasClearinghouseState;
2114
2292
  private accountType;
@@ -2167,6 +2345,27 @@ declare class HyperliquidAccountTracker extends BaseAccountTracker {
2167
2345
  * vault. Partial equity is worse than no equity, so nothing is published early.
2168
2346
  */
2169
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;
2170
2369
  /** The floor of `availableToTrade` over the tracked set; `null` when nothing is tracked. */
2171
2370
  private availableMargin;
2172
2371
  /** Clears both sides of the live balance join and the public account cache without emitting. */
@@ -2236,9 +2435,17 @@ declare const LighterUnifiedBalance: z.ZodObject<{
2236
2435
  }, z.core.$strip>;
2237
2436
  type LighterUnifiedBalance = z.infer<typeof LighterUnifiedBalance>;
2238
2437
 
2438
+ /**
2439
+ * The collateral asset each Lighter deployment margins perps in, as the venue names it in account
2440
+ * payloads. Everything else about the balance model is identical across deployments.
2441
+ */
2442
+ declare const LIGHTER_QUOTE_ASSETS: Record<LighterConnector, string>;
2443
+
2239
2444
  type LighterAccountTrackerConfig = AccountTrackerConfig & {
2240
2445
  /** Null leaves the tier unread: `/accountLimits` is authenticated and only Core mints a token. */
2241
2446
  sdk: PearSDK | null;
2447
+ /** The Lighter deployment this account lives on; hosts and collateral follow it. */
2448
+ connector: LighterConnector;
2242
2449
  account: TradeAccount;
2243
2450
  credentials: SupportedCredentials;
2244
2451
  };
@@ -2246,6 +2453,8 @@ type LighterAccountTrackerConfig = AccountTrackerConfig & {
2246
2453
  type AccountTierCallback = (tier: LighterAccountTier | null) => void;
2247
2454
  declare class LighterAccountTracker extends BaseAccountTracker {
2248
2455
  private readonly sdk;
2456
+ private readonly connector;
2457
+ private readonly quoteAsset;
2249
2458
  private readonly accountIdentifier;
2250
2459
  private readonly apiKeyIndex;
2251
2460
  private readonly apiPrivateKey;
@@ -2621,4 +2830,4 @@ declare class ExchangesSDK {
2621
2830
  private fetchCredentials;
2622
2831
  }
2623
2832
 
2624
- 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 };
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 };
package/dist/sdk.js CHANGED
@@ -63,6 +63,12 @@ class ExchangesSDK {
63
63
  sdk: this.sdk,
64
64
  demo: this.demo
65
65
  });
66
+ case "lighter_rhc":
67
+ return createExchangeHelper({
68
+ exchange: "lighter_rhc",
69
+ sdk: this.sdk,
70
+ demo: this.demo
71
+ });
66
72
  }
67
73
  }
68
74
  createSyncer(connection) {
@@ -17,7 +17,8 @@ function checkAccountStatus(exchange, config) {
17
17
  case "hyperliquid":
18
18
  return checkHyperliquidAccountStatus(config);
19
19
  case "lighter":
20
- return checkLighterAccountStatus(config);
20
+ case "lighter_rhc":
21
+ return checkLighterAccountStatus(config, exchange);
21
22
  default: {
22
23
  const _exhaustive = exchange;
23
24
  throw new Error(`Unsupported exchange: ${String(_exhaustive)}`);
@@ -5,7 +5,7 @@ import { warningStatus } from '../base';
5
5
 
6
6
  var __defProp = Object.defineProperty;
7
7
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
8
- async function checkLighterAccountStatus(config) {
8
+ async function checkLighterAccountStatus(config, connector) {
9
9
  const reasons = [];
10
10
  const options = config.statusOptions;
11
11
  const integratorAccountIndex = options?.integratorAccountIndex;
@@ -20,25 +20,25 @@ async function checkLighterAccountStatus(config) {
20
20
  reasons.push("lighter_api_key_invalid");
21
21
  } else {
22
22
  try {
23
- const token = await retrieveLighterAuthToken(config.sdk, {
23
+ const token = await retrieveLighterAuthToken(config.sdk, connector, {
24
24
  accountIndex,
25
25
  apiKeyIndex: credentials.api_key_index,
26
26
  apiPrivateKey: credentials.api_private_key
27
27
  }, config.demo);
28
- await fetchAccountMetadata(accountIndex, token, config.demo);
28
+ await fetchAccountMetadata(accountIndex, token, connector, config.demo);
29
29
  } catch {
30
30
  reasons.push("lighter_api_key_invalid");
31
31
  }
32
32
  }
33
33
  if (integratorAccountIndex !== void 0 && integratorMinPerpsMakerFee !== void 0 && integratorMinPerpsTakerFee !== void 0) {
34
34
  try {
35
- const token = await retrieveLighterAuthToken(config.sdk, {
35
+ const token = await retrieveLighterAuthToken(config.sdk, connector, {
36
36
  accountIndex,
37
37
  apiKeyIndex: credentials.api_key_index,
38
38
  apiPrivateKey: credentials.api_private_key
39
39
  }, config.demo);
40
40
  const helper = createExchangeHelper({
41
- exchange: "lighter",
41
+ exchange: connector,
42
42
  sdk: config.sdk,
43
43
  demo: config.demo
44
44
  });
@@ -17,7 +17,11 @@ function createAccountSyncer(exchange, config) {
17
17
  case "hyperliquid":
18
18
  return new HyperliquidAccountSyncer(config);
19
19
  case "lighter":
20
- return new LighterAccountSyncer(config);
20
+ case "lighter_rhc":
21
+ return new LighterAccountSyncer({
22
+ ...config,
23
+ connector: exchange
24
+ });
21
25
  default: {
22
26
  const _exhaustive = exchange;
23
27
  throw new Error(`Unsupported exchange: ${String(_exhaustive)}`);
@@ -2,7 +2,7 @@ import BigNumber from 'bignumber.js';
2
2
 
3
3
  var __defProp = Object.defineProperty;
4
4
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
5
- function toFundingPaymentEntries(events, instrumentIds) {
5
+ function toFundingPaymentEntries(events, instrumentIds, connector) {
6
6
  return events.reduce((entries, event) => {
7
7
  const instrumentId = event.market_id.toString();
8
8
  if (!instrumentIds.has(instrumentId)) {
@@ -13,7 +13,7 @@ function toFundingPaymentEntries(events, instrumentIds) {
13
13
  const signedSize = event.position_side === "short" ? unsignedSize.negated() : unsignedSize;
14
14
  const fundingPerUnit = signedSize.isZero() ? "0" : new BigNumber(event.change).div(signedSize).toFixed();
15
15
  entries.push({
16
- connector: "lighter",
16
+ connector,
17
17
  instrumentId,
18
18
  fundingRate: event.rate,
19
19
  notional: event.change,
@@ -23,7 +23,7 @@ class LighterAccountSyncer extends BaseAccountSyncer {
23
23
  }
24
24
  /** Returns this account's shared Lighter auth token. */
25
25
  async retrieveAuthToken() {
26
- return retrieveLighterAuthToken(this.sdk, {
26
+ return retrieveLighterAuthToken(this.sdk, this.connector, {
27
27
  accountIndex: this.accountIndex,
28
28
  apiKeyIndex: this.apiKeyIndex,
29
29
  apiPrivateKey: this.apiPrivateKey
@@ -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, this.throttle);
39
+ const response = await fetchAccount(this.accountIndex, token, this.connector, 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, this.throttle);
62
+ const trades = await fetchTradesSince(this.accountIndex, token, since, this.connector, 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();
@@ -71,7 +71,7 @@ class LighterAccountSyncer extends BaseAccountSyncer {
71
71
  if (!accountSide) return fills;
72
72
  const side = accountSide === "ask" ? "SELL" : "BUY";
73
73
  fills.push({
74
- connector: "lighter",
74
+ connector: this.connector,
75
75
  exchangeFillId: rawFill.trade_id_str ?? rawFill.trade_id.toString(),
76
76
  cloid: this.getClientOrderId(rawFill, accountSide),
77
77
  symbol: instrumentId,
@@ -92,9 +92,9 @@ 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, this.throttle);
95
+ const fundingEvents = await fetchPositionFundingSince(this.accountIndex, token, since, this.connector, this.demo, this.throttle);
96
96
  const instrumentIds = new Set(instruments.map((instrument) => instrument.id));
97
- return toFundingPaymentEntries(fundingEvents, instrumentIds);
97
+ return toFundingPaymentEntries(fundingEvents, instrumentIds, this.connector);
98
98
  }
99
99
  isReduceOnly(rawFill) {
100
100
  if (rawFill.type === "liquidation" || rawFill.type === "deleverage" || rawFill.type === "market-settlement") {
@@ -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 };