@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.
@@ -5,21 +5,30 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (all) => {
8
+ var __exportAll = (all, symbols) => {
9
9
  let target = {};
10
- for (var name in all) __defProp(target, name, {
11
- get: all[name],
12
- enumerable: true
13
- });
10
+ for (var name in all) {
11
+ __defProp(target, name, {
12
+ get: all[name],
13
+ enumerable: true
14
+ });
15
+ }
16
+ if (symbols) {
17
+ __defProp(target, Symbol.toStringTag, { value: "Module" });
18
+ }
14
19
  return target;
15
20
  };
16
- var __copyProps = (to, from$18, except, desc) => {
17
- if (from$18 && typeof from$18 === "object" || typeof from$18 === "function") for (var keys = __getOwnPropNames(from$18), i = 0, n = keys.length, key; i < n; i++) {
18
- key = keys[i];
19
- if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
20
- get: ((k) => from$18[k]).bind(null, key),
21
- enumerable: !(desc = __getOwnPropDesc(from$18, key)) || desc.enumerable
22
- });
21
+ var __copyProps = (to, from, except, desc) => {
22
+ if (from && typeof from === "object" || typeof from === "function") {
23
+ for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
24
+ key = keys[i];
25
+ if (!__hasOwnProp.call(to, key) && key !== except) {
26
+ __defProp(to, key, {
27
+ get: ((k) => from[k]).bind(null, key),
28
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
29
+ });
30
+ }
31
+ }
23
32
  }
24
33
  return to;
25
34
  };
@@ -32,7 +41,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
32
41
  let viem_actions = require("viem/actions");
33
42
  let node_async_hooks = require("node:async_hooks");
34
43
  let viem = require("viem");
35
- let __opentelemetry_api = require("@opentelemetry/api");
44
+ let _opentelemetry_api = require("@opentelemetry/api");
36
45
  require("@opentelemetry/exporter-trace-otlp-proto");
37
46
  require("@opentelemetry/id-generator-aws-xray");
38
47
  require("@opentelemetry/instrumentation");
@@ -45,9 +54,9 @@ require("@opentelemetry/semantic-conventions");
45
54
  let viem_chains = require("viem/chains");
46
55
  let zod = require("zod");
47
56
  zod = __toESM(zod);
48
- let __openzeppelin_merkle_tree = require("@openzeppelin/merkle-tree");
57
+ let _openzeppelin_merkle_tree = require("@openzeppelin/merkle-tree");
49
58
  let pako = require("pako");
50
- let __hono_node_server = require("@hono/node-server");
59
+ let _hono_node_server = require("@hono/node-server");
51
60
  let hono = require("hono");
52
61
  let hono_cors = require("hono/cors");
53
62
  let zod_v4 = require("zod/v4");
@@ -64,7 +73,7 @@ openapi_fetch = __toESM(openapi_fetch);
64
73
  let drizzle_orm_pg_core = require("drizzle-orm/pg-core");
65
74
  let node_crypto = require("node:crypto");
66
75
  node_crypto = __toESM(node_crypto);
67
- let __electric_sql_pglite = require("@electric-sql/pglite");
76
+ let _electric_sql_pglite = require("@electric-sql/pglite");
68
77
  let drizzle_orm_node_postgres = require("drizzle-orm/node-postgres");
69
78
  let drizzle_orm_node_postgres_migrator = require("drizzle-orm/node-postgres/migrator");
70
79
  let drizzle_orm_pglite = require("drizzle-orm/pglite");
@@ -73,7 +82,7 @@ let pg = require("pg");
73
82
  let drizzle_orm = require("drizzle-orm");
74
83
 
75
84
  //#region src/logger/Logger.ts
76
- var Logger_exports = /* @__PURE__ */ __export({
85
+ var Logger_exports = /* @__PURE__ */ __exportAll({
77
86
  LogLevelValues: () => LogLevelValues,
78
87
  defaultLogger: () => defaultLogger,
79
88
  getLogger: () => getLogger,
@@ -108,10 +117,10 @@ function defaultLogger(minLevel, pretty) {
108
117
  const { msg, ...rest } = entry;
109
118
  const stack = typeof rest.stack === "string" ? rest.stack : void 0;
110
119
  if (stack) delete rest.stack;
111
- const timestamp$1 = (/* @__PURE__ */ new Date()).toISOString();
120
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
112
121
  const level = methodLevel.toUpperCase();
113
122
  const extras = Object.entries(rest).map(([k, v]) => `${k}=${formatValue(v)}`).join(" ");
114
- const line = extras.length > 0 ? `${timestamp$1} [${level}] ${msg} ${extras}` : `${timestamp$1} [${level}] ${msg}`;
123
+ const line = extras.length > 0 ? `${timestamp} [${level}] ${msg} ${extras}` : `${timestamp} [${level}] ${msg}`;
115
124
  console[consoleMethod](line);
116
125
  if (stack) console[consoleMethod](stack);
117
126
  } : () => {};
@@ -176,7 +185,7 @@ function formatValue(value) {
176
185
  * ```
177
186
  */
178
187
  function getTracer(name) {
179
- return __opentelemetry_api.trace.getTracer(name);
188
+ return _opentelemetry_api.trace.getTracer(name);
180
189
  }
181
190
  /**
182
191
  * Helper to run a function inside an active span.
@@ -200,7 +209,7 @@ function startActiveSpan(tracer, name, fn) {
200
209
  return await fn(span);
201
210
  } catch (err) {
202
211
  span.recordException(err);
203
- span.setStatus({ code: __opentelemetry_api.SpanStatusCode.ERROR });
212
+ span.setStatus({ code: _opentelemetry_api.SpanStatusCode.ERROR });
204
213
  throw err;
205
214
  } finally {
206
215
  span.end();
@@ -291,7 +300,7 @@ async function batchMulticall(parameters) {
291
300
 
292
301
  //#endregion
293
302
  //#region src/utils/Errors.ts
294
- var Errors_exports = /* @__PURE__ */ __export({
303
+ var Errors_exports = /* @__PURE__ */ __exportAll({
295
304
  BaseError: () => BaseError,
296
305
  ReorgError: () => ReorgError
297
306
  });
@@ -348,7 +357,7 @@ var ReorgError = class extends BaseError {
348
357
 
349
358
  //#endregion
350
359
  //#region src/utils/Format.ts
351
- var Format_exports = /* @__PURE__ */ __export({
360
+ var Format_exports = /* @__PURE__ */ __exportAll({
352
361
  fromSnakeCase: () => fromSnakeCase$3,
353
362
  stringifyBigint: () => stringifyBigint,
354
363
  toSnakeCase: () => toSnakeCase$1
@@ -360,7 +369,7 @@ var Format_exports = /* @__PURE__ */ __export({
360
369
  * Stringifies bigint values to strings.
361
370
  */
362
371
  function toSnakeCase$1(obj) {
363
- return stringifyBigint(processObject(obj, (s$1) => s$1.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`), (value) => typeof value === "string" && (0, viem.isAddress)(value.toLowerCase()) ? (0, viem.getAddress)(value.toLowerCase()) : value));
372
+ return stringifyBigint(processObject(obj, (s) => s.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`), (value) => typeof value === "string" && (0, viem.isAddress)(value.toLowerCase()) ? (0, viem.getAddress)(value.toLowerCase()) : value));
364
373
  }
365
374
  /**
366
375
  * Formats a snake case object to its camel case type.
@@ -369,7 +378,7 @@ function toSnakeCase$1(obj) {
369
378
  * @warning Does not unstringify bigint values.
370
379
  */
371
380
  function fromSnakeCase$3(obj) {
372
- return processObject(obj, (s$1) => (0, viem.isAddress)(s$1.toLowerCase()) ? s$1 : s$1.replace(/_([a-z])/g, (_, c) => c.toUpperCase()), (value) => typeof value === "string" && (0, viem.isAddress)(value.toLowerCase()) ? value.toLowerCase() : value);
381
+ return processObject(obj, (s) => (0, viem.isAddress)(s.toLowerCase()) ? s : s.replace(/_([a-z])/g, (_, c) => c.toUpperCase()), (value) => typeof value === "string" && (0, viem.isAddress)(value.toLowerCase()) ? value.toLowerCase() : value);
373
382
  }
374
383
  function processObject(obj, fnKey, fnValue) {
375
384
  if (typeof obj !== "object" || obj === null) return obj;
@@ -393,7 +402,7 @@ function stringifyBigint(value) {
393
402
 
394
403
  //#endregion
395
404
  //#region src/utils/Group.ts
396
- var Group_exports = /* @__PURE__ */ __export({ fromNumber: () => fromNumber });
405
+ var Group_exports = /* @__PURE__ */ __exportAll({ fromNumber: () => fromNumber });
397
406
  /**
398
407
  * Creates a bytes32 group identifier from a number.
399
408
  * @param n - A non-negative integer.
@@ -417,8 +426,8 @@ function lazy(pollFn) {
417
426
  let active = true;
418
427
  let resolveNext = null;
419
428
  const queue = [];
420
- const wait$1 = () => new Promise((resolve$1) => {
421
- resolveNext = resolve$1;
429
+ const wait = () => new Promise((resolve) => {
430
+ resolveNext = resolve;
422
431
  });
423
432
  const emit = (item) => {
424
433
  queue.push(item);
@@ -435,7 +444,7 @@ function lazy(pollFn) {
435
444
  unpoll = pollFn(emit, { stop });
436
445
  try {
437
446
  while (active) {
438
- if (queue.length === 0) await wait$1();
447
+ if (queue.length === 0) await wait();
439
448
  while (queue.length > 0 && active) yield queue.shift();
440
449
  }
441
450
  } finally {
@@ -474,7 +483,7 @@ function poll(fn, { interval }) {
474
483
 
475
484
  //#endregion
476
485
  //#region src/utils/Random.ts
477
- var Random_exports = /* @__PURE__ */ __export({
486
+ var Random_exports = /* @__PURE__ */ __exportAll({
478
487
  address: () => address,
479
488
  bool: () => bool,
480
489
  bytes: () => bytes,
@@ -487,16 +496,16 @@ var Random_exports = /* @__PURE__ */ __export({
487
496
  let currentRng = Math.random;
488
497
  const FNV_OFFSET_BASIS = 2166136261;
489
498
  const FNV_PRIME = 16777619;
490
- const hashSeed = (seed$1) => {
491
- let hash$1 = FNV_OFFSET_BASIS;
492
- for (let i = 0; i < seed$1.length; i += 1) {
493
- hash$1 ^= seed$1.charCodeAt(i);
494
- hash$1 = Math.imul(hash$1, FNV_PRIME);
499
+ const hashSeed = (seed) => {
500
+ let hash = FNV_OFFSET_BASIS;
501
+ for (let i = 0; i < seed.length; i += 1) {
502
+ hash ^= seed.charCodeAt(i);
503
+ hash = Math.imul(hash, FNV_PRIME);
495
504
  }
496
- return hash$1 >>> 0;
505
+ return hash >>> 0;
497
506
  };
498
- const createSeededRng = (seed$1) => {
499
- let state = hashSeed(seed$1);
507
+ const createSeededRng = (seed) => {
508
+ let state = hashSeed(seed);
500
509
  return () => {
501
510
  state += 1831565813;
502
511
  let t = Math.imul(state ^ state >>> 15, state | 1);
@@ -507,9 +516,9 @@ const createSeededRng = (seed$1) => {
507
516
  /**
508
517
  * Runs a function with a deterministic RNG derived from the given seed.
509
518
  */
510
- function withSeed(seed$1, fn) {
519
+ function withSeed(seed, fn) {
511
520
  const previous = currentRng;
512
- currentRng = createSeededRng(seed$1);
521
+ currentRng = createSeededRng(seed);
513
522
  try {
514
523
  return fn();
515
524
  } finally {
@@ -519,8 +528,8 @@ function withSeed(seed$1, fn) {
519
528
  /**
520
529
  * Seeds the global RNG for deterministic test runs.
521
530
  */
522
- function seed(seed$1) {
523
- currentRng = createSeededRng(seed$1);
531
+ function seed(seed) {
532
+ currentRng = createSeededRng(seed);
524
533
  }
525
534
  /**
526
535
  * Returns a deterministic random float in [0, 1).
@@ -531,8 +540,8 @@ function float() {
531
540
  /**
532
541
  * Returns a deterministic random integer in [min, maxExclusive).
533
542
  */
534
- function int(maxExclusive, min$1 = 0) {
535
- return Math.floor(float() * (maxExclusive - min$1)) + min$1;
543
+ function int(maxExclusive, min = 0) {
544
+ return Math.floor(float() * (maxExclusive - min)) + min;
536
545
  }
537
546
  /**
538
547
  * Returns a deterministic random boolean.
@@ -564,7 +573,7 @@ function address() {
564
573
 
565
574
  //#endregion
566
575
  //#region src/utils/time.ts
567
- var time_exports = /* @__PURE__ */ __export({
576
+ var time_exports = /* @__PURE__ */ __exportAll({
568
577
  max: () => max,
569
578
  now: () => now
570
579
  });
@@ -577,7 +586,7 @@ function max() {
577
586
 
578
587
  //#endregion
579
588
  //#region src/utils/index.ts
580
- var utils_exports = /* @__PURE__ */ __export({
589
+ var utils_exports = /* @__PURE__ */ __exportAll({
581
590
  BaseError: () => BaseError,
582
591
  Group: () => Group_exports,
583
592
  Random: () => Random_exports,
@@ -720,14 +729,14 @@ const reconcile = async (parameters) => {
720
729
  if (block.hash === null || block.number === null || block.parentHash === null) throw new Error("Failed to get block");
721
730
  const latestBlock = unfinalizedBlocks[unfinalizedBlocks.length - 1];
722
731
  if (latestBlock === void 0) {
723
- const newBlock$1 = {
732
+ const newBlock = {
724
733
  hash: block.hash,
725
734
  number: block.number,
726
735
  parentHash: block.parentHash
727
736
  };
728
- unfinalizedBlocks.push(newBlock$1);
737
+ unfinalizedBlocks.push(newBlock);
729
738
  return {
730
- block: newBlock$1,
739
+ block: newBlock,
731
740
  didReorgHappened: false,
732
741
  unfinalizedBlocks
733
742
  };
@@ -762,14 +771,14 @@ const reconcile = async (parameters) => {
762
771
  msg: `Missing blocks`
763
772
  });
764
773
  const missingBlockNumbers = (() => {
765
- const missingBlockNumbers$1 = [];
766
- let start$1 = latestBlock.number + 1n;
774
+ const missingBlockNumbers = [];
775
+ let start = latestBlock.number + 1n;
767
776
  const threshold = latestBlock.number + BigInt(maxBatchSize) > block.number ? block.number : latestBlock.number + BigInt(maxBatchSize);
768
- while (start$1 < threshold) {
769
- missingBlockNumbers$1.push(start$1);
770
- start$1 = start$1 + 1n;
777
+ while (start < threshold) {
778
+ missingBlockNumbers.push(start);
779
+ start = start + 1n;
771
780
  }
772
- return missingBlockNumbers$1;
781
+ return missingBlockNumbers;
773
782
  })();
774
783
  const missingBlocks = await Promise.all(missingBlockNumbers.map((blockNumber) => retry(async () => await client.getBlock({
775
784
  blockNumber,
@@ -886,10 +895,10 @@ function create$16({ name, collect, client, db, options }) {
886
895
  }) && options.maxBlockNumber !== void 0 && lastBlockNumber !== void 0 && options.maxBlockNumber === lastBlockNumber) return;
887
896
  const { blockNumber, done } = await startActiveSpan(tracer, `${collectorId}.next`, async () => {
888
897
  if (iterator === null) throw new Error("Iterator is not initialized");
889
- const { value: blockNumber$1, done: done$1 } = await iterator.next();
898
+ const { value: blockNumber, done } = await iterator.next();
890
899
  return {
891
- blockNumber: blockNumber$1,
892
- done: done$1
900
+ blockNumber,
901
+ done
893
902
  };
894
903
  });
895
904
  if (done) iterator = null;
@@ -984,7 +993,7 @@ const MetaMorphoFactory = (0, viem.parseAbi)(["event CreateMetaMorpho(address in
984
993
 
985
994
  //#endregion
986
995
  //#region src/core/Abi/index.ts
987
- var Abi_exports = /* @__PURE__ */ __export({
996
+ var Abi_exports = /* @__PURE__ */ __exportAll({
988
997
  ERC4626: () => ERC4626,
989
998
  MetaMorpho: () => MetaMorpho,
990
999
  MetaMorphoFactory: () => MetaMorphoFactory,
@@ -1135,41 +1144,77 @@ const Morpho = [
1135
1144
 
1136
1145
  //#endregion
1137
1146
  //#region src/core/Callback.ts
1138
- var Callback_exports = /* @__PURE__ */ __export({
1139
- CallbackType: () => CallbackType,
1147
+ var Callback_exports = /* @__PURE__ */ __exportAll({
1148
+ Type: () => Type$1,
1140
1149
  decode: () => decode$2,
1150
+ decodeBuyERC20: () => decodeBuyERC20,
1141
1151
  decodeBuyVaultV1Callback: () => decodeBuyVaultV1Callback,
1142
1152
  decodeSellERC20Callback: () => decodeSellERC20Callback,
1143
1153
  encode: () => encode$2,
1154
+ encodeBuyERC20: () => encodeBuyERC20,
1144
1155
  encodeBuyVaultV1Callback: () => encodeBuyVaultV1Callback,
1145
1156
  encodeSellERC20Callback: () => encodeSellERC20Callback,
1146
1157
  isEmptyCallback: () => isEmptyCallback
1147
1158
  });
1148
- let CallbackType = /* @__PURE__ */ function(CallbackType$1) {
1149
- CallbackType$1["BuyWithEmptyCallback"] = "buy_with_empty_callback";
1150
- CallbackType$1["BuyVaultV1Callback"] = "buy_vault_v1_callback";
1151
- CallbackType$1["SellERC20Callback"] = "sell_erc20_callback";
1152
- return CallbackType$1;
1159
+ let Type$1 = /* @__PURE__ */ function(Type) {
1160
+ Type["BuyWithEmptyCallback"] = "buy_with_empty_callback";
1161
+ Type["BuyERC20"] = "buy_erc20";
1162
+ Type["BuyVaultV1Callback"] = "buy_vault_v1_callback";
1163
+ Type["SellERC20Callback"] = "sell_erc20_callback";
1164
+ return Type;
1153
1165
  }({});
1154
1166
  const isEmptyCallback = (offer) => offer.callback.data === "0x";
1155
1167
  function decode$2(type, data) {
1156
1168
  switch (type) {
1157
- case CallbackType.BuyVaultV1Callback: return decodeBuyVaultV1Callback(data);
1158
- case CallbackType.SellERC20Callback: return decodeSellERC20Callback(data);
1169
+ case Type$1.BuyERC20: return decodeBuyERC20(data);
1170
+ case Type$1.BuyVaultV1Callback: return decodeBuyVaultV1Callback(data);
1171
+ case Type$1.SellERC20Callback: return decodeSellERC20Callback(data);
1159
1172
  default: throw new Error("Invalid callback type");
1160
1173
  }
1161
1174
  }
1162
1175
  function encode$2(type, data) {
1163
1176
  switch (type) {
1164
- case CallbackType.BuyVaultV1Callback:
1177
+ case Type$1.BuyERC20:
1178
+ if (!("tokens" in data)) throw new Error("Invalid callback data");
1179
+ return encodeBuyERC20(data);
1180
+ case Type$1.BuyVaultV1Callback:
1165
1181
  if (!("vaults" in data)) throw new Error("Invalid callback data");
1166
1182
  return encodeBuyVaultV1Callback(data);
1167
- case CallbackType.SellERC20Callback:
1183
+ case Type$1.SellERC20Callback:
1168
1184
  if (!("collaterals" in data)) throw new Error("Invalid callback data");
1169
1185
  return encodeSellERC20Callback(data);
1170
1186
  default: throw new Error("Invalid callback type");
1171
1187
  }
1172
1188
  }
1189
+ /**
1190
+ * Decodes BuyERC20 callback data into positions.
1191
+ * @param data - The ABI-encoded callback data containing token addresses and amounts.
1192
+ * @returns Array of positions with contract address and amount.
1193
+ * @throws If data is empty, malformed, or arrays have mismatched lengths.
1194
+ */
1195
+ function decodeBuyERC20(data) {
1196
+ if (!data || data === "0x") throw new Error("Empty callback data");
1197
+ let tokens;
1198
+ let amounts;
1199
+ try {
1200
+ [tokens, amounts] = (0, viem.decodeAbiParameters)([{ type: "address[]" }, { type: "uint256[]" }], data);
1201
+ } catch (_) {
1202
+ throw new Error("Invalid BuyERC20 callback data");
1203
+ }
1204
+ if (tokens.length !== amounts.length) throw new Error("Mismatched array lengths");
1205
+ return tokens.map((token, index) => ({
1206
+ contract: token,
1207
+ amount: amounts[index]
1208
+ }));
1209
+ }
1210
+ /**
1211
+ * Encodes BuyERC20 callback parameters into ABI-encoded data.
1212
+ * @param parameters - The tokens and amounts to encode.
1213
+ * @returns ABI-encoded hex string.
1214
+ */
1215
+ function encodeBuyERC20(parameters) {
1216
+ return (0, viem.encodeAbiParameters)([{ type: "address[]" }, { type: "uint256[]" }], [parameters.tokens, parameters.amounts]);
1217
+ }
1173
1218
  function decodeBuyVaultV1Callback(data) {
1174
1219
  if (!data || data === "0x") throw new Error("Empty callback data");
1175
1220
  try {
@@ -1205,7 +1250,7 @@ function encodeSellERC20Callback(parameters) {
1205
1250
 
1206
1251
  //#endregion
1207
1252
  //#region src/core/Chain.ts
1208
- var Chain_exports = /* @__PURE__ */ __export({
1253
+ var Chain_exports = /* @__PURE__ */ __exportAll({
1209
1254
  ChainId: () => ChainId,
1210
1255
  InvalidBatchSizeError: () => InvalidBatchSizeError,
1211
1256
  InvalidBlockRangeError: () => InvalidBlockRangeError,
@@ -1267,7 +1312,8 @@ const chains$2 = {
1267
1312
  address: "0x1897A8997241C1cD4bD0698647e4EB7213535c24",
1268
1313
  blockCreated: 21439510
1269
1314
  }
1270
- } }
1315
+ } },
1316
+ callbacks: []
1271
1317
  }
1272
1318
  },
1273
1319
  base: {
@@ -1296,7 +1342,8 @@ const chains$2 = {
1296
1342
  address: "0xFf62A7c278C62eD665133147129245053Bbf5918",
1297
1343
  blockCreated: 23928808
1298
1344
  }
1299
- } }
1345
+ } },
1346
+ callbacks: []
1300
1347
  }
1301
1348
  },
1302
1349
  "ethereum-virtual-testnet": {
@@ -1325,7 +1372,8 @@ const chains$2 = {
1325
1372
  address: "0x1897A8997241C1cD4bD0698647e4EB7213535c24",
1326
1373
  blockCreated: 21439510
1327
1374
  }
1328
- } }
1375
+ } },
1376
+ callbacks: []
1329
1377
  }
1330
1378
  },
1331
1379
  anvil: {
@@ -1354,7 +1402,8 @@ const chains$2 = {
1354
1402
  address: "0x0000000000000000000000000000000000000000",
1355
1403
  blockCreated: 0
1356
1404
  }
1357
- } }
1405
+ } },
1406
+ callbacks: []
1358
1407
  }
1359
1408
  }
1360
1409
  };
@@ -1450,10 +1499,15 @@ var MissingBlockNumberError = class extends BaseError {
1450
1499
 
1451
1500
  //#endregion
1452
1501
  //#region src/core/ChainRegistry.ts
1453
- var ChainRegistry_exports = /* @__PURE__ */ __export({ create: () => create$15 });
1454
- function create$15(chains$3) {
1502
+ var ChainRegistry_exports = /* @__PURE__ */ __exportAll({ create: () => create$15 });
1503
+ /**
1504
+ * Creates a chain registry from a list of chains.
1505
+ * @param chains - Array of chain objects to register.
1506
+ * @returns A registry for looking up chains by ID. {@link ChainRegistry}
1507
+ */
1508
+ function create$15(chains) {
1455
1509
  const byId = /* @__PURE__ */ new Map();
1456
- for (const chain of chains$3) byId.set(chain.id, chain);
1510
+ for (const chain of chains) byId.set(chain.id, chain);
1457
1511
  return {
1458
1512
  getById: (chainId) => byId.get(chainId),
1459
1513
  list: () => Array.from(byId.values())
@@ -1543,12 +1597,12 @@ const transformAddress = (val, ctx) => {
1543
1597
 
1544
1598
  //#endregion
1545
1599
  //#region src/core/LLTV.ts
1546
- var LLTV_exports = /* @__PURE__ */ __export({
1600
+ var LLTV_exports = /* @__PURE__ */ __exportAll({
1547
1601
  InvalidLLTVError: () => InvalidLLTVError,
1548
1602
  InvalidOptionError: () => InvalidOptionError$1,
1549
1603
  LLTVSchema: () => LLTVSchema,
1550
1604
  Options: () => Options,
1551
- from: () => from$17
1605
+ from: () => from$18
1552
1606
  });
1553
1607
  const Options = [
1554
1608
  .385,
@@ -1567,7 +1621,7 @@ const LLTV_SCALED = Options.map((lltv) => BigInt(lltv * 10 ** 18));
1567
1621
  * @param lltv - The LLTV option or the scaled LLTV.
1568
1622
  * @returns The LLTV.
1569
1623
  */
1570
- function from$17(lltv) {
1624
+ function from$18(lltv) {
1571
1625
  if (typeof lltv === "bigint" && !LLTV_SCALED.includes(lltv)) throw new InvalidLLTVError(lltv);
1572
1626
  if (typeof lltv === "bigint") return lltv;
1573
1627
  if (typeof lltv === "number" && !Options.includes(lltv)) throw new InvalidOptionError$1(lltv);
@@ -1587,21 +1641,21 @@ var InvalidLLTVError = class extends BaseError {
1587
1641
  };
1588
1642
  const LLTVSchema = zod.bigint({ coerce: true }).refine((lltv) => {
1589
1643
  try {
1590
- from$17(lltv);
1644
+ from$18(lltv);
1591
1645
  return true;
1592
1646
  } catch (_) {
1593
1647
  return false;
1594
1648
  }
1595
1649
  }, { error: () => {
1596
1650
  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)";
1597
- } }).transform((lltv) => from$17(lltv));
1651
+ } }).transform((lltv) => from$18(lltv));
1598
1652
 
1599
1653
  //#endregion
1600
1654
  //#region src/core/Collateral.ts
1601
- var Collateral_exports = /* @__PURE__ */ __export({
1655
+ var Collateral_exports = /* @__PURE__ */ __exportAll({
1602
1656
  CollateralSchema: () => CollateralSchema,
1603
1657
  CollateralsSchema: () => CollateralsSchema,
1604
- from: () => from$16,
1658
+ from: () => from$17,
1605
1659
  random: () => random$3
1606
1660
  });
1607
1661
  const CollateralSchema = zod.object({
@@ -1621,10 +1675,10 @@ const CollateralsSchema = zod.array(CollateralSchema).min(1, { message: "At leas
1621
1675
  }
1622
1676
  return true;
1623
1677
  }, { message: "Collaterals must not contain duplicate assets" });
1624
- const from$16 = (parameters) => {
1678
+ const from$17 = (parameters) => {
1625
1679
  return {
1626
1680
  asset: parameters.asset.toLowerCase(),
1627
- lltv: from$17(parameters.lltv),
1681
+ lltv: from$18(parameters.lltv),
1628
1682
  oracle: parameters.oracle.toLowerCase()
1629
1683
  };
1630
1684
  };
@@ -1638,7 +1692,7 @@ const from$16 = (parameters) => {
1638
1692
  * ```
1639
1693
  */
1640
1694
  function random$3() {
1641
- return from$16({
1695
+ return from$17({
1642
1696
  asset: address(),
1643
1697
  oracle: address(),
1644
1698
  lltv: .965
@@ -1647,7 +1701,7 @@ function random$3() {
1647
1701
 
1648
1702
  //#endregion
1649
1703
  //#region src/core/ERC4626.ts
1650
- var ERC4626_exports = /* @__PURE__ */ __export({
1704
+ var ERC4626_exports = /* @__PURE__ */ __exportAll({
1651
1705
  DenominatorIsZeroError: () => DenominatorIsZeroError,
1652
1706
  convertToAssets: () => convertToAssets,
1653
1707
  convertToShares: () => convertToShares,
@@ -1710,7 +1764,7 @@ var DenominatorIsZeroError = class extends BaseError {
1710
1764
 
1711
1765
  //#endregion
1712
1766
  //#region src/core/Liquidity.ts
1713
- var Liquidity_exports = /* @__PURE__ */ __export({
1767
+ var Liquidity_exports = /* @__PURE__ */ __exportAll({
1714
1768
  calculateMaxDebt: () => calculateMaxDebt,
1715
1769
  generateAllowancePoolId: () => generateAllowancePoolId,
1716
1770
  generateBalancePoolId: () => generateBalancePoolId,
@@ -1736,23 +1790,23 @@ function calculateMaxDebt(amount, oraclePrice, lltv) {
1736
1790
  * Generate pool ID for balance pools.
1737
1791
  */
1738
1792
  function generateBalancePoolId(parameters) {
1739
- const { user, chainId, token: token$1 } = parameters;
1740
- return `${user}-${chainId.toString()}-${token$1}-balance`.toLowerCase();
1793
+ const { user, chainId, token } = parameters;
1794
+ return `${user}-${chainId.toString()}-${token}-balance`.toLowerCase();
1741
1795
  }
1742
1796
  /**
1743
1797
  * Generate pool ID for allowance pools.
1744
1798
  */
1745
1799
  function generateAllowancePoolId(parameters) {
1746
- const { user, chainId, token: token$1 } = parameters;
1747
- return `${user}-${chainId.toString()}-${token$1}-allowance`.toLowerCase();
1800
+ const { user, chainId, token } = parameters;
1801
+ return `${user}-${chainId.toString()}-${token}-allowance`.toLowerCase();
1748
1802
  }
1749
1803
  /**
1750
1804
  * Generate pool ID for sell ERC20 callback pools.
1751
1805
  * Each offer has its own callback pool to prevent liquidity conflicts.
1752
1806
  */
1753
1807
  function generateSellERC20CallbackPoolId(parameters) {
1754
- const { user, chainId, obligationId: obligationId$1, token: token$1, offerHash } = parameters;
1755
- return `${user}-${chainId.toString()}-${obligationId$1}-${token$1}-${offerHash}-sell_erc20_callback`.toLowerCase();
1808
+ const { user, chainId, obligationId, token, offerHash } = parameters;
1809
+ return `${user}-${chainId.toString()}-${obligationId}-${token}-${offerHash}-sell_erc20_callback`.toLowerCase();
1756
1810
  }
1757
1811
  /**
1758
1812
  * Generate pool ID for obligation collateral pools.
@@ -1760,22 +1814,22 @@ function generateSellERC20CallbackPoolId(parameters) {
1760
1814
  * These pools are shared across all offers with the same obligation.
1761
1815
  */
1762
1816
  function generateObligationCollateralPoolId(parameters) {
1763
- const { user, chainId, obligationId: obligationId$1, token: token$1 } = parameters;
1764
- return `${user}-${chainId.toString()}-${obligationId$1}-${token$1}-obligation-collateral`.toLowerCase();
1817
+ const { user, chainId, obligationId, token } = parameters;
1818
+ return `${user}-${chainId.toString()}-${obligationId}-${token}-obligation-collateral`.toLowerCase();
1765
1819
  }
1766
1820
  /**
1767
1821
  * Generate pool ID for buy vault callback pools.
1768
1822
  */
1769
1823
  function generateBuyVaultCallbackPoolId(parameters) {
1770
1824
  const { user, chainId, vault, offerHash } = parameters;
1771
- return `${user}-${chainId.toString()}-${vault}-${offerHash}-${CallbackType.BuyVaultV1Callback}`.toLowerCase();
1825
+ return `${user}-${chainId.toString()}-${vault}-${offerHash}-${Type$1.BuyVaultV1Callback}`.toLowerCase();
1772
1826
  }
1773
1827
  /**
1774
1828
  * Generate pool ID for debt pools.
1775
1829
  */
1776
1830
  function generateDebtPoolId(parameters) {
1777
- const { user, chainId, obligationId: obligationId$1 } = parameters;
1778
- return `${user}-${chainId.toString()}-${obligationId$1}-debt`.toLowerCase();
1831
+ const { user, chainId, obligationId } = parameters;
1832
+ return `${user}-${chainId.toString()}-${obligationId}-debt`.toLowerCase();
1779
1833
  }
1780
1834
  /**
1781
1835
  * Generate pool ID for user position in a vault.
@@ -1801,17 +1855,17 @@ function generateMarketLiquidityPoolId(parameters) {
1801
1855
 
1802
1856
  //#endregion
1803
1857
  //#region src/core/Maturity.ts
1804
- var Maturity_exports = /* @__PURE__ */ __export({
1858
+ var Maturity_exports = /* @__PURE__ */ __exportAll({
1805
1859
  InvalidDateError: () => InvalidDateError,
1806
1860
  InvalidFormatError: () => InvalidFormatError,
1807
1861
  InvalidOptionError: () => InvalidOptionError,
1808
1862
  MaturitySchema: () => MaturitySchema,
1809
1863
  MaturityType: () => MaturityType,
1810
- from: () => from$15
1864
+ from: () => from$16
1811
1865
  });
1812
- const MaturitySchema = zod.number().int().refine((maturity$1) => {
1866
+ const MaturitySchema = zod.number().int().refine((maturity) => {
1813
1867
  try {
1814
- from$15(maturity$1);
1868
+ from$16(maturity);
1815
1869
  return true;
1816
1870
  } catch (_e) {
1817
1871
  return false;
@@ -1822,15 +1876,15 @@ const MaturitySchema = zod.number().int().refine((maturity$1) => {
1822
1876
  } catch (_) {
1823
1877
  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).`;
1824
1878
  }
1825
- } }).transform((maturity$1) => maturity$1);
1826
- let MaturityType = /* @__PURE__ */ function(MaturityType$1) {
1827
- MaturityType$1["EndOfWeek"] = "end_of_week";
1828
- MaturityType$1["EndOfNextWeek"] = "end_of_next_week";
1829
- MaturityType$1["EndOfMonth"] = "end_of_month";
1830
- MaturityType$1["EndOfNextMonth"] = "end_of_next_month";
1831
- MaturityType$1["EndOfQuarter"] = "end_of_quarter";
1832
- MaturityType$1["EndOfNextQuarter"] = "end_of_next_quarter";
1833
- return MaturityType$1;
1879
+ } }).transform((maturity) => maturity);
1880
+ let MaturityType = /* @__PURE__ */ function(MaturityType) {
1881
+ MaturityType["EndOfWeek"] = "end_of_week";
1882
+ MaturityType["EndOfNextWeek"] = "end_of_next_week";
1883
+ MaturityType["EndOfMonth"] = "end_of_month";
1884
+ MaturityType["EndOfNextMonth"] = "end_of_next_month";
1885
+ MaturityType["EndOfQuarter"] = "end_of_quarter";
1886
+ MaturityType["EndOfNextQuarter"] = "end_of_next_quarter";
1887
+ return MaturityType;
1834
1888
  }({});
1835
1889
  const MaturityOptions = {
1836
1890
  end_of_week: () => endOfWeek(),
@@ -1846,7 +1900,7 @@ const MaturityOptions = {
1846
1900
  * @throws {InvalidDateError} If the maturity is in seconds but not a valid date.
1847
1901
  * @throws {InvalidOptionError} If the maturity is not a valid option.
1848
1902
  */
1849
- function from$15(ts) {
1903
+ function from$16(ts) {
1850
1904
  if (typeof ts === "string") {
1851
1905
  if (ts in MaturityOptions) return MaturityOptions[ts]();
1852
1906
  throw new InvalidOptionError(ts);
@@ -1864,23 +1918,23 @@ const endOfNextWeek = () => fridayOfWeek(1);
1864
1918
  * on that Friday), roll to the next month's last Friday.
1865
1919
  */
1866
1920
  const endOfMonth = () => {
1867
- const now$1 = /* @__PURE__ */ new Date();
1868
- const year = now$1.getUTCFullYear();
1869
- const month = now$1.getUTCMonth();
1870
- const endOfMonth$1 = lastFridayOfMonth(year, month);
1871
- if (now$1.getTime() > endOfMonth$1 * 1e3) return lastFridayOfMonth(year, month + 1);
1872
- return endOfMonth$1;
1921
+ const now = /* @__PURE__ */ new Date();
1922
+ const year = now.getUTCFullYear();
1923
+ const month = now.getUTCMonth();
1924
+ const endOfMonth = lastFridayOfMonth(year, month);
1925
+ if (now.getTime() > endOfMonth * 1e3) return lastFridayOfMonth(year, month + 1);
1926
+ return endOfMonth;
1873
1927
  };
1874
1928
  /** Returns the end of the next month (last friday of the next month at 15:00:00 UTC)
1875
1929
  * Business rule: if we are after the last Friday of the current month (strictly after 15:00 UTC
1876
1930
  * on that Friday), we consider being in the next month already, so "next month" becomes month+2.
1877
1931
  */
1878
1932
  const endOfNextMonth = () => {
1879
- const now$1 = /* @__PURE__ */ new Date();
1880
- const year = now$1.getUTCFullYear();
1881
- const month = now$1.getUTCMonth();
1882
- const endOfMonth$1 = lastFridayOfMonth(year, month);
1883
- if (now$1.getTime() > endOfMonth$1 * 1e3) return lastFridayOfMonth(year, month + 2);
1933
+ const now = /* @__PURE__ */ new Date();
1934
+ const year = now.getUTCFullYear();
1935
+ const month = now.getUTCMonth();
1936
+ const endOfMonth = lastFridayOfMonth(year, month);
1937
+ if (now.getTime() > endOfMonth * 1e3) return lastFridayOfMonth(year, month + 2);
1884
1938
  return lastFridayOfMonth(year, month + 1);
1885
1939
  };
1886
1940
  /** Returns the end of the current quarter (last friday of the quarter at 15:00:00 UTC) */
@@ -1888,10 +1942,10 @@ const endOfQuarter = () => lastFridayOfQuarter(0);
1888
1942
  /** Returns the end of the next quarter (last friday of the next quarter at 15:00:00 UTC) */
1889
1943
  const endOfNextQuarter = () => lastFridayOfQuarter(1);
1890
1944
  const fridayOfWeek = (weeksAhead = 0) => {
1891
- const now$1 = /* @__PURE__ */ new Date();
1892
- const today15H = new Date(Date.UTC(now$1.getUTCFullYear(), now$1.getUTCMonth(), now$1.getUTCDate(), 15));
1945
+ const now = /* @__PURE__ */ new Date();
1946
+ const today15H = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), 15));
1893
1947
  let daysUntilFriday = (5 - today15H.getUTCDay() + 7) % 7;
1894
- if (daysUntilFriday === 0 && now$1.getTime() >= today15H.getTime()) daysUntilFriday = 7;
1948
+ if (daysUntilFriday === 0 && now.getTime() >= today15H.getTime()) daysUntilFriday = 7;
1895
1949
  const friday = new Date(today15H);
1896
1950
  friday.setUTCDate(friday.getUTCDate() + daysUntilFriday + weeksAhead * 7);
1897
1951
  return friday.getTime() / 1e3;
@@ -1902,9 +1956,9 @@ const lastFridayOfMonth = (year, month) => {
1902
1956
  return lastDayOfMonth15H.setUTCDate(lastDayOfMonth15H.getUTCDate()) / 1e3;
1903
1957
  };
1904
1958
  const lastFridayOfQuarter = (quartersAhead = 0) => {
1905
- const now$1 = /* @__PURE__ */ new Date();
1906
- const quarterIndex = Math.floor(now$1.getUTCMonth() / 3) + quartersAhead;
1907
- return lastFridayOfMonth(now$1.getUTCFullYear() + Math.floor(quarterIndex / 4), quarterIndex % 4 * 3 + 2);
1959
+ const now = /* @__PURE__ */ new Date();
1960
+ const quarterIndex = Math.floor(now.getUTCMonth() / 3) + quartersAhead;
1961
+ return lastFridayOfMonth(now.getUTCFullYear() + Math.floor(quarterIndex / 4), quarterIndex % 4 * 3 + 2);
1908
1962
  };
1909
1963
  var InvalidFormatError = class extends BaseError {
1910
1964
  name = "Maturity.InvalidFormatError";
@@ -1927,11 +1981,11 @@ var InvalidOptionError = class extends BaseError {
1927
1981
 
1928
1982
  //#endregion
1929
1983
  //#region src/core/Obligation.ts
1930
- var Obligation_exports = /* @__PURE__ */ __export({
1984
+ var Obligation_exports = /* @__PURE__ */ __exportAll({
1931
1985
  CollateralsAreNotSortedError: () => CollateralsAreNotSortedError,
1932
1986
  InvalidObligationError: () => InvalidObligationError,
1933
1987
  ObligationSchema: () => ObligationSchema,
1934
- from: () => from$14,
1988
+ from: () => from$15,
1935
1989
  fromSnakeCase: () => fromSnakeCase$2,
1936
1990
  id: () => id,
1937
1991
  random: () => random$2
@@ -1965,11 +2019,11 @@ const ObligationSchema = zod.object({
1965
2019
  * });
1966
2020
  * ```
1967
2021
  */
1968
- function from$14(parameters) {
2022
+ function from$15(parameters) {
1969
2023
  try {
1970
2024
  const parsedObligation = ObligationSchema.parse({
1971
2025
  ...parameters,
1972
- maturity: from$15(parameters.maturity)
2026
+ maturity: from$16(parameters.maturity)
1973
2027
  });
1974
2028
  return {
1975
2029
  chainId: parsedObligation.chainId,
@@ -1988,7 +2042,7 @@ function from$14(parameters) {
1988
2042
  * @returns The created obligation. {@link fromSnakeCase.ReturnType}
1989
2043
  */
1990
2044
  function fromSnakeCase$2(input) {
1991
- return from$14(fromSnakeCase$3(input));
2045
+ return from$15(fromSnakeCase$3(input));
1992
2046
  }
1993
2047
  /**
1994
2048
  * Calculates the obligation id based on the smart contract's Obligation struct.
@@ -2053,11 +2107,11 @@ function id(parameters) {
2053
2107
  * ```
2054
2108
  */
2055
2109
  function random$2() {
2056
- return from$14({
2110
+ return from$15({
2057
2111
  chainId: 1,
2058
2112
  loanToken: address(),
2059
2113
  collaterals: [random$3()],
2060
- maturity: from$15("end_of_next_quarter")
2114
+ maturity: from$16("end_of_next_quarter")
2061
2115
  });
2062
2116
  }
2063
2117
  var InvalidObligationError = class extends BaseError {
@@ -2075,7 +2129,7 @@ var CollateralsAreNotSortedError = class extends BaseError {
2075
2129
 
2076
2130
  //#endregion
2077
2131
  //#region src/core/Tree.ts
2078
- var Tree_exports = /* @__PURE__ */ __export({
2132
+ var Tree_exports = /* @__PURE__ */ __exportAll({
2079
2133
  DecodeError: () => DecodeError,
2080
2134
  EncodeError: () => EncodeError,
2081
2135
  TreeError: () => TreeError,
@@ -2083,11 +2137,11 @@ var Tree_exports = /* @__PURE__ */ __export({
2083
2137
  decode: () => decode$1,
2084
2138
  encode: () => encode$1,
2085
2139
  encodeUnsigned: () => encodeUnsigned,
2086
- from: () => from$13,
2140
+ from: () => from$14,
2087
2141
  proofs: () => proofs
2088
2142
  });
2089
2143
  const VERSION$1 = 1;
2090
- const normalizeHash = (hash$1) => hash$1.toLowerCase();
2144
+ const normalizeHash = (hash) => hash.toLowerCase();
2091
2145
  /**
2092
2146
  * Builds a Merkle tree from a list of offers.
2093
2147
  *
@@ -2099,19 +2153,19 @@ const normalizeHash = (hash$1) => hash$1.toLowerCase();
2099
2153
  * @returns A `StandardMerkleTree` of `bytes32` leaves representing the offers.
2100
2154
  * @throws {TreeError} If tree building fails due to offer inconsistencies.
2101
2155
  */
2102
- const from$13 = (offers$1) => {
2103
- const leaves = offers$1.map((offer) => [hash(offer)]);
2104
- const tree = __openzeppelin_merkle_tree.StandardMerkleTree.of(leaves, ["bytes32"]);
2105
- const orderedOffers = orderOffers(tree, offers$1);
2156
+ const from$14 = (offers) => {
2157
+ const leaves = offers.map((offer) => [hash(offer)]);
2158
+ const tree = _openzeppelin_merkle_tree.StandardMerkleTree.of(leaves, ["bytes32"]);
2159
+ const orderedOffers = orderOffers(tree, offers);
2106
2160
  return Object.assign(tree, { offers: orderedOffers });
2107
2161
  };
2108
- const orderOffers = (tree, offers$1) => {
2162
+ const orderOffers = (tree, offers) => {
2109
2163
  const offerByHash = /* @__PURE__ */ new Map();
2110
- for (const offer of offers$1) offerByHash.set(normalizeHash(hash(offer)), offer);
2164
+ for (const offer of offers) offerByHash.set(normalizeHash(hash(offer)), offer);
2111
2165
  const entries = tree.dump().values.map((value) => {
2112
- const hash$1 = normalizeHash(value.value[0]);
2113
- const offer = offerByHash.get(hash$1);
2114
- if (!offer) throw new TreeError(`missing offer for leaf ${hash$1}`);
2166
+ const hash = normalizeHash(value.value[0]);
2167
+ const offer = offerByHash.get(hash);
2168
+ if (!offer) throw new TreeError(`missing offer for leaf ${hash}`);
2115
2169
  return {
2116
2170
  offer,
2117
2171
  treeIndex: value.treeIndex
@@ -2144,10 +2198,10 @@ const assertHex = (value, expectedBytes, name) => {
2144
2198
  const verifySignatureAndRecoverAddress = async (params) => {
2145
2199
  const { root, signature } = params;
2146
2200
  assertHex(signature, 65, "signature");
2147
- const hash$1 = (0, viem.hashMessage)({ raw: root });
2201
+ const hash = (0, viem.hashMessage)({ raw: root });
2148
2202
  try {
2149
2203
  return await (0, viem.recoverAddress)({
2150
- hash: hash$1,
2204
+ hash,
2151
2205
  signature
2152
2206
  });
2153
2207
  } catch {
@@ -2221,7 +2275,7 @@ const encodeUnsigned = (tree) => {
2221
2275
  };
2222
2276
  const validateTreeForEncoding = (tree) => {
2223
2277
  if (VERSION$1 > 255) throw new EncodeError(`version overflow: ${VERSION$1} exceeds 255`);
2224
- const computed = from$13(tree.offers);
2278
+ const computed = from$14(tree.offers);
2225
2279
  if (tree.root !== computed.root) throw new EncodeError(`root mismatch: expected ${computed.root}, got ${tree.root}`);
2226
2280
  };
2227
2281
  const encodeUnsignedBytes = (tree) => {
@@ -2257,19 +2311,19 @@ const encodeUnsignedBytes = (tree) => {
2257
2311
  * @throws {DecodeError} If version invalid, signature invalid, or root mismatch
2258
2312
  */
2259
2313
  const decode$1 = async (encoded) => {
2260
- const bytes$1 = (0, viem.hexToBytes)(encoded);
2261
- if (bytes$1.length < 98) throw new DecodeError("payload too short");
2262
- const version = bytes$1[0];
2314
+ const bytes = (0, viem.hexToBytes)(encoded);
2315
+ if (bytes.length < 98) throw new DecodeError("payload too short");
2316
+ const version = bytes[0];
2263
2317
  if (version !== (VERSION$1 & 255)) throw new DecodeError(`invalid version: expected ${VERSION$1}, got ${version ?? 0}`);
2264
- const signature = (0, viem.bytesToHex)(bytes$1.slice(-65));
2265
- const root = (0, viem.bytesToHex)(bytes$1.slice(-97, -65));
2318
+ const signature = (0, viem.bytesToHex)(bytes.slice(-65));
2319
+ const root = (0, viem.bytesToHex)(bytes.slice(-97, -65));
2266
2320
  assertHex(root, 32, "root");
2267
2321
  assertHex(signature, 65, "signature");
2268
2322
  const signer = await verifySignatureAndRecoverAddress({
2269
2323
  root,
2270
2324
  signature
2271
2325
  });
2272
- const compressed = bytes$1.slice(1, -97);
2326
+ const compressed = bytes.slice(1, -97);
2273
2327
  let decoded;
2274
2328
  try {
2275
2329
  decoded = (0, pako.ungzip)(compressed, { to: "string" });
@@ -2282,7 +2336,7 @@ const decode$1 = async (encoded) => {
2282
2336
  } catch {
2283
2337
  throw new DecodeError("JSON parse failed");
2284
2338
  }
2285
- const tree = from$13(rawOffers.map((o) => OfferSchema().parse(o)));
2339
+ const tree = from$14(rawOffers.map((o) => OfferSchema().parse(o)));
2286
2340
  if (root !== tree.root) throw new DecodeError(`root mismatch: expected ${tree.root}, got ${root}`);
2287
2341
  return {
2288
2342
  tree,
@@ -2323,7 +2377,7 @@ var DecodeError = class extends BaseError {
2323
2377
 
2324
2378
  //#endregion
2325
2379
  //#region src/core/Offer.ts
2326
- var Offer_exports = /* @__PURE__ */ __export({
2380
+ var Offer_exports = /* @__PURE__ */ __exportAll({
2327
2381
  AccountNotSetError: () => AccountNotSetError,
2328
2382
  InvalidOfferError: () => InvalidOfferError,
2329
2383
  OfferSchema: () => OfferSchema,
@@ -2332,7 +2386,7 @@ var Offer_exports = /* @__PURE__ */ __export({
2332
2386
  decode: () => decode,
2333
2387
  domain: () => domain,
2334
2388
  encode: () => encode,
2335
- from: () => from$12,
2389
+ from: () => from$13,
2336
2390
  fromSnakeCase: () => fromSnakeCase$1,
2337
2391
  hash: () => hash,
2338
2392
  obligationId: () => obligationId,
@@ -2345,10 +2399,10 @@ var Offer_exports = /* @__PURE__ */ __export({
2345
2399
  });
2346
2400
  /** Internal symbol for caching the computed hash. */
2347
2401
  const HASH_CACHE = Symbol("offer.hash");
2348
- let Status = /* @__PURE__ */ function(Status$1) {
2349
- Status$1["VALID"] = "VALID";
2350
- Status$1["SIMULATION_ERROR"] = "SIMULATION_ERROR";
2351
- return Status$1;
2402
+ let Status = /* @__PURE__ */ function(Status) {
2403
+ Status["VALID"] = "VALID";
2404
+ Status["SIMULATION_ERROR"] = "SIMULATION_ERROR";
2405
+ return Status;
2352
2406
  }({});
2353
2407
  const OfferSchema = () => {
2354
2408
  return zod.object({
@@ -2392,7 +2446,7 @@ const OfferSchema = () => {
2392
2446
  * @param input - The offer to create.
2393
2447
  * @returns The created offer.
2394
2448
  */
2395
- function from$12(input) {
2449
+ function from$13(input) {
2396
2450
  try {
2397
2451
  return OfferSchema().parse(input);
2398
2452
  } catch (error) {
@@ -2406,7 +2460,7 @@ function from$12(input) {
2406
2460
  * @returns The created offer.
2407
2461
  */
2408
2462
  function fromSnakeCase$1(input) {
2409
- return from$12(fromSnakeCase$3(input));
2463
+ return from$13(fromSnakeCase$3(input));
2410
2464
  }
2411
2465
  /**
2412
2466
  * Converts an offer to a snake case object.
@@ -2460,8 +2514,8 @@ function random$1(config) {
2460
2514
  const collateralCandidates = config?.collateralTokens ? config.collateralTokens.filter((a) => a !== loanToken) : [address()];
2461
2515
  const collateralAsset = collateralCandidates[int(collateralCandidates.length)];
2462
2516
  const maturityOption = weightedChoice([["end_of_month", 1], ["end_of_next_month", 1]]);
2463
- const maturity$1 = config?.maturity ?? from$15(maturityOption);
2464
- const lltv = from$17(weightedChoice([
2517
+ const maturity = config?.maturity ?? from$16(maturityOption);
2518
+ const lltv = from$18(weightedChoice([
2465
2519
  [.385, 1],
2466
2520
  [.5, 1],
2467
2521
  [.625, 2],
@@ -2500,15 +2554,15 @@ function random$1(config) {
2500
2554
  })
2501
2555
  };
2502
2556
  })();
2503
- return from$12({
2557
+ return from$13({
2504
2558
  maker: config?.maker ?? address(),
2505
2559
  assets: assetsScaled,
2506
2560
  obligationUnits: config?.obligationUnits ?? 0n,
2507
2561
  obligationShares: config?.obligationShares ?? 0n,
2508
2562
  price,
2509
- maturity: maturity$1,
2510
- expiry: config?.expiry ?? maturity$1 - 1,
2511
- start: config?.start ?? maturity$1 - 10,
2563
+ maturity,
2564
+ expiry: config?.expiry ?? maturity - 1,
2565
+ start: config?.start ?? maturity - 10,
2512
2566
  group: config?.group ?? hex(32),
2513
2567
  session: config?.session ?? hex(32),
2514
2568
  buy,
@@ -2635,15 +2689,15 @@ const types = {
2635
2689
  * @param wallet - The wallet to sign the offers with.
2636
2690
  * @returns The signed offers.
2637
2691
  */
2638
- async function sign(offers$1, wallet) {
2692
+ async function sign(offers, wallet) {
2639
2693
  if (!wallet.account) throw new AccountNotSetError();
2640
2694
  return wallet.signMessage({
2641
2695
  account: wallet.account,
2642
- message: { raw: signatureMsg(offers$1) }
2696
+ message: { raw: signatureMsg(offers) }
2643
2697
  });
2644
2698
  }
2645
- function signatureMsg(offers$1) {
2646
- return from$13(offers$1).root;
2699
+ function signatureMsg(offers) {
2700
+ return from$14(offers).root;
2647
2701
  }
2648
2702
  function hash(offer) {
2649
2703
  const cached = offer[HASH_CACHE];
@@ -2681,7 +2735,7 @@ function hash(offer) {
2681
2735
  * @returns The obligation id as a 32-byte hex string.
2682
2736
  */
2683
2737
  function obligationId(offer) {
2684
- return id(from$14({
2738
+ return id(from$15({
2685
2739
  chainId: offer.chainId,
2686
2740
  loanToken: offer.loanToken,
2687
2741
  collaterals: offer.collaterals,
@@ -2797,13 +2851,13 @@ function decode(data) {
2797
2851
  } catch (error) {
2798
2852
  throw new InvalidOfferError(error);
2799
2853
  }
2800
- return from$12({
2854
+ return from$13({
2801
2855
  maker: decoded[0],
2802
2856
  assets: decoded[1],
2803
2857
  obligationUnits: decoded[2],
2804
2858
  obligationShares: decoded[3],
2805
2859
  price: decoded[4],
2806
- maturity: from$15(Number(decoded[5])),
2860
+ maturity: from$16(Number(decoded[5])),
2807
2861
  expiry: Number(decoded[6]),
2808
2862
  group: decoded[7],
2809
2863
  session: decoded[8],
@@ -2812,7 +2866,7 @@ function decode(data) {
2812
2866
  loanToken: decoded[11],
2813
2867
  start: Number(decoded[12]),
2814
2868
  collaterals: decoded[13].map((c) => {
2815
- return from$16({
2869
+ return from$17({
2816
2870
  asset: c.asset,
2817
2871
  oracle: c.oracle,
2818
2872
  lltv: c.lltv
@@ -2885,16 +2939,16 @@ var AccountNotSetError = class extends BaseError {
2885
2939
 
2886
2940
  //#endregion
2887
2941
  //#region src/core/Oracle.ts
2888
- var Oracle_exports = /* @__PURE__ */ __export({
2942
+ var Oracle_exports = /* @__PURE__ */ __exportAll({
2889
2943
  Conversion: () => Conversion,
2890
- from: () => from$11
2944
+ from: () => from$12
2891
2945
  });
2892
2946
  /**
2893
2947
  * Create an Oracle from a plain object.
2894
2948
  * @param data - The data to create the oracle from.
2895
2949
  * @returns The created oracle.
2896
2950
  */
2897
- function from$11(data) {
2951
+ function from$12(data) {
2898
2952
  return {
2899
2953
  chainId: data.chainId,
2900
2954
  address: data.address.toLowerCase(),
@@ -2917,14 +2971,14 @@ let Conversion;
2917
2971
 
2918
2972
  //#endregion
2919
2973
  //#region src/core/Position.ts
2920
- var Position_exports = /* @__PURE__ */ __export({
2974
+ var Position_exports = /* @__PURE__ */ __exportAll({
2921
2975
  Type: () => Type,
2922
- from: () => from$10
2976
+ from: () => from$11
2923
2977
  });
2924
- let Type = /* @__PURE__ */ function(Type$1) {
2925
- Type$1["ERC20"] = "erc20";
2926
- Type$1["VAULT_V1"] = "vault_v1";
2927
- return Type$1;
2978
+ let Type = /* @__PURE__ */ function(Type) {
2979
+ Type["ERC20"] = "erc20";
2980
+ Type["VAULT_V1"] = "vault_v1";
2981
+ return Type;
2928
2982
  }({});
2929
2983
  /**
2930
2984
  * @constructor
@@ -2932,7 +2986,7 @@ let Type = /* @__PURE__ */ function(Type$1) {
2932
2986
  * @param parameters - {@link from.Parameters}
2933
2987
  * @returns The created Position. {@link from.ReturnType}
2934
2988
  */
2935
- function from$10(parameters) {
2989
+ function from$11(parameters) {
2936
2990
  return {
2937
2991
  chainId: parameters.chainId,
2938
2992
  contract: parameters.contract.toLowerCase(),
@@ -2946,10 +3000,10 @@ function from$10(parameters) {
2946
3000
 
2947
3001
  //#endregion
2948
3002
  //#region src/core/Quote.ts
2949
- var Quote_exports = /* @__PURE__ */ __export({
3003
+ var Quote_exports = /* @__PURE__ */ __exportAll({
2950
3004
  InvalidQuoteError: () => InvalidQuoteError,
2951
3005
  QuoteSchema: () => QuoteSchema,
2952
- from: () => from$9,
3006
+ from: () => from$10,
2953
3007
  fromSnakeCase: () => fromSnakeCase,
2954
3008
  random: () => random
2955
3009
  });
@@ -2970,7 +3024,7 @@ const QuoteSchema = zod.object({
2970
3024
  * const quote = Quote.from({ obligationId: "0x123", ask: { price: 100n }, bid: { price: 100n } });
2971
3025
  * ```
2972
3026
  */
2973
- function from$9(parameters) {
3027
+ function from$10(parameters) {
2974
3028
  try {
2975
3029
  const parsedQuote = QuoteSchema.parse(parameters);
2976
3030
  return {
@@ -2989,7 +3043,7 @@ function from$9(parameters) {
2989
3043
  * @returns The created quote. {@link fromSnakeCase.ReturnType}
2990
3044
  */
2991
3045
  function fromSnakeCase(snake) {
2992
- return from$9(fromSnakeCase$3(snake));
3046
+ return from$10(fromSnakeCase$3(snake));
2993
3047
  }
2994
3048
  /**
2995
3049
  * Generates a random quote.
@@ -3001,7 +3055,7 @@ function fromSnakeCase(snake) {
3001
3055
  * ```
3002
3056
  */
3003
3057
  function random() {
3004
- return from$9({
3058
+ return from$10({
3005
3059
  obligationId: id(random$2()),
3006
3060
  ask: { price: BigInt(int(1e6)) },
3007
3061
  bid: { price: BigInt(int(1e6)) }
@@ -3014,9 +3068,158 @@ var InvalidQuoteError = class extends BaseError {
3014
3068
  }
3015
3069
  };
3016
3070
 
3071
+ //#endregion
3072
+ //#region src/core/TradingFee.ts
3073
+ var TradingFee_exports = /* @__PURE__ */ __exportAll({
3074
+ BREAKPOINTS: () => BREAKPOINTS,
3075
+ InvalidFeeError: () => InvalidFeeError,
3076
+ InvalidFeesLengthError: () => InvalidFeesLengthError,
3077
+ WAD: () => WAD,
3078
+ activate: () => activate,
3079
+ compute: () => compute,
3080
+ deactivate: () => deactivate,
3081
+ from: () => from$9,
3082
+ getFees: () => getFees,
3083
+ isActivated: () => isActivated
3084
+ });
3085
+ /**
3086
+ * Time breakpoints in seconds for piecewise linear fee interpolation.
3087
+ * Matches on-chain constants: 0d, 1d, 7d, 30d, 90d, 180d.
3088
+ */
3089
+ const BREAKPOINTS = [
3090
+ 0n,
3091
+ 86400n,
3092
+ 604800n,
3093
+ 2592000n,
3094
+ 7776000n,
3095
+ 15552000n
3096
+ ];
3097
+ /** WAD constant (1e18) for fee scaling. */
3098
+ const WAD = 10n ** 18n;
3099
+ /**
3100
+ * Create a TradingFee from an activation flag and 6 fee values.
3101
+ * @param activated - Whether the fee is active.
3102
+ * @param fees - Tuple of 6 fee values in WAD (one per breakpoint: 0d, 1d, 7d, 30d, 90d, 180d).
3103
+ * @returns A new TradingFee instance.
3104
+ * @throws {@link InvalidFeeError} if any fee exceeds WAD (100%).
3105
+ * @throws {@link InvalidFeesLengthError} if fees array doesn't have exactly 6 elements.
3106
+ */
3107
+ function from$9(activated, fees) {
3108
+ if (fees.length !== 6) throw new InvalidFeesLengthError(fees.length);
3109
+ for (let i = 0; i < 6; i++) {
3110
+ const fee = fees[i];
3111
+ if (fee < 0n || fee > WAD) throw new InvalidFeeError(fee, i);
3112
+ }
3113
+ const frozenFees = Object.freeze([...fees]);
3114
+ return Object.freeze({
3115
+ _activated: activated,
3116
+ _fees: frozenFees
3117
+ });
3118
+ }
3119
+ /**
3120
+ * Compute the trading fee for a given time to maturity using piecewise linear interpolation.
3121
+ * @param tradingFee - The TradingFee instance.
3122
+ * @param timeToMaturity - Time to maturity in seconds.
3123
+ * @returns The interpolated fee in WAD. Returns 0n if not activated.
3124
+ */
3125
+ function compute(tradingFee, timeToMaturity) {
3126
+ if (!tradingFee._activated) return 0n;
3127
+ const time = BigInt(Math.max(0, Math.floor(timeToMaturity)));
3128
+ if (time >= BREAKPOINTS[5]) return tradingFee._fees[5];
3129
+ const { index, start, end } = getSegment(time);
3130
+ const feeLower = tradingFee._fees[index];
3131
+ const feeUpper = tradingFee._fees[index + 1];
3132
+ const segmentLength = end - start;
3133
+ return (feeLower * (end - time) + feeUpper * (time - start)) / segmentLength;
3134
+ }
3135
+ /**
3136
+ * Check if the trading fee is activated.
3137
+ * @param tradingFee - The TradingFee instance.
3138
+ * @returns True if activated, false otherwise.
3139
+ */
3140
+ function isActivated(tradingFee) {
3141
+ return tradingFee._activated;
3142
+ }
3143
+ /**
3144
+ * Create a new TradingFee with activation enabled.
3145
+ * @param tradingFee - The TradingFee instance.
3146
+ * @returns A new TradingFee with activated set to true.
3147
+ */
3148
+ function activate(tradingFee) {
3149
+ return Object.freeze({
3150
+ _activated: true,
3151
+ _fees: tradingFee._fees
3152
+ });
3153
+ }
3154
+ /**
3155
+ * Create a new TradingFee with activation disabled.
3156
+ * @param tradingFee - The TradingFee instance.
3157
+ * @returns A new TradingFee with activated set to false.
3158
+ */
3159
+ function deactivate(tradingFee) {
3160
+ return Object.freeze({
3161
+ _activated: false,
3162
+ _fees: tradingFee._fees
3163
+ });
3164
+ }
3165
+ /**
3166
+ * Get the fee values at each breakpoint.
3167
+ * @param tradingFee - The TradingFee instance.
3168
+ * @returns The tuple of 6 fee values.
3169
+ */
3170
+ function getFees(tradingFee) {
3171
+ return tradingFee._fees;
3172
+ }
3173
+ /**
3174
+ * Determine which segment a timeToMaturity falls into for interpolation.
3175
+ * @param timeToMaturity - Time to maturity in seconds.
3176
+ * @returns Object with index, start, and end of the segment.
3177
+ */
3178
+ function getSegment(timeToMaturity) {
3179
+ if (timeToMaturity < BREAKPOINTS[1]) return {
3180
+ index: 0,
3181
+ start: BREAKPOINTS[0],
3182
+ end: BREAKPOINTS[1]
3183
+ };
3184
+ if (timeToMaturity < BREAKPOINTS[2]) return {
3185
+ index: 1,
3186
+ start: BREAKPOINTS[1],
3187
+ end: BREAKPOINTS[2]
3188
+ };
3189
+ if (timeToMaturity < BREAKPOINTS[3]) return {
3190
+ index: 2,
3191
+ start: BREAKPOINTS[2],
3192
+ end: BREAKPOINTS[3]
3193
+ };
3194
+ if (timeToMaturity < BREAKPOINTS[4]) return {
3195
+ index: 3,
3196
+ start: BREAKPOINTS[3],
3197
+ end: BREAKPOINTS[4]
3198
+ };
3199
+ return {
3200
+ index: 4,
3201
+ start: BREAKPOINTS[4],
3202
+ end: BREAKPOINTS[5]
3203
+ };
3204
+ }
3205
+ /** Error thrown when a fee value is invalid (negative or exceeds WAD). */
3206
+ var InvalidFeeError = class extends BaseError {
3207
+ name = "TradingFee.InvalidFeeError";
3208
+ constructor(fee, index) {
3209
+ super(`Invalid fee at index ${index}: ${fee}. Fee must be between 0 and ${WAD} (WAD).`);
3210
+ }
3211
+ };
3212
+ /** Error thrown when fees array doesn't have exactly 6 elements. */
3213
+ var InvalidFeesLengthError = class extends BaseError {
3214
+ name = "TradingFee.InvalidFeesLengthError";
3215
+ constructor(length) {
3216
+ super(`Invalid fees length: ${length}. Expected exactly 6 fee values.`);
3217
+ }
3218
+ };
3219
+
3017
3220
  //#endregion
3018
3221
  //#region src/core/Transfer.ts
3019
- var Transfer_exports = /* @__PURE__ */ __export({ from: () => from$8 });
3222
+ var Transfer_exports = /* @__PURE__ */ __exportAll({ from: () => from$8 });
3020
3223
  /**
3021
3224
  * @constructor
3022
3225
  *
@@ -3251,10 +3454,13 @@ async function* collectOffersV2(parameters) {
3251
3454
  });
3252
3455
  totalValidOffers += tree.offers.length;
3253
3456
  } catch (err) {
3457
+ const error = err instanceof Error ? err : new Error(String(err));
3254
3458
  logger.error({
3255
- err,
3256
- msg: "Failed to validate offers for tree"
3459
+ err: error,
3460
+ msg: "Gatekeeper validation failed",
3461
+ chain_id: client.chain.id
3257
3462
  });
3463
+ throw new Error("Gatekeeper validation failed", { cause: error });
3258
3464
  }
3259
3465
  if (treesToInsert.length > 0) await dbTx.trees.create(treesToInsert);
3260
3466
  try {
@@ -3328,14 +3534,14 @@ async function* collectOffersV2(parameters) {
3328
3534
  * @returns {@link fetchOraclePrices.ReturnType} mapping {@link Address} to `bigint` price.
3329
3535
  */
3330
3536
  async function fetchOraclePrices(parameters) {
3331
- const { client, oracles: oracles$1, options } = parameters;
3332
- if (oracles$1.length === 0) return /* @__PURE__ */ new Map();
3537
+ const { client, oracles, options } = parameters;
3538
+ if (oracles.length === 0) return /* @__PURE__ */ new Map();
3333
3539
  const batchSize = Math.max(1, options?.batchSize ?? 5e3);
3334
3540
  const retryAttempts = Math.max(1, options?.retryAttempts ?? 3);
3335
3541
  const retryDelayMs = Math.max(0, options?.retryDelayMs ?? 50);
3336
3542
  const blockNumber = options?.blockNumber ? BigInt(options.blockNumber) : void 0;
3337
3543
  const out = /* @__PURE__ */ new Map();
3338
- for (const oraclesBatch of batch$1(oracles$1, batchSize)) {
3544
+ for (const oraclesBatch of batch$1(oracles, batchSize)) {
3339
3545
  const priceCalls = [];
3340
3546
  for (const oracle of oraclesBatch) priceCalls.push({
3341
3547
  address: oracle,
@@ -3387,17 +3593,17 @@ async function snapshotERC20Positions(parameters) {
3387
3593
  retryAttempts,
3388
3594
  retryDelayMs
3389
3595
  });
3390
- const positions$1 = [];
3596
+ const positions = [];
3391
3597
  for (let i = 0; i < balances.length; i++) {
3392
3598
  const oldPosition = oldPositions[i];
3393
3599
  if (!oldPosition) continue;
3394
- positions$1.push({
3600
+ positions.push({
3395
3601
  ...oldPosition,
3396
3602
  balance: balances[i],
3397
3603
  blockNumber
3398
3604
  });
3399
3605
  }
3400
- return positions$1;
3606
+ return positions;
3401
3607
  }
3402
3608
 
3403
3609
  //#endregion
@@ -3414,8 +3620,8 @@ async function snapshotVaultPositions(parameters) {
3414
3620
  const { client, positions: oldPositions, blockNumber, options: { maxBatchSize = 1e3, retryAttempts = 5, retryDelayMs = 500 } = {} } = parameters;
3415
3621
  const calls = [];
3416
3622
  const contracts = /* @__PURE__ */ new Map();
3417
- const positions$1 = structuredClone(oldPositions);
3418
- for (const position of positions$1) {
3623
+ const positions = structuredClone(oldPositions);
3624
+ for (const position of positions) {
3419
3625
  calls.push({
3420
3626
  address: position.contract,
3421
3627
  abi: MetaMorpho,
@@ -3512,8 +3718,8 @@ async function snapshotVaultPositions(parameters) {
3512
3718
  break;
3513
3719
  }
3514
3720
  }
3515
- for (const convertToAssets$1 of convertToAssetsList) convertToAssets$1();
3516
- return positions$1;
3721
+ for (const convertToAssets of convertToAssetsList) convertToAssets();
3722
+ return positions;
3517
3723
  }
3518
3724
 
3519
3725
  //#endregion
@@ -3562,7 +3768,7 @@ async function* collectPositions(parameters) {
3562
3768
  abi: [TransferEvent],
3563
3769
  logs
3564
3770
  });
3565
- const transfers$1 = [];
3771
+ const transfers = [];
3566
3772
  for (const log of parsedLogs) {
3567
3773
  if (log.blockNumber === null || log.logIndex === null || log.transactionHash === null) {
3568
3774
  logger.debug({
@@ -3572,7 +3778,7 @@ async function* collectPositions(parameters) {
3572
3778
  });
3573
3779
  continue;
3574
3780
  }
3575
- transfers$1.push(from$8({
3781
+ transfers.push(from$8({
3576
3782
  id: `${client.chain.id}-${log.blockNumber.toString()}-${log.transactionHash}-${log.logIndex.toString()}`,
3577
3783
  chainId: client.chain.id,
3578
3784
  contract: log.address,
@@ -3582,14 +3788,14 @@ async function* collectPositions(parameters) {
3582
3788
  blockNumber: Number(log.blockNumber)
3583
3789
  }));
3584
3790
  }
3585
- const { positions: positions$1 } = await db.positions.get({
3791
+ const { positions } = await db.positions.get({
3586
3792
  chainId: client.chain.id,
3587
3793
  filled: false
3588
3794
  });
3589
3795
  const newPositions = [];
3590
3796
  try {
3591
3797
  newPositions.push(...(await _snapshot({
3592
- positions: positions$1,
3798
+ positions,
3593
3799
  blockNumber: latestBlockNumberChain,
3594
3800
  client,
3595
3801
  maxBatchSize,
@@ -3628,9 +3834,9 @@ async function* collectPositions(parameters) {
3628
3834
  }
3629
3835
  };
3630
3836
  const insertTransfers = async () => {
3631
- if (transfers$1.length === 0) return;
3837
+ if (transfers.length === 0) return;
3632
3838
  try {
3633
- const created = await dbTx.transfers.create(transfers$1);
3839
+ const created = await dbTx.transfers.create(transfers);
3634
3840
  logger.info({
3635
3841
  msg: `New transfers`,
3636
3842
  collector,
@@ -3684,7 +3890,7 @@ async function* collectPositions(parameters) {
3684
3890
  logger.error({
3685
3891
  msg: "Failed to insert transfers",
3686
3892
  collector,
3687
- count: transfers$1.length,
3893
+ count: transfers.length,
3688
3894
  chain_id: client.chain.id,
3689
3895
  block_number: blockNumber,
3690
3896
  err
@@ -3694,7 +3900,7 @@ async function* collectPositions(parameters) {
3694
3900
  }
3695
3901
  if (!reorgDetected) {
3696
3902
  startBlock = blockNumber;
3697
- if (newPositions.length === 0 && transfers$1.length === 0 && lastStreamBlockNumber !== latestBlockNumberChain) continue;
3903
+ if (newPositions.length === 0 && transfers.length === 0 && lastStreamBlockNumber !== latestBlockNumberChain) continue;
3698
3904
  yield blockNumber;
3699
3905
  continue;
3700
3906
  }
@@ -3744,10 +3950,10 @@ async function* collectPositions(parameters) {
3744
3950
  * @returns The new positions. {@link _snapshot.ReturnType}
3745
3951
  */
3746
3952
  async function _snapshot(parameters) {
3747
- const { positions: positions$1, blockNumber, client, maxBatchSize, retryAttempts, retryDelayMs } = parameters;
3953
+ const { positions, blockNumber, client, maxBatchSize, retryAttempts, retryDelayMs } = parameters;
3748
3954
  const vaultV1Positions = [];
3749
3955
  const erc20Positions = [];
3750
- for (const position of positions$1) switch (position.type) {
3956
+ for (const position of positions) switch (position.type) {
3751
3957
  case Type.VAULT_V1:
3752
3958
  vaultV1Positions.push(position);
3753
3959
  break;
@@ -3806,12 +4012,12 @@ async function* collectPrices(parameters) {
3806
4012
  const { db, collector, client, options: { maxBatchSize = 5e3, retryAttempts = 5, retryDelayMs = 500 } = {} } = parameters;
3807
4013
  const logger = getLogger();
3808
4014
  let blockNumber = parameters.lastBlockNumber;
3809
- const [oracles$1, { blockNumber: latestBlockNumberChain, epoch }] = await Promise.all([db.oracles.get({ chainId: client.chain.id }), db.blocks.getChain(client.chain.id)]);
4015
+ const [oracles, { blockNumber: latestBlockNumberChain, epoch }] = await Promise.all([db.oracles.get({ chainId: client.chain.id }), db.blocks.getChain(client.chain.id)]);
3810
4016
  const updatedOracles = [];
3811
4017
  try {
3812
4018
  const pricesMap = await fetchOraclePrices({
3813
4019
  client,
3814
- oracles: oracles$1.map((oracle) => oracle.address),
4020
+ oracles: oracles.map((oracle) => oracle.address),
3815
4021
  options: {
3816
4022
  batchSize: maxBatchSize,
3817
4023
  blockNumber: latestBlockNumberChain,
@@ -3819,7 +4025,7 @@ async function* collectPrices(parameters) {
3819
4025
  retryDelayMs
3820
4026
  }
3821
4027
  });
3822
- for (const oracle of oracles$1) {
4028
+ for (const oracle of oracles) {
3823
4029
  const price = pricesMap.get(oracle.address);
3824
4030
  if (price !== void 0) updatedOracles.push({
3825
4031
  chainId: client.chain.id,
@@ -4002,7 +4208,7 @@ const from$7 = (parameters) => {
4002
4208
 
4003
4209
  //#endregion
4004
4210
  //#region src/indexer/Indexer.ts
4005
- var Indexer_exports = /* @__PURE__ */ __export({
4211
+ var Indexer_exports = /* @__PURE__ */ __exportAll({
4006
4212
  create: () => create$14,
4007
4213
  from: () => from$6
4008
4214
  });
@@ -4030,10 +4236,10 @@ function from$6(config) {
4030
4236
  });
4031
4237
  }
4032
4238
  function create$14(params) {
4033
- const { collectors: collectors$1, client } = params;
4239
+ const { collectors, client } = params;
4034
4240
  const indexerId = `${client.chain.id.toString()}.indexer`;
4035
4241
  const tracer = getTracer(`router.${indexerId}`);
4036
- const iterators = collectors$1.map((collector) => collector.collect());
4242
+ const iterators = collectors.map((collector) => collector.collect());
4037
4243
  const next = async () => {
4038
4244
  await startActiveSpan(tracer, `${indexerId}.next`, async () => {
4039
4245
  await Promise.all(iterators.map((iterator) => iterator.next()));
@@ -4044,7 +4250,7 @@ function create$14(params) {
4044
4250
  };
4045
4251
  return {
4046
4252
  start: () => {
4047
- const stops = collectors$1.map((collector) => start(collector));
4253
+ const stops = collectors.map((collector) => start(collector));
4048
4254
  return () => {
4049
4255
  stops.forEach((stop) => {
4050
4256
  stop();
@@ -4058,7 +4264,7 @@ function create$14(params) {
4058
4264
 
4059
4265
  //#endregion
4060
4266
  //#region src/api/Health.ts
4061
- var Health_exports = /* @__PURE__ */ __export({ create: () => create$13 });
4267
+ var Health_exports = /* @__PURE__ */ __exportAll({ create: () => create$13 });
4062
4268
  const DEFAULT_MAX_ALLOWED_LAG = 5;
4063
4269
  /**
4064
4270
  * Create a health service that exposes collector and chain block numbers.
@@ -4096,26 +4302,26 @@ function create$13(parameters) {
4096
4302
  name
4097
4303
  }))).sort((a, b) => a.chainId === b.chainId ? a.name.localeCompare(b.name) : a.chainId - b.chainId);
4098
4304
  const initialized = knownChainIds.size > 0 && missingChains.length === 0 && missingCollectors.length === 0;
4099
- const collectors$1 = Array.from(knownChainIds).sort((a, b) => a - b > 0 ? 1 : -1).flatMap((chainId) => [...names].sort().map((name) => {
4305
+ const collectors = Array.from(knownChainIds).sort((a, b) => a - b > 0 ? 1 : -1).flatMap((chainId) => [...names].sort().map((name) => {
4100
4306
  const row = collectorsByKey.get(collectorKey(chainId, name));
4101
4307
  const chain = chainById.get(chainId);
4102
4308
  const blockNumber = row?.blockNumber ?? null;
4103
4309
  const chainBlockNumber = chain?.blockNumber ?? null;
4104
4310
  const lag = blockNumber !== null && chainBlockNumber !== null ? Math.max(chainBlockNumber - blockNumber, 0) : null;
4105
- let status$1 = "unknown";
4106
- if (lag !== null) status$1 = lag <= maxAllowedLag ? "live" : "lagging";
4107
- else if (chainBlockNumber !== null) status$1 = "lagging";
4311
+ let status = "unknown";
4312
+ if (lag !== null) status = lag <= maxAllowedLag ? "live" : "lagging";
4313
+ else if (chainBlockNumber !== null) status = "lagging";
4108
4314
  return {
4109
4315
  name,
4110
4316
  chainId,
4111
4317
  blockNumber,
4112
4318
  updatedAt: row ? row.updatedAt.toISOString() : null,
4113
4319
  lag,
4114
- status: status$1,
4320
+ status,
4115
4321
  initialized: row !== void 0
4116
4322
  };
4117
4323
  }));
4118
- const chains$3 = Array.from(knownChainIds).sort((a, b) => a - b > 0 ? 1 : -1).map((chainId) => {
4324
+ const chains = Array.from(knownChainIds).sort((a, b) => a - b > 0 ? 1 : -1).map((chainId) => {
4119
4325
  const chain = chainById.get(chainId);
4120
4326
  return {
4121
4327
  chainId,
@@ -4127,12 +4333,12 @@ function create$13(parameters) {
4127
4333
  };
4128
4334
  });
4129
4335
  return {
4130
- status: collectors$1.length > 0 && collectors$1.every((collector) => collector.status === "live") ? "live" : "syncing",
4336
+ status: collectors.length > 0 && collectors.every((collector) => collector.status === "live") ? "live" : "syncing",
4131
4337
  initialized,
4132
4338
  missingChains,
4133
4339
  missingCollectors,
4134
- collectors: collectors$1,
4135
- chains: chains$3
4340
+ collectors,
4341
+ chains
4136
4342
  };
4137
4343
  };
4138
4344
  return {
@@ -4175,7 +4381,7 @@ async function getRemoteBlockNumbers(healthClients) {
4175
4381
 
4176
4382
  //#endregion
4177
4383
  //#region src/api/Schema/BookResponse.ts
4178
- var BookResponse_exports = /* @__PURE__ */ __export({ from: () => from$5 });
4384
+ var BookResponse_exports = /* @__PURE__ */ __exportAll({ from: () => from$5 });
4179
4385
  function from$5(level) {
4180
4386
  return {
4181
4387
  price: level.price.toString(),
@@ -4220,7 +4426,7 @@ const RouterStatusResponse = zod_v4.z.object({
4220
4426
 
4221
4427
  //#endregion
4222
4428
  //#region src/api/Schema/ObligationResponse.ts
4223
- var ObligationResponse_exports = /* @__PURE__ */ __export({ from: () => from$4 });
4429
+ var ObligationResponse_exports = /* @__PURE__ */ __exportAll({ from: () => from$4 });
4224
4430
  /**
4225
4431
  * Creates an `ObligationResponse` from a `Obligation`.
4226
4432
  * @constructor
@@ -4245,7 +4451,7 @@ function from$4(obligation, quote) {
4245
4451
 
4246
4452
  //#endregion
4247
4453
  //#region src/api/Schema/OfferResponse.ts
4248
- var OfferResponse_exports = /* @__PURE__ */ __export({ from: () => from$3 });
4454
+ var OfferResponse_exports = /* @__PURE__ */ __exportAll({ from: () => from$3 });
4249
4455
  /**
4250
4456
  * Creates an `OfferResponse` matching the Solidity Offer struct layout.
4251
4457
  * @constructor
@@ -4311,12 +4517,12 @@ const API_ERROR_CODES = [
4311
4517
  "INTERNAL_SERVER_ERROR",
4312
4518
  "BAD_REQUEST"
4313
4519
  ];
4314
- let STATUS_CODE = /* @__PURE__ */ function(STATUS_CODE$1) {
4315
- STATUS_CODE$1[STATUS_CODE$1["SUCCESS"] = 200] = "SUCCESS";
4316
- STATUS_CODE$1[STATUS_CODE$1["BAD_REQUEST"] = 400] = "BAD_REQUEST";
4317
- STATUS_CODE$1[STATUS_CODE$1["NOT_FOUND"] = 404] = "NOT_FOUND";
4318
- STATUS_CODE$1[STATUS_CODE$1["INTERNAL_SERVER_ERROR"] = 500] = "INTERNAL_SERVER_ERROR";
4319
- return STATUS_CODE$1;
4520
+ let STATUS_CODE = /* @__PURE__ */ function(STATUS_CODE) {
4521
+ STATUS_CODE[STATUS_CODE["SUCCESS"] = 200] = "SUCCESS";
4522
+ STATUS_CODE[STATUS_CODE["BAD_REQUEST"] = 400] = "BAD_REQUEST";
4523
+ STATUS_CODE[STATUS_CODE["NOT_FOUND"] = 404] = "NOT_FOUND";
4524
+ STATUS_CODE[STATUS_CODE["INTERNAL_SERVER_ERROR"] = 500] = "INTERNAL_SERVER_ERROR";
4525
+ return STATUS_CODE;
4320
4526
  }({});
4321
4527
  var APIError = class extends Error {
4322
4528
  constructor(statusCode, message, code, details) {
@@ -4402,7 +4608,7 @@ function handleZodError(error) {
4402
4608
  }
4403
4609
 
4404
4610
  //#endregion
4405
- //#region \0@oxc-project+runtime@0.97.0/helpers/decorate.js
4611
+ //#region \0@oxc-project+runtime@0.110.0/helpers/decorate.js
4406
4612
  function __decorate(decorators, target, key, desc) {
4407
4613
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4408
4614
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -5023,7 +5229,7 @@ __decorate([(0, openapi_metadata_decorators.ApiProperty)({
5023
5229
  type: () => [BookLevelResponse],
5024
5230
  description: "Aggregated book levels grouped by computed price."
5025
5231
  })], BookListResponse.prototype, "data", void 0);
5026
- let BooksController = class BooksController$1 {
5232
+ let BooksController = class BooksController {
5027
5233
  async getBook() {}
5028
5234
  };
5029
5235
  __decorate([
@@ -5069,7 +5275,7 @@ BooksController = __decorate([(0, openapi_metadata_decorators.ApiTags)("Markets"
5069
5275
  description: "Bad Request",
5070
5276
  type: BadRequestResponse
5071
5277
  })], BooksController);
5072
- let ValidateController = class ValidateController$1 {
5278
+ let ValidateController = class ValidateController {
5073
5279
  async validateOffers() {}
5074
5280
  };
5075
5281
  __decorate([
@@ -5096,7 +5302,7 @@ ValidateController = __decorate([(0, openapi_metadata_decorators.ApiTags)("Make"
5096
5302
  description: "Bad Request",
5097
5303
  type: BadRequestResponse
5098
5304
  })], ValidateController);
5099
- let OffersController = class OffersController$1 {
5305
+ let OffersController = class OffersController {
5100
5306
  async getOffers() {}
5101
5307
  };
5102
5308
  __decorate([
@@ -5151,7 +5357,7 @@ OffersController = __decorate([(0, openapi_metadata_decorators.ApiTags)("Markets
5151
5357
  description: "Bad Request",
5152
5358
  type: BadRequestResponse
5153
5359
  })], OffersController);
5154
- let HealthController = class HealthController$1 {
5360
+ let HealthController = class HealthController {
5155
5361
  async getRouterStatus() {}
5156
5362
  async getCollectorsHealth() {}
5157
5363
  async getChainsHealth() {}
@@ -5217,31 +5423,17 @@ __decorate([
5217
5423
  })
5218
5424
  ], HealthController.prototype, "getChainsHealth", null);
5219
5425
  HealthController = __decorate([(0, openapi_metadata_decorators.ApiTags)("System")], HealthController);
5220
- const maturitiesExample = {
5221
- end_of_month: 1738335600,
5222
- end_of_next_month: 1740754800
5223
- };
5426
+ const callbacksExample = [Type$1.BuyWithEmptyCallback];
5224
5427
  const chainConfigExample = {
5225
5428
  chain_id: 505050505,
5226
5429
  contracts: { mempool: "0xD946246695A9259F3B33a78629026F61B3Ab40aF" },
5227
- maturities: maturitiesExample
5430
+ callbacks: callbacksExample
5228
5431
  };
5229
5432
  var ConfigContractsResponse = class {};
5230
5433
  __decorate([(0, openapi_metadata_decorators.ApiProperty)({
5231
5434
  type: "string",
5232
5435
  example: chainConfigExample.contracts.mempool
5233
5436
  })], ConfigContractsResponse.prototype, "mempool", void 0);
5234
- var MaturitiesResponse = class {};
5235
- __decorate([(0, openapi_metadata_decorators.ApiProperty)({
5236
- type: "number",
5237
- description: "Unix timestamp for end of current month maturity (last Friday 15:00 UTC).",
5238
- example: maturitiesExample.end_of_month
5239
- })], MaturitiesResponse.prototype, "end_of_month", void 0);
5240
- __decorate([(0, openapi_metadata_decorators.ApiProperty)({
5241
- type: "number",
5242
- description: "Unix timestamp for end of next month maturity (last Friday 15:00 UTC).",
5243
- example: maturitiesExample.end_of_next_month
5244
- })], MaturitiesResponse.prototype, "end_of_next_month", void 0);
5245
5437
  var ConfigDataResponse = class {};
5246
5438
  __decorate([(0, openapi_metadata_decorators.ApiProperty)({
5247
5439
  type: "number",
@@ -5249,10 +5441,11 @@ __decorate([(0, openapi_metadata_decorators.ApiProperty)({
5249
5441
  })], ConfigDataResponse.prototype, "chain_id", void 0);
5250
5442
  __decorate([(0, openapi_metadata_decorators.ApiProperty)({ type: () => ConfigContractsResponse })], ConfigDataResponse.prototype, "contracts", void 0);
5251
5443
  __decorate([(0, openapi_metadata_decorators.ApiProperty)({
5252
- type: () => MaturitiesResponse,
5253
- description: "Supported maturity timestamps. Offers must use one of these values.",
5254
- example: chainConfigExample.maturities
5255
- })], ConfigDataResponse.prototype, "maturities", void 0);
5444
+ type: () => [String],
5445
+ enum: Object.values(Type$1),
5446
+ description: "Supported callback types for this chain.",
5447
+ example: callbacksExample
5448
+ })], ConfigDataResponse.prototype, "callbacks", void 0);
5256
5449
  var ConfigSuccessResponse = class extends SuccessResponse {};
5257
5450
  __decorate([(0, openapi_metadata_decorators.ApiProperty)({
5258
5451
  type: "string",
@@ -5264,21 +5457,21 @@ __decorate([(0, openapi_metadata_decorators.ApiProperty)({
5264
5457
  description: "Array of chain configurations for all indexed chains.",
5265
5458
  example: [chainConfigExample]
5266
5459
  })], ConfigSuccessResponse.prototype, "data", void 0);
5267
- let ConfigController = class ConfigController$1 {
5460
+ let ConfigController = class ConfigController {
5268
5461
  async getConfig() {}
5269
5462
  };
5270
5463
  __decorate([(0, openapi_metadata_decorators.ApiOperation)({
5271
5464
  methods: ["get"],
5272
5465
  path: "/v1/config",
5273
5466
  summary: "Get router configuration",
5274
- description: "Returns chain configurations including contract addresses and supported maturity timestamps."
5467
+ description: "Returns chain configurations including contract addresses and supported callback types."
5275
5468
  }), (0, openapi_metadata_decorators.ApiResponse)({
5276
5469
  status: 200,
5277
5470
  description: "Success",
5278
5471
  type: ConfigSuccessResponse
5279
5472
  })], ConfigController.prototype, "getConfig", null);
5280
5473
  ConfigController = __decorate([(0, openapi_metadata_decorators.ApiTags)("System")], ConfigController);
5281
- let ObligationsController = class ObligationsController$1 {
5474
+ let ObligationsController = class ObligationsController {
5282
5475
  async getObligations() {}
5283
5476
  async getObligation() {}
5284
5477
  };
@@ -5302,32 +5495,40 @@ __decorate([
5302
5495
  description: "Maximum number of obligations to return."
5303
5496
  }),
5304
5497
  (0, openapi_metadata_decorators.ApiQuery)({
5305
- name: "chain",
5306
- type: "number",
5498
+ name: "chains",
5499
+ type: ["number"],
5307
5500
  required: false,
5308
- example: 1,
5309
- description: "Filter by chain ID."
5501
+ example: "1,8453",
5502
+ description: "Filter by chain IDs (comma-separated).",
5503
+ style: "form",
5504
+ explode: false
5310
5505
  }),
5311
5506
  (0, openapi_metadata_decorators.ApiQuery)({
5312
- name: "loan_token",
5313
- type: "string",
5507
+ name: "loan_tokens",
5508
+ type: ["string"],
5314
5509
  required: false,
5315
- example: "0xC9A9C45C0eB717f8b5F193Af6bAa05A1c0Ac5078",
5316
- description: "Filter by loan token address."
5510
+ example: "0xC9A9C45C0eB717f8b5F193Af6bAa05A1c0Ac5078,0x34Cf890dB685FC536E05652FB41f02090c3fb751",
5511
+ description: "Filter by loan token addresses (comma-separated).",
5512
+ style: "form",
5513
+ explode: false
5317
5514
  }),
5318
5515
  (0, openapi_metadata_decorators.ApiQuery)({
5319
- name: "collateral_token",
5320
- type: "string",
5516
+ name: "collateral_tokens",
5517
+ type: ["string"],
5321
5518
  required: false,
5322
- example: "0x34Cf890dB685FC536E05652FB41f02090c3fb751",
5323
- description: "Filter by collateral token (matches any collateral in the obligation)."
5519
+ example: "0x34Cf890dB685FC536E05652FB41f02090c3fb751,0xC9A9C45C0eB717f8b5F193Af6bAa05A1c0Ac5078",
5520
+ description: "Filter by collateral tokens (comma-separated, matches any collateral).",
5521
+ style: "form",
5522
+ explode: false
5324
5523
  }),
5325
5524
  (0, openapi_metadata_decorators.ApiQuery)({
5326
- name: "maturity",
5327
- type: "number",
5525
+ name: "maturities",
5526
+ type: ["number"],
5328
5527
  required: false,
5329
- example: 1761922800,
5330
- description: "Filter by exact maturity timestamp (unix seconds)."
5528
+ example: "1761922800,1764524800",
5529
+ description: "Filter by exact maturity timestamps (comma-separated, unix seconds).",
5530
+ style: "form",
5531
+ explode: false
5331
5532
  }),
5332
5533
  (0, openapi_metadata_decorators.ApiResponse)({
5333
5534
  status: 200,
@@ -5359,7 +5560,7 @@ ObligationsController = __decorate([(0, openapi_metadata_decorators.ApiTags)("Ma
5359
5560
  description: "Bad Request",
5360
5561
  type: BadRequestResponse
5361
5562
  })], ObligationsController);
5362
- let UsersController = class UsersController$1 {
5563
+ let UsersController = class UsersController {
5363
5564
  async getUserPositions() {}
5364
5565
  };
5365
5566
  __decorate([
@@ -5449,7 +5650,7 @@ const OpenApi = async (options = {}) => {
5449
5650
 
5450
5651
  //#endregion
5451
5652
  //#region src/api/Schema/PositionResponse.ts
5452
- var PositionResponse_exports = /* @__PURE__ */ __export({ from: () => from$2 });
5653
+ var PositionResponse_exports = /* @__PURE__ */ __exportAll({ from: () => from$2 });
5453
5654
  /**
5454
5655
  * Creates a `PositionResponse` from a `PositionWithReserved`.
5455
5656
  * @param position - {@link PositionWithReserved}
@@ -5480,6 +5681,15 @@ function isValidBase64urlJson(val) {
5480
5681
  return false;
5481
5682
  }
5482
5683
  }
5684
+ const csvArray = (schema) => zod.preprocess((value) => {
5685
+ if (value === void 0) return void 0;
5686
+ if (Array.isArray(value)) {
5687
+ if (value.some((item) => typeof item !== "string")) return value;
5688
+ return value.flatMap((item) => item.split(",")).map((item) => item.trim()).filter((item) => item.length > 0);
5689
+ }
5690
+ if (typeof value === "string") return value.split(",").map((item) => item.trim()).filter((item) => item.length > 0);
5691
+ return value;
5692
+ }, zod.array(schema)).optional();
5483
5693
  const PaginationQueryParams = zod.object({
5484
5694
  cursor: zod.string().optional().refine((val) => {
5485
5695
  if (!val) return true;
@@ -5530,21 +5740,21 @@ const GetObligationsQueryParams = zod.object({
5530
5740
  description: "Obligation id cursor",
5531
5741
  example: "0x1234567890123456789012345678901234567890123456789012345678901234"
5532
5742
  }),
5533
- chain: zod.string().regex(/^[1-9]\d*$/, { message: "Chain must be a positive integer" }).transform((val) => Number.parseInt(val, 10)).optional().meta({
5534
- description: "Filter by chain ID",
5535
- example: "1"
5743
+ chains: csvArray(zod.string().regex(/^[1-9]\d*$/, { message: "Chain must be a positive integer" }).transform((val) => Number.parseInt(val, 10))).meta({
5744
+ description: "Filter by chain IDs (comma-separated).",
5745
+ example: "1,8453"
5536
5746
  }),
5537
- loan_token: zod.string().regex(/^0x[a-fA-F0-9]{40}$/, { error: "Loan token must be a valid 20-byte address" }).transform((val) => val.toLowerCase()).optional().meta({
5538
- description: "Filter by loan token address",
5539
- example: "0xC9A9C45C0eB717f8b5F193Af6bAa05A1c0Ac5078"
5747
+ loan_tokens: csvArray(zod.string().regex(/^0x[a-fA-F0-9]{40}$/, { error: "Loan token must be a valid 20-byte address" }).transform((val) => val.toLowerCase())).meta({
5748
+ description: "Filter by loan token addresses (comma-separated).",
5749
+ example: "0xC9A9C45C0eB717f8b5F193Af6bAa05A1c0Ac5078,0x34Cf890dB685FC536E05652FB41f02090c3fb751"
5540
5750
  }),
5541
- collateral_token: zod.string().regex(/^0x[a-fA-F0-9]{40}$/, { error: "Collateral token must be a valid 20-byte address" }).transform((val) => val.toLowerCase()).optional().meta({
5542
- description: "Filter by collateral token (matches any collateral in the obligation)",
5543
- example: "0x34Cf890dB685FC536E05652FB41f02090c3fb751"
5751
+ collateral_tokens: csvArray(zod.string().regex(/^0x[a-fA-F0-9]{40}$/, { error: "Collateral token must be a valid 20-byte address" }).transform((val) => val.toLowerCase())).meta({
5752
+ description: "Filter by collateral tokens (comma-separated, matches any collateral).",
5753
+ example: "0x34Cf890dB685FC536E05652FB41f02090c3fb751,0xC9A9C45C0eB717f8b5F193Af6bAa05A1c0Ac5078"
5544
5754
  }),
5545
- maturity: zod.string().regex(/^[1-9]\d*$/, { message: "Maturity must be a positive integer" }).transform((val) => Number.parseInt(val, 10)).optional().meta({
5546
- description: "Filter by exact maturity timestamp (unix seconds)",
5547
- example: "1761922800"
5755
+ maturities: csvArray(zod.string().regex(/^[1-9]\d*$/, { message: "Maturity must be a positive integer" }).transform((val) => Number.parseInt(val, 10))).meta({
5756
+ description: "Filter by exact maturity timestamps (comma-separated, unix seconds).",
5757
+ example: "1761922800,1764524800"
5548
5758
  })
5549
5759
  });
5550
5760
  const GetObligationParams = zod.object({ obligation_id: zod.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({
@@ -5657,18 +5867,14 @@ async function getBook(params, db) {
5657
5867
  * @returns The configuration for all chains the router is indexing. {@link ApiPayload.Payload<ChainConfig[]>}
5658
5868
  */
5659
5869
  async function getConfig(chainRegistry) {
5660
- const maturities = {
5661
- end_of_month: from$15(MaturityType.EndOfMonth),
5662
- end_of_next_month: from$15(MaturityType.EndOfNextMonth)
5663
- };
5664
- const configs$1 = [];
5665
- for (const chain of chainRegistry.list()) configs$1.push({
5870
+ const configs = [];
5871
+ for (const chain of chainRegistry.list()) configs.push({
5666
5872
  chain_id: chain.id,
5667
5873
  contracts: { mempool: chain.custom.mempool.address },
5668
- maturities
5874
+ callbacks: chain.custom.callbacks.map((c) => c.type)
5669
5875
  });
5670
- configs$1.sort((a, b) => a.chain_id - b.chain_id);
5671
- return success({ data: configs$1 });
5876
+ configs.sort((a, b) => a.chain_id - b.chain_id);
5877
+ return success({ data: configs });
5672
5878
  }
5673
5879
 
5674
5880
  //#endregion
@@ -5684,17 +5890,24 @@ const parse_error_Description = {
5684
5890
  name: "parse_error",
5685
5891
  description: "Returns when an offer fails to parse due to invalid format or missing required fields"
5686
5892
  };
5687
- const getGatekeeperRules = (gatekeeper) => {
5688
- return [parse_error_Description, ...gatekeeper.rules.map((rule) => ({
5689
- name: rule.name,
5690
- description: rule.description
5691
- }))];
5893
+ const getGatekeeperRules = async (gatekeeper) => {
5894
+ return [parse_error_Description, ...await gatekeeper.getRules()];
5692
5895
  };
5896
+ /**
5897
+ * Build the OpenAPI document for the router.
5898
+ * @param parameters - Includes a {@link RulesProvider} to fetch gatekeeper rules.
5899
+ * @returns OpenAPI document. {@link OpenAPIDocument}
5900
+ */
5693
5901
  async function getSwaggerJson({ gatekeeper }) {
5694
- return OpenApi({ rules: getGatekeeperRules(gatekeeper) });
5902
+ return OpenApi({ rules: await getGatekeeperRules(gatekeeper) });
5695
5903
  }
5904
+ /**
5905
+ * Render the API documentation HTML page.
5906
+ * @param parameters - Includes a {@link RulesProvider} to fetch gatekeeper rules.
5907
+ * @returns HTML page as string.
5908
+ */
5696
5909
  async function getDocsHtml({ gatekeeper }) {
5697
- const spec = await OpenApi({ rules: getGatekeeperRules(gatekeeper) });
5910
+ const spec = await OpenApi({ rules: await getGatekeeperRules(gatekeeper) });
5698
5911
  return `<!DOCTYPE html>
5699
5912
  <html>
5700
5913
  <head>
@@ -5799,8 +6012,8 @@ async function getHealthChains(query, db, healthClients, chainRegistry) {
5799
6012
  missingChains: snapshot.missingChains,
5800
6013
  missingCollectors: snapshot.missingCollectors
5801
6014
  })));
5802
- const chains$3 = snapshot.chains;
5803
- return success({ data: chains$3.map(({ chainId, localBlockNumber, remoteBlockNumber, updatedAt, initialized }) => toSnakeCase$1({
6015
+ const chains = snapshot.chains;
6016
+ return success({ data: chains.map(({ chainId, localBlockNumber, remoteBlockNumber, updatedAt, initialized }) => toSnakeCase$1({
5804
6017
  chainId,
5805
6018
  localBlockNumber,
5806
6019
  remoteBlockNumber,
@@ -5830,14 +6043,14 @@ async function getHealthCollectors(query, db, chainRegistry) {
5830
6043
  missingChains: snapshot.missingChains,
5831
6044
  missingCollectors: snapshot.missingCollectors
5832
6045
  })));
5833
- const collectors$1 = snapshot.collectors;
5834
- return success({ data: collectors$1.map(({ name, chainId, blockNumber, updatedAt, lag, status: status$1, initialized }) => toSnakeCase$1({
6046
+ const collectors = snapshot.collectors;
6047
+ return success({ data: collectors.map(({ name, chainId, blockNumber, updatedAt, lag, status, initialized }) => toSnakeCase$1({
5835
6048
  name,
5836
6049
  chainId,
5837
6050
  blockNumber,
5838
6051
  updatedAt,
5839
6052
  lag,
5840
- status: status$1,
6053
+ status,
5841
6054
  initialized
5842
6055
  })) });
5843
6056
  } catch (err) {
@@ -5859,9 +6072,9 @@ async function getObligation(params, db) {
5859
6072
  if (!result.success) return failure(result.error);
5860
6073
  const query = result.data;
5861
6074
  try {
5862
- const { obligations: obligations$1 } = await db.offers.getObligations({ ids: [query.obligation_id] });
5863
- if (obligations$1.length === 0) return failure(new NotFoundError("Obligation not found"));
5864
- const obligation = obligations$1[0];
6075
+ const { obligations } = await db.offers.getObligations({ ids: [query.obligation_id] });
6076
+ if (obligations.length === 0) return failure(new NotFoundError("Obligation not found"));
6077
+ const obligation = obligations[0];
5865
6078
  const [quote] = await db.offers.getQuotes({ obligationIds: [id(obligation)] });
5866
6079
  return success({
5867
6080
  data: from$4(obligation, quote ?? {
@@ -5890,17 +6103,21 @@ async function getObligations$1(queryParameters, db) {
5890
6103
  if (!result.success) return failure(result.error);
5891
6104
  const query = result.data;
5892
6105
  try {
5893
- const { obligations: obligations$1, nextCursor } = await db.offers.getObligations({
6106
+ const chainIds = query.chains?.length ? query.chains : void 0;
6107
+ const loanTokens = query.loan_tokens?.length ? query.loan_tokens : void 0;
6108
+ const collateralTokens = query.collateral_tokens?.length ? query.collateral_tokens : void 0;
6109
+ const maturities = query.maturities?.length ? query.maturities : void 0;
6110
+ const { obligations, nextCursor } = await db.offers.getObligations({
5894
6111
  cursor: query.cursor,
5895
6112
  limit: query.limit,
5896
- chainId: query.chain,
5897
- loanToken: query.loan_token,
5898
- collateralToken: query.collateral_token,
5899
- maturity: query.maturity
6113
+ chainId: chainIds,
6114
+ loanToken: loanTokens,
6115
+ collateralToken: collateralTokens,
6116
+ maturity: maturities
5900
6117
  });
5901
- const quotes = await db.offers.getQuotes({ obligationIds: obligations$1.map((o) => id(o)) });
6118
+ const quotes = await db.offers.getQuotes({ obligationIds: obligations.map((o) => id(o)) });
5902
6119
  return success({
5903
- data: obligations$1.map((o) => from$4(o, quotes.find((q) => q.obligationId === id(o)) ?? {
6120
+ data: obligations.map((o) => from$4(o, quotes.find((q) => q.obligationId === id(o)) ?? {
5904
6121
  obligationId: id(o),
5905
6122
  ask: { price: 0n },
5906
6123
  bid: { price: 0n }
@@ -5940,8 +6157,8 @@ async function getOffers$1(queryParameters, db) {
5940
6157
  const attestationMap = await db.trees.getAttestations(hashes);
5941
6158
  return success({
5942
6159
  data: rows.map((row) => {
5943
- const hash$1 = hash(row);
5944
- const attestation = attestationMap.get(hash$1);
6160
+ const hash$2 = hash(row);
6161
+ const attestation = attestationMap.get(hash$2);
5945
6162
  return from$3({
5946
6163
  ...row,
5947
6164
  ...attestation
@@ -5974,13 +6191,13 @@ async function getUserPositions(queryParameters, db) {
5974
6191
  if (!result.success) return failure(result.error);
5975
6192
  const query = result.data;
5976
6193
  try {
5977
- const { positions: positions$1, nextCursor } = await db.positions.getByUser({
6194
+ const { positions, nextCursor } = await db.positions.getByUser({
5978
6195
  user: query.user_address,
5979
6196
  cursor: query.cursor,
5980
6197
  limit: query.limit
5981
6198
  });
5982
6199
  return success({
5983
- data: positions$1.map((position) => from$2(position)),
6200
+ data: positions.map((position) => from$2(position)),
5984
6201
  cursor: nextCursor ?? null
5985
6202
  });
5986
6203
  } catch (err) {
@@ -6022,10 +6239,10 @@ async function validateOffers(body, gatekeeper) {
6022
6239
  const { issues } = await gatekeeper.isAllowed(parsedOffers);
6023
6240
  if (issues.length > 0) {
6024
6241
  const mappedIssues = issues.map((issue) => {
6025
- const index$1 = offerIndexByHash.get(hash(issue.item));
6026
- if (index$1 === void 0) return null;
6242
+ const index = offerIndexByHash.get(hash(issue.item));
6243
+ if (index === void 0) return null;
6027
6244
  return {
6028
- index: index$1,
6245
+ index,
6029
6246
  rule: issue.ruleName,
6030
6247
  message: issue.message
6031
6248
  };
@@ -6035,7 +6252,7 @@ async function validateOffers(body, gatekeeper) {
6035
6252
  cursor: null
6036
6253
  });
6037
6254
  }
6038
- const tree = from$13(parsedOffers);
6255
+ const tree = from$14(parsedOffers);
6039
6256
  const payload = encodeUnsigned(tree);
6040
6257
  return success({
6041
6258
  data: {
@@ -6057,7 +6274,7 @@ async function validateOffers(body, gatekeeper) {
6057
6274
 
6058
6275
  //#endregion
6059
6276
  //#region src/api/Controllers/index.ts
6060
- var Controllers_exports = /* @__PURE__ */ __export({
6277
+ var Controllers_exports = /* @__PURE__ */ __exportAll({
6061
6278
  getBook: () => getBook,
6062
6279
  getConfig: () => getConfig,
6063
6280
  getDocsHtml: () => getDocsHtml,
@@ -6109,7 +6326,7 @@ function serve(parameters) {
6109
6326
  span.setAttribute("http.target", path);
6110
6327
  span.setAttribute("http.route", path);
6111
6328
  span.setAttribute("http.status_code", c.res.status);
6112
- if (c.res.status >= 500) span.setStatus({ code: __opentelemetry_api.SpanStatusCode.ERROR });
6329
+ if (c.res.status >= 500) span.setStatus({ code: _opentelemetry_api.SpanStatusCode.ERROR });
6113
6330
  return res;
6114
6331
  });
6115
6332
  });
@@ -6122,8 +6339,8 @@ function serve(parameters) {
6122
6339
  return c.json(body, statusCode);
6123
6340
  });
6124
6341
  app.get("/v1/obligations/:obligationId", async (c) => {
6125
- const id$1 = c.req.param("obligationId");
6126
- const { statusCode, body } = await getObligation({ obligation_id: id$1 }, db);
6342
+ const id = c.req.param("obligationId");
6343
+ const { statusCode, body } = await getObligation({ obligation_id: id }, db);
6127
6344
  return c.json(body, statusCode);
6128
6345
  });
6129
6346
  app.get("/v1/books/:obligationId/:side", async (c) => {
@@ -6137,9 +6354,14 @@ function serve(parameters) {
6137
6354
  return c.json(body, statusCode);
6138
6355
  });
6139
6356
  app.post("/v1/validate", async (c) => {
6140
- const reqBody = await c.req.json();
6141
- const { statusCode, body } = await validateOffers(reqBody, gatekeeper);
6142
- return c.json(body, statusCode);
6357
+ try {
6358
+ const reqBody = await c.req.json();
6359
+ const { statusCode, body } = await gatekeeper.validate(reqBody);
6360
+ return c.json(body, statusCode);
6361
+ } catch (err) {
6362
+ const failure$1 = failure(err);
6363
+ return c.json(failure$1.body, failure$1.statusCode);
6364
+ }
6143
6365
  });
6144
6366
  app.get("/v1/users/:userAddress/positions", async (c) => {
6145
6367
  const query = c.req.query();
@@ -6169,7 +6391,7 @@ function serve(parameters) {
6169
6391
  app.get("/docs/openapi", async (c) => c.text(JSON.stringify(await getSwaggerJson({ gatekeeper })), 200, { "Content-Type": "application/json; charset=utf-8" }));
6170
6392
  app.get("/docs/api", async (c) => c.html(await getDocsHtml({ gatekeeper }), 200));
6171
6393
  app.get("/docs", async (c) => c.html(await getIntegratorDocsHtml(), 200));
6172
- (0, __hono_node_server.serve)({
6394
+ (0, _hono_node_server.serve)({
6173
6395
  fetch: app.fetch,
6174
6396
  port: parameters.port
6175
6397
  });
@@ -6177,7 +6399,7 @@ function serve(parameters) {
6177
6399
 
6178
6400
  //#endregion
6179
6401
  //#region src/api/RouterApi.ts
6180
- var RouterApi_exports = /* @__PURE__ */ __export({
6402
+ var RouterApi_exports = /* @__PURE__ */ __exportAll({
6181
6403
  BookResponse: () => BookResponse_exports,
6182
6404
  BooksController: () => BooksController,
6183
6405
  ChainHealth: () => ChainHealth,
@@ -6204,7 +6426,7 @@ var RouterApi_exports = /* @__PURE__ */ __export({
6204
6426
 
6205
6427
  //#endregion
6206
6428
  //#region src/client/Client.ts
6207
- var Client_exports = /* @__PURE__ */ __export({
6429
+ var Client_exports$1 = /* @__PURE__ */ __exportAll({
6208
6430
  HttpForbiddenError: () => HttpForbiddenError,
6209
6431
  HttpGetApiFailedError: () => HttpGetApiFailedError,
6210
6432
  HttpRateLimitError: () => HttpRateLimitError,
@@ -6237,12 +6459,16 @@ function connect$2(parameters) {
6237
6459
  };
6238
6460
  const apiClient = (0, openapi_fetch.default)({
6239
6461
  baseUrl: config.url.toString(),
6240
- headers: config.headers
6462
+ headers: config.headers,
6463
+ querySerializer: { array: {
6464
+ style: "form",
6465
+ explode: false
6466
+ } }
6241
6467
  });
6242
6468
  return {
6243
6469
  ...config,
6244
- getOffers: (parameters$1) => getOffers(apiClient, parameters$1),
6245
- getObligations: (parameters$1) => getObligations(apiClient, parameters$1)
6470
+ getOffers: (parameters) => getOffers(apiClient, parameters),
6471
+ getObligations: (parameters) => getObligations(apiClient, parameters)
6246
6472
  };
6247
6473
  }
6248
6474
  async function getOffers(apiClient, parameters) {
@@ -6260,7 +6486,7 @@ async function getOffers(apiClient, parameters) {
6260
6486
  }
6261
6487
  throw new HttpGetApiFailedError(`GET request returned ${response.status}`, { details: JSON.stringify(error) });
6262
6488
  }
6263
- const offers$1 = data?.data.map((item) => {
6489
+ const offers = data?.data.map((item) => {
6264
6490
  const { root, proof, signature, offer: offerData } = item;
6265
6491
  return {
6266
6492
  ...fromSnakeCase$1({
@@ -6269,7 +6495,7 @@ async function getOffers(apiClient, parameters) {
6269
6495
  obligation_units: offerData.obligation_units,
6270
6496
  obligation_shares: offerData.obligation_shares,
6271
6497
  price: offerData.price,
6272
- maturity: from$15(offerData.obligation.maturity),
6498
+ maturity: from$16(offerData.obligation.maturity),
6273
6499
  expiry: offerData.expiry,
6274
6500
  start: offerData.start,
6275
6501
  group: offerData.group,
@@ -6298,17 +6524,17 @@ async function getOffers(apiClient, parameters) {
6298
6524
  }) ?? [];
6299
6525
  return {
6300
6526
  cursor: data?.cursor ?? null,
6301
- offers: offers$1
6527
+ offers
6302
6528
  };
6303
6529
  }
6304
6530
  async function getObligations(apiClient, parameters) {
6305
6531
  const { data, error, response } = await apiClient.GET("/v1/obligations", { params: { query: {
6306
6532
  cursor: parameters?.cursor,
6307
6533
  limit: parameters?.limit,
6308
- chain: parameters?.chainId,
6309
- loan_token: parameters?.loanToken,
6310
- collateral_token: parameters?.collateralToken,
6311
- maturity: parameters?.maturity
6534
+ chains: parameters?.chainIds,
6535
+ loan_tokens: parameters?.loanTokens,
6536
+ collateral_tokens: parameters?.collateralTokens,
6537
+ maturities: parameters?.maturities
6312
6538
  } } });
6313
6539
  if (error !== void 0) {
6314
6540
  switch (response.status) {
@@ -6318,7 +6544,7 @@ async function getObligations(apiClient, parameters) {
6318
6544
  }
6319
6545
  throw new HttpGetApiFailedError(`GET request returned ${response.status}`, { details: JSON.stringify(error) });
6320
6546
  }
6321
- const obligations$1 = data?.data.map((item) => {
6547
+ const obligations = data?.data.map((item) => {
6322
6548
  const obligation = fromSnakeCase$2({
6323
6549
  chain_id: item.chain_id,
6324
6550
  loan_token: item.loan_token,
@@ -6327,7 +6553,7 @@ async function getObligations(apiClient, parameters) {
6327
6553
  oracle: collateral.oracle,
6328
6554
  lltv: collateral.lltv
6329
6555
  })),
6330
- maturity: from$15(item.maturity)
6556
+ maturity: from$16(item.maturity)
6331
6557
  });
6332
6558
  const { obligationId: _, ...returned } = {
6333
6559
  id: () => id(obligation),
@@ -6342,7 +6568,7 @@ async function getObligations(apiClient, parameters) {
6342
6568
  }) ?? [];
6343
6569
  return {
6344
6570
  cursor: data?.cursor ?? null,
6345
- obligations: obligations$1
6571
+ obligations
6346
6572
  };
6347
6573
  }
6348
6574
  var InvalidUrlError = class extends BaseError {
@@ -6382,7 +6608,7 @@ const VERSION = "router_v1.6";
6382
6608
 
6383
6609
  //#endregion
6384
6610
  //#region src/database/drizzle/schema.ts
6385
- var schema_exports = /* @__PURE__ */ __export({
6611
+ var schema_exports = /* @__PURE__ */ __exportAll({
6386
6612
  PositionTypes: () => PositionTypes,
6387
6613
  StatusCode: () => StatusCode,
6388
6614
  TABLE_NAMES: () => TABLE_NAMES,
@@ -6408,25 +6634,25 @@ var schema_exports = /* @__PURE__ */ __export({
6408
6634
  validations: () => validations
6409
6635
  });
6410
6636
  const s = (0, drizzle_orm_pg_core.pgSchema)(VERSION);
6411
- var EnumTableName = /* @__PURE__ */ function(EnumTableName$1) {
6412
- EnumTableName$1["OBLIGATIONS"] = "obligations";
6413
- EnumTableName$1["GROUPS"] = "groups";
6414
- EnumTableName$1["CONSUMED_EVENTS"] = "consumed_events";
6415
- EnumTableName$1["OBLIGATION_COLLATERALS_V2"] = "obligation_collaterals_v2";
6416
- EnumTableName$1["ORACLES"] = "oracles";
6417
- EnumTableName$1["OFFERS"] = "offers";
6418
- EnumTableName$1["OFFERS_CALLBACKS"] = "offers_callbacks";
6419
- EnumTableName$1["CALLBACKS"] = "callbacks";
6420
- EnumTableName$1["POSITIONS"] = "positions";
6421
- EnumTableName$1["TRANSFERS"] = "transfers";
6422
- EnumTableName$1["VALIDATIONS"] = "validations";
6423
- EnumTableName$1["COLLECTORS"] = "collectors";
6424
- EnumTableName$1["CHAINS"] = "chains";
6425
- EnumTableName$1["LOTS"] = "lots";
6426
- EnumTableName$1["OFFSETS"] = "offsets";
6427
- EnumTableName$1["TREES"] = "trees";
6428
- EnumTableName$1["MERKLE_PATHS"] = "merkle_paths";
6429
- return EnumTableName$1;
6637
+ var EnumTableName = /* @__PURE__ */ function(EnumTableName) {
6638
+ EnumTableName["OBLIGATIONS"] = "obligations";
6639
+ EnumTableName["GROUPS"] = "groups";
6640
+ EnumTableName["CONSUMED_EVENTS"] = "consumed_events";
6641
+ EnumTableName["OBLIGATION_COLLATERALS_V2"] = "obligation_collaterals_v2";
6642
+ EnumTableName["ORACLES"] = "oracles";
6643
+ EnumTableName["OFFERS"] = "offers";
6644
+ EnumTableName["OFFERS_CALLBACKS"] = "offers_callbacks";
6645
+ EnumTableName["CALLBACKS"] = "callbacks";
6646
+ EnumTableName["POSITIONS"] = "positions";
6647
+ EnumTableName["TRANSFERS"] = "transfers";
6648
+ EnumTableName["VALIDATIONS"] = "validations";
6649
+ EnumTableName["COLLECTORS"] = "collectors";
6650
+ EnumTableName["CHAINS"] = "chains";
6651
+ EnumTableName["LOTS"] = "lots";
6652
+ EnumTableName["OFFSETS"] = "offsets";
6653
+ EnumTableName["TREES"] = "trees";
6654
+ EnumTableName["MERKLE_PATHS"] = "merkle_paths";
6655
+ return EnumTableName;
6430
6656
  }(EnumTableName || {});
6431
6657
  const TABLE_NAMES = Object.values(EnumTableName);
6432
6658
  const VERSIONED_TABLE_NAMES = TABLE_NAMES.map((table) => `"${VERSION}"."${table}"`);
@@ -6783,7 +7009,7 @@ const merklePaths = s.table(EnumTableName.MERKLE_PATHS, {
6783
7009
 
6784
7010
  //#endregion
6785
7011
  //#region src/database/drizzle/index.ts
6786
- var drizzle_exports = /* @__PURE__ */ __export({
7012
+ var drizzle_exports = /* @__PURE__ */ __exportAll({
6787
7013
  PositionTypes: () => PositionTypes,
6788
7014
  StatusCode: () => StatusCode,
6789
7015
  TABLE_NAMES: () => TABLE_NAMES,
@@ -6815,7 +7041,7 @@ var drizzle_exports = /* @__PURE__ */ __export({
6815
7041
  /** Postgres implementation. */
6816
7042
  const create$11 = (config) => {
6817
7043
  const { db, chainRegistry } = config;
6818
- const getChain$1 = async (chainId) => {
7044
+ const getChain = async (chainId) => {
6819
7045
  const rows = await db.select({
6820
7046
  chainId: chains$1.chainId,
6821
7047
  blockNumber: chains$1.blockNumber,
@@ -6961,26 +7187,26 @@ const create$11 = (config) => {
6961
7187
  epoch
6962
7188
  });
6963
7189
  const collectorStates = await Promise.all(collectorNames.map(async (collectorName) => {
6964
- const { blockNumber: blockNumber$1, epoch: epoch$1 } = await getCollector({
7190
+ const { blockNumber, epoch } = await getCollector({
6965
7191
  chainId,
6966
7192
  collectorName
6967
7193
  });
6968
7194
  return {
6969
7195
  collectorName,
6970
- blockNumber: blockNumber$1,
6971
- epoch: epoch$1
7196
+ blockNumber,
7197
+ epoch
6972
7198
  };
6973
7199
  }));
6974
- await Promise.all(collectorStates.map(({ collectorName, blockNumber: blockNumber$1 }) => advanceCollector({
7200
+ await Promise.all(collectorStates.map(({ collectorName, blockNumber }) => advanceCollector({
6975
7201
  collectorName,
6976
7202
  chainId,
6977
- blockNumber: Math.min(blockNumber$1, parameters.blockNumber),
7203
+ blockNumber: Math.min(blockNumber, parameters.blockNumber),
6978
7204
  epoch: parameters.epoch
6979
7205
  })));
6980
7206
  };
6981
7207
  return {
6982
7208
  init,
6983
- getChain: getChain$1,
7209
+ getChain,
6984
7210
  getCollector,
6985
7211
  getChains,
6986
7212
  getCollectors,
@@ -6997,8 +7223,8 @@ const MAX_TOTAL_OFFERS = 500;
6997
7223
  function create$10(config) {
6998
7224
  const db = config.db;
6999
7225
  const logger = getLogger();
7000
- const getOffers$2 = async (parameters) => {
7001
- const { side, obligationId: obligationId$1, cursor: cursorString } = parameters;
7226
+ const getOffers = async (parameters) => {
7227
+ const { side, obligationId, cursor: cursorString } = parameters;
7002
7228
  const requestedLimit = parameters.limit ?? DEFAULT_LIMIT$3;
7003
7229
  const priceSortDirection = side === "sell" ? "asc" : "desc";
7004
7230
  const inputCursor = Cursor.decode(cursorString, logger);
@@ -7007,16 +7233,16 @@ function create$10(config) {
7007
7233
  nextCursor: null
7008
7234
  };
7009
7235
  if (inputCursor != null && inputCursor.side !== side) throw new Error("Cursor does not match the current sort parameters");
7010
- const now$1 = inputCursor?.now ?? Math.floor(Date.now() / 1e3);
7236
+ const now = inputCursor?.now ?? Math.floor(Date.now() / 1e3);
7011
7237
  const previouslyReturned = inputCursor?.totalReturned ?? 0;
7012
7238
  if (previouslyReturned >= MAX_TOTAL_OFFERS) return {
7013
7239
  rows: [],
7014
7240
  nextCursor: null
7015
7241
  };
7016
7242
  const { rows, hasMore } = await _getOffers(db, {
7017
- obligationId: obligationId$1,
7243
+ obligationId,
7018
7244
  side,
7019
- now: now$1,
7245
+ now,
7020
7246
  priceSortDirection,
7021
7247
  cursor: inputCursor,
7022
7248
  limit: Math.min(requestedLimit, MAX_TOTAL_OFFERS - previouslyReturned)
@@ -7026,23 +7252,23 @@ function create$10(config) {
7026
7252
  const hasHitHardLimit = newTotalReturned >= MAX_TOTAL_OFFERS;
7027
7253
  return {
7028
7254
  rows,
7029
- nextCursor: rows.length > 0 && lastReturnedOffer && !hasHitHardLimit && hasMore ? Cursor.encode(lastReturnedOffer, newTotalReturned, now$1, side) : null
7255
+ nextCursor: rows.length > 0 && lastReturnedOffer && !hasHitHardLimit && hasMore ? Cursor.encode(lastReturnedOffer, newTotalReturned, now, side) : null
7030
7256
  };
7031
7257
  };
7032
7258
  return {
7033
7259
  get: async (parameters) => {
7034
- const { side, obligationId: obligationId$1, cursor: cursorString, limit = DEFAULT_LIMIT$3 } = parameters;
7260
+ const { side, obligationId, cursor: cursorString, limit = DEFAULT_LIMIT$3 } = parameters;
7035
7261
  const inputCursor = LevelCursor.decode(cursorString, logger);
7036
7262
  if (cursorString != null && inputCursor === null) return {
7037
7263
  levels: [],
7038
7264
  nextCursor: null
7039
7265
  };
7040
7266
  if (inputCursor != null && inputCursor.side !== side) throw new Error("Cursor does not match the current sort parameters");
7041
- const now$1 = inputCursor?.now ?? Math.floor(Date.now() / 1e3);
7267
+ const now = inputCursor?.now ?? Math.floor(Date.now() / 1e3);
7042
7268
  const fetchLimit = limit * 10;
7043
- const { rows, nextCursor: offersNextCursor } = await getOffers$2({
7269
+ const { rows, nextCursor: offersNextCursor } = await getOffers({
7044
7270
  side,
7045
- obligationId: obligationId$1,
7271
+ obligationId,
7046
7272
  cursor: inputCursor?.offersCursor ?? void 0,
7047
7273
  limit: fetchLimit
7048
7274
  });
@@ -7068,15 +7294,15 @@ function create$10(config) {
7068
7294
  const lastLevel = paginatedLevels[paginatedLevels.length - 1];
7069
7295
  return {
7070
7296
  levels: paginatedLevels,
7071
- nextCursor: hasMore && lastLevel ? LevelCursor.encode(lastLevel, offersNextCursor, side, now$1) : null
7297
+ nextCursor: hasMore && lastLevel ? LevelCursor.encode(lastLevel, offersNextCursor, side, now) : null
7072
7298
  };
7073
7299
  },
7074
- getOffers: getOffers$2
7300
+ getOffers
7075
7301
  };
7076
7302
  }
7077
7303
  /** Get offers with computed takeable based on lot balance. */
7078
7304
  async function _getOffers(db, params) {
7079
- const { obligationId: obligationId$1, side, now: now$1, priceSortDirection, cursor, limit } = params;
7305
+ const { obligationId, side, now, priceSortDirection, cursor, limit } = params;
7080
7306
  const raw = await db.execute(drizzle_orm.sql`
7081
7307
  WITH collats AS MATERIALIZED (
7082
7308
  SELECT oc.obligation_id,
@@ -7089,7 +7315,7 @@ async function _getOffers(db, params) {
7089
7315
  JOIN ${oracles} oracle
7090
7316
  ON oracle.chain_id = oc.oracle_chain_id
7091
7317
  AND oracle.address = oc.oracle_address
7092
- WHERE oc.obligation_id = ${obligationId$1}
7318
+ WHERE oc.obligation_id = ${obligationId}
7093
7319
  GROUP BY oc.obligation_id
7094
7320
  ),
7095
7321
  winners AS (
@@ -7100,11 +7326,11 @@ async function _getOffers(db, params) {
7100
7326
  ON v.offer_hash = o.hash
7101
7327
  LEFT JOIN ${status} s
7102
7328
  ON s.id = v.status_id
7103
- WHERE o.obligation_id = ${obligationId$1}
7329
+ WHERE o.obligation_id = ${obligationId}
7104
7330
  AND o.buy = ${side === "buy"}
7105
- AND o.expiry > ${now$1}
7106
- AND o.maturity > ${now$1}
7107
- AND o.start <= ${now$1}
7331
+ AND o.expiry > ${now}
7332
+ AND o.maturity > ${now}
7333
+ AND o.start <= ${now}
7108
7334
  AND (s.code IS NULL OR s.code = ${Status.VALID})
7109
7335
  ORDER BY
7110
7336
  o.group_chain_id, o.group_maker, o."group_group",
@@ -7383,7 +7609,7 @@ async function _getOffers(db, params) {
7383
7609
  }
7384
7610
  let Cursor;
7385
7611
  (function(_Cursor) {
7386
- function encode$3(row, totalReturned, now$1, side) {
7612
+ function encode(row, totalReturned, now, side) {
7387
7613
  return Buffer.from(JSON.stringify({
7388
7614
  side,
7389
7615
  price: row.price.toString(),
@@ -7391,11 +7617,11 @@ let Cursor;
7391
7617
  assets: row.assets.toString(),
7392
7618
  hash: row.hash,
7393
7619
  totalReturned,
7394
- now: now$1
7620
+ now
7395
7621
  })).toString("base64url");
7396
7622
  }
7397
- _Cursor.encode = encode$3;
7398
- function decode$3(cursorString, logger) {
7623
+ _Cursor.encode = encode;
7624
+ function decode(cursorString, logger) {
7399
7625
  if (cursorString == null) return null;
7400
7626
  const isNumericString = (value) => typeof value === "string" && /^-?\d+$/.test(value);
7401
7627
  try {
@@ -7411,20 +7637,20 @@ let Cursor;
7411
7637
  return null;
7412
7638
  }
7413
7639
  }
7414
- _Cursor.decode = decode$3;
7640
+ _Cursor.decode = decode;
7415
7641
  })(Cursor || (Cursor = {}));
7416
7642
  let LevelCursor;
7417
7643
  (function(_LevelCursor) {
7418
- function encode$3(lastLevel, offersCursor, side, now$1) {
7644
+ function encode(lastLevel, offersCursor, side, now) {
7419
7645
  return Buffer.from(JSON.stringify({
7420
7646
  side,
7421
7647
  lastPrice: lastLevel.price.toString(),
7422
- now: now$1,
7648
+ now,
7423
7649
  offersCursor
7424
7650
  })).toString("base64url");
7425
7651
  }
7426
- _LevelCursor.encode = encode$3;
7427
- function decode$3(cursorString, logger) {
7652
+ _LevelCursor.encode = encode;
7653
+ function decode(cursorString, logger) {
7428
7654
  if (cursorString == null) return null;
7429
7655
  const isNumericString = (value) => typeof value === "string" && /^-?\d+$/.test(value);
7430
7656
  try {
@@ -7440,7 +7666,7 @@ let LevelCursor;
7440
7666
  return null;
7441
7667
  }
7442
7668
  }
7443
- _LevelCursor.decode = decode$3;
7669
+ _LevelCursor.decode = decode;
7444
7670
  })(LevelCursor || (LevelCursor = {}));
7445
7671
 
7446
7672
  //#endregion
@@ -7482,7 +7708,7 @@ function create$9(db) {
7482
7708
  consumed: "0",
7483
7709
  blockNumber: group.blockNumber
7484
7710
  }));
7485
- for (const batch$2 of batch$1(groupsRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(groups).values(batch$2).onConflictDoNothing();
7711
+ for (const batch of batch$1(groupsRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(groups).values(batch).onConflictDoNothing();
7486
7712
  const eventsRows = events.map((event) => ({
7487
7713
  eventId: event.id,
7488
7714
  chainId: event.chainId,
@@ -7491,7 +7717,7 @@ function create$9(db) {
7491
7717
  amount: event.amount.toString(),
7492
7718
  blockNumber: event.blockNumber
7493
7719
  }));
7494
- for (const batch$2 of batch$1(eventsRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(consumedEvents).values(batch$2).onConflictDoNothing();
7720
+ for (const batch of batch$1(eventsRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(consumedEvents).values(batch).onConflictDoNothing();
7495
7721
  });
7496
7722
  },
7497
7723
  delete: async (parameters) => {
@@ -7546,9 +7772,96 @@ function create$8(db) {
7546
7772
  };
7547
7773
  }
7548
7774
 
7775
+ //#endregion
7776
+ //#region src/gatekeeper/Client.ts
7777
+ var Client_exports = /* @__PURE__ */ __exportAll({ createHttpClient: () => createHttpClient });
7778
+ const DEFAULT_TIMEOUT_MS = 1e4;
7779
+ /**
7780
+ * Create an HTTP client for a gatekeeper service.
7781
+ * @param config - Gatekeeper client configuration. {@link ClientConfig}
7782
+ * @returns An HTTP-backed gatekeeper client. {@link GatekeeperClient}
7783
+ */
7784
+ function createHttpClient(config) {
7785
+ const fetchFn = config.fetchFn ?? fetch;
7786
+ const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;
7787
+ const baseUrl = normalizeBaseUrl(config.baseUrl);
7788
+ const request = async (path, init) => {
7789
+ const controller = new AbortController();
7790
+ const timeout = setTimeout(() => controller.abort(), timeoutMs);
7791
+ try {
7792
+ return await fetchFn(`${baseUrl}${path}`, {
7793
+ ...init,
7794
+ signal: controller.signal
7795
+ });
7796
+ } finally {
7797
+ clearTimeout(timeout);
7798
+ }
7799
+ };
7800
+ const validate = async (body) => {
7801
+ const response = await request("/v1/validate", {
7802
+ method: "POST",
7803
+ headers: { "content-type": "application/json" },
7804
+ body: JSON.stringify(body)
7805
+ });
7806
+ const json = await response.json();
7807
+ return {
7808
+ statusCode: response.status,
7809
+ body: json
7810
+ };
7811
+ };
7812
+ const getRules = async () => {
7813
+ const response = await request("/v1/rules", { method: "GET" });
7814
+ const json = await response.json();
7815
+ if (!response.ok) throw new Error(`Gatekeeper rules request failed: ${extractErrorMessage(json) ?? response.statusText}`);
7816
+ if (!("data" in json) || !Array.isArray(json.data)) throw new Error("Gatekeeper rules response is invalid.");
7817
+ return json.data;
7818
+ };
7819
+ const isAllowed = async (offers) => {
7820
+ const { statusCode, body } = await validate({ offers: offers.map((offer) => toSnakeCase(offer)) });
7821
+ if (statusCode !== 200) {
7822
+ const errorMessage = extractErrorMessage(body);
7823
+ throw new Error(`Gatekeeper validation failed: ${errorMessage ?? `status ${statusCode}`}`);
7824
+ }
7825
+ const data = body.data;
7826
+ if (!data || typeof data !== "object") throw new Error("Gatekeeper validation response is invalid.");
7827
+ if ("issues" in data) {
7828
+ const issues = data.issues.map((issue) => ({
7829
+ ruleName: issue.rule,
7830
+ message: issue.message,
7831
+ item: offers[issue.index]
7832
+ }));
7833
+ const invalidIndices = new Set(data.issues.map((issue) => issue.index));
7834
+ return {
7835
+ valid: offers.filter((_, index) => !invalidIndices.has(index)),
7836
+ issues
7837
+ };
7838
+ }
7839
+ if (!("payload" in data) || !("root" in data)) throw new Error("Gatekeeper validation response is missing payload data.");
7840
+ return {
7841
+ valid: offers.slice(),
7842
+ issues: []
7843
+ };
7844
+ };
7845
+ return {
7846
+ baseUrl,
7847
+ validate,
7848
+ isAllowed,
7849
+ getRules
7850
+ };
7851
+ }
7852
+ function normalizeBaseUrl(url) {
7853
+ return url.trim().replace(/\/+$/, "");
7854
+ }
7855
+ function extractErrorMessage(payload) {
7856
+ if (!payload || typeof payload !== "object") return void 0;
7857
+ const error = payload.error;
7858
+ if (!error || typeof error !== "object") return void 0;
7859
+ return typeof error.message === "string" ? error.message : void 0;
7860
+ }
7861
+
7549
7862
  //#endregion
7550
7863
  //#region src/gatekeeper/Gate.ts
7551
- var Gate_exports = /* @__PURE__ */ __export({
7864
+ var Gate_exports = /* @__PURE__ */ __exportAll({
7552
7865
  batch: () => batch,
7553
7866
  run: () => run,
7554
7867
  single: () => single
@@ -7560,12 +7873,12 @@ var Gate_exports = /* @__PURE__ */ __export({
7560
7873
  * @param run - The function that validates the rule.
7561
7874
  * @returns The created rule.
7562
7875
  */
7563
- function single(name, description, run$1) {
7876
+ function single(name, description, run) {
7564
7877
  return {
7565
7878
  kind: "single",
7566
7879
  name,
7567
7880
  description,
7568
- run: run$1
7881
+ run
7569
7882
  };
7570
7883
  }
7571
7884
  /**
@@ -7575,12 +7888,12 @@ function single(name, description, run$1) {
7575
7888
  * @param run - The function that validates the rule.
7576
7889
  * @returns The created rule.
7577
7890
  */
7578
- function batch(name, description, run$1) {
7891
+ function batch(name, description, run) {
7579
7892
  return {
7580
7893
  kind: "batch",
7581
7894
  name,
7582
7895
  description,
7583
- run: run$1
7896
+ run
7584
7897
  };
7585
7898
  }
7586
7899
  async function run(parameters) {
@@ -7633,7 +7946,7 @@ async function run(parameters) {
7633
7946
 
7634
7947
  //#endregion
7635
7948
  //#region src/gatekeeper/GateConfig.ts
7636
- var GateConfig_exports = /* @__PURE__ */ __export({
7949
+ var GateConfig_exports = /* @__PURE__ */ __exportAll({
7637
7950
  assets: () => assets,
7638
7951
  configs: () => configs,
7639
7952
  getCallback: () => getCallback,
@@ -7659,8 +7972,8 @@ function getCallback(chain, type) {
7659
7972
  * @param address - Callback contract address
7660
7973
  * @returns The callback type when found, otherwise undefined
7661
7974
  */
7662
- function getCallbackType(chain, address$1) {
7663
- return configs[chain].callbacks?.find((c) => c.type !== CallbackType.BuyWithEmptyCallback && c.addresses.includes(address$1?.toLowerCase()))?.type;
7975
+ function getCallbackType(chain, address) {
7976
+ return configs[chain].callbacks?.find((c) => c.type !== Type$1.BuyWithEmptyCallback && c.addresses.includes(address?.toLowerCase()))?.type;
7664
7977
  }
7665
7978
  /**
7666
7979
  * Returns the callback addresses for a given chain and callback type, if it exists.
@@ -7669,7 +7982,7 @@ function getCallbackType(chain, address$1) {
7669
7982
  * @returns The matching callback addresses or an empty array if not configured
7670
7983
  */
7671
7984
  function getCallbackTypeAddresses(chain, type) {
7672
- if (type === CallbackType.BuyWithEmptyCallback) return [];
7985
+ if (type === Type$1.BuyWithEmptyCallback) return [];
7673
7986
  const match = configs[chain].callbacks?.find((c) => c.type === type);
7674
7987
  return match && "addresses" in match ? match.addresses : [];
7675
7988
  }
@@ -7680,7 +7993,7 @@ function getCallbackTypeAddresses(chain, type) {
7680
7993
  * @returns Array of allowed callback addresses (lowercased). Empty when none configured
7681
7994
  */
7682
7995
  const getCallbackAddresses = (chain) => {
7683
- return configs[chain].callbacks?.filter((c) => c.type !== CallbackType.BuyWithEmptyCallback).flatMap((c) => c.addresses) ?? [];
7996
+ return configs[chain].callbacks?.filter((c) => c.type !== Type$1.BuyWithEmptyCallback).flatMap((c) => c.addresses) ?? [];
7684
7997
  };
7685
7998
  const assets = {
7686
7999
  [ChainId.ETHEREUM.toString()]: [
@@ -7713,60 +8026,60 @@ const configs = {
7713
8026
  ethereum: {
7714
8027
  callbacks: [
7715
8028
  {
7716
- type: CallbackType.BuyVaultV1Callback,
8029
+ type: Type$1.BuyVaultV1Callback,
7717
8030
  addresses: ["0x3333333333333333333333333333333333333333", "0x4444444444444444444444444444444444444444"],
7718
8031
  vaultFactories: ["0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101", "0x1897A8997241C1cD4bD0698647e4EB7213535c24"]
7719
8032
  },
7720
8033
  {
7721
- type: CallbackType.SellERC20Callback,
8034
+ type: Type$1.SellERC20Callback,
7722
8035
  addresses: ["0x1111111111111111111111111111111111111111", "0x2222222222222222222222222222222222222222"]
7723
8036
  },
7724
- { type: CallbackType.BuyWithEmptyCallback }
8037
+ { type: Type$1.BuyWithEmptyCallback }
7725
8038
  ],
7726
8039
  maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth]
7727
8040
  },
7728
8041
  base: {
7729
8042
  callbacks: [
7730
8043
  {
7731
- type: CallbackType.BuyVaultV1Callback,
8044
+ type: Type$1.BuyVaultV1Callback,
7732
8045
  addresses: ["0x3333333333333333333333333333333333333333", "0x4444444444444444444444444444444444444444"],
7733
8046
  vaultFactories: ["0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101", "0xFf62A7c278C62eD665133147129245053Bbf5918"]
7734
8047
  },
7735
8048
  {
7736
- type: CallbackType.SellERC20Callback,
8049
+ type: Type$1.SellERC20Callback,
7737
8050
  addresses: ["0x1111111111111111111111111111111111111111", "0x2222222222222222222222222222222222222222"]
7738
8051
  },
7739
- { type: CallbackType.BuyWithEmptyCallback }
8052
+ { type: Type$1.BuyWithEmptyCallback }
7740
8053
  ],
7741
8054
  maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth]
7742
8055
  },
7743
8056
  "ethereum-virtual-testnet": {
7744
8057
  callbacks: [
7745
8058
  {
7746
- type: CallbackType.BuyVaultV1Callback,
8059
+ type: Type$1.BuyVaultV1Callback,
7747
8060
  addresses: ["0x3333333333333333333333333333333333333333", "0x4444444444444444444444444444444444444444"],
7748
8061
  vaultFactories: ["0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101", "0x1897A8997241C1cD4bD0698647e4EB7213535c24"]
7749
8062
  },
7750
8063
  {
7751
- type: CallbackType.SellERC20Callback,
8064
+ type: Type$1.SellERC20Callback,
7752
8065
  addresses: ["0x1111111111111111111111111111111111111111", "0x2222222222222222222222222222222222222222"]
7753
8066
  },
7754
- { type: CallbackType.BuyWithEmptyCallback }
8067
+ { type: Type$1.BuyWithEmptyCallback }
7755
8068
  ],
7756
8069
  maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth]
7757
8070
  },
7758
8071
  anvil: {
7759
8072
  callbacks: [
7760
8073
  {
7761
- type: CallbackType.BuyVaultV1Callback,
8074
+ type: Type$1.BuyVaultV1Callback,
7762
8075
  addresses: ["0x3333333333333333333333333333333333333333", "0x4444444444444444444444444444444444444444"],
7763
8076
  vaultFactories: ["0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101", "0x1897A8997241C1cD4bD0698647e4EB7213535c24"]
7764
8077
  },
7765
8078
  {
7766
- type: CallbackType.SellERC20Callback,
8079
+ type: Type$1.SellERC20Callback,
7767
8080
  addresses: ["0x1111111111111111111111111111111111111111", "0x2222222222222222222222222222222222222222"]
7768
8081
  },
7769
- { type: CallbackType.BuyWithEmptyCallback }
8082
+ { type: Type$1.BuyWithEmptyCallback }
7770
8083
  ],
7771
8084
  maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth]
7772
8085
  }
@@ -7774,22 +8087,31 @@ const configs = {
7774
8087
 
7775
8088
  //#endregion
7776
8089
  //#region src/gatekeeper/Gatekeeper.ts
7777
- var Gatekeeper_exports = /* @__PURE__ */ __export({ create: () => create$7 });
8090
+ var Gatekeeper_exports = /* @__PURE__ */ __exportAll({ create: () => create$7 });
8091
+ /**
8092
+ * Create a gatekeeper instance with the provided rules.
8093
+ * @param parameters - Gatekeeper parameters. {@link GatekeeperParameters}
8094
+ * @returns Gatekeeper instance. {@link Gatekeeper}
8095
+ */
7778
8096
  function create$7(parameters) {
8097
+ const { rules } = parameters;
7779
8098
  return {
7780
- rules: parameters.rules,
7781
- isAllowed: async (offers$1) => {
8099
+ isAllowed: async (offers) => {
7782
8100
  return await run({
7783
- items: offers$1,
7784
- rules: parameters.rules
8101
+ items: offers,
8102
+ rules
7785
8103
  });
7786
- }
8104
+ },
8105
+ getRules: async () => rules.map((rule) => ({
8106
+ name: rule.name,
8107
+ description: rule.description
8108
+ }))
7787
8109
  };
7788
8110
  }
7789
8111
 
7790
8112
  //#endregion
7791
8113
  //#region src/gatekeeper/Rules.ts
7792
- var Rules_exports = /* @__PURE__ */ __export({
8114
+ var Rules_exports = /* @__PURE__ */ __exportAll({
7793
8115
  amountMutualExclusivity: () => amountMutualExclusivity,
7794
8116
  callback: () => callback,
7795
8117
  chains: () => chains,
@@ -7808,21 +8130,21 @@ function validity(parameters) {
7808
8130
  const { client } = parameters;
7809
8131
  const sellErc20CallbackInvalid = single("sell_erc20_callback_invalid", "Validates that sell offers have valid ERC20 callback data matching offer collaterals", (offer) => {
7810
8132
  const callbackType = getCallbackType(client.chain.name, offer.callback.address);
7811
- if (callbackType !== CallbackType.SellERC20Callback) return;
8133
+ if (callbackType !== Type$1.SellERC20Callback) return;
7812
8134
  const decoded = decode$2(callbackType, offer.callback.data);
7813
8135
  if (decoded.length === 0) return { message: "Callback data cannot be decoded or is empty." };
7814
- if (callbackType === CallbackType.SellERC20Callback) {
8136
+ if (callbackType === Type$1.SellERC20Callback) {
7815
8137
  const offerCollaterals = new Set(offer.collaterals.map((c) => c.asset.toLowerCase()));
7816
8138
  if (decoded.length !== offer.collaterals.length) return { message: `Sell callback collateral length mismatch. Expected ${offer.collaterals.length}, got ${decoded.length}.` };
7817
8139
  for (const { contract } of decoded) if (!offerCollaterals.has(contract.toLowerCase())) return { message: "Sell callback collateral is not part of offer collaterals." };
7818
8140
  }
7819
8141
  });
7820
- 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) => {
8142
+ 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) => {
7821
8143
  const validationIssues = /* @__PURE__ */ new Map();
7822
8144
  const offersByVaultAddress = /* @__PURE__ */ new Map();
7823
- for (let i = 0; i < offers$1.length; i++) {
7824
- const offer = offers$1[i];
7825
- if (getCallbackType(client.chain.name, offer.callback.address) !== CallbackType.BuyVaultV1Callback) continue;
8145
+ for (let i = 0; i < offers.length; i++) {
8146
+ const offer = offers[i];
8147
+ if (getCallbackType(client.chain.name, offer.callback.address) !== Type$1.BuyVaultV1Callback) continue;
7826
8148
  try {
7827
8149
  const callbackVaults = decodeBuyVaultV1Callback(offer.callback.data);
7828
8150
  for (const { contract } of callbackVaults) {
@@ -7837,7 +8159,7 @@ function validity(parameters) {
7837
8159
  }
7838
8160
  const uniqueVaultAddresses = Array.from(offersByVaultAddress.keys());
7839
8161
  if (uniqueVaultAddresses.length === 0) return validationIssues;
7840
- const allowedFactories = getCallback(client.chain.name, CallbackType.BuyVaultV1Callback)?.vaultFactories.map((f) => f.toLowerCase());
8162
+ const allowedFactories = getCallback(client.chain.name, Type$1.BuyVaultV1Callback)?.vaultFactories.map((f) => f.toLowerCase());
7841
8163
  if (!allowedFactories) return validationIssues;
7842
8164
  const multicallContracts = [];
7843
8165
  for (const vaultAddress of uniqueVaultAddresses) {
@@ -7873,8 +8195,8 @@ function validity(parameters) {
7873
8195
  if (isRegisteredInFactory) registeredVaults.add(vaultAddress);
7874
8196
  }
7875
8197
  const uniqueOffers = /* @__PURE__ */ new Map();
7876
- for (const offersArray of offersByVaultAddress.values()) for (const { index: index$1, offer } of offersArray) uniqueOffers.set(index$1, offer);
7877
- for (const [index$1, offer] of uniqueOffers) try {
8198
+ for (const offersArray of offersByVaultAddress.values()) for (const { index, offer } of offersArray) uniqueOffers.set(index, offer);
8199
+ for (const [index, offer] of uniqueOffers) try {
7878
8200
  const callbackVaults = decodeBuyVaultV1Callback(offer.callback.data);
7879
8201
  const vaultsWithIssues = [];
7880
8202
  for (const { contract } of callbackVaults) {
@@ -7892,7 +8214,7 @@ function validity(parameters) {
7892
8214
  }
7893
8215
  if (vaultsWithIssues.length > 0) {
7894
8216
  const failureDetails = vaultsWithIssues.map((v) => `${v.vaultAddress} (${v.failureReasons})`).join("; ");
7895
- validationIssues.set(index$1, { message: `Buy offer callback vaults are invalid: ${failureDetails}` });
8217
+ validationIssues.set(index, { message: `Buy offer callback vaults are invalid: ${failureDetails}` });
7896
8218
  }
7897
8219
  } catch (_) {}
7898
8220
  return validationIssues;
@@ -7905,16 +8227,16 @@ function validity(parameters) {
7905
8227
  buyCallbackVaultInvalid
7906
8228
  ];
7907
8229
  }
7908
- const chains = ({ chains: chains$3 }) => single("chain_ids", `Validates that offer chain is one of: [${chains$3.map((c) => c.id).join(", ")}]`, (offer) => {
7909
- const allowedChainIds = chains$3.map((c) => c.id);
7910
- if (!allowedChainIds.some((id$1) => id$1 === offer.chainId)) return { message: `Chain ID ${offer.chainId} is not in the allowed chains (${allowedChainIds.join(", ")})` };
8230
+ const chains = ({ chains }) => single("chain_ids", `Validates that offer chain is one of: [${chains.map((c) => c.id).join(", ")}]`, (offer) => {
8231
+ const allowedChainIds = chains.map((c) => c.id);
8232
+ if (!allowedChainIds.some((id) => id === offer.chainId)) return { message: `Chain ID ${offer.chainId} is not in the allowed chains (${allowedChainIds.join(", ")})` };
7911
8233
  });
7912
8234
  const maturity = ({ maturities }) => single("maturity", `Validates that offer maturity is one of: [${maturities.join(", ")}]`, (offer) => {
7913
- const allowedMaturities = maturities.map((m) => from$15(m));
8235
+ const allowedMaturities = maturities.map((m) => from$16(m));
7914
8236
  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}` };
7915
8237
  });
7916
- 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) => {
7917
- if (isEmptyCallback(offer) && offer.buy && !callbacks$1?.find((c) => c === CallbackType.BuyWithEmptyCallback)) return { message: "Buy offers with empty callback not allowed." };
8238
+ 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) => {
8239
+ if (isEmptyCallback(offer) && offer.buy && !callbacks?.find((c) => c === Type$1.BuyWithEmptyCallback)) return { message: "Buy offers with empty callback not allowed." };
7918
8240
  if (isEmptyCallback(offer) && !offer.buy) return { message: "Sell offers require a non-empty callback." };
7919
8241
  if (!isEmptyCallback(offer)) {
7920
8242
  if (!allowedAddresses.includes(offer.callback.address?.toLowerCase())) return { message: `Callback address ${offer.callback.address} is not allowed.` };
@@ -7936,14 +8258,14 @@ const token = ({ assetsByChainId }) => single("token", "Validates that offer loa
7936
8258
  * Returns an issue only for the first non-conforming offer.
7937
8259
  * This rule is signing-agnostic; signer verification is handled at the collector level.
7938
8260
  */
7939
- const sameMaker = () => batch("mixed_maker", "Validates that all offers in a batch have the same maker address", (offers$1) => {
8261
+ const sameMaker = () => batch("mixed_maker", "Validates that all offers in a batch have the same maker address", (offers) => {
7940
8262
  const issues = /* @__PURE__ */ new Map();
7941
- if (offers$1.length === 0) return issues;
7942
- const firstMaker = offers$1[0].maker.toLowerCase();
7943
- for (let i = 1; i < offers$1.length; i++) {
7944
- const offer = offers$1[i];
8263
+ if (offers.length === 0) return issues;
8264
+ const firstMaker = offers[0].maker.toLowerCase();
8265
+ for (let i = 1; i < offers.length; i++) {
8266
+ const offer = offers[i];
7945
8267
  if (offer.maker.toLowerCase() !== firstMaker) {
7946
- issues.set(i, { message: `Offer has different maker ${offer.maker} than first offer ${offers$1[0].maker}` });
8268
+ issues.set(i, { message: `Offer has different maker ${offer.maker} than first offer ${offers[0].maker}` });
7947
8269
  return issues;
7948
8270
  }
7949
8271
  }
@@ -7970,9 +8292,9 @@ const morphoRules = (chains$3) => {
7970
8292
  maturity({ maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth] }),
7971
8293
  callback({
7972
8294
  callbacks: [
7973
- CallbackType.BuyWithEmptyCallback,
7974
- CallbackType.BuyVaultV1Callback,
7975
- CallbackType.SellERC20Callback
8295
+ Type$1.BuyWithEmptyCallback,
8296
+ Type$1.BuyVaultV1Callback,
8297
+ Type$1.SellERC20Callback
7976
8298
  ],
7977
8299
  allowedAddresses: chains$3.flatMap((c) => getCallbackAddresses(c.name))
7978
8300
  }),
@@ -7988,7 +8310,7 @@ function create$6(config) {
7988
8310
  return {
7989
8311
  create: async (batches) => {
7990
8312
  if (batches.length === 0) return [];
7991
- const offersWithBlock = batches.flatMap(({ blockNumber, offers: offers$1 }) => offers$1.map((offer) => ({
8313
+ const offersWithBlock = batches.flatMap(({ blockNumber, offers }) => offers.map((offer) => ({
7992
8314
  offer,
7993
8315
  blockNumber
7994
8316
  })));
@@ -8000,7 +8322,7 @@ function create$6(config) {
8000
8322
  for (const { offer, blockNumber } of offersWithBlock) {
8001
8323
  const obligationId$1 = obligationId(offer);
8002
8324
  if (!obligationsMap.has(obligationId$1)) {
8003
- obligationsMap.set(obligationId$1, from$14({
8325
+ obligationsMap.set(obligationId$1, from$15({
8004
8326
  chainId: offer.chainId,
8005
8327
  loanToken: offer.loanToken,
8006
8328
  maturity: offer.maturity,
@@ -8028,28 +8350,28 @@ function create$6(config) {
8028
8350
  });
8029
8351
  }
8030
8352
  return await db.transaction(async (dbTx) => {
8031
- const obligationsRows = Array.from(obligationsMap.entries()).map(([obligationId$1, obligation]) => ({
8032
- obligationId: obligationId$1,
8353
+ const obligationsRows = Array.from(obligationsMap.entries()).map(([obligationId, obligation]) => ({
8354
+ obligationId,
8033
8355
  chainId: obligation.chainId,
8034
8356
  loanToken: obligation.loanToken.toLowerCase(),
8035
8357
  maturity: obligation.maturity
8036
8358
  }));
8037
- for (const batch$2 of batch$1(obligationsRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(obligations).values(batch$2).onConflictDoNothing();
8359
+ for (const batch of batch$1(obligationsRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(obligations).values(batch).onConflictDoNothing();
8038
8360
  const oraclesRows = Array.from(oraclesMap.values()).map((oracle) => ({
8039
8361
  chainId: oracle.chainId,
8040
8362
  address: oracle.address.toLowerCase(),
8041
8363
  blockNumber: oracle.blockNumber
8042
8364
  }));
8043
- for (const batch$2 of batch$1(oraclesRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(oracles).values(batch$2).onConflictDoNothing();
8044
- const collateralsRows = Array.from(collateralsMap.entries()).flatMap(([obligationId$1, items]) => items.collaterals.map((collateral) => ({
8045
- obligationId: obligationId$1,
8365
+ for (const batch of batch$1(oraclesRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(oracles).values(batch).onConflictDoNothing();
8366
+ const collateralsRows = Array.from(collateralsMap.entries()).flatMap(([obligationId, items]) => items.collaterals.map((collateral) => ({
8367
+ obligationId,
8046
8368
  asset: collateral.asset.toLowerCase(),
8047
- oracleChainId: obligationsMap.get(obligationId$1).chainId,
8369
+ oracleChainId: obligationsMap.get(obligationId).chainId,
8048
8370
  oracleAddress: collateral.oracle.toLowerCase(),
8049
8371
  lltv: collateral.lltv,
8050
8372
  blockNumber: items.blockNumber
8051
8373
  })));
8052
- for (const batch$2 of batch$1(collateralsRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(obligationCollateralsV2).values(batch$2).onConflictDoNothing();
8374
+ for (const batch of batch$1(collateralsRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(obligationCollateralsV2).values(batch).onConflictDoNothing();
8053
8375
  const groupsRows = Array.from(groupsMap.values()).map((group) => ({
8054
8376
  chainId: group.chainId,
8055
8377
  maker: group.maker.toLowerCase(),
@@ -8057,7 +8379,7 @@ function create$6(config) {
8057
8379
  consumed: "0",
8058
8380
  blockNumber: group.blockNumber
8059
8381
  }));
8060
- for (const batch$2 of batch$1(groupsRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(groups).values(batch$2).onConflictDoNothing();
8382
+ for (const batch of batch$1(groupsRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(groups).values(batch).onConflictDoNothing();
8061
8383
  const offersRows = offersWithBlock.map(({ offer, blockNumber }) => ({
8062
8384
  ...serialize(offer),
8063
8385
  obligationId: obligationId(offer),
@@ -8068,17 +8390,17 @@ function create$6(config) {
8068
8390
  blockNumber
8069
8391
  }));
8070
8392
  const inserted = [];
8071
- for (const batch$2 of batch$1(offersRows, DEFAULT_BATCH_SIZE$1)) {
8072
- const result = await dbTx.insert(offers).values(batch$2).onConflictDoNothing().returning();
8393
+ for (const batch of batch$1(offersRows, DEFAULT_BATCH_SIZE$1)) {
8394
+ const result = await dbTx.insert(offers).values(batch).onConflictDoNothing().returning();
8073
8395
  inserted.push(...result);
8074
8396
  }
8075
8397
  if (inserted.length === 0) return [];
8076
8398
  const idCached = /* @__PURE__ */ new Map();
8077
- const id$1 = (params) => {
8399
+ const id = (params) => {
8078
8400
  const preimage = `0x${params.chainId}${params.contract}${params.user}${params.amount}`.toLowerCase();
8079
- const id$2 = idCached.get(preimage) ?? (0, viem.keccak256)(preimage);
8080
- idCached.set(preimage, id$2);
8081
- return id$2;
8401
+ const id = idCached.get(preimage) ?? (0, viem.keccak256)(preimage);
8402
+ idCached.set(preimage, id);
8403
+ return id;
8082
8404
  };
8083
8405
  const offersCallbacksMap = /* @__PURE__ */ new Map();
8084
8406
  for (const offer of inserted) {
@@ -8089,21 +8411,21 @@ function create$6(config) {
8089
8411
  if (!chain) continue;
8090
8412
  const callbackType = getCallbackType(chain.name, offer.callbackAddress);
8091
8413
  if (!callbackType) continue;
8092
- const callbacks$1 = decode$2(callbackType, offer.callbackData).map((callback$1) => ({
8414
+ const callbacks = decode$2(callbackType, offer.callbackData).map((callback) => ({
8093
8415
  chainId: offer.groupChainId,
8094
- contract: callback$1.contract.toLowerCase(),
8416
+ contract: callback.contract.toLowerCase(),
8095
8417
  user: user.toLowerCase(),
8096
- amount: callback$1.amount.toString(),
8097
- type: callbackType === CallbackType.BuyVaultV1Callback ? Type.VAULT_V1 : Type.ERC20,
8098
- asset: callbackType === CallbackType.BuyVaultV1Callback ? void 0 : callback$1.contract.toLowerCase(),
8418
+ amount: callback.amount.toString(),
8419
+ type: callbackType === Type$1.BuyVaultV1Callback ? Type.VAULT_V1 : Type.ERC20,
8420
+ asset: callbackType === Type$1.BuyVaultV1Callback ? void 0 : callback.contract.toLowerCase(),
8099
8421
  blockNumber: offer.blockNumber
8100
8422
  }));
8101
8423
  try {
8102
- await dbTx.insert(offersCallbacks).values(callbacks$1.map((callback$1) => ({
8424
+ await dbTx.insert(offersCallbacks).values(callbacks.map((callback) => ({
8103
8425
  offerHash: offer.hash,
8104
- callbackId: id$1(callback$1)
8426
+ callbackId: id(callback)
8105
8427
  }))).onConflictDoNothing();
8106
- offersCallbacksMap.get(offer.hash).push(...callbacks$1);
8428
+ offersCallbacksMap.get(offer.hash).push(...callbacks);
8107
8429
  } catch (_) {
8108
8430
  offersCallbacksMap.delete(offer.hash);
8109
8431
  }
@@ -8117,34 +8439,34 @@ function create$6(config) {
8117
8439
  idCached.clear();
8118
8440
  return inserted.map((offer) => offer.hash);
8119
8441
  }
8120
- await dbTx.positions.upsert(Array.from(offersCallbacksMap.values()).flatMap((callbacks$1) => callbacks$1.map((callback$1) => ({
8121
- chainId: callback$1.chainId,
8122
- contract: callback$1.contract,
8123
- user: callback$1.user,
8124
- type: callback$1.type,
8125
- asset: callback$1.asset,
8126
- blockNumber: callback$1.blockNumber
8442
+ await dbTx.positions.upsert(Array.from(offersCallbacksMap.values()).flatMap((callbacks) => callbacks.map((callback) => ({
8443
+ chainId: callback.chainId,
8444
+ contract: callback.contract,
8445
+ user: callback.user,
8446
+ type: callback.type,
8447
+ asset: callback.asset,
8448
+ blockNumber: callback.blockNumber
8127
8449
  }))));
8128
- const callbacksRows = Array.from(offersCallbacksMap.values()).flatMap((callbacks$1) => callbacks$1.map((callback$1) => ({
8129
- id: id$1(callback$1),
8130
- positionChainId: callback$1.chainId,
8131
- positionContract: callback$1.contract,
8132
- positionUser: callback$1.user,
8133
- amount: callback$1.amount
8450
+ const callbacksRows = Array.from(offersCallbacksMap.values()).flatMap((callbacks) => callbacks.map((callback) => ({
8451
+ id: id(callback),
8452
+ positionChainId: callback.chainId,
8453
+ positionContract: callback.contract,
8454
+ positionUser: callback.user,
8455
+ amount: callback.amount
8134
8456
  })));
8135
- for (const batch$2 of batch$1(callbacksRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(callbacks).values(batch$2).onConflictDoNothing();
8457
+ for (const batch of batch$1(callbacksRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(callbacks).values(batch).onConflictDoNothing();
8136
8458
  const lotInfos = [];
8137
- for (const [offerHash, callbacks$1] of offersCallbacksMap.entries()) {
8459
+ for (const [offerHash, callbacks] of offersCallbacksMap.entries()) {
8138
8460
  const offer = inserted.find((o) => o.hash === offerHash);
8139
8461
  if (!offer) continue;
8140
- for (const callback$1 of callbacks$1) {
8141
- const isLoanPosition = obligationsMap.get(offer.obligationId)?.loanToken.toLowerCase() === callback$1.asset?.toLowerCase();
8462
+ for (const callback of callbacks) {
8463
+ const isLoanPosition = obligationsMap.get(offer.obligationId)?.loanToken.toLowerCase() === callback.asset?.toLowerCase();
8142
8464
  lotInfos.push({
8143
- positionChainId: callback$1.chainId,
8144
- positionContract: callback$1.contract,
8145
- positionUser: callback$1.user,
8465
+ positionChainId: callback.chainId,
8466
+ positionContract: callback.contract,
8467
+ positionUser: callback.user,
8146
8468
  group: offer.group,
8147
- size: isLoanPosition ? BigInt(offer.assets) : BigInt(callback$1.amount)
8469
+ size: isLoanPosition ? BigInt(offer.assets) : BigInt(callback.amount)
8148
8470
  });
8149
8471
  }
8150
8472
  }
@@ -8238,7 +8560,7 @@ function create$6(config) {
8238
8560
  obligationUnits: BigInt(row.obligationUnits),
8239
8561
  obligationShares: BigInt(row.obligationShares),
8240
8562
  price: BigInt(row.price),
8241
- maturity: from$15(row.maturity),
8563
+ maturity: from$16(row.maturity),
8242
8564
  expiry: row.expiry,
8243
8565
  start: row.start,
8244
8566
  group: row.group,
@@ -8274,7 +8596,7 @@ function create$6(config) {
8274
8596
  if ("hashes" in parameters) {
8275
8597
  const { hashes } = parameters;
8276
8598
  if (hashes.length === 0) return 0;
8277
- const normalizedHashes = hashes.map((hash$1) => hash$1.toLowerCase());
8599
+ const normalizedHashes = hashes.map((hash) => hash.toLowerCase());
8278
8600
  return (await db.delete(offers).where((0, drizzle_orm.inArray)(offers.hash, normalizedHashes))).affectedRows;
8279
8601
  }
8280
8602
  if ("blockNumberGte" in parameters) {
@@ -8284,12 +8606,13 @@ function create$6(config) {
8284
8606
  throw new Error("Invalid parameters");
8285
8607
  },
8286
8608
  getObligations: async (parameters) => {
8287
- const { ids, chainId, loanToken, collateralToken, maturity: maturity$1, cursor, limit = DEFAULT_LIMIT$2 } = parameters ?? {};
8609
+ const { ids, chainId: chainIds, loanToken: loanTokens, collateralToken: collateralTokens, maturity: maturities, cursor, limit = DEFAULT_LIMIT$2 } = parameters ?? {};
8288
8610
  const now$1 = now();
8289
- const collateralFilter = collateralToken !== void 0 ? drizzle_orm.sql`EXISTS (
8611
+ const loanTokenFilter = loanTokens !== void 0 && loanTokens.length > 0 ? drizzle_orm.sql`(${drizzle_orm.sql.join(loanTokens.map((token) => drizzle_orm.sql`LOWER(${obligations.loanToken}) = ${token.toLowerCase()}`), drizzle_orm.sql` OR `)})` : void 0;
8612
+ const collateralFilter = collateralTokens !== void 0 && collateralTokens.length > 0 ? drizzle_orm.sql`EXISTS (
8290
8613
  SELECT 1 FROM ${obligationCollateralsV2} oc
8291
8614
  WHERE oc.obligation_id = ${obligations.obligationId}
8292
- AND LOWER(oc.asset) = ${collateralToken.toLowerCase()}
8615
+ AND (${drizzle_orm.sql.join(collateralTokens.map((token) => drizzle_orm.sql`LOWER(oc.asset) = ${token.toLowerCase()}`), drizzle_orm.sql` OR `)})
8293
8616
  )` : void 0;
8294
8617
  const result = await db.select({
8295
8618
  obligationId: obligations.obligationId,
@@ -8298,15 +8621,15 @@ function create$6(config) {
8298
8621
  collaterals: drizzle_orm.sql`ARRAY_AGG(jsonb_build_object('asset', ${obligationCollateralsV2.asset}, 'oracle', ${oracles.address}, 'lltv', ${obligationCollateralsV2.lltv}))`.as("collaterals"),
8299
8622
  maturity: obligations.maturity
8300
8623
  }).from(obligations).innerJoin(obligationCollateralsV2, (0, drizzle_orm.eq)(obligations.obligationId, obligationCollateralsV2.obligationId)).innerJoin(oracles, drizzle_orm.sql`${obligationCollateralsV2.oracleChainId} = ${oracles.chainId}
8301
- AND ${obligationCollateralsV2.oracleAddress} = ${oracles.address}`).groupBy(obligations.obligationId).where((0, drizzle_orm.and)(cursor !== null && cursor !== void 0 ? (0, drizzle_orm.gt)(obligations.obligationId, cursor) : drizzle_orm.sql`true`, ids !== void 0 && ids.length > 0 ? (0, drizzle_orm.inArray)(obligations.obligationId, ids) : void 0, chainId !== void 0 ? (0, drizzle_orm.eq)(obligations.chainId, chainId) : void 0, loanToken !== void 0 ? drizzle_orm.sql`LOWER(${obligations.loanToken}) = ${loanToken.toLowerCase()}` : void 0, maturity$1 !== void 0 ? (0, drizzle_orm.eq)(obligations.maturity, maturity$1) : (0, drizzle_orm.gte)(obligations.maturity, now$1), collateralFilter)).orderBy((0, drizzle_orm.asc)(obligations.obligationId)).limit(limit);
8624
+ AND ${obligationCollateralsV2.oracleAddress} = ${oracles.address}`).groupBy(obligations.obligationId).where((0, drizzle_orm.and)(cursor !== null && cursor !== void 0 ? (0, drizzle_orm.gt)(obligations.obligationId, cursor) : drizzle_orm.sql`true`, ids !== void 0 && ids.length > 0 ? (0, drizzle_orm.inArray)(obligations.obligationId, ids) : void 0, chainIds !== void 0 && chainIds.length > 0 ? (0, drizzle_orm.inArray)(obligations.chainId, chainIds) : void 0, loanTokenFilter, maturities !== void 0 && maturities.length > 0 ? (0, drizzle_orm.inArray)(obligations.maturity, maturities) : (0, drizzle_orm.gte)(obligations.maturity, now$1), collateralFilter)).orderBy((0, drizzle_orm.asc)(obligations.obligationId)).limit(limit);
8302
8625
  const items = [];
8303
- for (const row of result) items.push(from$14({
8626
+ for (const row of result) items.push(from$15({
8304
8627
  chainId: row.chainId,
8305
8628
  loanToken: row.loanToken,
8306
- collaterals: row.collaterals.sort((a, b) => a.asset.localeCompare(b.asset)).map((c) => from$16({
8629
+ collaterals: row.collaterals.sort((a, b) => a.asset.localeCompare(b.asset)).map((c) => from$17({
8307
8630
  asset: c.asset,
8308
8631
  oracle: c.oracle,
8309
- lltv: from$17(BigInt(c.lltv))
8632
+ lltv: from$18(BigInt(c.lltv))
8310
8633
  })),
8311
8634
  maturity: row.maturity
8312
8635
  }));
@@ -8319,11 +8642,11 @@ function create$6(config) {
8319
8642
  getQuotes: async (parameters) => {
8320
8643
  const { obligationIds } = parameters;
8321
8644
  if (obligationIds.length === 0) return [];
8322
- const now$1 = now();
8645
+ const now$2 = now();
8323
8646
  const query = ({ side }) => db.selectDistinctOn([offers.obligationId], {
8324
8647
  obligationId: offers.obligationId,
8325
8648
  price: offers.price
8326
- }).from(offers).innerJoin(groups, (0, drizzle_orm.and)((0, drizzle_orm.eq)(offers.groupChainId, groups.chainId), (0, drizzle_orm.eq)(offers.groupMaker, groups.maker), (0, drizzle_orm.eq)(offers.group, groups.group))).leftJoin(validations, (0, drizzle_orm.eq)(offers.hash, validations.offerHash)).leftJoin(status, (0, drizzle_orm.eq)(validations.statusId, status.id)).where((0, drizzle_orm.and)((0, drizzle_orm.inArray)(offers.obligationId, obligationIds), (0, drizzle_orm.eq)(offers.buy, side === "buy"), (0, drizzle_orm.gte)(offers.expiry, now$1), (0, drizzle_orm.gte)(offers.maturity, now$1), (0, drizzle_orm.lte)(offers.start, now$1), drizzle_orm.sql`(${status.code} IS NULL OR ${status.code} = ${Status.VALID})`)).orderBy(offers.obligationId, side === "buy" ? drizzle_orm.sql`${offers.price}::numeric ASC` : drizzle_orm.sql`${offers.price}::numeric DESC`);
8649
+ }).from(offers).innerJoin(groups, (0, drizzle_orm.and)((0, drizzle_orm.eq)(offers.groupChainId, groups.chainId), (0, drizzle_orm.eq)(offers.groupMaker, groups.maker), (0, drizzle_orm.eq)(offers.group, groups.group))).leftJoin(validations, (0, drizzle_orm.eq)(offers.hash, validations.offerHash)).leftJoin(status, (0, drizzle_orm.eq)(validations.statusId, status.id)).where((0, drizzle_orm.and)((0, drizzle_orm.inArray)(offers.obligationId, obligationIds), (0, drizzle_orm.eq)(offers.buy, side === "buy"), (0, drizzle_orm.gte)(offers.expiry, now$2), (0, drizzle_orm.gte)(offers.maturity, now$2), (0, drizzle_orm.lte)(offers.start, now$2), drizzle_orm.sql`(${status.code} IS NULL OR ${status.code} = ${Status.VALID})`)).orderBy(offers.obligationId, side === "buy" ? drizzle_orm.sql`${offers.price}::numeric ASC` : drizzle_orm.sql`${offers.price}::numeric DESC`);
8327
8650
  const [bestBuys, bestSells] = await Promise.all([query({ side: "buy" }), query({ side: "sell" })]);
8328
8651
  const quotes = /* @__PURE__ */ new Map();
8329
8652
  for (const row of bestSells) quotes.set(row.obligationId, {
@@ -8341,9 +8664,9 @@ function create$6(config) {
8341
8664
  }
8342
8665
  quote.bid = { price: BigInt(row.price) };
8343
8666
  }
8344
- return Array.from(quotes.entries()).map(([id$1, quote]) => {
8345
- return from$9({
8346
- obligationId: id$1,
8667
+ return Array.from(quotes.entries()).map(([id, quote]) => {
8668
+ return from$10({
8669
+ obligationId: id,
8347
8670
  ask: quote.ask,
8348
8671
  bid: quote.bid
8349
8672
  });
@@ -8384,7 +8707,7 @@ function create$4(db) {
8384
8707
  price: oracles.price,
8385
8708
  blockNumber: oracles.blockNumber,
8386
8709
  chainId: oracles.chainId
8387
- }).from(oracles).where((0, drizzle_orm.eq)(oracles.chainId, chainId))).map((r) => from$11({
8710
+ }).from(oracles).where((0, drizzle_orm.eq)(oracles.chainId, chainId))).map((r) => from$12({
8388
8711
  chainId: r.chainId,
8389
8712
  address: r.address,
8390
8713
  price: r.price,
@@ -8400,7 +8723,7 @@ function create$4(db) {
8400
8723
  blockNumber: o.blockNumber
8401
8724
  }));
8402
8725
  db.transaction(async (dbTx) => {
8403
- for (const batch$2 of batch$1(rows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(oracles).values(batch$2).onConflictDoUpdate({
8726
+ for (const batch of batch$1(rows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(oracles).values(batch).onConflictDoUpdate({
8404
8727
  target: [oracles.chainId, oracles.address],
8405
8728
  set: {
8406
8729
  price: drizzle_orm.sql`EXCLUDED.price`,
@@ -8451,8 +8774,8 @@ const create$3 = (db) => {
8451
8774
  };
8452
8775
  });
8453
8776
  let totalUpdated = 0;
8454
- for (const batch$2 of batch$1(rows, DEFAULT_BATCH_SIZE$1)) {
8455
- const updated = await db.insert(positions).values(batch$2).onConflictDoUpdate({
8777
+ for (const batch of batch$1(rows, DEFAULT_BATCH_SIZE$1)) {
8778
+ const updated = await db.insert(positions).values(batch).onConflictDoUpdate({
8456
8779
  target: [
8457
8780
  positions.chainId,
8458
8781
  positions.contract,
@@ -8482,20 +8805,20 @@ const create$3 = (db) => {
8482
8805
  user: parsed.user
8483
8806
  };
8484
8807
  }
8485
- const positions$1 = await db.select().from(positions).where((0, drizzle_orm.and)((0, drizzle_orm.ne)(positions.user, viem.zeroAddress), filled === void 0 ? drizzle_orm.sql`true` : drizzle_orm.sql`${positions.balance} IS ${filled === true ? drizzle_orm.sql`NOT` : drizzle_orm.sql``} NULL`, type !== void 0 ? (0, drizzle_orm.eq)(positions.positionTypeId, Object.values(Type).indexOf(type) + 1) : drizzle_orm.sql`true`, chainId !== void 0 ? (0, drizzle_orm.eq)(positions.chainId, chainId) : drizzle_orm.sql`true`, (() => {
8808
+ const positions$2 = await db.select().from(positions).where((0, drizzle_orm.and)((0, drizzle_orm.ne)(positions.user, viem.zeroAddress), filled === void 0 ? drizzle_orm.sql`true` : drizzle_orm.sql`${positions.balance} IS ${filled === true ? drizzle_orm.sql`NOT` : drizzle_orm.sql``} NULL`, type !== void 0 ? (0, drizzle_orm.eq)(positions.positionTypeId, Object.values(Type).indexOf(type) + 1) : drizzle_orm.sql`true`, chainId !== void 0 ? (0, drizzle_orm.eq)(positions.chainId, chainId) : drizzle_orm.sql`true`, (() => {
8486
8809
  if (cursor === null || cursor === void 0) return drizzle_orm.sql`true`;
8487
8810
  return drizzle_orm.sql`
8488
8811
  (${chainId === void 0 ? drizzle_orm.sql`"chain_id", ` : drizzle_orm.sql``}"contract", "user") > (${chainId === void 0 ? drizzle_orm.sql`${cursor.chainId}, ` : drizzle_orm.sql``}${cursor.contract}, ${cursor.user})
8489
8812
  `;
8490
8813
  })())).orderBy((0, drizzle_orm.asc)(positions.chainId), (0, drizzle_orm.asc)(positions.contract), (0, drizzle_orm.asc)(positions.user), (0, drizzle_orm.asc)(positions.blockNumber)).limit(limit);
8491
- const nextCursor = positions$1.length === limit ? Buffer.from(JSON.stringify({
8492
- chainId: positions$1[positions$1.length - 1].chainId.toString(),
8493
- contract: positions$1[positions$1.length - 1].contract,
8494
- user: positions$1[positions$1.length - 1].user,
8495
- blockNumber: positions$1[positions$1.length - 1].blockNumber.toString()
8814
+ const nextCursor = positions$2.length === limit ? Buffer.from(JSON.stringify({
8815
+ chainId: positions$2[positions$2.length - 1].chainId.toString(),
8816
+ contract: positions$2[positions$2.length - 1].contract,
8817
+ user: positions$2[positions$2.length - 1].user,
8818
+ blockNumber: positions$2[positions$2.length - 1].blockNumber.toString()
8496
8819
  })).toString("base64url") : null;
8497
8820
  return {
8498
- positions: positions$1.map((p) => ({
8821
+ positions: positions$2.map((p) => ({
8499
8822
  chainId: p.chainId,
8500
8823
  contract: p.contract,
8501
8824
  user: p.user,
@@ -8774,7 +9097,7 @@ function create$1(config) {
8774
9097
  treeRoot: root,
8775
9098
  proofNodes: concatenateProofs(proof.path)
8776
9099
  }));
8777
- for (const batch$2 of batch$1(pathRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(merklePaths).values(batch$2).onConflictDoUpdate({
9100
+ for (const batch of batch$1(pathRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(merklePaths).values(batch).onConflictDoUpdate({
8778
9101
  target: [merklePaths.offerHash],
8779
9102
  set: {
8780
9103
  treeRoot: drizzle_orm.sql`excluded.tree_root`,
@@ -8809,9 +9132,9 @@ function create$1(config) {
8809
9132
  * Concatenates an array of 32-byte hex hashes into a single hex string.
8810
9133
  * Empty arrays return "0x".
8811
9134
  */
8812
- function concatenateProofs(proofs$1) {
8813
- if (proofs$1.length === 0) return "0x";
8814
- return `0x${proofs$1.map((p) => p.slice(2)).join("")}`;
9135
+ function concatenateProofs(proofs) {
9136
+ if (proofs.length === 0) return "0x";
9137
+ return `0x${proofs.map((p) => p.slice(2)).join("")}`;
8815
9138
  }
8816
9139
  /**
8817
9140
  * Splits a concatenated hex string back into an array of 32-byte hex hashes.
@@ -8819,10 +9142,10 @@ function concatenateProofs(proofs$1) {
8819
9142
  */
8820
9143
  function splitProofs(concatenated) {
8821
9144
  if (!concatenated || concatenated === "0x" || concatenated.length <= 2) return [];
8822
- const hex$1 = concatenated.slice(2);
8823
- const proofs$1 = [];
8824
- for (let i = 0; i < hex$1.length; i += 64) proofs$1.push(`0x${hex$1.slice(i, i + 64)}`);
8825
- return proofs$1;
9145
+ const hex = concatenated.slice(2);
9146
+ const proofs = [];
9147
+ for (let i = 0; i < hex.length; i += 64) proofs.push(`0x${hex.slice(i, i + 64)}`);
9148
+ return proofs;
8826
9149
  }
8827
9150
 
8828
9151
  //#endregion
@@ -8857,7 +9180,7 @@ function create(db) {
8857
9180
  upsert: async (results) => {
8858
9181
  if (results.length === 0) return;
8859
9182
  const allowedStatuses = new Set(Object.values(Status));
8860
- const invalidStatuses = Array.from(new Set(results.map((r) => r.status).filter((s$1) => !allowedStatuses.has(s$1))));
9183
+ const invalidStatuses = Array.from(new Set(results.map((r) => r.status).filter((s) => !allowedStatuses.has(s))));
8861
9184
  if (invalidStatuses.length > 0) throw new Error(`Unknown validation status: ${invalidStatuses.join(", ")}`);
8862
9185
  const normalized = results.map((r) => ({
8863
9186
  offerHash: r.offerHash.toLowerCase(),
@@ -8869,12 +9192,12 @@ function create(db) {
8869
9192
  code: status.code
8870
9193
  }).from(status).where((0, drizzle_orm.inArray)(status.code, uniqueStatuses));
8871
9194
  const statusMap = new Map(statusRows.map((row) => [row.code, row.id]));
8872
- for (const status$1 of uniqueStatuses) if (!statusMap.has(status$1)) throw new Error(`Unknown validation status: ${status$1}`);
9195
+ for (const status of uniqueStatuses) if (!statusMap.has(status)) throw new Error(`Unknown validation status: ${status}`);
8873
9196
  const values = normalized.map((row) => ({
8874
9197
  offerHash: row.offerHash,
8875
9198
  statusId: statusMap.get(row.status)
8876
9199
  }));
8877
- for (const batch$2 of batch$1(values, DEFAULT_BATCH_SIZE$1)) await db.insert(validations).values(batch$2).onConflictDoUpdate({
9200
+ for (const batch of batch$1(values, DEFAULT_BATCH_SIZE$1)) await db.insert(validations).values(batch).onConflictDoUpdate({
8878
9201
  target: [validations.offerHash],
8879
9202
  set: {
8880
9203
  statusId: drizzle_orm.sql`excluded.status_id`,
@@ -8887,7 +9210,7 @@ function create(db) {
8887
9210
 
8888
9211
  //#endregion
8889
9212
  //#region src/database/Database.ts
8890
- var Database_exports = /* @__PURE__ */ __export({ connect: () => connect$1 });
9213
+ var Database_exports = /* @__PURE__ */ __exportAll({ connect: () => connect$1 });
8891
9214
  function createDomains(core, chainRegistry) {
8892
9215
  return {
8893
9216
  book: create$10({ db: core }),
@@ -8979,25 +9302,26 @@ const InMemoryDbMap = /* @__PURE__ */ new Map();
8979
9302
  * @returns The database client {@link connect.ReturnType}
8980
9303
  */
8981
9304
  function connect$1(chainRegistry, connectionString) {
8982
- const clean = async (driver$1) => {
9305
+ const clean = async (driver) => {
8983
9306
  if (TABLE_NAMES.length === 0) return;
8984
- await driver$1.execute(`TRUNCATE TABLE ${VERSIONED_TABLE_NAMES.join(", ")} RESTART IDENTITY CASCADE;`);
9307
+ await driver.execute(`TRUNCATE TABLE ${VERSIONED_TABLE_NAMES.join(", ")} RESTART IDENTITY CASCADE;`);
8985
9308
  };
8986
9309
  if (connectionString !== void 0) {
8987
- const pool$1 = new pg.Pool({ connectionString });
8988
- const driver$1 = (0, drizzle_orm_node_postgres.drizzle)(pool$1, { schema: schema_exports });
8989
- const core$1 = augmentWithDomains(driver$1, chainRegistry);
8990
- return Object.assign(core$1, {
9310
+ const pool = new pg.Pool({ connectionString });
9311
+ const driver = (0, drizzle_orm_node_postgres.drizzle)(pool, { schema: schema_exports });
9312
+ const core = augmentWithDomains(driver, chainRegistry);
9313
+ return Object.assign(core, {
8991
9314
  name: "pg",
8992
- pool: pool$1,
8993
- applyMigrations: applyMigrations("pg", driver$1),
8994
- clean: async () => await clean(driver$1)
9315
+ pool,
9316
+ applyMigrations: applyMigrations("pg", driver),
9317
+ clean: async () => await clean(driver)
8995
9318
  });
8996
9319
  }
8997
- const key = node_crypto.default.createHash("md5").update(JSON.stringify(chainRegistry.list())).digest("hex");
9320
+ const poolId = process.env.VITEST_POOL_ID ?? "";
9321
+ const key = node_crypto.default.createHash("md5").update(JSON.stringify(chainRegistry.list()) + poolId).digest("hex");
8998
9322
  const cached = InMemoryDbMap.get(key);
8999
9323
  if (cached) return cached;
9000
- const pool = new __electric_sql_pglite.PGlite();
9324
+ const pool = new _electric_sql_pglite.PGlite();
9001
9325
  const driver = (0, drizzle_orm_pglite.drizzle)(pool, { schema: schema_exports });
9002
9326
  const core = augmentWithDomains(driver, chainRegistry);
9003
9327
  InMemoryDbMap.set(key, Object.assign(core, {
@@ -9357,9 +9681,9 @@ function from(parameters) {
9357
9681
  blockWindow: parameters.blockWindow
9358
9682
  };
9359
9683
  return {
9360
- add: (parameters$1) => add(config, parameters$1),
9361
- get: (parameters$1) => get(config, parameters$1),
9362
- stream: (parameters$1) => streamOffers(config, parameters$1)
9684
+ add: (parameters) => add(config, parameters),
9685
+ get: (parameters) => get(config, parameters),
9686
+ stream: (parameters) => streamOffers(config, parameters)
9363
9687
  };
9364
9688
  }
9365
9689
  /**
@@ -9369,9 +9693,9 @@ function from(parameters) {
9369
9693
  * @throws ViemClientError if the viem client throws an error.
9370
9694
  * @throws Offer.InvalidOfferError if the offer is invalid.
9371
9695
  */
9372
- async function add(config, offers$1) {
9696
+ async function add(config, offers) {
9373
9697
  if (!config.client.account) throw new WalletAccountNotSetError();
9374
- const tree = from$13(offers$1.map((o) => from$12(o)));
9698
+ const tree = from$14(offers.map((o) => from$13(o)));
9375
9699
  const chainId = await getChainId(config.client);
9376
9700
  for (const offer of tree.offers) if (chainId !== offer.chainId) throw new ChainIdMismatchError(offer.chainId, chainId);
9377
9701
  const signature = await sign(tree.offers, config.client);
@@ -9440,7 +9764,7 @@ async function* streamOffers(config, parameters) {
9440
9764
  for await (const { logs, blockNumber: newBlockNumber } of stream) {
9441
9765
  blockNumber = newBlockNumber;
9442
9766
  if (logs.length === 0) continue;
9443
- const offers$1 = [];
9767
+ const offers = [];
9444
9768
  for (const log of logs) {
9445
9769
  if (!log) continue;
9446
9770
  const [payload] = (0, viem.decodeAbiParameters)([{ type: "bytes" }], log.data);
@@ -9448,12 +9772,12 @@ async function* streamOffers(config, parameters) {
9448
9772
  const { tree } = await decode$1(payload);
9449
9773
  for (const offer of tree.offers) {
9450
9774
  if (loanToken && offer.loanToken.toLowerCase() !== loanToken.toLowerCase()) continue;
9451
- offers$1.push(offer);
9775
+ offers.push(offer);
9452
9776
  }
9453
9777
  } catch (_) {}
9454
9778
  }
9455
9779
  yield {
9456
- offers: offers$1,
9780
+ offers,
9457
9781
  blockNumber
9458
9782
  };
9459
9783
  }
@@ -9489,7 +9813,7 @@ function connect(parameters) {
9489
9813
 
9490
9814
  //#endregion
9491
9815
  //#region src/mempool/index.ts
9492
- var mempool_exports = /* @__PURE__ */ __export({
9816
+ var mempool_exports = /* @__PURE__ */ __exportAll({
9493
9817
  ChainIdMismatchError: () => ChainIdMismatchError,
9494
9818
  ViemClientError: () => ViemClientError,
9495
9819
  WalletAccountNotSetError: () => WalletAccountNotSetError,
@@ -9589,6 +9913,12 @@ Object.defineProperty(exports, 'Gatekeeper', {
9589
9913
  return Gatekeeper_exports;
9590
9914
  }
9591
9915
  });
9916
+ Object.defineProperty(exports, 'GatekeeperClient', {
9917
+ enumerable: true,
9918
+ get: function () {
9919
+ return Client_exports;
9920
+ }
9921
+ });
9592
9922
  Object.defineProperty(exports, 'Health', {
9593
9923
  enumerable: true,
9594
9924
  get: function () {
@@ -9713,7 +10043,7 @@ Object.defineProperty(exports, 'RouterApi', {
9713
10043
  Object.defineProperty(exports, 'RouterClient', {
9714
10044
  enumerable: true,
9715
10045
  get: function () {
9716
- return Client_exports;
10046
+ return Client_exports$1;
9717
10047
  }
9718
10048
  });
9719
10049
  exports.RouterStatusResponse = RouterStatusResponse;
@@ -9729,6 +10059,12 @@ Object.defineProperty(exports, 'Time', {
9729
10059
  return time_exports;
9730
10060
  }
9731
10061
  });
10062
+ Object.defineProperty(exports, 'TradingFee', {
10063
+ enumerable: true,
10064
+ get: function () {
10065
+ return TradingFee_exports;
10066
+ }
10067
+ });
9732
10068
  Object.defineProperty(exports, 'Transfer', {
9733
10069
  enumerable: true,
9734
10070
  get: function () {