@morpho-org/midnight-sdk 0.1.0 → 1.0.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 (118) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +56 -46
  3. package/lib/cjs/abis.d.ts +1185 -996
  4. package/lib/cjs/abis.js +1445 -1211
  5. package/lib/cjs/api/MidnightApi.d.ts +22 -16
  6. package/lib/cjs/api/MidnightApi.js +22 -16
  7. package/lib/cjs/api/helpers.js +6 -3
  8. package/lib/cjs/api/types.d.ts +35 -9
  9. package/lib/cjs/constants.d.ts +12 -11
  10. package/lib/cjs/constants.js +14 -12
  11. package/lib/cjs/errors.d.ts +74 -1
  12. package/lib/cjs/errors.js +94 -3
  13. package/lib/cjs/fetch/Market.js +0 -1
  14. package/lib/cjs/fetch/index.d.ts +0 -1
  15. package/lib/cjs/fetch/index.js +0 -1
  16. package/lib/cjs/index.d.ts +1 -1
  17. package/lib/cjs/index.js +2 -23
  18. package/lib/cjs/market/Market.d.ts +99 -33
  19. package/lib/cjs/market/Market.js +137 -28
  20. package/lib/cjs/market/MarketUtils.d.ts +61 -41
  21. package/lib/cjs/market/MarketUtils.js +108 -48
  22. package/lib/cjs/market/Position.d.ts +16 -11
  23. package/lib/cjs/market/Position.js +18 -12
  24. package/lib/cjs/market/PositionUtils.d.ts +6 -4
  25. package/lib/cjs/market/PositionUtils.js +9 -6
  26. package/lib/cjs/math/TickLib.d.ts +22 -0
  27. package/lib/cjs/math/TickLib.js +30 -0
  28. package/lib/cjs/math/index.d.ts +0 -1
  29. package/lib/cjs/math/index.js +0 -1
  30. package/lib/cjs/offers/Offer.d.ts +217 -11
  31. package/lib/cjs/offers/Offer.js +215 -7
  32. package/lib/cjs/offers/OfferUtils.d.ts +245 -139
  33. package/lib/cjs/offers/OfferUtils.js +304 -36
  34. package/lib/cjs/queries/GetPosition.d.ts +1 -1
  35. package/lib/cjs/queries/GetPosition.js +1 -1
  36. package/lib/cjs/signatures/EcrecoverRatifierUtils.d.ts +66 -38
  37. package/lib/cjs/signatures/EcrecoverRatifierUtils.js +147 -79
  38. package/lib/cjs/signatures/Group.d.ts +12 -4
  39. package/lib/cjs/signatures/Group.js +12 -4
  40. package/lib/cjs/signatures/GroupUtils.d.ts +12 -4
  41. package/lib/cjs/signatures/GroupUtils.js +6 -2
  42. package/lib/cjs/signatures/Payload.d.ts +277 -277
  43. package/lib/cjs/signatures/Payload.js +517 -534
  44. package/lib/cjs/signatures/RatifierUtils.d.ts +57 -0
  45. package/lib/cjs/signatures/RatifierUtils.js +94 -0
  46. package/lib/cjs/signatures/SetterRatifierUtils.d.ts +21 -13
  47. package/lib/cjs/signatures/SetterRatifierUtils.js +25 -20
  48. package/lib/cjs/signatures/Tree.d.ts +28 -16
  49. package/lib/cjs/signatures/Tree.js +25 -13
  50. package/lib/cjs/signatures/TreeUtils.d.ts +181 -62
  51. package/lib/cjs/signatures/TreeUtils.js +73 -76
  52. package/lib/cjs/signatures/index.d.ts +1 -0
  53. package/lib/cjs/signatures/index.js +3 -0
  54. package/lib/cjs/signatures/offerStructInternal.d.ts +14 -0
  55. package/lib/cjs/signatures/offerStructInternal.js +72 -0
  56. package/lib/esm/abis.d.ts +1185 -996
  57. package/lib/esm/abis.js +1445 -1211
  58. package/lib/esm/api/MidnightApi.d.ts +22 -16
  59. package/lib/esm/api/MidnightApi.js +23 -17
  60. package/lib/esm/api/helpers.js +6 -3
  61. package/lib/esm/api/types.d.ts +35 -9
  62. package/lib/esm/constants.d.ts +12 -11
  63. package/lib/esm/constants.js +13 -11
  64. package/lib/esm/errors.d.ts +74 -1
  65. package/lib/esm/errors.js +89 -2
  66. package/lib/esm/fetch/Market.js +0 -1
  67. package/lib/esm/fetch/index.d.ts +0 -1
  68. package/lib/esm/fetch/index.js +0 -1
  69. package/lib/esm/index.d.ts +1 -1
  70. package/lib/esm/index.js +1 -1
  71. package/lib/esm/market/Market.d.ts +99 -33
  72. package/lib/esm/market/Market.js +137 -28
  73. package/lib/esm/market/MarketUtils.d.ts +61 -41
  74. package/lib/esm/market/MarketUtils.js +109 -49
  75. package/lib/esm/market/Position.d.ts +16 -11
  76. package/lib/esm/market/Position.js +19 -13
  77. package/lib/esm/market/PositionUtils.d.ts +6 -4
  78. package/lib/esm/market/PositionUtils.js +9 -6
  79. package/lib/esm/math/TickLib.d.ts +22 -0
  80. package/lib/esm/math/TickLib.js +31 -1
  81. package/lib/esm/math/index.d.ts +0 -1
  82. package/lib/esm/math/index.js +0 -1
  83. package/lib/esm/offers/Offer.d.ts +217 -11
  84. package/lib/esm/offers/Offer.js +216 -8
  85. package/lib/esm/offers/OfferUtils.d.ts +245 -139
  86. package/lib/esm/offers/OfferUtils.js +306 -38
  87. package/lib/esm/queries/GetPosition.d.ts +1 -1
  88. package/lib/esm/queries/GetPosition.js +1 -1
  89. package/lib/esm/signatures/EcrecoverRatifierUtils.d.ts +66 -38
  90. package/lib/esm/signatures/EcrecoverRatifierUtils.js +149 -81
  91. package/lib/esm/signatures/Group.d.ts +12 -4
  92. package/lib/esm/signatures/Group.js +12 -4
  93. package/lib/esm/signatures/GroupUtils.d.ts +12 -4
  94. package/lib/esm/signatures/GroupUtils.js +6 -2
  95. package/lib/esm/signatures/Payload.d.ts +277 -277
  96. package/lib/esm/signatures/Payload.js +517 -531
  97. package/lib/esm/signatures/RatifierUtils.d.ts +57 -0
  98. package/lib/esm/signatures/RatifierUtils.js +94 -0
  99. package/lib/esm/signatures/SetterRatifierUtils.d.ts +21 -13
  100. package/lib/esm/signatures/SetterRatifierUtils.js +25 -20
  101. package/lib/esm/signatures/Tree.d.ts +28 -16
  102. package/lib/esm/signatures/Tree.js +25 -13
  103. package/lib/esm/signatures/TreeUtils.d.ts +181 -62
  104. package/lib/esm/signatures/TreeUtils.js +75 -78
  105. package/lib/esm/signatures/index.d.ts +1 -0
  106. package/lib/esm/signatures/index.js +1 -0
  107. package/lib/esm/signatures/offerStructInternal.d.ts +14 -0
  108. package/lib/esm/signatures/offerStructInternal.js +67 -0
  109. package/package.json +28 -32
  110. package/src/index.ts +1 -1
  111. package/lib/cjs/fetch/Offer.d.ts +0 -74
  112. package/lib/cjs/fetch/Offer.js +0 -119
  113. package/lib/cjs/math/ConsumableUnitsLib.d.ts +0 -57
  114. package/lib/cjs/math/ConsumableUnitsLib.js +0 -77
  115. package/lib/esm/fetch/Offer.d.ts +0 -74
  116. package/lib/esm/fetch/Offer.js +0 -116
  117. package/lib/esm/math/ConsumableUnitsLib.d.ts +0 -57
  118. package/lib/esm/math/ConsumableUnitsLib.js +0 -74
@@ -6,28 +6,31 @@ const viem_1 = require("viem");
6
6
  const actions_1 = require("viem/actions");
7
7
  const constants_js_1 = require("../constants.js");
8
8
  const errors_js_1 = require("../errors.js");
9
+ const index_js_1 = require("../market/index.js");
10
+ const RatifierUtils_js_1 = require("./RatifierUtils.js");
11
+ const TreeUtils_js_1 = require("./TreeUtils.js");
9
12
  const treeTypeHashes = [
10
- "0xc27c38e446b48c820ab9c4373dc63a4a750a08165cb4bb488206ebabe045d650",
11
- "0x4e15d8736f4406e07bf9844b1653474472a827130c61e899bf1f574a88b8d987",
12
- "0x46d107447b480c38ef5b7f54603dba0cb23b887f302b01a998b9d8a80320dd53",
13
- "0xd1f3607a8e81454bb3baf5f898274ab47541fffc690278a74f13e174e116be72",
14
- "0xb2d98adca9d116c9bc02ce59ec599ac3c2d33db1c0d1217c7e411d9198d427be",
15
- "0x5931e0597fcf986027f3118b2495a9ac22139d133f9ad2c2198e6738dc3886c5",
16
- "0x3967d37928614a085b47e8758fbc3869a8aed63bdf60ccee8536ff2b5064da06",
17
- "0xd6b9f5f45915a260f6e521d9b40f86c385730b6bc330590fcde212e2fea64263",
18
- "0x080caa519dbd5328c119d9907e0fa3d9a50dc2ae4bf6dd42c93c100dbc89b51a",
19
- "0x45da471048924165ea2ad1855ba940e454b486e71dcf1666c71a928c8844c419",
20
- "0xa49a9434fc1836bd08097368325b31039b6a0fd44919f53e4d8f4bf814084cb0",
21
- "0xd3e93e4525132f0187a6964dc01fef33fde414538ffd212e9f2f478c3263e0a0",
22
- "0x25990db2d26547f92c711988300df317af57bad5cd5d9d8e787a82f95c929474",
23
- "0x8e0c648afa977572ead40a1d10a6db2c425b8099545006d834a7b849c6166643",
24
- "0x4b635250efa6243e277fdd0cf6df993c2943b64f10f3a0756ceb1f47ef8f9b18",
25
- "0xbde1c927f6222c07c8df264e68b42b8382c7c2b85f4729e0df94297cfeebfa91",
26
- "0x4d58aea1a67f94be21ab1415bf3b602592430eb9112268fd0fc4e141b1a35e76",
27
- "0x14c03281bce13010b158e5a4a3378be394ac9e16118aedb17d82ced51e66836c",
28
- "0x99fd3e76f43b2cc221cb9860bc6c96cda95af3fa07ef5f04e071b54aa9386d06",
29
- "0x1b1c2f1a04968094d8d0453d49838f7a809d1202ae04a1c2e0964e442ff7988b",
30
- "0xc8ccd3cb3267dd76f563584920ac60f2283b719917481b85fe5e10b754932455",
13
+ "0x270da1ebafc0f24637af3612fb8c3a1d828fcb56d3637c24e86dd006b12ca7f9",
14
+ "0x828b9cdf8326a1cf234328e4d5229546a98fb72ef73624f5b6b31538e555b96c",
15
+ "0xfcb7a3ca4094246b8185620c4cf025c93032b6f0384805aa3f22afe04290e982",
16
+ "0xcc97cb1955496a5269b5a7afca62ba694edcab26ba838a1adbd257931249de92",
17
+ "0xda3feb08db360ad9e09540132ff04d2b6a596fdaa4747892217aaa4c7c9bcc31",
18
+ "0x15bd6e2aa1a7a61614187ac16d2cbf8610c8f2f3c3d9eaa380ae7a501ee3cf06",
19
+ "0xb726cb7fab1a24c28213cbd482fa5a301f127fb25feb01da341919983a72711a",
20
+ "0xcea9cd557c6f821868ea287304199d0e0554af630bfa8fe36c64eb3bbacca418",
21
+ "0xf7dbde8234e8e345cec8fc0a8ac5909ee336b214882751ecd51e7b37df4f6cdd",
22
+ "0x5400a5d43d39e6bfe910af8cb84ac77bf501d310413769dffd62ccecda8b00c6",
23
+ "0x0754209b60d99d0822b3ecd5a970f9db09df9c8998a8441e24b81f06d6c76fee",
24
+ "0xf5d561d88647c3b38ed6636709d3166819fc66f8ed52a0daf4ae186387b4646c",
25
+ "0x5801c07a6c7df039ce00a7a2b8bd92aa1cf333c30b0bc3d78768590b6063d09e",
26
+ "0xc9da7190eaf4b14c7cb1c14f9898256c0adb6b1dc303afe79594dea64fe199c0",
27
+ "0xa47534c85ac57c583568465d40fd46683d2d558d8129fe1aca01e93023afca92",
28
+ "0xb1e841691fb54f4ef85e2ed9de45d610e57f49e1e6eb2510ceead16e447dd519",
29
+ "0x4fa4f16f09f0c36c7670449a4032073380d28a60071e12ee8874bb3e5a8318fc",
30
+ "0x817bbaac8bb863670f488b454cdd5d0990d9d81871a68e9df381c3c13d3f2ba2",
31
+ "0xc447f06079bddf4b011523c4bce119e9e90fdf937de4ee88f48010406560e9c1",
32
+ "0x1608d5eb56943c667c34b413f9f8a1c24a84ddfe1301a9c25487e638de1f5822",
33
+ "0x3a677100d2e855c24a62d1e9c365bff90d02287f066a07064843ca1ee70ea113",
31
34
  ];
32
35
  const signatureAbi = [
33
36
  {
@@ -59,10 +62,12 @@ const typedDataTypes = {
59
62
  CollateralParams: [
60
63
  { name: "token", type: "address" },
61
64
  { name: "lltv", type: "uint256" },
62
- { name: "maxLif", type: "uint256" },
65
+ { name: "liquidationCursor", type: "uint256" },
63
66
  { name: "oracle", type: "address" },
64
67
  ],
65
68
  Market: [
69
+ { name: "chainId", type: "uint256" },
70
+ { name: "midnight", type: "address" },
66
71
  { name: "loanToken", type: "address" },
67
72
  { name: "collateralParams", type: "CollateralParams[]" },
68
73
  { name: "maturity", type: "uint256" },
@@ -83,8 +88,8 @@ const typedDataTypes = {
83
88
  { name: "receiverIfMakerIsSeller", type: "address" },
84
89
  { name: "ratifier", type: "address" },
85
90
  { name: "reduceOnly", type: "bool" },
86
- { name: "maxUnits", type: "uint256" },
87
- { name: "maxAssets", type: "uint256" },
91
+ { name: "maxUnits", type: "uint128" },
92
+ { name: "maxAssets", type: "uint128" },
88
93
  { name: "continuousFeeCap", type: "uint256" },
89
94
  ],
90
95
  };
@@ -97,21 +102,6 @@ const buildTreeValue = (offers) => {
97
102
  buildTreeValue(offers.slice(mid)),
98
103
  ];
99
104
  };
100
- const getTreeRatifier = (tree) => {
101
- const offers = tree.offers;
102
- const firstOffer = offers[0];
103
- if (firstOffer == null) {
104
- throw new errors_js_1.InvalidTreeError("Tree must contain at least one offer.");
105
- }
106
- const ratifier = firstOffer.ratifier;
107
- const comparableRatifier = ratifier.toLowerCase();
108
- for (const offer of offers.slice(1)) {
109
- if (offer.ratifier.toLowerCase() !== comparableRatifier) {
110
- throw new errors_js_1.InvalidTreeError(`All offers in an Ecrecover tree must use one ratifier; expected "${ratifier}", got "${offer.ratifier}". Build separate trees per ratifier.`);
111
- }
112
- }
113
- return ratifier;
114
- };
115
105
  /**
116
106
  * EcrecoverRatifier-specific pure utilities.
117
107
  *
@@ -120,7 +110,10 @@ const getTreeRatifier = (tree) => {
120
110
  * validate the tree, sign the typed data, call `ratify`, then pass the returned
121
111
  * items to `Payload.encode`. Ecrecover trees must contain one ratifier; split
122
112
  * trees by ratifier before signing. The signer may be the maker or an address
123
- * authorized by every maker in the tree.
113
+ * authorized by every maker in the tree. Ratifier helpers accept tree-like
114
+ * inputs rather than requiring the `Tree` class. Passing an existing `Tree`
115
+ * remains the optimal path because its cached offers, leaves, root, and height
116
+ * are reused for typed data and per-leaf proofs.
124
117
  *
125
118
  * @example
126
119
  * ```ts
@@ -152,14 +145,14 @@ var EcrecoverRatifierUtils;
152
145
  }
153
146
  EcrecoverRatifierUtils.treeTypeHash = treeTypeHash;
154
147
  /**
155
- * Builds EcrecoverRatifier typed data for a tree.
148
+ * Builds EcrecoverRatifier typed data for a tree-like input.
156
149
  *
157
150
  * Use after the tree is built and validated, before requesting the signer
158
151
  * signature. The EIP-712 verifier is derived from the shared ratifier address
159
152
  * on the tree offers. `ratify` calls this for you when given a client and
160
153
  * account.
161
154
  *
162
- * @param params.tree - Ecrecover-ratified offer tree to sign.
155
+ * @param params.tree - Ecrecover-ratified offer tree-like input to sign.
163
156
  * @param params.chainId - EIP-155 chain id included in the EIP-712 domain.
164
157
  * @returns EIP-712 typed-data descriptor.
165
158
  * @throws {InvalidTreeError} when the tree is invalid or contains multiple ratifiers.
@@ -172,12 +165,14 @@ var EcrecoverRatifierUtils;
172
165
  *
173
166
  * const offer = Offer.create({
174
167
  * market: {
168
+ * chainId: 8453,
169
+ * midnight: "0x0000000000000000000000000000000000001000",
175
170
  * loanToken: "0x0000000000000000000000000000000000006000",
176
171
  * collateralParams: [
177
172
  * {
178
173
  * token: "0x0000000000000000000000000000000000007000",
179
174
  * lltv: 770000000000000000n,
180
- * maxLif: 1061007957559681697n,
175
+ * liquidationCursor: 250000000000000000n,
181
176
  * oracle: "0x0000000000000000000000000000000000008000",
182
177
  * },
183
178
  * ],
@@ -202,10 +197,11 @@ var EcrecoverRatifierUtils;
202
197
  * ```
203
198
  */
204
199
  function typedData(params) {
205
- const verifyingContract = getTreeRatifier(params.tree);
206
- const treeType = params.tree.height === 0
207
- ? "Offer"
208
- : `Offer${"[2]".repeat(params.tree.height)}`;
200
+ const { tree, ratifier: verifyingContract } = RatifierUtils_js_1.RatifierUtils.normalizeRatifierTree({
201
+ tree: params.tree,
202
+ label: "Ecrecover",
203
+ });
204
+ const treeType = tree.height === 0 ? "Offer" : `Offer${"[2]".repeat(tree.height)}`;
209
205
  return (0, morpho_ts_1.deepFreeze)({
210
206
  domain: {
211
207
  chainId: BigInt(params.chainId),
@@ -217,7 +213,7 @@ var EcrecoverRatifierUtils;
217
213
  },
218
214
  primaryType: "OfferTree",
219
215
  message: {
220
- offerTree: buildTreeValue(params.tree.paddedOffers),
216
+ offerTree: buildTreeValue(tree.paddedOffers),
221
217
  },
222
218
  });
223
219
  }
@@ -225,7 +221,7 @@ var EcrecoverRatifierUtils;
225
221
  /**
226
222
  * Builds the EcrecoverRatifier digest used by the Solidity ratifier.
227
223
  *
228
- * @param params.tree - Ecrecover-ratified offer tree to hash.
224
+ * @param params.tree - Ecrecover-ratified offer tree-like input to hash.
229
225
  * @param params.chainId - EIP-155 chain id included in the EIP-712 domain.
230
226
  * @returns EIP-712 digest.
231
227
  * @throws {InvalidTreeError} when the tree contains multiple ratifiers.
@@ -238,12 +234,14 @@ var EcrecoverRatifierUtils;
238
234
  *
239
235
  * const offer = Offer.create({
240
236
  * market: {
237
+ * chainId: 8453,
238
+ * midnight: "0x0000000000000000000000000000000000001000",
241
239
  * loanToken: "0x0000000000000000000000000000000000006000",
242
240
  * collateralParams: [
243
241
  * {
244
242
  * token: "0x0000000000000000000000000000000000007000",
245
243
  * lltv: 770000000000000000n,
246
- * maxLif: 1061007957559681697n,
244
+ * liquidationCursor: 250000000000000000n,
247
245
  * oracle: "0x0000000000000000000000000000000000008000",
248
246
  * },
249
247
  * ],
@@ -268,15 +266,18 @@ var EcrecoverRatifierUtils;
268
266
  * ```
269
267
  */
270
268
  function digest(params) {
271
- const verifyingContract = getTreeRatifier(params.tree);
269
+ const { tree, ratifier: verifyingContract } = RatifierUtils_js_1.RatifierUtils.normalizeRatifierTree({
270
+ tree: params.tree,
271
+ label: "Ecrecover",
272
+ });
272
273
  const domainSeparator = (0, viem_1.keccak256)((0, viem_1.encodeAbiParameters)(domainSeparatorAbi, [
273
274
  constants_js_1.EIP712_DOMAIN_TYPEHASH,
274
275
  BigInt(params.chainId),
275
276
  verifyingContract,
276
277
  ]));
277
278
  const structHash = (0, viem_1.keccak256)((0, viem_1.encodeAbiParameters)(treeStructHashAbi, [
278
- treeTypeHash(params.tree.height),
279
- params.tree.root,
279
+ treeTypeHash(tree.height),
280
+ tree.root,
280
281
  ]));
281
282
  return (0, viem_1.keccak256)((0, viem_1.concat)(["0x1901", domainSeparator, structHash]));
282
283
  }
@@ -289,12 +290,13 @@ var EcrecoverRatifierUtils;
289
290
  * client and account. The account may be the maker or an address authorized
290
291
  * by every maker in the tree; the protocol checks that authorization onchain.
291
292
  *
292
- * @param params.tree - Ecrecover-ratified offer tree to sign.
293
+ * @param params.tree - Ecrecover-ratified offer tree-like input to sign.
293
294
  * @param params.client - Viem client whose transport signs the tree typed data.
294
295
  * @param params.account - Account used to sign the tree typed data.
295
296
  * @returns Signature returned by the client.
296
- * @throws {InvalidTreeError} when the tree is invalid or contains multiple ratifiers.
297
+ * @throws {InvalidTreeError} when the tree is invalid, contains multiple ratifiers, or spans multiple chain ids.
297
298
  * @throws {InvalidTreeHeightError} when the tree height is unsupported.
299
+ * @throws {ChainIdMismatchError} when `params.client.chain?.id` does not match the tree offer chain id.
298
300
  * @throws {InvalidTypedDataSignatureError} when the returned signature does not recover to `params.account`.
299
301
  * @example
300
302
  * ```ts
@@ -305,12 +307,14 @@ var EcrecoverRatifierUtils;
305
307
  *
306
308
  * const offer = Offer.create({
307
309
  * market: {
310
+ * chainId: 8453,
311
+ * midnight: "0x0000000000000000000000000000000000001000",
308
312
  * loanToken: "0x0000000000000000000000000000000000006000",
309
313
  * collateralParams: [
310
314
  * {
311
315
  * token: "0x0000000000000000000000000000000000007000",
312
316
  * lltv: 770000000000000000n,
313
- * maxLif: 1061007957559681697n,
317
+ * liquidationCursor: 250000000000000000n,
314
318
  * oracle: "0x0000000000000000000000000000000000008000",
315
319
  * },
316
320
  * ],
@@ -340,24 +344,46 @@ var EcrecoverRatifierUtils;
340
344
  * ```
341
345
  */
342
346
  async function sign(params) {
347
+ const { tree } = RatifierUtils_js_1.RatifierUtils.normalizeRatifierTree({
348
+ tree: params.tree,
349
+ label: "Ecrecover",
350
+ });
351
+ const expectedChainId = index_js_1.MarketParams.from(tree.offers[0].market).chainId;
352
+ for (const offer of tree.offers.slice(1)) {
353
+ const offerChainId = index_js_1.MarketParams.from(offer.market).chainId;
354
+ if (offerChainId !== expectedChainId) {
355
+ throw new errors_js_1.InvalidTreeError(`All offers in an Ecrecover tree must use one chain id; expected "${expectedChainId}", got "${offerChainId}". Build separate trees per chain.`);
356
+ }
357
+ }
358
+ const clientChainId = params.client.chain?.id;
359
+ if (clientChainId == null || BigInt(clientChainId) !== expectedChainId) {
360
+ throw new errors_js_1.ChainIdMismatchError(clientChainId, expectedChainId);
361
+ }
343
362
  const signer = typeof params.account === "string"
344
363
  ? params.account
345
364
  : params.account.address;
346
365
  const data = typedData({
347
- tree: params.tree,
348
- chainId: params.client.chain.id,
366
+ tree,
367
+ chainId: expectedChainId,
349
368
  });
350
369
  const signature = await (0, actions_1.signTypedData)(params.client, {
351
370
  account: params.account,
352
371
  ...data,
353
372
  });
354
- const isValidSignature = await (0, viem_1.verifyTypedData)({
355
- ...data,
356
- address: signer,
357
- signature,
358
- });
359
- if (!isValidSignature)
373
+ let isValidSignature = false;
374
+ try {
375
+ isValidSignature = await (0, viem_1.verifyHash)({
376
+ address: signer,
377
+ hash: digest({ tree, chainId: expectedChainId }),
378
+ signature,
379
+ });
380
+ }
381
+ catch (cause) {
382
+ throw new errors_js_1.InvalidTypedDataSignatureError(signer, cause);
383
+ }
384
+ if (!isValidSignature) {
360
385
  throw new errors_js_1.InvalidTypedDataSignatureError(signer);
386
+ }
361
387
  return signature;
362
388
  }
363
389
  EcrecoverRatifierUtils.sign = sign;
@@ -381,17 +407,17 @@ var EcrecoverRatifierUtils;
381
407
  */
382
408
  function toSignature(signature) {
383
409
  if (typeof signature !== "string") {
410
+ const v = signature.v != null ? Number(signature.v) : Number(signature.yParity);
384
411
  return {
385
- v: signature.v != null
386
- ? Number(signature.v)
387
- : Number(signature.yParity) + 27,
412
+ v: v < 27 ? v + 27 : v,
388
413
  r: signature.r,
389
414
  s: signature.s,
390
415
  };
391
416
  }
392
417
  const parsed = (0, viem_1.parseSignature)(signature);
418
+ const v = Number(parsed.v ?? BigInt(parsed.yParity));
393
419
  return {
394
- v: Number(parsed.v ?? BigInt(parsed.yParity + 27)),
420
+ v: v < 27 ? v + 27 : v,
395
421
  r: parsed.r,
396
422
  s: parsed.s,
397
423
  };
@@ -482,7 +508,7 @@ var EcrecoverRatifierUtils;
482
508
  * Use after a tree has been signed when a caller needs data for one offer
483
509
  * leaf. Use `ratify` to produce payload-ready items for the whole tree.
484
510
  *
485
- * @param params.tree - Ecrecover-ratified offer tree that produced the proof.
511
+ * @param params.tree - Ecrecover-ratified offer tree-like input that produced the proof.
486
512
  * @param params.leafIndex - Leaf index to prove.
487
513
  * @param params.signature - Ecrecover signature for the tree root.
488
514
  * @returns ABI-encoded EcrecoverRatifier data.
@@ -494,12 +520,14 @@ var EcrecoverRatifierUtils;
494
520
  *
495
521
  * const offer = Offer.create({
496
522
  * market: {
523
+ * chainId: 8453,
524
+ * midnight: "0x0000000000000000000000000000000000001000",
497
525
  * loanToken: "0x0000000000000000000000000000000000006000",
498
526
  * collateralParams: [
499
527
  * {
500
528
  * token: "0x0000000000000000000000000000000000007000",
501
529
  * lltv: 770000000000000000n,
502
- * maxLif: 1061007957559681697n,
530
+ * liquidationCursor: 250000000000000000n,
503
531
  * oracle: "0x0000000000000000000000000000000000008000",
504
532
  * },
505
533
  * ],
@@ -524,8 +552,11 @@ var EcrecoverRatifierUtils;
524
552
  * ```
525
553
  */
526
554
  function ratifierData(params) {
527
- getTreeRatifier(params.tree);
528
- const proof = params.tree.proof(params.leafIndex);
555
+ const { tree } = RatifierUtils_js_1.RatifierUtils.normalizeRatifierTree({
556
+ tree: params.tree,
557
+ label: "Ecrecover",
558
+ });
559
+ const proof = TreeUtils_js_1.TreeUtils.buildProof({ tree, leafIndex: params.leafIndex });
529
560
  return encodeRatifierData({
530
561
  signature: toSignature(params.signature),
531
562
  root: proof.root,
@@ -541,14 +572,14 @@ var EcrecoverRatifierUtils;
541
572
  * The returned items preserve tree leaf order and include ratifier data
542
573
  * required by takers. The group id is stored on each inline offer.
543
574
  *
544
- * @param params.tree - Ecrecover-ratified offer tree to ratify.
575
+ * @param params.tree - Ecrecover-ratified offer tree-like input to ratify.
545
576
  * @param params.client - Optional viem client whose transport signs typed data built from `params.tree`.
546
577
  * @param params.account - Optional account used to sign typed data built from `params.tree`.
547
578
  * @param params.signature - Optional precomputed signature for `params.tree`.
548
579
  * @returns Items containing each offer and its ratifier data.
549
580
  * @throws {InvalidTreeError} when the tree is invalid or contains multiple ratifiers.
550
581
  * @throws {InvalidTreeHeightError} when the tree height is unsupported.
551
- * @throws {InvalidTypedDataSignatureError} when client signing returns a signature that does not recover to `params.account`.
582
+ * @throws {InvalidTypedDataSignatureError} when client signing or a precomputed signature does not recover to `params.account`.
552
583
  * @example
553
584
  * ```ts
554
585
  * import { EcrecoverRatifierUtils, Tree } from "@morpho-org/midnight-sdk";
@@ -558,12 +589,14 @@ var EcrecoverRatifierUtils;
558
589
  *
559
590
  * const offer = Offer.create({
560
591
  * market: {
592
+ * chainId: 8453,
593
+ * midnight: "0x0000000000000000000000000000000000001000",
561
594
  * loanToken: "0x0000000000000000000000000000000000006000",
562
595
  * collateralParams: [
563
596
  * {
564
597
  * token: "0x0000000000000000000000000000000000007000",
565
598
  * lltv: 770000000000000000n,
566
- * maxLif: 1061007957559681697n,
599
+ * liquidationCursor: 250000000000000000n,
567
600
  * oracle: "0x0000000000000000000000000000000000008000",
568
601
  * },
569
602
  * ],
@@ -593,20 +626,55 @@ var EcrecoverRatifierUtils;
593
626
  * ```
594
627
  */
595
628
  async function ratify(params) {
629
+ const { tree } = RatifierUtils_js_1.RatifierUtils.normalizeRatifierTree({
630
+ tree: params.tree,
631
+ label: "Ecrecover",
632
+ });
596
633
  let signature;
597
634
  if (params.signature != null) {
598
- getTreeRatifier(params.tree);
599
635
  signature = toSignature(params.signature);
636
+ const expectedChainId = index_js_1.MarketParams.from(tree.offers[0].market).chainId;
637
+ for (const offer of tree.offers.slice(1)) {
638
+ const offerChainId = index_js_1.MarketParams.from(offer.market).chainId;
639
+ if (offerChainId !== expectedChainId) {
640
+ throw new errors_js_1.InvalidTreeError(`All offers in an Ecrecover tree must use one chain id; expected "${expectedChainId}", got "${offerChainId}". Build separate trees per chain.`);
641
+ }
642
+ }
643
+ const signer = typeof params.account === "string"
644
+ ? params.account
645
+ : params.account.address;
646
+ let isValidSignature = false;
647
+ try {
648
+ isValidSignature = await (0, viem_1.verifyHash)({
649
+ address: signer,
650
+ hash: digest({ tree, chainId: expectedChainId }),
651
+ signature: (0, viem_1.serializeSignature)({
652
+ r: signature.r,
653
+ s: signature.s,
654
+ yParity: signature.v - 27,
655
+ }),
656
+ });
657
+ }
658
+ catch (cause) {
659
+ throw new errors_js_1.InvalidTypedDataSignatureError(signer, cause);
660
+ }
661
+ if (!isValidSignature) {
662
+ throw new errors_js_1.InvalidTypedDataSignatureError(signer);
663
+ }
600
664
  }
601
665
  else {
602
- signature = toSignature(await sign(params));
666
+ signature = toSignature(await sign({
667
+ tree,
668
+ client: params.client,
669
+ account: params.account,
670
+ }));
603
671
  }
604
672
  const items = [];
605
- for (const offer of params.tree.offers) {
673
+ for (const offer of tree.offers) {
606
674
  items.push({
607
675
  offer,
608
676
  ratifierData: ratifierData({
609
- tree: params.tree,
677
+ tree,
610
678
  leafIndex: items.length,
611
679
  signature,
612
680
  }),
@@ -18,12 +18,14 @@ import { type GroupInput, type IGroup } from "./GroupUtils.js";
18
18
  *
19
19
  * const offer = Offer.create({
20
20
  * market: {
21
+ * chainId: 8453,
22
+ * midnight: "0x0000000000000000000000000000000000001000",
21
23
  * loanToken: "0x0000000000000000000000000000000000006000",
22
24
  * collateralParams: [
23
25
  * {
24
26
  * token: "0x0000000000000000000000000000000000007000",
25
27
  * lltv: 770000000000000000n,
26
- * maxLif: 1061007957559681697n,
28
+ * liquidationCursor: 250000000000000000n,
27
29
  * oracle: "0x0000000000000000000000000000000000008000",
28
30
  * },
29
31
  * ],
@@ -61,12 +63,14 @@ export declare class Group implements IGroup {
61
63
  *
62
64
  * const offer = Offer.create({
63
65
  * market: {
66
+ * chainId: 8453,
67
+ * midnight: "0x0000000000000000000000000000000000001000",
64
68
  * loanToken: "0x0000000000000000000000000000000000006000",
65
69
  * collateralParams: [
66
70
  * {
67
71
  * token: "0x0000000000000000000000000000000000007000",
68
72
  * lltv: 770000000000000000n,
69
- * maxLif: 1061007957559681697n,
73
+ * liquidationCursor: 250000000000000000n,
70
74
  * oracle: "0x0000000000000000000000000000000000008000",
71
75
  * },
72
76
  * ],
@@ -104,12 +108,14 @@ export declare class Group implements IGroup {
104
108
  *
105
109
  * const offer = Offer.create({
106
110
  * market: {
111
+ * chainId: 8453,
112
+ * midnight: "0x0000000000000000000000000000000000001000",
107
113
  * loanToken: "0x0000000000000000000000000000000000006000",
108
114
  * collateralParams: [
109
115
  * {
110
116
  * token: "0x0000000000000000000000000000000000007000",
111
117
  * lltv: 770000000000000000n,
112
- * maxLif: 1061007957559681697n,
118
+ * liquidationCursor: 250000000000000000n,
113
119
  * oracle: "0x0000000000000000000000000000000000008000",
114
120
  * },
115
121
  * ],
@@ -149,12 +155,14 @@ export declare class Group implements IGroup {
149
155
  *
150
156
  * const offer = Offer.create({
151
157
  * market: {
158
+ * chainId: 8453,
159
+ * midnight: "0x0000000000000000000000000000000000001000",
152
160
  * loanToken: "0x0000000000000000000000000000000000006000",
153
161
  * collateralParams: [
154
162
  * {
155
163
  * token: "0x0000000000000000000000000000000000007000",
156
164
  * lltv: 770000000000000000n,
157
- * maxLif: 1061007957559681697n,
165
+ * liquidationCursor: 250000000000000000n,
158
166
  * oracle: "0x0000000000000000000000000000000000008000",
159
167
  * },
160
168
  * ],
@@ -20,12 +20,14 @@ const GroupUtils_js_1 = require("./GroupUtils.js");
20
20
  *
21
21
  * const offer = Offer.create({
22
22
  * market: {
23
+ * chainId: 8453,
24
+ * midnight: "0x0000000000000000000000000000000000001000",
23
25
  * loanToken: "0x0000000000000000000000000000000000006000",
24
26
  * collateralParams: [
25
27
  * {
26
28
  * token: "0x0000000000000000000000000000000000007000",
27
29
  * lltv: 770000000000000000n,
28
- * maxLif: 1061007957559681697n,
30
+ * liquidationCursor: 250000000000000000n,
29
31
  * oracle: "0x0000000000000000000000000000000000008000",
30
32
  * },
31
33
  * ],
@@ -67,12 +69,14 @@ class Group {
67
69
  *
68
70
  * const offer = Offer.create({
69
71
  * market: {
72
+ * chainId: 8453,
73
+ * midnight: "0x0000000000000000000000000000000000001000",
70
74
  * loanToken: "0x0000000000000000000000000000000000006000",
71
75
  * collateralParams: [
72
76
  * {
73
77
  * token: "0x0000000000000000000000000000000000007000",
74
78
  * lltv: 770000000000000000n,
75
- * maxLif: 1061007957559681697n,
79
+ * liquidationCursor: 250000000000000000n,
76
80
  * oracle: "0x0000000000000000000000000000000000008000",
77
81
  * },
78
82
  * ],
@@ -112,12 +116,14 @@ class Group {
112
116
  *
113
117
  * const offer = Offer.create({
114
118
  * market: {
119
+ * chainId: 8453,
120
+ * midnight: "0x0000000000000000000000000000000000001000",
115
121
  * loanToken: "0x0000000000000000000000000000000000006000",
116
122
  * collateralParams: [
117
123
  * {
118
124
  * token: "0x0000000000000000000000000000000000007000",
119
125
  * lltv: 770000000000000000n,
120
- * maxLif: 1061007957559681697n,
126
+ * liquidationCursor: 250000000000000000n,
121
127
  * oracle: "0x0000000000000000000000000000000000008000",
122
128
  * },
123
129
  * ],
@@ -161,12 +167,14 @@ class Group {
161
167
  *
162
168
  * const offer = Offer.create({
163
169
  * market: {
170
+ * chainId: 8453,
171
+ * midnight: "0x0000000000000000000000000000000000001000",
164
172
  * loanToken: "0x0000000000000000000000000000000000006000",
165
173
  * collateralParams: [
166
174
  * {
167
175
  * token: "0x0000000000000000000000000000000000007000",
168
176
  * lltv: 770000000000000000n,
169
- * maxLif: 1061007957559681697n,
177
+ * liquidationCursor: 250000000000000000n,
170
178
  * oracle: "0x0000000000000000000000000000000000008000",
171
179
  * },
172
180
  * ],
@@ -12,12 +12,14 @@ import { type IOffer, type OfferStruct } from "../offers/index.js";
12
12
  * offers: [
13
13
  * Offer.create({
14
14
  * market: {
15
+ * chainId: 8453,
16
+ * midnight: "0x0000000000000000000000000000000000001000",
15
17
  * loanToken: "0x0000000000000000000000000000000000006000",
16
18
  * collateralParams: [
17
19
  * {
18
20
  * token: "0x0000000000000000000000000000000000007000",
19
21
  * lltv: 770000000000000000n,
20
- * maxLif: 1061007957559681697n,
22
+ * liquidationCursor: 250000000000000000n,
21
23
  * oracle: "0x0000000000000000000000000000000000008000",
22
24
  * },
23
25
  * ],
@@ -57,12 +59,14 @@ export interface IGroup {
57
59
  *
58
60
  * const input: GroupInput = Offer.create({
59
61
  * market: {
62
+ * chainId: 8453,
63
+ * midnight: "0x0000000000000000000000000000000000001000",
60
64
  * loanToken: "0x0000000000000000000000000000000000006000",
61
65
  * collateralParams: [
62
66
  * {
63
67
  * token: "0x0000000000000000000000000000000000007000",
64
68
  * lltv: 770000000000000000n,
65
- * maxLif: 1061007957559681697n,
69
+ * liquidationCursor: 250000000000000000n,
66
70
  * oracle: "0x0000000000000000000000000000000000008000",
67
71
  * },
68
72
  * ],
@@ -115,12 +119,14 @@ export declare namespace GroupUtils {
115
119
  *
116
120
  * const offer = Offer.create({
117
121
  * market: {
122
+ * chainId: 8453,
123
+ * midnight: "0x0000000000000000000000000000000000001000",
118
124
  * loanToken: "0x0000000000000000000000000000000000006000",
119
125
  * collateralParams: [
120
126
  * {
121
127
  * token: "0x0000000000000000000000000000000000007000",
122
128
  * lltv: 770000000000000000n,
123
- * maxLif: 1061007957559681697n,
129
+ * liquidationCursor: 250000000000000000n,
124
130
  * oracle: "0x0000000000000000000000000000000000008000",
125
131
  * },
126
132
  * ],
@@ -162,12 +168,14 @@ export declare namespace GroupUtils {
162
168
  *
163
169
  * const offer = Offer.create({
164
170
  * market: {
171
+ * chainId: 8453,
172
+ * midnight: "0x0000000000000000000000000000000000001000",
165
173
  * loanToken: "0x0000000000000000000000000000000000006000",
166
174
  * collateralParams: [
167
175
  * {
168
176
  * token: "0x0000000000000000000000000000000000007000",
169
177
  * lltv: 770000000000000000n,
170
- * maxLif: 1061007957559681697n,
178
+ * liquidationCursor: 250000000000000000n,
171
179
  * oracle: "0x0000000000000000000000000000000000008000",
172
180
  * },
173
181
  * ],