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