@gearbox-protocol/sdk 14.12.0-next.71 → 14.12.0-next.72

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 (130) hide show
  1. package/dist/cjs/model/history.js +25 -0
  2. package/dist/cjs/model/history.schema.js +45 -1
  3. package/dist/cjs/model/index.js +17 -3
  4. package/dist/cjs/model/positions.js +89 -0
  5. package/dist/cjs/model/positions.schema.js +28 -0
  6. package/dist/cjs/new-sdk/GearboxSDK.js +7 -0
  7. package/dist/cjs/new-sdk/index.js +3 -0
  8. package/dist/cjs/new-sdk/positions/PositionsNamespace.js +119 -0
  9. package/dist/cjs/new-sdk/positions/index.js +4 -0
  10. package/dist/cjs/new-sdk/positions/types.js +1 -0
  11. package/dist/cjs/offchain/GearboxAPI.js +9 -2
  12. package/dist/cjs/offchain/index.js +5 -2
  13. package/dist/cjs/offchain/opportunities/OffchainOpportunities.js +3 -14
  14. package/dist/cjs/offchain/opportunities/index.js +0 -1
  15. package/dist/cjs/offchain/positions/OffchainPositions.js +69 -0
  16. package/dist/cjs/offchain/positions/index.js +3 -0
  17. package/dist/cjs/offchain/types.js +17 -0
  18. package/dist/cjs/sdk/MultichainSDK.js +7 -0
  19. package/dist/cjs/sdk/OnchainSDK.js +7 -0
  20. package/dist/cjs/sdk/accounts/CreditAccountsServiceV310.js +84 -0
  21. package/dist/cjs/sdk/accounts/constants.js +12 -0
  22. package/dist/cjs/sdk/accounts/dominantCollateral.js +33 -0
  23. package/dist/cjs/sdk/accounts/index.js +4 -1
  24. package/dist/cjs/sdk/accounts/liquidations/LiquidationsService.js +3 -10
  25. package/dist/cjs/sdk/accounts/liquidations/constants.js +2 -6
  26. package/dist/cjs/sdk/accounts/liquidations/index.js +2 -1
  27. package/dist/cjs/sdk/index.js +11 -1
  28. package/dist/cjs/sdk/market/MarketSuite.js +7 -1
  29. package/dist/cjs/sdk/market/credit/CreditSuite.js +10 -1
  30. package/dist/cjs/sdk/market/math.js +37 -0
  31. package/dist/cjs/sdk/opportunities/index.js +2 -0
  32. package/dist/cjs/sdk/pools/PoolService.js +37 -0
  33. package/dist/cjs/sdk/positions/MultichainPositionsService.js +48 -0
  34. package/dist/cjs/sdk/positions/PositionsService.js +39 -0
  35. package/dist/cjs/sdk/positions/index.js +6 -0
  36. package/dist/cjs/sdk/positions/types.js +1 -0
  37. package/dist/esm/model/history.js +24 -1
  38. package/dist/esm/model/history.schema.js +42 -2
  39. package/dist/esm/model/index.js +6 -6
  40. package/dist/esm/model/positions.js +85 -1
  41. package/dist/esm/model/positions.schema.js +26 -1
  42. package/dist/esm/new-sdk/GearboxSDK.js +7 -0
  43. package/dist/esm/new-sdk/index.js +3 -1
  44. package/dist/esm/new-sdk/positions/PositionsNamespace.js +118 -0
  45. package/dist/esm/new-sdk/positions/index.js +3 -0
  46. package/dist/esm/new-sdk/positions/types.js +1 -0
  47. package/dist/esm/offchain/GearboxAPI.js +9 -2
  48. package/dist/esm/offchain/index.js +5 -3
  49. package/dist/esm/offchain/opportunities/OffchainOpportunities.js +2 -12
  50. package/dist/esm/offchain/opportunities/index.js +2 -2
  51. package/dist/esm/offchain/positions/OffchainPositions.js +68 -0
  52. package/dist/esm/offchain/positions/index.js +2 -0
  53. package/dist/esm/offchain/types.js +17 -1
  54. package/dist/esm/sdk/MultichainSDK.js +7 -0
  55. package/dist/esm/sdk/OnchainSDK.js +7 -0
  56. package/dist/esm/sdk/accounts/CreditAccountsServiceV310.js +84 -0
  57. package/dist/esm/sdk/accounts/constants.js +11 -0
  58. package/dist/esm/sdk/accounts/dominantCollateral.js +32 -0
  59. package/dist/esm/sdk/accounts/index.js +4 -2
  60. package/dist/esm/sdk/accounts/liquidations/LiquidationsService.js +3 -10
  61. package/dist/esm/sdk/accounts/liquidations/constants.js +1 -5
  62. package/dist/esm/sdk/accounts/liquidations/index.js +2 -1
  63. package/dist/esm/sdk/index.js +8 -3
  64. package/dist/esm/sdk/market/MarketSuite.js +7 -1
  65. package/dist/esm/sdk/market/credit/CreditSuite.js +10 -1
  66. package/dist/esm/sdk/market/math.js +37 -2
  67. package/dist/esm/sdk/opportunities/index.js +2 -2
  68. package/dist/esm/sdk/pools/PoolService.js +37 -0
  69. package/dist/esm/sdk/positions/MultichainPositionsService.js +47 -0
  70. package/dist/esm/sdk/positions/PositionsService.js +38 -0
  71. package/dist/esm/sdk/positions/index.js +4 -0
  72. package/dist/esm/sdk/positions/types.js +1 -0
  73. package/dist/types/model/history.d.ts +50 -2
  74. package/dist/types/model/history.schema.d.ts +32 -3
  75. package/dist/types/model/index.d.ts +5 -5
  76. package/dist/types/model/positions.d.ts +100 -1
  77. package/dist/types/model/positions.schema.d.ts +29 -1
  78. package/dist/types/new-sdk/AbstractNamespace.d.ts +2 -2
  79. package/dist/types/new-sdk/GearboxSDK.d.ts +6 -0
  80. package/dist/types/new-sdk/index.d.ts +4 -1
  81. package/dist/types/new-sdk/opportunities/OpportunitiesNamespace.d.ts +1 -1
  82. package/dist/types/new-sdk/positions/PositionsNamespace.d.ts +62 -0
  83. package/dist/types/new-sdk/positions/index.d.ts +3 -0
  84. package/dist/types/new-sdk/positions/types.d.ts +62 -0
  85. package/dist/types/new-sdk/utils/history.d.ts +6 -2
  86. package/dist/types/offchain/GearboxAPI.d.ts +8 -2
  87. package/dist/types/offchain/index.d.ts +5 -3
  88. package/dist/types/offchain/opportunities/OffchainOpportunities.d.ts +1 -9
  89. package/dist/types/offchain/opportunities/index.d.ts +2 -2
  90. package/dist/types/offchain/positions/OffchainPositions.d.ts +47 -0
  91. package/dist/types/offchain/positions/index.d.ts +2 -0
  92. package/dist/types/offchain/types.d.ts +12 -1
  93. package/dist/types/sdk/MultichainSDK.d.ts +6 -0
  94. package/dist/types/sdk/OnchainSDK.d.ts +6 -0
  95. package/dist/types/sdk/accounts/CreditAccountsServiceV310.d.ts +7 -1
  96. package/dist/types/sdk/accounts/constants.d.ts +11 -0
  97. package/dist/types/sdk/accounts/dominantCollateral.d.ts +22 -0
  98. package/dist/types/sdk/accounts/index.d.ts +5 -3
  99. package/dist/types/sdk/accounts/liquidations/MultichainLiquidationsService.d.ts +2 -2
  100. package/dist/types/sdk/accounts/liquidations/constants.d.ts +1 -5
  101. package/dist/types/sdk/accounts/liquidations/index.d.ts +2 -1
  102. package/dist/types/sdk/accounts/liquidations/types.d.ts +1 -1
  103. package/dist/types/sdk/accounts/types.d.ts +26 -1
  104. package/dist/types/sdk/base/TokensMeta.d.ts +1 -1
  105. package/dist/types/sdk/index.d.ts +11 -5
  106. package/dist/types/sdk/market/MarketConfiguratorContract.d.ts +1 -1
  107. package/dist/types/sdk/market/MarketSuite.d.ts +5 -1
  108. package/dist/types/sdk/market/credit/CreditManagerV310Contract.d.ts +1 -1
  109. package/dist/types/sdk/market/credit/CreditSuite.d.ts +8 -1
  110. package/dist/types/sdk/market/credit/types.d.ts +1 -1
  111. package/dist/types/sdk/market/math.d.ts +29 -1
  112. package/dist/types/sdk/market/oracle/PriceOracleBaseContract.d.ts +2 -2
  113. package/dist/types/sdk/market/oracle/types.d.ts +2 -2
  114. package/dist/types/sdk/market/pool/LinearInterestRateModelContract.d.ts +1 -1
  115. package/dist/types/sdk/market/pool/PoolQuotaKeeperV310Contract.d.ts +1 -1
  116. package/dist/types/sdk/market/pool/PoolSuite.d.ts +1 -1
  117. package/dist/types/sdk/market/pool/PoolV310Contract.d.ts +1 -1
  118. package/dist/types/sdk/market/pool/types.d.ts +1 -1
  119. package/dist/types/sdk/market/pricefeeds/AbstractPriceFeed.d.ts +1 -1
  120. package/dist/types/sdk/market/pricefeeds/types.d.ts +1 -1
  121. package/dist/types/sdk/opportunities/MultichainOpportunitiesService.d.ts +2 -2
  122. package/dist/types/sdk/opportunities/index.d.ts +2 -2
  123. package/dist/types/sdk/pools/PoolService.d.ts +7 -1
  124. package/dist/types/sdk/pools/index.d.ts +2 -2
  125. package/dist/types/sdk/pools/types.d.ts +18 -1
  126. package/dist/types/sdk/positions/MultichainPositionsService.d.ts +33 -0
  127. package/dist/types/sdk/positions/PositionsService.d.ts +22 -0
  128. package/dist/types/sdk/positions/index.d.ts +4 -0
  129. package/dist/types/sdk/positions/types.d.ts +25 -0
  130. package/package.json +1 -1
@@ -17,10 +17,13 @@ import { hexEq } from "../utils/hex.js";
17
17
  import "../utils/index.js";
18
18
  import { SDKConstruct } from "../base/SDKConstruct.js";
19
19
  import "../base/index.js";
20
+ import { borrowApyBps, healthFactorBps, positionLeverage, usdToNumber } from "../market/math.js";
20
21
  import { simulateWithPriceUpdates } from "../utils/viem/simulateWithPriceUpdates.js";
21
22
  import "../utils/viem/index.js";
22
23
  import { getRawPriceUpdates } from "../market/pricefeeds/getRawPriceUpdates.js";
23
24
  import "../market/index.js";
25
+ import "./constants.js";
26
+ import { dominantCollateral } from "./dominantCollateral.js";
24
27
  import { extractPriceUpdates, extractQuotaTokens, mergePriceUpdates } from "./multicall-utils.js";
25
28
  import { encodeFunctionData, getContract } from "viem";
26
29
  //#region src/sdk/accounts/CreditAccountsServiceV310.ts
@@ -218,6 +221,87 @@ var CreditAccountsServiceV310 = class extends SDKConstruct {
218
221
  return filtered.sort((a, b) => Number(a.healthFactor - b.healthFactor));
219
222
  }
220
223
  /**
224
+ * {@inheritDoc ICreditAccountsService.listPositions}
225
+ **/
226
+ async listPositions(props) {
227
+ const { owner, includeZeroDebt } = props;
228
+ const [accounts] = await Promise.all([this.getBorrowerCreditAccounts(owner, { includeZeroDebt }), this.sdk.withdrawalCompressor?.loadWithdrawableAssets()]);
229
+ const describable = accounts.filter((ca) => {
230
+ if (!ca.success) this.logger?.warn(`cannot describe position of ${this.labelAddress(ca.creditAccount)}: collateral computation failed`);
231
+ return ca.success;
232
+ });
233
+ const withdrawals = await Promise.all(describable.map((ca) => this.#accountWithdrawals(ca)));
234
+ return describable.map((ca, i) => this.#strategyPosition(ca, withdrawals[i] ?? new AddressMap()));
235
+ }
236
+ /**
237
+ * Builds one strategy position from an account snapshot.
238
+ *
239
+ * @param withdrawals - Delayed withdrawals of the account, keyed by the
240
+ * phantom token that represents them on it.
241
+ **/
242
+ #strategyPosition(ca, withdrawals) {
243
+ const suite = this.sdk.marketRegister.findCreditManager(ca.creditManager);
244
+ const { market } = suite;
245
+ const { priceOracle } = market;
246
+ const { pool } = market.pool;
247
+ const token = this.sdk.tokensMeta.mustGetToken(market.unwrappedUnderlying);
248
+ const totalDebtValue = ca.debt + ca.accruedInterest + ca.accruedFees;
249
+ const collateral = dominantCollateral(ca, market);
250
+ return {
251
+ kind: "strategy",
252
+ chainId: this.sdk.chainId,
253
+ creditManager: ca.creditManager,
254
+ creditAccount: ca.creditAccount,
255
+ name: collateral ? suite.strategyName(collateral) : token.symbol,
256
+ targetCollateral: collateral ? this.sdk.tokensMeta.mustGetToken(collateral) : null,
257
+ leverage: positionLeverage(totalDebtValue, ca.totalValue),
258
+ borrowApy: borrowApyBps(pool.baseInterestRate, suite.creditManager.feeInterest),
259
+ totalDebt: {
260
+ token,
261
+ value: totalDebtValue,
262
+ valueUsd: usdToNumber(ca.totalDebtUSD)
263
+ },
264
+ totalValue: {
265
+ token,
266
+ value: ca.totalValue,
267
+ valueUsd: usdToNumber(ca.totalValueUSD)
268
+ },
269
+ healthFactor: healthFactorBps(ca.healthFactor),
270
+ collaterals: ca.tokens.flatMap((t) => {
271
+ if ((t.mask & ca.enabledTokensMask) === 0n || t.balance <= 10n) return [];
272
+ return [{
273
+ collateral: priceOracle.toTokenAmount(t.token, t.balance),
274
+ quota: priceOracle.toTokenAmount(market.underlying, t.quota),
275
+ withdrawals: withdrawals.get(t.token) ?? []
276
+ }];
277
+ })
278
+ };
279
+ }
280
+ /**
281
+ * Delayed withdrawals of one account, keyed by the phantom token that
282
+ * represents them on it, so that each collateral row can pick up its own.
283
+ **/
284
+ async #accountWithdrawals(ca) {
285
+ const compressor = this.sdk.withdrawalCompressor;
286
+ const byPhantomToken = new AddressMap(void 0, "accountWithdrawals");
287
+ const holdsPhantomToken = ca.tokens.some((t) => t.balance > 10n && compressor?.getWithdrawalSourceToken(t.token) !== void 0);
288
+ if (!compressor || !holdsPhantomToken) return byPhantomToken;
289
+ const { priceOracle } = this.sdk.marketRegister.findByCreditManager(ca.creditManager);
290
+ const { claimable, pending } = await compressor.getCurrentWithdrawals(ca.creditAccount);
291
+ const add = (w, outputs, claimableAt) => {
292
+ const assets = outputs.map((o) => ({
293
+ isDelayed: true,
294
+ ...priceOracle.toTokenAmount(o.token, o.amount),
295
+ redeemer: w.redeemer,
296
+ claimableAt: claimableAt === void 0 ? void 0 : Number(claimableAt)
297
+ }));
298
+ byPhantomToken.upsert(w.withdrawalPhantomToken, [...byPhantomToken.get(w.withdrawalPhantomToken) ?? [], ...assets]);
299
+ };
300
+ for (const w of claimable) add(w, w.outputs);
301
+ for (const w of pending) add(w, w.expectedOutputs, w.claimableAt);
302
+ return byPhantomToken;
303
+ }
304
+ /**
221
305
  * {@inheritDoc ICreditAccountsService.getRewards}
222
306
  **/
223
307
  async getRewards(creditAccount) {
@@ -0,0 +1,11 @@
1
+ //#region src/sdk/accounts/constants.ts
2
+ /**
3
+ * Token balances at or below this threshold are treated as dust and ignored,
4
+ * consistent with the rest of the SDK (see `filterDust`).
5
+ *
6
+ * Shared by every service that describes what a credit account holds, so that
7
+ * a liquidation row and a position row agree on which balances exist at all.
8
+ **/
9
+ const DUST_THRESHOLD = 10n;
10
+ //#endregion
11
+ export { DUST_THRESHOLD };
@@ -0,0 +1,32 @@
1
+ import { hexEq } from "../utils/hex.js";
2
+ import "../utils/index.js";
3
+ import "./constants.js";
4
+ //#region src/sdk/accounts/dominantCollateral.ts
5
+ /**
6
+ * The account's dominant collateral: the most valuable enabled non-underlying
7
+ * token it holds above dust, by USD value.
8
+ *
9
+ * This is the single definition of "what this account is a position in".
10
+ * Using onchain-only data we can only determine at the time of the call (without
11
+ * unreasably difficult calls)
12
+ *
13
+ * @param account - Account to inspect.
14
+ * @param market - Market of the account, whose oracle prices the candidates.
15
+ * @returns The dominant collateral, or `undefined` when the account holds
16
+ * nothing but its underlying, or nothing the oracle can price.
17
+ **/
18
+ function dominantCollateral(account, market) {
19
+ let bestValue = 0;
20
+ let dominant;
21
+ for (const t of account.tokens) {
22
+ if (hexEq(t.token, account.underlying) || (t.mask & account.enabledTokensMask) === 0n || t.balance <= 10n) continue;
23
+ const value = market.priceOracle.safeUsdValue(t.token, t.balance) ?? 0;
24
+ if (value > bestValue) {
25
+ bestValue = value;
26
+ dominant = t.token;
27
+ }
28
+ }
29
+ return dominant;
30
+ }
31
+ //#endregion
32
+ export { dominantCollateral };
@@ -1,7 +1,9 @@
1
+ import { DUST_THRESHOLD } from "./constants.js";
2
+ import { dominantCollateral } from "./dominantCollateral.js";
1
3
  import { CreditAccountsServiceV310 } from "./CreditAccountsServiceV310.js";
2
4
  import { primaryInstantOutput } from "./intents/operations/claim-delayed/index.js";
3
5
  import { CreditAccountOperationsService } from "./intents/index.js";
4
- import { DUST_THRESHOLD, LIQUIDATION_APPROVAL_BUFFER, LIQUIDATION_COMPRESSOR_V313_ADDRESS } from "./liquidations/constants.js";
6
+ import { LIQUIDATION_APPROVAL_BUFFER, LIQUIDATION_COMPRESSOR_V313_ADDRESS } from "./liquidations/constants.js";
5
7
  import { LiquidationsService } from "./liquidations/LiquidationsService.js";
6
8
  import { MultichainLiquidationsService } from "./liquidations/MultichainLiquidationsService.js";
7
9
  import "./liquidations/index.js";
@@ -18,4 +20,4 @@ import { toWithdrawalStatus } from "./withdrawal-compressor/types.js";
18
20
  import { WithdrawalCompressorV313Contract } from "./withdrawal-compressor/WithdrawalCompressorV313Contract.js";
19
21
  import { createWithdrawalCompressor } from "./withdrawal-compressor/createWithdrawalCompressor.js";
20
22
  import "./withdrawal-compressor/index.js";
21
- export { AbstractWithdrawalCompressorContract, CreditAccountOperationsService, CreditAccountsServiceV310, DELAYED_INTENT_TYPES, DELAYED_INTENT_VERSION, DUST_THRESHOLD, InvalidDelayedIntentError, LIQUIDATION_APPROVAL_BUFFER, LIQUIDATION_COMPRESSOR_V313_ADDRESS, LiquidationsService, MultichainLiquidationsService, RedemptionLoggerV310Contract, WithdrawalCompressorV310Contract, WithdrawalCompressorV311Contract, WithdrawalCompressorV313Contract, createRedemptionLogger, createWithdrawalCompressor, decodeDelayedIntent, encodeDelayedIntent, getWithdrawalCompressorAddress, iCreditAccountAbi, primaryInstantOutput, toClaimableWithdrawal, toPendingWithdrawal, toRequestableWithdrawal, toWithdrawalStatus };
23
+ export { AbstractWithdrawalCompressorContract, CreditAccountOperationsService, CreditAccountsServiceV310, DELAYED_INTENT_TYPES, DELAYED_INTENT_VERSION, DUST_THRESHOLD, InvalidDelayedIntentError, LIQUIDATION_APPROVAL_BUFFER, LIQUIDATION_COMPRESSOR_V313_ADDRESS, LiquidationsService, MultichainLiquidationsService, RedemptionLoggerV310Contract, WithdrawalCompressorV310Contract, WithdrawalCompressorV311Contract, WithdrawalCompressorV313Contract, createRedemptionLogger, createWithdrawalCompressor, decodeDelayedIntent, dominantCollateral, encodeDelayedIntent, getWithdrawalCompressorAddress, iCreditAccountAbi, primaryInstantOutput, toClaimableWithdrawal, toPendingWithdrawal, toRequestableWithdrawal, toWithdrawalStatus };
@@ -17,6 +17,8 @@ import "../../market/rwa/midas/index.js";
17
17
  import { RWA_LIQUIDATOR_SECURITIZE } from "../../market/rwa/securitize/constants.js";
18
18
  import { SecuritizeLiquidatorContract } from "../../market/rwa/securitize/SecuritizeLiquidatorContract.js";
19
19
  import "../../market/rwa/securitize/index.js";
20
+ import "../constants.js";
21
+ import { dominantCollateral } from "../dominantCollateral.js";
20
22
  import { LIQUIDATION_APPROVAL_BUFFER, LIQUIDATION_COMPRESSOR_V313_ADDRESS } from "./constants.js";
21
23
  //#region src/sdk/accounts/liquidations/LiquidationsService.ts
22
24
  /**
@@ -279,16 +281,7 @@ var LiquidationsService = class extends SDKConstruct {
279
281
  };
280
282
  }
281
283
  #mainAsset(ca, market, fallback) {
282
- let bestValue = 0;
283
- let asset;
284
- for (const t of ca.tokens) {
285
- if (hexEq(t.token, ca.underlying) || (t.mask & ca.enabledTokensMask) === 0n || t.balance <= 10n) continue;
286
- const value = market.priceOracle.safeUsdValue(t.token, t.balance) ?? 0;
287
- if (value > bestValue) {
288
- bestValue = value;
289
- asset = t.token;
290
- }
291
- }
284
+ const asset = dominantCollateral(ca, market);
292
285
  if (!asset) return fallback;
293
286
  return this.sdk.withdrawalCompressor?.getWithdrawalSourceToken(asset) ?? asset;
294
287
  }
@@ -1,11 +1,7 @@
1
+ import { DUST_THRESHOLD } from "../constants.js";
1
2
  //#region src/sdk/accounts/liquidations/constants.ts
2
3
  const LIQUIDATION_COMPRESSOR_V313_ADDRESS = "0xB70C4500a0afF02107eB983a348F22492fB6dC94";
3
4
  /**
4
- * Token balances at or below this threshold are treated as dust and ignored,
5
- * consistent with the rest of the SDK (see `filterDust`).
6
- **/
7
- const DUST_THRESHOLD = 10n;
8
- /**
9
5
  * Headroom (in bps) added on top of the amount the liquidation pulls when
10
6
  * building the liquidator's approval, so that the transaction does not revert
11
7
  * when prices move between the preview and the execution.
@@ -1,4 +1,5 @@
1
- import { DUST_THRESHOLD, LIQUIDATION_APPROVAL_BUFFER, LIQUIDATION_COMPRESSOR_V313_ADDRESS } from "./constants.js";
1
+ import { DUST_THRESHOLD } from "../constants.js";
2
+ import { LIQUIDATION_APPROVAL_BUFFER, LIQUIDATION_COMPRESSOR_V313_ADDRESS } from "./constants.js";
2
3
  import { LiquidationsService } from "./LiquidationsService.js";
3
4
  import { MultichainLiquidationsService } from "./MultichainLiquidationsService.js";
4
5
  import "./types.js";
@@ -47,7 +47,7 @@ import { createAdapter } from "./market/adapters/createAdapter.js";
47
47
  import { CreditConfiguratorV310Contract } from "./market/credit/CreditConfiguratorV310Contract.js";
48
48
  import { CreditFacadeV310BaseContract, creditFacadeV310Abi as abi } from "./market/credit/CreditFacadeV310BaseContract.js";
49
49
  import { CreditFacadeV310Contract } from "./market/credit/CreditFacadeV310Contract.js";
50
- import { additionalBorrowApyBps, borrowApyBps, maxLeverage, rayToBps, usdToNumber, utilizationBps } from "./market/math.js";
50
+ import { additionalBorrowApyBps, borrowApyBps, healthFactorBps, maxLeverage, positionLeverage, rayToBps, usdToNumber, utilizationBps } from "./market/math.js";
51
51
  import { CreditManagerV310Contract } from "./market/credit/CreditManagerV310Contract.js";
52
52
  import { CreditSuite } from "./market/credit/CreditSuite.js";
53
53
  import { simulateMulticall } from "./utils/viem/simulateMulticall.js";
@@ -102,10 +102,12 @@ import { SecuritizeRWAFactory } from "./market/rwa/securitize/SecuritizeRWAFacto
102
102
  import { RWARegistry } from "./market/rwa/RWARegistry.js";
103
103
  import { RWA_FACTORY_TYPES, isRWAFactory } from "./market/rwa/types.js";
104
104
  import "./market/index.js";
105
+ import { DUST_THRESHOLD } from "./accounts/constants.js";
106
+ import { dominantCollateral } from "./accounts/dominantCollateral.js";
105
107
  import { CreditAccountsServiceV310 } from "./accounts/CreditAccountsServiceV310.js";
106
108
  import { primaryInstantOutput } from "./accounts/intents/operations/claim-delayed/index.js";
107
109
  import { CreditAccountOperationsService } from "./accounts/intents/index.js";
108
- import { DUST_THRESHOLD, LIQUIDATION_APPROVAL_BUFFER, LIQUIDATION_COMPRESSOR_V313_ADDRESS } from "./accounts/liquidations/constants.js";
110
+ import { LIQUIDATION_APPROVAL_BUFFER, LIQUIDATION_COMPRESSOR_V313_ADDRESS } from "./accounts/liquidations/constants.js";
109
111
  import { LiquidationsService } from "./accounts/liquidations/LiquidationsService.js";
110
112
  import { MultichainLiquidationsService } from "./accounts/liquidations/MultichainLiquidationsService.js";
111
113
  import { DELAYED_INTENT_TYPES, DELAYED_INTENT_VERSION, decodeDelayedIntent, encodeDelayedIntent } from "./accounts/withdrawal-compressor/intent-codec.js";
@@ -131,6 +133,9 @@ import { PluginStateVersionError } from "./plugins/errors.js";
131
133
  import "./plugins/index.js";
132
134
  import { PoolService } from "./pools/PoolService.js";
133
135
  import "./pools/index.js";
136
+ import { MultichainPositionsService } from "./positions/MultichainPositionsService.js";
137
+ import { PositionsService } from "./positions/PositionsService.js";
138
+ import "./positions/index.js";
134
139
  import { assetsMap } from "./router/helpers.js";
135
140
  import { RouterV310Contract } from "./router/RouterV310Contract.js";
136
141
  import { createRouter } from "./router/createRouter.js";
@@ -139,4 +144,4 @@ import { OnchainSDK, STATE_VERSION } from "./OnchainSDK.js";
139
144
  import { MultichainSDK } from "./MultichainSDK.js";
140
145
  import { attachOptionsSchema, onchainSDKOptionsSchema } from "./options.js";
141
146
  import "./types/index.js";
142
- export { ADDRESS_0X0, ADDRESS_PROVIDER_V310, AP_ACCOUNT_FACTORY, AP_ACL, AP_BOT_LIST, AP_BYTECODE_REPOSITORY, AP_CONTRACTS_REGISTER, AP_CONTROLLER_TIMELOCK, AP_CREDIT_ACCOUNT_COMPRESSOR, AP_CREDIT_SUITE_COMPRESSOR, AP_DATA_COMPRESSOR, AP_DELEVERAGE_BOT_HV, AP_DELEVERAGE_BOT_LV, AP_DELEVERAGE_BOT_PEGGED, AP_GAUGE_COMPRESSOR, AP_GEAR_STAKING, AP_GEAR_TOKEN, AP_INFLATION_ATTACK_BLOCKER, AP_INSOLVENCY_CHECKER, AP_MARKET_COMPRESSOR, AP_MARKET_CONFIGURATOR, AP_PARTIAL_LIQUIDATION_BOT, AP_PERIPHERY_COMPRESSOR, AP_PRICE_FEED_COMPRESSOR, AP_PRICE_FEED_STORE, AP_PRICE_ORACLE, AP_REDEMPTION_LOGGER, AP_REWARDS_COMPRESSOR, AP_ROUTER, AP_RWA_COMPRESSOR, AP_TOKEN_COMPRESSOR, AP_TREASURY, AP_WETH_GATEWAY, AP_WETH_TOKEN, AP_ZAPPER_REGISTER, AP_ZERO_PRICE_FEED, AbstractLPPriceFeedContract, AbstractPriceFeedContract, AbstractWithdrawalCompressorContract, AddressMap, AddressProviderV310Contract, AddressSet, AssetsMap, BLOCKS_PER_WEEK_BY_NETWORK, BalancerStablePriceFeedContract, BalancerWeightedPriceFeedContract, BaseContract, BasePlugin, BigIntMath, BotPermissions, BoundedPriceFeedContract, ChainContractsRegister, ChainNotConfiguredError, CompositePriceFeedContract, Construct, ContractParseError, CreditAccountOperationsService, CreditAccountsServiceV310, CreditConfiguratorV310Contract, CreditFacadeV310BaseContract, CreditFacadeV310Contract, CreditManagerV310Contract, CreditSuite, CurveCryptoPriceFeedContract, CurveStablePriceFeedContract, CurveUSDPriceFeedContract, DELAYED_INTENT_TYPES, DELAYED_INTENT_VERSION, DUST_THRESHOLD, Erc4626PriceFeedContract, ExternalPriceFeedContract, GaugeContract, IERC20ZapperContract, IETHZapperContract, InvalidDelayedIntentError, LEVERAGE_DECIMALS, LIQUIDATION_APPROVAL_BUFFER, LIQUIDATION_COMPRESSOR_V313_ADDRESS, LinearInterestRateModelContract, LiquidationsService, MAX_INT, MAX_UINT16, MAX_UINT256, MIN_INT96, MULTICALL_ADDRESS, MarketRegister, MarketSuite, MellowLRTPriceFeedContract, MidasLiquidatorContract, MissingSerializedParamsError, MultichainConstruct, MultichainLiquidationsService, MultichainOpportunitiesService, MultichainSDK, NATIVE_ADDRESS, NOT_DEPLOYED, NO_VERSION, NetworkType, OnchainSDK, OpportunitiesService, PERCENTAGE_DECIMALS, PERCENTAGE_FACTOR, PERCENTAGE_FACTOR_1KK, PERIPHERY_CONTRACTS, PHANTOM_TOKEN_CONTRACT_TYPES, PHANTOM_TOKEN_MIDAS_REDEMPTION, PHANTOM_TOKEN_SECURITIZE_REDEMPTION, PRICE_DECIMALS, PRICE_DECIMALS_POW, PartialPriceFeedInitError, PendleTWAPPTPriceFeed, PlaceholderAdapterContract, PlaceholderContract, PluginStateVersionError, PoolService, PoolSuite, PoolV310Contract, PriceFeedRef, PriceFeedRegister, PriceOracleV310Contract, PythPriceFeed, RAMP_DURATION_BY_NETWORK, RAY, RAY_DECIMALS_POW, RWARegistry, RWA_FACTORY_SECURITIZE, RWA_FACTORY_TYPES, RWA_LIQUIDATOR_MIDAS, RWA_LIQUIDATOR_SECURITIZE, RWA_ON_DEMAND_LP_MONOPOLIZED, RWA_UNDERLYING_DEFAULT, RWA_UNDERLYING_ON_DEMAND, RedemptionLoggerV310Contract, RedstonePriceFeedContract, RouterV310Contract, SDKConstruct, SECONDS_PER_YEAR, SECURITIZE_REGISTER_VAULT_TYPES, SLIPPAGE_DECIMALS, STATE_VERSION, SUPPORTED_NETWORKS, SdkAlreadyAttachedError, SdkChainMismatchError, SdkMissingChainStateError, SdkNotAttachedError, SdkStateVersionMismatchError, SdkSyncFailedError, SecuritizeLiquidatorContract, SecuritizeRWAFactory, SimulateWithPriceUpdatesError, SimulationError, TokensMeta, TypedObjectUtils, UnsupportedZapperFunctionError, VERSION_RANGE_310, VotingContractStatus, WAD, WAD_DECIMALS_POW, WithdrawalCompressorV310Contract, WithdrawalCompressorV311Contract, WithdrawalCompressorV313Contract, WstETHPriceFeedContract, YearnPriceFeedContract, ZapperContract, ZeroPriceFeedContract, ZodAddress, ZodHex, additionalBorrowApyBps, assetsMap, attachOptionsSchema, borrowApyBps, botPermissionsToString, bytes32ToString, chains, childLogger, createAdapter, createAddressProvider, createPriceOracle, createRawTx, createRedemptionLogger, createRouter, createWithdrawalCompressor, createZapper, abi as creditFacadeV310Abi, decodeDelayedIntent, detectNetwork, encodeDelayedIntent, estimateRawTxGas, etherscanApiUrl, etherscanUrl, executeDelegatedMulticalls, fetchPythPayloads, fetchRedstonePayloads, filterDust, filterDustUSD, findCuratorMarketConfigurator, fmtBinaryMask, formatBN, formatBNvalue, formatDuration, formatLeverage, formatNumberToString_, formatPercentage, formatTimestamp, functionArgsToMap, functionArgsToRecord, generateCastTraceCall, getAssetType, getCastTraceArgs, getChain, getCuratorName, getFunctionSignature, getNetworkType, getRawPriceUpdates, getSimulateWithPriceUpdatesError, getWithdrawalCompressorAddress, halfRAY, hexEq, hydrateAddressProvider, iCreditAccountAbi, isDust, isLPPriceFeed, isPublicNetwork, isRWAFactory, isRWAToken, isSunsetPool, isSunsetStrategy, isSupportedNetwork, isUpdatablePriceFeed, isV310, isVersionRange, json_parse, json_stringify, maxLeverage, numberWithCommas, onchainSDKOptionsSchema, percentFmt, primaryInstantOutput, rayToBps, rayToNumber, retry, sendRawTx, shortAddress, shortHash, simulateCall, simulateMulticall, simulateWithPriceUpdates, toAddress, toBN, toBigInt, toClaimableWithdrawal, toPendingWithdrawal, toRequestableWithdrawal, toSignificant, toWithdrawalStatus, usdToNumber, utilizationBps, watchBlocksAsync };
147
+ export { ADDRESS_0X0, ADDRESS_PROVIDER_V310, AP_ACCOUNT_FACTORY, AP_ACL, AP_BOT_LIST, AP_BYTECODE_REPOSITORY, AP_CONTRACTS_REGISTER, AP_CONTROLLER_TIMELOCK, AP_CREDIT_ACCOUNT_COMPRESSOR, AP_CREDIT_SUITE_COMPRESSOR, AP_DATA_COMPRESSOR, AP_DELEVERAGE_BOT_HV, AP_DELEVERAGE_BOT_LV, AP_DELEVERAGE_BOT_PEGGED, AP_GAUGE_COMPRESSOR, AP_GEAR_STAKING, AP_GEAR_TOKEN, AP_INFLATION_ATTACK_BLOCKER, AP_INSOLVENCY_CHECKER, AP_MARKET_COMPRESSOR, AP_MARKET_CONFIGURATOR, AP_PARTIAL_LIQUIDATION_BOT, AP_PERIPHERY_COMPRESSOR, AP_PRICE_FEED_COMPRESSOR, AP_PRICE_FEED_STORE, AP_PRICE_ORACLE, AP_REDEMPTION_LOGGER, AP_REWARDS_COMPRESSOR, AP_ROUTER, AP_RWA_COMPRESSOR, AP_TOKEN_COMPRESSOR, AP_TREASURY, AP_WETH_GATEWAY, AP_WETH_TOKEN, AP_ZAPPER_REGISTER, AP_ZERO_PRICE_FEED, AbstractLPPriceFeedContract, AbstractPriceFeedContract, AbstractWithdrawalCompressorContract, AddressMap, AddressProviderV310Contract, AddressSet, AssetsMap, BLOCKS_PER_WEEK_BY_NETWORK, BalancerStablePriceFeedContract, BalancerWeightedPriceFeedContract, BaseContract, BasePlugin, BigIntMath, BotPermissions, BoundedPriceFeedContract, ChainContractsRegister, ChainNotConfiguredError, CompositePriceFeedContract, Construct, ContractParseError, CreditAccountOperationsService, CreditAccountsServiceV310, CreditConfiguratorV310Contract, CreditFacadeV310BaseContract, CreditFacadeV310Contract, CreditManagerV310Contract, CreditSuite, CurveCryptoPriceFeedContract, CurveStablePriceFeedContract, CurveUSDPriceFeedContract, DELAYED_INTENT_TYPES, DELAYED_INTENT_VERSION, DUST_THRESHOLD, Erc4626PriceFeedContract, ExternalPriceFeedContract, GaugeContract, IERC20ZapperContract, IETHZapperContract, InvalidDelayedIntentError, LEVERAGE_DECIMALS, LIQUIDATION_APPROVAL_BUFFER, LIQUIDATION_COMPRESSOR_V313_ADDRESS, LinearInterestRateModelContract, LiquidationsService, MAX_INT, MAX_UINT16, MAX_UINT256, MIN_INT96, MULTICALL_ADDRESS, MarketRegister, MarketSuite, MellowLRTPriceFeedContract, MidasLiquidatorContract, MissingSerializedParamsError, MultichainConstruct, MultichainLiquidationsService, MultichainOpportunitiesService, MultichainPositionsService, MultichainSDK, NATIVE_ADDRESS, NOT_DEPLOYED, NO_VERSION, NetworkType, OnchainSDK, OpportunitiesService, PERCENTAGE_DECIMALS, PERCENTAGE_FACTOR, PERCENTAGE_FACTOR_1KK, PERIPHERY_CONTRACTS, PHANTOM_TOKEN_CONTRACT_TYPES, PHANTOM_TOKEN_MIDAS_REDEMPTION, PHANTOM_TOKEN_SECURITIZE_REDEMPTION, PRICE_DECIMALS, PRICE_DECIMALS_POW, PartialPriceFeedInitError, PendleTWAPPTPriceFeed, PlaceholderAdapterContract, PlaceholderContract, PluginStateVersionError, PoolService, PoolSuite, PoolV310Contract, PositionsService, PriceFeedRef, PriceFeedRegister, PriceOracleV310Contract, PythPriceFeed, RAMP_DURATION_BY_NETWORK, RAY, RAY_DECIMALS_POW, RWARegistry, RWA_FACTORY_SECURITIZE, RWA_FACTORY_TYPES, RWA_LIQUIDATOR_MIDAS, RWA_LIQUIDATOR_SECURITIZE, RWA_ON_DEMAND_LP_MONOPOLIZED, RWA_UNDERLYING_DEFAULT, RWA_UNDERLYING_ON_DEMAND, RedemptionLoggerV310Contract, RedstonePriceFeedContract, RouterV310Contract, SDKConstruct, SECONDS_PER_YEAR, SECURITIZE_REGISTER_VAULT_TYPES, SLIPPAGE_DECIMALS, STATE_VERSION, SUPPORTED_NETWORKS, SdkAlreadyAttachedError, SdkChainMismatchError, SdkMissingChainStateError, SdkNotAttachedError, SdkStateVersionMismatchError, SdkSyncFailedError, SecuritizeLiquidatorContract, SecuritizeRWAFactory, SimulateWithPriceUpdatesError, SimulationError, TokensMeta, TypedObjectUtils, UnsupportedZapperFunctionError, VERSION_RANGE_310, VotingContractStatus, WAD, WAD_DECIMALS_POW, WithdrawalCompressorV310Contract, WithdrawalCompressorV311Contract, WithdrawalCompressorV313Contract, WstETHPriceFeedContract, YearnPriceFeedContract, ZapperContract, ZeroPriceFeedContract, ZodAddress, ZodHex, additionalBorrowApyBps, assetsMap, attachOptionsSchema, borrowApyBps, botPermissionsToString, bytes32ToString, chains, childLogger, createAdapter, createAddressProvider, createPriceOracle, createRawTx, createRedemptionLogger, createRouter, createWithdrawalCompressor, createZapper, abi as creditFacadeV310Abi, decodeDelayedIntent, detectNetwork, dominantCollateral, encodeDelayedIntent, estimateRawTxGas, etherscanApiUrl, etherscanUrl, executeDelegatedMulticalls, fetchPythPayloads, fetchRedstonePayloads, filterDust, filterDustUSD, findCuratorMarketConfigurator, fmtBinaryMask, formatBN, formatBNvalue, formatDuration, formatLeverage, formatNumberToString_, formatPercentage, formatTimestamp, functionArgsToMap, functionArgsToRecord, generateCastTraceCall, getAssetType, getCastTraceArgs, getChain, getCuratorName, getFunctionSignature, getNetworkType, getRawPriceUpdates, getSimulateWithPriceUpdatesError, getWithdrawalCompressorAddress, halfRAY, healthFactorBps, hexEq, hydrateAddressProvider, iCreditAccountAbi, isDust, isLPPriceFeed, isPublicNetwork, isRWAFactory, isRWAToken, isSunsetPool, isSunsetStrategy, isSupportedNetwork, isUpdatablePriceFeed, isV310, isVersionRange, json_parse, json_stringify, maxLeverage, numberWithCommas, onchainSDKOptionsSchema, percentFmt, positionLeverage, primaryInstantOutput, rayToBps, rayToNumber, retry, sendRawTx, shortAddress, shortHash, simulateCall, simulateMulticall, simulateWithPriceUpdates, toAddress, toBN, toBigInt, toClaimableWithdrawal, toPendingWithdrawal, toRequestableWithdrawal, toSignificant, toWithdrawalStatus, usdToNumber, utilizationBps, watchBlocksAsync };
@@ -123,6 +123,12 @@ var MarketSuite = class extends SDKConstruct {
123
123
  return this.tokensMeta.mustGetToken(this.unwrappedUnderlying);
124
124
  }
125
125
  /**
126
+ * Display name of this market's pool, e.g. `"USDC Pool"`.
127
+ */
128
+ get poolName() {
129
+ return `${this.underlyingToken.symbol} Pool`;
130
+ }
131
+ /**
126
132
  * {@inheritDoc MarketConfiguratorContract.curator}
127
133
  */
128
134
  get curator() {
@@ -212,7 +218,7 @@ var MarketSuite = class extends SDKConstruct {
212
218
  kind: "pool",
213
219
  chainId: this.chainId,
214
220
  pool: pool.address,
215
- name: `${this.underlyingToken.symbol} Pool`,
221
+ name: this.poolName,
216
222
  curator: this.curator,
217
223
  underlyingToken: this.underlyingToken,
218
224
  totalSupply: oracle.toAmount(pool.underlying, pool.totalAssets),
@@ -141,6 +141,15 @@ var CreditSuite = class extends SDKConstruct {
141
141
  return BigIntMath.min(debtParams?.available ?? 115792089237316195423570985008687907853269984665640564039457584007913129639935n, pool.availableLiquidity, this.creditFacade.maxDebt);
142
142
  }
143
143
  /**
144
+ * Display name of a leveraged position built on one collateral token, e.g.
145
+ * `"wstETH / WETH"`.
146
+ *
147
+ * @param collateral - Target collateral of the position.
148
+ */
149
+ strategyName(collateral) {
150
+ return `${this.tokensMeta.symbol(collateral)} / ${this.market.underlyingToken.symbol}`;
151
+ }
152
+ /**
144
153
  * Describes a leveraged position built on one collateral token as the shared
145
154
  * read model does.
146
155
  *
@@ -159,7 +168,7 @@ var CreditSuite = class extends SDKConstruct {
159
168
  chainId: this.chainId,
160
169
  creditManager: cm.address,
161
170
  targetCollateral: this.tokensMeta.mustGetToken(collateral),
162
- name: `${this.tokensMeta.symbol(collateral)} / ${market.underlyingToken.symbol}`,
171
+ name: this.strategyName(collateral),
163
172
  curator: market.curator,
164
173
  underlyingToken: market.underlyingToken,
165
174
  totalBorrow: oracle.toAmount(pool.underlying, borrowed),
@@ -1,4 +1,4 @@
1
- import { PERCENTAGE_FACTOR, PRICE_DECIMALS, RAY } from "../constants/math.js";
1
+ import { PERCENTAGE_FACTOR, PRICE_DECIMALS, RAY, WAD } from "../constants/math.js";
2
2
  //#region src/sdk/market/math.ts
3
3
  /**
4
4
  * Conversions between the units the protocol stores and the basis points the
@@ -80,6 +80,41 @@ function maxLeverage(liquidationThreshold) {
80
80
  return equity > 0 ? FULL / equity : Number.POSITIVE_INFINITY;
81
81
  }
82
82
  /**
83
+ * Converts a credit account's health factor from the 18-decimal fixed point the
84
+ * contracts store to basis points.
85
+ *
86
+ * An account with no debt return MAX_UINT256 from contract, here we return 0
87
+ *
88
+ * @example
89
+ * ```ts
90
+ * healthFactorBps(1_250_000_000_000_000_000n) // 12500, i.e. 1.25
91
+ * ```
92
+ **/
93
+ function healthFactorBps(healthFactor) {
94
+ if (healthFactor === 115792089237316195423570985008687907853269984665640564039457584007913129639935n) return 0;
95
+ return Number(healthFactor * PERCENTAGE_FACTOR / WAD);
96
+ }
97
+ /**
98
+ * Leverage of an open position: `totalDebt / equity`, where equity is what is
99
+ * left of the position's value once its debt is repaid.
100
+ *
101
+ * Returns `0` for a position that carries no debt and for one that is
102
+ * underwater, where there is no equity to lever.
103
+ *
104
+ * @param totalDebt - Debt principal plus accrued interest and fees.
105
+ * @param totalValue - Total value of the position, in the same token.
106
+ *
107
+ * @example
108
+ * ```ts
109
+ * positionLeverage(800n, 1000n) // 4, i.e. 4x debt per unit of equity
110
+ * ```
111
+ **/
112
+ function positionLeverage(totalDebt, totalValue) {
113
+ const equity = totalValue - totalDebt;
114
+ if (equity <= 0n || totalDebt <= 0n) return 0;
115
+ return Number(totalDebt) / Number(equity);
116
+ }
117
+ /**
83
118
  * Annual quota cost scaled to the debt a maximally leveraged position carries,
84
119
  * in basis points. Every unit of own capital carries `maxLeverage - 1` units of
85
120
  * debt, and the quota is paid on the whole quoted position.
@@ -95,4 +130,4 @@ function additionalBorrowApyBps(quotaRate, leverage) {
95
130
  return Math.round(quotaRate * Math.max(leverage - 1, 0));
96
131
  }
97
132
  //#endregion
98
- export { additionalBorrowApyBps, borrowApyBps, maxLeverage, rayToBps, usdToNumber, utilizationBps };
133
+ export { additionalBorrowApyBps, borrowApyBps, healthFactorBps, maxLeverage, positionLeverage, rayToBps, usdToNumber, utilizationBps };
@@ -1,4 +1,4 @@
1
- import { additionalBorrowApyBps, borrowApyBps, maxLeverage, rayToBps, usdToNumber, utilizationBps } from "../market/math.js";
1
+ import { additionalBorrowApyBps, borrowApyBps, healthFactorBps, maxLeverage, positionLeverage, rayToBps, usdToNumber, utilizationBps } from "../market/math.js";
2
2
  import { MultichainOpportunitiesService } from "./MultichainOpportunitiesService.js";
3
3
  import { OpportunitiesService } from "./OpportunitiesService.js";
4
- export { MultichainOpportunitiesService, OpportunitiesService, additionalBorrowApyBps, borrowApyBps, maxLeverage, rayToBps, usdToNumber, utilizationBps };
4
+ export { MultichainOpportunitiesService, OpportunitiesService, additionalBorrowApyBps, borrowApyBps, healthFactorBps, maxLeverage, positionLeverage, rayToBps, usdToNumber, utilizationBps };
@@ -1,6 +1,7 @@
1
1
  import { ierc20Abi } from "../../abi/iERC20.js";
2
2
  import { AddressSet } from "../utils/AddressSet.js";
3
3
  import "../constants/addresses.js";
4
+ import { RAY } from "../constants/math.js";
4
5
  import "../constants/index.js";
5
6
  import { hexEq } from "../utils/hex.js";
6
7
  import "../utils/index.js";
@@ -8,6 +9,7 @@ import { BaseContract } from "../base/BaseContract.js";
8
9
  import { SDKConstruct } from "../base/SDKConstruct.js";
9
10
  import { RWA_UNDERLYING_DEFAULT, RWA_UNDERLYING_ON_DEMAND } from "../base/token-types.js";
10
11
  import "../base/index.js";
12
+ import { rayToBps } from "../market/math.js";
11
13
  import { IERC20ZapperContract } from "../market/zapper/IERC20ZapperContract.js";
12
14
  import { IETHZapperContract } from "../market/zapper/IETHZapperContract.js";
13
15
  import "../market/index.js";
@@ -173,6 +175,27 @@ var PoolService = class extends SDKConstruct {
173
175
  return this.#withdrawalMetadata("classic", pool, tokenIn, tokenOut, true);
174
176
  }
175
177
  /**
178
+ * {@inheritDoc IPoolsService.listPositions}
179
+ */
180
+ async listPositions(props) {
181
+ const { markets } = this.sdk.marketRegister;
182
+ if (markets.length === 0) return [];
183
+ const balances = await this.client.multicall({
184
+ contracts: markets.map((market) => ({
185
+ address: market.pool.pool.address,
186
+ abi: ierc20Abi,
187
+ functionName: "balanceOf",
188
+ args: [props.wallet]
189
+ })),
190
+ allowFailure: false,
191
+ batchSize: 0
192
+ });
193
+ return markets.flatMap((market, i) => {
194
+ const shares = balances[i] ?? 0n;
195
+ return shares > 0n ? [this.#poolPosition(market, shares)] : [];
196
+ });
197
+ }
198
+ /**
176
199
  * Returns non-migration zappers available for the pool.
177
200
  */
178
201
  #getDepositZappers(poolAddr) {
@@ -289,6 +312,20 @@ var PoolService = class extends SDKConstruct {
289
312
  const market = this.sdk.marketRegister.findByPool(pool);
290
313
  return this.sdk.tokensMeta.mustGet(market.underlying);
291
314
  }
315
+ #poolPosition(market, shares) {
316
+ const { pool } = market.pool;
317
+ return {
318
+ kind: "pool",
319
+ name: market.poolName,
320
+ chainId: this.chainId,
321
+ pool: pool.address,
322
+ netValue: {
323
+ token: this.sdk.tokensMeta.mustGetToken(market.unwrappedUnderlying),
324
+ ...market.priceOracle.toAmount(market.underlying, shares * pool.dieselRate / RAY)
325
+ },
326
+ apy: { organicApy: rayToBps(pool.supplyRate) }
327
+ };
328
+ }
292
329
  };
293
330
  //#endregion
294
331
  export { PoolService };
@@ -0,0 +1,47 @@
1
+ import { getNetworkType } from "../chain/chains.js";
2
+ import { MultichainConstruct } from "../base/MultichainConstruct.js";
3
+ import "../base/index.js";
4
+ //#region src/sdk/positions/MultichainPositionsService.ts
5
+ /**
6
+ * Cross-chain counterpart of {@link PositionsService}.
7
+ *
8
+ * Fans out over every chain configured in {@link MultichainSDK}. A chain that
9
+ * fails is logged and skipped so one dead RPC does not hide the positions a
10
+ * wallet holds elsewhere; its failure is reported in
11
+ * {@link MultichainResult.meta}.
12
+ *
13
+ * @typeParam Plugins - Map of attached plugin types.
14
+ **/
15
+ var MultichainPositionsService = class extends MultichainConstruct {
16
+ /**
17
+ * Positions of a wallet on all queried chains, see
18
+ * {@link PositionsService.list}.
19
+ *
20
+ * A filter that names chains narrows the fan-out itself, so chains whose rows
21
+ * would be discarded are never queried and never appear in the meta.
22
+ **/
23
+ async list(props) {
24
+ return this.queryChains({
25
+ networks: this.#networksOf(props.filter),
26
+ label: "list positions",
27
+ run: (sdk) => sdk.positions.list(props)
28
+ });
29
+ }
30
+ /**
31
+ * Chains named by the filter, or `undefined` to query all of them. Chain ids
32
+ * the SDK does not support are dropped here rather than reported as failures:
33
+ * a filter naming them is a narrowing, not a request.
34
+ **/
35
+ #networksOf(filter) {
36
+ if (!filter?.chainIds) return;
37
+ const networks = [];
38
+ for (const chainId of filter.chainIds) try {
39
+ networks.push(getNetworkType(chainId));
40
+ } catch {
41
+ this.sdk.logger?.debug(`ignoring unsupported chain ${chainId} in positions filter`);
42
+ }
43
+ return networks;
44
+ }
45
+ };
46
+ //#endregion
47
+ export { MultichainPositionsService };
@@ -0,0 +1,38 @@
1
+ import { SDKConstruct } from "../base/SDKConstruct.js";
2
+ import "../base/index.js";
3
+ import { matchesPositionFilter } from "../../model/positions.js";
4
+ import "../../model/index.js";
5
+ //#region src/sdk/positions/PositionsService.ts
6
+ /**
7
+ * The `positions` read model of one chain: everything a wallet holds in the
8
+ * protocol — pool shares, open credit accounts, and delayed withdrawals it
9
+ * took over by liquidating.
10
+ **/
11
+ var PositionsService = class extends SDKConstruct {
12
+ /**
13
+ * Every position of a wallet on this chain, optionally narrowed by
14
+ * {@link PositionFilter} (see {@link matchesPositionFilter} for what each
15
+ * criterion selects). Reads live chain state, so rows reflect the moment of
16
+ * the call rather than the SDK's loaded snapshot.
17
+ **/
18
+ async list(props) {
19
+ const { wallet, filter } = props;
20
+ if (filter?.chainIds && !filter.chainIds.includes(this.chainId)) return [];
21
+ const wanted = (kind) => !filter?.kind || filter.kind === kind;
22
+ const [pool, strategy, liquidation] = await Promise.all([
23
+ wanted("pool") ? this.sdk.pools.listPositions({ wallet }) : Promise.resolve([]),
24
+ wanted("strategy") ? this.sdk.accounts.listPositions({
25
+ owner: wallet,
26
+ includeZeroDebt: filter?.isZeroDebt !== false
27
+ }) : Promise.resolve([]),
28
+ wanted("liquidation") ? this.sdk.liquidations.getLiquidationPositions({ liquidator: wallet }) : Promise.resolve([])
29
+ ]);
30
+ return [
31
+ ...pool,
32
+ ...strategy,
33
+ ...liquidation
34
+ ].filter((row) => matchesPositionFilter(row, filter));
35
+ }
36
+ };
37
+ //#endregion
38
+ export { PositionsService };
@@ -0,0 +1,4 @@
1
+ import { MultichainPositionsService } from "./MultichainPositionsService.js";
2
+ import { PositionsService } from "./PositionsService.js";
3
+ import "./types.js";
4
+ export { MultichainPositionsService, PositionsService };
@@ -0,0 +1 @@
1
+ export {};
@@ -1,5 +1,6 @@
1
1
  import { Timestamp } from "./primitives.js";
2
2
  import { OpportunityKey } from "./opportunities.js";
3
+ import { PositionKey } from "./positions.js";
3
4
  //#region src/model/history.d.ts
4
5
  /**
5
6
  * Historical time series of an opportunity.
@@ -32,10 +33,37 @@ type StrategyHistoryMetric = "netApy" | "borrowApy" | "collateralApy" | "tvl" |
32
33
  * Every {@link StrategyHistoryMetric}, for callers that enumerate them.
33
34
  **/
34
35
  declare const STRATEGY_HISTORY_METRICS: readonly ["netApy", "borrowApy", "collateralApy", "tvl", "collateralPrice", "collateralUsdPrice", "underlyingUsdPrice"];
36
+ /**
37
+ * Series available for a pool position.
38
+ *
39
+ * Spelled out rather than aliased to {@link PoolHistoryMetric}: an opportunity
40
+ * and a position are separate contracts with the backend, and the position
41
+ * series are expected to grow their own members (PnL above all) without that
42
+ * change reaching the opportunity charts.
43
+ **/
44
+ type PoolPositionHistoryMetric = "depositApy" | "borrowApy" | "dieselRate" | "supplied" | "borrowed" | "availableLiquidity";
45
+ /**
46
+ * Every {@link PoolPositionHistoryMetric}, for callers that enumerate them.
47
+ **/
48
+ declare const POOL_POSITION_HISTORY_METRICS: readonly ["depositApy", "borrowApy", "dieselRate", "supplied", "borrowed", "availableLiquidity"];
49
+ /**
50
+ * Series available for a strategy position, see the note on
51
+ * {@link PoolPositionHistoryMetric} for why these are spelled out separately
52
+ * from {@link StrategyHistoryMetric}.
53
+ **/
54
+ type StrategyPositionHistoryMetric = "netApy" | "borrowApy" | "collateralApy" | "tvl" | "collateralPrice" | "collateralUsdPrice" | "underlyingUsdPrice";
55
+ /**
56
+ * Every {@link StrategyPositionHistoryMetric}, for callers that enumerate them.
57
+ **/
58
+ declare const STRATEGY_POSITION_HISTORY_METRICS: readonly ["netApy", "borrowApy", "collateralApy", "tvl", "collateralPrice", "collateralUsdPrice", "underlyingUsdPrice"];
59
+ /**
60
+ * Any series a position can return.
61
+ **/
62
+ type PositionHistoryMetric = PoolPositionHistoryMetric | StrategyPositionHistoryMetric;
35
63
  /**
36
64
  * Any series the read model can return.
37
65
  **/
38
- type HistoryMetric = PoolHistoryMetric | StrategyHistoryMetric;
66
+ type HistoryMetric = PoolHistoryMetric | StrategyHistoryMetric | PositionHistoryMetric;
39
67
  /**
40
68
  * One sample of a series.
41
69
  **/
@@ -101,5 +129,25 @@ interface OpportunityHistoryQuery<M extends HistoryMetric = HistoryMetric> {
101
129
  **/
102
130
  metric: M;
103
131
  }
132
+ /**
133
+ * A request for one series of a single position.
134
+ *
135
+ * @typeParam M - Metric requested.
136
+ **/
137
+ interface PositionHistoryQuery<M extends PositionHistoryMetric = PositionHistoryMetric> {
138
+ /**
139
+ * Position the series belongs to.
140
+ **/
141
+ position: PositionKey;
142
+ /**
143
+ * Window to cover.
144
+ **/
145
+ range: HistoryRange;
146
+ /**
147
+ * Metric to return. A metric that does not apply to the position's kind has
148
+ * no series.
149
+ **/
150
+ metric: M;
151
+ }
104
152
  //#endregion
105
- export { HistoryChartMetadata, HistoryMetric, HistoryPoint, HistoryRange, HistorySeries, OpportunityHistoryQuery, POOL_HISTORY_METRICS, PoolHistoryMetric, STRATEGY_HISTORY_METRICS, StrategyHistoryMetric };
153
+ export { HistoryChartMetadata, HistoryMetric, HistoryPoint, HistoryRange, HistorySeries, OpportunityHistoryQuery, POOL_HISTORY_METRICS, POOL_POSITION_HISTORY_METRICS, PoolHistoryMetric, PoolPositionHistoryMetric, PositionHistoryMetric, PositionHistoryQuery, STRATEGY_HISTORY_METRICS, STRATEGY_POSITION_HISTORY_METRICS, StrategyHistoryMetric, StrategyPositionHistoryMetric };