origin-morpho-utils 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +264 -0
- package/dist/chunk-35AORYVF.cjs +709 -0
- package/dist/chunk-35AORYVF.cjs.map +1 -0
- package/dist/chunk-37KGZP4O.cjs +150 -0
- package/dist/chunk-37KGZP4O.cjs.map +1 -0
- package/dist/chunk-K2ZKPGSF.js +150 -0
- package/dist/chunk-K2ZKPGSF.js.map +1 -0
- package/dist/chunk-M43IOBUD.js +709 -0
- package/dist/chunk-M43IOBUD.js.map +1 -0
- package/dist/cli.cjs +207 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +207 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.cjs +59 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +314 -0
- package/dist/index.d.ts +314 -0
- package/dist/index.js +59 -0
- package/dist/index.js.map +1 -0
- package/dist/math-ClwpjVti.d.cts +164 -0
- package/dist/math-ClwpjVti.d.ts +164 -0
- package/dist/math.cjs +17 -0
- package/dist/math.cjs.map +1 -0
- package/dist/math.d.cts +1 -0
- package/dist/math.d.ts +1 -0
- package/dist/math.js +17 -0
- package/dist/math.js.map +1 -0
- package/package.json +77 -0
|
@@ -0,0 +1,709 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
var _chunk37KGZP4Ocjs = require('./chunk-37KGZP4O.cjs');
|
|
7
|
+
|
|
8
|
+
// src/abi/erc20.ts
|
|
9
|
+
var erc20Abi = [
|
|
10
|
+
{
|
|
11
|
+
inputs: [],
|
|
12
|
+
name: "decimals",
|
|
13
|
+
outputs: [{ name: "", type: "uint8" }],
|
|
14
|
+
stateMutability: "view",
|
|
15
|
+
type: "function"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
inputs: [],
|
|
19
|
+
name: "symbol",
|
|
20
|
+
outputs: [{ name: "", type: "string" }],
|
|
21
|
+
stateMutability: "view",
|
|
22
|
+
type: "function"
|
|
23
|
+
}
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
// src/abi/irm-adaptive-curve.ts
|
|
27
|
+
var irmAdaptiveCurveAbi = [
|
|
28
|
+
{
|
|
29
|
+
inputs: [{ name: "id", type: "bytes32" }],
|
|
30
|
+
name: "rateAtTarget",
|
|
31
|
+
outputs: [{ name: "", type: "int256" }],
|
|
32
|
+
stateMutability: "view",
|
|
33
|
+
type: "function"
|
|
34
|
+
}
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
// src/abi/meta-morpho.ts
|
|
38
|
+
var metaMorphoAbi = [
|
|
39
|
+
{
|
|
40
|
+
inputs: [],
|
|
41
|
+
name: "supplyQueueLength",
|
|
42
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
43
|
+
stateMutability: "view",
|
|
44
|
+
type: "function"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
inputs: [],
|
|
48
|
+
name: "withdrawQueueLength",
|
|
49
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
50
|
+
stateMutability: "view",
|
|
51
|
+
type: "function"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
inputs: [],
|
|
55
|
+
name: "totalAssets",
|
|
56
|
+
outputs: [{ name: "totalManagedAssets", type: "uint256" }],
|
|
57
|
+
stateMutability: "view",
|
|
58
|
+
type: "function"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
inputs: [{ name: "", type: "uint256" }],
|
|
62
|
+
name: "supplyQueue",
|
|
63
|
+
outputs: [{ name: "", type: "bytes32" }],
|
|
64
|
+
stateMutability: "view",
|
|
65
|
+
type: "function"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
inputs: [{ name: "", type: "uint256" }],
|
|
69
|
+
name: "withdrawQueue",
|
|
70
|
+
outputs: [{ name: "", type: "bytes32" }],
|
|
71
|
+
stateMutability: "view",
|
|
72
|
+
type: "function"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
inputs: [{ name: "", type: "bytes32" }],
|
|
76
|
+
name: "config",
|
|
77
|
+
outputs: [
|
|
78
|
+
{ name: "cap", type: "uint184" },
|
|
79
|
+
{ name: "enabled", type: "bool" },
|
|
80
|
+
{ name: "removableAt", type: "uint64" }
|
|
81
|
+
],
|
|
82
|
+
stateMutability: "view",
|
|
83
|
+
type: "function"
|
|
84
|
+
}
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
// src/abi/morpho.ts
|
|
88
|
+
var morphoAbi = [
|
|
89
|
+
{
|
|
90
|
+
inputs: [{ name: "id", type: "bytes32" }],
|
|
91
|
+
name: "market",
|
|
92
|
+
outputs: [
|
|
93
|
+
{ name: "totalSupplyAssets", type: "uint128" },
|
|
94
|
+
{ name: "totalSupplyShares", type: "uint128" },
|
|
95
|
+
{ name: "totalBorrowAssets", type: "uint128" },
|
|
96
|
+
{ name: "totalBorrowShares", type: "uint128" },
|
|
97
|
+
{ name: "lastUpdate", type: "uint128" },
|
|
98
|
+
{ name: "fee", type: "uint128" }
|
|
99
|
+
],
|
|
100
|
+
stateMutability: "view",
|
|
101
|
+
type: "function"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
inputs: [
|
|
105
|
+
{ name: "id", type: "bytes32" },
|
|
106
|
+
{ name: "user", type: "address" }
|
|
107
|
+
],
|
|
108
|
+
name: "position",
|
|
109
|
+
outputs: [
|
|
110
|
+
{ name: "supplyShares", type: "uint256" },
|
|
111
|
+
{ name: "borrowShares", type: "uint128" },
|
|
112
|
+
{ name: "collateral", type: "uint128" }
|
|
113
|
+
],
|
|
114
|
+
stateMutability: "view",
|
|
115
|
+
type: "function"
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
inputs: [{ name: "id", type: "bytes32" }],
|
|
119
|
+
name: "idToMarketParams",
|
|
120
|
+
outputs: [
|
|
121
|
+
{ name: "loanToken", type: "address" },
|
|
122
|
+
{ name: "collateralToken", type: "address" },
|
|
123
|
+
{ name: "oracle", type: "address" },
|
|
124
|
+
{ name: "irm", type: "address" },
|
|
125
|
+
{ name: "lltv", type: "uint256" }
|
|
126
|
+
],
|
|
127
|
+
stateMutability: "view",
|
|
128
|
+
type: "function"
|
|
129
|
+
}
|
|
130
|
+
];
|
|
131
|
+
|
|
132
|
+
// src/fetch.ts
|
|
133
|
+
var _viem = require('viem');
|
|
134
|
+
var ADDRESS_ZERO = "0x0000000000000000000000000000000000000000";
|
|
135
|
+
async function fetchVaultMarketsViem(client, vaultAddress, morphoAddress) {
|
|
136
|
+
const vault = _viem.getAddress.call(void 0, vaultAddress);
|
|
137
|
+
const morpho = _viem.getAddress.call(void 0, morphoAddress);
|
|
138
|
+
const [supplyLen, withdrawLen, totalAssets] = await client.multicall({
|
|
139
|
+
contracts: [
|
|
140
|
+
{ address: vault, abi: metaMorphoAbi, functionName: "supplyQueueLength" },
|
|
141
|
+
{ address: vault, abi: metaMorphoAbi, functionName: "withdrawQueueLength" },
|
|
142
|
+
{ address: vault, abi: metaMorphoAbi, functionName: "totalAssets" }
|
|
143
|
+
],
|
|
144
|
+
allowFailure: false
|
|
145
|
+
});
|
|
146
|
+
const supplyLenN = Number(supplyLen);
|
|
147
|
+
const withdrawLenN = Number(withdrawLen);
|
|
148
|
+
if (supplyLenN === 0 && withdrawLenN === 0) return { markets: [], idleAssets: 0n };
|
|
149
|
+
const queueCalls = [
|
|
150
|
+
...Array.from({ length: supplyLenN }, (_, i) => ({
|
|
151
|
+
address: vault,
|
|
152
|
+
abi: metaMorphoAbi,
|
|
153
|
+
functionName: "supplyQueue",
|
|
154
|
+
args: [BigInt(i)]
|
|
155
|
+
})),
|
|
156
|
+
...Array.from({ length: withdrawLenN }, (_, i) => ({
|
|
157
|
+
address: vault,
|
|
158
|
+
abi: metaMorphoAbi,
|
|
159
|
+
functionName: "withdrawQueue",
|
|
160
|
+
args: [BigInt(i)]
|
|
161
|
+
}))
|
|
162
|
+
];
|
|
163
|
+
const queueResults = await client.multicall({ contracts: queueCalls, allowFailure: false });
|
|
164
|
+
const supplyIds = queueResults.slice(0, supplyLenN);
|
|
165
|
+
const withdrawIds = queueResults.slice(supplyLenN);
|
|
166
|
+
const supplySet = new Set(supplyIds);
|
|
167
|
+
const withdrawSet = new Set(withdrawIds);
|
|
168
|
+
const withdrawQueueOrder = /* @__PURE__ */ new Map();
|
|
169
|
+
withdrawIds.forEach((id, i) => withdrawQueueOrder.set(id, i));
|
|
170
|
+
const allIds = [.../* @__PURE__ */ new Set([...supplyIds, ...withdrawIds])];
|
|
171
|
+
if (allIds.length === 0) return { markets: [], idleAssets: 0n };
|
|
172
|
+
const [marketStates, positions, marketParams, configs] = await Promise.all([
|
|
173
|
+
client.multicall({
|
|
174
|
+
contracts: allIds.map((id) => ({
|
|
175
|
+
address: morpho,
|
|
176
|
+
abi: morphoAbi,
|
|
177
|
+
functionName: "market",
|
|
178
|
+
args: [id]
|
|
179
|
+
})),
|
|
180
|
+
allowFailure: false
|
|
181
|
+
}),
|
|
182
|
+
client.multicall({
|
|
183
|
+
contracts: allIds.map((id) => ({
|
|
184
|
+
address: morpho,
|
|
185
|
+
abi: morphoAbi,
|
|
186
|
+
functionName: "position",
|
|
187
|
+
args: [id, vault]
|
|
188
|
+
})),
|
|
189
|
+
allowFailure: false
|
|
190
|
+
}),
|
|
191
|
+
client.multicall({
|
|
192
|
+
contracts: allIds.map((id) => ({
|
|
193
|
+
address: morpho,
|
|
194
|
+
abi: morphoAbi,
|
|
195
|
+
functionName: "idToMarketParams",
|
|
196
|
+
args: [id]
|
|
197
|
+
})),
|
|
198
|
+
allowFailure: false
|
|
199
|
+
}),
|
|
200
|
+
client.multicall({
|
|
201
|
+
contracts: allIds.map((id) => ({
|
|
202
|
+
address: vault,
|
|
203
|
+
abi: metaMorphoAbi,
|
|
204
|
+
functionName: "config",
|
|
205
|
+
args: [id]
|
|
206
|
+
})),
|
|
207
|
+
allowFailure: false
|
|
208
|
+
})
|
|
209
|
+
]);
|
|
210
|
+
const irmAndDecimalCalls = marketParams.flatMap(
|
|
211
|
+
([loanToken, collateralToken, , irm], i) => {
|
|
212
|
+
const hasIrm = irm && irm.toLowerCase() !== ADDRESS_ZERO;
|
|
213
|
+
const hasCollateral = collateralToken && collateralToken.toLowerCase() !== ADDRESS_ZERO;
|
|
214
|
+
const calls = [
|
|
215
|
+
hasIrm ? {
|
|
216
|
+
address: _viem.getAddress.call(void 0, irm),
|
|
217
|
+
abi: irmAdaptiveCurveAbi,
|
|
218
|
+
functionName: "rateAtTarget",
|
|
219
|
+
args: [allIds[i]]
|
|
220
|
+
} : null,
|
|
221
|
+
{ address: _viem.getAddress.call(void 0, loanToken), abi: erc20Abi, functionName: "decimals" },
|
|
222
|
+
{ address: _viem.getAddress.call(void 0, loanToken), abi: erc20Abi, functionName: "symbol" },
|
|
223
|
+
hasCollateral ? { address: _viem.getAddress.call(void 0, collateralToken), abi: erc20Abi, functionName: "symbol" } : null
|
|
224
|
+
];
|
|
225
|
+
return calls.filter((c) => c !== null);
|
|
226
|
+
}
|
|
227
|
+
);
|
|
228
|
+
const irmAndDecimalResults = await client.multicall({
|
|
229
|
+
contracts: irmAndDecimalCalls,
|
|
230
|
+
allowFailure: true
|
|
231
|
+
});
|
|
232
|
+
let resultIdx = 0;
|
|
233
|
+
const ratesAtTarget = [];
|
|
234
|
+
const decimals = [];
|
|
235
|
+
const loanSymbols = [];
|
|
236
|
+
const collateralSymbols = [];
|
|
237
|
+
for (const [, collateralToken, , irm] of marketParams) {
|
|
238
|
+
const hasIrm = irm && irm.toLowerCase() !== ADDRESS_ZERO;
|
|
239
|
+
const hasCollateral = collateralToken && collateralToken.toLowerCase() !== ADDRESS_ZERO;
|
|
240
|
+
if (hasIrm) {
|
|
241
|
+
const r = irmAndDecimalResults[resultIdx++];
|
|
242
|
+
const rate = r.status === "success" ? r.result : 0n;
|
|
243
|
+
ratesAtTarget.push(rate < 0n ? 0n : rate);
|
|
244
|
+
} else {
|
|
245
|
+
ratesAtTarget.push(0n);
|
|
246
|
+
}
|
|
247
|
+
const d = irmAndDecimalResults[resultIdx++];
|
|
248
|
+
decimals.push(d.status === "success" ? Number(d.result) : 18);
|
|
249
|
+
const ls = irmAndDecimalResults[resultIdx++];
|
|
250
|
+
loanSymbols.push(ls.status === "success" ? ls.result : "???");
|
|
251
|
+
if (hasCollateral) {
|
|
252
|
+
const cs = irmAndDecimalResults[resultIdx++];
|
|
253
|
+
collateralSymbols.push(cs.status === "success" ? cs.result : "???");
|
|
254
|
+
} else {
|
|
255
|
+
collateralSymbols.push("\u2014");
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
const markets = allIds.map((marketId, i) => {
|
|
259
|
+
const [totalSupplyAssets, totalSupplyShares, totalBorrowAssets, , , fee] = marketStates[i];
|
|
260
|
+
const [supplyShares] = positions[i];
|
|
261
|
+
const [cap] = configs[i];
|
|
262
|
+
let vaultSupplyAssets = 0n;
|
|
263
|
+
if (supplyShares > 0n && totalSupplyShares > 0n) {
|
|
264
|
+
vaultSupplyAssets = supplyShares * totalSupplyAssets / totalSupplyShares;
|
|
265
|
+
}
|
|
266
|
+
const [loanToken, collateralToken] = marketParams[i];
|
|
267
|
+
return {
|
|
268
|
+
marketId,
|
|
269
|
+
name: `${collateralSymbols[i]}/${loanSymbols[i]}`,
|
|
270
|
+
loanToken,
|
|
271
|
+
collateralToken,
|
|
272
|
+
totalSupplyAssets,
|
|
273
|
+
totalBorrowAssets,
|
|
274
|
+
fee,
|
|
275
|
+
vaultSupplyAssets,
|
|
276
|
+
rateAtTarget: ratesAtTarget[i],
|
|
277
|
+
cap,
|
|
278
|
+
decimals: decimals[i],
|
|
279
|
+
inSupplyQueue: supplySet.has(marketId),
|
|
280
|
+
inWithdrawQueue: withdrawSet.has(marketId),
|
|
281
|
+
withdrawQueueIndex: _nullishCoalesce(withdrawQueueOrder.get(marketId), () => ( -1))
|
|
282
|
+
};
|
|
283
|
+
});
|
|
284
|
+
const sumVaultSupply = markets.reduce((acc, m) => acc + m.vaultSupplyAssets, 0n);
|
|
285
|
+
const idleAssets = totalAssets > sumVaultSupply ? totalAssets - sumVaultSupply : 0n;
|
|
286
|
+
return { markets, idleAssets };
|
|
287
|
+
}
|
|
288
|
+
async function fetchVaultApyViem(client, vaultAddress, morphoAddress, options) {
|
|
289
|
+
const { markets, idleAssets } = await fetchVaultMarketsViem(client, vaultAddress, morphoAddress);
|
|
290
|
+
if (markets.length === 0) return null;
|
|
291
|
+
const detailed = _chunk37KGZP4Ocjs.weightedVaultApyDetailed.call(void 0, markets);
|
|
292
|
+
return { apy: detailed.apy, markets, idleAssets, marketDetails: _optionalChain([options, 'optionalAccess', _2 => _2.includeMarkets]) ? detailed.markets : [] };
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// src/addresses.ts
|
|
296
|
+
var MORPHO_BLUE_ADDRESSES = {
|
|
297
|
+
1: "0xbbbbbbbbbb9cc5e90e3b3af64bdaf62c37eeffcb",
|
|
298
|
+
// Ethereum
|
|
299
|
+
8453: "0xbbbbbbbbbb9cc5e90e3b3af64bdaf62c37eeffcb",
|
|
300
|
+
// Base
|
|
301
|
+
999: "0x68e37de8d93d3496ae143f2e900490f6280c57cd"
|
|
302
|
+
// HyperEVM
|
|
303
|
+
};
|
|
304
|
+
function getMorphoBlueAddress(chainId) {
|
|
305
|
+
const addr = MORPHO_BLUE_ADDRESSES[chainId];
|
|
306
|
+
if (!addr) {
|
|
307
|
+
throw new Error(
|
|
308
|
+
`No Morpho Blue address configured for chainId ${chainId}. Known chains: ${Object.keys(MORPHO_BLUE_ADDRESSES).join(", ")}`
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
return addr;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// src/deposit-impact.ts
|
|
315
|
+
async function computeDepositImpact(client, chainId, vaultAddress, depositAmount, options) {
|
|
316
|
+
const morpho = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _3 => _3.morphoAddress]), () => ( getMorphoBlueAddress(chainId)));
|
|
317
|
+
const incMkts = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _4 => _4.includeMarkets]), () => ( false));
|
|
318
|
+
const result = await fetchVaultApyViem(client, vaultAddress, morpho);
|
|
319
|
+
if (!result) {
|
|
320
|
+
return { currentApy: 0, newApy: 0, impact: 0, impactBps: 0, markets: [] };
|
|
321
|
+
}
|
|
322
|
+
const { markets } = result;
|
|
323
|
+
const current = _chunk37KGZP4Ocjs.weightedVaultApyDetailed.call(void 0, markets);
|
|
324
|
+
const sim = _chunk37KGZP4Ocjs.simulateDeposit.call(void 0, markets, depositAmount);
|
|
325
|
+
const simulated = _chunk37KGZP4Ocjs.weightedVaultApyDetailed.call(void 0, markets, sim);
|
|
326
|
+
const impact = simulated.apy - current.apy;
|
|
327
|
+
return {
|
|
328
|
+
currentApy: current.apy,
|
|
329
|
+
newApy: simulated.apy,
|
|
330
|
+
impact,
|
|
331
|
+
impactBps: Math.round(impact * 1e4),
|
|
332
|
+
markets: incMkts ? _chunk37KGZP4Ocjs.mergeMarketDetails.call(void 0, current.markets, simulated.markets) : []
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// src/withdrawal-impact.ts
|
|
337
|
+
async function computeWithdrawalImpact(client, chainId, vaultAddress, withdrawAmount, options) {
|
|
338
|
+
const morpho = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _5 => _5.morphoAddress]), () => ( getMorphoBlueAddress(chainId)));
|
|
339
|
+
const incMkts = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _6 => _6.includeMarkets]), () => ( false));
|
|
340
|
+
const result = await fetchVaultApyViem(client, vaultAddress, morpho);
|
|
341
|
+
if (!result) {
|
|
342
|
+
return {
|
|
343
|
+
currentApy: 0,
|
|
344
|
+
newApy: 0,
|
|
345
|
+
impact: 0,
|
|
346
|
+
impactBps: 0,
|
|
347
|
+
isPartial: false,
|
|
348
|
+
withdrawableAmount: "0",
|
|
349
|
+
markets: []
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
const { markets, idleAssets } = result;
|
|
353
|
+
const current = _chunk37KGZP4Ocjs.weightedVaultApyDetailed.call(void 0, markets);
|
|
354
|
+
const { sim, withdrawable, remaining } = _chunk37KGZP4Ocjs.simulateWithdrawal.call(void 0, markets, withdrawAmount, idleAssets);
|
|
355
|
+
const totalVaultAssets = markets.reduce((acc, m) => acc + m.vaultSupplyAssets, 0n) + idleAssets;
|
|
356
|
+
const simulated = withdrawable >= totalVaultAssets ? { apy: 0, markets: [] } : _chunk37KGZP4Ocjs.weightedVaultApyDetailed.call(void 0, markets, {}, sim);
|
|
357
|
+
const impact = simulated.apy - current.apy;
|
|
358
|
+
return {
|
|
359
|
+
currentApy: current.apy,
|
|
360
|
+
newApy: simulated.apy,
|
|
361
|
+
impact,
|
|
362
|
+
impactBps: Math.round(impact * 1e4),
|
|
363
|
+
isPartial: remaining > 0n,
|
|
364
|
+
withdrawableAmount: withdrawable.toString(),
|
|
365
|
+
markets: incMkts ? _chunk37KGZP4Ocjs.mergeMarketDetails.call(void 0, current.markets, simulated.markets) : []
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// src/find-max.ts
|
|
370
|
+
function defaultPrecision(markets) {
|
|
371
|
+
const decimals = markets.length > 0 ? markets[0].decimals : 18;
|
|
372
|
+
return 10n ** BigInt(decimals);
|
|
373
|
+
}
|
|
374
|
+
function computeMaxDepositable(markets) {
|
|
375
|
+
return markets.filter((m) => m.inSupplyQueue && m.cap > m.vaultSupplyAssets).reduce((sum, m) => sum + (m.cap - m.vaultSupplyAssets), 0n);
|
|
376
|
+
}
|
|
377
|
+
function computeMaxWithdrawable(markets, idleAssets) {
|
|
378
|
+
const fromMarkets = markets.filter((m) => m.inWithdrawQueue && m.withdrawQueueIndex >= 0).reduce((sum, m) => {
|
|
379
|
+
const liquidity = m.totalSupplyAssets > m.totalBorrowAssets ? m.totalSupplyAssets - m.totalBorrowAssets : 0n;
|
|
380
|
+
const available = m.vaultSupplyAssets < liquidity ? m.vaultSupplyAssets : liquidity;
|
|
381
|
+
return sum + (available > 0n ? available : 0n);
|
|
382
|
+
}, 0n);
|
|
383
|
+
return idleAssets + fromMarkets;
|
|
384
|
+
}
|
|
385
|
+
function buildDepositImpact(current, simulated, includeMarkets) {
|
|
386
|
+
const impact = simulated.apy - current.apy;
|
|
387
|
+
return {
|
|
388
|
+
currentApy: current.apy,
|
|
389
|
+
newApy: simulated.apy,
|
|
390
|
+
impact,
|
|
391
|
+
impactBps: Math.round(impact * 1e4),
|
|
392
|
+
markets: includeMarkets ? _chunk37KGZP4Ocjs.mergeMarketDetails.call(void 0, current.markets, simulated.markets) : []
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
function buildWithdrawalImpact(current, simulated, withdrawable, remaining, includeMarkets) {
|
|
396
|
+
const impact = simulated.apy - current.apy;
|
|
397
|
+
return {
|
|
398
|
+
currentApy: current.apy,
|
|
399
|
+
newApy: simulated.apy,
|
|
400
|
+
impact,
|
|
401
|
+
impactBps: Math.round(impact * 1e4),
|
|
402
|
+
isPartial: remaining > 0n,
|
|
403
|
+
withdrawableAmount: withdrawable.toString(),
|
|
404
|
+
markets: includeMarkets ? _chunk37KGZP4Ocjs.mergeMarketDetails.call(void 0, current.markets, simulated.markets) : []
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
function zeroDepositImpact(markets, includeMarkets) {
|
|
408
|
+
if (markets.length === 0) {
|
|
409
|
+
return { currentApy: 0, newApy: 0, impact: 0, impactBps: 0, markets: [] };
|
|
410
|
+
}
|
|
411
|
+
const current = _chunk37KGZP4Ocjs.weightedVaultApyDetailed.call(void 0, markets);
|
|
412
|
+
return buildDepositImpact(current, current, includeMarkets);
|
|
413
|
+
}
|
|
414
|
+
function zeroWithdrawalImpact(markets, idleAssets, includeMarkets) {
|
|
415
|
+
if (markets.length === 0) {
|
|
416
|
+
return { currentApy: 0, newApy: 0, impact: 0, impactBps: 0, isPartial: false, withdrawableAmount: "0", markets: [] };
|
|
417
|
+
}
|
|
418
|
+
const current = _chunk37KGZP4Ocjs.weightedVaultApyDetailed.call(void 0, markets);
|
|
419
|
+
return buildWithdrawalImpact(current, current, 0n, 0n, includeMarkets);
|
|
420
|
+
}
|
|
421
|
+
async function findMaxDepositAmount(markets, maxAmount, maxImpactBps, options) {
|
|
422
|
+
const raw = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _7 => _7.precision]), () => ( defaultPrecision(markets)));
|
|
423
|
+
const step = raw > 0n ? raw : 1n;
|
|
424
|
+
const maxImpact = maxImpactBps / 1e4;
|
|
425
|
+
const incMkts = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _8 => _8.includeMarkets]), () => ( false));
|
|
426
|
+
const constraint = _optionalChain([options, 'optionalAccess', _9 => _9.constraint]);
|
|
427
|
+
if (markets.length === 0 || maxAmount === 0n) {
|
|
428
|
+
return {
|
|
429
|
+
amount: 0n,
|
|
430
|
+
maxPossibleAmount: 0n,
|
|
431
|
+
isMaxAmount: maxAmount === 0n,
|
|
432
|
+
isCapped: false,
|
|
433
|
+
impact: zeroDepositImpact(markets, incMkts)
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
const maxPossible = computeMaxDepositable(markets);
|
|
437
|
+
const effectiveMax = maxAmount < maxPossible ? maxAmount : maxPossible;
|
|
438
|
+
if (effectiveMax === 0n) {
|
|
439
|
+
return {
|
|
440
|
+
amount: 0n,
|
|
441
|
+
maxPossibleAmount: maxPossible,
|
|
442
|
+
isMaxAmount: false,
|
|
443
|
+
isCapped: maxPossible === 0n,
|
|
444
|
+
impact: zeroDepositImpact(markets, incMkts)
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
const current = _chunk37KGZP4Ocjs.weightedVaultApyDetailed.call(void 0, markets);
|
|
448
|
+
async function isAcceptable(amount) {
|
|
449
|
+
const sim2 = _chunk37KGZP4Ocjs.simulateDeposit.call(void 0, markets, amount);
|
|
450
|
+
const simulated2 = _chunk37KGZP4Ocjs.weightedVaultApyDetailed.call(void 0, markets, sim2);
|
|
451
|
+
const impact = Math.abs(simulated2.apy - current.apy);
|
|
452
|
+
if (impact > maxImpact) return false;
|
|
453
|
+
if (!constraint) return true;
|
|
454
|
+
return constraint({
|
|
455
|
+
amount,
|
|
456
|
+
currentApy: current.apy,
|
|
457
|
+
simulatedApy: simulated2.apy,
|
|
458
|
+
impactBps: Math.round((simulated2.apy - current.apy) * 1e4),
|
|
459
|
+
markets: _chunk37KGZP4Ocjs.mergeMarketDetails.call(void 0, current.markets, simulated2.markets)
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
if (await isAcceptable(effectiveMax)) {
|
|
463
|
+
const sim2 = _chunk37KGZP4Ocjs.simulateDeposit.call(void 0, markets, effectiveMax);
|
|
464
|
+
const simulated2 = _chunk37KGZP4Ocjs.weightedVaultApyDetailed.call(void 0, markets, sim2);
|
|
465
|
+
return {
|
|
466
|
+
amount: effectiveMax,
|
|
467
|
+
maxPossibleAmount: maxPossible,
|
|
468
|
+
isMaxAmount: effectiveMax === maxAmount,
|
|
469
|
+
isCapped: effectiveMax < maxAmount,
|
|
470
|
+
impact: buildDepositImpact(current, simulated2, incMkts)
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
if (step >= effectiveMax || !await isAcceptable(step)) {
|
|
474
|
+
return {
|
|
475
|
+
amount: 0n,
|
|
476
|
+
maxPossibleAmount: maxPossible,
|
|
477
|
+
isMaxAmount: false,
|
|
478
|
+
isCapped: false,
|
|
479
|
+
impact: zeroDepositImpact(markets, incMkts)
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
let lo = step;
|
|
483
|
+
let hi = effectiveMax;
|
|
484
|
+
while (hi - lo > step) {
|
|
485
|
+
let mid = lo + (hi - lo) / 2n;
|
|
486
|
+
mid = mid / step * step;
|
|
487
|
+
if (mid === lo) break;
|
|
488
|
+
if (await isAcceptable(mid)) {
|
|
489
|
+
lo = mid;
|
|
490
|
+
} else {
|
|
491
|
+
hi = mid;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
const sim = _chunk37KGZP4Ocjs.simulateDeposit.call(void 0, markets, lo);
|
|
495
|
+
const simulated = _chunk37KGZP4Ocjs.weightedVaultApyDetailed.call(void 0, markets, sim);
|
|
496
|
+
return {
|
|
497
|
+
amount: lo,
|
|
498
|
+
maxPossibleAmount: maxPossible,
|
|
499
|
+
isMaxAmount: false,
|
|
500
|
+
isCapped: false,
|
|
501
|
+
impact: buildDepositImpact(current, simulated, incMkts)
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
async function findMaxWithdrawalAmount(markets, idleAssets, maxAmount, maxImpactBps, options) {
|
|
505
|
+
const raw = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _10 => _10.precision]), () => ( defaultPrecision(markets)));
|
|
506
|
+
const step = raw > 0n ? raw : 1n;
|
|
507
|
+
const maxImpact = maxImpactBps / 1e4;
|
|
508
|
+
const incMkts = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _11 => _11.includeMarkets]), () => ( false));
|
|
509
|
+
const constraint = _optionalChain([options, 'optionalAccess', _12 => _12.constraint]);
|
|
510
|
+
if (markets.length === 0 || maxAmount === 0n) {
|
|
511
|
+
return {
|
|
512
|
+
amount: 0n,
|
|
513
|
+
maxPossibleAmount: 0n,
|
|
514
|
+
isMaxAmount: maxAmount === 0n,
|
|
515
|
+
isCapped: false,
|
|
516
|
+
impact: zeroWithdrawalImpact(markets, idleAssets, incMkts)
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
const maxPossible = computeMaxWithdrawable(markets, idleAssets);
|
|
520
|
+
const effectiveMax = maxAmount < maxPossible ? maxAmount : maxPossible;
|
|
521
|
+
if (effectiveMax === 0n) {
|
|
522
|
+
return {
|
|
523
|
+
amount: 0n,
|
|
524
|
+
maxPossibleAmount: maxPossible,
|
|
525
|
+
isMaxAmount: false,
|
|
526
|
+
isCapped: maxPossible === 0n,
|
|
527
|
+
impact: zeroWithdrawalImpact(markets, idleAssets, incMkts)
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
const current = _chunk37KGZP4Ocjs.weightedVaultApyDetailed.call(void 0, markets);
|
|
531
|
+
const totalVaultAssets = markets.reduce((acc, m) => acc + m.vaultSupplyAssets, 0n) + idleAssets;
|
|
532
|
+
async function isAcceptable(amount) {
|
|
533
|
+
const { sim: sim2, withdrawable: withdrawable2, remaining: remaining2 } = _chunk37KGZP4Ocjs.simulateWithdrawal.call(void 0, markets, amount, idleAssets);
|
|
534
|
+
const isFullDrain = withdrawable2 >= totalVaultAssets;
|
|
535
|
+
const simulated2 = isFullDrain ? { apy: 0, markets: [] } : _chunk37KGZP4Ocjs.weightedVaultApyDetailed.call(void 0, markets, {}, sim2);
|
|
536
|
+
const impact = Math.abs(simulated2.apy - current.apy);
|
|
537
|
+
if (impact > maxImpact) return false;
|
|
538
|
+
if (!constraint) return true;
|
|
539
|
+
return constraint({
|
|
540
|
+
amount,
|
|
541
|
+
currentApy: current.apy,
|
|
542
|
+
simulatedApy: simulated2.apy,
|
|
543
|
+
impactBps: Math.round((simulated2.apy - current.apy) * 1e4),
|
|
544
|
+
markets: _chunk37KGZP4Ocjs.mergeMarketDetails.call(void 0, current.markets, simulated2.markets),
|
|
545
|
+
isPartial: remaining2 > 0n,
|
|
546
|
+
withdrawableAmount: withdrawable2
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
if (effectiveMax <= idleAssets) {
|
|
550
|
+
if (!constraint || await isAcceptable(effectiveMax)) {
|
|
551
|
+
const { withdrawable: withdrawable2, remaining: remaining2 } = _chunk37KGZP4Ocjs.simulateWithdrawal.call(void 0, markets, effectiveMax, idleAssets);
|
|
552
|
+
return {
|
|
553
|
+
amount: effectiveMax,
|
|
554
|
+
maxPossibleAmount: maxPossible,
|
|
555
|
+
isMaxAmount: effectiveMax === maxAmount,
|
|
556
|
+
isCapped: effectiveMax < maxAmount,
|
|
557
|
+
impact: buildWithdrawalImpact(current, current, withdrawable2, remaining2, incMkts)
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
if (await isAcceptable(effectiveMax)) {
|
|
562
|
+
const { sim: sim2, withdrawable: withdrawable2, remaining: remaining2 } = _chunk37KGZP4Ocjs.simulateWithdrawal.call(void 0, markets, effectiveMax, idleAssets);
|
|
563
|
+
const simulated2 = withdrawable2 >= totalVaultAssets ? { apy: 0, markets: [] } : _chunk37KGZP4Ocjs.weightedVaultApyDetailed.call(void 0, markets, {}, sim2);
|
|
564
|
+
return {
|
|
565
|
+
amount: effectiveMax,
|
|
566
|
+
maxPossibleAmount: maxPossible,
|
|
567
|
+
isMaxAmount: effectiveMax === maxAmount,
|
|
568
|
+
isCapped: effectiveMax < maxAmount,
|
|
569
|
+
impact: buildWithdrawalImpact(current, simulated2, withdrawable2, remaining2, incMkts)
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
if (step >= effectiveMax || !await isAcceptable(step)) {
|
|
573
|
+
return {
|
|
574
|
+
amount: 0n,
|
|
575
|
+
maxPossibleAmount: maxPossible,
|
|
576
|
+
isMaxAmount: false,
|
|
577
|
+
isCapped: false,
|
|
578
|
+
impact: zeroWithdrawalImpact(markets, idleAssets, incMkts)
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
let lo = step;
|
|
582
|
+
let hi = effectiveMax;
|
|
583
|
+
while (hi - lo > step) {
|
|
584
|
+
let mid = lo + (hi - lo) / 2n;
|
|
585
|
+
mid = mid / step * step;
|
|
586
|
+
if (mid === lo) break;
|
|
587
|
+
if (await isAcceptable(mid)) {
|
|
588
|
+
lo = mid;
|
|
589
|
+
} else {
|
|
590
|
+
hi = mid;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
const { sim, withdrawable, remaining } = _chunk37KGZP4Ocjs.simulateWithdrawal.call(void 0, markets, lo, idleAssets);
|
|
594
|
+
const simulated = withdrawable >= totalVaultAssets ? { apy: 0, markets: [] } : _chunk37KGZP4Ocjs.weightedVaultApyDetailed.call(void 0, markets, {}, sim);
|
|
595
|
+
return {
|
|
596
|
+
amount: lo,
|
|
597
|
+
maxPossibleAmount: maxPossible,
|
|
598
|
+
isMaxAmount: false,
|
|
599
|
+
isCapped: false,
|
|
600
|
+
impact: buildWithdrawalImpact(current, simulated, withdrawable, remaining, incMkts)
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// src/find-max-impact.ts
|
|
605
|
+
async function findMaxDeposit(client, chainId, vaultAddress, maxAmount, maxImpactBps, options) {
|
|
606
|
+
const morpho = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _13 => _13.morphoAddress]), () => ( getMorphoBlueAddress(chainId)));
|
|
607
|
+
const result = await fetchVaultApyViem(client, vaultAddress, morpho);
|
|
608
|
+
if (!result) {
|
|
609
|
+
return {
|
|
610
|
+
amount: 0n,
|
|
611
|
+
maxPossibleAmount: 0n,
|
|
612
|
+
isMaxAmount: false,
|
|
613
|
+
isCapped: false,
|
|
614
|
+
impact: { currentApy: 0, newApy: 0, impact: 0, impactBps: 0, markets: [] }
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
return findMaxDepositAmount(result.markets, maxAmount, maxImpactBps, {
|
|
618
|
+
precision: _optionalChain([options, 'optionalAccess', _14 => _14.precision]),
|
|
619
|
+
includeMarkets: _optionalChain([options, 'optionalAccess', _15 => _15.includeMarkets]),
|
|
620
|
+
constraint: _optionalChain([options, 'optionalAccess', _16 => _16.constraint])
|
|
621
|
+
});
|
|
622
|
+
}
|
|
623
|
+
async function findMaxWithdrawal(client, chainId, vaultAddress, maxAmount, maxImpactBps, options) {
|
|
624
|
+
const morpho = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _17 => _17.morphoAddress]), () => ( getMorphoBlueAddress(chainId)));
|
|
625
|
+
const result = await fetchVaultApyViem(client, vaultAddress, morpho);
|
|
626
|
+
if (!result) {
|
|
627
|
+
return {
|
|
628
|
+
amount: 0n,
|
|
629
|
+
maxPossibleAmount: 0n,
|
|
630
|
+
isMaxAmount: false,
|
|
631
|
+
isCapped: false,
|
|
632
|
+
impact: {
|
|
633
|
+
currentApy: 0,
|
|
634
|
+
newApy: 0,
|
|
635
|
+
impact: 0,
|
|
636
|
+
impactBps: 0,
|
|
637
|
+
isPartial: false,
|
|
638
|
+
withdrawableAmount: "0",
|
|
639
|
+
markets: []
|
|
640
|
+
}
|
|
641
|
+
};
|
|
642
|
+
}
|
|
643
|
+
return findMaxWithdrawalAmount(result.markets, result.idleAssets, maxAmount, maxImpactBps, {
|
|
644
|
+
precision: _optionalChain([options, 'optionalAccess', _18 => _18.precision]),
|
|
645
|
+
includeMarkets: _optionalChain([options, 'optionalAccess', _19 => _19.includeMarkets]),
|
|
646
|
+
constraint: _optionalChain([options, 'optionalAccess', _20 => _20.constraint])
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
// src/rpc.ts
|
|
651
|
+
|
|
652
|
+
var MULTICALL3 = "0xcA11bde05977b3631167028862bE2a173976CA11";
|
|
653
|
+
function makeClient(rpcUrl, chainId) {
|
|
654
|
+
return _viem.createPublicClient.call(void 0, {
|
|
655
|
+
transport: _viem.http.call(void 0, rpcUrl),
|
|
656
|
+
chain: _viem.defineChain.call(void 0, {
|
|
657
|
+
id: chainId,
|
|
658
|
+
name: `Chain ${chainId}`,
|
|
659
|
+
nativeCurrency: { name: "ETH", symbol: "ETH", decimals: 18 },
|
|
660
|
+
rpcUrls: { default: { http: [rpcUrl] } },
|
|
661
|
+
contracts: { multicall3: { address: MULTICALL3 } }
|
|
662
|
+
})
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
async function fetchVaultMarkets(rpcUrl, chainId, vaultAddress, morphoAddress) {
|
|
666
|
+
return fetchVaultMarketsViem(makeClient(rpcUrl, chainId), vaultAddress, morphoAddress);
|
|
667
|
+
}
|
|
668
|
+
async function fetchVaultApy(rpcUrl, chainId, vaultAddress, options) {
|
|
669
|
+
const morpho = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _21 => _21.morphoAddress]), () => ( getMorphoBlueAddress(chainId)));
|
|
670
|
+
return fetchVaultApyViem(makeClient(rpcUrl, chainId), vaultAddress, morpho, {
|
|
671
|
+
includeMarkets: _optionalChain([options, 'optionalAccess', _22 => _22.includeMarkets])
|
|
672
|
+
});
|
|
673
|
+
}
|
|
674
|
+
async function computeDepositImpactRpc(rpcUrl, chainId, vaultAddress, depositAmount, options) {
|
|
675
|
+
return computeDepositImpact(makeClient(rpcUrl, chainId), chainId, vaultAddress, depositAmount, options);
|
|
676
|
+
}
|
|
677
|
+
async function computeWithdrawalImpactRpc(rpcUrl, chainId, vaultAddress, withdrawAmount, options) {
|
|
678
|
+
return computeWithdrawalImpact(makeClient(rpcUrl, chainId), chainId, vaultAddress, withdrawAmount, options);
|
|
679
|
+
}
|
|
680
|
+
async function findMaxDepositRpc(rpcUrl, chainId, vaultAddress, maxAmount, maxImpactBps, options) {
|
|
681
|
+
return findMaxDeposit(makeClient(rpcUrl, chainId), chainId, vaultAddress, maxAmount, maxImpactBps, options);
|
|
682
|
+
}
|
|
683
|
+
async function findMaxWithdrawalRpc(rpcUrl, chainId, vaultAddress, maxAmount, maxImpactBps, options) {
|
|
684
|
+
return findMaxWithdrawal(makeClient(rpcUrl, chainId), chainId, vaultAddress, maxAmount, maxImpactBps, options);
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
|
|
688
|
+
|
|
689
|
+
|
|
690
|
+
|
|
691
|
+
|
|
692
|
+
|
|
693
|
+
|
|
694
|
+
|
|
695
|
+
|
|
696
|
+
|
|
697
|
+
|
|
698
|
+
|
|
699
|
+
|
|
700
|
+
|
|
701
|
+
|
|
702
|
+
|
|
703
|
+
|
|
704
|
+
|
|
705
|
+
|
|
706
|
+
|
|
707
|
+
|
|
708
|
+
exports.erc20Abi = erc20Abi; exports.irmAdaptiveCurveAbi = irmAdaptiveCurveAbi; exports.metaMorphoAbi = metaMorphoAbi; exports.morphoAbi = morphoAbi; exports.fetchVaultMarketsViem = fetchVaultMarketsViem; exports.fetchVaultApyViem = fetchVaultApyViem; exports.MORPHO_BLUE_ADDRESSES = MORPHO_BLUE_ADDRESSES; exports.getMorphoBlueAddress = getMorphoBlueAddress; exports.computeDepositImpact = computeDepositImpact; exports.computeWithdrawalImpact = computeWithdrawalImpact; exports.findMaxDepositAmount = findMaxDepositAmount; exports.findMaxWithdrawalAmount = findMaxWithdrawalAmount; exports.findMaxDeposit = findMaxDeposit; exports.findMaxWithdrawal = findMaxWithdrawal; exports.fetchVaultMarkets = fetchVaultMarkets; exports.fetchVaultApy = fetchVaultApy; exports.computeDepositImpactRpc = computeDepositImpactRpc; exports.computeWithdrawalImpactRpc = computeWithdrawalImpactRpc; exports.findMaxDepositRpc = findMaxDepositRpc; exports.findMaxWithdrawalRpc = findMaxWithdrawalRpc;
|
|
709
|
+
//# sourceMappingURL=chunk-35AORYVF.cjs.map
|