@gearbox-protocol/sdk 13.5.3 → 13.6.0-apy-plugin.2
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/dist/cjs/plugins/adapters/abi/actionAbi.js +1 -1
- package/dist/cjs/plugins/adapters/abi/conctructorAbi.js +1 -1
- package/dist/cjs/plugins/adapters/createAdapter.js +1 -1
- package/dist/cjs/plugins/adapters/types.js +1 -1
- package/dist/cjs/plugins/pools-history/ApyPlugin.js +265 -0
- package/dist/cjs/plugins/pools-history/apy-cache.js +120 -0
- package/dist/cjs/plugins/pools-history/apy-parser.js +169 -0
- package/dist/cjs/plugins/pools-history/constants.js +31 -0
- package/dist/cjs/plugins/pools-history/index.js +12 -2
- package/dist/cjs/plugins/pools-history/pool-apy-types.js +16 -0
- package/dist/cjs/plugins/pools-history/pool-apy-utils.js +141 -0
- package/dist/cjs/rewards/rewards/extra-apy.js +10 -8
- package/dist/cjs/sdk/utils/viem/simulateWithPriceUpdates.js +2 -39
- package/dist/esm/plugins/adapters/abi/actionAbi.js +1 -1
- package/dist/esm/plugins/adapters/abi/conctructorAbi.js +1 -1
- package/dist/esm/plugins/adapters/createAdapter.js +1 -1
- package/dist/esm/plugins/adapters/types.js +1 -1
- package/dist/esm/plugins/pools-history/ApyPlugin.js +254 -0
- package/dist/esm/plugins/pools-history/apy-cache.js +86 -0
- package/dist/esm/plugins/pools-history/apy-parser.js +143 -0
- package/dist/esm/plugins/pools-history/constants.js +6 -0
- package/dist/esm/plugins/pools-history/index.js +6 -1
- package/dist/esm/plugins/pools-history/pool-apy-types.js +0 -0
- package/dist/esm/plugins/pools-history/pool-apy-utils.js +113 -0
- package/dist/esm/rewards/rewards/extra-apy.js +10 -8
- package/dist/esm/sdk/utils/viem/simulateWithPriceUpdates.js +2 -41
- package/dist/types/plugins/adapters/types.d.ts +2 -2
- package/dist/types/plugins/pools-history/ApyPlugin.d.ts +46 -0
- package/dist/types/plugins/pools-history/apy-cache.d.ts +28 -0
- package/dist/types/plugins/pools-history/apy-parser.d.ts +5 -0
- package/dist/types/plugins/pools-history/constants.d.ts +2 -0
- package/dist/types/plugins/pools-history/index.d.ts +6 -1
- package/dist/types/plugins/pools-history/pool-apy-types.d.ts +39 -0
- package/dist/types/plugins/pools-history/pool-apy-utils.d.ts +71 -0
- package/dist/types/plugins/pools-history/types.d.ts +28 -0
- package/dist/types/rewards/rewards/api.d.ts +10 -1
- package/dist/types/rewards/rewards/common.d.ts +0 -10
- package/dist/types/rewards/rewards/extra-apy.d.ts +4 -6
- package/dist/types/sdk/base/types.d.ts +0 -9
- package/package.json +1 -1
- package/dist/cjs/plugins/pools-history/Pools7DAgoPlugin.js +0 -108
- package/dist/esm/plugins/pools-history/Pools7DAgoPlugin.js +0 -90
- package/dist/types/plugins/pools-history/Pools7DAgoPlugin.d.ts +0 -20
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { PERCENTAGE_FACTOR } from "../../sdk/index.js";
|
|
2
|
+
function numberToAPY(baseApy) {
|
|
3
|
+
return Math.round(baseApy * Number(PERCENTAGE_FACTOR));
|
|
4
|
+
}
|
|
5
|
+
function parseGearStats(output) {
|
|
6
|
+
const d = output.gearApy?.status === "ok" ? output.gearApy.data : void 0;
|
|
7
|
+
if (!d) return null;
|
|
8
|
+
return {
|
|
9
|
+
base: numberToAPY(d.base ?? 0),
|
|
10
|
+
crv: numberToAPY(d.crv ?? 0),
|
|
11
|
+
gear: numberToAPY(d.gear ?? 0),
|
|
12
|
+
gearPrice: d.gearPrice ?? 0
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function parseNetworkApy(apyResp, poolResp) {
|
|
16
|
+
const baseAPYList = {};
|
|
17
|
+
const extraCollateralAPYList = {};
|
|
18
|
+
const basePointsList = {};
|
|
19
|
+
const extraCollateralPointsList = {};
|
|
20
|
+
const tokenExtraRewardsList = {};
|
|
21
|
+
const apyData = apyResp?.status === "ok" ? apyResp.data : void 0;
|
|
22
|
+
for (const d of apyData ?? []) {
|
|
23
|
+
const tokenAddress = d.address.toLowerCase();
|
|
24
|
+
const tokenSymbol = d.symbol;
|
|
25
|
+
const apy = d.rewards.apy?.[0];
|
|
26
|
+
if (apy) {
|
|
27
|
+
baseAPYList[tokenAddress] = numberToAPY(apy.value ?? 0);
|
|
28
|
+
}
|
|
29
|
+
const points = d.rewards.points?.[0];
|
|
30
|
+
if (points) {
|
|
31
|
+
basePointsList[tokenAddress] = {
|
|
32
|
+
address: tokenAddress,
|
|
33
|
+
symbol: tokenSymbol,
|
|
34
|
+
rewards: points.rewards.map((p) => ({
|
|
35
|
+
...p,
|
|
36
|
+
multiplier: p.multiplier === "soon" ? p.multiplier : BigInt(p.multiplier || 0)
|
|
37
|
+
})),
|
|
38
|
+
debtRewards: points.debtRewards?.map((p) => ({
|
|
39
|
+
...p,
|
|
40
|
+
cm: (p.cm || "").toLowerCase(),
|
|
41
|
+
multiplier: p.multiplier === "soon" ? p.multiplier : BigInt(p.multiplier || 0)
|
|
42
|
+
}))
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
const extraRewards = d.rewards.extraRewards;
|
|
46
|
+
if (extraRewards && extraRewards.length > 0) {
|
|
47
|
+
tokenExtraRewardsList[tokenAddress] = extraRewards.map((r) => ({
|
|
48
|
+
address: tokenAddress,
|
|
49
|
+
symbol: r.rewardSymbol,
|
|
50
|
+
rewardToken: r.rewardToken.toLowerCase(),
|
|
51
|
+
rewardSymbol: r.rewardSymbol,
|
|
52
|
+
token: r.rewardToken.toLowerCase(),
|
|
53
|
+
finished: BigInt(r.finished || 0),
|
|
54
|
+
duration: BigInt(r.duration || 0),
|
|
55
|
+
reward: BigInt(r.reward || 0),
|
|
56
|
+
balance: BigInt(r.balance || 0)
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
const ecApy = d.rewards.extraCollateralAPY;
|
|
60
|
+
if (ecApy && ecApy.length > 0) {
|
|
61
|
+
for (const ea of ecApy) {
|
|
62
|
+
const pool = ea.pool.toLowerCase();
|
|
63
|
+
if (!extraCollateralAPYList[pool]) extraCollateralAPYList[pool] = {};
|
|
64
|
+
extraCollateralAPYList[pool][tokenAddress] = {
|
|
65
|
+
...ea,
|
|
66
|
+
address: tokenAddress,
|
|
67
|
+
symbol: tokenSymbol,
|
|
68
|
+
pool,
|
|
69
|
+
value: numberToAPY(ea.value ?? 0)
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const ecPoints = d.rewards.extraCollateralPoints;
|
|
74
|
+
if (ecPoints && ecPoints.length > 0) {
|
|
75
|
+
for (const ea of ecPoints) {
|
|
76
|
+
const pool = ea.pool.toLowerCase();
|
|
77
|
+
if (!extraCollateralPointsList[pool])
|
|
78
|
+
extraCollateralPointsList[pool] = {};
|
|
79
|
+
extraCollateralPointsList[pool][tokenAddress] = {
|
|
80
|
+
address: tokenAddress,
|
|
81
|
+
symbol: tokenSymbol,
|
|
82
|
+
rewards: ea.rewards.map((p) => ({
|
|
83
|
+
...p,
|
|
84
|
+
multiplier: p.multiplier === "soon" ? p.multiplier : BigInt(p.multiplier || 0)
|
|
85
|
+
})),
|
|
86
|
+
debtRewards: ea.debtRewards?.map((p) => ({
|
|
87
|
+
...p,
|
|
88
|
+
cm: (p.cm || "").toLowerCase(),
|
|
89
|
+
multiplier: p.multiplier === "soon" ? p.multiplier : BigInt(p.multiplier || 0)
|
|
90
|
+
}))
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const poolRewardsList = {};
|
|
96
|
+
const poolExternalAPYList = {};
|
|
97
|
+
const poolExtraAPYList = {};
|
|
98
|
+
const poolData = poolResp?.status === "ok" ? poolResp.data : void 0;
|
|
99
|
+
for (const r of poolData ?? []) {
|
|
100
|
+
const pool = (r.pool || "").toLowerCase();
|
|
101
|
+
const points = r.rewards.points;
|
|
102
|
+
if (points && points.length > 0) {
|
|
103
|
+
poolRewardsList[pool] = points.map((p) => ({
|
|
104
|
+
...p,
|
|
105
|
+
token: p.token.toLowerCase(),
|
|
106
|
+
pool,
|
|
107
|
+
amount: BigInt(p.amount || 0)
|
|
108
|
+
}));
|
|
109
|
+
}
|
|
110
|
+
const externalAPY = r.rewards.externalAPY;
|
|
111
|
+
if (externalAPY && externalAPY.length > 0) {
|
|
112
|
+
poolExternalAPYList[pool] = externalAPY.map((ex) => ({ ...ex, pool }));
|
|
113
|
+
}
|
|
114
|
+
const extraAPY = r.rewards.extraAPY;
|
|
115
|
+
if (extraAPY && extraAPY.length > 0) {
|
|
116
|
+
poolExtraAPYList[extraAPY[0].token.toLowerCase()] = extraAPY.map((ex) => ({
|
|
117
|
+
...ex,
|
|
118
|
+
token: ex.token.toLowerCase(),
|
|
119
|
+
rewardToken: ex.rewardToken.toLowerCase()
|
|
120
|
+
}));
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
const allResponses = [apyResp, poolResp];
|
|
124
|
+
const allErrors = allResponses.filter((r) => r?.status === "error");
|
|
125
|
+
if (allResponses.length > 0 && allErrors.length === allResponses.length) {
|
|
126
|
+
return void 0;
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
apyList: Object.keys(baseAPYList).length > 0 ? baseAPYList : void 0,
|
|
130
|
+
extraCollateralAPYList: Object.keys(extraCollateralAPYList).length > 0 ? extraCollateralAPYList : void 0,
|
|
131
|
+
pointsList: Object.keys(basePointsList).length > 0 ? basePointsList : void 0,
|
|
132
|
+
extraCollateralPointsList: Object.keys(extraCollateralPointsList).length > 0 ? extraCollateralPointsList : void 0,
|
|
133
|
+
poolRewardsList: Object.keys(poolRewardsList).length > 0 ? poolRewardsList : void 0,
|
|
134
|
+
tokenExtraRewardsList: Object.keys(tokenExtraRewardsList).length > 0 ? tokenExtraRewardsList : void 0,
|
|
135
|
+
poolExternalAPYList: Object.keys(poolExternalAPYList).length > 0 ? poolExternalAPYList : void 0,
|
|
136
|
+
poolExtraAPYList: Object.keys(poolExtraAPYList).length > 0 ? poolExtraAPYList : void 0
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
export {
|
|
140
|
+
numberToAPY,
|
|
141
|
+
parseGearStats,
|
|
142
|
+
parseNetworkApy
|
|
143
|
+
};
|
|
@@ -1,2 +1,7 @@
|
|
|
1
|
-
export * from "./
|
|
1
|
+
export * from "./ApyPlugin.js";
|
|
2
|
+
export * from "./apy-cache.js";
|
|
3
|
+
export * from "./apy-parser.js";
|
|
4
|
+
export * from "./constants.js";
|
|
5
|
+
export * from "./pool-apy-types.js";
|
|
6
|
+
export * from "./pool-apy-utils.js";
|
|
2
7
|
export * from "./types.js";
|
|
File without changes
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { PERCENTAGE_FACTOR, RAY } from "../../sdk/constants/index.js";
|
|
2
|
+
import { formatBN, rayToNumber } from "../../sdk/utils/formatter.js";
|
|
3
|
+
const SCALE = 1000000n;
|
|
4
|
+
const WEEKS_PER_YEAR = 54n;
|
|
5
|
+
function getPoolExtraAPY(lookupAddresses, poolExtraAPYList) {
|
|
6
|
+
if (!poolExtraAPYList) return [];
|
|
7
|
+
const result = [];
|
|
8
|
+
for (const addr of lookupAddresses) {
|
|
9
|
+
const extra = poolExtraAPYList[addr.toLowerCase()];
|
|
10
|
+
if (extra) {
|
|
11
|
+
result.push(...extra);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return result;
|
|
15
|
+
}
|
|
16
|
+
function calculateSupplyApy7d(currentDieselRate, currentSupplyRate, dieselRate7DAgo) {
|
|
17
|
+
if (dieselRate7DAgo > currentDieselRate) {
|
|
18
|
+
return rayToNumber(currentSupplyRate * SCALE) / Number(PERCENTAGE_FACTOR);
|
|
19
|
+
}
|
|
20
|
+
const apy = (currentDieselRate * RAY / dieselRate7DAgo - RAY) * WEEKS_PER_YEAR;
|
|
21
|
+
return rayToNumber(apy * SCALE) / Number(PERCENTAGE_FACTOR);
|
|
22
|
+
}
|
|
23
|
+
function calculatePoolFullAPY({
|
|
24
|
+
depositAPY,
|
|
25
|
+
underlyingAPY,
|
|
26
|
+
extraAPY,
|
|
27
|
+
currentExternalList
|
|
28
|
+
}) {
|
|
29
|
+
const baseAPY = [
|
|
30
|
+
{ type: "supplyAPY", apy: depositAPY },
|
|
31
|
+
...underlyingAPY > 0 ? [
|
|
32
|
+
{
|
|
33
|
+
type: "tokenYield",
|
|
34
|
+
apy: Number(underlyingAPY) / Number(PERCENTAGE_FACTOR)
|
|
35
|
+
}
|
|
36
|
+
] : []
|
|
37
|
+
];
|
|
38
|
+
const filteredExtra = [...extraAPY ?? []].filter((r) => r.apy > 0);
|
|
39
|
+
const baseAPYTotal = baseAPY.reduce((s, r) => s + (r.apy || 0), 0);
|
|
40
|
+
const extraAPYTotal = filteredExtra.reduce((s, r) => s + (r.apy || 0), 0);
|
|
41
|
+
const total = baseAPYTotal + extraAPYTotal;
|
|
42
|
+
const externalAPY = resolveExternalAPY(currentExternalList, total);
|
|
43
|
+
return {
|
|
44
|
+
totalAPY: total,
|
|
45
|
+
baseAPY,
|
|
46
|
+
extraAPY: filteredExtra,
|
|
47
|
+
extraAPYTotal,
|
|
48
|
+
externalAPY
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function resolveExternalAPY(list, baseTotal) {
|
|
52
|
+
const first = list?.[0];
|
|
53
|
+
if (!first) return void 0;
|
|
54
|
+
return {
|
|
55
|
+
...first,
|
|
56
|
+
totalValue: baseTotal + first.value
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function calculatePoolFullAPY7DAgo({
|
|
60
|
+
supplyAPY7DAgo,
|
|
61
|
+
depositAPY,
|
|
62
|
+
poolAPY
|
|
63
|
+
}) {
|
|
64
|
+
const {
|
|
65
|
+
baseAPY = [],
|
|
66
|
+
extraAPYTotal = 0,
|
|
67
|
+
extraAPY = [],
|
|
68
|
+
externalAPY
|
|
69
|
+
} = poolAPY ?? {};
|
|
70
|
+
const base = [
|
|
71
|
+
{ apy: supplyAPY7DAgo || depositAPY, type: "supplyAPY" },
|
|
72
|
+
...baseAPY.filter((r) => r.type !== "supplyAPY")
|
|
73
|
+
];
|
|
74
|
+
const baseTotal = base.reduce((acc, r) => acc + r.apy, 0);
|
|
75
|
+
const total = baseTotal + extraAPYTotal;
|
|
76
|
+
return {
|
|
77
|
+
totalAPY: total,
|
|
78
|
+
extraAPYTotal,
|
|
79
|
+
baseAPY: base,
|
|
80
|
+
extraAPY,
|
|
81
|
+
externalAPY,
|
|
82
|
+
loading7DAgo: supplyAPY7DAgo === void 0
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function calculatePoolPoints({
|
|
86
|
+
poolTokenSymbol,
|
|
87
|
+
points,
|
|
88
|
+
tokensList
|
|
89
|
+
}) {
|
|
90
|
+
return points?.map(({ info, points: pts }) => {
|
|
91
|
+
const { decimals = 18 } = tokensList.get(info.token) || {};
|
|
92
|
+
const amount = formatBN(pts, decimals);
|
|
93
|
+
const { name = "Points", duration } = info ?? {};
|
|
94
|
+
return {
|
|
95
|
+
reward: info,
|
|
96
|
+
name,
|
|
97
|
+
amount,
|
|
98
|
+
tokenTitle: poolTokenSymbol,
|
|
99
|
+
fullTip: [
|
|
100
|
+
`${amount} ${name}`,
|
|
101
|
+
...duration ? [duration] : [],
|
|
102
|
+
...poolTokenSymbol ? [poolTokenSymbol] : []
|
|
103
|
+
].join(" per ")
|
|
104
|
+
};
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
export {
|
|
108
|
+
calculatePoolFullAPY,
|
|
109
|
+
calculatePoolFullAPY7DAgo,
|
|
110
|
+
calculatePoolPoints,
|
|
111
|
+
calculateSupplyApy7d,
|
|
112
|
+
getPoolExtraAPY
|
|
113
|
+
};
|
|
@@ -52,11 +52,13 @@ class PoolPointsAPI {
|
|
|
52
52
|
tokensList
|
|
53
53
|
}) {
|
|
54
54
|
const r = pools.reduce((acc, p) => {
|
|
55
|
-
const
|
|
55
|
+
const poolAddress = p.pool.pool.address.toLowerCase();
|
|
56
|
+
const pointsInfo = poolRewards[poolAddress] || [];
|
|
56
57
|
const poolPointsList = pointsInfo.reduce(
|
|
57
58
|
(acc2, pointsInfo2) => {
|
|
58
|
-
const {
|
|
59
|
-
const
|
|
59
|
+
const { addr: tokenAddress } = tokensList.get(pointsInfo2.token) || {};
|
|
60
|
+
const tokenAddressLower = (tokenAddress || "").toLowerCase();
|
|
61
|
+
const tokenBalance = totalTokenBalances[tokenAddressLower];
|
|
60
62
|
const points = PoolPointsAPI.getPoolTokenPoints(
|
|
61
63
|
tokenBalance,
|
|
62
64
|
p,
|
|
@@ -74,22 +76,22 @@ class PoolPointsAPI {
|
|
|
74
76
|
},
|
|
75
77
|
[]
|
|
76
78
|
);
|
|
77
|
-
acc[
|
|
79
|
+
acc[poolAddress] = poolPointsList;
|
|
78
80
|
return acc;
|
|
79
81
|
}, {});
|
|
80
82
|
return r;
|
|
81
83
|
}
|
|
82
84
|
static getPoolTokenPoints(tokenBalanceInPool, pool, tokensList, pointsInfo) {
|
|
83
|
-
if (pool.expectedLiquidity <= 0) return 0n;
|
|
85
|
+
if (pool.pool.pool.expectedLiquidity <= 0) return 0n;
|
|
84
86
|
if (pointsInfo.estimation === "relative" && !tokenBalanceInPool)
|
|
85
87
|
return null;
|
|
86
|
-
const { decimals = 18 } = tokensList
|
|
88
|
+
const { decimals = 18 } = tokensList.get(pointsInfo.token) || {};
|
|
87
89
|
const targetFactor = 10n ** BigInt(decimals);
|
|
88
90
|
const defaultPoints = pointsInfo.amount * targetFactor / PERCENTAGE_FACTOR;
|
|
89
91
|
if (pointsInfo.estimation === "absolute") return defaultPoints;
|
|
90
|
-
const { decimals: underlyingDecimals = 18 } = tokensList
|
|
92
|
+
const { decimals: underlyingDecimals = 18 } = tokensList.get(pool.pool.pool.underlying) || {};
|
|
91
93
|
const underlyingFactor = 10n ** BigInt(underlyingDecimals);
|
|
92
|
-
const points = (tokenBalanceInPool?.balance || 0n) * defaultPoints / (pool.expectedLiquidity * targetFactor / underlyingFactor);
|
|
94
|
+
const points = (tokenBalanceInPool?.balance || 0n) * defaultPoints / (pool.pool.pool.expectedLiquidity * targetFactor / underlyingFactor);
|
|
93
95
|
return BigIntMath.min(points, defaultPoints);
|
|
94
96
|
}
|
|
95
97
|
}
|
|
@@ -3,12 +3,8 @@ import {
|
|
|
3
3
|
CallExecutionError,
|
|
4
4
|
ContractFunctionRevertedError,
|
|
5
5
|
decodeFunctionData,
|
|
6
|
-
decodeFunctionResult,
|
|
7
|
-
encodeFunctionData,
|
|
8
6
|
parseAbi
|
|
9
7
|
} from "viem";
|
|
10
|
-
import { call } from "viem/actions";
|
|
11
|
-
import { getAction, parseAccount } from "viem/utils";
|
|
12
8
|
import { errorAbis } from "../../../abi/errors.js";
|
|
13
9
|
import { iUpdatablePriceFeedAbi } from "../../../abi/iUpdatablePriceFeed.js";
|
|
14
10
|
import { generateCastTraceCall } from "./cast.js";
|
|
@@ -38,41 +34,6 @@ async function simulateWithPriceUpdates(client, parameters) {
|
|
|
38
34
|
"client chain not configured. multicallAddress is required."
|
|
39
35
|
);
|
|
40
36
|
}
|
|
41
|
-
if (priceUpdates.length === 0 && restContracts.length === 1) {
|
|
42
|
-
const contract = restContracts[0];
|
|
43
|
-
const { abi, address, args, functionName } = contract;
|
|
44
|
-
const callData = encodeFunctionData({ abi, args, functionName });
|
|
45
|
-
const request2 = {
|
|
46
|
-
batch: false,
|
|
47
|
-
data: callData,
|
|
48
|
-
to: address,
|
|
49
|
-
blockNumber: rest.blockNumber,
|
|
50
|
-
blockTag: rest.blockTag,
|
|
51
|
-
gas: rest.gas,
|
|
52
|
-
account: rest.account ? parseAccount(rest.account) : client.account,
|
|
53
|
-
value: rest.value
|
|
54
|
-
};
|
|
55
|
-
try {
|
|
56
|
-
const { data } = await getAction(client, call, "call")(request2);
|
|
57
|
-
const result = decodeFunctionResult({
|
|
58
|
-
abi,
|
|
59
|
-
args,
|
|
60
|
-
data: data || "0x",
|
|
61
|
-
functionName
|
|
62
|
-
});
|
|
63
|
-
return [
|
|
64
|
-
result
|
|
65
|
-
];
|
|
66
|
-
} catch (e) {
|
|
67
|
-
throw getSimulateWithPriceUpdatesError(
|
|
68
|
-
e,
|
|
69
|
-
priceUpdates,
|
|
70
|
-
restContracts,
|
|
71
|
-
void 0,
|
|
72
|
-
request2
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
37
|
let request;
|
|
77
38
|
try {
|
|
78
39
|
const contracts = [
|
|
@@ -193,8 +154,8 @@ function getSimulateWithPriceUpdatesError(cause, priceUpdates, calls, results, r
|
|
|
193
154
|
return [extractCallError(result), p.pretty, tsValid].filter(Boolean).join(" ");
|
|
194
155
|
});
|
|
195
156
|
const prettyCalls = callsResults.map((c, i) => {
|
|
196
|
-
const
|
|
197
|
-
return [extractCallError(c), `${
|
|
157
|
+
const call = calls[i];
|
|
158
|
+
return [extractCallError(c), `${call.address}.${call.functionName}`].filter(Boolean).join(" ");
|
|
198
159
|
});
|
|
199
160
|
if (results[0]?.status === "failure") {
|
|
200
161
|
prettyCalls.unshift(
|
|
@@ -2,7 +2,7 @@ import type { AbiParameter, Address } from "viem";
|
|
|
2
2
|
import type { BaseContractStateHuman } from "../../sdk/types/state-human.js";
|
|
3
3
|
import type { LegacyAdapterOperation } from "./legacyAdapterOperations.js";
|
|
4
4
|
export type VersionedAbi = Record<number, readonly AbiParameter[]>;
|
|
5
|
-
export type AdapterContractType = "ADAPTER::ACCOUNT_MIGRATOR" | "ADAPTER::BALANCER_V3_ROUTER" | "ADAPTER::BALANCER_V3_WRAPPER" | "ADAPTER::BALANCER_VAULT" | "ADAPTER::CAMELOT_V3_ROUTER" | "ADAPTER::CURVE_STABLE_NG" | "ADAPTER::CURVE_V1_2ASSETS" | "ADAPTER::CURVE_V1_3ASSETS" | "ADAPTER::CURVE_V1_4ASSETS" | "ADAPTER::CURVE_V1_STECRV_POOL" | "ADAPTER::CURVE_V1_WRAPPER" | "ADAPTER::CVX_V1_BASE_REWARD_POOL" | "ADAPTER::CVX_V1_BOOSTER" | "ADAPTER::DAI_USDS_EXCHANGE" | "ADAPTER::EQUALIZER_ROUTER" | "ADAPTER::ERC4626_VAULT" | "ADAPTER::ERC4626_VAULT_REFERRAL" | "ADAPTER::FLUID_DEX" | "ADAPTER::INFINIFI_GATEWAY" | "ADAPTER::INFINIFI_UNWINDING" | "ADAPTER::INFRARED_VAULT" | "ADAPTER::KELP_DEPOSIT_POOL" | "ADAPTER::KELP_WITHDRAWAL" | "ADAPTER::KODIAK_ISLAND_GATEWAY" | "ADAPTER::LIDO_V1" | "ADAPTER::LIDO_WSTETH_V1" | "ADAPTER::MELLOW_CLAIMER" | "ADAPTER::MELLOW_DVV" | "ADAPTER::MELLOW_ERC4626_VAULT" | "ADAPTER::MELLOW_LRT_VAULT" | "ADAPTER::MELLOW_WRAPPER" | "ADAPTER::MELLOW_DEPOSIT_QUEUE_QUEUE" | "ADAPTER::MELLOW_REDEEM_QUEUE_QUEUE" | "ADAPTER::MIDAS_ISSUANCE_VAULT" | "ADAPTER::MIDAS_REDEMPTION_VAULT" | "ADAPTER::PENDLE_ROUTER" | "ADAPTER::STAKING_REWARDS" | "ADAPTER::
|
|
5
|
+
export type AdapterContractType = "ADAPTER::ACCOUNT_MIGRATOR" | "ADAPTER::BALANCER_V3_ROUTER" | "ADAPTER::BALANCER_V3_WRAPPER" | "ADAPTER::BALANCER_VAULT" | "ADAPTER::CAMELOT_V3_ROUTER" | "ADAPTER::CURVE_STABLE_NG" | "ADAPTER::CURVE_V1_2ASSETS" | "ADAPTER::CURVE_V1_3ASSETS" | "ADAPTER::CURVE_V1_4ASSETS" | "ADAPTER::CURVE_V1_STECRV_POOL" | "ADAPTER::CURVE_V1_WRAPPER" | "ADAPTER::CVX_V1_BASE_REWARD_POOL" | "ADAPTER::CVX_V1_BOOSTER" | "ADAPTER::DAI_USDS_EXCHANGE" | "ADAPTER::EQUALIZER_ROUTER" | "ADAPTER::ERC4626_VAULT" | "ADAPTER::ERC4626_VAULT_REFERRAL" | "ADAPTER::FLUID_DEX" | "ADAPTER::INFINIFI_GATEWAY" | "ADAPTER::INFINIFI_UNWINDING" | "ADAPTER::INFRARED_VAULT" | "ADAPTER::KELP_DEPOSIT_POOL" | "ADAPTER::KELP_WITHDRAWAL" | "ADAPTER::KODIAK_ISLAND_GATEWAY" | "ADAPTER::LIDO_V1" | "ADAPTER::LIDO_WSTETH_V1" | "ADAPTER::MELLOW_CLAIMER" | "ADAPTER::MELLOW_DVV" | "ADAPTER::MELLOW_ERC4626_VAULT" | "ADAPTER::MELLOW_LRT_VAULT" | "ADAPTER::MELLOW_WRAPPER" | "ADAPTER::MELLOW_DEPOSIT_QUEUE_QUEUE" | "ADAPTER::MELLOW_REDEEM_QUEUE_QUEUE" | "ADAPTER::MIDAS_ISSUANCE_VAULT" | "ADAPTER::MIDAS_REDEMPTION_VAULT" | "ADAPTER::PENDLE_ROUTER" | "ADAPTER::STAKING_REWARDS" | "ADAPTER::TRADERJOE_ROUTER" | "ADAPTER::UNISWAP_V2_ROUTER" | "ADAPTER::UNISWAP_V3_ROUTER" | "ADAPTER::UNISWAP_V4_GATEWAY" | "ADAPTER::UPSHIFT_VAULT" | "ADAPTER::VELODROME_V2_ROUTER" | "ADAPTER::YEARN_V2";
|
|
6
6
|
export declare enum AdapterType {
|
|
7
7
|
ACCOUNT_MIGRATOR = "ACCOUNT_MIGRATOR",
|
|
8
8
|
BALANCER_V3_ROUTER = "BALANCER_V3_ROUTER",
|
|
@@ -41,7 +41,7 @@ export declare enum AdapterType {
|
|
|
41
41
|
MIDAS_REDEMPTION_VAULT = "MIDAS_REDEMPTION_VAULT",
|
|
42
42
|
PENDLE_ROUTER = "PENDLE_ROUTER",
|
|
43
43
|
STAKING_REWARDS = "STAKING_REWARDS",
|
|
44
|
-
|
|
44
|
+
TRADERJOE_ROUTER = "TRADERJOE_ROUTER",
|
|
45
45
|
UNISWAP_V2_ROUTER = "UNISWAP_V2_ROUTER",
|
|
46
46
|
UNISWAP_V3_ROUTER = "UNISWAP_V3_ROUTER",
|
|
47
47
|
UNISWAP_V4_GATEWAY = "UNISWAP_V4_GATEWAY",
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { Address } from "viem";
|
|
2
|
+
import type { IGearboxSDKPlugin } from "../../sdk/index.js";
|
|
3
|
+
import { AddressMap, BasePlugin } from "../../sdk/index.js";
|
|
4
|
+
import type { GetPoolsAPYResult } from "./pool-apy-types.js";
|
|
5
|
+
import type { ApySnapshotState, Pool7DAgoState, Pools7DAgoStateHuman } from "./types.js";
|
|
6
|
+
export interface ApyPluginState {
|
|
7
|
+
pools7DAgo: Record<Address, Pool7DAgoState>;
|
|
8
|
+
apySnapshot: ApySnapshotState;
|
|
9
|
+
}
|
|
10
|
+
export interface ApyPluginConstructorOptions {
|
|
11
|
+
apyUrl?: string;
|
|
12
|
+
/** TTL for the shared HTTP cache in milliseconds (default: 10 minutes, see `DEFAULT_APY_INTERVAL_MS`) */
|
|
13
|
+
cacheTtlMs?: number;
|
|
14
|
+
}
|
|
15
|
+
export interface ApyPluginLoadOptions {
|
|
16
|
+
/**
|
|
17
|
+
* When `false` and the plugin is already loaded, skips the multicall that loads
|
|
18
|
+
* pool diesel rates at the ~7d-ago block; only the APY snapshot is refreshed.
|
|
19
|
+
* Ignored on the first load (both datasets are always fetched initially).
|
|
20
|
+
*/
|
|
21
|
+
loadPools7DAgo?: boolean;
|
|
22
|
+
}
|
|
23
|
+
export declare class ApyPlugin extends BasePlugin<ApyPluginState> implements IGearboxSDKPlugin<ApyPluginState> {
|
|
24
|
+
#private;
|
|
25
|
+
constructor(loadOnAttach?: boolean, options?: ApyPluginConstructorOptions);
|
|
26
|
+
load(force?: boolean, loadOptions?: ApyPluginLoadOptions): Promise<ApyPluginState>;
|
|
27
|
+
get loaded(): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* @throws if plugin is not loaded
|
|
30
|
+
*/
|
|
31
|
+
get pools7DAgo(): AddressMap<Pool7DAgoState>;
|
|
32
|
+
/**
|
|
33
|
+
* @throws if plugin is not loaded
|
|
34
|
+
*/
|
|
35
|
+
get apySnapshot(): ApySnapshotState;
|
|
36
|
+
/**
|
|
37
|
+
* Computes per-pool APY (current + 7d-ago) and points for all markets.
|
|
38
|
+
*
|
|
39
|
+
* @throws if plugin is not loaded
|
|
40
|
+
*/
|
|
41
|
+
getPoolsAPY(): GetPoolsAPYResult;
|
|
42
|
+
syncState(): Promise<void>;
|
|
43
|
+
stateHuman(_?: boolean): Pools7DAgoStateHuman[];
|
|
44
|
+
get state(): ApyPluginState;
|
|
45
|
+
hydrate(state: ApyPluginState): void;
|
|
46
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Output } from "../../rewards/apy/index.js";
|
|
2
|
+
import type { ILogger } from "../../sdk/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* Process-wide cache for the APY state-cache JSON.
|
|
5
|
+
*
|
|
6
|
+
* Multiple ApyPlugin instances (one per SDK / network) share the same
|
|
7
|
+
* cached HTTP response so that only **one** request is made per TTL window
|
|
8
|
+
* regardless of how many SDK instances exist.
|
|
9
|
+
*
|
|
10
|
+
* Concurrent callers that arrive while a fetch is already in flight
|
|
11
|
+
* are de-duplicated — they all await the same promise.
|
|
12
|
+
*/
|
|
13
|
+
export declare class ApyOutputCache {
|
|
14
|
+
#private;
|
|
15
|
+
private constructor();
|
|
16
|
+
/**
|
|
17
|
+
* Returns a shared cache instance for the given URL.
|
|
18
|
+
* The same instance is reused across all callers with identical URL.
|
|
19
|
+
*/
|
|
20
|
+
static get(url: string, ttlMs: number, logger?: ILogger): ApyOutputCache;
|
|
21
|
+
/**
|
|
22
|
+
* Returns cached Output if fresh, otherwise fetches from the network.
|
|
23
|
+
* Concurrent calls are de-duplicated.
|
|
24
|
+
*/
|
|
25
|
+
fetch(): Promise<Output<string, string> | undefined>;
|
|
26
|
+
/** Evicts all cached entries. Mainly useful for tests. */
|
|
27
|
+
static clearAll(): void;
|
|
28
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { DataResult, Output, PoolOutputDetails, TokenOutputDetails } from "../../rewards/apy/index.js";
|
|
2
|
+
import type { GearStats, NetworkApyData } from "./types.js";
|
|
3
|
+
export declare function numberToAPY(baseApy: number): number;
|
|
4
|
+
export declare function parseGearStats(output: Output<string, string>): GearStats | null;
|
|
5
|
+
export declare function parseNetworkApy(apyResp: DataResult<TokenOutputDetails<string>[]> | undefined, poolResp: DataResult<PoolOutputDetails<string>[]> | undefined): NetworkApyData | undefined;
|
|
@@ -1,2 +1,7 @@
|
|
|
1
|
-
export * from "./
|
|
1
|
+
export * from "./ApyPlugin.js";
|
|
2
|
+
export * from "./apy-cache.js";
|
|
3
|
+
export * from "./apy-parser.js";
|
|
4
|
+
export * from "./constants.js";
|
|
5
|
+
export * from "./pool-apy-types.js";
|
|
6
|
+
export * from "./pool-apy-utils.js";
|
|
2
7
|
export * from "./types.js";
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Address } from "viem";
|
|
2
|
+
import type { ExternalApy as ExternalApySDK, PoolExtraApy, PoolPointsInfo } from "../../rewards/apy/index.js";
|
|
3
|
+
export interface PoolBaseAPY {
|
|
4
|
+
type: "supplyAPY" | "tokenYield";
|
|
5
|
+
apy: number;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* External APY enriched with the cumulative `totalValue`
|
|
9
|
+
* (base + extra + external).
|
|
10
|
+
*/
|
|
11
|
+
export interface PoolExternalAPY extends ExternalApySDK {
|
|
12
|
+
totalValue: number;
|
|
13
|
+
}
|
|
14
|
+
export interface PoolFullAPY {
|
|
15
|
+
totalAPY: number;
|
|
16
|
+
baseAPY: PoolBaseAPY[];
|
|
17
|
+
extraAPY: PoolExtraApy[];
|
|
18
|
+
extraAPYTotal: number;
|
|
19
|
+
externalAPY: PoolExternalAPY | undefined;
|
|
20
|
+
}
|
|
21
|
+
export interface PoolFullAPY7DAgo extends PoolFullAPY {
|
|
22
|
+
loading7DAgo: boolean;
|
|
23
|
+
}
|
|
24
|
+
export interface PoolPointsWithTips {
|
|
25
|
+
reward?: PoolPointsInfo<string>;
|
|
26
|
+
amount: string;
|
|
27
|
+
name: string;
|
|
28
|
+
tokenTitle?: string;
|
|
29
|
+
fullTip: string;
|
|
30
|
+
}
|
|
31
|
+
type AllPoolsAPY = Record<Address, PoolFullAPY>;
|
|
32
|
+
type AllPoolsAPY7DAgo = Record<Address, PoolFullAPY7DAgo>;
|
|
33
|
+
type AllPoolsPoints = Record<Address, PoolPointsWithTips[] | undefined>;
|
|
34
|
+
export interface GetPoolsAPYResult {
|
|
35
|
+
data: AllPoolsAPY;
|
|
36
|
+
data7DAgo: AllPoolsAPY7DAgo;
|
|
37
|
+
points: AllPoolsPoints;
|
|
38
|
+
}
|
|
39
|
+
export {};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { Address } from "viem";
|
|
2
|
+
import type { ExternalApy, PoolExtraApy } from "../../rewards/apy/index.js";
|
|
3
|
+
import type { PoolPointsBase } from "../../rewards/rewards/extra-apy.js";
|
|
4
|
+
import type { TokensMeta } from "../../sdk/index.js";
|
|
5
|
+
import type { PoolFullAPY, PoolFullAPY7DAgo, PoolPointsWithTips } from "./pool-apy-types.js";
|
|
6
|
+
/**
|
|
7
|
+
* Collects extra APY entries for the given token addresses from the
|
|
8
|
+
* `poolExtraAPYList` map.
|
|
9
|
+
*
|
|
10
|
+
* In the client, `lookupAddresses` = [pool.address, ...pool.stakedDieselToken].
|
|
11
|
+
* The caller is responsible for providing the correct set of addresses.
|
|
12
|
+
*/
|
|
13
|
+
export declare function getPoolExtraAPY(lookupAddresses: Address[], poolExtraAPYList: Record<Address, PoolExtraApy[]> | undefined): PoolExtraApy[];
|
|
14
|
+
/**
|
|
15
|
+
* Computes annualized supply APY based on diesel rate change over ~7 days.
|
|
16
|
+
*
|
|
17
|
+
* Returns a value in "percentage" units (e.g. 5 ≈ 5 %).
|
|
18
|
+
* Falls back to current on-chain `supplyRate` if 7d-ago diesel rate is
|
|
19
|
+
* missing or higher than the current rate.
|
|
20
|
+
*/
|
|
21
|
+
export declare function calculateSupplyApy7d(currentDieselRate: bigint, currentSupplyRate: bigint, dieselRate7DAgo: bigint): number;
|
|
22
|
+
interface CalculatePoolFullAPYProps {
|
|
23
|
+
depositAPY: number;
|
|
24
|
+
underlyingAPY: number;
|
|
25
|
+
extraAPY: PoolExtraApy[] | undefined;
|
|
26
|
+
currentExternalList: ExternalApy[] | undefined;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Aggregates all APY components for a single pool.
|
|
30
|
+
*
|
|
31
|
+
* `depositAPY` and returned values are in "percentage" units (5 ≈ 5 %).
|
|
32
|
+
* `underlyingAPY` comes from `apyList` (scaled by `PERCENTAGE_FACTOR`),
|
|
33
|
+
* so it is divided by `PERCENTAGE_FACTOR` here.
|
|
34
|
+
*
|
|
35
|
+
* External APY: first entry in `currentExternalList`, enriched with `totalValue`.
|
|
36
|
+
*/
|
|
37
|
+
export declare function calculatePoolFullAPY({ depositAPY, underlyingAPY, extraAPY, currentExternalList, }: CalculatePoolFullAPYProps): PoolFullAPY;
|
|
38
|
+
interface CalculatePoolFullAPY7DAgoProps {
|
|
39
|
+
depositAPY: number;
|
|
40
|
+
/**
|
|
41
|
+
* Annualized supply APY from the ~7d diesel snapshot, in the same units as
|
|
42
|
+
* `depositAPY`.
|
|
43
|
+
*
|
|
44
|
+
* - `undefined` — 7d snapshot not loaded yet (`loading7DAgo: true`); supply
|
|
45
|
+
* row uses `depositAPY`.
|
|
46
|
+
* - `null` — snapshot loaded but no numeric 7d supply; supply row uses
|
|
47
|
+
* `depositAPY` (`||` semantics, same as client `pool7DAgo` with missing
|
|
48
|
+
* `supplyAPY7DAgo`).
|
|
49
|
+
* - `number` — explicit 7d supply; `0` falls back to `depositAPY` via `||`.
|
|
50
|
+
*/
|
|
51
|
+
supplyAPY7DAgo?: number | null;
|
|
52
|
+
poolAPY?: PoolFullAPY | null;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Computes the 7-days-ago APY snapshot for a pool.
|
|
56
|
+
*
|
|
57
|
+
* `supplyAPY7DAgo` replaces the current deposit APY in the base component;
|
|
58
|
+
* extra & external APY are kept from the "current" calculation.
|
|
59
|
+
*/
|
|
60
|
+
export declare function calculatePoolFullAPY7DAgo({ supplyAPY7DAgo, depositAPY, poolAPY, }: CalculatePoolFullAPY7DAgoProps): PoolFullAPY7DAgo;
|
|
61
|
+
interface CalculatePoolPointsProps {
|
|
62
|
+
poolTokenSymbol: string | undefined;
|
|
63
|
+
points: PoolPointsBase[Address] | undefined;
|
|
64
|
+
tokensList: TokensMeta;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Transforms raw `PoolPointsBase` entries into consumer-friendly
|
|
68
|
+
* `PoolPointsWithTips` items with formatted amounts and tooltip strings.
|
|
69
|
+
*/
|
|
70
|
+
export declare function calculatePoolPoints({ poolTokenSymbol, points, tokensList, }: CalculatePoolPointsProps): PoolPointsWithTips[] | undefined;
|
|
71
|
+
export {};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Address } from "viem";
|
|
2
|
+
import type { ExternalApy, ExtraCollateralAPY, GearAPYDetails, PointsInfo, PoolExtraApy, PoolPointsInfo } from "../../rewards/apy/index.js";
|
|
2
3
|
import type { BaseContractStateHuman } from "../../sdk/index.js";
|
|
3
4
|
export interface Pool7DAgoState {
|
|
4
5
|
pool: Address;
|
|
@@ -7,3 +8,30 @@ export interface Pool7DAgoState {
|
|
|
7
8
|
export interface Pools7DAgoStateHuman extends BaseContractStateHuman {
|
|
8
9
|
dieselRate: bigint;
|
|
9
10
|
}
|
|
11
|
+
export interface FarmRewardInfo {
|
|
12
|
+
address: Address;
|
|
13
|
+
symbol: string;
|
|
14
|
+
rewardToken: Address;
|
|
15
|
+
rewardSymbol: string;
|
|
16
|
+
token: Address;
|
|
17
|
+
duration: bigint;
|
|
18
|
+
finished: bigint;
|
|
19
|
+
reward: bigint;
|
|
20
|
+
balance: bigint;
|
|
21
|
+
}
|
|
22
|
+
export interface NetworkApyData {
|
|
23
|
+
apyList: Record<Address, number> | undefined;
|
|
24
|
+
extraCollateralAPYList: Record<Address, Record<Address, ExtraCollateralAPY>> | undefined;
|
|
25
|
+
pointsList: Record<Address, PointsInfo<string>> | undefined;
|
|
26
|
+
extraCollateralPointsList: Record<Address, Record<Address, PointsInfo<string>>> | undefined;
|
|
27
|
+
poolRewardsList: Record<Address, Array<PoolPointsInfo<string>>> | undefined;
|
|
28
|
+
tokenExtraRewardsList: Record<Address, Array<FarmRewardInfo>> | undefined;
|
|
29
|
+
poolExternalAPYList: Record<Address, Array<ExternalApy>> | undefined;
|
|
30
|
+
poolExtraAPYList: Record<Address, Array<PoolExtraApy>> | undefined;
|
|
31
|
+
}
|
|
32
|
+
export type GearStats = Omit<GearAPYDetails, "lastUpdated">;
|
|
33
|
+
export interface ApySnapshotState {
|
|
34
|
+
apy: NetworkApyData;
|
|
35
|
+
gearStats: GearStats | null;
|
|
36
|
+
timestamp: string;
|
|
37
|
+
}
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import type { Address } from "viem";
|
|
2
2
|
import { type NetworkType } from "../../sdk/index.js";
|
|
3
|
-
|
|
3
|
+
export interface PoolData {
|
|
4
|
+
address: Address;
|
|
5
|
+
version: number;
|
|
6
|
+
underlyingToken: Address;
|
|
7
|
+
dieselRateRay: bigint;
|
|
8
|
+
dieselToken: Address;
|
|
9
|
+
stakedDieselToken: Address[];
|
|
10
|
+
stakedDieselToken_old: Address[];
|
|
11
|
+
expectedLiquidity: bigint;
|
|
12
|
+
}
|
|
4
13
|
export interface GearboxExtraMerkleLmReward {
|
|
5
14
|
pool: Address;
|
|
6
15
|
poolToken: Address;
|