@gearbox-protocol/sdk 3.0.0-next.14 → 3.0.0-next.16

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.
@@ -1,8 +1,8 @@
1
- import { LPTokens, SupportedToken } from "@gearbox-protocol/sdk-gov";
1
+ import { LPTokens, PartialRecord, SupportedToken } from "@gearbox-protocol/sdk-gov";
2
2
  export type AdditionalTokenWithAPY = Extract<SupportedToken, "STETH">;
3
3
  export declare const additionalTokensWIthAPY: Record<AdditionalTokenWithAPY, true>;
4
4
  export type TokensWithAPY = LPTokens | Extract<SupportedToken, "STETH">;
5
- export type LpTokensAPY = Record<TokensWithAPY, number>;
5
+ export type LpTokensAPY = PartialRecord<TokensWithAPY, number>;
6
6
  export declare const isTokenWithAPY: (t: unknown) => t is TokensWithAPY;
7
7
  export * from "./convexAPY";
8
8
  export * from "./curveAPY";
@@ -24,12 +24,12 @@ export declare class AssetUtils {
24
24
  static memoWrap: (unwrappedAddress: string, wrappedAddress: string, prices: Record<string, bigint>, tokensList: Record<string, TokenData>) => (assets: Array<Asset>) => WrapResult;
25
25
  /**
26
26
  * Sums the the second assets list into the first assets list
27
- * Creates new assets.
27
+ * Balances cant be negative; Creates new assets.
28
28
  */
29
29
  static sumAssets<A extends Asset, B extends Asset>(a: Array<A>, b: Array<B>): Array<A | B>;
30
30
  /**
31
31
  * Subtracts the the second assets list from the first assets list
32
- * Balance cant be negative; doesn't create new assets.
32
+ * Balances cant be negative; doesn't create new assets.
33
33
  */
34
34
  static subAssets<A extends Asset, B extends Asset>(a: Array<A>, b: Array<B>): Array<A>;
35
35
  }
@@ -65,7 +65,7 @@ class AssetUtils {
65
65
  };
66
66
  /**
67
67
  * Sums the the second assets list into the first assets list
68
- * Creates new assets.
68
+ * Balances cant be negative; Creates new assets.
69
69
  */
70
70
  static sumAssets(a, b) {
71
71
  const aRecord = AssetUtils.constructAssetRecord(a);
@@ -84,7 +84,7 @@ class AssetUtils {
84
84
  }
85
85
  /**
86
86
  * Subtracts the the second assets list from the first assets list
87
- * Balance cant be negative; doesn't create new assets.
87
+ * Balances cant be negative; doesn't create new assets.
88
88
  */
89
89
  static subAssets(a, b) {
90
90
  const bRecord = AssetUtils.constructAssetRecord(b);
@@ -1,23 +1,44 @@
1
1
  import { LpTokensAPY } from "../apy";
2
2
  import { CaTokenBalance, CreditAccountDataPayload, ScheduledWithdrawal } from "../payload/creditAccount";
3
+ import { QuotaInfo } from "../payload/creditManager";
3
4
  import { TokenData } from "../tokens/tokenData";
4
- import { Asset } from "./assets";
5
+ import { Asset, AssetWithAmountInTarget } from "./assets";
5
6
  export interface CalcOverallAPYProps {
6
7
  caAssets: Array<Asset>;
7
8
  lpAPY: LpTokensAPY | undefined;
9
+ quotas: Record<string, Asset>;
10
+ quotaRates: Record<string, Pick<QuotaInfo, "rate">>;
8
11
  prices: Record<string, bigint>;
9
12
  totalValue: bigint | undefined;
10
13
  debt: bigint | undefined;
11
- borrowRate: number;
14
+ baseBorrowRate: number;
12
15
  underlyingToken: string;
13
16
  }
14
17
  export interface CalcHealthFactorProps {
15
18
  assets: Array<Asset>;
19
+ quotas: Record<string, Asset>;
16
20
  prices: Record<string, bigint>;
17
21
  liquidationThresholds: Record<string, bigint>;
18
22
  underlyingToken: string;
19
23
  borrowed: bigint;
20
24
  }
25
+ export interface CalcQuotaUpdateProps {
26
+ quotas: Record<string, Pick<QuotaInfo, "isActive" | "token">>;
27
+ initialQuotas: Record<string, Pick<CaTokenBalance, "quota">>;
28
+ assetsAfterUpdate: Record<string, AssetWithAmountInTarget>;
29
+ allowedToSpend: Record<string, {}>;
30
+ allowedToObtain: Record<string, {}>;
31
+ }
32
+ interface CalcQuotaUpdateReturnType {
33
+ desiredQuota: Record<string, Asset>;
34
+ quotaIncrease: Array<Asset>;
35
+ quotaDecrease: Array<Asset>;
36
+ }
37
+ export interface CalcQuotaBorrowRateProps {
38
+ quotas: Record<string, Asset>;
39
+ quotaRates: Record<string, Pick<QuotaInfo, "rate">>;
40
+ borrowAmount: bigint;
41
+ }
21
42
  export declare class CreditAccountData {
22
43
  readonly addr: string;
23
44
  readonly borrower: string;
@@ -62,8 +83,11 @@ export declare class CreditAccountData {
62
83
  isTokenEnabled(index: number): boolean;
63
84
  static isTokenEnabled(index: number, enabledTokenMask: bigint): boolean;
64
85
  static calcMaxDebtIncrease(healthFactor: number, borrowAmountPlusInterest: bigint, underlyingLT: number, minHf?: number): bigint;
65
- static calcOverallAPY({ caAssets, lpAPY, prices, totalValue, debt, borrowRate, underlyingToken, }: CalcOverallAPYProps): number | undefined;
86
+ static calcOverallAPY({ caAssets, lpAPY, prices, quotas, quotaRates, totalValue, debt, baseBorrowRate, underlyingToken, }: CalcOverallAPYProps): number | undefined;
66
87
  hash(): string;
67
88
  static hash(creditManager: string, borrower: string): string;
68
- static calcHealthFactor({ assets, prices, liquidationThresholds, underlyingToken, borrowed, }: CalcHealthFactorProps): number;
89
+ static calcHealthFactor({ assets, quotas, liquidationThresholds, underlyingToken, borrowed, prices, }: CalcHealthFactorProps): number;
90
+ static calcQuotaUpdate({ quotas, initialQuotas, assetsAfterUpdate, allowedToSpend, allowedToObtain, }: CalcQuotaUpdateProps): CalcQuotaUpdateReturnType;
91
+ static calcQuotaBorrowRate({ quotas, quotaRates, borrowAmount, }: CalcQuotaBorrowRateProps): number;
69
92
  }
93
+ export {};
@@ -2,8 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CreditAccountData = void 0;
4
4
  const sdk_gov_1 = require("@gearbox-protocol/sdk-gov");
5
- const apy_1 = require("../apy");
6
5
  const formatter_1 = require("../utils/formatter");
6
+ const math_1 = require("../utils/math");
7
7
  const price_1 = require("../utils/price");
8
8
  class CreditAccountData {
9
9
  addr;
@@ -146,36 +146,38 @@ class CreditAccountData {
146
146
  static calcMaxDebtIncrease(healthFactor, borrowAmountPlusInterest, underlyingLT, minHf = Number(sdk_gov_1.PERCENTAGE_FACTOR)) {
147
147
  const result = (borrowAmountPlusInterest * BigInt(healthFactor - minHf)) /
148
148
  BigInt(minHf - underlyingLT);
149
- return result < 0 ? 0n : result;
149
+ return math_1.BigIntMath.max(0n, result);
150
150
  }
151
- static calcOverallAPY({ caAssets, lpAPY, prices, totalValue, debt, borrowRate, underlyingToken, }) {
151
+ static calcOverallAPY({ caAssets, lpAPY, prices, quotas, quotaRates, totalValue, debt, baseBorrowRate, underlyingToken, }) {
152
152
  if (!lpAPY ||
153
153
  !totalValue ||
154
154
  totalValue <= 0n ||
155
155
  !debt ||
156
156
  totalValue <= debt)
157
157
  return undefined;
158
+ const underlyingTokenAddressLC = underlyingToken.toLowerCase();
159
+ const underlyingTokenSymbol = sdk_gov_1.tokenSymbolByAddress[underlyingTokenAddressLC] || "";
160
+ const underlyingTokenDecimals = sdk_gov_1.decimals[underlyingTokenSymbol] || 18;
161
+ const underlyingPrice = prices[underlyingTokenAddressLC];
158
162
  const assetAPYMoney = caAssets.reduce((acc, { token: tokenAddress, balance: amount }) => {
159
163
  const tokenAddressLC = tokenAddress.toLowerCase();
160
- const symbol = sdk_gov_1.tokenSymbolByAddress[tokenAddressLC];
161
- if (!(0, apy_1.isTokenWithAPY)(symbol))
162
- return acc;
164
+ const symbol = sdk_gov_1.tokenSymbolByAddress[tokenAddressLC] || "";
163
165
  const apy = lpAPY[symbol] || 0;
164
166
  const price = prices[tokenAddressLC] || 0n;
165
167
  const tokenDecimals = sdk_gov_1.decimals[symbol];
166
168
  const money = price_1.PriceUtils.calcTotalPrice(price, amount, tokenDecimals);
167
169
  const apyMoney = money * BigInt(apy);
168
- return acc + apyMoney;
170
+ const { balance: quotaAmount = 0n } = quotas[tokenAddressLC] || {};
171
+ const quotaMoney = price_1.PriceUtils.calcTotalPrice(underlyingPrice || 0n, quotaAmount, underlyingTokenDecimals);
172
+ const { rate: quotaAPY = 0 } = quotaRates[tokenAddressLC] || {};
173
+ const quotaAPYMoney = quotaMoney * BigInt(quotaAPY);
174
+ return acc + apyMoney - quotaAPYMoney;
169
175
  }, 0n);
170
- const underlyingTokenAddressLC = underlyingToken.toLowerCase();
171
- const underlyingTokenSymbol = sdk_gov_1.tokenSymbolByAddress[underlyingTokenAddressLC] || "";
172
- const underlyingTokenDecimals = sdk_gov_1.decimals[underlyingTokenSymbol] || 18;
173
- const underlyingPrice = prices[underlyingTokenAddressLC] || sdk_gov_1.PRICE_DECIMALS;
174
176
  const assetAPYAmountInUnderlying = price_1.PriceUtils.convertByPrice(assetAPYMoney, {
175
- price: underlyingPrice,
177
+ price: underlyingPrice || sdk_gov_1.PRICE_DECIMALS,
176
178
  decimals: underlyingTokenDecimals,
177
179
  });
178
- const debtAPY = debt * BigInt(borrowRate);
180
+ const debtAPY = debt * BigInt(baseBorrowRate);
179
181
  const yourAssets = totalValue - debt;
180
182
  const apyInPercent = ((assetAPYAmountInUnderlying - debtAPY) * sdk_gov_1.WAD) /
181
183
  yourAssets /
@@ -188,22 +190,75 @@ class CreditAccountData {
188
190
  static hash(creditManager, borrower) {
189
191
  return `${creditManager.toLowerCase()}:${borrower.toLowerCase()}`;
190
192
  }
191
- static calcHealthFactor({ assets, prices, liquidationThresholds, underlyingToken, borrowed, }) {
193
+ static calcHealthFactor({ assets, quotas, liquidationThresholds, underlyingToken, borrowed, prices, }) {
194
+ const [, underlyingDecimals] = (0, sdk_gov_1.extractTokenData)(underlyingToken);
195
+ const underlyingPrice = prices[underlyingToken];
192
196
  const assetLTMoney = assets.reduce((acc, { token: tokenAddress, balance: amount }) => {
193
- const tokenSymbol = sdk_gov_1.tokenSymbolByAddress[tokenAddress.toLowerCase()];
194
- const tokenDecimals = sdk_gov_1.decimals[tokenSymbol];
195
- const lt = liquidationThresholds[tokenAddress.toLowerCase()] || 0n;
196
- const price = prices[tokenAddress.toLowerCase()] || 0n;
197
- const money = price_1.PriceUtils.calcTotalPrice(price, amount, tokenDecimals);
197
+ const [, tokenDecimals] = (0, sdk_gov_1.extractTokenData)(tokenAddress);
198
+ const lt = liquidationThresholds[tokenAddress] || 0n;
199
+ const price = prices[tokenAddress] || 0n;
200
+ const tokenMoney = price_1.PriceUtils.calcTotalPrice(price, amount, tokenDecimals);
201
+ const quota = quotas[tokenAddress];
202
+ const quotaMoney = price_1.PriceUtils.calcTotalPrice(underlyingPrice, quota?.balance || 0n, underlyingDecimals);
203
+ // if quota is undefined, then it is not a quoted token
204
+ const money = quota
205
+ ? math_1.BigIntMath.min(quotaMoney, tokenMoney)
206
+ : tokenMoney;
198
207
  const ltMoney = money * lt;
199
208
  return acc + ltMoney;
200
209
  }, 0n);
201
- const underlyingSymbol = sdk_gov_1.tokenSymbolByAddress[underlyingToken.toLowerCase()];
202
- const underlyingDecimals = sdk_gov_1.decimals[underlyingSymbol];
203
- const underlyingPrice = prices[underlyingToken.toLowerCase()] || sdk_gov_1.PRICE_DECIMALS;
204
- const borrowedMoney = price_1.PriceUtils.calcTotalPrice(underlyingPrice, borrowed, underlyingDecimals);
210
+ const borrowedMoney = price_1.PriceUtils.calcTotalPrice(underlyingPrice || sdk_gov_1.PRICE_DECIMALS, borrowed, underlyingDecimals);
205
211
  const hfInPercent = borrowedMoney > 0n ? assetLTMoney / borrowedMoney : 0n;
206
212
  return Number(hfInPercent);
207
213
  }
214
+ static calcQuotaUpdate({ quotas, initialQuotas, assetsAfterUpdate, allowedToSpend, allowedToObtain, }) {
215
+ const r = Object.values(quotas).reduce((acc, cmQuota) => {
216
+ const { token } = cmQuota;
217
+ const { quota: initialQuota = 0n } = initialQuotas[token] || {};
218
+ const after = assetsAfterUpdate[token];
219
+ const { amountInTarget = 0n } = after || {};
220
+ const desiredQuota = (amountInTarget * 101n) / 100n;
221
+ const quotaChange = desiredQuota - initialQuota;
222
+ const correctIncrease = after && allowedToObtain[token] && quotaChange > 0;
223
+ const correctDecrease = after && allowedToSpend[token] && quotaChange < 0;
224
+ if (correctIncrease || correctDecrease) {
225
+ acc.desiredQuota[token] = {
226
+ balance: desiredQuota,
227
+ token,
228
+ };
229
+ }
230
+ else {
231
+ acc.desiredQuota[token] = {
232
+ balance: initialQuota,
233
+ token,
234
+ };
235
+ }
236
+ if (correctIncrease) {
237
+ acc.quotaIncrease.push({
238
+ balance: quotaChange,
239
+ token,
240
+ });
241
+ }
242
+ if (correctDecrease) {
243
+ acc.quotaDecrease.push({
244
+ balance: quotaChange,
245
+ token,
246
+ });
247
+ }
248
+ return acc;
249
+ }, { desiredQuota: {}, quotaIncrease: [], quotaDecrease: [] });
250
+ return r;
251
+ }
252
+ static calcQuotaBorrowRate({ quotas, quotaRates, borrowAmount, }) {
253
+ if (borrowAmount <= 0)
254
+ return 0;
255
+ const totalRateBalance = Object.values(quotas).reduce((acc, { token, balance }) => {
256
+ const { rate = 0 } = quotaRates[token] || {};
257
+ const rateBalance = balance * BigInt(rate);
258
+ return acc + rateBalance;
259
+ }, 0n);
260
+ const quotaBorrowRate = Number(totalRateBalance / borrowAmount);
261
+ return quotaBorrowRate;
262
+ }
208
263
  }
209
264
  exports.CreditAccountData = CreditAccountData;
@@ -27,6 +27,17 @@ const caWithoutLP = {
27
27
  debt: (0, formatter_1.toBN)("54780", sdk_gov_1.decimals.DAI),
28
28
  borrowRate: 7712,
29
29
  underlyingToken: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI.toLowerCase(),
30
+ quotas: {
31
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH.toLowerCase()]: {
32
+ balance: (0, formatter_1.toBN)("173811.830000", sdk_gov_1.decimals.WETH),
33
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI.toLowerCase(),
34
+ },
35
+ },
36
+ rates: {
37
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH.toLowerCase()]: {
38
+ rate: 38434,
39
+ },
40
+ },
30
41
  };
31
42
  const caWithLP = {
32
43
  assets: [
@@ -43,6 +54,17 @@ const caWithLP = {
43
54
  debt: (0, formatter_1.toBN)("90.000000000000000000", sdk_gov_1.decimals.WETH),
44
55
  borrowRate: 5736,
45
56
  underlyingToken: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH.toLowerCase(),
57
+ quotas: {
58
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.STETH.toLowerCase()]: {
59
+ balance: (0, formatter_1.toBN)(String((1703.87588096 * 119.9999999999999) / 1738.1183), sdk_gov_1.decimals.WETH),
60
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.STETH.toLowerCase(),
61
+ },
62
+ },
63
+ rates: {
64
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.STETH.toLowerCase()]: {
65
+ rate: 38434,
66
+ },
67
+ },
46
68
  };
47
69
  describe("CreditAccount CreditAccountData.calcOverallAPY test", () => {
48
70
  it("overall APY calculation for caWithoutLP is correct", () => {
@@ -50,8 +72,10 @@ describe("CreditAccount CreditAccountData.calcOverallAPY test", () => {
50
72
  caAssets: caWithoutLP.assets,
51
73
  totalValue: caWithoutLP.totalValue,
52
74
  debt: caWithoutLP.debt,
53
- borrowRate: caWithoutLP.borrowRate,
75
+ baseBorrowRate: caWithoutLP.borrowRate,
54
76
  underlyingToken: caWithoutLP.underlyingToken,
77
+ quotaRates: {},
78
+ quotas: {},
55
79
  lpAPY,
56
80
  prices,
57
81
  });
@@ -62,8 +86,10 @@ describe("CreditAccount CreditAccountData.calcOverallAPY test", () => {
62
86
  caAssets: caWithLP.assets,
63
87
  totalValue: caWithLP.totalValue,
64
88
  debt: caWithLP.debt,
65
- borrowRate: caWithLP.borrowRate,
89
+ baseBorrowRate: caWithLP.borrowRate,
66
90
  underlyingToken: caWithLP.underlyingToken,
91
+ quotaRates: {},
92
+ quotas: {},
67
93
  lpAPY,
68
94
  prices,
69
95
  });
@@ -74,8 +100,10 @@ describe("CreditAccount CreditAccountData.calcOverallAPY test", () => {
74
100
  caAssets: caWithLP.assets,
75
101
  totalValue: caWithLP.totalValue,
76
102
  debt: caWithLP.debt,
77
- borrowRate: caWithLP.borrowRate,
103
+ baseBorrowRate: caWithLP.borrowRate,
78
104
  underlyingToken: caWithLP.underlyingToken,
105
+ quotaRates: {},
106
+ quotas: {},
79
107
  lpAPY: undefined,
80
108
  prices,
81
109
  });
@@ -86,8 +114,10 @@ describe("CreditAccount CreditAccountData.calcOverallAPY test", () => {
86
114
  caAssets: caWithLP.assets,
87
115
  totalValue: undefined,
88
116
  debt: caWithLP.debt,
89
- borrowRate: caWithLP.borrowRate,
117
+ baseBorrowRate: caWithLP.borrowRate,
90
118
  underlyingToken: caWithLP.underlyingToken,
119
+ quotaRates: {},
120
+ quotas: {},
91
121
  lpAPY,
92
122
  prices,
93
123
  });
@@ -98,8 +128,10 @@ describe("CreditAccount CreditAccountData.calcOverallAPY test", () => {
98
128
  caAssets: caWithLP.assets,
99
129
  totalValue: caWithLP.totalValue,
100
130
  debt: undefined,
101
- borrowRate: caWithLP.borrowRate,
131
+ baseBorrowRate: caWithLP.borrowRate,
102
132
  underlyingToken: caWithLP.underlyingToken,
133
+ quotaRates: {},
134
+ quotas: {},
103
135
  lpAPY,
104
136
  prices,
105
137
  });
@@ -110,13 +142,48 @@ describe("CreditAccount CreditAccountData.calcOverallAPY test", () => {
110
142
  caAssets: caWithLP.assets,
111
143
  totalValue: 0n,
112
144
  debt: undefined,
113
- borrowRate: caWithLP.borrowRate,
145
+ baseBorrowRate: caWithLP.borrowRate,
114
146
  underlyingToken: caWithLP.underlyingToken,
147
+ quotaRates: {},
148
+ quotas: {},
115
149
  lpAPY,
116
150
  prices,
117
151
  });
118
152
  (0, chai_1.expect)(result).to.be.eq(undefined);
119
153
  });
154
+ it("overall APY calculation for caWithLP with sufficient quota is correct", () => {
155
+ const result = creditAccount_1.CreditAccountData.calcOverallAPY({
156
+ caAssets: caWithLP.assets,
157
+ totalValue: caWithLP.totalValue,
158
+ debt: caWithLP.debt,
159
+ baseBorrowRate: caWithLP.borrowRate,
160
+ underlyingToken: caWithLP.underlyingToken,
161
+ quotaRates: caWithLP.rates,
162
+ quotas: caWithLP.quotas,
163
+ lpAPY,
164
+ prices,
165
+ });
166
+ (0, chai_1.expect)(result).to.be.eq(-1.86801);
167
+ });
168
+ it("overall APY calculation for caWithLP with insufficient quota is correct", () => {
169
+ const result = creditAccount_1.CreditAccountData.calcOverallAPY({
170
+ caAssets: caWithLP.assets,
171
+ totalValue: caWithLP.totalValue,
172
+ debt: caWithLP.debt,
173
+ baseBorrowRate: caWithLP.borrowRate,
174
+ underlyingToken: caWithLP.underlyingToken,
175
+ quotaRates: caWithLP.rates,
176
+ quotas: {
177
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.STETH.toLowerCase()]: {
178
+ balance: 0n,
179
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.STETH.toLowerCase(),
180
+ },
181
+ },
182
+ lpAPY,
183
+ prices,
184
+ });
185
+ (0, chai_1.expect)(result).to.be.eq(14.4919);
186
+ });
120
187
  });
121
188
  describe("CreditAccount calcMaxIncreaseBorrow test", () => {
122
189
  it("health max increase borrow is zero if hf < 1", () => {
@@ -152,10 +219,17 @@ const defaultCA = {
152
219
  healthFactor: 10244,
153
220
  underlyingToken: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI.toLowerCase(),
154
221
  underlyingDecimals: sdk_gov_1.decimals.DAI,
222
+ quotas: {
223
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH.toLowerCase()]: {
224
+ balance: (0, formatter_1.toBN)(String(1750 * 10), sdk_gov_1.decimals.DAI),
225
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH.toLowerCase(),
226
+ },
227
+ },
155
228
  };
156
- describe("CreditManager calcHealthFactor test", () => {
157
- it("health factor calculation is calculated correctly", () => {
229
+ describe("CreditAccount calcHealthFactor test", () => {
230
+ it("health factor is calculated correctly", () => {
158
231
  const result = creditAccount_1.CreditAccountData.calcHealthFactor({
232
+ quotas: {},
159
233
  assets: defaultCA.assets,
160
234
  prices,
161
235
  liquidationThresholds,
@@ -166,6 +240,7 @@ describe("CreditManager calcHealthFactor test", () => {
166
240
  });
167
241
  it("health factor calculation has no division by zero error", () => {
168
242
  const result = creditAccount_1.CreditAccountData.calcHealthFactor({
243
+ quotas: {},
169
244
  assets: [],
170
245
  prices: {},
171
246
  liquidationThresholds: {},
@@ -181,6 +256,7 @@ describe("CreditManager calcHealthFactor test", () => {
181
256
  };
182
257
  const afterAdd = assets_1.AssetUtils.sumAssets(defaultCA.assets, [collateral]);
183
258
  const result = creditAccount_1.CreditAccountData.calcHealthFactor({
259
+ quotas: {},
184
260
  assets: afterAdd,
185
261
  prices,
186
262
  liquidationThresholds,
@@ -199,6 +275,7 @@ describe("CreditManager calcHealthFactor test", () => {
199
275
  debtDecrease,
200
276
  ]);
201
277
  const result = creditAccount_1.CreditAccountData.calcHealthFactor({
278
+ quotas: {},
202
279
  assets: afterDecrease,
203
280
  prices,
204
281
  liquidationThresholds,
@@ -217,6 +294,7 @@ describe("CreditManager calcHealthFactor test", () => {
217
294
  debtIncrease,
218
295
  ]);
219
296
  const result = creditAccount_1.CreditAccountData.calcHealthFactor({
297
+ quotas: {},
220
298
  assets: afterIncrease,
221
299
  prices,
222
300
  liquidationThresholds,
@@ -240,6 +318,7 @@ describe("CreditManager calcHealthFactor test", () => {
240
318
  const afterSub = assets_1.AssetUtils.subAssets(defaultCA.assets, [swapAsset]);
241
319
  const afterSwap = assets_1.AssetUtils.sumAssets(afterSub, [getAsset]);
242
320
  const result = creditAccount_1.CreditAccountData.calcHealthFactor({
321
+ quotas: {},
243
322
  assets: afterSwap,
244
323
  prices,
245
324
  liquidationThresholds,
@@ -248,4 +327,481 @@ describe("CreditManager calcHealthFactor test", () => {
248
327
  });
249
328
  (0, chai_1.expect)(result).to.be.eq(9444);
250
329
  });
330
+ it("health factor with sufficient quotas is calculated correctly", () => {
331
+ const result = creditAccount_1.CreditAccountData.calcHealthFactor({
332
+ quotas: defaultCA.quotas,
333
+ assets: defaultCA.assets,
334
+ prices,
335
+ liquidationThresholds,
336
+ underlyingToken: defaultCA.underlyingToken,
337
+ borrowed: defaultCA.debt,
338
+ });
339
+ (0, chai_1.expect)(result).to.be.eq(defaultCA.healthFactor);
340
+ });
341
+ it("health factor with insufficient quotas is calculated correctly", () => {
342
+ const result = creditAccount_1.CreditAccountData.calcHealthFactor({
343
+ quotas: {
344
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH.toLowerCase()]: {
345
+ balance: 0n,
346
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH.toLowerCase(),
347
+ },
348
+ },
349
+ assets: defaultCA.assets,
350
+ prices,
351
+ liquidationThresholds,
352
+ underlyingToken: defaultCA.underlyingToken,
353
+ borrowed: defaultCA.debt,
354
+ });
355
+ (0, chai_1.expect)(result).to.be.eq(9300);
356
+ });
357
+ });
358
+ const cmQuotas = {
359
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {
360
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI,
361
+ isActive: true,
362
+ },
363
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {
364
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
365
+ isActive: true,
366
+ },
367
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.STETH]: {
368
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.STETH,
369
+ isActive: true,
370
+ },
371
+ };
372
+ const caQuota = {
373
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {
374
+ quota: 5n,
375
+ },
376
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {
377
+ quota: 10n,
378
+ },
379
+ };
380
+ describe("CreditAccount calcQuotaUpdate test", () => {
381
+ it("open account should buy quota", () => {
382
+ const result = creditAccount_1.CreditAccountData.calcQuotaUpdate({
383
+ quotas: cmQuotas,
384
+ initialQuotas: {},
385
+ assetsAfterUpdate: {
386
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {
387
+ amountInTarget: 10n,
388
+ balance: 0n,
389
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI,
390
+ },
391
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {
392
+ amountInTarget: 20n,
393
+ balance: 0n,
394
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
395
+ },
396
+ },
397
+ allowedToObtain: {
398
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {},
399
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {},
400
+ },
401
+ allowedToSpend: {},
402
+ });
403
+ (0, chai_1.expect)(result.quotaIncrease).to.be.deep.eq([
404
+ {
405
+ balance: 10n,
406
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI,
407
+ },
408
+ {
409
+ balance: 20n,
410
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
411
+ },
412
+ ]);
413
+ (0, chai_1.expect)(result.quotaDecrease).to.be.deep.eq([]);
414
+ (0, chai_1.expect)(result.desiredQuota).to.be.deep.eq({
415
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {
416
+ balance: 10n,
417
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI,
418
+ },
419
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {
420
+ balance: 20n,
421
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
422
+ },
423
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.STETH]: {
424
+ balance: 0n,
425
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.STETH,
426
+ },
427
+ });
428
+ });
429
+ it("add collateral should buy quota", () => {
430
+ const result = creditAccount_1.CreditAccountData.calcQuotaUpdate({
431
+ quotas: cmQuotas,
432
+ initialQuotas: caQuota,
433
+ assetsAfterUpdate: {
434
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.STETH]: {
435
+ amountInTarget: 10n,
436
+ balance: 0n,
437
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI,
438
+ },
439
+ },
440
+ allowedToObtain: {
441
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.STETH]: {},
442
+ },
443
+ allowedToSpend: {},
444
+ });
445
+ (0, chai_1.expect)(result.quotaIncrease).to.be.deep.eq([
446
+ {
447
+ balance: 10n,
448
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.STETH,
449
+ },
450
+ ]);
451
+ (0, chai_1.expect)(result.quotaDecrease).to.be.deep.eq([]);
452
+ (0, chai_1.expect)(result.desiredQuota).to.be.deep.eq({
453
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {
454
+ balance: 5n,
455
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI,
456
+ },
457
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {
458
+ balance: 10n,
459
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
460
+ },
461
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.STETH]: {
462
+ balance: 10n,
463
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.STETH,
464
+ },
465
+ });
466
+ });
467
+ it("add collateral should add additional quota", () => {
468
+ const result = creditAccount_1.CreditAccountData.calcQuotaUpdate({
469
+ quotas: cmQuotas,
470
+ initialQuotas: caQuota,
471
+ assetsAfterUpdate: {
472
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {
473
+ amountInTarget: 10n,
474
+ balance: 0n,
475
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI,
476
+ },
477
+ },
478
+ allowedToObtain: {
479
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {},
480
+ },
481
+ allowedToSpend: {},
482
+ });
483
+ (0, chai_1.expect)(result.quotaIncrease).to.be.deep.eq([
484
+ {
485
+ balance: 5n,
486
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI,
487
+ },
488
+ ]);
489
+ (0, chai_1.expect)(result.quotaDecrease).to.be.deep.eq([]);
490
+ (0, chai_1.expect)(result.desiredQuota).to.be.deep.eq({
491
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {
492
+ balance: 10n,
493
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI,
494
+ },
495
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {
496
+ balance: 10n,
497
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
498
+ },
499
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.STETH]: {
500
+ balance: 0n,
501
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.STETH,
502
+ },
503
+ });
504
+ });
505
+ it("add collateral shouldn't add additional quota", () => {
506
+ const result = creditAccount_1.CreditAccountData.calcQuotaUpdate({
507
+ quotas: cmQuotas,
508
+ initialQuotas: caQuota,
509
+ assetsAfterUpdate: {
510
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {
511
+ amountInTarget: 10n,
512
+ balance: 0n,
513
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
514
+ },
515
+ },
516
+ allowedToObtain: {
517
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {},
518
+ },
519
+ allowedToSpend: {},
520
+ });
521
+ (0, chai_1.expect)(result.quotaIncrease).to.be.deep.eq([]);
522
+ (0, chai_1.expect)(result.quotaDecrease).to.be.deep.eq([]);
523
+ (0, chai_1.expect)(result.desiredQuota).to.be.deep.eq({
524
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {
525
+ balance: 5n,
526
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI,
527
+ },
528
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {
529
+ balance: 10n,
530
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
531
+ },
532
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.STETH]: {
533
+ balance: 0n,
534
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.STETH,
535
+ },
536
+ });
537
+ });
538
+ it("swap should buy quota", () => {
539
+ const result = creditAccount_1.CreditAccountData.calcQuotaUpdate({
540
+ quotas: cmQuotas,
541
+ initialQuotas: caQuota,
542
+ assetsAfterUpdate: {
543
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.STETH]: {
544
+ amountInTarget: 10n,
545
+ balance: 0n,
546
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI,
547
+ },
548
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {
549
+ amountInTarget: 0n,
550
+ balance: 0n,
551
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI,
552
+ },
553
+ },
554
+ allowedToObtain: {
555
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.STETH]: {},
556
+ },
557
+ allowedToSpend: { [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {} },
558
+ });
559
+ (0, chai_1.expect)(result.quotaIncrease).to.be.deep.eq([
560
+ {
561
+ balance: 10n,
562
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.STETH,
563
+ },
564
+ ]);
565
+ (0, chai_1.expect)(result.quotaDecrease).to.be.deep.eq([
566
+ { balance: -10n, token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH },
567
+ ]);
568
+ (0, chai_1.expect)(result.desiredQuota).to.be.deep.eq({
569
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {
570
+ balance: 5n,
571
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI,
572
+ },
573
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {
574
+ balance: 0n,
575
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
576
+ },
577
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.STETH]: {
578
+ balance: 10n,
579
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.STETH,
580
+ },
581
+ });
582
+ });
583
+ it("swap should add additional quota", () => {
584
+ const result = creditAccount_1.CreditAccountData.calcQuotaUpdate({
585
+ quotas: cmQuotas,
586
+ initialQuotas: caQuota,
587
+ assetsAfterUpdate: {
588
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {
589
+ amountInTarget: 10n,
590
+ balance: 0n,
591
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI,
592
+ },
593
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {
594
+ amountInTarget: 0n,
595
+ balance: 0n,
596
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
597
+ },
598
+ },
599
+ allowedToObtain: {
600
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {},
601
+ },
602
+ allowedToSpend: {
603
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {},
604
+ },
605
+ });
606
+ (0, chai_1.expect)(result.quotaIncrease).to.be.deep.eq([
607
+ {
608
+ balance: 5n,
609
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI,
610
+ },
611
+ ]);
612
+ (0, chai_1.expect)(result.quotaDecrease).to.be.deep.eq([
613
+ {
614
+ balance: -10n,
615
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
616
+ },
617
+ ]);
618
+ (0, chai_1.expect)(result.desiredQuota).to.be.deep.eq({
619
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {
620
+ balance: 10n,
621
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI,
622
+ },
623
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {
624
+ balance: 0n,
625
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
626
+ },
627
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.STETH]: {
628
+ balance: 0n,
629
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.STETH,
630
+ },
631
+ });
632
+ });
633
+ it("swap shouldn't add additional quota", () => {
634
+ const result = creditAccount_1.CreditAccountData.calcQuotaUpdate({
635
+ quotas: cmQuotas,
636
+ initialQuotas: caQuota,
637
+ assetsAfterUpdate: {
638
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {
639
+ amountInTarget: 10n,
640
+ balance: 0n,
641
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
642
+ },
643
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {
644
+ amountInTarget: 0n,
645
+ balance: 0n,
646
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI,
647
+ },
648
+ },
649
+ allowedToObtain: {
650
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {},
651
+ },
652
+ allowedToSpend: { [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {} },
653
+ });
654
+ (0, chai_1.expect)(result.quotaIncrease).to.be.deep.eq([]);
655
+ (0, chai_1.expect)(result.quotaDecrease).to.be.deep.eq([
656
+ {
657
+ balance: -5n,
658
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI,
659
+ },
660
+ ]);
661
+ (0, chai_1.expect)(result.desiredQuota).to.be.deep.eq({
662
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {
663
+ balance: 0n,
664
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI,
665
+ },
666
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {
667
+ balance: 10n,
668
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
669
+ },
670
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.STETH]: {
671
+ balance: 0n,
672
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.STETH,
673
+ },
674
+ });
675
+ });
676
+ it("shouldn't change quota if disallowed", () => {
677
+ const result = creditAccount_1.CreditAccountData.calcQuotaUpdate({
678
+ quotas: cmQuotas,
679
+ initialQuotas: caQuota,
680
+ assetsAfterUpdate: {
681
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {
682
+ amountInTarget: 10n,
683
+ balance: 0n,
684
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
685
+ },
686
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {
687
+ amountInTarget: 0n,
688
+ balance: 0n,
689
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI,
690
+ },
691
+ },
692
+ allowedToObtain: {},
693
+ allowedToSpend: {},
694
+ });
695
+ (0, chai_1.expect)(result.quotaIncrease).to.be.deep.eq([]);
696
+ (0, chai_1.expect)(result.quotaDecrease).to.be.deep.eq([]);
697
+ (0, chai_1.expect)(result.desiredQuota).to.be.deep.eq({
698
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {
699
+ balance: 5n,
700
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI,
701
+ },
702
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {
703
+ balance: 10n,
704
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
705
+ },
706
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.STETH]: {
707
+ balance: 0n,
708
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.STETH,
709
+ },
710
+ });
711
+ });
712
+ });
713
+ describe("CreditAccount calcQuotaBorrowRate test", () => {
714
+ it("should calculate quota rate (same amounts, different rates)", () => {
715
+ const result = creditAccount_1.CreditAccountData.calcQuotaBorrowRate({
716
+ quotas: {
717
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {
718
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI,
719
+ balance: 10n,
720
+ },
721
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {
722
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
723
+ balance: 10n,
724
+ },
725
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.STETH]: {
726
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.STETH,
727
+ balance: 10n,
728
+ },
729
+ },
730
+ quotaRates: {
731
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {
732
+ rate: 5,
733
+ },
734
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {
735
+ rate: 10,
736
+ },
737
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.STETH]: {
738
+ rate: 15,
739
+ },
740
+ },
741
+ borrowAmount: 30n,
742
+ });
743
+ (0, chai_1.expect)(result).to.be.eq(10);
744
+ });
745
+ it("should calculate quota rate (same rates, different amounts)", () => {
746
+ const result = creditAccount_1.CreditAccountData.calcQuotaBorrowRate({
747
+ quotas: {
748
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {
749
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI,
750
+ balance: 5n,
751
+ },
752
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {
753
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
754
+ balance: 10n,
755
+ },
756
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.STETH]: {
757
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.STETH,
758
+ balance: 15n,
759
+ },
760
+ },
761
+ quotaRates: {
762
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {
763
+ rate: 10,
764
+ },
765
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {
766
+ rate: 10,
767
+ },
768
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.STETH]: {
769
+ rate: 10,
770
+ },
771
+ },
772
+ borrowAmount: 30n,
773
+ });
774
+ (0, chai_1.expect)(result).to.be.eq(10);
775
+ });
776
+ it("should calculate quota rate (borrow amount)", () => {
777
+ const result = creditAccount_1.CreditAccountData.calcQuotaBorrowRate({
778
+ quotas: {
779
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {
780
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI,
781
+ balance: 5n,
782
+ },
783
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {
784
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
785
+ balance: 10n,
786
+ },
787
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.STETH]: {
788
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.STETH,
789
+ balance: 15n,
790
+ },
791
+ },
792
+ quotaRates: {
793
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {
794
+ rate: 10,
795
+ },
796
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {
797
+ rate: 10,
798
+ },
799
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.STETH]: {
800
+ rate: 10,
801
+ },
802
+ },
803
+ borrowAmount: 60n,
804
+ });
805
+ (0, chai_1.expect)(result).to.be.eq(5);
806
+ });
251
807
  });
@@ -14,7 +14,7 @@ export declare class CreditManagerData {
14
14
  readonly forbiddenTokenMask: bigint;
15
15
  readonly maxEnabledTokensLength: number;
16
16
  readonly name: string;
17
- readonly borrowRate: number;
17
+ readonly baseBorrowRate: number;
18
18
  readonly minDebt: bigint;
19
19
  readonly maxDebt: bigint;
20
20
  readonly availableToBorrow: bigint;
@@ -17,7 +17,7 @@ class CreditManagerData {
17
17
  forbiddenTokenMask; // V2 only: mask which forbids some particular tokens
18
18
  maxEnabledTokensLength;
19
19
  name;
20
- borrowRate;
20
+ baseBorrowRate;
21
21
  minDebt;
22
22
  maxDebt;
23
23
  availableToBorrow;
@@ -47,7 +47,7 @@ class CreditManagerData {
47
47
  this.forbiddenTokenMask = (0, sdk_gov_1.toBigInt)(payload.forbiddenTokenMask);
48
48
  this.maxEnabledTokensLength = payload.maxEnabledTokensLength;
49
49
  this.name = payload.name;
50
- this.borrowRate = Number(((0, sdk_gov_1.toBigInt)(payload.baseBorrowRate) *
50
+ this.baseBorrowRate = Number(((0, sdk_gov_1.toBigInt)(payload.baseBorrowRate) *
51
51
  ((0, sdk_gov_1.toBigInt)(payload.feeInterest) + sdk_gov_1.PERCENTAGE_FACTOR) *
52
52
  sdk_gov_1.PERCENTAGE_DECIMALS) /
53
53
  sdk_gov_1.RAY);
@@ -7,4 +7,6 @@ export declare const nonNegativeBn: (v: bigint) => bigint;
7
7
  export declare class BigIntMath {
8
8
  static abs: (x: bigint) => bigint;
9
9
  static toHexString: (x: bigint) => string;
10
+ static max: (a: bigint, b: bigint) => bigint;
11
+ static min: (a: bigint, b: bigint) => bigint;
10
12
  }
package/lib/utils/math.js CHANGED
@@ -41,5 +41,7 @@ exports.nonNegativeBn = nonNegativeBn;
41
41
  class BigIntMath {
42
42
  static abs = (x) => (x < 0n ? -x : x);
43
43
  static toHexString = (x) => ethers_1.BigNumber.from(x).toHexString();
44
+ static max = (a, b) => (a > b ? a : b);
45
+ static min = (a, b) => (a < b ? a : b);
44
46
  }
45
47
  exports.BigIntMath = BigIntMath;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gearbox-protocol/sdk",
3
- "version": "3.0.0-next.14",
3
+ "version": "3.0.0-next.16",
4
4
  "description": "Gearbox SDK",
5
5
  "main": "./lib/index.js",
6
6
  "types": "./lib/index.d.ts",