@1delta/margin-fetcher 0.0.34 → 0.0.36
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/abis/morpho/lens.d.ts +38 -15
- package/dist/abis/morpho/lens.d.ts.map +1 -1
- package/dist/abis/morpho/lens.js +30 -20
- package/dist/flash-liquidity/assets.d.ts +2 -2
- package/dist/flash-liquidity/assets.d.ts.map +1 -1
- package/dist/flash-liquidity/assets.js +2 -2
- package/dist/flash-liquidity/fetchLiquidity.d.ts.map +1 -1
- package/dist/flash-liquidity/fetchLiquidity.js +2 -2
- package/dist/lending/fetchLender.d.ts.map +1 -1
- package/dist/lending/fetchLender.js +24 -5
- package/dist/lending/fetchLenderAll.d.ts.map +1 -1
- package/dist/lending/fetchLenderAll.js +15 -3
- package/dist/lending/morpho/chainsConfigs.d.ts +21 -0
- package/dist/lending/morpho/chainsConfigs.d.ts.map +1 -0
- package/dist/lending/morpho/chainsConfigs.js +234 -0
- package/dist/lending/morpho/constants/markets.d.ts +4 -0
- package/dist/lending/morpho/constants/markets.d.ts.map +1 -0
- package/dist/lending/morpho/constants/markets.js +63 -0
- package/dist/lending/morpho/convertPublic.d.ts.map +1 -1
- package/dist/lending/morpho/convertPublic.js +2 -13
- package/dist/lending/morpho/getMarketsFromChain.d.ts +8 -0
- package/dist/lending/morpho/getMarketsFromChain.d.ts.map +1 -0
- package/dist/lending/morpho/getMarketsFromChain.js +318 -0
- package/dist/lending/morpho/publicCallBuild.d.ts +5 -0
- package/dist/lending/morpho/publicCallBuild.d.ts.map +1 -1
- package/dist/lending/morpho/publicCallBuild.js +16 -0
- package/dist/lending/morpho/utils/evmParser.d.ts +22 -0
- package/dist/lending/morpho/utils/evmParser.d.ts.map +1 -0
- package/dist/lending/morpho/utils/evmParser.js +103 -0
- package/dist/lending/morpho/utils/mathLib.d.ts +125 -0
- package/dist/lending/morpho/utils/mathLib.d.ts.map +1 -0
- package/dist/lending/morpho/utils/mathLib.js +334 -0
- package/dist/lending/morpho/utils/parsers.d.ts +10 -0
- package/dist/lending/morpho/utils/parsers.d.ts.map +1 -0
- package/dist/lending/morpho/utils/parsers.js +37 -0
- package/dist/lending/user-data/aave-v2-type/userCallParse.js +2 -2
- package/dist/lending/user-data/aave-v3-type/userCallParse.js +2 -2
- package/dist/lending/user-data/aave-v3-type/userCallParseYldr.js +2 -2
- package/dist/lending/user-data/abis.d.ts +37 -14
- package/dist/lending/user-data/abis.d.ts.map +1 -1
- package/dist/lending/user-data/morpho/userCallBuild.d.ts +3 -0
- package/dist/lending/user-data/morpho/userCallBuild.d.ts.map +1 -1
- package/dist/lending/user-data/morpho/userCallBuild.js +9 -8
- package/dist/lending-pairs/computeLendingPairs.d.ts.map +1 -1
- package/dist/lending-pairs/computeLendingPairs.js +11 -7
- package/dist/prices/main-prices/fetchOracleData.d.ts +0 -2
- package/dist/prices/main-prices/fetchOracleData.d.ts.map +1 -1
- package/dist/prices/main-prices/fetchOracleData.js +2 -22
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +2 -5
- package/dist/utils/parsing.d.ts +2 -0
- package/dist/utils/parsing.d.ts.map +1 -1
- package/dist/utils/parsing.js +20 -0
- package/package.json +1 -1
- package/src/abis/morpho/lens.ts +40 -30
- package/src/flash-liquidity/assets.ts +3 -2
- package/src/flash-liquidity/fetchLiquidity.ts +3 -2
- package/src/lending/fetchLender.ts +29 -4
- package/src/lending/fetchLenderAll.ts +32 -12
- package/src/lending/morpho/chainsConfigs.ts +268 -0
- package/src/lending/morpho/constants/markets.ts +64 -0
- package/src/lending/morpho/convertPublic.ts +2 -14
- package/src/lending/morpho/getMarketsFromChain.ts +402 -0
- package/src/lending/morpho/publicCallBuild.ts +17 -0
- package/src/lending/morpho/utils/evmParser.ts +122 -0
- package/src/lending/morpho/utils/mathLib.ts +434 -0
- package/src/lending/morpho/utils/parsers.ts +53 -0
- package/src/lending/user-data/aave-v2-type/userCallParse.ts +2 -2
- package/src/lending/user-data/aave-v3-type/userCallParse.ts +2 -2
- package/src/lending/user-data/aave-v3-type/userCallParseYldr.ts +2 -2
- package/src/lending/user-data/morpho/userCallBuild.ts +9 -8
- package/src/lending-pairs/computeLendingPairs.ts +15 -10
- package/src/prices/main-prices/fetchOracleData.ts +2 -34
- package/src/utils/index.ts +3 -4
- package/src/utils/parsing.ts +32 -0
- package/test/lenderData.test.ts +1 -1
- package/test/mbChain.test.ts +44 -0
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
import { rateToApy, SECONDS_PER_YEAR } from './parsers'
|
|
2
|
+
|
|
3
|
+
export type RoundingDirection = 'Up' | 'Down'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Library to manage fixed-point arithmetic.
|
|
7
|
+
* https://github.com/morpho-org/morpho-blue/blob/main/src/libraries/MathLib.sol
|
|
8
|
+
*/
|
|
9
|
+
export namespace MathLib {
|
|
10
|
+
export const WAD = 1_000000000000000000n
|
|
11
|
+
export const RAY = 1_000000000000000000000000000n
|
|
12
|
+
|
|
13
|
+
export const MAX_UINT_256 = maxUint(256)
|
|
14
|
+
export const MAX_UINT_160 = maxUint(160)
|
|
15
|
+
export const MAX_UINT_128 = maxUint(128)
|
|
16
|
+
export const MAX_UINT_48 = maxUint(48)
|
|
17
|
+
|
|
18
|
+
export function maxUint(nBits: number) {
|
|
19
|
+
if (nBits % 4 !== 0) throw new Error(`Invalid number of bits: ${nBits}`)
|
|
20
|
+
|
|
21
|
+
return BigInt(`0x${'f'.repeat(nBits / 4)}`)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Returns the absolute value of a number
|
|
26
|
+
* @param a The number
|
|
27
|
+
*/
|
|
28
|
+
export function abs(a: bigint) {
|
|
29
|
+
a = BigInt(a)
|
|
30
|
+
|
|
31
|
+
return a >= 0 ? a : -a
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Returns the smallest number given as param
|
|
36
|
+
* @param x The first number
|
|
37
|
+
* @param y The second number
|
|
38
|
+
*/
|
|
39
|
+
export function min(...xs: bigint[]) {
|
|
40
|
+
return xs.map(BigInt).reduce((x, y) => (x <= y ? x : y))
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Returns the greatest number given as param
|
|
45
|
+
* @param x The first number
|
|
46
|
+
* @param y The second number
|
|
47
|
+
*/
|
|
48
|
+
export function max(...xs: bigint[]) {
|
|
49
|
+
return xs.map(BigInt).reduce((x, y) => (x <= y ? y : x))
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Returns the subtraction of b from a, floored to zero if negative
|
|
54
|
+
* @param x The first number
|
|
55
|
+
* @param y The second number
|
|
56
|
+
*/
|
|
57
|
+
export function zeroFloorSub(x: bigint, y: bigint) {
|
|
58
|
+
x = BigInt(x)
|
|
59
|
+
y = BigInt(y)
|
|
60
|
+
|
|
61
|
+
return x <= y ? 0n : x - y
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Perform the WAD-based multiplication of 2 numbers, rounded down
|
|
66
|
+
* @param x The first number
|
|
67
|
+
* @param y The second number
|
|
68
|
+
*/
|
|
69
|
+
export function wMulDown(x: bigint, y: bigint) {
|
|
70
|
+
return MathLib.wMul(x, y, 'Down')
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Perform the WAD-based multiplication of 2 numbers, rounded up
|
|
75
|
+
* @param x The first number
|
|
76
|
+
* @param y The second number
|
|
77
|
+
*/
|
|
78
|
+
export function wMulUp(x: bigint, y: bigint) {
|
|
79
|
+
return MathLib.wMul(x, y, 'Up')
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Perform the WAD-based multiplication of 2 numbers with a provided rounding direction
|
|
84
|
+
* @param x The first number
|
|
85
|
+
* @param y The second number
|
|
86
|
+
*/
|
|
87
|
+
export function wMul(x: bigint, y: bigint, rounding: RoundingDirection) {
|
|
88
|
+
return MathLib.mulDiv(x, y, MathLib.WAD, rounding)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Perform the WAD-based division of 2 numbers, rounded down
|
|
93
|
+
* @param x The first number
|
|
94
|
+
* @param y The second number
|
|
95
|
+
*/
|
|
96
|
+
export function wDivDown(x: bigint, y: bigint) {
|
|
97
|
+
return MathLib.wDiv(x, y, 'Down')
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Perform the WAD-based multiplication of 2 numbers, rounded up
|
|
102
|
+
* @param x The first number
|
|
103
|
+
* @param y The second number
|
|
104
|
+
*/
|
|
105
|
+
export function wDivUp(x: bigint, y: bigint) {
|
|
106
|
+
return MathLib.wDiv(x, y, 'Up')
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Perform the WAD-based multiplication of 2 numbers with a provided rounding direction
|
|
111
|
+
* @param x The first number
|
|
112
|
+
* @param y The second number
|
|
113
|
+
*/
|
|
114
|
+
export function wDiv(x: bigint, y: bigint, rounding: RoundingDirection) {
|
|
115
|
+
return MathLib.mulDiv(x, MathLib.WAD, y, rounding)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Multiply two numbers and divide by a denominator, rounding down the result
|
|
120
|
+
* @param x The first number
|
|
121
|
+
* @param y The second number
|
|
122
|
+
* @param denominator The denominator
|
|
123
|
+
*/
|
|
124
|
+
export function mulDivDown(x: bigint, y: bigint, denominator: bigint) {
|
|
125
|
+
x = BigInt(x)
|
|
126
|
+
y = BigInt(y)
|
|
127
|
+
denominator = BigInt(denominator)
|
|
128
|
+
if (denominator === 0n) throw Error('MathLib: DIVISION_BY_ZERO')
|
|
129
|
+
|
|
130
|
+
return (x * y) / denominator
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Multiply two numbers and divide by a denominator, rounding up the result
|
|
135
|
+
* @param x The first number
|
|
136
|
+
* @param y The second number
|
|
137
|
+
* @param denominator The denominator
|
|
138
|
+
*/
|
|
139
|
+
export function mulDivUp(x: bigint, y: bigint, denominator: bigint) {
|
|
140
|
+
x = BigInt(x)
|
|
141
|
+
y = BigInt(y)
|
|
142
|
+
denominator = BigInt(denominator)
|
|
143
|
+
if (denominator === 0n) throw Error('MathLib: DIVISION_BY_ZERO')
|
|
144
|
+
|
|
145
|
+
const roundup = (x * y) % denominator > 0 ? 1n : 0n
|
|
146
|
+
|
|
147
|
+
return (x * y) / denominator + roundup
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export function mulDiv(
|
|
151
|
+
x: bigint,
|
|
152
|
+
y: bigint,
|
|
153
|
+
denominator: bigint,
|
|
154
|
+
rounding: RoundingDirection,
|
|
155
|
+
) {
|
|
156
|
+
return MathLib[`mulDiv${rounding}`](x, y, denominator)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* The sum of the first three non-zero terms of a Taylor expansion of e^(nx) - 1,
|
|
161
|
+
* to approximate a continuously compounded interest rate.
|
|
162
|
+
*
|
|
163
|
+
* @param x The base of the exponent
|
|
164
|
+
* @param n The exponent
|
|
165
|
+
*/
|
|
166
|
+
export function wTaylorCompounded(x: bigint, n: bigint) {
|
|
167
|
+
const firstTerm = BigInt(x) * BigInt(n)
|
|
168
|
+
const secondTerm = MathLib.mulDivDown(
|
|
169
|
+
firstTerm,
|
|
170
|
+
firstTerm,
|
|
171
|
+
2n * MathLib.WAD,
|
|
172
|
+
)
|
|
173
|
+
const thirdTerm = MathLib.mulDivDown(
|
|
174
|
+
secondTerm,
|
|
175
|
+
firstTerm,
|
|
176
|
+
3n * MathLib.WAD,
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
return firstTerm + secondTerm + thirdTerm
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Converts a WAD-based quantity to a RAY-based quantity.
|
|
184
|
+
* @param x The WAD-based quantity.
|
|
185
|
+
*/
|
|
186
|
+
export function wToRay(x: bigint) {
|
|
187
|
+
return BigInt(x) * 1_000000000n
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Returns the market's utilization rate (scaled by WAD).
|
|
192
|
+
* @param market The market state.
|
|
193
|
+
*/
|
|
194
|
+
export function getUtilization({
|
|
195
|
+
totalSupplyAssets,
|
|
196
|
+
totalBorrowAssets,
|
|
197
|
+
}: {
|
|
198
|
+
totalSupplyAssets: bigint
|
|
199
|
+
totalBorrowAssets: bigint
|
|
200
|
+
}) {
|
|
201
|
+
if (totalSupplyAssets === 0n) {
|
|
202
|
+
if (totalBorrowAssets > 0n) return MathLib.MAX_UINT_256
|
|
203
|
+
|
|
204
|
+
return 0n
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return MathLib.wDivDown(totalBorrowAssets, totalSupplyAssets)
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* The market's instantaneous supply-side Annual Percentage Yield (APY) at the given timestamp,
|
|
212
|
+
* if the state remains unchanged (not accrued) (scaled by WAD).
|
|
213
|
+
* @param timestamp The timestamp at which to calculate the supply APY.
|
|
214
|
+
* Must be greater than or equal to `lastUpdate`.
|
|
215
|
+
* Defaults to `Time.timestamp()` (returns the current supply APY).
|
|
216
|
+
*/
|
|
217
|
+
export function getSupplyApy(
|
|
218
|
+
borrowApy: bigint,
|
|
219
|
+
utilization: bigint,
|
|
220
|
+
fee: bigint,
|
|
221
|
+
) {
|
|
222
|
+
if (!utilization) return 0n
|
|
223
|
+
return MathLib.wMulUp(
|
|
224
|
+
MathLib.wMulDown(borrowApy, utilization),
|
|
225
|
+
MathLib.WAD - fee,
|
|
226
|
+
)
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Returns the rates that _would_ apply to interest accrual for borrowers of this market,
|
|
231
|
+
* if `accrueInterest` was called at the given timestamp (scaled by WAD).
|
|
232
|
+
* @param timestamp The timestamp at which to calculate the accrual borrow rate.
|
|
233
|
+
* Must be greater than or equal to `lastUpdate`.
|
|
234
|
+
* Defaults to `Time.timestamp()` (returns the current accrual borrow rate).
|
|
235
|
+
*/
|
|
236
|
+
function getAccrualBorrowRates(
|
|
237
|
+
rateAtTarget: bigint | null,
|
|
238
|
+
utilization: bigint,
|
|
239
|
+
_timestamp: number = Math.floor(Date.now() / 1000),
|
|
240
|
+
_lastUpdate: number,
|
|
241
|
+
):
|
|
242
|
+
| {
|
|
243
|
+
elapsed: bigint
|
|
244
|
+
avgBorrowRate: bigint
|
|
245
|
+
endBorrowRate: bigint
|
|
246
|
+
endRateAtTarget?: bigint
|
|
247
|
+
}
|
|
248
|
+
| undefined {
|
|
249
|
+
const timestamp = BigInt(_timestamp)
|
|
250
|
+
|
|
251
|
+
const elapsed = timestamp - BigInt(_lastUpdate)
|
|
252
|
+
if (elapsed < 0n) return undefined
|
|
253
|
+
|
|
254
|
+
if (rateAtTarget == null)
|
|
255
|
+
return {
|
|
256
|
+
elapsed,
|
|
257
|
+
avgBorrowRate: 0n,
|
|
258
|
+
endBorrowRate: 0n,
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return {
|
|
262
|
+
elapsed,
|
|
263
|
+
..._getBorrowRate(utilization, rateAtTarget, elapsed),
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
*/
|
|
269
|
+
function getEndBorrowRate(
|
|
270
|
+
rateAtTarget: bigint | null,
|
|
271
|
+
utilization: bigint,
|
|
272
|
+
_timestamp: number = Math.floor(Date.now() / 1000),
|
|
273
|
+
_lastUpdate: number,
|
|
274
|
+
) {
|
|
275
|
+
return getAccrualBorrowRates(
|
|
276
|
+
rateAtTarget,
|
|
277
|
+
utilization,
|
|
278
|
+
_timestamp,
|
|
279
|
+
_lastUpdate,
|
|
280
|
+
)?.endBorrowRate
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
export function getBorrowApy(
|
|
284
|
+
rateAtTarget: bigint | null,
|
|
285
|
+
utilization: bigint,
|
|
286
|
+
_timestamp: number = Math.floor(Date.now() / 1000),
|
|
287
|
+
_lastUpdate: number,
|
|
288
|
+
) {
|
|
289
|
+
const borrowRate = getEndBorrowRate(
|
|
290
|
+
rateAtTarget,
|
|
291
|
+
utilization,
|
|
292
|
+
_timestamp,
|
|
293
|
+
_lastUpdate,
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
return borrowRate ? rateToApy(borrowRate) : 0n
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const CURVE_STEEPNESS = 4_000000000000000000n
|
|
300
|
+
const TARGET_UTILIZATION = 90_0000000000000000n
|
|
301
|
+
const INITIAL_RATE_AT_TARGET = 4_0000000000000000n / SECONDS_PER_YEAR
|
|
302
|
+
const ADJUSTMENT_SPEED = 50_000000000000000000n / SECONDS_PER_YEAR
|
|
303
|
+
const MIN_RATE_AT_TARGET = 10_00000000000000n / SECONDS_PER_YEAR
|
|
304
|
+
const MAX_RATE_AT_TARGET = 2_000000000000000000n / SECONDS_PER_YEAR
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* ln(2), scaled by WAD.
|
|
308
|
+
*/
|
|
309
|
+
const LN_2_INT = 693147180559945309n
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* ln(1e-18), scaled by WAD.
|
|
313
|
+
*/
|
|
314
|
+
const LN_WEI_INT = -41_446531673892822312n
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Above this bound, `wExp` is clipped to avoid overflowing when multiplied with 1 ether.
|
|
318
|
+
* This upper bound corresponds to: ln(type(int256).max / 1e36) (scaled by WAD, floored).
|
|
319
|
+
*/
|
|
320
|
+
const WEXP_UPPER_BOUND = 93_859467695000404319n
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* The value of wExp(`WEXP_UPPER_BOUND`).
|
|
324
|
+
*/
|
|
325
|
+
const WEXP_UPPER_VALUE =
|
|
326
|
+
57716089161558943949701069502944508345128_422502756744429568n
|
|
327
|
+
|
|
328
|
+
export function wExp(x: bigint) {
|
|
329
|
+
x = BigInt(x)
|
|
330
|
+
|
|
331
|
+
// If x < ln(1e-18) then exp(x) < 1e-18 so it is rounded to zero.
|
|
332
|
+
if (x < LN_WEI_INT) return 0n
|
|
333
|
+
// `wExp` is clipped to avoid overflowing when multiplied with 1 ether.
|
|
334
|
+
if (x >= WEXP_UPPER_BOUND) return WEXP_UPPER_VALUE
|
|
335
|
+
|
|
336
|
+
// Decompose x as x = q * ln(2) + r with q an integer and -ln(2)/2 <= r <= ln(2)/2.
|
|
337
|
+
// q = x / ln(2) rounded half toward zero.
|
|
338
|
+
const roundingAdjustment = x < 0n ? -(LN_2_INT / 2n) : LN_2_INT / 2n
|
|
339
|
+
const q = (x + roundingAdjustment) / LN_2_INT
|
|
340
|
+
const r = x - q * LN_2_INT
|
|
341
|
+
|
|
342
|
+
// Compute e^r with a 2nd-order Taylor polynomial.
|
|
343
|
+
const expR = MathLib.WAD + r + (r * r) / MathLib.WAD / 2n
|
|
344
|
+
|
|
345
|
+
// Return e^x = 2^q * e^r.
|
|
346
|
+
if (q >= 0n) return expR << q
|
|
347
|
+
return expR >> -q
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
export function _getBorrowRate(
|
|
351
|
+
startUtilization: bigint,
|
|
352
|
+
startRateAtTarget: bigint,
|
|
353
|
+
elapsed: bigint,
|
|
354
|
+
) {
|
|
355
|
+
startUtilization = BigInt(startUtilization)
|
|
356
|
+
startRateAtTarget = BigInt(startRateAtTarget)
|
|
357
|
+
elapsed = BigInt(elapsed)
|
|
358
|
+
|
|
359
|
+
const errNormFactor =
|
|
360
|
+
startUtilization > TARGET_UTILIZATION
|
|
361
|
+
? MathLib.WAD - TARGET_UTILIZATION
|
|
362
|
+
: TARGET_UTILIZATION
|
|
363
|
+
const err = MathLib.wDivDown(
|
|
364
|
+
startUtilization - TARGET_UTILIZATION,
|
|
365
|
+
errNormFactor,
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
let avgRateAtTarget: bigint
|
|
369
|
+
let endRateAtTarget: bigint
|
|
370
|
+
|
|
371
|
+
if (startRateAtTarget === 0n) {
|
|
372
|
+
// First interaction.
|
|
373
|
+
avgRateAtTarget = INITIAL_RATE_AT_TARGET
|
|
374
|
+
endRateAtTarget = INITIAL_RATE_AT_TARGET
|
|
375
|
+
} else {
|
|
376
|
+
// The speed is assumed constant between two updates, but it is in fact not constant because of interest.
|
|
377
|
+
// So the rate is always underestimated.
|
|
378
|
+
const speed = MathLib.wMulDown(ADJUSTMENT_SPEED, err)
|
|
379
|
+
const linearAdaptation = speed * elapsed
|
|
380
|
+
|
|
381
|
+
if (linearAdaptation === 0n) {
|
|
382
|
+
// If linearAdaptation == 0, avgRateAtTarget = endRateAtTarget = startRateAtTarget;
|
|
383
|
+
avgRateAtTarget = startRateAtTarget
|
|
384
|
+
endRateAtTarget = startRateAtTarget
|
|
385
|
+
} else {
|
|
386
|
+
// Non negative because MIN_RATE_AT_TARGET > 0.
|
|
387
|
+
const _newRateAtTarget = (linearAdaptation: bigint) =>
|
|
388
|
+
MathLib.min(
|
|
389
|
+
MathLib.max(
|
|
390
|
+
MathLib.wMulDown(startRateAtTarget, wExp(linearAdaptation)),
|
|
391
|
+
MIN_RATE_AT_TARGET,
|
|
392
|
+
),
|
|
393
|
+
MAX_RATE_AT_TARGET,
|
|
394
|
+
)
|
|
395
|
+
|
|
396
|
+
// Formula of the average rate that should be returned to Morpho Blue:
|
|
397
|
+
// avg = 1/T * ∫_0^T curve(startRateAtTarget*exp(speed*x), err) dx
|
|
398
|
+
// The integral is approximated with the trapezoidal rule:
|
|
399
|
+
// avg ~= 1/T * Σ_i=1^N [curve(f((i-1) * T/N), err) + curve(f(i * T/N), err)] / 2 * T/N
|
|
400
|
+
// Where f(x) = startRateAtTarget*exp(speed*x)
|
|
401
|
+
// avg ~= Σ_i=1^N [curve(f((i-1) * T/N), err) + curve(f(i * T/N), err)] / (2 * N)
|
|
402
|
+
// As curve is linear in its first argument:
|
|
403
|
+
// avg ~= curve([Σ_i=1^N [f((i-1) * T/N) + f(i * T/N)] / (2 * N), err)
|
|
404
|
+
// avg ~= curve([(f(0) + f(T))/2 + Σ_i=1^(N-1) f(i * T/N)] / N, err)
|
|
405
|
+
// avg ~= curve([(startRateAtTarget + endRateAtTarget)/2 + Σ_i=1^(N-1) f(i * T/N)] / N, err)
|
|
406
|
+
// With N = 2:
|
|
407
|
+
// avg ~= curve([(startRateAtTarget + endRateAtTarget)/2 + startRateAtTarget*exp(speed*T/2)] / 2, err)
|
|
408
|
+
// avg ~= curve([startRateAtTarget + endRateAtTarget + 2*startRateAtTarget*exp(speed*T/2)] / 4, err)
|
|
409
|
+
endRateAtTarget = _newRateAtTarget(linearAdaptation)
|
|
410
|
+
avgRateAtTarget =
|
|
411
|
+
(startRateAtTarget +
|
|
412
|
+
endRateAtTarget +
|
|
413
|
+
2n * _newRateAtTarget(linearAdaptation / 2n)) /
|
|
414
|
+
4n
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// Non negative because 1 - 1/C >= 0, C - 1 >= 0.
|
|
419
|
+
const coeff =
|
|
420
|
+
err < 0
|
|
421
|
+
? MathLib.WAD - MathLib.wDivDown(MathLib.WAD, CURVE_STEEPNESS)
|
|
422
|
+
: CURVE_STEEPNESS - MathLib.WAD
|
|
423
|
+
|
|
424
|
+
const _curve = (rateAtTarget: bigint) =>
|
|
425
|
+
MathLib.wMulDown(MathLib.wMulDown(coeff, err) + MathLib.WAD, rateAtTarget)
|
|
426
|
+
|
|
427
|
+
// Non negative if avgRateAtTarget >= 0 because if err < 0, coeff <= 1.
|
|
428
|
+
return {
|
|
429
|
+
avgBorrowRate: _curve(avgRateAtTarget),
|
|
430
|
+
endBorrowRate: _curve(endRateAtTarget),
|
|
431
|
+
endRateAtTarget,
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { formatEther, formatUnits, parseUnits } from 'viem'
|
|
2
|
+
|
|
3
|
+
export const SECONDS_PER_YEAR = 31_556_952n
|
|
4
|
+
|
|
5
|
+
// Alternative to Number.toFixed that doesn't use scientific notation for excessively small or large numbers.
|
|
6
|
+
const toFixed = (x: number, decimals: number) =>
|
|
7
|
+
new Intl.NumberFormat('en-US', {
|
|
8
|
+
style: 'decimal',
|
|
9
|
+
useGrouping: false,
|
|
10
|
+
maximumFractionDigits: decimals,
|
|
11
|
+
minimumFractionDigits: decimals,
|
|
12
|
+
}).format(x)
|
|
13
|
+
|
|
14
|
+
const safeParseNumber = (value: number, decimals = 18) =>
|
|
15
|
+
safeParseUnits(toFixed(value, decimals), decimals)
|
|
16
|
+
|
|
17
|
+
const safeParseUnits = (strValue: string, decimals = 18) => {
|
|
18
|
+
if (!/[-+]?[0-9]*\.?[0-9]+/.test(strValue))
|
|
19
|
+
throw Error(`invalid number: ${strValue}`)
|
|
20
|
+
|
|
21
|
+
let [whole, dec = ''] = strValue.split('.')
|
|
22
|
+
|
|
23
|
+
dec = dec.slice(0, decimals)
|
|
24
|
+
|
|
25
|
+
return parseUnits(
|
|
26
|
+
[whole || '0', dec].filter((v) => v.length > 0).join('.'),
|
|
27
|
+
decimals,
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Returns the per-second rate continuously compounded over a year (scaled by WAD),
|
|
33
|
+
* as calculated in Morpho Blue assuming the market is frequently accrued onchain.
|
|
34
|
+
* @param rate The per-second rate to compound annually (scaled by WAD).
|
|
35
|
+
*/
|
|
36
|
+
// TODO: return a Number for APYs.
|
|
37
|
+
export function rateToApy(rate: bigint) {
|
|
38
|
+
return safeParseNumber(
|
|
39
|
+
Math.expm1(+formatEther(BigInt(rate) * SECONDS_PER_YEAR)),
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function parseLtv(ltv: bigint | number | string) {
|
|
44
|
+
let str = 0
|
|
45
|
+
try {
|
|
46
|
+
str = Number(formatUnits(BigInt(ltv), 18))
|
|
47
|
+
} catch (e) {}
|
|
48
|
+
return str
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function formatNr(n: string | bigint, d: number) {
|
|
52
|
+
return Number(formatUnits(BigInt(n ?? 0), d))
|
|
53
|
+
}
|
|
@@ -375,8 +375,8 @@ function createAaveV2Entry(
|
|
|
375
375
|
const priceHist = pricesHist?.[key] ?? price
|
|
376
376
|
|
|
377
377
|
const dataForAsset = {
|
|
378
|
-
poolId: asset,
|
|
379
|
-
underlying: asset,
|
|
378
|
+
poolId: asset.address,
|
|
379
|
+
underlying: asset.address,
|
|
380
380
|
deposits: currentATokenBalance,
|
|
381
381
|
depositsRaw: currentATokenBalanceRaw,
|
|
382
382
|
debtStable: currentStableDebt,
|
|
@@ -114,8 +114,8 @@ function createAaveV3Entry(
|
|
|
114
114
|
const priceHist = pricesHist?.[key] ?? price
|
|
115
115
|
|
|
116
116
|
const dataForAsset = {
|
|
117
|
-
poolId: asset,
|
|
118
|
-
underlying: asset,
|
|
117
|
+
poolId: asset.address,
|
|
118
|
+
underlying: asset.address,
|
|
119
119
|
deposits: currentATokenBalance,
|
|
120
120
|
depositsRaw: currentATokenBalanceRaw,
|
|
121
121
|
debtStable: currentStableDebt,
|
|
@@ -103,8 +103,8 @@ function createAaveV3Entry(
|
|
|
103
103
|
const priceHist = pricesHist?.[key] ?? price
|
|
104
104
|
|
|
105
105
|
const dataForAsset = {
|
|
106
|
-
poolId: asset,
|
|
107
|
-
underlying: asset,
|
|
106
|
+
poolId: asset.address,
|
|
107
|
+
underlying: asset.address,
|
|
108
108
|
deposits: currentATokenBalance,
|
|
109
109
|
depositsRaw: currentATokenBalanceRaw,
|
|
110
110
|
debtStable: '0',
|
|
@@ -4,14 +4,15 @@ import { Call } from '../../../utils/multicall'
|
|
|
4
4
|
import { chunk } from 'lodash'
|
|
5
5
|
import { morphoPools } from '@1delta/data-sdk'
|
|
6
6
|
|
|
7
|
-
const MORPHO_LENS: { [c: string]: string } = {
|
|
8
|
-
[Chain.BASE]: '
|
|
9
|
-
[Chain.POLYGON_MAINNET]: '
|
|
10
|
-
[Chain.OP_MAINNET]: '
|
|
11
|
-
[Chain.ARBITRUM_ONE]: '
|
|
12
|
-
[Chain.KATANA]: '
|
|
13
|
-
[Chain.HYPEREVM]: '
|
|
14
|
-
[Chain.
|
|
7
|
+
export const MORPHO_LENS: { [c: string]: string } = {
|
|
8
|
+
[Chain.BASE]: '0x05f3f58716a88A52493Be45aA0871c55b3748f18',
|
|
9
|
+
[Chain.POLYGON_MAINNET]: '0x04102873b1A80647879Aa8B8a119F07aE08f457a',
|
|
10
|
+
[Chain.OP_MAINNET]: '0x61895aEB0a42679E2Df8EE64334C405a8d47D244',
|
|
11
|
+
[Chain.ARBITRUM_ONE]: '0xeaC918F73Ba5b11D21D31a72BD00ca4A22865C3f',
|
|
12
|
+
[Chain.KATANA]: '0xCe434378adacC51d54312c872113D687Ac19B516',
|
|
13
|
+
[Chain.HYPEREVM]: '0x6Bc6aCB905c1216B0119C87Bf9E178ce298310FA',
|
|
14
|
+
[Chain.SONEIUM]: '0x4b5458BB47dCBC1a41B31b41e1a8773dE312BE9d',
|
|
15
|
+
[Chain.ETHEREUM_MAINNET]: '0x4b5458BB47dCBC1a41B31b41e1a8773dE312BE9d'
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
const getBaseMorphoCalls = (
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
} from '../assets/liquidityThresholds'
|
|
7
7
|
import { GenericCurrency } from '../lending/types'
|
|
8
8
|
import { ConfigEntry, LenderData, PoolData } from '../types'
|
|
9
|
-
import { isAaveV3Type, isInit } from '../utils'
|
|
9
|
+
import { isAaveV3Type, isInit, isMorphoType } from '../utils'
|
|
10
10
|
|
|
11
11
|
interface SimpleAssetInfo {
|
|
12
12
|
asset: GenericCurrency
|
|
@@ -252,7 +252,8 @@ function getPriceKey(asset: GenericCurrency): [string, string] {
|
|
|
252
252
|
const assetGroup = asset?.assetGroup
|
|
253
253
|
return [
|
|
254
254
|
assetGroup,
|
|
255
|
-
toOracleKey(assetGroup) ??
|
|
255
|
+
toOracleKey(assetGroup) ??
|
|
256
|
+
toGenericPriceKey(asset?.address, asset?.chainId),
|
|
256
257
|
]
|
|
257
258
|
}
|
|
258
259
|
|
|
@@ -301,14 +302,18 @@ function filterPairsByCategory(
|
|
|
301
302
|
p.assetGroupShort,
|
|
302
303
|
)
|
|
303
304
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
305
|
+
// note: morpho does not allow to borrow collateral
|
|
306
|
+
// therefore, the collateral is always withdrawable if debt is repaid
|
|
307
|
+
const longMeetsThresholds =
|
|
308
|
+
isMorphoType(p.lender) ||
|
|
309
|
+
meetsLiquidityThresholdsLong(
|
|
310
|
+
{
|
|
311
|
+
totalDepositsUSD: p.longTotalDepositsUSD,
|
|
312
|
+
totalDebtUSD: p.longTotalDebtUSD,
|
|
313
|
+
totalLiquidityUSD: p.longTotalLiquidityUSD,
|
|
314
|
+
},
|
|
315
|
+
longThresholds,
|
|
316
|
+
)
|
|
312
317
|
|
|
313
318
|
const shortMeetsThresholds = meetsLiquidityThresholdsShort(
|
|
314
319
|
{
|
|
@@ -7,7 +7,7 @@ import { RWADynamicOracleAbi } from '../../abis/oracle/RWADynamicOracle'
|
|
|
7
7
|
import { api3OracleAddresses } from './addresses/api3'
|
|
8
8
|
import { AAVE_V2_LENDERS } from '@1delta/lender-registry'
|
|
9
9
|
import { Chain } from '@1delta/chain-registry'
|
|
10
|
-
import {
|
|
10
|
+
import { formatUnits } from 'viem'
|
|
11
11
|
import { getAaveAssets } from '../../assets'
|
|
12
12
|
import {
|
|
13
13
|
chainlinkOracles,
|
|
@@ -17,45 +17,13 @@ import {
|
|
|
17
17
|
import { fetchDefillamaData } from '../defillama'
|
|
18
18
|
import { fetchPendlePrices } from '../pendle'
|
|
19
19
|
import { getAavesForChain } from '../../utils'
|
|
20
|
-
import { parseRawAmount } from '../../utils/parsing'
|
|
20
|
+
import { formatAavePrice, formatMorphoPrice, parseRawAmount } from '../../utils/parsing'
|
|
21
21
|
import { ProxyOracleAbi } from '../../abis/oracle/ProxyOracle'
|
|
22
22
|
import { multicallRetry } from '@1delta/providers'
|
|
23
23
|
import { TokenList } from '../../types'
|
|
24
24
|
import { UniswapV3Abi } from '../../abis/oracle/UniV3'
|
|
25
25
|
import { aaveOracles, morphoOracles } from '@1delta/data-sdk'
|
|
26
26
|
|
|
27
|
-
export const formatAavePrice = (price: string, isV2 = false): number => {
|
|
28
|
-
try {
|
|
29
|
-
return Number(
|
|
30
|
-
formatEther(
|
|
31
|
-
BigInt(price ?? '0') *
|
|
32
|
-
// 10^(18 - decimals)
|
|
33
|
-
10n ** (isV2 ? 0n : 10n),
|
|
34
|
-
),
|
|
35
|
-
)
|
|
36
|
-
} catch {
|
|
37
|
-
return NaN
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export const formatMorphoPrice = (
|
|
42
|
-
price: string,
|
|
43
|
-
collateralDec: number,
|
|
44
|
-
debtDec: number,
|
|
45
|
-
): number => {
|
|
46
|
-
try {
|
|
47
|
-
return Number(
|
|
48
|
-
formatUnits(
|
|
49
|
-
BigInt(price ?? '0'),
|
|
50
|
-
// 10^(18 - decimals)
|
|
51
|
-
36 + collateralDec - debtDec,
|
|
52
|
-
),
|
|
53
|
-
)
|
|
54
|
-
} catch {
|
|
55
|
-
return NaN
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
27
|
const LENDLE_PAIR_MANTLE = '0x4c57BE599d0e0414785943569E9B6A66dA79Aa6b'
|
|
60
28
|
const AU_PAIR_MANTLE = '0x709503fbb50b10f921e812c48fbd5c5522a0b20c'
|
|
61
29
|
const WMNT_USDT_PAIR = '0x3e5922cd0cec71dc2d60ec8b36aa4c05b7c1672f'
|
package/src/utils/index.ts
CHANGED
|
@@ -63,10 +63,9 @@ export const getLendersForChain = (c: string) => {
|
|
|
63
63
|
})
|
|
64
64
|
|
|
65
65
|
// compound V3s
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
})
|
|
66
|
+
|
|
67
|
+
if (compoundV3Pools()?.[c])
|
|
68
|
+
lenders = [...lenders, ...Object.keys(compoundV3Pools()?.[c])]
|
|
70
69
|
|
|
71
70
|
// init
|
|
72
71
|
Object.entries(initConfig() ?? {}).forEach(([l, data]) => {
|
package/src/utils/parsing.ts
CHANGED
|
@@ -80,3 +80,35 @@ export const convertRateToApr = (ratePerSecond: number | string) => {
|
|
|
80
80
|
if (isNaN(rps)) return 0
|
|
81
81
|
return rps * 3600 * 24 * 365 * 100
|
|
82
82
|
}
|
|
83
|
+
|
|
84
|
+
export const formatAavePrice = (price: string, isV2 = false): number => {
|
|
85
|
+
try {
|
|
86
|
+
return Number(
|
|
87
|
+
formatEther(
|
|
88
|
+
BigInt(price ?? '0') *
|
|
89
|
+
// 10^(18 - decimals)
|
|
90
|
+
10n ** (isV2 ? 0n : 10n),
|
|
91
|
+
),
|
|
92
|
+
)
|
|
93
|
+
} catch {
|
|
94
|
+
return NaN
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export const formatMorphoPrice = (
|
|
99
|
+
price: string,
|
|
100
|
+
collateralDec: number,
|
|
101
|
+
debtDec: number,
|
|
102
|
+
): number => {
|
|
103
|
+
try {
|
|
104
|
+
return Number(
|
|
105
|
+
formatUnits(
|
|
106
|
+
BigInt(price ?? '0'),
|
|
107
|
+
// 10^(18 - decimals)
|
|
108
|
+
36 + collateralDec - debtDec,
|
|
109
|
+
),
|
|
110
|
+
)
|
|
111
|
+
} catch {
|
|
112
|
+
return NaN
|
|
113
|
+
}
|
|
114
|
+
}
|