@morpho-dev/router 0.1.6 → 0.1.8

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.
@@ -14,7 +14,7 @@ var __export = (target, all) => {
14
14
  };
15
15
  var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value);
16
16
 
17
- // src/Callback.ts
17
+ // src/core/Callback.ts
18
18
  var Callback_exports = {};
19
19
  __export(Callback_exports, {
20
20
  CallbackType: () => CallbackType,
@@ -67,7 +67,7 @@ function getCallbackIdForOffer(offer) {
67
67
  return null;
68
68
  }
69
69
 
70
- // src/Cursor.ts
70
+ // src/core/Cursor.ts
71
71
  var Cursor_exports = {};
72
72
  __export(Cursor_exports, {
73
73
  decode: () => decode,
@@ -153,20 +153,141 @@ function decode(token) {
153
153
  return decoded;
154
154
  }
155
155
 
156
- // src/core/router/Client.ts
157
- var Client_exports = {};
158
- __export(Client_exports, {
159
- HttpForbiddenError: () => HttpForbiddenError,
160
- HttpGetOffersFailedError: () => HttpGetOffersFailedError,
161
- HttpRateLimitError: () => HttpRateLimitError,
162
- HttpUnauthorizedError: () => HttpUnauthorizedError,
163
- InvalidUrlError: () => InvalidUrlError,
164
- connect: () => connect,
165
- get: () => get,
166
- match: () => match
156
+ // src/core/Liquidity.ts
157
+ var Liquidity_exports = {};
158
+ __export(Liquidity_exports, {
159
+ fetch: () => fetch2,
160
+ fetchBalancesAndAllowances: () => fetchBalancesAndAllowances,
161
+ serialize: () => serialize
167
162
  });
163
+ async function fetchBalancesAndAllowances(parameters) {
164
+ const { client, spender, pairs, options } = parameters;
165
+ if (pairs.length === 0) return /* @__PURE__ */ new Map();
166
+ const batchSize = Math.max(1, options?.batchSize ?? 5e3);
167
+ const retryAttempts = Math.max(1, options?.retryAttempts ?? 3);
168
+ const retryDelayMs = Math.max(0, options?.retryDelayMs ?? 50);
169
+ const blockNumber = options?.blockNumber ? BigInt(options.blockNumber) : void 0;
170
+ const out = /* @__PURE__ */ new Map();
171
+ for (const pairsBatch of mempool.Utils.batch(pairs, batchSize)) {
172
+ const balanceContracts = [];
173
+ const allowanceContracts = [];
174
+ for (const { user, token } of pairsBatch) {
175
+ balanceContracts.push({
176
+ address: token,
177
+ abi: viem.erc20Abi,
178
+ functionName: "balanceOf",
179
+ args: [user]
180
+ });
181
+ allowanceContracts.push({
182
+ address: token,
183
+ abi: viem.erc20Abi,
184
+ functionName: "allowance",
185
+ args: [user, spender]
186
+ });
187
+ }
188
+ const [balances, allowances] = await Promise.all([
189
+ mempool.Utils.retry(
190
+ () => client.multicall({
191
+ allowFailure: false,
192
+ contracts: balanceContracts,
193
+ ...blockNumber ? { blockNumber } : {}
194
+ }),
195
+ retryAttempts,
196
+ retryDelayMs
197
+ ),
198
+ mempool.Utils.retry(
199
+ () => client.multicall({
200
+ allowFailure: false,
201
+ contracts: allowanceContracts,
202
+ ...blockNumber ? { blockNumber } : {}
203
+ }),
204
+ retryAttempts,
205
+ retryDelayMs
206
+ )
207
+ ]);
208
+ for (let i = 0; i < pairsBatch.length; i++) {
209
+ const { user, token } = pairsBatch[i];
210
+ const balance = balances[i];
211
+ const allowance = allowances[i];
212
+ let perUser = out.get(user);
213
+ if (!perUser) {
214
+ perUser = /* @__PURE__ */ new Map();
215
+ out.set(user, perUser);
216
+ }
217
+ perUser.set(token, { balance, allowance });
218
+ }
219
+ }
220
+ return out;
221
+ }
222
+ async function fetch2(parameters) {
223
+ const { client, chainId, spender, type, pairs, options } = parameters;
224
+ if (type !== "buy_with_empty_callback" /* BuyWithEmptyCallback */)
225
+ throw new Error(`CallbackType not implemented: ${type}`);
226
+ const map = await fetchBalancesAndAllowances({
227
+ client,
228
+ spender,
229
+ pairs: pairs.map(({ user, contract }) => ({ user, token: contract })),
230
+ options
231
+ });
232
+ const out = [];
233
+ for (const [user, perContract] of map) {
234
+ for (const [contract, { balance, allowance }] of perContract) {
235
+ const amount = balance < allowance ? balance : allowance;
236
+ out.push(
237
+ buildLiquidity({
238
+ type,
239
+ user,
240
+ contract,
241
+ chainId,
242
+ amount: amount.toString(),
243
+ index: 0
244
+ })
245
+ );
246
+ }
247
+ }
248
+ return out;
249
+ }
250
+ function serialize(liquidity) {
251
+ const normalized = {
252
+ userPosition: {
253
+ id: liquidity.userPosition.id,
254
+ availableLiquidityQueueId: liquidity.userPosition.availableLiquidityQueueId,
255
+ user: liquidity.userPosition.user,
256
+ chainId: String(liquidity.userPosition.chainId),
257
+ amount: String(liquidity.userPosition.amount)
258
+ },
259
+ queues: liquidity.queues.map((queueWithPool) => ({
260
+ queue: {
261
+ queueId: queueWithPool.queue.queueId,
262
+ availableLiquidityPoolId: queueWithPool.queue.availableLiquidityPoolId,
263
+ index: queueWithPool.queue.index
264
+ },
265
+ pool: {
266
+ id: queueWithPool.pool.id,
267
+ amount: String(queueWithPool.pool.amount)
268
+ }
269
+ })).sort(
270
+ (left, right) => {
271
+ const leftQueueId = left.queue.queueId || "";
272
+ const rightQueueId = right.queue.queueId || "";
273
+ if (leftQueueId < rightQueueId) return -1;
274
+ if (leftQueueId > rightQueueId) return 1;
275
+ const leftPoolId = left.pool.id;
276
+ const rightPoolId = right.pool.id;
277
+ if (leftPoolId < rightPoolId) return -1;
278
+ if (leftPoolId > rightPoolId) return 1;
279
+ const leftIndex = left.queue.index;
280
+ const rightIndex = right.queue.index;
281
+ if (leftIndex < rightIndex) return -1;
282
+ if (leftIndex > rightIndex) return 1;
283
+ return 0;
284
+ }
285
+ )
286
+ };
287
+ return JSON.stringify(normalized);
288
+ }
168
289
 
169
- // src/RouterOffer.ts
290
+ // src/core/RouterOffer.ts
170
291
  var RouterOffer_exports = {};
171
292
  __export(RouterOffer_exports, {
172
293
  InvalidRouterOfferError: () => InvalidRouterOfferError,
@@ -246,7 +367,18 @@ var InvalidRouterOfferError = class extends mempool.Errors.BaseError {
246
367
  }
247
368
  };
248
369
 
249
- // src/core/apiSchema/requests.ts
370
+ // src/core/router/Client.ts
371
+ var Client_exports = {};
372
+ __export(Client_exports, {
373
+ HttpForbiddenError: () => HttpForbiddenError,
374
+ HttpGetOffersFailedError: () => HttpGetOffersFailedError,
375
+ HttpRateLimitError: () => HttpRateLimitError,
376
+ HttpUnauthorizedError: () => HttpUnauthorizedError,
377
+ InvalidUrlError: () => InvalidUrlError,
378
+ connect: () => connect,
379
+ get: () => get,
380
+ match: () => match
381
+ });
250
382
  var MAX_LIMIT = 100;
251
383
  var DEFAULT_LIMIT = 20;
252
384
  var MAX_LLTV = 100;
@@ -988,550 +1120,7 @@ var HttpGetOffersFailedError = class extends mempool.Errors.BaseError {
988
1120
  }
989
1121
  };
990
1122
 
991
- // src/Liquidity.ts
992
- var Liquidity_exports = {};
993
- __export(Liquidity_exports, {
994
- fetch: () => fetch2,
995
- fetchBalancesAndAllowances: () => fetchBalancesAndAllowances,
996
- serialize: () => serialize
997
- });
998
- async function fetchBalancesAndAllowances(parameters) {
999
- const { client, spender, pairs, options } = parameters;
1000
- if (pairs.length === 0) return /* @__PURE__ */ new Map();
1001
- const batchSize = Math.max(1, options?.batchSize ?? 5e3);
1002
- const retryAttempts = Math.max(1, options?.retryAttempts ?? 3);
1003
- const retryDelayMs = Math.max(0, options?.retryDelayMs ?? 50);
1004
- const blockNumber = options?.blockNumber ? BigInt(options.blockNumber) : void 0;
1005
- const out = /* @__PURE__ */ new Map();
1006
- for (const pairsBatch of mempool.Utils.batch(pairs, batchSize)) {
1007
- const balanceContracts = [];
1008
- const allowanceContracts = [];
1009
- for (const { user, token } of pairsBatch) {
1010
- balanceContracts.push({
1011
- address: token,
1012
- abi: viem.erc20Abi,
1013
- functionName: "balanceOf",
1014
- args: [user]
1015
- });
1016
- allowanceContracts.push({
1017
- address: token,
1018
- abi: viem.erc20Abi,
1019
- functionName: "allowance",
1020
- args: [user, spender]
1021
- });
1022
- }
1023
- const [balances, allowances] = await Promise.all([
1024
- mempool.Utils.retry(
1025
- () => client.multicall({
1026
- allowFailure: false,
1027
- contracts: balanceContracts,
1028
- ...blockNumber ? { blockNumber } : {}
1029
- }),
1030
- retryAttempts,
1031
- retryDelayMs
1032
- ),
1033
- mempool.Utils.retry(
1034
- () => client.multicall({
1035
- allowFailure: false,
1036
- contracts: allowanceContracts,
1037
- ...blockNumber ? { blockNumber } : {}
1038
- }),
1039
- retryAttempts,
1040
- retryDelayMs
1041
- )
1042
- ]);
1043
- for (let i = 0; i < pairsBatch.length; i++) {
1044
- const { user, token } = pairsBatch[i];
1045
- const balance = balances[i];
1046
- const allowance = allowances[i];
1047
- let perUser = out.get(user);
1048
- if (!perUser) {
1049
- perUser = /* @__PURE__ */ new Map();
1050
- out.set(user, perUser);
1051
- }
1052
- perUser.set(token, { balance, allowance });
1053
- }
1054
- }
1055
- return out;
1056
- }
1057
- async function fetch2(parameters) {
1058
- const { client, chainId, spender, type, pairs, options } = parameters;
1059
- if (type !== "buy_with_empty_callback" /* BuyWithEmptyCallback */)
1060
- throw new Error(`CallbackType not implemented: ${type}`);
1061
- const map = await fetchBalancesAndAllowances({
1062
- client,
1063
- spender,
1064
- pairs: pairs.map(({ user, contract }) => ({ user, token: contract })),
1065
- options
1066
- });
1067
- const out = [];
1068
- for (const [user, perContract] of map) {
1069
- for (const [contract, { balance, allowance }] of perContract) {
1070
- const amount = balance < allowance ? balance : allowance;
1071
- out.push(
1072
- buildLiquidity({
1073
- type,
1074
- user,
1075
- contract,
1076
- chainId,
1077
- amount: amount.toString(),
1078
- index: 0
1079
- })
1080
- );
1081
- }
1082
- }
1083
- return out;
1084
- }
1085
- function serialize(liquidity) {
1086
- const normalized = {
1087
- userPosition: {
1088
- id: liquidity.userPosition.id,
1089
- availableLiquidityQueueId: liquidity.userPosition.availableLiquidityQueueId,
1090
- user: liquidity.userPosition.user,
1091
- chainId: String(liquidity.userPosition.chainId),
1092
- amount: String(liquidity.userPosition.amount)
1093
- },
1094
- queues: liquidity.queues.map((queueWithPool) => ({
1095
- queue: {
1096
- queueId: queueWithPool.queue.queueId,
1097
- availableLiquidityPoolId: queueWithPool.queue.availableLiquidityPoolId,
1098
- index: queueWithPool.queue.index
1099
- },
1100
- pool: {
1101
- id: queueWithPool.pool.id,
1102
- amount: String(queueWithPool.pool.amount)
1103
- }
1104
- })).sort(
1105
- (left, right) => {
1106
- const leftQueueId = left.queue.queueId || "";
1107
- const rightQueueId = right.queue.queueId || "";
1108
- if (leftQueueId < rightQueueId) return -1;
1109
- if (leftQueueId > rightQueueId) return 1;
1110
- const leftPoolId = left.pool.id;
1111
- const rightPoolId = right.pool.id;
1112
- if (leftPoolId < rightPoolId) return -1;
1113
- if (leftPoolId > rightPoolId) return 1;
1114
- const leftIndex = left.queue.index;
1115
- const rightIndex = right.queue.index;
1116
- if (leftIndex < rightIndex) return -1;
1117
- if (leftIndex > rightIndex) return 1;
1118
- return 0;
1119
- }
1120
- )
1121
- };
1122
- return JSON.stringify(normalized);
1123
- }
1124
-
1125
- // src/OfferStore/index.ts
1126
- var OfferStore_exports = {};
1127
- __export(OfferStore_exports, {
1128
- memory: () => memory
1129
- });
1130
- function memory(parameters) {
1131
- const map = parameters.offers;
1132
- const filled = parameters.filled;
1133
- const consumedIds = /* @__PURE__ */ new Set();
1134
- const create = async (parameters2) => {
1135
- if (map.has(parameters2.offer.hash.toLowerCase())) return parameters2.offer.hash;
1136
- const callbackId = getCallbackIdForOffer(parameters2.offer);
1137
- map.set(parameters2.offer.hash.toLowerCase(), {
1138
- ...parameters2.offer,
1139
- ...callbackId ? { callbackId } : {},
1140
- status: parameters2.status,
1141
- metadata: parameters2.metadata
1142
- });
1143
- const chainId = parameters2.offer.chainId;
1144
- const address = parameters2.offer.offering.toLowerCase();
1145
- const nonce = parameters2.offer.nonce;
1146
- const filledForChain = filled.get(chainId) || /* @__PURE__ */ new Map();
1147
- const filledForOffering = filledForChain.get(address) || /* @__PURE__ */ new Map();
1148
- if (!filledForOffering.has(nonce)) filledForOffering.set(nonce, 0n);
1149
- filledForChain.set(address, filledForOffering);
1150
- filled.set(chainId, filledForChain);
1151
- return Promise.resolve(parameters2.offer.hash);
1152
- };
1153
- const sort = (sortBy, sortOrder, a, b) => {
1154
- sortBy = sortBy || "expiry";
1155
- sortOrder = sortOrder || "desc";
1156
- const sortKey = sortBy === "amount" ? "assets" : sortBy;
1157
- if (a[sortKey] === b[sortKey]) {
1158
- if (a.hash === b.hash) return 0;
1159
- return sortOrder === "asc" ? a.hash > b.hash ? 1 : -1 : b.hash > a.hash ? 1 : -1;
1160
- }
1161
- switch (sortBy) {
1162
- case "rate":
1163
- if (a.rate === b.rate) {
1164
- if (a.hash === b.hash) return 0;
1165
- return sortOrder === "asc" ? a.hash > b.hash ? 1 : -1 : a.hash > b.hash ? -1 : 1;
1166
- }
1167
- return sortOrder === "asc" ? a.rate > b.rate ? 1 : -1 : b.rate > a.rate ? 1 : -1;
1168
- case "maturity":
1169
- if (a.maturity === b.maturity) {
1170
- if (a.hash === b.hash) return 0;
1171
- return sortOrder === "asc" ? a.hash > b.hash ? 1 : -1 : a.hash > b.hash ? -1 : 1;
1172
- }
1173
- return sortOrder === "asc" ? a.maturity > b.maturity ? 1 : -1 : b.maturity > a.maturity ? 1 : -1;
1174
- case "expiry":
1175
- if (a.expiry === b.expiry) {
1176
- if (a.hash === b.hash) return 0;
1177
- return sortOrder === "asc" ? a.hash > b.hash ? 1 : -1 : a.hash > b.hash ? -1 : 1;
1178
- }
1179
- return sortOrder === "asc" ? a.expiry > b.expiry ? 1 : -1 : b.expiry > a.expiry ? 1 : -1;
1180
- case "amount":
1181
- if (a.assets === b.assets) {
1182
- if (a.hash === b.hash) return 0;
1183
- return sortOrder === "asc" ? a.hash > b.hash ? 1 : -1 : a.hash > b.hash ? -1 : 1;
1184
- }
1185
- return sortOrder === "asc" ? a.assets > b.assets ? 1 : -1 : b.assets > a.assets ? 1 : -1;
1186
- default:
1187
- if (a.expiry === b.expiry) {
1188
- if (a.hash === b.hash) return 0;
1189
- return sortOrder === "asc" ? a.hash > b.hash ? 1 : -1 : a.hash > b.hash ? -1 : 1;
1190
- }
1191
- return sortOrder === "asc" ? a.expiry > b.expiry ? 1 : -1 : b.expiry > a.expiry ? 1 : -1;
1192
- }
1193
- };
1194
- return {
1195
- create,
1196
- createMany: async (parameters2) => {
1197
- return Promise.all(
1198
- parameters2.map((p) => create({ offer: p.offer, status: p.status, metadata: p.metadata }))
1199
- );
1200
- },
1201
- getAll: async (params) => {
1202
- const { query } = params || {};
1203
- let {
1204
- creators,
1205
- side,
1206
- chains,
1207
- loanTokens,
1208
- status = ["valid"],
1209
- callbackAddresses,
1210
- minAmount,
1211
- maxAmount,
1212
- minRate,
1213
- maxRate,
1214
- minMaturity,
1215
- maxMaturity,
1216
- minExpiry,
1217
- maxExpiry,
1218
- collateralAssets,
1219
- collateralOracles,
1220
- collateralTuple,
1221
- minLltv,
1222
- maxLltv,
1223
- sortBy = "expiry",
1224
- sortOrder = "desc",
1225
- cursor: queryCursor,
1226
- limit = 20
1227
- } = query || {};
1228
- const now = mempool.Time.now();
1229
- const buy = side === "buy";
1230
- let offers = Array.from(map.values()).map((o) => ({
1231
- ...o,
1232
- consumed: filled.get(o.chainId)?.get(o.offering.toLowerCase())?.get(o.nonce) || 0n
1233
- })).filter((o) => o.consumed < o.assets);
1234
- const cursor = decode(queryCursor);
1235
- if (cursor) {
1236
- if (cursor.sort !== sortBy || cursor.dir !== sortOrder) {
1237
- throw new Error("Cursor does not match the current sort parameters");
1238
- }
1239
- switch (cursor.sort) {
1240
- case "rate":
1241
- offers = offers.filter(
1242
- (o) => (sortOrder === "asc" ? o.rate >= BigInt(cursor.rate) : o.rate <= BigInt(cursor.rate)) && (o.rate !== BigInt(cursor.rate) || (sortOrder === "asc" ? o.hash > cursor.hash : o.hash < cursor.hash))
1243
- );
1244
- break;
1245
- case "maturity":
1246
- offers = offers.filter(
1247
- (o) => (sortOrder === "asc" ? o.maturity >= BigInt(cursor.maturity) : o.maturity <= BigInt(cursor.maturity)) && (o.maturity !== mempool.Maturity.from(cursor.maturity) || (sortOrder === "asc" ? o.hash > cursor.hash : o.hash < cursor.hash))
1248
- );
1249
- break;
1250
- case "expiry":
1251
- offers = offers.filter(
1252
- (o) => (sortOrder === "asc" ? o.expiry >= cursor.expiry : o.expiry <= cursor.expiry) && (o.expiry !== cursor.expiry || (sortOrder === "asc" ? o.hash > cursor.hash : o.hash < cursor.hash))
1253
- );
1254
- break;
1255
- case "amount":
1256
- offers = offers.filter(
1257
- (o) => (sortOrder === "asc" ? o.assets >= BigInt(cursor.assets) : o.assets <= BigInt(cursor.assets)) && (o.assets !== BigInt(cursor.assets) || (sortOrder === "asc" ? o.hash > cursor.hash : o.hash < cursor.hash))
1258
- );
1259
- break;
1260
- default:
1261
- throw new Error("Invalid sort parameter");
1262
- }
1263
- offers = offers.filter((o) => o.hash !== cursor.hash);
1264
- }
1265
- creators && (creators = creators.map((c) => c.toLowerCase()));
1266
- loanTokens && (loanTokens = loanTokens.map((lt) => lt.toLowerCase()));
1267
- callbackAddresses && (callbackAddresses = callbackAddresses.map((ca) => ca.toLowerCase()));
1268
- collateralAssets && (collateralAssets = collateralAssets.map((ca) => ca.toLowerCase()));
1269
- collateralOracles && (collateralOracles = collateralOracles.map((co) => co.toLowerCase()));
1270
- collateralTuple && (collateralTuple = collateralTuple.map((ct) => ({
1271
- asset: ct.asset.toLowerCase(),
1272
- oracle: ct.oracle?.toLowerCase()
1273
- })));
1274
- offers = offers.filter((o) => o.expiry >= now);
1275
- creators && (offers = offers.filter((o) => creators.includes(o.offering.toLowerCase())));
1276
- side && (offers = offers.filter((o) => o.buy === buy));
1277
- chains && (offers = offers.filter((o) => chains.includes(Number(o.chainId))));
1278
- loanTokens && (offers = offers.filter((o) => loanTokens.includes(o.loanToken.toLowerCase())));
1279
- status && (offers = offers.filter((o) => status.includes(o.status)));
1280
- callbackAddresses && (offers = offers.filter(
1281
- (o) => callbackAddresses.includes(o.callback.address.toLowerCase())
1282
- ));
1283
- minAmount && (offers = offers.filter((o) => o.assets >= minAmount));
1284
- maxAmount && (offers = offers.filter((o) => o.assets <= maxAmount));
1285
- minRate && (offers = offers.filter((o) => o.rate >= minRate));
1286
- maxRate && (offers = offers.filter((o) => o.rate <= maxRate));
1287
- minMaturity && (offers = offers.filter((o) => o.maturity >= minMaturity));
1288
- maxMaturity && (offers = offers.filter((o) => o.maturity <= maxMaturity));
1289
- minExpiry && (offers = offers.filter((o) => o.expiry >= minExpiry));
1290
- maxExpiry && (offers = offers.filter((o) => o.expiry <= maxExpiry));
1291
- collateralAssets && (offers = offers.filter(
1292
- (o) => o.collaterals.some((c) => collateralAssets.includes(c.asset.toLowerCase()))
1293
- ));
1294
- collateralOracles && (offers = offers.filter(
1295
- (o) => o.collaterals.some((c) => collateralOracles.includes(c.oracle.toLowerCase()))
1296
- ));
1297
- collateralTuple && (offers = offers.filter(
1298
- (o) => o.collaterals.some(
1299
- (c) => collateralTuple.some(
1300
- (ct) => c.asset.toLowerCase() === ct.asset.toLowerCase() && (ct.oracle ? c.oracle.toLowerCase() === ct.oracle.toLowerCase() : true) && (ct.lltv ? c.lltv === mempool.LLTV.from(BigInt(ct.lltv)) : true)
1301
- )
1302
- )
1303
- ));
1304
- minLltv && (offers = offers.filter(
1305
- (o) => o.collaterals.every((c) => c.lltv >= viem.parseUnits(minLltv.toString(), 16))
1306
- ));
1307
- maxLltv && (offers = offers.filter(
1308
- (o) => o.collaterals.every((c) => c.lltv <= viem.parseUnits(maxLltv.toString(), 16))
1309
- ));
1310
- offers = offers.sort((a, b) => sort(sortBy, sortOrder, a, b));
1311
- let nextCursor = null;
1312
- if (offers.length > limit) {
1313
- const last = offers[limit - 1];
1314
- const base = {
1315
- sort: sortBy,
1316
- dir: sortOrder,
1317
- hash: last.hash
1318
- };
1319
- switch (sortBy) {
1320
- case "rate":
1321
- base.rate = last.rate.toString();
1322
- break;
1323
- case "amount":
1324
- base.assets = last.assets.toString();
1325
- break;
1326
- case "maturity":
1327
- base.maturity = last.maturity;
1328
- break;
1329
- default:
1330
- base.expiry = last.expiry;
1331
- }
1332
- nextCursor = encode(base);
1333
- }
1334
- offers = offers.slice(0, limit);
1335
- const data = offers.map((o) => ({
1336
- ...mempool.Offer.from({
1337
- offering: o.offering,
1338
- assets: o.assets,
1339
- rate: o.rate,
1340
- maturity: mempool.Maturity.from(o.maturity),
1341
- expiry: o.expiry,
1342
- start: o.start,
1343
- nonce: o.nonce,
1344
- buy: o.buy,
1345
- chainId: o.chainId,
1346
- loanToken: o.loanToken,
1347
- collaterals: o.collaterals.map((c) => ({ asset: c.asset, oracle: c.oracle, lltv: c.lltv })).sort((a, b) => a.asset.toLowerCase().localeCompare(b.asset.toLowerCase())),
1348
- callback: {
1349
- address: o.callback.address,
1350
- data: o.callback.data,
1351
- gasLimit: o.callback.gasLimit
1352
- },
1353
- ...o.signature !== null && o.signature !== void 0 ? { signature: o.signature } : {}
1354
- }),
1355
- consumed: o.consumed,
1356
- status: o.status,
1357
- ...o.metadata ? { metadata: o.metadata } : {}
1358
- }));
1359
- return {
1360
- offers: data,
1361
- nextCursor
1362
- };
1363
- },
1364
- findMatchingOffers: async (params) => {
1365
- const {
1366
- side,
1367
- chainId,
1368
- rate,
1369
- collaterals = [],
1370
- maturity,
1371
- minMaturity,
1372
- maxMaturity,
1373
- loanToken,
1374
- creator,
1375
- cursor: queryCursor,
1376
- limit = 20
1377
- } = params;
1378
- const now = mempool.Time.now();
1379
- const isBuying = side === "buy";
1380
- const sortOrder = isBuying ? "desc" : "asc";
1381
- let offers = Array.from(map.values()).map((o) => ({
1382
- ...o,
1383
- consumed: filled.get(o.chainId)?.get(o.offering.toLowerCase())?.get(o.nonce) || 0n
1384
- })).filter((o) => o.consumed < o.assets);
1385
- const cursor = decode(queryCursor);
1386
- if (cursor) {
1387
- if (cursor.sort !== "rate" || cursor.dir !== sortOrder) {
1388
- throw new Error("Cursor does not match the current sort parameters");
1389
- }
1390
- offers = offers.filter(
1391
- (o) => sortOrder === "asc" ? o.rate >= BigInt(cursor.rate) : o.rate <= BigInt(cursor.rate)
1392
- );
1393
- }
1394
- offers = offers.filter((o) => o.buy === !isBuying);
1395
- offers = offers.filter((o) => o.chainId === BigInt(chainId));
1396
- offers = offers.filter((o) => o.expiry >= now);
1397
- rate && (offers = offers.filter((o) => isBuying ? o.rate >= rate : o.rate <= rate));
1398
- collaterals.length > 0 && (offers = offers.filter(
1399
- (o) => isBuying ? (
1400
- // when wanting to buy, sell offer collaterals ⊆ user buy collaterals
1401
- o.collaterals.every((oc) => {
1402
- return collaterals.some(
1403
- (c) => oc.asset.toLowerCase() === c.asset.toLowerCase() && oc.oracle.toLowerCase() === c.oracle.toLowerCase() && oc.lltv === c.lltv
1404
- );
1405
- })
1406
- ) : (
1407
- // when wanting to sell, user sell collaterals ⊆ buy offer collaterals
1408
- collaterals.every((c) => {
1409
- return o.collaterals.some(
1410
- (oc) => oc.asset.toLowerCase() === c.asset.toLowerCase() && oc.oracle.toLowerCase() === c.oracle.toLowerCase() && oc.lltv === c.lltv
1411
- );
1412
- })
1413
- )
1414
- ));
1415
- maturity && (offers = offers.filter((o) => o.maturity === maturity));
1416
- minMaturity && (offers = offers.filter((o) => o.maturity >= minMaturity));
1417
- maxMaturity && (offers = offers.filter((o) => o.maturity <= maxMaturity));
1418
- loanToken && (offers = offers.filter((o) => o.loanToken.toLowerCase() === loanToken.toLowerCase()));
1419
- creator && (offers = offers.filter((o) => o.offering.toLowerCase() === creator.toLowerCase()));
1420
- offers = offers.filter((o) => ["valid"].includes(o.status));
1421
- const byGroup = /* @__PURE__ */ new Map();
1422
- for (const offer of offers) {
1423
- const groupKey = `${offer.chainId}-${offer.offering.toLowerCase()}-${offer.nonce}-${offer.buy}`;
1424
- const current = byGroup.get(groupKey);
1425
- if (!current) {
1426
- byGroup.set(groupKey, offer);
1427
- continue;
1428
- }
1429
- const remainingCandidate = offer.assets - offer.consumed;
1430
- const remainingCurrent = current.assets - current.consumed;
1431
- let candidateIsBetter = false;
1432
- if (offer.buy) {
1433
- if (offer.rate !== current.rate) candidateIsBetter = offer.rate < current.rate;
1434
- else if (remainingCandidate !== remainingCurrent)
1435
- candidateIsBetter = remainingCandidate > remainingCurrent;
1436
- else if (offer.maturity !== current.maturity)
1437
- candidateIsBetter = offer.maturity > current.maturity;
1438
- else candidateIsBetter = offer.hash < current.hash;
1439
- } else {
1440
- if (offer.rate !== current.rate) candidateIsBetter = offer.rate > current.rate;
1441
- else if (remainingCandidate !== remainingCurrent)
1442
- candidateIsBetter = remainingCandidate > remainingCurrent;
1443
- else if (offer.maturity !== current.maturity)
1444
- candidateIsBetter = offer.maturity > current.maturity;
1445
- else candidateIsBetter = offer.hash < current.hash;
1446
- }
1447
- if (candidateIsBetter) byGroup.set(groupKey, offer);
1448
- }
1449
- offers = Array.from(byGroup.values());
1450
- offers = offers.sort((a, b) => sort("rate", sortOrder, a, b));
1451
- cursor && (offers = offers.filter((o) => o.hash !== cursor.hash));
1452
- let nextCursor = null;
1453
- if (offers.length > limit) {
1454
- const last = offers[limit - 1];
1455
- nextCursor = encode({
1456
- sort: "rate",
1457
- dir: sortOrder,
1458
- hash: last.hash,
1459
- rate: last.rate.toString()
1460
- });
1461
- }
1462
- offers = offers.slice(0, limit);
1463
- const data = offers.map((o) => ({
1464
- ...mempool.Offer.from({
1465
- offering: o.offering,
1466
- assets: o.assets,
1467
- rate: o.rate,
1468
- maturity: mempool.Maturity.from(o.maturity),
1469
- expiry: o.expiry,
1470
- start: o.start,
1471
- nonce: o.nonce,
1472
- buy: o.buy,
1473
- chainId: o.chainId,
1474
- loanToken: o.loanToken,
1475
- collaterals: o.collaterals.map((c) => ({ asset: c.asset, oracle: c.oracle, lltv: c.lltv })).sort((a, b) => a.asset.toLowerCase().localeCompare(b.asset.toLowerCase())),
1476
- callback: {
1477
- address: o.callback.address,
1478
- data: o.callback.data,
1479
- gasLimit: o.callback.gasLimit
1480
- },
1481
- ...o.signature !== null && o.signature !== void 0 ? { signature: o.signature } : {}
1482
- }),
1483
- consumed: o.consumed,
1484
- status: o.status,
1485
- ...o.metadata ? { metadata: o.metadata } : {}
1486
- }));
1487
- return {
1488
- offers: data,
1489
- nextCursor
1490
- };
1491
- },
1492
- delete: async (hash) => {
1493
- if (!map.has(hash.toLowerCase())) return false;
1494
- map.delete(hash.toLowerCase());
1495
- return true;
1496
- },
1497
- deleteMany: async (hashes) => {
1498
- let deleted = 0;
1499
- for (const hash of hashes) {
1500
- if (map.has(hash.toLowerCase())) {
1501
- map.delete(hash.toLowerCase());
1502
- deleted++;
1503
- }
1504
- }
1505
- return deleted;
1506
- },
1507
- updateStatus: async (parameters2) => {
1508
- const key = parameters2.offerHash.toLowerCase();
1509
- const existing = map.get(key);
1510
- if (!existing) return;
1511
- if (existing.status === parameters2.status) return;
1512
- map.set(key, {
1513
- ...existing,
1514
- status: parameters2.status,
1515
- metadata: parameters2.metadata
1516
- });
1517
- },
1518
- updateConsumedAmount: async (parameters2) => {
1519
- if (consumedIds.has(parameters2.id)) return;
1520
- consumedIds.add(parameters2.id);
1521
- const chainId = parameters2.chainId;
1522
- const address = parameters2.offering.toLowerCase();
1523
- const nonce = parameters2.nonce;
1524
- const filledForChain = filled.get(chainId) || /* @__PURE__ */ new Map();
1525
- const filledForOffering = filledForChain.get(address) || /* @__PURE__ */ new Map();
1526
- const current = filledForOffering.get(nonce) || 0n;
1527
- filledForOffering.set(nonce, current + parameters2.consumed);
1528
- filledForChain.set(address, filledForOffering);
1529
- filled.set(chainId, filledForChain);
1530
- }
1531
- };
1532
- }
1533
-
1534
- // src/Validation.ts
1123
+ // src/core/Validation.ts
1535
1124
  var Validation_exports = {};
1536
1125
  __export(Validation_exports, {
1537
1126
  run: () => run
@@ -1578,7 +1167,7 @@ async function run(parameters) {
1578
1167
  };
1579
1168
  }
1580
1169
 
1581
- // src/ValidationRule.ts
1170
+ // src/core/ValidationRule.ts
1582
1171
  var ValidationRule_exports = {};
1583
1172
  __export(ValidationRule_exports, {
1584
1173
  batch: () => batch,
@@ -1632,7 +1221,6 @@ function morpho() {
1632
1221
  exports.Callback = Callback_exports;
1633
1222
  exports.Cursor = Cursor_exports;
1634
1223
  exports.Liquidity = Liquidity_exports;
1635
- exports.OfferStore = OfferStore_exports;
1636
1224
  exports.Router = Client_exports;
1637
1225
  exports.RouterOffer = RouterOffer_exports;
1638
1226
  exports.Validation = Validation_exports;