@morpho-dev/router 0.4.2 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
- import { t as __export } from "./chunk-jass6xSI.mjs";
1
+ import { t as __exportAll } from "./chunk-Bo1DHCg-.mjs";
2
2
  import { z } from "zod/v4";
3
- import { bytesToHex, decodeAbiParameters, encodeAbiParameters, getAddress, hashMessage, hashTypedData, hexToBytes, isAddress, isHex, keccak256, maxUint256, numberToHex, pad, parseAbi, publicActions, recoverAddress, zeroAddress } from "viem";
3
+ import { bytesToHex, decodeAbiParameters, encodeAbiParameters, getAddress, hashTypedData, hexToBytes, isAddress, isHex, keccak256, maxUint256, numberToHex, pad, parseAbi, publicActions, recoverAddress, zeroAddress } from "viem";
4
4
  import { getBlock, getLogs, multicall } from "viem/actions";
5
5
  import { anvil, base, mainnet } from "viem/chains";
6
6
  import * as z$1 from "zod";
@@ -12,8 +12,8 @@ import { ApiBody, ApiOperation, ApiParam, ApiProperty, ApiQuery, ApiResponse, Ap
12
12
  import createOpenApiFetchClient from "openapi-fetch";
13
13
 
14
14
  //#region src/api/Schema/BookResponse.ts
15
- var BookResponse_exports = /* @__PURE__ */ __export({ from: () => from$14 });
16
- function from$14(level) {
15
+ var BookResponse_exports = /* @__PURE__ */ __exportAll({ from: () => from$15 });
16
+ function from$15(level) {
17
17
  return {
18
18
  price: level.price.toString(),
19
19
  assets: level.assets.toString(),
@@ -57,14 +57,14 @@ const RouterStatusResponse = z.object({
57
57
 
58
58
  //#endregion
59
59
  //#region src/api/Schema/ObligationResponse.ts
60
- var ObligationResponse_exports = /* @__PURE__ */ __export({ from: () => from$13 });
60
+ var ObligationResponse_exports = /* @__PURE__ */ __exportAll({ from: () => from$14 });
61
61
  /**
62
62
  * Creates an `ObligationResponse` from a `Obligation`.
63
63
  * @constructor
64
64
  * @param obligation - {@link Obligation}
65
65
  * @returns The created `ObligationResponse`. {@link ObligationResponse}
66
66
  */
67
- function from$13(obligation, quote) {
67
+ function from$14(obligation, quote) {
68
68
  return {
69
69
  id: quote.obligationId,
70
70
  chain_id: obligation.chainId,
@@ -100,7 +100,7 @@ const MetaMorphoFactory = parseAbi(["event CreateMetaMorpho(address indexed meta
100
100
 
101
101
  //#endregion
102
102
  //#region src/core/Abi/index.ts
103
- var Abi_exports = /* @__PURE__ */ __export({
103
+ var Abi_exports = /* @__PURE__ */ __exportAll({
104
104
  ERC4626: () => ERC4626,
105
105
  MetaMorpho: () => MetaMorpho,
106
106
  MetaMorphoFactory: () => MetaMorphoFactory,
@@ -251,41 +251,77 @@ const Morpho = [
251
251
 
252
252
  //#endregion
253
253
  //#region src/core/Callback.ts
254
- var Callback_exports = /* @__PURE__ */ __export({
255
- CallbackType: () => CallbackType,
254
+ var Callback_exports = /* @__PURE__ */ __exportAll({
255
+ Type: () => Type$1,
256
256
  decode: () => decode$2,
257
+ decodeBuyERC20: () => decodeBuyERC20,
257
258
  decodeBuyVaultV1Callback: () => decodeBuyVaultV1Callback,
258
259
  decodeSellERC20Callback: () => decodeSellERC20Callback,
259
260
  encode: () => encode$2,
261
+ encodeBuyERC20: () => encodeBuyERC20,
260
262
  encodeBuyVaultV1Callback: () => encodeBuyVaultV1Callback,
261
263
  encodeSellERC20Callback: () => encodeSellERC20Callback,
262
264
  isEmptyCallback: () => isEmptyCallback
263
265
  });
264
- let CallbackType = /* @__PURE__ */ function(CallbackType$1) {
265
- CallbackType$1["BuyWithEmptyCallback"] = "buy_with_empty_callback";
266
- CallbackType$1["BuyVaultV1Callback"] = "buy_vault_v1_callback";
267
- CallbackType$1["SellERC20Callback"] = "sell_erc20_callback";
268
- return CallbackType$1;
266
+ let Type$1 = /* @__PURE__ */ function(Type) {
267
+ Type["BuyWithEmptyCallback"] = "buy_with_empty_callback";
268
+ Type["BuyERC20"] = "buy_erc20";
269
+ Type["BuyVaultV1Callback"] = "buy_vault_v1_callback";
270
+ Type["SellERC20Callback"] = "sell_erc20_callback";
271
+ return Type;
269
272
  }({});
270
273
  const isEmptyCallback = (offer) => offer.callback.data === "0x";
271
274
  function decode$2(type, data) {
272
275
  switch (type) {
273
- case CallbackType.BuyVaultV1Callback: return decodeBuyVaultV1Callback(data);
274
- case CallbackType.SellERC20Callback: return decodeSellERC20Callback(data);
276
+ case Type$1.BuyERC20: return decodeBuyERC20(data);
277
+ case Type$1.BuyVaultV1Callback: return decodeBuyVaultV1Callback(data);
278
+ case Type$1.SellERC20Callback: return decodeSellERC20Callback(data);
275
279
  default: throw new Error("Invalid callback type");
276
280
  }
277
281
  }
278
282
  function encode$2(type, data) {
279
283
  switch (type) {
280
- case CallbackType.BuyVaultV1Callback:
284
+ case Type$1.BuyERC20:
285
+ if (!("tokens" in data)) throw new Error("Invalid callback data");
286
+ return encodeBuyERC20(data);
287
+ case Type$1.BuyVaultV1Callback:
281
288
  if (!("vaults" in data)) throw new Error("Invalid callback data");
282
289
  return encodeBuyVaultV1Callback(data);
283
- case CallbackType.SellERC20Callback:
290
+ case Type$1.SellERC20Callback:
284
291
  if (!("collaterals" in data)) throw new Error("Invalid callback data");
285
292
  return encodeSellERC20Callback(data);
286
293
  default: throw new Error("Invalid callback type");
287
294
  }
288
295
  }
296
+ /**
297
+ * Decodes BuyERC20 callback data into positions.
298
+ * @param data - The ABI-encoded callback data containing token addresses and amounts.
299
+ * @returns Array of positions with contract address and amount.
300
+ * @throws If data is empty, malformed, or arrays have mismatched lengths.
301
+ */
302
+ function decodeBuyERC20(data) {
303
+ if (!data || data === "0x") throw new Error("Empty callback data");
304
+ let tokens;
305
+ let amounts;
306
+ try {
307
+ [tokens, amounts] = decodeAbiParameters([{ type: "address[]" }, { type: "uint256[]" }], data);
308
+ } catch (_) {
309
+ throw new Error("Invalid BuyERC20 callback data");
310
+ }
311
+ if (tokens.length !== amounts.length) throw new Error("Mismatched array lengths");
312
+ return tokens.map((token, index) => ({
313
+ contract: token,
314
+ amount: amounts[index]
315
+ }));
316
+ }
317
+ /**
318
+ * Encodes BuyERC20 callback parameters into ABI-encoded data.
319
+ * @param parameters - The tokens and amounts to encode.
320
+ * @returns ABI-encoded hex string.
321
+ */
322
+ function encodeBuyERC20(parameters) {
323
+ return encodeAbiParameters([{ type: "address[]" }, { type: "uint256[]" }], [parameters.tokens, parameters.amounts]);
324
+ }
289
325
  function decodeBuyVaultV1Callback(data) {
290
326
  if (!data || data === "0x") throw new Error("Empty callback data");
291
327
  try {
@@ -360,23 +396,23 @@ function atMostOneNonZero(...values) {
360
396
  * // [5]
361
397
  * ```
362
398
  */
363
- function* batch(array, batchSize) {
399
+ function* batch$1(array, batchSize) {
364
400
  for (let i = 0; i < array.length; i += batchSize) yield array.slice(i, i + batchSize);
365
401
  }
366
402
 
367
403
  //#endregion
368
- //#region \0@oxc-project+runtime@0.97.0/helpers/typeof.js
404
+ //#region \0@oxc-project+runtime@0.110.0/helpers/typeof.js
369
405
  function _typeof(o) {
370
406
  "@babel/helpers - typeof";
371
- return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o$1) {
372
- return typeof o$1;
373
- } : function(o$1) {
374
- return o$1 && "function" == typeof Symbol && o$1.constructor === Symbol && o$1 !== Symbol.prototype ? "symbol" : typeof o$1;
407
+ return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
408
+ return typeof o;
409
+ } : function(o) {
410
+ return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
375
411
  }, _typeof(o);
376
412
  }
377
413
 
378
414
  //#endregion
379
- //#region \0@oxc-project+runtime@0.97.0/helpers/toPrimitive.js
415
+ //#region \0@oxc-project+runtime@0.110.0/helpers/toPrimitive.js
380
416
  function toPrimitive(t, r) {
381
417
  if ("object" != _typeof(t) || !t) return t;
382
418
  var e = t[Symbol.toPrimitive];
@@ -389,14 +425,14 @@ function toPrimitive(t, r) {
389
425
  }
390
426
 
391
427
  //#endregion
392
- //#region \0@oxc-project+runtime@0.97.0/helpers/toPropertyKey.js
428
+ //#region \0@oxc-project+runtime@0.110.0/helpers/toPropertyKey.js
393
429
  function toPropertyKey(t) {
394
430
  var i = toPrimitive(t, "string");
395
431
  return "symbol" == _typeof(i) ? i : i + "";
396
432
  }
397
433
 
398
434
  //#endregion
399
- //#region \0@oxc-project+runtime@0.97.0/helpers/defineProperty.js
435
+ //#region \0@oxc-project+runtime@0.110.0/helpers/defineProperty.js
400
436
  function _defineProperty(e, r, t) {
401
437
  return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
402
438
  value: t,
@@ -408,7 +444,7 @@ function _defineProperty(e, r, t) {
408
444
 
409
445
  //#endregion
410
446
  //#region src/utils/Errors.ts
411
- var Errors_exports = /* @__PURE__ */ __export({
447
+ var Errors_exports = /* @__PURE__ */ __exportAll({
412
448
  BaseError: () => BaseError,
413
449
  ReorgError: () => ReorgError
414
450
  });
@@ -465,7 +501,7 @@ var ReorgError = class extends BaseError {
465
501
 
466
502
  //#endregion
467
503
  //#region src/core/Chain.ts
468
- var Chain_exports = /* @__PURE__ */ __export({
504
+ var Chain_exports = /* @__PURE__ */ __exportAll({
469
505
  ChainId: () => ChainId,
470
506
  InvalidBatchSizeError: () => InvalidBatchSizeError,
471
507
  InvalidBlockRangeError: () => InvalidBlockRangeError,
@@ -527,7 +563,8 @@ const chains$1 = {
527
563
  address: "0x1897A8997241C1cD4bD0698647e4EB7213535c24",
528
564
  blockCreated: 21439510
529
565
  }
530
- } }
566
+ } },
567
+ callbacks: []
531
568
  }
532
569
  },
533
570
  base: {
@@ -556,7 +593,8 @@ const chains$1 = {
556
593
  address: "0xFf62A7c278C62eD665133147129245053Bbf5918",
557
594
  blockCreated: 23928808
558
595
  }
559
- } }
596
+ } },
597
+ callbacks: []
560
598
  }
561
599
  },
562
600
  "ethereum-virtual-testnet": {
@@ -585,7 +623,8 @@ const chains$1 = {
585
623
  address: "0x1897A8997241C1cD4bD0698647e4EB7213535c24",
586
624
  blockCreated: 21439510
587
625
  }
588
- } }
626
+ } },
627
+ callbacks: []
589
628
  }
590
629
  },
591
630
  anvil: {
@@ -614,7 +653,8 @@ const chains$1 = {
614
653
  address: "0x0000000000000000000000000000000000000000",
615
654
  blockCreated: 0
616
655
  }
617
- } }
656
+ } },
657
+ callbacks: []
618
658
  }
619
659
  }
620
660
  };
@@ -659,7 +699,7 @@ async function* streamLogs(parameters) {
659
699
  if (a.transactionIndex !== b.transactionIndex) return order === "asc" ? a.transactionIndex - b.transactionIndex : b.transactionIndex - a.transactionIndex;
660
700
  return order === "asc" ? a.logIndex - b.logIndex : b.logIndex - a.logIndex;
661
701
  });
662
- for (const logBatch of batch(logs, maxBatchSize)) yield {
702
+ for (const logBatch of batch$1(logs, maxBatchSize)) yield {
663
703
  logs: logBatch,
664
704
  blockNumber: logBatch.length === maxBatchSize ? Number(logBatch[logBatch.length - 1]?.blockNumber) : order === "asc" ? Number(toBlock) : Number(fromBlock)
665
705
  };
@@ -710,10 +750,15 @@ var MissingBlockNumberError = class extends BaseError {
710
750
 
711
751
  //#endregion
712
752
  //#region src/core/ChainRegistry.ts
713
- var ChainRegistry_exports = /* @__PURE__ */ __export({ create: () => create$1 });
714
- function create$1(chains$2) {
753
+ var ChainRegistry_exports = /* @__PURE__ */ __exportAll({ create: () => create$1 });
754
+ /**
755
+ * Creates a chain registry from a list of chains.
756
+ * @param chains - Array of chain objects to register.
757
+ * @returns A registry for looking up chains by ID. {@link ChainRegistry}
758
+ */
759
+ function create$1(chains) {
715
760
  const byId = /* @__PURE__ */ new Map();
716
- for (const chain of chains$2) byId.set(chain.id, chain);
761
+ for (const chain of chains) byId.set(chain.id, chain);
717
762
  return {
718
763
  getById: (chainId) => byId.get(chainId),
719
764
  list: () => Array.from(byId.values())
@@ -722,7 +767,7 @@ function create$1(chains$2) {
722
767
 
723
768
  //#endregion
724
769
  //#region src/utils/Random.ts
725
- var Random_exports = /* @__PURE__ */ __export({
770
+ var Random_exports = /* @__PURE__ */ __exportAll({
726
771
  address: () => address,
727
772
  bool: () => bool,
728
773
  bytes: () => bytes,
@@ -735,16 +780,16 @@ var Random_exports = /* @__PURE__ */ __export({
735
780
  let currentRng = Math.random;
736
781
  const FNV_OFFSET_BASIS = 2166136261;
737
782
  const FNV_PRIME = 16777619;
738
- const hashSeed = (seed$1) => {
739
- let hash$1 = FNV_OFFSET_BASIS;
740
- for (let i = 0; i < seed$1.length; i += 1) {
741
- hash$1 ^= seed$1.charCodeAt(i);
742
- hash$1 = Math.imul(hash$1, FNV_PRIME);
783
+ const hashSeed = (seed) => {
784
+ let hash = FNV_OFFSET_BASIS;
785
+ for (let i = 0; i < seed.length; i += 1) {
786
+ hash ^= seed.charCodeAt(i);
787
+ hash = Math.imul(hash, FNV_PRIME);
743
788
  }
744
- return hash$1 >>> 0;
789
+ return hash >>> 0;
745
790
  };
746
- const createSeededRng = (seed$1) => {
747
- let state = hashSeed(seed$1);
791
+ const createSeededRng = (seed) => {
792
+ let state = hashSeed(seed);
748
793
  return () => {
749
794
  state += 1831565813;
750
795
  let t = Math.imul(state ^ state >>> 15, state | 1);
@@ -755,9 +800,9 @@ const createSeededRng = (seed$1) => {
755
800
  /**
756
801
  * Runs a function with a deterministic RNG derived from the given seed.
757
802
  */
758
- function withSeed(seed$1, fn) {
803
+ function withSeed(seed, fn) {
759
804
  const previous = currentRng;
760
- currentRng = createSeededRng(seed$1);
805
+ currentRng = createSeededRng(seed);
761
806
  try {
762
807
  return fn();
763
808
  } finally {
@@ -767,8 +812,8 @@ function withSeed(seed$1, fn) {
767
812
  /**
768
813
  * Seeds the global RNG for deterministic test runs.
769
814
  */
770
- function seed(seed$1) {
771
- currentRng = createSeededRng(seed$1);
815
+ function seed(seed) {
816
+ currentRng = createSeededRng(seed);
772
817
  }
773
818
  /**
774
819
  * Returns a deterministic random float in [0, 1).
@@ -779,8 +824,8 @@ function float() {
779
824
  /**
780
825
  * Returns a deterministic random integer in [min, maxExclusive).
781
826
  */
782
- function int(maxExclusive, min$1 = 0) {
783
- return Math.floor(float() * (maxExclusive - min$1)) + min$1;
827
+ function int(maxExclusive, min = 0) {
828
+ return Math.floor(float() * (maxExclusive - min)) + min;
784
829
  }
785
830
  /**
786
831
  * Returns a deterministic random boolean.
@@ -893,12 +938,12 @@ const transformAddress = (val, ctx) => {
893
938
 
894
939
  //#endregion
895
940
  //#region src/core/LLTV.ts
896
- var LLTV_exports = /* @__PURE__ */ __export({
941
+ var LLTV_exports = /* @__PURE__ */ __exportAll({
897
942
  InvalidLLTVError: () => InvalidLLTVError,
898
943
  InvalidOptionError: () => InvalidOptionError$1,
899
944
  LLTVSchema: () => LLTVSchema,
900
945
  Options: () => Options,
901
- from: () => from$12
946
+ from: () => from$13
902
947
  });
903
948
  const Options = [
904
949
  .385,
@@ -917,7 +962,7 @@ const LLTV_SCALED = Options.map((lltv) => BigInt(lltv * 10 ** 18));
917
962
  * @param lltv - The LLTV option or the scaled LLTV.
918
963
  * @returns The LLTV.
919
964
  */
920
- function from$12(lltv) {
965
+ function from$13(lltv) {
921
966
  if (typeof lltv === "bigint" && !LLTV_SCALED.includes(lltv)) throw new InvalidLLTVError(lltv);
922
967
  if (typeof lltv === "bigint") return lltv;
923
968
  if (typeof lltv === "number" && !Options.includes(lltv)) throw new InvalidOptionError$1(lltv);
@@ -937,21 +982,21 @@ var InvalidLLTVError = class extends BaseError {
937
982
  };
938
983
  const LLTVSchema = z$1.bigint({ coerce: true }).refine((lltv) => {
939
984
  try {
940
- from$12(lltv);
985
+ from$13(lltv);
941
986
  return true;
942
987
  } catch (_) {
943
988
  return false;
944
989
  }
945
990
  }, { error: () => {
946
991
  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)";
947
- } }).transform((lltv) => from$12(lltv));
992
+ } }).transform((lltv) => from$13(lltv));
948
993
 
949
994
  //#endregion
950
995
  //#region src/core/Collateral.ts
951
- var Collateral_exports = /* @__PURE__ */ __export({
996
+ var Collateral_exports = /* @__PURE__ */ __exportAll({
952
997
  CollateralSchema: () => CollateralSchema,
953
998
  CollateralsSchema: () => CollateralsSchema,
954
- from: () => from$11,
999
+ from: () => from$12,
955
1000
  random: () => random$3
956
1001
  });
957
1002
  const CollateralSchema = z$1.object({
@@ -971,10 +1016,10 @@ const CollateralsSchema = z$1.array(CollateralSchema).min(1, { message: "At leas
971
1016
  }
972
1017
  return true;
973
1018
  }, { message: "Collaterals must not contain duplicate assets" });
974
- const from$11 = (parameters) => {
1019
+ const from$12 = (parameters) => {
975
1020
  return {
976
1021
  asset: parameters.asset.toLowerCase(),
977
- lltv: from$12(parameters.lltv),
1022
+ lltv: from$13(parameters.lltv),
978
1023
  oracle: parameters.oracle.toLowerCase()
979
1024
  };
980
1025
  };
@@ -988,7 +1033,7 @@ const from$11 = (parameters) => {
988
1033
  * ```
989
1034
  */
990
1035
  function random$3() {
991
- return from$11({
1036
+ return from$12({
992
1037
  asset: address(),
993
1038
  oracle: address(),
994
1039
  lltv: .965
@@ -997,7 +1042,7 @@ function random$3() {
997
1042
 
998
1043
  //#endregion
999
1044
  //#region src/core/ERC4626.ts
1000
- var ERC4626_exports = /* @__PURE__ */ __export({
1045
+ var ERC4626_exports = /* @__PURE__ */ __exportAll({
1001
1046
  DenominatorIsZeroError: () => DenominatorIsZeroError,
1002
1047
  convertToAssets: () => convertToAssets,
1003
1048
  convertToShares: () => convertToShares,
@@ -1060,7 +1105,7 @@ var DenominatorIsZeroError = class extends BaseError {
1060
1105
 
1061
1106
  //#endregion
1062
1107
  //#region src/core/Liquidity.ts
1063
- var Liquidity_exports = /* @__PURE__ */ __export({
1108
+ var Liquidity_exports = /* @__PURE__ */ __exportAll({
1064
1109
  calculateMaxDebt: () => calculateMaxDebt,
1065
1110
  generateAllowancePoolId: () => generateAllowancePoolId,
1066
1111
  generateBalancePoolId: () => generateBalancePoolId,
@@ -1086,23 +1131,23 @@ function calculateMaxDebt(amount, oraclePrice, lltv) {
1086
1131
  * Generate pool ID for balance pools.
1087
1132
  */
1088
1133
  function generateBalancePoolId(parameters) {
1089
- const { user, chainId, token: token$1 } = parameters;
1090
- return `${user}-${chainId.toString()}-${token$1}-balance`.toLowerCase();
1134
+ const { user, chainId, token } = parameters;
1135
+ return `${user}-${chainId.toString()}-${token}-balance`.toLowerCase();
1091
1136
  }
1092
1137
  /**
1093
1138
  * Generate pool ID for allowance pools.
1094
1139
  */
1095
1140
  function generateAllowancePoolId(parameters) {
1096
- const { user, chainId, token: token$1 } = parameters;
1097
- return `${user}-${chainId.toString()}-${token$1}-allowance`.toLowerCase();
1141
+ const { user, chainId, token } = parameters;
1142
+ return `${user}-${chainId.toString()}-${token}-allowance`.toLowerCase();
1098
1143
  }
1099
1144
  /**
1100
1145
  * Generate pool ID for sell ERC20 callback pools.
1101
1146
  * Each offer has its own callback pool to prevent liquidity conflicts.
1102
1147
  */
1103
1148
  function generateSellERC20CallbackPoolId(parameters) {
1104
- const { user, chainId, obligationId: obligationId$1, token: token$1, offerHash } = parameters;
1105
- return `${user}-${chainId.toString()}-${obligationId$1}-${token$1}-${offerHash}-sell_erc20_callback`.toLowerCase();
1149
+ const { user, chainId, obligationId, token, offerHash } = parameters;
1150
+ return `${user}-${chainId.toString()}-${obligationId}-${token}-${offerHash}-sell_erc20_callback`.toLowerCase();
1106
1151
  }
1107
1152
  /**
1108
1153
  * Generate pool ID for obligation collateral pools.
@@ -1110,22 +1155,22 @@ function generateSellERC20CallbackPoolId(parameters) {
1110
1155
  * These pools are shared across all offers with the same obligation.
1111
1156
  */
1112
1157
  function generateObligationCollateralPoolId(parameters) {
1113
- const { user, chainId, obligationId: obligationId$1, token: token$1 } = parameters;
1114
- return `${user}-${chainId.toString()}-${obligationId$1}-${token$1}-obligation-collateral`.toLowerCase();
1158
+ const { user, chainId, obligationId, token } = parameters;
1159
+ return `${user}-${chainId.toString()}-${obligationId}-${token}-obligation-collateral`.toLowerCase();
1115
1160
  }
1116
1161
  /**
1117
1162
  * Generate pool ID for buy vault callback pools.
1118
1163
  */
1119
1164
  function generateBuyVaultCallbackPoolId(parameters) {
1120
1165
  const { user, chainId, vault, offerHash } = parameters;
1121
- return `${user}-${chainId.toString()}-${vault}-${offerHash}-${CallbackType.BuyVaultV1Callback}`.toLowerCase();
1166
+ return `${user}-${chainId.toString()}-${vault}-${offerHash}-${Type$1.BuyVaultV1Callback}`.toLowerCase();
1122
1167
  }
1123
1168
  /**
1124
1169
  * Generate pool ID for debt pools.
1125
1170
  */
1126
1171
  function generateDebtPoolId(parameters) {
1127
- const { user, chainId, obligationId: obligationId$1 } = parameters;
1128
- return `${user}-${chainId.toString()}-${obligationId$1}-debt`.toLowerCase();
1172
+ const { user, chainId, obligationId } = parameters;
1173
+ return `${user}-${chainId.toString()}-${obligationId}-debt`.toLowerCase();
1129
1174
  }
1130
1175
  /**
1131
1176
  * Generate pool ID for user position in a vault.
@@ -1151,17 +1196,17 @@ function generateMarketLiquidityPoolId(parameters) {
1151
1196
 
1152
1197
  //#endregion
1153
1198
  //#region src/core/Maturity.ts
1154
- var Maturity_exports = /* @__PURE__ */ __export({
1199
+ var Maturity_exports = /* @__PURE__ */ __exportAll({
1155
1200
  InvalidDateError: () => InvalidDateError,
1156
1201
  InvalidFormatError: () => InvalidFormatError,
1157
1202
  InvalidOptionError: () => InvalidOptionError,
1158
1203
  MaturitySchema: () => MaturitySchema,
1159
1204
  MaturityType: () => MaturityType,
1160
- from: () => from$10
1205
+ from: () => from$11
1161
1206
  });
1162
- const MaturitySchema = z$1.number().int().refine((maturity$1) => {
1207
+ const MaturitySchema = z$1.number().int().refine((maturity) => {
1163
1208
  try {
1164
- from$10(maturity$1);
1209
+ from$11(maturity);
1165
1210
  return true;
1166
1211
  } catch (_e) {
1167
1212
  return false;
@@ -1172,15 +1217,15 @@ const MaturitySchema = z$1.number().int().refine((maturity$1) => {
1172
1217
  } catch (_) {
1173
1218
  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).`;
1174
1219
  }
1175
- } }).transform((maturity$1) => maturity$1);
1176
- let MaturityType = /* @__PURE__ */ function(MaturityType$1) {
1177
- MaturityType$1["EndOfWeek"] = "end_of_week";
1178
- MaturityType$1["EndOfNextWeek"] = "end_of_next_week";
1179
- MaturityType$1["EndOfMonth"] = "end_of_month";
1180
- MaturityType$1["EndOfNextMonth"] = "end_of_next_month";
1181
- MaturityType$1["EndOfQuarter"] = "end_of_quarter";
1182
- MaturityType$1["EndOfNextQuarter"] = "end_of_next_quarter";
1183
- return MaturityType$1;
1220
+ } }).transform((maturity) => maturity);
1221
+ let MaturityType = /* @__PURE__ */ function(MaturityType) {
1222
+ MaturityType["EndOfWeek"] = "end_of_week";
1223
+ MaturityType["EndOfNextWeek"] = "end_of_next_week";
1224
+ MaturityType["EndOfMonth"] = "end_of_month";
1225
+ MaturityType["EndOfNextMonth"] = "end_of_next_month";
1226
+ MaturityType["EndOfQuarter"] = "end_of_quarter";
1227
+ MaturityType["EndOfNextQuarter"] = "end_of_next_quarter";
1228
+ return MaturityType;
1184
1229
  }({});
1185
1230
  const MaturityOptions = {
1186
1231
  end_of_week: () => endOfWeek(),
@@ -1196,7 +1241,7 @@ const MaturityOptions = {
1196
1241
  * @throws {InvalidDateError} If the maturity is in seconds but not a valid date.
1197
1242
  * @throws {InvalidOptionError} If the maturity is not a valid option.
1198
1243
  */
1199
- function from$10(ts) {
1244
+ function from$11(ts) {
1200
1245
  if (typeof ts === "string") {
1201
1246
  if (ts in MaturityOptions) return MaturityOptions[ts]();
1202
1247
  throw new InvalidOptionError(ts);
@@ -1214,23 +1259,23 @@ const endOfNextWeek = () => fridayOfWeek(1);
1214
1259
  * on that Friday), roll to the next month's last Friday.
1215
1260
  */
1216
1261
  const endOfMonth = () => {
1217
- const now$1 = /* @__PURE__ */ new Date();
1218
- const year = now$1.getUTCFullYear();
1219
- const month = now$1.getUTCMonth();
1220
- const endOfMonth$1 = lastFridayOfMonth(year, month);
1221
- if (now$1.getTime() > endOfMonth$1 * 1e3) return lastFridayOfMonth(year, month + 1);
1222
- return endOfMonth$1;
1262
+ const now = /* @__PURE__ */ new Date();
1263
+ const year = now.getUTCFullYear();
1264
+ const month = now.getUTCMonth();
1265
+ const endOfMonth = lastFridayOfMonth(year, month);
1266
+ if (now.getTime() > endOfMonth * 1e3) return lastFridayOfMonth(year, month + 1);
1267
+ return endOfMonth;
1223
1268
  };
1224
1269
  /** Returns the end of the next month (last friday of the next month at 15:00:00 UTC)
1225
1270
  * Business rule: if we are after the last Friday of the current month (strictly after 15:00 UTC
1226
1271
  * on that Friday), we consider being in the next month already, so "next month" becomes month+2.
1227
1272
  */
1228
1273
  const endOfNextMonth = () => {
1229
- const now$1 = /* @__PURE__ */ new Date();
1230
- const year = now$1.getUTCFullYear();
1231
- const month = now$1.getUTCMonth();
1232
- const endOfMonth$1 = lastFridayOfMonth(year, month);
1233
- if (now$1.getTime() > endOfMonth$1 * 1e3) return lastFridayOfMonth(year, month + 2);
1274
+ const now = /* @__PURE__ */ new Date();
1275
+ const year = now.getUTCFullYear();
1276
+ const month = now.getUTCMonth();
1277
+ const endOfMonth = lastFridayOfMonth(year, month);
1278
+ if (now.getTime() > endOfMonth * 1e3) return lastFridayOfMonth(year, month + 2);
1234
1279
  return lastFridayOfMonth(year, month + 1);
1235
1280
  };
1236
1281
  /** Returns the end of the current quarter (last friday of the quarter at 15:00:00 UTC) */
@@ -1238,10 +1283,10 @@ const endOfQuarter = () => lastFridayOfQuarter(0);
1238
1283
  /** Returns the end of the next quarter (last friday of the next quarter at 15:00:00 UTC) */
1239
1284
  const endOfNextQuarter = () => lastFridayOfQuarter(1);
1240
1285
  const fridayOfWeek = (weeksAhead = 0) => {
1241
- const now$1 = /* @__PURE__ */ new Date();
1242
- const today15H = new Date(Date.UTC(now$1.getUTCFullYear(), now$1.getUTCMonth(), now$1.getUTCDate(), 15));
1286
+ const now = /* @__PURE__ */ new Date();
1287
+ const today15H = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), 15));
1243
1288
  let daysUntilFriday = (5 - today15H.getUTCDay() + 7) % 7;
1244
- if (daysUntilFriday === 0 && now$1.getTime() >= today15H.getTime()) daysUntilFriday = 7;
1289
+ if (daysUntilFriday === 0 && now.getTime() >= today15H.getTime()) daysUntilFriday = 7;
1245
1290
  const friday = new Date(today15H);
1246
1291
  friday.setUTCDate(friday.getUTCDate() + daysUntilFriday + weeksAhead * 7);
1247
1292
  return friday.getTime() / 1e3;
@@ -1252,9 +1297,9 @@ const lastFridayOfMonth = (year, month) => {
1252
1297
  return lastDayOfMonth15H.setUTCDate(lastDayOfMonth15H.getUTCDate()) / 1e3;
1253
1298
  };
1254
1299
  const lastFridayOfQuarter = (quartersAhead = 0) => {
1255
- const now$1 = /* @__PURE__ */ new Date();
1256
- const quarterIndex = Math.floor(now$1.getUTCMonth() / 3) + quartersAhead;
1257
- return lastFridayOfMonth(now$1.getUTCFullYear() + Math.floor(quarterIndex / 4), quarterIndex % 4 * 3 + 2);
1300
+ const now = /* @__PURE__ */ new Date();
1301
+ const quarterIndex = Math.floor(now.getUTCMonth() / 3) + quartersAhead;
1302
+ return lastFridayOfMonth(now.getUTCFullYear() + Math.floor(quarterIndex / 4), quarterIndex % 4 * 3 + 2);
1258
1303
  };
1259
1304
  var InvalidFormatError = class extends BaseError {
1260
1305
  constructor() {
@@ -1277,7 +1322,7 @@ var InvalidOptionError = class extends BaseError {
1277
1322
 
1278
1323
  //#endregion
1279
1324
  //#region src/utils/Format.ts
1280
- var Format_exports = /* @__PURE__ */ __export({
1325
+ var Format_exports = /* @__PURE__ */ __exportAll({
1281
1326
  fromSnakeCase: () => fromSnakeCase$3,
1282
1327
  stringifyBigint: () => stringifyBigint,
1283
1328
  toSnakeCase: () => toSnakeCase$1
@@ -1322,11 +1367,12 @@ function stringifyBigint(value) {
1322
1367
 
1323
1368
  //#endregion
1324
1369
  //#region src/core/Obligation.ts
1325
- var Obligation_exports = /* @__PURE__ */ __export({
1370
+ var Obligation_exports = /* @__PURE__ */ __exportAll({
1326
1371
  CollateralsAreNotSortedError: () => CollateralsAreNotSortedError,
1327
1372
  InvalidObligationError: () => InvalidObligationError,
1328
1373
  ObligationSchema: () => ObligationSchema,
1329
- from: () => from$9,
1374
+ from: () => from$10,
1375
+ fromOffer: () => fromOffer$1,
1330
1376
  fromSnakeCase: () => fromSnakeCase$2,
1331
1377
  id: () => id,
1332
1378
  random: () => random$2
@@ -1360,11 +1406,11 @@ const ObligationSchema = z$1.object({
1360
1406
  * });
1361
1407
  * ```
1362
1408
  */
1363
- function from$9(parameters) {
1409
+ function from$10(parameters) {
1364
1410
  try {
1365
1411
  const parsedObligation = ObligationSchema.parse({
1366
1412
  ...parameters,
1367
- maturity: from$10(parameters.maturity)
1413
+ maturity: from$11(parameters.maturity)
1368
1414
  });
1369
1415
  return {
1370
1416
  chainId: parsedObligation.chainId,
@@ -1383,7 +1429,7 @@ function from$9(parameters) {
1383
1429
  * @returns The created obligation. {@link fromSnakeCase.ReturnType}
1384
1430
  */
1385
1431
  function fromSnakeCase$2(input) {
1386
- return from$9(fromSnakeCase$3(input));
1432
+ return from$10(fromSnakeCase$3(input));
1387
1433
  }
1388
1434
  /**
1389
1435
  * Calculates the obligation id based on the smart contract's Obligation struct.
@@ -1448,11 +1494,26 @@ function id(parameters) {
1448
1494
  * ```
1449
1495
  */
1450
1496
  function random$2() {
1451
- return from$9({
1497
+ return from$10({
1452
1498
  chainId: 1,
1453
1499
  loanToken: address(),
1454
1500
  collaterals: [random$3()],
1455
- maturity: from$10("end_of_next_quarter")
1501
+ maturity: from$11("end_of_next_quarter")
1502
+ });
1503
+ }
1504
+ /**
1505
+ * Creates an obligation from an offer.
1506
+ * @constructor
1507
+ *
1508
+ * @param offer - The offer to create the obligation from.
1509
+ * @returns The created obligation. {@link fromOffer.ReturnType}
1510
+ */
1511
+ function fromOffer$1(offer) {
1512
+ return from$10({
1513
+ chainId: offer.chainId,
1514
+ loanToken: offer.loanToken,
1515
+ collaterals: offer.collaterals,
1516
+ maturity: offer.maturity
1456
1517
  });
1457
1518
  }
1458
1519
  var InvalidObligationError = class extends BaseError {
@@ -1468,282 +1529,31 @@ var CollateralsAreNotSortedError = class extends BaseError {
1468
1529
  }
1469
1530
  };
1470
1531
 
1471
- //#endregion
1472
- //#region src/core/Tree.ts
1473
- var Tree_exports = /* @__PURE__ */ __export({
1474
- DecodeError: () => DecodeError,
1475
- EncodeError: () => EncodeError,
1476
- TreeError: () => TreeError,
1477
- VERSION: () => VERSION,
1478
- decode: () => decode$1,
1479
- encode: () => encode$1,
1480
- encodeUnsigned: () => encodeUnsigned,
1481
- from: () => from$8,
1482
- proofs: () => proofs
1483
- });
1484
- const VERSION = 1;
1485
- const normalizeHash = (hash$1) => hash$1.toLowerCase();
1486
- /**
1487
- * Builds a Merkle tree from a list of offers.
1488
- *
1489
- * Leaves are the offer `hash` values as `bytes32` and are deterministically
1490
- * ordered following the StandardMerkleTree leaf ordering so that the resulting
1491
- * root is stable regardless of the input order.
1492
- *
1493
- * @param offers - Offers to include in the tree.
1494
- * @returns A `StandardMerkleTree` of `bytes32` leaves representing the offers.
1495
- * @throws {TreeError} If tree building fails due to offer inconsistencies.
1496
- */
1497
- const from$8 = (offers) => {
1498
- const leaves = offers.map((offer) => [hash(offer)]);
1499
- const tree = StandardMerkleTree.of(leaves, ["bytes32"]);
1500
- const orderedOffers = orderOffers(tree, offers);
1501
- return Object.assign(tree, { offers: orderedOffers });
1502
- };
1503
- const orderOffers = (tree, offers) => {
1504
- const offerByHash = /* @__PURE__ */ new Map();
1505
- for (const offer of offers) offerByHash.set(normalizeHash(hash(offer)), offer);
1506
- const entries = tree.dump().values.map((value) => {
1507
- const hash$1 = normalizeHash(value.value[0]);
1508
- const offer = offerByHash.get(hash$1);
1509
- if (!offer) throw new TreeError(`missing offer for leaf ${hash$1}`);
1510
- return {
1511
- offer,
1512
- treeIndex: value.treeIndex
1513
- };
1514
- });
1515
- entries.sort((a, b) => b.treeIndex - a.treeIndex);
1516
- return entries.map((item) => item.offer);
1517
- };
1518
- /**
1519
- * Generates merkle proofs for all offers in a tree.
1520
- *
1521
- * Each proof allows independent verification that an offer is included in the tree
1522
- * without requiring the full tree. Proofs are ordered by StandardMerkleTree leaf ordering.
1523
- *
1524
- * @param tree - The {@link Tree} to generate proofs for.
1525
- * @returns Array of proofs - {@link Proof}
1526
- */
1527
- const proofs = (tree) => {
1528
- return tree.offers.map((offer) => {
1529
- return {
1530
- offer,
1531
- path: tree.getProof([hash(offer)])
1532
- };
1533
- });
1534
- };
1535
- const assertHex = (value, expectedBytes, name) => {
1536
- if (typeof value !== "string" || !isHex(value)) throw new DecodeError(`${name} is not a valid hex string`);
1537
- if (hexToBytes(value).length !== expectedBytes) throw new DecodeError(`${name}: expected ${expectedBytes} bytes`);
1538
- };
1539
- const verifySignatureAndRecoverAddress = async (params) => {
1540
- const { root, signature } = params;
1541
- assertHex(signature, 65, "signature");
1542
- const hash$1 = hashMessage({ raw: root });
1543
- try {
1544
- return await recoverAddress({
1545
- hash: hash$1,
1546
- signature
1547
- });
1548
- } catch {
1549
- throw new DecodeError("signature recovery failed");
1550
- }
1551
- };
1552
- /**
1553
- * Encodes a merkle tree with signature into hex calldata for onchain broadcast.
1554
- *
1555
- * Layout: `0x{vv}{gzip([...offers])}{root}{signature}` where:
1556
- * - `{vv}`: 1-byte version (currently 0x01)
1557
- * - `{gzip([...offers])}`: gzipped JSON array of serialized offers
1558
- * - `{root}`: 32-byte merkle root
1559
- * - `{signature}`: 65-byte EIP-191 signature over raw root bytes
1560
- *
1561
- * Validates signature authenticity and root integrity before encoding.
1562
- *
1563
- * @example
1564
- * ```typescript
1565
- * const tree = Tree.from(offers);
1566
- * const signature = await wallet.signMessage({ message: { raw: tree.root } });
1567
- * const calldata = await Tree.encode(tree, signature);
1568
- * await broadcast(calldata);
1569
- * ```
1570
- *
1571
- * @example
1572
- * Manual construction (for advanced users):
1573
- * ```typescript
1574
- * const tree = Tree.from(offers);
1575
- * const compressed = gzip(JSON.stringify(tree.offers.map(Offer.serialize)));
1576
- * const partial = `0x01${bytesToHex(compressed)}${tree.root.slice(2)}`;
1577
- * const signature = await wallet.signMessage({ message: { raw: tree.root } });
1578
- * const calldata = `${partial}${signature.slice(2)}`;
1579
- * ```
1580
- *
1581
- * @param tree - Merkle tree of offers
1582
- * @param signature - EIP-191 signature over raw root bytes
1583
- * @returns Hex-encoded calldata ready for onchain broadcast
1584
- * @throws {EncodeError} If signature verification fails or root mismatch
1585
- */
1586
- const encode$1 = async (tree, signature) => {
1587
- validateTreeForEncoding(tree);
1588
- await verifySignatureAndRecoverAddress({
1589
- root: tree.root,
1590
- signature
1591
- });
1592
- const unsigned = encodeUnsignedBytes(tree);
1593
- const sigBytes = hexToBytes(signature);
1594
- const encoded = new Uint8Array(unsigned.length + sigBytes.length);
1595
- encoded.set(unsigned, 0);
1596
- encoded.set(sigBytes, unsigned.length);
1597
- return bytesToHex(encoded);
1598
- };
1599
- /**
1600
- * Encodes a merkle tree without a signature into hex payload for client-side signing.
1601
- *
1602
- * Layout: `0x{vv}{gzip([...offers])}{root}` where:
1603
- * - `{vv}`: 1-byte version (currently 0x01)
1604
- * - `{gzip([...offers])}`: gzipped JSON array of serialized offers
1605
- * - `{root}`: 32-byte merkle root
1606
- *
1607
- * Validates root integrity before encoding.
1608
- *
1609
- * @param tree - Merkle tree of offers
1610
- * @returns Hex-encoded unsigned payload
1611
- * @throws {EncodeError} If root mismatch
1612
- */
1613
- const encodeUnsigned = (tree) => {
1614
- validateTreeForEncoding(tree);
1615
- return bytesToHex(encodeUnsignedBytes(tree));
1616
- };
1617
- const validateTreeForEncoding = (tree) => {
1618
- if (VERSION > 255) throw new EncodeError(`version overflow: ${VERSION} exceeds 255`);
1619
- const computed = from$8(tree.offers);
1620
- if (tree.root !== computed.root) throw new EncodeError(`root mismatch: expected ${computed.root}, got ${tree.root}`);
1621
- };
1622
- const encodeUnsignedBytes = (tree) => {
1623
- const offersPayload = tree.offers.map(serialize);
1624
- const compressed = gzip(JSON.stringify(offersPayload));
1625
- const rootBytes = hexToBytes(tree.root);
1626
- const encoded = new Uint8Array(1 + compressed.length + 32);
1627
- encoded[0] = VERSION;
1628
- encoded.set(compressed, 1);
1629
- encoded.set(rootBytes, 1 + compressed.length);
1630
- return encoded;
1631
- };
1632
- /**
1633
- * Decodes hex calldata into a validated merkle tree.
1634
- *
1635
- * Validates signature before decompression for fail-fast rejection of invalid payloads.
1636
- * Returns the tree with separately validated signature and recovered signer address.
1637
- *
1638
- * Validation order:
1639
- * 1. Version check
1640
- * 2. Signature verification (fail-fast, before decompression)
1641
- * 3. Decompression (only if signature valid)
1642
- * 4. Root verification (computed from offers vs embedded root)
1643
- *
1644
- * @example
1645
- * ```typescript
1646
- * const { tree, signature, signer } = await Tree.decode(calldata);
1647
- * console.log(`Tree signed by ${signer} with ${tree.offers.length} offers`);
1648
- * ```
1649
- *
1650
- * @param encoded - Hex calldata in format `0x{vv}{gzip}{root}{signature}`
1651
- * @returns Validated tree, signature, and recovered signer address
1652
- * @throws {DecodeError} If version invalid, signature invalid, or root mismatch
1653
- */
1654
- const decode$1 = async (encoded) => {
1655
- const bytes$1 = hexToBytes(encoded);
1656
- if (bytes$1.length < 98) throw new DecodeError("payload too short");
1657
- const version = bytes$1[0];
1658
- if (version !== (VERSION & 255)) throw new DecodeError(`invalid version: expected ${VERSION}, got ${version ?? 0}`);
1659
- const signature = bytesToHex(bytes$1.slice(-65));
1660
- const root = bytesToHex(bytes$1.slice(-97, -65));
1661
- assertHex(root, 32, "root");
1662
- assertHex(signature, 65, "signature");
1663
- const signer = await verifySignatureAndRecoverAddress({
1664
- root,
1665
- signature
1666
- });
1667
- const compressed = bytes$1.slice(1, -97);
1668
- let decoded;
1669
- try {
1670
- decoded = ungzip(compressed, { to: "string" });
1671
- } catch {
1672
- throw new DecodeError("decompression failed");
1673
- }
1674
- let rawOffers;
1675
- try {
1676
- rawOffers = JSON.parse(decoded);
1677
- } catch {
1678
- throw new DecodeError("JSON parse failed");
1679
- }
1680
- const tree = from$8(rawOffers.map((o) => OfferSchema().parse(o)));
1681
- if (root !== tree.root) throw new DecodeError(`root mismatch: expected ${tree.root}, got ${root}`);
1682
- return {
1683
- tree,
1684
- signature,
1685
- signer
1686
- };
1687
- };
1688
- /**
1689
- * Error thrown during tree building operations.
1690
- * Indicates structural issues with the tree (missing offers, inconsistent state).
1691
- */
1692
- var TreeError = class extends BaseError {
1693
- constructor(reason) {
1694
- super(`Tree error: ${reason}`);
1695
- _defineProperty(this, "name", "Tree.TreeError");
1696
- }
1697
- };
1698
- /**
1699
- * Error thrown during tree encoding.
1700
- * Indicates validation failures (signature, root mismatch, mixed makers).
1701
- */
1702
- var EncodeError = class extends BaseError {
1703
- constructor(reason) {
1704
- super(`Failed to encode tree: ${reason}`);
1705
- _defineProperty(this, "name", "Tree.EncodeError");
1706
- }
1707
- };
1708
- /**
1709
- * Error thrown during tree decoding.
1710
- * Indicates payload corruption, version mismatch, or validation failures.
1711
- */
1712
- var DecodeError = class extends BaseError {
1713
- constructor(reason) {
1714
- super(`Failed to decode tree: ${reason}`);
1715
- _defineProperty(this, "name", "Tree.DecodeError");
1716
- }
1717
- };
1718
-
1719
1532
  //#endregion
1720
1533
  //#region src/core/Offer.ts
1721
- var Offer_exports = /* @__PURE__ */ __export({
1722
- AccountNotSetError: () => AccountNotSetError,
1534
+ var Offer_exports = /* @__PURE__ */ __exportAll({
1723
1535
  InvalidOfferError: () => InvalidOfferError,
1724
1536
  OfferSchema: () => OfferSchema,
1725
1537
  Status: () => Status,
1726
1538
  consumedEvent: () => consumedEvent,
1727
- decode: () => decode,
1539
+ decode: () => decode$1,
1728
1540
  domain: () => domain,
1729
- encode: () => encode,
1730
- from: () => from$7,
1541
+ encode: () => encode$1,
1542
+ from: () => from$9,
1731
1543
  fromSnakeCase: () => fromSnakeCase$1,
1732
1544
  hash: () => hash,
1733
1545
  obligationId: () => obligationId,
1734
1546
  random: () => random$1,
1735
1547
  serialize: () => serialize,
1736
- sign: () => sign,
1737
- signatureMsg: () => signatureMsg,
1738
1548
  toSnakeCase: () => toSnakeCase,
1739
1549
  types: () => types
1740
1550
  });
1741
1551
  /** Internal symbol for caching the computed hash. */
1742
1552
  const HASH_CACHE = Symbol("offer.hash");
1743
- let Status = /* @__PURE__ */ function(Status$1) {
1744
- Status$1["VALID"] = "VALID";
1745
- Status$1["SIMULATION_ERROR"] = "SIMULATION_ERROR";
1746
- return Status$1;
1553
+ let Status = /* @__PURE__ */ function(Status) {
1554
+ Status["VALID"] = "VALID";
1555
+ Status["SIMULATION_ERROR"] = "SIMULATION_ERROR";
1556
+ return Status;
1747
1557
  }({});
1748
1558
  const OfferSchema = () => {
1749
1559
  return z$1.object({
@@ -1787,7 +1597,7 @@ const OfferSchema = () => {
1787
1597
  * @param input - The offer to create.
1788
1598
  * @returns The created offer.
1789
1599
  */
1790
- function from$7(input) {
1600
+ function from$9(input) {
1791
1601
  try {
1792
1602
  return OfferSchema().parse(input);
1793
1603
  } catch (error) {
@@ -1801,7 +1611,7 @@ function from$7(input) {
1801
1611
  * @returns The created offer.
1802
1612
  */
1803
1613
  function fromSnakeCase$1(input) {
1804
- return from$7(fromSnakeCase$3(input));
1614
+ return from$9(fromSnakeCase$3(input));
1805
1615
  }
1806
1616
  /**
1807
1617
  * Converts an offer to a snake case object.
@@ -1855,8 +1665,8 @@ function random$1(config) {
1855
1665
  const collateralCandidates = config?.collateralTokens ? config.collateralTokens.filter((a) => a !== loanToken) : [address()];
1856
1666
  const collateralAsset = collateralCandidates[int(collateralCandidates.length)];
1857
1667
  const maturityOption = weightedChoice([["end_of_month", 1], ["end_of_next_month", 1]]);
1858
- const maturity$1 = config?.maturity ?? from$10(maturityOption);
1859
- const lltv = from$12(weightedChoice([
1668
+ const maturity = config?.maturity ?? from$11(maturityOption);
1669
+ const lltv = from$13(weightedChoice([
1860
1670
  [.385, 1],
1861
1671
  [.5, 1],
1862
1672
  [.625, 2],
@@ -1895,15 +1705,15 @@ function random$1(config) {
1895
1705
  })
1896
1706
  };
1897
1707
  })();
1898
- return from$7({
1708
+ return from$9({
1899
1709
  maker: config?.maker ?? address(),
1900
1710
  assets: assetsScaled,
1901
1711
  obligationUnits: config?.obligationUnits ?? 0n,
1902
1712
  obligationShares: config?.obligationShares ?? 0n,
1903
1713
  price,
1904
- maturity: maturity$1,
1905
- expiry: config?.expiry ?? maturity$1 - 1,
1906
- start: config?.start ?? maturity$1 - 10,
1714
+ maturity,
1715
+ expiry: config?.expiry ?? maturity - 1,
1716
+ start: config?.start ?? maturity - 10,
1907
1717
  group: config?.group ?? hex(32),
1908
1718
  session: config?.session ?? hex(32),
1909
1719
  buy,
@@ -2023,23 +1833,6 @@ const types = {
2023
1833
  type: "bytes"
2024
1834
  }]
2025
1835
  };
2026
- /**
2027
- * Signs an array of offers.
2028
- * @throws {Error} If the wallet account is not set.
2029
- * @param offers - The offers to sign.
2030
- * @param wallet - The wallet to sign the offers with.
2031
- * @returns The signed offers.
2032
- */
2033
- async function sign(offers, wallet) {
2034
- if (!wallet.account) throw new AccountNotSetError();
2035
- return wallet.signMessage({
2036
- account: wallet.account,
2037
- message: { raw: signatureMsg(offers) }
2038
- });
2039
- }
2040
- function signatureMsg(offers) {
2041
- return from$8(offers).root;
2042
- }
2043
1836
  function hash(offer) {
2044
1837
  const cached = offer[HASH_CACHE];
2045
1838
  if (cached) return cached;
@@ -2076,7 +1869,7 @@ function hash(offer) {
2076
1869
  * @returns The obligation id as a 32-byte hex string.
2077
1870
  */
2078
1871
  function obligationId(offer) {
2079
- return id(from$9({
1872
+ return id(from$10({
2080
1873
  chainId: offer.chainId,
2081
1874
  loanToken: offer.loanToken,
2082
1875
  collaterals: offer.collaterals,
@@ -2166,7 +1959,7 @@ const OfferAbi = [
2166
1959
  }]
2167
1960
  }
2168
1961
  ];
2169
- function encode(offer) {
1962
+ function encode$1(offer) {
2170
1963
  return encodeAbiParameters(OfferAbi, [
2171
1964
  offer.maker,
2172
1965
  offer.assets,
@@ -2185,20 +1978,20 @@ function encode(offer) {
2185
1978
  offer.callback
2186
1979
  ]);
2187
1980
  }
2188
- function decode(data) {
1981
+ function decode$1(data) {
2189
1982
  let decoded;
2190
1983
  try {
2191
1984
  decoded = decodeAbiParameters(OfferAbi, data);
2192
1985
  } catch (error) {
2193
1986
  throw new InvalidOfferError(error);
2194
1987
  }
2195
- return from$7({
1988
+ return from$9({
2196
1989
  maker: decoded[0],
2197
1990
  assets: decoded[1],
2198
1991
  obligationUnits: decoded[2],
2199
1992
  obligationShares: decoded[3],
2200
1993
  price: decoded[4],
2201
- maturity: from$10(Number(decoded[5])),
1994
+ maturity: from$11(Number(decoded[5])),
2202
1995
  expiry: Number(decoded[6]),
2203
1996
  group: decoded[7],
2204
1997
  session: decoded[8],
@@ -2207,7 +2000,7 @@ function decode(data) {
2207
2000
  loanToken: decoded[11],
2208
2001
  start: Number(decoded[12]),
2209
2002
  collaterals: decoded[13].map((c) => {
2210
- return from$11({
2003
+ return from$12({
2211
2004
  asset: c.asset,
2212
2005
  oracle: c.oracle,
2213
2006
  lltv: c.lltv
@@ -2271,25 +2064,22 @@ var InvalidOfferError = class InvalidOfferError extends BaseError {
2271
2064
  return `Invalid offer. ${InvalidOfferError.formatDetails(this.cause)}`;
2272
2065
  }
2273
2066
  };
2274
- var AccountNotSetError = class extends BaseError {
2275
- constructor() {
2276
- super("Account not set.");
2277
- _defineProperty(this, "name", "Offer.AccountNotSetError");
2278
- }
2279
- };
2280
2067
 
2281
2068
  //#endregion
2282
2069
  //#region src/core/Oracle.ts
2283
- var Oracle_exports = /* @__PURE__ */ __export({
2070
+ var Oracle_exports = /* @__PURE__ */ __exportAll({
2284
2071
  Conversion: () => Conversion,
2285
- from: () => from$6
2072
+ from: () => from$8,
2073
+ fromCollateral: () => fromCollateral,
2074
+ fromOffer: () => fromOffer,
2075
+ fromOffers: () => fromOffers
2286
2076
  });
2287
2077
  /**
2288
2078
  * Create an Oracle from a plain object.
2289
2079
  * @param data - The data to create the oracle from.
2290
2080
  * @returns The created oracle.
2291
2081
  */
2292
- function from$6(data) {
2082
+ function from$8(data) {
2293
2083
  return {
2294
2084
  chainId: data.chainId,
2295
2085
  address: data.address.toLowerCase(),
@@ -2297,6 +2087,59 @@ function from$6(data) {
2297
2087
  blockNumber: data.blockNumber
2298
2088
  };
2299
2089
  }
2090
+ /**
2091
+ * Creates an oracle from a collateral.
2092
+ * @constructor
2093
+ *
2094
+ * @param parameters - {@link fromCollateral.Parameters}
2095
+ * @returns The created oracle. {@link fromCollateral.ReturnType}
2096
+ */
2097
+ function fromCollateral(parameters) {
2098
+ const { chainId, collateral, blockNumber, price = null } = parameters;
2099
+ return {
2100
+ chainId,
2101
+ address: collateral.oracle.toLowerCase(),
2102
+ price,
2103
+ blockNumber
2104
+ };
2105
+ }
2106
+ /**
2107
+ * Creates oracles from a single offer.
2108
+ * @constructor
2109
+ *
2110
+ * @param parameters - {@link fromOffer.Parameters}
2111
+ * @returns The created oracles. {@link fromOffer.ReturnType}
2112
+ */
2113
+ function fromOffer(parameters) {
2114
+ const { offer, blockNumber, price = null } = parameters;
2115
+ return fromOffers({
2116
+ offers: [offer],
2117
+ blockNumber,
2118
+ price
2119
+ });
2120
+ }
2121
+ /**
2122
+ * Creates oracles from a list of offers.
2123
+ * @constructor
2124
+ *
2125
+ * @param parameters - {@link fromOffers.Parameters}
2126
+ * @returns The created oracles. {@link fromOffers.ReturnType}
2127
+ */
2128
+ function fromOffers(parameters) {
2129
+ const { offers, blockNumber, price = null } = parameters;
2130
+ const rowsByKey = /* @__PURE__ */ new Map();
2131
+ for (const offer of offers) for (const collateral of offer.collaterals) {
2132
+ const key = `${offer.chainId}-${collateral.oracle}`.toLowerCase();
2133
+ if (rowsByKey.has(key)) continue;
2134
+ rowsByKey.set(key, fromCollateral({
2135
+ chainId: offer.chainId,
2136
+ collateral,
2137
+ blockNumber,
2138
+ price
2139
+ }));
2140
+ }
2141
+ return Array.from(rowsByKey.values());
2142
+ }
2300
2143
  let Conversion;
2301
2144
  (function(_Conversion) {
2302
2145
  function collateralToLoan(amount, params) {
@@ -2312,14 +2155,14 @@ let Conversion;
2312
2155
 
2313
2156
  //#endregion
2314
2157
  //#region src/core/Position.ts
2315
- var Position_exports = /* @__PURE__ */ __export({
2158
+ var Position_exports = /* @__PURE__ */ __exportAll({
2316
2159
  Type: () => Type,
2317
- from: () => from$5
2160
+ from: () => from$7
2318
2161
  });
2319
- let Type = /* @__PURE__ */ function(Type$1) {
2320
- Type$1["ERC20"] = "erc20";
2321
- Type$1["VAULT_V1"] = "vault_v1";
2322
- return Type$1;
2162
+ let Type = /* @__PURE__ */ function(Type) {
2163
+ Type["ERC20"] = "erc20";
2164
+ Type["VAULT_V1"] = "vault_v1";
2165
+ return Type;
2323
2166
  }({});
2324
2167
  /**
2325
2168
  * @constructor
@@ -2327,7 +2170,7 @@ let Type = /* @__PURE__ */ function(Type$1) {
2327
2170
  * @param parameters - {@link from.Parameters}
2328
2171
  * @returns The created Position. {@link from.ReturnType}
2329
2172
  */
2330
- function from$5(parameters) {
2173
+ function from$7(parameters) {
2331
2174
  return {
2332
2175
  chainId: parameters.chainId,
2333
2176
  contract: parameters.contract.toLowerCase(),
@@ -2341,10 +2184,10 @@ function from$5(parameters) {
2341
2184
 
2342
2185
  //#endregion
2343
2186
  //#region src/core/Quote.ts
2344
- var Quote_exports = /* @__PURE__ */ __export({
2187
+ var Quote_exports = /* @__PURE__ */ __exportAll({
2345
2188
  InvalidQuoteError: () => InvalidQuoteError,
2346
2189
  QuoteSchema: () => QuoteSchema,
2347
- from: () => from$4,
2190
+ from: () => from$6,
2348
2191
  fromSnakeCase: () => fromSnakeCase,
2349
2192
  random: () => random
2350
2193
  });
@@ -2365,7 +2208,7 @@ const QuoteSchema = z$1.object({
2365
2208
  * const quote = Quote.from({ obligationId: "0x123", ask: { price: 100n }, bid: { price: 100n } });
2366
2209
  * ```
2367
2210
  */
2368
- function from$4(parameters) {
2211
+ function from$6(parameters) {
2369
2212
  try {
2370
2213
  const parsedQuote = QuoteSchema.parse(parameters);
2371
2214
  return {
@@ -2384,57 +2227,537 @@ function from$4(parameters) {
2384
2227
  * @returns The created quote. {@link fromSnakeCase.ReturnType}
2385
2228
  */
2386
2229
  function fromSnakeCase(snake) {
2387
- return from$4(fromSnakeCase$3(snake));
2230
+ return from$6(fromSnakeCase$3(snake));
2231
+ }
2232
+ /**
2233
+ * Generates a random quote.
2234
+ * @returns A randomly generated quote. {@link random.ReturnType}
2235
+ *
2236
+ * @example
2237
+ * ```ts
2238
+ * const quote = Quote.random();
2239
+ * ```
2240
+ */
2241
+ function random() {
2242
+ return from$6({
2243
+ obligationId: id(random$2()),
2244
+ ask: { price: BigInt(int(1e6)) },
2245
+ bid: { price: BigInt(int(1e6)) }
2246
+ });
2247
+ }
2248
+ var InvalidQuoteError = class extends BaseError {
2249
+ constructor(error) {
2250
+ super("Invalid quote.", { cause: error });
2251
+ _defineProperty(this, "name", "Quote.InvalidQuoteError");
2252
+ }
2253
+ };
2254
+
2255
+ //#endregion
2256
+ //#region src/core/TradingFee.ts
2257
+ var TradingFee_exports = /* @__PURE__ */ __exportAll({
2258
+ BREAKPOINTS: () => BREAKPOINTS,
2259
+ InvalidFeeError: () => InvalidFeeError,
2260
+ InvalidFeesLengthError: () => InvalidFeesLengthError,
2261
+ WAD: () => WAD,
2262
+ activate: () => activate,
2263
+ compute: () => compute,
2264
+ deactivate: () => deactivate,
2265
+ from: () => from$5,
2266
+ getFees: () => getFees,
2267
+ isActivated: () => isActivated
2268
+ });
2269
+ /**
2270
+ * Time breakpoints in seconds for piecewise linear fee interpolation.
2271
+ * Matches on-chain constants: 0d, 1d, 7d, 30d, 90d, 180d.
2272
+ */
2273
+ const BREAKPOINTS = [
2274
+ 0n,
2275
+ 86400n,
2276
+ 604800n,
2277
+ 2592000n,
2278
+ 7776000n,
2279
+ 15552000n
2280
+ ];
2281
+ /** WAD constant (1e18) for fee scaling. */
2282
+ const WAD = 10n ** 18n;
2283
+ /**
2284
+ * Create a TradingFee from an activation flag and 6 fee values.
2285
+ * @param activated - Whether the fee is active.
2286
+ * @param fees - Tuple of 6 fee values in WAD (one per breakpoint: 0d, 1d, 7d, 30d, 90d, 180d).
2287
+ * @returns A new TradingFee instance.
2288
+ * @throws {@link InvalidFeeError} if any fee exceeds WAD (100%).
2289
+ * @throws {@link InvalidFeesLengthError} if fees array doesn't have exactly 6 elements.
2290
+ */
2291
+ function from$5(activated, fees) {
2292
+ if (fees.length !== 6) throw new InvalidFeesLengthError(fees.length);
2293
+ for (let i = 0; i < 6; i++) {
2294
+ const fee = fees[i];
2295
+ if (fee < 0n || fee > WAD) throw new InvalidFeeError(fee, i);
2296
+ }
2297
+ const frozenFees = Object.freeze([...fees]);
2298
+ return Object.freeze({
2299
+ _activated: activated,
2300
+ _fees: frozenFees
2301
+ });
2302
+ }
2303
+ /**
2304
+ * Compute the trading fee for a given time to maturity using piecewise linear interpolation.
2305
+ * @param tradingFee - The TradingFee instance.
2306
+ * @param timeToMaturity - Time to maturity in seconds.
2307
+ * @returns The interpolated fee in WAD. Returns 0n if not activated.
2308
+ */
2309
+ function compute(tradingFee, timeToMaturity) {
2310
+ if (!tradingFee._activated) return 0n;
2311
+ const time = BigInt(Math.max(0, Math.floor(timeToMaturity)));
2312
+ if (time >= BREAKPOINTS[5]) return tradingFee._fees[5];
2313
+ const { index, start, end } = getSegment(time);
2314
+ const feeLower = tradingFee._fees[index];
2315
+ const feeUpper = tradingFee._fees[index + 1];
2316
+ const segmentLength = end - start;
2317
+ return (feeLower * (end - time) + feeUpper * (time - start)) / segmentLength;
2318
+ }
2319
+ /**
2320
+ * Check if the trading fee is activated.
2321
+ * @param tradingFee - The TradingFee instance.
2322
+ * @returns True if activated, false otherwise.
2323
+ */
2324
+ function isActivated(tradingFee) {
2325
+ return tradingFee._activated;
2326
+ }
2327
+ /**
2328
+ * Create a new TradingFee with activation enabled.
2329
+ * @param tradingFee - The TradingFee instance.
2330
+ * @returns A new TradingFee with activated set to true.
2331
+ */
2332
+ function activate(tradingFee) {
2333
+ return Object.freeze({
2334
+ _activated: true,
2335
+ _fees: tradingFee._fees
2336
+ });
2337
+ }
2338
+ /**
2339
+ * Create a new TradingFee with activation disabled.
2340
+ * @param tradingFee - The TradingFee instance.
2341
+ * @returns A new TradingFee with activated set to false.
2342
+ */
2343
+ function deactivate(tradingFee) {
2344
+ return Object.freeze({
2345
+ _activated: false,
2346
+ _fees: tradingFee._fees
2347
+ });
2348
+ }
2349
+ /**
2350
+ * Get the fee values at each breakpoint.
2351
+ * @param tradingFee - The TradingFee instance.
2352
+ * @returns The tuple of 6 fee values.
2353
+ */
2354
+ function getFees(tradingFee) {
2355
+ return tradingFee._fees;
2356
+ }
2357
+ /**
2358
+ * Determine which segment a timeToMaturity falls into for interpolation.
2359
+ * @param timeToMaturity - Time to maturity in seconds.
2360
+ * @returns Object with index, start, and end of the segment.
2361
+ */
2362
+ function getSegment(timeToMaturity) {
2363
+ if (timeToMaturity < BREAKPOINTS[1]) return {
2364
+ index: 0,
2365
+ start: BREAKPOINTS[0],
2366
+ end: BREAKPOINTS[1]
2367
+ };
2368
+ if (timeToMaturity < BREAKPOINTS[2]) return {
2369
+ index: 1,
2370
+ start: BREAKPOINTS[1],
2371
+ end: BREAKPOINTS[2]
2372
+ };
2373
+ if (timeToMaturity < BREAKPOINTS[3]) return {
2374
+ index: 2,
2375
+ start: BREAKPOINTS[2],
2376
+ end: BREAKPOINTS[3]
2377
+ };
2378
+ if (timeToMaturity < BREAKPOINTS[4]) return {
2379
+ index: 3,
2380
+ start: BREAKPOINTS[3],
2381
+ end: BREAKPOINTS[4]
2382
+ };
2383
+ return {
2384
+ index: 4,
2385
+ start: BREAKPOINTS[4],
2386
+ end: BREAKPOINTS[5]
2387
+ };
2388
+ }
2389
+ /** Error thrown when a fee value is invalid (negative or exceeds WAD). */
2390
+ var InvalidFeeError = class extends BaseError {
2391
+ constructor(fee, index) {
2392
+ super(`Invalid fee at index ${index}: ${fee}. Fee must be between 0 and ${WAD} (WAD).`);
2393
+ _defineProperty(this, "name", "TradingFee.InvalidFeeError");
2394
+ }
2395
+ };
2396
+ /** Error thrown when fees array doesn't have exactly 6 elements. */
2397
+ var InvalidFeesLengthError = class extends BaseError {
2398
+ constructor(length) {
2399
+ super(`Invalid fees length: ${length}. Expected exactly 6 fee values.`);
2400
+ _defineProperty(this, "name", "TradingFee.InvalidFeesLengthError");
2401
+ }
2402
+ };
2403
+
2404
+ //#endregion
2405
+ //#region src/core/Transfer.ts
2406
+ var Transfer_exports = /* @__PURE__ */ __exportAll({ from: () => from$4 });
2407
+ /**
2408
+ * @constructor
2409
+ *
2410
+ * Creates a {@link Transfer}.
2411
+ * @param parameters - {@link from.Parameters}
2412
+ * @returns The created Transfer. {@link from.ReturnType}
2413
+ *
2414
+ * @example
2415
+ * ```ts
2416
+ * const transfer = Transfer.from({ id: "1", chainId: 1, contract: "0x123", from: "0x456", to: "0x789", value: 100n, blockNumber: 100n });
2417
+ * ```
2418
+ */
2419
+ function from$4(parameters) {
2420
+ return {
2421
+ id: parameters.id,
2422
+ chainId: parameters.chainId,
2423
+ contract: parameters.contract.toLowerCase(),
2424
+ from: parameters.from.toLowerCase(),
2425
+ to: parameters.to.toLowerCase(),
2426
+ value: parameters.value,
2427
+ blockNumber: parameters.blockNumber
2428
+ };
2388
2429
  }
2430
+
2431
+ //#endregion
2432
+ //#region src/core/Tree.ts
2433
+ var Tree_exports = /* @__PURE__ */ __exportAll({
2434
+ DecodeError: () => DecodeError,
2435
+ EncodeError: () => EncodeError,
2436
+ SignatureDomainError: () => SignatureDomainError,
2437
+ TreeError: () => TreeError,
2438
+ VERSION: () => VERSION,
2439
+ decode: () => decode,
2440
+ encode: () => encode,
2441
+ encodeUnsigned: () => encodeUnsigned,
2442
+ from: () => from$3,
2443
+ proofs: () => proofs,
2444
+ signatureDomain: () => signatureDomain,
2445
+ signatureTypes: () => signatureTypes
2446
+ });
2447
+ const VERSION = 1;
2448
+ /**
2449
+ * EIP-712 types for signing the tree root (Root(bytes32 root)).
2450
+ */
2451
+ const signatureTypes = {
2452
+ EIP712Domain: [{
2453
+ name: "chainId",
2454
+ type: "uint256"
2455
+ }, {
2456
+ name: "verifyingContract",
2457
+ type: "address"
2458
+ }],
2459
+ Root: [{
2460
+ name: "root",
2461
+ type: "bytes32"
2462
+ }]
2463
+ };
2464
+ const normalizeHash = (hash) => hash.toLowerCase();
2465
+ /**
2466
+ * Builds a Merkle tree from a list of offers.
2467
+ *
2468
+ * Leaves are the offer `hash` values as `bytes32` and are deterministically
2469
+ * ordered following the StandardMerkleTree leaf ordering so that the resulting
2470
+ * root is stable regardless of the input order.
2471
+ *
2472
+ * @param offers - Offers to include in the tree.
2473
+ * @returns A `StandardMerkleTree` of `bytes32` leaves representing the offers.
2474
+ * @throws {TreeError} If tree building fails due to offer inconsistencies.
2475
+ */
2476
+ const from$3 = (offers) => {
2477
+ const leaves = offers.map((offer) => [hash(offer)]);
2478
+ const tree = StandardMerkleTree.of(leaves, ["bytes32"]);
2479
+ const orderedOffers = orderOffers(tree, offers);
2480
+ return Object.assign(tree, { offers: orderedOffers });
2481
+ };
2482
+ const orderOffers = (tree, offers) => {
2483
+ const offerByHash = /* @__PURE__ */ new Map();
2484
+ for (const offer of offers) offerByHash.set(normalizeHash(hash(offer)), offer);
2485
+ const entries = tree.dump().values.map((value) => {
2486
+ const hash = normalizeHash(value.value[0]);
2487
+ const offer = offerByHash.get(hash);
2488
+ if (!offer) throw new TreeError(`missing offer for leaf ${hash}`);
2489
+ return {
2490
+ offer,
2491
+ treeIndex: value.treeIndex
2492
+ };
2493
+ });
2494
+ entries.sort((a, b) => b.treeIndex - a.treeIndex);
2495
+ return entries.map((item) => item.offer);
2496
+ };
2497
+ /**
2498
+ * Generates merkle proofs for all offers in a tree.
2499
+ *
2500
+ * Each proof allows independent verification that an offer is included in the tree
2501
+ * without requiring the full tree. Proofs are ordered by StandardMerkleTree leaf ordering.
2502
+ *
2503
+ * @param tree - The {@link Tree} to generate proofs for.
2504
+ * @returns Array of proofs - {@link Proof}
2505
+ */
2506
+ const proofs = (tree) => {
2507
+ return tree.offers.map((offer) => {
2508
+ return {
2509
+ offer,
2510
+ path: tree.getProof([hash(offer)])
2511
+ };
2512
+ });
2513
+ };
2514
+ /**
2515
+ * Normalizes a Root signature domain (BigInt chain id, lowercase address).
2516
+ * @throws {SignatureDomainError} When the domain is invalid.
2517
+ */
2518
+ const signatureDomain = (domain) => {
2519
+ return normalizeSignatureDomain(domain, (reason) => new SignatureDomainError(reason));
2520
+ };
2521
+ const normalizeSignatureDomain = (domain, errorFactory) => {
2522
+ let chainId;
2523
+ try {
2524
+ chainId = typeof domain.chainId === "bigint" ? domain.chainId : BigInt(domain.chainId);
2525
+ } catch {
2526
+ throw errorFactory("invalid chainId");
2527
+ }
2528
+ if (chainId < 0n) throw errorFactory("invalid chainId");
2529
+ if (!isAddress(domain.verifyingContract)) throw errorFactory("invalid verifyingContract");
2530
+ return {
2531
+ chainId,
2532
+ verifyingContract: domain.verifyingContract.toLowerCase()
2533
+ };
2534
+ };
2535
+ const assertHex = (value, expectedBytes, name, errorFactory = (reason) => new DecodeError(reason)) => {
2536
+ if (typeof value !== "string" || !isHex(value)) throw errorFactory(`${name} is not a valid hex string`);
2537
+ if (hexToBytes(value).length !== expectedBytes) throw errorFactory(`${name}: expected ${expectedBytes} bytes`);
2538
+ };
2539
+ const verifySignatureAndRecoverAddress = async (params) => {
2540
+ const { root, signature, domain, errorFactory } = params;
2541
+ assertHex(root, 32, "root", errorFactory);
2542
+ assertHex(signature, 65, "signature", errorFactory);
2543
+ const hash = hashTypedData({
2544
+ domain,
2545
+ types: signatureTypes,
2546
+ primaryType: "Root",
2547
+ message: { root }
2548
+ });
2549
+ try {
2550
+ return await recoverAddress({
2551
+ hash,
2552
+ signature
2553
+ });
2554
+ } catch {
2555
+ throw errorFactory("signature recovery failed");
2556
+ }
2557
+ };
2558
+ /**
2559
+ * Encodes a merkle tree with signature into hex calldata for onchain broadcast.
2560
+ *
2561
+ * Layout: `0x{vv}{gzip([...offers])}{root}{signature}` where:
2562
+ * - `{vv}`: 1-byte version (currently 0x01)
2563
+ * - `{gzip([...offers])}`: gzipped JSON array of serialized offers
2564
+ * - `{root}`: 32-byte merkle root
2565
+ * - `{signature}`: 65-byte EIP-712 signature over Root(bytes32 root)
2566
+ *
2567
+ * Validates signature authenticity and root integrity before encoding.
2568
+ *
2569
+ * @example
2570
+ * ```typescript
2571
+ * const tree = Tree.from(offers);
2572
+ * const signature = await wallet.signTypedData({
2573
+ * account: wallet.account,
2574
+ * domain: Tree.signatureDomain({ chainId, verifyingContract }),
2575
+ * types: Tree.signatureTypes,
2576
+ * primaryType: "Root",
2577
+ * message: { root: tree.root },
2578
+ * });
2579
+ * const calldata = await Tree.encode(tree, signature, { chainId, verifyingContract });
2580
+ * await broadcast(calldata);
2581
+ * ```
2582
+ *
2583
+ * @example
2584
+ * Manual construction (for advanced users):
2585
+ * ```typescript
2586
+ * const tree = Tree.from(offers);
2587
+ * const compressed = gzip(JSON.stringify(tree.offers.map(Offer.serialize)));
2588
+ * const partial = `0x01${bytesToHex(compressed)}${tree.root.slice(2)}`;
2589
+ * const signature = await wallet.signTypedData({
2590
+ * account: wallet.account,
2591
+ * domain: Tree.signatureDomain({ chainId, verifyingContract }),
2592
+ * types: Tree.signatureTypes,
2593
+ * primaryType: "Root",
2594
+ * message: { root: tree.root },
2595
+ * });
2596
+ * const calldata = `${partial}${signature.slice(2)}`;
2597
+ * ```
2598
+ *
2599
+ * @param tree - Merkle tree of offers
2600
+ * @param signature - EIP-712 signature over Root(bytes32 root)
2601
+ * @param domain - EIP-712 domain with chain id and verifying contract
2602
+ * @returns Hex-encoded calldata ready for onchain broadcast
2603
+ * @throws {EncodeError} If signature verification fails or root mismatch
2604
+ */
2605
+ const encode = async (tree, signature, domain) => {
2606
+ const errorFactory = (reason) => new EncodeError(reason);
2607
+ const normalizedDomain = normalizeSignatureDomain(domain, errorFactory);
2608
+ validateTreeForEncoding(tree, normalizedDomain);
2609
+ await verifySignatureAndRecoverAddress({
2610
+ root: tree.root,
2611
+ signature,
2612
+ domain: normalizedDomain,
2613
+ errorFactory
2614
+ });
2615
+ const unsigned = encodeUnsignedBytes(tree);
2616
+ const sigBytes = hexToBytes(signature);
2617
+ const encoded = new Uint8Array(unsigned.length + sigBytes.length);
2618
+ encoded.set(unsigned, 0);
2619
+ encoded.set(sigBytes, unsigned.length);
2620
+ return bytesToHex(encoded);
2621
+ };
2622
+ /**
2623
+ * Encodes a merkle tree without a signature into hex payload for client-side signing.
2624
+ *
2625
+ * Layout: `0x{vv}{gzip([...offers])}{root}` where:
2626
+ * - `{vv}`: 1-byte version (currently 0x01)
2627
+ * - `{gzip([...offers])}`: gzipped JSON array of serialized offers
2628
+ * - `{root}`: 32-byte merkle root
2629
+ *
2630
+ * Validates root integrity before encoding.
2631
+ *
2632
+ * @param tree - Merkle tree of offers
2633
+ * @returns Hex-encoded unsigned payload
2634
+ * @throws {EncodeError} If root mismatch
2635
+ */
2636
+ const encodeUnsigned = (tree) => {
2637
+ validateTreeForEncoding(tree);
2638
+ return bytesToHex(encodeUnsignedBytes(tree));
2639
+ };
2640
+ const validateTreeForEncoding = (tree, domain) => {
2641
+ if (VERSION > 255) throw new EncodeError(`version overflow: ${VERSION} exceeds 255`);
2642
+ const computed = from$3(tree.offers);
2643
+ if (tree.root !== computed.root) throw new EncodeError(`root mismatch: expected ${computed.root}, got ${tree.root}`);
2644
+ if (domain) {
2645
+ const mismatched = tree.offers.find((offer) => BigInt(offer.chainId) !== domain.chainId);
2646
+ if (mismatched) throw new EncodeError(`chainId mismatch: expected ${domain.chainId}, got ${mismatched.chainId}`);
2647
+ }
2648
+ };
2649
+ const encodeUnsignedBytes = (tree) => {
2650
+ const offersPayload = tree.offers.map(serialize);
2651
+ const compressed = gzip(JSON.stringify(offersPayload));
2652
+ const rootBytes = hexToBytes(tree.root);
2653
+ const encoded = new Uint8Array(1 + compressed.length + 32);
2654
+ encoded[0] = VERSION;
2655
+ encoded.set(compressed, 1);
2656
+ encoded.set(rootBytes, 1 + compressed.length);
2657
+ return encoded;
2658
+ };
2659
+ /**
2660
+ * Decodes hex calldata into a validated merkle tree.
2661
+ *
2662
+ * Validates signature before decompression for fail-fast rejection of invalid payloads.
2663
+ * Returns the tree with separately validated signature and recovered signer address.
2664
+ *
2665
+ * Validation order:
2666
+ * 1. Version check
2667
+ * 2. Signature verification (fail-fast, before decompression)
2668
+ * 3. Decompression (only if signature valid)
2669
+ * 4. Root verification (computed from offers vs embedded root)
2670
+ *
2671
+ * @example
2672
+ * ```typescript
2673
+ * const { tree, signature, signer } = await Tree.decode(calldata, { chainId, verifyingContract });
2674
+ * console.log(`Tree signed by ${signer} with ${tree.offers.length} offers`);
2675
+ * ```
2676
+ *
2677
+ * @param encoded - Hex calldata in format `0x{vv}{gzip}{root}{signature}`
2678
+ * @param domain - EIP-712 domain with chain id and verifying contract
2679
+ * @returns Validated tree, signature, and recovered signer address
2680
+ * @throws {DecodeError} If version invalid, signature invalid, or root mismatch
2681
+ */
2682
+ const decode = async (encoded, domain) => {
2683
+ const errorFactory = (reason) => new DecodeError(reason);
2684
+ const normalizedDomain = normalizeSignatureDomain(domain, errorFactory);
2685
+ const bytes = hexToBytes(encoded);
2686
+ if (bytes.length < 98) throw new DecodeError("payload too short");
2687
+ const version = bytes[0];
2688
+ if (version !== (VERSION & 255)) throw new DecodeError(`invalid version: expected ${VERSION}, got ${version ?? 0}`);
2689
+ const signature = bytesToHex(bytes.slice(-65));
2690
+ const root = bytesToHex(bytes.slice(-97, -65));
2691
+ assertHex(root, 32, "root");
2692
+ assertHex(signature, 65, "signature");
2693
+ const signer = await verifySignatureAndRecoverAddress({
2694
+ root,
2695
+ signature,
2696
+ domain: normalizedDomain,
2697
+ errorFactory
2698
+ });
2699
+ const compressed = bytes.slice(1, -97);
2700
+ let decoded;
2701
+ try {
2702
+ decoded = ungzip(compressed, { to: "string" });
2703
+ } catch {
2704
+ throw new DecodeError("decompression failed");
2705
+ }
2706
+ let rawOffers;
2707
+ try {
2708
+ rawOffers = JSON.parse(decoded);
2709
+ } catch {
2710
+ throw new DecodeError("JSON parse failed");
2711
+ }
2712
+ const tree = from$3(rawOffers.map((o) => OfferSchema().parse(o)));
2713
+ if (root !== tree.root) throw new DecodeError(`root mismatch: expected ${tree.root}, got ${root}`);
2714
+ const chainIdMismatch = tree.offers.find((offer) => BigInt(offer.chainId) !== normalizedDomain.chainId);
2715
+ if (chainIdMismatch) throw new DecodeError(`chainId mismatch: expected ${normalizedDomain.chainId}, got ${chainIdMismatch.chainId}`);
2716
+ return {
2717
+ tree,
2718
+ signature,
2719
+ signer
2720
+ };
2721
+ };
2722
+ /**
2723
+ * Error thrown during tree building operations.
2724
+ * Indicates structural issues with the tree (missing offers, inconsistent state).
2725
+ */
2726
+ var TreeError = class extends BaseError {
2727
+ constructor(reason) {
2728
+ super(`Tree error: ${reason}`);
2729
+ _defineProperty(this, "name", "Tree.TreeError");
2730
+ }
2731
+ };
2732
+ /**
2733
+ * Error thrown during tree encoding.
2734
+ * Indicates validation failures (signature, root mismatch, mixed makers).
2735
+ */
2736
+ var EncodeError = class extends BaseError {
2737
+ constructor(reason) {
2738
+ super(`Failed to encode tree: ${reason}`);
2739
+ _defineProperty(this, "name", "Tree.EncodeError");
2740
+ }
2741
+ };
2389
2742
  /**
2390
- * Generates a random quote.
2391
- * @returns A randomly generated quote. {@link random.ReturnType}
2392
- *
2393
- * @example
2394
- * ```ts
2395
- * const quote = Quote.random();
2396
- * ```
2743
+ * Error thrown during tree decoding.
2744
+ * Indicates payload corruption, version mismatch, or validation failures.
2397
2745
  */
2398
- function random() {
2399
- return from$4({
2400
- obligationId: id(random$2()),
2401
- ask: { price: BigInt(int(1e6)) },
2402
- bid: { price: BigInt(int(1e6)) }
2403
- });
2404
- }
2405
- var InvalidQuoteError = class extends BaseError {
2406
- constructor(error) {
2407
- super("Invalid quote.", { cause: error });
2408
- _defineProperty(this, "name", "Quote.InvalidQuoteError");
2746
+ var DecodeError = class extends BaseError {
2747
+ constructor(reason) {
2748
+ super(`Failed to decode tree: ${reason}`);
2749
+ _defineProperty(this, "name", "Tree.DecodeError");
2409
2750
  }
2410
2751
  };
2411
-
2412
- //#endregion
2413
- //#region src/core/Transfer.ts
2414
- var Transfer_exports = /* @__PURE__ */ __export({ from: () => from$3 });
2415
2752
  /**
2416
- * @constructor
2417
- *
2418
- * Creates a {@link Transfer}.
2419
- * @param parameters - {@link from.Parameters}
2420
- * @returns The created Transfer. {@link from.ReturnType}
2421
- *
2422
- * @example
2423
- * ```ts
2424
- * const transfer = Transfer.from({ id: "1", chainId: 1, contract: "0x123", from: "0x456", to: "0x789", value: 100n, blockNumber: 100n });
2425
- * ```
2753
+ * Error thrown when an invalid signature domain is supplied.
2426
2754
  */
2427
- function from$3(parameters) {
2428
- return {
2429
- id: parameters.id,
2430
- chainId: parameters.chainId,
2431
- contract: parameters.contract.toLowerCase(),
2432
- from: parameters.from.toLowerCase(),
2433
- to: parameters.to.toLowerCase(),
2434
- value: parameters.value,
2435
- blockNumber: parameters.blockNumber
2436
- };
2437
- }
2755
+ var SignatureDomainError = class extends BaseError {
2756
+ constructor(reason) {
2757
+ super(`Invalid signature domain: ${reason}`);
2758
+ _defineProperty(this, "name", "Tree.SignatureDomainError");
2759
+ }
2760
+ };
2438
2761
 
2439
2762
  //#endregion
2440
2763
  //#region src/core/types.ts
@@ -2442,7 +2765,7 @@ const BrandTypeId = Symbol.for("mempool/Brand");
2442
2765
 
2443
2766
  //#endregion
2444
2767
  //#region src/api/Schema/OfferResponse.ts
2445
- var OfferResponse_exports = /* @__PURE__ */ __export({ from: () => from$2 });
2768
+ var OfferResponse_exports = /* @__PURE__ */ __exportAll({ from: () => from$2 });
2446
2769
  /**
2447
2770
  * Creates an `OfferResponse` matching the Solidity Offer struct layout.
2448
2771
  * @constructor
@@ -2450,7 +2773,7 @@ var OfferResponse_exports = /* @__PURE__ */ __export({ from: () => from$2 });
2450
2773
  * @returns The created `OfferResponse`. {@link OfferResponse}
2451
2774
  */
2452
2775
  function from$2(input) {
2453
- const base$1 = {
2776
+ const base = {
2454
2777
  offer: {
2455
2778
  obligation: {
2456
2779
  loan_token: input.loanToken,
@@ -2487,13 +2810,13 @@ function from$2(input) {
2487
2810
  block_number: input.blockNumber
2488
2811
  };
2489
2812
  if (!input.proof || !input.root || !input.signature) return {
2490
- ...base$1,
2813
+ ...base,
2491
2814
  root: null,
2492
2815
  proof: null,
2493
2816
  signature: null
2494
2817
  };
2495
2818
  return {
2496
- ...base$1,
2819
+ ...base,
2497
2820
  root: input.root.toLowerCase(),
2498
2821
  proof: input.proof.map((p) => p.toLowerCase()),
2499
2822
  signature: input.signature.toLowerCase()
@@ -2510,7 +2833,7 @@ const API_ERROR_CODES = [
2510
2833
  ];
2511
2834
 
2512
2835
  //#endregion
2513
- //#region \0@oxc-project+runtime@0.97.0/helpers/decorate.js
2836
+ //#region \0@oxc-project+runtime@0.110.0/helpers/decorate.js
2514
2837
  function __decorate(decorators, target, key, desc) {
2515
2838
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2516
2839
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -2601,6 +2924,21 @@ const validateOfferExample = {
2601
2924
  data: "0x00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000100000000000000000000000034cf890db685fc536e05652fb41f02090c3fb751000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000108e644e3ab01184155270aa92a00000000000"
2602
2925
  }
2603
2926
  };
2927
+ const callbackTypesRequestExample = { callbacks: [{
2928
+ chain_id: 1,
2929
+ addresses: [
2930
+ "0x1111111111111111111111111111111111111111",
2931
+ "0x3333333333333333333333333333333333333333",
2932
+ "0x9999999999999999999999999999999999999999"
2933
+ ]
2934
+ }] };
2935
+ const callbackTypesResponseExample = [{
2936
+ chain_id: 1,
2937
+ sell_erc20_callback: ["0x1111111111111111111111111111111111111111"],
2938
+ buy_erc20: ["0x5555555555555555555555555555555555555555"],
2939
+ buy_vault_v1_callback: ["0x3333333333333333333333333333333333333333"],
2940
+ not_supported: ["0x9999999999999999999999999999999999999999"]
2941
+ }];
2604
2942
  const routerStatusExample = {
2605
2943
  status: "live",
2606
2944
  initialized: true,
@@ -2669,6 +3007,55 @@ __decorate([ApiProperty({
2669
3007
  type: "string",
2670
3008
  example: validateOfferExample.callback.data
2671
3009
  })], ValidateCallbackRequest.prototype, "data", void 0);
3010
+ var CallbackTypesChainRequest = class {};
3011
+ __decorate([ApiProperty({
3012
+ type: "number",
3013
+ example: callbackTypesRequestExample.callbacks[0].chain_id
3014
+ })], CallbackTypesChainRequest.prototype, "chain_id", void 0);
3015
+ __decorate([ApiProperty({
3016
+ type: () => [String],
3017
+ example: callbackTypesRequestExample.callbacks[0].addresses
3018
+ })], CallbackTypesChainRequest.prototype, "addresses", void 0);
3019
+ var CallbackTypesRequest = class {};
3020
+ __decorate([ApiProperty({
3021
+ type: () => [CallbackTypesChainRequest],
3022
+ example: callbackTypesRequestExample.callbacks
3023
+ })], CallbackTypesRequest.prototype, "callbacks", void 0);
3024
+ var CallbackTypesChainResponse = class {};
3025
+ __decorate([ApiProperty({
3026
+ type: "number",
3027
+ example: callbackTypesResponseExample[0].chain_id
3028
+ })], CallbackTypesChainResponse.prototype, "chain_id", void 0);
3029
+ __decorate([ApiProperty({
3030
+ type: () => [String],
3031
+ required: false,
3032
+ example: callbackTypesResponseExample[0].buy_vault_v1_callback
3033
+ })], CallbackTypesChainResponse.prototype, "buy_vault_v1_callback", void 0);
3034
+ __decorate([ApiProperty({
3035
+ type: () => [String],
3036
+ required: false,
3037
+ example: callbackTypesResponseExample[0].sell_erc20_callback
3038
+ })], CallbackTypesChainResponse.prototype, "sell_erc20_callback", void 0);
3039
+ __decorate([ApiProperty({
3040
+ type: () => [String],
3041
+ required: false,
3042
+ example: callbackTypesResponseExample[0].buy_erc20
3043
+ })], CallbackTypesChainResponse.prototype, "buy_erc20", void 0);
3044
+ __decorate([ApiProperty({
3045
+ type: () => [String],
3046
+ example: callbackTypesResponseExample[0].not_supported
3047
+ })], CallbackTypesChainResponse.prototype, "not_supported", void 0);
3048
+ var CallbackTypesSuccessResponse = class extends SuccessResponse {};
3049
+ __decorate([ApiProperty({
3050
+ type: "string",
3051
+ nullable: true,
3052
+ example: "maturity:1:1730415600:end_of_next_month"
3053
+ })], CallbackTypesSuccessResponse.prototype, "cursor", void 0);
3054
+ __decorate([ApiProperty({
3055
+ type: () => [CallbackTypesChainResponse],
3056
+ description: "Callback types grouped by chain.",
3057
+ example: callbackTypesResponseExample
3058
+ })], CallbackTypesSuccessResponse.prototype, "data", void 0);
2672
3059
  var AskResponse = class {};
2673
3060
  __decorate([ApiProperty({
2674
3061
  type: "string",
@@ -3131,7 +3518,7 @@ __decorate([ApiProperty({
3131
3518
  type: () => [BookLevelResponse],
3132
3519
  description: "Aggregated book levels grouped by computed price."
3133
3520
  })], BookListResponse.prototype, "data", void 0);
3134
- let BooksController = class BooksController$1 {
3521
+ let BooksController = class BooksController {
3135
3522
  async getBook() {}
3136
3523
  };
3137
3524
  __decorate([
@@ -3177,7 +3564,7 @@ BooksController = __decorate([ApiTags("Markets"), ApiResponse({
3177
3564
  description: "Bad Request",
3178
3565
  type: BadRequestResponse
3179
3566
  })], BooksController);
3180
- let ValidateController = class ValidateController$1 {
3567
+ let ValidateController = class ValidateController {
3181
3568
  async validateOffers() {}
3182
3569
  };
3183
3570
  __decorate([
@@ -3204,7 +3591,29 @@ ValidateController = __decorate([ApiTags("Make"), ApiResponse({
3204
3591
  description: "Bad Request",
3205
3592
  type: BadRequestResponse
3206
3593
  })], ValidateController);
3207
- let OffersController = class OffersController$1 {
3594
+ let CallbacksController = class CallbacksController {
3595
+ async resolveCallbackTypes() {}
3596
+ };
3597
+ __decorate([
3598
+ ApiOperation({
3599
+ methods: ["post"],
3600
+ path: "/v1/callbacks",
3601
+ summary: "Resolve callback types",
3602
+ description: "Returns callback types for callback addresses grouped by chain."
3603
+ }),
3604
+ ApiBody({ type: CallbackTypesRequest }),
3605
+ ApiResponse({
3606
+ status: 200,
3607
+ description: "Success",
3608
+ type: CallbackTypesSuccessResponse
3609
+ })
3610
+ ], CallbacksController.prototype, "resolveCallbackTypes", null);
3611
+ CallbacksController = __decorate([ApiTags("Make"), ApiResponse({
3612
+ status: 400,
3613
+ description: "Bad Request",
3614
+ type: BadRequestResponse
3615
+ })], CallbacksController);
3616
+ let OffersController = class OffersController {
3208
3617
  async getOffers() {}
3209
3618
  };
3210
3619
  __decorate([
@@ -3259,7 +3668,7 @@ OffersController = __decorate([ApiTags("Markets"), ApiResponse({
3259
3668
  description: "Bad Request",
3260
3669
  type: BadRequestResponse
3261
3670
  })], OffersController);
3262
- let HealthController = class HealthController$1 {
3671
+ let HealthController = class HealthController {
3263
3672
  async getRouterStatus() {}
3264
3673
  async getCollectorsHealth() {}
3265
3674
  async getChainsHealth() {}
@@ -3325,68 +3734,222 @@ __decorate([
3325
3734
  })
3326
3735
  ], HealthController.prototype, "getChainsHealth", null);
3327
3736
  HealthController = __decorate([ApiTags("System")], HealthController);
3328
- const maturitiesExample = {
3329
- end_of_month: 1738335600,
3330
- end_of_next_month: 1740754800
3331
- };
3332
- const chainConfigExample = {
3737
+ const configContractsExample = {
3333
3738
  chain_id: 505050505,
3334
- contracts: { mempool: "0xD946246695A9259F3B33a78629026F61B3Ab40aF" },
3335
- maturities: maturitiesExample
3739
+ address: "0xD946246695A9259F3B33a78629026F61B3Ab40aF",
3740
+ name: "mempool"
3741
+ };
3742
+ const configContractsPayloadExample = [
3743
+ {
3744
+ chain_id: 505050505,
3745
+ address: "0xD946246695A9259F3B33a78629026F61B3Ab40aF",
3746
+ name: "mempool"
3747
+ },
3748
+ {
3749
+ chain_id: 505050505,
3750
+ address: "0x8A409D5D6394fC197c596d4E6E2c35e5d13f8a4d",
3751
+ name: "multicall"
3752
+ },
3753
+ {
3754
+ chain_id: 505050505,
3755
+ address: "0x23DFBc4B8B80C14CC5e25011B8491f268395BAd6",
3756
+ name: "v2"
3757
+ }
3758
+ ];
3759
+ const configRulesMaturityExample = {
3760
+ type: "maturity",
3761
+ chain_id: 1,
3762
+ name: "end_of_next_month",
3763
+ timestamp: 1730415600
3764
+ };
3765
+ const configRulesCallbackExample = {
3766
+ type: "callback",
3767
+ chain_id: 1,
3768
+ address: "0x1111111111111111111111111111111111111111",
3769
+ callback_type: "sell_erc20_callback"
3770
+ };
3771
+ const configRulesLoanTokenExample = {
3772
+ type: "loan_token",
3773
+ chain_id: 1,
3774
+ address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
3336
3775
  };
3337
- var ConfigContractsResponse = class {};
3776
+ const configRulesChecksumExample = "f1d2d2f924e986ac86fdf7b36c94bcdf";
3777
+ const configRulesPayloadExample = [
3778
+ configRulesMaturityExample,
3779
+ configRulesCallbackExample,
3780
+ configRulesLoanTokenExample
3781
+ ];
3782
+ const configContractNames = [
3783
+ "mempool",
3784
+ "multicall",
3785
+ "v2"
3786
+ ];
3787
+ const configContractsCursorExample = "505050505:0xd946246695a9259f3b33a78629026f61b3ab40af";
3788
+ var ConfigContractResponse = class {};
3789
+ __decorate([ApiProperty({
3790
+ type: "number",
3791
+ example: configContractsExample.chain_id
3792
+ })], ConfigContractResponse.prototype, "chain_id", void 0);
3338
3793
  __decorate([ApiProperty({
3339
3794
  type: "string",
3340
- example: chainConfigExample.contracts.mempool
3341
- })], ConfigContractsResponse.prototype, "mempool", void 0);
3342
- var MaturitiesResponse = class {};
3795
+ example: configContractsExample.address
3796
+ })], ConfigContractResponse.prototype, "address", void 0);
3343
3797
  __decorate([ApiProperty({
3344
- type: "number",
3345
- description: "Unix timestamp for end of current month maturity (last Friday 15:00 UTC).",
3346
- example: maturitiesExample.end_of_month
3347
- })], MaturitiesResponse.prototype, "end_of_month", void 0);
3798
+ type: "string",
3799
+ enum: configContractNames,
3800
+ example: configContractsExample.name
3801
+ })], ConfigContractResponse.prototype, "name", void 0);
3802
+ var ConfigContractsSuccessResponse = class extends SuccessResponse {};
3803
+ __decorate([ApiProperty({
3804
+ type: "string",
3805
+ nullable: true,
3806
+ example: null
3807
+ })], ConfigContractsSuccessResponse.prototype, "cursor", void 0);
3808
+ __decorate([ApiProperty({
3809
+ type: () => [ConfigContractResponse],
3810
+ description: "Indexer contract configuration for all indexed chains.",
3811
+ example: configContractsPayloadExample
3812
+ })], ConfigContractsSuccessResponse.prototype, "data", void 0);
3813
+ var ConfigRulesMeta = class {};
3814
+ __decorate([ApiProperty({
3815
+ type: "string",
3816
+ example: timestampExample
3817
+ })], ConfigRulesMeta.prototype, "timestamp", void 0);
3818
+ __decorate([ApiProperty({
3819
+ type: "string",
3820
+ example: configRulesChecksumExample
3821
+ })], ConfigRulesMeta.prototype, "checksum", void 0);
3822
+ var ConfigRulesRuleResponse = class {};
3823
+ __decorate([ApiProperty({
3824
+ type: "string",
3825
+ example: configRulesMaturityExample.type
3826
+ })], ConfigRulesRuleResponse.prototype, "type", void 0);
3348
3827
  __decorate([ApiProperty({
3349
3828
  type: "number",
3350
- description: "Unix timestamp for end of next month maturity (last Friday 15:00 UTC).",
3351
- example: maturitiesExample.end_of_next_month
3352
- })], MaturitiesResponse.prototype, "end_of_next_month", void 0);
3353
- var ConfigDataResponse = class {};
3829
+ example: configRulesMaturityExample.chain_id
3830
+ })], ConfigRulesRuleResponse.prototype, "chain_id", void 0);
3831
+ __decorate([ApiProperty({
3832
+ type: "string",
3833
+ example: configRulesMaturityExample.name,
3834
+ required: false
3835
+ })], ConfigRulesRuleResponse.prototype, "name", void 0);
3354
3836
  __decorate([ApiProperty({
3355
3837
  type: "number",
3356
- example: chainConfigExample.chain_id
3357
- })], ConfigDataResponse.prototype, "chain_id", void 0);
3358
- __decorate([ApiProperty({ type: () => ConfigContractsResponse })], ConfigDataResponse.prototype, "contracts", void 0);
3838
+ example: configRulesMaturityExample.timestamp,
3839
+ required: false
3840
+ })], ConfigRulesRuleResponse.prototype, "timestamp", void 0);
3841
+ __decorate([ApiProperty({
3842
+ type: "string",
3843
+ example: configRulesCallbackExample.address,
3844
+ required: false
3845
+ })], ConfigRulesRuleResponse.prototype, "address", void 0);
3359
3846
  __decorate([ApiProperty({
3360
- type: () => MaturitiesResponse,
3361
- description: "Supported maturity timestamps. Offers must use one of these values.",
3362
- example: chainConfigExample.maturities
3363
- })], ConfigDataResponse.prototype, "maturities", void 0);
3364
- var ConfigSuccessResponse = class extends SuccessResponse {};
3847
+ type: "string",
3848
+ example: configRulesCallbackExample.callback_type,
3849
+ required: false
3850
+ })], ConfigRulesRuleResponse.prototype, "callback_type", void 0);
3851
+ var ConfigRulesSuccessResponse = class {};
3852
+ __decorate([ApiProperty({ type: () => ConfigRulesMeta })], ConfigRulesSuccessResponse.prototype, "meta", void 0);
3365
3853
  __decorate([ApiProperty({
3366
3854
  type: "string",
3367
3855
  nullable: true,
3368
3856
  example: null
3369
- })], ConfigSuccessResponse.prototype, "cursor", void 0);
3370
- __decorate([ApiProperty({
3371
- type: () => [ConfigDataResponse],
3372
- description: "Array of chain configurations for all indexed chains.",
3373
- example: [chainConfigExample]
3374
- })], ConfigSuccessResponse.prototype, "data", void 0);
3375
- let ConfigController = class ConfigController$1 {
3376
- async getConfig() {}
3857
+ })], ConfigRulesSuccessResponse.prototype, "cursor", void 0);
3858
+ __decorate([ApiProperty({
3859
+ type: () => [ConfigRulesRuleResponse],
3860
+ description: "Configured rules returned by the router API.",
3861
+ example: configRulesPayloadExample
3862
+ })], ConfigRulesSuccessResponse.prototype, "data", void 0);
3863
+ let ConfigContractsController = class ConfigContractsController {
3864
+ async getConfigContracts() {}
3865
+ };
3866
+ __decorate([
3867
+ ApiOperation({
3868
+ methods: ["get"],
3869
+ path: "/v1/config/contracts",
3870
+ summary: "Get indexer contract configuration",
3871
+ description: "Returns contract addresses used by indexers (mempool, v2) and multicall for indexed chains."
3872
+ }),
3873
+ ApiQuery({
3874
+ name: "cursor",
3875
+ type: "string",
3876
+ required: false,
3877
+ example: configContractsCursorExample,
3878
+ description: "Pagination cursor in chain_id:address format (lowercase address)."
3879
+ }),
3880
+ ApiQuery({
3881
+ name: "limit",
3882
+ type: "number",
3883
+ required: false,
3884
+ example: 1e3,
3885
+ description: "Maximum number of contracts to return (max 1000)."
3886
+ }),
3887
+ ApiQuery({
3888
+ name: "chains",
3889
+ type: ["number"],
3890
+ required: false,
3891
+ example: "1,8453",
3892
+ description: "Filter by chain IDs (comma-separated).",
3893
+ style: "form",
3894
+ explode: false
3895
+ }),
3896
+ ApiResponse({
3897
+ status: 200,
3898
+ description: "Success",
3899
+ type: ConfigContractsSuccessResponse
3900
+ })
3901
+ ], ConfigContractsController.prototype, "getConfigContracts", null);
3902
+ ConfigContractsController = __decorate([ApiTags("System")], ConfigContractsController);
3903
+ let ConfigRulesController = class ConfigRulesController {
3904
+ async getConfigRules() {}
3377
3905
  };
3378
- __decorate([ApiOperation({
3379
- methods: ["get"],
3380
- path: "/v1/config",
3381
- summary: "Get router configuration",
3382
- description: "Returns chain configurations including contract addresses and supported maturity timestamps."
3383
- }), ApiResponse({
3384
- status: 200,
3385
- description: "Success",
3386
- type: ConfigSuccessResponse
3387
- })], ConfigController.prototype, "getConfig", null);
3388
- ConfigController = __decorate([ApiTags("System")], ConfigController);
3389
- let ObligationsController = class ObligationsController$1 {
3906
+ __decorate([
3907
+ ApiOperation({
3908
+ methods: ["get"],
3909
+ path: "/v1/config/rules",
3910
+ summary: "Get config rules",
3911
+ description: "Returns configured rules for supported chains."
3912
+ }),
3913
+ ApiQuery({
3914
+ name: "cursor",
3915
+ type: "string",
3916
+ required: false,
3917
+ example: "maturity:1:1730415600:end_of_next_month",
3918
+ description: "Pagination cursor in type:chain_id:<value> format."
3919
+ }),
3920
+ ApiQuery({
3921
+ name: "limit",
3922
+ type: "number",
3923
+ required: false,
3924
+ example: 100,
3925
+ description: "Maximum number of rules to return (max 1000)."
3926
+ }),
3927
+ ApiQuery({
3928
+ name: "types",
3929
+ type: ["string"],
3930
+ required: false,
3931
+ example: "maturity,loan_token",
3932
+ description: "Filter by rule types (comma-separated).",
3933
+ style: "form",
3934
+ explode: false
3935
+ }),
3936
+ ApiQuery({
3937
+ name: "chains",
3938
+ type: ["number"],
3939
+ required: false,
3940
+ example: "1,8453",
3941
+ description: "Filter by chain IDs (comma-separated).",
3942
+ style: "form",
3943
+ explode: false
3944
+ }),
3945
+ ApiResponse({
3946
+ status: 200,
3947
+ description: "Success",
3948
+ type: ConfigRulesSuccessResponse
3949
+ })
3950
+ ], ConfigRulesController.prototype, "getConfigRules", null);
3951
+ ConfigRulesController = __decorate([ApiTags("System")], ConfigRulesController);
3952
+ let ObligationsController = class ObligationsController {
3390
3953
  async getObligations() {}
3391
3954
  async getObligation() {}
3392
3955
  };
@@ -3410,32 +3973,40 @@ __decorate([
3410
3973
  description: "Maximum number of obligations to return."
3411
3974
  }),
3412
3975
  ApiQuery({
3413
- name: "chain",
3414
- type: "number",
3976
+ name: "chains",
3977
+ type: ["number"],
3415
3978
  required: false,
3416
- example: 1,
3417
- description: "Filter by chain ID."
3979
+ example: "1,8453",
3980
+ description: "Filter by chain IDs (comma-separated).",
3981
+ style: "form",
3982
+ explode: false
3418
3983
  }),
3419
3984
  ApiQuery({
3420
- name: "loan_token",
3421
- type: "string",
3985
+ name: "loan_tokens",
3986
+ type: ["string"],
3422
3987
  required: false,
3423
- example: "0xC9A9C45C0eB717f8b5F193Af6bAa05A1c0Ac5078",
3424
- description: "Filter by loan token address."
3988
+ example: "0xC9A9C45C0eB717f8b5F193Af6bAa05A1c0Ac5078,0x34Cf890dB685FC536E05652FB41f02090c3fb751",
3989
+ description: "Filter by loan token addresses (comma-separated).",
3990
+ style: "form",
3991
+ explode: false
3425
3992
  }),
3426
3993
  ApiQuery({
3427
- name: "collateral_token",
3428
- type: "string",
3994
+ name: "collateral_tokens",
3995
+ type: ["string"],
3429
3996
  required: false,
3430
- example: "0x34Cf890dB685FC536E05652FB41f02090c3fb751",
3431
- description: "Filter by collateral token (matches any collateral in the obligation)."
3997
+ example: "0x34Cf890dB685FC536E05652FB41f02090c3fb751,0xC9A9C45C0eB717f8b5F193Af6bAa05A1c0Ac5078",
3998
+ description: "Filter by collateral tokens (comma-separated, matches any collateral).",
3999
+ style: "form",
4000
+ explode: false
3432
4001
  }),
3433
4002
  ApiQuery({
3434
- name: "maturity",
3435
- type: "number",
4003
+ name: "maturities",
4004
+ type: ["number"],
3436
4005
  required: false,
3437
- example: 1761922800,
3438
- description: "Filter by exact maturity timestamp (unix seconds)."
4006
+ example: "1761922800,1764524800",
4007
+ description: "Filter by exact maturity timestamps (comma-separated, unix seconds).",
4008
+ style: "form",
4009
+ explode: false
3439
4010
  }),
3440
4011
  ApiResponse({
3441
4012
  status: 200,
@@ -3467,7 +4038,7 @@ ObligationsController = __decorate([ApiTags("Markets"), ApiResponse({
3467
4038
  description: "Bad Request",
3468
4039
  type: BadRequestResponse
3469
4040
  })], ObligationsController);
3470
- let UsersController = class UsersController$1 {
4041
+ let UsersController = class UsersController {
3471
4042
  async getUserPositions() {}
3472
4043
  };
3473
4044
  __decorate([
@@ -3506,16 +4077,18 @@ UsersController = __decorate([ApiTags("Make"), ApiResponse({
3506
4077
  description: "Bad Request",
3507
4078
  type: BadRequestResponse
3508
4079
  })], UsersController);
3509
- const OpenApi = async (options = {}) => {
3510
- const document = await generateDocument({
4080
+ const OpenApi = async () => {
4081
+ return await generateDocument({
3511
4082
  controllers: [
3512
4083
  BooksController,
3513
- ConfigController,
4084
+ ConfigContractsController,
4085
+ ConfigRulesController,
3514
4086
  OffersController,
3515
4087
  ObligationsController,
3516
4088
  HealthController,
3517
4089
  UsersController,
3518
- ValidateController
4090
+ ValidateController,
4091
+ CallbacksController
3519
4092
  ],
3520
4093
  document: {
3521
4094
  openapi: "3.1.0",
@@ -3547,17 +4120,11 @@ const OpenApi = async (options = {}) => {
3547
4120
  ]
3548
4121
  }
3549
4122
  });
3550
- if (options.rules && options.rules.length > 0) {
3551
- const rulesDescription = options.rules.map((rule) => `- **${rule.name}**: ${rule.description}`).join("\n");
3552
- const validatePath = document.paths?.["/v1/validate"];
3553
- if (validatePath && "post" in validatePath && validatePath.post) validatePath.post.description = `Validates offers against router validation rules. Returns unsigned payload + root on success, or issues only on validation failure.\n\n**Available validation rules:**\n${rulesDescription}`;
3554
- }
3555
- return document;
3556
4123
  };
3557
4124
 
3558
4125
  //#endregion
3559
4126
  //#region src/api/Schema/PositionResponse.ts
3560
- var PositionResponse_exports = /* @__PURE__ */ __export({ from: () => from$1 });
4127
+ var PositionResponse_exports = /* @__PURE__ */ __exportAll({ from: () => from$1 });
3561
4128
  /**
3562
4129
  * Creates a `PositionResponse` from a `PositionWithReserved`.
3563
4130
  * @param position - {@link PositionWithReserved}
@@ -3577,6 +4144,10 @@ function from$1(position) {
3577
4144
  //#region src/api/Schema/requests.ts
3578
4145
  const MAX_LIMIT = 100;
3579
4146
  const DEFAULT_LIMIT = 20;
4147
+ const CONFIG_RULES_MAX_LIMIT = 1e3;
4148
+ const CONFIG_RULES_DEFAULT_LIMIT = 100;
4149
+ const CONFIG_CONTRACTS_MAX_LIMIT = 1e3;
4150
+ const CONFIG_CONTRACTS_DEFAULT_LIMIT = 1e3;
3580
4151
  /** Validate cursor is a valid base64url-encoded JSON object.
3581
4152
  * Domain layer handles semantic validation of cursor fields. */
3582
4153
  function isValidBase64urlJson(val) {
@@ -3588,6 +4159,15 @@ function isValidBase64urlJson(val) {
3588
4159
  return false;
3589
4160
  }
3590
4161
  }
4162
+ const csvArray = (schema) => z$1.preprocess((value) => {
4163
+ if (value === void 0) return void 0;
4164
+ if (Array.isArray(value)) {
4165
+ if (value.some((item) => typeof item !== "string")) return value;
4166
+ return value.flatMap((item) => item.split(",")).map((item) => item.trim()).filter((item) => item.length > 0);
4167
+ }
4168
+ if (typeof value === "string") return value.split(",").map((item) => item.trim()).filter((item) => item.length > 0);
4169
+ return value;
4170
+ }, z$1.array(schema)).optional();
3591
4171
  const PaginationQueryParams = z$1.object({
3592
4172
  cursor: z$1.string().optional().refine((val) => {
3593
4173
  if (!val) return true;
@@ -3601,6 +4181,43 @@ const PaginationQueryParams = z$1.object({
3601
4181
  example: 10
3602
4182
  })
3603
4183
  });
4184
+ const ConfigRuleTypes = z$1.enum([
4185
+ "maturity",
4186
+ "callback",
4187
+ "loan_token"
4188
+ ]);
4189
+ const GetConfigRulesQueryParams = z$1.object({
4190
+ cursor: z$1.string().regex(/^(maturity|callback|loan_token):[1-9]\d*:.+$/, { message: "Cursor must be in the format type:chain_id:<value>" }).optional().meta({
4191
+ description: "Pagination cursor in type:chain_id:<value> format",
4192
+ example: "maturity:1:1730415600:end_of_next_month"
4193
+ }),
4194
+ limit: z$1.string().regex(/^[1-9]\d*$/, { message: "Limit must be a positive integer" }).transform((val) => Number.parseInt(val, 10)).pipe(z$1.number().max(CONFIG_RULES_MAX_LIMIT, { message: `Limit cannot exceed ${CONFIG_RULES_MAX_LIMIT}` })).optional().default(CONFIG_RULES_DEFAULT_LIMIT).meta({
4195
+ description: `Limit maximum: ${CONFIG_RULES_MAX_LIMIT}. Default: ${CONFIG_RULES_DEFAULT_LIMIT}`,
4196
+ example: 100
4197
+ }),
4198
+ types: csvArray(ConfigRuleTypes).meta({
4199
+ description: "Filter by rule types (comma-separated).",
4200
+ example: "maturity,loan_token"
4201
+ }),
4202
+ chains: csvArray(z$1.string().regex(/^[1-9]\d*$/, { message: "Chain must be a positive integer" }).transform((val) => Number.parseInt(val, 10))).meta({
4203
+ description: "Filter by chain IDs (comma-separated).",
4204
+ example: "1,8453"
4205
+ })
4206
+ });
4207
+ const GetConfigContractsQueryParams = z$1.object({
4208
+ cursor: z$1.string().regex(/^[1-9]\d*:0x[a-fA-F0-9]{40}$/, { message: "Cursor must be in the format chain_id:0x..." }).optional().meta({
4209
+ description: "Pagination cursor in chain_id:address format (lowercase address).",
4210
+ example: "1:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
4211
+ }),
4212
+ limit: z$1.string().regex(/^[1-9]\d*$/, { message: "Limit must be a positive integer" }).transform((val) => Number.parseInt(val, 10)).pipe(z$1.number().max(CONFIG_CONTRACTS_MAX_LIMIT, { message: `Limit cannot exceed ${CONFIG_CONTRACTS_MAX_LIMIT}` })).optional().default(CONFIG_CONTRACTS_DEFAULT_LIMIT).meta({
4213
+ description: `Limit maximum: ${CONFIG_CONTRACTS_MAX_LIMIT}. Default: ${CONFIG_CONTRACTS_DEFAULT_LIMIT}`,
4214
+ example: 1e3
4215
+ }),
4216
+ chains: csvArray(z$1.string().regex(/^[1-9]\d*$/, { message: "Chain must be a positive integer" }).transform((val) => Number.parseInt(val, 10))).meta({
4217
+ description: "Filter by chain IDs (comma-separated).",
4218
+ example: "1,8453"
4219
+ })
4220
+ });
3604
4221
  const GetOffersQueryParams = z$1.object({
3605
4222
  ...PaginationQueryParams.shape,
3606
4223
  side: z$1.enum(["buy", "sell"]).optional().meta({
@@ -3638,21 +4255,21 @@ const GetObligationsQueryParams = z$1.object({
3638
4255
  description: "Obligation id cursor",
3639
4256
  example: "0x1234567890123456789012345678901234567890123456789012345678901234"
3640
4257
  }),
3641
- chain: z$1.string().regex(/^[1-9]\d*$/, { message: "Chain must be a positive integer" }).transform((val) => Number.parseInt(val, 10)).optional().meta({
3642
- description: "Filter by chain ID",
3643
- example: "1"
4258
+ chains: csvArray(z$1.string().regex(/^[1-9]\d*$/, { message: "Chain must be a positive integer" }).transform((val) => Number.parseInt(val, 10))).meta({
4259
+ description: "Filter by chain IDs (comma-separated).",
4260
+ example: "1,8453"
3644
4261
  }),
3645
- loan_token: z$1.string().regex(/^0x[a-fA-F0-9]{40}$/, { error: "Loan token must be a valid 20-byte address" }).transform((val) => val.toLowerCase()).optional().meta({
3646
- description: "Filter by loan token address",
3647
- example: "0xC9A9C45C0eB717f8b5F193Af6bAa05A1c0Ac5078"
4262
+ loan_tokens: csvArray(z$1.string().regex(/^0x[a-fA-F0-9]{40}$/, { error: "Loan token must be a valid 20-byte address" }).transform((val) => val.toLowerCase())).meta({
4263
+ description: "Filter by loan token addresses (comma-separated).",
4264
+ example: "0xC9A9C45C0eB717f8b5F193Af6bAa05A1c0Ac5078,0x34Cf890dB685FC536E05652FB41f02090c3fb751"
3648
4265
  }),
3649
- collateral_token: z$1.string().regex(/^0x[a-fA-F0-9]{40}$/, { error: "Collateral token must be a valid 20-byte address" }).transform((val) => val.toLowerCase()).optional().meta({
3650
- description: "Filter by collateral token (matches any collateral in the obligation)",
3651
- example: "0x34Cf890dB685FC536E05652FB41f02090c3fb751"
4266
+ collateral_tokens: csvArray(z$1.string().regex(/^0x[a-fA-F0-9]{40}$/, { error: "Collateral token must be a valid 20-byte address" }).transform((val) => val.toLowerCase())).meta({
4267
+ description: "Filter by collateral tokens (comma-separated, matches any collateral).",
4268
+ example: "0x34Cf890dB685FC536E05652FB41f02090c3fb751,0xC9A9C45C0eB717f8b5F193Af6bAa05A1c0Ac5078"
3652
4269
  }),
3653
- maturity: z$1.string().regex(/^[1-9]\d*$/, { message: "Maturity must be a positive integer" }).transform((val) => Number.parseInt(val, 10)).optional().meta({
3654
- description: "Filter by exact maturity timestamp (unix seconds)",
3655
- example: "1761922800"
4270
+ maturities: csvArray(z$1.string().regex(/^[1-9]\d*$/, { message: "Maturity must be a positive integer" }).transform((val) => Number.parseInt(val, 10))).meta({
4271
+ description: "Filter by exact maturity timestamps (comma-separated, unix seconds).",
4272
+ example: "1761922800,1764524800"
3656
4273
  })
3657
4274
  });
3658
4275
  const GetObligationParams = z$1.object({ obligation_id: z$1.string({ error: "Obligation id is required and must be a valid 32-byte hex string" }).regex(/^0x[a-fA-F0-9]{64}$/, { error: "Obligation id must be a valid 32-byte hex string" }).transform((val) => val.toLowerCase()).meta({
@@ -3703,6 +4320,16 @@ const GetBookParams = z$1.object({
3703
4320
  })
3704
4321
  });
3705
4322
  const ValidateOffersBody = z$1.object({ offers: z$1.array(z$1.unknown()).min(1, { message: "'offers' must contain at least 1 offer" }) }).strict();
4323
+ const CallbackTypesBody = z$1.object({ callbacks: z$1.array(z$1.object({
4324
+ chain_id: z$1.number().int().positive().meta({
4325
+ description: "Chain id.",
4326
+ example: 1
4327
+ }),
4328
+ addresses: z$1.array(z$1.string().regex(/^0x[a-fA-F0-9]{40}$/, { error: "Callback address must be a valid 20-byte address" }).transform((val) => val.toLowerCase())).meta({
4329
+ description: "Callback contract addresses.",
4330
+ example: ["0x1111111111111111111111111111111111111111", "0x3333333333333333333333333333333333333333"]
4331
+ })
4332
+ }).strict()) }).strict();
3706
4333
  const GetUserPositionsParams = z$1.object({
3707
4334
  ...PaginationQueryParams.shape,
3708
4335
  user_address: z$1.string().regex(/^0x[a-fA-F0-9]{40}$/, { error: "User address must be a valid 20-byte address" }).transform((val) => val.toLowerCase()).meta({
@@ -3714,11 +4341,14 @@ const schemas = {
3714
4341
  get_health: HealthQueryParams,
3715
4342
  get_health_collectors: HealthQueryParams,
3716
4343
  get_health_chains: HealthQueryParams,
4344
+ get_config_contracts: GetConfigContractsQueryParams,
4345
+ get_config_rules: GetConfigRulesQueryParams,
3717
4346
  get_offers: GetOffersQueryParams,
3718
4347
  get_obligations: GetObligationsQueryParams,
3719
4348
  get_obligation: GetObligationParams,
3720
4349
  get_book: GetBookParams,
3721
4350
  validate_offers: ValidateOffersBody,
4351
+ callback_types: CallbackTypesBody,
3722
4352
  get_user_positions: GetUserPositionsParams
3723
4353
  };
3724
4354
  function parse(action, query) {
@@ -3730,14 +4360,16 @@ function safeParse(action, query, error) {
3730
4360
 
3731
4361
  //#endregion
3732
4362
  //#region src/api/Schema/index.ts
3733
- var Schema_exports = /* @__PURE__ */ __export({
4363
+ var Schema_exports = /* @__PURE__ */ __exportAll({
3734
4364
  BookResponse: () => BookResponse_exports,
3735
4365
  BooksController: () => BooksController,
4366
+ CallbacksController: () => CallbacksController,
3736
4367
  ChainHealth: () => ChainHealth,
3737
4368
  ChainsHealthResponse: () => ChainsHealthResponse,
3738
4369
  CollectorHealth: () => CollectorHealth,
3739
4370
  CollectorsHealthResponse: () => CollectorsHealthResponse,
3740
- ConfigController: () => ConfigController,
4371
+ ConfigContractsController: () => ConfigContractsController,
4372
+ ConfigRulesController: () => ConfigRulesController,
3741
4373
  HealthController: () => HealthController,
3742
4374
  ObligationResponse: () => ObligationResponse_exports,
3743
4375
  ObligationsController: () => ObligationsController,
@@ -3754,7 +4386,7 @@ var Schema_exports = /* @__PURE__ */ __export({
3754
4386
 
3755
4387
  //#endregion
3756
4388
  //#region src/client/Client.ts
3757
- var Client_exports = /* @__PURE__ */ __export({
4389
+ var Client_exports$1 = /* @__PURE__ */ __exportAll({
3758
4390
  HttpForbiddenError: () => HttpForbiddenError,
3759
4391
  HttpGetApiFailedError: () => HttpGetApiFailedError,
3760
4392
  HttpRateLimitError: () => HttpRateLimitError,
@@ -3787,12 +4419,16 @@ function connect$1(parameters) {
3787
4419
  };
3788
4420
  const apiClient = createOpenApiFetchClient({
3789
4421
  baseUrl: config.url.toString(),
3790
- headers: config.headers
4422
+ headers: config.headers,
4423
+ querySerializer: { array: {
4424
+ style: "form",
4425
+ explode: false
4426
+ } }
3791
4427
  });
3792
4428
  return {
3793
4429
  ...config,
3794
- getOffers: (parameters$1) => getOffers(apiClient, parameters$1),
3795
- getObligations: (parameters$1) => getObligations(apiClient, parameters$1)
4430
+ getOffers: (parameters) => getOffers(apiClient, parameters),
4431
+ getObligations: (parameters) => getObligations(apiClient, parameters)
3796
4432
  };
3797
4433
  }
3798
4434
  async function getOffers(apiClient, parameters) {
@@ -3819,7 +4455,7 @@ async function getOffers(apiClient, parameters) {
3819
4455
  obligation_units: offerData.obligation_units,
3820
4456
  obligation_shares: offerData.obligation_shares,
3821
4457
  price: offerData.price,
3822
- maturity: from$10(offerData.obligation.maturity),
4458
+ maturity: from$11(offerData.obligation.maturity),
3823
4459
  expiry: offerData.expiry,
3824
4460
  start: offerData.start,
3825
4461
  group: offerData.group,
@@ -3855,10 +4491,10 @@ async function getObligations(apiClient, parameters) {
3855
4491
  const { data, error, response } = await apiClient.GET("/v1/obligations", { params: { query: {
3856
4492
  cursor: parameters?.cursor,
3857
4493
  limit: parameters?.limit,
3858
- chain: parameters?.chainId,
3859
- loan_token: parameters?.loanToken,
3860
- collateral_token: parameters?.collateralToken,
3861
- maturity: parameters?.maturity
4494
+ chains: parameters?.chainIds,
4495
+ loan_tokens: parameters?.loanTokens,
4496
+ collateral_tokens: parameters?.collateralTokens,
4497
+ maturities: parameters?.maturities
3862
4498
  } } });
3863
4499
  if (error !== void 0) {
3864
4500
  switch (response.status) {
@@ -3877,7 +4513,7 @@ async function getObligations(apiClient, parameters) {
3877
4513
  oracle: collateral.oracle,
3878
4514
  lltv: collateral.lltv
3879
4515
  })),
3880
- maturity: from$10(item.maturity)
4516
+ maturity: from$11(item.maturity)
3881
4517
  });
3882
4518
  const { obligationId: _, ...returned } = {
3883
4519
  id: () => id(obligation),
@@ -3926,10 +4562,125 @@ var HttpGetApiFailedError = class extends BaseError {
3926
4562
  }
3927
4563
  };
3928
4564
 
4565
+ //#endregion
4566
+ //#region src/gatekeeper/Client.ts
4567
+ var Client_exports = /* @__PURE__ */ __exportAll({ createHttpClient: () => createHttpClient });
4568
+ const DEFAULT_TIMEOUT_MS = 1e4;
4569
+ /**
4570
+ * Create an HTTP client for a gatekeeper service.
4571
+ * @param config - Gatekeeper client configuration. {@link ClientConfig}
4572
+ * @returns An HTTP-backed gatekeeper client. {@link GatekeeperClient}
4573
+ */
4574
+ function createHttpClient(config) {
4575
+ const fetchFn = config.fetchFn ?? fetch;
4576
+ const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;
4577
+ const baseUrl = normalizeBaseUrl(config.baseUrl);
4578
+ const baseHeaders = config.originSecret ? { "x-origin-verify": config.originSecret } : void 0;
4579
+ const request = async (path, init) => {
4580
+ const controller = new AbortController();
4581
+ const timeout = setTimeout(() => controller.abort(), timeoutMs);
4582
+ try {
4583
+ return await fetchFn(`${baseUrl}${path}`, {
4584
+ ...init,
4585
+ headers: mergeHeaders(baseHeaders, init.headers),
4586
+ signal: controller.signal
4587
+ });
4588
+ } finally {
4589
+ clearTimeout(timeout);
4590
+ }
4591
+ };
4592
+ const validate = async (body) => {
4593
+ const response = await request("/v1/validate", {
4594
+ method: "POST",
4595
+ headers: { "content-type": "application/json" },
4596
+ body: JSON.stringify(body)
4597
+ });
4598
+ const json = await response.json();
4599
+ return {
4600
+ statusCode: response.status,
4601
+ body: json
4602
+ };
4603
+ };
4604
+ const getConfigRules = async (query) => {
4605
+ const params = new URLSearchParams();
4606
+ if (query?.cursor) params.set("cursor", query.cursor);
4607
+ if (query?.limit !== void 0) params.set("limit", query.limit.toString());
4608
+ if (query?.types !== void 0) {
4609
+ const typesValue = Array.isArray(query.types) ? query.types.join(",") : query.types;
4610
+ if (typesValue.length > 0) params.set("types", typesValue);
4611
+ }
4612
+ const response = await request(params.size > 0 ? `/v1/config/rules?${params.toString()}` : "/v1/config/rules", { method: "GET" });
4613
+ const json = await response.json();
4614
+ return {
4615
+ statusCode: response.status,
4616
+ body: json
4617
+ };
4618
+ };
4619
+ const isAllowed = async (offers) => {
4620
+ const { statusCode, body } = await validate({ offers: offers.map((offer) => toSnakeCase(offer)) });
4621
+ if (statusCode !== 200) {
4622
+ const errorMessage = extractErrorMessage(body);
4623
+ throw new Error(`Gatekeeper validation failed: ${errorMessage ?? `status ${statusCode}`}`);
4624
+ }
4625
+ const data = body.data;
4626
+ if (!data || typeof data !== "object") throw new Error("Gatekeeper validation response is invalid.");
4627
+ if ("issues" in data) {
4628
+ const issues = data.issues.map((issue) => ({
4629
+ ruleName: issue.rule,
4630
+ message: issue.message,
4631
+ item: offers[issue.index]
4632
+ }));
4633
+ const invalidIndices = new Set(data.issues.map((issue) => issue.index));
4634
+ return {
4635
+ valid: offers.filter((_, index) => !invalidIndices.has(index)),
4636
+ issues
4637
+ };
4638
+ }
4639
+ if (!("payload" in data) || !("root" in data)) throw new Error("Gatekeeper validation response is missing payload data.");
4640
+ return {
4641
+ valid: offers.slice(),
4642
+ issues: []
4643
+ };
4644
+ };
4645
+ const getCallbackTypes = async (requestPayload) => {
4646
+ const response = await request("/v1/callbacks", {
4647
+ method: "POST",
4648
+ headers: { "content-type": "application/json" },
4649
+ body: JSON.stringify(requestPayload)
4650
+ });
4651
+ const json = await response.json();
4652
+ if (!response.ok) throw new Error(`Gatekeeper callbacks request failed: ${extractErrorMessage(json) ?? response.statusText}`);
4653
+ if (!("data" in json) || !Array.isArray(json.data)) throw new Error("Gatekeeper callbacks response is invalid.");
4654
+ return json.data;
4655
+ };
4656
+ return {
4657
+ baseUrl,
4658
+ validate,
4659
+ getConfigRules,
4660
+ isAllowed,
4661
+ getCallbackTypes
4662
+ };
4663
+ }
4664
+ function mergeHeaders(base, extra) {
4665
+ if (!base && !extra) return void 0;
4666
+ const merged = new Headers(base ?? void 0);
4667
+ if (extra) for (const [key, value] of new Headers(extra).entries()) merged.set(key, value);
4668
+ return merged;
4669
+ }
4670
+ function normalizeBaseUrl(url) {
4671
+ return url.trim().replace(/\/+$/, "");
4672
+ }
4673
+ function extractErrorMessage(payload) {
4674
+ if (!payload || typeof payload !== "object") return void 0;
4675
+ const error = payload.error;
4676
+ if (!error || typeof error !== "object") return void 0;
4677
+ return typeof error.message === "string" ? error.message : void 0;
4678
+ }
4679
+
3929
4680
  //#endregion
3930
4681
  //#region src/gatekeeper/Gate.ts
3931
- var Gate_exports = /* @__PURE__ */ __export({
3932
- batch: () => batch$1,
4682
+ var Gate_exports = /* @__PURE__ */ __exportAll({
4683
+ batch: () => batch,
3933
4684
  run: () => run,
3934
4685
  single: () => single
3935
4686
  });
@@ -3940,12 +4691,12 @@ var Gate_exports = /* @__PURE__ */ __export({
3940
4691
  * @param run - The function that validates the rule.
3941
4692
  * @returns The created rule.
3942
4693
  */
3943
- function single(name, description, run$1) {
4694
+ function single(name, description, run) {
3944
4695
  return {
3945
4696
  kind: "single",
3946
4697
  name,
3947
4698
  description,
3948
- run: run$1
4699
+ run
3949
4700
  };
3950
4701
  }
3951
4702
  /**
@@ -3955,12 +4706,12 @@ function single(name, description, run$1) {
3955
4706
  * @param run - The function that validates the rule.
3956
4707
  * @returns The created rule.
3957
4708
  */
3958
- function batch$1(name, description, run$1) {
4709
+ function batch(name, description, run) {
3959
4710
  return {
3960
4711
  kind: "batch",
3961
4712
  name,
3962
4713
  description,
3963
- run: run$1
4714
+ run
3964
4715
  };
3965
4716
  }
3966
4717
  async function run(parameters) {
@@ -4011,16 +4762,26 @@ async function run(parameters) {
4011
4762
  };
4012
4763
  }
4013
4764
 
4765
+ //#endregion
4766
+ //#region src/gatekeeper/Gatekeeper.ts
4767
+ var Gatekeeper_exports = /* @__PURE__ */ __exportAll({ create: () => create });
4768
+ /**
4769
+ * Create a gatekeeper instance with the provided rules.
4770
+ * @param parameters - Gatekeeper parameters. {@link GatekeeperParameters}
4771
+ * @returns Gatekeeper instance. {@link Gatekeeper}
4772
+ */
4773
+ function create(parameters) {
4774
+ const { rules } = parameters;
4775
+ return { isAllowed: async (offers) => {
4776
+ return await run({
4777
+ items: offers,
4778
+ rules
4779
+ });
4780
+ } };
4781
+ }
4782
+
4014
4783
  //#endregion
4015
4784
  //#region src/gatekeeper/GateConfig.ts
4016
- var GateConfig_exports = /* @__PURE__ */ __export({
4017
- assets: () => assets,
4018
- configs: () => configs,
4019
- getCallback: () => getCallback,
4020
- getCallbackAddresses: () => getCallbackAddresses,
4021
- getCallbackType: () => getCallbackType,
4022
- getCallbackTypeAddresses: () => getCallbackTypeAddresses
4023
- });
4024
4785
  /**
4025
4786
  * Returns the callback configuration for a given chain and callback type, if it exists.
4026
4787
  *
@@ -4039,19 +4800,8 @@ function getCallback(chain, type) {
4039
4800
  * @param address - Callback contract address
4040
4801
  * @returns The callback type when found, otherwise undefined
4041
4802
  */
4042
- function getCallbackType(chain, address$1) {
4043
- return configs[chain].callbacks?.find((c) => c.type !== CallbackType.BuyWithEmptyCallback && c.addresses.includes(address$1?.toLowerCase()))?.type;
4044
- }
4045
- /**
4046
- * Returns the callback addresses for a given chain and callback type, if it exists.
4047
- * @param chain - Chain name for which to read the validation configuration
4048
- * @param type - Callback type to retrieve
4049
- * @returns The matching callback addresses or an empty array if not configured
4050
- */
4051
- function getCallbackTypeAddresses(chain, type) {
4052
- if (type === CallbackType.BuyWithEmptyCallback) return [];
4053
- const match = configs[chain].callbacks?.find((c) => c.type === type);
4054
- return match && "addresses" in match ? match.addresses : [];
4803
+ function getCallbackType(chain, address) {
4804
+ return configs[chain].callbacks?.find((c) => c.type !== Type$1.BuyWithEmptyCallback && c.addresses.includes(address?.toLowerCase()))?.type;
4055
4805
  }
4056
4806
  /**
4057
4807
  * Returns the list of allowed non-empty callback addresses for a chain.
@@ -4060,7 +4810,7 @@ function getCallbackTypeAddresses(chain, type) {
4060
4810
  * @returns Array of allowed callback addresses (lowercased). Empty when none configured
4061
4811
  */
4062
4812
  const getCallbackAddresses = (chain) => {
4063
- return configs[chain].callbacks?.filter((c) => c.type !== CallbackType.BuyWithEmptyCallback).flatMap((c) => c.addresses) ?? [];
4813
+ return configs[chain].callbacks?.filter((c) => c.type !== Type$1.BuyWithEmptyCallback).flatMap((c) => c.addresses) ?? [];
4064
4814
  };
4065
4815
  const assets = {
4066
4816
  [ChainId.ETHEREUM.toString()]: [
@@ -4093,83 +4843,68 @@ const configs = {
4093
4843
  ethereum: {
4094
4844
  callbacks: [
4095
4845
  {
4096
- type: CallbackType.BuyVaultV1Callback,
4846
+ type: Type$1.BuyVaultV1Callback,
4097
4847
  addresses: ["0x3333333333333333333333333333333333333333", "0x4444444444444444444444444444444444444444"],
4098
4848
  vaultFactories: ["0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101", "0x1897A8997241C1cD4bD0698647e4EB7213535c24"]
4099
4849
  },
4100
4850
  {
4101
- type: CallbackType.SellERC20Callback,
4851
+ type: Type$1.SellERC20Callback,
4102
4852
  addresses: ["0x1111111111111111111111111111111111111111", "0x2222222222222222222222222222222222222222"]
4103
4853
  },
4104
- { type: CallbackType.BuyWithEmptyCallback }
4854
+ { type: Type$1.BuyWithEmptyCallback }
4105
4855
  ],
4106
4856
  maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth]
4107
4857
  },
4108
4858
  base: {
4109
4859
  callbacks: [
4110
4860
  {
4111
- type: CallbackType.BuyVaultV1Callback,
4861
+ type: Type$1.BuyVaultV1Callback,
4112
4862
  addresses: ["0x3333333333333333333333333333333333333333", "0x4444444444444444444444444444444444444444"],
4113
4863
  vaultFactories: ["0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101", "0xFf62A7c278C62eD665133147129245053Bbf5918"]
4114
4864
  },
4115
4865
  {
4116
- type: CallbackType.SellERC20Callback,
4866
+ type: Type$1.SellERC20Callback,
4117
4867
  addresses: ["0x1111111111111111111111111111111111111111", "0x2222222222222222222222222222222222222222"]
4118
4868
  },
4119
- { type: CallbackType.BuyWithEmptyCallback }
4869
+ { type: Type$1.BuyWithEmptyCallback }
4120
4870
  ],
4121
4871
  maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth]
4122
4872
  },
4123
4873
  "ethereum-virtual-testnet": {
4124
4874
  callbacks: [
4125
4875
  {
4126
- type: CallbackType.BuyVaultV1Callback,
4876
+ type: Type$1.BuyVaultV1Callback,
4127
4877
  addresses: ["0x3333333333333333333333333333333333333333", "0x4444444444444444444444444444444444444444"],
4128
4878
  vaultFactories: ["0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101", "0x1897A8997241C1cD4bD0698647e4EB7213535c24"]
4129
4879
  },
4130
4880
  {
4131
- type: CallbackType.SellERC20Callback,
4881
+ type: Type$1.SellERC20Callback,
4132
4882
  addresses: ["0x1111111111111111111111111111111111111111", "0x2222222222222222222222222222222222222222"]
4133
4883
  },
4134
- { type: CallbackType.BuyWithEmptyCallback }
4884
+ { type: Type$1.BuyWithEmptyCallback }
4135
4885
  ],
4136
4886
  maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth]
4137
4887
  },
4138
4888
  anvil: {
4139
4889
  callbacks: [
4140
4890
  {
4141
- type: CallbackType.BuyVaultV1Callback,
4891
+ type: Type$1.BuyVaultV1Callback,
4142
4892
  addresses: ["0x3333333333333333333333333333333333333333", "0x4444444444444444444444444444444444444444"],
4143
4893
  vaultFactories: ["0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101", "0x1897A8997241C1cD4bD0698647e4EB7213535c24"]
4144
4894
  },
4145
4895
  {
4146
- type: CallbackType.SellERC20Callback,
4896
+ type: Type$1.SellERC20Callback,
4147
4897
  addresses: ["0x1111111111111111111111111111111111111111", "0x2222222222222222222222222222222222222222"]
4148
4898
  },
4149
- { type: CallbackType.BuyWithEmptyCallback }
4899
+ { type: Type$1.BuyWithEmptyCallback }
4150
4900
  ],
4151
4901
  maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth]
4152
4902
  }
4153
4903
  };
4154
4904
 
4155
- //#endregion
4156
- //#region src/gatekeeper/Gatekeeper.ts
4157
- var Gatekeeper_exports = /* @__PURE__ */ __export({ create: () => create });
4158
- function create(parameters) {
4159
- return {
4160
- rules: parameters.rules,
4161
- isAllowed: async (offers) => {
4162
- return await run({
4163
- items: offers,
4164
- rules: parameters.rules
4165
- });
4166
- }
4167
- };
4168
- }
4169
-
4170
4905
  //#endregion
4171
4906
  //#region src/gatekeeper/Rules.ts
4172
- var Rules_exports = /* @__PURE__ */ __export({
4907
+ var Rules_exports = /* @__PURE__ */ __exportAll({
4173
4908
  amountMutualExclusivity: () => amountMutualExclusivity,
4174
4909
  callback: () => callback,
4175
4910
  chains: () => chains,
@@ -4188,21 +4923,21 @@ function validity(parameters) {
4188
4923
  const { client } = parameters;
4189
4924
  const sellErc20CallbackInvalid = single("sell_erc20_callback_invalid", "Validates that sell offers have valid ERC20 callback data matching offer collaterals", (offer) => {
4190
4925
  const callbackType = getCallbackType(client.chain.name, offer.callback.address);
4191
- if (callbackType !== CallbackType.SellERC20Callback) return;
4926
+ if (callbackType !== Type$1.SellERC20Callback) return;
4192
4927
  const decoded = decode$2(callbackType, offer.callback.data);
4193
4928
  if (decoded.length === 0) return { message: "Callback data cannot be decoded or is empty." };
4194
- if (callbackType === CallbackType.SellERC20Callback) {
4929
+ if (callbackType === Type$1.SellERC20Callback) {
4195
4930
  const offerCollaterals = new Set(offer.collaterals.map((c) => c.asset.toLowerCase()));
4196
4931
  if (decoded.length !== offer.collaterals.length) return { message: `Sell callback collateral length mismatch. Expected ${offer.collaterals.length}, got ${decoded.length}.` };
4197
4932
  for (const { contract } of decoded) if (!offerCollaterals.has(contract.toLowerCase())) return { message: "Sell callback collateral is not part of offer collaterals." };
4198
4933
  }
4199
4934
  });
4200
- const buyCallbackVaultInvalid = batch$1("buy_offers_callback_vault_invalid", "Validates that buy offers have valid vault callbacks registered in allowed factories with matching assets", async (offers) => {
4935
+ 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) => {
4201
4936
  const validationIssues = /* @__PURE__ */ new Map();
4202
4937
  const offersByVaultAddress = /* @__PURE__ */ new Map();
4203
4938
  for (let i = 0; i < offers.length; i++) {
4204
4939
  const offer = offers[i];
4205
- if (getCallbackType(client.chain.name, offer.callback.address) !== CallbackType.BuyVaultV1Callback) continue;
4940
+ if (getCallbackType(client.chain.name, offer.callback.address) !== Type$1.BuyVaultV1Callback) continue;
4206
4941
  try {
4207
4942
  const callbackVaults = decodeBuyVaultV1Callback(offer.callback.data);
4208
4943
  for (const { contract } of callbackVaults) {
@@ -4217,7 +4952,7 @@ function validity(parameters) {
4217
4952
  }
4218
4953
  const uniqueVaultAddresses = Array.from(offersByVaultAddress.keys());
4219
4954
  if (uniqueVaultAddresses.length === 0) return validationIssues;
4220
- const allowedFactories = getCallback(client.chain.name, CallbackType.BuyVaultV1Callback)?.vaultFactories.map((f) => f.toLowerCase());
4955
+ const allowedFactories = getCallback(client.chain.name, Type$1.BuyVaultV1Callback)?.vaultFactories.map((f) => f.toLowerCase());
4221
4956
  if (!allowedFactories) return validationIssues;
4222
4957
  const multicallContracts = [];
4223
4958
  for (const vaultAddress of uniqueVaultAddresses) {
@@ -4285,16 +5020,16 @@ function validity(parameters) {
4285
5020
  buyCallbackVaultInvalid
4286
5021
  ];
4287
5022
  }
4288
- const chains = ({ chains: chains$2 }) => single("chain_ids", `Validates that offer chain is one of: [${chains$2.map((c) => c.id).join(", ")}]`, (offer) => {
4289
- const allowedChainIds = chains$2.map((c) => c.id);
4290
- if (!allowedChainIds.some((id$1) => id$1 === offer.chainId)) return { message: `Chain ID ${offer.chainId} is not in the allowed chains (${allowedChainIds.join(", ")})` };
5023
+ const chains = ({ chains }) => single("chain_ids", `Validates that offer chain is one of: [${chains.map((c) => c.id).join(", ")}]`, (offer) => {
5024
+ const allowedChainIds = chains.map((c) => c.id);
5025
+ if (!allowedChainIds.some((id) => id === offer.chainId)) return { message: `Chain ID ${offer.chainId} is not in the allowed chains (${allowedChainIds.join(", ")})` };
4291
5026
  });
4292
5027
  const maturity = ({ maturities }) => single("maturity", `Validates that offer maturity is one of: [${maturities.join(", ")}]`, (offer) => {
4293
- const allowedMaturities = maturities.map((m) => from$10(m));
5028
+ const allowedMaturities = maturities.map((m) => from$11(m));
4294
5029
  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}` };
4295
5030
  });
4296
- const callback = ({ callbacks, allowedAddresses }) => single("callback", `Validates callbacks: buy empty callback is ${callbacks.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) => {
4297
- if (isEmptyCallback(offer) && offer.buy && !callbacks?.find((c) => c === CallbackType.BuyWithEmptyCallback)) return { message: "Buy offers with empty callback not allowed." };
5031
+ 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) => {
5032
+ if (isEmptyCallback(offer) && offer.buy && !callbacks?.find((c) => c === Type$1.BuyWithEmptyCallback)) return { message: "Buy offers with empty callback not allowed." };
4298
5033
  if (isEmptyCallback(offer) && !offer.buy) return { message: "Sell offers require a non-empty callback." };
4299
5034
  if (!isEmptyCallback(offer)) {
4300
5035
  if (!allowedAddresses.includes(offer.callback.address?.toLowerCase())) return { message: `Callback address ${offer.callback.address} is not allowed.` };
@@ -4316,7 +5051,7 @@ const token = ({ assetsByChainId }) => single("token", "Validates that offer loa
4316
5051
  * Returns an issue only for the first non-conforming offer.
4317
5052
  * This rule is signing-agnostic; signer verification is handled at the collector level.
4318
5053
  */
4319
- const sameMaker = () => batch$1("mixed_maker", "Validates that all offers in a batch have the same maker address", (offers) => {
5054
+ const sameMaker = () => batch("mixed_maker", "Validates that all offers in a batch have the same maker address", (offers) => {
4320
5055
  const issues = /* @__PURE__ */ new Map();
4321
5056
  if (offers.length === 0) return issues;
4322
5057
  const firstMaker = offers[0].maker.toLowerCase();
@@ -4350,9 +5085,9 @@ const morphoRules = (chains$2) => {
4350
5085
  maturity({ maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth] }),
4351
5086
  callback({
4352
5087
  callbacks: [
4353
- CallbackType.BuyWithEmptyCallback,
4354
- CallbackType.BuyVaultV1Callback,
4355
- CallbackType.SellERC20Callback
5088
+ Type$1.BuyWithEmptyCallback,
5089
+ Type$1.BuyVaultV1Callback,
5090
+ Type$1.SellERC20Callback
4356
5091
  ],
4357
5092
  allowedAddresses: chains$2.flatMap((c) => getCallbackAddresses(c.name))
4358
5093
  }),
@@ -4367,12 +5102,13 @@ function from(parameters) {
4367
5102
  const config = {
4368
5103
  client: parameters.client,
4369
5104
  mempoolAddress: parameters.mempoolAddress,
5105
+ morphoAddress: parameters.morphoAddress,
4370
5106
  blockWindow: parameters.blockWindow
4371
5107
  };
4372
5108
  return {
4373
- add: (parameters$1) => add(config, parameters$1),
4374
- get: (parameters$1) => get(config, parameters$1),
4375
- stream: (parameters$1) => streamOffers(config, parameters$1)
5109
+ add: (parameters) => add(config, parameters),
5110
+ get: (parameters) => get(config, parameters),
5111
+ stream: (parameters) => streamOffers(config, parameters)
4376
5112
  };
4377
5113
  }
4378
5114
  /**
@@ -4384,11 +5120,18 @@ function from(parameters) {
4384
5120
  */
4385
5121
  async function add(config, offers) {
4386
5122
  if (!config.client.account) throw new WalletAccountNotSetError();
4387
- const tree = from$8(offers.map((o) => from$7(o)));
5123
+ const tree = from$3(offers.map((o) => from$9(o)));
4388
5124
  const chainId = await getChainId(config.client);
4389
5125
  for (const offer of tree.offers) if (chainId !== offer.chainId) throw new ChainIdMismatchError(offer.chainId, chainId);
4390
- const signature = await sign(tree.offers, config.client);
4391
- const encoded = await encode$1(tree, signature);
5126
+ const signatureDomain$1 = resolveSignatureDomain(config, chainId);
5127
+ const signature = await config.client.signTypedData({
5128
+ account: config.client.account,
5129
+ domain: signatureDomain(signatureDomain$1),
5130
+ types: signatureTypes,
5131
+ primaryType: "Root",
5132
+ message: { root: tree.root }
5133
+ });
5134
+ const encoded = await encode(tree, signature, signatureDomain$1);
4392
5135
  try {
4393
5136
  return await config.client.sendTransaction({
4394
5137
  chain: config.client.chain,
@@ -4427,6 +5170,7 @@ const getChainId = async (client) => {
4427
5170
  };
4428
5171
  async function* streamOffers(config, parameters) {
4429
5172
  const { loanToken, blockNumberGte, blockNumberLte, order = "desc", options: { maxBatchSize = DEFAULT_BATCH_SIZE, blockWindow = config.blockWindow } = {} } = parameters;
5173
+ const signatureDomain = resolveSignatureDomain(config, await getChainId(config.client));
4430
5174
  const stream = streamLogs({
4431
5175
  client: config.client.extend(publicActions),
4432
5176
  contractAddress: config.mempoolAddress,
@@ -4458,7 +5202,7 @@ async function* streamOffers(config, parameters) {
4458
5202
  if (!log) continue;
4459
5203
  const [payload] = decodeAbiParameters([{ type: "bytes" }], log.data);
4460
5204
  try {
4461
- const { tree } = await decode$1(payload);
5205
+ const { tree } = await decode(payload, signatureDomain);
4462
5206
  for (const offer of tree.offers) {
4463
5207
  if (loanToken && offer.loanToken.toLowerCase() !== loanToken.toLowerCase()) continue;
4464
5208
  offers.push(offer);
@@ -4493,10 +5237,25 @@ var ChainIdMismatchError = class extends BaseError {
4493
5237
  _defineProperty(this, "name", "Mempool.ChainIdMismatchError");
4494
5238
  }
4495
5239
  };
5240
+ const resolveSignatureDomain = (config, chainId) => {
5241
+ const chain = config.client.chain;
5242
+ const verifyingContract = config.morphoAddress ?? chain?.custom?.morpho?.address ?? getChain(chainId)?.custom.morpho.address;
5243
+ if (!verifyingContract || verifyingContract.toLowerCase() === zeroAddress) throw new MissingMorphoAddressError();
5244
+ return {
5245
+ chainId,
5246
+ verifyingContract
5247
+ };
5248
+ };
5249
+ var MissingMorphoAddressError = class extends BaseError {
5250
+ constructor() {
5251
+ super("Morpho address is required to verify root signatures (zero address is invalid).");
5252
+ _defineProperty(this, "name", "Mempool.MissingMorphoAddressError");
5253
+ }
5254
+ };
4496
5255
 
4497
5256
  //#endregion
4498
5257
  //#region src/mempool/MempoolClient.ts
4499
- var MempoolClient_exports = /* @__PURE__ */ __export({ connect: () => connect });
5258
+ var MempoolClient_exports = /* @__PURE__ */ __exportAll({ connect: () => connect });
4500
5259
  /**
4501
5260
  * Client to interact with the Mempool contract on a specific chain.
4502
5261
  */
@@ -4529,7 +5288,7 @@ const retry = async (fn, attempts = 3, delayMs = 50) => {
4529
5288
  async function batchMulticall(parameters) {
4530
5289
  const { client, calls, batchSize, retryAttempts, retryDelayMs, blockNumber } = parameters;
4531
5290
  const results = [];
4532
- for (const callsBatch of batch(calls, batchSize)) {
5291
+ for (const callsBatch of batch$1(calls, batchSize)) {
4533
5292
  const batchResults = await retry(() => multicall(client, {
4534
5293
  allowFailure: false,
4535
5294
  contracts: callsBatch,
@@ -4542,7 +5301,7 @@ async function batchMulticall(parameters) {
4542
5301
 
4543
5302
  //#endregion
4544
5303
  //#region src/utils/Group.ts
4545
- var Group_exports = /* @__PURE__ */ __export({ fromNumber: () => fromNumber });
5304
+ var Group_exports = /* @__PURE__ */ __exportAll({ fromNumber: () => fromNumber });
4546
5305
  /**
4547
5306
  * Creates a bytes32 group identifier from a number.
4548
5307
  * @param n - A non-negative integer.
@@ -4566,7 +5325,7 @@ function lazy(pollFn) {
4566
5325
  let active = true;
4567
5326
  let resolveNext = null;
4568
5327
  const queue = [];
4569
- const wait$1 = () => new Promise((resolve) => {
5328
+ const wait = () => new Promise((resolve) => {
4570
5329
  resolveNext = resolve;
4571
5330
  });
4572
5331
  const emit = (item) => {
@@ -4584,7 +5343,7 @@ function lazy(pollFn) {
4584
5343
  unpoll = pollFn(emit, { stop });
4585
5344
  try {
4586
5345
  while (active) {
4587
- if (queue.length === 0) await wait$1();
5346
+ if (queue.length === 0) await wait();
4588
5347
  while (queue.length > 0 && active) yield queue.shift();
4589
5348
  }
4590
5349
  } finally {
@@ -4623,7 +5382,7 @@ function poll(fn, { interval }) {
4623
5382
 
4624
5383
  //#endregion
4625
5384
  //#region src/utils/time.ts
4626
- var time_exports = /* @__PURE__ */ __export({
5385
+ var time_exports = /* @__PURE__ */ __exportAll({
4627
5386
  max: () => max,
4628
5387
  now: () => now
4629
5388
  });
@@ -4636,14 +5395,14 @@ function max() {
4636
5395
 
4637
5396
  //#endregion
4638
5397
  //#region src/utils/index.ts
4639
- var utils_exports = /* @__PURE__ */ __export({
5398
+ var utils_exports = /* @__PURE__ */ __exportAll({
4640
5399
  BaseError: () => BaseError,
4641
5400
  Group: () => Group_exports,
4642
5401
  Random: () => Random_exports,
4643
5402
  ReorgError: () => ReorgError,
4644
5403
  Time: () => time_exports,
4645
5404
  atMostOneNonZero: () => atMostOneNonZero,
4646
- batch: () => batch,
5405
+ batch: () => batch$1,
4647
5406
  batchMulticall: () => batchMulticall,
4648
5407
  fromSnakeCase: () => fromSnakeCase$3,
4649
5408
  lazy: () => lazy,
@@ -4657,5 +5416,5 @@ var utils_exports = /* @__PURE__ */ __export({
4657
5416
  });
4658
5417
 
4659
5418
  //#endregion
4660
- export { Abi_exports as Abi, BrandTypeId, Callback_exports as Callback, Chain_exports as Chain, ChainRegistry_exports as ChainRegistry, Collateral_exports as Collateral, ERC4626_exports as ERC4626, Errors_exports as Errors, Format_exports as Format, GateConfig_exports as GateConfig, Gatekeeper_exports as Gatekeeper, LLTV_exports as LLTV, Liquidity_exports as Liquidity, Maturity_exports as Maturity, MempoolClient_exports as Mempool, Obligation_exports as Obligation, Offer_exports as Offer, Oracle_exports as Oracle, Position_exports as Position, Quote_exports as Quote, Schema_exports as RouterApi, Client_exports as RouterClient, Rules_exports as Rules, time_exports as Time, Transfer_exports as Transfer, Tree_exports as Tree, utils_exports as Utils, Gate_exports as Validation, morphoRules };
5419
+ export { Abi_exports as Abi, BrandTypeId, Callback_exports as Callback, Chain_exports as Chain, ChainRegistry_exports as ChainRegistry, Collateral_exports as Collateral, ERC4626_exports as ERC4626, Errors_exports as Errors, Format_exports as Format, Gatekeeper_exports as Gatekeeper, Client_exports as GatekeeperClient, LLTV_exports as LLTV, Liquidity_exports as Liquidity, Maturity_exports as Maturity, MempoolClient_exports as Mempool, Obligation_exports as Obligation, Offer_exports as Offer, Oracle_exports as Oracle, Position_exports as Position, Quote_exports as Quote, Schema_exports as RouterApi, Client_exports$1 as RouterClient, Rules_exports as Rules, time_exports as Time, TradingFee_exports as TradingFee, Transfer_exports as Transfer, Tree_exports as Tree, utils_exports as Utils, Gate_exports as Validation, morphoRules };
4661
5420
  //# sourceMappingURL=index.browser.mjs.map