@morpho-dev/router 0.4.2 → 0.5.0

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 { t as __export } from "./chunk-jass6xSI.mjs";
1
+ import { t as __exportAll } from "./chunk-Bo1DHCg-.mjs";
2
2
  import { getBlock, getBlockNumber, getLogs, multicall } from "viem/actions";
3
3
  import { AsyncLocalStorage } from "node:async_hooks";
4
4
  import { bytesToHex, decodeAbiParameters, encodeAbiParameters, erc20Abi, getAddress, hashMessage, hashTypedData, hexToBytes, isAddress, isHex, keccak256, maxUint256, numberToHex, pad, parseAbi, parseEventLogs, publicActions, recoverAddress, stringify, zeroAddress } from "viem";
@@ -40,7 +40,7 @@ import { Pool } from "pg";
40
40
  import { and, asc, eq, gt, gte, inArray, lte, ne, sql } from "drizzle-orm";
41
41
 
42
42
  //#region src/logger/Logger.ts
43
- var Logger_exports = /* @__PURE__ */ __export({
43
+ var Logger_exports = /* @__PURE__ */ __exportAll({
44
44
  LogLevelValues: () => LogLevelValues,
45
45
  defaultLogger: () => defaultLogger,
46
46
  getLogger: () => getLogger,
@@ -75,10 +75,10 @@ function defaultLogger(minLevel, pretty) {
75
75
  const { msg, ...rest } = entry;
76
76
  const stack = typeof rest.stack === "string" ? rest.stack : void 0;
77
77
  if (stack) delete rest.stack;
78
- const timestamp$1 = (/* @__PURE__ */ new Date()).toISOString();
78
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
79
79
  const level = methodLevel.toUpperCase();
80
80
  const extras = Object.entries(rest).map(([k, v]) => `${k}=${formatValue(v)}`).join(" ");
81
- const line = extras.length > 0 ? `${timestamp$1} [${level}] ${msg} ${extras}` : `${timestamp$1} [${level}] ${msg}`;
81
+ const line = extras.length > 0 ? `${timestamp} [${level}] ${msg} ${extras}` : `${timestamp} [${level}] ${msg}`;
82
82
  console[consoleMethod](line);
83
83
  if (stack) console[consoleMethod](stack);
84
84
  } : () => {};
@@ -258,7 +258,7 @@ async function batchMulticall(parameters) {
258
258
 
259
259
  //#endregion
260
260
  //#region src/utils/Errors.ts
261
- var Errors_exports = /* @__PURE__ */ __export({
261
+ var Errors_exports = /* @__PURE__ */ __exportAll({
262
262
  BaseError: () => BaseError,
263
263
  ReorgError: () => ReorgError
264
264
  });
@@ -315,7 +315,7 @@ var ReorgError = class extends BaseError {
315
315
 
316
316
  //#endregion
317
317
  //#region src/utils/Format.ts
318
- var Format_exports = /* @__PURE__ */ __export({
318
+ var Format_exports = /* @__PURE__ */ __exportAll({
319
319
  fromSnakeCase: () => fromSnakeCase$3,
320
320
  stringifyBigint: () => stringifyBigint,
321
321
  toSnakeCase: () => toSnakeCase$1
@@ -327,7 +327,7 @@ var Format_exports = /* @__PURE__ */ __export({
327
327
  * Stringifies bigint values to strings.
328
328
  */
329
329
  function toSnakeCase$1(obj) {
330
- return stringifyBigint(processObject(obj, (s$1) => s$1.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`), (value) => typeof value === "string" && isAddress(value.toLowerCase()) ? getAddress(value.toLowerCase()) : value));
330
+ return stringifyBigint(processObject(obj, (s) => s.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`), (value) => typeof value === "string" && isAddress(value.toLowerCase()) ? getAddress(value.toLowerCase()) : value));
331
331
  }
332
332
  /**
333
333
  * Formats a snake case object to its camel case type.
@@ -336,7 +336,7 @@ function toSnakeCase$1(obj) {
336
336
  * @warning Does not unstringify bigint values.
337
337
  */
338
338
  function fromSnakeCase$3(obj) {
339
- return processObject(obj, (s$1) => isAddress(s$1.toLowerCase()) ? s$1 : s$1.replace(/_([a-z])/g, (_, c) => c.toUpperCase()), (value) => typeof value === "string" && isAddress(value.toLowerCase()) ? value.toLowerCase() : value);
339
+ return processObject(obj, (s) => isAddress(s.toLowerCase()) ? s : s.replace(/_([a-z])/g, (_, c) => c.toUpperCase()), (value) => typeof value === "string" && isAddress(value.toLowerCase()) ? value.toLowerCase() : value);
340
340
  }
341
341
  function processObject(obj, fnKey, fnValue) {
342
342
  if (typeof obj !== "object" || obj === null) return obj;
@@ -360,7 +360,7 @@ function stringifyBigint(value) {
360
360
 
361
361
  //#endregion
362
362
  //#region src/utils/Group.ts
363
- var Group_exports = /* @__PURE__ */ __export({ fromNumber: () => fromNumber });
363
+ var Group_exports = /* @__PURE__ */ __exportAll({ fromNumber: () => fromNumber });
364
364
  /**
365
365
  * Creates a bytes32 group identifier from a number.
366
366
  * @param n - A non-negative integer.
@@ -384,8 +384,8 @@ function lazy(pollFn) {
384
384
  let active = true;
385
385
  let resolveNext = null;
386
386
  const queue = [];
387
- const wait$1 = () => new Promise((resolve$1) => {
388
- resolveNext = resolve$1;
387
+ const wait = () => new Promise((resolve) => {
388
+ resolveNext = resolve;
389
389
  });
390
390
  const emit = (item) => {
391
391
  queue.push(item);
@@ -402,7 +402,7 @@ function lazy(pollFn) {
402
402
  unpoll = pollFn(emit, { stop });
403
403
  try {
404
404
  while (active) {
405
- if (queue.length === 0) await wait$1();
405
+ if (queue.length === 0) await wait();
406
406
  while (queue.length > 0 && active) yield queue.shift();
407
407
  }
408
408
  } finally {
@@ -441,7 +441,7 @@ function poll(fn, { interval }) {
441
441
 
442
442
  //#endregion
443
443
  //#region src/utils/Random.ts
444
- var Random_exports = /* @__PURE__ */ __export({
444
+ var Random_exports = /* @__PURE__ */ __exportAll({
445
445
  address: () => address,
446
446
  bool: () => bool,
447
447
  bytes: () => bytes,
@@ -454,16 +454,16 @@ var Random_exports = /* @__PURE__ */ __export({
454
454
  let currentRng = Math.random;
455
455
  const FNV_OFFSET_BASIS = 2166136261;
456
456
  const FNV_PRIME = 16777619;
457
- const hashSeed = (seed$1) => {
458
- let hash$1 = FNV_OFFSET_BASIS;
459
- for (let i = 0; i < seed$1.length; i += 1) {
460
- hash$1 ^= seed$1.charCodeAt(i);
461
- hash$1 = Math.imul(hash$1, FNV_PRIME);
457
+ const hashSeed = (seed) => {
458
+ let hash = FNV_OFFSET_BASIS;
459
+ for (let i = 0; i < seed.length; i += 1) {
460
+ hash ^= seed.charCodeAt(i);
461
+ hash = Math.imul(hash, FNV_PRIME);
462
462
  }
463
- return hash$1 >>> 0;
463
+ return hash >>> 0;
464
464
  };
465
- const createSeededRng = (seed$1) => {
466
- let state = hashSeed(seed$1);
465
+ const createSeededRng = (seed) => {
466
+ let state = hashSeed(seed);
467
467
  return () => {
468
468
  state += 1831565813;
469
469
  let t = Math.imul(state ^ state >>> 15, state | 1);
@@ -474,9 +474,9 @@ const createSeededRng = (seed$1) => {
474
474
  /**
475
475
  * Runs a function with a deterministic RNG derived from the given seed.
476
476
  */
477
- function withSeed(seed$1, fn) {
477
+ function withSeed(seed, fn) {
478
478
  const previous = currentRng;
479
- currentRng = createSeededRng(seed$1);
479
+ currentRng = createSeededRng(seed);
480
480
  try {
481
481
  return fn();
482
482
  } finally {
@@ -486,8 +486,8 @@ function withSeed(seed$1, fn) {
486
486
  /**
487
487
  * Seeds the global RNG for deterministic test runs.
488
488
  */
489
- function seed(seed$1) {
490
- currentRng = createSeededRng(seed$1);
489
+ function seed(seed) {
490
+ currentRng = createSeededRng(seed);
491
491
  }
492
492
  /**
493
493
  * Returns a deterministic random float in [0, 1).
@@ -498,8 +498,8 @@ function float() {
498
498
  /**
499
499
  * Returns a deterministic random integer in [min, maxExclusive).
500
500
  */
501
- function int(maxExclusive, min$1 = 0) {
502
- return Math.floor(float() * (maxExclusive - min$1)) + min$1;
501
+ function int(maxExclusive, min = 0) {
502
+ return Math.floor(float() * (maxExclusive - min)) + min;
503
503
  }
504
504
  /**
505
505
  * Returns a deterministic random boolean.
@@ -531,7 +531,7 @@ function address() {
531
531
 
532
532
  //#endregion
533
533
  //#region src/utils/time.ts
534
- var time_exports = /* @__PURE__ */ __export({
534
+ var time_exports = /* @__PURE__ */ __exportAll({
535
535
  max: () => max,
536
536
  now: () => now
537
537
  });
@@ -544,7 +544,7 @@ function max() {
544
544
 
545
545
  //#endregion
546
546
  //#region src/utils/index.ts
547
- var utils_exports = /* @__PURE__ */ __export({
547
+ var utils_exports = /* @__PURE__ */ __exportAll({
548
548
  BaseError: () => BaseError,
549
549
  Group: () => Group_exports,
550
550
  Random: () => Random_exports,
@@ -687,14 +687,14 @@ const reconcile = async (parameters) => {
687
687
  if (block.hash === null || block.number === null || block.parentHash === null) throw new Error("Failed to get block");
688
688
  const latestBlock = unfinalizedBlocks[unfinalizedBlocks.length - 1];
689
689
  if (latestBlock === void 0) {
690
- const newBlock$1 = {
690
+ const newBlock = {
691
691
  hash: block.hash,
692
692
  number: block.number,
693
693
  parentHash: block.parentHash
694
694
  };
695
- unfinalizedBlocks.push(newBlock$1);
695
+ unfinalizedBlocks.push(newBlock);
696
696
  return {
697
- block: newBlock$1,
697
+ block: newBlock,
698
698
  didReorgHappened: false,
699
699
  unfinalizedBlocks
700
700
  };
@@ -729,14 +729,14 @@ const reconcile = async (parameters) => {
729
729
  msg: `Missing blocks`
730
730
  });
731
731
  const missingBlockNumbers = (() => {
732
- const missingBlockNumbers$1 = [];
733
- let start$1 = latestBlock.number + 1n;
732
+ const missingBlockNumbers = [];
733
+ let start = latestBlock.number + 1n;
734
734
  const threshold = latestBlock.number + BigInt(maxBatchSize) > block.number ? block.number : latestBlock.number + BigInt(maxBatchSize);
735
- while (start$1 < threshold) {
736
- missingBlockNumbers$1.push(start$1);
737
- start$1 = start$1 + 1n;
735
+ while (start < threshold) {
736
+ missingBlockNumbers.push(start);
737
+ start = start + 1n;
738
738
  }
739
- return missingBlockNumbers$1;
739
+ return missingBlockNumbers;
740
740
  })();
741
741
  const missingBlocks = await Promise.all(missingBlockNumbers.map((blockNumber) => retry(async () => await client.getBlock({
742
742
  blockNumber,
@@ -853,10 +853,10 @@ function create$16({ name, collect, client, db, options }) {
853
853
  }) && options.maxBlockNumber !== void 0 && lastBlockNumber !== void 0 && options.maxBlockNumber === lastBlockNumber) return;
854
854
  const { blockNumber, done } = await startActiveSpan(tracer, `${collectorId}.next`, async () => {
855
855
  if (iterator === null) throw new Error("Iterator is not initialized");
856
- const { value: blockNumber$1, done: done$1 } = await iterator.next();
856
+ const { value: blockNumber, done } = await iterator.next();
857
857
  return {
858
- blockNumber: blockNumber$1,
859
- done: done$1
858
+ blockNumber,
859
+ done
860
860
  };
861
861
  });
862
862
  if (done) iterator = null;
@@ -951,7 +951,7 @@ const MetaMorphoFactory = parseAbi(["event CreateMetaMorpho(address indexed meta
951
951
 
952
952
  //#endregion
953
953
  //#region src/core/Abi/index.ts
954
- var Abi_exports = /* @__PURE__ */ __export({
954
+ var Abi_exports = /* @__PURE__ */ __exportAll({
955
955
  ERC4626: () => ERC4626,
956
956
  MetaMorpho: () => MetaMorpho,
957
957
  MetaMorphoFactory: () => MetaMorphoFactory,
@@ -1102,41 +1102,77 @@ const Morpho = [
1102
1102
 
1103
1103
  //#endregion
1104
1104
  //#region src/core/Callback.ts
1105
- var Callback_exports = /* @__PURE__ */ __export({
1106
- CallbackType: () => CallbackType,
1105
+ var Callback_exports = /* @__PURE__ */ __exportAll({
1106
+ Type: () => Type$1,
1107
1107
  decode: () => decode$2,
1108
+ decodeBuyERC20: () => decodeBuyERC20,
1108
1109
  decodeBuyVaultV1Callback: () => decodeBuyVaultV1Callback,
1109
1110
  decodeSellERC20Callback: () => decodeSellERC20Callback,
1110
1111
  encode: () => encode$2,
1112
+ encodeBuyERC20: () => encodeBuyERC20,
1111
1113
  encodeBuyVaultV1Callback: () => encodeBuyVaultV1Callback,
1112
1114
  encodeSellERC20Callback: () => encodeSellERC20Callback,
1113
1115
  isEmptyCallback: () => isEmptyCallback
1114
1116
  });
1115
- let CallbackType = /* @__PURE__ */ function(CallbackType$1) {
1116
- CallbackType$1["BuyWithEmptyCallback"] = "buy_with_empty_callback";
1117
- CallbackType$1["BuyVaultV1Callback"] = "buy_vault_v1_callback";
1118
- CallbackType$1["SellERC20Callback"] = "sell_erc20_callback";
1119
- return CallbackType$1;
1117
+ let Type$1 = /* @__PURE__ */ function(Type) {
1118
+ Type["BuyWithEmptyCallback"] = "buy_with_empty_callback";
1119
+ Type["BuyERC20"] = "buy_erc20";
1120
+ Type["BuyVaultV1Callback"] = "buy_vault_v1_callback";
1121
+ Type["SellERC20Callback"] = "sell_erc20_callback";
1122
+ return Type;
1120
1123
  }({});
1121
1124
  const isEmptyCallback = (offer) => offer.callback.data === "0x";
1122
1125
  function decode$2(type, data) {
1123
1126
  switch (type) {
1124
- case CallbackType.BuyVaultV1Callback: return decodeBuyVaultV1Callback(data);
1125
- case CallbackType.SellERC20Callback: return decodeSellERC20Callback(data);
1127
+ case Type$1.BuyERC20: return decodeBuyERC20(data);
1128
+ case Type$1.BuyVaultV1Callback: return decodeBuyVaultV1Callback(data);
1129
+ case Type$1.SellERC20Callback: return decodeSellERC20Callback(data);
1126
1130
  default: throw new Error("Invalid callback type");
1127
1131
  }
1128
1132
  }
1129
1133
  function encode$2(type, data) {
1130
1134
  switch (type) {
1131
- case CallbackType.BuyVaultV1Callback:
1135
+ case Type$1.BuyERC20:
1136
+ if (!("tokens" in data)) throw new Error("Invalid callback data");
1137
+ return encodeBuyERC20(data);
1138
+ case Type$1.BuyVaultV1Callback:
1132
1139
  if (!("vaults" in data)) throw new Error("Invalid callback data");
1133
1140
  return encodeBuyVaultV1Callback(data);
1134
- case CallbackType.SellERC20Callback:
1141
+ case Type$1.SellERC20Callback:
1135
1142
  if (!("collaterals" in data)) throw new Error("Invalid callback data");
1136
1143
  return encodeSellERC20Callback(data);
1137
1144
  default: throw new Error("Invalid callback type");
1138
1145
  }
1139
1146
  }
1147
+ /**
1148
+ * Decodes BuyERC20 callback data into positions.
1149
+ * @param data - The ABI-encoded callback data containing token addresses and amounts.
1150
+ * @returns Array of positions with contract address and amount.
1151
+ * @throws If data is empty, malformed, or arrays have mismatched lengths.
1152
+ */
1153
+ function decodeBuyERC20(data) {
1154
+ if (!data || data === "0x") throw new Error("Empty callback data");
1155
+ let tokens;
1156
+ let amounts;
1157
+ try {
1158
+ [tokens, amounts] = decodeAbiParameters([{ type: "address[]" }, { type: "uint256[]" }], data);
1159
+ } catch (_) {
1160
+ throw new Error("Invalid BuyERC20 callback data");
1161
+ }
1162
+ if (tokens.length !== amounts.length) throw new Error("Mismatched array lengths");
1163
+ return tokens.map((token, index) => ({
1164
+ contract: token,
1165
+ amount: amounts[index]
1166
+ }));
1167
+ }
1168
+ /**
1169
+ * Encodes BuyERC20 callback parameters into ABI-encoded data.
1170
+ * @param parameters - The tokens and amounts to encode.
1171
+ * @returns ABI-encoded hex string.
1172
+ */
1173
+ function encodeBuyERC20(parameters) {
1174
+ return encodeAbiParameters([{ type: "address[]" }, { type: "uint256[]" }], [parameters.tokens, parameters.amounts]);
1175
+ }
1140
1176
  function decodeBuyVaultV1Callback(data) {
1141
1177
  if (!data || data === "0x") throw new Error("Empty callback data");
1142
1178
  try {
@@ -1172,7 +1208,7 @@ function encodeSellERC20Callback(parameters) {
1172
1208
 
1173
1209
  //#endregion
1174
1210
  //#region src/core/Chain.ts
1175
- var Chain_exports = /* @__PURE__ */ __export({
1211
+ var Chain_exports = /* @__PURE__ */ __exportAll({
1176
1212
  ChainId: () => ChainId,
1177
1213
  InvalidBatchSizeError: () => InvalidBatchSizeError,
1178
1214
  InvalidBlockRangeError: () => InvalidBlockRangeError,
@@ -1234,7 +1270,8 @@ const chains$2 = {
1234
1270
  address: "0x1897A8997241C1cD4bD0698647e4EB7213535c24",
1235
1271
  blockCreated: 21439510
1236
1272
  }
1237
- } }
1273
+ } },
1274
+ callbacks: []
1238
1275
  }
1239
1276
  },
1240
1277
  base: {
@@ -1263,7 +1300,8 @@ const chains$2 = {
1263
1300
  address: "0xFf62A7c278C62eD665133147129245053Bbf5918",
1264
1301
  blockCreated: 23928808
1265
1302
  }
1266
- } }
1303
+ } },
1304
+ callbacks: []
1267
1305
  }
1268
1306
  },
1269
1307
  "ethereum-virtual-testnet": {
@@ -1292,7 +1330,8 @@ const chains$2 = {
1292
1330
  address: "0x1897A8997241C1cD4bD0698647e4EB7213535c24",
1293
1331
  blockCreated: 21439510
1294
1332
  }
1295
- } }
1333
+ } },
1334
+ callbacks: []
1296
1335
  }
1297
1336
  },
1298
1337
  anvil: {
@@ -1321,7 +1360,8 @@ const chains$2 = {
1321
1360
  address: "0x0000000000000000000000000000000000000000",
1322
1361
  blockCreated: 0
1323
1362
  }
1324
- } }
1363
+ } },
1364
+ callbacks: []
1325
1365
  }
1326
1366
  }
1327
1367
  };
@@ -1417,10 +1457,15 @@ var MissingBlockNumberError = class extends BaseError {
1417
1457
 
1418
1458
  //#endregion
1419
1459
  //#region src/core/ChainRegistry.ts
1420
- var ChainRegistry_exports = /* @__PURE__ */ __export({ create: () => create$15 });
1421
- function create$15(chains$3) {
1460
+ var ChainRegistry_exports = /* @__PURE__ */ __exportAll({ create: () => create$15 });
1461
+ /**
1462
+ * Creates a chain registry from a list of chains.
1463
+ * @param chains - Array of chain objects to register.
1464
+ * @returns A registry for looking up chains by ID. {@link ChainRegistry}
1465
+ */
1466
+ function create$15(chains) {
1422
1467
  const byId = /* @__PURE__ */ new Map();
1423
- for (const chain of chains$3) byId.set(chain.id, chain);
1468
+ for (const chain of chains) byId.set(chain.id, chain);
1424
1469
  return {
1425
1470
  getById: (chainId) => byId.get(chainId),
1426
1471
  list: () => Array.from(byId.values())
@@ -1510,12 +1555,12 @@ const transformAddress = (val, ctx) => {
1510
1555
 
1511
1556
  //#endregion
1512
1557
  //#region src/core/LLTV.ts
1513
- var LLTV_exports = /* @__PURE__ */ __export({
1558
+ var LLTV_exports = /* @__PURE__ */ __exportAll({
1514
1559
  InvalidLLTVError: () => InvalidLLTVError,
1515
1560
  InvalidOptionError: () => InvalidOptionError$1,
1516
1561
  LLTVSchema: () => LLTVSchema,
1517
1562
  Options: () => Options,
1518
- from: () => from$17
1563
+ from: () => from$18
1519
1564
  });
1520
1565
  const Options = [
1521
1566
  .385,
@@ -1534,7 +1579,7 @@ const LLTV_SCALED = Options.map((lltv) => BigInt(lltv * 10 ** 18));
1534
1579
  * @param lltv - The LLTV option or the scaled LLTV.
1535
1580
  * @returns The LLTV.
1536
1581
  */
1537
- function from$17(lltv) {
1582
+ function from$18(lltv) {
1538
1583
  if (typeof lltv === "bigint" && !LLTV_SCALED.includes(lltv)) throw new InvalidLLTVError(lltv);
1539
1584
  if (typeof lltv === "bigint") return lltv;
1540
1585
  if (typeof lltv === "number" && !Options.includes(lltv)) throw new InvalidOptionError$1(lltv);
@@ -1554,21 +1599,21 @@ var InvalidLLTVError = class extends BaseError {
1554
1599
  };
1555
1600
  const LLTVSchema = z$1.bigint({ coerce: true }).refine((lltv) => {
1556
1601
  try {
1557
- from$17(lltv);
1602
+ from$18(lltv);
1558
1603
  return true;
1559
1604
  } catch (_) {
1560
1605
  return false;
1561
1606
  }
1562
1607
  }, { error: () => {
1563
1608
  return "Invalid LLTV: must be one of 0.385, 0.625, 0.77, 0.86, 0.915, 0.945, 0.965 or 0.98 (scaled by 1e18)";
1564
- } }).transform((lltv) => from$17(lltv));
1609
+ } }).transform((lltv) => from$18(lltv));
1565
1610
 
1566
1611
  //#endregion
1567
1612
  //#region src/core/Collateral.ts
1568
- var Collateral_exports = /* @__PURE__ */ __export({
1613
+ var Collateral_exports = /* @__PURE__ */ __exportAll({
1569
1614
  CollateralSchema: () => CollateralSchema,
1570
1615
  CollateralsSchema: () => CollateralsSchema,
1571
- from: () => from$16,
1616
+ from: () => from$17,
1572
1617
  random: () => random$3
1573
1618
  });
1574
1619
  const CollateralSchema = z$1.object({
@@ -1588,10 +1633,10 @@ const CollateralsSchema = z$1.array(CollateralSchema).min(1, { message: "At leas
1588
1633
  }
1589
1634
  return true;
1590
1635
  }, { message: "Collaterals must not contain duplicate assets" });
1591
- const from$16 = (parameters) => {
1636
+ const from$17 = (parameters) => {
1592
1637
  return {
1593
1638
  asset: parameters.asset.toLowerCase(),
1594
- lltv: from$17(parameters.lltv),
1639
+ lltv: from$18(parameters.lltv),
1595
1640
  oracle: parameters.oracle.toLowerCase()
1596
1641
  };
1597
1642
  };
@@ -1605,7 +1650,7 @@ const from$16 = (parameters) => {
1605
1650
  * ```
1606
1651
  */
1607
1652
  function random$3() {
1608
- return from$16({
1653
+ return from$17({
1609
1654
  asset: address(),
1610
1655
  oracle: address(),
1611
1656
  lltv: .965
@@ -1614,7 +1659,7 @@ function random$3() {
1614
1659
 
1615
1660
  //#endregion
1616
1661
  //#region src/core/ERC4626.ts
1617
- var ERC4626_exports = /* @__PURE__ */ __export({
1662
+ var ERC4626_exports = /* @__PURE__ */ __exportAll({
1618
1663
  DenominatorIsZeroError: () => DenominatorIsZeroError,
1619
1664
  convertToAssets: () => convertToAssets,
1620
1665
  convertToShares: () => convertToShares,
@@ -1677,7 +1722,7 @@ var DenominatorIsZeroError = class extends BaseError {
1677
1722
 
1678
1723
  //#endregion
1679
1724
  //#region src/core/Liquidity.ts
1680
- var Liquidity_exports = /* @__PURE__ */ __export({
1725
+ var Liquidity_exports = /* @__PURE__ */ __exportAll({
1681
1726
  calculateMaxDebt: () => calculateMaxDebt,
1682
1727
  generateAllowancePoolId: () => generateAllowancePoolId,
1683
1728
  generateBalancePoolId: () => generateBalancePoolId,
@@ -1703,23 +1748,23 @@ function calculateMaxDebt(amount, oraclePrice, lltv) {
1703
1748
  * Generate pool ID for balance pools.
1704
1749
  */
1705
1750
  function generateBalancePoolId(parameters) {
1706
- const { user, chainId, token: token$1 } = parameters;
1707
- return `${user}-${chainId.toString()}-${token$1}-balance`.toLowerCase();
1751
+ const { user, chainId, token } = parameters;
1752
+ return `${user}-${chainId.toString()}-${token}-balance`.toLowerCase();
1708
1753
  }
1709
1754
  /**
1710
1755
  * Generate pool ID for allowance pools.
1711
1756
  */
1712
1757
  function generateAllowancePoolId(parameters) {
1713
- const { user, chainId, token: token$1 } = parameters;
1714
- return `${user}-${chainId.toString()}-${token$1}-allowance`.toLowerCase();
1758
+ const { user, chainId, token } = parameters;
1759
+ return `${user}-${chainId.toString()}-${token}-allowance`.toLowerCase();
1715
1760
  }
1716
1761
  /**
1717
1762
  * Generate pool ID for sell ERC20 callback pools.
1718
1763
  * Each offer has its own callback pool to prevent liquidity conflicts.
1719
1764
  */
1720
1765
  function generateSellERC20CallbackPoolId(parameters) {
1721
- const { user, chainId, obligationId: obligationId$1, token: token$1, offerHash } = parameters;
1722
- return `${user}-${chainId.toString()}-${obligationId$1}-${token$1}-${offerHash}-sell_erc20_callback`.toLowerCase();
1766
+ const { user, chainId, obligationId, token, offerHash } = parameters;
1767
+ return `${user}-${chainId.toString()}-${obligationId}-${token}-${offerHash}-sell_erc20_callback`.toLowerCase();
1723
1768
  }
1724
1769
  /**
1725
1770
  * Generate pool ID for obligation collateral pools.
@@ -1727,22 +1772,22 @@ function generateSellERC20CallbackPoolId(parameters) {
1727
1772
  * These pools are shared across all offers with the same obligation.
1728
1773
  */
1729
1774
  function generateObligationCollateralPoolId(parameters) {
1730
- const { user, chainId, obligationId: obligationId$1, token: token$1 } = parameters;
1731
- return `${user}-${chainId.toString()}-${obligationId$1}-${token$1}-obligation-collateral`.toLowerCase();
1775
+ const { user, chainId, obligationId, token } = parameters;
1776
+ return `${user}-${chainId.toString()}-${obligationId}-${token}-obligation-collateral`.toLowerCase();
1732
1777
  }
1733
1778
  /**
1734
1779
  * Generate pool ID for buy vault callback pools.
1735
1780
  */
1736
1781
  function generateBuyVaultCallbackPoolId(parameters) {
1737
1782
  const { user, chainId, vault, offerHash } = parameters;
1738
- return `${user}-${chainId.toString()}-${vault}-${offerHash}-${CallbackType.BuyVaultV1Callback}`.toLowerCase();
1783
+ return `${user}-${chainId.toString()}-${vault}-${offerHash}-${Type$1.BuyVaultV1Callback}`.toLowerCase();
1739
1784
  }
1740
1785
  /**
1741
1786
  * Generate pool ID for debt pools.
1742
1787
  */
1743
1788
  function generateDebtPoolId(parameters) {
1744
- const { user, chainId, obligationId: obligationId$1 } = parameters;
1745
- return `${user}-${chainId.toString()}-${obligationId$1}-debt`.toLowerCase();
1789
+ const { user, chainId, obligationId } = parameters;
1790
+ return `${user}-${chainId.toString()}-${obligationId}-debt`.toLowerCase();
1746
1791
  }
1747
1792
  /**
1748
1793
  * Generate pool ID for user position in a vault.
@@ -1768,17 +1813,17 @@ function generateMarketLiquidityPoolId(parameters) {
1768
1813
 
1769
1814
  //#endregion
1770
1815
  //#region src/core/Maturity.ts
1771
- var Maturity_exports = /* @__PURE__ */ __export({
1816
+ var Maturity_exports = /* @__PURE__ */ __exportAll({
1772
1817
  InvalidDateError: () => InvalidDateError,
1773
1818
  InvalidFormatError: () => InvalidFormatError,
1774
1819
  InvalidOptionError: () => InvalidOptionError,
1775
1820
  MaturitySchema: () => MaturitySchema,
1776
1821
  MaturityType: () => MaturityType,
1777
- from: () => from$15
1822
+ from: () => from$16
1778
1823
  });
1779
- const MaturitySchema = z$1.number().int().refine((maturity$1) => {
1824
+ const MaturitySchema = z$1.number().int().refine((maturity) => {
1780
1825
  try {
1781
- from$15(maturity$1);
1826
+ from$16(maturity);
1782
1827
  return true;
1783
1828
  } catch (_e) {
1784
1829
  return false;
@@ -1789,15 +1834,15 @@ const MaturitySchema = z$1.number().int().refine((maturity$1) => {
1789
1834
  } catch (_) {
1790
1835
  return `The maturity is set to ${issue.input}. It must fall on the allowed settlement cycles (Friday 15:00 UTC at the end of week/month/quarter).`;
1791
1836
  }
1792
- } }).transform((maturity$1) => maturity$1);
1793
- let MaturityType = /* @__PURE__ */ function(MaturityType$1) {
1794
- MaturityType$1["EndOfWeek"] = "end_of_week";
1795
- MaturityType$1["EndOfNextWeek"] = "end_of_next_week";
1796
- MaturityType$1["EndOfMonth"] = "end_of_month";
1797
- MaturityType$1["EndOfNextMonth"] = "end_of_next_month";
1798
- MaturityType$1["EndOfQuarter"] = "end_of_quarter";
1799
- MaturityType$1["EndOfNextQuarter"] = "end_of_next_quarter";
1800
- return MaturityType$1;
1837
+ } }).transform((maturity) => maturity);
1838
+ let MaturityType = /* @__PURE__ */ function(MaturityType) {
1839
+ MaturityType["EndOfWeek"] = "end_of_week";
1840
+ MaturityType["EndOfNextWeek"] = "end_of_next_week";
1841
+ MaturityType["EndOfMonth"] = "end_of_month";
1842
+ MaturityType["EndOfNextMonth"] = "end_of_next_month";
1843
+ MaturityType["EndOfQuarter"] = "end_of_quarter";
1844
+ MaturityType["EndOfNextQuarter"] = "end_of_next_quarter";
1845
+ return MaturityType;
1801
1846
  }({});
1802
1847
  const MaturityOptions = {
1803
1848
  end_of_week: () => endOfWeek(),
@@ -1813,7 +1858,7 @@ const MaturityOptions = {
1813
1858
  * @throws {InvalidDateError} If the maturity is in seconds but not a valid date.
1814
1859
  * @throws {InvalidOptionError} If the maturity is not a valid option.
1815
1860
  */
1816
- function from$15(ts) {
1861
+ function from$16(ts) {
1817
1862
  if (typeof ts === "string") {
1818
1863
  if (ts in MaturityOptions) return MaturityOptions[ts]();
1819
1864
  throw new InvalidOptionError(ts);
@@ -1831,23 +1876,23 @@ const endOfNextWeek = () => fridayOfWeek(1);
1831
1876
  * on that Friday), roll to the next month's last Friday.
1832
1877
  */
1833
1878
  const endOfMonth = () => {
1834
- const now$1 = /* @__PURE__ */ new Date();
1835
- const year = now$1.getUTCFullYear();
1836
- const month = now$1.getUTCMonth();
1837
- const endOfMonth$1 = lastFridayOfMonth(year, month);
1838
- if (now$1.getTime() > endOfMonth$1 * 1e3) return lastFridayOfMonth(year, month + 1);
1839
- return endOfMonth$1;
1879
+ const now = /* @__PURE__ */ new Date();
1880
+ const year = now.getUTCFullYear();
1881
+ const month = now.getUTCMonth();
1882
+ const endOfMonth = lastFridayOfMonth(year, month);
1883
+ if (now.getTime() > endOfMonth * 1e3) return lastFridayOfMonth(year, month + 1);
1884
+ return endOfMonth;
1840
1885
  };
1841
1886
  /** Returns the end of the next month (last friday of the next month at 15:00:00 UTC)
1842
1887
  * Business rule: if we are after the last Friday of the current month (strictly after 15:00 UTC
1843
1888
  * on that Friday), we consider being in the next month already, so "next month" becomes month+2.
1844
1889
  */
1845
1890
  const endOfNextMonth = () => {
1846
- const now$1 = /* @__PURE__ */ new Date();
1847
- const year = now$1.getUTCFullYear();
1848
- const month = now$1.getUTCMonth();
1849
- const endOfMonth$1 = lastFridayOfMonth(year, month);
1850
- if (now$1.getTime() > endOfMonth$1 * 1e3) return lastFridayOfMonth(year, month + 2);
1891
+ const now = /* @__PURE__ */ new Date();
1892
+ const year = now.getUTCFullYear();
1893
+ const month = now.getUTCMonth();
1894
+ const endOfMonth = lastFridayOfMonth(year, month);
1895
+ if (now.getTime() > endOfMonth * 1e3) return lastFridayOfMonth(year, month + 2);
1851
1896
  return lastFridayOfMonth(year, month + 1);
1852
1897
  };
1853
1898
  /** Returns the end of the current quarter (last friday of the quarter at 15:00:00 UTC) */
@@ -1855,10 +1900,10 @@ const endOfQuarter = () => lastFridayOfQuarter(0);
1855
1900
  /** Returns the end of the next quarter (last friday of the next quarter at 15:00:00 UTC) */
1856
1901
  const endOfNextQuarter = () => lastFridayOfQuarter(1);
1857
1902
  const fridayOfWeek = (weeksAhead = 0) => {
1858
- const now$1 = /* @__PURE__ */ new Date();
1859
- const today15H = new Date(Date.UTC(now$1.getUTCFullYear(), now$1.getUTCMonth(), now$1.getUTCDate(), 15));
1903
+ const now = /* @__PURE__ */ new Date();
1904
+ const today15H = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), 15));
1860
1905
  let daysUntilFriday = (5 - today15H.getUTCDay() + 7) % 7;
1861
- if (daysUntilFriday === 0 && now$1.getTime() >= today15H.getTime()) daysUntilFriday = 7;
1906
+ if (daysUntilFriday === 0 && now.getTime() >= today15H.getTime()) daysUntilFriday = 7;
1862
1907
  const friday = new Date(today15H);
1863
1908
  friday.setUTCDate(friday.getUTCDate() + daysUntilFriday + weeksAhead * 7);
1864
1909
  return friday.getTime() / 1e3;
@@ -1869,9 +1914,9 @@ const lastFridayOfMonth = (year, month) => {
1869
1914
  return lastDayOfMonth15H.setUTCDate(lastDayOfMonth15H.getUTCDate()) / 1e3;
1870
1915
  };
1871
1916
  const lastFridayOfQuarter = (quartersAhead = 0) => {
1872
- const now$1 = /* @__PURE__ */ new Date();
1873
- const quarterIndex = Math.floor(now$1.getUTCMonth() / 3) + quartersAhead;
1874
- return lastFridayOfMonth(now$1.getUTCFullYear() + Math.floor(quarterIndex / 4), quarterIndex % 4 * 3 + 2);
1917
+ const now = /* @__PURE__ */ new Date();
1918
+ const quarterIndex = Math.floor(now.getUTCMonth() / 3) + quartersAhead;
1919
+ return lastFridayOfMonth(now.getUTCFullYear() + Math.floor(quarterIndex / 4), quarterIndex % 4 * 3 + 2);
1875
1920
  };
1876
1921
  var InvalidFormatError = class extends BaseError {
1877
1922
  name = "Maturity.InvalidFormatError";
@@ -1894,11 +1939,11 @@ var InvalidOptionError = class extends BaseError {
1894
1939
 
1895
1940
  //#endregion
1896
1941
  //#region src/core/Obligation.ts
1897
- var Obligation_exports = /* @__PURE__ */ __export({
1942
+ var Obligation_exports = /* @__PURE__ */ __exportAll({
1898
1943
  CollateralsAreNotSortedError: () => CollateralsAreNotSortedError,
1899
1944
  InvalidObligationError: () => InvalidObligationError,
1900
1945
  ObligationSchema: () => ObligationSchema,
1901
- from: () => from$14,
1946
+ from: () => from$15,
1902
1947
  fromSnakeCase: () => fromSnakeCase$2,
1903
1948
  id: () => id,
1904
1949
  random: () => random$2
@@ -1932,11 +1977,11 @@ const ObligationSchema = z$1.object({
1932
1977
  * });
1933
1978
  * ```
1934
1979
  */
1935
- function from$14(parameters) {
1980
+ function from$15(parameters) {
1936
1981
  try {
1937
1982
  const parsedObligation = ObligationSchema.parse({
1938
1983
  ...parameters,
1939
- maturity: from$15(parameters.maturity)
1984
+ maturity: from$16(parameters.maturity)
1940
1985
  });
1941
1986
  return {
1942
1987
  chainId: parsedObligation.chainId,
@@ -1955,7 +2000,7 @@ function from$14(parameters) {
1955
2000
  * @returns The created obligation. {@link fromSnakeCase.ReturnType}
1956
2001
  */
1957
2002
  function fromSnakeCase$2(input) {
1958
- return from$14(fromSnakeCase$3(input));
2003
+ return from$15(fromSnakeCase$3(input));
1959
2004
  }
1960
2005
  /**
1961
2006
  * Calculates the obligation id based on the smart contract's Obligation struct.
@@ -2020,11 +2065,11 @@ function id(parameters) {
2020
2065
  * ```
2021
2066
  */
2022
2067
  function random$2() {
2023
- return from$14({
2068
+ return from$15({
2024
2069
  chainId: 1,
2025
2070
  loanToken: address(),
2026
2071
  collaterals: [random$3()],
2027
- maturity: from$15("end_of_next_quarter")
2072
+ maturity: from$16("end_of_next_quarter")
2028
2073
  });
2029
2074
  }
2030
2075
  var InvalidObligationError = class extends BaseError {
@@ -2042,7 +2087,7 @@ var CollateralsAreNotSortedError = class extends BaseError {
2042
2087
 
2043
2088
  //#endregion
2044
2089
  //#region src/core/Tree.ts
2045
- var Tree_exports = /* @__PURE__ */ __export({
2090
+ var Tree_exports = /* @__PURE__ */ __exportAll({
2046
2091
  DecodeError: () => DecodeError,
2047
2092
  EncodeError: () => EncodeError,
2048
2093
  TreeError: () => TreeError,
@@ -2050,11 +2095,11 @@ var Tree_exports = /* @__PURE__ */ __export({
2050
2095
  decode: () => decode$1,
2051
2096
  encode: () => encode$1,
2052
2097
  encodeUnsigned: () => encodeUnsigned,
2053
- from: () => from$13,
2098
+ from: () => from$14,
2054
2099
  proofs: () => proofs
2055
2100
  });
2056
2101
  const VERSION$1 = 1;
2057
- const normalizeHash = (hash$1) => hash$1.toLowerCase();
2102
+ const normalizeHash = (hash) => hash.toLowerCase();
2058
2103
  /**
2059
2104
  * Builds a Merkle tree from a list of offers.
2060
2105
  *
@@ -2066,19 +2111,19 @@ const normalizeHash = (hash$1) => hash$1.toLowerCase();
2066
2111
  * @returns A `StandardMerkleTree` of `bytes32` leaves representing the offers.
2067
2112
  * @throws {TreeError} If tree building fails due to offer inconsistencies.
2068
2113
  */
2069
- const from$13 = (offers$1) => {
2070
- const leaves = offers$1.map((offer) => [hash(offer)]);
2114
+ const from$14 = (offers) => {
2115
+ const leaves = offers.map((offer) => [hash(offer)]);
2071
2116
  const tree = StandardMerkleTree.of(leaves, ["bytes32"]);
2072
- const orderedOffers = orderOffers(tree, offers$1);
2117
+ const orderedOffers = orderOffers(tree, offers);
2073
2118
  return Object.assign(tree, { offers: orderedOffers });
2074
2119
  };
2075
- const orderOffers = (tree, offers$1) => {
2120
+ const orderOffers = (tree, offers) => {
2076
2121
  const offerByHash = /* @__PURE__ */ new Map();
2077
- for (const offer of offers$1) offerByHash.set(normalizeHash(hash(offer)), offer);
2122
+ for (const offer of offers) offerByHash.set(normalizeHash(hash(offer)), offer);
2078
2123
  const entries = tree.dump().values.map((value) => {
2079
- const hash$1 = normalizeHash(value.value[0]);
2080
- const offer = offerByHash.get(hash$1);
2081
- if (!offer) throw new TreeError(`missing offer for leaf ${hash$1}`);
2124
+ const hash = normalizeHash(value.value[0]);
2125
+ const offer = offerByHash.get(hash);
2126
+ if (!offer) throw new TreeError(`missing offer for leaf ${hash}`);
2082
2127
  return {
2083
2128
  offer,
2084
2129
  treeIndex: value.treeIndex
@@ -2111,10 +2156,10 @@ const assertHex = (value, expectedBytes, name) => {
2111
2156
  const verifySignatureAndRecoverAddress = async (params) => {
2112
2157
  const { root, signature } = params;
2113
2158
  assertHex(signature, 65, "signature");
2114
- const hash$1 = hashMessage({ raw: root });
2159
+ const hash = hashMessage({ raw: root });
2115
2160
  try {
2116
2161
  return await recoverAddress({
2117
- hash: hash$1,
2162
+ hash,
2118
2163
  signature
2119
2164
  });
2120
2165
  } catch {
@@ -2188,7 +2233,7 @@ const encodeUnsigned = (tree) => {
2188
2233
  };
2189
2234
  const validateTreeForEncoding = (tree) => {
2190
2235
  if (VERSION$1 > 255) throw new EncodeError(`version overflow: ${VERSION$1} exceeds 255`);
2191
- const computed = from$13(tree.offers);
2236
+ const computed = from$14(tree.offers);
2192
2237
  if (tree.root !== computed.root) throw new EncodeError(`root mismatch: expected ${computed.root}, got ${tree.root}`);
2193
2238
  };
2194
2239
  const encodeUnsignedBytes = (tree) => {
@@ -2224,19 +2269,19 @@ const encodeUnsignedBytes = (tree) => {
2224
2269
  * @throws {DecodeError} If version invalid, signature invalid, or root mismatch
2225
2270
  */
2226
2271
  const decode$1 = async (encoded) => {
2227
- const bytes$1 = hexToBytes(encoded);
2228
- if (bytes$1.length < 98) throw new DecodeError("payload too short");
2229
- const version = bytes$1[0];
2272
+ const bytes = hexToBytes(encoded);
2273
+ if (bytes.length < 98) throw new DecodeError("payload too short");
2274
+ const version = bytes[0];
2230
2275
  if (version !== (VERSION$1 & 255)) throw new DecodeError(`invalid version: expected ${VERSION$1}, got ${version ?? 0}`);
2231
- const signature = bytesToHex(bytes$1.slice(-65));
2232
- const root = bytesToHex(bytes$1.slice(-97, -65));
2276
+ const signature = bytesToHex(bytes.slice(-65));
2277
+ const root = bytesToHex(bytes.slice(-97, -65));
2233
2278
  assertHex(root, 32, "root");
2234
2279
  assertHex(signature, 65, "signature");
2235
2280
  const signer = await verifySignatureAndRecoverAddress({
2236
2281
  root,
2237
2282
  signature
2238
2283
  });
2239
- const compressed = bytes$1.slice(1, -97);
2284
+ const compressed = bytes.slice(1, -97);
2240
2285
  let decoded;
2241
2286
  try {
2242
2287
  decoded = ungzip(compressed, { to: "string" });
@@ -2249,7 +2294,7 @@ const decode$1 = async (encoded) => {
2249
2294
  } catch {
2250
2295
  throw new DecodeError("JSON parse failed");
2251
2296
  }
2252
- const tree = from$13(rawOffers.map((o) => OfferSchema().parse(o)));
2297
+ const tree = from$14(rawOffers.map((o) => OfferSchema().parse(o)));
2253
2298
  if (root !== tree.root) throw new DecodeError(`root mismatch: expected ${tree.root}, got ${root}`);
2254
2299
  return {
2255
2300
  tree,
@@ -2290,7 +2335,7 @@ var DecodeError = class extends BaseError {
2290
2335
 
2291
2336
  //#endregion
2292
2337
  //#region src/core/Offer.ts
2293
- var Offer_exports = /* @__PURE__ */ __export({
2338
+ var Offer_exports = /* @__PURE__ */ __exportAll({
2294
2339
  AccountNotSetError: () => AccountNotSetError,
2295
2340
  InvalidOfferError: () => InvalidOfferError,
2296
2341
  OfferSchema: () => OfferSchema,
@@ -2299,7 +2344,7 @@ var Offer_exports = /* @__PURE__ */ __export({
2299
2344
  decode: () => decode,
2300
2345
  domain: () => domain,
2301
2346
  encode: () => encode,
2302
- from: () => from$12,
2347
+ from: () => from$13,
2303
2348
  fromSnakeCase: () => fromSnakeCase$1,
2304
2349
  hash: () => hash,
2305
2350
  obligationId: () => obligationId,
@@ -2312,10 +2357,10 @@ var Offer_exports = /* @__PURE__ */ __export({
2312
2357
  });
2313
2358
  /** Internal symbol for caching the computed hash. */
2314
2359
  const HASH_CACHE = Symbol("offer.hash");
2315
- let Status = /* @__PURE__ */ function(Status$1) {
2316
- Status$1["VALID"] = "VALID";
2317
- Status$1["SIMULATION_ERROR"] = "SIMULATION_ERROR";
2318
- return Status$1;
2360
+ let Status = /* @__PURE__ */ function(Status) {
2361
+ Status["VALID"] = "VALID";
2362
+ Status["SIMULATION_ERROR"] = "SIMULATION_ERROR";
2363
+ return Status;
2319
2364
  }({});
2320
2365
  const OfferSchema = () => {
2321
2366
  return z$1.object({
@@ -2359,7 +2404,7 @@ const OfferSchema = () => {
2359
2404
  * @param input - The offer to create.
2360
2405
  * @returns The created offer.
2361
2406
  */
2362
- function from$12(input) {
2407
+ function from$13(input) {
2363
2408
  try {
2364
2409
  return OfferSchema().parse(input);
2365
2410
  } catch (error) {
@@ -2373,7 +2418,7 @@ function from$12(input) {
2373
2418
  * @returns The created offer.
2374
2419
  */
2375
2420
  function fromSnakeCase$1(input) {
2376
- return from$12(fromSnakeCase$3(input));
2421
+ return from$13(fromSnakeCase$3(input));
2377
2422
  }
2378
2423
  /**
2379
2424
  * Converts an offer to a snake case object.
@@ -2427,8 +2472,8 @@ function random$1(config) {
2427
2472
  const collateralCandidates = config?.collateralTokens ? config.collateralTokens.filter((a) => a !== loanToken) : [address()];
2428
2473
  const collateralAsset = collateralCandidates[int(collateralCandidates.length)];
2429
2474
  const maturityOption = weightedChoice([["end_of_month", 1], ["end_of_next_month", 1]]);
2430
- const maturity$1 = config?.maturity ?? from$15(maturityOption);
2431
- const lltv = from$17(weightedChoice([
2475
+ const maturity = config?.maturity ?? from$16(maturityOption);
2476
+ const lltv = from$18(weightedChoice([
2432
2477
  [.385, 1],
2433
2478
  [.5, 1],
2434
2479
  [.625, 2],
@@ -2467,15 +2512,15 @@ function random$1(config) {
2467
2512
  })
2468
2513
  };
2469
2514
  })();
2470
- return from$12({
2515
+ return from$13({
2471
2516
  maker: config?.maker ?? address(),
2472
2517
  assets: assetsScaled,
2473
2518
  obligationUnits: config?.obligationUnits ?? 0n,
2474
2519
  obligationShares: config?.obligationShares ?? 0n,
2475
2520
  price,
2476
- maturity: maturity$1,
2477
- expiry: config?.expiry ?? maturity$1 - 1,
2478
- start: config?.start ?? maturity$1 - 10,
2521
+ maturity,
2522
+ expiry: config?.expiry ?? maturity - 1,
2523
+ start: config?.start ?? maturity - 10,
2479
2524
  group: config?.group ?? hex(32),
2480
2525
  session: config?.session ?? hex(32),
2481
2526
  buy,
@@ -2602,15 +2647,15 @@ const types = {
2602
2647
  * @param wallet - The wallet to sign the offers with.
2603
2648
  * @returns The signed offers.
2604
2649
  */
2605
- async function sign(offers$1, wallet) {
2650
+ async function sign(offers, wallet) {
2606
2651
  if (!wallet.account) throw new AccountNotSetError();
2607
2652
  return wallet.signMessage({
2608
2653
  account: wallet.account,
2609
- message: { raw: signatureMsg(offers$1) }
2654
+ message: { raw: signatureMsg(offers) }
2610
2655
  });
2611
2656
  }
2612
- function signatureMsg(offers$1) {
2613
- return from$13(offers$1).root;
2657
+ function signatureMsg(offers) {
2658
+ return from$14(offers).root;
2614
2659
  }
2615
2660
  function hash(offer) {
2616
2661
  const cached = offer[HASH_CACHE];
@@ -2648,7 +2693,7 @@ function hash(offer) {
2648
2693
  * @returns The obligation id as a 32-byte hex string.
2649
2694
  */
2650
2695
  function obligationId(offer) {
2651
- return id(from$14({
2696
+ return id(from$15({
2652
2697
  chainId: offer.chainId,
2653
2698
  loanToken: offer.loanToken,
2654
2699
  collaterals: offer.collaterals,
@@ -2764,13 +2809,13 @@ function decode(data) {
2764
2809
  } catch (error) {
2765
2810
  throw new InvalidOfferError(error);
2766
2811
  }
2767
- return from$12({
2812
+ return from$13({
2768
2813
  maker: decoded[0],
2769
2814
  assets: decoded[1],
2770
2815
  obligationUnits: decoded[2],
2771
2816
  obligationShares: decoded[3],
2772
2817
  price: decoded[4],
2773
- maturity: from$15(Number(decoded[5])),
2818
+ maturity: from$16(Number(decoded[5])),
2774
2819
  expiry: Number(decoded[6]),
2775
2820
  group: decoded[7],
2776
2821
  session: decoded[8],
@@ -2779,7 +2824,7 @@ function decode(data) {
2779
2824
  loanToken: decoded[11],
2780
2825
  start: Number(decoded[12]),
2781
2826
  collaterals: decoded[13].map((c) => {
2782
- return from$16({
2827
+ return from$17({
2783
2828
  asset: c.asset,
2784
2829
  oracle: c.oracle,
2785
2830
  lltv: c.lltv
@@ -2852,16 +2897,16 @@ var AccountNotSetError = class extends BaseError {
2852
2897
 
2853
2898
  //#endregion
2854
2899
  //#region src/core/Oracle.ts
2855
- var Oracle_exports = /* @__PURE__ */ __export({
2900
+ var Oracle_exports = /* @__PURE__ */ __exportAll({
2856
2901
  Conversion: () => Conversion,
2857
- from: () => from$11
2902
+ from: () => from$12
2858
2903
  });
2859
2904
  /**
2860
2905
  * Create an Oracle from a plain object.
2861
2906
  * @param data - The data to create the oracle from.
2862
2907
  * @returns The created oracle.
2863
2908
  */
2864
- function from$11(data) {
2909
+ function from$12(data) {
2865
2910
  return {
2866
2911
  chainId: data.chainId,
2867
2912
  address: data.address.toLowerCase(),
@@ -2884,14 +2929,14 @@ let Conversion;
2884
2929
 
2885
2930
  //#endregion
2886
2931
  //#region src/core/Position.ts
2887
- var Position_exports = /* @__PURE__ */ __export({
2932
+ var Position_exports = /* @__PURE__ */ __exportAll({
2888
2933
  Type: () => Type,
2889
- from: () => from$10
2934
+ from: () => from$11
2890
2935
  });
2891
- let Type = /* @__PURE__ */ function(Type$1) {
2892
- Type$1["ERC20"] = "erc20";
2893
- Type$1["VAULT_V1"] = "vault_v1";
2894
- return Type$1;
2936
+ let Type = /* @__PURE__ */ function(Type) {
2937
+ Type["ERC20"] = "erc20";
2938
+ Type["VAULT_V1"] = "vault_v1";
2939
+ return Type;
2895
2940
  }({});
2896
2941
  /**
2897
2942
  * @constructor
@@ -2899,7 +2944,7 @@ let Type = /* @__PURE__ */ function(Type$1) {
2899
2944
  * @param parameters - {@link from.Parameters}
2900
2945
  * @returns The created Position. {@link from.ReturnType}
2901
2946
  */
2902
- function from$10(parameters) {
2947
+ function from$11(parameters) {
2903
2948
  return {
2904
2949
  chainId: parameters.chainId,
2905
2950
  contract: parameters.contract.toLowerCase(),
@@ -2913,10 +2958,10 @@ function from$10(parameters) {
2913
2958
 
2914
2959
  //#endregion
2915
2960
  //#region src/core/Quote.ts
2916
- var Quote_exports = /* @__PURE__ */ __export({
2961
+ var Quote_exports = /* @__PURE__ */ __exportAll({
2917
2962
  InvalidQuoteError: () => InvalidQuoteError,
2918
2963
  QuoteSchema: () => QuoteSchema,
2919
- from: () => from$9,
2964
+ from: () => from$10,
2920
2965
  fromSnakeCase: () => fromSnakeCase,
2921
2966
  random: () => random
2922
2967
  });
@@ -2937,7 +2982,7 @@ const QuoteSchema = z$1.object({
2937
2982
  * const quote = Quote.from({ obligationId: "0x123", ask: { price: 100n }, bid: { price: 100n } });
2938
2983
  * ```
2939
2984
  */
2940
- function from$9(parameters) {
2985
+ function from$10(parameters) {
2941
2986
  try {
2942
2987
  const parsedQuote = QuoteSchema.parse(parameters);
2943
2988
  return {
@@ -2956,7 +3001,7 @@ function from$9(parameters) {
2956
3001
  * @returns The created quote. {@link fromSnakeCase.ReturnType}
2957
3002
  */
2958
3003
  function fromSnakeCase(snake) {
2959
- return from$9(fromSnakeCase$3(snake));
3004
+ return from$10(fromSnakeCase$3(snake));
2960
3005
  }
2961
3006
  /**
2962
3007
  * Generates a random quote.
@@ -2968,7 +3013,7 @@ function fromSnakeCase(snake) {
2968
3013
  * ```
2969
3014
  */
2970
3015
  function random() {
2971
- return from$9({
3016
+ return from$10({
2972
3017
  obligationId: id(random$2()),
2973
3018
  ask: { price: BigInt(int(1e6)) },
2974
3019
  bid: { price: BigInt(int(1e6)) }
@@ -2981,9 +3026,158 @@ var InvalidQuoteError = class extends BaseError {
2981
3026
  }
2982
3027
  };
2983
3028
 
3029
+ //#endregion
3030
+ //#region src/core/TradingFee.ts
3031
+ var TradingFee_exports = /* @__PURE__ */ __exportAll({
3032
+ BREAKPOINTS: () => BREAKPOINTS,
3033
+ InvalidFeeError: () => InvalidFeeError,
3034
+ InvalidFeesLengthError: () => InvalidFeesLengthError,
3035
+ WAD: () => WAD,
3036
+ activate: () => activate,
3037
+ compute: () => compute,
3038
+ deactivate: () => deactivate,
3039
+ from: () => from$9,
3040
+ getFees: () => getFees,
3041
+ isActivated: () => isActivated
3042
+ });
3043
+ /**
3044
+ * Time breakpoints in seconds for piecewise linear fee interpolation.
3045
+ * Matches on-chain constants: 0d, 1d, 7d, 30d, 90d, 180d.
3046
+ */
3047
+ const BREAKPOINTS = [
3048
+ 0n,
3049
+ 86400n,
3050
+ 604800n,
3051
+ 2592000n,
3052
+ 7776000n,
3053
+ 15552000n
3054
+ ];
3055
+ /** WAD constant (1e18) for fee scaling. */
3056
+ const WAD = 10n ** 18n;
3057
+ /**
3058
+ * Create a TradingFee from an activation flag and 6 fee values.
3059
+ * @param activated - Whether the fee is active.
3060
+ * @param fees - Tuple of 6 fee values in WAD (one per breakpoint: 0d, 1d, 7d, 30d, 90d, 180d).
3061
+ * @returns A new TradingFee instance.
3062
+ * @throws {@link InvalidFeeError} if any fee exceeds WAD (100%).
3063
+ * @throws {@link InvalidFeesLengthError} if fees array doesn't have exactly 6 elements.
3064
+ */
3065
+ function from$9(activated, fees) {
3066
+ if (fees.length !== 6) throw new InvalidFeesLengthError(fees.length);
3067
+ for (let i = 0; i < 6; i++) {
3068
+ const fee = fees[i];
3069
+ if (fee < 0n || fee > WAD) throw new InvalidFeeError(fee, i);
3070
+ }
3071
+ const frozenFees = Object.freeze([...fees]);
3072
+ return Object.freeze({
3073
+ _activated: activated,
3074
+ _fees: frozenFees
3075
+ });
3076
+ }
3077
+ /**
3078
+ * Compute the trading fee for a given time to maturity using piecewise linear interpolation.
3079
+ * @param tradingFee - The TradingFee instance.
3080
+ * @param timeToMaturity - Time to maturity in seconds.
3081
+ * @returns The interpolated fee in WAD. Returns 0n if not activated.
3082
+ */
3083
+ function compute(tradingFee, timeToMaturity) {
3084
+ if (!tradingFee._activated) return 0n;
3085
+ const time = BigInt(Math.max(0, Math.floor(timeToMaturity)));
3086
+ if (time >= BREAKPOINTS[5]) return tradingFee._fees[5];
3087
+ const { index, start, end } = getSegment(time);
3088
+ const feeLower = tradingFee._fees[index];
3089
+ const feeUpper = tradingFee._fees[index + 1];
3090
+ const segmentLength = end - start;
3091
+ return (feeLower * (end - time) + feeUpper * (time - start)) / segmentLength;
3092
+ }
3093
+ /**
3094
+ * Check if the trading fee is activated.
3095
+ * @param tradingFee - The TradingFee instance.
3096
+ * @returns True if activated, false otherwise.
3097
+ */
3098
+ function isActivated(tradingFee) {
3099
+ return tradingFee._activated;
3100
+ }
3101
+ /**
3102
+ * Create a new TradingFee with activation enabled.
3103
+ * @param tradingFee - The TradingFee instance.
3104
+ * @returns A new TradingFee with activated set to true.
3105
+ */
3106
+ function activate(tradingFee) {
3107
+ return Object.freeze({
3108
+ _activated: true,
3109
+ _fees: tradingFee._fees
3110
+ });
3111
+ }
3112
+ /**
3113
+ * Create a new TradingFee with activation disabled.
3114
+ * @param tradingFee - The TradingFee instance.
3115
+ * @returns A new TradingFee with activated set to false.
3116
+ */
3117
+ function deactivate(tradingFee) {
3118
+ return Object.freeze({
3119
+ _activated: false,
3120
+ _fees: tradingFee._fees
3121
+ });
3122
+ }
3123
+ /**
3124
+ * Get the fee values at each breakpoint.
3125
+ * @param tradingFee - The TradingFee instance.
3126
+ * @returns The tuple of 6 fee values.
3127
+ */
3128
+ function getFees(tradingFee) {
3129
+ return tradingFee._fees;
3130
+ }
3131
+ /**
3132
+ * Determine which segment a timeToMaturity falls into for interpolation.
3133
+ * @param timeToMaturity - Time to maturity in seconds.
3134
+ * @returns Object with index, start, and end of the segment.
3135
+ */
3136
+ function getSegment(timeToMaturity) {
3137
+ if (timeToMaturity < BREAKPOINTS[1]) return {
3138
+ index: 0,
3139
+ start: BREAKPOINTS[0],
3140
+ end: BREAKPOINTS[1]
3141
+ };
3142
+ if (timeToMaturity < BREAKPOINTS[2]) return {
3143
+ index: 1,
3144
+ start: BREAKPOINTS[1],
3145
+ end: BREAKPOINTS[2]
3146
+ };
3147
+ if (timeToMaturity < BREAKPOINTS[3]) return {
3148
+ index: 2,
3149
+ start: BREAKPOINTS[2],
3150
+ end: BREAKPOINTS[3]
3151
+ };
3152
+ if (timeToMaturity < BREAKPOINTS[4]) return {
3153
+ index: 3,
3154
+ start: BREAKPOINTS[3],
3155
+ end: BREAKPOINTS[4]
3156
+ };
3157
+ return {
3158
+ index: 4,
3159
+ start: BREAKPOINTS[4],
3160
+ end: BREAKPOINTS[5]
3161
+ };
3162
+ }
3163
+ /** Error thrown when a fee value is invalid (negative or exceeds WAD). */
3164
+ var InvalidFeeError = class extends BaseError {
3165
+ name = "TradingFee.InvalidFeeError";
3166
+ constructor(fee, index) {
3167
+ super(`Invalid fee at index ${index}: ${fee}. Fee must be between 0 and ${WAD} (WAD).`);
3168
+ }
3169
+ };
3170
+ /** Error thrown when fees array doesn't have exactly 6 elements. */
3171
+ var InvalidFeesLengthError = class extends BaseError {
3172
+ name = "TradingFee.InvalidFeesLengthError";
3173
+ constructor(length) {
3174
+ super(`Invalid fees length: ${length}. Expected exactly 6 fee values.`);
3175
+ }
3176
+ };
3177
+
2984
3178
  //#endregion
2985
3179
  //#region src/core/Transfer.ts
2986
- var Transfer_exports = /* @__PURE__ */ __export({ from: () => from$8 });
3180
+ var Transfer_exports = /* @__PURE__ */ __exportAll({ from: () => from$8 });
2987
3181
  /**
2988
3182
  * @constructor
2989
3183
  *
@@ -3218,10 +3412,13 @@ async function* collectOffersV2(parameters) {
3218
3412
  });
3219
3413
  totalValidOffers += tree.offers.length;
3220
3414
  } catch (err) {
3415
+ const error = err instanceof Error ? err : new Error(String(err));
3221
3416
  logger.error({
3222
- err,
3223
- msg: "Failed to validate offers for tree"
3417
+ err: error,
3418
+ msg: "Gatekeeper validation failed",
3419
+ chain_id: client.chain.id
3224
3420
  });
3421
+ throw new Error("Gatekeeper validation failed", { cause: error });
3225
3422
  }
3226
3423
  if (treesToInsert.length > 0) await dbTx.trees.create(treesToInsert);
3227
3424
  try {
@@ -3295,14 +3492,14 @@ async function* collectOffersV2(parameters) {
3295
3492
  * @returns {@link fetchOraclePrices.ReturnType} mapping {@link Address} to `bigint` price.
3296
3493
  */
3297
3494
  async function fetchOraclePrices(parameters) {
3298
- const { client, oracles: oracles$1, options } = parameters;
3299
- if (oracles$1.length === 0) return /* @__PURE__ */ new Map();
3495
+ const { client, oracles, options } = parameters;
3496
+ if (oracles.length === 0) return /* @__PURE__ */ new Map();
3300
3497
  const batchSize = Math.max(1, options?.batchSize ?? 5e3);
3301
3498
  const retryAttempts = Math.max(1, options?.retryAttempts ?? 3);
3302
3499
  const retryDelayMs = Math.max(0, options?.retryDelayMs ?? 50);
3303
3500
  const blockNumber = options?.blockNumber ? BigInt(options.blockNumber) : void 0;
3304
3501
  const out = /* @__PURE__ */ new Map();
3305
- for (const oraclesBatch of batch$1(oracles$1, batchSize)) {
3502
+ for (const oraclesBatch of batch$1(oracles, batchSize)) {
3306
3503
  const priceCalls = [];
3307
3504
  for (const oracle of oraclesBatch) priceCalls.push({
3308
3505
  address: oracle,
@@ -3354,17 +3551,17 @@ async function snapshotERC20Positions(parameters) {
3354
3551
  retryAttempts,
3355
3552
  retryDelayMs
3356
3553
  });
3357
- const positions$1 = [];
3554
+ const positions = [];
3358
3555
  for (let i = 0; i < balances.length; i++) {
3359
3556
  const oldPosition = oldPositions[i];
3360
3557
  if (!oldPosition) continue;
3361
- positions$1.push({
3558
+ positions.push({
3362
3559
  ...oldPosition,
3363
3560
  balance: balances[i],
3364
3561
  blockNumber
3365
3562
  });
3366
3563
  }
3367
- return positions$1;
3564
+ return positions;
3368
3565
  }
3369
3566
 
3370
3567
  //#endregion
@@ -3381,8 +3578,8 @@ async function snapshotVaultPositions(parameters) {
3381
3578
  const { client, positions: oldPositions, blockNumber, options: { maxBatchSize = 1e3, retryAttempts = 5, retryDelayMs = 500 } = {} } = parameters;
3382
3579
  const calls = [];
3383
3580
  const contracts = /* @__PURE__ */ new Map();
3384
- const positions$1 = structuredClone(oldPositions);
3385
- for (const position of positions$1) {
3581
+ const positions = structuredClone(oldPositions);
3582
+ for (const position of positions) {
3386
3583
  calls.push({
3387
3584
  address: position.contract,
3388
3585
  abi: MetaMorpho,
@@ -3479,8 +3676,8 @@ async function snapshotVaultPositions(parameters) {
3479
3676
  break;
3480
3677
  }
3481
3678
  }
3482
- for (const convertToAssets$1 of convertToAssetsList) convertToAssets$1();
3483
- return positions$1;
3679
+ for (const convertToAssets of convertToAssetsList) convertToAssets();
3680
+ return positions;
3484
3681
  }
3485
3682
 
3486
3683
  //#endregion
@@ -3529,7 +3726,7 @@ async function* collectPositions(parameters) {
3529
3726
  abi: [TransferEvent],
3530
3727
  logs
3531
3728
  });
3532
- const transfers$1 = [];
3729
+ const transfers = [];
3533
3730
  for (const log of parsedLogs) {
3534
3731
  if (log.blockNumber === null || log.logIndex === null || log.transactionHash === null) {
3535
3732
  logger.debug({
@@ -3539,7 +3736,7 @@ async function* collectPositions(parameters) {
3539
3736
  });
3540
3737
  continue;
3541
3738
  }
3542
- transfers$1.push(from$8({
3739
+ transfers.push(from$8({
3543
3740
  id: `${client.chain.id}-${log.blockNumber.toString()}-${log.transactionHash}-${log.logIndex.toString()}`,
3544
3741
  chainId: client.chain.id,
3545
3742
  contract: log.address,
@@ -3549,14 +3746,14 @@ async function* collectPositions(parameters) {
3549
3746
  blockNumber: Number(log.blockNumber)
3550
3747
  }));
3551
3748
  }
3552
- const { positions: positions$1 } = await db.positions.get({
3749
+ const { positions } = await db.positions.get({
3553
3750
  chainId: client.chain.id,
3554
3751
  filled: false
3555
3752
  });
3556
3753
  const newPositions = [];
3557
3754
  try {
3558
3755
  newPositions.push(...(await _snapshot({
3559
- positions: positions$1,
3756
+ positions,
3560
3757
  blockNumber: latestBlockNumberChain,
3561
3758
  client,
3562
3759
  maxBatchSize,
@@ -3595,9 +3792,9 @@ async function* collectPositions(parameters) {
3595
3792
  }
3596
3793
  };
3597
3794
  const insertTransfers = async () => {
3598
- if (transfers$1.length === 0) return;
3795
+ if (transfers.length === 0) return;
3599
3796
  try {
3600
- const created = await dbTx.transfers.create(transfers$1);
3797
+ const created = await dbTx.transfers.create(transfers);
3601
3798
  logger.info({
3602
3799
  msg: `New transfers`,
3603
3800
  collector,
@@ -3651,7 +3848,7 @@ async function* collectPositions(parameters) {
3651
3848
  logger.error({
3652
3849
  msg: "Failed to insert transfers",
3653
3850
  collector,
3654
- count: transfers$1.length,
3851
+ count: transfers.length,
3655
3852
  chain_id: client.chain.id,
3656
3853
  block_number: blockNumber,
3657
3854
  err
@@ -3661,7 +3858,7 @@ async function* collectPositions(parameters) {
3661
3858
  }
3662
3859
  if (!reorgDetected) {
3663
3860
  startBlock = blockNumber;
3664
- if (newPositions.length === 0 && transfers$1.length === 0 && lastStreamBlockNumber !== latestBlockNumberChain) continue;
3861
+ if (newPositions.length === 0 && transfers.length === 0 && lastStreamBlockNumber !== latestBlockNumberChain) continue;
3665
3862
  yield blockNumber;
3666
3863
  continue;
3667
3864
  }
@@ -3711,10 +3908,10 @@ async function* collectPositions(parameters) {
3711
3908
  * @returns The new positions. {@link _snapshot.ReturnType}
3712
3909
  */
3713
3910
  async function _snapshot(parameters) {
3714
- const { positions: positions$1, blockNumber, client, maxBatchSize, retryAttempts, retryDelayMs } = parameters;
3911
+ const { positions, blockNumber, client, maxBatchSize, retryAttempts, retryDelayMs } = parameters;
3715
3912
  const vaultV1Positions = [];
3716
3913
  const erc20Positions = [];
3717
- for (const position of positions$1) switch (position.type) {
3914
+ for (const position of positions) switch (position.type) {
3718
3915
  case Type.VAULT_V1:
3719
3916
  vaultV1Positions.push(position);
3720
3917
  break;
@@ -3773,12 +3970,12 @@ async function* collectPrices(parameters) {
3773
3970
  const { db, collector, client, options: { maxBatchSize = 5e3, retryAttempts = 5, retryDelayMs = 500 } = {} } = parameters;
3774
3971
  const logger = getLogger();
3775
3972
  let blockNumber = parameters.lastBlockNumber;
3776
- const [oracles$1, { blockNumber: latestBlockNumberChain, epoch }] = await Promise.all([db.oracles.get({ chainId: client.chain.id }), db.blocks.getChain(client.chain.id)]);
3973
+ const [oracles, { blockNumber: latestBlockNumberChain, epoch }] = await Promise.all([db.oracles.get({ chainId: client.chain.id }), db.blocks.getChain(client.chain.id)]);
3777
3974
  const updatedOracles = [];
3778
3975
  try {
3779
3976
  const pricesMap = await fetchOraclePrices({
3780
3977
  client,
3781
- oracles: oracles$1.map((oracle) => oracle.address),
3978
+ oracles: oracles.map((oracle) => oracle.address),
3782
3979
  options: {
3783
3980
  batchSize: maxBatchSize,
3784
3981
  blockNumber: latestBlockNumberChain,
@@ -3786,7 +3983,7 @@ async function* collectPrices(parameters) {
3786
3983
  retryDelayMs
3787
3984
  }
3788
3985
  });
3789
- for (const oracle of oracles$1) {
3986
+ for (const oracle of oracles) {
3790
3987
  const price = pricesMap.get(oracle.address);
3791
3988
  if (price !== void 0) updatedOracles.push({
3792
3989
  chainId: client.chain.id,
@@ -3969,7 +4166,7 @@ const from$7 = (parameters) => {
3969
4166
 
3970
4167
  //#endregion
3971
4168
  //#region src/indexer/Indexer.ts
3972
- var Indexer_exports = /* @__PURE__ */ __export({
4169
+ var Indexer_exports = /* @__PURE__ */ __exportAll({
3973
4170
  create: () => create$14,
3974
4171
  from: () => from$6
3975
4172
  });
@@ -3997,10 +4194,10 @@ function from$6(config) {
3997
4194
  });
3998
4195
  }
3999
4196
  function create$14(params) {
4000
- const { collectors: collectors$1, client } = params;
4197
+ const { collectors, client } = params;
4001
4198
  const indexerId = `${client.chain.id.toString()}.indexer`;
4002
4199
  const tracer = getTracer(`router.${indexerId}`);
4003
- const iterators = collectors$1.map((collector) => collector.collect());
4200
+ const iterators = collectors.map((collector) => collector.collect());
4004
4201
  const next = async () => {
4005
4202
  await startActiveSpan(tracer, `${indexerId}.next`, async () => {
4006
4203
  await Promise.all(iterators.map((iterator) => iterator.next()));
@@ -4011,7 +4208,7 @@ function create$14(params) {
4011
4208
  };
4012
4209
  return {
4013
4210
  start: () => {
4014
- const stops = collectors$1.map((collector) => start(collector));
4211
+ const stops = collectors.map((collector) => start(collector));
4015
4212
  return () => {
4016
4213
  stops.forEach((stop) => {
4017
4214
  stop();
@@ -4025,7 +4222,7 @@ function create$14(params) {
4025
4222
 
4026
4223
  //#endregion
4027
4224
  //#region src/api/Health.ts
4028
- var Health_exports = /* @__PURE__ */ __export({ create: () => create$13 });
4225
+ var Health_exports = /* @__PURE__ */ __exportAll({ create: () => create$13 });
4029
4226
  const DEFAULT_MAX_ALLOWED_LAG = 5;
4030
4227
  /**
4031
4228
  * Create a health service that exposes collector and chain block numbers.
@@ -4063,26 +4260,26 @@ function create$13(parameters) {
4063
4260
  name
4064
4261
  }))).sort((a, b) => a.chainId === b.chainId ? a.name.localeCompare(b.name) : a.chainId - b.chainId);
4065
4262
  const initialized = knownChainIds.size > 0 && missingChains.length === 0 && missingCollectors.length === 0;
4066
- const collectors$1 = Array.from(knownChainIds).sort((a, b) => a - b > 0 ? 1 : -1).flatMap((chainId) => [...names].sort().map((name) => {
4263
+ const collectors = Array.from(knownChainIds).sort((a, b) => a - b > 0 ? 1 : -1).flatMap((chainId) => [...names].sort().map((name) => {
4067
4264
  const row = collectorsByKey.get(collectorKey(chainId, name));
4068
4265
  const chain = chainById.get(chainId);
4069
4266
  const blockNumber = row?.blockNumber ?? null;
4070
4267
  const chainBlockNumber = chain?.blockNumber ?? null;
4071
4268
  const lag = blockNumber !== null && chainBlockNumber !== null ? Math.max(chainBlockNumber - blockNumber, 0) : null;
4072
- let status$1 = "unknown";
4073
- if (lag !== null) status$1 = lag <= maxAllowedLag ? "live" : "lagging";
4074
- else if (chainBlockNumber !== null) status$1 = "lagging";
4269
+ let status = "unknown";
4270
+ if (lag !== null) status = lag <= maxAllowedLag ? "live" : "lagging";
4271
+ else if (chainBlockNumber !== null) status = "lagging";
4075
4272
  return {
4076
4273
  name,
4077
4274
  chainId,
4078
4275
  blockNumber,
4079
4276
  updatedAt: row ? row.updatedAt.toISOString() : null,
4080
4277
  lag,
4081
- status: status$1,
4278
+ status,
4082
4279
  initialized: row !== void 0
4083
4280
  };
4084
4281
  }));
4085
- const chains$3 = Array.from(knownChainIds).sort((a, b) => a - b > 0 ? 1 : -1).map((chainId) => {
4282
+ const chains = Array.from(knownChainIds).sort((a, b) => a - b > 0 ? 1 : -1).map((chainId) => {
4086
4283
  const chain = chainById.get(chainId);
4087
4284
  return {
4088
4285
  chainId,
@@ -4094,12 +4291,12 @@ function create$13(parameters) {
4094
4291
  };
4095
4292
  });
4096
4293
  return {
4097
- status: collectors$1.length > 0 && collectors$1.every((collector) => collector.status === "live") ? "live" : "syncing",
4294
+ status: collectors.length > 0 && collectors.every((collector) => collector.status === "live") ? "live" : "syncing",
4098
4295
  initialized,
4099
4296
  missingChains,
4100
4297
  missingCollectors,
4101
- collectors: collectors$1,
4102
- chains: chains$3
4298
+ collectors,
4299
+ chains
4103
4300
  };
4104
4301
  };
4105
4302
  return {
@@ -4142,7 +4339,7 @@ async function getRemoteBlockNumbers(healthClients) {
4142
4339
 
4143
4340
  //#endregion
4144
4341
  //#region src/api/Schema/BookResponse.ts
4145
- var BookResponse_exports = /* @__PURE__ */ __export({ from: () => from$5 });
4342
+ var BookResponse_exports = /* @__PURE__ */ __exportAll({ from: () => from$5 });
4146
4343
  function from$5(level) {
4147
4344
  return {
4148
4345
  price: level.price.toString(),
@@ -4187,7 +4384,7 @@ const RouterStatusResponse = z.object({
4187
4384
 
4188
4385
  //#endregion
4189
4386
  //#region src/api/Schema/ObligationResponse.ts
4190
- var ObligationResponse_exports = /* @__PURE__ */ __export({ from: () => from$4 });
4387
+ var ObligationResponse_exports = /* @__PURE__ */ __exportAll({ from: () => from$4 });
4191
4388
  /**
4192
4389
  * Creates an `ObligationResponse` from a `Obligation`.
4193
4390
  * @constructor
@@ -4212,7 +4409,7 @@ function from$4(obligation, quote) {
4212
4409
 
4213
4410
  //#endregion
4214
4411
  //#region src/api/Schema/OfferResponse.ts
4215
- var OfferResponse_exports = /* @__PURE__ */ __export({ from: () => from$3 });
4412
+ var OfferResponse_exports = /* @__PURE__ */ __exportAll({ from: () => from$3 });
4216
4413
  /**
4217
4414
  * Creates an `OfferResponse` matching the Solidity Offer struct layout.
4218
4415
  * @constructor
@@ -4220,7 +4417,7 @@ var OfferResponse_exports = /* @__PURE__ */ __export({ from: () => from$3 });
4220
4417
  * @returns The created `OfferResponse`. {@link OfferResponse}
4221
4418
  */
4222
4419
  function from$3(input) {
4223
- const base$1 = {
4420
+ const base = {
4224
4421
  offer: {
4225
4422
  obligation: {
4226
4423
  loan_token: input.loanToken,
@@ -4257,13 +4454,13 @@ function from$3(input) {
4257
4454
  block_number: input.blockNumber
4258
4455
  };
4259
4456
  if (!input.proof || !input.root || !input.signature) return {
4260
- ...base$1,
4457
+ ...base,
4261
4458
  root: null,
4262
4459
  proof: null,
4263
4460
  signature: null
4264
4461
  };
4265
4462
  return {
4266
- ...base$1,
4463
+ ...base,
4267
4464
  root: input.root.toLowerCase(),
4268
4465
  proof: input.proof.map((p) => p.toLowerCase()),
4269
4466
  signature: input.signature.toLowerCase()
@@ -4278,12 +4475,12 @@ const API_ERROR_CODES = [
4278
4475
  "INTERNAL_SERVER_ERROR",
4279
4476
  "BAD_REQUEST"
4280
4477
  ];
4281
- let STATUS_CODE = /* @__PURE__ */ function(STATUS_CODE$1) {
4282
- STATUS_CODE$1[STATUS_CODE$1["SUCCESS"] = 200] = "SUCCESS";
4283
- STATUS_CODE$1[STATUS_CODE$1["BAD_REQUEST"] = 400] = "BAD_REQUEST";
4284
- STATUS_CODE$1[STATUS_CODE$1["NOT_FOUND"] = 404] = "NOT_FOUND";
4285
- STATUS_CODE$1[STATUS_CODE$1["INTERNAL_SERVER_ERROR"] = 500] = "INTERNAL_SERVER_ERROR";
4286
- return STATUS_CODE$1;
4478
+ let STATUS_CODE = /* @__PURE__ */ function(STATUS_CODE) {
4479
+ STATUS_CODE[STATUS_CODE["SUCCESS"] = 200] = "SUCCESS";
4480
+ STATUS_CODE[STATUS_CODE["BAD_REQUEST"] = 400] = "BAD_REQUEST";
4481
+ STATUS_CODE[STATUS_CODE["NOT_FOUND"] = 404] = "NOT_FOUND";
4482
+ STATUS_CODE[STATUS_CODE["INTERNAL_SERVER_ERROR"] = 500] = "INTERNAL_SERVER_ERROR";
4483
+ return STATUS_CODE;
4287
4484
  }({});
4288
4485
  var APIError = class extends Error {
4289
4486
  constructor(statusCode, message, code, details) {
@@ -4369,7 +4566,7 @@ function handleZodError(error) {
4369
4566
  }
4370
4567
 
4371
4568
  //#endregion
4372
- //#region \0@oxc-project+runtime@0.97.0/helpers/decorate.js
4569
+ //#region \0@oxc-project+runtime@0.110.0/helpers/decorate.js
4373
4570
  function __decorate(decorators, target, key, desc) {
4374
4571
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4375
4572
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -4990,7 +5187,7 @@ __decorate([ApiProperty({
4990
5187
  type: () => [BookLevelResponse],
4991
5188
  description: "Aggregated book levels grouped by computed price."
4992
5189
  })], BookListResponse.prototype, "data", void 0);
4993
- let BooksController = class BooksController$1 {
5190
+ let BooksController = class BooksController {
4994
5191
  async getBook() {}
4995
5192
  };
4996
5193
  __decorate([
@@ -5036,7 +5233,7 @@ BooksController = __decorate([ApiTags("Markets"), ApiResponse({
5036
5233
  description: "Bad Request",
5037
5234
  type: BadRequestResponse
5038
5235
  })], BooksController);
5039
- let ValidateController = class ValidateController$1 {
5236
+ let ValidateController = class ValidateController {
5040
5237
  async validateOffers() {}
5041
5238
  };
5042
5239
  __decorate([
@@ -5063,7 +5260,7 @@ ValidateController = __decorate([ApiTags("Make"), ApiResponse({
5063
5260
  description: "Bad Request",
5064
5261
  type: BadRequestResponse
5065
5262
  })], ValidateController);
5066
- let OffersController = class OffersController$1 {
5263
+ let OffersController = class OffersController {
5067
5264
  async getOffers() {}
5068
5265
  };
5069
5266
  __decorate([
@@ -5118,7 +5315,7 @@ OffersController = __decorate([ApiTags("Markets"), ApiResponse({
5118
5315
  description: "Bad Request",
5119
5316
  type: BadRequestResponse
5120
5317
  })], OffersController);
5121
- let HealthController = class HealthController$1 {
5318
+ let HealthController = class HealthController {
5122
5319
  async getRouterStatus() {}
5123
5320
  async getCollectorsHealth() {}
5124
5321
  async getChainsHealth() {}
@@ -5184,31 +5381,17 @@ __decorate([
5184
5381
  })
5185
5382
  ], HealthController.prototype, "getChainsHealth", null);
5186
5383
  HealthController = __decorate([ApiTags("System")], HealthController);
5187
- const maturitiesExample = {
5188
- end_of_month: 1738335600,
5189
- end_of_next_month: 1740754800
5190
- };
5384
+ const callbacksExample = [Type$1.BuyWithEmptyCallback];
5191
5385
  const chainConfigExample = {
5192
5386
  chain_id: 505050505,
5193
5387
  contracts: { mempool: "0xD946246695A9259F3B33a78629026F61B3Ab40aF" },
5194
- maturities: maturitiesExample
5388
+ callbacks: callbacksExample
5195
5389
  };
5196
5390
  var ConfigContractsResponse = class {};
5197
5391
  __decorate([ApiProperty({
5198
5392
  type: "string",
5199
5393
  example: chainConfigExample.contracts.mempool
5200
5394
  })], ConfigContractsResponse.prototype, "mempool", void 0);
5201
- var MaturitiesResponse = class {};
5202
- __decorate([ApiProperty({
5203
- type: "number",
5204
- description: "Unix timestamp for end of current month maturity (last Friday 15:00 UTC).",
5205
- example: maturitiesExample.end_of_month
5206
- })], MaturitiesResponse.prototype, "end_of_month", void 0);
5207
- __decorate([ApiProperty({
5208
- type: "number",
5209
- description: "Unix timestamp for end of next month maturity (last Friday 15:00 UTC).",
5210
- example: maturitiesExample.end_of_next_month
5211
- })], MaturitiesResponse.prototype, "end_of_next_month", void 0);
5212
5395
  var ConfigDataResponse = class {};
5213
5396
  __decorate([ApiProperty({
5214
5397
  type: "number",
@@ -5216,10 +5399,11 @@ __decorate([ApiProperty({
5216
5399
  })], ConfigDataResponse.prototype, "chain_id", void 0);
5217
5400
  __decorate([ApiProperty({ type: () => ConfigContractsResponse })], ConfigDataResponse.prototype, "contracts", void 0);
5218
5401
  __decorate([ApiProperty({
5219
- type: () => MaturitiesResponse,
5220
- description: "Supported maturity timestamps. Offers must use one of these values.",
5221
- example: chainConfigExample.maturities
5222
- })], ConfigDataResponse.prototype, "maturities", void 0);
5402
+ type: () => [String],
5403
+ enum: Object.values(Type$1),
5404
+ description: "Supported callback types for this chain.",
5405
+ example: callbacksExample
5406
+ })], ConfigDataResponse.prototype, "callbacks", void 0);
5223
5407
  var ConfigSuccessResponse = class extends SuccessResponse {};
5224
5408
  __decorate([ApiProperty({
5225
5409
  type: "string",
@@ -5231,21 +5415,21 @@ __decorate([ApiProperty({
5231
5415
  description: "Array of chain configurations for all indexed chains.",
5232
5416
  example: [chainConfigExample]
5233
5417
  })], ConfigSuccessResponse.prototype, "data", void 0);
5234
- let ConfigController = class ConfigController$1 {
5418
+ let ConfigController = class ConfigController {
5235
5419
  async getConfig() {}
5236
5420
  };
5237
5421
  __decorate([ApiOperation({
5238
5422
  methods: ["get"],
5239
5423
  path: "/v1/config",
5240
5424
  summary: "Get router configuration",
5241
- description: "Returns chain configurations including contract addresses and supported maturity timestamps."
5425
+ description: "Returns chain configurations including contract addresses and supported callback types."
5242
5426
  }), ApiResponse({
5243
5427
  status: 200,
5244
5428
  description: "Success",
5245
5429
  type: ConfigSuccessResponse
5246
5430
  })], ConfigController.prototype, "getConfig", null);
5247
5431
  ConfigController = __decorate([ApiTags("System")], ConfigController);
5248
- let ObligationsController = class ObligationsController$1 {
5432
+ let ObligationsController = class ObligationsController {
5249
5433
  async getObligations() {}
5250
5434
  async getObligation() {}
5251
5435
  };
@@ -5269,32 +5453,40 @@ __decorate([
5269
5453
  description: "Maximum number of obligations to return."
5270
5454
  }),
5271
5455
  ApiQuery({
5272
- name: "chain",
5273
- type: "number",
5456
+ name: "chains",
5457
+ type: ["number"],
5274
5458
  required: false,
5275
- example: 1,
5276
- description: "Filter by chain ID."
5459
+ example: "1,8453",
5460
+ description: "Filter by chain IDs (comma-separated).",
5461
+ style: "form",
5462
+ explode: false
5277
5463
  }),
5278
5464
  ApiQuery({
5279
- name: "loan_token",
5280
- type: "string",
5465
+ name: "loan_tokens",
5466
+ type: ["string"],
5281
5467
  required: false,
5282
- example: "0xC9A9C45C0eB717f8b5F193Af6bAa05A1c0Ac5078",
5283
- description: "Filter by loan token address."
5468
+ example: "0xC9A9C45C0eB717f8b5F193Af6bAa05A1c0Ac5078,0x34Cf890dB685FC536E05652FB41f02090c3fb751",
5469
+ description: "Filter by loan token addresses (comma-separated).",
5470
+ style: "form",
5471
+ explode: false
5284
5472
  }),
5285
5473
  ApiQuery({
5286
- name: "collateral_token",
5287
- type: "string",
5474
+ name: "collateral_tokens",
5475
+ type: ["string"],
5288
5476
  required: false,
5289
- example: "0x34Cf890dB685FC536E05652FB41f02090c3fb751",
5290
- description: "Filter by collateral token (matches any collateral in the obligation)."
5477
+ example: "0x34Cf890dB685FC536E05652FB41f02090c3fb751,0xC9A9C45C0eB717f8b5F193Af6bAa05A1c0Ac5078",
5478
+ description: "Filter by collateral tokens (comma-separated, matches any collateral).",
5479
+ style: "form",
5480
+ explode: false
5291
5481
  }),
5292
5482
  ApiQuery({
5293
- name: "maturity",
5294
- type: "number",
5483
+ name: "maturities",
5484
+ type: ["number"],
5295
5485
  required: false,
5296
- example: 1761922800,
5297
- description: "Filter by exact maturity timestamp (unix seconds)."
5486
+ example: "1761922800,1764524800",
5487
+ description: "Filter by exact maturity timestamps (comma-separated, unix seconds).",
5488
+ style: "form",
5489
+ explode: false
5298
5490
  }),
5299
5491
  ApiResponse({
5300
5492
  status: 200,
@@ -5326,7 +5518,7 @@ ObligationsController = __decorate([ApiTags("Markets"), ApiResponse({
5326
5518
  description: "Bad Request",
5327
5519
  type: BadRequestResponse
5328
5520
  })], ObligationsController);
5329
- let UsersController = class UsersController$1 {
5521
+ let UsersController = class UsersController {
5330
5522
  async getUserPositions() {}
5331
5523
  };
5332
5524
  __decorate([
@@ -5416,7 +5608,7 @@ const OpenApi = async (options = {}) => {
5416
5608
 
5417
5609
  //#endregion
5418
5610
  //#region src/api/Schema/PositionResponse.ts
5419
- var PositionResponse_exports = /* @__PURE__ */ __export({ from: () => from$2 });
5611
+ var PositionResponse_exports = /* @__PURE__ */ __exportAll({ from: () => from$2 });
5420
5612
  /**
5421
5613
  * Creates a `PositionResponse` from a `PositionWithReserved`.
5422
5614
  * @param position - {@link PositionWithReserved}
@@ -5447,6 +5639,15 @@ function isValidBase64urlJson(val) {
5447
5639
  return false;
5448
5640
  }
5449
5641
  }
5642
+ const csvArray = (schema) => z$1.preprocess((value) => {
5643
+ if (value === void 0) return void 0;
5644
+ if (Array.isArray(value)) {
5645
+ if (value.some((item) => typeof item !== "string")) return value;
5646
+ return value.flatMap((item) => item.split(",")).map((item) => item.trim()).filter((item) => item.length > 0);
5647
+ }
5648
+ if (typeof value === "string") return value.split(",").map((item) => item.trim()).filter((item) => item.length > 0);
5649
+ return value;
5650
+ }, z$1.array(schema)).optional();
5450
5651
  const PaginationQueryParams = z$1.object({
5451
5652
  cursor: z$1.string().optional().refine((val) => {
5452
5653
  if (!val) return true;
@@ -5497,21 +5698,21 @@ const GetObligationsQueryParams = z$1.object({
5497
5698
  description: "Obligation id cursor",
5498
5699
  example: "0x1234567890123456789012345678901234567890123456789012345678901234"
5499
5700
  }),
5500
- chain: z$1.string().regex(/^[1-9]\d*$/, { message: "Chain must be a positive integer" }).transform((val) => Number.parseInt(val, 10)).optional().meta({
5501
- description: "Filter by chain ID",
5502
- example: "1"
5701
+ chains: csvArray(z$1.string().regex(/^[1-9]\d*$/, { message: "Chain must be a positive integer" }).transform((val) => Number.parseInt(val, 10))).meta({
5702
+ description: "Filter by chain IDs (comma-separated).",
5703
+ example: "1,8453"
5503
5704
  }),
5504
- loan_token: z$1.string().regex(/^0x[a-fA-F0-9]{40}$/, { error: "Loan token must be a valid 20-byte address" }).transform((val) => val.toLowerCase()).optional().meta({
5505
- description: "Filter by loan token address",
5506
- example: "0xC9A9C45C0eB717f8b5F193Af6bAa05A1c0Ac5078"
5705
+ loan_tokens: csvArray(z$1.string().regex(/^0x[a-fA-F0-9]{40}$/, { error: "Loan token must be a valid 20-byte address" }).transform((val) => val.toLowerCase())).meta({
5706
+ description: "Filter by loan token addresses (comma-separated).",
5707
+ example: "0xC9A9C45C0eB717f8b5F193Af6bAa05A1c0Ac5078,0x34Cf890dB685FC536E05652FB41f02090c3fb751"
5507
5708
  }),
5508
- collateral_token: z$1.string().regex(/^0x[a-fA-F0-9]{40}$/, { error: "Collateral token must be a valid 20-byte address" }).transform((val) => val.toLowerCase()).optional().meta({
5509
- description: "Filter by collateral token (matches any collateral in the obligation)",
5510
- example: "0x34Cf890dB685FC536E05652FB41f02090c3fb751"
5709
+ collateral_tokens: csvArray(z$1.string().regex(/^0x[a-fA-F0-9]{40}$/, { error: "Collateral token must be a valid 20-byte address" }).transform((val) => val.toLowerCase())).meta({
5710
+ description: "Filter by collateral tokens (comma-separated, matches any collateral).",
5711
+ example: "0x34Cf890dB685FC536E05652FB41f02090c3fb751,0xC9A9C45C0eB717f8b5F193Af6bAa05A1c0Ac5078"
5511
5712
  }),
5512
- maturity: z$1.string().regex(/^[1-9]\d*$/, { message: "Maturity must be a positive integer" }).transform((val) => Number.parseInt(val, 10)).optional().meta({
5513
- description: "Filter by exact maturity timestamp (unix seconds)",
5514
- example: "1761922800"
5713
+ maturities: csvArray(z$1.string().regex(/^[1-9]\d*$/, { message: "Maturity must be a positive integer" }).transform((val) => Number.parseInt(val, 10))).meta({
5714
+ description: "Filter by exact maturity timestamps (comma-separated, unix seconds).",
5715
+ example: "1761922800,1764524800"
5515
5716
  })
5516
5717
  });
5517
5718
  const GetObligationParams = z$1.object({ obligation_id: z$1.string({ error: "Obligation id is required and must be a valid 32-byte hex string" }).regex(/^0x[a-fA-F0-9]{64}$/, { error: "Obligation id must be a valid 32-byte hex string" }).transform((val) => val.toLowerCase()).meta({
@@ -5624,18 +5825,14 @@ async function getBook(params, db) {
5624
5825
  * @returns The configuration for all chains the router is indexing. {@link ApiPayload.Payload<ChainConfig[]>}
5625
5826
  */
5626
5827
  async function getConfig(chainRegistry) {
5627
- const maturities = {
5628
- end_of_month: from$15(MaturityType.EndOfMonth),
5629
- end_of_next_month: from$15(MaturityType.EndOfNextMonth)
5630
- };
5631
- const configs$1 = [];
5632
- for (const chain of chainRegistry.list()) configs$1.push({
5828
+ const configs = [];
5829
+ for (const chain of chainRegistry.list()) configs.push({
5633
5830
  chain_id: chain.id,
5634
5831
  contracts: { mempool: chain.custom.mempool.address },
5635
- maturities
5832
+ callbacks: chain.custom.callbacks.map((c) => c.type)
5636
5833
  });
5637
- configs$1.sort((a, b) => a.chain_id - b.chain_id);
5638
- return success({ data: configs$1 });
5834
+ configs.sort((a, b) => a.chain_id - b.chain_id);
5835
+ return success({ data: configs });
5639
5836
  }
5640
5837
 
5641
5838
  //#endregion
@@ -5651,17 +5848,24 @@ const parse_error_Description = {
5651
5848
  name: "parse_error",
5652
5849
  description: "Returns when an offer fails to parse due to invalid format or missing required fields"
5653
5850
  };
5654
- const getGatekeeperRules = (gatekeeper) => {
5655
- return [parse_error_Description, ...gatekeeper.rules.map((rule) => ({
5656
- name: rule.name,
5657
- description: rule.description
5658
- }))];
5851
+ const getGatekeeperRules = async (gatekeeper) => {
5852
+ return [parse_error_Description, ...await gatekeeper.getRules()];
5659
5853
  };
5854
+ /**
5855
+ * Build the OpenAPI document for the router.
5856
+ * @param parameters - Includes a {@link RulesProvider} to fetch gatekeeper rules.
5857
+ * @returns OpenAPI document. {@link OpenAPIDocument}
5858
+ */
5660
5859
  async function getSwaggerJson({ gatekeeper }) {
5661
- return OpenApi({ rules: getGatekeeperRules(gatekeeper) });
5860
+ return OpenApi({ rules: await getGatekeeperRules(gatekeeper) });
5662
5861
  }
5862
+ /**
5863
+ * Render the API documentation HTML page.
5864
+ * @param parameters - Includes a {@link RulesProvider} to fetch gatekeeper rules.
5865
+ * @returns HTML page as string.
5866
+ */
5663
5867
  async function getDocsHtml({ gatekeeper }) {
5664
- const spec = await OpenApi({ rules: getGatekeeperRules(gatekeeper) });
5868
+ const spec = await OpenApi({ rules: await getGatekeeperRules(gatekeeper) });
5665
5869
  return `<!DOCTYPE html>
5666
5870
  <html>
5667
5871
  <head>
@@ -5766,8 +5970,8 @@ async function getHealthChains(query, db, healthClients, chainRegistry) {
5766
5970
  missingChains: snapshot.missingChains,
5767
5971
  missingCollectors: snapshot.missingCollectors
5768
5972
  })));
5769
- const chains$3 = snapshot.chains;
5770
- return success({ data: chains$3.map(({ chainId, localBlockNumber, remoteBlockNumber, updatedAt, initialized }) => toSnakeCase$1({
5973
+ const chains = snapshot.chains;
5974
+ return success({ data: chains.map(({ chainId, localBlockNumber, remoteBlockNumber, updatedAt, initialized }) => toSnakeCase$1({
5771
5975
  chainId,
5772
5976
  localBlockNumber,
5773
5977
  remoteBlockNumber,
@@ -5797,14 +6001,14 @@ async function getHealthCollectors(query, db, chainRegistry) {
5797
6001
  missingChains: snapshot.missingChains,
5798
6002
  missingCollectors: snapshot.missingCollectors
5799
6003
  })));
5800
- const collectors$1 = snapshot.collectors;
5801
- return success({ data: collectors$1.map(({ name, chainId, blockNumber, updatedAt, lag, status: status$1, initialized }) => toSnakeCase$1({
6004
+ const collectors = snapshot.collectors;
6005
+ return success({ data: collectors.map(({ name, chainId, blockNumber, updatedAt, lag, status, initialized }) => toSnakeCase$1({
5802
6006
  name,
5803
6007
  chainId,
5804
6008
  blockNumber,
5805
6009
  updatedAt,
5806
6010
  lag,
5807
- status: status$1,
6011
+ status,
5808
6012
  initialized
5809
6013
  })) });
5810
6014
  } catch (err) {
@@ -5826,9 +6030,9 @@ async function getObligation(params, db) {
5826
6030
  if (!result.success) return failure(result.error);
5827
6031
  const query = result.data;
5828
6032
  try {
5829
- const { obligations: obligations$1 } = await db.offers.getObligations({ ids: [query.obligation_id] });
5830
- if (obligations$1.length === 0) return failure(new NotFoundError("Obligation not found"));
5831
- const obligation = obligations$1[0];
6033
+ const { obligations } = await db.offers.getObligations({ ids: [query.obligation_id] });
6034
+ if (obligations.length === 0) return failure(new NotFoundError("Obligation not found"));
6035
+ const obligation = obligations[0];
5832
6036
  const [quote] = await db.offers.getQuotes({ obligationIds: [id(obligation)] });
5833
6037
  return success({
5834
6038
  data: from$4(obligation, quote ?? {
@@ -5857,17 +6061,21 @@ async function getObligations$1(queryParameters, db) {
5857
6061
  if (!result.success) return failure(result.error);
5858
6062
  const query = result.data;
5859
6063
  try {
5860
- const { obligations: obligations$1, nextCursor } = await db.offers.getObligations({
6064
+ const chainIds = query.chains?.length ? query.chains : void 0;
6065
+ const loanTokens = query.loan_tokens?.length ? query.loan_tokens : void 0;
6066
+ const collateralTokens = query.collateral_tokens?.length ? query.collateral_tokens : void 0;
6067
+ const maturities = query.maturities?.length ? query.maturities : void 0;
6068
+ const { obligations, nextCursor } = await db.offers.getObligations({
5861
6069
  cursor: query.cursor,
5862
6070
  limit: query.limit,
5863
- chainId: query.chain,
5864
- loanToken: query.loan_token,
5865
- collateralToken: query.collateral_token,
5866
- maturity: query.maturity
6071
+ chainId: chainIds,
6072
+ loanToken: loanTokens,
6073
+ collateralToken: collateralTokens,
6074
+ maturity: maturities
5867
6075
  });
5868
- const quotes = await db.offers.getQuotes({ obligationIds: obligations$1.map((o) => id(o)) });
6076
+ const quotes = await db.offers.getQuotes({ obligationIds: obligations.map((o) => id(o)) });
5869
6077
  return success({
5870
- data: obligations$1.map((o) => from$4(o, quotes.find((q) => q.obligationId === id(o)) ?? {
6078
+ data: obligations.map((o) => from$4(o, quotes.find((q) => q.obligationId === id(o)) ?? {
5871
6079
  obligationId: id(o),
5872
6080
  ask: { price: 0n },
5873
6081
  bid: { price: 0n }
@@ -5907,8 +6115,8 @@ async function getOffers$1(queryParameters, db) {
5907
6115
  const attestationMap = await db.trees.getAttestations(hashes);
5908
6116
  return success({
5909
6117
  data: rows.map((row) => {
5910
- const hash$1 = hash(row);
5911
- const attestation = attestationMap.get(hash$1);
6118
+ const hash$2 = hash(row);
6119
+ const attestation = attestationMap.get(hash$2);
5912
6120
  return from$3({
5913
6121
  ...row,
5914
6122
  ...attestation
@@ -5941,13 +6149,13 @@ async function getUserPositions(queryParameters, db) {
5941
6149
  if (!result.success) return failure(result.error);
5942
6150
  const query = result.data;
5943
6151
  try {
5944
- const { positions: positions$1, nextCursor } = await db.positions.getByUser({
6152
+ const { positions, nextCursor } = await db.positions.getByUser({
5945
6153
  user: query.user_address,
5946
6154
  cursor: query.cursor,
5947
6155
  limit: query.limit
5948
6156
  });
5949
6157
  return success({
5950
- data: positions$1.map((position) => from$2(position)),
6158
+ data: positions.map((position) => from$2(position)),
5951
6159
  cursor: nextCursor ?? null
5952
6160
  });
5953
6161
  } catch (err) {
@@ -5989,10 +6197,10 @@ async function validateOffers(body, gatekeeper) {
5989
6197
  const { issues } = await gatekeeper.isAllowed(parsedOffers);
5990
6198
  if (issues.length > 0) {
5991
6199
  const mappedIssues = issues.map((issue) => {
5992
- const index$1 = offerIndexByHash.get(hash(issue.item));
5993
- if (index$1 === void 0) return null;
6200
+ const index = offerIndexByHash.get(hash(issue.item));
6201
+ if (index === void 0) return null;
5994
6202
  return {
5995
- index: index$1,
6203
+ index,
5996
6204
  rule: issue.ruleName,
5997
6205
  message: issue.message
5998
6206
  };
@@ -6002,7 +6210,7 @@ async function validateOffers(body, gatekeeper) {
6002
6210
  cursor: null
6003
6211
  });
6004
6212
  }
6005
- const tree = from$13(parsedOffers);
6213
+ const tree = from$14(parsedOffers);
6006
6214
  const payload = encodeUnsigned(tree);
6007
6215
  return success({
6008
6216
  data: {
@@ -6024,7 +6232,7 @@ async function validateOffers(body, gatekeeper) {
6024
6232
 
6025
6233
  //#endregion
6026
6234
  //#region src/api/Controllers/index.ts
6027
- var Controllers_exports = /* @__PURE__ */ __export({
6235
+ var Controllers_exports = /* @__PURE__ */ __exportAll({
6028
6236
  getBook: () => getBook,
6029
6237
  getConfig: () => getConfig,
6030
6238
  getDocsHtml: () => getDocsHtml,
@@ -6089,8 +6297,8 @@ function serve$1(parameters) {
6089
6297
  return c.json(body, statusCode);
6090
6298
  });
6091
6299
  app.get("/v1/obligations/:obligationId", async (c) => {
6092
- const id$1 = c.req.param("obligationId");
6093
- const { statusCode, body } = await getObligation({ obligation_id: id$1 }, db);
6300
+ const id = c.req.param("obligationId");
6301
+ const { statusCode, body } = await getObligation({ obligation_id: id }, db);
6094
6302
  return c.json(body, statusCode);
6095
6303
  });
6096
6304
  app.get("/v1/books/:obligationId/:side", async (c) => {
@@ -6104,9 +6312,14 @@ function serve$1(parameters) {
6104
6312
  return c.json(body, statusCode);
6105
6313
  });
6106
6314
  app.post("/v1/validate", async (c) => {
6107
- const reqBody = await c.req.json();
6108
- const { statusCode, body } = await validateOffers(reqBody, gatekeeper);
6109
- return c.json(body, statusCode);
6315
+ try {
6316
+ const reqBody = await c.req.json();
6317
+ const { statusCode, body } = await gatekeeper.validate(reqBody);
6318
+ return c.json(body, statusCode);
6319
+ } catch (err) {
6320
+ const failure$1 = failure(err);
6321
+ return c.json(failure$1.body, failure$1.statusCode);
6322
+ }
6110
6323
  });
6111
6324
  app.get("/v1/users/:userAddress/positions", async (c) => {
6112
6325
  const query = c.req.query();
@@ -6144,7 +6357,7 @@ function serve$1(parameters) {
6144
6357
 
6145
6358
  //#endregion
6146
6359
  //#region src/api/RouterApi.ts
6147
- var RouterApi_exports = /* @__PURE__ */ __export({
6360
+ var RouterApi_exports = /* @__PURE__ */ __exportAll({
6148
6361
  BookResponse: () => BookResponse_exports,
6149
6362
  BooksController: () => BooksController,
6150
6363
  ChainHealth: () => ChainHealth,
@@ -6171,7 +6384,7 @@ var RouterApi_exports = /* @__PURE__ */ __export({
6171
6384
 
6172
6385
  //#endregion
6173
6386
  //#region src/client/Client.ts
6174
- var Client_exports = /* @__PURE__ */ __export({
6387
+ var Client_exports$1 = /* @__PURE__ */ __exportAll({
6175
6388
  HttpForbiddenError: () => HttpForbiddenError,
6176
6389
  HttpGetApiFailedError: () => HttpGetApiFailedError,
6177
6390
  HttpRateLimitError: () => HttpRateLimitError,
@@ -6204,12 +6417,16 @@ function connect$2(parameters) {
6204
6417
  };
6205
6418
  const apiClient = createOpenApiFetchClient({
6206
6419
  baseUrl: config.url.toString(),
6207
- headers: config.headers
6420
+ headers: config.headers,
6421
+ querySerializer: { array: {
6422
+ style: "form",
6423
+ explode: false
6424
+ } }
6208
6425
  });
6209
6426
  return {
6210
6427
  ...config,
6211
- getOffers: (parameters$1) => getOffers(apiClient, parameters$1),
6212
- getObligations: (parameters$1) => getObligations(apiClient, parameters$1)
6428
+ getOffers: (parameters) => getOffers(apiClient, parameters),
6429
+ getObligations: (parameters) => getObligations(apiClient, parameters)
6213
6430
  };
6214
6431
  }
6215
6432
  async function getOffers(apiClient, parameters) {
@@ -6227,7 +6444,7 @@ async function getOffers(apiClient, parameters) {
6227
6444
  }
6228
6445
  throw new HttpGetApiFailedError(`GET request returned ${response.status}`, { details: JSON.stringify(error) });
6229
6446
  }
6230
- const offers$1 = data?.data.map((item) => {
6447
+ const offers = data?.data.map((item) => {
6231
6448
  const { root, proof, signature, offer: offerData } = item;
6232
6449
  return {
6233
6450
  ...fromSnakeCase$1({
@@ -6236,7 +6453,7 @@ async function getOffers(apiClient, parameters) {
6236
6453
  obligation_units: offerData.obligation_units,
6237
6454
  obligation_shares: offerData.obligation_shares,
6238
6455
  price: offerData.price,
6239
- maturity: from$15(offerData.obligation.maturity),
6456
+ maturity: from$16(offerData.obligation.maturity),
6240
6457
  expiry: offerData.expiry,
6241
6458
  start: offerData.start,
6242
6459
  group: offerData.group,
@@ -6265,17 +6482,17 @@ async function getOffers(apiClient, parameters) {
6265
6482
  }) ?? [];
6266
6483
  return {
6267
6484
  cursor: data?.cursor ?? null,
6268
- offers: offers$1
6485
+ offers
6269
6486
  };
6270
6487
  }
6271
6488
  async function getObligations(apiClient, parameters) {
6272
6489
  const { data, error, response } = await apiClient.GET("/v1/obligations", { params: { query: {
6273
6490
  cursor: parameters?.cursor,
6274
6491
  limit: parameters?.limit,
6275
- chain: parameters?.chainId,
6276
- loan_token: parameters?.loanToken,
6277
- collateral_token: parameters?.collateralToken,
6278
- maturity: parameters?.maturity
6492
+ chains: parameters?.chainIds,
6493
+ loan_tokens: parameters?.loanTokens,
6494
+ collateral_tokens: parameters?.collateralTokens,
6495
+ maturities: parameters?.maturities
6279
6496
  } } });
6280
6497
  if (error !== void 0) {
6281
6498
  switch (response.status) {
@@ -6285,7 +6502,7 @@ async function getObligations(apiClient, parameters) {
6285
6502
  }
6286
6503
  throw new HttpGetApiFailedError(`GET request returned ${response.status}`, { details: JSON.stringify(error) });
6287
6504
  }
6288
- const obligations$1 = data?.data.map((item) => {
6505
+ const obligations = data?.data.map((item) => {
6289
6506
  const obligation = fromSnakeCase$2({
6290
6507
  chain_id: item.chain_id,
6291
6508
  loan_token: item.loan_token,
@@ -6294,7 +6511,7 @@ async function getObligations(apiClient, parameters) {
6294
6511
  oracle: collateral.oracle,
6295
6512
  lltv: collateral.lltv
6296
6513
  })),
6297
- maturity: from$15(item.maturity)
6514
+ maturity: from$16(item.maturity)
6298
6515
  });
6299
6516
  const { obligationId: _, ...returned } = {
6300
6517
  id: () => id(obligation),
@@ -6309,7 +6526,7 @@ async function getObligations(apiClient, parameters) {
6309
6526
  }) ?? [];
6310
6527
  return {
6311
6528
  cursor: data?.cursor ?? null,
6312
- obligations: obligations$1
6529
+ obligations
6313
6530
  };
6314
6531
  }
6315
6532
  var InvalidUrlError = class extends BaseError {
@@ -6349,7 +6566,7 @@ const VERSION = "router_v1.6";
6349
6566
 
6350
6567
  //#endregion
6351
6568
  //#region src/database/drizzle/schema.ts
6352
- var schema_exports = /* @__PURE__ */ __export({
6569
+ var schema_exports = /* @__PURE__ */ __exportAll({
6353
6570
  PositionTypes: () => PositionTypes,
6354
6571
  StatusCode: () => StatusCode,
6355
6572
  TABLE_NAMES: () => TABLE_NAMES,
@@ -6375,25 +6592,25 @@ var schema_exports = /* @__PURE__ */ __export({
6375
6592
  validations: () => validations
6376
6593
  });
6377
6594
  const s = pgSchema(VERSION);
6378
- var EnumTableName = /* @__PURE__ */ function(EnumTableName$1) {
6379
- EnumTableName$1["OBLIGATIONS"] = "obligations";
6380
- EnumTableName$1["GROUPS"] = "groups";
6381
- EnumTableName$1["CONSUMED_EVENTS"] = "consumed_events";
6382
- EnumTableName$1["OBLIGATION_COLLATERALS_V2"] = "obligation_collaterals_v2";
6383
- EnumTableName$1["ORACLES"] = "oracles";
6384
- EnumTableName$1["OFFERS"] = "offers";
6385
- EnumTableName$1["OFFERS_CALLBACKS"] = "offers_callbacks";
6386
- EnumTableName$1["CALLBACKS"] = "callbacks";
6387
- EnumTableName$1["POSITIONS"] = "positions";
6388
- EnumTableName$1["TRANSFERS"] = "transfers";
6389
- EnumTableName$1["VALIDATIONS"] = "validations";
6390
- EnumTableName$1["COLLECTORS"] = "collectors";
6391
- EnumTableName$1["CHAINS"] = "chains";
6392
- EnumTableName$1["LOTS"] = "lots";
6393
- EnumTableName$1["OFFSETS"] = "offsets";
6394
- EnumTableName$1["TREES"] = "trees";
6395
- EnumTableName$1["MERKLE_PATHS"] = "merkle_paths";
6396
- return EnumTableName$1;
6595
+ var EnumTableName = /* @__PURE__ */ function(EnumTableName) {
6596
+ EnumTableName["OBLIGATIONS"] = "obligations";
6597
+ EnumTableName["GROUPS"] = "groups";
6598
+ EnumTableName["CONSUMED_EVENTS"] = "consumed_events";
6599
+ EnumTableName["OBLIGATION_COLLATERALS_V2"] = "obligation_collaterals_v2";
6600
+ EnumTableName["ORACLES"] = "oracles";
6601
+ EnumTableName["OFFERS"] = "offers";
6602
+ EnumTableName["OFFERS_CALLBACKS"] = "offers_callbacks";
6603
+ EnumTableName["CALLBACKS"] = "callbacks";
6604
+ EnumTableName["POSITIONS"] = "positions";
6605
+ EnumTableName["TRANSFERS"] = "transfers";
6606
+ EnumTableName["VALIDATIONS"] = "validations";
6607
+ EnumTableName["COLLECTORS"] = "collectors";
6608
+ EnumTableName["CHAINS"] = "chains";
6609
+ EnumTableName["LOTS"] = "lots";
6610
+ EnumTableName["OFFSETS"] = "offsets";
6611
+ EnumTableName["TREES"] = "trees";
6612
+ EnumTableName["MERKLE_PATHS"] = "merkle_paths";
6613
+ return EnumTableName;
6397
6614
  }(EnumTableName || {});
6398
6615
  const TABLE_NAMES = Object.values(EnumTableName);
6399
6616
  const VERSIONED_TABLE_NAMES = TABLE_NAMES.map((table) => `"${VERSION}"."${table}"`);
@@ -6750,7 +6967,7 @@ const merklePaths = s.table(EnumTableName.MERKLE_PATHS, {
6750
6967
 
6751
6968
  //#endregion
6752
6969
  //#region src/database/drizzle/index.ts
6753
- var drizzle_exports = /* @__PURE__ */ __export({
6970
+ var drizzle_exports = /* @__PURE__ */ __exportAll({
6754
6971
  PositionTypes: () => PositionTypes,
6755
6972
  StatusCode: () => StatusCode,
6756
6973
  TABLE_NAMES: () => TABLE_NAMES,
@@ -6782,7 +6999,7 @@ var drizzle_exports = /* @__PURE__ */ __export({
6782
6999
  /** Postgres implementation. */
6783
7000
  const create$11 = (config) => {
6784
7001
  const { db, chainRegistry } = config;
6785
- const getChain$1 = async (chainId) => {
7002
+ const getChain = async (chainId) => {
6786
7003
  const rows = await db.select({
6787
7004
  chainId: chains$1.chainId,
6788
7005
  blockNumber: chains$1.blockNumber,
@@ -6928,26 +7145,26 @@ const create$11 = (config) => {
6928
7145
  epoch
6929
7146
  });
6930
7147
  const collectorStates = await Promise.all(collectorNames.map(async (collectorName) => {
6931
- const { blockNumber: blockNumber$1, epoch: epoch$1 } = await getCollector({
7148
+ const { blockNumber, epoch } = await getCollector({
6932
7149
  chainId,
6933
7150
  collectorName
6934
7151
  });
6935
7152
  return {
6936
7153
  collectorName,
6937
- blockNumber: blockNumber$1,
6938
- epoch: epoch$1
7154
+ blockNumber,
7155
+ epoch
6939
7156
  };
6940
7157
  }));
6941
- await Promise.all(collectorStates.map(({ collectorName, blockNumber: blockNumber$1 }) => advanceCollector({
7158
+ await Promise.all(collectorStates.map(({ collectorName, blockNumber }) => advanceCollector({
6942
7159
  collectorName,
6943
7160
  chainId,
6944
- blockNumber: Math.min(blockNumber$1, parameters.blockNumber),
7161
+ blockNumber: Math.min(blockNumber, parameters.blockNumber),
6945
7162
  epoch: parameters.epoch
6946
7163
  })));
6947
7164
  };
6948
7165
  return {
6949
7166
  init,
6950
- getChain: getChain$1,
7167
+ getChain,
6951
7168
  getCollector,
6952
7169
  getChains,
6953
7170
  getCollectors,
@@ -6964,8 +7181,8 @@ const MAX_TOTAL_OFFERS = 500;
6964
7181
  function create$10(config) {
6965
7182
  const db = config.db;
6966
7183
  const logger = getLogger();
6967
- const getOffers$2 = async (parameters) => {
6968
- const { side, obligationId: obligationId$1, cursor: cursorString } = parameters;
7184
+ const getOffers = async (parameters) => {
7185
+ const { side, obligationId, cursor: cursorString } = parameters;
6969
7186
  const requestedLimit = parameters.limit ?? DEFAULT_LIMIT$3;
6970
7187
  const priceSortDirection = side === "sell" ? "asc" : "desc";
6971
7188
  const inputCursor = Cursor.decode(cursorString, logger);
@@ -6974,16 +7191,16 @@ function create$10(config) {
6974
7191
  nextCursor: null
6975
7192
  };
6976
7193
  if (inputCursor != null && inputCursor.side !== side) throw new Error("Cursor does not match the current sort parameters");
6977
- const now$1 = inputCursor?.now ?? Math.floor(Date.now() / 1e3);
7194
+ const now = inputCursor?.now ?? Math.floor(Date.now() / 1e3);
6978
7195
  const previouslyReturned = inputCursor?.totalReturned ?? 0;
6979
7196
  if (previouslyReturned >= MAX_TOTAL_OFFERS) return {
6980
7197
  rows: [],
6981
7198
  nextCursor: null
6982
7199
  };
6983
7200
  const { rows, hasMore } = await _getOffers(db, {
6984
- obligationId: obligationId$1,
7201
+ obligationId,
6985
7202
  side,
6986
- now: now$1,
7203
+ now,
6987
7204
  priceSortDirection,
6988
7205
  cursor: inputCursor,
6989
7206
  limit: Math.min(requestedLimit, MAX_TOTAL_OFFERS - previouslyReturned)
@@ -6993,23 +7210,23 @@ function create$10(config) {
6993
7210
  const hasHitHardLimit = newTotalReturned >= MAX_TOTAL_OFFERS;
6994
7211
  return {
6995
7212
  rows,
6996
- nextCursor: rows.length > 0 && lastReturnedOffer && !hasHitHardLimit && hasMore ? Cursor.encode(lastReturnedOffer, newTotalReturned, now$1, side) : null
7213
+ nextCursor: rows.length > 0 && lastReturnedOffer && !hasHitHardLimit && hasMore ? Cursor.encode(lastReturnedOffer, newTotalReturned, now, side) : null
6997
7214
  };
6998
7215
  };
6999
7216
  return {
7000
7217
  get: async (parameters) => {
7001
- const { side, obligationId: obligationId$1, cursor: cursorString, limit = DEFAULT_LIMIT$3 } = parameters;
7218
+ const { side, obligationId, cursor: cursorString, limit = DEFAULT_LIMIT$3 } = parameters;
7002
7219
  const inputCursor = LevelCursor.decode(cursorString, logger);
7003
7220
  if (cursorString != null && inputCursor === null) return {
7004
7221
  levels: [],
7005
7222
  nextCursor: null
7006
7223
  };
7007
7224
  if (inputCursor != null && inputCursor.side !== side) throw new Error("Cursor does not match the current sort parameters");
7008
- const now$1 = inputCursor?.now ?? Math.floor(Date.now() / 1e3);
7225
+ const now = inputCursor?.now ?? Math.floor(Date.now() / 1e3);
7009
7226
  const fetchLimit = limit * 10;
7010
- const { rows, nextCursor: offersNextCursor } = await getOffers$2({
7227
+ const { rows, nextCursor: offersNextCursor } = await getOffers({
7011
7228
  side,
7012
- obligationId: obligationId$1,
7229
+ obligationId,
7013
7230
  cursor: inputCursor?.offersCursor ?? void 0,
7014
7231
  limit: fetchLimit
7015
7232
  });
@@ -7035,15 +7252,15 @@ function create$10(config) {
7035
7252
  const lastLevel = paginatedLevels[paginatedLevels.length - 1];
7036
7253
  return {
7037
7254
  levels: paginatedLevels,
7038
- nextCursor: hasMore && lastLevel ? LevelCursor.encode(lastLevel, offersNextCursor, side, now$1) : null
7255
+ nextCursor: hasMore && lastLevel ? LevelCursor.encode(lastLevel, offersNextCursor, side, now) : null
7039
7256
  };
7040
7257
  },
7041
- getOffers: getOffers$2
7258
+ getOffers
7042
7259
  };
7043
7260
  }
7044
7261
  /** Get offers with computed takeable based on lot balance. */
7045
7262
  async function _getOffers(db, params) {
7046
- const { obligationId: obligationId$1, side, now: now$1, priceSortDirection, cursor, limit } = params;
7263
+ const { obligationId, side, now, priceSortDirection, cursor, limit } = params;
7047
7264
  const raw = await db.execute(sql`
7048
7265
  WITH collats AS MATERIALIZED (
7049
7266
  SELECT oc.obligation_id,
@@ -7056,7 +7273,7 @@ async function _getOffers(db, params) {
7056
7273
  JOIN ${oracles} oracle
7057
7274
  ON oracle.chain_id = oc.oracle_chain_id
7058
7275
  AND oracle.address = oc.oracle_address
7059
- WHERE oc.obligation_id = ${obligationId$1}
7276
+ WHERE oc.obligation_id = ${obligationId}
7060
7277
  GROUP BY oc.obligation_id
7061
7278
  ),
7062
7279
  winners AS (
@@ -7067,11 +7284,11 @@ async function _getOffers(db, params) {
7067
7284
  ON v.offer_hash = o.hash
7068
7285
  LEFT JOIN ${status} s
7069
7286
  ON s.id = v.status_id
7070
- WHERE o.obligation_id = ${obligationId$1}
7287
+ WHERE o.obligation_id = ${obligationId}
7071
7288
  AND o.buy = ${side === "buy"}
7072
- AND o.expiry > ${now$1}
7073
- AND o.maturity > ${now$1}
7074
- AND o.start <= ${now$1}
7289
+ AND o.expiry > ${now}
7290
+ AND o.maturity > ${now}
7291
+ AND o.start <= ${now}
7075
7292
  AND (s.code IS NULL OR s.code = ${Status.VALID})
7076
7293
  ORDER BY
7077
7294
  o.group_chain_id, o.group_maker, o."group_group",
@@ -7350,7 +7567,7 @@ async function _getOffers(db, params) {
7350
7567
  }
7351
7568
  let Cursor;
7352
7569
  (function(_Cursor) {
7353
- function encode$3(row, totalReturned, now$1, side) {
7570
+ function encode(row, totalReturned, now, side) {
7354
7571
  return Buffer.from(JSON.stringify({
7355
7572
  side,
7356
7573
  price: row.price.toString(),
@@ -7358,11 +7575,11 @@ let Cursor;
7358
7575
  assets: row.assets.toString(),
7359
7576
  hash: row.hash,
7360
7577
  totalReturned,
7361
- now: now$1
7578
+ now
7362
7579
  })).toString("base64url");
7363
7580
  }
7364
- _Cursor.encode = encode$3;
7365
- function decode$3(cursorString, logger) {
7581
+ _Cursor.encode = encode;
7582
+ function decode(cursorString, logger) {
7366
7583
  if (cursorString == null) return null;
7367
7584
  const isNumericString = (value) => typeof value === "string" && /^-?\d+$/.test(value);
7368
7585
  try {
@@ -7378,20 +7595,20 @@ let Cursor;
7378
7595
  return null;
7379
7596
  }
7380
7597
  }
7381
- _Cursor.decode = decode$3;
7598
+ _Cursor.decode = decode;
7382
7599
  })(Cursor || (Cursor = {}));
7383
7600
  let LevelCursor;
7384
7601
  (function(_LevelCursor) {
7385
- function encode$3(lastLevel, offersCursor, side, now$1) {
7602
+ function encode(lastLevel, offersCursor, side, now) {
7386
7603
  return Buffer.from(JSON.stringify({
7387
7604
  side,
7388
7605
  lastPrice: lastLevel.price.toString(),
7389
- now: now$1,
7606
+ now,
7390
7607
  offersCursor
7391
7608
  })).toString("base64url");
7392
7609
  }
7393
- _LevelCursor.encode = encode$3;
7394
- function decode$3(cursorString, logger) {
7610
+ _LevelCursor.encode = encode;
7611
+ function decode(cursorString, logger) {
7395
7612
  if (cursorString == null) return null;
7396
7613
  const isNumericString = (value) => typeof value === "string" && /^-?\d+$/.test(value);
7397
7614
  try {
@@ -7407,7 +7624,7 @@ let LevelCursor;
7407
7624
  return null;
7408
7625
  }
7409
7626
  }
7410
- _LevelCursor.decode = decode$3;
7627
+ _LevelCursor.decode = decode;
7411
7628
  })(LevelCursor || (LevelCursor = {}));
7412
7629
 
7413
7630
  //#endregion
@@ -7449,7 +7666,7 @@ function create$9(db) {
7449
7666
  consumed: "0",
7450
7667
  blockNumber: group.blockNumber
7451
7668
  }));
7452
- for (const batch$2 of batch$1(groupsRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(groups).values(batch$2).onConflictDoNothing();
7669
+ for (const batch of batch$1(groupsRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(groups).values(batch).onConflictDoNothing();
7453
7670
  const eventsRows = events.map((event) => ({
7454
7671
  eventId: event.id,
7455
7672
  chainId: event.chainId,
@@ -7458,7 +7675,7 @@ function create$9(db) {
7458
7675
  amount: event.amount.toString(),
7459
7676
  blockNumber: event.blockNumber
7460
7677
  }));
7461
- for (const batch$2 of batch$1(eventsRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(consumedEvents).values(batch$2).onConflictDoNothing();
7678
+ for (const batch of batch$1(eventsRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(consumedEvents).values(batch).onConflictDoNothing();
7462
7679
  });
7463
7680
  },
7464
7681
  delete: async (parameters) => {
@@ -7513,9 +7730,96 @@ function create$8(db) {
7513
7730
  };
7514
7731
  }
7515
7732
 
7733
+ //#endregion
7734
+ //#region src/gatekeeper/Client.ts
7735
+ var Client_exports = /* @__PURE__ */ __exportAll({ createHttpClient: () => createHttpClient });
7736
+ const DEFAULT_TIMEOUT_MS = 1e4;
7737
+ /**
7738
+ * Create an HTTP client for a gatekeeper service.
7739
+ * @param config - Gatekeeper client configuration. {@link ClientConfig}
7740
+ * @returns An HTTP-backed gatekeeper client. {@link GatekeeperClient}
7741
+ */
7742
+ function createHttpClient(config) {
7743
+ const fetchFn = config.fetchFn ?? fetch;
7744
+ const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;
7745
+ const baseUrl = normalizeBaseUrl(config.baseUrl);
7746
+ const request = async (path, init) => {
7747
+ const controller = new AbortController();
7748
+ const timeout = setTimeout(() => controller.abort(), timeoutMs);
7749
+ try {
7750
+ return await fetchFn(`${baseUrl}${path}`, {
7751
+ ...init,
7752
+ signal: controller.signal
7753
+ });
7754
+ } finally {
7755
+ clearTimeout(timeout);
7756
+ }
7757
+ };
7758
+ const validate = async (body) => {
7759
+ const response = await request("/v1/validate", {
7760
+ method: "POST",
7761
+ headers: { "content-type": "application/json" },
7762
+ body: JSON.stringify(body)
7763
+ });
7764
+ const json = await response.json();
7765
+ return {
7766
+ statusCode: response.status,
7767
+ body: json
7768
+ };
7769
+ };
7770
+ const getRules = async () => {
7771
+ const response = await request("/v1/rules", { method: "GET" });
7772
+ const json = await response.json();
7773
+ if (!response.ok) throw new Error(`Gatekeeper rules request failed: ${extractErrorMessage(json) ?? response.statusText}`);
7774
+ if (!("data" in json) || !Array.isArray(json.data)) throw new Error("Gatekeeper rules response is invalid.");
7775
+ return json.data;
7776
+ };
7777
+ const isAllowed = async (offers) => {
7778
+ const { statusCode, body } = await validate({ offers: offers.map((offer) => toSnakeCase(offer)) });
7779
+ if (statusCode !== 200) {
7780
+ const errorMessage = extractErrorMessage(body);
7781
+ throw new Error(`Gatekeeper validation failed: ${errorMessage ?? `status ${statusCode}`}`);
7782
+ }
7783
+ const data = body.data;
7784
+ if (!data || typeof data !== "object") throw new Error("Gatekeeper validation response is invalid.");
7785
+ if ("issues" in data) {
7786
+ const issues = data.issues.map((issue) => ({
7787
+ ruleName: issue.rule,
7788
+ message: issue.message,
7789
+ item: offers[issue.index]
7790
+ }));
7791
+ const invalidIndices = new Set(data.issues.map((issue) => issue.index));
7792
+ return {
7793
+ valid: offers.filter((_, index) => !invalidIndices.has(index)),
7794
+ issues
7795
+ };
7796
+ }
7797
+ if (!("payload" in data) || !("root" in data)) throw new Error("Gatekeeper validation response is missing payload data.");
7798
+ return {
7799
+ valid: offers.slice(),
7800
+ issues: []
7801
+ };
7802
+ };
7803
+ return {
7804
+ baseUrl,
7805
+ validate,
7806
+ isAllowed,
7807
+ getRules
7808
+ };
7809
+ }
7810
+ function normalizeBaseUrl(url) {
7811
+ return url.trim().replace(/\/+$/, "");
7812
+ }
7813
+ function extractErrorMessage(payload) {
7814
+ if (!payload || typeof payload !== "object") return void 0;
7815
+ const error = payload.error;
7816
+ if (!error || typeof error !== "object") return void 0;
7817
+ return typeof error.message === "string" ? error.message : void 0;
7818
+ }
7819
+
7516
7820
  //#endregion
7517
7821
  //#region src/gatekeeper/Gate.ts
7518
- var Gate_exports = /* @__PURE__ */ __export({
7822
+ var Gate_exports = /* @__PURE__ */ __exportAll({
7519
7823
  batch: () => batch,
7520
7824
  run: () => run,
7521
7825
  single: () => single
@@ -7527,12 +7831,12 @@ var Gate_exports = /* @__PURE__ */ __export({
7527
7831
  * @param run - The function that validates the rule.
7528
7832
  * @returns The created rule.
7529
7833
  */
7530
- function single(name, description, run$1) {
7834
+ function single(name, description, run) {
7531
7835
  return {
7532
7836
  kind: "single",
7533
7837
  name,
7534
7838
  description,
7535
- run: run$1
7839
+ run
7536
7840
  };
7537
7841
  }
7538
7842
  /**
@@ -7542,12 +7846,12 @@ function single(name, description, run$1) {
7542
7846
  * @param run - The function that validates the rule.
7543
7847
  * @returns The created rule.
7544
7848
  */
7545
- function batch(name, description, run$1) {
7849
+ function batch(name, description, run) {
7546
7850
  return {
7547
7851
  kind: "batch",
7548
7852
  name,
7549
7853
  description,
7550
- run: run$1
7854
+ run
7551
7855
  };
7552
7856
  }
7553
7857
  async function run(parameters) {
@@ -7600,7 +7904,7 @@ async function run(parameters) {
7600
7904
 
7601
7905
  //#endregion
7602
7906
  //#region src/gatekeeper/GateConfig.ts
7603
- var GateConfig_exports = /* @__PURE__ */ __export({
7907
+ var GateConfig_exports = /* @__PURE__ */ __exportAll({
7604
7908
  assets: () => assets,
7605
7909
  configs: () => configs,
7606
7910
  getCallback: () => getCallback,
@@ -7626,8 +7930,8 @@ function getCallback(chain, type) {
7626
7930
  * @param address - Callback contract address
7627
7931
  * @returns The callback type when found, otherwise undefined
7628
7932
  */
7629
- function getCallbackType(chain, address$1) {
7630
- return configs[chain].callbacks?.find((c) => c.type !== CallbackType.BuyWithEmptyCallback && c.addresses.includes(address$1?.toLowerCase()))?.type;
7933
+ function getCallbackType(chain, address) {
7934
+ return configs[chain].callbacks?.find((c) => c.type !== Type$1.BuyWithEmptyCallback && c.addresses.includes(address?.toLowerCase()))?.type;
7631
7935
  }
7632
7936
  /**
7633
7937
  * Returns the callback addresses for a given chain and callback type, if it exists.
@@ -7636,7 +7940,7 @@ function getCallbackType(chain, address$1) {
7636
7940
  * @returns The matching callback addresses or an empty array if not configured
7637
7941
  */
7638
7942
  function getCallbackTypeAddresses(chain, type) {
7639
- if (type === CallbackType.BuyWithEmptyCallback) return [];
7943
+ if (type === Type$1.BuyWithEmptyCallback) return [];
7640
7944
  const match = configs[chain].callbacks?.find((c) => c.type === type);
7641
7945
  return match && "addresses" in match ? match.addresses : [];
7642
7946
  }
@@ -7647,7 +7951,7 @@ function getCallbackTypeAddresses(chain, type) {
7647
7951
  * @returns Array of allowed callback addresses (lowercased). Empty when none configured
7648
7952
  */
7649
7953
  const getCallbackAddresses = (chain) => {
7650
- return configs[chain].callbacks?.filter((c) => c.type !== CallbackType.BuyWithEmptyCallback).flatMap((c) => c.addresses) ?? [];
7954
+ return configs[chain].callbacks?.filter((c) => c.type !== Type$1.BuyWithEmptyCallback).flatMap((c) => c.addresses) ?? [];
7651
7955
  };
7652
7956
  const assets = {
7653
7957
  [ChainId.ETHEREUM.toString()]: [
@@ -7680,60 +7984,60 @@ const configs = {
7680
7984
  ethereum: {
7681
7985
  callbacks: [
7682
7986
  {
7683
- type: CallbackType.BuyVaultV1Callback,
7987
+ type: Type$1.BuyVaultV1Callback,
7684
7988
  addresses: ["0x3333333333333333333333333333333333333333", "0x4444444444444444444444444444444444444444"],
7685
7989
  vaultFactories: ["0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101", "0x1897A8997241C1cD4bD0698647e4EB7213535c24"]
7686
7990
  },
7687
7991
  {
7688
- type: CallbackType.SellERC20Callback,
7992
+ type: Type$1.SellERC20Callback,
7689
7993
  addresses: ["0x1111111111111111111111111111111111111111", "0x2222222222222222222222222222222222222222"]
7690
7994
  },
7691
- { type: CallbackType.BuyWithEmptyCallback }
7995
+ { type: Type$1.BuyWithEmptyCallback }
7692
7996
  ],
7693
7997
  maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth]
7694
7998
  },
7695
7999
  base: {
7696
8000
  callbacks: [
7697
8001
  {
7698
- type: CallbackType.BuyVaultV1Callback,
8002
+ type: Type$1.BuyVaultV1Callback,
7699
8003
  addresses: ["0x3333333333333333333333333333333333333333", "0x4444444444444444444444444444444444444444"],
7700
8004
  vaultFactories: ["0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101", "0xFf62A7c278C62eD665133147129245053Bbf5918"]
7701
8005
  },
7702
8006
  {
7703
- type: CallbackType.SellERC20Callback,
8007
+ type: Type$1.SellERC20Callback,
7704
8008
  addresses: ["0x1111111111111111111111111111111111111111", "0x2222222222222222222222222222222222222222"]
7705
8009
  },
7706
- { type: CallbackType.BuyWithEmptyCallback }
8010
+ { type: Type$1.BuyWithEmptyCallback }
7707
8011
  ],
7708
8012
  maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth]
7709
8013
  },
7710
8014
  "ethereum-virtual-testnet": {
7711
8015
  callbacks: [
7712
8016
  {
7713
- type: CallbackType.BuyVaultV1Callback,
8017
+ type: Type$1.BuyVaultV1Callback,
7714
8018
  addresses: ["0x3333333333333333333333333333333333333333", "0x4444444444444444444444444444444444444444"],
7715
8019
  vaultFactories: ["0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101", "0x1897A8997241C1cD4bD0698647e4EB7213535c24"]
7716
8020
  },
7717
8021
  {
7718
- type: CallbackType.SellERC20Callback,
8022
+ type: Type$1.SellERC20Callback,
7719
8023
  addresses: ["0x1111111111111111111111111111111111111111", "0x2222222222222222222222222222222222222222"]
7720
8024
  },
7721
- { type: CallbackType.BuyWithEmptyCallback }
8025
+ { type: Type$1.BuyWithEmptyCallback }
7722
8026
  ],
7723
8027
  maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth]
7724
8028
  },
7725
8029
  anvil: {
7726
8030
  callbacks: [
7727
8031
  {
7728
- type: CallbackType.BuyVaultV1Callback,
8032
+ type: Type$1.BuyVaultV1Callback,
7729
8033
  addresses: ["0x3333333333333333333333333333333333333333", "0x4444444444444444444444444444444444444444"],
7730
8034
  vaultFactories: ["0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101", "0x1897A8997241C1cD4bD0698647e4EB7213535c24"]
7731
8035
  },
7732
8036
  {
7733
- type: CallbackType.SellERC20Callback,
8037
+ type: Type$1.SellERC20Callback,
7734
8038
  addresses: ["0x1111111111111111111111111111111111111111", "0x2222222222222222222222222222222222222222"]
7735
8039
  },
7736
- { type: CallbackType.BuyWithEmptyCallback }
8040
+ { type: Type$1.BuyWithEmptyCallback }
7737
8041
  ],
7738
8042
  maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth]
7739
8043
  }
@@ -7741,22 +8045,31 @@ const configs = {
7741
8045
 
7742
8046
  //#endregion
7743
8047
  //#region src/gatekeeper/Gatekeeper.ts
7744
- var Gatekeeper_exports = /* @__PURE__ */ __export({ create: () => create$7 });
8048
+ var Gatekeeper_exports = /* @__PURE__ */ __exportAll({ create: () => create$7 });
8049
+ /**
8050
+ * Create a gatekeeper instance with the provided rules.
8051
+ * @param parameters - Gatekeeper parameters. {@link GatekeeperParameters}
8052
+ * @returns Gatekeeper instance. {@link Gatekeeper}
8053
+ */
7745
8054
  function create$7(parameters) {
8055
+ const { rules } = parameters;
7746
8056
  return {
7747
- rules: parameters.rules,
7748
- isAllowed: async (offers$1) => {
8057
+ isAllowed: async (offers) => {
7749
8058
  return await run({
7750
- items: offers$1,
7751
- rules: parameters.rules
8059
+ items: offers,
8060
+ rules
7752
8061
  });
7753
- }
8062
+ },
8063
+ getRules: async () => rules.map((rule) => ({
8064
+ name: rule.name,
8065
+ description: rule.description
8066
+ }))
7754
8067
  };
7755
8068
  }
7756
8069
 
7757
8070
  //#endregion
7758
8071
  //#region src/gatekeeper/Rules.ts
7759
- var Rules_exports = /* @__PURE__ */ __export({
8072
+ var Rules_exports = /* @__PURE__ */ __exportAll({
7760
8073
  amountMutualExclusivity: () => amountMutualExclusivity,
7761
8074
  callback: () => callback,
7762
8075
  chains: () => chains,
@@ -7775,21 +8088,21 @@ function validity(parameters) {
7775
8088
  const { client } = parameters;
7776
8089
  const sellErc20CallbackInvalid = single("sell_erc20_callback_invalid", "Validates that sell offers have valid ERC20 callback data matching offer collaterals", (offer) => {
7777
8090
  const callbackType = getCallbackType(client.chain.name, offer.callback.address);
7778
- if (callbackType !== CallbackType.SellERC20Callback) return;
8091
+ if (callbackType !== Type$1.SellERC20Callback) return;
7779
8092
  const decoded = decode$2(callbackType, offer.callback.data);
7780
8093
  if (decoded.length === 0) return { message: "Callback data cannot be decoded or is empty." };
7781
- if (callbackType === CallbackType.SellERC20Callback) {
8094
+ if (callbackType === Type$1.SellERC20Callback) {
7782
8095
  const offerCollaterals = new Set(offer.collaterals.map((c) => c.asset.toLowerCase()));
7783
8096
  if (decoded.length !== offer.collaterals.length) return { message: `Sell callback collateral length mismatch. Expected ${offer.collaterals.length}, got ${decoded.length}.` };
7784
8097
  for (const { contract } of decoded) if (!offerCollaterals.has(contract.toLowerCase())) return { message: "Sell callback collateral is not part of offer collaterals." };
7785
8098
  }
7786
8099
  });
7787
- const buyCallbackVaultInvalid = batch("buy_offers_callback_vault_invalid", "Validates that buy offers have valid vault callbacks registered in allowed factories with matching assets", async (offers$1) => {
8100
+ const buyCallbackVaultInvalid = batch("buy_offers_callback_vault_invalid", "Validates that buy offers have valid vault callbacks registered in allowed factories with matching assets", async (offers) => {
7788
8101
  const validationIssues = /* @__PURE__ */ new Map();
7789
8102
  const offersByVaultAddress = /* @__PURE__ */ new Map();
7790
- for (let i = 0; i < offers$1.length; i++) {
7791
- const offer = offers$1[i];
7792
- if (getCallbackType(client.chain.name, offer.callback.address) !== CallbackType.BuyVaultV1Callback) continue;
8103
+ for (let i = 0; i < offers.length; i++) {
8104
+ const offer = offers[i];
8105
+ if (getCallbackType(client.chain.name, offer.callback.address) !== Type$1.BuyVaultV1Callback) continue;
7793
8106
  try {
7794
8107
  const callbackVaults = decodeBuyVaultV1Callback(offer.callback.data);
7795
8108
  for (const { contract } of callbackVaults) {
@@ -7804,7 +8117,7 @@ function validity(parameters) {
7804
8117
  }
7805
8118
  const uniqueVaultAddresses = Array.from(offersByVaultAddress.keys());
7806
8119
  if (uniqueVaultAddresses.length === 0) return validationIssues;
7807
- const allowedFactories = getCallback(client.chain.name, CallbackType.BuyVaultV1Callback)?.vaultFactories.map((f) => f.toLowerCase());
8120
+ const allowedFactories = getCallback(client.chain.name, Type$1.BuyVaultV1Callback)?.vaultFactories.map((f) => f.toLowerCase());
7808
8121
  if (!allowedFactories) return validationIssues;
7809
8122
  const multicallContracts = [];
7810
8123
  for (const vaultAddress of uniqueVaultAddresses) {
@@ -7840,8 +8153,8 @@ function validity(parameters) {
7840
8153
  if (isRegisteredInFactory) registeredVaults.add(vaultAddress);
7841
8154
  }
7842
8155
  const uniqueOffers = /* @__PURE__ */ new Map();
7843
- for (const offersArray of offersByVaultAddress.values()) for (const { index: index$1, offer } of offersArray) uniqueOffers.set(index$1, offer);
7844
- for (const [index$1, offer] of uniqueOffers) try {
8156
+ for (const offersArray of offersByVaultAddress.values()) for (const { index, offer } of offersArray) uniqueOffers.set(index, offer);
8157
+ for (const [index, offer] of uniqueOffers) try {
7845
8158
  const callbackVaults = decodeBuyVaultV1Callback(offer.callback.data);
7846
8159
  const vaultsWithIssues = [];
7847
8160
  for (const { contract } of callbackVaults) {
@@ -7859,7 +8172,7 @@ function validity(parameters) {
7859
8172
  }
7860
8173
  if (vaultsWithIssues.length > 0) {
7861
8174
  const failureDetails = vaultsWithIssues.map((v) => `${v.vaultAddress} (${v.failureReasons})`).join("; ");
7862
- validationIssues.set(index$1, { message: `Buy offer callback vaults are invalid: ${failureDetails}` });
8175
+ validationIssues.set(index, { message: `Buy offer callback vaults are invalid: ${failureDetails}` });
7863
8176
  }
7864
8177
  } catch (_) {}
7865
8178
  return validationIssues;
@@ -7872,16 +8185,16 @@ function validity(parameters) {
7872
8185
  buyCallbackVaultInvalid
7873
8186
  ];
7874
8187
  }
7875
- const chains = ({ chains: chains$3 }) => single("chain_ids", `Validates that offer chain is one of: [${chains$3.map((c) => c.id).join(", ")}]`, (offer) => {
7876
- const allowedChainIds = chains$3.map((c) => c.id);
7877
- if (!allowedChainIds.some((id$1) => id$1 === offer.chainId)) return { message: `Chain ID ${offer.chainId} is not in the allowed chains (${allowedChainIds.join(", ")})` };
8188
+ const chains = ({ chains }) => single("chain_ids", `Validates that offer chain is one of: [${chains.map((c) => c.id).join(", ")}]`, (offer) => {
8189
+ const allowedChainIds = chains.map((c) => c.id);
8190
+ if (!allowedChainIds.some((id) => id === offer.chainId)) return { message: `Chain ID ${offer.chainId} is not in the allowed chains (${allowedChainIds.join(", ")})` };
7878
8191
  });
7879
8192
  const maturity = ({ maturities }) => single("maturity", `Validates that offer maturity is one of: [${maturities.join(", ")}]`, (offer) => {
7880
- const allowedMaturities = maturities.map((m) => from$15(m));
8193
+ const allowedMaturities = maturities.map((m) => from$16(m));
7881
8194
  if (!allowedMaturities.includes(offer.maturity)) return { message: `Maturity must be end of current month (${allowedMaturities[0]}) or end of next month (${allowedMaturities[1]}). Got: ${offer.maturity}` };
7882
8195
  });
7883
- const callback = ({ callbacks: callbacks$1, allowedAddresses }) => single("callback", `Validates callbacks: buy empty callback is ${callbacks$1.includes(CallbackType.BuyWithEmptyCallback) ? "allowed" : "not allowed"}; sell offers must use a non-empty callback; non-empty callbacks must target one of [${allowedAddresses.map((a) => a.toLowerCase()).join(", ")}]`, (offer) => {
7884
- if (isEmptyCallback(offer) && offer.buy && !callbacks$1?.find((c) => c === CallbackType.BuyWithEmptyCallback)) return { message: "Buy offers with empty callback not allowed." };
8196
+ const callback = ({ callbacks, allowedAddresses }) => single("callback", `Validates callbacks: buy empty callback is ${callbacks.includes(Type$1.BuyWithEmptyCallback) ? "allowed" : "not allowed"}; sell offers must use a non-empty callback; non-empty callbacks must target one of [${allowedAddresses.map((a) => a.toLowerCase()).join(", ")}]`, (offer) => {
8197
+ if (isEmptyCallback(offer) && offer.buy && !callbacks?.find((c) => c === Type$1.BuyWithEmptyCallback)) return { message: "Buy offers with empty callback not allowed." };
7885
8198
  if (isEmptyCallback(offer) && !offer.buy) return { message: "Sell offers require a non-empty callback." };
7886
8199
  if (!isEmptyCallback(offer)) {
7887
8200
  if (!allowedAddresses.includes(offer.callback.address?.toLowerCase())) return { message: `Callback address ${offer.callback.address} is not allowed.` };
@@ -7903,14 +8216,14 @@ const token = ({ assetsByChainId }) => single("token", "Validates that offer loa
7903
8216
  * Returns an issue only for the first non-conforming offer.
7904
8217
  * This rule is signing-agnostic; signer verification is handled at the collector level.
7905
8218
  */
7906
- const sameMaker = () => batch("mixed_maker", "Validates that all offers in a batch have the same maker address", (offers$1) => {
8219
+ const sameMaker = () => batch("mixed_maker", "Validates that all offers in a batch have the same maker address", (offers) => {
7907
8220
  const issues = /* @__PURE__ */ new Map();
7908
- if (offers$1.length === 0) return issues;
7909
- const firstMaker = offers$1[0].maker.toLowerCase();
7910
- for (let i = 1; i < offers$1.length; i++) {
7911
- const offer = offers$1[i];
8221
+ if (offers.length === 0) return issues;
8222
+ const firstMaker = offers[0].maker.toLowerCase();
8223
+ for (let i = 1; i < offers.length; i++) {
8224
+ const offer = offers[i];
7912
8225
  if (offer.maker.toLowerCase() !== firstMaker) {
7913
- issues.set(i, { message: `Offer has different maker ${offer.maker} than first offer ${offers$1[0].maker}` });
8226
+ issues.set(i, { message: `Offer has different maker ${offer.maker} than first offer ${offers[0].maker}` });
7914
8227
  return issues;
7915
8228
  }
7916
8229
  }
@@ -7937,9 +8250,9 @@ const morphoRules = (chains$3) => {
7937
8250
  maturity({ maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth] }),
7938
8251
  callback({
7939
8252
  callbacks: [
7940
- CallbackType.BuyWithEmptyCallback,
7941
- CallbackType.BuyVaultV1Callback,
7942
- CallbackType.SellERC20Callback
8253
+ Type$1.BuyWithEmptyCallback,
8254
+ Type$1.BuyVaultV1Callback,
8255
+ Type$1.SellERC20Callback
7943
8256
  ],
7944
8257
  allowedAddresses: chains$3.flatMap((c) => getCallbackAddresses(c.name))
7945
8258
  }),
@@ -7955,7 +8268,7 @@ function create$6(config) {
7955
8268
  return {
7956
8269
  create: async (batches) => {
7957
8270
  if (batches.length === 0) return [];
7958
- const offersWithBlock = batches.flatMap(({ blockNumber, offers: offers$1 }) => offers$1.map((offer) => ({
8271
+ const offersWithBlock = batches.flatMap(({ blockNumber, offers }) => offers.map((offer) => ({
7959
8272
  offer,
7960
8273
  blockNumber
7961
8274
  })));
@@ -7967,7 +8280,7 @@ function create$6(config) {
7967
8280
  for (const { offer, blockNumber } of offersWithBlock) {
7968
8281
  const obligationId$1 = obligationId(offer);
7969
8282
  if (!obligationsMap.has(obligationId$1)) {
7970
- obligationsMap.set(obligationId$1, from$14({
8283
+ obligationsMap.set(obligationId$1, from$15({
7971
8284
  chainId: offer.chainId,
7972
8285
  loanToken: offer.loanToken,
7973
8286
  maturity: offer.maturity,
@@ -7995,28 +8308,28 @@ function create$6(config) {
7995
8308
  });
7996
8309
  }
7997
8310
  return await db.transaction(async (dbTx) => {
7998
- const obligationsRows = Array.from(obligationsMap.entries()).map(([obligationId$1, obligation]) => ({
7999
- obligationId: obligationId$1,
8311
+ const obligationsRows = Array.from(obligationsMap.entries()).map(([obligationId, obligation]) => ({
8312
+ obligationId,
8000
8313
  chainId: obligation.chainId,
8001
8314
  loanToken: obligation.loanToken.toLowerCase(),
8002
8315
  maturity: obligation.maturity
8003
8316
  }));
8004
- for (const batch$2 of batch$1(obligationsRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(obligations).values(batch$2).onConflictDoNothing();
8317
+ for (const batch of batch$1(obligationsRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(obligations).values(batch).onConflictDoNothing();
8005
8318
  const oraclesRows = Array.from(oraclesMap.values()).map((oracle) => ({
8006
8319
  chainId: oracle.chainId,
8007
8320
  address: oracle.address.toLowerCase(),
8008
8321
  blockNumber: oracle.blockNumber
8009
8322
  }));
8010
- for (const batch$2 of batch$1(oraclesRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(oracles).values(batch$2).onConflictDoNothing();
8011
- const collateralsRows = Array.from(collateralsMap.entries()).flatMap(([obligationId$1, items]) => items.collaterals.map((collateral) => ({
8012
- obligationId: obligationId$1,
8323
+ for (const batch of batch$1(oraclesRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(oracles).values(batch).onConflictDoNothing();
8324
+ const collateralsRows = Array.from(collateralsMap.entries()).flatMap(([obligationId, items]) => items.collaterals.map((collateral) => ({
8325
+ obligationId,
8013
8326
  asset: collateral.asset.toLowerCase(),
8014
- oracleChainId: obligationsMap.get(obligationId$1).chainId,
8327
+ oracleChainId: obligationsMap.get(obligationId).chainId,
8015
8328
  oracleAddress: collateral.oracle.toLowerCase(),
8016
8329
  lltv: collateral.lltv,
8017
8330
  blockNumber: items.blockNumber
8018
8331
  })));
8019
- for (const batch$2 of batch$1(collateralsRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(obligationCollateralsV2).values(batch$2).onConflictDoNothing();
8332
+ for (const batch of batch$1(collateralsRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(obligationCollateralsV2).values(batch).onConflictDoNothing();
8020
8333
  const groupsRows = Array.from(groupsMap.values()).map((group) => ({
8021
8334
  chainId: group.chainId,
8022
8335
  maker: group.maker.toLowerCase(),
@@ -8024,7 +8337,7 @@ function create$6(config) {
8024
8337
  consumed: "0",
8025
8338
  blockNumber: group.blockNumber
8026
8339
  }));
8027
- for (const batch$2 of batch$1(groupsRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(groups).values(batch$2).onConflictDoNothing();
8340
+ for (const batch of batch$1(groupsRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(groups).values(batch).onConflictDoNothing();
8028
8341
  const offersRows = offersWithBlock.map(({ offer, blockNumber }) => ({
8029
8342
  ...serialize(offer),
8030
8343
  obligationId: obligationId(offer),
@@ -8035,17 +8348,17 @@ function create$6(config) {
8035
8348
  blockNumber
8036
8349
  }));
8037
8350
  const inserted = [];
8038
- for (const batch$2 of batch$1(offersRows, DEFAULT_BATCH_SIZE$1)) {
8039
- const result = await dbTx.insert(offers).values(batch$2).onConflictDoNothing().returning();
8351
+ for (const batch of batch$1(offersRows, DEFAULT_BATCH_SIZE$1)) {
8352
+ const result = await dbTx.insert(offers).values(batch).onConflictDoNothing().returning();
8040
8353
  inserted.push(...result);
8041
8354
  }
8042
8355
  if (inserted.length === 0) return [];
8043
8356
  const idCached = /* @__PURE__ */ new Map();
8044
- const id$1 = (params) => {
8357
+ const id = (params) => {
8045
8358
  const preimage = `0x${params.chainId}${params.contract}${params.user}${params.amount}`.toLowerCase();
8046
- const id$2 = idCached.get(preimage) ?? keccak256(preimage);
8047
- idCached.set(preimage, id$2);
8048
- return id$2;
8359
+ const id = idCached.get(preimage) ?? keccak256(preimage);
8360
+ idCached.set(preimage, id);
8361
+ return id;
8049
8362
  };
8050
8363
  const offersCallbacksMap = /* @__PURE__ */ new Map();
8051
8364
  for (const offer of inserted) {
@@ -8056,21 +8369,21 @@ function create$6(config) {
8056
8369
  if (!chain) continue;
8057
8370
  const callbackType = getCallbackType(chain.name, offer.callbackAddress);
8058
8371
  if (!callbackType) continue;
8059
- const callbacks$1 = decode$2(callbackType, offer.callbackData).map((callback$1) => ({
8372
+ const callbacks = decode$2(callbackType, offer.callbackData).map((callback) => ({
8060
8373
  chainId: offer.groupChainId,
8061
- contract: callback$1.contract.toLowerCase(),
8374
+ contract: callback.contract.toLowerCase(),
8062
8375
  user: user.toLowerCase(),
8063
- amount: callback$1.amount.toString(),
8064
- type: callbackType === CallbackType.BuyVaultV1Callback ? Type.VAULT_V1 : Type.ERC20,
8065
- asset: callbackType === CallbackType.BuyVaultV1Callback ? void 0 : callback$1.contract.toLowerCase(),
8376
+ amount: callback.amount.toString(),
8377
+ type: callbackType === Type$1.BuyVaultV1Callback ? Type.VAULT_V1 : Type.ERC20,
8378
+ asset: callbackType === Type$1.BuyVaultV1Callback ? void 0 : callback.contract.toLowerCase(),
8066
8379
  blockNumber: offer.blockNumber
8067
8380
  }));
8068
8381
  try {
8069
- await dbTx.insert(offersCallbacks).values(callbacks$1.map((callback$1) => ({
8382
+ await dbTx.insert(offersCallbacks).values(callbacks.map((callback) => ({
8070
8383
  offerHash: offer.hash,
8071
- callbackId: id$1(callback$1)
8384
+ callbackId: id(callback)
8072
8385
  }))).onConflictDoNothing();
8073
- offersCallbacksMap.get(offer.hash).push(...callbacks$1);
8386
+ offersCallbacksMap.get(offer.hash).push(...callbacks);
8074
8387
  } catch (_) {
8075
8388
  offersCallbacksMap.delete(offer.hash);
8076
8389
  }
@@ -8084,34 +8397,34 @@ function create$6(config) {
8084
8397
  idCached.clear();
8085
8398
  return inserted.map((offer) => offer.hash);
8086
8399
  }
8087
- await dbTx.positions.upsert(Array.from(offersCallbacksMap.values()).flatMap((callbacks$1) => callbacks$1.map((callback$1) => ({
8088
- chainId: callback$1.chainId,
8089
- contract: callback$1.contract,
8090
- user: callback$1.user,
8091
- type: callback$1.type,
8092
- asset: callback$1.asset,
8093
- blockNumber: callback$1.blockNumber
8400
+ await dbTx.positions.upsert(Array.from(offersCallbacksMap.values()).flatMap((callbacks) => callbacks.map((callback) => ({
8401
+ chainId: callback.chainId,
8402
+ contract: callback.contract,
8403
+ user: callback.user,
8404
+ type: callback.type,
8405
+ asset: callback.asset,
8406
+ blockNumber: callback.blockNumber
8094
8407
  }))));
8095
- const callbacksRows = Array.from(offersCallbacksMap.values()).flatMap((callbacks$1) => callbacks$1.map((callback$1) => ({
8096
- id: id$1(callback$1),
8097
- positionChainId: callback$1.chainId,
8098
- positionContract: callback$1.contract,
8099
- positionUser: callback$1.user,
8100
- amount: callback$1.amount
8408
+ const callbacksRows = Array.from(offersCallbacksMap.values()).flatMap((callbacks) => callbacks.map((callback) => ({
8409
+ id: id(callback),
8410
+ positionChainId: callback.chainId,
8411
+ positionContract: callback.contract,
8412
+ positionUser: callback.user,
8413
+ amount: callback.amount
8101
8414
  })));
8102
- for (const batch$2 of batch$1(callbacksRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(callbacks).values(batch$2).onConflictDoNothing();
8415
+ for (const batch of batch$1(callbacksRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(callbacks).values(batch).onConflictDoNothing();
8103
8416
  const lotInfos = [];
8104
- for (const [offerHash, callbacks$1] of offersCallbacksMap.entries()) {
8417
+ for (const [offerHash, callbacks] of offersCallbacksMap.entries()) {
8105
8418
  const offer = inserted.find((o) => o.hash === offerHash);
8106
8419
  if (!offer) continue;
8107
- for (const callback$1 of callbacks$1) {
8108
- const isLoanPosition = obligationsMap.get(offer.obligationId)?.loanToken.toLowerCase() === callback$1.asset?.toLowerCase();
8420
+ for (const callback of callbacks) {
8421
+ const isLoanPosition = obligationsMap.get(offer.obligationId)?.loanToken.toLowerCase() === callback.asset?.toLowerCase();
8109
8422
  lotInfos.push({
8110
- positionChainId: callback$1.chainId,
8111
- positionContract: callback$1.contract,
8112
- positionUser: callback$1.user,
8423
+ positionChainId: callback.chainId,
8424
+ positionContract: callback.contract,
8425
+ positionUser: callback.user,
8113
8426
  group: offer.group,
8114
- size: isLoanPosition ? BigInt(offer.assets) : BigInt(callback$1.amount)
8427
+ size: isLoanPosition ? BigInt(offer.assets) : BigInt(callback.amount)
8115
8428
  });
8116
8429
  }
8117
8430
  }
@@ -8205,7 +8518,7 @@ function create$6(config) {
8205
8518
  obligationUnits: BigInt(row.obligationUnits),
8206
8519
  obligationShares: BigInt(row.obligationShares),
8207
8520
  price: BigInt(row.price),
8208
- maturity: from$15(row.maturity),
8521
+ maturity: from$16(row.maturity),
8209
8522
  expiry: row.expiry,
8210
8523
  start: row.start,
8211
8524
  group: row.group,
@@ -8241,7 +8554,7 @@ function create$6(config) {
8241
8554
  if ("hashes" in parameters) {
8242
8555
  const { hashes } = parameters;
8243
8556
  if (hashes.length === 0) return 0;
8244
- const normalizedHashes = hashes.map((hash$1) => hash$1.toLowerCase());
8557
+ const normalizedHashes = hashes.map((hash) => hash.toLowerCase());
8245
8558
  return (await db.delete(offers).where(inArray(offers.hash, normalizedHashes))).affectedRows;
8246
8559
  }
8247
8560
  if ("blockNumberGte" in parameters) {
@@ -8251,12 +8564,13 @@ function create$6(config) {
8251
8564
  throw new Error("Invalid parameters");
8252
8565
  },
8253
8566
  getObligations: async (parameters) => {
8254
- const { ids, chainId, loanToken, collateralToken, maturity: maturity$1, cursor, limit = DEFAULT_LIMIT$2 } = parameters ?? {};
8567
+ const { ids, chainId: chainIds, loanToken: loanTokens, collateralToken: collateralTokens, maturity: maturities, cursor, limit = DEFAULT_LIMIT$2 } = parameters ?? {};
8255
8568
  const now$1 = now();
8256
- const collateralFilter = collateralToken !== void 0 ? sql`EXISTS (
8569
+ const loanTokenFilter = loanTokens !== void 0 && loanTokens.length > 0 ? sql`(${sql.join(loanTokens.map((token) => sql`LOWER(${obligations.loanToken}) = ${token.toLowerCase()}`), sql` OR `)})` : void 0;
8570
+ const collateralFilter = collateralTokens !== void 0 && collateralTokens.length > 0 ? sql`EXISTS (
8257
8571
  SELECT 1 FROM ${obligationCollateralsV2} oc
8258
8572
  WHERE oc.obligation_id = ${obligations.obligationId}
8259
- AND LOWER(oc.asset) = ${collateralToken.toLowerCase()}
8573
+ AND (${sql.join(collateralTokens.map((token) => sql`LOWER(oc.asset) = ${token.toLowerCase()}`), sql` OR `)})
8260
8574
  )` : void 0;
8261
8575
  const result = await db.select({
8262
8576
  obligationId: obligations.obligationId,
@@ -8265,15 +8579,15 @@ function create$6(config) {
8265
8579
  collaterals: sql`ARRAY_AGG(jsonb_build_object('asset', ${obligationCollateralsV2.asset}, 'oracle', ${oracles.address}, 'lltv', ${obligationCollateralsV2.lltv}))`.as("collaterals"),
8266
8580
  maturity: obligations.maturity
8267
8581
  }).from(obligations).innerJoin(obligationCollateralsV2, eq(obligations.obligationId, obligationCollateralsV2.obligationId)).innerJoin(oracles, sql`${obligationCollateralsV2.oracleChainId} = ${oracles.chainId}
8268
- AND ${obligationCollateralsV2.oracleAddress} = ${oracles.address}`).groupBy(obligations.obligationId).where(and(cursor !== null && cursor !== void 0 ? gt(obligations.obligationId, cursor) : sql`true`, ids !== void 0 && ids.length > 0 ? inArray(obligations.obligationId, ids) : void 0, chainId !== void 0 ? eq(obligations.chainId, chainId) : void 0, loanToken !== void 0 ? sql`LOWER(${obligations.loanToken}) = ${loanToken.toLowerCase()}` : void 0, maturity$1 !== void 0 ? eq(obligations.maturity, maturity$1) : gte(obligations.maturity, now$1), collateralFilter)).orderBy(asc(obligations.obligationId)).limit(limit);
8582
+ AND ${obligationCollateralsV2.oracleAddress} = ${oracles.address}`).groupBy(obligations.obligationId).where(and(cursor !== null && cursor !== void 0 ? gt(obligations.obligationId, cursor) : sql`true`, ids !== void 0 && ids.length > 0 ? inArray(obligations.obligationId, ids) : void 0, chainIds !== void 0 && chainIds.length > 0 ? inArray(obligations.chainId, chainIds) : void 0, loanTokenFilter, maturities !== void 0 && maturities.length > 0 ? inArray(obligations.maturity, maturities) : gte(obligations.maturity, now$1), collateralFilter)).orderBy(asc(obligations.obligationId)).limit(limit);
8269
8583
  const items = [];
8270
- for (const row of result) items.push(from$14({
8584
+ for (const row of result) items.push(from$15({
8271
8585
  chainId: row.chainId,
8272
8586
  loanToken: row.loanToken,
8273
- collaterals: row.collaterals.sort((a, b) => a.asset.localeCompare(b.asset)).map((c) => from$16({
8587
+ collaterals: row.collaterals.sort((a, b) => a.asset.localeCompare(b.asset)).map((c) => from$17({
8274
8588
  asset: c.asset,
8275
8589
  oracle: c.oracle,
8276
- lltv: from$17(BigInt(c.lltv))
8590
+ lltv: from$18(BigInt(c.lltv))
8277
8591
  })),
8278
8592
  maturity: row.maturity
8279
8593
  }));
@@ -8286,11 +8600,11 @@ function create$6(config) {
8286
8600
  getQuotes: async (parameters) => {
8287
8601
  const { obligationIds } = parameters;
8288
8602
  if (obligationIds.length === 0) return [];
8289
- const now$1 = now();
8603
+ const now$2 = now();
8290
8604
  const query = ({ side }) => db.selectDistinctOn([offers.obligationId], {
8291
8605
  obligationId: offers.obligationId,
8292
8606
  price: offers.price
8293
- }).from(offers).innerJoin(groups, and(eq(offers.groupChainId, groups.chainId), eq(offers.groupMaker, groups.maker), eq(offers.group, groups.group))).leftJoin(validations, eq(offers.hash, validations.offerHash)).leftJoin(status, eq(validations.statusId, status.id)).where(and(inArray(offers.obligationId, obligationIds), eq(offers.buy, side === "buy"), gte(offers.expiry, now$1), gte(offers.maturity, now$1), lte(offers.start, now$1), sql`(${status.code} IS NULL OR ${status.code} = ${Status.VALID})`)).orderBy(offers.obligationId, side === "buy" ? sql`${offers.price}::numeric ASC` : sql`${offers.price}::numeric DESC`);
8607
+ }).from(offers).innerJoin(groups, and(eq(offers.groupChainId, groups.chainId), eq(offers.groupMaker, groups.maker), eq(offers.group, groups.group))).leftJoin(validations, eq(offers.hash, validations.offerHash)).leftJoin(status, eq(validations.statusId, status.id)).where(and(inArray(offers.obligationId, obligationIds), eq(offers.buy, side === "buy"), gte(offers.expiry, now$2), gte(offers.maturity, now$2), lte(offers.start, now$2), sql`(${status.code} IS NULL OR ${status.code} = ${Status.VALID})`)).orderBy(offers.obligationId, side === "buy" ? sql`${offers.price}::numeric ASC` : sql`${offers.price}::numeric DESC`);
8294
8608
  const [bestBuys, bestSells] = await Promise.all([query({ side: "buy" }), query({ side: "sell" })]);
8295
8609
  const quotes = /* @__PURE__ */ new Map();
8296
8610
  for (const row of bestSells) quotes.set(row.obligationId, {
@@ -8308,9 +8622,9 @@ function create$6(config) {
8308
8622
  }
8309
8623
  quote.bid = { price: BigInt(row.price) };
8310
8624
  }
8311
- return Array.from(quotes.entries()).map(([id$1, quote]) => {
8312
- return from$9({
8313
- obligationId: id$1,
8625
+ return Array.from(quotes.entries()).map(([id, quote]) => {
8626
+ return from$10({
8627
+ obligationId: id,
8314
8628
  ask: quote.ask,
8315
8629
  bid: quote.bid
8316
8630
  });
@@ -8351,7 +8665,7 @@ function create$4(db) {
8351
8665
  price: oracles.price,
8352
8666
  blockNumber: oracles.blockNumber,
8353
8667
  chainId: oracles.chainId
8354
- }).from(oracles).where(eq(oracles.chainId, chainId))).map((r) => from$11({
8668
+ }).from(oracles).where(eq(oracles.chainId, chainId))).map((r) => from$12({
8355
8669
  chainId: r.chainId,
8356
8670
  address: r.address,
8357
8671
  price: r.price,
@@ -8367,7 +8681,7 @@ function create$4(db) {
8367
8681
  blockNumber: o.blockNumber
8368
8682
  }));
8369
8683
  db.transaction(async (dbTx) => {
8370
- for (const batch$2 of batch$1(rows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(oracles).values(batch$2).onConflictDoUpdate({
8684
+ for (const batch of batch$1(rows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(oracles).values(batch).onConflictDoUpdate({
8371
8685
  target: [oracles.chainId, oracles.address],
8372
8686
  set: {
8373
8687
  price: sql`EXCLUDED.price`,
@@ -8418,8 +8732,8 @@ const create$3 = (db) => {
8418
8732
  };
8419
8733
  });
8420
8734
  let totalUpdated = 0;
8421
- for (const batch$2 of batch$1(rows, DEFAULT_BATCH_SIZE$1)) {
8422
- const updated = await db.insert(positions).values(batch$2).onConflictDoUpdate({
8735
+ for (const batch of batch$1(rows, DEFAULT_BATCH_SIZE$1)) {
8736
+ const updated = await db.insert(positions).values(batch).onConflictDoUpdate({
8423
8737
  target: [
8424
8738
  positions.chainId,
8425
8739
  positions.contract,
@@ -8449,20 +8763,20 @@ const create$3 = (db) => {
8449
8763
  user: parsed.user
8450
8764
  };
8451
8765
  }
8452
- const positions$1 = await db.select().from(positions).where(and(ne(positions.user, zeroAddress), filled === void 0 ? sql`true` : sql`${positions.balance} IS ${filled === true ? sql`NOT` : sql``} NULL`, type !== void 0 ? eq(positions.positionTypeId, Object.values(Type).indexOf(type) + 1) : sql`true`, chainId !== void 0 ? eq(positions.chainId, chainId) : sql`true`, (() => {
8766
+ const positions$2 = await db.select().from(positions).where(and(ne(positions.user, zeroAddress), filled === void 0 ? sql`true` : sql`${positions.balance} IS ${filled === true ? sql`NOT` : sql``} NULL`, type !== void 0 ? eq(positions.positionTypeId, Object.values(Type).indexOf(type) + 1) : sql`true`, chainId !== void 0 ? eq(positions.chainId, chainId) : sql`true`, (() => {
8453
8767
  if (cursor === null || cursor === void 0) return sql`true`;
8454
8768
  return sql`
8455
8769
  (${chainId === void 0 ? sql`"chain_id", ` : sql``}"contract", "user") > (${chainId === void 0 ? sql`${cursor.chainId}, ` : sql``}${cursor.contract}, ${cursor.user})
8456
8770
  `;
8457
8771
  })())).orderBy(asc(positions.chainId), asc(positions.contract), asc(positions.user), asc(positions.blockNumber)).limit(limit);
8458
- const nextCursor = positions$1.length === limit ? Buffer.from(JSON.stringify({
8459
- chainId: positions$1[positions$1.length - 1].chainId.toString(),
8460
- contract: positions$1[positions$1.length - 1].contract,
8461
- user: positions$1[positions$1.length - 1].user,
8462
- blockNumber: positions$1[positions$1.length - 1].blockNumber.toString()
8772
+ const nextCursor = positions$2.length === limit ? Buffer.from(JSON.stringify({
8773
+ chainId: positions$2[positions$2.length - 1].chainId.toString(),
8774
+ contract: positions$2[positions$2.length - 1].contract,
8775
+ user: positions$2[positions$2.length - 1].user,
8776
+ blockNumber: positions$2[positions$2.length - 1].blockNumber.toString()
8463
8777
  })).toString("base64url") : null;
8464
8778
  return {
8465
- positions: positions$1.map((p) => ({
8779
+ positions: positions$2.map((p) => ({
8466
8780
  chainId: p.chainId,
8467
8781
  contract: p.contract,
8468
8782
  user: p.user,
@@ -8741,7 +9055,7 @@ function create$1(config) {
8741
9055
  treeRoot: root,
8742
9056
  proofNodes: concatenateProofs(proof.path)
8743
9057
  }));
8744
- for (const batch$2 of batch$1(pathRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(merklePaths).values(batch$2).onConflictDoUpdate({
9058
+ for (const batch of batch$1(pathRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(merklePaths).values(batch).onConflictDoUpdate({
8745
9059
  target: [merklePaths.offerHash],
8746
9060
  set: {
8747
9061
  treeRoot: sql`excluded.tree_root`,
@@ -8776,9 +9090,9 @@ function create$1(config) {
8776
9090
  * Concatenates an array of 32-byte hex hashes into a single hex string.
8777
9091
  * Empty arrays return "0x".
8778
9092
  */
8779
- function concatenateProofs(proofs$1) {
8780
- if (proofs$1.length === 0) return "0x";
8781
- return `0x${proofs$1.map((p) => p.slice(2)).join("")}`;
9093
+ function concatenateProofs(proofs) {
9094
+ if (proofs.length === 0) return "0x";
9095
+ return `0x${proofs.map((p) => p.slice(2)).join("")}`;
8782
9096
  }
8783
9097
  /**
8784
9098
  * Splits a concatenated hex string back into an array of 32-byte hex hashes.
@@ -8786,10 +9100,10 @@ function concatenateProofs(proofs$1) {
8786
9100
  */
8787
9101
  function splitProofs(concatenated) {
8788
9102
  if (!concatenated || concatenated === "0x" || concatenated.length <= 2) return [];
8789
- const hex$1 = concatenated.slice(2);
8790
- const proofs$1 = [];
8791
- for (let i = 0; i < hex$1.length; i += 64) proofs$1.push(`0x${hex$1.slice(i, i + 64)}`);
8792
- return proofs$1;
9103
+ const hex = concatenated.slice(2);
9104
+ const proofs = [];
9105
+ for (let i = 0; i < hex.length; i += 64) proofs.push(`0x${hex.slice(i, i + 64)}`);
9106
+ return proofs;
8793
9107
  }
8794
9108
 
8795
9109
  //#endregion
@@ -8824,7 +9138,7 @@ function create(db) {
8824
9138
  upsert: async (results) => {
8825
9139
  if (results.length === 0) return;
8826
9140
  const allowedStatuses = new Set(Object.values(Status));
8827
- const invalidStatuses = Array.from(new Set(results.map((r) => r.status).filter((s$1) => !allowedStatuses.has(s$1))));
9141
+ const invalidStatuses = Array.from(new Set(results.map((r) => r.status).filter((s) => !allowedStatuses.has(s))));
8828
9142
  if (invalidStatuses.length > 0) throw new Error(`Unknown validation status: ${invalidStatuses.join(", ")}`);
8829
9143
  const normalized = results.map((r) => ({
8830
9144
  offerHash: r.offerHash.toLowerCase(),
@@ -8836,12 +9150,12 @@ function create(db) {
8836
9150
  code: status.code
8837
9151
  }).from(status).where(inArray(status.code, uniqueStatuses));
8838
9152
  const statusMap = new Map(statusRows.map((row) => [row.code, row.id]));
8839
- for (const status$1 of uniqueStatuses) if (!statusMap.has(status$1)) throw new Error(`Unknown validation status: ${status$1}`);
9153
+ for (const status of uniqueStatuses) if (!statusMap.has(status)) throw new Error(`Unknown validation status: ${status}`);
8840
9154
  const values = normalized.map((row) => ({
8841
9155
  offerHash: row.offerHash,
8842
9156
  statusId: statusMap.get(row.status)
8843
9157
  }));
8844
- for (const batch$2 of batch$1(values, DEFAULT_BATCH_SIZE$1)) await db.insert(validations).values(batch$2).onConflictDoUpdate({
9158
+ for (const batch of batch$1(values, DEFAULT_BATCH_SIZE$1)) await db.insert(validations).values(batch).onConflictDoUpdate({
8845
9159
  target: [validations.offerHash],
8846
9160
  set: {
8847
9161
  statusId: sql`excluded.status_id`,
@@ -8854,7 +9168,7 @@ function create(db) {
8854
9168
 
8855
9169
  //#endregion
8856
9170
  //#region src/database/Database.ts
8857
- var Database_exports = /* @__PURE__ */ __export({ connect: () => connect$1 });
9171
+ var Database_exports = /* @__PURE__ */ __exportAll({ connect: () => connect$1 });
8858
9172
  function createDomains(core, chainRegistry) {
8859
9173
  return {
8860
9174
  book: create$10({ db: core }),
@@ -8877,12 +9191,12 @@ function createDomains(core, chainRegistry) {
8877
9191
  };
8878
9192
  }
8879
9193
  const AUGMENT_CACHE = /* @__PURE__ */ new WeakMap();
8880
- function augmentWithDomains(base$1, chainRegistry) {
8881
- const cached = AUGMENT_CACHE.get(base$1)?.get(chainRegistry);
9194
+ function augmentWithDomains(base, chainRegistry) {
9195
+ const cached = AUGMENT_CACHE.get(base)?.get(chainRegistry);
8882
9196
  if (cached) return cached;
8883
- const wrapped = Object.create(base$1);
9197
+ const wrapped = Object.create(base);
8884
9198
  wrapped.transaction = async (fn) => {
8885
- return base$1.transaction(async (tx) => {
9199
+ return base.transaction(async (tx) => {
8886
9200
  return fn(augmentWithDomains(tx, chainRegistry));
8887
9201
  });
8888
9202
  };
@@ -8933,8 +9247,8 @@ function augmentWithDomains(base$1, chainRegistry) {
8933
9247
  enumerable: true
8934
9248
  }
8935
9249
  });
8936
- const chainRegistryMap = AUGMENT_CACHE.get(base$1);
8937
- if (!chainRegistryMap) AUGMENT_CACHE.set(base$1, new Map([[chainRegistry, wrapped]]));
9250
+ const chainRegistryMap = AUGMENT_CACHE.get(base);
9251
+ if (!chainRegistryMap) AUGMENT_CACHE.set(base, new Map([[chainRegistry, wrapped]]));
8938
9252
  else chainRegistryMap.set(chainRegistry, wrapped);
8939
9253
  return wrapped;
8940
9254
  }
@@ -8946,22 +9260,23 @@ const InMemoryDbMap = /* @__PURE__ */ new Map();
8946
9260
  * @returns The database client {@link connect.ReturnType}
8947
9261
  */
8948
9262
  function connect$1(chainRegistry, connectionString) {
8949
- const clean = async (driver$1) => {
9263
+ const clean = async (driver) => {
8950
9264
  if (TABLE_NAMES.length === 0) return;
8951
- await driver$1.execute(`TRUNCATE TABLE ${VERSIONED_TABLE_NAMES.join(", ")} RESTART IDENTITY CASCADE;`);
9265
+ await driver.execute(`TRUNCATE TABLE ${VERSIONED_TABLE_NAMES.join(", ")} RESTART IDENTITY CASCADE;`);
8952
9266
  };
8953
9267
  if (connectionString !== void 0) {
8954
- const pool$1 = new Pool({ connectionString });
8955
- const driver$1 = drizzle(pool$1, { schema: schema_exports });
8956
- const core$1 = augmentWithDomains(driver$1, chainRegistry);
8957
- return Object.assign(core$1, {
9268
+ const pool = new Pool({ connectionString });
9269
+ const driver = drizzle(pool, { schema: schema_exports });
9270
+ const core = augmentWithDomains(driver, chainRegistry);
9271
+ return Object.assign(core, {
8958
9272
  name: "pg",
8959
- pool: pool$1,
8960
- applyMigrations: applyMigrations("pg", driver$1),
8961
- clean: async () => await clean(driver$1)
9273
+ pool,
9274
+ applyMigrations: applyMigrations("pg", driver),
9275
+ clean: async () => await clean(driver)
8962
9276
  });
8963
9277
  }
8964
- const key = crypto.createHash("md5").update(JSON.stringify(chainRegistry.list())).digest("hex");
9278
+ const poolId = process.env.VITEST_POOL_ID ?? "";
9279
+ const key = crypto.createHash("md5").update(JSON.stringify(chainRegistry.list()) + poolId).digest("hex");
8965
9280
  const cached = InMemoryDbMap.get(key);
8966
9281
  if (cached) return cached;
8967
9282
  const pool = new PGlite();
@@ -9324,9 +9639,9 @@ function from(parameters) {
9324
9639
  blockWindow: parameters.blockWindow
9325
9640
  };
9326
9641
  return {
9327
- add: (parameters$1) => add(config, parameters$1),
9328
- get: (parameters$1) => get(config, parameters$1),
9329
- stream: (parameters$1) => streamOffers(config, parameters$1)
9642
+ add: (parameters) => add(config, parameters),
9643
+ get: (parameters) => get(config, parameters),
9644
+ stream: (parameters) => streamOffers(config, parameters)
9330
9645
  };
9331
9646
  }
9332
9647
  /**
@@ -9336,9 +9651,9 @@ function from(parameters) {
9336
9651
  * @throws ViemClientError if the viem client throws an error.
9337
9652
  * @throws Offer.InvalidOfferError if the offer is invalid.
9338
9653
  */
9339
- async function add(config, offers$1) {
9654
+ async function add(config, offers) {
9340
9655
  if (!config.client.account) throw new WalletAccountNotSetError();
9341
- const tree = from$13(offers$1.map((o) => from$12(o)));
9656
+ const tree = from$14(offers.map((o) => from$13(o)));
9342
9657
  const chainId = await getChainId(config.client);
9343
9658
  for (const offer of tree.offers) if (chainId !== offer.chainId) throw new ChainIdMismatchError(offer.chainId, chainId);
9344
9659
  const signature = await sign(tree.offers, config.client);
@@ -9407,7 +9722,7 @@ async function* streamOffers(config, parameters) {
9407
9722
  for await (const { logs, blockNumber: newBlockNumber } of stream) {
9408
9723
  blockNumber = newBlockNumber;
9409
9724
  if (logs.length === 0) continue;
9410
- const offers$1 = [];
9725
+ const offers = [];
9411
9726
  for (const log of logs) {
9412
9727
  if (!log) continue;
9413
9728
  const [payload] = decodeAbiParameters([{ type: "bytes" }], log.data);
@@ -9415,12 +9730,12 @@ async function* streamOffers(config, parameters) {
9415
9730
  const { tree } = await decode$1(payload);
9416
9731
  for (const offer of tree.offers) {
9417
9732
  if (loanToken && offer.loanToken.toLowerCase() !== loanToken.toLowerCase()) continue;
9418
- offers$1.push(offer);
9733
+ offers.push(offer);
9419
9734
  }
9420
9735
  } catch (_) {}
9421
9736
  }
9422
9737
  yield {
9423
- offers: offers$1,
9738
+ offers,
9424
9739
  blockNumber
9425
9740
  };
9426
9741
  }
@@ -9456,7 +9771,7 @@ function connect(parameters) {
9456
9771
 
9457
9772
  //#endregion
9458
9773
  //#region src/mempool/index.ts
9459
- var mempool_exports = /* @__PURE__ */ __export({
9774
+ var mempool_exports = /* @__PURE__ */ __exportAll({
9460
9775
  ChainIdMismatchError: () => ChainIdMismatchError,
9461
9776
  ViemClientError: () => ViemClientError,
9462
9777
  WalletAccountNotSetError: () => WalletAccountNotSetError,
@@ -9467,5 +9782,5 @@ var mempool_exports = /* @__PURE__ */ __export({
9467
9782
  });
9468
9783
 
9469
9784
  //#endregion
9470
- export { Abi_exports as Abi, BookResponse_exports as BookResponse, BooksController, BrandTypeId, Callback_exports as Callback, Chain_exports as Chain, ChainHealth, ChainRegistry_exports as ChainRegistry, ChainsHealthResponse, Collateral_exports as Collateral, CollectorHealth, CollectorsHealthResponse, ConfigController, Database_exports as Database, ERC4626_exports as ERC4626, Errors_exports as Errors, Format_exports as Format, GateConfig_exports as GateConfig, Gatekeeper_exports as Gatekeeper, Health_exports as Health, HealthController, Indexer_exports as Indexer, LLTV_exports as LLTV, Liquidity_exports as Liquidity, Logger_exports as Logger, Maturity_exports as Maturity, mempool_exports as Mempool, Obligation_exports as Obligation, ObligationResponse_exports as ObligationResponse, ObligationsController, Offer_exports as Offer, OfferResponse_exports as OfferResponse, OffersController, drizzle_exports as OffersSchema, OpenApi, Oracle_exports as Oracle, Position_exports as Position, PositionResponse_exports as PositionResponse, Quote_exports as Quote, RouterApi_exports as RouterApi, Client_exports as RouterClient, RouterStatusResponse, Rules_exports as Rules, time_exports as Time, Transfer_exports as Transfer, Tree_exports as Tree, UsersController, utils_exports as Utils, ValidateController, Gate_exports as Validation, morphoRules, parse, safeParse };
9785
+ export { Abi_exports as Abi, BookResponse_exports as BookResponse, BooksController, BrandTypeId, Callback_exports as Callback, Chain_exports as Chain, ChainHealth, ChainRegistry_exports as ChainRegistry, ChainsHealthResponse, Collateral_exports as Collateral, CollectorHealth, CollectorsHealthResponse, ConfigController, Database_exports as Database, ERC4626_exports as ERC4626, Errors_exports as Errors, Format_exports as Format, GateConfig_exports as GateConfig, Gatekeeper_exports as Gatekeeper, Client_exports as GatekeeperClient, Health_exports as Health, HealthController, Indexer_exports as Indexer, LLTV_exports as LLTV, Liquidity_exports as Liquidity, Logger_exports as Logger, Maturity_exports as Maturity, mempool_exports as Mempool, Obligation_exports as Obligation, ObligationResponse_exports as ObligationResponse, ObligationsController, Offer_exports as Offer, OfferResponse_exports as OfferResponse, OffersController, drizzle_exports as OffersSchema, OpenApi, Oracle_exports as Oracle, Position_exports as Position, PositionResponse_exports as PositionResponse, Quote_exports as Quote, RouterApi_exports as RouterApi, Client_exports$1 as RouterClient, RouterStatusResponse, Rules_exports as Rules, time_exports as Time, TradingFee_exports as TradingFee, Transfer_exports as Transfer, Tree_exports as Tree, UsersController, utils_exports as Utils, ValidateController, Gate_exports as Validation, morphoRules, parse, safeParse };
9471
9786
  //# sourceMappingURL=index.node.mjs.map