@gearbox-protocol/sdk 3.0.0-next.14 → 3.0.0-next.15
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.
- package/lib/apy/index.d.ts +2 -2
- package/lib/core/assets.d.ts +2 -2
- package/lib/core/assets.js +2 -2
- package/lib/core/creditAccount.d.ts +22 -4
- package/lib/core/creditAccount.js +67 -23
- package/lib/core/creditAccount.spec.js +469 -8
- package/lib/core/creditManager.d.ts +1 -1
- package/lib/core/creditManager.js +2 -2
- package/lib/utils/math.d.ts +2 -0
- package/lib/utils/math.js +2 -0
- package/package.json +1 -1
package/lib/apy/index.d.ts
CHANGED
|
@@ -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 =
|
|
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";
|
package/lib/core/assets.d.ts
CHANGED
|
@@ -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
|
-
*
|
|
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
|
}
|
package/lib/core/assets.js
CHANGED
|
@@ -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
|
-
*
|
|
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,39 @@
|
|
|
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
|
-
|
|
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
|
+
}
|
|
21
37
|
export declare class CreditAccountData {
|
|
22
38
|
readonly addr: string;
|
|
23
39
|
readonly borrower: string;
|
|
@@ -62,8 +78,10 @@ export declare class CreditAccountData {
|
|
|
62
78
|
isTokenEnabled(index: number): boolean;
|
|
63
79
|
static isTokenEnabled(index: number, enabledTokenMask: bigint): boolean;
|
|
64
80
|
static calcMaxDebtIncrease(healthFactor: number, borrowAmountPlusInterest: bigint, underlyingLT: number, minHf?: number): bigint;
|
|
65
|
-
static calcOverallAPY({ caAssets, lpAPY, prices, totalValue, debt,
|
|
81
|
+
static calcOverallAPY({ caAssets, lpAPY, prices, quotas, quotaRates, totalValue, debt, baseBorrowRate, underlyingToken, }: CalcOverallAPYProps): number | undefined;
|
|
66
82
|
hash(): string;
|
|
67
83
|
static hash(creditManager: string, borrower: string): string;
|
|
68
|
-
static calcHealthFactor({ assets,
|
|
84
|
+
static calcHealthFactor({ assets, quotas, liquidationThresholds, underlyingToken, borrowed, prices, }: CalcHealthFactorProps): number;
|
|
85
|
+
static calcQuotaUpdate({ quotas, initialQuotas, assetsAfterUpdate, allowedToSpend, allowedToObtain, }: CalcQuotaUpdateProps): CalcQuotaUpdateReturnType;
|
|
69
86
|
}
|
|
87
|
+
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
|
|
149
|
+
return math_1.BigIntMath.max(0n, result);
|
|
150
150
|
}
|
|
151
|
-
static calcOverallAPY({ caAssets, lpAPY, prices, totalValue, debt,
|
|
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
|
-
|
|
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(
|
|
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,64 @@ class CreditAccountData {
|
|
|
188
190
|
static hash(creditManager, borrower) {
|
|
189
191
|
return `${creditManager.toLowerCase()}:${borrower.toLowerCase()}`;
|
|
190
192
|
}
|
|
191
|
-
static calcHealthFactor({ assets,
|
|
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
|
|
194
|
-
const
|
|
195
|
-
const
|
|
196
|
-
const
|
|
197
|
-
const
|
|
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
|
|
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
|
+
}
|
|
208
252
|
}
|
|
209
253
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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("
|
|
157
|
-
it("health factor
|
|
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,386 @@ 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
|
+
});
|
|
251
712
|
});
|
|
@@ -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
|
|
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
|
-
|
|
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.
|
|
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);
|
package/lib/utils/math.d.ts
CHANGED
|
@@ -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;
|