@morpho-dev/router 0.1.3 → 0.1.4

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.
@@ -1,10 +1,10 @@
1
1
  'use strict';
2
2
 
3
3
  var mempool = require('@morpho-dev/mempool');
4
+ var jsBase64 = require('js-base64');
4
5
  var v4 = require('zod/v4');
5
6
  var zodOpenapi = require('zod-openapi');
6
7
  var viem = require('viem');
7
- var jsBase64 = require('js-base64');
8
8
  var nodeServer = require('@hono/node-server');
9
9
  var hono = require('hono');
10
10
  var async_hooks = require('async_hooks');
@@ -15,6 +15,145 @@ var __export = (target, all) => {
15
15
  __defProp(target, name, { get: all[name], enumerable: true });
16
16
  };
17
17
 
18
+ // src/Callback.ts
19
+ var Callback_exports = {};
20
+ __export(Callback_exports, {
21
+ CallbackType: () => CallbackType,
22
+ buildLiquidity: () => buildLiquidity,
23
+ getCallbackIdForOffer: () => getCallbackIdForOffer
24
+ });
25
+ var CallbackType = /* @__PURE__ */ ((CallbackType2) => {
26
+ CallbackType2["BuyWithEmptyCallback"] = "buy_with_empty_callback";
27
+ return CallbackType2;
28
+ })(CallbackType || {});
29
+ function buildLiquidity(parameters) {
30
+ const { type, user, contract, chainId, amount, index = 0, updatedAt = /* @__PURE__ */ new Date() } = parameters;
31
+ if (type !== "buy_with_empty_callback" /* BuyWithEmptyCallback */)
32
+ throw new Error(`CallbackType not implemented: ${type}`);
33
+ const amountStr = amount.toString();
34
+ const id = `${user}-${chainId.toString()}-${type}-${contract}`.toLowerCase();
35
+ return {
36
+ userPosition: {
37
+ id,
38
+ availableLiquidityQueueId: id,
39
+ user: user.toLowerCase(),
40
+ chainId,
41
+ amount: amountStr,
42
+ updatedAt
43
+ },
44
+ queues: [
45
+ {
46
+ queue: {
47
+ queueId: id,
48
+ availableLiquidityPoolId: id,
49
+ index,
50
+ updatedAt
51
+ },
52
+ pool: {
53
+ id,
54
+ amount: amountStr,
55
+ updatedAt
56
+ }
57
+ }
58
+ ]
59
+ };
60
+ }
61
+ function getCallbackIdForOffer(offer) {
62
+ if (offer.buy && offer.callback.data === "0x") {
63
+ const type = "buy_with_empty_callback" /* BuyWithEmptyCallback */;
64
+ const user = offer.offering;
65
+ const loanToken = offer.loanToken;
66
+ return `${user}-${offer.chainId.toString()}-${type}-${loanToken}`.toLowerCase();
67
+ }
68
+ return null;
69
+ }
70
+
71
+ // src/Cursor.ts
72
+ var Cursor_exports = {};
73
+ __export(Cursor_exports, {
74
+ decode: () => decode,
75
+ encode: () => encode,
76
+ validate: () => validate
77
+ });
78
+ function validate(cursor) {
79
+ if (!cursor || typeof cursor !== "object") {
80
+ throw new Error("Cursor must be an object");
81
+ }
82
+ const c = cursor;
83
+ if (!["rate", "maturity", "expiry", "amount"].includes(c.sort)) {
84
+ throw new Error(
85
+ `Invalid sort field: ${c.sort}. Must be one of: rate, maturity, expiry, amount`
86
+ );
87
+ }
88
+ if (!["asc", "desc"].includes(c.dir)) {
89
+ throw new Error(`Invalid direction: ${c.dir}. Must be one of: asc, desc`);
90
+ }
91
+ if (!/^0x[a-fA-F0-9]{64}$/.test(c.hash)) {
92
+ throw new Error(
93
+ `Invalid hash format: ${c.hash}. Must be a 64-character hex string starting with 0x`
94
+ );
95
+ }
96
+ const validations = {
97
+ rate: {
98
+ field: "rate",
99
+ type: "string",
100
+ pattern: /^\d+$/,
101
+ error: "numeric string"
102
+ },
103
+ amount: {
104
+ field: "assets",
105
+ type: "string",
106
+ pattern: /^\d+$/,
107
+ error: "numeric string"
108
+ },
109
+ maturity: {
110
+ field: "maturity",
111
+ type: "number",
112
+ validator: (val) => val > 0,
113
+ error: "positive number"
114
+ },
115
+ expiry: {
116
+ field: "expiry",
117
+ type: "number",
118
+ validator: (val) => val > 0,
119
+ error: "positive number"
120
+ }
121
+ };
122
+ const validation = validations[c.sort];
123
+ if (!validation) {
124
+ throw new Error(`Invalid sort field: ${c.sort}`);
125
+ }
126
+ const fieldValue = c[validation.field];
127
+ if (!fieldValue) {
128
+ throw new Error(`${c.sort} sort requires '${validation.field}' field to be present`);
129
+ }
130
+ if (typeof fieldValue !== validation.type) {
131
+ throw new Error(
132
+ `${c.sort} sort requires '${validation.field}' field of type ${validation.type}`
133
+ );
134
+ }
135
+ if (validation.pattern && !validation.pattern.test(fieldValue)) {
136
+ throw new Error(
137
+ `Invalid ${validation.field} format: ${fieldValue}. Must be a ${validation.error}`
138
+ );
139
+ }
140
+ if (validation.validator && !validation.validator(fieldValue)) {
141
+ throw new Error(
142
+ `Invalid ${validation.field} value: ${fieldValue}. Must be a ${validation.error}`
143
+ );
144
+ }
145
+ return true;
146
+ }
147
+ function encode(c) {
148
+ return jsBase64.Base64.encodeURL(JSON.stringify(c));
149
+ }
150
+ function decode(token) {
151
+ if (!token) return null;
152
+ const decoded = JSON.parse(jsBase64.Base64.decode(token));
153
+ validate(decoded);
154
+ return decoded;
155
+ }
156
+
18
157
  // src/core/apiSchema/index.ts
19
158
  var apiSchema_exports = {};
20
159
  __export(apiSchema_exports, {
@@ -105,140 +244,6 @@ var InvalidRouterOfferError = class extends mempool.Errors.BaseError {
105
244
  }
106
245
  };
107
246
 
108
- // src/utils/index.ts
109
- var utils_exports = {};
110
- __export(utils_exports, {
111
- batch: () => batch,
112
- decodeCursor: () => decodeCursor,
113
- encodeCursor: () => encodeCursor,
114
- poll: () => poll,
115
- retry: () => retry,
116
- validateCursor: () => validateCursor,
117
- wait: () => wait
118
- });
119
-
120
- // src/utils/batch.ts
121
- function* batch(array, batchSize) {
122
- for (let i = 0; i < array.length; i += batchSize) {
123
- yield array.slice(i, i + batchSize);
124
- }
125
- }
126
- function validateCursor(cursor) {
127
- if (!cursor || typeof cursor !== "object") {
128
- throw new Error("Cursor must be an object");
129
- }
130
- const c = cursor;
131
- if (!["rate", "maturity", "expiry", "amount"].includes(c.sort)) {
132
- throw new Error(
133
- `Invalid sort field: ${c.sort}. Must be one of: rate, maturity, expiry, amount`
134
- );
135
- }
136
- if (!["asc", "desc"].includes(c.dir)) {
137
- throw new Error(`Invalid direction: ${c.dir}. Must be one of: asc, desc`);
138
- }
139
- if (!/^0x[a-fA-F0-9]{64}$/.test(c.hash)) {
140
- throw new Error(
141
- `Invalid hash format: ${c.hash}. Must be a 64-character hex string starting with 0x`
142
- );
143
- }
144
- const validations = {
145
- rate: {
146
- field: "rate",
147
- type: "string",
148
- pattern: /^\d+$/,
149
- error: "numeric string"
150
- },
151
- amount: {
152
- field: "assets",
153
- type: "string",
154
- pattern: /^\d+$/,
155
- error: "numeric string"
156
- },
157
- maturity: {
158
- field: "maturity",
159
- type: "number",
160
- validator: (val) => val > 0,
161
- error: "positive number"
162
- },
163
- expiry: {
164
- field: "expiry",
165
- type: "number",
166
- validator: (val) => val > 0,
167
- error: "positive number"
168
- }
169
- };
170
- const validation = validations[c.sort];
171
- if (!validation) {
172
- throw new Error(`Invalid sort field: ${c.sort}`);
173
- }
174
- const fieldValue = c[validation.field];
175
- if (!fieldValue) {
176
- throw new Error(`${c.sort} sort requires '${validation.field}' field to be present`);
177
- }
178
- if (typeof fieldValue !== validation.type) {
179
- throw new Error(
180
- `${c.sort} sort requires '${validation.field}' field of type ${validation.type}`
181
- );
182
- }
183
- if (validation.pattern && !validation.pattern.test(fieldValue)) {
184
- throw new Error(
185
- `Invalid ${validation.field} format: ${fieldValue}. Must be a ${validation.error}`
186
- );
187
- }
188
- if (validation.validator && !validation.validator(fieldValue)) {
189
- throw new Error(
190
- `Invalid ${validation.field} value: ${fieldValue}. Must be a ${validation.error}`
191
- );
192
- }
193
- return true;
194
- }
195
- function encodeCursor(c) {
196
- return jsBase64.Base64.encodeURL(JSON.stringify(c));
197
- }
198
- function decodeCursor(token) {
199
- if (!token) return null;
200
- const decoded = JSON.parse(jsBase64.Base64.decode(token));
201
- validateCursor(decoded);
202
- return decoded;
203
- }
204
-
205
- // src/utils/wait.ts
206
- async function wait(time) {
207
- return new Promise((res) => setTimeout(res, time));
208
- }
209
-
210
- // src/utils/poll.ts
211
- function poll(fn, { interval }) {
212
- let active = true;
213
- const unwatch = () => active = false;
214
- const watch = async () => {
215
- await wait(interval);
216
- const poll2 = async () => {
217
- if (!active) return;
218
- await fn({ unpoll: unwatch });
219
- await wait(interval);
220
- poll2();
221
- };
222
- poll2();
223
- };
224
- watch();
225
- return unwatch;
226
- }
227
-
228
- // src/utils/retry.ts
229
- var retry = async (fn, attempts = 3, delayMs = 50) => {
230
- let lastErr;
231
- for (let i = 0; i < attempts; i++) {
232
- try {
233
- return await fn();
234
- } catch (err) {
235
- lastErr = err;
236
- if (i < attempts - 1) await new Promise((r) => setTimeout(r, delayMs));
237
- }
238
- }
239
- throw lastErr;
240
- };
241
-
242
247
  // src/core/apiSchema/requests.ts
243
248
  var MAX_LIMIT = 100;
244
249
  var DEFAULT_LIMIT = 20;
@@ -416,7 +421,7 @@ var GetOffersQueryParams = v4.z.object({
416
421
  (val) => {
417
422
  if (!val) return true;
418
423
  try {
419
- const decoded = decodeCursor(val);
424
+ const decoded = decode(val);
420
425
  return decoded !== null;
421
426
  } catch (_error) {
422
427
  return false;
@@ -583,21 +588,12 @@ var MatchOffersQueryParams = v4.z.object({
583
588
  description: "Filter by a specific offer creator address",
584
589
  example: "0x1234567890123456789012345678901234567890"
585
590
  }),
586
- // Status filtering
587
- status: v4.z.string().regex(/^[a-zA-Z_]+(,[a-zA-Z_]+)*$/, {
588
- message: "Status must be comma-separated status values"
589
- }).transform((val) => val.split(",")).refine((statuses) => statuses.every((status) => OfferStatusValues.includes(status)), {
590
- message: `Invalid status value. Must be one of: ${OfferStatusValues.join(", ")}`
591
- }).optional().meta({
592
- description: `Filter by multiple statuses (comma-separated). Valid values: ${OfferStatusValues.join(", ")}. By default, only offers with 'valid' status are returned.`,
593
- example: "valid,callback_error"
594
- }),
595
591
  // Pagination
596
592
  cursor: v4.z.string().optional().refine(
597
593
  (val) => {
598
594
  if (!val) return true;
599
595
  try {
600
- const decoded = decodeCursor(val);
596
+ const decoded = decode(val);
601
597
  return decoded !== null;
602
598
  } catch (_error) {
603
599
  return false;
@@ -1024,8 +1020,10 @@ function memory(parameters) {
1024
1020
  const consumedIds = /* @__PURE__ */ new Set();
1025
1021
  const create = async (parameters2) => {
1026
1022
  if (map.has(parameters2.offer.hash.toLowerCase())) return parameters2.offer.hash;
1023
+ const callbackId = getCallbackIdForOffer(parameters2.offer);
1027
1024
  map.set(parameters2.offer.hash.toLowerCase(), {
1028
1025
  ...parameters2.offer,
1026
+ ...callbackId ? { callbackId } : {},
1029
1027
  status: parameters2.status,
1030
1028
  metadata: parameters2.metadata
1031
1029
  });
@@ -1120,7 +1118,7 @@ function memory(parameters) {
1120
1118
  ...o,
1121
1119
  consumed: filled.get(o.chainId)?.get(o.offering.toLowerCase())?.get(o.nonce) || 0n
1122
1120
  })).filter((o) => o.consumed < o.assets);
1123
- const cursor = decodeCursor(queryCursor);
1121
+ const cursor = decode(queryCursor);
1124
1122
  if (cursor) {
1125
1123
  if (cursor.sort !== sortBy || cursor.dir !== sortOrder) {
1126
1124
  throw new Error("Cursor does not match the current sort parameters");
@@ -1218,11 +1216,35 @@ function memory(parameters) {
1218
1216
  default:
1219
1217
  base.expiry = last.expiry;
1220
1218
  }
1221
- nextCursor = encodeCursor(base);
1219
+ nextCursor = encode(base);
1222
1220
  }
1223
1221
  offers = offers.slice(0, limit);
1222
+ const data = offers.map((o) => ({
1223
+ ...mempool.Offer.from({
1224
+ offering: o.offering,
1225
+ assets: o.assets,
1226
+ rate: o.rate,
1227
+ maturity: mempool.Maturity.from(o.maturity),
1228
+ expiry: o.expiry,
1229
+ start: o.start,
1230
+ nonce: o.nonce,
1231
+ buy: o.buy,
1232
+ chainId: o.chainId,
1233
+ loanToken: o.loanToken,
1234
+ collaterals: o.collaterals.map((c) => ({ asset: c.asset, oracle: c.oracle, lltv: c.lltv })).sort((a, b) => a.asset.toLowerCase().localeCompare(b.asset.toLowerCase())),
1235
+ callback: {
1236
+ address: o.callback.address,
1237
+ data: o.callback.data,
1238
+ gasLimit: o.callback.gasLimit
1239
+ },
1240
+ ...o.signature !== null && o.signature !== void 0 ? { signature: o.signature } : {}
1241
+ }),
1242
+ consumed: o.consumed,
1243
+ status: o.status,
1244
+ ...o.metadata ? { metadata: o.metadata } : {}
1245
+ }));
1224
1246
  return {
1225
- offers,
1247
+ offers: data,
1226
1248
  nextCursor
1227
1249
  };
1228
1250
  },
@@ -1237,7 +1259,6 @@ function memory(parameters) {
1237
1259
  maxMaturity,
1238
1260
  loanToken,
1239
1261
  creator,
1240
- status,
1241
1262
  cursor: queryCursor,
1242
1263
  limit = 20
1243
1264
  } = params;
@@ -1248,7 +1269,7 @@ function memory(parameters) {
1248
1269
  ...o,
1249
1270
  consumed: filled.get(o.chainId)?.get(o.offering.toLowerCase())?.get(o.nonce) || 0n
1250
1271
  })).filter((o) => o.consumed < o.assets);
1251
- const cursor = decodeCursor(queryCursor);
1272
+ const cursor = decode(queryCursor);
1252
1273
  if (cursor) {
1253
1274
  if (cursor.sort !== "rate" || cursor.dir !== sortOrder) {
1254
1275
  throw new Error("Cursor does not match the current sort parameters");
@@ -1283,7 +1304,7 @@ function memory(parameters) {
1283
1304
  maxMaturity && (offers = offers.filter((o) => o.maturity <= maxMaturity));
1284
1305
  loanToken && (offers = offers.filter((o) => o.loanToken.toLowerCase() === loanToken.toLowerCase()));
1285
1306
  creator && (offers = offers.filter((o) => o.offering.toLowerCase() === creator.toLowerCase()));
1286
- status && (offers = offers.filter((o) => status.includes(o.status)));
1307
+ offers = offers.filter((o) => ["valid"].includes(o.status));
1287
1308
  const byGroup = /* @__PURE__ */ new Map();
1288
1309
  for (const offer of offers) {
1289
1310
  const groupKey = `${offer.chainId}-${offer.offering.toLowerCase()}-${offer.nonce}-${offer.buy}`;
@@ -1318,7 +1339,7 @@ function memory(parameters) {
1318
1339
  let nextCursor = null;
1319
1340
  if (offers.length > limit) {
1320
1341
  const last = offers[limit - 1];
1321
- nextCursor = encodeCursor({
1342
+ nextCursor = encode({
1322
1343
  sort: "rate",
1323
1344
  dir: sortOrder,
1324
1345
  hash: last.hash,
@@ -1326,8 +1347,32 @@ function memory(parameters) {
1326
1347
  });
1327
1348
  }
1328
1349
  offers = offers.slice(0, limit);
1350
+ const data = offers.map((o) => ({
1351
+ ...mempool.Offer.from({
1352
+ offering: o.offering,
1353
+ assets: o.assets,
1354
+ rate: o.rate,
1355
+ maturity: mempool.Maturity.from(o.maturity),
1356
+ expiry: o.expiry,
1357
+ start: o.start,
1358
+ nonce: o.nonce,
1359
+ buy: o.buy,
1360
+ chainId: o.chainId,
1361
+ loanToken: o.loanToken,
1362
+ collaterals: o.collaterals.map((c) => ({ asset: c.asset, oracle: c.oracle, lltv: c.lltv })).sort((a, b) => a.asset.toLowerCase().localeCompare(b.asset.toLowerCase())),
1363
+ callback: {
1364
+ address: o.callback.address,
1365
+ data: o.callback.data,
1366
+ gasLimit: o.callback.gasLimit
1367
+ },
1368
+ ...o.signature !== null && o.signature !== void 0 ? { signature: o.signature } : {}
1369
+ }),
1370
+ consumed: o.consumed,
1371
+ status: o.status,
1372
+ ...o.metadata ? { metadata: o.metadata } : {}
1373
+ }));
1329
1374
  return {
1330
- offers,
1375
+ offers: data,
1331
1376
  nextCursor
1332
1377
  };
1333
1378
  },
@@ -1434,7 +1479,6 @@ async function serve(parameters) {
1434
1479
  maxMaturity: params.max_maturity,
1435
1480
  loanToken: params.loan_token,
1436
1481
  creator: params.creator,
1437
- status: params.status,
1438
1482
  cursor: params.cursor,
1439
1483
  limit: params.limit
1440
1484
  });
@@ -1550,6 +1594,140 @@ function handleAPIError(error2, c) {
1550
1594
  });
1551
1595
  }
1552
1596
 
1597
+ // src/Liquidity.ts
1598
+ var Liquidity_exports = {};
1599
+ __export(Liquidity_exports, {
1600
+ fetch: () => fetch2,
1601
+ fetchBalancesAndAllowances: () => fetchBalancesAndAllowances,
1602
+ serialize: () => serialize
1603
+ });
1604
+ async function fetchBalancesAndAllowances(parameters) {
1605
+ const { client, spender, pairs, options } = parameters;
1606
+ if (pairs.length === 0) return /* @__PURE__ */ new Map();
1607
+ const batchSize = Math.max(1, options?.batchSize ?? 5e3);
1608
+ const retryAttempts = Math.max(1, options?.retryAttempts ?? 3);
1609
+ const retryDelayMs = Math.max(0, options?.retryDelayMs ?? 50);
1610
+ const blockNumber = options?.blockNumber ? BigInt(options.blockNumber) : void 0;
1611
+ const out = /* @__PURE__ */ new Map();
1612
+ for (const pairsBatch of mempool.Utils.batch(pairs, batchSize)) {
1613
+ const balanceContracts = [];
1614
+ const allowanceContracts = [];
1615
+ for (const { user, token } of pairsBatch) {
1616
+ balanceContracts.push({
1617
+ address: token,
1618
+ abi: viem.erc20Abi,
1619
+ functionName: "balanceOf",
1620
+ args: [user]
1621
+ });
1622
+ allowanceContracts.push({
1623
+ address: token,
1624
+ abi: viem.erc20Abi,
1625
+ functionName: "allowance",
1626
+ args: [user, spender]
1627
+ });
1628
+ }
1629
+ const [balances, allowances] = await Promise.all([
1630
+ mempool.Utils.retry(
1631
+ () => client.multicall({
1632
+ allowFailure: false,
1633
+ contracts: balanceContracts,
1634
+ ...blockNumber ? { blockNumber } : {}
1635
+ }),
1636
+ retryAttempts,
1637
+ retryDelayMs
1638
+ ),
1639
+ mempool.Utils.retry(
1640
+ () => client.multicall({
1641
+ allowFailure: false,
1642
+ contracts: allowanceContracts,
1643
+ ...blockNumber ? { blockNumber } : {}
1644
+ }),
1645
+ retryAttempts,
1646
+ retryDelayMs
1647
+ )
1648
+ ]);
1649
+ for (let i = 0; i < pairsBatch.length; i++) {
1650
+ const { user, token } = pairsBatch[i];
1651
+ const balance = balances[i];
1652
+ const allowance = allowances[i];
1653
+ let perUser = out.get(user);
1654
+ if (!perUser) {
1655
+ perUser = /* @__PURE__ */ new Map();
1656
+ out.set(user, perUser);
1657
+ }
1658
+ perUser.set(token, { balance, allowance });
1659
+ }
1660
+ }
1661
+ return out;
1662
+ }
1663
+ async function fetch2(parameters) {
1664
+ const { client, chainId, spender, type, pairs, options } = parameters;
1665
+ if (type !== "buy_with_empty_callback" /* BuyWithEmptyCallback */)
1666
+ throw new Error(`CallbackType not implemented: ${type}`);
1667
+ const map = await fetchBalancesAndAllowances({
1668
+ client,
1669
+ spender,
1670
+ pairs: pairs.map(({ user, contract }) => ({ user, token: contract })),
1671
+ options
1672
+ });
1673
+ const out = [];
1674
+ for (const [user, perContract] of map) {
1675
+ for (const [contract, { balance, allowance }] of perContract) {
1676
+ const amount = balance < allowance ? balance : allowance;
1677
+ out.push(
1678
+ buildLiquidity({
1679
+ type,
1680
+ user,
1681
+ contract,
1682
+ chainId,
1683
+ amount: amount.toString(),
1684
+ index: 0
1685
+ })
1686
+ );
1687
+ }
1688
+ }
1689
+ return out;
1690
+ }
1691
+ function serialize(liquidity) {
1692
+ const normalized = {
1693
+ userPosition: {
1694
+ id: liquidity.userPosition.id,
1695
+ availableLiquidityQueueId: liquidity.userPosition.availableLiquidityQueueId,
1696
+ user: liquidity.userPosition.user,
1697
+ chainId: String(liquidity.userPosition.chainId),
1698
+ amount: String(liquidity.userPosition.amount)
1699
+ },
1700
+ queues: liquidity.queues.map((queueWithPool) => ({
1701
+ queue: {
1702
+ queueId: queueWithPool.queue.queueId,
1703
+ availableLiquidityPoolId: queueWithPool.queue.availableLiquidityPoolId,
1704
+ index: queueWithPool.queue.index
1705
+ },
1706
+ pool: {
1707
+ id: queueWithPool.pool.id,
1708
+ amount: String(queueWithPool.pool.amount)
1709
+ }
1710
+ })).sort(
1711
+ (left, right) => {
1712
+ const leftQueueId = left.queue.queueId || "";
1713
+ const rightQueueId = right.queue.queueId || "";
1714
+ if (leftQueueId < rightQueueId) return -1;
1715
+ if (leftQueueId > rightQueueId) return 1;
1716
+ const leftPoolId = left.pool.id;
1717
+ const rightPoolId = right.pool.id;
1718
+ if (leftPoolId < rightPoolId) return -1;
1719
+ if (leftPoolId > rightPoolId) return 1;
1720
+ const leftIndex = left.queue.index;
1721
+ const rightIndex = right.queue.index;
1722
+ if (leftIndex < rightIndex) return -1;
1723
+ if (leftIndex > rightIndex) return 1;
1724
+ return 0;
1725
+ }
1726
+ )
1727
+ };
1728
+ return JSON.stringify(normalized);
1729
+ }
1730
+
1553
1731
  // src/Logger.ts
1554
1732
  var Logger_exports = {};
1555
1733
  __export(Logger_exports, {
@@ -1672,14 +1850,14 @@ async function run(parameters) {
1672
1850
  // src/ValidationRule.ts
1673
1851
  var ValidationRule_exports = {};
1674
1852
  __export(ValidationRule_exports, {
1675
- batch: () => batch2,
1853
+ batch: () => batch,
1676
1854
  morpho: () => morpho,
1677
1855
  single: () => single
1678
1856
  });
1679
1857
  function single(name, run2) {
1680
1858
  return { kind: "single", name, run: run2 };
1681
1859
  }
1682
- function batch2(name, run2) {
1860
+ function batch(name, run2) {
1683
1861
  return { kind: "batch", name, run: run2 };
1684
1862
  }
1685
1863
  function morpho() {
@@ -1721,11 +1899,13 @@ function morpho() {
1721
1899
  }
1722
1900
 
1723
1901
  exports.ApiSchema = apiSchema_exports;
1902
+ exports.Callback = Callback_exports;
1903
+ exports.Cursor = Cursor_exports;
1904
+ exports.Liquidity = Liquidity_exports;
1724
1905
  exports.Logger = Logger_exports;
1725
1906
  exports.OfferStore = OfferStore_exports;
1726
1907
  exports.Router = router_exports;
1727
1908
  exports.RouterOffer = RouterOffer_exports;
1728
- exports.Utils = utils_exports;
1729
1909
  exports.Validation = Validation_exports;
1730
1910
  exports.ValidationRule = ValidationRule_exports;
1731
1911
  Object.keys(mempool).forEach(function (k) {