@morpho-dev/router 0.7.2 → 0.8.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.
Files changed (65) hide show
  1. package/dist/cli.js +292 -122
  2. package/dist/drizzle/migrations/0000_setup_single_migration_folder.sql +64 -64
  3. package/dist/drizzle/migrations/0001_add-trigger-for-consumed-events.sql +5 -5
  4. package/dist/drizzle/migrations/0002_insert-status-code.sql +1 -1
  5. package/dist/drizzle/migrations/0003_update-triggers-for-consumed-events.sql +1 -1
  6. package/dist/drizzle/migrations/0004_drop-status-offers-foreign-key-constraint.sql +1 -1
  7. package/dist/drizzle/migrations/0005_add-index-to-boost-group-query-and-offer-hash.sql +1 -1
  8. package/dist/drizzle/migrations/0006_add-callbacks-and-positions-relations.sql +11 -11
  9. package/dist/drizzle/migrations/0008_validation.sql +10 -10
  10. package/dist/drizzle/migrations/0009_add-transfers-table.sql +4 -4
  11. package/dist/drizzle/migrations/0010_add-price.sql +1 -1
  12. package/dist/drizzle/migrations/0011_nullable-callback-amount.sql +1 -1
  13. package/dist/drizzle/migrations/0012_add-position-asset.sql +1 -1
  14. package/dist/drizzle/migrations/0013_remove-depecrated-domains.sql +13 -13
  15. package/dist/drizzle/migrations/0014_rename-offers-v2-into-offers.sql +19 -19
  16. package/dist/drizzle/migrations/0015_add-lots-table.sql +3 -3
  17. package/dist/drizzle/migrations/0016_merkle-metadata.sql +7 -7
  18. package/dist/drizzle/migrations/0017_dusty_the_hunter.sql +1 -1
  19. package/dist/drizzle/migrations/0018_add_chain_collector_constraints.sql +3 -3
  20. package/dist/drizzle/migrations/0019_add-obligation-units-shares.sql +2 -2
  21. package/dist/drizzle/migrations/0020_add-session.sql +1 -1
  22. package/dist/drizzle/migrations/0021_drop_chain_collector_epoch_indexes.sql +2 -2
  23. package/dist/drizzle/migrations/0021_migrate-rate-to-price.sql +6 -6
  24. package/dist/drizzle/migrations/0022_consolidate-price.sql +5 -5
  25. package/dist/drizzle/migrations/0023_remove-block-number-for-collaterals.sql +1 -1
  26. package/dist/drizzle/migrations/0024_add-obligation-id-to-lots.sql +8 -0
  27. package/dist/drizzle/migrations/0025_rename-price-to-tick.sql +202 -0
  28. package/dist/drizzle/migrations/meta/0000_snapshot.json +48 -48
  29. package/dist/drizzle/migrations/meta/0001_snapshot.json +48 -48
  30. package/dist/drizzle/migrations/meta/0002_snapshot.json +48 -48
  31. package/dist/drizzle/migrations/meta/0003_snapshot.json +48 -48
  32. package/dist/drizzle/migrations/meta/0004_snapshot.json +47 -47
  33. package/dist/drizzle/migrations/meta/0005_snapshot.json +47 -47
  34. package/dist/drizzle/migrations/meta/0006_snapshot.json +61 -61
  35. package/dist/drizzle/migrations/meta/0008_snapshot.json +62 -62
  36. package/dist/drizzle/migrations/meta/0009_snapshot.json +66 -66
  37. package/dist/drizzle/migrations/meta/0010_snapshot.json +66 -66
  38. package/dist/drizzle/migrations/meta/0013_snapshot.json +48 -48
  39. package/dist/drizzle/migrations/meta/0014_snapshot.json +48 -48
  40. package/dist/drizzle/migrations/meta/0015_snapshot.json +52 -52
  41. package/dist/drizzle/migrations/meta/0016_snapshot.json +61 -61
  42. package/dist/drizzle/migrations/meta/0017_snapshot.json +61 -61
  43. package/dist/drizzle/migrations/meta/0018_snapshot.json +62 -62
  44. package/dist/drizzle/migrations/meta/0019_snapshot.json +62 -62
  45. package/dist/drizzle/migrations/meta/0023_snapshot.json +62 -62
  46. package/dist/drizzle/migrations/meta/0024_snapshot.json +1448 -0
  47. package/dist/drizzle/migrations/meta/0025_snapshot.json +1448 -0
  48. package/dist/drizzle/migrations/meta/_journal.json +14 -0
  49. package/dist/index.browser.d.mts +103 -33
  50. package/dist/index.browser.d.mts.map +1 -1
  51. package/dist/index.browser.d.ts +103 -33
  52. package/dist/index.browser.d.ts.map +1 -1
  53. package/dist/index.browser.js +298 -146
  54. package/dist/index.browser.js.map +1 -1
  55. package/dist/index.browser.mjs +293 -147
  56. package/dist/index.browser.mjs.map +1 -1
  57. package/dist/index.node.d.mts +182 -63
  58. package/dist/index.node.d.mts.map +1 -1
  59. package/dist/index.node.d.ts +182 -63
  60. package/dist/index.node.d.ts.map +1 -1
  61. package/dist/index.node.js +342 -127
  62. package/dist/index.node.js.map +1 -1
  63. package/dist/index.node.mjs +337 -128
  64. package/dist/index.node.mjs.map +1 -1
  65. package/package.json +1 -1
@@ -52,11 +52,191 @@ let openapi_metadata_decorators = require("openapi-metadata/decorators");
52
52
  let openapi_fetch = require("openapi-fetch");
53
53
  openapi_fetch = __toESM(openapi_fetch);
54
54
 
55
+ //#region \0@oxc-project+runtime@0.110.0/helpers/typeof.js
56
+ function _typeof(o) {
57
+ "@babel/helpers - typeof";
58
+ return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
59
+ return typeof o;
60
+ } : function(o) {
61
+ return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
62
+ }, _typeof(o);
63
+ }
64
+
65
+ //#endregion
66
+ //#region \0@oxc-project+runtime@0.110.0/helpers/toPrimitive.js
67
+ function toPrimitive(t, r) {
68
+ if ("object" != _typeof(t) || !t) return t;
69
+ var e = t[Symbol.toPrimitive];
70
+ if (void 0 !== e) {
71
+ var i = e.call(t, r || "default");
72
+ if ("object" != _typeof(i)) return i;
73
+ throw new TypeError("@@toPrimitive must return a primitive value.");
74
+ }
75
+ return ("string" === r ? String : Number)(t);
76
+ }
77
+
78
+ //#endregion
79
+ //#region \0@oxc-project+runtime@0.110.0/helpers/toPropertyKey.js
80
+ function toPropertyKey(t) {
81
+ var i = toPrimitive(t, "string");
82
+ return "symbol" == _typeof(i) ? i : i + "";
83
+ }
84
+
85
+ //#endregion
86
+ //#region \0@oxc-project+runtime@0.110.0/helpers/defineProperty.js
87
+ function _defineProperty(e, r, t) {
88
+ return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
89
+ value: t,
90
+ enumerable: !0,
91
+ configurable: !0,
92
+ writable: !0
93
+ }) : e[r] = t, e;
94
+ }
95
+
96
+ //#endregion
97
+ //#region src/utils/Errors.ts
98
+ var Errors_exports = /* @__PURE__ */ __exportAll({
99
+ BaseError: () => BaseError,
100
+ ReorgError: () => ReorgError
101
+ });
102
+ /**
103
+ * Base error class inherited by all errors thrown by mempool.
104
+ *
105
+ * @example
106
+ * ```ts
107
+ * import { Errors } from 'mempool'
108
+ * throw new Errors.BaseError('An error occurred')
109
+ * ```
110
+ */
111
+ var BaseError = class BaseError extends Error {
112
+ constructor(shortMessage, options = {}) {
113
+ const details = (() => {
114
+ if (options.cause instanceof BaseError) {
115
+ if (options.cause.details) return options.cause.details;
116
+ if (options.cause.shortMessage) return options.cause.shortMessage;
117
+ }
118
+ if (options.cause && "details" in options.cause && typeof options.cause.details === "string") return options.cause.details;
119
+ if (options.cause?.message) return options.cause.message;
120
+ return options.details;
121
+ })();
122
+ const message = [
123
+ shortMessage || "An error occurred.",
124
+ ...options.metaMessages ? ["", ...options.metaMessages] : [],
125
+ ...details ? ["", details ? `Details: ${details}` : void 0] : []
126
+ ].filter((x) => typeof x === "string").join("\n");
127
+ super(message, options.cause ? { cause: options.cause } : void 0);
128
+ _defineProperty(this, "details", void 0);
129
+ _defineProperty(this, "shortMessage", void 0);
130
+ _defineProperty(this, "cause", void 0);
131
+ _defineProperty(this, "name", "BaseError");
132
+ this.cause = options.cause;
133
+ this.details = details;
134
+ this.shortMessage = shortMessage;
135
+ }
136
+ walk(fn) {
137
+ return walk(this, fn);
138
+ }
139
+ };
140
+ /** @internal */
141
+ function walk(err, fn) {
142
+ if (fn?.(err)) return err;
143
+ if (err && typeof err === "object" && "cause" in err && err.cause) return walk(err.cause, fn);
144
+ return fn ? null : err;
145
+ }
146
+ var ReorgError = class extends BaseError {
147
+ constructor(blockNumber) {
148
+ super(`Reorg detected at block number ${blockNumber}`);
149
+ _defineProperty(this, "name", "ReorgError");
150
+ }
151
+ };
152
+
153
+ //#endregion
154
+ //#region src/core/Tick.ts
155
+ var Tick_exports = /* @__PURE__ */ __exportAll({
156
+ InvalidPriceError: () => InvalidPriceError,
157
+ InvalidTickError: () => InvalidTickError,
158
+ MAX_PRICE: () => MAX_PRICE,
159
+ TICK_RANGE: () => TICK_RANGE,
160
+ priceToTick: () => priceToTick,
161
+ tickToPrice: () => tickToPrice
162
+ });
163
+ /** ln(1 + 0.025), scaled by 1e18. Matches TickLib onchain constant. */
164
+ const LN_ONE_PLUS_DELTA = 24692612590371501n;
165
+ /** ln(2), scaled by 1e18. Matches TickLib onchain constant. */
166
+ const LN2 = 693147180559945309n;
167
+ const WAD$1 = 10n ** 18n;
168
+ const WAD_SQUARED = 10n ** 36n;
169
+ const PRICE_STEP = 10n ** 13n;
170
+ const HALF_TICK_RANGE = 495n;
171
+ /** Tick domain supported by Morpho V2. */
172
+ const TICK_RANGE = 990;
173
+ /** Max allowed price (1e18 in wad). */
174
+ const MAX_PRICE = WAD$1;
175
+ /**
176
+ * Converts a tick to a wad price using the same approximation and rounding as TickLib.
177
+ * @param tick - Tick value in the inclusive range [0, 990].
178
+ * @returns The price in wad units.
179
+ * @throws {@link InvalidTickError} If tick is not an integer in range [0, 990].
180
+ */
181
+ function tickToPrice(tick) {
182
+ assertTick(tick);
183
+ return divHalfDownUnchecked(divHalfDownUnchecked(WAD_SQUARED, WAD$1 + wExp(LN_ONE_PLUS_DELTA * (HALF_TICK_RANGE - BigInt(tick)))), PRICE_STEP) * PRICE_STEP;
184
+ }
185
+ /**
186
+ * Returns the lowest tick with a higher-or-equal price.
187
+ * @param price - Price in wad units.
188
+ * @returns The first tick whose {@link tickToPrice} is greater than or equal to `price`.
189
+ * @throws {@link InvalidPriceError} If price is outside [0, 1e18].
190
+ */
191
+ function priceToTick(price) {
192
+ assertPrice(price);
193
+ let low = 0;
194
+ let high = TICK_RANGE;
195
+ while (low !== high) {
196
+ const mid = Math.floor((low + high) / 2);
197
+ if (tickToPrice(mid) < price) low = mid + 1;
198
+ else high = mid;
199
+ }
200
+ return low;
201
+ }
202
+ function divHalfDownUnchecked(x, d) {
203
+ return (x + (d - 1n) / 2n) / d;
204
+ }
205
+ function wExp(x) {
206
+ if (x < 0n) return WAD_SQUARED / wExp(-x);
207
+ const q = (x + LN2 / 2n) / LN2;
208
+ const r = x - q * LN2;
209
+ const secondTerm = r * r / (2n * WAD$1);
210
+ const thirdTerm = secondTerm * r / (3n * WAD$1);
211
+ return WAD$1 + r + secondTerm + thirdTerm << q;
212
+ }
213
+ function assertTick(tick) {
214
+ if (!Number.isInteger(tick) || tick < 0 || tick > TICK_RANGE) throw new InvalidTickError(tick);
215
+ }
216
+ function assertPrice(price) {
217
+ if (price < 0n || price > MAX_PRICE) throw new InvalidPriceError(price);
218
+ }
219
+ var InvalidTickError = class extends BaseError {
220
+ constructor(tick) {
221
+ super(`Invalid tick: ${tick}. Tick must be an integer between 0 and ${TICK_RANGE}.`);
222
+ _defineProperty(this, "name", "Tick.InvalidTickError");
223
+ }
224
+ };
225
+ var InvalidPriceError = class extends BaseError {
226
+ constructor(price) {
227
+ super(`Invalid price: ${price}. Price must be between 0 and ${MAX_PRICE}.`);
228
+ _defineProperty(this, "name", "Tick.InvalidPriceError");
229
+ }
230
+ };
231
+
232
+ //#endregion
55
233
  //#region src/api/Schema/BookResponse.ts
56
234
  var BookResponse_exports = /* @__PURE__ */ __exportAll({ from: () => from$15 });
57
235
  function from$15(level) {
236
+ const price = tickToPrice(level.tick);
58
237
  return {
59
- price: level.price.toString(),
238
+ tick: level.tick,
239
+ price: price.toString(),
60
240
  assets: level.assets.toString(),
61
241
  count: level.count
62
242
  };
@@ -404,105 +584,6 @@ function* batch$1(array, batchSize) {
404
584
  for (let i = 0; i < array.length; i += batchSize) yield array.slice(i, i + batchSize);
405
585
  }
406
586
 
407
- //#endregion
408
- //#region \0@oxc-project+runtime@0.110.0/helpers/typeof.js
409
- function _typeof(o) {
410
- "@babel/helpers - typeof";
411
- return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
412
- return typeof o;
413
- } : function(o) {
414
- return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
415
- }, _typeof(o);
416
- }
417
-
418
- //#endregion
419
- //#region \0@oxc-project+runtime@0.110.0/helpers/toPrimitive.js
420
- function toPrimitive(t, r) {
421
- if ("object" != _typeof(t) || !t) return t;
422
- var e = t[Symbol.toPrimitive];
423
- if (void 0 !== e) {
424
- var i = e.call(t, r || "default");
425
- if ("object" != _typeof(i)) return i;
426
- throw new TypeError("@@toPrimitive must return a primitive value.");
427
- }
428
- return ("string" === r ? String : Number)(t);
429
- }
430
-
431
- //#endregion
432
- //#region \0@oxc-project+runtime@0.110.0/helpers/toPropertyKey.js
433
- function toPropertyKey(t) {
434
- var i = toPrimitive(t, "string");
435
- return "symbol" == _typeof(i) ? i : i + "";
436
- }
437
-
438
- //#endregion
439
- //#region \0@oxc-project+runtime@0.110.0/helpers/defineProperty.js
440
- function _defineProperty(e, r, t) {
441
- return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
442
- value: t,
443
- enumerable: !0,
444
- configurable: !0,
445
- writable: !0
446
- }) : e[r] = t, e;
447
- }
448
-
449
- //#endregion
450
- //#region src/utils/Errors.ts
451
- var Errors_exports = /* @__PURE__ */ __exportAll({
452
- BaseError: () => BaseError,
453
- ReorgError: () => ReorgError
454
- });
455
- /**
456
- * Base error class inherited by all errors thrown by mempool.
457
- *
458
- * @example
459
- * ```ts
460
- * import { Errors } from 'mempool'
461
- * throw new Errors.BaseError('An error occurred')
462
- * ```
463
- */
464
- var BaseError = class BaseError extends Error {
465
- constructor(shortMessage, options = {}) {
466
- const details = (() => {
467
- if (options.cause instanceof BaseError) {
468
- if (options.cause.details) return options.cause.details;
469
- if (options.cause.shortMessage) return options.cause.shortMessage;
470
- }
471
- if (options.cause && "details" in options.cause && typeof options.cause.details === "string") return options.cause.details;
472
- if (options.cause?.message) return options.cause.message;
473
- return options.details;
474
- })();
475
- const message = [
476
- shortMessage || "An error occurred.",
477
- ...options.metaMessages ? ["", ...options.metaMessages] : [],
478
- ...details ? ["", details ? `Details: ${details}` : void 0] : []
479
- ].filter((x) => typeof x === "string").join("\n");
480
- super(message, options.cause ? { cause: options.cause } : void 0);
481
- _defineProperty(this, "details", void 0);
482
- _defineProperty(this, "shortMessage", void 0);
483
- _defineProperty(this, "cause", void 0);
484
- _defineProperty(this, "name", "BaseError");
485
- this.cause = options.cause;
486
- this.details = details;
487
- this.shortMessage = shortMessage;
488
- }
489
- walk(fn) {
490
- return walk(this, fn);
491
- }
492
- };
493
- /** @internal */
494
- function walk(err, fn) {
495
- if (fn?.(err)) return err;
496
- if (err && typeof err === "object" && "cause" in err && err.cause) return walk(err.cause, fn);
497
- return fn ? null : err;
498
- }
499
- var ReorgError = class extends BaseError {
500
- constructor(blockNumber) {
501
- super(`Reorg detected at block number ${blockNumber}`);
502
- _defineProperty(this, "name", "ReorgError");
503
- }
504
- };
505
-
506
587
  //#endregion
507
588
  //#region src/core/Chain.ts
508
589
  var Chain_exports = /* @__PURE__ */ __exportAll({
@@ -1549,7 +1630,7 @@ const OfferSchema = () => {
1549
1630
  assets: zod.bigint({ coerce: true }).min(0n).max(viem.maxUint256),
1550
1631
  obligationUnits: zod.bigint({ coerce: true }).min(0n).max(viem.maxUint256).optional().default(0n),
1551
1632
  obligationShares: zod.bigint({ coerce: true }).min(0n).max(viem.maxUint256).optional().default(0n),
1552
- price: zod.bigint({ coerce: true }).min(0n).max(viem.maxUint256),
1633
+ tick: zod.coerce.number().int().min(0).max(990),
1553
1634
  maturity: MaturitySchema,
1554
1635
  expiry: zod.number().int().max(Number.MAX_SAFE_INTEGER),
1555
1636
  start: zod.number().int().max(Number.MAX_SAFE_INTEGER),
@@ -1621,7 +1702,7 @@ const serialize = (offer) => ({
1621
1702
  assets: offer.assets.toString(),
1622
1703
  obligationUnits: offer.obligationUnits.toString(),
1623
1704
  obligationShares: offer.obligationShares.toString(),
1624
- price: offer.price.toString(),
1705
+ tick: offer.tick,
1625
1706
  maturity: Number(offer.maturity),
1626
1707
  expiry: Number(offer.expiry),
1627
1708
  start: Number(offer.start),
@@ -1666,14 +1747,13 @@ function random$1(config) {
1666
1747
  [.98, 2]
1667
1748
  ]));
1668
1749
  const buy = config?.buy !== void 0 ? config.buy : bool();
1669
- const ONE = 1000000000000000000n;
1670
- const qMin = buy ? 16 : 4;
1671
- const len = (buy ? 32 : 16) - qMin + 1;
1672
- const pricePairs = Array.from({ length: len }, (_, idx) => {
1673
- const q = qMin + idx;
1674
- return [BigInt(q) * (ONE / 4n), buy ? 1 + idx : 1 + (len - 1 - idx)];
1750
+ const tickMin = buy ? 0 : 495;
1751
+ const len = (buy ? 495 : 990) - tickMin + 1;
1752
+ const tickPairs = Array.from({ length: len }, (_, idx) => {
1753
+ const weight = buy ? 1 + idx : 1 + (len - 1 - idx);
1754
+ return [tickMin + idx, weight];
1675
1755
  });
1676
- const price = config?.price ?? weightedChoice(pricePairs);
1756
+ const tick = config?.tick ?? weightedChoice(tickPairs);
1677
1757
  const loanTokenDecimals = config?.assetsDecimals?.[loanToken] ?? 18;
1678
1758
  const unit = BigInt(10) ** BigInt(loanTokenDecimals);
1679
1759
  const amountBase = BigInt(100 + int(999901));
@@ -1687,7 +1767,7 @@ function random$1(config) {
1687
1767
  assets: assetsScaled,
1688
1768
  obligationUnits: config?.obligationUnits ?? 0n,
1689
1769
  obligationShares: config?.obligationShares ?? 0n,
1690
- price,
1770
+ tick,
1691
1771
  maturity,
1692
1772
  expiry: config?.expiry ?? maturity - 1,
1693
1773
  start: config?.start ?? maturity - 10,
@@ -1752,7 +1832,7 @@ const types = {
1752
1832
  type: "uint256"
1753
1833
  },
1754
1834
  {
1755
- name: "price",
1835
+ name: "tick",
1756
1836
  type: "uint256"
1757
1837
  },
1758
1838
  {
@@ -1820,7 +1900,7 @@ function hash(offer) {
1820
1900
  assets: offer.assets,
1821
1901
  obligationUnits: offer.obligationUnits,
1822
1902
  obligationShares: offer.obligationShares,
1823
- price: offer.price,
1903
+ tick: BigInt(offer.tick),
1824
1904
  maturity: BigInt(offer.maturity),
1825
1905
  expiry: BigInt(offer.expiry),
1826
1906
  group: offer.group,
@@ -1871,7 +1951,7 @@ const OfferAbi = [
1871
1951
  type: "uint256"
1872
1952
  },
1873
1953
  {
1874
- name: "price",
1954
+ name: "tick",
1875
1955
  type: "uint256"
1876
1956
  },
1877
1957
  {
@@ -1942,7 +2022,7 @@ function encode$1(offer) {
1942
2022
  offer.assets,
1943
2023
  offer.obligationUnits,
1944
2024
  offer.obligationShares,
1945
- offer.price,
2025
+ BigInt(offer.tick),
1946
2026
  BigInt(offer.maturity),
1947
2027
  BigInt(offer.expiry),
1948
2028
  offer.group,
@@ -1967,7 +2047,7 @@ function decode$1(data) {
1967
2047
  assets: decoded[1],
1968
2048
  obligationUnits: decoded[2],
1969
2049
  obligationShares: decoded[3],
1970
- price: decoded[4],
2050
+ tick: Number(decoded[4]),
1971
2051
  maturity: from$11(Number(decoded[5])),
1972
2052
  expiry: Number(decoded[6]),
1973
2053
  group: decoded[7],
@@ -2868,7 +2948,7 @@ function from$2(input) {
2868
2948
  obligation_shares: input.obligationShares.toString(),
2869
2949
  start: input.start,
2870
2950
  expiry: input.expiry,
2871
- price: input.price.toString(),
2951
+ tick: input.tick,
2872
2952
  group: input.group,
2873
2953
  session: input.session,
2874
2954
  callback: input.callback.address,
@@ -2941,7 +3021,7 @@ const offerExample = {
2941
3021
  obligation_shares: "0",
2942
3022
  start: 1761922790,
2943
3023
  expiry: 1761922799,
2944
- price: "2750000000000000000",
3024
+ tick: 495,
2945
3025
  group: "0x000000000000000000000000000000000000000000000000000000000008b8f4",
2946
3026
  session: "0x0000000000000000000000000000000000000000000000000000000000000000",
2947
3027
  callback: "0x0000000000000000000000000000000000000000",
@@ -2982,7 +3062,7 @@ const validateOfferExample = {
2982
3062
  assets: "369216000000000000000000",
2983
3063
  obligation_units: "0",
2984
3064
  obligation_shares: "0",
2985
- price: "2750000000000000000",
3065
+ tick: 495,
2986
3066
  maturity: 1761922799,
2987
3067
  expiry: 1761922799,
2988
3068
  start: 1761922790,
@@ -3126,9 +3206,11 @@ __decorate([(0, openapi_metadata_decorators.ApiProperty)({
3126
3206
  example: offerExample.offer.expiry
3127
3207
  })], OfferDataResponse.prototype, "expiry", void 0);
3128
3208
  __decorate([(0, openapi_metadata_decorators.ApiProperty)({
3129
- type: "string",
3130
- example: offerExample.offer.price
3131
- })], OfferDataResponse.prototype, "price", void 0);
3209
+ type: "number",
3210
+ example: offerExample.offer.tick,
3211
+ minimum: 0,
3212
+ maximum: 990
3213
+ })], OfferDataResponse.prototype, "tick", void 0);
3132
3214
  __decorate([(0, openapi_metadata_decorators.ApiProperty)({
3133
3215
  type: "string",
3134
3216
  example: offerExample.offer.group
@@ -3369,9 +3451,11 @@ __decorate([(0, openapi_metadata_decorators.ApiProperty)({
3369
3451
  required: false
3370
3452
  })], ValidateOfferRequest.prototype, "obligation_shares", void 0);
3371
3453
  __decorate([(0, openapi_metadata_decorators.ApiProperty)({
3372
- type: "string",
3373
- example: validateOfferExample.price
3374
- })], ValidateOfferRequest.prototype, "price", void 0);
3454
+ type: "number",
3455
+ example: validateOfferExample.tick,
3456
+ minimum: 0,
3457
+ maximum: 990
3458
+ })], ValidateOfferRequest.prototype, "tick", void 0);
3375
3459
  __decorate([(0, openapi_metadata_decorators.ApiProperty)({
3376
3460
  type: "number",
3377
3461
  example: validateOfferExample.maturity
@@ -3471,9 +3555,16 @@ __decorate([(0, openapi_metadata_decorators.ApiProperty)({
3471
3555
  description: "List of validation issues. Returned when any offer fails validation."
3472
3556
  })], ValidationFailureResponse.prototype, "data", void 0);
3473
3557
  var BookLevelResponse = class {};
3558
+ __decorate([(0, openapi_metadata_decorators.ApiProperty)({
3559
+ type: "number",
3560
+ example: 495,
3561
+ minimum: 0,
3562
+ maximum: 990
3563
+ })], BookLevelResponse.prototype, "tick", void 0);
3474
3564
  __decorate([(0, openapi_metadata_decorators.ApiProperty)({
3475
3565
  type: "string",
3476
- example: "2750000000000000000"
3566
+ example: "500000000000000000",
3567
+ description: "Price derived from tick, scaled by 1e18."
3477
3568
  })], BookLevelResponse.prototype, "price", void 0);
3478
3569
  __decorate([(0, openapi_metadata_decorators.ApiProperty)({
3479
3570
  type: "string",
@@ -3487,6 +3578,7 @@ const positionExample = {
3487
3578
  chain_id: 1,
3488
3579
  contract: "0xC9A9C45C0eB717f8b5F193Af6bAa05A1c0Ac5078",
3489
3580
  user: "0x7b093658BE7f90B63D7c359e8f408e503c2D9401",
3581
+ obligation_id: "0x12590ae1aee324a005be565f3bcdd16dbf8daf7969b26c181c8b8f467dad9f67",
3490
3582
  reserved: "200000000000000000000",
3491
3583
  block_number: 21345678
3492
3584
  };
@@ -3503,6 +3595,12 @@ __decorate([(0, openapi_metadata_decorators.ApiProperty)({
3503
3595
  type: "string",
3504
3596
  example: positionExample.user
3505
3597
  })], PositionListItemResponse.prototype, "user", void 0);
3598
+ __decorate([(0, openapi_metadata_decorators.ApiProperty)({
3599
+ type: "string",
3600
+ nullable: true,
3601
+ example: positionExample.obligation_id,
3602
+ description: "Obligation id this reserved amount belongs to, or null if no lots exist."
3603
+ })], PositionListItemResponse.prototype, "obligation_id", void 0);
3506
3604
  __decorate([(0, openapi_metadata_decorators.ApiProperty)({
3507
3605
  type: "string",
3508
3606
  example: positionExample.reserved
@@ -3530,7 +3628,7 @@ __decorate([(0, openapi_metadata_decorators.ApiProperty)({
3530
3628
  })], BookListResponse.prototype, "cursor", void 0);
3531
3629
  __decorate([(0, openapi_metadata_decorators.ApiProperty)({
3532
3630
  type: () => [BookLevelResponse],
3533
- description: "Aggregated book levels grouped by computed price."
3631
+ description: "Aggregated book levels grouped by offer tick."
3534
3632
  })], BookListResponse.prototype, "data", void 0);
3535
3633
  let BooksController = class BooksController {
3536
3634
  async getBook() {}
@@ -3540,7 +3638,7 @@ __decorate([
3540
3638
  methods: ["get"],
3541
3639
  path: "/v1/books/{obligationId}/{side}",
3542
3640
  summary: "Get aggregated book",
3543
- description: "Returns aggregated book data for a given obligation and side. Offers are grouped by computed price with summed takeable amounts. Book levels are sorted by price (ascending for buy side, descending for sell side)."
3641
+ description: "Returns aggregated book data for a given obligation and side. Offers are grouped by tick with summed takeable amounts, and each level includes the corresponding wad-scaled price. Book levels are sorted by tick (ascending for sell side, descending for buy side)."
3544
3642
  }),
3545
3643
  (0, openapi_metadata_decorators.ApiParam)({
3546
3644
  name: "obligationId",
@@ -3565,7 +3663,7 @@ __decorate([
3565
3663
  name: "limit",
3566
3664
  type: "number",
3567
3665
  example: 10,
3568
- description: "Maximum number of price levels to return."
3666
+ description: "Maximum number of tick levels to return."
3569
3667
  }),
3570
3668
  (0, openapi_metadata_decorators.ApiResponse)({
3571
3669
  status: 200,
@@ -3759,6 +3857,11 @@ const configRulesLoanTokenExample = {
3759
3857
  chain_id: 1,
3760
3858
  address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
3761
3859
  };
3860
+ const configRulesCollateralTokenExample = {
3861
+ type: "collateral_token",
3862
+ chain_id: 1,
3863
+ address: "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0"
3864
+ };
3762
3865
  const configRulesOracleExample = {
3763
3866
  type: "oracle",
3764
3867
  chain_id: 1,
@@ -3768,6 +3871,7 @@ const configRulesChecksumExample = "f1d2d2f924e986ac86fdf7b36c94bcdf";
3768
3871
  const configRulesPayloadExample = [
3769
3872
  configRulesMaturityExample,
3770
3873
  configRulesLoanTokenExample,
3874
+ configRulesCollateralTokenExample,
3771
3875
  configRulesOracleExample
3772
3876
  ];
3773
3877
  const configContractNames = [
@@ -3894,7 +3998,7 @@ __decorate([
3894
3998
  methods: ["get"],
3895
3999
  path: "/v1/config/rules",
3896
4000
  summary: "Get config rules",
3897
- description: "Returns configured rules (maturities, loan tokens, oracles) for supported chains."
4001
+ description: "Returns configured rules (maturities, loan tokens, collateral tokens, oracles) for supported chains."
3898
4002
  }),
3899
4003
  (0, openapi_metadata_decorators.ApiQuery)({
3900
4004
  name: "cursor",
@@ -3914,7 +4018,7 @@ __decorate([
3914
4018
  name: "types",
3915
4019
  type: ["string"],
3916
4020
  required: false,
3917
- example: "maturity,loan_token,oracle",
4021
+ example: "maturity,loan_token,collateral_token,oracle",
3918
4022
  description: "Filter by rule types (comma-separated).",
3919
4023
  style: "form",
3920
4024
  explode: false
@@ -4032,7 +4136,7 @@ __decorate([
4032
4136
  methods: ["get"],
4033
4137
  path: "/v1/users/{userAddress}/positions",
4034
4138
  summary: "Get user positions",
4035
- description: "Returns positions for a user with reserved balance. The reserved balance is the amount locked by active offers (max lot upper - offset - consumed)."
4139
+ description: "Returns positions for a user with reserved balance per obligation. Each (position, obligation) pair is returned as a separate row. Positions with no lots return a single row with obligation_id = null and reserved = 0."
4036
4140
  }),
4037
4141
  (0, openapi_metadata_decorators.ApiParam)({
4038
4142
  name: "userAddress",
@@ -4120,6 +4224,7 @@ function from$1(position) {
4120
4224
  chain_id: position.chainId,
4121
4225
  contract: position.contract,
4122
4226
  user: position.user,
4227
+ obligation_id: position.obligationId,
4123
4228
  reserved: position.reserved.toString(),
4124
4229
  block_number: position.blockNumber
4125
4230
  };
@@ -4173,10 +4278,11 @@ const ConfigRuleTypes = zod.enum([
4173
4278
  "maturity",
4174
4279
  "callback",
4175
4280
  "loan_token",
4281
+ "collateral_token",
4176
4282
  "oracle"
4177
4283
  ]);
4178
4284
  const GetConfigRulesQueryParams = zod.object({
4179
- cursor: zod.string().regex(/^(maturity|callback|loan_token|oracle):[1-9]\d*:.+$/, { message: "Cursor must be in the format type:chain_id:<value>" }).optional().meta({
4285
+ cursor: zod.string().regex(/^(maturity|callback|loan_token|collateral_token|oracle):[1-9]\d*:.+$/, { message: "Cursor must be in the format type:chain_id:<value>" }).optional().meta({
4180
4286
  description: "Pagination cursor in type:chain_id:<value> format",
4181
4287
  example: "maturity:1:1730415600:end_of_next_month"
4182
4288
  }),
@@ -4186,7 +4292,7 @@ const GetConfigRulesQueryParams = zod.object({
4186
4292
  }),
4187
4293
  types: csvArray(ConfigRuleTypes).meta({
4188
4294
  description: "Filter by rule types (comma-separated).",
4189
- example: "maturity,loan_token,oracle"
4295
+ example: "maturity,loan_token,collateral_token,oracle"
4190
4296
  }),
4191
4297
  chains: csvArray(zod.string().regex(/^[1-9]\d*$/, { message: "Chain must be a positive integer" }).transform((val) => Number.parseInt(val, 10))).meta({
4192
4298
  description: "Filter by chain IDs (comma-separated).",
@@ -4286,12 +4392,11 @@ const GetObligationParams = zod.object({ obligation_id: zod.string({ error: "Obl
4286
4392
  description: "Obligation id",
4287
4393
  example: "0x1234567890123456789012345678901234567890123456789012345678901234"
4288
4394
  }) });
4289
- /** Validate a book cursor format: {side, lastPrice, offersCursor} */
4395
+ /** Validate a book cursor format: {side, lastTick, offersCursor} */
4290
4396
  function isValidBookCursor(cursorString) {
4291
- const isNumericString = (value) => typeof value === "string" && /^-?\d+$/.test(value);
4292
4397
  try {
4293
4398
  const v = JSON.parse(Buffer.from(cursorString, "base64url").toString("utf8"));
4294
- return (v?.side === "buy" || v?.side === "sell") && isNumericString(v?.lastPrice) && (v?.offersCursor === null || typeof v?.offersCursor === "string");
4399
+ return (v?.side === "buy" || v?.side === "sell") && typeof v?.lastTick === "number" && Number.isInteger(v.lastTick) && (v?.offersCursor === null || typeof v?.offersCursor === "string");
4295
4400
  } catch {
4296
4401
  return false;
4297
4402
  }
@@ -4452,7 +4557,7 @@ async function getOffers(apiClient, parameters) {
4452
4557
  assets: offerData.assets,
4453
4558
  obligation_units: offerData.obligation_units,
4454
4559
  obligation_shares: offerData.obligation_shares,
4455
- price: offerData.price,
4560
+ tick: offerData.tick,
4456
4561
  maturity: from$11(offerData.obligation.maturity),
4457
4562
  expiry: offerData.expiry,
4458
4563
  start: offerData.start,
@@ -4800,6 +4905,33 @@ const assets = {
4800
4905
  "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"
4801
4906
  ]
4802
4907
  };
4908
+ const collateralAssets = {
4909
+ [ChainId.ETHEREUM.toString()]: [
4910
+ "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
4911
+ "0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c",
4912
+ "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",
4913
+ "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0"
4914
+ ],
4915
+ [ChainId.BASE.toString()]: [
4916
+ "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
4917
+ "0x4200000000000000000000000000000000000006",
4918
+ "0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf",
4919
+ "0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452",
4920
+ "0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42"
4921
+ ],
4922
+ [ChainId["ETHEREUM-VIRTUAL-TESTNET"].toString()]: [
4923
+ "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
4924
+ "0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c",
4925
+ "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",
4926
+ "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0"
4927
+ ],
4928
+ [ChainId.ANVIL.toString()]: [
4929
+ "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
4930
+ "0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c",
4931
+ "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",
4932
+ "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0"
4933
+ ]
4934
+ };
4803
4935
  const oracles = {
4804
4936
  [ChainId.ETHEREUM.toString()]: [
4805
4937
  "0xDddd770BADd886dF3864029e4B377B5F6a2B6b83",
@@ -4862,10 +4994,11 @@ var Rules_exports = /* @__PURE__ */ __exportAll({
4862
4994
  amountMutualExclusivity: () => amountMutualExclusivity,
4863
4995
  callback: () => callback,
4864
4996
  chains: () => chains,
4997
+ collateralToken: () => collateralToken,
4998
+ loanToken: () => loanToken,
4865
4999
  maturity: () => maturity,
4866
5000
  oracle: () => oracle,
4867
5001
  sameMaker: () => sameMaker,
4868
- token: () => token,
4869
5002
  validity: () => validity
4870
5003
  });
4871
5004
  /**
@@ -4893,15 +5026,25 @@ const callback = ({ callbacks }) => single("callback", `Validates callbacks: buy
4893
5026
  if (isEmptyCallback(offer) && !offer.buy && !callbacks.includes(Type$1.SellWithEmptyCallback)) return { message: "Sell offers with empty callback not allowed." };
4894
5027
  });
4895
5028
  /**
4896
- * A validation rule that checks if the offer's tokens are allowed for its chain.
4897
- * @param assetsByChainId - Allowed assets indexed by chain id.
5029
+ * A validation rule that checks if the offer's loan token is allowed for its chain.
5030
+ * @param assetsByChainId - Allowed loan tokens indexed by chain id.
4898
5031
  * @returns The issue that was found. If the offer is valid, this will be undefined.
4899
5032
  */
4900
- const token = ({ assetsByChainId }) => single("token", "Validates that offer loan token and collateral tokens are in the allowed assets list for the offer chain", (offer) => {
4901
- const allowedAssets = assetsByChainId[offer.chainId]?.map((asset) => asset.toLowerCase());
4902
- if (!allowedAssets || allowedAssets.length === 0) return { message: `No allowed assets for chain ${offer.chainId}` };
4903
- if (!allowedAssets.includes(offer.loanToken.toLowerCase())) return { message: "Loan token is not allowed" };
4904
- if (offer.collaterals.some((collateral) => !allowedAssets.includes(collateral.asset.toLowerCase()))) return { message: "Collateral is not allowed" };
5033
+ const loanToken = ({ assetsByChainId }) => single("loan_token", "Validates that offer loan token is in the allowed token list for the offer chain", (offer) => {
5034
+ const allowedLoanTokens = assetsByChainId[offer.chainId]?.map((asset) => asset.toLowerCase());
5035
+ if (!allowedLoanTokens || allowedLoanTokens.length === 0) return { message: `No allowed loan tokens for chain ${offer.chainId}` };
5036
+ if (!allowedLoanTokens.includes(offer.loanToken.toLowerCase())) return { message: "Loan token is not allowed" };
5037
+ });
5038
+ /**
5039
+ * A validation rule that checks if the offer's collateral tokens are allowed for its chain.
5040
+ * @param collateralAssetsByChainId - Allowed collateral tokens indexed by chain id.
5041
+ * @returns The issue that was found. If the offer is valid, this will be undefined.
5042
+ */
5043
+ const collateralToken = ({ collateralAssetsByChainId }) => single("collateral_token", "Validates that offer collateral tokens are in the allowed token list for the offer chain", (offer) => {
5044
+ const allowedCollateralTokens = collateralAssetsByChainId[offer.chainId]?.map((asset) => asset.toLowerCase()) ?? [];
5045
+ if (allowedCollateralTokens.length === 0) return { message: `No allowed collateral tokens for chain ${offer.chainId}` };
5046
+ if (offer.collaterals.length === 0) return { message: "At least one collateral token is required" };
5047
+ if (offer.collaterals.some((collateral) => !allowedCollateralTokens.includes(collateral.asset.toLowerCase()))) return { message: "Collateral token is not allowed" };
4905
5048
  });
4906
5049
  /**
4907
5050
  * A validation rule that checks if the offer's oracle addresses are allowed for its chain.
@@ -4944,9 +5087,11 @@ const amountMutualExclusivity = () => single("amount_mutual_exclusivity", "Valid
4944
5087
  //#region src/gatekeeper/morphoRules.ts
4945
5088
  const morphoRules = (chains$2) => {
4946
5089
  const assetsByChainId = {};
5090
+ const collateralAssetsByChainId = {};
4947
5091
  const oraclesByChainId = {};
4948
5092
  for (const chain of chains$2) {
4949
5093
  assetsByChainId[chain.id] = assets[chain.id.toString()] ?? [];
5094
+ collateralAssetsByChainId[chain.id] = collateralAssets[chain.id.toString()] ?? [];
4950
5095
  oraclesByChainId[chain.id] = oracles[chain.id.toString()] ?? [];
4951
5096
  }
4952
5097
  return [
@@ -4958,7 +5103,8 @@ const morphoRules = (chains$2) => {
4958
5103
  callbacks: [Type$1.BuyWithEmptyCallback, Type$1.SellWithEmptyCallback],
4959
5104
  allowedAddresses: []
4960
5105
  }),
4961
- token({ assetsByChainId }),
5106
+ loanToken({ assetsByChainId }),
5107
+ collateralToken({ collateralAssetsByChainId }),
4962
5108
  oracle({ oraclesByChainId })
4963
5109
  ];
4964
5110
  };
@@ -5417,6 +5563,12 @@ Object.defineProperty(exports, 'Rules', {
5417
5563
  return Rules_exports;
5418
5564
  }
5419
5565
  });
5566
+ Object.defineProperty(exports, 'Tick', {
5567
+ enumerable: true,
5568
+ get: function () {
5569
+ return Tick_exports;
5570
+ }
5571
+ });
5420
5572
  Object.defineProperty(exports, 'Time', {
5421
5573
  enumerable: true,
5422
5574
  get: function () {