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