@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,15 +1,19 @@
|
|
|
1
|
-
import { parseAbi, isAddress, getAddress,
|
|
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
|
-
|
|
5
|
-
var
|
|
6
|
-
function
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
|
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
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
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
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
return
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
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
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
const
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
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
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
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
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
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
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
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
|
-
|
|
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/
|
|
1522
|
-
|
|
1523
|
-
|
|
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
|
|
1527
|
-
"function allowance(address owner, address spender) view returns (uint256)"
|
|
1528
|
-
|
|
1529
|
-
|
|
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
|
-
|
|
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:
|
|
1544
|
-
name: "
|
|
1951
|
+
id: chainId,
|
|
1952
|
+
name: "MorphoMidnight",
|
|
1545
1953
|
nativeCurrency: { decimals: 18, name: "Ether", symbol: "ETH" },
|
|
1546
|
-
rpcUrls: { default: { http: [
|
|
1954
|
+
rpcUrls: { default: { http: [rpcUrl] } }
|
|
1547
1955
|
});
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
const
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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-
|
|
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
|