@morpho-dev/router 0.1.11 → 0.1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -7
- package/dist/drizzle/{offers_v1.1 → router_v1.1}/0000_init.sql +47 -39
- package/dist/drizzle/{offers_v1.1/meta/0007_snapshot.json → router_v1.1/meta/0000_snapshot.json} +21 -21
- package/dist/drizzle/router_v1.1/meta/_journal.json +13 -0
- package/dist/index.browser.d.cts +186 -159
- package/dist/index.browser.d.ts +186 -159
- package/dist/index.browser.js +807 -491
- package/dist/index.browser.js.map +1 -1
- package/dist/index.browser.mjs +809 -493
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.node.d.cts +1795 -1759
- package/dist/index.node.d.ts +1795 -1759
- package/dist/index.node.js +2923 -2495
- package/dist/index.node.js.map +1 -1
- package/dist/index.node.mjs +2925 -2496
- package/dist/index.node.mjs.map +1 -1
- package/package.json +4 -4
- package/dist/drizzle/offers_v1.1/0001_new_table_for_collectors_block_numbers.sql +0 -5
- package/dist/drizzle/offers_v1.1/0002_update-liquidity-tables.sql +0 -8
- package/dist/drizzle/offers_v1.1/0003_add-not-null-for-queue-id.sql +0 -1
- package/dist/drizzle/offers_v1.1/0004_add-callback-id-to-offer.sql +0 -1
- package/dist/drizzle/offers_v1.1/0005_add-missing-indices-to-liquidity-tables.sql +0 -2
- package/dist/drizzle/offers_v1.1/0006_add-callback-amount-to-queues-table.sql +0 -1
- package/dist/drizzle/offers_v1.1/0007_add-index-to-created-at.sql +0 -2
- package/dist/drizzle/offers_v1.1/meta/0000_snapshot.json +0 -827
- package/dist/drizzle/offers_v1.1/meta/0001_snapshot.json +0 -827
- package/dist/drizzle/offers_v1.1/meta/0002_snapshot.json +0 -833
- package/dist/drizzle/offers_v1.1/meta/0003_snapshot.json +0 -833
- package/dist/drizzle/offers_v1.1/meta/0004_snapshot.json +0 -839
- package/dist/drizzle/offers_v1.1/meta/0005_snapshot.json +0 -877
- package/dist/drizzle/offers_v1.1/meta/0006_snapshot.json +0 -884
- package/dist/drizzle/offers_v1.1/meta/_journal.json +0 -62
package/dist/index.browser.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { Errors, LLTV, Offer, Utils,
|
|
1
|
+
import { Errors, LLTV, Offer, Format, Utils, Maturity } from '@morpho-dev/mempool';
|
|
2
2
|
export * from '@morpho-dev/mempool';
|
|
3
|
-
import { parseUnits,
|
|
4
|
-
import { Base64 } from 'js-base64';
|
|
3
|
+
import { parseUnits, maxUint256, formatUnits, encodeAbiParameters, decodeAbiParameters, erc20Abi } from 'viem';
|
|
5
4
|
import { z } from 'zod/v4';
|
|
6
5
|
import { createDocument } from 'zod-openapi';
|
|
6
|
+
import { Base64 } from 'js-base64';
|
|
7
7
|
|
|
8
8
|
var __defProp = Object.defineProperty;
|
|
9
9
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
@@ -13,157 +13,104 @@ var __export = (target, all) => {
|
|
|
13
13
|
};
|
|
14
14
|
var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value);
|
|
15
15
|
|
|
16
|
-
// src/
|
|
17
|
-
var
|
|
18
|
-
__export(
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
16
|
+
// src/api/Client.ts
|
|
17
|
+
var Client_exports = {};
|
|
18
|
+
__export(Client_exports, {
|
|
19
|
+
HttpForbiddenError: () => HttpForbiddenError,
|
|
20
|
+
HttpGetOffersFailedError: () => HttpGetOffersFailedError,
|
|
21
|
+
HttpRateLimitError: () => HttpRateLimitError,
|
|
22
|
+
HttpUnauthorizedError: () => HttpUnauthorizedError,
|
|
23
|
+
InvalidUrlError: () => InvalidUrlError,
|
|
24
|
+
connect: () => connect,
|
|
25
|
+
get: () => get,
|
|
26
|
+
match: () => match
|
|
25
27
|
});
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
28
|
+
|
|
29
|
+
// src/core/RouterOffer.ts
|
|
30
|
+
var RouterOffer_exports = {};
|
|
31
|
+
__export(RouterOffer_exports, {
|
|
32
|
+
InvalidRouterOfferError: () => InvalidRouterOfferError,
|
|
33
|
+
OfferStatusValues: () => OfferStatusValues,
|
|
34
|
+
RouterOfferSchema: () => RouterOfferSchema,
|
|
35
|
+
consumedEvent: () => consumedEvent,
|
|
36
|
+
from: () => from,
|
|
37
|
+
fromConsumedLog: () => fromConsumedLog,
|
|
38
|
+
fromSnakeCase: () => fromSnakeCase,
|
|
39
|
+
random: () => random,
|
|
40
|
+
toSnakeCase: () => toSnakeCase
|
|
41
|
+
});
|
|
42
|
+
var OfferStatusValues = [
|
|
43
|
+
"valid",
|
|
44
|
+
"callback_not_supported",
|
|
45
|
+
"callback_error",
|
|
46
|
+
"unverified"
|
|
47
|
+
];
|
|
48
|
+
var RouterOfferSchema = (parameters) => Offer.OfferSchema(parameters).extend({
|
|
49
|
+
consumed: z.bigint({ coerce: true }).min(0n).max(maxUint256),
|
|
50
|
+
status: z.enum(OfferStatusValues),
|
|
51
|
+
metadata: z.object({
|
|
52
|
+
issue: z.string()
|
|
53
|
+
}).optional()
|
|
54
|
+
});
|
|
55
|
+
var consumedEvent = {
|
|
56
|
+
type: "event",
|
|
57
|
+
name: "Consumed",
|
|
58
|
+
inputs: [
|
|
59
|
+
{ name: "user", type: "address", indexed: true, internalType: "address" },
|
|
60
|
+
{ name: "nonce", type: "uint256", indexed: true, internalType: "uint256" },
|
|
61
|
+
{ name: "amount", type: "uint256", indexed: false, internalType: "uint256" }
|
|
62
|
+
],
|
|
63
|
+
anonymous: false
|
|
38
64
|
};
|
|
39
|
-
function
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
availableLiquidityQueueId: id,
|
|
50
|
-
user: user.toLowerCase(),
|
|
51
|
-
chainId,
|
|
52
|
-
amount: amountStr,
|
|
53
|
-
updatedAt
|
|
54
|
-
},
|
|
55
|
-
queues: [
|
|
56
|
-
{
|
|
57
|
-
queue: {
|
|
58
|
-
queueId: id,
|
|
59
|
-
availableLiquidityPoolId: poolId,
|
|
60
|
-
index,
|
|
61
|
-
callbackAmount: "0",
|
|
62
|
-
updatedAt
|
|
63
|
-
},
|
|
64
|
-
pool: {
|
|
65
|
-
id: poolId,
|
|
66
|
-
amount: amountStr,
|
|
67
|
-
updatedAt
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
]
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
case "sell_withdraw_from_wallet" /* SellWithdrawFromWallet */: {
|
|
74
|
-
const {
|
|
75
|
-
user,
|
|
76
|
-
termId,
|
|
77
|
-
chainId,
|
|
78
|
-
amount,
|
|
79
|
-
collaterals,
|
|
80
|
-
index = 0,
|
|
81
|
-
updatedAt = /* @__PURE__ */ new Date()
|
|
82
|
-
} = parameters;
|
|
83
|
-
const amountStr = amount.toString();
|
|
84
|
-
const id = `${user}-${chainId.toString()}-${parameters.type}-${termId}`.toLowerCase();
|
|
85
|
-
return {
|
|
86
|
-
userPosition: {
|
|
87
|
-
id,
|
|
88
|
-
availableLiquidityQueueId: id,
|
|
89
|
-
user: user.toLowerCase(),
|
|
90
|
-
chainId,
|
|
91
|
-
amount: amountStr,
|
|
92
|
-
updatedAt
|
|
93
|
-
},
|
|
94
|
-
queues: collaterals.map((collateral) => {
|
|
95
|
-
const poolId = `${user}-${chainId.toString()}-${collateral.collateralAddress}`.toLowerCase();
|
|
96
|
-
return {
|
|
97
|
-
queue: {
|
|
98
|
-
queueId: id,
|
|
99
|
-
availableLiquidityPoolId: poolId,
|
|
100
|
-
index,
|
|
101
|
-
callbackAmount: collateral.callbackAmount.toString(),
|
|
102
|
-
updatedAt
|
|
103
|
-
},
|
|
104
|
-
pool: {
|
|
105
|
-
id: poolId,
|
|
106
|
-
amount: collateral.balance.toString(),
|
|
107
|
-
updatedAt
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
|
-
})
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
default: {
|
|
114
|
-
throw new Error(`CallbackType not implemented`);
|
|
115
|
-
}
|
|
65
|
+
function from(input) {
|
|
66
|
+
try {
|
|
67
|
+
const parsedOffer = RouterOfferSchema({ omitHash: true }).parse(input);
|
|
68
|
+
const parsedHash = Offer.OfferHashSchema.parse(Offer.hash(parsedOffer));
|
|
69
|
+
return {
|
|
70
|
+
...parsedOffer,
|
|
71
|
+
hash: parsedHash
|
|
72
|
+
};
|
|
73
|
+
} catch (error) {
|
|
74
|
+
throw new InvalidRouterOfferError(error);
|
|
116
75
|
}
|
|
117
76
|
}
|
|
118
|
-
function
|
|
119
|
-
|
|
120
|
-
return `${offer.offering}-${offer.chainId.toString()}-${"buy_with_empty_callback" /* BuyWithEmptyCallback */}-${offer.loanToken}`.toLowerCase();
|
|
121
|
-
}
|
|
122
|
-
if (!offer.buy && offer.callback.data !== "0x" && WhitelistedCallbackAddresses["sell_withdraw_from_wallet" /* SellWithdrawFromWallet */].includes(
|
|
123
|
-
offer.callback.address.toLowerCase()
|
|
124
|
-
)) {
|
|
125
|
-
return `${offer.offering}-${offer.chainId.toString()}-${"sell_withdraw_from_wallet" /* SellWithdrawFromWallet */}-${Offer.termId(offer)}`.toLowerCase();
|
|
126
|
-
}
|
|
127
|
-
return null;
|
|
77
|
+
function fromSnakeCase(input) {
|
|
78
|
+
return from(Format.fromSnakeCase(input));
|
|
128
79
|
}
|
|
129
|
-
function
|
|
130
|
-
|
|
131
|
-
try {
|
|
132
|
-
const [collaterals, amounts] = decodeAbiParameters(
|
|
133
|
-
[{ type: "address[]" }, { type: "uint256[]" }],
|
|
134
|
-
data
|
|
135
|
-
);
|
|
136
|
-
if (collaterals.length !== amounts.length) {
|
|
137
|
-
throw new Error("Mismatched array lengths");
|
|
138
|
-
}
|
|
139
|
-
return collaterals.map((c, i) => ({ collateral: c, amount: amounts[i] }));
|
|
140
|
-
} catch (_) {
|
|
141
|
-
throw new Error("Invalid SellWithdrawFromWallet callback data");
|
|
142
|
-
}
|
|
80
|
+
function toSnakeCase(offer) {
|
|
81
|
+
return Format.toSnakeCase(offer);
|
|
143
82
|
}
|
|
144
|
-
function
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
83
|
+
function random() {
|
|
84
|
+
const baseOffer = Offer.random();
|
|
85
|
+
return from({
|
|
86
|
+
...baseOffer,
|
|
87
|
+
status: "valid",
|
|
88
|
+
metadata: void 0,
|
|
89
|
+
consumed: 0n
|
|
90
|
+
});
|
|
150
91
|
}
|
|
151
|
-
function
|
|
152
|
-
const {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
92
|
+
function fromConsumedLog(parameters) {
|
|
93
|
+
const { blockNumber, logIndex, chainId, transactionHash, user, nonce, amount } = parameters;
|
|
94
|
+
return {
|
|
95
|
+
id: `${blockNumber.toString()}-${logIndex.toString()}-${chainId}-${transactionHash}`,
|
|
96
|
+
chainId: BigInt(chainId),
|
|
97
|
+
offering: user,
|
|
98
|
+
nonce,
|
|
99
|
+
amount
|
|
100
|
+
};
|
|
160
101
|
}
|
|
102
|
+
var InvalidRouterOfferError = class extends Errors.BaseError {
|
|
103
|
+
constructor(error) {
|
|
104
|
+
super("Invalid router offer.", { cause: error });
|
|
105
|
+
__publicField(this, "name", "RouterOffer.InvalidRouterOfferError");
|
|
106
|
+
}
|
|
107
|
+
};
|
|
161
108
|
|
|
162
109
|
// src/core/Cursor.ts
|
|
163
110
|
var Cursor_exports = {};
|
|
164
111
|
__export(Cursor_exports, {
|
|
165
|
-
decode: () =>
|
|
166
|
-
encode: () =>
|
|
112
|
+
decode: () => decode,
|
|
113
|
+
encode: () => encode,
|
|
167
114
|
validate: () => validate
|
|
168
115
|
});
|
|
169
116
|
function validate(cursor) {
|
|
@@ -235,242 +182,17 @@ function validate(cursor) {
|
|
|
235
182
|
}
|
|
236
183
|
return true;
|
|
237
184
|
}
|
|
238
|
-
function
|
|
185
|
+
function encode(c) {
|
|
239
186
|
return Base64.encodeURL(JSON.stringify(c));
|
|
240
187
|
}
|
|
241
|
-
function
|
|
188
|
+
function decode(token) {
|
|
242
189
|
if (!token) return null;
|
|
243
190
|
const decoded = JSON.parse(Base64.decode(token));
|
|
244
191
|
validate(decoded);
|
|
245
192
|
return decoded;
|
|
246
193
|
}
|
|
247
194
|
|
|
248
|
-
// src/
|
|
249
|
-
var Liquidity_exports = {};
|
|
250
|
-
__export(Liquidity_exports, {
|
|
251
|
-
fetch: () => fetch2,
|
|
252
|
-
fetchBalancesAndAllowances: () => fetchBalancesAndAllowances,
|
|
253
|
-
serialize: () => serialize
|
|
254
|
-
});
|
|
255
|
-
async function fetchBalancesAndAllowances(parameters) {
|
|
256
|
-
const { client, spender, pairs, options } = parameters;
|
|
257
|
-
if (pairs.length === 0) return /* @__PURE__ */ new Map();
|
|
258
|
-
const batchSize = Math.max(1, options?.batchSize ?? 5e3);
|
|
259
|
-
const retryAttempts = Math.max(1, options?.retryAttempts ?? 3);
|
|
260
|
-
const retryDelayMs = Math.max(0, options?.retryDelayMs ?? 50);
|
|
261
|
-
const blockNumber = options?.blockNumber ? BigInt(options.blockNumber) : void 0;
|
|
262
|
-
const out = /* @__PURE__ */ new Map();
|
|
263
|
-
for (const pairsBatch of Utils.batch(pairs, batchSize)) {
|
|
264
|
-
const balanceContracts = [];
|
|
265
|
-
const allowanceContracts = [];
|
|
266
|
-
for (const { user, token } of pairsBatch) {
|
|
267
|
-
balanceContracts.push({
|
|
268
|
-
address: token,
|
|
269
|
-
abi: erc20Abi,
|
|
270
|
-
functionName: "balanceOf",
|
|
271
|
-
args: [user]
|
|
272
|
-
});
|
|
273
|
-
allowanceContracts.push({
|
|
274
|
-
address: token,
|
|
275
|
-
abi: erc20Abi,
|
|
276
|
-
functionName: "allowance",
|
|
277
|
-
args: [user, spender]
|
|
278
|
-
});
|
|
279
|
-
}
|
|
280
|
-
const [balances, allowances] = await Promise.all([
|
|
281
|
-
Utils.retry(
|
|
282
|
-
() => client.multicall({
|
|
283
|
-
allowFailure: false,
|
|
284
|
-
contracts: balanceContracts,
|
|
285
|
-
...blockNumber ? { blockNumber } : {}
|
|
286
|
-
}),
|
|
287
|
-
retryAttempts,
|
|
288
|
-
retryDelayMs
|
|
289
|
-
),
|
|
290
|
-
Utils.retry(
|
|
291
|
-
() => client.multicall({
|
|
292
|
-
allowFailure: false,
|
|
293
|
-
contracts: allowanceContracts,
|
|
294
|
-
...blockNumber ? { blockNumber } : {}
|
|
295
|
-
}),
|
|
296
|
-
retryAttempts,
|
|
297
|
-
retryDelayMs
|
|
298
|
-
)
|
|
299
|
-
]);
|
|
300
|
-
for (let i = 0; i < pairsBatch.length; i++) {
|
|
301
|
-
const { user, token } = pairsBatch[i];
|
|
302
|
-
const balance = balances[i];
|
|
303
|
-
const allowance = allowances[i];
|
|
304
|
-
let perUser = out.get(user);
|
|
305
|
-
if (!perUser) {
|
|
306
|
-
perUser = /* @__PURE__ */ new Map();
|
|
307
|
-
out.set(user, perUser);
|
|
308
|
-
}
|
|
309
|
-
perUser.set(token, { balance, allowance });
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
return out;
|
|
313
|
-
}
|
|
314
|
-
async function fetch2(parameters) {
|
|
315
|
-
const { client, chainId, spender, type, pairs, options } = parameters;
|
|
316
|
-
if (type !== "buy_with_empty_callback" /* BuyWithEmptyCallback */)
|
|
317
|
-
throw new Error(`CallbackType not implemented: ${type}`);
|
|
318
|
-
const map = await fetchBalancesAndAllowances({
|
|
319
|
-
client,
|
|
320
|
-
spender,
|
|
321
|
-
pairs: pairs.map(({ user, loanToken }) => ({ user, token: loanToken })),
|
|
322
|
-
options
|
|
323
|
-
});
|
|
324
|
-
const out = [];
|
|
325
|
-
for (const [user, perLoanToken] of map) {
|
|
326
|
-
for (const [loanToken, { balance, allowance }] of perLoanToken) {
|
|
327
|
-
const amount = balance < allowance ? balance : allowance;
|
|
328
|
-
out.push(
|
|
329
|
-
buildLiquidity({
|
|
330
|
-
type,
|
|
331
|
-
user,
|
|
332
|
-
loanToken,
|
|
333
|
-
chainId,
|
|
334
|
-
amount,
|
|
335
|
-
index: 0
|
|
336
|
-
})
|
|
337
|
-
);
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
return out;
|
|
341
|
-
}
|
|
342
|
-
function serialize(liquidity) {
|
|
343
|
-
const normalized = {
|
|
344
|
-
userPosition: {
|
|
345
|
-
id: liquidity.userPosition.id,
|
|
346
|
-
availableLiquidityQueueId: liquidity.userPosition.availableLiquidityQueueId,
|
|
347
|
-
user: liquidity.userPosition.user,
|
|
348
|
-
chainId: String(liquidity.userPosition.chainId),
|
|
349
|
-
amount: String(liquidity.userPosition.amount)
|
|
350
|
-
},
|
|
351
|
-
queues: liquidity.queues.map((queueWithPool) => ({
|
|
352
|
-
queue: {
|
|
353
|
-
queueId: queueWithPool.queue.queueId,
|
|
354
|
-
availableLiquidityPoolId: queueWithPool.queue.availableLiquidityPoolId,
|
|
355
|
-
index: queueWithPool.queue.index
|
|
356
|
-
},
|
|
357
|
-
pool: {
|
|
358
|
-
id: queueWithPool.pool.id,
|
|
359
|
-
amount: String(queueWithPool.pool.amount)
|
|
360
|
-
}
|
|
361
|
-
})).sort(
|
|
362
|
-
(left, right) => {
|
|
363
|
-
const leftQueueId = left.queue.queueId || "";
|
|
364
|
-
const rightQueueId = right.queue.queueId || "";
|
|
365
|
-
if (leftQueueId < rightQueueId) return -1;
|
|
366
|
-
if (leftQueueId > rightQueueId) return 1;
|
|
367
|
-
const leftPoolId = left.pool.id;
|
|
368
|
-
const rightPoolId = right.pool.id;
|
|
369
|
-
if (leftPoolId < rightPoolId) return -1;
|
|
370
|
-
if (leftPoolId > rightPoolId) return 1;
|
|
371
|
-
const leftIndex = left.queue.index;
|
|
372
|
-
const rightIndex = right.queue.index;
|
|
373
|
-
if (leftIndex < rightIndex) return -1;
|
|
374
|
-
if (leftIndex > rightIndex) return 1;
|
|
375
|
-
return 0;
|
|
376
|
-
}
|
|
377
|
-
)
|
|
378
|
-
};
|
|
379
|
-
return JSON.stringify(normalized);
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
// src/core/RouterOffer.ts
|
|
383
|
-
var RouterOffer_exports = {};
|
|
384
|
-
__export(RouterOffer_exports, {
|
|
385
|
-
InvalidRouterOfferError: () => InvalidRouterOfferError,
|
|
386
|
-
OfferStatusValues: () => OfferStatusValues,
|
|
387
|
-
RouterOfferSchema: () => RouterOfferSchema,
|
|
388
|
-
consumedEvent: () => consumedEvent,
|
|
389
|
-
from: () => from,
|
|
390
|
-
fromConsumedLog: () => fromConsumedLog,
|
|
391
|
-
fromSnakeCase: () => fromSnakeCase,
|
|
392
|
-
random: () => random,
|
|
393
|
-
toSnakeCase: () => toSnakeCase
|
|
394
|
-
});
|
|
395
|
-
var OfferStatusValues = [
|
|
396
|
-
"valid",
|
|
397
|
-
"callback_not_supported",
|
|
398
|
-
"callback_error",
|
|
399
|
-
"unverified"
|
|
400
|
-
];
|
|
401
|
-
var RouterOfferSchema = (parameters) => Offer.OfferSchema(parameters).extend({
|
|
402
|
-
consumed: z.bigint({ coerce: true }).min(0n).max(maxUint256),
|
|
403
|
-
status: z.enum(OfferStatusValues),
|
|
404
|
-
metadata: z.object({
|
|
405
|
-
issue: z.string()
|
|
406
|
-
}).optional()
|
|
407
|
-
});
|
|
408
|
-
var consumedEvent = {
|
|
409
|
-
type: "event",
|
|
410
|
-
name: "Consumed",
|
|
411
|
-
inputs: [
|
|
412
|
-
{ name: "user", type: "address", indexed: true, internalType: "address" },
|
|
413
|
-
{ name: "nonce", type: "uint256", indexed: true, internalType: "uint256" },
|
|
414
|
-
{ name: "amount", type: "uint256", indexed: false, internalType: "uint256" }
|
|
415
|
-
],
|
|
416
|
-
anonymous: false
|
|
417
|
-
};
|
|
418
|
-
function from(input) {
|
|
419
|
-
try {
|
|
420
|
-
const parsedOffer = RouterOfferSchema({ omitHash: true }).parse(input);
|
|
421
|
-
const parsedHash = Offer.OfferHashSchema.parse(Offer.hash(parsedOffer));
|
|
422
|
-
return {
|
|
423
|
-
...parsedOffer,
|
|
424
|
-
hash: parsedHash
|
|
425
|
-
};
|
|
426
|
-
} catch (error) {
|
|
427
|
-
throw new InvalidRouterOfferError(error);
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
function fromSnakeCase(input) {
|
|
431
|
-
return from(Format.fromSnakeCase(input));
|
|
432
|
-
}
|
|
433
|
-
function toSnakeCase(offer) {
|
|
434
|
-
return Format.toSnakeCase(offer);
|
|
435
|
-
}
|
|
436
|
-
function random() {
|
|
437
|
-
const baseOffer = Offer.random();
|
|
438
|
-
return from({
|
|
439
|
-
...baseOffer,
|
|
440
|
-
status: "valid",
|
|
441
|
-
metadata: void 0,
|
|
442
|
-
consumed: 0n
|
|
443
|
-
});
|
|
444
|
-
}
|
|
445
|
-
function fromConsumedLog(parameters) {
|
|
446
|
-
const { blockNumber, logIndex, chainId, transactionHash, user, nonce, amount } = parameters;
|
|
447
|
-
return {
|
|
448
|
-
id: `${blockNumber.toString()}-${logIndex.toString()}-${chainId}-${transactionHash}`,
|
|
449
|
-
chainId: BigInt(chainId),
|
|
450
|
-
offering: user,
|
|
451
|
-
nonce,
|
|
452
|
-
amount
|
|
453
|
-
};
|
|
454
|
-
}
|
|
455
|
-
var InvalidRouterOfferError = class extends Errors.BaseError {
|
|
456
|
-
constructor(error) {
|
|
457
|
-
super("Invalid router offer.", { cause: error });
|
|
458
|
-
__publicField(this, "name", "RouterOffer.InvalidRouterOfferError");
|
|
459
|
-
}
|
|
460
|
-
};
|
|
461
|
-
|
|
462
|
-
// src/core/router/Client.ts
|
|
463
|
-
var Client_exports = {};
|
|
464
|
-
__export(Client_exports, {
|
|
465
|
-
HttpForbiddenError: () => HttpForbiddenError,
|
|
466
|
-
HttpGetOffersFailedError: () => HttpGetOffersFailedError,
|
|
467
|
-
HttpRateLimitError: () => HttpRateLimitError,
|
|
468
|
-
HttpUnauthorizedError: () => HttpUnauthorizedError,
|
|
469
|
-
InvalidUrlError: () => InvalidUrlError,
|
|
470
|
-
connect: () => connect,
|
|
471
|
-
get: () => get,
|
|
472
|
-
match: () => match
|
|
473
|
-
});
|
|
195
|
+
// src/api/Schema/requests.ts
|
|
474
196
|
var MAX_LIMIT = 100;
|
|
475
197
|
var DEFAULT_LIMIT = 20;
|
|
476
198
|
var MAX_LLTV = 100;
|
|
@@ -647,7 +369,7 @@ var GetOffersQueryParams = z.object({
|
|
|
647
369
|
(val) => {
|
|
648
370
|
if (!val) return true;
|
|
649
371
|
try {
|
|
650
|
-
const decoded =
|
|
372
|
+
const decoded = decode(val);
|
|
651
373
|
return decoded !== null;
|
|
652
374
|
} catch (_error) {
|
|
653
375
|
return false;
|
|
@@ -819,7 +541,7 @@ var MatchOffersQueryParams = z.object({
|
|
|
819
541
|
(val) => {
|
|
820
542
|
if (!val) return true;
|
|
821
543
|
try {
|
|
822
|
-
const decoded =
|
|
544
|
+
const decoded = decode(val);
|
|
823
545
|
return decoded !== null;
|
|
824
546
|
} catch (_error) {
|
|
825
547
|
return false;
|
|
@@ -859,7 +581,7 @@ function safeParse(action, query, error) {
|
|
|
859
581
|
});
|
|
860
582
|
}
|
|
861
583
|
|
|
862
|
-
// src/
|
|
584
|
+
// src/api/Schema/openapi.ts
|
|
863
585
|
var successResponseSchema = z.object({
|
|
864
586
|
status: z.literal("success"),
|
|
865
587
|
cursor: z.string().nullable(),
|
|
@@ -962,7 +684,7 @@ createDocument({
|
|
|
962
684
|
paths
|
|
963
685
|
});
|
|
964
686
|
|
|
965
|
-
// src/
|
|
687
|
+
// src/api/Schema/utils.ts
|
|
966
688
|
function toResponse(routerOffer) {
|
|
967
689
|
const { consumed, status, metadata, ...offer } = routerOffer;
|
|
968
690
|
return {
|
|
@@ -982,7 +704,7 @@ function fromResponse(offerResponse) {
|
|
|
982
704
|
};
|
|
983
705
|
}
|
|
984
706
|
|
|
985
|
-
// src/
|
|
707
|
+
// src/api/Client.ts
|
|
986
708
|
function connect(opts) {
|
|
987
709
|
const u = new URL(opts?.url || "https://router.morpho.dev");
|
|
988
710
|
if (u.protocol !== "http:" && u.protocol !== "https:") {
|
|
@@ -1082,135 +804,720 @@ async function get(config, parameters) {
|
|
|
1082
804
|
if (parameters.limit !== void 0) {
|
|
1083
805
|
url.searchParams.set("limit", parameters.limit.toString());
|
|
1084
806
|
}
|
|
1085
|
-
const { cursor: returnedCursor, data: offers } = await getApi(config, url);
|
|
1086
|
-
const routerOffers = offers.map(Format.fromSnakeCase).map(fromResponse);
|
|
1087
|
-
return {
|
|
1088
|
-
cursor: returnedCursor,
|
|
1089
|
-
offers: routerOffers.map(from).map(toResponse)
|
|
1090
|
-
};
|
|
807
|
+
const { cursor: returnedCursor, data: offers } = await getApi(config, url);
|
|
808
|
+
const routerOffers = offers.map(Format.fromSnakeCase).map(fromResponse);
|
|
809
|
+
return {
|
|
810
|
+
cursor: returnedCursor,
|
|
811
|
+
offers: routerOffers.map(from).map(toResponse)
|
|
812
|
+
};
|
|
813
|
+
}
|
|
814
|
+
async function match(config, parameters) {
|
|
815
|
+
const url = new URL(`${config.url.toString()}v1/offers/match`);
|
|
816
|
+
url.searchParams.set("side", parameters.side);
|
|
817
|
+
url.searchParams.set("chain_id", parameters.chainId.toString());
|
|
818
|
+
if (parameters.rate !== void 0) {
|
|
819
|
+
url.searchParams.set("rate", parameters.rate.toString());
|
|
820
|
+
}
|
|
821
|
+
if (parameters.collaterals?.length) {
|
|
822
|
+
const collateralsStr = parameters.collaterals.map(({ asset, oracle, lltv }) => `${asset}:${oracle}:${formatUnits(lltv, 16)}`).join("#");
|
|
823
|
+
url.searchParams.set("collaterals", collateralsStr);
|
|
824
|
+
}
|
|
825
|
+
if (parameters.maturity !== void 0) {
|
|
826
|
+
url.searchParams.set("maturity", parameters.maturity.toString());
|
|
827
|
+
}
|
|
828
|
+
if (parameters.minMaturity !== void 0) {
|
|
829
|
+
url.searchParams.set("min_maturity", parameters.minMaturity.toString());
|
|
830
|
+
}
|
|
831
|
+
if (parameters.maxMaturity !== void 0) {
|
|
832
|
+
url.searchParams.set("max_maturity", parameters.maxMaturity.toString());
|
|
833
|
+
}
|
|
834
|
+
if (parameters.loanToken) {
|
|
835
|
+
url.searchParams.set("loan_token", parameters.loanToken);
|
|
836
|
+
}
|
|
837
|
+
if (parameters.creator) {
|
|
838
|
+
url.searchParams.set("creator", parameters.creator);
|
|
839
|
+
}
|
|
840
|
+
if (parameters.status?.length) {
|
|
841
|
+
url.searchParams.set("status", parameters.status.join(","));
|
|
842
|
+
}
|
|
843
|
+
if (parameters.cursor) {
|
|
844
|
+
url.searchParams.set("cursor", parameters.cursor);
|
|
845
|
+
}
|
|
846
|
+
if (parameters.limit !== void 0) {
|
|
847
|
+
url.searchParams.set("limit", parameters.limit.toString());
|
|
848
|
+
}
|
|
849
|
+
const { cursor: returnedCursor, data: offers } = await getApi(config, url);
|
|
850
|
+
const routerOffers = offers.map(Format.fromSnakeCase).map(fromResponse);
|
|
851
|
+
return {
|
|
852
|
+
cursor: returnedCursor,
|
|
853
|
+
offers: routerOffers.map(from).map(toResponse)
|
|
854
|
+
};
|
|
855
|
+
}
|
|
856
|
+
async function getApi(config, url) {
|
|
857
|
+
const pathname = url.pathname;
|
|
858
|
+
let action;
|
|
859
|
+
switch (true) {
|
|
860
|
+
case pathname.includes("/v1/offers/match"):
|
|
861
|
+
action = "match_offers";
|
|
862
|
+
break;
|
|
863
|
+
case pathname.includes("/v1/offers"):
|
|
864
|
+
action = "get_offers";
|
|
865
|
+
break;
|
|
866
|
+
default:
|
|
867
|
+
throw new HttpGetOffersFailedError("Unknown endpoint", {
|
|
868
|
+
details: `Unsupported path: ${pathname}`
|
|
869
|
+
});
|
|
870
|
+
}
|
|
871
|
+
const schemaParseResult = safeParse(action, Object.fromEntries(url.searchParams));
|
|
872
|
+
if (!schemaParseResult.success) {
|
|
873
|
+
throw new HttpGetOffersFailedError(`Invalid URL parameters`, {
|
|
874
|
+
details: schemaParseResult.error.issues[0]?.message
|
|
875
|
+
});
|
|
876
|
+
}
|
|
877
|
+
const response = await fetch(url.toString(), {
|
|
878
|
+
method: "GET",
|
|
879
|
+
headers: config.headers
|
|
880
|
+
});
|
|
881
|
+
if (!response.ok) {
|
|
882
|
+
switch (response.status) {
|
|
883
|
+
case 401:
|
|
884
|
+
throw new HttpUnauthorizedError();
|
|
885
|
+
case 403:
|
|
886
|
+
throw new HttpForbiddenError();
|
|
887
|
+
case 429:
|
|
888
|
+
throw new HttpRateLimitError();
|
|
889
|
+
}
|
|
890
|
+
throw new HttpGetOffersFailedError(`GET request returned ${response.status}`, {
|
|
891
|
+
details: await response.text()
|
|
892
|
+
});
|
|
893
|
+
}
|
|
894
|
+
return response.json();
|
|
895
|
+
}
|
|
896
|
+
var InvalidUrlError = class extends Errors.BaseError {
|
|
897
|
+
constructor(url) {
|
|
898
|
+
super(`URL "${url}" is not http/https.`);
|
|
899
|
+
__publicField(this, "name", "Router.InvalidUrlError");
|
|
900
|
+
}
|
|
901
|
+
};
|
|
902
|
+
var HttpUnauthorizedError = class extends Errors.BaseError {
|
|
903
|
+
constructor() {
|
|
904
|
+
super("Unauthorized.", {
|
|
905
|
+
metaMessages: ["Ensure that an API key is provided."]
|
|
906
|
+
});
|
|
907
|
+
__publicField(this, "name", "Router.HttpUnauthorizedError");
|
|
908
|
+
}
|
|
909
|
+
};
|
|
910
|
+
var HttpForbiddenError = class extends Errors.BaseError {
|
|
911
|
+
constructor() {
|
|
912
|
+
super("Forbidden.", {
|
|
913
|
+
metaMessages: ["Ensure that the API key is valid."]
|
|
914
|
+
});
|
|
915
|
+
__publicField(this, "name", "Router.HttpForbiddenError");
|
|
916
|
+
}
|
|
917
|
+
};
|
|
918
|
+
var HttpRateLimitError = class extends Errors.BaseError {
|
|
919
|
+
constructor() {
|
|
920
|
+
super("Rate limit exceeded.", {
|
|
921
|
+
metaMessages: [
|
|
922
|
+
"The number of allowed requests has been exceeded. You must wait for the rate limit to reset."
|
|
923
|
+
]
|
|
924
|
+
});
|
|
925
|
+
__publicField(this, "name", "Router.HttpRateLimitError");
|
|
926
|
+
}
|
|
927
|
+
};
|
|
928
|
+
var HttpGetOffersFailedError = class extends Errors.BaseError {
|
|
929
|
+
constructor(message, { details } = {}) {
|
|
930
|
+
super(message, {
|
|
931
|
+
metaMessages: [details]
|
|
932
|
+
});
|
|
933
|
+
__publicField(this, "name", "Router.HttpGetOffersFailedError");
|
|
934
|
+
}
|
|
935
|
+
};
|
|
936
|
+
|
|
937
|
+
// src/core/Callback.ts
|
|
938
|
+
var Callback_exports = {};
|
|
939
|
+
__export(Callback_exports, {
|
|
940
|
+
CallbackType: () => CallbackType,
|
|
941
|
+
WhitelistedCallbackAddresses: () => WhitelistedCallbackAddresses,
|
|
942
|
+
buildLiquidity: () => buildLiquidity,
|
|
943
|
+
decode: () => decode2,
|
|
944
|
+
encode: () => encode2,
|
|
945
|
+
getCallbackIdForOffer: () => getCallbackIdForOffer
|
|
946
|
+
});
|
|
947
|
+
var CallbackType = /* @__PURE__ */ ((CallbackType2) => {
|
|
948
|
+
CallbackType2["BuyWithEmptyCallback"] = "buy_with_empty_callback";
|
|
949
|
+
CallbackType2["SellERC20Callback"] = "sell_erc20_callback";
|
|
950
|
+
return CallbackType2;
|
|
951
|
+
})(CallbackType || {});
|
|
952
|
+
var WhitelistedCallbackAddresses = {
|
|
953
|
+
["buy_with_empty_callback" /* BuyWithEmptyCallback */]: [],
|
|
954
|
+
["sell_erc20_callback" /* SellERC20Callback */]: [
|
|
955
|
+
"0x1111111111111111111111111111111111111111",
|
|
956
|
+
"0x2222222222222222222222222222222222222222"
|
|
957
|
+
// @TODO: update once deployed and add mapping per chain if needed
|
|
958
|
+
].map((address) => address.toLowerCase())
|
|
959
|
+
};
|
|
960
|
+
function buildLiquidity(parameters) {
|
|
961
|
+
switch (parameters.type) {
|
|
962
|
+
case "buy_with_empty_callback" /* BuyWithEmptyCallback */: {
|
|
963
|
+
const { user, loanToken, chainId, amount, index = 0, updatedAt = /* @__PURE__ */ new Date() } = parameters;
|
|
964
|
+
const amountStr = amount.toString();
|
|
965
|
+
const id = `${user}-${chainId.toString()}-${parameters.type}-${loanToken}`.toLowerCase();
|
|
966
|
+
const poolId = `${user}-${chainId.toString()}-${loanToken}`.toLowerCase();
|
|
967
|
+
return {
|
|
968
|
+
userPosition: {
|
|
969
|
+
id,
|
|
970
|
+
availableLiquidityQueueId: id,
|
|
971
|
+
user: user.toLowerCase(),
|
|
972
|
+
chainId,
|
|
973
|
+
amount: amountStr,
|
|
974
|
+
updatedAt
|
|
975
|
+
},
|
|
976
|
+
queues: [
|
|
977
|
+
{
|
|
978
|
+
queue: {
|
|
979
|
+
queueId: id,
|
|
980
|
+
availableLiquidityPoolId: poolId,
|
|
981
|
+
index,
|
|
982
|
+
callbackAmount: "0",
|
|
983
|
+
updatedAt
|
|
984
|
+
},
|
|
985
|
+
pool: {
|
|
986
|
+
id: poolId,
|
|
987
|
+
amount: amountStr,
|
|
988
|
+
updatedAt
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
]
|
|
992
|
+
};
|
|
993
|
+
}
|
|
994
|
+
case "sell_erc20_callback" /* SellERC20Callback */: {
|
|
995
|
+
const {
|
|
996
|
+
user,
|
|
997
|
+
termId,
|
|
998
|
+
offerHash,
|
|
999
|
+
chainId,
|
|
1000
|
+
amount,
|
|
1001
|
+
collaterals,
|
|
1002
|
+
index = 0,
|
|
1003
|
+
updatedAt = /* @__PURE__ */ new Date()
|
|
1004
|
+
} = parameters;
|
|
1005
|
+
const amountStr = amount.toString();
|
|
1006
|
+
const id = `${user}-${chainId.toString()}-${parameters.type}-${termId}-${offerHash}`.toLowerCase();
|
|
1007
|
+
return {
|
|
1008
|
+
userPosition: {
|
|
1009
|
+
id,
|
|
1010
|
+
availableLiquidityQueueId: id,
|
|
1011
|
+
user: user.toLowerCase(),
|
|
1012
|
+
chainId,
|
|
1013
|
+
amount: amountStr,
|
|
1014
|
+
updatedAt
|
|
1015
|
+
},
|
|
1016
|
+
queues: collaterals.map((collateral) => {
|
|
1017
|
+
const poolId = `${user}-${chainId.toString()}-${collateral.collateralAddress}`.toLowerCase();
|
|
1018
|
+
return {
|
|
1019
|
+
queue: {
|
|
1020
|
+
queueId: id,
|
|
1021
|
+
availableLiquidityPoolId: poolId,
|
|
1022
|
+
index,
|
|
1023
|
+
callbackAmount: collateral.callbackAmount.toString(),
|
|
1024
|
+
updatedAt
|
|
1025
|
+
},
|
|
1026
|
+
pool: {
|
|
1027
|
+
id: poolId,
|
|
1028
|
+
amount: collateral.balance.toString(),
|
|
1029
|
+
updatedAt
|
|
1030
|
+
}
|
|
1031
|
+
};
|
|
1032
|
+
})
|
|
1033
|
+
};
|
|
1034
|
+
}
|
|
1035
|
+
default: {
|
|
1036
|
+
throw new Error(`CallbackType not implemented`);
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
function getCallbackIdForOffer(offer) {
|
|
1041
|
+
if (offer.buy && offer.callback.data === "0x") {
|
|
1042
|
+
return `${offer.offering}-${offer.chainId.toString()}-${"buy_with_empty_callback" /* BuyWithEmptyCallback */}-${offer.loanToken}`.toLowerCase();
|
|
1043
|
+
}
|
|
1044
|
+
if (!offer.buy && offer.callback.data !== "0x" && WhitelistedCallbackAddresses["sell_erc20_callback" /* SellERC20Callback */].includes(
|
|
1045
|
+
offer.callback.address.toLowerCase()
|
|
1046
|
+
)) {
|
|
1047
|
+
return `${offer.offering}-${offer.chainId.toString()}-${"sell_erc20_callback" /* SellERC20Callback */}-${Offer.termId(offer)}-${offer.hash}`.toLowerCase();
|
|
1048
|
+
}
|
|
1049
|
+
return null;
|
|
1050
|
+
}
|
|
1051
|
+
function decodeSellERC20CallbackData(data) {
|
|
1052
|
+
if (!data || data === "0x") throw new Error("Empty callback data");
|
|
1053
|
+
try {
|
|
1054
|
+
const [collaterals, amounts] = decodeAbiParameters(
|
|
1055
|
+
[{ type: "address[]" }, { type: "uint256[]" }],
|
|
1056
|
+
data
|
|
1057
|
+
);
|
|
1058
|
+
if (collaterals.length !== amounts.length) {
|
|
1059
|
+
throw new Error("Mismatched array lengths");
|
|
1060
|
+
}
|
|
1061
|
+
return collaterals.map((c, i) => ({ collateral: c, amount: amounts[i] }));
|
|
1062
|
+
} catch (_) {
|
|
1063
|
+
throw new Error("Invalid SellERC20Callback callback data");
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
function decode2(parameters) {
|
|
1067
|
+
const { type, data } = parameters;
|
|
1068
|
+
if (type === "sell_erc20_callback" /* SellERC20Callback */) {
|
|
1069
|
+
return decodeSellERC20CallbackData(data);
|
|
1070
|
+
}
|
|
1071
|
+
throw new Error(`CallbackType not implemented: ${type}`);
|
|
1072
|
+
}
|
|
1073
|
+
function encode2(parameters) {
|
|
1074
|
+
const { type, data } = parameters;
|
|
1075
|
+
if (type === "sell_erc20_callback" /* SellERC20Callback */) {
|
|
1076
|
+
return encodeAbiParameters(
|
|
1077
|
+
[{ type: "address[]" }, { type: "uint256[]" }],
|
|
1078
|
+
[data.collaterals, data.amounts]
|
|
1079
|
+
);
|
|
1080
|
+
}
|
|
1081
|
+
throw new Error(`CallbackType not implemented: ${type}`);
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
// src/core/Liquidity.ts
|
|
1085
|
+
var Liquidity_exports = {};
|
|
1086
|
+
__export(Liquidity_exports, {
|
|
1087
|
+
create: () => create,
|
|
1088
|
+
serialize: () => serialize
|
|
1089
|
+
});
|
|
1090
|
+
|
|
1091
|
+
// src/core/Abi.ts
|
|
1092
|
+
var Oracle = [
|
|
1093
|
+
{
|
|
1094
|
+
type: "function",
|
|
1095
|
+
name: "price",
|
|
1096
|
+
inputs: [],
|
|
1097
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
1098
|
+
stateMutability: "view"
|
|
1099
|
+
}
|
|
1100
|
+
];
|
|
1101
|
+
var Morpho = [
|
|
1102
|
+
{
|
|
1103
|
+
type: "function",
|
|
1104
|
+
name: "collateralOf",
|
|
1105
|
+
inputs: [
|
|
1106
|
+
{
|
|
1107
|
+
name: "",
|
|
1108
|
+
type: "address",
|
|
1109
|
+
internalType: "address"
|
|
1110
|
+
},
|
|
1111
|
+
{
|
|
1112
|
+
name: "",
|
|
1113
|
+
type: "bytes32",
|
|
1114
|
+
internalType: "bytes32"
|
|
1115
|
+
},
|
|
1116
|
+
{
|
|
1117
|
+
name: "",
|
|
1118
|
+
type: "address",
|
|
1119
|
+
internalType: "address"
|
|
1120
|
+
}
|
|
1121
|
+
],
|
|
1122
|
+
outputs: [
|
|
1123
|
+
{
|
|
1124
|
+
name: "",
|
|
1125
|
+
type: "uint256",
|
|
1126
|
+
internalType: "uint256"
|
|
1127
|
+
}
|
|
1128
|
+
],
|
|
1129
|
+
stateMutability: "view"
|
|
1130
|
+
},
|
|
1131
|
+
{
|
|
1132
|
+
type: "function",
|
|
1133
|
+
name: "debtOf",
|
|
1134
|
+
inputs: [
|
|
1135
|
+
{
|
|
1136
|
+
name: "",
|
|
1137
|
+
type: "address",
|
|
1138
|
+
internalType: "address"
|
|
1139
|
+
},
|
|
1140
|
+
{
|
|
1141
|
+
name: "",
|
|
1142
|
+
type: "bytes32",
|
|
1143
|
+
internalType: "bytes32"
|
|
1144
|
+
}
|
|
1145
|
+
],
|
|
1146
|
+
outputs: [
|
|
1147
|
+
{
|
|
1148
|
+
name: "",
|
|
1149
|
+
type: "uint256",
|
|
1150
|
+
internalType: "uint256"
|
|
1151
|
+
}
|
|
1152
|
+
],
|
|
1153
|
+
stateMutability: "view"
|
|
1154
|
+
}
|
|
1155
|
+
];
|
|
1156
|
+
|
|
1157
|
+
// src/core/Fetchers.ts
|
|
1158
|
+
async function fetchBalancesAndAllowances(parameters) {
|
|
1159
|
+
const { client, spender, pairs, options } = parameters;
|
|
1160
|
+
if (pairs.length === 0) return /* @__PURE__ */ new Map();
|
|
1161
|
+
const batchSize = Math.max(1, options?.batchSize ?? 5e3);
|
|
1162
|
+
const retryAttempts = Math.max(1, options?.retryAttempts ?? 3);
|
|
1163
|
+
const retryDelayMs = Math.max(0, options?.retryDelayMs ?? 50);
|
|
1164
|
+
const blockNumber = options?.blockNumber ? BigInt(options.blockNumber) : void 0;
|
|
1165
|
+
const out = /* @__PURE__ */ new Map();
|
|
1166
|
+
for (const pairsBatch of Utils.batch(pairs, batchSize)) {
|
|
1167
|
+
const balanceCalls = [];
|
|
1168
|
+
const allowanceCalls = [];
|
|
1169
|
+
for (const { user, token } of pairsBatch) {
|
|
1170
|
+
balanceCalls.push({
|
|
1171
|
+
address: token,
|
|
1172
|
+
abi: erc20Abi,
|
|
1173
|
+
functionName: "balanceOf",
|
|
1174
|
+
args: [user]
|
|
1175
|
+
});
|
|
1176
|
+
allowanceCalls.push({
|
|
1177
|
+
address: token,
|
|
1178
|
+
abi: erc20Abi,
|
|
1179
|
+
functionName: "allowance",
|
|
1180
|
+
args: [user, spender]
|
|
1181
|
+
});
|
|
1182
|
+
}
|
|
1183
|
+
const [balances, allowances] = await Promise.all([
|
|
1184
|
+
Utils.retry(
|
|
1185
|
+
() => client.multicall({
|
|
1186
|
+
allowFailure: false,
|
|
1187
|
+
contracts: balanceCalls,
|
|
1188
|
+
...blockNumber ? { blockNumber } : {}
|
|
1189
|
+
}),
|
|
1190
|
+
retryAttempts,
|
|
1191
|
+
retryDelayMs
|
|
1192
|
+
),
|
|
1193
|
+
Utils.retry(
|
|
1194
|
+
() => client.multicall({
|
|
1195
|
+
allowFailure: false,
|
|
1196
|
+
contracts: allowanceCalls,
|
|
1197
|
+
...blockNumber ? { blockNumber } : {}
|
|
1198
|
+
}),
|
|
1199
|
+
retryAttempts,
|
|
1200
|
+
retryDelayMs
|
|
1201
|
+
)
|
|
1202
|
+
]);
|
|
1203
|
+
for (let i = 0; i < pairsBatch.length; i++) {
|
|
1204
|
+
const { user, token } = pairsBatch[i];
|
|
1205
|
+
const balance = balances[i];
|
|
1206
|
+
const allowance = allowances[i];
|
|
1207
|
+
let perUser = out.get(user);
|
|
1208
|
+
if (!perUser) {
|
|
1209
|
+
perUser = /* @__PURE__ */ new Map();
|
|
1210
|
+
out.set(user, perUser);
|
|
1211
|
+
}
|
|
1212
|
+
perUser.set(token, { balance, allowance });
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
return out;
|
|
1091
1216
|
}
|
|
1092
|
-
async function
|
|
1093
|
-
const
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
if (parameters.limit !== void 0) {
|
|
1125
|
-
url.searchParams.set("limit", parameters.limit.toString());
|
|
1217
|
+
async function fetchOraclePrices(parameters) {
|
|
1218
|
+
const { client, oracles, options } = parameters;
|
|
1219
|
+
if (oracles.length === 0) return /* @__PURE__ */ new Map();
|
|
1220
|
+
const batchSize = Math.max(1, options?.batchSize ?? 5e3);
|
|
1221
|
+
const retryAttempts = Math.max(1, options?.retryAttempts ?? 3);
|
|
1222
|
+
const retryDelayMs = Math.max(0, options?.retryDelayMs ?? 50);
|
|
1223
|
+
const blockNumber = options?.blockNumber ? BigInt(options.blockNumber) : void 0;
|
|
1224
|
+
const out = /* @__PURE__ */ new Map();
|
|
1225
|
+
for (const oraclesBatch of Utils.batch(oracles, batchSize)) {
|
|
1226
|
+
const priceCalls = [];
|
|
1227
|
+
for (const oracle of oraclesBatch) {
|
|
1228
|
+
priceCalls.push({
|
|
1229
|
+
address: oracle,
|
|
1230
|
+
abi: Oracle,
|
|
1231
|
+
functionName: "price",
|
|
1232
|
+
args: []
|
|
1233
|
+
});
|
|
1234
|
+
}
|
|
1235
|
+
const prices = await Utils.retry(
|
|
1236
|
+
() => client.multicall({
|
|
1237
|
+
allowFailure: false,
|
|
1238
|
+
contracts: priceCalls,
|
|
1239
|
+
...blockNumber ? { blockNumber } : {}
|
|
1240
|
+
}),
|
|
1241
|
+
retryAttempts,
|
|
1242
|
+
retryDelayMs
|
|
1243
|
+
);
|
|
1244
|
+
for (let i = 0; i < oraclesBatch.length; i++) {
|
|
1245
|
+
const oracle = oraclesBatch[i];
|
|
1246
|
+
const price = prices[i];
|
|
1247
|
+
out.set(oracle, price);
|
|
1248
|
+
}
|
|
1126
1249
|
}
|
|
1127
|
-
|
|
1128
|
-
const routerOffers = offers.map(Format.fromSnakeCase).map(fromResponse);
|
|
1129
|
-
return {
|
|
1130
|
-
cursor: returnedCursor,
|
|
1131
|
-
offers: routerOffers.map(from).map(toResponse)
|
|
1132
|
-
};
|
|
1250
|
+
return out;
|
|
1133
1251
|
}
|
|
1134
|
-
async function
|
|
1135
|
-
const
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1252
|
+
async function fetchCollateralAndDebt(parameters) {
|
|
1253
|
+
const { client, morphoAddress, queries, options } = parameters;
|
|
1254
|
+
if (queries.length === 0) return /* @__PURE__ */ new Map();
|
|
1255
|
+
const batchSize = Math.max(1, options?.batchSize ?? 5e3);
|
|
1256
|
+
const retryAttempts = Math.max(1, options?.retryAttempts ?? 3);
|
|
1257
|
+
const retryDelayMs = Math.max(0, options?.retryDelayMs ?? 50);
|
|
1258
|
+
const blockNumber = options?.blockNumber ? BigInt(options.blockNumber) : void 0;
|
|
1259
|
+
const out = /* @__PURE__ */ new Map();
|
|
1260
|
+
for (const queriesBatch of Utils.batch(queries, batchSize)) {
|
|
1261
|
+
const collateralCalls = [];
|
|
1262
|
+
const debtCalls = [];
|
|
1263
|
+
for (const { user, termId, collateralAssets } of queriesBatch) {
|
|
1264
|
+
debtCalls.push({
|
|
1265
|
+
address: morphoAddress,
|
|
1266
|
+
abi: Morpho,
|
|
1267
|
+
functionName: "debtOf",
|
|
1268
|
+
args: [user, termId]
|
|
1147
1269
|
});
|
|
1270
|
+
for (const collateralAsset of collateralAssets) {
|
|
1271
|
+
collateralCalls.push({
|
|
1272
|
+
address: morphoAddress,
|
|
1273
|
+
abi: Morpho,
|
|
1274
|
+
functionName: "collateralOf",
|
|
1275
|
+
args: [user, termId, collateralAsset]
|
|
1276
|
+
});
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
const [collateralResults, debtResults] = await Promise.all([
|
|
1280
|
+
Utils.retry(
|
|
1281
|
+
() => client.multicall({
|
|
1282
|
+
allowFailure: false,
|
|
1283
|
+
contracts: collateralCalls,
|
|
1284
|
+
...blockNumber ? { blockNumber } : {}
|
|
1285
|
+
}),
|
|
1286
|
+
retryAttempts,
|
|
1287
|
+
retryDelayMs
|
|
1288
|
+
),
|
|
1289
|
+
Utils.retry(
|
|
1290
|
+
() => client.multicall({
|
|
1291
|
+
allowFailure: false,
|
|
1292
|
+
contracts: debtCalls,
|
|
1293
|
+
...blockNumber ? { blockNumber } : {}
|
|
1294
|
+
}),
|
|
1295
|
+
retryAttempts,
|
|
1296
|
+
retryDelayMs
|
|
1297
|
+
)
|
|
1298
|
+
]);
|
|
1299
|
+
let collateralIndex = 0;
|
|
1300
|
+
for (let queryIndex = 0; queryIndex < queriesBatch.length; queryIndex++) {
|
|
1301
|
+
const { user, termId, collateralAssets } = queriesBatch[queryIndex];
|
|
1302
|
+
const debt = debtResults[queryIndex];
|
|
1303
|
+
const collateralByAsset = /* @__PURE__ */ new Map();
|
|
1304
|
+
for (const collateralAsset of collateralAssets) {
|
|
1305
|
+
const collateralAmount = collateralResults[collateralIndex];
|
|
1306
|
+
collateralByAsset.set(collateralAsset.toLowerCase(), collateralAmount);
|
|
1307
|
+
collateralIndex++;
|
|
1308
|
+
}
|
|
1309
|
+
let perUser = out.get(user);
|
|
1310
|
+
if (!perUser) {
|
|
1311
|
+
perUser = /* @__PURE__ */ new Map();
|
|
1312
|
+
out.set(user, perUser);
|
|
1313
|
+
}
|
|
1314
|
+
perUser.set(termId, {
|
|
1315
|
+
collateralByAsset,
|
|
1316
|
+
debt
|
|
1317
|
+
});
|
|
1318
|
+
}
|
|
1148
1319
|
}
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
}
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1320
|
+
return out;
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
// src/core/Liquidity.ts
|
|
1324
|
+
async function fetchMaxBorrowCapacity(parameters) {
|
|
1325
|
+
const { client, collaterals, existingDebt, options } = parameters;
|
|
1326
|
+
if (collaterals.length === 0) return 0n;
|
|
1327
|
+
const uniqueOracles = [...new Set(collaterals.map((c) => c.oracle))];
|
|
1328
|
+
const oraclePrices = await fetchOraclePrices({
|
|
1329
|
+
client,
|
|
1330
|
+
oracles: uniqueOracles,
|
|
1331
|
+
options
|
|
1158
1332
|
});
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1333
|
+
const ORACLE_PRICE_SCALE = 10n ** 36n;
|
|
1334
|
+
const PRECISION = 10n ** 18n;
|
|
1335
|
+
let maxDebt = 0n;
|
|
1336
|
+
for (const collateral of collaterals) {
|
|
1337
|
+
const price = oraclePrices.get(collateral.oracle);
|
|
1338
|
+
if (!price) continue;
|
|
1339
|
+
const collateralQuoted = collateral.totalAmount * price / ORACLE_PRICE_SCALE;
|
|
1340
|
+
const collateralMaxDebt = collateralQuoted * collateral.lltv / PRECISION;
|
|
1341
|
+
maxDebt = maxDebt + collateralMaxDebt;
|
|
1342
|
+
}
|
|
1343
|
+
if (existingDebt > 0n) {
|
|
1344
|
+
if (maxDebt > existingDebt) {
|
|
1345
|
+
maxDebt = maxDebt - existingDebt;
|
|
1346
|
+
} else {
|
|
1347
|
+
maxDebt = 0n;
|
|
1167
1348
|
}
|
|
1168
|
-
throw new HttpGetOffersFailedError(`GET request returned ${response.status}`, {
|
|
1169
|
-
details: await response.text()
|
|
1170
|
-
});
|
|
1171
1349
|
}
|
|
1172
|
-
return
|
|
1350
|
+
return maxDebt;
|
|
1173
1351
|
}
|
|
1174
|
-
var
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1352
|
+
var create = (config) => {
|
|
1353
|
+
const { client } = config;
|
|
1354
|
+
return {
|
|
1355
|
+
fetchBuyLiquidity: (parameters) => fetchBuyLiquidity({ ...parameters, client }),
|
|
1356
|
+
fetchSellLiquidity: (parameters) => fetchSellLiquidity({ ...parameters, client })
|
|
1357
|
+
};
|
|
1179
1358
|
};
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1359
|
+
async function fetchBuyLiquidity(parameters) {
|
|
1360
|
+
const { client, chainId, spender, pairs, options } = parameters;
|
|
1361
|
+
const map = await fetchBalancesAndAllowances({
|
|
1362
|
+
client,
|
|
1363
|
+
spender,
|
|
1364
|
+
pairs: pairs.map(({ user, loanToken }) => ({ user, token: loanToken })),
|
|
1365
|
+
options
|
|
1366
|
+
});
|
|
1367
|
+
const out = [];
|
|
1368
|
+
for (const [user, perLoanToken] of map) {
|
|
1369
|
+
for (const [loanToken, { balance, allowance }] of perLoanToken) {
|
|
1370
|
+
const amount = balance < allowance ? balance : allowance;
|
|
1371
|
+
out.push(
|
|
1372
|
+
buildLiquidity({
|
|
1373
|
+
type: "buy_with_empty_callback" /* BuyWithEmptyCallback */,
|
|
1374
|
+
user,
|
|
1375
|
+
loanToken,
|
|
1376
|
+
chainId,
|
|
1377
|
+
amount,
|
|
1378
|
+
index: 0
|
|
1379
|
+
})
|
|
1380
|
+
);
|
|
1381
|
+
}
|
|
1186
1382
|
}
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1383
|
+
return out;
|
|
1384
|
+
}
|
|
1385
|
+
async function fetchSellLiquidity(parameters) {
|
|
1386
|
+
const { client, chainId, spender, morphoAddress, offers, options } = parameters;
|
|
1387
|
+
const collateralPairs = [];
|
|
1388
|
+
for (const offer of offers) {
|
|
1389
|
+
const user = offer.offering;
|
|
1390
|
+
const callbackData = decode2({
|
|
1391
|
+
type: "sell_erc20_callback" /* SellERC20Callback */,
|
|
1392
|
+
data: offer.callback.data
|
|
1192
1393
|
});
|
|
1193
|
-
|
|
1394
|
+
for (const { collateral } of callbackData) {
|
|
1395
|
+
collateralPairs.push({ user, token: collateral });
|
|
1396
|
+
}
|
|
1194
1397
|
}
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1398
|
+
const map = await fetchBalancesAndAllowances({
|
|
1399
|
+
client,
|
|
1400
|
+
spender,
|
|
1401
|
+
pairs: collateralPairs,
|
|
1402
|
+
options
|
|
1403
|
+
});
|
|
1404
|
+
const collateralDebt = [];
|
|
1405
|
+
for (const offer of offers) {
|
|
1406
|
+
const user = offer.offering;
|
|
1407
|
+
const termId = Offer.termId(offer);
|
|
1408
|
+
const collateralAssets = offer.collaterals.map((collateral) => collateral.asset);
|
|
1409
|
+
collateralDebt.push({
|
|
1410
|
+
user,
|
|
1411
|
+
termId,
|
|
1412
|
+
collateralAssets
|
|
1202
1413
|
});
|
|
1203
|
-
__publicField(this, "name", "Router.HttpRateLimitError");
|
|
1204
1414
|
}
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1415
|
+
const existingPositions = await fetchCollateralAndDebt({
|
|
1416
|
+
client,
|
|
1417
|
+
morphoAddress,
|
|
1418
|
+
queries: collateralDebt,
|
|
1419
|
+
options
|
|
1420
|
+
});
|
|
1421
|
+
const out = [];
|
|
1422
|
+
for (const offer of offers) {
|
|
1423
|
+
const user = offer.offering;
|
|
1424
|
+
const termId = Offer.termId(offer);
|
|
1425
|
+
const callbackData = decode2({
|
|
1426
|
+
type: "sell_erc20_callback" /* SellERC20Callback */,
|
|
1427
|
+
data: offer.callback.data
|
|
1210
1428
|
});
|
|
1211
|
-
|
|
1429
|
+
const callbackCollaterals = callbackData.map((callbackItem) => {
|
|
1430
|
+
const userMap = map.get(user);
|
|
1431
|
+
const tokenData = userMap?.get(callbackItem.collateral);
|
|
1432
|
+
if (!tokenData) return null;
|
|
1433
|
+
const offerCollateral = offer.collaterals.find(
|
|
1434
|
+
(c) => c.asset.toLowerCase() === callbackItem.collateral.toLowerCase()
|
|
1435
|
+
);
|
|
1436
|
+
if (!offerCollateral) return null;
|
|
1437
|
+
const { balance, allowance } = tokenData;
|
|
1438
|
+
const availableAmount = balance < allowance ? balance : allowance;
|
|
1439
|
+
return {
|
|
1440
|
+
collateralAddress: callbackItem.collateral,
|
|
1441
|
+
balance: availableAmount,
|
|
1442
|
+
callbackAmount: callbackItem.amount
|
|
1443
|
+
};
|
|
1444
|
+
}).filter((collateral) => collateral !== null);
|
|
1445
|
+
if (callbackCollaterals.length === 0) continue;
|
|
1446
|
+
const existingPosition = existingPositions.get(user)?.get(termId);
|
|
1447
|
+
const collaterals = offer.collaterals.map((c) => {
|
|
1448
|
+
const callbackCollateral = callbackCollaterals.find(
|
|
1449
|
+
(cc) => cc.collateralAddress.toLowerCase() === c.asset.toLowerCase()
|
|
1450
|
+
);
|
|
1451
|
+
const callbackAmount = callbackCollateral?.balance ?? 0n;
|
|
1452
|
+
const existingAmount = existingPosition?.collateralByAsset.get(c.asset.toLowerCase()) ?? 0n;
|
|
1453
|
+
return {
|
|
1454
|
+
asset: c.asset,
|
|
1455
|
+
oracle: c.oracle,
|
|
1456
|
+
lltv: c.lltv,
|
|
1457
|
+
totalAmount: existingAmount + callbackAmount
|
|
1458
|
+
};
|
|
1459
|
+
});
|
|
1460
|
+
const existingDebt = existingPosition?.debt ?? 0n;
|
|
1461
|
+
const userPositionAmount = await fetchMaxBorrowCapacity({
|
|
1462
|
+
client,
|
|
1463
|
+
collaterals,
|
|
1464
|
+
existingDebt,
|
|
1465
|
+
options
|
|
1466
|
+
});
|
|
1467
|
+
out.push(
|
|
1468
|
+
buildLiquidity({
|
|
1469
|
+
type: "sell_erc20_callback" /* SellERC20Callback */,
|
|
1470
|
+
user,
|
|
1471
|
+
termId,
|
|
1472
|
+
offerHash: offer.hash,
|
|
1473
|
+
chainId,
|
|
1474
|
+
amount: userPositionAmount,
|
|
1475
|
+
collaterals: callbackCollaterals,
|
|
1476
|
+
index: 0
|
|
1477
|
+
})
|
|
1478
|
+
);
|
|
1212
1479
|
}
|
|
1213
|
-
|
|
1480
|
+
return out;
|
|
1481
|
+
}
|
|
1482
|
+
function serialize(liquidity) {
|
|
1483
|
+
const normalized = {
|
|
1484
|
+
userPosition: {
|
|
1485
|
+
id: liquidity.userPosition.id,
|
|
1486
|
+
availableLiquidityQueueId: liquidity.userPosition.availableLiquidityQueueId,
|
|
1487
|
+
user: liquidity.userPosition.user,
|
|
1488
|
+
chainId: String(liquidity.userPosition.chainId),
|
|
1489
|
+
amount: String(liquidity.userPosition.amount)
|
|
1490
|
+
},
|
|
1491
|
+
queues: liquidity.queues.map((queueWithPool) => ({
|
|
1492
|
+
queue: {
|
|
1493
|
+
queueId: queueWithPool.queue.queueId,
|
|
1494
|
+
availableLiquidityPoolId: queueWithPool.queue.availableLiquidityPoolId,
|
|
1495
|
+
index: queueWithPool.queue.index
|
|
1496
|
+
},
|
|
1497
|
+
pool: {
|
|
1498
|
+
id: queueWithPool.pool.id,
|
|
1499
|
+
amount: String(queueWithPool.pool.amount)
|
|
1500
|
+
}
|
|
1501
|
+
})).sort(
|
|
1502
|
+
(left, right) => {
|
|
1503
|
+
const leftQueueId = left.queue.queueId || "";
|
|
1504
|
+
const rightQueueId = right.queue.queueId || "";
|
|
1505
|
+
if (leftQueueId < rightQueueId) return -1;
|
|
1506
|
+
if (leftQueueId > rightQueueId) return 1;
|
|
1507
|
+
const leftPoolId = left.pool.id;
|
|
1508
|
+
const rightPoolId = right.pool.id;
|
|
1509
|
+
if (leftPoolId < rightPoolId) return -1;
|
|
1510
|
+
if (leftPoolId > rightPoolId) return 1;
|
|
1511
|
+
const leftIndex = left.queue.index;
|
|
1512
|
+
const rightIndex = right.queue.index;
|
|
1513
|
+
if (leftIndex < rightIndex) return -1;
|
|
1514
|
+
if (leftIndex > rightIndex) return 1;
|
|
1515
|
+
return 0;
|
|
1516
|
+
}
|
|
1517
|
+
)
|
|
1518
|
+
};
|
|
1519
|
+
return JSON.stringify(normalized);
|
|
1520
|
+
}
|
|
1214
1521
|
|
|
1215
1522
|
// src/core/Validation.ts
|
|
1216
1523
|
var Validation_exports = {};
|
|
@@ -1316,7 +1623,7 @@ function morpho() {
|
|
|
1316
1623
|
(offer, _) => {
|
|
1317
1624
|
if (!offer.buy && offer.callback.data !== "0x") {
|
|
1318
1625
|
const allowed = new Set(
|
|
1319
|
-
WhitelistedCallbackAddresses["
|
|
1626
|
+
WhitelistedCallbackAddresses["sell_erc20_callback" /* SellERC20Callback */].map(
|
|
1320
1627
|
(a) => a.toLowerCase()
|
|
1321
1628
|
)
|
|
1322
1629
|
);
|
|
@@ -1332,8 +1639,8 @@ function morpho() {
|
|
|
1332
1639
|
(offer, _) => {
|
|
1333
1640
|
if (!offer.buy && offer.callback.data !== "0x") {
|
|
1334
1641
|
try {
|
|
1335
|
-
const decoded =
|
|
1336
|
-
type: "
|
|
1642
|
+
const decoded = decode2({
|
|
1643
|
+
type: "sell_erc20_callback" /* SellERC20Callback */,
|
|
1337
1644
|
data: offer.callback.data
|
|
1338
1645
|
});
|
|
1339
1646
|
if (decoded.length === 0) {
|
|
@@ -1350,8 +1657,8 @@ function morpho() {
|
|
|
1350
1657
|
(offer, _) => {
|
|
1351
1658
|
if (!offer.buy && offer.callback.data !== "0x") {
|
|
1352
1659
|
try {
|
|
1353
|
-
const decoded =
|
|
1354
|
-
type: "
|
|
1660
|
+
const decoded = decode2({
|
|
1661
|
+
type: "sell_erc20_callback" /* SellERC20Callback */,
|
|
1355
1662
|
data: offer.callback.data
|
|
1356
1663
|
});
|
|
1357
1664
|
const offerCollaterals = new Set(
|
|
@@ -1367,10 +1674,19 @@ function morpho() {
|
|
|
1367
1674
|
}
|
|
1368
1675
|
}
|
|
1369
1676
|
);
|
|
1677
|
+
const maturity = single("maturity", (offer, _) => {
|
|
1678
|
+
const allowedMaturities = [Maturity.from("end_of_month"), Maturity.from("end_of_next_month")];
|
|
1679
|
+
if (!allowedMaturities.includes(offer.maturity)) {
|
|
1680
|
+
return {
|
|
1681
|
+
message: `Maturity must be end of current month (${allowedMaturities[0]}) or end of next month (${allowedMaturities[1]}). Got: ${offer.maturity}`
|
|
1682
|
+
};
|
|
1683
|
+
}
|
|
1684
|
+
});
|
|
1370
1685
|
return [
|
|
1371
1686
|
chainId,
|
|
1372
1687
|
loanToken,
|
|
1373
1688
|
expiry,
|
|
1689
|
+
maturity,
|
|
1374
1690
|
// note: callback rules should be the last ones, since they do not mean that the offer is forever invalid
|
|
1375
1691
|
// integrators should be able to choose if they want to keep the offer or not
|
|
1376
1692
|
sellEmptyCallback,
|
|
@@ -1381,6 +1697,6 @@ function morpho() {
|
|
|
1381
1697
|
];
|
|
1382
1698
|
}
|
|
1383
1699
|
|
|
1384
|
-
export { Callback_exports as Callback, Cursor_exports as Cursor, Liquidity_exports as Liquidity, Client_exports as
|
|
1700
|
+
export { Callback_exports as Callback, Cursor_exports as Cursor, Liquidity_exports as Liquidity, Client_exports as RouterApi, RouterOffer_exports as RouterOffer, Validation_exports as Validation, ValidationRule_exports as ValidationRule };
|
|
1385
1701
|
//# sourceMappingURL=index.browser.mjs.map
|
|
1386
1702
|
//# sourceMappingURL=index.browser.mjs.map
|