@continuumdao/ctm-mpc-defi 0.2.26 → 0.2.28
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/agent/catalog.cjs +681 -46
- package/dist/agent/catalog.cjs.map +1 -1
- package/dist/agent/catalog.d.ts +1209 -21
- package/dist/agent/catalog.js +668 -47
- package/dist/agent/catalog.js.map +1 -1
- package/dist/agent/skills/morpho/SKILL.md +38 -6
- package/dist/agent/skills/uniswap-v4/SKILL.md +15 -0
- package/dist/core/index.cjs +19 -0
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.ts +8 -1
- package/dist/core/index.js +17 -1
- package/dist/core/index.js.map +1 -1
- package/dist/index.cjs +363 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +361 -23
- package/dist/index.js.map +1 -1
- package/dist/protocols/evm/aave-v4/index.cjs.map +1 -1
- package/dist/protocols/evm/aave-v4/index.js.map +1 -1
- package/dist/protocols/evm/euler-v2/index.cjs.map +1 -1
- package/dist/protocols/evm/euler-v2/index.js.map +1 -1
- package/dist/protocols/evm/maple/index.cjs.map +1 -1
- package/dist/protocols/evm/maple/index.js.map +1 -1
- package/dist/protocols/evm/morpho/index.cjs +1153 -142
- package/dist/protocols/evm/morpho/index.cjs.map +1 -1
- package/dist/protocols/evm/morpho/index.d.ts +314 -8
- package/dist/protocols/evm/morpho/index.js +1131 -144
- package/dist/protocols/evm/morpho/index.js.map +1 -1
- package/dist/protocols/evm/permit2/index.cjs.map +1 -1
- package/dist/protocols/evm/permit2/index.js.map +1 -1
- package/dist/protocols/evm/sky/index.cjs.map +1 -1
- package/dist/protocols/evm/sky/index.js.map +1 -1
- package/dist/protocols/evm/uniswap-v4/index.cjs +863 -25
- package/dist/protocols/evm/uniswap-v4/index.cjs.map +1 -1
- package/dist/protocols/evm/uniswap-v4/index.d.ts +266 -9
- package/dist/protocols/evm/uniswap-v4/index.js +834 -27
- package/dist/protocols/evm/uniswap-v4/index.js.map +1 -1
- package/package.json +2 -1
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var viem = require('viem');
|
|
4
|
+
var api = require('@morpho-org/midnight-sdk/api');
|
|
5
|
+
var midnightSdk = require('@morpho-org/midnight-sdk');
|
|
4
6
|
var continuumNodeSdk = require('@continuumdao/continuum-node-sdk');
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
var
|
|
8
|
-
function
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
var __defProp = Object.defineProperty;
|
|
9
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
10
|
+
var __esm = (fn, res) => function __init() {
|
|
11
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
12
|
+
};
|
|
13
|
+
var __export = (target, all) => {
|
|
14
|
+
for (var name in all)
|
|
15
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
16
|
+
};
|
|
17
|
+
function getMorphoMidnightRestProxyUrl() {
|
|
18
|
+
return morphoMidnightRestProxyUrl;
|
|
15
19
|
}
|
|
16
20
|
async function postJsonViaOptionalProxy(args) {
|
|
17
21
|
const r = await fetch(args.directUrl, {
|
|
@@ -25,8 +29,254 @@ async function postJsonViaOptionalProxy(args) {
|
|
|
25
29
|
}
|
|
26
30
|
return await r.json();
|
|
27
31
|
}
|
|
32
|
+
async function getJsonViaOptionalProxy(args) {
|
|
33
|
+
const url = args.directUrl;
|
|
34
|
+
const r = await fetch(url, { method: "GET", headers: { accept: "application/json" } });
|
|
35
|
+
if (!r.ok) {
|
|
36
|
+
const t = await r.text().catch(() => "");
|
|
37
|
+
throw new Error(t ? `HTTP ${r.status}: ${t.slice(0, 200)}` : `HTTP ${r.status}`);
|
|
38
|
+
}
|
|
39
|
+
return await r.json();
|
|
40
|
+
}
|
|
41
|
+
var morphoMidnightRestProxyUrl;
|
|
42
|
+
var init_defiProxy = __esm({
|
|
43
|
+
"src/core/defiProxy.ts"() {
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// src/protocols/evm/morpho/midnightConstants.ts
|
|
48
|
+
var midnightConstants_exports = {};
|
|
49
|
+
__export(midnightConstants_exports, {
|
|
50
|
+
MORPHO_MIDNIGHT_ADDRESSES: () => exports.MORPHO_MIDNIGHT_ADDRESSES,
|
|
51
|
+
MORPHO_MIDNIGHT_AUTHORIZE_FALLBACK_GAS: () => exports.MORPHO_MIDNIGHT_AUTHORIZE_FALLBACK_GAS,
|
|
52
|
+
MORPHO_MIDNIGHT_BASE_CHAIN_ID: () => exports.MORPHO_MIDNIGHT_BASE_CHAIN_ID,
|
|
53
|
+
MORPHO_MIDNIGHT_BOOKS_MAX_LIMIT: () => exports.MORPHO_MIDNIGHT_BOOKS_MAX_LIMIT,
|
|
54
|
+
MORPHO_MIDNIGHT_BORROW_FALLBACK_GAS: () => exports.MORPHO_MIDNIGHT_BORROW_FALLBACK_GAS,
|
|
55
|
+
MORPHO_MIDNIGHT_DEFAULT_DEADLINE_SECONDS: () => exports.MORPHO_MIDNIGHT_DEFAULT_DEADLINE_SECONDS,
|
|
56
|
+
MORPHO_MIDNIGHT_DEFAULT_SLIPPAGE_PCT: () => exports.MORPHO_MIDNIGHT_DEFAULT_SLIPPAGE_PCT,
|
|
57
|
+
MORPHO_MIDNIGHT_ERC20_APPROVE_FALLBACK: () => exports.MORPHO_MIDNIGHT_ERC20_APPROVE_FALLBACK,
|
|
58
|
+
MORPHO_MIDNIGHT_LEND_FALLBACK_GAS: () => exports.MORPHO_MIDNIGHT_LEND_FALLBACK_GAS,
|
|
59
|
+
MORPHO_MIDNIGHT_REPAY_FALLBACK_GAS: () => exports.MORPHO_MIDNIGHT_REPAY_FALLBACK_GAS,
|
|
60
|
+
MORPHO_MIDNIGHT_REST_BASE: () => exports.MORPHO_MIDNIGHT_REST_BASE,
|
|
61
|
+
MORPHO_MIDNIGHT_WETH_DEPOSIT_FALLBACK: () => exports.MORPHO_MIDNIGHT_WETH_DEPOSIT_FALLBACK,
|
|
62
|
+
TOKEN_PERMIT_NONE: () => exports.TOKEN_PERMIT_NONE,
|
|
63
|
+
morphoMidnightAddressesForChain: () => morphoMidnightAddressesForChain
|
|
64
|
+
});
|
|
65
|
+
function morphoMidnightAddressesForChain(chainId) {
|
|
66
|
+
return exports.MORPHO_MIDNIGHT_ADDRESSES[chainId] ?? null;
|
|
67
|
+
}
|
|
68
|
+
exports.MORPHO_MIDNIGHT_REST_BASE = void 0; exports.MORPHO_MIDNIGHT_BOOKS_MAX_LIMIT = void 0; exports.MORPHO_MIDNIGHT_DEFAULT_SLIPPAGE_PCT = void 0; exports.MORPHO_MIDNIGHT_DEFAULT_DEADLINE_SECONDS = void 0; exports.MORPHO_MIDNIGHT_BASE_CHAIN_ID = void 0; exports.MORPHO_MIDNIGHT_ADDRESSES = void 0; exports.TOKEN_PERMIT_NONE = void 0; exports.MORPHO_MIDNIGHT_LEND_FALLBACK_GAS = void 0; exports.MORPHO_MIDNIGHT_BORROW_FALLBACK_GAS = void 0; exports.MORPHO_MIDNIGHT_REPAY_FALLBACK_GAS = void 0; exports.MORPHO_MIDNIGHT_AUTHORIZE_FALLBACK_GAS = void 0; exports.MORPHO_MIDNIGHT_ERC20_APPROVE_FALLBACK = void 0; exports.MORPHO_MIDNIGHT_WETH_DEPOSIT_FALLBACK = void 0;
|
|
69
|
+
var init_midnightConstants = __esm({
|
|
70
|
+
"src/protocols/evm/morpho/midnightConstants.ts"() {
|
|
71
|
+
exports.MORPHO_MIDNIGHT_REST_BASE = "https://api.morpho.org/v0/midnight";
|
|
72
|
+
exports.MORPHO_MIDNIGHT_BOOKS_MAX_LIMIT = 20;
|
|
73
|
+
exports.MORPHO_MIDNIGHT_DEFAULT_SLIPPAGE_PCT = "0.5";
|
|
74
|
+
exports.MORPHO_MIDNIGHT_DEFAULT_DEADLINE_SECONDS = 3600;
|
|
75
|
+
exports.MORPHO_MIDNIGHT_BASE_CHAIN_ID = 8453;
|
|
76
|
+
exports.MORPHO_MIDNIGHT_ADDRESSES = {
|
|
77
|
+
[exports.MORPHO_MIDNIGHT_BASE_CHAIN_ID]: {
|
|
78
|
+
midnight: "0xadedd8ab6de832766fedf0fac4992e5c4d3ea18a",
|
|
79
|
+
bundles: "0x6688dEc8878f43905e11B3C6Bc025E098133144f"
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
exports.TOKEN_PERMIT_NONE = { kind: 0, data: "0x" };
|
|
83
|
+
exports.MORPHO_MIDNIGHT_LEND_FALLBACK_GAS = 2500000n;
|
|
84
|
+
exports.MORPHO_MIDNIGHT_BORROW_FALLBACK_GAS = 3000000n;
|
|
85
|
+
exports.MORPHO_MIDNIGHT_REPAY_FALLBACK_GAS = 2200000n;
|
|
86
|
+
exports.MORPHO_MIDNIGHT_AUTHORIZE_FALLBACK_GAS = 80000n;
|
|
87
|
+
exports.MORPHO_MIDNIGHT_ERC20_APPROVE_FALLBACK = 100000n;
|
|
88
|
+
exports.MORPHO_MIDNIGHT_WETH_DEPOSIT_FALLBACK = 120000n;
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// src/protocols/evm/morpho/midnightApi.ts
|
|
93
|
+
var midnightApi_exports = {};
|
|
94
|
+
__export(midnightApi_exports, {
|
|
95
|
+
fetchMorphoMidnightBook: () => fetchMorphoMidnightBook,
|
|
96
|
+
fetchMorphoMidnightBookQuote: () => fetchMorphoMidnightBookQuote,
|
|
97
|
+
fetchMorphoMidnightBooks: () => fetchMorphoMidnightBooks,
|
|
98
|
+
fetchMorphoMidnightMarketById: () => fetchMorphoMidnightMarketById,
|
|
99
|
+
fetchMorphoMidnightUserMarketPosition: () => fetchMorphoMidnightUserMarketPosition,
|
|
100
|
+
fetchMorphoMidnightUserPositions: () => fetchMorphoMidnightUserPositions,
|
|
101
|
+
morphoMidnightApiBaseUrl: () => morphoMidnightApiBaseUrl,
|
|
102
|
+
morphoMidnightBookToMarketParams: () => morphoMidnightBookToMarketParams,
|
|
103
|
+
morphoMidnightMarketToParams: () => morphoMidnightMarketToParams
|
|
104
|
+
});
|
|
105
|
+
function morphoMidnightApiBaseUrl() {
|
|
106
|
+
const proxy = getMorphoMidnightRestProxyUrl()?.replace(/\/$/, "");
|
|
107
|
+
return proxy || exports.MORPHO_MIDNIGHT_REST_BASE;
|
|
108
|
+
}
|
|
109
|
+
function midnightApiConfig() {
|
|
110
|
+
return { baseUrl: morphoMidnightApiBaseUrl() };
|
|
111
|
+
}
|
|
112
|
+
async function midnightGetJson(pathAndQuery) {
|
|
113
|
+
const path = pathAndQuery.startsWith("/") ? pathAndQuery : `/${pathAndQuery}`;
|
|
114
|
+
const directUrl = `${exports.MORPHO_MIDNIGHT_REST_BASE}${path}`;
|
|
115
|
+
return getJsonViaOptionalProxy({ directUrl});
|
|
116
|
+
}
|
|
117
|
+
async function fetchMorphoMidnightBooks(args) {
|
|
118
|
+
const limit = args.limit == null ? void 0 : Math.min(Math.max(Math.floor(args.limit), 1), exports.MORPHO_MIDNIGHT_BOOKS_MAX_LIMIT);
|
|
119
|
+
const result = await api.MidnightApi.fetchBooks({
|
|
120
|
+
...midnightApiConfig(),
|
|
121
|
+
chainIds: [args.chainId],
|
|
122
|
+
loanTokens: args.loanTokens?.filter((a) => viem.isAddress(a)).map((a) => viem.getAddress(a)),
|
|
123
|
+
collateralTokens: args.collateralTokens?.filter((a) => viem.isAddress(a)).map((a) => viem.getAddress(a)),
|
|
124
|
+
sort: args.sort ? [args.sort] : ["maturity"],
|
|
125
|
+
limit,
|
|
126
|
+
cursor: args.cursor
|
|
127
|
+
});
|
|
128
|
+
return { data: [...result.data], cursor: result.cursor ?? null };
|
|
129
|
+
}
|
|
130
|
+
async function fetchMorphoMidnightBook(marketId) {
|
|
131
|
+
const id = marketId.trim();
|
|
132
|
+
if (!id) return null;
|
|
133
|
+
try {
|
|
134
|
+
const result = await api.MidnightApi.fetchBook({
|
|
135
|
+
...midnightApiConfig(),
|
|
136
|
+
marketId: id
|
|
137
|
+
});
|
|
138
|
+
return result.data;
|
|
139
|
+
} catch {
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
async function fetchMorphoMidnightBookQuote(args) {
|
|
144
|
+
const quote = await api.MidnightApi.fetchBookQuote({
|
|
145
|
+
...midnightApiConfig(),
|
|
146
|
+
marketId: args.marketId.trim(),
|
|
147
|
+
side: args.side,
|
|
148
|
+
assets: args.assets,
|
|
149
|
+
slippage: args.slippage?.trim() || "0.5"
|
|
150
|
+
});
|
|
151
|
+
return quote.data;
|
|
152
|
+
}
|
|
153
|
+
async function fetchMorphoMidnightMarketById(marketId) {
|
|
154
|
+
const id = marketId.trim();
|
|
155
|
+
if (!id) return null;
|
|
156
|
+
const j = await midnightGetJson(`/markets/${encodeURIComponent(id)}`);
|
|
157
|
+
const d = j.data;
|
|
158
|
+
if (!d?.market_id || !d.loan_token || !viem.isAddress(d.loan_token)) return null;
|
|
159
|
+
const midnight = d.midnight && viem.isAddress(d.midnight) ? viem.getAddress(d.midnight) : "0x0000000000000000000000000000000000000000";
|
|
160
|
+
const collaterals = (d.collaterals ?? []).filter((c) => c.token && viem.isAddress(c.token) && c.oracle && viem.isAddress(c.oracle)).map((c) => ({
|
|
161
|
+
token: viem.getAddress(c.token),
|
|
162
|
+
lltv: String(c.lltv ?? "0"),
|
|
163
|
+
liquidationCursor: String(c.liquidation_cursor ?? "0"),
|
|
164
|
+
oracle: viem.getAddress(c.oracle)
|
|
165
|
+
}));
|
|
166
|
+
return {
|
|
167
|
+
chainId: Number(d.chain_id ?? 0),
|
|
168
|
+
marketId: d.market_id,
|
|
169
|
+
midnight,
|
|
170
|
+
loanToken: viem.getAddress(d.loan_token),
|
|
171
|
+
maturity: Number(d.maturity ?? 0),
|
|
172
|
+
rcfThreshold: String(d.rcf_threshold ?? "0"),
|
|
173
|
+
enterGate: d.enter_gate && viem.isAddress(d.enter_gate) ? viem.getAddress(d.enter_gate) : viem.getAddress("0x0000000000000000000000000000000000000000"),
|
|
174
|
+
liquidatorGate: d.liquidator_gate && viem.isAddress(d.liquidator_gate) ? viem.getAddress(d.liquidator_gate) : viem.getAddress("0x0000000000000000000000000000000000000000"),
|
|
175
|
+
collaterals
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
function morphoMidnightMarketToParams(row) {
|
|
179
|
+
return {
|
|
180
|
+
chainId: BigInt(row.chainId),
|
|
181
|
+
midnight: row.midnight,
|
|
182
|
+
loanToken: row.loanToken,
|
|
183
|
+
collateralParams: row.collaterals.map((c) => ({
|
|
184
|
+
token: c.token,
|
|
185
|
+
lltv: BigInt(c.lltv),
|
|
186
|
+
liquidationCursor: BigInt(c.liquidationCursor),
|
|
187
|
+
oracle: c.oracle
|
|
188
|
+
})),
|
|
189
|
+
maturity: BigInt(row.maturity),
|
|
190
|
+
rcfThreshold: BigInt(row.rcfThreshold),
|
|
191
|
+
enterGate: row.enterGate,
|
|
192
|
+
liquidatorGate: row.liquidatorGate
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
function morphoMidnightBookToMarketParams(book) {
|
|
196
|
+
return {
|
|
197
|
+
chainId: BigInt(book.chainId),
|
|
198
|
+
midnight: viem.getAddress(book.midnight),
|
|
199
|
+
loanToken: viem.getAddress(book.loanToken),
|
|
200
|
+
collateralParams: book.collaterals.map((c) => ({
|
|
201
|
+
token: viem.getAddress(c.token),
|
|
202
|
+
lltv: BigInt(c.lltv),
|
|
203
|
+
liquidationCursor: BigInt(c.liquidationCursor),
|
|
204
|
+
oracle: viem.getAddress(c.oracle)
|
|
205
|
+
})),
|
|
206
|
+
maturity: BigInt(book.maturity),
|
|
207
|
+
rcfThreshold: BigInt(book.rcfThreshold),
|
|
208
|
+
enterGate: viem.getAddress(book.enterGate),
|
|
209
|
+
liquidatorGate: viem.getAddress(book.liquidatorGate)
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
async function fetchMorphoMidnightUserPositions(args) {
|
|
213
|
+
const user = args.user.trim();
|
|
214
|
+
if (!viem.isAddress(user)) return [];
|
|
215
|
+
const qs = new URLSearchParams();
|
|
216
|
+
if (args.types) qs.set("types", args.types);
|
|
217
|
+
if (args.activeOnly) qs.set("active_only", "true");
|
|
218
|
+
const q = qs.toString();
|
|
219
|
+
const path = `/users/${encodeURIComponent(viem.getAddress(user))}/positions${q ? `?${q}` : ""}`;
|
|
220
|
+
const j = await midnightGetJson(path);
|
|
221
|
+
const rows = [];
|
|
222
|
+
for (const p of j.data ?? []) {
|
|
223
|
+
if (!p.market_id) continue;
|
|
224
|
+
rows.push({
|
|
225
|
+
marketId: p.market_id,
|
|
226
|
+
type: p.type ?? "lend",
|
|
227
|
+
credit: String(p.credit ?? "0"),
|
|
228
|
+
debt: String(p.debt ?? "0"),
|
|
229
|
+
pendingFee: String(p.pending_fee ?? "0"),
|
|
230
|
+
lossFactor: String(p.loss_factor ?? "0"),
|
|
231
|
+
costBasis: p.cost_basis ?? null,
|
|
232
|
+
effectiveRateWad: p.effective_rate_wad ?? null,
|
|
233
|
+
maturity: p.maturity != null ? Number(p.maturity) : null,
|
|
234
|
+
loanToken: p.loan_token && viem.isAddress(p.loan_token) ? viem.getAddress(p.loan_token) : null,
|
|
235
|
+
collaterals: (p.collaterals ?? []).filter((c) => c.token && viem.isAddress(c.token)).map((c) => ({ token: viem.getAddress(c.token), amount: String(c.amount ?? "0") }))
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
return rows;
|
|
239
|
+
}
|
|
240
|
+
async function fetchMorphoMidnightUserMarketPosition(args) {
|
|
241
|
+
const marketId = args.marketId.trim();
|
|
242
|
+
const user = args.user.trim();
|
|
243
|
+
if (!marketId || !viem.isAddress(user)) return null;
|
|
244
|
+
const path = `/markets/${encodeURIComponent(marketId)}/users/${encodeURIComponent(viem.getAddress(user))}/position`;
|
|
245
|
+
const j = await midnightGetJson(path);
|
|
246
|
+
const p = j.data;
|
|
247
|
+
if (!p) return null;
|
|
248
|
+
return {
|
|
249
|
+
marketId,
|
|
250
|
+
type: p.type ?? "borrow",
|
|
251
|
+
credit: String(p.credit ?? "0"),
|
|
252
|
+
debt: String(p.debt ?? "0"),
|
|
253
|
+
pendingFee: String(p.pending_fee ?? "0"),
|
|
254
|
+
lossFactor: String(p.loss_factor ?? "0"),
|
|
255
|
+
maturity: p.maturity != null ? Number(p.maturity) : null,
|
|
256
|
+
loanToken: p.loan_token && viem.isAddress(p.loan_token) ? viem.getAddress(p.loan_token) : null,
|
|
257
|
+
collaterals: (p.collaterals ?? []).filter((c) => c.token && viem.isAddress(c.token)).map((c) => ({ token: viem.getAddress(c.token), amount: String(c.amount ?? "0") }))
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
var init_midnightApi = __esm({
|
|
261
|
+
"src/protocols/evm/morpho/midnightApi.ts"() {
|
|
262
|
+
init_defiProxy();
|
|
263
|
+
init_midnightConstants();
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
// src/core/registry.ts
|
|
268
|
+
var modules = [];
|
|
269
|
+
function registerProtocolModule(mod) {
|
|
270
|
+
const existing = modules.findIndex((m) => m.id === mod.id);
|
|
271
|
+
if (existing >= 0) {
|
|
272
|
+
modules[existing] = mod;
|
|
273
|
+
} else {
|
|
274
|
+
modules.push(mod);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
28
277
|
|
|
29
278
|
// src/protocols/evm/morpho/api.ts
|
|
279
|
+
init_defiProxy();
|
|
30
280
|
var MORPHO_GRAPHQL_URL = "https://api.morpho.org/graphql";
|
|
31
281
|
async function morphoGql(query, variables) {
|
|
32
282
|
const body = { query, variables: variables ?? {} };
|
|
@@ -797,6 +1047,32 @@ async function ensureMorphoChainAssetCache(chainId) {
|
|
|
797
1047
|
modes.set(k, prev);
|
|
798
1048
|
}
|
|
799
1049
|
}
|
|
1050
|
+
try {
|
|
1051
|
+
const { fetchMorphoMidnightBooks: fetchMorphoMidnightBooks2 } = await Promise.resolve().then(() => (init_midnightApi(), midnightApi_exports));
|
|
1052
|
+
const { MORPHO_MIDNIGHT_BOOKS_MAX_LIMIT: MORPHO_MIDNIGHT_BOOKS_MAX_LIMIT2 } = await Promise.resolve().then(() => (init_midnightConstants(), midnightConstants_exports));
|
|
1053
|
+
const { data: books } = await fetchMorphoMidnightBooks2({
|
|
1054
|
+
chainId,
|
|
1055
|
+
limit: MORPHO_MIDNIGHT_BOOKS_MAX_LIMIT2
|
|
1056
|
+
});
|
|
1057
|
+
for (const book of books) {
|
|
1058
|
+
const loanAddr = (book.loanToken ?? "").toString().trim();
|
|
1059
|
+
if (viem.isAddress(loanAddr)) {
|
|
1060
|
+
const k = viem.getAddress(loanAddr).toLowerCase();
|
|
1061
|
+
const prev = modes.get(k) ?? { earn: false, borrow: false, collateral: false };
|
|
1062
|
+
prev.borrow = true;
|
|
1063
|
+
modes.set(k, prev);
|
|
1064
|
+
}
|
|
1065
|
+
for (const c of book.collaterals ?? []) {
|
|
1066
|
+
const colAddr = (c.token ?? "").toString().trim();
|
|
1067
|
+
if (!viem.isAddress(colAddr)) continue;
|
|
1068
|
+
const k = viem.getAddress(colAddr).toLowerCase();
|
|
1069
|
+
const prev = modes.get(k) ?? { earn: false, borrow: false, collateral: false };
|
|
1070
|
+
prev.collateral = true;
|
|
1071
|
+
modes.set(k, prev);
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
} catch {
|
|
1075
|
+
}
|
|
800
1076
|
const cache = { modesByUnderlying: modes, nativeWrapped: null };
|
|
801
1077
|
chainAssetCache.set(chainId, cache);
|
|
802
1078
|
return cache;
|
|
@@ -1179,111 +1455,254 @@ function formatMorphoMarketApySummary(apy) {
|
|
|
1179
1455
|
}
|
|
1180
1456
|
|
|
1181
1457
|
// src/protocols/evm/morpho/midnightTypes.ts
|
|
1182
|
-
var MORPHO_MIDNIGHT_UNAVAILABLE_MESSAGE = "Morpho Midnight fixed-rate
|
|
1458
|
+
var MORPHO_MIDNIGHT_UNAVAILABLE_MESSAGE = "Morpho Midnight fixed-rate markets are available on supported chains (starting with Base). Open the Midnight tab to browse books.";
|
|
1183
1459
|
async function fetchMorphoMidnightIntents(_args) {
|
|
1184
1460
|
return [];
|
|
1185
1461
|
}
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
functionName: "decimals"
|
|
1211
|
-
});
|
|
1212
|
-
const n = typeof d === "bigint" ? Number(d) : Number(d);
|
|
1213
|
-
return !Number.isFinite(n) || n < 0 || n > 36 ? 18 : n;
|
|
1462
|
+
|
|
1463
|
+
// src/protocols/evm/morpho/index.ts
|
|
1464
|
+
init_midnightConstants();
|
|
1465
|
+
init_midnightApi();
|
|
1466
|
+
|
|
1467
|
+
// src/protocols/evm/morpho/midnightMath.ts
|
|
1468
|
+
function morphoMidnightAprFromPriceWad(priceWad, ttmSeconds) {
|
|
1469
|
+
const raw = typeof priceWad === "bigint" ? priceWad : BigInt(priceWad.split(".")[0] || "0");
|
|
1470
|
+
if (raw <= 0n || !Number.isFinite(ttmSeconds) || ttmSeconds <= 0) return null;
|
|
1471
|
+
const p = Number(raw) / 1e18;
|
|
1472
|
+
if (!Number.isFinite(p) || p <= 0) return null;
|
|
1473
|
+
const apr = (1 / p - 1) * (365 * 86400 / ttmSeconds);
|
|
1474
|
+
return Number.isFinite(apr) ? apr : null;
|
|
1475
|
+
}
|
|
1476
|
+
function formatMorphoMidnightAprPct(apr, digits = 2) {
|
|
1477
|
+
if (apr == null || !Number.isFinite(apr)) return "\u2014";
|
|
1478
|
+
return `${(apr * 100).toFixed(digits)}%`;
|
|
1479
|
+
}
|
|
1480
|
+
function morphoMidnightTtmSeconds(maturityUnix, nowMs = Date.now()) {
|
|
1481
|
+
return Math.max(0, maturityUnix - nowMs / 1e3);
|
|
1482
|
+
}
|
|
1483
|
+
function morphoMidnightUnitsFromAssets(targetAssets, priceWad) {
|
|
1484
|
+
if (priceWad <= 0n || targetAssets <= 0n) return 0n;
|
|
1485
|
+
return (targetAssets * 10n ** 18n + priceWad - 1n) / priceWad;
|
|
1214
1486
|
}
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
return
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
}
|
|
1487
|
+
|
|
1488
|
+
// src/protocols/evm/morpho/midnightDiscovery.ts
|
|
1489
|
+
init_midnightApi();
|
|
1490
|
+
init_midnightConstants();
|
|
1491
|
+
function shortAddr(a) {
|
|
1492
|
+
return a.length > 10 ? `${a.slice(0, 6)}\u2026${a.slice(-4)}` : a;
|
|
1493
|
+
}
|
|
1494
|
+
function maturityIso(maturity) {
|
|
1495
|
+
if (!maturity || maturity <= 0) return "\u2014";
|
|
1496
|
+
try {
|
|
1497
|
+
return new Date(maturity * 1e3).toISOString().slice(0, 10);
|
|
1498
|
+
} catch {
|
|
1499
|
+
return "\u2014";
|
|
1500
|
+
}
|
|
1229
1501
|
}
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
const
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1502
|
+
function morphoMidnightBookToDiscoveryRow(book) {
|
|
1503
|
+
const ttm = morphoMidnightTtmSeconds(book.maturity);
|
|
1504
|
+
const bestAsk = book.asks[0];
|
|
1505
|
+
const bestBid = book.bids[0];
|
|
1506
|
+
const lendAprN = bestAsk ? morphoMidnightAprFromPriceWad(bestAsk.price, ttm) : null;
|
|
1507
|
+
const borrowAprN = bestBid ? morphoMidnightAprFromPriceWad(bestBid.price, ttm) : null;
|
|
1508
|
+
const loan = viem.getAddress(book.loanToken);
|
|
1509
|
+
const collaterals = book.collaterals.map((c) => viem.getAddress(c.token));
|
|
1510
|
+
const primary = book.collaterals[0];
|
|
1511
|
+
const primaryAddr = primary ? viem.getAddress(primary.token) : null;
|
|
1512
|
+
const marketLabel = `${shortAddr(primaryAddr ?? "\u2014")}/${shortAddr(loan)} \xB7 ${maturityIso(book.maturity)}`;
|
|
1513
|
+
return {
|
|
1514
|
+
marketId: book.marketId,
|
|
1515
|
+
chainId: book.chainId,
|
|
1516
|
+
midnightAddress: viem.getAddress(book.midnight),
|
|
1517
|
+
loanTokenAddress: loan,
|
|
1518
|
+
maturity: book.maturity,
|
|
1519
|
+
maturityIso: maturityIso(book.maturity),
|
|
1520
|
+
collateralTokenAddresses: collaterals,
|
|
1521
|
+
primaryCollateralTokenAddress: primaryAddr,
|
|
1522
|
+
primaryCollateralLltv: primary?.lltv ?? null,
|
|
1523
|
+
bestAskPriceWad: bestAsk?.price ?? null,
|
|
1524
|
+
bestBidPriceWad: bestBid?.price ?? null,
|
|
1525
|
+
bestAskAssets: bestAsk?.assets ?? null,
|
|
1526
|
+
bestBidAssets: bestBid?.assets ?? null,
|
|
1527
|
+
lendApr: formatMorphoMidnightAprPct(lendAprN),
|
|
1528
|
+
borrowApr: formatMorphoMidnightAprPct(borrowAprN),
|
|
1529
|
+
lendAprNumeric: lendAprN,
|
|
1530
|
+
borrowAprNumeric: borrowAprN,
|
|
1531
|
+
marketLabel
|
|
1532
|
+
};
|
|
1533
|
+
}
|
|
1534
|
+
async function morphoFetchMidnightBooksSummary(args) {
|
|
1535
|
+
const limit = Math.min(Math.max(args.limit ?? exports.MORPHO_MIDNIGHT_BOOKS_MAX_LIMIT, 1), exports.MORPHO_MIDNIGHT_BOOKS_MAX_LIMIT);
|
|
1536
|
+
const loan = args.loan?.trim();
|
|
1537
|
+
const collateral = args.collateral?.trim();
|
|
1538
|
+
const loanTokens = loan && viem.isAddress(loan) ? [viem.getAddress(loan)] : void 0;
|
|
1539
|
+
const collateralTokens = collateral && viem.isAddress(collateral) ? [viem.getAddress(collateral)] : void 0;
|
|
1540
|
+
const { data } = await fetchMorphoMidnightBooks({
|
|
1541
|
+
chainId: args.chainId,
|
|
1542
|
+
loanTokens,
|
|
1543
|
+
collateralTokens,
|
|
1544
|
+
sort: "maturity",
|
|
1545
|
+
limit
|
|
1244
1546
|
});
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1547
|
+
let rows = data.map(morphoMidnightBookToDiscoveryRow);
|
|
1548
|
+
if (collateral && viem.isAddress(collateral)) {
|
|
1549
|
+
const col = viem.getAddress(collateral).toLowerCase();
|
|
1550
|
+
rows = rows.filter((r) => r.collateralTokenAddresses.some((a) => a.toLowerCase() === col));
|
|
1551
|
+
}
|
|
1552
|
+
const side = args.side ?? "either";
|
|
1553
|
+
if (side === "bids") {
|
|
1554
|
+
rows = rows.filter((r) => r.bestBidPriceWad != null);
|
|
1555
|
+
} else if (side === "asks") {
|
|
1556
|
+
rows = rows.filter((r) => r.bestAskPriceWad != null);
|
|
1557
|
+
}
|
|
1558
|
+
const q = (args.query ?? "").trim().toLowerCase();
|
|
1559
|
+
if (q) {
|
|
1560
|
+
rows = rows.filter((r) => {
|
|
1561
|
+
const hay = [
|
|
1562
|
+
r.marketId,
|
|
1563
|
+
r.marketLabel,
|
|
1564
|
+
r.loanTokenAddress,
|
|
1565
|
+
r.primaryCollateralTokenAddress ?? "",
|
|
1566
|
+
...r.collateralTokenAddresses
|
|
1567
|
+
].join(" ").toLowerCase();
|
|
1568
|
+
return hay.includes(q);
|
|
1569
|
+
});
|
|
1570
|
+
}
|
|
1571
|
+
return { books: rows.slice(0, limit) };
|
|
1572
|
+
}
|
|
1573
|
+
async function fetchMorphoMidnightBooksForAsset(args) {
|
|
1574
|
+
const asset = args.assetAddress.trim();
|
|
1575
|
+
if (!viem.isAddress(asset)) return [];
|
|
1576
|
+
const mode = args.mode ?? "any";
|
|
1577
|
+
if (mode === "lend") {
|
|
1578
|
+
const { books } = await morphoFetchMidnightBooksSummary({
|
|
1579
|
+
chainId: args.chainId,
|
|
1580
|
+
loan: asset,
|
|
1581
|
+
side: "asks",
|
|
1582
|
+
limit: exports.MORPHO_MIDNIGHT_BOOKS_MAX_LIMIT
|
|
1583
|
+
});
|
|
1584
|
+
return books;
|
|
1585
|
+
}
|
|
1586
|
+
if (mode === "borrow") {
|
|
1587
|
+
const asCollateral = await morphoFetchMidnightBooksSummary({
|
|
1588
|
+
chainId: args.chainId,
|
|
1589
|
+
collateral: asset,
|
|
1590
|
+
side: "bids",
|
|
1591
|
+
limit: exports.MORPHO_MIDNIGHT_BOOKS_MAX_LIMIT
|
|
1592
|
+
});
|
|
1593
|
+
const asLoan2 = await morphoFetchMidnightBooksSummary({
|
|
1594
|
+
chainId: args.chainId,
|
|
1595
|
+
loan: asset,
|
|
1596
|
+
side: "bids",
|
|
1597
|
+
limit: exports.MORPHO_MIDNIGHT_BOOKS_MAX_LIMIT
|
|
1598
|
+
});
|
|
1599
|
+
const byId2 = /* @__PURE__ */ new Map();
|
|
1600
|
+
for (const b of [...asCollateral.books, ...asLoan2.books]) byId2.set(b.marketId.toLowerCase(), b);
|
|
1601
|
+
return [...byId2.values()];
|
|
1602
|
+
}
|
|
1603
|
+
const [asLoan, asCol] = await Promise.all([
|
|
1604
|
+
morphoFetchMidnightBooksSummary({
|
|
1605
|
+
chainId: args.chainId,
|
|
1606
|
+
loan: asset,
|
|
1607
|
+
limit: exports.MORPHO_MIDNIGHT_BOOKS_MAX_LIMIT
|
|
1261
1608
|
}),
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
args: [id]
|
|
1609
|
+
morphoFetchMidnightBooksSummary({
|
|
1610
|
+
chainId: args.chainId,
|
|
1611
|
+
collateral: asset,
|
|
1612
|
+
limit: exports.MORPHO_MIDNIGHT_BOOKS_MAX_LIMIT
|
|
1267
1613
|
})
|
|
1268
1614
|
]);
|
|
1269
|
-
const
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1615
|
+
const byId = /* @__PURE__ */ new Map();
|
|
1616
|
+
for (const b of [...asLoan.books, ...asCol.books]) byId.set(b.marketId.toLowerCase(), b);
|
|
1617
|
+
return [...byId.values()];
|
|
1618
|
+
}
|
|
1619
|
+
|
|
1620
|
+
// src/protocols/evm/morpho/midnightQuote.ts
|
|
1621
|
+
init_midnightApi();
|
|
1622
|
+
init_midnightConstants();
|
|
1623
|
+
async function morphoFetchMidnightQuote(args) {
|
|
1624
|
+
const assets = typeof args.assets === "bigint" ? args.assets : BigInt(String(args.assets).split(".")[0] || "0");
|
|
1625
|
+
if (assets <= 0n) throw new Error("Quote assets must be > 0.");
|
|
1626
|
+
const slippage = (args.slippagePct ?? exports.MORPHO_MIDNIGHT_DEFAULT_SLIPPAGE_PCT).trim() || exports.MORPHO_MIDNIGHT_DEFAULT_SLIPPAGE_PCT;
|
|
1627
|
+
const [quote, book] = await Promise.all([
|
|
1628
|
+
fetchMorphoMidnightBookQuote({
|
|
1629
|
+
marketId: args.marketId,
|
|
1630
|
+
side: args.side,
|
|
1631
|
+
assets,
|
|
1632
|
+
slippage
|
|
1633
|
+
}),
|
|
1634
|
+
fetchMorphoMidnightBook(args.marketId)
|
|
1635
|
+
]);
|
|
1636
|
+
const maturity = book?.maturity ?? null;
|
|
1637
|
+
const ttm = maturity != null ? morphoMidnightTtmSeconds(maturity) : 0;
|
|
1638
|
+
const aprN = morphoMidnightAprFromPriceWad(quote.averageBestPrice, ttm);
|
|
1639
|
+
return {
|
|
1640
|
+
marketId: args.marketId.trim(),
|
|
1641
|
+
side: args.side,
|
|
1642
|
+
averageBestPriceWad: quote.averageBestPrice,
|
|
1643
|
+
averageWorstPriceWad: quote.averageWorstPrice,
|
|
1644
|
+
availableAssets: quote.availableAssets,
|
|
1645
|
+
availableUnits: quote.availableUnits,
|
|
1646
|
+
impliedApr: formatMorphoMidnightAprPct(aprN),
|
|
1647
|
+
impliedAprNumeric: aprN,
|
|
1648
|
+
maturity,
|
|
1649
|
+
takeableOfferCount: quote.takeableOffers.length,
|
|
1650
|
+
takeableOffers: quote.takeableOffers
|
|
1651
|
+
};
|
|
1652
|
+
}
|
|
1653
|
+
async function morphoFetchMidnightQuoteSummary(args) {
|
|
1654
|
+
const { takeableOffers: _takes, ...rest } = await morphoFetchMidnightQuote(args);
|
|
1655
|
+
return rest;
|
|
1656
|
+
}
|
|
1657
|
+
|
|
1658
|
+
// src/protocols/evm/morpho/midnightPositions.ts
|
|
1659
|
+
init_midnightApi();
|
|
1660
|
+
function maturityIso2(maturity) {
|
|
1661
|
+
if (maturity == null || maturity <= 0) return "\u2014";
|
|
1662
|
+
try {
|
|
1663
|
+
return new Date(maturity * 1e3).toISOString().slice(0, 10);
|
|
1664
|
+
} catch {
|
|
1665
|
+
return "\u2014";
|
|
1666
|
+
}
|
|
1667
|
+
}
|
|
1668
|
+
function effectiveRateLabel(wad) {
|
|
1669
|
+
if (!wad) return "\u2014";
|
|
1670
|
+
try {
|
|
1671
|
+
const n = Number(BigInt(wad.split(".")[0] || "0")) / 1e18;
|
|
1672
|
+
return formatMorphoMidnightAprPct(Number.isFinite(n) ? n : null);
|
|
1673
|
+
} catch {
|
|
1674
|
+
return "\u2014";
|
|
1675
|
+
}
|
|
1676
|
+
}
|
|
1677
|
+
function morphoMidnightPositionToDiscoveryRow(p) {
|
|
1678
|
+
const debt = BigInt(p.debt || "0");
|
|
1679
|
+
const fee = BigInt(p.pendingFee || "0");
|
|
1680
|
+
return {
|
|
1681
|
+
marketId: p.marketId,
|
|
1682
|
+
type: p.type,
|
|
1683
|
+
credit: p.credit,
|
|
1684
|
+
debt: p.debt,
|
|
1685
|
+
pendingFee: p.pendingFee,
|
|
1686
|
+
repayAssets: (debt + fee).toString(),
|
|
1687
|
+
maturity: p.maturity ?? null,
|
|
1688
|
+
maturityIso: maturityIso2(p.maturity ?? null),
|
|
1689
|
+
loanTokenAddress: p.loanToken ?? null,
|
|
1690
|
+
collateralTokenAddresses: p.collaterals.map((c) => c.token),
|
|
1691
|
+
collateralAmounts: p.collaterals.map((c) => ({ token: c.token, amount: c.amount })),
|
|
1692
|
+
effectiveRate: effectiveRateLabel(p.effectiveRateWad),
|
|
1693
|
+
costBasis: p.costBasis ?? null
|
|
1694
|
+
};
|
|
1695
|
+
}
|
|
1696
|
+
async function morphoFetchMidnightPositionsSummary(args) {
|
|
1697
|
+
if (!viem.isAddress(args.user)) {
|
|
1698
|
+
throw new Error("user must be a valid EVM address.");
|
|
1699
|
+
}
|
|
1700
|
+
const rows = await fetchMorphoMidnightUserPositions({
|
|
1701
|
+
user: viem.getAddress(args.user),
|
|
1702
|
+
types: args.types,
|
|
1703
|
+
activeOnly: args.activeOnly
|
|
1278
1704
|
});
|
|
1279
|
-
|
|
1280
|
-
const totalBorrowShares = BigInt(mkt[3]);
|
|
1281
|
-
if (totalBorrowShares === 0n) return { healthy: true, healthFactor: null };
|
|
1282
|
-
const borrowed = (borrowShares * totalBorrowAssets + totalBorrowShares - 1n) / totalBorrowShares;
|
|
1283
|
-
const maxBorrow = collateral * price / ORACLE_PRICE_SCALE * lltv / WAD;
|
|
1284
|
-
const healthy = maxBorrow >= borrowed;
|
|
1285
|
-
const hf = borrowed === 0n ? null : Number(maxBorrow * WAD / borrowed) / Number(WAD);
|
|
1286
|
-
return { healthy, healthFactor: hf != null && Number.isFinite(hf) ? hf : null };
|
|
1705
|
+
return { positions: rows.map(morphoMidnightPositionToDiscoveryRow) };
|
|
1287
1706
|
}
|
|
1288
1707
|
|
|
1289
1708
|
// src/core/purpose.ts
|
|
@@ -1520,40 +1939,603 @@ async function buildEvmMultisignBatch(args) {
|
|
|
1520
1939
|
return result;
|
|
1521
1940
|
}
|
|
1522
1941
|
|
|
1523
|
-
// src/protocols/evm/morpho/
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
var MORPHO_WETH_DEPOSIT_FALLBACK = 120000n;
|
|
1942
|
+
// src/protocols/evm/morpho/midnightMultisign.ts
|
|
1943
|
+
init_midnightConstants();
|
|
1944
|
+
init_midnightApi();
|
|
1527
1945
|
var wethDepositAbi = viem.parseAbi(["function deposit() payable"]);
|
|
1528
|
-
var
|
|
1529
|
-
"function allowance(address owner, address spender) view returns (uint256)"
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
var vaultDepositAbi = viem.parseAbi([
|
|
1533
|
-
"function deposit(uint256 assets, address onBehalf) returns (uint256 shares)"
|
|
1946
|
+
var erc20Abi = viem.parseAbi([
|
|
1947
|
+
"function allowance(address owner, address spender) view returns (uint256)",
|
|
1948
|
+
"function decimals() view returns (uint8)",
|
|
1949
|
+
"function approve(address spender, uint256 amount) returns (bool)"
|
|
1534
1950
|
]);
|
|
1535
|
-
|
|
1536
|
-
const asset = viem.getAddress(args.underlying);
|
|
1537
|
-
const vault = viem.getAddress(args.vault);
|
|
1538
|
-
const weth = viem.getAddress(args.nativeWrapped);
|
|
1539
|
-
const executor = viem.getAddress(args.executorAddress);
|
|
1540
|
-
const onBehalf = viem.getAddress(args.onBehalf);
|
|
1541
|
-
if (args.isNativeIn && asset.toLowerCase() !== weth.toLowerCase()) {
|
|
1542
|
-
throw new Error("Native deposit path: underlying asset must match the chain wrapped native token.");
|
|
1543
|
-
}
|
|
1951
|
+
function publicClientFor(rpcUrl, chainId) {
|
|
1544
1952
|
const ch = viem.defineChain({
|
|
1545
|
-
id:
|
|
1546
|
-
name: "
|
|
1953
|
+
id: chainId,
|
|
1954
|
+
name: "MorphoMidnight",
|
|
1547
1955
|
nativeCurrency: { decimals: 18, name: "Ether", symbol: "ETH" },
|
|
1548
|
-
rpcUrls: { default: { http: [
|
|
1956
|
+
rpcUrls: { default: { http: [rpcUrl] } }
|
|
1549
1957
|
});
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
const
|
|
1958
|
+
return viem.createPublicClient({ chain: ch, transport: viem.http(rpcUrl) });
|
|
1959
|
+
}
|
|
1960
|
+
async function readTokenDecimals(args) {
|
|
1961
|
+
const publicClient = publicClientFor(args.rpcUrl, args.chainId);
|
|
1962
|
+
const d = await publicClient.readContract({
|
|
1963
|
+
address: args.token,
|
|
1964
|
+
abi: erc20Abi,
|
|
1965
|
+
functionName: "decimals"
|
|
1966
|
+
});
|
|
1967
|
+
const n = typeof d === "bigint" ? Number(d) : Number(d);
|
|
1968
|
+
return !Number.isFinite(n) || n < 0 || n > 36 ? 18 : n;
|
|
1969
|
+
}
|
|
1970
|
+
async function buildApproveSteps(args) {
|
|
1971
|
+
const steps = [];
|
|
1972
|
+
let spendToken = args.token;
|
|
1973
|
+
if (args.isNativeIn && args.nativeWrapped) {
|
|
1974
|
+
const weth = viem.getAddress(args.nativeWrapped);
|
|
1975
|
+
if (spendToken.toLowerCase() !== weth.toLowerCase()) {
|
|
1976
|
+
throw new Error("Native path: token must match wrapped native.");
|
|
1977
|
+
}
|
|
1978
|
+
steps.push({
|
|
1979
|
+
kind: "weth_deposit",
|
|
1980
|
+
to: weth,
|
|
1981
|
+
data: viem.encodeFunctionData({ abi: wethDepositAbi, functionName: "deposit" }),
|
|
1982
|
+
value: args.amountWei
|
|
1983
|
+
});
|
|
1984
|
+
spendToken = weth;
|
|
1985
|
+
}
|
|
1986
|
+
const publicClient = publicClientFor(args.rpcUrl, args.chainId);
|
|
1987
|
+
const currentAllowance = await publicClient.readContract({
|
|
1988
|
+
address: spendToken,
|
|
1989
|
+
abi: erc20Abi,
|
|
1990
|
+
functionName: "allowance",
|
|
1991
|
+
args: [args.executor, args.spender]
|
|
1992
|
+
});
|
|
1993
|
+
if (currentAllowance < args.amountWei) {
|
|
1994
|
+
if (currentAllowance > 0n) {
|
|
1995
|
+
steps.push({
|
|
1996
|
+
kind: "approve",
|
|
1997
|
+
to: spendToken,
|
|
1998
|
+
data: viem.encodeFunctionData({ abi: erc20Abi, functionName: "approve", args: [args.spender, 0n] }),
|
|
1999
|
+
value: 0n
|
|
2000
|
+
});
|
|
2001
|
+
}
|
|
2002
|
+
steps.push({
|
|
2003
|
+
kind: "approve",
|
|
2004
|
+
to: spendToken,
|
|
2005
|
+
data: viem.encodeFunctionData({
|
|
2006
|
+
abi: erc20Abi,
|
|
2007
|
+
functionName: "approve",
|
|
2008
|
+
args: [args.spender, args.amountWei]
|
|
2009
|
+
}),
|
|
2010
|
+
value: 0n
|
|
2011
|
+
});
|
|
2012
|
+
}
|
|
2013
|
+
return steps;
|
|
2014
|
+
}
|
|
2015
|
+
async function ensureBundlesAuthorizedSteps(args) {
|
|
2016
|
+
const publicClient = publicClientFor(args.rpcUrl, args.chainId);
|
|
2017
|
+
const authorized = await publicClient.readContract({
|
|
2018
|
+
address: args.midnight,
|
|
2019
|
+
abi: midnightSdk.midnightAbi,
|
|
2020
|
+
functionName: "isAuthorized",
|
|
2021
|
+
args: [args.onBehalf, args.bundles]
|
|
2022
|
+
});
|
|
2023
|
+
if (authorized) return [];
|
|
2024
|
+
return [
|
|
2025
|
+
{
|
|
2026
|
+
to: args.midnight,
|
|
2027
|
+
data: viem.encodeFunctionData({
|
|
2028
|
+
abi: midnightSdk.midnightAbi,
|
|
2029
|
+
functionName: "setIsAuthorized",
|
|
2030
|
+
args: [args.bundles, true, args.onBehalf]
|
|
2031
|
+
}),
|
|
2032
|
+
value: 0n,
|
|
2033
|
+
fallbackGas: exports.MORPHO_MIDNIGHT_AUTHORIZE_FALLBACK_GAS
|
|
2034
|
+
}
|
|
2035
|
+
];
|
|
2036
|
+
}
|
|
2037
|
+
function approveStepsToEvm(steps) {
|
|
2038
|
+
return steps.map((s) => ({
|
|
2039
|
+
to: s.to,
|
|
2040
|
+
data: s.data,
|
|
2041
|
+
value: s.value,
|
|
2042
|
+
fallbackGas: s.kind === "weth_deposit" ? exports.MORPHO_MIDNIGHT_WETH_DEPOSIT_FALLBACK : exports.MORPHO_MIDNIGHT_ERC20_APPROVE_FALLBACK
|
|
2043
|
+
}));
|
|
2044
|
+
}
|
|
2045
|
+
function offerFillsFromTakes(takes) {
|
|
2046
|
+
return takes.map((t) => ({
|
|
2047
|
+
offer: t.offer,
|
|
2048
|
+
ratifierData: t.ratifierData,
|
|
2049
|
+
units: t.units
|
|
2050
|
+
}));
|
|
2051
|
+
}
|
|
2052
|
+
function resolveAddresses(args) {
|
|
2053
|
+
const known = morphoMidnightAddressesForChain(args.chainId);
|
|
2054
|
+
const midnight = args.midnight ? viem.getAddress(args.midnight) : args.marketMidnight ? viem.getAddress(args.marketMidnight) : known?.midnight;
|
|
2055
|
+
const bundles = args.bundles ? viem.getAddress(args.bundles) : known?.bundles;
|
|
2056
|
+
if (!midnight || !bundles) {
|
|
2057
|
+
throw new Error(
|
|
2058
|
+
`Morpho Midnight addresses unknown for chain ${args.chainId}. Pass midnight/bundles or use a supported chain.`
|
|
2059
|
+
);
|
|
2060
|
+
}
|
|
2061
|
+
return { midnight, bundles };
|
|
2062
|
+
}
|
|
2063
|
+
function deadlineFromNow(seconds) {
|
|
2064
|
+
const s = seconds && seconds > 0 ? seconds : exports.MORPHO_MIDNIGHT_DEFAULT_DEADLINE_SECONDS;
|
|
2065
|
+
return BigInt(Math.floor(Date.now() / 1e3) + s);
|
|
2066
|
+
}
|
|
2067
|
+
function collateralIndex(market, collateralToken) {
|
|
2068
|
+
const idx = market.collateralParams.findIndex(
|
|
2069
|
+
(c) => c.token.toLowerCase() === collateralToken.toLowerCase()
|
|
2070
|
+
);
|
|
2071
|
+
if (idx < 0) {
|
|
2072
|
+
throw new Error(`Collateral ${collateralToken} is not in market collateralParams.`);
|
|
2073
|
+
}
|
|
2074
|
+
return BigInt(idx);
|
|
2075
|
+
}
|
|
2076
|
+
async function buildEvmMultisignBodyMorphoMidnightLendBatch(args) {
|
|
2077
|
+
const taker = viem.getAddress(args.taker);
|
|
2078
|
+
const executor = viem.getAddress(args.executorAddress);
|
|
2079
|
+
const book = await fetchMorphoMidnightBook(args.marketId);
|
|
2080
|
+
if (!book) throw new Error(`Midnight book not found: ${args.marketId}`);
|
|
2081
|
+
const market = morphoMidnightBookToMarketParams(book);
|
|
2082
|
+
const { midnight, bundles } = resolveAddresses({
|
|
2083
|
+
chainId: args.chainId,
|
|
2084
|
+
midnight: args.midnight,
|
|
2085
|
+
bundles: args.bundles,
|
|
2086
|
+
marketMidnight: market.midnight
|
|
2087
|
+
});
|
|
2088
|
+
const loanToken = args.loanToken ? viem.getAddress(args.loanToken) : viem.getAddress(market.loanToken);
|
|
2089
|
+
if (loanToken.toLowerCase() !== market.loanToken.toLowerCase()) {
|
|
2090
|
+
throw new Error("loanToken does not match Midnight market loan token.");
|
|
2091
|
+
}
|
|
2092
|
+
const dec = await readTokenDecimals({ rpcUrl: args.rpcUrl, chainId: args.chainId, token: loanToken });
|
|
2093
|
+
const targetBuyerAssets = viem.parseUnits(args.amountHuman, dec);
|
|
2094
|
+
if (targetBuyerAssets === 0n) throw new Error("Lend amount is zero.");
|
|
2095
|
+
const slippage = (args.slippagePct ?? exports.MORPHO_MIDNIGHT_DEFAULT_SLIPPAGE_PCT).trim();
|
|
2096
|
+
const quote = await fetchMorphoMidnightBookQuote({
|
|
2097
|
+
marketId: args.marketId,
|
|
2098
|
+
side: "asks",
|
|
2099
|
+
assets: targetBuyerAssets,
|
|
2100
|
+
slippage
|
|
2101
|
+
});
|
|
2102
|
+
if (!quote.takeableOffers.length) {
|
|
2103
|
+
throw new Error("No takeable Midnight asks for this size. Try a smaller amount or another maturity.");
|
|
2104
|
+
}
|
|
2105
|
+
const worst = BigInt(quote.averageWorstPrice.split(".")[0] || "0");
|
|
2106
|
+
const minUnits = morphoMidnightUnitsFromAssets(targetBuyerAssets, worst);
|
|
2107
|
+
const deadline = deadlineFromNow(args.deadlineSeconds);
|
|
2108
|
+
const offerFills = offerFillsFromTakes(quote.takeableOffers);
|
|
2109
|
+
const approveSteps = await buildApproveSteps({
|
|
2110
|
+
rpcUrl: args.rpcUrl,
|
|
2111
|
+
chainId: args.chainId,
|
|
2112
|
+
token: loanToken,
|
|
2113
|
+
spender: bundles,
|
|
2114
|
+
amountWei: targetBuyerAssets,
|
|
2115
|
+
executor,
|
|
2116
|
+
isNativeIn: args.isNativeIn,
|
|
2117
|
+
nativeWrapped: args.nativeWrapped
|
|
2118
|
+
});
|
|
2119
|
+
const authSteps = await ensureBundlesAuthorizedSteps({
|
|
2120
|
+
rpcUrl: args.rpcUrl,
|
|
2121
|
+
chainId: args.chainId,
|
|
2122
|
+
midnight,
|
|
2123
|
+
bundles,
|
|
2124
|
+
onBehalf: taker
|
|
2125
|
+
});
|
|
2126
|
+
const lendData = viem.encodeFunctionData({
|
|
2127
|
+
abi: midnightSdk.midnightBundlesAbi,
|
|
2128
|
+
functionName: "midnightBundlesV1BuyWithAssetsTargetAndWithdrawCollateral",
|
|
2129
|
+
args: [
|
|
2130
|
+
targetBuyerAssets,
|
|
2131
|
+
minUnits,
|
|
2132
|
+
taker,
|
|
2133
|
+
false,
|
|
2134
|
+
exports.TOKEN_PERMIT_NONE,
|
|
2135
|
+
offerFills,
|
|
2136
|
+
[],
|
|
2137
|
+
taker,
|
|
2138
|
+
0n,
|
|
2139
|
+
viem.zeroAddress,
|
|
2140
|
+
viem.maxUint256,
|
|
2141
|
+
deadline
|
|
2142
|
+
]
|
|
2143
|
+
});
|
|
2144
|
+
const marketLabel = (args.marketLabel ?? "").trim() || `Midnight ${args.marketId.slice(0, 10)}\u2026`;
|
|
2145
|
+
const evmSteps = [
|
|
2146
|
+
...approveStepsToEvm(approveSteps),
|
|
2147
|
+
...authSteps,
|
|
2148
|
+
{ to: bundles, data: lendData, value: 0n, fallbackGas: exports.MORPHO_MIDNIGHT_LEND_FALLBACK_GAS }
|
|
2149
|
+
];
|
|
2150
|
+
return buildEvmMultisignBatch({
|
|
2151
|
+
context: {
|
|
2152
|
+
chainCategory: "evm",
|
|
2153
|
+
keyGen: args.keyGen,
|
|
2154
|
+
purposeText: args.purposeText,
|
|
2155
|
+
chainId: args.chainId,
|
|
2156
|
+
rpcUrl: args.rpcUrl,
|
|
2157
|
+
executorAddress: executor,
|
|
2158
|
+
chainDetail: args.chainDetail,
|
|
2159
|
+
useCustomGas: args.useCustomGas,
|
|
2160
|
+
customGasChainDetails: args.customGasChainDetails
|
|
2161
|
+
},
|
|
2162
|
+
steps: evmSteps,
|
|
2163
|
+
purposeSuffix: `Morpho Midnight: lend (${args.amountHuman}) on "${marketLabel}".`,
|
|
2164
|
+
firstMsgRawNo0x: evmSteps[0].data.slice(2),
|
|
2165
|
+
destinationAddress: bundles,
|
|
2166
|
+
buildBatchMeta: ({ gasLimit }) => ({
|
|
2167
|
+
signatureText: JSON.stringify({
|
|
2168
|
+
kind: "MorphoMidnight",
|
|
2169
|
+
name: "lend",
|
|
2170
|
+
marketLabel,
|
|
2171
|
+
amountHuman: args.amountHuman
|
|
2172
|
+
}),
|
|
2173
|
+
evm: { type: "morpho_midnight_lend", version: 1, chainId: String(args.chainId) },
|
|
2174
|
+
morpho: {
|
|
2175
|
+
marketId: args.marketId,
|
|
2176
|
+
marketLabel,
|
|
2177
|
+
amountHuman: args.amountHuman,
|
|
2178
|
+
gasBuild: { baseGasUnits: gasLimit.toString() }
|
|
2179
|
+
}
|
|
2180
|
+
})
|
|
2181
|
+
});
|
|
2182
|
+
}
|
|
2183
|
+
async function buildEvmMultisignBodyMorphoMidnightBorrowBatch(args) {
|
|
2184
|
+
const taker = viem.getAddress(args.taker);
|
|
2185
|
+
const receiver = viem.getAddress(args.receiver ?? args.taker);
|
|
2186
|
+
const executor = viem.getAddress(args.executorAddress);
|
|
2187
|
+
const collateralToken = viem.getAddress(args.collateralToken);
|
|
2188
|
+
const book = await fetchMorphoMidnightBook(args.marketId);
|
|
2189
|
+
if (!book) throw new Error(`Midnight book not found: ${args.marketId}`);
|
|
2190
|
+
const market = morphoMidnightBookToMarketParams(book);
|
|
2191
|
+
const { midnight, bundles } = resolveAddresses({
|
|
2192
|
+
chainId: args.chainId,
|
|
2193
|
+
midnight: args.midnight,
|
|
2194
|
+
bundles: args.bundles,
|
|
2195
|
+
marketMidnight: market.midnight
|
|
2196
|
+
});
|
|
2197
|
+
const loanToken = args.loanToken ? viem.getAddress(args.loanToken) : viem.getAddress(market.loanToken);
|
|
2198
|
+
const loanDec = await readTokenDecimals({ rpcUrl: args.rpcUrl, chainId: args.chainId, token: loanToken });
|
|
2199
|
+
const colDec = await readTokenDecimals({
|
|
2200
|
+
rpcUrl: args.rpcUrl,
|
|
2201
|
+
chainId: args.chainId,
|
|
2202
|
+
token: collateralToken
|
|
2203
|
+
});
|
|
2204
|
+
const targetSellerAssets = viem.parseUnits(args.borrowAmountHuman, loanDec);
|
|
2205
|
+
const collateralAmount = viem.parseUnits(args.collateralAmountHuman, colDec);
|
|
2206
|
+
if (targetSellerAssets === 0n) throw new Error("Borrow amount is zero.");
|
|
2207
|
+
if (collateralAmount === 0n) throw new Error("Collateral amount is zero.");
|
|
2208
|
+
const colIdx = args.collateralIndex != null && args.collateralIndex >= 0 ? BigInt(args.collateralIndex) : collateralIndex(market, collateralToken);
|
|
2209
|
+
const slippage = (args.slippagePct ?? exports.MORPHO_MIDNIGHT_DEFAULT_SLIPPAGE_PCT).trim();
|
|
2210
|
+
const quote = await fetchMorphoMidnightBookQuote({
|
|
2211
|
+
marketId: args.marketId,
|
|
2212
|
+
side: "bids",
|
|
2213
|
+
assets: targetSellerAssets,
|
|
2214
|
+
slippage
|
|
2215
|
+
});
|
|
2216
|
+
if (!quote.takeableOffers.length) {
|
|
2217
|
+
throw new Error("No takeable Midnight bids for this size. Try a smaller amount or another maturity.");
|
|
2218
|
+
}
|
|
2219
|
+
const worst = BigInt(quote.averageWorstPrice.split(".")[0] || "0");
|
|
2220
|
+
const maxUnits = morphoMidnightUnitsFromAssets(targetSellerAssets, worst);
|
|
2221
|
+
const deadline = deadlineFromNow(args.deadlineSeconds);
|
|
2222
|
+
const offerFills = offerFillsFromTakes(quote.takeableOffers);
|
|
2223
|
+
const approveSteps = await buildApproveSteps({
|
|
2224
|
+
rpcUrl: args.rpcUrl,
|
|
2225
|
+
chainId: args.chainId,
|
|
2226
|
+
token: collateralToken,
|
|
2227
|
+
spender: bundles,
|
|
2228
|
+
amountWei: collateralAmount,
|
|
2229
|
+
executor,
|
|
2230
|
+
isNativeIn: args.isNativeIn,
|
|
2231
|
+
nativeWrapped: args.nativeWrapped
|
|
2232
|
+
});
|
|
2233
|
+
const authSteps = await ensureBundlesAuthorizedSteps({
|
|
2234
|
+
rpcUrl: args.rpcUrl,
|
|
2235
|
+
chainId: args.chainId,
|
|
2236
|
+
midnight,
|
|
2237
|
+
bundles,
|
|
2238
|
+
onBehalf: taker
|
|
2239
|
+
});
|
|
2240
|
+
const borrowData = viem.encodeFunctionData({
|
|
2241
|
+
abi: midnightSdk.midnightBundlesAbi,
|
|
2242
|
+
functionName: "midnightBundlesV1SupplyCollateralAndSellWithAssetsTarget",
|
|
2243
|
+
args: [
|
|
2244
|
+
targetSellerAssets,
|
|
2245
|
+
maxUnits,
|
|
2246
|
+
taker,
|
|
2247
|
+
false,
|
|
2248
|
+
receiver,
|
|
2249
|
+
[{ collateralIndex: colIdx, assets: collateralAmount, permit: exports.TOKEN_PERMIT_NONE }],
|
|
2250
|
+
offerFills,
|
|
2251
|
+
0n,
|
|
2252
|
+
viem.zeroAddress,
|
|
2253
|
+
viem.maxUint256,
|
|
2254
|
+
deadline
|
|
2255
|
+
]
|
|
2256
|
+
});
|
|
2257
|
+
const marketLabel = (args.marketLabel ?? "").trim() || `Midnight ${args.marketId.slice(0, 10)}\u2026`;
|
|
2258
|
+
const evmSteps = [
|
|
2259
|
+
...approveStepsToEvm(approveSteps),
|
|
2260
|
+
...authSteps,
|
|
2261
|
+
{ to: bundles, data: borrowData, value: 0n, fallbackGas: exports.MORPHO_MIDNIGHT_BORROW_FALLBACK_GAS }
|
|
2262
|
+
];
|
|
2263
|
+
return buildEvmMultisignBatch({
|
|
2264
|
+
context: {
|
|
2265
|
+
chainCategory: "evm",
|
|
2266
|
+
keyGen: args.keyGen,
|
|
2267
|
+
purposeText: args.purposeText,
|
|
2268
|
+
chainId: args.chainId,
|
|
2269
|
+
rpcUrl: args.rpcUrl,
|
|
2270
|
+
executorAddress: executor,
|
|
2271
|
+
chainDetail: args.chainDetail,
|
|
2272
|
+
useCustomGas: args.useCustomGas,
|
|
2273
|
+
customGasChainDetails: args.customGasChainDetails
|
|
2274
|
+
},
|
|
2275
|
+
steps: evmSteps,
|
|
2276
|
+
purposeSuffix: `Morpho Midnight: borrow (${args.borrowAmountHuman}) on "${marketLabel}".`,
|
|
2277
|
+
firstMsgRawNo0x: evmSteps[0].data.slice(2),
|
|
2278
|
+
destinationAddress: bundles,
|
|
2279
|
+
buildBatchMeta: ({ gasLimit }) => ({
|
|
2280
|
+
signatureText: JSON.stringify({
|
|
2281
|
+
kind: "MorphoMidnight",
|
|
2282
|
+
name: "borrow",
|
|
2283
|
+
marketLabel,
|
|
2284
|
+
borrowAmountHuman: args.borrowAmountHuman,
|
|
2285
|
+
collateralAmountHuman: args.collateralAmountHuman
|
|
2286
|
+
}),
|
|
2287
|
+
evm: { type: "morpho_midnight_borrow", version: 1, chainId: String(args.chainId) },
|
|
2288
|
+
morpho: {
|
|
2289
|
+
marketId: args.marketId,
|
|
2290
|
+
marketLabel,
|
|
2291
|
+
amountHuman: args.borrowAmountHuman,
|
|
2292
|
+
gasBuild: { baseGasUnits: gasLimit.toString() }
|
|
2293
|
+
}
|
|
2294
|
+
})
|
|
2295
|
+
});
|
|
2296
|
+
}
|
|
2297
|
+
async function buildEvmMultisignBodyMorphoMidnightRepayBatch(args) {
|
|
2298
|
+
const onBehalf = viem.getAddress(args.onBehalf);
|
|
2299
|
+
const collateralReceiver = viem.getAddress(args.collateralReceiver ?? args.onBehalf);
|
|
2300
|
+
const executor = viem.getAddress(args.executorAddress);
|
|
2301
|
+
const [marketRow, position] = await Promise.all([
|
|
2302
|
+
fetchMorphoMidnightMarketById(args.marketId),
|
|
2303
|
+
fetchMorphoMidnightUserMarketPosition({ marketId: args.marketId, user: onBehalf })
|
|
2304
|
+
]);
|
|
2305
|
+
if (!marketRow) throw new Error(`Midnight market not found: ${args.marketId}`);
|
|
2306
|
+
if (!position) throw new Error(`No Midnight position for ${onBehalf} in ${args.marketId}`);
|
|
2307
|
+
const baseMarket = morphoMidnightMarketToParams(marketRow);
|
|
2308
|
+
let midnightAddr = baseMarket.midnight;
|
|
2309
|
+
if (midnightAddr === viem.zeroAddress) {
|
|
2310
|
+
const book = await fetchMorphoMidnightBook(args.marketId);
|
|
2311
|
+
if (book) midnightAddr = viem.getAddress(book.midnight);
|
|
2312
|
+
}
|
|
2313
|
+
const { midnight, bundles } = resolveAddresses({
|
|
2314
|
+
chainId: args.chainId,
|
|
2315
|
+
midnight: args.midnight ?? (midnightAddr !== viem.zeroAddress ? midnightAddr : void 0),
|
|
2316
|
+
bundles: args.bundles,
|
|
2317
|
+
marketMidnight: midnightAddr !== viem.zeroAddress ? midnightAddr : void 0
|
|
2318
|
+
});
|
|
2319
|
+
const market = { ...baseMarket, midnight };
|
|
2320
|
+
const loanToken = args.loanToken ? viem.getAddress(args.loanToken) : viem.getAddress(market.loanToken);
|
|
2321
|
+
const dec = await readTokenDecimals({ rpcUrl: args.rpcUrl, chainId: args.chainId, token: loanToken });
|
|
2322
|
+
const debt = BigInt(position.debt || "0");
|
|
2323
|
+
const fee = BigInt(position.pendingFee || "0");
|
|
2324
|
+
const buffer = viem.parseUnits("1", Math.min(dec, 6));
|
|
2325
|
+
let repayAssets;
|
|
2326
|
+
if (args.repayAmountHuman?.trim()) {
|
|
2327
|
+
repayAssets = viem.parseUnits(args.repayAmountHuman.trim(), dec);
|
|
2328
|
+
} else {
|
|
2329
|
+
repayAssets = debt + fee + buffer;
|
|
2330
|
+
}
|
|
2331
|
+
if (repayAssets === 0n) throw new Error("Repay amount is zero.");
|
|
2332
|
+
const withdrawAll = args.withdrawAllCollateral !== false;
|
|
2333
|
+
const collateralWithdrawals = withdrawAll ? position.collaterals.map((c) => {
|
|
2334
|
+
const idx = market.collateralParams.findIndex(
|
|
2335
|
+
(cp) => cp.token.toLowerCase() === c.token.toLowerCase()
|
|
2336
|
+
);
|
|
2337
|
+
if (idx < 0) throw new Error(`Collateral ${c.token} missing from market params.`);
|
|
2338
|
+
return { collateralIndex: BigInt(idx), assets: BigInt(c.amount || "0") };
|
|
2339
|
+
}) : [];
|
|
2340
|
+
const deadline = deadlineFromNow(args.deadlineSeconds);
|
|
2341
|
+
const approveSteps = await buildApproveSteps({
|
|
2342
|
+
rpcUrl: args.rpcUrl,
|
|
2343
|
+
chainId: args.chainId,
|
|
2344
|
+
token: loanToken,
|
|
2345
|
+
spender: bundles,
|
|
2346
|
+
amountWei: repayAssets,
|
|
2347
|
+
executor
|
|
2348
|
+
});
|
|
2349
|
+
const authSteps = await ensureBundlesAuthorizedSteps({
|
|
2350
|
+
rpcUrl: args.rpcUrl,
|
|
2351
|
+
chainId: args.chainId,
|
|
2352
|
+
midnight,
|
|
2353
|
+
bundles,
|
|
2354
|
+
onBehalf
|
|
2355
|
+
});
|
|
2356
|
+
const repayData = viem.encodeFunctionData({
|
|
2357
|
+
abi: midnightSdk.midnightBundlesAbi,
|
|
2358
|
+
functionName: "midnightBundlesV1RepayAndWithdrawCollateral",
|
|
2359
|
+
args: [
|
|
2360
|
+
market,
|
|
2361
|
+
repayAssets,
|
|
2362
|
+
onBehalf,
|
|
2363
|
+
exports.TOKEN_PERMIT_NONE,
|
|
2364
|
+
collateralWithdrawals,
|
|
2365
|
+
collateralReceiver,
|
|
2366
|
+
0n,
|
|
2367
|
+
viem.zeroAddress,
|
|
2368
|
+
deadline
|
|
2369
|
+
]
|
|
2370
|
+
});
|
|
2371
|
+
const marketLabel = (args.marketLabel ?? "").trim() || `Midnight ${args.marketId.slice(0, 10)}\u2026`;
|
|
2372
|
+
const evmSteps = [
|
|
2373
|
+
...approveStepsToEvm(approveSteps),
|
|
2374
|
+
...authSteps,
|
|
2375
|
+
{ to: bundles, data: repayData, value: 0n, fallbackGas: exports.MORPHO_MIDNIGHT_REPAY_FALLBACK_GAS }
|
|
2376
|
+
];
|
|
2377
|
+
return buildEvmMultisignBatch({
|
|
2378
|
+
context: {
|
|
2379
|
+
chainCategory: "evm",
|
|
2380
|
+
keyGen: args.keyGen,
|
|
2381
|
+
purposeText: args.purposeText,
|
|
2382
|
+
chainId: args.chainId,
|
|
2383
|
+
rpcUrl: args.rpcUrl,
|
|
2384
|
+
executorAddress: executor,
|
|
2385
|
+
chainDetail: args.chainDetail,
|
|
2386
|
+
useCustomGas: args.useCustomGas,
|
|
2387
|
+
customGasChainDetails: args.customGasChainDetails
|
|
2388
|
+
},
|
|
2389
|
+
steps: evmSteps,
|
|
2390
|
+
purposeSuffix: `Morpho Midnight: repay + withdraw on "${marketLabel}".`,
|
|
2391
|
+
firstMsgRawNo0x: evmSteps[0].data.slice(2),
|
|
2392
|
+
destinationAddress: bundles,
|
|
2393
|
+
buildBatchMeta: ({ gasLimit }) => ({
|
|
2394
|
+
signatureText: JSON.stringify({ kind: "MorphoMidnight", name: "repay", marketLabel }),
|
|
2395
|
+
evm: { type: "morpho_midnight_repay", version: 1, chainId: String(args.chainId) },
|
|
2396
|
+
morpho: {
|
|
2397
|
+
marketId: args.marketId,
|
|
2398
|
+
marketLabel,
|
|
2399
|
+
gasBuild: { baseGasUnits: gasLimit.toString() }
|
|
2400
|
+
}
|
|
2401
|
+
})
|
|
2402
|
+
});
|
|
2403
|
+
}
|
|
2404
|
+
var erc4626Abi = viem.parseAbi([
|
|
2405
|
+
"function asset() view returns (address)",
|
|
2406
|
+
"function decimals() view returns (uint8)",
|
|
2407
|
+
"function balanceOf(address account) view returns (uint256)",
|
|
2408
|
+
"function convertToAssets(uint256 shares) view returns (uint256)",
|
|
2409
|
+
"function maxWithdraw(address owner) view returns (uint256)"
|
|
2410
|
+
]);
|
|
2411
|
+
async function fetchMorphoVaultAssetDecimals(args) {
|
|
2412
|
+
const ch = viem.defineChain({
|
|
2413
|
+
id: args.chainId,
|
|
2414
|
+
name: "MorphoVault",
|
|
2415
|
+
nativeCurrency: { decimals: 18, name: "Ether", symbol: "ETH" },
|
|
2416
|
+
rpcUrls: { default: { http: [args.rpcUrl] } }
|
|
2417
|
+
});
|
|
2418
|
+
const publicClient = viem.createPublicClient({ chain: ch, transport: viem.http(args.rpcUrl) });
|
|
2419
|
+
const vault = viem.getAddress(args.vault);
|
|
2420
|
+
const assetAddr = await publicClient.readContract({
|
|
2421
|
+
address: vault,
|
|
2422
|
+
abi: erc4626Abi,
|
|
2423
|
+
functionName: "asset"
|
|
2424
|
+
});
|
|
2425
|
+
const d = await publicClient.readContract({
|
|
2426
|
+
address: viem.getAddress(assetAddr),
|
|
2427
|
+
abi: viem.parseAbi(["function decimals() view returns (uint8)"]),
|
|
2428
|
+
functionName: "decimals"
|
|
2429
|
+
});
|
|
2430
|
+
const n = typeof d === "bigint" ? Number(d) : Number(d);
|
|
2431
|
+
return !Number.isFinite(n) || n < 0 || n > 36 ? 18 : n;
|
|
2432
|
+
}
|
|
2433
|
+
async function fetchMorphoVaultMaxWithdrawWei(args) {
|
|
2434
|
+
const ch = viem.defineChain({
|
|
2435
|
+
id: args.chainId,
|
|
2436
|
+
name: "MorphoVault",
|
|
2437
|
+
nativeCurrency: { decimals: 18, name: "Ether", symbol: "ETH" },
|
|
2438
|
+
rpcUrls: { default: { http: [args.rpcUrl] } }
|
|
2439
|
+
});
|
|
2440
|
+
const publicClient = viem.createPublicClient({ chain: ch, transport: viem.http(args.rpcUrl) });
|
|
2441
|
+
return publicClient.readContract({
|
|
2442
|
+
address: viem.getAddress(args.vault),
|
|
2443
|
+
abi: erc4626Abi,
|
|
2444
|
+
functionName: "maxWithdraw",
|
|
2445
|
+
args: [viem.getAddress(args.owner)]
|
|
2446
|
+
});
|
|
2447
|
+
}
|
|
2448
|
+
var morphoBlueAbi = viem.parseAbi([
|
|
2449
|
+
"function position(bytes32 id, address user) view returns (uint256 supplyShares, uint128 borrowShares, uint128 collateral)",
|
|
2450
|
+
"function market(bytes32 id) view returns (uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee)",
|
|
2451
|
+
"function idToMarketParams(bytes32 id) view returns (address loanToken, address collateralToken, address oracle, address irm, uint256 lltv)"
|
|
2452
|
+
]);
|
|
2453
|
+
var oracleAbi = viem.parseAbi(["function price() view returns (uint256)"]);
|
|
2454
|
+
var WAD = 10n ** 18n;
|
|
2455
|
+
var ORACLE_PRICE_SCALE = 10n ** 36n;
|
|
2456
|
+
async function previewMorphoBlueHealthAfterCollateralWithdraw(args) {
|
|
2457
|
+
const ch = viem.defineChain({
|
|
2458
|
+
id: args.chainId,
|
|
2459
|
+
name: "MorphoBlue",
|
|
2460
|
+
nativeCurrency: { decimals: 18, name: "Ether", symbol: "ETH" },
|
|
2461
|
+
rpcUrls: { default: { http: [args.rpcUrl] } }
|
|
2462
|
+
});
|
|
2463
|
+
const publicClient = viem.createPublicClient({ chain: ch, transport: viem.http(args.rpcUrl) });
|
|
2464
|
+
const morpho = viem.getAddress(args.morphoBlue);
|
|
2465
|
+
const user = viem.getAddress(args.user);
|
|
2466
|
+
const id = args.marketId;
|
|
2467
|
+
const [pos, mkt, params] = await Promise.all([
|
|
2468
|
+
publicClient.readContract({
|
|
2469
|
+
address: morpho,
|
|
2470
|
+
abi: morphoBlueAbi,
|
|
2471
|
+
functionName: "position",
|
|
2472
|
+
args: [id, user]
|
|
2473
|
+
}),
|
|
2474
|
+
publicClient.readContract({
|
|
2475
|
+
address: morpho,
|
|
2476
|
+
abi: morphoBlueAbi,
|
|
2477
|
+
functionName: "market",
|
|
2478
|
+
args: [id]
|
|
2479
|
+
}),
|
|
2480
|
+
publicClient.readContract({
|
|
2481
|
+
address: morpho,
|
|
2482
|
+
abi: morphoBlueAbi,
|
|
2483
|
+
functionName: "idToMarketParams",
|
|
2484
|
+
args: [id]
|
|
2485
|
+
})
|
|
2486
|
+
]);
|
|
2487
|
+
const borrowShares = BigInt(pos[1]);
|
|
2488
|
+
if (borrowShares === 0n) return { healthy: true, healthFactor: null };
|
|
2489
|
+
const collateral = BigInt(pos[2]) - args.withdrawCollateralWei;
|
|
2490
|
+
const oracle = viem.getAddress(params[2]);
|
|
2491
|
+
const lltv = BigInt(params[4]);
|
|
2492
|
+
const price = await publicClient.readContract({
|
|
2493
|
+
address: oracle,
|
|
2494
|
+
abi: oracleAbi,
|
|
2495
|
+
functionName: "price"
|
|
2496
|
+
});
|
|
2497
|
+
const totalBorrowAssets = BigInt(mkt[2]);
|
|
2498
|
+
const totalBorrowShares = BigInt(mkt[3]);
|
|
2499
|
+
if (totalBorrowShares === 0n) return { healthy: true, healthFactor: null };
|
|
2500
|
+
const borrowed = (borrowShares * totalBorrowAssets + totalBorrowShares - 1n) / totalBorrowShares;
|
|
2501
|
+
const maxBorrow = collateral * price / ORACLE_PRICE_SCALE * lltv / WAD;
|
|
2502
|
+
const healthy = maxBorrow >= borrowed;
|
|
2503
|
+
const hf = borrowed === 0n ? null : Number(maxBorrow * WAD / borrowed) / Number(WAD);
|
|
2504
|
+
return { healthy, healthFactor: hf != null && Number.isFinite(hf) ? hf : null };
|
|
2505
|
+
}
|
|
2506
|
+
var MORPHO_VAULT_DEPOSIT_FALLBACK_GAS = 950000n;
|
|
2507
|
+
var MORPHO_ERC20_APPROVE_FALLBACK = 100000n;
|
|
2508
|
+
var MORPHO_WETH_DEPOSIT_FALLBACK = 120000n;
|
|
2509
|
+
var wethDepositAbi2 = viem.parseAbi(["function deposit() payable"]);
|
|
2510
|
+
var erc20AllowanceAbi = viem.parseAbi([
|
|
2511
|
+
"function allowance(address owner, address spender) view returns (uint256)"
|
|
2512
|
+
]);
|
|
2513
|
+
var erc20ApproveAbi = viem.parseAbi(["function approve(address spender, uint256 amount) returns (bool)"]);
|
|
2514
|
+
var vaultDepositAbi = viem.parseAbi([
|
|
2515
|
+
"function deposit(uint256 assets, address onBehalf) returns (uint256 shares)"
|
|
2516
|
+
]);
|
|
2517
|
+
async function buildEvmMultisignBodyMorphoVaultDepositBatch(args) {
|
|
2518
|
+
const asset = viem.getAddress(args.underlying);
|
|
2519
|
+
const vault = viem.getAddress(args.vault);
|
|
2520
|
+
const weth = viem.getAddress(args.nativeWrapped);
|
|
2521
|
+
const executor = viem.getAddress(args.executorAddress);
|
|
2522
|
+
const onBehalf = viem.getAddress(args.onBehalf);
|
|
2523
|
+
if (args.isNativeIn && asset.toLowerCase() !== weth.toLowerCase()) {
|
|
2524
|
+
throw new Error("Native deposit path: underlying asset must match the chain wrapped native token.");
|
|
2525
|
+
}
|
|
2526
|
+
const ch = viem.defineChain({
|
|
2527
|
+
id: args.chainId,
|
|
2528
|
+
name: "MorphoVaultDeposit",
|
|
2529
|
+
nativeCurrency: { decimals: 18, name: "Ether", symbol: "ETH" },
|
|
2530
|
+
rpcUrls: { default: { http: [args.rpcUrl] } }
|
|
2531
|
+
});
|
|
2532
|
+
const publicClient = viem.createPublicClient({ chain: ch, transport: viem.http(args.rpcUrl) });
|
|
2533
|
+
const dec = await fetchMorphoVaultAssetDecimals({ rpcUrl: args.rpcUrl, chainId: args.chainId, vault });
|
|
2534
|
+
const amountWei = viem.parseUnits(args.amountHuman, dec);
|
|
2535
|
+
if (amountWei === 0n) throw new Error("Deposit amount is zero after converting with token decimals.");
|
|
2536
|
+
const steps = [];
|
|
1555
2537
|
if (args.isNativeIn) {
|
|
1556
|
-
const wethData = viem.encodeFunctionData({ abi:
|
|
2538
|
+
const wethData = viem.encodeFunctionData({ abi: wethDepositAbi2, functionName: "deposit" });
|
|
1557
2539
|
steps.push({ kind: "weth_deposit", to: weth, data: wethData, value: amountWei });
|
|
1558
2540
|
}
|
|
1559
2541
|
const spendToken = args.isNativeIn ? weth : asset;
|
|
@@ -1705,7 +2687,7 @@ var MORPHO_BLUE_REPAY_FALLBACK_GAS = 1000000n;
|
|
|
1705
2687
|
var MORPHO_BLUE_COLLATERAL_WITHDRAW_FALLBACK_GAS = 900000n;
|
|
1706
2688
|
var MORPHO_ERC20_APPROVE_FALLBACK2 = 100000n;
|
|
1707
2689
|
var MORPHO_WETH_DEPOSIT_FALLBACK2 = 120000n;
|
|
1708
|
-
var
|
|
2690
|
+
var wethDepositAbi3 = viem.parseAbi(["function deposit() payable"]);
|
|
1709
2691
|
var erc20AllowanceAbi2 = viem.parseAbi([
|
|
1710
2692
|
"function allowance(address owner, address spender) view returns (uint256)",
|
|
1711
2693
|
"function decimals() view returns (uint8)"
|
|
@@ -1726,7 +2708,7 @@ function marketParamsTuple(p) {
|
|
|
1726
2708
|
lltv: p.lltv
|
|
1727
2709
|
};
|
|
1728
2710
|
}
|
|
1729
|
-
async function
|
|
2711
|
+
async function readTokenDecimals2(args) {
|
|
1730
2712
|
const ch = viem.defineChain({
|
|
1731
2713
|
id: args.chainId,
|
|
1732
2714
|
name: "MorphoToken",
|
|
@@ -1742,7 +2724,7 @@ async function readTokenDecimals(args) {
|
|
|
1742
2724
|
const n = typeof d === "bigint" ? Number(d) : Number(d);
|
|
1743
2725
|
return !Number.isFinite(n) || n < 0 || n > 36 ? 18 : n;
|
|
1744
2726
|
}
|
|
1745
|
-
async function
|
|
2727
|
+
async function buildApproveSteps2(args) {
|
|
1746
2728
|
const steps = [];
|
|
1747
2729
|
let spendToken = args.token;
|
|
1748
2730
|
if (args.isNativeIn && args.nativeWrapped) {
|
|
@@ -1750,7 +2732,7 @@ async function buildApproveSteps(args) {
|
|
|
1750
2732
|
if (spendToken.toLowerCase() !== weth.toLowerCase()) {
|
|
1751
2733
|
throw new Error("Native collateral path: token must match wrapped native.");
|
|
1752
2734
|
}
|
|
1753
|
-
const wethData = viem.encodeFunctionData({ abi:
|
|
2735
|
+
const wethData = viem.encodeFunctionData({ abi: wethDepositAbi3, functionName: "deposit" });
|
|
1754
2736
|
steps.push({ kind: "weth_deposit", to: weth, data: wethData, value: args.amountWei });
|
|
1755
2737
|
spendToken = weth;
|
|
1756
2738
|
}
|
|
@@ -1801,10 +2783,10 @@ async function buildEvmMultisignBodyMorphoBlueSupplyCollateralBatch(args) {
|
|
|
1801
2783
|
const onBehalf = viem.getAddress(args.onBehalf);
|
|
1802
2784
|
const executor = viem.getAddress(args.executorAddress);
|
|
1803
2785
|
const collateral = viem.getAddress(args.collateralToken);
|
|
1804
|
-
const dec = await
|
|
2786
|
+
const dec = await readTokenDecimals2({ rpcUrl: args.rpcUrl, chainId: args.chainId, token: collateral });
|
|
1805
2787
|
const amountWei = viem.parseUnits(args.amountHuman, dec);
|
|
1806
2788
|
if (amountWei === 0n) throw new Error("Collateral amount is zero.");
|
|
1807
|
-
const approveSteps = await
|
|
2789
|
+
const approveSteps = await buildApproveSteps2({
|
|
1808
2790
|
rpcUrl: args.rpcUrl,
|
|
1809
2791
|
chainId: args.chainId,
|
|
1810
2792
|
token: collateral,
|
|
@@ -1855,7 +2837,7 @@ async function buildEvmMultisignBodyMorphoBlueBorrowBatch(args) {
|
|
|
1855
2837
|
const receiver = viem.getAddress(args.receiver);
|
|
1856
2838
|
const executor = viem.getAddress(args.executorAddress);
|
|
1857
2839
|
const loan = viem.getAddress(args.loanToken);
|
|
1858
|
-
const dec = await
|
|
2840
|
+
const dec = await readTokenDecimals2({ rpcUrl: args.rpcUrl, chainId: args.chainId, token: loan });
|
|
1859
2841
|
const amountWei = viem.parseUnits(args.amountHuman, dec);
|
|
1860
2842
|
if (amountWei === 0n) throw new Error("Borrow amount is zero.");
|
|
1861
2843
|
const borrowData = viem.encodeFunctionData({
|
|
@@ -1895,10 +2877,10 @@ async function buildEvmMultisignBodyMorphoBlueRepayBatch(args) {
|
|
|
1895
2877
|
const onBehalf = viem.getAddress(args.onBehalf);
|
|
1896
2878
|
const executor = viem.getAddress(args.executorAddress);
|
|
1897
2879
|
const loan = viem.getAddress(args.loanToken);
|
|
1898
|
-
const dec = await
|
|
2880
|
+
const dec = await readTokenDecimals2({ rpcUrl: args.rpcUrl, chainId: args.chainId, token: loan });
|
|
1899
2881
|
const amountWei = viem.parseUnits(args.amountHuman, dec);
|
|
1900
2882
|
if (amountWei === 0n) throw new Error("Repay amount is zero.");
|
|
1901
|
-
const approveSteps = await
|
|
2883
|
+
const approveSteps = await buildApproveSteps2({
|
|
1902
2884
|
rpcUrl: args.rpcUrl,
|
|
1903
2885
|
chainId: args.chainId,
|
|
1904
2886
|
token: loan,
|
|
@@ -2034,7 +3016,12 @@ var morphoProtocolModule = {
|
|
|
2034
3016
|
{ id: "morpho.blue-repay", protocolId: MORPHO_PROTOCOL_ID, chainCategory: "evm", description: "Repay Morpho Blue borrow", commonParams: ["keyGen", "purposeText", "useCustomGas"], params: {} },
|
|
2035
3017
|
{ id: "morpho.blue-collateral-withdraw", protocolId: MORPHO_PROTOCOL_ID, chainCategory: "evm", description: "Withdraw Morpho Blue collateral", commonParams: ["keyGen", "purposeText", "useCustomGas"], params: {} },
|
|
2036
3018
|
{ id: "morpho.merkl-claim", protocolId: MORPHO_PROTOCOL_ID, chainCategory: "evm", description: "Claim Morpho Merkl rewards", commonParams: ["keyGen", "purposeText", "useCustomGas"], params: {} },
|
|
2037
|
-
{ id: "morpho.midnight-
|
|
3019
|
+
{ id: "morpho.fetch-midnight-books", protocolId: MORPHO_PROTOCOL_ID, chainCategory: "evm", description: "List Morpho Midnight fixed-rate books", commonParams: [], params: {} },
|
|
3020
|
+
{ id: "morpho.fetch-midnight-quote", protocolId: MORPHO_PROTOCOL_ID, chainCategory: "evm", description: "Quote Morpho Midnight lend/borrow fill", commonParams: [], params: {} },
|
|
3021
|
+
{ id: "morpho.fetch-midnight-positions", protocolId: MORPHO_PROTOCOL_ID, chainCategory: "evm", description: "List Morpho Midnight user positions", commonParams: [], params: {} },
|
|
3022
|
+
{ id: "morpho.midnight-lend", protocolId: MORPHO_PROTOCOL_ID, chainCategory: "evm", description: "Morpho Midnight fixed-rate lend (take asks)", commonParams: ["keyGen", "purposeText", "useCustomGas"], params: {} },
|
|
3023
|
+
{ id: "morpho.midnight-borrow", protocolId: MORPHO_PROTOCOL_ID, chainCategory: "evm", description: "Morpho Midnight fixed-rate borrow (supply collateral + take bids)", commonParams: ["keyGen", "purposeText", "useCustomGas"], params: {} },
|
|
3024
|
+
{ id: "morpho.midnight-repay", protocolId: MORPHO_PROTOCOL_ID, chainCategory: "evm", description: "Morpho Midnight repay debt and withdraw collateral", commonParams: ["keyGen", "purposeText", "useCustomGas"], params: {} }
|
|
2038
3025
|
]
|
|
2039
3026
|
};
|
|
2040
3027
|
registerProtocolModule(morphoProtocolModule);
|
|
@@ -2059,6 +3046,9 @@ exports.buildEvmMultisignBodyMorphoBlueRepayBatch = buildEvmMultisignBodyMorphoB
|
|
|
2059
3046
|
exports.buildEvmMultisignBodyMorphoBlueSupplyCollateralBatch = buildEvmMultisignBodyMorphoBlueSupplyCollateralBatch;
|
|
2060
3047
|
exports.buildEvmMultisignBodyMorphoBlueWithdrawCollateralBatch = buildEvmMultisignBodyMorphoBlueWithdrawCollateralBatch;
|
|
2061
3048
|
exports.buildEvmMultisignBodyMorphoMerklDistributorClaim = buildEvmMultisignBodyMorphoMerklDistributorClaim;
|
|
3049
|
+
exports.buildEvmMultisignBodyMorphoMidnightBorrowBatch = buildEvmMultisignBodyMorphoMidnightBorrowBatch;
|
|
3050
|
+
exports.buildEvmMultisignBodyMorphoMidnightLendBatch = buildEvmMultisignBodyMorphoMidnightLendBatch;
|
|
3051
|
+
exports.buildEvmMultisignBodyMorphoMidnightRepayBatch = buildEvmMultisignBodyMorphoMidnightRepayBatch;
|
|
2062
3052
|
exports.buildEvmMultisignBodyMorphoVaultDepositBatch = buildEvmMultisignBodyMorphoVaultDepositBatch;
|
|
2063
3053
|
exports.buildEvmMultisignBodyMorphoVaultWithdraw = buildEvmMultisignBodyMorphoVaultWithdraw;
|
|
2064
3054
|
exports.emptyMorphoEarnVaultDetailFields = emptyMorphoEarnVaultDetailFields;
|
|
@@ -2072,7 +3062,14 @@ exports.fetchMorphoEarnOfferingsForAsset = fetchMorphoEarnOfferingsForAsset;
|
|
|
2072
3062
|
exports.fetchMorphoEarnVaultDetails = fetchMorphoEarnVaultDetails;
|
|
2073
3063
|
exports.fetchMorphoMarketById = fetchMorphoMarketById;
|
|
2074
3064
|
exports.fetchMorphoMarketsForChain = fetchMorphoMarketsForChain;
|
|
3065
|
+
exports.fetchMorphoMidnightBook = fetchMorphoMidnightBook;
|
|
3066
|
+
exports.fetchMorphoMidnightBookQuote = fetchMorphoMidnightBookQuote;
|
|
3067
|
+
exports.fetchMorphoMidnightBooks = fetchMorphoMidnightBooks;
|
|
3068
|
+
exports.fetchMorphoMidnightBooksForAsset = fetchMorphoMidnightBooksForAsset;
|
|
2075
3069
|
exports.fetchMorphoMidnightIntents = fetchMorphoMidnightIntents;
|
|
3070
|
+
exports.fetchMorphoMidnightMarketById = fetchMorphoMidnightMarketById;
|
|
3071
|
+
exports.fetchMorphoMidnightUserMarketPosition = fetchMorphoMidnightUserMarketPosition;
|
|
3072
|
+
exports.fetchMorphoMidnightUserPositions = fetchMorphoMidnightUserPositions;
|
|
2076
3073
|
exports.fetchMorphoUserBluePositions = fetchMorphoUserBluePositions;
|
|
2077
3074
|
exports.fetchMorphoUserPortfolioUsd = fetchMorphoUserPortfolioUsd;
|
|
2078
3075
|
exports.fetchMorphoUserVaultPositions = fetchMorphoUserVaultPositions;
|
|
@@ -2084,6 +3081,7 @@ exports.fetchMorphoVaultsForChain = fetchMorphoVaultsForChain;
|
|
|
2084
3081
|
exports.formatMorphoApyPct = formatMorphoApyPct;
|
|
2085
3082
|
exports.formatMorphoFeePct = formatMorphoFeePct;
|
|
2086
3083
|
exports.formatMorphoMarketApySummary = formatMorphoMarketApySummary;
|
|
3084
|
+
exports.formatMorphoMidnightAprPct = formatMorphoMidnightAprPct;
|
|
2087
3085
|
exports.formatMorphoUsd = formatMorphoUsd;
|
|
2088
3086
|
exports.isMorphoVaultListed = isMorphoVaultListed;
|
|
2089
3087
|
exports.isRobinhoodEarnProductFlag = isRobinhoodEarnProductFlag;
|
|
@@ -2093,9 +3091,22 @@ exports.marketParamsFromApiRow = marketParamsFromApiRow;
|
|
|
2093
3091
|
exports.morphoEarnOfferingToDiscoveryRow = morphoEarnOfferingToDiscoveryRow;
|
|
2094
3092
|
exports.morphoFetchBlueMarketsSummary = morphoFetchBlueMarketsSummary;
|
|
2095
3093
|
exports.morphoFetchEarnVaultsSummary = morphoFetchEarnVaultsSummary;
|
|
3094
|
+
exports.morphoFetchMidnightBooksSummary = morphoFetchMidnightBooksSummary;
|
|
3095
|
+
exports.morphoFetchMidnightPositionsSummary = morphoFetchMidnightPositionsSummary;
|
|
3096
|
+
exports.morphoFetchMidnightQuote = morphoFetchMidnightQuote;
|
|
3097
|
+
exports.morphoFetchMidnightQuoteSummary = morphoFetchMidnightQuoteSummary;
|
|
2096
3098
|
exports.morphoGql = morphoGql;
|
|
2097
3099
|
exports.morphoKeyForAssetRow = morphoKeyForAssetRow;
|
|
2098
3100
|
exports.morphoMarketToBorrowRow = morphoMarketToBorrowRow;
|
|
3101
|
+
exports.morphoMidnightAddressesForChain = morphoMidnightAddressesForChain;
|
|
3102
|
+
exports.morphoMidnightApiBaseUrl = morphoMidnightApiBaseUrl;
|
|
3103
|
+
exports.morphoMidnightAprFromPriceWad = morphoMidnightAprFromPriceWad;
|
|
3104
|
+
exports.morphoMidnightBookToDiscoveryRow = morphoMidnightBookToDiscoveryRow;
|
|
3105
|
+
exports.morphoMidnightBookToMarketParams = morphoMidnightBookToMarketParams;
|
|
3106
|
+
exports.morphoMidnightMarketToParams = morphoMidnightMarketToParams;
|
|
3107
|
+
exports.morphoMidnightPositionToDiscoveryRow = morphoMidnightPositionToDiscoveryRow;
|
|
3108
|
+
exports.morphoMidnightTtmSeconds = morphoMidnightTtmSeconds;
|
|
3109
|
+
exports.morphoMidnightUnitsFromAssets = morphoMidnightUnitsFromAssets;
|
|
2099
3110
|
exports.morphoProtocolModule = morphoProtocolModule;
|
|
2100
3111
|
exports.morphoResolveListedEarnVaultByAddress = morphoResolveListedEarnVaultByAddress;
|
|
2101
3112
|
exports.previewMorphoBlueHealthAfterCollateralWithdraw = previewMorphoBlueHealthAfterCollateralWithdraw;
|