@gearbox-protocol/sdk 1.5.30 → 1.6.0
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 +4 -1
- package/lib/apy/index.js +11 -0
- package/lib/core/assets.d.ts +0 -5
- package/lib/core/creditAccount.d.ts +3 -4
- package/lib/core/creditAccount.js +28 -22
- package/lib/core/creditAccount.spec.d.ts +1 -0
- package/lib/core/creditAccount.spec.js +122 -0
- package/lib/core/creditManager.d.ts +2 -4
- package/lib/core/creditManager.js +20 -18
- package/lib/core/creditManager.spec.d.ts +1 -0
- package/lib/core/creditManager.spec.js +144 -0
- package/lib/core/creditSession.js +1 -3
- package/lib/core/strategy.d.ts +3 -5
- package/lib/core/strategy.js +32 -17
- package/lib/core/strategy.spec.d.ts +1 -0
- package/lib/core/strategy.spec.js +76 -0
- package/lib/utils/formatter.d.ts +1 -1
- package/lib/utils/formatter.js +5 -4
- package/package.json +1 -1
package/lib/apy/index.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { LPTokens, SupportedToken } from "../tokens/token";
|
|
2
|
-
export declare type
|
|
2
|
+
export declare type AdditionalTokenWithAPY = Extract<SupportedToken, "STETH">;
|
|
3
|
+
export declare const additionalTokensWIthAPY: Record<AdditionalTokenWithAPY, true>;
|
|
4
|
+
export declare type TokensWithAPY = LPTokens | Extract<SupportedToken, "STETH">;
|
|
3
5
|
export declare type LpTokensAPY = Record<TokensWithAPY, number>;
|
|
6
|
+
export declare const isTokenWithAPY: (t: unknown) => t is TokensWithAPY;
|
|
4
7
|
export * from "./convexAPY";
|
|
5
8
|
export * from "./curveAPY";
|
|
6
9
|
export * from "./lidoAPY";
|
package/lib/apy/index.js
CHANGED
|
@@ -14,6 +14,17 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.isTokenWithAPY = exports.additionalTokensWIthAPY = void 0;
|
|
18
|
+
var token_1 = require("../tokens/token");
|
|
19
|
+
exports.additionalTokensWIthAPY = {
|
|
20
|
+
STETH: true,
|
|
21
|
+
};
|
|
22
|
+
var isTokenWithAPY = function (t) {
|
|
23
|
+
return typeof t === "string" &&
|
|
24
|
+
(!!token_1.lpTokens[t] ||
|
|
25
|
+
!!exports.additionalTokensWIthAPY[t]);
|
|
26
|
+
};
|
|
27
|
+
exports.isTokenWithAPY = isTokenWithAPY;
|
|
17
28
|
__exportStar(require("./convexAPY"), exports);
|
|
18
29
|
__exportStar(require("./curveAPY"), exports);
|
|
19
30
|
__exportStar(require("./lidoAPY"), exports);
|
package/lib/core/assets.d.ts
CHANGED
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
import { BigNumber } from "ethers";
|
|
2
|
-
import { LPTokens } from "../tokens/token";
|
|
3
2
|
import { TokenData } from "../tokens/tokenData";
|
|
4
3
|
export interface Asset {
|
|
5
4
|
token: string;
|
|
6
5
|
balance: BigNumber;
|
|
7
6
|
}
|
|
8
|
-
export interface LpAsset extends Asset {
|
|
9
|
-
symbol: LPTokens;
|
|
10
|
-
name: string;
|
|
11
|
-
}
|
|
12
7
|
interface NextAssetProps<T extends Asset> {
|
|
13
8
|
allowedTokens: Array<string>;
|
|
14
9
|
selectedAssets: Array<T>;
|
|
@@ -2,7 +2,7 @@ import { BigNumber } from "ethers";
|
|
|
2
2
|
import { LpTokensAPY } from "../apy";
|
|
3
3
|
import { CreditAccountDataPayload } from "../payload/creditAccount";
|
|
4
4
|
import { TokenData } from "../tokens/tokenData";
|
|
5
|
-
import { Asset
|
|
5
|
+
import { Asset } from "./assets";
|
|
6
6
|
import { CreditManagerData } from "./creditManager";
|
|
7
7
|
import { PriceOracleData } from "./priceOracle";
|
|
8
8
|
export declare class CreditAccountData {
|
|
@@ -40,13 +40,12 @@ export declare function sortBalances(balances: Record<string, BigNumber>, prices
|
|
|
40
40
|
export declare function tokensAbcComparator(t1?: TokenData, t2?: TokenData): 1 | -1;
|
|
41
41
|
export declare function amountAbcComparator(t1: BigNumber, t2: BigNumber): 1 | -1;
|
|
42
42
|
export interface CalcOverallAPYProps {
|
|
43
|
-
|
|
43
|
+
caAssets: Array<Asset>;
|
|
44
44
|
lpAPY: LpTokensAPY | undefined;
|
|
45
45
|
prices: Record<string, BigNumber>;
|
|
46
|
-
tokensList: Record<string, TokenData>;
|
|
47
46
|
totalValue: BigNumber | undefined;
|
|
48
47
|
debt: BigNumber | undefined;
|
|
49
48
|
borrowRate: number;
|
|
50
49
|
underlyingToken: string;
|
|
51
50
|
}
|
|
52
|
-
export declare function calcOverallAPY({
|
|
51
|
+
export declare function calcOverallAPY({ caAssets, lpAPY, prices, totalValue, debt, borrowRate, underlyingToken, }: CalcOverallAPYProps): number | undefined;
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.calcOverallAPY = exports.amountAbcComparator = exports.tokensAbcComparator = exports.sortBalances = exports.CreditAccountData = void 0;
|
|
4
4
|
var ethers_1 = require("ethers");
|
|
5
|
+
var apy_1 = require("../apy");
|
|
6
|
+
var decimals_1 = require("../tokens/decimals");
|
|
7
|
+
var token_1 = require("../tokens/token");
|
|
5
8
|
var formatter_1 = require("../utils/formatter");
|
|
6
9
|
var price_1 = require("../utils/price");
|
|
7
10
|
var constants_1 = require("./constants");
|
|
@@ -24,12 +27,11 @@ var CreditAccountData = /** @class */ (function () {
|
|
|
24
27
|
this.borrowedAmountPlusInterest = payload.borrowedAmountPlusInterest;
|
|
25
28
|
this.totalValue = payload.totalValue;
|
|
26
29
|
this.healthFactor = payload.healthFactor.toNumber();
|
|
27
|
-
this.borrowRate =
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
.toNumber() / constants_1.PERCENTAGE_FACTOR;
|
|
30
|
+
this.borrowRate = payload.borrowRate
|
|
31
|
+
.mul(constants_1.PERCENTAGE_FACTOR)
|
|
32
|
+
.mul(constants_1.PERCENTAGE_DECIMALS)
|
|
33
|
+
.div(constants_1.RAY)
|
|
34
|
+
.toNumber();
|
|
33
35
|
payload.balances.forEach(function (b) {
|
|
34
36
|
var tokenLC = b.token.toLowerCase();
|
|
35
37
|
if (b.isAllowed) {
|
|
@@ -125,33 +127,37 @@ function amountAbcComparator(t1, t2) {
|
|
|
125
127
|
}
|
|
126
128
|
exports.amountAbcComparator = amountAbcComparator;
|
|
127
129
|
function calcOverallAPY(_a) {
|
|
128
|
-
var
|
|
129
|
-
if (!lpAPY || !totalValue || !debt)
|
|
130
|
+
var caAssets = _a.caAssets, lpAPY = _a.lpAPY, prices = _a.prices, totalValue = _a.totalValue, debt = _a.debt, borrowRate = _a.borrowRate, underlyingToken = _a.underlyingToken;
|
|
131
|
+
if (!lpAPY || !totalValue || totalValue.lte(0) || !debt)
|
|
130
132
|
return undefined;
|
|
131
|
-
var assetAPYMoney =
|
|
132
|
-
var
|
|
133
|
+
var assetAPYMoney = caAssets.reduce(function (acc, _a) {
|
|
134
|
+
var tokenAddress = _a.token, amount = _a.balance;
|
|
135
|
+
var tokenAddressLC = tokenAddress.toLowerCase();
|
|
136
|
+
var symbol = token_1.tokenSymbolByAddress[tokenAddressLC];
|
|
137
|
+
if (!(0, apy_1.isTokenWithAPY)(symbol))
|
|
138
|
+
return acc;
|
|
133
139
|
var apy = lpAPY[symbol] || 0;
|
|
134
|
-
var price = prices[
|
|
135
|
-
var
|
|
136
|
-
var
|
|
137
|
-
var
|
|
138
|
-
var apyMoney = money.mul(apyBN).div(constants_1.WAD);
|
|
140
|
+
var price = prices[tokenAddressLC] || ethers_1.BigNumber.from(0);
|
|
141
|
+
var tokenDecimals = decimals_1.decimals[symbol];
|
|
142
|
+
var money = (0, price_1.calcTotalPrice)(price, amount, tokenDecimals);
|
|
143
|
+
var apyMoney = money.mul(ethers_1.BigNumber.from(apy));
|
|
139
144
|
return acc.add(apyMoney);
|
|
140
145
|
}, ethers_1.BigNumber.from(0));
|
|
141
|
-
var
|
|
142
|
-
var
|
|
146
|
+
var underlyingTokenAddressLC = underlyingToken.toLowerCase();
|
|
147
|
+
var underlyingTokenSymbol = token_1.tokenSymbolByAddress[underlyingTokenAddressLC] || "";
|
|
148
|
+
var underlyingTokenDecimals = decimals_1.decimals[underlyingTokenSymbol] || 18;
|
|
149
|
+
var underlyingPrice = prices[underlyingTokenAddressLC] || constants_1.PRICE_DECIMALS;
|
|
143
150
|
var assetAPYAmountInUnderlying = (0, price_1.convertByPrice)(assetAPYMoney, {
|
|
144
151
|
price: underlyingPrice,
|
|
145
|
-
decimals:
|
|
152
|
+
decimals: underlyingTokenDecimals,
|
|
146
153
|
});
|
|
147
|
-
var
|
|
148
|
-
var debtAPY = debt.mul(borrowAPY).div(constants_1.WAD);
|
|
154
|
+
var debtAPY = debt.mul(ethers_1.BigNumber.from(borrowRate));
|
|
149
155
|
var yourAssets = totalValue.sub(debt);
|
|
150
156
|
var apyInPercent = assetAPYAmountInUnderlying
|
|
151
157
|
.sub(debtAPY)
|
|
152
|
-
.mul(constants_1.PERCENTAGE_DECIMALS)
|
|
153
158
|
.mul(constants_1.WAD)
|
|
154
|
-
.div(yourAssets)
|
|
159
|
+
.div(yourAssets)
|
|
160
|
+
.div(constants_1.PERCENTAGE_FACTOR);
|
|
155
161
|
return Number((0, formatter_1.toSignificant)(apyInPercent, constants_1.WAD_DECIMALS_POW));
|
|
156
162
|
}
|
|
157
163
|
exports.calcOverallAPY = calcOverallAPY;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var _a;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
var chai_1 = require("chai");
|
|
5
|
+
var ethers_1 = require("ethers");
|
|
6
|
+
var decimals_1 = require("../tokens/decimals");
|
|
7
|
+
var token_1 = require("../tokens/token");
|
|
8
|
+
var formatter_1 = require("../utils/formatter");
|
|
9
|
+
var constants_1 = require("./constants");
|
|
10
|
+
var creditAccount_1 = require("./creditAccount");
|
|
11
|
+
var prices = (_a = {},
|
|
12
|
+
_a[token_1.tokenDataByNetwork.Mainnet.WETH.toLowerCase()] = (0, formatter_1.toBN)("1738.11830000", constants_1.PRICE_DECIMALS_POW),
|
|
13
|
+
_a[token_1.tokenDataByNetwork.Mainnet.DAI.toLowerCase()] = (0, formatter_1.toBN)("0.99941103", constants_1.PRICE_DECIMALS_POW),
|
|
14
|
+
_a[token_1.tokenDataByNetwork.Mainnet.STETH.toLowerCase()] = (0, formatter_1.toBN)("1703.87588096", constants_1.PRICE_DECIMALS_POW),
|
|
15
|
+
_a);
|
|
16
|
+
var lpAPY = { STETH: 38434 };
|
|
17
|
+
var caWithoutLP = {
|
|
18
|
+
assets: [
|
|
19
|
+
{
|
|
20
|
+
balance: (0, formatter_1.toBN)("54780", decimals_1.decimals.DAI),
|
|
21
|
+
token: token_1.tokenDataByNetwork.Mainnet.DAI.toLowerCase(),
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
balance: (0, formatter_1.toBN)("3.5", decimals_1.decimals.WETH),
|
|
25
|
+
token: token_1.tokenDataByNetwork.Mainnet.WETH.toLowerCase(),
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
totalValue: (0, formatter_1.toBN)("60860", decimals_1.decimals.DAI),
|
|
29
|
+
debt: (0, formatter_1.toBN)("54780", decimals_1.decimals.DAI),
|
|
30
|
+
borrowRate: 7712,
|
|
31
|
+
underlyingToken: token_1.tokenDataByNetwork.Mainnet.DAI.toLowerCase(),
|
|
32
|
+
};
|
|
33
|
+
var caWithLP = {
|
|
34
|
+
assets: [
|
|
35
|
+
{
|
|
36
|
+
balance: (0, formatter_1.toBN)("119.999999999999999997", decimals_1.decimals.STETH),
|
|
37
|
+
token: token_1.tokenDataByNetwork.Mainnet.STETH.toLowerCase(),
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
balance: (0, formatter_1.toBN)("3.5", decimals_1.decimals.WETH),
|
|
41
|
+
token: token_1.tokenDataByNetwork.Mainnet.WETH.toLowerCase(),
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
totalValue: (0, formatter_1.toBN)("117.635897231615362429", decimals_1.decimals.WETH),
|
|
45
|
+
debt: (0, formatter_1.toBN)("90.000000000000000000", decimals_1.decimals.WETH),
|
|
46
|
+
borrowRate: 5736,
|
|
47
|
+
underlyingToken: token_1.tokenDataByNetwork.Mainnet.WETH.toLowerCase(),
|
|
48
|
+
};
|
|
49
|
+
describe("CreditAccount calcOverallAPY test", function () {
|
|
50
|
+
it("overall APY calculation for caWithoutLP is correct", function () {
|
|
51
|
+
var result = (0, creditAccount_1.calcOverallAPY)({
|
|
52
|
+
caAssets: caWithoutLP.assets,
|
|
53
|
+
totalValue: caWithoutLP.totalValue,
|
|
54
|
+
debt: caWithoutLP.debt,
|
|
55
|
+
borrowRate: caWithoutLP.borrowRate,
|
|
56
|
+
underlyingToken: caWithoutLP.underlyingToken,
|
|
57
|
+
lpAPY: lpAPY,
|
|
58
|
+
prices: prices,
|
|
59
|
+
});
|
|
60
|
+
(0, chai_1.expect)(result).to.be.eq(-6.94841);
|
|
61
|
+
});
|
|
62
|
+
it("overall APY calculation for caWithLP is correct", function () {
|
|
63
|
+
var result = (0, creditAccount_1.calcOverallAPY)({
|
|
64
|
+
caAssets: caWithLP.assets,
|
|
65
|
+
totalValue: caWithLP.totalValue,
|
|
66
|
+
debt: caWithLP.debt,
|
|
67
|
+
borrowRate: caWithLP.borrowRate,
|
|
68
|
+
underlyingToken: caWithLP.underlyingToken,
|
|
69
|
+
lpAPY: lpAPY,
|
|
70
|
+
prices: prices,
|
|
71
|
+
});
|
|
72
|
+
(0, chai_1.expect)(result).to.be.eq(14.4919);
|
|
73
|
+
});
|
|
74
|
+
it("overall APY is undefined when !lpAPY", function () {
|
|
75
|
+
var result = (0, creditAccount_1.calcOverallAPY)({
|
|
76
|
+
caAssets: caWithLP.assets,
|
|
77
|
+
totalValue: caWithLP.totalValue,
|
|
78
|
+
debt: caWithLP.debt,
|
|
79
|
+
borrowRate: caWithLP.borrowRate,
|
|
80
|
+
underlyingToken: caWithLP.underlyingToken,
|
|
81
|
+
lpAPY: undefined,
|
|
82
|
+
prices: prices,
|
|
83
|
+
});
|
|
84
|
+
(0, chai_1.expect)(result).to.be.eq(undefined);
|
|
85
|
+
});
|
|
86
|
+
it("overall APY is undefined when !totalValue", function () {
|
|
87
|
+
var result = (0, creditAccount_1.calcOverallAPY)({
|
|
88
|
+
caAssets: caWithLP.assets,
|
|
89
|
+
totalValue: undefined,
|
|
90
|
+
debt: caWithLP.debt,
|
|
91
|
+
borrowRate: caWithLP.borrowRate,
|
|
92
|
+
underlyingToken: caWithLP.underlyingToken,
|
|
93
|
+
lpAPY: lpAPY,
|
|
94
|
+
prices: prices,
|
|
95
|
+
});
|
|
96
|
+
(0, chai_1.expect)(result).to.be.eq(undefined);
|
|
97
|
+
});
|
|
98
|
+
it("overall APY is undefined when !debt", function () {
|
|
99
|
+
var result = (0, creditAccount_1.calcOverallAPY)({
|
|
100
|
+
caAssets: caWithLP.assets,
|
|
101
|
+
totalValue: caWithLP.totalValue,
|
|
102
|
+
debt: undefined,
|
|
103
|
+
borrowRate: caWithLP.borrowRate,
|
|
104
|
+
underlyingToken: caWithLP.underlyingToken,
|
|
105
|
+
lpAPY: lpAPY,
|
|
106
|
+
prices: prices,
|
|
107
|
+
});
|
|
108
|
+
(0, chai_1.expect)(result).to.be.eq(undefined);
|
|
109
|
+
});
|
|
110
|
+
it("overall APY is undefined when totalValue lte 0", function () {
|
|
111
|
+
var result = (0, creditAccount_1.calcOverallAPY)({
|
|
112
|
+
caAssets: caWithLP.assets,
|
|
113
|
+
totalValue: ethers_1.BigNumber.from(0),
|
|
114
|
+
debt: undefined,
|
|
115
|
+
borrowRate: caWithLP.borrowRate,
|
|
116
|
+
underlyingToken: caWithLP.underlyingToken,
|
|
117
|
+
lpAPY: lpAPY,
|
|
118
|
+
prices: prices,
|
|
119
|
+
});
|
|
120
|
+
(0, chai_1.expect)(result).to.be.eq(undefined);
|
|
121
|
+
});
|
|
122
|
+
});
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { BigNumber, ethers, Signer } from "ethers";
|
|
2
2
|
import { MultiCall } from "../pathfinder/core";
|
|
3
3
|
import { CreditManagerDataPayload, CreditManagerStatPayload } from "../payload/creditManager";
|
|
4
|
-
import { TokenData } from "../tokens/tokenData";
|
|
5
4
|
import { ICreditManager } from "../types";
|
|
6
5
|
import { Asset } from "./assets";
|
|
7
6
|
export declare class CreditManagerData {
|
|
@@ -60,9 +59,8 @@ export declare function calcMaxIncreaseBorrow(healthFactor: number, borrowAmount
|
|
|
60
59
|
export interface CalcHealthFactorProps {
|
|
61
60
|
assets: Array<Asset>;
|
|
62
61
|
prices: Record<string, BigNumber>;
|
|
63
|
-
tokensList: Record<string, TokenData>;
|
|
64
62
|
liquidationThresholds: Record<string, BigNumber>;
|
|
65
|
-
underlyingToken:
|
|
63
|
+
underlyingToken: string;
|
|
66
64
|
borrowed: BigNumber;
|
|
67
65
|
}
|
|
68
|
-
export declare function calcHealthFactor({ assets, prices,
|
|
66
|
+
export declare function calcHealthFactor({ assets, prices, liquidationThresholds, underlyingToken, borrowed, }: CalcHealthFactorProps): number;
|
|
@@ -29,6 +29,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
29
29
|
exports.calcHealthFactor = exports.calcMaxIncreaseBorrow = exports.CreditManagerStat = exports.CreditManagerData = void 0;
|
|
30
30
|
var ethers_1 = require("ethers");
|
|
31
31
|
var txParser_1 = require("../parsers/txParser");
|
|
32
|
+
var decimals_1 = require("../tokens/decimals");
|
|
32
33
|
var token_1 = require("../tokens/token");
|
|
33
34
|
var types_1 = require("../types");
|
|
34
35
|
var price_1 = require("../utils/price");
|
|
@@ -42,12 +43,11 @@ var CreditManagerData = /** @class */ (function () {
|
|
|
42
43
|
this.pool = payload.pool.toLowerCase();
|
|
43
44
|
this.isWETH = payload.isWETH;
|
|
44
45
|
this.canBorrow = payload.canBorrow;
|
|
45
|
-
this.borrowRate =
|
|
46
|
-
payload.
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
.toNumber() / constants_1.PERCENTAGE_FACTOR;
|
|
46
|
+
this.borrowRate = payload.borrowRate
|
|
47
|
+
.mul(payload.feeInterest + constants_1.PERCENTAGE_FACTOR)
|
|
48
|
+
.mul(constants_1.PERCENTAGE_DECIMALS)
|
|
49
|
+
.div(constants_1.RAY)
|
|
50
|
+
.toNumber();
|
|
51
51
|
this.minAmount = payload.minAmount;
|
|
52
52
|
this.maxAmount = payload.maxAmount;
|
|
53
53
|
this.maxLeverageFactor = ethers_1.BigNumber.from(payload.maxLeverageFactor).toNumber();
|
|
@@ -173,34 +173,36 @@ var CreditManagerStat = /** @class */ (function (_super) {
|
|
|
173
173
|
}(CreditManagerData));
|
|
174
174
|
exports.CreditManagerStat = CreditManagerStat;
|
|
175
175
|
function calcMaxIncreaseBorrow(healthFactor, borrowAmountPlusInterest, maxLeverageFactor) {
|
|
176
|
-
var healthFactorPercentage = Math.floor(healthFactor * constants_1.PERCENTAGE_FACTOR);
|
|
177
176
|
var minHealthFactor = maxLeverageFactor > 0
|
|
178
177
|
? Math.floor((constants_1.UNDERLYING_TOKEN_LIQUIDATION_THRESHOLD *
|
|
179
178
|
(maxLeverageFactor + constants_1.LEVERAGE_DECIMALS)) /
|
|
180
179
|
maxLeverageFactor)
|
|
181
180
|
: 10000;
|
|
182
181
|
var result = borrowAmountPlusInterest
|
|
183
|
-
.mul(
|
|
182
|
+
.mul(healthFactor - minHealthFactor)
|
|
184
183
|
.div(minHealthFactor - constants_1.UNDERLYING_TOKEN_LIQUIDATION_THRESHOLD);
|
|
185
184
|
return result.isNegative() ? ethers_1.BigNumber.from(0) : result;
|
|
186
185
|
}
|
|
187
186
|
exports.calcMaxIncreaseBorrow = calcMaxIncreaseBorrow;
|
|
188
187
|
function calcHealthFactor(_a) {
|
|
189
|
-
var assets = _a.assets, prices = _a.prices,
|
|
188
|
+
var assets = _a.assets, prices = _a.prices, liquidationThresholds = _a.liquidationThresholds, underlyingToken = _a.underlyingToken, borrowed = _a.borrowed;
|
|
190
189
|
var assetLTMoney = assets.reduce(function (acc, _a) {
|
|
191
190
|
var tokenAddress = _a.token, amount = _a.balance;
|
|
192
|
-
var
|
|
193
|
-
var
|
|
194
|
-
var
|
|
195
|
-
var
|
|
196
|
-
var
|
|
191
|
+
var tokenSymbol = token_1.tokenSymbolByAddress[tokenAddress.toLowerCase()];
|
|
192
|
+
var tokenDecimals = decimals_1.decimals[tokenSymbol];
|
|
193
|
+
var lt = liquidationThresholds[tokenAddress.toLowerCase()] || ethers_1.BigNumber.from(0);
|
|
194
|
+
var price = prices[tokenAddress.toLowerCase()] || ethers_1.BigNumber.from(0);
|
|
195
|
+
var money = (0, price_1.calcTotalPrice)(price, amount, tokenDecimals);
|
|
196
|
+
var ltMoney = money.mul(lt);
|
|
197
197
|
return acc.add(ltMoney);
|
|
198
198
|
}, ethers_1.BigNumber.from(0));
|
|
199
|
-
var
|
|
200
|
-
var
|
|
199
|
+
var underlyingSymbol = token_1.tokenSymbolByAddress[underlyingToken.toLowerCase()];
|
|
200
|
+
var underlyingDecimals = decimals_1.decimals[underlyingSymbol];
|
|
201
|
+
var underlyingPrice = prices[underlyingToken.toLowerCase()] || constants_1.PRICE_DECIMALS;
|
|
202
|
+
var borrowedMoney = (0, price_1.calcTotalPrice)(underlyingPrice, borrowed, underlyingDecimals);
|
|
201
203
|
var hfInPercent = borrowedMoney.gt(0)
|
|
202
|
-
? assetLTMoney.
|
|
204
|
+
? assetLTMoney.div(borrowedMoney)
|
|
203
205
|
: ethers_1.BigNumber.from(0);
|
|
204
|
-
return hfInPercent.toNumber()
|
|
206
|
+
return hfInPercent.toNumber();
|
|
205
207
|
}
|
|
206
208
|
exports.calcHealthFactor = calcHealthFactor;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var _a, _b;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
var chai_1 = require("chai");
|
|
5
|
+
var ethers_1 = require("ethers");
|
|
6
|
+
var decimals_1 = require("../tokens/decimals");
|
|
7
|
+
var token_1 = require("../tokens/token");
|
|
8
|
+
var formatter_1 = require("../utils/formatter");
|
|
9
|
+
var price_1 = require("../utils/price");
|
|
10
|
+
var assets_1 = require("./assets");
|
|
11
|
+
var constants_1 = require("./constants");
|
|
12
|
+
var creditManager_1 = require("./creditManager");
|
|
13
|
+
var liquidationThresholds = (_a = {},
|
|
14
|
+
_a[token_1.tokenDataByNetwork.Mainnet.DAI.toLowerCase()] = ethers_1.BigNumber.from("9300"),
|
|
15
|
+
_a[token_1.tokenDataByNetwork.Mainnet.WETH.toLowerCase()] = ethers_1.BigNumber.from("8500"),
|
|
16
|
+
_a);
|
|
17
|
+
var prices = (_b = {},
|
|
18
|
+
_b[token_1.tokenDataByNetwork.Mainnet.WETH.toLowerCase()] = (0, formatter_1.toBN)("1738.11830000", constants_1.PRICE_DECIMALS_POW),
|
|
19
|
+
_b[token_1.tokenDataByNetwork.Mainnet.DAI.toLowerCase()] = (0, formatter_1.toBN)("0.99941103", constants_1.PRICE_DECIMALS_POW),
|
|
20
|
+
_b[token_1.tokenDataByNetwork.Mainnet.STETH.toLowerCase()] = (0, formatter_1.toBN)("1703.87588096", constants_1.PRICE_DECIMALS_POW),
|
|
21
|
+
_b);
|
|
22
|
+
var defaultCA = {
|
|
23
|
+
assets: [
|
|
24
|
+
{
|
|
25
|
+
balance: (0, formatter_1.toBN)("156552", decimals_1.decimals.DAI),
|
|
26
|
+
token: token_1.tokenDataByNetwork.Mainnet.DAI.toLowerCase(),
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
balance: (0, formatter_1.toBN)("10", decimals_1.decimals.WETH),
|
|
30
|
+
token: token_1.tokenDataByNetwork.Mainnet.WETH.toLowerCase(),
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
debt: (0, formatter_1.toBN)("156552", decimals_1.decimals.DAI),
|
|
34
|
+
healthFactor: 10244,
|
|
35
|
+
underlyingToken: token_1.tokenDataByNetwork.Mainnet.DAI.toLowerCase(),
|
|
36
|
+
underlyingDecimals: decimals_1.decimals.DAI,
|
|
37
|
+
};
|
|
38
|
+
describe("CreditManager calcHealthFactor test", function () {
|
|
39
|
+
it("health factor calculation is calculated correctly", function () {
|
|
40
|
+
var result = (0, creditManager_1.calcHealthFactor)({
|
|
41
|
+
assets: defaultCA.assets,
|
|
42
|
+
prices: prices,
|
|
43
|
+
liquidationThresholds: liquidationThresholds,
|
|
44
|
+
underlyingToken: defaultCA.underlyingToken,
|
|
45
|
+
borrowed: defaultCA.debt,
|
|
46
|
+
});
|
|
47
|
+
(0, chai_1.expect)(result).to.be.eq(defaultCA.healthFactor);
|
|
48
|
+
});
|
|
49
|
+
it("health factor calculation has no division by zero error", function () {
|
|
50
|
+
var result = (0, creditManager_1.calcHealthFactor)({
|
|
51
|
+
assets: [],
|
|
52
|
+
prices: {},
|
|
53
|
+
liquidationThresholds: {},
|
|
54
|
+
underlyingToken: "",
|
|
55
|
+
borrowed: ethers_1.BigNumber.from(0),
|
|
56
|
+
});
|
|
57
|
+
(0, chai_1.expect)(result).to.be.eq(0);
|
|
58
|
+
});
|
|
59
|
+
it("health factor after add collateral is calculated correctly", function () {
|
|
60
|
+
var collateral = {
|
|
61
|
+
balance: (0, formatter_1.toBN)("10", decimals_1.decimals.WETH),
|
|
62
|
+
token: token_1.tokenDataByNetwork.Mainnet.WETH.toLowerCase(),
|
|
63
|
+
};
|
|
64
|
+
var afterAdd = (0, assets_1.sumAssets)(defaultCA.assets, [collateral]);
|
|
65
|
+
var result = (0, creditManager_1.calcHealthFactor)({
|
|
66
|
+
assets: afterAdd,
|
|
67
|
+
prices: prices,
|
|
68
|
+
liquidationThresholds: liquidationThresholds,
|
|
69
|
+
underlyingToken: defaultCA.underlyingToken,
|
|
70
|
+
borrowed: defaultCA.debt,
|
|
71
|
+
});
|
|
72
|
+
(0, chai_1.expect)(result).to.be.eq(11188);
|
|
73
|
+
});
|
|
74
|
+
it("health factor after decrease debt is calculated correctly", function () {
|
|
75
|
+
var amountDecrease = (0, formatter_1.toBN)("10000", defaultCA.underlyingDecimals);
|
|
76
|
+
var debtDecrease = {
|
|
77
|
+
balance: amountDecrease,
|
|
78
|
+
token: defaultCA.underlyingToken,
|
|
79
|
+
};
|
|
80
|
+
var afterDecrease = (0, assets_1.subAssets)(defaultCA.assets, [debtDecrease]);
|
|
81
|
+
var result = (0, creditManager_1.calcHealthFactor)({
|
|
82
|
+
assets: afterDecrease,
|
|
83
|
+
prices: prices,
|
|
84
|
+
liquidationThresholds: liquidationThresholds,
|
|
85
|
+
underlyingToken: defaultCA.underlyingToken,
|
|
86
|
+
borrowed: defaultCA.debt.sub(amountDecrease),
|
|
87
|
+
});
|
|
88
|
+
(0, chai_1.expect)(result).to.be.eq(10308);
|
|
89
|
+
});
|
|
90
|
+
it("health factor after increase debt is calculated correctly", function () {
|
|
91
|
+
var amountIncrease = (0, formatter_1.toBN)("20000", defaultCA.underlyingDecimals);
|
|
92
|
+
var debtIncrease = {
|
|
93
|
+
balance: amountIncrease,
|
|
94
|
+
token: defaultCA.underlyingToken,
|
|
95
|
+
};
|
|
96
|
+
var afterIncrease = (0, assets_1.sumAssets)(defaultCA.assets, [debtIncrease]);
|
|
97
|
+
var result = (0, creditManager_1.calcHealthFactor)({
|
|
98
|
+
assets: afterIncrease,
|
|
99
|
+
prices: prices,
|
|
100
|
+
liquidationThresholds: liquidationThresholds,
|
|
101
|
+
underlyingToken: defaultCA.underlyingToken,
|
|
102
|
+
borrowed: defaultCA.debt.add(amountIncrease),
|
|
103
|
+
});
|
|
104
|
+
(0, chai_1.expect)(result).to.be.eq(10137);
|
|
105
|
+
});
|
|
106
|
+
it("health factor after swap is calculated correctly", function () {
|
|
107
|
+
var swapAsset = {
|
|
108
|
+
balance: defaultCA.debt,
|
|
109
|
+
token: defaultCA.underlyingToken,
|
|
110
|
+
};
|
|
111
|
+
var underlyingPrice = prices[defaultCA.underlyingToken];
|
|
112
|
+
var wethPrice = prices[token_1.tokenDataByNetwork.Mainnet.WETH.toLowerCase()];
|
|
113
|
+
var getAmount = (0, price_1.convertByPrice)((0, price_1.calcTotalPrice)(underlyingPrice, defaultCA.debt, defaultCA.underlyingDecimals), { price: wethPrice, decimals: decimals_1.decimals.WETH });
|
|
114
|
+
var getAsset = {
|
|
115
|
+
balance: getAmount,
|
|
116
|
+
token: token_1.tokenDataByNetwork.Mainnet.WETH.toLowerCase(),
|
|
117
|
+
};
|
|
118
|
+
var afterSub = (0, assets_1.subAssets)(defaultCA.assets, [swapAsset]);
|
|
119
|
+
var afterSwap = (0, assets_1.sumAssets)(afterSub, [getAsset]);
|
|
120
|
+
var result = (0, creditManager_1.calcHealthFactor)({
|
|
121
|
+
assets: afterSwap,
|
|
122
|
+
prices: prices,
|
|
123
|
+
liquidationThresholds: liquidationThresholds,
|
|
124
|
+
underlyingToken: defaultCA.underlyingToken,
|
|
125
|
+
borrowed: defaultCA.debt,
|
|
126
|
+
});
|
|
127
|
+
(0, chai_1.expect)(result).to.be.eq(9444);
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
describe("CreditManager calcMaxIncreaseBorrow test", function () {
|
|
131
|
+
it("health max increase borrow is zero if hf < 1", function () {
|
|
132
|
+
var result = (0, creditManager_1.calcMaxIncreaseBorrow)(9999, ethers_1.BigNumber.from("156522834253690396032546"), 0);
|
|
133
|
+
(0, chai_1.expect)(result.toString()).to.be.eq(ethers_1.BigNumber.from(0).toString());
|
|
134
|
+
});
|
|
135
|
+
it("health max increase borrow is calculated correctly", function () {
|
|
136
|
+
var result = (0, creditManager_1.calcMaxIncreaseBorrow)(defaultCA.healthFactor, ethers_1.BigNumber.from("156522834253690396032546"), 0);
|
|
137
|
+
(0, chai_1.expect)(result.toString()).to.be.eq(ethers_1.BigNumber.from("54559387939857795188487").toString());
|
|
138
|
+
});
|
|
139
|
+
it("health max increase borrow is calculated correctly (low hf, high debt)", function () {
|
|
140
|
+
var loweHf = 10244;
|
|
141
|
+
var result = (0, creditManager_1.calcMaxIncreaseBorrow)(loweHf, ethers_1.BigNumber.from("54782991988791638611392"), 0);
|
|
142
|
+
(0, chai_1.expect)(result.toString()).to.be.eq(ethers_1.BigNumber.from("19095785778950228315970").toString());
|
|
143
|
+
});
|
|
144
|
+
});
|
|
@@ -17,7 +17,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
exports.CreditSession = void 0;
|
|
18
18
|
var ethers_1 = require("ethers");
|
|
19
19
|
var moment_1 = __importDefault(require("moment"));
|
|
20
|
-
var constants_1 = require("./constants");
|
|
21
20
|
var statusEnum = [
|
|
22
21
|
"active",
|
|
23
22
|
"closed",
|
|
@@ -40,8 +39,7 @@ var CreditSession = /** @class */ (function () {
|
|
|
40
39
|
this.profit = ethers_1.BigNumber.from(payload.profit || 0);
|
|
41
40
|
this.profitPercentage = payload.profitPercentage || 0;
|
|
42
41
|
this.totalValue = ethers_1.BigNumber.from(payload.totalValue || 0);
|
|
43
|
-
this.healthFactor =
|
|
44
|
-
ethers_1.BigNumber.from(payload.healthFactor || 0).toNumber() / constants_1.PERCENTAGE_FACTOR;
|
|
42
|
+
this.healthFactor = ethers_1.BigNumber.from(payload.healthFactor || 0).toNumber();
|
|
45
43
|
this.score = payload.score;
|
|
46
44
|
this.operations = (payload.operations || []).map(function (op) {
|
|
47
45
|
var formattedOp = __assign(__assign({}, op), { date: (0, moment_1.default)(op.timestamp * 1000).format("Do MMM YYYY") });
|
package/lib/core/strategy.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { BigNumber } from "ethers";
|
|
2
2
|
import { TokensWithAPY } from "../apy";
|
|
3
|
-
import { TokenData } from "../tokens/tokenData";
|
|
4
3
|
import { Asset } from "./assets";
|
|
5
4
|
import { CreditManagerData } from "./creditManager";
|
|
6
5
|
export interface StrategyPayload {
|
|
@@ -20,12 +19,11 @@ declare type PoolList = Record<string, PoolStats>;
|
|
|
20
19
|
interface LiquidationPriceProps {
|
|
21
20
|
assets: Array<Asset>;
|
|
22
21
|
prices: Record<string, BigNumber>;
|
|
23
|
-
tokensList: Record<string, TokenData>;
|
|
24
22
|
liquidationThresholds: Record<string, BigNumber>;
|
|
25
23
|
borrowed: BigNumber;
|
|
26
|
-
underlyingToken:
|
|
24
|
+
underlyingToken: string;
|
|
27
25
|
lpAmount: BigNumber;
|
|
28
|
-
lpToken:
|
|
26
|
+
lpToken: string;
|
|
29
27
|
}
|
|
30
28
|
export declare class Strategy {
|
|
31
29
|
apy: number | undefined;
|
|
@@ -39,7 +37,7 @@ export declare class Strategy {
|
|
|
39
37
|
static maxLeverage(lpToken: string, cms: Array<PartialCM>): number;
|
|
40
38
|
maxAPY(maxLeverage: number, poolApy: PoolList): number;
|
|
41
39
|
overallAPY(apy: number, leverage: number, depositCollateral: string, borrowAPY: number): number;
|
|
42
|
-
liquidationPrice({ assets, prices,
|
|
40
|
+
liquidationPrice({ assets, prices, liquidationThresholds, borrowed, underlyingToken, lpAmount, lpToken, }: LiquidationPriceProps): BigNumber;
|
|
43
41
|
protected farmLev(leverage: number, depositCollateral: string): number;
|
|
44
42
|
protected inBaseAssets(depositCollateral: string): boolean;
|
|
45
43
|
protected inLeveragableAssets(depositCollateral: string): boolean;
|
package/lib/core/strategy.js
CHANGED
|
@@ -2,17 +2,23 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Strategy = void 0;
|
|
4
4
|
var ethers_1 = require("ethers");
|
|
5
|
+
var decimals_1 = require("../tokens/decimals");
|
|
6
|
+
var token_1 = require("../tokens/token");
|
|
5
7
|
var price_1 = require("../utils/price");
|
|
6
8
|
var constants_1 = require("./constants");
|
|
7
9
|
var Strategy = /** @class */ (function () {
|
|
8
10
|
function Strategy(payload) {
|
|
9
11
|
this.apy = payload.apy;
|
|
10
12
|
this.name = payload.name;
|
|
11
|
-
this.lpToken = payload.lpToken;
|
|
12
|
-
this.pools = payload.pools;
|
|
13
|
-
this.unleveragableCollateral = payload.unleveragableCollateral
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
this.lpToken = payload.lpToken.toLowerCase();
|
|
14
|
+
this.pools = payload.pools.map(function (addr) { return addr.toLowerCase(); });
|
|
15
|
+
this.unleveragableCollateral = payload.unleveragableCollateral.map(function (addr) {
|
|
16
|
+
return addr.toLowerCase();
|
|
17
|
+
});
|
|
18
|
+
this.leveragableCollateral = payload.leveragableCollateral.map(function (addr) {
|
|
19
|
+
return addr.toLowerCase();
|
|
20
|
+
});
|
|
21
|
+
this.baseAssets = payload.baseAssets.map(function (addr) { return addr.toLowerCase(); });
|
|
16
22
|
}
|
|
17
23
|
Strategy.maxLeverage = function (lpToken, cms) {
|
|
18
24
|
var maxThreshold = maxLeverageThreshold(lpToken, cms)[0];
|
|
@@ -30,20 +36,28 @@ var Strategy = /** @class */ (function () {
|
|
|
30
36
|
};
|
|
31
37
|
// eslint-disable-next-line class-methods-use-this
|
|
32
38
|
Strategy.prototype.liquidationPrice = function (_a) {
|
|
33
|
-
var assets = _a.assets, prices = _a.prices,
|
|
39
|
+
var assets = _a.assets, prices = _a.prices, liquidationThresholds = _a.liquidationThresholds, borrowed = _a.borrowed, underlyingToken = _a.underlyingToken, lpAmount = _a.lpAmount, lpToken = _a.lpToken;
|
|
34
40
|
var collateralLTMoney = assets.reduce(function (acc, _a) {
|
|
35
41
|
var tokenAddress = _a.token, amount = _a.balance;
|
|
36
|
-
var
|
|
37
|
-
var
|
|
38
|
-
var
|
|
39
|
-
var
|
|
42
|
+
var tokenAddressLC = tokenAddress.toLowerCase();
|
|
43
|
+
var tokenSymbol = token_1.tokenSymbolByAddress[tokenAddressLC];
|
|
44
|
+
var lt = liquidationThresholds[tokenAddressLC] || ethers_1.BigNumber.from(0);
|
|
45
|
+
var price = prices[tokenAddressLC] || ethers_1.BigNumber.from(0);
|
|
46
|
+
var tokenDecimals = decimals_1.decimals[tokenSymbol];
|
|
47
|
+
var money = (0, price_1.calcTotalPrice)(price, amount, tokenDecimals);
|
|
40
48
|
var ltMoney = money.mul(lt).div(constants_1.PERCENTAGE_FACTOR);
|
|
41
49
|
return acc.add(ltMoney);
|
|
42
50
|
}, ethers_1.BigNumber.from(0));
|
|
43
|
-
var
|
|
44
|
-
var
|
|
45
|
-
var
|
|
46
|
-
var
|
|
51
|
+
var underlyingTokenAddressLC = underlyingToken.toLowerCase();
|
|
52
|
+
var underlyingTokenSymbol = token_1.tokenSymbolByAddress[underlyingTokenAddressLC];
|
|
53
|
+
var underlyingTokenDecimals = decimals_1.decimals[underlyingTokenSymbol];
|
|
54
|
+
var underlyingPrice = prices[underlyingTokenAddressLC] || constants_1.PRICE_DECIMALS;
|
|
55
|
+
var borrowedMoney = (0, price_1.calcTotalPrice)(underlyingPrice, borrowed, underlyingTokenDecimals);
|
|
56
|
+
var lpTokenAddressLC = lpToken.toLowerCase();
|
|
57
|
+
var lpTokenSymbol = token_1.tokenSymbolByAddress[lpTokenAddressLC];
|
|
58
|
+
var lpTokenDecimals = decimals_1.decimals[lpTokenSymbol];
|
|
59
|
+
var lpPrice = prices[lpTokenAddressLC] || constants_1.PRICE_DECIMALS;
|
|
60
|
+
var lpMoney = (0, price_1.calcTotalPrice)(lpPrice, lpAmount, lpTokenDecimals);
|
|
47
61
|
if (lpMoney.gt(0)) {
|
|
48
62
|
var lqPrice = borrowedMoney
|
|
49
63
|
.sub(collateralLTMoney)
|
|
@@ -60,10 +74,10 @@ var Strategy = /** @class */ (function () {
|
|
|
60
74
|
: leverage - constants_1.LEVERAGE_DECIMALS;
|
|
61
75
|
};
|
|
62
76
|
Strategy.prototype.inBaseAssets = function (depositCollateral) {
|
|
63
|
-
return this.baseAssets.some(function (c) { return c
|
|
77
|
+
return this.baseAssets.some(function (c) { return c === depositCollateral.toLowerCase(); });
|
|
64
78
|
};
|
|
65
79
|
Strategy.prototype.inLeveragableAssets = function (depositCollateral) {
|
|
66
|
-
return this.leveragableCollateral.some(function (c) { return c
|
|
80
|
+
return this.leveragableCollateral.some(function (c) { return c === depositCollateral.toLowerCase(); });
|
|
67
81
|
};
|
|
68
82
|
return Strategy;
|
|
69
83
|
}());
|
|
@@ -76,8 +90,9 @@ function minBorrowApy(poolApy) {
|
|
|
76
90
|
return apys.length > 0 ? apys[0].borrowRate : 0;
|
|
77
91
|
}
|
|
78
92
|
function maxLeverageThreshold(lpToken, cms) {
|
|
93
|
+
var lpTokenLC = lpToken.toLowerCase();
|
|
79
94
|
var ltByCM = cms.map(function (cm) {
|
|
80
|
-
var lt = cm.liquidationThresholds[
|
|
95
|
+
var lt = cm.liquidationThresholds[lpTokenLC] || ethers_1.BigNumber.from(0);
|
|
81
96
|
return [cm.address, lt];
|
|
82
97
|
});
|
|
83
98
|
var sorted = ltByCM.sort(function (_a, _b) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var _a, _b;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
var chai_1 = require("chai");
|
|
5
|
+
var ethers_1 = require("ethers");
|
|
6
|
+
var decimals_1 = require("../tokens/decimals");
|
|
7
|
+
var token_1 = require("../tokens/token");
|
|
8
|
+
var formatter_1 = require("../utils/formatter");
|
|
9
|
+
var constants_1 = require("./constants");
|
|
10
|
+
var strategy_1 = require("./strategy");
|
|
11
|
+
var lidoPayload = {
|
|
12
|
+
name: "Lido",
|
|
13
|
+
lpToken: token_1.tokenDataByNetwork.Mainnet.STETH,
|
|
14
|
+
apyTokenSymbol: "STETH",
|
|
15
|
+
apy: 38434,
|
|
16
|
+
pools: [token_1.tokenDataByNetwork.Mainnet.WETH],
|
|
17
|
+
unleveragableCollateral: [
|
|
18
|
+
token_1.tokenDataByNetwork.Mainnet.USDC,
|
|
19
|
+
token_1.tokenDataByNetwork.Mainnet.DAI,
|
|
20
|
+
token_1.tokenDataByNetwork.Mainnet.WBTC,
|
|
21
|
+
],
|
|
22
|
+
leveragableCollateral: [],
|
|
23
|
+
baseAssets: [token_1.tokenDataByNetwork.Mainnet.WETH],
|
|
24
|
+
};
|
|
25
|
+
var lidoStrategy = new strategy_1.Strategy(lidoPayload);
|
|
26
|
+
var pools = {
|
|
27
|
+
"0x1": {
|
|
28
|
+
borrowRate: 7712,
|
|
29
|
+
},
|
|
30
|
+
"0x2": {
|
|
31
|
+
borrowRate: 5736,
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
var prices = (_a = {},
|
|
35
|
+
_a[token_1.tokenDataByNetwork.Mainnet.WETH.toLowerCase()] = (0, formatter_1.toBN)("1738.11830000", constants_1.PRICE_DECIMALS_POW),
|
|
36
|
+
_a[token_1.tokenDataByNetwork.Mainnet.DAI.toLowerCase()] = (0, formatter_1.toBN)("0.99941103", constants_1.PRICE_DECIMALS_POW),
|
|
37
|
+
_a[token_1.tokenDataByNetwork.Mainnet.STETH.toLowerCase()] = (0, formatter_1.toBN)("1703.87588096", constants_1.PRICE_DECIMALS_POW),
|
|
38
|
+
_a);
|
|
39
|
+
var liquidationThresholds = (_b = {},
|
|
40
|
+
_b[token_1.tokenDataByNetwork.Mainnet.DAI.toLowerCase()] = ethers_1.BigNumber.from("9300"),
|
|
41
|
+
_b[token_1.tokenDataByNetwork.Mainnet.WETH.toLowerCase()] = ethers_1.BigNumber.from("8500"),
|
|
42
|
+
_b[token_1.tokenDataByNetwork.Mainnet.STETH.toLowerCase()] = ethers_1.BigNumber.from("9000"),
|
|
43
|
+
_b);
|
|
44
|
+
describe("Strategy test", function () {
|
|
45
|
+
it("maxAPY calculation is correct", function () {
|
|
46
|
+
var result = lidoStrategy.maxAPY(10 * constants_1.LEVERAGE_DECIMALS, pools);
|
|
47
|
+
(0, chai_1.expect)(result).to.be.eq(332716);
|
|
48
|
+
});
|
|
49
|
+
it("overallAPY calculation is correct", function () {
|
|
50
|
+
var result = lidoStrategy.overallAPY(lidoStrategy.apy || 0, 10 * constants_1.LEVERAGE_DECIMALS, token_1.tokenDataByNetwork.Mainnet.WETH, pools["0x2"].borrowRate);
|
|
51
|
+
(0, chai_1.expect)(result).to.be.eq(332716);
|
|
52
|
+
});
|
|
53
|
+
it("liquidationPrice calculation is correct", function () {
|
|
54
|
+
var result = lidoStrategy.liquidationPrice({
|
|
55
|
+
assets: [
|
|
56
|
+
{
|
|
57
|
+
balance: (0, formatter_1.toBN)("30", decimals_1.decimals.WETH),
|
|
58
|
+
token: token_1.tokenDataByNetwork.Mainnet.WETH,
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
liquidationThresholds: liquidationThresholds,
|
|
62
|
+
prices: prices,
|
|
63
|
+
borrowed: (0, formatter_1.toBN)("90", decimals_1.decimals.WETH),
|
|
64
|
+
underlyingToken: token_1.tokenDataByNetwork.Mainnet.WETH,
|
|
65
|
+
lpAmount: (0, formatter_1.toBN)("119.40", decimals_1.decimals.STETH),
|
|
66
|
+
lpToken: token_1.tokenDataByNetwork.Mainnet.STETH,
|
|
67
|
+
});
|
|
68
|
+
(0, chai_1.expect)(Number((0, formatter_1.toSignificant)(result, constants_1.WAD_DECIMALS_POW)).toFixed(3)).to.be.eq("0.551");
|
|
69
|
+
});
|
|
70
|
+
it("liquidationPrice maxLeverage is correct", function () {
|
|
71
|
+
var result = strategy_1.Strategy.maxLeverage(token_1.tokenDataByNetwork.Mainnet.STETH, [
|
|
72
|
+
{ address: "0x1", liquidationThresholds: liquidationThresholds },
|
|
73
|
+
]);
|
|
74
|
+
(0, chai_1.expect)(result).to.be.eq(9 * constants_1.LEVERAGE_DECIMALS);
|
|
75
|
+
});
|
|
76
|
+
});
|
package/lib/utils/formatter.d.ts
CHANGED
|
@@ -10,5 +10,5 @@ export declare function shortAddress(address?: string): string;
|
|
|
10
10
|
export declare function shortHash(address?: string): string;
|
|
11
11
|
export declare const formatRate: (rate: BigNumberish | undefined) => string;
|
|
12
12
|
export declare function formatDate(date: Date): string;
|
|
13
|
-
export declare function
|
|
13
|
+
export declare function formatPercentage(healthFactor: number, decimals?: number): string;
|
|
14
14
|
export declare function formatLeverage(leverage: number, decimals?: number): string;
|
package/lib/utils/formatter.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.formatLeverage = exports.
|
|
3
|
+
exports.formatLeverage = exports.formatPercentage = exports.formatDate = exports.formatRate = exports.shortHash = exports.shortAddress = exports.toBN = exports.toSignificant = exports.toHumanFormat = exports.formatBn4dig = exports.formatBN = exports.formatRAY = exports.rayToNumber = void 0;
|
|
4
4
|
var decimal_js_light_1 = require("decimal.js-light");
|
|
5
5
|
var ethers_1 = require("ethers");
|
|
6
6
|
var constants_1 = require("../core/constants");
|
|
@@ -129,10 +129,11 @@ function formatDate(date) {
|
|
|
129
129
|
return [year, month, day].join("-");
|
|
130
130
|
}
|
|
131
131
|
exports.formatDate = formatDate;
|
|
132
|
-
function
|
|
133
|
-
|
|
132
|
+
function formatPercentage(healthFactor, decimals) {
|
|
133
|
+
if (decimals === void 0) { decimals = 2; }
|
|
134
|
+
return (healthFactor / constants_1.PERCENTAGE_FACTOR).toFixed(decimals);
|
|
134
135
|
}
|
|
135
|
-
exports.
|
|
136
|
+
exports.formatPercentage = formatPercentage;
|
|
136
137
|
function formatLeverage(leverage, decimals) {
|
|
137
138
|
if (decimals === void 0) { decimals = 2; }
|
|
138
139
|
return (leverage / constants_1.LEVERAGE_DECIMALS).toFixed(decimals);
|