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