@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.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { Errors, LLTV,
|
|
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,108 +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
|
-
const { type, user, contract, chainId, amount, index = 0, updatedAt = /* @__PURE__ */ new Date() } = parameters;
|
|
41
|
-
if (type !== "buy_with_empty_callback" /* BuyWithEmptyCallback */)
|
|
42
|
-
throw new Error(`CallbackType not implemented: ${type}`);
|
|
43
|
-
const amountStr = amount.toString();
|
|
44
|
-
const id = `${user}-${chainId.toString()}-${type}-${contract}`.toLowerCase();
|
|
45
|
-
return {
|
|
46
|
-
userPosition: {
|
|
47
|
-
id,
|
|
48
|
-
availableLiquidityQueueId: id,
|
|
49
|
-
user: user.toLowerCase(),
|
|
50
|
-
chainId,
|
|
51
|
-
amount: amountStr,
|
|
52
|
-
updatedAt
|
|
53
|
-
},
|
|
54
|
-
queues: [
|
|
55
|
-
{
|
|
56
|
-
queue: {
|
|
57
|
-
queueId: id,
|
|
58
|
-
availableLiquidityPoolId: id,
|
|
59
|
-
index,
|
|
60
|
-
updatedAt
|
|
61
|
-
},
|
|
62
|
-
pool: {
|
|
63
|
-
id,
|
|
64
|
-
amount: amountStr,
|
|
65
|
-
updatedAt
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
]
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
function getCallbackIdForOffer(offer) {
|
|
72
|
-
if (offer.buy && offer.callback.data === "0x") {
|
|
73
|
-
const type = "buy_with_empty_callback" /* BuyWithEmptyCallback */;
|
|
74
|
-
const user = offer.offering;
|
|
75
|
-
const loanToken = offer.loanToken;
|
|
76
|
-
return `${user}-${offer.chainId.toString()}-${type}-${loanToken}`.toLowerCase();
|
|
77
|
-
}
|
|
78
|
-
return null;
|
|
79
|
-
}
|
|
80
|
-
function decodeSellWithdrawFromWalletData(data) {
|
|
81
|
-
if (!data || data === "0x") throw new Error("Empty callback data");
|
|
65
|
+
function from(input) {
|
|
82
66
|
try {
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
} catch (_) {
|
|
92
|
-
throw new Error("Invalid SellWithdrawFromWallet callback data");
|
|
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);
|
|
93
75
|
}
|
|
94
76
|
}
|
|
95
|
-
function
|
|
96
|
-
|
|
97
|
-
if (type === "sell_withdraw_from_wallet" /* SellWithdrawFromWallet */) {
|
|
98
|
-
return decodeSellWithdrawFromWalletData(data);
|
|
99
|
-
}
|
|
100
|
-
throw new Error(`CallbackType not implemented: ${type}`);
|
|
77
|
+
function fromSnakeCase(input) {
|
|
78
|
+
return from(Format.fromSnakeCase(input));
|
|
101
79
|
}
|
|
102
|
-
function
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
80
|
+
function toSnakeCase(offer) {
|
|
81
|
+
return Format.toSnakeCase(offer);
|
|
82
|
+
}
|
|
83
|
+
function random() {
|
|
84
|
+
const baseOffer = Offer.random();
|
|
85
|
+
return from({
|
|
86
|
+
...baseOffer,
|
|
87
|
+
status: "valid",
|
|
88
|
+
metadata: void 0,
|
|
89
|
+
consumed: 0n
|
|
90
|
+
});
|
|
111
91
|
}
|
|
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
|
+
};
|
|
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
|
+
};
|
|
112
108
|
|
|
113
109
|
// src/core/Cursor.ts
|
|
114
110
|
var Cursor_exports = {};
|
|
115
111
|
__export(Cursor_exports, {
|
|
116
|
-
decode: () =>
|
|
117
|
-
encode: () =>
|
|
112
|
+
decode: () => decode,
|
|
113
|
+
encode: () => encode,
|
|
118
114
|
validate: () => validate
|
|
119
115
|
});
|
|
120
116
|
function validate(cursor) {
|
|
@@ -186,242 +182,17 @@ function validate(cursor) {
|
|
|
186
182
|
}
|
|
187
183
|
return true;
|
|
188
184
|
}
|
|
189
|
-
function
|
|
185
|
+
function encode(c) {
|
|
190
186
|
return Base64.encodeURL(JSON.stringify(c));
|
|
191
187
|
}
|
|
192
|
-
function
|
|
188
|
+
function decode(token) {
|
|
193
189
|
if (!token) return null;
|
|
194
190
|
const decoded = JSON.parse(Base64.decode(token));
|
|
195
191
|
validate(decoded);
|
|
196
192
|
return decoded;
|
|
197
193
|
}
|
|
198
194
|
|
|
199
|
-
// src/
|
|
200
|
-
var Liquidity_exports = {};
|
|
201
|
-
__export(Liquidity_exports, {
|
|
202
|
-
fetch: () => fetch2,
|
|
203
|
-
fetchBalancesAndAllowances: () => fetchBalancesAndAllowances,
|
|
204
|
-
serialize: () => serialize
|
|
205
|
-
});
|
|
206
|
-
async function fetchBalancesAndAllowances(parameters) {
|
|
207
|
-
const { client, spender, pairs, options } = parameters;
|
|
208
|
-
if (pairs.length === 0) return /* @__PURE__ */ new Map();
|
|
209
|
-
const batchSize = Math.max(1, options?.batchSize ?? 5e3);
|
|
210
|
-
const retryAttempts = Math.max(1, options?.retryAttempts ?? 3);
|
|
211
|
-
const retryDelayMs = Math.max(0, options?.retryDelayMs ?? 50);
|
|
212
|
-
const blockNumber = options?.blockNumber ? BigInt(options.blockNumber) : void 0;
|
|
213
|
-
const out = /* @__PURE__ */ new Map();
|
|
214
|
-
for (const pairsBatch of Utils.batch(pairs, batchSize)) {
|
|
215
|
-
const balanceContracts = [];
|
|
216
|
-
const allowanceContracts = [];
|
|
217
|
-
for (const { user, token } of pairsBatch) {
|
|
218
|
-
balanceContracts.push({
|
|
219
|
-
address: token,
|
|
220
|
-
abi: erc20Abi,
|
|
221
|
-
functionName: "balanceOf",
|
|
222
|
-
args: [user]
|
|
223
|
-
});
|
|
224
|
-
allowanceContracts.push({
|
|
225
|
-
address: token,
|
|
226
|
-
abi: erc20Abi,
|
|
227
|
-
functionName: "allowance",
|
|
228
|
-
args: [user, spender]
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
const [balances, allowances] = await Promise.all([
|
|
232
|
-
Utils.retry(
|
|
233
|
-
() => client.multicall({
|
|
234
|
-
allowFailure: false,
|
|
235
|
-
contracts: balanceContracts,
|
|
236
|
-
...blockNumber ? { blockNumber } : {}
|
|
237
|
-
}),
|
|
238
|
-
retryAttempts,
|
|
239
|
-
retryDelayMs
|
|
240
|
-
),
|
|
241
|
-
Utils.retry(
|
|
242
|
-
() => client.multicall({
|
|
243
|
-
allowFailure: false,
|
|
244
|
-
contracts: allowanceContracts,
|
|
245
|
-
...blockNumber ? { blockNumber } : {}
|
|
246
|
-
}),
|
|
247
|
-
retryAttempts,
|
|
248
|
-
retryDelayMs
|
|
249
|
-
)
|
|
250
|
-
]);
|
|
251
|
-
for (let i = 0; i < pairsBatch.length; i++) {
|
|
252
|
-
const { user, token } = pairsBatch[i];
|
|
253
|
-
const balance = balances[i];
|
|
254
|
-
const allowance = allowances[i];
|
|
255
|
-
let perUser = out.get(user);
|
|
256
|
-
if (!perUser) {
|
|
257
|
-
perUser = /* @__PURE__ */ new Map();
|
|
258
|
-
out.set(user, perUser);
|
|
259
|
-
}
|
|
260
|
-
perUser.set(token, { balance, allowance });
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
return out;
|
|
264
|
-
}
|
|
265
|
-
async function fetch2(parameters) {
|
|
266
|
-
const { client, chainId, spender, type, pairs, options } = parameters;
|
|
267
|
-
if (type !== "buy_with_empty_callback" /* BuyWithEmptyCallback */)
|
|
268
|
-
throw new Error(`CallbackType not implemented: ${type}`);
|
|
269
|
-
const map = await fetchBalancesAndAllowances({
|
|
270
|
-
client,
|
|
271
|
-
spender,
|
|
272
|
-
pairs: pairs.map(({ user, contract }) => ({ user, token: contract })),
|
|
273
|
-
options
|
|
274
|
-
});
|
|
275
|
-
const out = [];
|
|
276
|
-
for (const [user, perContract] of map) {
|
|
277
|
-
for (const [contract, { balance, allowance }] of perContract) {
|
|
278
|
-
const amount = balance < allowance ? balance : allowance;
|
|
279
|
-
out.push(
|
|
280
|
-
buildLiquidity({
|
|
281
|
-
type,
|
|
282
|
-
user,
|
|
283
|
-
contract,
|
|
284
|
-
chainId,
|
|
285
|
-
amount: amount.toString(),
|
|
286
|
-
index: 0
|
|
287
|
-
})
|
|
288
|
-
);
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
return out;
|
|
292
|
-
}
|
|
293
|
-
function serialize(liquidity) {
|
|
294
|
-
const normalized = {
|
|
295
|
-
userPosition: {
|
|
296
|
-
id: liquidity.userPosition.id,
|
|
297
|
-
availableLiquidityQueueId: liquidity.userPosition.availableLiquidityQueueId,
|
|
298
|
-
user: liquidity.userPosition.user,
|
|
299
|
-
chainId: String(liquidity.userPosition.chainId),
|
|
300
|
-
amount: String(liquidity.userPosition.amount)
|
|
301
|
-
},
|
|
302
|
-
queues: liquidity.queues.map((queueWithPool) => ({
|
|
303
|
-
queue: {
|
|
304
|
-
queueId: queueWithPool.queue.queueId,
|
|
305
|
-
availableLiquidityPoolId: queueWithPool.queue.availableLiquidityPoolId,
|
|
306
|
-
index: queueWithPool.queue.index
|
|
307
|
-
},
|
|
308
|
-
pool: {
|
|
309
|
-
id: queueWithPool.pool.id,
|
|
310
|
-
amount: String(queueWithPool.pool.amount)
|
|
311
|
-
}
|
|
312
|
-
})).sort(
|
|
313
|
-
(left, right) => {
|
|
314
|
-
const leftQueueId = left.queue.queueId || "";
|
|
315
|
-
const rightQueueId = right.queue.queueId || "";
|
|
316
|
-
if (leftQueueId < rightQueueId) return -1;
|
|
317
|
-
if (leftQueueId > rightQueueId) return 1;
|
|
318
|
-
const leftPoolId = left.pool.id;
|
|
319
|
-
const rightPoolId = right.pool.id;
|
|
320
|
-
if (leftPoolId < rightPoolId) return -1;
|
|
321
|
-
if (leftPoolId > rightPoolId) return 1;
|
|
322
|
-
const leftIndex = left.queue.index;
|
|
323
|
-
const rightIndex = right.queue.index;
|
|
324
|
-
if (leftIndex < rightIndex) return -1;
|
|
325
|
-
if (leftIndex > rightIndex) return 1;
|
|
326
|
-
return 0;
|
|
327
|
-
}
|
|
328
|
-
)
|
|
329
|
-
};
|
|
330
|
-
return JSON.stringify(normalized);
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
// src/core/RouterOffer.ts
|
|
334
|
-
var RouterOffer_exports = {};
|
|
335
|
-
__export(RouterOffer_exports, {
|
|
336
|
-
InvalidRouterOfferError: () => InvalidRouterOfferError,
|
|
337
|
-
OfferStatusValues: () => OfferStatusValues,
|
|
338
|
-
RouterOfferSchema: () => RouterOfferSchema,
|
|
339
|
-
consumedEvent: () => consumedEvent,
|
|
340
|
-
from: () => from,
|
|
341
|
-
fromConsumedLog: () => fromConsumedLog,
|
|
342
|
-
fromSnakeCase: () => fromSnakeCase,
|
|
343
|
-
random: () => random,
|
|
344
|
-
toSnakeCase: () => toSnakeCase
|
|
345
|
-
});
|
|
346
|
-
var OfferStatusValues = [
|
|
347
|
-
"valid",
|
|
348
|
-
"callback_not_supported",
|
|
349
|
-
"callback_error",
|
|
350
|
-
"unverified"
|
|
351
|
-
];
|
|
352
|
-
var RouterOfferSchema = (parameters) => Offer.OfferSchema(parameters).extend({
|
|
353
|
-
consumed: z.bigint({ coerce: true }).min(0n).max(maxUint256),
|
|
354
|
-
status: z.enum(OfferStatusValues),
|
|
355
|
-
metadata: z.object({
|
|
356
|
-
issue: z.string()
|
|
357
|
-
}).optional()
|
|
358
|
-
});
|
|
359
|
-
var consumedEvent = {
|
|
360
|
-
type: "event",
|
|
361
|
-
name: "Consumed",
|
|
362
|
-
inputs: [
|
|
363
|
-
{ name: "user", type: "address", indexed: true, internalType: "address" },
|
|
364
|
-
{ name: "nonce", type: "uint256", indexed: true, internalType: "uint256" },
|
|
365
|
-
{ name: "amount", type: "uint256", indexed: false, internalType: "uint256" }
|
|
366
|
-
],
|
|
367
|
-
anonymous: false
|
|
368
|
-
};
|
|
369
|
-
function from(input) {
|
|
370
|
-
try {
|
|
371
|
-
const parsedOffer = RouterOfferSchema({ omitHash: true }).parse(input);
|
|
372
|
-
const parsedHash = Offer.OfferHashSchema.parse(Offer.hash(parsedOffer));
|
|
373
|
-
return {
|
|
374
|
-
...parsedOffer,
|
|
375
|
-
hash: parsedHash
|
|
376
|
-
};
|
|
377
|
-
} catch (error) {
|
|
378
|
-
throw new InvalidRouterOfferError(error);
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
function fromSnakeCase(input) {
|
|
382
|
-
return from(Format.fromSnakeCase(input));
|
|
383
|
-
}
|
|
384
|
-
function toSnakeCase(offer) {
|
|
385
|
-
return Format.toSnakeCase(offer);
|
|
386
|
-
}
|
|
387
|
-
function random() {
|
|
388
|
-
const baseOffer = Offer.random();
|
|
389
|
-
return from({
|
|
390
|
-
...baseOffer,
|
|
391
|
-
status: "valid",
|
|
392
|
-
metadata: void 0,
|
|
393
|
-
consumed: 0n
|
|
394
|
-
});
|
|
395
|
-
}
|
|
396
|
-
function fromConsumedLog(parameters) {
|
|
397
|
-
const { blockNumber, logIndex, chainId, transactionHash, user, nonce, amount } = parameters;
|
|
398
|
-
return {
|
|
399
|
-
id: `${blockNumber.toString()}-${logIndex.toString()}-${chainId}-${transactionHash}`,
|
|
400
|
-
chainId: BigInt(chainId),
|
|
401
|
-
offering: user,
|
|
402
|
-
nonce,
|
|
403
|
-
amount
|
|
404
|
-
};
|
|
405
|
-
}
|
|
406
|
-
var InvalidRouterOfferError = class extends Errors.BaseError {
|
|
407
|
-
constructor(error) {
|
|
408
|
-
super("Invalid router offer.", { cause: error });
|
|
409
|
-
__publicField(this, "name", "RouterOffer.InvalidRouterOfferError");
|
|
410
|
-
}
|
|
411
|
-
};
|
|
412
|
-
|
|
413
|
-
// src/core/router/Client.ts
|
|
414
|
-
var Client_exports = {};
|
|
415
|
-
__export(Client_exports, {
|
|
416
|
-
HttpForbiddenError: () => HttpForbiddenError,
|
|
417
|
-
HttpGetOffersFailedError: () => HttpGetOffersFailedError,
|
|
418
|
-
HttpRateLimitError: () => HttpRateLimitError,
|
|
419
|
-
HttpUnauthorizedError: () => HttpUnauthorizedError,
|
|
420
|
-
InvalidUrlError: () => InvalidUrlError,
|
|
421
|
-
connect: () => connect,
|
|
422
|
-
get: () => get,
|
|
423
|
-
match: () => match
|
|
424
|
-
});
|
|
195
|
+
// src/api/Schema/requests.ts
|
|
425
196
|
var MAX_LIMIT = 100;
|
|
426
197
|
var DEFAULT_LIMIT = 20;
|
|
427
198
|
var MAX_LLTV = 100;
|
|
@@ -598,7 +369,7 @@ var GetOffersQueryParams = z.object({
|
|
|
598
369
|
(val) => {
|
|
599
370
|
if (!val) return true;
|
|
600
371
|
try {
|
|
601
|
-
const decoded =
|
|
372
|
+
const decoded = decode(val);
|
|
602
373
|
return decoded !== null;
|
|
603
374
|
} catch (_error) {
|
|
604
375
|
return false;
|
|
@@ -770,7 +541,7 @@ var MatchOffersQueryParams = z.object({
|
|
|
770
541
|
(val) => {
|
|
771
542
|
if (!val) return true;
|
|
772
543
|
try {
|
|
773
|
-
const decoded =
|
|
544
|
+
const decoded = decode(val);
|
|
774
545
|
return decoded !== null;
|
|
775
546
|
} catch (_error) {
|
|
776
547
|
return false;
|
|
@@ -810,7 +581,7 @@ function safeParse(action, query, error) {
|
|
|
810
581
|
});
|
|
811
582
|
}
|
|
812
583
|
|
|
813
|
-
// src/
|
|
584
|
+
// src/api/Schema/openapi.ts
|
|
814
585
|
var successResponseSchema = z.object({
|
|
815
586
|
status: z.literal("success"),
|
|
816
587
|
cursor: z.string().nullable(),
|
|
@@ -913,7 +684,7 @@ createDocument({
|
|
|
913
684
|
paths
|
|
914
685
|
});
|
|
915
686
|
|
|
916
|
-
// src/
|
|
687
|
+
// src/api/Schema/utils.ts
|
|
917
688
|
function toResponse(routerOffer) {
|
|
918
689
|
const { consumed, status, metadata, ...offer } = routerOffer;
|
|
919
690
|
return {
|
|
@@ -933,7 +704,7 @@ function fromResponse(offerResponse) {
|
|
|
933
704
|
};
|
|
934
705
|
}
|
|
935
706
|
|
|
936
|
-
// src/
|
|
707
|
+
// src/api/Client.ts
|
|
937
708
|
function connect(opts) {
|
|
938
709
|
const u = new URL(opts?.url || "https://router.morpho.dev");
|
|
939
710
|
if (u.protocol !== "http:" && u.protocol !== "https:") {
|
|
@@ -1033,135 +804,720 @@ async function get(config, parameters) {
|
|
|
1033
804
|
if (parameters.limit !== void 0) {
|
|
1034
805
|
url.searchParams.set("limit", parameters.limit.toString());
|
|
1035
806
|
}
|
|
1036
|
-
const { cursor: returnedCursor, data: offers } = await getApi(config, url);
|
|
1037
|
-
const routerOffers = offers.map(Format.fromSnakeCase).map(fromResponse);
|
|
1038
|
-
return {
|
|
1039
|
-
cursor: returnedCursor,
|
|
1040
|
-
offers: routerOffers.map(from).map(toResponse)
|
|
1041
|
-
};
|
|
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;
|
|
1042
1216
|
}
|
|
1043
|
-
async function
|
|
1044
|
-
const
|
|
1045
|
-
|
|
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
|
-
if (parameters.limit !== void 0) {
|
|
1076
|
-
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
|
+
}
|
|
1077
1249
|
}
|
|
1078
|
-
|
|
1079
|
-
const routerOffers = offers.map(Format.fromSnakeCase).map(fromResponse);
|
|
1080
|
-
return {
|
|
1081
|
-
cursor: returnedCursor,
|
|
1082
|
-
offers: routerOffers.map(from).map(toResponse)
|
|
1083
|
-
};
|
|
1250
|
+
return out;
|
|
1084
1251
|
}
|
|
1085
|
-
async function
|
|
1086
|
-
const
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
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]
|
|
1098
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
|
+
}
|
|
1099
1319
|
}
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
}
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
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
|
|
1109
1332
|
});
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
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;
|
|
1118
1348
|
}
|
|
1119
|
-
throw new HttpGetOffersFailedError(`GET request returned ${response.status}`, {
|
|
1120
|
-
details: await response.text()
|
|
1121
|
-
});
|
|
1122
1349
|
}
|
|
1123
|
-
return
|
|
1350
|
+
return maxDebt;
|
|
1124
1351
|
}
|
|
1125
|
-
var
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1352
|
+
var create = (config) => {
|
|
1353
|
+
const { client } = config;
|
|
1354
|
+
return {
|
|
1355
|
+
fetchBuyLiquidity: (parameters) => fetchBuyLiquidity({ ...parameters, client }),
|
|
1356
|
+
fetchSellLiquidity: (parameters) => fetchSellLiquidity({ ...parameters, client })
|
|
1357
|
+
};
|
|
1130
1358
|
};
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
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
|
+
}
|
|
1137
1382
|
}
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
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
|
|
1143
1393
|
});
|
|
1144
|
-
|
|
1394
|
+
for (const { collateral } of callbackData) {
|
|
1395
|
+
collateralPairs.push({ user, token: collateral });
|
|
1396
|
+
}
|
|
1145
1397
|
}
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
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
|
|
1153
1413
|
});
|
|
1154
|
-
__publicField(this, "name", "Router.HttpRateLimitError");
|
|
1155
1414
|
}
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
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
|
|
1161
1428
|
});
|
|
1162
|
-
|
|
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
|
+
);
|
|
1163
1479
|
}
|
|
1164
|
-
|
|
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
|
+
}
|
|
1165
1521
|
|
|
1166
1522
|
// src/core/Validation.ts
|
|
1167
1523
|
var Validation_exports = {};
|
|
@@ -1267,7 +1623,7 @@ function morpho() {
|
|
|
1267
1623
|
(offer, _) => {
|
|
1268
1624
|
if (!offer.buy && offer.callback.data !== "0x") {
|
|
1269
1625
|
const allowed = new Set(
|
|
1270
|
-
WhitelistedCallbackAddresses["
|
|
1626
|
+
WhitelistedCallbackAddresses["sell_erc20_callback" /* SellERC20Callback */].map(
|
|
1271
1627
|
(a) => a.toLowerCase()
|
|
1272
1628
|
)
|
|
1273
1629
|
);
|
|
@@ -1283,8 +1639,8 @@ function morpho() {
|
|
|
1283
1639
|
(offer, _) => {
|
|
1284
1640
|
if (!offer.buy && offer.callback.data !== "0x") {
|
|
1285
1641
|
try {
|
|
1286
|
-
const decoded =
|
|
1287
|
-
type: "
|
|
1642
|
+
const decoded = decode2({
|
|
1643
|
+
type: "sell_erc20_callback" /* SellERC20Callback */,
|
|
1288
1644
|
data: offer.callback.data
|
|
1289
1645
|
});
|
|
1290
1646
|
if (decoded.length === 0) {
|
|
@@ -1301,8 +1657,8 @@ function morpho() {
|
|
|
1301
1657
|
(offer, _) => {
|
|
1302
1658
|
if (!offer.buy && offer.callback.data !== "0x") {
|
|
1303
1659
|
try {
|
|
1304
|
-
const decoded =
|
|
1305
|
-
type: "
|
|
1660
|
+
const decoded = decode2({
|
|
1661
|
+
type: "sell_erc20_callback" /* SellERC20Callback */,
|
|
1306
1662
|
data: offer.callback.data
|
|
1307
1663
|
});
|
|
1308
1664
|
const offerCollaterals = new Set(
|
|
@@ -1318,10 +1674,19 @@ function morpho() {
|
|
|
1318
1674
|
}
|
|
1319
1675
|
}
|
|
1320
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
|
+
});
|
|
1321
1685
|
return [
|
|
1322
1686
|
chainId,
|
|
1323
1687
|
loanToken,
|
|
1324
1688
|
expiry,
|
|
1689
|
+
maturity,
|
|
1325
1690
|
// note: callback rules should be the last ones, since they do not mean that the offer is forever invalid
|
|
1326
1691
|
// integrators should be able to choose if they want to keep the offer or not
|
|
1327
1692
|
sellEmptyCallback,
|
|
@@ -1332,6 +1697,6 @@ function morpho() {
|
|
|
1332
1697
|
];
|
|
1333
1698
|
}
|
|
1334
1699
|
|
|
1335
|
-
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 };
|
|
1336
1701
|
//# sourceMappingURL=index.browser.mjs.map
|
|
1337
1702
|
//# sourceMappingURL=index.browser.mjs.map
|