@gearbox-protocol/sdk 0.0.98 → 0.0.101
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/convexAPY.d.ts +8 -0
- package/lib/apy/convexAPY.js +202 -0
- package/lib/apy/lidoAPY.d.ts +4 -0
- package/lib/apy/lidoAPY.js +97 -0
- package/lib/config.d.ts +1 -0
- package/lib/config.js +2 -1
- package/lib/contracts/contracts.d.ts +6 -1
- package/lib/contracts/contracts.js +52 -14
- package/lib/contracts/contractsRegister.js +3 -3
- package/lib/core/constants.d.ts +4 -0
- package/lib/core/constants.js +8 -4
- package/lib/core/creditAccount.d.ts +2 -0
- package/lib/core/creditAccount.js +31 -30
- package/lib/core/creditManager.d.ts +13 -2
- package/lib/core/creditManager.js +79 -29
- package/lib/core/errors.d.ts +10 -0
- package/lib/core/errors.js +16 -1
- package/lib/core/events.js +9 -9
- package/lib/core/multicall.d.ts +1 -1
- package/lib/core/pool.d.ts +1 -1
- package/lib/core/pool.js +7 -5
- package/lib/core/price.d.ts +4 -0
- package/lib/core/price.js +12 -0
- package/lib/core/strategy.d.ts +34 -0
- package/lib/core/strategy.js +57 -0
- package/lib/index.d.ts +7 -1
- package/lib/index.js +8 -3
- package/lib/pathfinder/path.js +1 -1
- package/lib/pathfinder/yVault.js +7 -4
- package/lib/payload/creditAccount.d.ts +4 -26
- package/lib/payload/creditManager.d.ts +12 -24
- package/lib/payload/pool.d.ts +2 -17
- package/lib/payload/pool.js +0 -1
- package/lib/tokens/token.js +4 -4
- package/lib/utils/formatter.d.ts +1 -0
- package/lib/utils/formatter.js +6 -1
- package/lib/utils/mappers.d.ts +2 -1
- package/lib/utils/mappers.js +13 -5
- package/lib/utils/multicall.js +4 -3
- package/lib/utils/types.d.ts +1 -0
- package/package.json +1 -1
- package/src/apy/convexAPY.ts +249 -0
- package/src/apy/lidoAPY.ts +81 -0
- package/src/config.ts +2 -1
- package/src/contracts/contracts.ts +69 -16
- package/src/contracts/contractsRegister.ts +3 -3
- package/src/core/constants.ts +7 -3
- package/src/core/creditAccount.ts +39 -33
- package/src/core/creditManager.ts +230 -148
- package/src/core/errors.ts +24 -0
- package/src/core/events.ts +921 -915
- package/src/core/multicall.ts +1 -1
- package/src/core/pool.ts +56 -51
- package/src/core/price.ts +16 -0
- package/src/core/strategy.ts +123 -0
- package/src/index.ts +8 -1
- package/src/pathfinder/path.ts +154 -154
- package/src/pathfinder/yVault.ts +57 -56
- package/src/payload/creditAccount.ts +4 -26
- package/src/payload/creditManager.ts +13 -25
- package/src/payload/pool.ts +2 -19
- package/src/tokens/token.ts +10 -5
- package/src/utils/formatter.ts +5 -1
- package/src/utils/mappers.ts +12 -5
- package/src/utils/multicall.ts +4 -9
- package/src/utils/types.ts +6 -2
- package/lib/core/adapters.d.ts +0 -15
- package/lib/core/adapters.js +0 -19
- package/lib/core/contracts.d.ts +0 -67
- package/lib/core/contracts.js +0 -254
- package/lib/core/contractsRegister.d.ts +0 -2
- package/lib/core/contractsRegister.js +0 -58
- package/lib/core/creditCard.d.ts +0 -13
- package/lib/core/creditCard.js +0 -2
- package/lib/core/oracles.d.ts +0 -38
- package/lib/core/oracles.js +0 -12
- package/lib/core/priceFeeds.d.ts +0 -3
- package/lib/core/priceFeeds.js +0 -492
- package/lib/core/protocols.d.ts +0 -13
- package/lib/core/protocols.js +0 -39
- package/lib/core/swap.d.ts +0 -4
- package/lib/core/swap.js +0 -8
- package/lib/core/trade.d.ts +0 -35
- package/lib/core/trade.js +0 -62
- package/lib/core/tradeTypes.d.ts +0 -79
- package/lib/core/tradeTypes.js +0 -21
package/lib/tokens/token.js
CHANGED
|
@@ -141,12 +141,12 @@ exports.tokenDataByNetwork = {
|
|
|
141
141
|
cvxsteCRV: "0xb22c2015327cfbeD480eF45B6382d4bC963a4595",
|
|
142
142
|
cvxcrvPlain3andSUSD: "0xBBeAdEA3C648cF4026d0422EAF2463050202700b",
|
|
143
143
|
cvxFRAX3CRV: "0xBC523005975D86de9226785DD83e4f8d2A87fA73",
|
|
144
|
-
cvxLUSD3CRV: "
|
|
144
|
+
cvxLUSD3CRV: "0xF90d9a96985a80e6c2cA9952cd2C6Db5B720408F",
|
|
145
145
|
cvxgusd3CRV: "0xa3aDFDf18d166e26bF1Bc0ee63D26d0d1064b056",
|
|
146
146
|
// CONVEX PHANTOM TOKEN ADDRESSES
|
|
147
147
|
stkcvx3Crv: "0xf4FC4Aa052346fEa87f1e864f10de0f7383e9502",
|
|
148
148
|
stkcvxFRAX3CRV: "0xd726f9684245065B120E1ac18de389f6b05351Ba",
|
|
149
|
-
stkcvxLUSD3CRV: "",
|
|
149
|
+
stkcvxLUSD3CRV: "0x5c355c46413B45Cc58aB61AcaF5BB72E7c2d1465",
|
|
150
150
|
stkcvxgusd3CRV: "0x9A74e8106f6c28b21b1B6a0F985cf1227BE05F04",
|
|
151
151
|
stkcvxsteCRV: "0xd8bAbB7EfBF7F931a69B209f71b27421F8b18516",
|
|
152
152
|
stkcvxcrvPlain3andSUSD: "0x6b45Cab756B41a7204973b71362ef5F73E67F6DA",
|
|
@@ -158,7 +158,7 @@ exports.tokenDataByNetwork = {
|
|
|
158
158
|
GEAR: "0xe01c5d0297c56e992dab3886057a1441485ff7c7"
|
|
159
159
|
}
|
|
160
160
|
};
|
|
161
|
-
exports.tokenSymbolByAddress = (0, mappers_1.objectEntries)(exports.tokenDataByNetwork).reduce(function (
|
|
161
|
+
exports.tokenSymbolByAddress = (0, mappers_1.objectEntries)(exports.tokenDataByNetwork).reduce(function (acc, _a) {
|
|
162
162
|
var _ = _a[0], tokens = _a[1];
|
|
163
|
-
return __assign(__assign({},
|
|
163
|
+
return __assign(__assign({}, acc), (0, mappers_1.filterEmptyKeys)((0, mappers_1.keyToLowercase)((0, mappers_1.swapKeyValue)(tokens))));
|
|
164
164
|
}, {});
|
package/lib/utils/formatter.d.ts
CHANGED
|
@@ -11,3 +11,4 @@ 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
13
|
export declare function formatHf(healthFactor: number): string;
|
|
14
|
+
export declare function formatLeverage(leverage: number, decimals?: number): string;
|
package/lib/utils/formatter.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.formatHf = exports.formatDate = exports.formatRate = exports.shortHash = exports.shortAddress = exports.toBN = exports.toSignificant = exports.toHumanFormat = exports.formatBn4dig = exports.formatBN = exports.formatRAY = exports.rayToNumber = void 0;
|
|
6
|
+
exports.formatLeverage = exports.formatHf = exports.formatDate = exports.formatRate = exports.shortHash = exports.shortAddress = exports.toBN = exports.toSignificant = exports.toHumanFormat = exports.formatBn4dig = exports.formatBN = exports.formatRAY = exports.rayToNumber = void 0;
|
|
7
7
|
var ethers_1 = require("ethers");
|
|
8
8
|
var constants_1 = require("../core/constants");
|
|
9
9
|
var decimal_js_light_1 = __importDefault(require("decimal.js-light"));
|
|
@@ -123,3 +123,8 @@ function formatHf(healthFactor) {
|
|
|
123
123
|
return (healthFactor / 10000).toFixed(2);
|
|
124
124
|
}
|
|
125
125
|
exports.formatHf = formatHf;
|
|
126
|
+
function formatLeverage(leverage, decimals) {
|
|
127
|
+
if (decimals === void 0) { decimals = 2; }
|
|
128
|
+
return (leverage / constants_1.LEVERAGE_DECIMALS).toFixed(decimals);
|
|
129
|
+
}
|
|
130
|
+
exports.formatLeverage = formatLeverage;
|
package/lib/utils/mappers.d.ts
CHANGED
|
@@ -2,5 +2,6 @@ declare type SupportedValue = string | number;
|
|
|
2
2
|
declare const objectEntries: <K extends SupportedValue, T>(o: Record<K, T>) => [K, T][];
|
|
3
3
|
declare const swapKeyValue: <K extends SupportedValue, T extends SupportedValue>(o: Record<K, T>) => Record<T, K>;
|
|
4
4
|
declare const keyToLowercase: <K extends SupportedValue, T extends SupportedValue>(o: Record<K, T>) => Record<K, T>;
|
|
5
|
+
declare const filterEmptyKeys: <K extends SupportedValue, T extends SupportedValue>(o: Record<K, T>) => Record<K, T>;
|
|
5
6
|
export type { SupportedValue };
|
|
6
|
-
export { objectEntries, swapKeyValue, keyToLowercase };
|
|
7
|
+
export { objectEntries, swapKeyValue, keyToLowercase, filterEmptyKeys };
|
package/lib/utils/mappers.js
CHANGED
|
@@ -11,23 +11,31 @@ var __assign = (this && this.__assign) || function () {
|
|
|
11
11
|
return __assign.apply(this, arguments);
|
|
12
12
|
};
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
-
exports.keyToLowercase = exports.swapKeyValue = exports.objectEntries = void 0;
|
|
14
|
+
exports.filterEmptyKeys = exports.keyToLowercase = exports.swapKeyValue = exports.objectEntries = void 0;
|
|
15
15
|
var objectEntries = function (o) { return Object.entries(o); };
|
|
16
16
|
exports.objectEntries = objectEntries;
|
|
17
17
|
var swapKeyValue = function (o) {
|
|
18
|
-
return objectEntries(o).reduce(function (
|
|
18
|
+
return objectEntries(o).reduce(function (acc, _a) {
|
|
19
19
|
var _b;
|
|
20
20
|
var key = _a[0], value = _a[1];
|
|
21
|
-
return __assign(__assign({},
|
|
21
|
+
return __assign(__assign({}, acc), (_b = {}, _b[value] = key, _b));
|
|
22
22
|
}, {});
|
|
23
23
|
};
|
|
24
24
|
exports.swapKeyValue = swapKeyValue;
|
|
25
25
|
var keyToLowercase = function (o) {
|
|
26
|
-
return objectEntries(o).reduce(function (
|
|
26
|
+
return objectEntries(o).reduce(function (acc, _a) {
|
|
27
27
|
var _b;
|
|
28
28
|
var key = _a[0], value = _a[1];
|
|
29
29
|
var keyTransformed = typeof key === "string" ? key.toLowerCase() : key;
|
|
30
|
-
return __assign(__assign({},
|
|
30
|
+
return __assign(__assign({}, acc), (_b = {}, _b[keyTransformed] = value, _b));
|
|
31
31
|
}, {});
|
|
32
32
|
};
|
|
33
33
|
exports.keyToLowercase = keyToLowercase;
|
|
34
|
+
var filterEmptyKeys = function (o) {
|
|
35
|
+
return objectEntries(o).reduce(function (acc, _a) {
|
|
36
|
+
var _b;
|
|
37
|
+
var key = _a[0], value = _a[1];
|
|
38
|
+
return !!key ? __assign(__assign({}, acc), (_b = {}, _b[key] = value, _b)) : acc;
|
|
39
|
+
}, {});
|
|
40
|
+
};
|
|
41
|
+
exports.filterEmptyKeys = filterEmptyKeys;
|
package/lib/utils/multicall.js
CHANGED
|
@@ -37,6 +37,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
exports.MultiCallContract = exports.multicall = void 0;
|
|
40
|
+
var config_1 = require("../config");
|
|
40
41
|
var types_1 = require("../types");
|
|
41
42
|
function multicall(calls, p) {
|
|
42
43
|
return __awaiter(this, void 0, void 0, function () {
|
|
@@ -44,7 +45,7 @@ function multicall(calls, p) {
|
|
|
44
45
|
return __generator(this, function (_a) {
|
|
45
46
|
switch (_a.label) {
|
|
46
47
|
case 0:
|
|
47
|
-
multiCallContract = types_1.Multicall2__factory.connect(
|
|
48
|
+
multiCallContract = types_1.Multicall2__factory.connect(config_1.MULTICALL_ADDRESS, p);
|
|
48
49
|
return [4 /*yield*/, multiCallContract.callStatic.aggregate(calls.map(function (c) { return ({
|
|
49
50
|
target: c.address,
|
|
50
51
|
callData: c.interface.encodeFunctionData(c.method, c.params)
|
|
@@ -55,7 +56,7 @@ function multicall(calls, p) {
|
|
|
55
56
|
.map(function (d, num) {
|
|
56
57
|
return calls[num].interface.decodeFunctionResult(calls[num].method, d);
|
|
57
58
|
})
|
|
58
|
-
.map(function (r) { return r[0]; })];
|
|
59
|
+
.map(function (r) { return (Array.isArray(r) && r.length <= 1 ? r[0] : r); })];
|
|
59
60
|
}
|
|
60
61
|
});
|
|
61
62
|
});
|
|
@@ -65,7 +66,7 @@ var MultiCallContract = /** @class */ (function () {
|
|
|
65
66
|
function MultiCallContract(address, intrerface, provider) {
|
|
66
67
|
this._address = address;
|
|
67
68
|
this._interface = intrerface;
|
|
68
|
-
this._multiCall = types_1.Multicall2__factory.connect(
|
|
69
|
+
this._multiCall = types_1.Multicall2__factory.connect(config_1.MULTICALL_ADDRESS, provider);
|
|
69
70
|
}
|
|
70
71
|
MultiCallContract.prototype.call = function (data) {
|
|
71
72
|
return __awaiter(this, void 0, void 0, function () {
|
package/lib/utils/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import { BigNumber, providers } from "ethers";
|
|
2
|
+
import axios from "axios";
|
|
3
|
+
import {
|
|
4
|
+
ConvexPoolContract,
|
|
5
|
+
ConvexPoolParams,
|
|
6
|
+
contractsByNetwork,
|
|
7
|
+
contractParams,
|
|
8
|
+
CurvePoolContract
|
|
9
|
+
} from "../contracts/contracts";
|
|
10
|
+
|
|
11
|
+
import { tokenDataByNetwork, supportedTokens } from "../tokens/token";
|
|
12
|
+
import { CurveLPToken } from "../tokens/curveLP";
|
|
13
|
+
import { ConvexPhantomTokenData } from "../tokens/convex";
|
|
14
|
+
|
|
15
|
+
import {
|
|
16
|
+
IBaseRewardPool__factory,
|
|
17
|
+
IBaseRewardPool,
|
|
18
|
+
IConvexToken__factory,
|
|
19
|
+
IConvexToken,
|
|
20
|
+
CurveV1AdapterStETH,
|
|
21
|
+
CurveV1AdapterStETH__factory
|
|
22
|
+
} from "../types";
|
|
23
|
+
|
|
24
|
+
import { multicall, MCall } from "../utils/multicall";
|
|
25
|
+
import { toBN } from "../utils/formatter";
|
|
26
|
+
import { AwaitedRes } from "../utils/types";
|
|
27
|
+
|
|
28
|
+
import {
|
|
29
|
+
SECONDS_PER_YEAR,
|
|
30
|
+
WAD,
|
|
31
|
+
WAD_DECIMALS,
|
|
32
|
+
NetworkType
|
|
33
|
+
} from "../core/constants";
|
|
34
|
+
|
|
35
|
+
type SupportedPools = Extract<
|
|
36
|
+
ConvexPoolContract,
|
|
37
|
+
| "CONVEX_3CRV_POOL"
|
|
38
|
+
| "CONVEX_FRAX3CRV_POOL"
|
|
39
|
+
| "CONVEX_LUSD3CRV_POOL"
|
|
40
|
+
| "CONVEX_GUSD_POOL"
|
|
41
|
+
| "CONVEX_SUSD_POOL"
|
|
42
|
+
>;
|
|
43
|
+
|
|
44
|
+
type SupportedConvex = Extract<
|
|
45
|
+
CurvePoolContract,
|
|
46
|
+
| "CURVE_3CRV_POOL"
|
|
47
|
+
| "CURVE_FRAX_POOL"
|
|
48
|
+
| "CURVE_LUSD_POOL"
|
|
49
|
+
| "CURVE_GUSD_POOL"
|
|
50
|
+
| "CURVE_SUSD_POOL"
|
|
51
|
+
>;
|
|
52
|
+
|
|
53
|
+
const curveSwapByPool: Record<SupportedPools, SupportedConvex> = {
|
|
54
|
+
CONVEX_3CRV_POOL: "CURVE_3CRV_POOL",
|
|
55
|
+
CONVEX_FRAX3CRV_POOL: "CURVE_FRAX_POOL",
|
|
56
|
+
CONVEX_LUSD3CRV_POOL: "CURVE_LUSD_POOL",
|
|
57
|
+
CONVEX_GUSD_POOL: "CURVE_GUSD_POOL",
|
|
58
|
+
CONVEX_SUSD_POOL: "CURVE_SUSD_POOL"
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export async function getConvexApy(
|
|
62
|
+
pool: SupportedPools,
|
|
63
|
+
provider: providers.Provider,
|
|
64
|
+
networkType: NetworkType,
|
|
65
|
+
getTokenPrice: (tokenAddress: string) => BigNumber
|
|
66
|
+
) {
|
|
67
|
+
const tokenList = tokenDataByNetwork[networkType];
|
|
68
|
+
const contractsList = contractsByNetwork[networkType];
|
|
69
|
+
|
|
70
|
+
const poolParams = contractParams[pool] as ConvexPoolParams;
|
|
71
|
+
const stakedTokenParams = supportedTokens[
|
|
72
|
+
poolParams.stakedToken
|
|
73
|
+
] as ConvexPhantomTokenData;
|
|
74
|
+
|
|
75
|
+
const underlying = stakedTokenParams.underlying;
|
|
76
|
+
const basePoolAddress = contractsList[pool];
|
|
77
|
+
const swapPoolAddress = contractsList[curveSwapByPool[pool]];
|
|
78
|
+
const cvxAddress = tokenList.CVX;
|
|
79
|
+
|
|
80
|
+
const extraPoolAddresses = poolParams.extraRewards.map(d => {
|
|
81
|
+
return d.poolAddress[networkType];
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const [basePoolRate, basePoolSupply, vPrice, cvxSupply, ...extra] =
|
|
85
|
+
await getPoolData(
|
|
86
|
+
basePoolAddress,
|
|
87
|
+
swapPoolAddress,
|
|
88
|
+
cvxAddress,
|
|
89
|
+
extraPoolAddresses,
|
|
90
|
+
provider
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
const cvxPrice = getTokenPrice(tokenList["CVX"]);
|
|
94
|
+
const crvPrice = getTokenPrice(tokenList["CRV"]);
|
|
95
|
+
|
|
96
|
+
const crvPerSecond = basePoolRate;
|
|
97
|
+
const virtualSupply = basePoolSupply.mul(vPrice).div(WAD);
|
|
98
|
+
const crvPerUnderlying = crvPerSecond.mul(WAD).div(virtualSupply);
|
|
99
|
+
|
|
100
|
+
const crvPerYear = crvPerUnderlying.mul(SECONDS_PER_YEAR);
|
|
101
|
+
const cvxPerYear = getCVXMintAmount(crvPerYear, cvxSupply);
|
|
102
|
+
|
|
103
|
+
const crvAPY = crvPerYear.mul(cvxPrice).div(WAD);
|
|
104
|
+
const cvxAPY = cvxPerYear.mul(crvPrice).div(WAD);
|
|
105
|
+
|
|
106
|
+
const extraAPRs = await Promise.all(
|
|
107
|
+
extraPoolAddresses.map(async (_, index) => {
|
|
108
|
+
const extraRewardSymbol = poolParams.extraRewards[index].rewardToken;
|
|
109
|
+
const extraPoolRate = extra[index];
|
|
110
|
+
|
|
111
|
+
const perUnderlying = extraPoolRate.mul(WAD).div(virtualSupply);
|
|
112
|
+
const perYear = perUnderlying.mul(SECONDS_PER_YEAR);
|
|
113
|
+
|
|
114
|
+
const extraPrise = getTokenPrice(tokenList[extraRewardSymbol]);
|
|
115
|
+
|
|
116
|
+
const extraAPY = perYear.mul(extraPrise).div(WAD);
|
|
117
|
+
|
|
118
|
+
return extraAPY;
|
|
119
|
+
})
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
const extraAPYTotal = extraAPRs.reduce(
|
|
123
|
+
(acc, apy) => acc.add(apy),
|
|
124
|
+
BigNumber.from(0)
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
const baseApyRAY = await getCurveBaseApy(underlying);
|
|
128
|
+
|
|
129
|
+
return baseApyRAY.add(crvAPY).add(cvxAPY).add(extraAPYTotal);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const CVX_MAX_SUPPLY = WAD.mul(100000000);
|
|
133
|
+
const CVX_REDUCTION_PER_CLIFF = BigNumber.from(100000);
|
|
134
|
+
const CVX_TOTAL_CLIFFS = WAD.mul(1000);
|
|
135
|
+
|
|
136
|
+
function getCVXMintAmount(crvAmount: BigNumber, cvxSupply: BigNumber) {
|
|
137
|
+
const currentCliff = cvxSupply.div(CVX_REDUCTION_PER_CLIFF);
|
|
138
|
+
|
|
139
|
+
if (currentCliff.lt(CVX_TOTAL_CLIFFS)) {
|
|
140
|
+
const remainingCliffs = CVX_TOTAL_CLIFFS.sub(currentCliff);
|
|
141
|
+
|
|
142
|
+
const mintedAmount = crvAmount.mul(remainingCliffs).div(CVX_TOTAL_CLIFFS);
|
|
143
|
+
|
|
144
|
+
const amountTillMax = CVX_MAX_SUPPLY.sub(cvxSupply);
|
|
145
|
+
|
|
146
|
+
return mintedAmount.gt(amountTillMax) ? amountTillMax : mintedAmount;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return BigNumber.from(0);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
type IBaseRewardPoolInterface = IBaseRewardPool["interface"];
|
|
153
|
+
type IConvexTokenInterface = IConvexToken["interface"];
|
|
154
|
+
type CurveV1AdapterStETHInterface = CurveV1AdapterStETH["interface"];
|
|
155
|
+
|
|
156
|
+
async function getPoolData(
|
|
157
|
+
basePoolAddress: string,
|
|
158
|
+
underlying: string,
|
|
159
|
+
cvxAddress: string,
|
|
160
|
+
extraPoolAddresses: string[],
|
|
161
|
+
provider: providers.Provider
|
|
162
|
+
) {
|
|
163
|
+
const calls: [
|
|
164
|
+
MCall<IBaseRewardPoolInterface>,
|
|
165
|
+
MCall<IBaseRewardPoolInterface>,
|
|
166
|
+
MCall<CurveV1AdapterStETHInterface>,
|
|
167
|
+
MCall<IConvexTokenInterface>,
|
|
168
|
+
...Array<MCall<IBaseRewardPoolInterface>>
|
|
169
|
+
] = [
|
|
170
|
+
{
|
|
171
|
+
address: basePoolAddress,
|
|
172
|
+
interface: IBaseRewardPool__factory.createInterface(),
|
|
173
|
+
method: "rewardRate()"
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
address: basePoolAddress,
|
|
177
|
+
interface: IBaseRewardPool__factory.createInterface(),
|
|
178
|
+
method: "totalSupply()"
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
address: underlying,
|
|
182
|
+
interface: CurveV1AdapterStETH__factory.createInterface(),
|
|
183
|
+
method: "get_virtual_price()"
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
address: cvxAddress,
|
|
187
|
+
interface: IConvexToken__factory.createInterface(),
|
|
188
|
+
method: "totalSupply()"
|
|
189
|
+
},
|
|
190
|
+
...extraPoolAddresses.map(
|
|
191
|
+
(extraPoolAddress): MCall<IBaseRewardPoolInterface> => ({
|
|
192
|
+
address: extraPoolAddress,
|
|
193
|
+
interface: IBaseRewardPool__factory.createInterface(),
|
|
194
|
+
method: "rewardRate()"
|
|
195
|
+
})
|
|
196
|
+
)
|
|
197
|
+
];
|
|
198
|
+
|
|
199
|
+
return multicall<
|
|
200
|
+
[
|
|
201
|
+
AwaitedRes<IBaseRewardPool["rewardRate"]>,
|
|
202
|
+
AwaitedRes<IBaseRewardPool["totalSupply"]>,
|
|
203
|
+
AwaitedRes<CurveV1AdapterStETH["get_virtual_price"]>,
|
|
204
|
+
AwaitedRes<IConvexToken["totalSupply"]>,
|
|
205
|
+
...Array<AwaitedRes<IBaseRewardPool["rewardRate"]>>
|
|
206
|
+
]
|
|
207
|
+
>(calls, provider);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
interface CurveAPRData {
|
|
211
|
+
baseApy: number;
|
|
212
|
+
crvApy: number;
|
|
213
|
+
crvBoost: number;
|
|
214
|
+
crvPrice: number;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
interface APYResponse {
|
|
218
|
+
apys: Record<string, CurveAPRData>;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const curveLPTokenToPoolName: Record<CurveLPToken, string> = {
|
|
222
|
+
"3Crv": "3pool",
|
|
223
|
+
FRAX3CRV: "frax",
|
|
224
|
+
gusd3CRV: "gusd",
|
|
225
|
+
LUSD3CRV: "lusd",
|
|
226
|
+
crvPlain3andSUSD: "susdv2",
|
|
227
|
+
steCRV: "steth"
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
const RESPONSE_DECIMALS = 100;
|
|
231
|
+
|
|
232
|
+
// https://www.convexfinance.com/api/curve-apys
|
|
233
|
+
|
|
234
|
+
export async function getCurveBaseApy(
|
|
235
|
+
curveLPToken: CurveLPToken
|
|
236
|
+
): Promise<BigNumber> {
|
|
237
|
+
const poolName = curveLPTokenToPoolName[curveLPToken];
|
|
238
|
+
|
|
239
|
+
try {
|
|
240
|
+
const url = "https://www.convexfinance.com/api/curve-apys";
|
|
241
|
+
const result = await axios.get<APYResponse>(url);
|
|
242
|
+
|
|
243
|
+
const { baseApy = 0 } = result.data.apys[poolName] || {};
|
|
244
|
+
|
|
245
|
+
return toBN((baseApy / RESPONSE_DECIMALS).toString(), WAD_DECIMALS);
|
|
246
|
+
} catch (e) {
|
|
247
|
+
return BigNumber.from(0);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { providers } from "ethers";
|
|
2
|
+
|
|
3
|
+
import { multicall, MCall } from "../utils/multicall";
|
|
4
|
+
|
|
5
|
+
import { WAD, SECONDS_PER_YEAR, NetworkType } from "../core/constants";
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
ILidoOracle__factory,
|
|
9
|
+
ILidoOracle,
|
|
10
|
+
IstETH__factory,
|
|
11
|
+
IstETH
|
|
12
|
+
} from "../types";
|
|
13
|
+
|
|
14
|
+
type ILidoOracleInterface = ILidoOracle["interface"];
|
|
15
|
+
|
|
16
|
+
type IstETHInterface = IstETH["interface"];
|
|
17
|
+
|
|
18
|
+
const lidoOracleAddress: Record<NetworkType, string> = {
|
|
19
|
+
Mainnet: "0x442af784A788A5bd6F42A01Ebe9F287a871243fb",
|
|
20
|
+
Kovan: ""
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const lidoStEthAddress: Record<NetworkType, string> = {
|
|
24
|
+
Mainnet: "0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84",
|
|
25
|
+
Kovan: ""
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export async function getLidoApy(
|
|
29
|
+
provider: providers.Provider,
|
|
30
|
+
networkType: NetworkType
|
|
31
|
+
) {
|
|
32
|
+
if (!lidoOracleAddress[networkType]) {
|
|
33
|
+
throw `No Lido APR oracle found on current network: ${networkType}`;
|
|
34
|
+
}
|
|
35
|
+
if (!lidoStEthAddress[networkType]) {
|
|
36
|
+
throw `No Lido stETH found on current network: ${networkType}`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const [{ postTotalPooledEther, preTotalPooledEther, timeElapsed }, fee] =
|
|
40
|
+
await geLidoData(
|
|
41
|
+
lidoOracleAddress[networkType],
|
|
42
|
+
lidoStEthAddress[networkType],
|
|
43
|
+
provider
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const lidoAPRRay = postTotalPooledEther
|
|
47
|
+
.sub(preTotalPooledEther)
|
|
48
|
+
.mul(SECONDS_PER_YEAR)
|
|
49
|
+
.mul(WAD)
|
|
50
|
+
.div(preTotalPooledEther.mul(timeElapsed));
|
|
51
|
+
|
|
52
|
+
return [lidoAPRRay, fee] as const;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function geLidoData(
|
|
56
|
+
lidoOracleAddress: string,
|
|
57
|
+
stETHAddress: string,
|
|
58
|
+
provider: providers.Provider
|
|
59
|
+
) {
|
|
60
|
+
const calls: [MCall<ILidoOracleInterface>, MCall<IstETHInterface>] = [
|
|
61
|
+
{
|
|
62
|
+
address: lidoOracleAddress,
|
|
63
|
+
interface: ILidoOracle__factory.createInterface(),
|
|
64
|
+
method: "getLastCompletedReportDelta()"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
address: stETHAddress,
|
|
68
|
+
interface: IstETH__factory.createInterface(),
|
|
69
|
+
method: "getFee()"
|
|
70
|
+
}
|
|
71
|
+
];
|
|
72
|
+
|
|
73
|
+
return multicall<
|
|
74
|
+
[
|
|
75
|
+
Awaited<ReturnType<ILidoOracle["getLastCompletedReportDelta"]>>,
|
|
76
|
+
Awaited<ReturnType<IstETH["getFee"]>>
|
|
77
|
+
]
|
|
78
|
+
>(calls, provider);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export const LIDO_FEE_DECIMALS = 10000;
|
package/src/config.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export const STATIC_TOKEN = "https://static.gearbox.fi/tokens/"
|
|
1
|
+
export const STATIC_TOKEN = "https://static.gearbox.fi/tokens/";
|
|
2
|
+
export const MULTICALL_ADDRESS = "0x5ba1e12693dc8f9c48aad8770482f4739beed696";
|
|
@@ -3,7 +3,12 @@
|
|
|
3
3
|
* Gearbox. Generalized leverage protocol, which allows to take leverage and then use it across other DeFi protocols and platforms in a composable way.
|
|
4
4
|
* (c) Gearbox.fi, 2021
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
keyToLowercase,
|
|
8
|
+
objectEntries,
|
|
9
|
+
swapKeyValue,
|
|
10
|
+
filterEmptyKeys
|
|
11
|
+
} from "../utils/mappers";
|
|
7
12
|
import { AdapterInterface } from "./adapters";
|
|
8
13
|
import { NetworkType } from "../core/constants";
|
|
9
14
|
import { Protocols } from "./protocols";
|
|
@@ -122,7 +127,7 @@ export const contractsByNetwork: Record<
|
|
|
122
127
|
CONVEX_STECRV_POOL: "0x25edfea00131DAF9b23a8E07720Eea2382d58E71",
|
|
123
128
|
CONVEX_SUSD_POOL: "0xE9998a1c357dc62550f2ED72b736a7CaEB262823",
|
|
124
129
|
CONVEX_FRAX3CRV_POOL: "0xEBE0A1B948eB83333906EB80eE4b87Ee0b5CC84f",
|
|
125
|
-
CONVEX_LUSD3CRV_POOL: "
|
|
130
|
+
CONVEX_LUSD3CRV_POOL: "0x493Bd59EEcFfCa1BF88611CEd478aA5b74427e06",
|
|
126
131
|
CONVEX_GUSD_POOL: "0xE7370DA7FD3d511dAB095Dd7d10388653d5cDE21",
|
|
127
132
|
CONVEX_CLAIM_ZAP: "0x1330C2E5Cd8c333683aE511550f82d25918FFdd5",
|
|
128
133
|
|
|
@@ -179,10 +184,16 @@ type ConvexParams = {
|
|
|
179
184
|
| AdapterInterface.CONVEX_V1_CLAIM_ZAP;
|
|
180
185
|
} & BaseContractParams;
|
|
181
186
|
|
|
182
|
-
type
|
|
187
|
+
type ConvexExtraPoolParams = {
|
|
188
|
+
rewardToken: NormalToken;
|
|
189
|
+
poolAddress: Record<NetworkType, string>;
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
export type ConvexPoolParams = {
|
|
183
193
|
protocol: Protocols.Convex;
|
|
184
194
|
type: AdapterInterface.CONVEX_V1_BASE_REWARD_POOL;
|
|
185
195
|
stakedToken: ConvexStakedPhantomToken;
|
|
196
|
+
extraRewards: Array<ConvexExtraPoolParams>;
|
|
186
197
|
} & BaseContractParams;
|
|
187
198
|
|
|
188
199
|
export type LidoParams = {
|
|
@@ -314,46 +325,85 @@ export const contractParams: Record<SupportedContract, ContractParams> = {
|
|
|
314
325
|
protocol: Protocols.Convex,
|
|
315
326
|
type: AdapterInterface.CONVEX_V1_BOOSTER
|
|
316
327
|
},
|
|
328
|
+
CONVEX_CLAIM_ZAP: {
|
|
329
|
+
name: "Convex ZAP",
|
|
330
|
+
protocol: Protocols.Convex,
|
|
331
|
+
type: AdapterInterface.CONVEX_V1_CLAIM_ZAP
|
|
332
|
+
},
|
|
333
|
+
|
|
317
334
|
CONVEX_3CRV_POOL: {
|
|
318
335
|
name: "Convex 3crv",
|
|
319
336
|
protocol: Protocols.Convex,
|
|
320
337
|
type: AdapterInterface.CONVEX_V1_BASE_REWARD_POOL,
|
|
321
|
-
stakedToken: "stkcvx3Crv"
|
|
338
|
+
stakedToken: "stkcvx3Crv",
|
|
339
|
+
extraRewards: []
|
|
322
340
|
},
|
|
323
341
|
CONVEX_GUSD_POOL: {
|
|
324
342
|
name: "Convex GUSD",
|
|
325
343
|
protocol: Protocols.Convex,
|
|
326
344
|
type: AdapterInterface.CONVEX_V1_BASE_REWARD_POOL,
|
|
327
|
-
stakedToken: "stkcvxgusd3CRV"
|
|
345
|
+
stakedToken: "stkcvxgusd3CRV",
|
|
346
|
+
extraRewards: []
|
|
328
347
|
},
|
|
329
348
|
CONVEX_SUSD_POOL: {
|
|
330
349
|
name: "Convex SUSD",
|
|
331
350
|
protocol: Protocols.Convex,
|
|
332
351
|
type: AdapterInterface.CONVEX_V1_BASE_REWARD_POOL,
|
|
333
|
-
stakedToken: "stkcvxcrvPlain3andSUSD"
|
|
352
|
+
stakedToken: "stkcvxcrvPlain3andSUSD",
|
|
353
|
+
extraRewards: [
|
|
354
|
+
{
|
|
355
|
+
rewardToken: "SNX",
|
|
356
|
+
poolAddress: {
|
|
357
|
+
Mainnet: "0x81fCe3E10D12Da6c7266a1A169c4C96813435263",
|
|
358
|
+
Kovan: "0x26a535146557FA58FA37e3078FEAc523b554939C"
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
]
|
|
334
362
|
},
|
|
335
363
|
CONVEX_STECRV_POOL: {
|
|
336
364
|
name: "Convex STECRV",
|
|
337
365
|
protocol: Protocols.Convex,
|
|
338
366
|
type: AdapterInterface.CONVEX_V1_BASE_REWARD_POOL,
|
|
339
|
-
stakedToken: "stkcvxsteCRV"
|
|
367
|
+
stakedToken: "stkcvxsteCRV",
|
|
368
|
+
extraRewards: [
|
|
369
|
+
{
|
|
370
|
+
rewardToken: "LDO",
|
|
371
|
+
poolAddress: {
|
|
372
|
+
Mainnet: "0x008aEa5036b819B4FEAEd10b2190FBb3954981E8",
|
|
373
|
+
Kovan: "0xd0B1CC3B4839363b1eC92F35eF45794CB07B1183"
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
]
|
|
340
377
|
},
|
|
341
378
|
CONVEX_FRAX3CRV_POOL: {
|
|
342
379
|
name: "Convex FRAX3CRV",
|
|
343
380
|
protocol: Protocols.Convex,
|
|
344
381
|
type: AdapterInterface.CONVEX_V1_BASE_REWARD_POOL,
|
|
345
|
-
stakedToken: "stkcvxFRAX3CRV"
|
|
382
|
+
stakedToken: "stkcvxFRAX3CRV",
|
|
383
|
+
extraRewards: [
|
|
384
|
+
{
|
|
385
|
+
rewardToken: "FXS",
|
|
386
|
+
poolAddress: {
|
|
387
|
+
Mainnet: "0xcDEC6714eB482f28f4889A0c122868450CDBF0b0",
|
|
388
|
+
Kovan: "0x89869c2e79FC6EFf51e714F1239D53702B5CDFCD"
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
]
|
|
346
392
|
},
|
|
347
393
|
CONVEX_LUSD3CRV_POOL: {
|
|
348
394
|
name: "Convex LUSD3CRV",
|
|
349
395
|
protocol: Protocols.Convex,
|
|
350
396
|
type: AdapterInterface.CONVEX_V1_BASE_REWARD_POOL,
|
|
351
|
-
stakedToken: "stkcvxLUSD3CRV"
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
397
|
+
stakedToken: "stkcvxLUSD3CRV",
|
|
398
|
+
extraRewards: [
|
|
399
|
+
{
|
|
400
|
+
rewardToken: "LQTY",
|
|
401
|
+
poolAddress: {
|
|
402
|
+
Mainnet: "0x55d59b791f06dc519B176791c4E037E8Cf2f6361",
|
|
403
|
+
Kovan: ""
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
]
|
|
357
407
|
},
|
|
358
408
|
|
|
359
409
|
LIDO_STETH_GATEWAY: {
|
|
@@ -370,6 +420,9 @@ export const contractParams: Record<SupportedContract, ContractParams> = {
|
|
|
370
420
|
|
|
371
421
|
export const contractsByAddress = objectEntries(contractsByNetwork).reduce<
|
|
372
422
|
Record<string, SupportedContract>
|
|
373
|
-
>((
|
|
374
|
-
return {
|
|
423
|
+
>((acc, [_, contracts]) => {
|
|
424
|
+
return {
|
|
425
|
+
...acc,
|
|
426
|
+
...filterEmptyKeys(keyToLowercase(swapKeyValue(contracts)))
|
|
427
|
+
};
|
|
375
428
|
}, {});
|
|
@@ -35,11 +35,11 @@ export const deployedContracts: Record<string, string> = {
|
|
|
35
35
|
|
|
36
36
|
const contractNames = Object.entries(contractsByAddress).reduce<
|
|
37
37
|
Record<string, string>
|
|
38
|
-
>((
|
|
38
|
+
>((acc, [addr, cSymbol]) => {
|
|
39
39
|
const params = contractParams[cSymbol];
|
|
40
|
-
if (!params) return
|
|
40
|
+
if (!params) return acc;
|
|
41
41
|
|
|
42
|
-
return { ...
|
|
42
|
+
return { ...acc, [addr]: params.name };
|
|
43
43
|
}, {});
|
|
44
44
|
|
|
45
45
|
const contractsFullList = {
|
package/src/core/constants.ts
CHANGED
|
@@ -22,12 +22,15 @@ export const getNetworkType = (chainId: number): NetworkType => {
|
|
|
22
22
|
}
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
export const
|
|
25
|
+
export const RAY_DECIMALS = 27;
|
|
26
|
+
export const RAY = BigNumber.from(10).pow(RAY_DECIMALS);
|
|
26
27
|
export const halfRAY = RAY.div(2);
|
|
27
|
-
export const
|
|
28
|
+
export const WAD_DECIMALS = 18;
|
|
29
|
+
export const WAD = BigNumber.from(10).pow(WAD_DECIMALS);
|
|
28
30
|
|
|
29
31
|
export const SECONDS_PER_YEAR = 365 * 24 * 3600;
|
|
30
32
|
|
|
33
|
+
export const PERCENTAGE_DECIMALS = 100;
|
|
31
34
|
export const PERCENTAGE_FACTOR = 1e4;
|
|
32
35
|
export const LIQUIDATION_DISCOUNTED_SUM = 9500;
|
|
33
36
|
export const UNDERLYING_TOKEN_LIQUIDATION_THRESHOLD = 9300;
|
|
@@ -37,8 +40,9 @@ export const timeRanges: Record<string, number> = {
|
|
|
37
40
|
"1D": 3600 * 24,
|
|
38
41
|
"1W": 3600 * 24 * 7,
|
|
39
42
|
"1M": 3600 * 24 * 30,
|
|
40
|
-
"1Y": 3600 * 24 * 365
|
|
43
|
+
"1Y": 3600 * 24 * 365
|
|
41
44
|
};
|
|
42
45
|
|
|
43
46
|
export const LEVERAGE_DECIMALS = 100;
|
|
47
|
+
export const SLIPPAGE_DECIMALS = 100;
|
|
44
48
|
export const ADDRESS_0x0 = "0x0000000000000000000000000000000000000000";
|