@defisaver/positions-sdk 2.1.160-pos-history-2-dev → 2.1.160-shifter-v2-dev

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 (120) hide show
  1. package/cjs/aaveV2/index.js +2 -0
  2. package/cjs/aaveV3/index.d.ts +0 -39
  3. package/cjs/aaveV3/index.js +1 -230
  4. package/cjs/curveUsd/index.d.ts +5 -2
  5. package/cjs/curveUsd/index.js +30 -15
  6. package/cjs/fluid/index.d.ts +5 -0
  7. package/cjs/fluid/index.js +36 -1
  8. package/cjs/helpers/aaveHelpers/index.js +3 -0
  9. package/cjs/helpers/aaveV4Helpers/index.js +1 -0
  10. package/cjs/helpers/compoundHelpers/index.js +2 -0
  11. package/cjs/helpers/curveUsdHelpers/index.d.ts +3 -1
  12. package/cjs/helpers/curveUsdHelpers/index.js +16 -2
  13. package/cjs/helpers/fluidHelpers/index.js +1 -0
  14. package/cjs/helpers/liquityV2Helpers/index.js +1 -0
  15. package/cjs/helpers/llamaLendHelpers/index.js +2 -0
  16. package/cjs/helpers/makerHelpers/index.d.ts +1 -1
  17. package/cjs/helpers/makerHelpers/index.js +2 -2
  18. package/cjs/helpers/morphoBlueHelpers/index.js +2 -0
  19. package/cjs/helpers/morphoMidnightHelpers/index.js +2 -0
  20. package/cjs/helpers/sparkHelpers/index.js +1 -0
  21. package/cjs/liquity/index.js +16 -2
  22. package/cjs/maker/index.d.ts +7 -2
  23. package/cjs/maker/index.js +45 -12
  24. package/cjs/markets/index.d.ts +1 -0
  25. package/cjs/markets/index.js +3 -1
  26. package/cjs/markets/maker/index.d.ts +1 -0
  27. package/cjs/markets/maker/index.js +13 -0
  28. package/cjs/portfolio/index.d.ts +5 -1
  29. package/cjs/portfolio/index.js +274 -2
  30. package/cjs/staking/staking.d.ts +20 -0
  31. package/cjs/staking/staking.js +19 -1
  32. package/cjs/types/aave.d.ts +2 -0
  33. package/cjs/types/aaveV4.d.ts +1 -0
  34. package/cjs/types/compound.d.ts +2 -0
  35. package/cjs/types/curveUsd.d.ts +6 -0
  36. package/cjs/types/fluid.d.ts +1 -0
  37. package/cjs/types/liquity.d.ts +4 -0
  38. package/cjs/types/liquityV2.d.ts +2 -0
  39. package/cjs/types/maker.d.ts +4 -0
  40. package/cjs/types/morphoBlue.d.ts +2 -0
  41. package/cjs/types/morphoMidnight.d.ts +1 -0
  42. package/cjs/types/portfolio.d.ts +26 -10
  43. package/cjs/types/spark.d.ts +2 -0
  44. package/esm/aaveV2/index.js +2 -0
  45. package/esm/aaveV3/index.d.ts +0 -39
  46. package/esm/aaveV3/index.js +1 -224
  47. package/esm/curveUsd/index.d.ts +5 -2
  48. package/esm/curveUsd/index.js +30 -15
  49. package/esm/fluid/index.d.ts +5 -0
  50. package/esm/fluid/index.js +33 -0
  51. package/esm/helpers/aaveHelpers/index.js +3 -0
  52. package/esm/helpers/aaveV4Helpers/index.js +1 -0
  53. package/esm/helpers/compoundHelpers/index.js +2 -0
  54. package/esm/helpers/curveUsdHelpers/index.d.ts +3 -1
  55. package/esm/helpers/curveUsdHelpers/index.js +16 -2
  56. package/esm/helpers/fluidHelpers/index.js +1 -0
  57. package/esm/helpers/liquityV2Helpers/index.js +1 -0
  58. package/esm/helpers/llamaLendHelpers/index.js +2 -0
  59. package/esm/helpers/makerHelpers/index.d.ts +1 -1
  60. package/esm/helpers/makerHelpers/index.js +2 -2
  61. package/esm/helpers/morphoBlueHelpers/index.js +2 -0
  62. package/esm/helpers/morphoMidnightHelpers/index.js +2 -0
  63. package/esm/helpers/sparkHelpers/index.js +1 -0
  64. package/esm/liquity/index.js +16 -2
  65. package/esm/maker/index.d.ts +7 -2
  66. package/esm/maker/index.js +44 -13
  67. package/esm/markets/index.d.ts +1 -0
  68. package/esm/markets/index.js +1 -0
  69. package/esm/markets/maker/index.d.ts +1 -0
  70. package/esm/markets/maker/index.js +10 -0
  71. package/esm/portfolio/index.d.ts +5 -1
  72. package/esm/portfolio/index.js +276 -5
  73. package/esm/staking/staking.d.ts +20 -0
  74. package/esm/staking/staking.js +17 -0
  75. package/esm/types/aave.d.ts +2 -0
  76. package/esm/types/aaveV4.d.ts +1 -0
  77. package/esm/types/compound.d.ts +2 -0
  78. package/esm/types/curveUsd.d.ts +6 -0
  79. package/esm/types/fluid.d.ts +1 -0
  80. package/esm/types/liquity.d.ts +4 -0
  81. package/esm/types/liquityV2.d.ts +2 -0
  82. package/esm/types/maker.d.ts +4 -0
  83. package/esm/types/morphoBlue.d.ts +2 -0
  84. package/esm/types/morphoMidnight.d.ts +1 -0
  85. package/esm/types/portfolio.d.ts +26 -10
  86. package/esm/types/spark.d.ts +2 -0
  87. package/package.json +1 -1
  88. package/src/aaveV2/index.ts +2 -0
  89. package/src/aaveV3/index.ts +0 -285
  90. package/src/curveUsd/index.ts +33 -16
  91. package/src/fluid/index.ts +40 -0
  92. package/src/helpers/aaveHelpers/index.ts +3 -0
  93. package/src/helpers/aaveV4Helpers/index.ts +1 -0
  94. package/src/helpers/compoundHelpers/index.ts +2 -0
  95. package/src/helpers/curveUsdHelpers/index.ts +23 -2
  96. package/src/helpers/fluidHelpers/index.ts +1 -0
  97. package/src/helpers/liquityV2Helpers/index.ts +1 -0
  98. package/src/helpers/llamaLendHelpers/index.ts +2 -0
  99. package/src/helpers/makerHelpers/index.ts +2 -1
  100. package/src/helpers/morphoBlueHelpers/index.ts +2 -0
  101. package/src/helpers/morphoMidnightHelpers/index.ts +2 -0
  102. package/src/helpers/sparkHelpers/index.ts +1 -0
  103. package/src/liquity/index.ts +17 -2
  104. package/src/maker/index.ts +77 -29
  105. package/src/markets/index.ts +2 -1
  106. package/src/markets/maker/index.ts +10 -0
  107. package/src/portfolio/index.ts +259 -4
  108. package/src/staking/staking.ts +28 -0
  109. package/src/types/aave.ts +3 -0
  110. package/src/types/aaveV4.ts +1 -0
  111. package/src/types/compound.ts +2 -0
  112. package/src/types/curveUsd.ts +7 -0
  113. package/src/types/fluid.ts +1 -0
  114. package/src/types/liquity.ts +6 -0
  115. package/src/types/liquityV2.ts +2 -0
  116. package/src/types/maker.ts +6 -0
  117. package/src/types/morphoBlue.ts +2 -0
  118. package/src/types/morphoMidnight.ts +1 -0
  119. package/src/types/portfolio.ts +31 -12
  120. package/src/types/spark.ts +2 -0
@@ -177,6 +177,8 @@ const _getAaveV2AccountData = (provider, network, address, assetsData, market) =
177
177
  payload.collRatio = payload.borrowedUsd && payload.borrowedUsd !== '0'
178
178
  ? new decimal_js_1.default(payload.suppliedCollateralUsd).div(payload.borrowedUsd).mul(100).toString()
179
179
  : '0';
180
+ // Aave v2 has no LTV-0 fallback (AaveV3View only), so its safety ratio is the plain ratio.
181
+ payload.safetyRatio = payload.ratio;
180
182
  // Calculate borrow limits per asset
181
183
  Object.values(payload.usedAssets).forEach((item) => {
182
184
  if (item.isBorrowed) {
@@ -32,45 +32,6 @@ export declare const EMPTY_AAVE_DATA: {
32
32
  };
33
33
  export declare const _getAaveV3AccountBalances: (provider: Client, network: NetworkNumber, block: Blockish, addressMapping: boolean, address: EthAddress) => Promise<PositionBalances>;
34
34
  export declare const getAaveV3AccountBalances: (provider: EthereumProvider, network: NetworkNumber, block: Blockish, addressMapping: boolean, address: EthAddress) => Promise<PositionBalances>;
35
- export interface AaveV3ReserveTokenAddresses {
36
- [symbol: string]: {
37
- symbol: string;
38
- underlyingAddress: EthAddress;
39
- aTokenAddress: EthAddress;
40
- stableDebtTokenAddress: EthAddress;
41
- variableDebtTokenAddress: EthAddress;
42
- };
43
- }
44
- export interface AaveV3HistoricalBalance {
45
- block: number;
46
- suppliedUsd: string;
47
- borrowedUsd: string;
48
- netUsd: string;
49
- }
50
- /**
51
- * Fetches the aToken / stable-debt / variable-debt token addresses for every asset in the market.
52
- * These are effectively immutable per reserve, so fetch once and reuse across all history points.
53
- */
54
- export declare const _getAaveV3ReserveTokenAddresses: (provider: Client, network: NetworkNumber, market: AaveMarketInfo) => Promise<AaveV3ReserveTokenAddresses>;
55
- export declare const getAaveV3ReserveTokenAddresses: (provider: EthereumProvider, network: NetworkNumber, market: AaveMarketInfo) => Promise<AaveV3ReserveTokenAddresses>;
56
- /**
57
- * Resolves the price oracle the market's addresses provider points at (at `block`, or latest).
58
- * Aave can rotate the oracle over time, so a caller hoisting one address across many historical
59
- * points must resolve it at both ends of its block range and only reuse it when the two agree —
60
- * otherwise leave `oracleAddress` unset on _getAaveV3HistoricalBalance and it resolves per block.
61
- */
62
- export declare const _getAaveV3OracleAddress: (provider: Client, network: NetworkNumber, market: AaveMarketInfo, block?: Blockish) => Promise<EthAddress>;
63
- export declare const getAaveV3OracleAddress: (provider: EthereumProvider, network: NetworkNumber, market: AaveMarketInfo, block?: Blockish) => Promise<EthAddress>;
64
- /**
65
- * Computes a user's Aave v3 net USD balance (supplied collateral - borrowed debt) at a historical block,
66
- * without touching the AaveV3View contract. Pass `reserveTokens` (from getAaveV3ReserveTokenAddresses)
67
- * to avoid refetching token addresses for every point, and `oracleAddress` (from getAaveV3OracleAddress,
68
- * verified identical at both ends of the sampled range) to collapse the point into a single multicall —
69
- * with it the balances and all prices ride one request; without it the oracle is resolved at the block
70
- * inside the balance multicall and the active assets are priced in a second one.
71
- */
72
- export declare const _getAaveV3HistoricalBalance: (provider: Client, network: NetworkNumber, market: AaveMarketInfo, address: EthAddress, block: number, reserveTokens?: AaveV3ReserveTokenAddresses, oracleAddress?: EthAddress) => Promise<AaveV3HistoricalBalance>;
73
- export declare const getAaveV3HistoricalBalance: (provider: EthereumProvider, network: NetworkNumber, market: AaveMarketInfo, address: EthAddress, block: number, reserveTokens?: AaveV3ReserveTokenAddresses, oracleAddress?: EthAddress) => Promise<AaveV3HistoricalBalance>;
74
35
  export declare const _getAaveV3AccountData: (provider: Client, network: NetworkNumber, address: EthAddress, extractedState: any, blockNumber?: "latest" | number) => Promise<AaveV3PositionData>;
75
36
  export declare const getAaveV3AccountData: (provider: EthereumProvider, network: NetworkNumber, address: EthAddress, extractedState: any, blockNumber?: "latest" | number) => Promise<AaveV3PositionData>;
76
37
  export declare const getAaveV3FullPositionData: (provider: EthereumProvider, network: NetworkNumber, address: EthAddress, market: AaveMarketInfo) => Promise<AaveV3PositionData>;
@@ -12,7 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.getSghoData = exports.getMerkleCampaigns = exports.getMeritCampaigns = exports.getStakeAaveData = exports.fetchYearlyMeritApyForStakingGho = exports.REWARDABLE_ASSETS = exports.getAaveV3FullPositionData = exports.getAaveV3AccountData = exports._getAaveV3AccountData = exports.getAaveV3HistoricalBalance = exports._getAaveV3HistoricalBalance = exports.getAaveV3OracleAddress = exports._getAaveV3OracleAddress = exports.getAaveV3ReserveTokenAddresses = exports._getAaveV3ReserveTokenAddresses = exports.getAaveV3AccountBalances = exports._getAaveV3AccountBalances = exports.EMPTY_AAVE_DATA = exports.aaveV3EmodeCategoriesMapping = void 0;
15
+ exports.getSghoData = exports.getMerkleCampaigns = exports.getMeritCampaigns = exports.getStakeAaveData = exports.fetchYearlyMeritApyForStakingGho = exports.REWARDABLE_ASSETS = exports.getAaveV3FullPositionData = exports.getAaveV3AccountData = exports._getAaveV3AccountData = exports.getAaveV3AccountBalances = exports._getAaveV3AccountBalances = exports.EMPTY_AAVE_DATA = exports.aaveV3EmodeCategoriesMapping = void 0;
16
16
  exports._getAaveV3MarketData = _getAaveV3MarketData;
17
17
  exports.getAaveV3MarketData = getAaveV3MarketData;
18
18
  const tokens_1 = require("@defisaver/tokens");
@@ -375,235 +375,6 @@ const _getAaveV3AccountBalances = (provider, network, block, addressMapping, add
375
375
  exports._getAaveV3AccountBalances = _getAaveV3AccountBalances;
376
376
  const getAaveV3AccountBalances = (provider, network, block, addressMapping, address) => __awaiter(void 0, void 0, void 0, function* () { return (0, exports._getAaveV3AccountBalances)((0, viem_1.getViemProvider)(provider, network), network, block, addressMapping, address); });
377
377
  exports.getAaveV3AccountBalances = getAaveV3AccountBalances;
378
- /**
379
- * Historical net-balance helpers that bypass the AaveV3View contract.
380
- *
381
- * The View contract (and therefore `getAaveV3AccountData` / `getAaveV3AccountBalances`) can only be
382
- * queried from its deployment block onwards, so it cannot read balances for positions older than that.
383
- * The aTokens/debt tokens, the ProtocolDataProvider and the Aave price oracle all exist from Aave v3
384
- * launch, so reading `balanceOf` on those tokens + the oracle price directly reaches much further back
385
- * and costs ~1 multicall per point. Used to build a position balance-history chart.
386
- */
387
- // matches morphoVaults' batchSize; stays under the 500k portfolio discovery allows on simulation fork RPCs
388
- const HISTORICAL_MULTICALL_BATCH_SIZE = 250000;
389
- // Minimal Aave price oracle ABI (getAssetPrice returns the asset price in the market base currency).
390
- const AAVE_ORACLE_ABI = [
391
- {
392
- inputs: [{ internalType: 'address', name: 'asset', type: 'address' }],
393
- name: 'getAssetPrice',
394
- outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],
395
- stateMutability: 'view',
396
- type: 'function',
397
- },
398
- ];
399
- /**
400
- * Fetches the aToken / stable-debt / variable-debt token addresses for every asset in the market.
401
- * These are effectively immutable per reserve, so fetch once and reuse across all history points.
402
- */
403
- const _getAaveV3ReserveTokenAddresses = (provider, network, market) => __awaiter(void 0, void 0, void 0, function* () {
404
- const symbols = market.assets;
405
- const underlyingAddresses = symbols.map((a) => (0, tokens_1.getAssetInfo)((0, utils_1.getWrappedNativeAssetFromUnwrapped)(a), network).address);
406
- // @ts-ignore market.protocolData is a valid config key at runtime
407
- const dataProviderAbi = (0, contracts_1.getConfigContractAbi)(market.protocolData, network);
408
- const contracts = underlyingAddresses.map((underlying) => ({
409
- address: market.protocolDataAddress,
410
- abi: dataProviderAbi,
411
- functionName: 'getReserveTokensAddresses',
412
- args: [underlying],
413
- }));
414
- // @ts-ignore
415
- const results = yield provider.multicall({ contracts, allowFailure: true, batchSize: HISTORICAL_MULTICALL_BATCH_SIZE });
416
- const mapping = {};
417
- results.forEach((res, i) => {
418
- if (res.status !== 'success' || !res.result)
419
- return;
420
- // outputs order: [aTokenAddress, stableDebtTokenAddress, variableDebtTokenAddress]
421
- const [aTokenAddress, stableDebtTokenAddress, variableDebtTokenAddress] = res.result;
422
- mapping[symbols[i]] = {
423
- symbol: symbols[i],
424
- underlyingAddress: underlyingAddresses[i],
425
- aTokenAddress,
426
- stableDebtTokenAddress,
427
- variableDebtTokenAddress,
428
- };
429
- });
430
- return mapping;
431
- });
432
- exports._getAaveV3ReserveTokenAddresses = _getAaveV3ReserveTokenAddresses;
433
- const getAaveV3ReserveTokenAddresses = (provider, network, market) => __awaiter(void 0, void 0, void 0, function* () { return (0, exports._getAaveV3ReserveTokenAddresses)((0, viem_1.getViemProvider)(provider, network, { batch: { multicall: true } }), network, market); });
434
- exports.getAaveV3ReserveTokenAddresses = getAaveV3ReserveTokenAddresses;
435
- /**
436
- * Resolves the price oracle the market's addresses provider points at (at `block`, or latest).
437
- * Aave can rotate the oracle over time, so a caller hoisting one address across many historical
438
- * points must resolve it at both ends of its block range and only reuse it when the two agree —
439
- * otherwise leave `oracleAddress` unset on _getAaveV3HistoricalBalance and it resolves per block.
440
- */
441
- const _getAaveV3OracleAddress = (provider_1, network_1, market_1, ...args_1) => __awaiter(void 0, [provider_1, network_1, market_1, ...args_1], void 0, function* (provider, network, market, block = 'latest') {
442
- // @ts-ignore market.provider is a valid config key at runtime
443
- const providerAbi = (0, contracts_1.getConfigContractAbi)(market.provider, network);
444
- // @ts-ignore readContract exists on the public client returned by getViemProvider
445
- const oracleAddress = yield provider.readContract(Object.assign({ address: market.providerAddress, abi: providerAbi, functionName: 'getPriceOracle' }, (0, viem_1.setViemBlockNumber)(block)));
446
- if (!oracleAddress)
447
- throw new Error(`AaveV3 oracle unavailable at block ${block}`);
448
- return oracleAddress;
449
- });
450
- exports._getAaveV3OracleAddress = _getAaveV3OracleAddress;
451
- const getAaveV3OracleAddress = (provider_1, network_1, market_1, ...args_1) => __awaiter(void 0, [provider_1, network_1, market_1, ...args_1], void 0, function* (provider, network, market, block = 'latest') { return (0, exports._getAaveV3OracleAddress)((0, viem_1.getViemProvider)(provider, network, { batch: { multicall: true } }), network, market, block); });
452
- exports.getAaveV3OracleAddress = getAaveV3OracleAddress;
453
- // supply = aToken.balanceOf, debt = variableDebtToken.balanceOf + stableDebtToken.balanceOf — three reads per reserve
454
- const getHistoricalBalanceContracts = (entries, address) => {
455
- const erc20Abi = (0, contracts_1.getConfigContractAbi)('Erc20');
456
- return entries.flatMap((e) => ([
457
- {
458
- address: e.aTokenAddress, abi: erc20Abi, functionName: 'balanceOf', args: [address],
459
- },
460
- {
461
- address: e.variableDebtTokenAddress, abi: erc20Abi, functionName: 'balanceOf', args: [address],
462
- },
463
- {
464
- address: e.stableDebtTokenAddress, abi: erc20Abi, functionName: 'balanceOf', args: [address],
465
- },
466
- ]));
467
- };
468
- const getAssetPriceContract = (oracle, underlyingAddress) => ({
469
- address: oracle,
470
- abi: AAVE_ORACLE_ABI,
471
- functionName: 'getAssetPrice',
472
- args: [underlyingAddress],
473
- });
474
- /**
475
- * Pairs each reserve with its three balance reads and keeps the assets the wallet actually held.
476
- * Throws when every read failed — a totally failed fetch must not masquerade as a real $0 balance,
477
- * so the caller can distinguish "fetch failed" (gap) from "position was empty" (genuine 0).
478
- */
479
- const toActiveHistoricalAssets = (entries, balanceResults, block) => {
480
- const anyBalanceRead = balanceResults.some((r) => (r === null || r === void 0 ? void 0 : r.status) === 'success');
481
- if (!anyBalanceRead)
482
- throw new Error(`AaveV3 historical balance: all balance reads failed at block ${block}`);
483
- return entries.map((e, i) => {
484
- const supplyRes = balanceResults[i * 3];
485
- const varDebtRes = balanceResults[(i * 3) + 1];
486
- const stableDebtRes = balanceResults[(i * 3) + 2];
487
- const supplied = (supplyRes === null || supplyRes === void 0 ? void 0 : supplyRes.status) === 'success' ? supplyRes.result.toString() : '0';
488
- const varDebt = (varDebtRes === null || varDebtRes === void 0 ? void 0 : varDebtRes.status) === 'success' ? varDebtRes.result.toString() : '0';
489
- const stableDebt = (stableDebtRes === null || stableDebtRes === void 0 ? void 0 : stableDebtRes.status) === 'success' ? stableDebtRes.result.toString() : '0';
490
- const debt = new decimal_js_1.default(varDebt).add(stableDebt).toString();
491
- return Object.assign(Object.assign({}, e), { supplied, debt });
492
- }).filter((a) => a.supplied !== '0' || a.debt !== '0');
493
- };
494
- /**
495
- * Sums the active assets into the point's USD totals. Throws when every price read failed — the
496
- * oracle couldn't serve this block (pruned state, or a hoisted oracle that wasn't deployed yet back
497
- * then), and totalling it up anyway would return a fake near-$0 balance. A single asset's price
498
- * failure still just skips that asset, matching the live data path.
499
- */
500
- const sumHistoricalUsd = (activeAssets, priceResBySymbol, block) => {
501
- const anyPriceRead = activeAssets.some((a) => { var _a; return ((_a = priceResBySymbol[a.symbol]) === null || _a === void 0 ? void 0 : _a.status) === 'success'; });
502
- if (!anyPriceRead)
503
- throw new Error(`AaveV3 historical balance: all price reads failed at block ${block}`);
504
- let suppliedUsd = new decimal_js_1.default(0);
505
- let borrowedUsd = new decimal_js_1.default(0);
506
- activeAssets.forEach((a) => {
507
- const priceRes = priceResBySymbol[a.symbol];
508
- if ((priceRes === null || priceRes === void 0 ? void 0 : priceRes.status) !== 'success')
509
- return;
510
- const priceUsd = new decimal_js_1.default(priceRes.result.toString()).div(1e8); // Aave v3 base currency is USD with 8 decimals
511
- if (a.supplied !== '0')
512
- suppliedUsd = suppliedUsd.add(new decimal_js_1.default((0, tokens_1.assetAmountInEth)(a.supplied, a.symbol)).mul(priceUsd));
513
- if (a.debt !== '0')
514
- borrowedUsd = borrowedUsd.add(new decimal_js_1.default((0, tokens_1.assetAmountInEth)(a.debt, a.symbol)).mul(priceUsd));
515
- });
516
- return {
517
- block,
518
- suppliedUsd: suppliedUsd.toString(),
519
- borrowedUsd: borrowedUsd.toString(),
520
- netUsd: suppliedUsd.minus(borrowedUsd).toString(),
521
- };
522
- };
523
- /**
524
- * Fast path, ONE multicall: balances plus a price read for every reserve through the caller-hoisted
525
- * oracle. Prices are read for all reserves because which assets are active isn't known until the
526
- * balances come back — extra reads inside an already-paid multicall are nearly free.
527
- */
528
- const fetchHistoricalPointWithOracle = (provider, entries, address, block, oracleAddress) => __awaiter(void 0, void 0, void 0, function* () {
529
- const balanceContracts = getHistoricalBalanceContracts(entries, address);
530
- const priceContracts = entries.map((e) => getAssetPriceContract(oracleAddress, e.underlyingAddress));
531
- // @ts-ignore
532
- const results = yield provider.multicall({
533
- contracts: [...balanceContracts, ...priceContracts], allowFailure: true, blockNumber: BigInt(block), batchSize: HISTORICAL_MULTICALL_BATCH_SIZE,
534
- });
535
- const activeAssets = toActiveHistoricalAssets(entries, results.slice(0, balanceContracts.length), block);
536
- const priceResBySymbol = {};
537
- results.slice(balanceContracts.length).forEach((res, i) => {
538
- priceResBySymbol[entries[i].symbol] = res;
539
- });
540
- return { activeAssets, priceResBySymbol };
541
- });
542
- /**
543
- * Fallback path, TWO multicalls: balances plus getPriceOracle (resolving the oracle that was active
544
- * AT the block — Aave can rotate it over time), then prices for just the active assets. The oracle
545
- * read has no fallback: if it fails (bad archive node, rate limit, ...) the failure must surface
546
- * rather than silently returning $0 — the caller renders a gap instead of a misleading zero.
547
- */
548
- const fetchHistoricalPointResolvingOracle = (provider, network, market, entries, address, block) => __awaiter(void 0, void 0, void 0, function* () {
549
- const balanceContracts = getHistoricalBalanceContracts(entries, address);
550
- // @ts-ignore market.provider is a valid config key at runtime
551
- const providerAbi = (0, contracts_1.getConfigContractAbi)(market.provider, network);
552
- const oracleContract = {
553
- address: market.providerAddress,
554
- abi: providerAbi,
555
- functionName: 'getPriceOracle',
556
- };
557
- const blockNumber = BigInt(block);
558
- // @ts-ignore
559
- const results = yield provider.multicall({
560
- contracts: [...balanceContracts, oracleContract], allowFailure: true, blockNumber, batchSize: HISTORICAL_MULTICALL_BATCH_SIZE,
561
- });
562
- const oracleRes = results[balanceContracts.length];
563
- if ((oracleRes === null || oracleRes === void 0 ? void 0 : oracleRes.status) !== 'success' || !oracleRes.result)
564
- throw new Error(`AaveV3 historical balance: oracle unavailable at block ${block}`);
565
- const activeAssets = toActiveHistoricalAssets(entries, results.slice(0, balanceContracts.length), block);
566
- if (!activeAssets.length)
567
- return { activeAssets, priceResBySymbol: {} };
568
- const priceContracts = activeAssets.map((a) => getAssetPriceContract(oracleRes.result, a.underlyingAddress));
569
- // @ts-ignore
570
- const priceResults = yield provider.multicall({
571
- contracts: priceContracts, allowFailure: true, blockNumber, batchSize: HISTORICAL_MULTICALL_BATCH_SIZE,
572
- });
573
- const priceResBySymbol = {};
574
- priceResults.forEach((res, i) => {
575
- priceResBySymbol[activeAssets[i].symbol] = res;
576
- });
577
- return { activeAssets, priceResBySymbol };
578
- });
579
- /**
580
- * Computes a user's Aave v3 net USD balance (supplied collateral - borrowed debt) at a historical block,
581
- * without touching the AaveV3View contract. Pass `reserveTokens` (from getAaveV3ReserveTokenAddresses)
582
- * to avoid refetching token addresses for every point, and `oracleAddress` (from getAaveV3OracleAddress,
583
- * verified identical at both ends of the sampled range) to collapse the point into a single multicall —
584
- * with it the balances and all prices ride one request; without it the oracle is resolved at the block
585
- * inside the balance multicall and the active assets are priced in a second one.
586
- */
587
- const _getAaveV3HistoricalBalance = (provider, network, market, address, block, reserveTokens, oracleAddress) => __awaiter(void 0, void 0, void 0, function* () {
588
- const empty = {
589
- block, suppliedUsd: '0', borrowedUsd: '0', netUsd: '0',
590
- };
591
- if (!address)
592
- return empty;
593
- const tokens = reserveTokens || (yield (0, exports._getAaveV3ReserveTokenAddresses)(provider, network, market));
594
- const entries = Object.values(tokens);
595
- if (!entries.length)
596
- return empty;
597
- const { activeAssets, priceResBySymbol } = oracleAddress
598
- ? yield fetchHistoricalPointWithOracle(provider, entries, address, block, oracleAddress)
599
- : yield fetchHistoricalPointResolvingOracle(provider, network, market, entries, address, block);
600
- if (!activeAssets.length)
601
- return empty;
602
- return sumHistoricalUsd(activeAssets, priceResBySymbol, block);
603
- });
604
- exports._getAaveV3HistoricalBalance = _getAaveV3HistoricalBalance;
605
- const getAaveV3HistoricalBalance = (provider, network, market, address, block, reserveTokens, oracleAddress) => __awaiter(void 0, void 0, void 0, function* () { return (0, exports._getAaveV3HistoricalBalance)((0, viem_1.getViemProvider)(provider, network, { batch: { multicall: true } }), network, market, address, block, reserveTokens, oracleAddress); });
606
- exports.getAaveV3HistoricalBalance = getAaveV3HistoricalBalance;
607
378
  const _getAaveV3AccountData = (provider_1, network_1, address_1, extractedState_1, ...args_1) => __awaiter(void 0, [provider_1, network_1, address_1, extractedState_1, ...args_1], void 0, function* (provider, network, address, extractedState, blockNumber = 'latest') {
608
379
  const { selectedMarket: market, assetsData, eModeCategoriesData, } = extractedState;
609
380
  let payload = Object.assign(Object.assign({}, exports.EMPTY_AAVE_DATA), { lastUpdated: Date.now() });
@@ -5,6 +5,9 @@ export declare const _getCurveUsdGlobalData: (provider: Client, network: Network
5
5
  export declare const getCurveUsdGlobalData: (provider: EthereumProvider, network: NetworkNumber, selectedMarket: CrvUSDMarketData) => Promise<CrvUSDGlobalMarketData>;
6
6
  export declare const _getCrvUsdAccountBalances: (provider: Client, network: NetworkNumber, block: Blockish, addressMapping: boolean, address: EthAddress, controllerAddress: EthAddress) => Promise<PositionBalances>;
7
7
  export declare const getCrvUsdAccountBalances: (provider: EthereumProvider, network: NetworkNumber, block: Blockish, addressMapping: boolean, address: EthAddress, controllerAddress: EthAddress) => Promise<PositionBalances>;
8
- export declare const _getCurveUsdUserData: (provider: Client, network: NetworkNumber, address: EthAddress, selectedMarket: CrvUSDMarketData, activeBand: string) => Promise<CrvUSDUserData>;
9
- export declare const getCurveUsdUserData: (provider: EthereumProvider, network: NetworkNumber, address: EthAddress, selectedMarket: CrvUSDMarketData, activeBand: string) => Promise<CrvUSDUserData>;
8
+ /**
9
+ * @param borrowRate market borrow APY in % (`CrvUSDGlobalMarketData.borrowRate`); when omitted it is read from the view contract
10
+ */
11
+ export declare const _getCurveUsdUserData: (provider: Client, network: NetworkNumber, address: EthAddress, selectedMarket: CrvUSDMarketData, activeBand: string, borrowRate?: string) => Promise<CrvUSDUserData>;
12
+ export declare const getCurveUsdUserData: (provider: EthereumProvider, network: NetworkNumber, address: EthAddress, selectedMarket: CrvUSDMarketData, activeBand: string, borrowRate?: string) => Promise<CrvUSDUserData>;
10
13
  export declare const getCurveUsdFullPositionData: (provider: EthereumProvider, network: NetworkNumber, address: EthAddress, selectedMarket: CrvUSDMarketData) => Promise<CrvUSDUserData>;
@@ -22,6 +22,12 @@ const curveUsdHelpers_1 = require("../helpers/curveUsdHelpers");
22
22
  const markets_1 = require("../markets");
23
23
  const utils_1 = require("../services/utils");
24
24
  const viem_1 = require("../services/viem");
25
+ const staking_1 = require("../staking");
26
+ /** Converts a per-second AMM rate (wei, 18 decimals) into a yearly compounded borrow APY in %. */
27
+ const ammRateToBorrowApy = (rateWei) => {
28
+ const exponent = new decimal_js_1.default((0, tokens_1.assetAmountInEth)(rateWei)).mul(365).mul(86400);
29
+ return new decimal_js_1.default(new decimal_js_1.default(2.718281828459).pow(exponent).minus(1)).mul(100).toString();
30
+ };
25
31
  const getAndFormatBands = (provider, network, selectedMarket, _minBand, _maxBand) => __awaiter(void 0, void 0, void 0, function* () {
26
32
  const contract = (0, contracts_1.CrvUSDViewContractViem)(provider, network);
27
33
  const minBand = parseInt(_minBand, 10);
@@ -71,14 +77,8 @@ const _getCurveUsdGlobalData = (provider, network, selectedMarket) => __awaiter(
71
77
  // all prices are in 18 decimals
72
78
  const totalDebt = (0, tokens_1.assetAmountInEth)(data.totalDebt.toString(), debtAsset);
73
79
  const ammPrice = (0, tokens_1.assetAmountInEth)(data.ammPrice.toString(), debtAsset);
74
- const rate = (0, tokens_1.assetAmountInEth)(data.ammRate.toString());
75
- const futureRate = (0, tokens_1.assetAmountInEth)(data.monetaryPolicyRate.toString());
76
- const exponentRate = new decimal_js_1.default(rate).mul(365).mul(86400);
77
- const exponentFutureRate = new decimal_js_1.default(futureRate).mul(365).mul(86400);
78
- const borrowRate = new decimal_js_1.default(new decimal_js_1.default(2.718281828459).pow(exponentRate).minus(1)).mul(100)
79
- .toString();
80
- const futureBorrowRate = new decimal_js_1.default(new decimal_js_1.default(2.718281828459).pow(exponentFutureRate).minus(1)).mul(100)
81
- .toString();
80
+ const borrowRate = ammRateToBorrowApy(data.ammRate.toString());
81
+ const futureBorrowRate = ammRateToBorrowApy(data.monetaryPolicyRate.toString());
82
82
  const bandsData = yield getAndFormatBands(provider, network, selectedMarket, data.minBand.toString(), data.maxBand.toString());
83
83
  const leftToBorrow = new decimal_js_1.default(debtCeiling.toString()).minus(totalDebt).toString();
84
84
  const loanDiscount = (0, tokens_1.assetAmountInEth)(loanDiscountWei.toString(), debtAsset);
@@ -131,11 +131,20 @@ const _getCrvUsdAccountBalances = (provider, network, block, addressMapping, add
131
131
  exports._getCrvUsdAccountBalances = _getCrvUsdAccountBalances;
132
132
  const getCrvUsdAccountBalances = (provider, network, block, addressMapping, address, controllerAddress) => __awaiter(void 0, void 0, void 0, function* () { return (0, exports._getCrvUsdAccountBalances)((0, viem_1.getViemProvider)(provider, network), network, block, addressMapping, address, controllerAddress); });
133
133
  exports.getCrvUsdAccountBalances = getCrvUsdAccountBalances;
134
- const _getCurveUsdUserData = (provider, network, address, selectedMarket, activeBand) => __awaiter(void 0, void 0, void 0, function* () {
134
+ /**
135
+ * @param borrowRate market borrow APY in % (`CrvUSDGlobalMarketData.borrowRate`); when omitted it is read from the view contract
136
+ */
137
+ const _getCurveUsdUserData = (provider, network, address, selectedMarket, activeBand, borrowRate) => __awaiter(void 0, void 0, void 0, function* () {
135
138
  const contract = (0, contracts_1.CrvUSDViewContractViem)(provider, network);
136
- const data = yield contract.read.userData([selectedMarket.controllerAddress, address]);
137
139
  const collAsset = selectedMarket.collAsset;
138
140
  const debtAsset = selectedMarket.baseAsset;
141
+ const [data, collStakingApy, marketBorrowRate] = yield Promise.all([
142
+ contract.read.userData([selectedMarket.controllerAddress, address]),
143
+ staking_1.STAKING_ASSETS.includes(collAsset) ? (0, staking_1.getStakingApy)(collAsset) : Promise.resolve('0'),
144
+ borrowRate !== undefined
145
+ ? Promise.resolve(borrowRate)
146
+ : contract.read.globalData([selectedMarket.controllerAddress]).then((globalData) => ammRateToBorrowApy(globalData.ammRate.toString())),
147
+ ]);
139
148
  const health = (0, tokens_1.assetAmountInEth)(data.health.toString());
140
149
  const healthPercent = new decimal_js_1.default(health).mul(100).toString();
141
150
  const collPrice = (0, tokens_1.assetAmountInEth)(data.collateralPrice.toString(), debtAsset);
@@ -166,7 +175,7 @@ const _getCurveUsdUserData = (provider, network, address, selectedMarket, active
166
175
  isBorrowed: new decimal_js_1.default(debtBorrowed).gt('0'),
167
176
  symbol: 'crvUSD',
168
177
  price: '1',
169
- interestRate: '0',
178
+ interestRate: marketBorrowRate,
170
179
  },
171
180
  } : {};
172
181
  const priceHigh = (0, tokens_1.assetAmountInEth)(data.priceHigh.toString());
@@ -178,16 +187,22 @@ const _getCurveUsdUserData = (provider, network, address, selectedMarket, active
178
187
  healthPercent,
179
188
  priceHigh,
180
189
  priceLow, liquidationDiscount: (0, tokens_1.assetAmountInEth)(data.liquidationDiscount.toString()), numOfBands: data.N.toString(), usedAssets,
181
- status }), (0, curveUsdHelpers_1.getCrvUsdAggregatedData)({
182
- loanExists: data.loanExists, usedAssets, network: common_1.NetworkNumber.Eth, selectedMarket, numOfBands: data.N.toString(),
190
+ status, borrowRate: marketBorrowRate }), (0, curveUsdHelpers_1.getCrvUsdAggregatedData)({
191
+ loanExists: data.loanExists,
192
+ usedAssets,
193
+ network: common_1.NetworkNumber.Eth,
194
+ selectedMarket,
195
+ numOfBands: data.N.toString(),
196
+ borrowRate: marketBorrowRate,
197
+ collStakingApy,
183
198
  })), { userBands });
184
199
  });
185
200
  exports._getCurveUsdUserData = _getCurveUsdUserData;
186
- const getCurveUsdUserData = (provider, network, address, selectedMarket, activeBand) => __awaiter(void 0, void 0, void 0, function* () { return (0, exports._getCurveUsdUserData)((0, viem_1.getViemProvider)(provider, network), network, address, selectedMarket, activeBand); });
201
+ const getCurveUsdUserData = (provider, network, address, selectedMarket, activeBand, borrowRate) => __awaiter(void 0, void 0, void 0, function* () { return (0, exports._getCurveUsdUserData)((0, viem_1.getViemProvider)(provider, network), network, address, selectedMarket, activeBand, borrowRate); });
187
202
  exports.getCurveUsdUserData = getCurveUsdUserData;
188
203
  const getCurveUsdFullPositionData = (provider, network, address, selectedMarket) => __awaiter(void 0, void 0, void 0, function* () {
189
204
  const marketData = yield (0, exports.getCurveUsdGlobalData)(provider, network, selectedMarket);
190
- const positionData = yield (0, exports.getCurveUsdUserData)(provider, network, address, selectedMarket, marketData.activeBand);
205
+ const positionData = yield (0, exports.getCurveUsdUserData)(provider, network, address, selectedMarket, marketData.activeBand, marketData.borrowRate);
191
206
  return positionData;
192
207
  });
193
208
  exports.getCurveUsdFullPositionData = getCurveUsdFullPositionData;
@@ -133,6 +133,7 @@ export declare const _getUserPositions: (provider: PublicClient, network: Networ
133
133
  merklBorrowIncentives: import("../types").IncentiveData[];
134
134
  ratio: string;
135
135
  collRatio: string;
136
+ safetyRatio: string;
136
137
  minRatio: string;
137
138
  totalInterestUsd: string;
138
139
  leveragedType?: import("../types").LeverageType;
@@ -167,6 +168,7 @@ export declare const getUserPositions: (provider: EthereumProvider, network: Net
167
168
  merklBorrowIncentives: import("../types").IncentiveData[];
168
169
  ratio: string;
169
170
  collRatio: string;
171
+ safetyRatio: string;
170
172
  minRatio: string;
171
173
  totalInterestUsd: string;
172
174
  leveragedType?: import("../types").LeverageType;
@@ -201,6 +203,7 @@ export declare const _getUserPositionsPortfolio: (provider: PublicClient, networ
201
203
  merklBorrowIncentives: import("../types").IncentiveData[];
202
204
  ratio: string;
203
205
  collRatio: string;
206
+ safetyRatio: string;
204
207
  minRatio: string;
205
208
  totalInterestUsd: string;
206
209
  leveragedType?: import("../types").LeverageType;
@@ -221,3 +224,5 @@ export declare const _getUserPositionsPortfolio: (provider: PublicClient, networ
221
224
  nftId: string;
222
225
  } | undefined;
223
226
  }[]>;
227
+ export declare const _getAllFluidMarketDataPortfolio: (provider: PublicClient, network: NetworkNumber) => Promise<Record<string, FluidMarketData>>;
228
+ export declare const getAllFluidMarketDataPortfolio: (provider: EthereumProvider, network: NetworkNumber) => Promise<Record<string, FluidMarketData>>;
@@ -12,7 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports._getUserPositionsPortfolio = exports.getUserPositions = exports._getUserPositions = exports.getAllUserEarnPositionsWithFTokens = exports._getAllUserEarnPositionsWithFTokens = exports.getFluidDepositData = exports._getFluidDepositData = exports.getFluidTokenData = exports._getFluidTokenData = exports.getAllFluidMarketDataChunked = exports._getAllFluidMarketDataChunked = exports.getFluidPositionWithMarket = exports._getFluidPositionWithMarket = exports.getFluidPosition = exports._getFluidPosition = exports.getFluidVaultIdsForUser = exports._getFluidVaultIdsForUser = exports.getFluidMarketData = exports._getFluidMarketData = exports.EMPTY_FLUID_DATA = exports.EMPTY_USED_ASSET = exports.attachFluidMerklIncentives = exports.getFluidMerklCampaigns = exports.buildFluidMerklRewardMap = exports.FluidMerklOpportunityType = void 0;
15
+ exports.getAllFluidMarketDataPortfolio = exports._getAllFluidMarketDataPortfolio = exports._getUserPositionsPortfolio = exports.getUserPositions = exports._getUserPositions = exports.getAllUserEarnPositionsWithFTokens = exports._getAllUserEarnPositionsWithFTokens = exports.getFluidDepositData = exports._getFluidDepositData = exports.getFluidTokenData = exports._getFluidTokenData = exports.getAllFluidMarketDataChunked = exports._getAllFluidMarketDataChunked = exports.getFluidPositionWithMarket = exports._getFluidPositionWithMarket = exports.getFluidPosition = exports._getFluidPosition = exports.getFluidVaultIdsForUser = exports._getFluidVaultIdsForUser = exports.getFluidMarketData = exports._getFluidMarketData = exports.EMPTY_FLUID_DATA = exports.EMPTY_USED_ASSET = exports.attachFluidMerklIncentives = exports.getFluidMerklCampaigns = exports.buildFluidMerklRewardMap = exports.FluidMerklOpportunityType = void 0;
16
16
  const decimal_js_1 = __importDefault(require("decimal.js"));
17
17
  const tokens_1 = require("@defisaver/tokens");
18
18
  const common_1 = require("../types/common");
@@ -1410,3 +1410,38 @@ const _getUserPositionsPortfolio = (provider, network, user) => __awaiter(void 0
1410
1410
  })).filter(md => md.marketData !== undefined);
1411
1411
  });
1412
1412
  exports._getUserPositionsPortfolio = _getUserPositionsPortfolio;
1413
+ const _getAllFluidMarketDataPortfolio = (provider, network) => __awaiter(void 0, void 0, void 0, function* () {
1414
+ const versions = (0, markets_1.getFluidVersionsDataForNetwork)(network);
1415
+ if (versions.length === 0)
1416
+ return {};
1417
+ const view = (0, contracts_1.FluidViewContractViem)(provider, network);
1418
+ const vaultsData = yield Promise.all(versions.map((version) => view.read.getVaultData([version.marketAddress])));
1419
+ const tokens = Array.from(new Set(vaultsData.map((vaultData) => {
1420
+ const vaultTokens = [(0, tokens_1.getAssetInfoByAddress)(vaultData.supplyToken0, network).symbol, (0, tokens_1.getAssetInfoByAddress)(vaultData.borrowToken0, network).symbol];
1421
+ if (vaultData.supplyToken1 && !(0, utils_1.compareAddresses)(constants_1.ZERO_ADDRESS, vaultData.supplyToken1))
1422
+ vaultTokens.push((0, tokens_1.getAssetInfoByAddress)(vaultData.supplyToken1, network).symbol);
1423
+ if (vaultData.borrowToken1 && !(0, utils_1.compareAddresses)(constants_1.ZERO_ADDRESS, vaultData.borrowToken1))
1424
+ vaultTokens.push((0, tokens_1.getAssetInfoByAddress)(vaultData.borrowToken1, network).symbol);
1425
+ return vaultTokens;
1426
+ }).flat()));
1427
+ // ETH and WBTC needed for other tokens prices
1428
+ if (!tokens.includes('ETH'))
1429
+ tokens.push('ETH');
1430
+ if (!tokens.includes('WBTC'))
1431
+ tokens.push('WBTC');
1432
+ const [tokenPrices, merklCampaigns] = yield Promise.all([
1433
+ getTokensPricesForPortfolio(tokens, provider, network),
1434
+ (0, merkl_1.getFluidMerklCampaigns)(network),
1435
+ ]);
1436
+ const parsedMarketsData = yield Promise.all(vaultsData.map((vaultData) => __awaiter(void 0, void 0, void 0, function* () { return parseMarketData(provider, vaultData, network, tokenPrices); })));
1437
+ const marketsData = {};
1438
+ parsedMarketsData.forEach((marketData, i) => {
1439
+ if (!marketData)
1440
+ return;
1441
+ marketsData[versions[i].value] = (0, merkl_1.attachFluidMerklIncentives)(marketData, merklCampaigns);
1442
+ });
1443
+ return marketsData;
1444
+ });
1445
+ exports._getAllFluidMarketDataPortfolio = _getAllFluidMarketDataPortfolio;
1446
+ const getAllFluidMarketDataPortfolio = (provider, network) => __awaiter(void 0, void 0, void 0, function* () { return (0, exports._getAllFluidMarketDataPortfolio)((0, viem_1.getViemProvider)(provider, network, { batch: { multicall: true } }), network); });
1447
+ exports.getAllFluidMarketDataPortfolio = getAllFluidMarketDataPortfolio;
@@ -140,6 +140,9 @@ const aaveAnyGetAggregatedPositionData = (_a) => {
140
140
  return new decimal_js_1.default(suppliedUsd).mul(effectiveLtv);
141
141
  });
142
142
  payload.safetyRatioWithLtvZeroFallback = +payload.suppliedUsd ? new decimal_js_1.default(payload.borrowLimitWithLtvZeroFallbackUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
143
+ // Normalised safety ratio (100 = liquidation on every protocol): the automation ratio above, falling back
144
+ // to the regular ratio when the fallback carries its '0' placeholder.
145
+ payload.safetyRatio = +payload.safetyRatioWithLtvZeroFallback ? payload.safetyRatioWithLtvZeroFallback : payload.ratio;
143
146
  payload.liqRatio = new decimal_js_1.default(payload.borrowLimitUsd).div(payload.liquidationLimitUsd).toString();
144
147
  payload.liqPercent = new decimal_js_1.default(payload.borrowLimitUsd).div(payload.liquidationLimitUsd).mul(100).toString();
145
148
  const { leveragedType, leveragedAsset } = (0, moneymarket_1.isLeveragedPos)(usedAssets);
@@ -219,6 +219,7 @@ const aaveV4GetAggregatedPositionData = ({ usedAssets, assetsData, network, useU
219
219
  payload.ratio = +payload.suppliedUsd ? new decimal_js_1.default(payload.borrowLimitUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
220
220
  payload.minRatio = '100';
221
221
  payload.collRatio = +payload.suppliedUsd ? new decimal_js_1.default(payload.suppliedCollateralUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
222
+ payload.safetyRatio = payload.ratio;
222
223
  payload.liqRatio = new decimal_js_1.default(payload.borrowLimitUsd).div(payload.liquidationLimitUsd).toString();
223
224
  payload.liqPercent = new decimal_js_1.default(payload.borrowLimitUsd).div(payload.liquidationLimitUsd).mul(100).toString();
224
225
  const { leveragedType, leveragedAsset } = (0, exports.isLeveragedPosAaveV4)(usedAssets);
@@ -102,6 +102,7 @@ const getCompoundV2AggregatedData = (_a) => {
102
102
  payload.collRatio = payload.borrowedUsd && payload.borrowedUsd !== '0'
103
103
  ? new decimal_js_1.default(payload.suppliedCollateralUsd).div(payload.borrowedUsd).mul(100).toString()
104
104
  : '0';
105
+ payload.safetyRatio = payload.ratio;
105
106
  // Calculate borrow limits per asset
106
107
  Object.values(usedAssets).forEach((item) => {
107
108
  if (item.isBorrowed) {
@@ -144,6 +145,7 @@ const getCompoundV3AggregatedData = (_a) => {
144
145
  payload.incentiveUsd = incentiveUsd;
145
146
  payload.totalInterestUsd = totalInterestUsd;
146
147
  payload.minRatio = '100';
148
+ payload.safetyRatio = payload.ratio;
147
149
  payload.liqRatio = new decimal_js_1.default(payload.borrowLimitUsd).div(payload.liquidationLimitUsd).toString();
148
150
  payload.liqPercent = new decimal_js_1.default(payload.borrowLimitUsd).div(payload.liquidationLimitUsd).mul(100).toString();
149
151
  payload.minDebt = assetsData[selectedMarket.baseAsset].minDebt;
@@ -1,9 +1,11 @@
1
1
  import { CrvUSDAggregatedPositionData, CrvUSDMarketData, CrvUSDUsedAssets } from '../../types';
2
2
  import { NetworkNumber } from '../../types/common';
3
- export declare const getCrvUsdAggregatedData: ({ loanExists, usedAssets, network, selectedMarket, numOfBands, ...rest }: {
3
+ export declare const getCrvUsdAggregatedData: ({ loanExists, usedAssets, network, selectedMarket, numOfBands, borrowRate, collStakingApy, ...rest }: {
4
4
  loanExists: boolean;
5
5
  usedAssets: CrvUSDUsedAssets;
6
6
  network: NetworkNumber;
7
7
  selectedMarket: CrvUSDMarketData;
8
8
  numOfBands: number | string;
9
+ borrowRate?: string;
10
+ collStakingApy?: string;
9
11
  }) => CrvUSDAggregatedPositionData;
@@ -18,9 +18,10 @@ exports.getCrvUsdAggregatedData = void 0;
18
18
  const decimal_js_1 = __importDefault(require("decimal.js"));
19
19
  const moneymarket_1 = require("../../moneymarket");
20
20
  const utils_1 = require("../../services/utils");
21
+ const staking_1 = require("../../staking");
21
22
  const getCrvUsdAggregatedData = (_a) => {
22
- var _b;
23
- var { loanExists, usedAssets, network, selectedMarket, numOfBands } = _a, rest = __rest(_a, ["loanExists", "usedAssets", "network", "selectedMarket", "numOfBands"]);
23
+ var _b, _c;
24
+ var { loanExists, usedAssets, network, selectedMarket, numOfBands, borrowRate = '0', collStakingApy = '0' } = _a, rest = __rest(_a, ["loanExists", "usedAssets", "network", "selectedMarket", "numOfBands", "borrowRate", "collStakingApy"]);
24
25
  const payload = {};
25
26
  payload.supplied = (0, moneymarket_1.getAssetsTotal)(usedAssets, ({ isSupplied }) => isSupplied, ({ supplied }) => supplied); // this is wrong if we are in soft-liquidations
26
27
  payload.borrowed = (0, moneymarket_1.getAssetsTotal)(usedAssets, ({ isBorrowed }) => isBorrowed, ({ borrowed }) => borrowed);
@@ -34,6 +35,8 @@ const getCrvUsdAggregatedData = (_a) => {
34
35
  : '0';
35
36
  // this is all approximation
36
37
  payload.minAllowedRatio = (0, utils_1.mapRange)(numOfBands, 4, 50, 115, 140); // collateral ratio
38
+ // Collateral ratio rebased so 100 sits on the band-derived minimum (normalised safety ratio, same scale as the other protocols).
39
+ payload.safetyRatio = loanExists && payload.minAllowedRatio ? new decimal_js_1.default(payload.ratio).div(payload.minAllowedRatio).mul(100).toString() : '0';
37
40
  payload.collFactor = new decimal_js_1.default(1).div(payload.minAllowedRatio).mul(100).toString(); // collateral factor = 1 / collateral ratio
38
41
  // only take in consideration collAsset
39
42
  payload.borrowLimitUsd = ((_b = usedAssets === null || usedAssets === void 0 ? void 0 : usedAssets[selectedMarket.collAsset]) === null || _b === void 0 ? void 0 : _b.isSupplied)
@@ -47,6 +50,17 @@ const getCrvUsdAggregatedData = (_a) => {
47
50
  payload.liquidationPrice = (0, moneymarket_1.calcLeverageLiqPrice)(leveragedType, usedAssets[selectedMarket.collAsset].price, payload.borrowedUsd, payload.borrowLimitUsd);
48
51
  }
49
52
  payload.exposure = (0, moneymarket_1.getExposure)(payload.borrowedUsd, payload.suppliedUsd);
53
+ // crvUSD debt accrues the market borrow rate. Collateral (including crvUSD held during soft liquidation) earns
54
+ // nothing from the protocol itself; only the native yield of staked collateral is counted, as an incentive.
55
+ const { netApy, totalInterestUsd, incentiveUsd } = (0, staking_1.calculateNetApyFromRates)({
56
+ suppliedUsd: payload.suppliedUsd,
57
+ borrowedUsd: payload.borrowedUsd,
58
+ borrowRate,
59
+ incentives: [{ apy: collStakingApy, amountUsd: ((_c = usedAssets === null || usedAssets === void 0 ? void 0 : usedAssets[selectedMarket.collAsset]) === null || _c === void 0 ? void 0 : _c.suppliedUsd) || '0' }],
60
+ });
61
+ payload.netApy = netApy;
62
+ payload.totalInterestUsd = totalInterestUsd;
63
+ payload.incentiveUsd = incentiveUsd;
50
64
  return payload;
51
65
  };
52
66
  exports.getCrvUsdAggregatedData = getCrvUsdAggregatedData;
@@ -85,6 +85,7 @@ const getFluidAggregatedData = ({ usedAssets, assetsData, marketData, }, supplyS
85
85
  payload.ratio = +payload.suppliedUsd ? new decimal_js_1.default(payload.borrowLimitUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
86
86
  payload.collRatio = +payload.suppliedUsd ? new decimal_js_1.default(payload.suppliedUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
87
87
  payload.minRatio = marketData.minRatio;
88
+ payload.safetyRatio = payload.ratio;
88
89
  const { leveragedType, leveragedAsset } = (0, moneymarket_1.isLeveragedPos)(usedAssets);
89
90
  payload.leveragedType = leveragedType;
90
91
  payload.liquidationPrice = '';
@@ -48,6 +48,7 @@ const getLiquityV2AggregatedPositionData = ({ usedAssets, assetsData, minCollRat
48
48
  payload.leftToBorrowUsd = leftToBorrowUsd.lte('0') ? '0' : leftToBorrowUsd.toString();
49
49
  payload.ratio = (+payload.suppliedUsd && +payload.borrowedUsd) ? new decimal_js_1.default(payload.borrowLimitUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
50
50
  payload.collRatio = (+payload.suppliedUsd && +payload.borrowedUsd) ? new decimal_js_1.default(payload.suppliedUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
51
+ payload.safetyRatio = payload.ratio;
51
52
  const { netApy, incentiveUsd, totalInterestUsd } = (0, exports.calculateNetApyLiquityV2)(usedAssets, assetsData, interestRate);
52
53
  payload.netApy = netApy;
53
54
  payload.incentiveUsd = incentiveUsd;
@@ -42,6 +42,8 @@ const getLlamaLendAggregatedData = (_a) => {
42
42
  : '0';
43
43
  // this is all approximation
44
44
  payload.minAllowedRatio = (0, utils_1.mapRange)(numOfBands, 4, 50, 115, 140); // collateral ratio
45
+ // Collateral ratio rebased so 100 sits on the band-derived minimum (normalised safety ratio, same scale as the other protocols).
46
+ payload.safetyRatio = loanExists && payload.minAllowedRatio ? new decimal_js_1.default(payload.ratio).div(payload.minAllowedRatio).mul(100).toString() : '0';
45
47
  payload.collFactor = new decimal_js_1.default(1).div(payload.minAllowedRatio).mul(100).toString(); // collateral factor = 1 / collateral ratio
46
48
  // only take in consideration collAsset
47
49
  payload.borrowLimitUsd = ((_b = usedAssets === null || usedAssets === void 0 ? void 0 : usedAssets[collAsset]) === null || _b === void 0 ? void 0 : _b.isSupplied)
@@ -1,4 +1,4 @@
1
- export declare const parseCollateralInfo: (ilk: string, _par: string, _mat: string, _art: string, _rate: string, _spot: string, _line: string, _duty: string, _futureRate: string, _chop: string) => {
1
+ export declare const parseCollateralInfo: (ilk: string, _par: string, _mat: string, _art: string, _rate: string, _spot: string, _line: string, _dust: string, _duty: string, _futureRate: string, _chop: string) => {
2
2
  ilkLabel: string;
3
3
  currentRate: string;
4
4
  futureRate: string;