@defisaver/positions-sdk 2.1.152-shifter-v2-dev-dev → 2.1.152-shifter-v2-2-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 (72) hide show
  1. package/cjs/aaveV2/index.js +2 -0
  2. package/cjs/fluid/index.d.ts +3 -0
  3. package/cjs/helpers/aaveHelpers/index.js +3 -0
  4. package/cjs/helpers/aaveV4Helpers/index.js +1 -0
  5. package/cjs/helpers/compoundHelpers/index.js +2 -0
  6. package/cjs/helpers/curveUsdHelpers/index.js +2 -0
  7. package/cjs/helpers/fluidHelpers/index.js +1 -0
  8. package/cjs/helpers/liquityV2Helpers/index.js +1 -0
  9. package/cjs/helpers/llamaLendHelpers/index.js +2 -0
  10. package/cjs/helpers/morphoBlueHelpers/index.js +2 -0
  11. package/cjs/helpers/morphoMidnightHelpers/index.js +2 -0
  12. package/cjs/helpers/sparkHelpers/index.js +1 -0
  13. package/cjs/liquity/index.js +8 -1
  14. package/cjs/maker/index.js +3 -0
  15. package/cjs/types/aave.d.ts +2 -0
  16. package/cjs/types/aaveV4.d.ts +1 -0
  17. package/cjs/types/compound.d.ts +2 -0
  18. package/cjs/types/fluid.d.ts +1 -0
  19. package/cjs/types/liquity.d.ts +1 -0
  20. package/cjs/types/liquityV2.d.ts +2 -0
  21. package/cjs/types/maker.d.ts +1 -0
  22. package/cjs/types/morphoBlue.d.ts +2 -0
  23. package/cjs/types/morphoMidnight.d.ts +1 -0
  24. package/cjs/types/spark.d.ts +2 -0
  25. package/esm/aaveV2/index.js +2 -0
  26. package/esm/fluid/index.d.ts +3 -0
  27. package/esm/helpers/aaveHelpers/index.js +3 -0
  28. package/esm/helpers/aaveV4Helpers/index.js +1 -0
  29. package/esm/helpers/compoundHelpers/index.js +2 -0
  30. package/esm/helpers/curveUsdHelpers/index.js +2 -0
  31. package/esm/helpers/fluidHelpers/index.js +1 -0
  32. package/esm/helpers/liquityV2Helpers/index.js +1 -0
  33. package/esm/helpers/llamaLendHelpers/index.js +2 -0
  34. package/esm/helpers/morphoBlueHelpers/index.js +2 -0
  35. package/esm/helpers/morphoMidnightHelpers/index.js +2 -0
  36. package/esm/helpers/sparkHelpers/index.js +1 -0
  37. package/esm/liquity/index.js +8 -1
  38. package/esm/maker/index.js +3 -0
  39. package/esm/types/aave.d.ts +2 -0
  40. package/esm/types/aaveV4.d.ts +1 -0
  41. package/esm/types/compound.d.ts +2 -0
  42. package/esm/types/fluid.d.ts +1 -0
  43. package/esm/types/liquity.d.ts +1 -0
  44. package/esm/types/liquityV2.d.ts +2 -0
  45. package/esm/types/maker.d.ts +1 -0
  46. package/esm/types/morphoBlue.d.ts +2 -0
  47. package/esm/types/morphoMidnight.d.ts +1 -0
  48. package/esm/types/spark.d.ts +2 -0
  49. package/package.json +1 -1
  50. package/src/aaveV2/index.ts +2 -0
  51. package/src/helpers/aaveHelpers/index.ts +3 -0
  52. package/src/helpers/aaveV4Helpers/index.ts +1 -0
  53. package/src/helpers/compoundHelpers/index.ts +2 -0
  54. package/src/helpers/curveUsdHelpers/index.ts +2 -0
  55. package/src/helpers/fluidHelpers/index.ts +1 -0
  56. package/src/helpers/liquityV2Helpers/index.ts +1 -0
  57. package/src/helpers/llamaLendHelpers/index.ts +2 -0
  58. package/src/helpers/morphoBlueHelpers/index.ts +2 -0
  59. package/src/helpers/morphoMidnightHelpers/index.ts +2 -0
  60. package/src/helpers/sparkHelpers/index.ts +1 -0
  61. package/src/liquity/index.ts +8 -1
  62. package/src/maker/index.ts +3 -0
  63. package/src/types/aave.ts +3 -0
  64. package/src/types/aaveV4.ts +1 -0
  65. package/src/types/compound.ts +2 -0
  66. package/src/types/fluid.ts +1 -0
  67. package/src/types/liquity.ts +2 -0
  68. package/src/types/liquityV2.ts +2 -0
  69. package/src/types/maker.ts +2 -0
  70. package/src/types/morphoBlue.ts +2 -0
  71. package/src/types/morphoMidnight.ts +1 -0
  72. 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) {
@@ -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;
@@ -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);
@@ -209,6 +209,7 @@ const aaveV4GetAggregatedPositionData = ({ usedAssets, assetsData, network, useU
209
209
  payload.ratio = +payload.suppliedUsd ? new decimal_js_1.default(payload.borrowLimitUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
210
210
  payload.minRatio = '100';
211
211
  payload.collRatio = +payload.suppliedUsd ? new decimal_js_1.default(payload.suppliedCollateralUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
212
+ payload.safetyRatio = payload.ratio;
212
213
  payload.liqRatio = new decimal_js_1.default(payload.borrowLimitUsd).div(payload.liquidationLimitUsd).toString();
213
214
  payload.liqPercent = new decimal_js_1.default(payload.borrowLimitUsd).div(payload.liquidationLimitUsd).mul(100).toString();
214
215
  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;
@@ -34,6 +34,8 @@ const getCrvUsdAggregatedData = (_a) => {
34
34
  : '0';
35
35
  // this is all approximation
36
36
  payload.minAllowedRatio = (0, utils_1.mapRange)(numOfBands, 4, 50, 115, 140); // collateral ratio
37
+ // Collateral ratio rebased so 100 sits on the band-derived minimum (normalised safety ratio, same scale as the other protocols).
38
+ payload.safetyRatio = loanExists && payload.minAllowedRatio ? new decimal_js_1.default(payload.ratio).div(payload.minAllowedRatio).mul(100).toString() : '0';
37
39
  payload.collFactor = new decimal_js_1.default(1).div(payload.minAllowedRatio).mul(100).toString(); // collateral factor = 1 / collateral ratio
38
40
  // only take in consideration collAsset
39
41
  payload.borrowLimitUsd = ((_b = usedAssets === null || usedAssets === void 0 ? void 0 : usedAssets[selectedMarket.collAsset]) === null || _b === void 0 ? void 0 : _b.isSupplied)
@@ -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)
@@ -46,6 +46,8 @@ const getMorphoBlueAggregatedPositionData = ({ usedAssets, assetsData, marketInf
46
46
  payload.ltv = new decimal_js_1.default(((_c = usedAssets[loanToken]) === null || _c === void 0 ? void 0 : _c.borrowed) || 0).div(oracle).div(((_d = usedAssets[collateralToken]) === null || _d === void 0 ? void 0 : _d.supplied) || 1).toString(); // default to 1 because can't div 0
47
47
  payload.ratio = new decimal_js_1.default(((_e = usedAssets[collateralToken]) === null || _e === void 0 ? void 0 : _e.supplied) || 0).mul(oracle).div(((_f = usedAssets[loanToken]) === null || _f === void 0 ? void 0 : _f.borrowed) || 1).mul(100)
48
48
  .toString();
49
+ // Borrow limit over debt, so 100 sits on the market's LLTV however low it is (`ratio` is the raw collateral ratio).
50
+ payload.safetyRatio = +payload.borrowedUsd > 0 ? new decimal_js_1.default(payload.borrowLimitUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
49
51
  const { leveragedType, leveragedAsset } = (0, moneymarket_1.isLeveragedPos)(usedAssets);
50
52
  payload.leveragedType = leveragedType;
51
53
  payload.liquidationPrice = '';
@@ -77,6 +77,8 @@ const getMorphoMidnightAggregatedPositionData = ({ usedAssets, assetsData, marke
77
77
  payload.ltv = new decimal_js_1.default(payload.suppliedCollateralUsd).eq(0) ? '0' : new decimal_js_1.default(payload.borrowedUsd).div(payload.suppliedCollateralUsd).toString();
78
78
  payload.ratio = new decimal_js_1.default(payload.borrowedUsd).eq(0) ? '0' : new decimal_js_1.default(payload.suppliedCollateralUsd).div(payload.borrowedUsd).mul(100).toString();
79
79
  payload.healthRatio = new decimal_js_1.default(payload.borrowedUsd).eq(0) ? 'Infinity' : new decimal_js_1.default(payload.liquidationLimitUsd).div(payload.borrowedUsd).toDP(4).toString();
80
+ // Borrow limit over debt, so 100 sits on the market's LLTV however low it is (`ratio` is the raw collateral ratio).
81
+ payload.safetyRatio = +payload.borrowedUsd > 0 ? new decimal_js_1.default(payload.borrowLimitUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
80
82
  const { leveragedType, leveragedAsset } = (0, moneymarket_1.isLeveragedPos)(usedAssets);
81
83
  payload.leveragedType = leveragedType;
82
84
  payload.liquidationPrice = '';
@@ -81,6 +81,7 @@ const sparkGetAggregatedPositionData = (_a) => {
81
81
  payload.leftToBorrowUsd = leftToBorrowUsd.lte('0') ? '0' : leftToBorrowUsd.toString();
82
82
  payload.ratio = +payload.suppliedUsd ? new decimal_js_1.default(payload.borrowLimitUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
83
83
  payload.collRatio = +payload.suppliedUsd ? new decimal_js_1.default(payload.suppliedCollateralUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
84
+ payload.safetyRatio = payload.ratio;
84
85
  const { netApy, incentiveUsd, totalInterestUsd } = (0, staking_1.calculateNetApy)({ usedAssets, assetsData });
85
86
  payload.netApy = netApy;
86
87
  payload.incentiveUsd = incentiveUsd;
@@ -77,6 +77,11 @@ const _getLiquityTroveInfo = (provider, network, address) => __awaiter(void 0, v
77
77
  _getDebtInFront(viewContract, address),
78
78
  ]);
79
79
  const recoveryMode = troveInfo[6];
80
+ const minCollateralRatio = recoveryMode ? exports.LIQUITY_RECOVERY_MODE_RATIO : exports.LIQUITY_NORMAL_MODE_RATIO;
81
+ const collateral = (0, tokens_1.assetAmountInEth)(troveInfo[1].toString());
82
+ const debtInAsset = (0, tokens_1.assetAmountInEth)(troveInfo[2].toString());
83
+ const collRatio = +debtInAsset ? new decimal_js_1.default(collateral).mul((0, tokens_1.assetAmountInEth)(assetPrice.toString())).div(debtInAsset).mul(100)
84
+ .toString() : '0';
80
85
  const payload = {
81
86
  troveStatus: types_1.LIQUITY_TROVE_STATUS_ENUM[+(troveInfo[0].toString())],
82
87
  collateral: (0, tokens_1.assetAmountInEth)(troveInfo[1].toString()),
@@ -89,7 +94,9 @@ const _getLiquityTroveInfo = (provider, network, address) => __awaiter(void 0, v
89
94
  totalETH: totalETH.toString(),
90
95
  totalLUSD: totalLUSD.toString(),
91
96
  debtInFront: debtInFront.toString(),
92
- minCollateralRatio: recoveryMode ? exports.LIQUITY_RECOVERY_MODE_RATIO : exports.LIQUITY_NORMAL_MODE_RATIO,
97
+ minCollateralRatio,
98
+ // Collateral ratio rebased so 100 sits on the trove's minimum collateral ratio (normalised safety ratio).
99
+ safetyRatio: +minCollateralRatio > 0 ? new decimal_js_1.default(collRatio).div(minCollateralRatio).mul(100).toString() : '0',
93
100
  priceForRecovery: new decimal_js_1.default(recoveryMode ? exports.LIQUITY_RECOVERY_MODE_RATIO : exports.LIQUITY_NORMAL_MODE_RATIO).mul(totalLUSD).div(totalETH).div(100)
94
101
  .toString(),
95
102
  exposure: (0, moneymarket_1.getExposure)((0, tokens_1.assetAmountInEth)(troveInfo[2].toString()), new decimal_js_1.default((0, tokens_1.assetAmountInEth)(troveInfo[1].toString())).mul(assetPrice).toString()),
@@ -134,6 +134,8 @@ const _getMakerCdpData = (provider, network, cdp, ilkInfo) => __awaiter(void 0,
134
134
  .toString();
135
135
  if (new decimal_js_1.default(debt).eq(0))
136
136
  ratio = '0';
137
+ // Collateral ratio rebased so 100 sits on the ilk's liquidation ratio (normalised safety ratio).
138
+ const safetyRatio = +collInfo.liqPercent > 0 ? new decimal_js_1.default(ratio).div(collInfo.liqPercent).mul(100).toString() : '0';
137
139
  const debtTooLow = new decimal_js_1.default(debt).gt(0) && new decimal_js_1.default((0, tokens_1.assetAmountInEth)(debt, 'DAI')).lt(collInfo.minDebt);
138
140
  return {
139
141
  owner: cdp.owner,
@@ -153,6 +155,7 @@ const _getMakerCdpData = (provider, network, cdp, ilkInfo) => __awaiter(void 0,
153
155
  debtAssetMarketPrice: '1',
154
156
  liquidationPrice,
155
157
  ratio,
158
+ safetyRatio,
156
159
  liqRatio: collInfo.liqRatio.toString(),
157
160
  liqPercent: parseFloat(collInfo.liqPercent.toString()),
158
161
  assetPrice: collInfo.assetPrice,
@@ -126,6 +126,7 @@ export interface AavePositionData extends MMPositionData {
126
126
  minRatio: string;
127
127
  collRatio: string;
128
128
  safetyRatioWithLtvZeroFallback?: string;
129
+ safetyRatio?: string;
129
130
  suppliedUsd: string;
130
131
  borrowedUsd: string;
131
132
  borrowLimitUsd: string;
@@ -159,6 +160,7 @@ export interface AaveV3AggregatedPositionData {
159
160
  collRatio: string;
160
161
  borrowLimitWithLtvZeroFallbackUsd: string;
161
162
  safetyRatioWithLtvZeroFallback: string;
163
+ safetyRatio: string;
162
164
  netApy: string;
163
165
  incentiveUsd: string;
164
166
  totalInterestUsd: string;
@@ -169,6 +169,7 @@ export interface AaveV4AggregatedPositionData {
169
169
  leftToBorrowUsd: string;
170
170
  ratio: string;
171
171
  collRatio: string;
172
+ safetyRatio: string;
172
173
  liqRatio: string;
173
174
  liqPercent: string;
174
175
  leveragedType: LeverageType;
@@ -96,6 +96,7 @@ export interface CompoundAggregatedPositionData {
96
96
  leftToBorrowUsd: string;
97
97
  ratio: string;
98
98
  collRatio: string;
99
+ safetyRatio: string;
99
100
  netApy: string;
100
101
  incentiveUsd: string;
101
102
  totalInterestUsd: string;
@@ -115,6 +116,7 @@ export interface CompoundAggregatedPositionData {
115
116
  export interface CompoundPositionData extends MMPositionData {
116
117
  ratio: string;
117
118
  minRatio: string;
119
+ safetyRatio?: string;
118
120
  suppliedUsd: string;
119
121
  borrowedUsd: string;
120
122
  borrowLimitUsd: string;
@@ -323,6 +323,7 @@ export interface FluidAggregatedVaultData {
323
323
  merklBorrowIncentives: IncentiveData[];
324
324
  ratio: string;
325
325
  collRatio: string;
326
+ safetyRatio: string;
326
327
  minRatio: string;
327
328
  totalInterestUsd: string;
328
329
  leveragedType?: LeverageType;
@@ -24,6 +24,7 @@ export interface LiquityTroveInfo {
24
24
  totalETH: string;
25
25
  totalLUSD: string;
26
26
  minCollateralRatio: number;
27
+ safetyRatio: string;
27
28
  priceForRecovery: string;
28
29
  debtInFront: string;
29
30
  exposure: string;
@@ -94,6 +94,7 @@ export interface LiquityV2AggregatedTroveData {
94
94
  liquidationPrice: string;
95
95
  ratio: string;
96
96
  collRatio: string;
97
+ safetyRatio: string;
97
98
  exposure: string;
98
99
  }
99
100
  export interface LiquityV2TroveData {
@@ -101,6 +102,7 @@ export interface LiquityV2TroveData {
101
102
  troveId: string;
102
103
  ratio: string;
103
104
  collRatio: string;
105
+ safetyRatio?: string;
104
106
  liqRatio: string;
105
107
  borrowLimitRatio: string;
106
108
  interestRate: string;
@@ -43,6 +43,7 @@ export interface CdpData {
43
43
  debtAssetMarketPrice: string;
44
44
  liquidationPrice: string;
45
45
  ratio: string;
46
+ safetyRatio: string;
46
47
  liqRatio: string;
47
48
  liqPercent: number;
48
49
  assetPrice: string;
@@ -185,6 +185,7 @@ export interface MorphoBlueAggregatedPositionData {
185
185
  totalInterestUsd: string;
186
186
  ltv: string;
187
187
  ratio: string;
188
+ safetyRatio: string;
188
189
  leveragedType: LeverageType;
189
190
  leveragedAsset?: string;
190
191
  currentVolatilePairRatio?: string;
@@ -207,6 +208,7 @@ export interface MorphoBluePositionData {
207
208
  totalInterestUsd: string;
208
209
  ltv: string;
209
210
  ratio: string;
211
+ safetyRatio?: string;
210
212
  leveragedType: LeverageType;
211
213
  leveragedAsset?: string;
212
214
  currentVolatilePairRatio?: string;
@@ -169,6 +169,7 @@ export interface MorphoMidnightAggregatedPositionData {
169
169
  ltv: string;
170
170
  ratio: string;
171
171
  healthRatio: string;
172
+ safetyRatio: string;
172
173
  leveragedType: LeverageType;
173
174
  leveragedAsset?: string;
174
175
  currentVolatilePairRatio?: string;
@@ -85,6 +85,7 @@ export interface SparkAggregatedPositionData {
85
85
  leftToBorrowUsd: string;
86
86
  ratio: string;
87
87
  collRatio: string;
88
+ safetyRatio: string;
88
89
  netApy: string;
89
90
  incentiveUsd: string;
90
91
  totalInterestUsd: string;
@@ -104,6 +105,7 @@ export interface SparkPositionData extends MMPositionData {
104
105
  ratio: string;
105
106
  minRatio: string;
106
107
  collRatio: string;
108
+ safetyRatio?: string;
107
109
  suppliedUsd: string;
108
110
  borrowedUsd: string;
109
111
  borrowLimitUsd: string;
@@ -167,6 +167,8 @@ export const _getAaveV2AccountData = (provider, network, address, assetsData, ma
167
167
  payload.collRatio = payload.borrowedUsd && payload.borrowedUsd !== '0'
168
168
  ? new Dec(payload.suppliedCollateralUsd).div(payload.borrowedUsd).mul(100).toString()
169
169
  : '0';
170
+ // Aave v2 has no LTV-0 fallback (AaveV3View only), so its safety ratio is the plain ratio.
171
+ payload.safetyRatio = payload.ratio;
170
172
  // Calculate borrow limits per asset
171
173
  Object.values(payload.usedAssets).forEach((item) => {
172
174
  if (item.isBorrowed) {
@@ -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;
@@ -125,6 +125,9 @@ export const aaveAnyGetAggregatedPositionData = (_a) => {
125
125
  return new Dec(suppliedUsd).mul(effectiveLtv);
126
126
  });
127
127
  payload.safetyRatioWithLtvZeroFallback = +payload.suppliedUsd ? new Dec(payload.borrowLimitWithLtvZeroFallbackUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
128
+ // Normalised safety ratio (100 = liquidation on every protocol): the automation ratio above, falling back
129
+ // to the regular ratio when the fallback carries its '0' placeholder.
130
+ payload.safetyRatio = +payload.safetyRatioWithLtvZeroFallback ? payload.safetyRatioWithLtvZeroFallback : payload.ratio;
128
131
  payload.liqRatio = new Dec(payload.borrowLimitUsd).div(payload.liquidationLimitUsd).toString();
129
132
  payload.liqPercent = new Dec(payload.borrowLimitUsd).div(payload.liquidationLimitUsd).mul(100).toString();
130
133
  const { leveragedType, leveragedAsset } = isLeveragedPos(usedAssets);
@@ -198,6 +198,7 @@ export const aaveV4GetAggregatedPositionData = ({ usedAssets, assetsData, networ
198
198
  payload.ratio = +payload.suppliedUsd ? new Dec(payload.borrowLimitUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
199
199
  payload.minRatio = '100';
200
200
  payload.collRatio = +payload.suppliedUsd ? new Dec(payload.suppliedCollateralUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
201
+ payload.safetyRatio = payload.ratio;
201
202
  payload.liqRatio = new Dec(payload.borrowLimitUsd).div(payload.liquidationLimitUsd).toString();
202
203
  payload.liqPercent = new Dec(payload.borrowLimitUsd).div(payload.liquidationLimitUsd).mul(100).toString();
203
204
  const { leveragedType, leveragedAsset } = isLeveragedPosAaveV4(usedAssets);
@@ -93,6 +93,7 @@ export const getCompoundV2AggregatedData = (_a) => {
93
93
  payload.collRatio = payload.borrowedUsd && payload.borrowedUsd !== '0'
94
94
  ? new Dec(payload.suppliedCollateralUsd).div(payload.borrowedUsd).mul(100).toString()
95
95
  : '0';
96
+ payload.safetyRatio = payload.ratio;
96
97
  // Calculate borrow limits per asset
97
98
  Object.values(usedAssets).forEach((item) => {
98
99
  if (item.isBorrowed) {
@@ -134,6 +135,7 @@ export const getCompoundV3AggregatedData = (_a) => {
134
135
  payload.incentiveUsd = incentiveUsd;
135
136
  payload.totalInterestUsd = totalInterestUsd;
136
137
  payload.minRatio = '100';
138
+ payload.safetyRatio = payload.ratio;
137
139
  payload.liqRatio = new Dec(payload.borrowLimitUsd).div(payload.liquidationLimitUsd).toString();
138
140
  payload.liqPercent = new Dec(payload.borrowLimitUsd).div(payload.liquidationLimitUsd).mul(100).toString();
139
141
  payload.minDebt = assetsData[selectedMarket.baseAsset].minDebt;
@@ -28,6 +28,8 @@ export const getCrvUsdAggregatedData = (_a) => {
28
28
  : '0';
29
29
  // this is all approximation
30
30
  payload.minAllowedRatio = mapRange(numOfBands, 4, 50, 115, 140); // collateral ratio
31
+ // Collateral ratio rebased so 100 sits on the band-derived minimum (normalised safety ratio, same scale as the other protocols).
32
+ payload.safetyRatio = loanExists && payload.minAllowedRatio ? new Dec(payload.ratio).div(payload.minAllowedRatio).mul(100).toString() : '0';
31
33
  payload.collFactor = new Dec(1).div(payload.minAllowedRatio).mul(100).toString(); // collateral factor = 1 / collateral ratio
32
34
  // only take in consideration collAsset
33
35
  payload.borrowLimitUsd = ((_b = usedAssets === null || usedAssets === void 0 ? void 0 : usedAssets[selectedMarket.collAsset]) === null || _b === void 0 ? void 0 : _b.isSupplied)
@@ -78,6 +78,7 @@ export const getFluidAggregatedData = ({ usedAssets, assetsData, marketData, },
78
78
  payload.ratio = +payload.suppliedUsd ? new Dec(payload.borrowLimitUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
79
79
  payload.collRatio = +payload.suppliedUsd ? new Dec(payload.suppliedUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
80
80
  payload.minRatio = marketData.minRatio;
81
+ payload.safetyRatio = payload.ratio;
81
82
  const { leveragedType, leveragedAsset } = isLeveragedPos(usedAssets);
82
83
  payload.leveragedType = leveragedType;
83
84
  payload.liquidationPrice = '';
@@ -41,6 +41,7 @@ export const getLiquityV2AggregatedPositionData = ({ usedAssets, assetsData, min
41
41
  payload.leftToBorrowUsd = leftToBorrowUsd.lte('0') ? '0' : leftToBorrowUsd.toString();
42
42
  payload.ratio = (+payload.suppliedUsd && +payload.borrowedUsd) ? new Dec(payload.borrowLimitUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
43
43
  payload.collRatio = (+payload.suppliedUsd && +payload.borrowedUsd) ? new Dec(payload.suppliedUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
44
+ payload.safetyRatio = payload.ratio;
44
45
  const { netApy, incentiveUsd, totalInterestUsd } = calculateNetApyLiquityV2(usedAssets, assetsData, interestRate);
45
46
  payload.netApy = netApy;
46
47
  payload.incentiveUsd = incentiveUsd;
@@ -36,6 +36,8 @@ export const getLlamaLendAggregatedData = (_a) => {
36
36
  : '0';
37
37
  // this is all approximation
38
38
  payload.minAllowedRatio = mapRange(numOfBands, 4, 50, 115, 140); // collateral ratio
39
+ // Collateral ratio rebased so 100 sits on the band-derived minimum (normalised safety ratio, same scale as the other protocols).
40
+ payload.safetyRatio = loanExists && payload.minAllowedRatio ? new Dec(payload.ratio).div(payload.minAllowedRatio).mul(100).toString() : '0';
39
41
  payload.collFactor = new Dec(1).div(payload.minAllowedRatio).mul(100).toString(); // collateral factor = 1 / collateral ratio
40
42
  // only take in consideration collAsset
41
43
  payload.borrowLimitUsd = ((_b = usedAssets === null || usedAssets === void 0 ? void 0 : usedAssets[collAsset]) === null || _b === void 0 ? void 0 : _b.isSupplied)
@@ -40,6 +40,8 @@ export const getMorphoBlueAggregatedPositionData = ({ usedAssets, assetsData, ma
40
40
  payload.ltv = new Dec(((_c = usedAssets[loanToken]) === null || _c === void 0 ? void 0 : _c.borrowed) || 0).div(oracle).div(((_d = usedAssets[collateralToken]) === null || _d === void 0 ? void 0 : _d.supplied) || 1).toString(); // default to 1 because can't div 0
41
41
  payload.ratio = new Dec(((_e = usedAssets[collateralToken]) === null || _e === void 0 ? void 0 : _e.supplied) || 0).mul(oracle).div(((_f = usedAssets[loanToken]) === null || _f === void 0 ? void 0 : _f.borrowed) || 1).mul(100)
42
42
  .toString();
43
+ // Borrow limit over debt, so 100 sits on the market's LLTV however low it is (`ratio` is the raw collateral ratio).
44
+ payload.safetyRatio = +payload.borrowedUsd > 0 ? new Dec(payload.borrowLimitUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
43
45
  const { leveragedType, leveragedAsset } = isLeveragedPos(usedAssets);
44
46
  payload.leveragedType = leveragedType;
45
47
  payload.liquidationPrice = '';
@@ -58,6 +58,8 @@ export const getMorphoMidnightAggregatedPositionData = ({ usedAssets, assetsData
58
58
  payload.ltv = new Dec(payload.suppliedCollateralUsd).eq(0) ? '0' : new Dec(payload.borrowedUsd).div(payload.suppliedCollateralUsd).toString();
59
59
  payload.ratio = new Dec(payload.borrowedUsd).eq(0) ? '0' : new Dec(payload.suppliedCollateralUsd).div(payload.borrowedUsd).mul(100).toString();
60
60
  payload.healthRatio = new Dec(payload.borrowedUsd).eq(0) ? 'Infinity' : new Dec(payload.liquidationLimitUsd).div(payload.borrowedUsd).toDP(4).toString();
61
+ // Borrow limit over debt, so 100 sits on the market's LLTV however low it is (`ratio` is the raw collateral ratio).
62
+ payload.safetyRatio = +payload.borrowedUsd > 0 ? new Dec(payload.borrowLimitUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
61
63
  const { leveragedType, leveragedAsset } = isLeveragedPos(usedAssets);
62
64
  payload.leveragedType = leveragedType;
63
65
  payload.liquidationPrice = '';
@@ -70,6 +70,7 @@ export const sparkGetAggregatedPositionData = (_a) => {
70
70
  payload.leftToBorrowUsd = leftToBorrowUsd.lte('0') ? '0' : leftToBorrowUsd.toString();
71
71
  payload.ratio = +payload.suppliedUsd ? new Dec(payload.borrowLimitUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
72
72
  payload.collRatio = +payload.suppliedUsd ? new Dec(payload.suppliedCollateralUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
73
+ payload.safetyRatio = payload.ratio;
73
74
  const { netApy, incentiveUsd, totalInterestUsd } = calculateNetApy({ usedAssets, assetsData });
74
75
  payload.netApy = netApy;
75
76
  payload.incentiveUsd = incentiveUsd;
@@ -68,6 +68,11 @@ export const _getLiquityTroveInfo = (provider, network, address) => __awaiter(vo
68
68
  _getDebtInFront(viewContract, address),
69
69
  ]);
70
70
  const recoveryMode = troveInfo[6];
71
+ const minCollateralRatio = recoveryMode ? LIQUITY_RECOVERY_MODE_RATIO : LIQUITY_NORMAL_MODE_RATIO;
72
+ const collateral = assetAmountInEth(troveInfo[1].toString());
73
+ const debtInAsset = assetAmountInEth(troveInfo[2].toString());
74
+ const collRatio = +debtInAsset ? new Dec(collateral).mul(assetAmountInEth(assetPrice.toString())).div(debtInAsset).mul(100)
75
+ .toString() : '0';
71
76
  const payload = {
72
77
  troveStatus: LIQUITY_TROVE_STATUS_ENUM[+(troveInfo[0].toString())],
73
78
  collateral: assetAmountInEth(troveInfo[1].toString()),
@@ -80,7 +85,9 @@ export const _getLiquityTroveInfo = (provider, network, address) => __awaiter(vo
80
85
  totalETH: totalETH.toString(),
81
86
  totalLUSD: totalLUSD.toString(),
82
87
  debtInFront: debtInFront.toString(),
83
- minCollateralRatio: recoveryMode ? LIQUITY_RECOVERY_MODE_RATIO : LIQUITY_NORMAL_MODE_RATIO,
88
+ minCollateralRatio,
89
+ // Collateral ratio rebased so 100 sits on the trove's minimum collateral ratio (normalised safety ratio).
90
+ safetyRatio: +minCollateralRatio > 0 ? new Dec(collRatio).div(minCollateralRatio).mul(100).toString() : '0',
84
91
  priceForRecovery: new Dec(recoveryMode ? LIQUITY_RECOVERY_MODE_RATIO : LIQUITY_NORMAL_MODE_RATIO).mul(totalLUSD).div(totalETH).div(100)
85
92
  .toString(),
86
93
  exposure: getExposure(assetAmountInEth(troveInfo[2].toString()), new Dec(assetAmountInEth(troveInfo[1].toString())).mul(assetPrice).toString()),
@@ -122,6 +122,8 @@ export const _getMakerCdpData = (provider, network, cdp, ilkInfo) => __awaiter(v
122
122
  .toString();
123
123
  if (new Dec(debt).eq(0))
124
124
  ratio = '0';
125
+ // Collateral ratio rebased so 100 sits on the ilk's liquidation ratio (normalised safety ratio).
126
+ const safetyRatio = +collInfo.liqPercent > 0 ? new Dec(ratio).div(collInfo.liqPercent).mul(100).toString() : '0';
125
127
  const debtTooLow = new Dec(debt).gt(0) && new Dec(assetAmountInEth(debt, 'DAI')).lt(collInfo.minDebt);
126
128
  return {
127
129
  owner: cdp.owner,
@@ -141,6 +143,7 @@ export const _getMakerCdpData = (provider, network, cdp, ilkInfo) => __awaiter(v
141
143
  debtAssetMarketPrice: '1',
142
144
  liquidationPrice,
143
145
  ratio,
146
+ safetyRatio,
144
147
  liqRatio: collInfo.liqRatio.toString(),
145
148
  liqPercent: parseFloat(collInfo.liqPercent.toString()),
146
149
  assetPrice: collInfo.assetPrice,
@@ -126,6 +126,7 @@ export interface AavePositionData extends MMPositionData {
126
126
  minRatio: string;
127
127
  collRatio: string;
128
128
  safetyRatioWithLtvZeroFallback?: string;
129
+ safetyRatio?: string;
129
130
  suppliedUsd: string;
130
131
  borrowedUsd: string;
131
132
  borrowLimitUsd: string;
@@ -159,6 +160,7 @@ export interface AaveV3AggregatedPositionData {
159
160
  collRatio: string;
160
161
  borrowLimitWithLtvZeroFallbackUsd: string;
161
162
  safetyRatioWithLtvZeroFallback: string;
163
+ safetyRatio: string;
162
164
  netApy: string;
163
165
  incentiveUsd: string;
164
166
  totalInterestUsd: string;
@@ -169,6 +169,7 @@ export interface AaveV4AggregatedPositionData {
169
169
  leftToBorrowUsd: string;
170
170
  ratio: string;
171
171
  collRatio: string;
172
+ safetyRatio: string;
172
173
  liqRatio: string;
173
174
  liqPercent: string;
174
175
  leveragedType: LeverageType;
@@ -96,6 +96,7 @@ export interface CompoundAggregatedPositionData {
96
96
  leftToBorrowUsd: string;
97
97
  ratio: string;
98
98
  collRatio: string;
99
+ safetyRatio: string;
99
100
  netApy: string;
100
101
  incentiveUsd: string;
101
102
  totalInterestUsd: string;
@@ -115,6 +116,7 @@ export interface CompoundAggregatedPositionData {
115
116
  export interface CompoundPositionData extends MMPositionData {
116
117
  ratio: string;
117
118
  minRatio: string;
119
+ safetyRatio?: string;
118
120
  suppliedUsd: string;
119
121
  borrowedUsd: string;
120
122
  borrowLimitUsd: string;
@@ -323,6 +323,7 @@ export interface FluidAggregatedVaultData {
323
323
  merklBorrowIncentives: IncentiveData[];
324
324
  ratio: string;
325
325
  collRatio: string;
326
+ safetyRatio: string;
326
327
  minRatio: string;
327
328
  totalInterestUsd: string;
328
329
  leveragedType?: LeverageType;
@@ -24,6 +24,7 @@ export interface LiquityTroveInfo {
24
24
  totalETH: string;
25
25
  totalLUSD: string;
26
26
  minCollateralRatio: number;
27
+ safetyRatio: string;
27
28
  priceForRecovery: string;
28
29
  debtInFront: string;
29
30
  exposure: string;
@@ -94,6 +94,7 @@ export interface LiquityV2AggregatedTroveData {
94
94
  liquidationPrice: string;
95
95
  ratio: string;
96
96
  collRatio: string;
97
+ safetyRatio: string;
97
98
  exposure: string;
98
99
  }
99
100
  export interface LiquityV2TroveData {
@@ -101,6 +102,7 @@ export interface LiquityV2TroveData {
101
102
  troveId: string;
102
103
  ratio: string;
103
104
  collRatio: string;
105
+ safetyRatio?: string;
104
106
  liqRatio: string;
105
107
  borrowLimitRatio: string;
106
108
  interestRate: string;
@@ -43,6 +43,7 @@ export interface CdpData {
43
43
  debtAssetMarketPrice: string;
44
44
  liquidationPrice: string;
45
45
  ratio: string;
46
+ safetyRatio: string;
46
47
  liqRatio: string;
47
48
  liqPercent: number;
48
49
  assetPrice: string;
@@ -185,6 +185,7 @@ export interface MorphoBlueAggregatedPositionData {
185
185
  totalInterestUsd: string;
186
186
  ltv: string;
187
187
  ratio: string;
188
+ safetyRatio: string;
188
189
  leveragedType: LeverageType;
189
190
  leveragedAsset?: string;
190
191
  currentVolatilePairRatio?: string;
@@ -207,6 +208,7 @@ export interface MorphoBluePositionData {
207
208
  totalInterestUsd: string;
208
209
  ltv: string;
209
210
  ratio: string;
211
+ safetyRatio?: string;
210
212
  leveragedType: LeverageType;
211
213
  leveragedAsset?: string;
212
214
  currentVolatilePairRatio?: string;
@@ -169,6 +169,7 @@ export interface MorphoMidnightAggregatedPositionData {
169
169
  ltv: string;
170
170
  ratio: string;
171
171
  healthRatio: string;
172
+ safetyRatio: string;
172
173
  leveragedType: LeverageType;
173
174
  leveragedAsset?: string;
174
175
  currentVolatilePairRatio?: string;
@@ -85,6 +85,7 @@ export interface SparkAggregatedPositionData {
85
85
  leftToBorrowUsd: string;
86
86
  ratio: string;
87
87
  collRatio: string;
88
+ safetyRatio: string;
88
89
  netApy: string;
89
90
  incentiveUsd: string;
90
91
  totalInterestUsd: string;
@@ -104,6 +105,7 @@ export interface SparkPositionData extends MMPositionData {
104
105
  ratio: string;
105
106
  minRatio: string;
106
107
  collRatio: string;
108
+ safetyRatio?: string;
107
109
  suppliedUsd: string;
108
110
  borrowedUsd: string;
109
111
  borrowLimitUsd: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defisaver/positions-sdk",
3
- "version": "2.1.152-shifter-v2-dev-dev",
3
+ "version": "2.1.152-shifter-v2-2-dev",
4
4
  "description": "",
5
5
  "main": "./cjs/index.js",
6
6
  "module": "./esm/index.js",
@@ -210,6 +210,8 @@ export const _getAaveV2AccountData = async (provider: Client, network: NetworkNu
210
210
  payload.collRatio = payload.borrowedUsd && payload.borrowedUsd !== '0'
211
211
  ? new Dec(payload.suppliedCollateralUsd).div(payload.borrowedUsd).mul(100).toString()
212
212
  : '0';
213
+ // Aave v2 has no LTV-0 fallback (AaveV3View only), so its safety ratio is the plain ratio.
214
+ payload.safetyRatio = payload.ratio;
213
215
 
214
216
  // Calculate borrow limits per asset
215
217
  Object.values(payload.usedAssets).forEach((item) => {
@@ -169,6 +169,9 @@ export const aaveAnyGetAggregatedPositionData = ({
169
169
  },
170
170
  );
171
171
  payload.safetyRatioWithLtvZeroFallback = +payload.suppliedUsd ? new Dec(payload.borrowLimitWithLtvZeroFallbackUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
172
+ // Normalised safety ratio (100 = liquidation on every protocol): the automation ratio above, falling back
173
+ // to the regular ratio when the fallback carries its '0' placeholder.
174
+ payload.safetyRatio = +payload.safetyRatioWithLtvZeroFallback ? payload.safetyRatioWithLtvZeroFallback : payload.ratio;
172
175
  payload.liqRatio = new Dec(payload.borrowLimitUsd).div(payload.liquidationLimitUsd).toString();
173
176
  payload.liqPercent = new Dec(payload.borrowLimitUsd).div(payload.liquidationLimitUsd).mul(100).toString();
174
177
  const { leveragedType, leveragedAsset } = isLeveragedPos(usedAssets);
@@ -258,6 +258,7 @@ export const aaveV4GetAggregatedPositionData = ({
258
258
  payload.ratio = +payload.suppliedUsd ? new Dec(payload.borrowLimitUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
259
259
  payload.minRatio = '100';
260
260
  payload.collRatio = +payload.suppliedUsd ? new Dec(payload.suppliedCollateralUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
261
+ payload.safetyRatio = payload.ratio;
261
262
  payload.liqRatio = new Dec(payload.borrowLimitUsd).div(payload.liquidationLimitUsd).toString();
262
263
  payload.liqPercent = new Dec(payload.borrowLimitUsd).div(payload.liquidationLimitUsd).mul(100).toString();
263
264
  const { leveragedType, leveragedAsset } = isLeveragedPosAaveV4(usedAssets);
@@ -139,6 +139,7 @@ export const getCompoundV2AggregatedData = ({
139
139
  payload.collRatio = payload.borrowedUsd && payload.borrowedUsd !== '0'
140
140
  ? new Dec(payload.suppliedCollateralUsd).div(payload.borrowedUsd).mul(100).toString()
141
141
  : '0';
142
+ payload.safetyRatio = payload.ratio;
142
143
 
143
144
  // Calculate borrow limits per asset
144
145
  Object.values(usedAssets).forEach((item) => {
@@ -185,6 +186,7 @@ export const getCompoundV3AggregatedData = ({
185
186
  payload.incentiveUsd = incentiveUsd;
186
187
  payload.totalInterestUsd = totalInterestUsd;
187
188
  payload.minRatio = '100';
189
+ payload.safetyRatio = payload.ratio;
188
190
  payload.liqRatio = new Dec(payload.borrowLimitUsd).div(payload.liquidationLimitUsd).toString();
189
191
  payload.liqPercent = new Dec(payload.borrowLimitUsd).div(payload.liquidationLimitUsd).mul(100).toString();
190
192
  payload.minDebt = assetsData[selectedMarket.baseAsset].minDebt;
@@ -26,6 +26,8 @@ export const getCrvUsdAggregatedData = ({
26
26
 
27
27
  // this is all approximation
28
28
  payload.minAllowedRatio = mapRange(numOfBands, 4, 50, 115, 140); // collateral ratio
29
+ // Collateral ratio rebased so 100 sits on the band-derived minimum (normalised safety ratio, same scale as the other protocols).
30
+ payload.safetyRatio = loanExists && payload.minAllowedRatio ? new Dec(payload.ratio).div(payload.minAllowedRatio).mul(100).toString() : '0';
29
31
  payload.collFactor = new Dec(1).div(payload.minAllowedRatio).mul(100).toString(); // collateral factor = 1 / collateral ratio
30
32
  // only take in consideration collAsset
31
33
  payload.borrowLimitUsd = usedAssets?.[selectedMarket.collAsset]?.isSupplied
@@ -143,6 +143,7 @@ borrowShares?: string,
143
143
  payload.ratio = +payload.suppliedUsd ? new Dec(payload.borrowLimitUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
144
144
  payload.collRatio = +payload.suppliedUsd ? new Dec(payload.suppliedUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
145
145
  payload.minRatio = marketData.minRatio;
146
+ payload.safetyRatio = payload.ratio;
146
147
  const { leveragedType, leveragedAsset } = isLeveragedPos(usedAssets);
147
148
 
148
149
  payload.leveragedType = leveragedType;
@@ -69,6 +69,7 @@ export const getLiquityV2AggregatedPositionData = ({
69
69
  payload.leftToBorrowUsd = leftToBorrowUsd.lte('0') ? '0' : leftToBorrowUsd.toString();
70
70
  payload.ratio = (+payload.suppliedUsd && +payload.borrowedUsd) ? new Dec(payload.borrowLimitUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
71
71
  payload.collRatio = (+payload.suppliedUsd && +payload.borrowedUsd) ? new Dec(payload.suppliedUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
72
+ payload.safetyRatio = payload.ratio;
72
73
  const { netApy, incentiveUsd, totalInterestUsd } = calculateNetApyLiquityV2(usedAssets, assetsData, interestRate);
73
74
  payload.netApy = netApy;
74
75
  payload.incentiveUsd = incentiveUsd;
@@ -38,6 +38,8 @@ export const getLlamaLendAggregatedData = ({
38
38
 
39
39
  // this is all approximation
40
40
  payload.minAllowedRatio = mapRange(numOfBands, 4, 50, 115, 140); // collateral ratio
41
+ // Collateral ratio rebased so 100 sits on the band-derived minimum (normalised safety ratio, same scale as the other protocols).
42
+ payload.safetyRatio = loanExists && payload.minAllowedRatio ? new Dec(payload.ratio).div(payload.minAllowedRatio).mul(100).toString() : '0';
41
43
  payload.collFactor = new Dec(1).div(payload.minAllowedRatio).mul(100).toString(); // collateral factor = 1 / collateral ratio
42
44
  // only take in consideration collAsset
43
45
  payload.borrowLimitUsd = usedAssets?.[collAsset]?.isSupplied
@@ -52,6 +52,8 @@ export const getMorphoBlueAggregatedPositionData = ({ usedAssets, assetsData, ma
52
52
  payload.ltv = new Dec(usedAssets[loanToken]?.borrowed || 0).div(oracle).div(usedAssets[collateralToken]?.supplied || 1).toString(); // default to 1 because can't div 0
53
53
  payload.ratio = new Dec(usedAssets[collateralToken]?.supplied || 0).mul(oracle).div(usedAssets[loanToken]?.borrowed || 1).mul(100)
54
54
  .toString();
55
+ // Borrow limit over debt, so 100 sits on the market's LLTV however low it is (`ratio` is the raw collateral ratio).
56
+ payload.safetyRatio = +payload.borrowedUsd > 0 ? new Dec(payload.borrowLimitUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
55
57
 
56
58
  const { leveragedType, leveragedAsset } = isLeveragedPos(usedAssets);
57
59
  payload.leveragedType = leveragedType;
@@ -102,6 +102,8 @@ export const getMorphoMidnightAggregatedPositionData = ({
102
102
  payload.ltv = new Dec(payload.suppliedCollateralUsd).eq(0) ? '0' : new Dec(payload.borrowedUsd).div(payload.suppliedCollateralUsd).toString();
103
103
  payload.ratio = new Dec(payload.borrowedUsd).eq(0) ? '0' : new Dec(payload.suppliedCollateralUsd).div(payload.borrowedUsd).mul(100).toString();
104
104
  payload.healthRatio = new Dec(payload.borrowedUsd).eq(0) ? 'Infinity' : new Dec(payload.liquidationLimitUsd).div(payload.borrowedUsd).toDP(4).toString();
105
+ // Borrow limit over debt, so 100 sits on the market's LLTV however low it is (`ratio` is the raw collateral ratio).
106
+ payload.safetyRatio = +payload.borrowedUsd > 0 ? new Dec(payload.borrowLimitUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
105
107
 
106
108
  const { leveragedType, leveragedAsset } = isLeveragedPos(usedAssets);
107
109
  payload.leveragedType = leveragedType;
@@ -96,6 +96,7 @@ export const sparkGetAggregatedPositionData = ({
96
96
  payload.leftToBorrowUsd = leftToBorrowUsd.lte('0') ? '0' : leftToBorrowUsd.toString();
97
97
  payload.ratio = +payload.suppliedUsd ? new Dec(payload.borrowLimitUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
98
98
  payload.collRatio = +payload.suppliedUsd ? new Dec(payload.suppliedCollateralUsd).div(payload.borrowedUsd).mul(100).toString() : '0';
99
+ payload.safetyRatio = payload.ratio;
99
100
  const { netApy, incentiveUsd, totalInterestUsd } = calculateNetApy({ usedAssets, assetsData });
100
101
  payload.netApy = netApy;
101
102
  payload.incentiveUsd = incentiveUsd;
@@ -89,6 +89,11 @@ export const _getLiquityTroveInfo = async (provider: Client, network: NetworkNum
89
89
  ]);
90
90
 
91
91
  const recoveryMode = troveInfo[6];
92
+ const minCollateralRatio = recoveryMode ? LIQUITY_RECOVERY_MODE_RATIO : LIQUITY_NORMAL_MODE_RATIO;
93
+ const collateral = assetAmountInEth(troveInfo[1].toString());
94
+ const debtInAsset = assetAmountInEth(troveInfo[2].toString());
95
+ const collRatio = +debtInAsset ? new Dec(collateral).mul(assetAmountInEth(assetPrice.toString())).div(debtInAsset).mul(100)
96
+ .toString() : '0';
92
97
 
93
98
  const payload = {
94
99
  troveStatus: LIQUITY_TROVE_STATUS_ENUM[+(troveInfo[0].toString())],
@@ -102,7 +107,9 @@ export const _getLiquityTroveInfo = async (provider: Client, network: NetworkNum
102
107
  totalETH: totalETH.toString(),
103
108
  totalLUSD: totalLUSD.toString(),
104
109
  debtInFront: debtInFront.toString(),
105
- minCollateralRatio: recoveryMode ? LIQUITY_RECOVERY_MODE_RATIO : LIQUITY_NORMAL_MODE_RATIO,
110
+ minCollateralRatio,
111
+ // Collateral ratio rebased so 100 sits on the trove's minimum collateral ratio (normalised safety ratio).
112
+ safetyRatio: +minCollateralRatio > 0 ? new Dec(collRatio).div(minCollateralRatio).mul(100).toString() : '0',
106
113
  priceForRecovery: new Dec(recoveryMode ? LIQUITY_RECOVERY_MODE_RATIO : LIQUITY_NORMAL_MODE_RATIO).mul(totalLUSD).div(totalETH).div(100)
107
114
  .toString(),
108
115
  exposure: getExposure(assetAmountInEth(troveInfo[2].toString()), new Dec(assetAmountInEth(troveInfo[1].toString())).mul(assetPrice).toString()),
@@ -208,6 +208,8 @@ export const _getMakerCdpData = async (provider: Client, network: NetworkNumber,
208
208
  let ratio = new Dec(ink).times(collInfo.assetPrice).div(debt).times(100)
209
209
  .toString();
210
210
  if (new Dec(debt).eq(0)) ratio = '0';
211
+ // Collateral ratio rebased so 100 sits on the ilk's liquidation ratio (normalised safety ratio).
212
+ const safetyRatio = +collInfo.liqPercent > 0 ? new Dec(ratio).div(collInfo.liqPercent).mul(100).toString() : '0';
211
213
 
212
214
  const debtTooLow = new Dec(debt).gt(0) && new Dec(assetAmountInEth(debt, 'DAI')).lt(collInfo.minDebt);
213
215
 
@@ -229,6 +231,7 @@ export const _getMakerCdpData = async (provider: Client, network: NetworkNumber,
229
231
  debtAssetMarketPrice: '1',
230
232
  liquidationPrice,
231
233
  ratio,
234
+ safetyRatio,
232
235
  liqRatio: collInfo.liqRatio.toString(),
233
236
  liqPercent: parseFloat(collInfo.liqPercent.toString()),
234
237
  assetPrice: collInfo.assetPrice,
package/src/types/aave.ts CHANGED
@@ -143,6 +143,8 @@ export interface AavePositionData extends MMPositionData {
143
143
  collRatio: string,
144
144
  // Safety ratio as evaluated by automation bots (LTV-0 collateral credited at LLTV - 5%). Aave v3 only.
145
145
  safetyRatioWithLtvZeroFallback?: string,
146
+ // Normalised safety ratio (100 = liquidation on every protocol). Aave v3: the LTV-0 fallback ratio, Aave v2: `ratio`.
147
+ safetyRatio?: string,
146
148
  suppliedUsd: string,
147
149
  borrowedUsd: string,
148
150
  borrowLimitUsd: string,
@@ -177,6 +179,7 @@ export interface AaveV3AggregatedPositionData {
177
179
  collRatio: string,
178
180
  borrowLimitWithLtvZeroFallbackUsd: string,
179
181
  safetyRatioWithLtvZeroFallback: string,
182
+ safetyRatio: string,
180
183
  netApy: string,
181
184
  incentiveUsd: string,
182
185
  totalInterestUsd: string,
@@ -183,6 +183,7 @@ export interface AaveV4AggregatedPositionData {
183
183
  leftToBorrowUsd: string,
184
184
  ratio: string,
185
185
  collRatio: string,
186
+ safetyRatio: string,
186
187
  liqRatio: string,
187
188
  liqPercent: string,
188
189
  leveragedType: LeverageType,
@@ -112,6 +112,7 @@ export interface CompoundAggregatedPositionData {
112
112
  leftToBorrowUsd: string,
113
113
  ratio: string,
114
114
  collRatio: string,
115
+ safetyRatio: string,
115
116
  netApy: string,
116
117
  incentiveUsd: string,
117
118
  totalInterestUsd: string,
@@ -132,6 +133,7 @@ export interface CompoundAggregatedPositionData {
132
133
  export interface CompoundPositionData extends MMPositionData {
133
134
  ratio: string,
134
135
  minRatio: string,
136
+ safetyRatio?: string,
135
137
  suppliedUsd: string,
136
138
  borrowedUsd: string,
137
139
  borrowLimitUsd: string,
@@ -344,6 +344,7 @@ export interface FluidAggregatedVaultData {
344
344
  merklBorrowIncentives: IncentiveData[],
345
345
  ratio: string,
346
346
  collRatio: string,
347
+ safetyRatio: string,
347
348
  minRatio: string,
348
349
  totalInterestUsd: string,
349
350
  leveragedType?: LeverageType,
@@ -26,6 +26,8 @@ export interface LiquityTroveInfo {
26
26
  totalETH: string,
27
27
  totalLUSD: string,
28
28
  minCollateralRatio: number,
29
+ // Collateral ratio rebased so 100 sits on `minCollateralRatio` (normalised safety ratio).
30
+ safetyRatio: string,
29
31
  priceForRecovery: string,
30
32
  debtInFront: string,
31
33
  exposure: string,
@@ -104,6 +104,7 @@ export interface LiquityV2AggregatedTroveData {
104
104
  liquidationPrice: string,
105
105
  ratio: string,
106
106
  collRatio: string,
107
+ safetyRatio: string,
107
108
  exposure: string,
108
109
  }
109
110
 
@@ -112,6 +113,7 @@ export interface LiquityV2TroveData {
112
113
  troveId: string,
113
114
  ratio: string,
114
115
  collRatio: string,
116
+ safetyRatio?: string,
115
117
  liqRatio: string,
116
118
  borrowLimitRatio: string,
117
119
  interestRate: string,
@@ -47,6 +47,8 @@ export interface CdpData {
47
47
  debtAssetMarketPrice: string,
48
48
  liquidationPrice: string,
49
49
  ratio: string,
50
+ // Collateral ratio rebased so 100 sits on `liqPercent` (normalised safety ratio).
51
+ safetyRatio: string,
50
52
  liqRatio: string,
51
53
  liqPercent: number,
52
54
  assetPrice: string,
@@ -206,6 +206,7 @@ export interface MorphoBlueAggregatedPositionData {
206
206
  totalInterestUsd: string,
207
207
  ltv: string,
208
208
  ratio: string,
209
+ safetyRatio: string, // borrowLimitUsd / borrowedUsd as a percentage (100 = liquidation)
209
210
  leveragedType: LeverageType,
210
211
  leveragedAsset?: string,
211
212
  currentVolatilePairRatio?: string,
@@ -229,6 +230,7 @@ export interface MorphoBluePositionData {
229
230
  totalInterestUsd: string,
230
231
  ltv: string,
231
232
  ratio: string,
233
+ safetyRatio?: string,
232
234
  leveragedType: LeverageType,
233
235
  leveragedAsset?: string,
234
236
  currentVolatilePairRatio?: string,
@@ -190,6 +190,7 @@ export interface MorphoMidnightAggregatedPositionData {
190
190
  ltv: string,
191
191
  ratio: string, // health ratio as a percentage (from MidnightView.ratio, 1e18-scaled)
192
192
  healthRatio: string, // liquidationLimitUsd / borrowedUsd
193
+ safetyRatio: string, // borrowLimitUsd / borrowedUsd as a percentage (100 = liquidation)
193
194
  leveragedType: LeverageType,
194
195
  leveragedAsset?: string,
195
196
  currentVolatilePairRatio?: string,
@@ -99,6 +99,7 @@ export interface SparkAggregatedPositionData {
99
99
  leftToBorrowUsd: string,
100
100
  ratio: string,
101
101
  collRatio: string,
102
+ safetyRatio: string,
102
103
  netApy: string,
103
104
  incentiveUsd: string,
104
105
  totalInterestUsd: string,
@@ -119,6 +120,7 @@ export interface SparkPositionData extends MMPositionData {
119
120
  ratio: string,
120
121
  minRatio: string,
121
122
  collRatio: string,
123
+ safetyRatio?: string,
122
124
  suppliedUsd: string,
123
125
  borrowedUsd: string,
124
126
  borrowLimitUsd: string,