@morpho-org/midnight-sdk 0.1.0 → 1.1.1

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 (128) 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 +89 -19
  7. package/lib/cjs/api/helpers.d.ts +11 -1
  8. package/lib/cjs/api/helpers.js +54 -4
  9. package/lib/cjs/api/types.d.ts +35 -9
  10. package/lib/cjs/constants.d.ts +12 -11
  11. package/lib/cjs/constants.js +14 -12
  12. package/lib/cjs/errors.d.ts +89 -1
  13. package/lib/cjs/errors.js +114 -3
  14. package/lib/cjs/fetch/Market.js +37 -3
  15. package/lib/cjs/fetch/index.d.ts +0 -1
  16. package/lib/cjs/fetch/index.js +0 -1
  17. package/lib/cjs/fetch/utils.d.ts +1 -1
  18. package/lib/cjs/fetch/utils.js +9 -2
  19. package/lib/cjs/index.d.ts +1 -1
  20. package/lib/cjs/index.js +2 -23
  21. package/lib/cjs/market/Market.d.ts +99 -33
  22. package/lib/cjs/market/Market.js +137 -28
  23. package/lib/cjs/market/MarketUtils.d.ts +61 -41
  24. package/lib/cjs/market/MarketUtils.js +108 -48
  25. package/lib/cjs/market/Position.d.ts +16 -11
  26. package/lib/cjs/market/Position.js +18 -12
  27. package/lib/cjs/market/PositionUtils.d.ts +6 -4
  28. package/lib/cjs/market/PositionUtils.js +9 -6
  29. package/lib/cjs/math/TickLib.d.ts +22 -0
  30. package/lib/cjs/math/TickLib.js +30 -0
  31. package/lib/cjs/math/index.d.ts +0 -1
  32. package/lib/cjs/math/index.js +0 -1
  33. package/lib/cjs/offers/Offer.d.ts +218 -12
  34. package/lib/cjs/offers/Offer.js +215 -7
  35. package/lib/cjs/offers/OfferUtils.d.ts +249 -143
  36. package/lib/cjs/offers/OfferUtils.js +326 -45
  37. package/lib/cjs/queries/GetPosition.d.ts +1 -1
  38. package/lib/cjs/queries/GetPosition.js +1 -1
  39. package/lib/cjs/signatures/EcrecoverRatifierUtils.d.ts +184 -38
  40. package/lib/cjs/signatures/EcrecoverRatifierUtils.js +296 -80
  41. package/lib/cjs/signatures/Group.d.ts +12 -4
  42. package/lib/cjs/signatures/Group.js +17 -7
  43. package/lib/cjs/signatures/GroupUtils.d.ts +60 -4
  44. package/lib/cjs/signatures/GroupUtils.js +57 -2
  45. package/lib/cjs/signatures/Payload.d.ts +277 -277
  46. package/lib/cjs/signatures/Payload.js +517 -534
  47. package/lib/cjs/signatures/RatifierUtils.d.ts +57 -0
  48. package/lib/cjs/signatures/RatifierUtils.js +105 -0
  49. package/lib/cjs/signatures/SetterRatifierUtils.d.ts +52 -13
  50. package/lib/cjs/signatures/SetterRatifierUtils.js +62 -19
  51. package/lib/cjs/signatures/Tree.d.ts +28 -16
  52. package/lib/cjs/signatures/Tree.js +35 -15
  53. package/lib/cjs/signatures/TreeUtils.d.ts +185 -63
  54. package/lib/cjs/signatures/TreeUtils.js +89 -79
  55. package/lib/cjs/signatures/eip712.d.ts +22 -0
  56. package/lib/cjs/signatures/eip712.js +26 -0
  57. package/lib/cjs/signatures/index.d.ts +2 -0
  58. package/lib/cjs/signatures/index.js +4 -0
  59. package/lib/cjs/signatures/offerStructInternal.d.ts +14 -0
  60. package/lib/cjs/signatures/offerStructInternal.js +72 -0
  61. package/lib/esm/abis.d.ts +1185 -996
  62. package/lib/esm/abis.js +1445 -1211
  63. package/lib/esm/api/MidnightApi.d.ts +22 -16
  64. package/lib/esm/api/MidnightApi.js +91 -21
  65. package/lib/esm/api/helpers.d.ts +11 -1
  66. package/lib/esm/api/helpers.js +54 -5
  67. package/lib/esm/api/types.d.ts +35 -9
  68. package/lib/esm/constants.d.ts +12 -11
  69. package/lib/esm/constants.js +13 -11
  70. package/lib/esm/errors.d.ts +89 -1
  71. package/lib/esm/errors.js +108 -2
  72. package/lib/esm/fetch/Market.js +38 -4
  73. package/lib/esm/fetch/index.d.ts +0 -1
  74. package/lib/esm/fetch/index.js +0 -1
  75. package/lib/esm/fetch/utils.d.ts +1 -1
  76. package/lib/esm/fetch/utils.js +9 -2
  77. package/lib/esm/index.d.ts +1 -1
  78. package/lib/esm/index.js +1 -1
  79. package/lib/esm/market/Market.d.ts +99 -33
  80. package/lib/esm/market/Market.js +137 -28
  81. package/lib/esm/market/MarketUtils.d.ts +61 -41
  82. package/lib/esm/market/MarketUtils.js +109 -49
  83. package/lib/esm/market/Position.d.ts +16 -11
  84. package/lib/esm/market/Position.js +19 -13
  85. package/lib/esm/market/PositionUtils.d.ts +6 -4
  86. package/lib/esm/market/PositionUtils.js +9 -6
  87. package/lib/esm/math/TickLib.d.ts +22 -0
  88. package/lib/esm/math/TickLib.js +31 -1
  89. package/lib/esm/math/index.d.ts +0 -1
  90. package/lib/esm/math/index.js +0 -1
  91. package/lib/esm/offers/Offer.d.ts +218 -12
  92. package/lib/esm/offers/Offer.js +216 -8
  93. package/lib/esm/offers/OfferUtils.d.ts +249 -143
  94. package/lib/esm/offers/OfferUtils.js +329 -48
  95. package/lib/esm/queries/GetPosition.d.ts +1 -1
  96. package/lib/esm/queries/GetPosition.js +1 -1
  97. package/lib/esm/signatures/EcrecoverRatifierUtils.d.ts +184 -38
  98. package/lib/esm/signatures/EcrecoverRatifierUtils.js +298 -82
  99. package/lib/esm/signatures/Group.d.ts +12 -4
  100. package/lib/esm/signatures/Group.js +17 -7
  101. package/lib/esm/signatures/GroupUtils.d.ts +60 -4
  102. package/lib/esm/signatures/GroupUtils.js +57 -2
  103. package/lib/esm/signatures/Payload.d.ts +277 -277
  104. package/lib/esm/signatures/Payload.js +517 -531
  105. package/lib/esm/signatures/RatifierUtils.d.ts +57 -0
  106. package/lib/esm/signatures/RatifierUtils.js +105 -0
  107. package/lib/esm/signatures/SetterRatifierUtils.d.ts +52 -13
  108. package/lib/esm/signatures/SetterRatifierUtils.js +62 -19
  109. package/lib/esm/signatures/Tree.d.ts +28 -16
  110. package/lib/esm/signatures/Tree.js +36 -16
  111. package/lib/esm/signatures/TreeUtils.d.ts +185 -63
  112. package/lib/esm/signatures/TreeUtils.js +91 -81
  113. package/lib/esm/signatures/eip712.d.ts +22 -0
  114. package/lib/esm/signatures/eip712.js +22 -0
  115. package/lib/esm/signatures/index.d.ts +2 -0
  116. package/lib/esm/signatures/index.js +2 -0
  117. package/lib/esm/signatures/offerStructInternal.d.ts +14 -0
  118. package/lib/esm/signatures/offerStructInternal.js +67 -0
  119. package/package.json +31 -34
  120. package/lib/cjs/fetch/Offer.d.ts +0 -74
  121. package/lib/cjs/fetch/Offer.js +0 -119
  122. package/lib/cjs/math/ConsumableUnitsLib.d.ts +0 -57
  123. package/lib/cjs/math/ConsumableUnitsLib.js +0 -77
  124. package/lib/esm/fetch/Offer.d.ts +0 -74
  125. package/lib/esm/fetch/Offer.js +0 -116
  126. package/lib/esm/math/ConsumableUnitsLib.d.ts +0 -57
  127. package/lib/esm/math/ConsumableUnitsLib.js +0 -74
  128. package/src/index.ts +0 -19
@@ -6,59 +6,12 @@ const viem_1 = require("viem");
6
6
  const MidnightApi_js_1 = require("../api/MidnightApi.js");
7
7
  const errors_js_1 = require("../errors.js");
8
8
  const index_js_1 = require("../offers/index.js");
9
+ const EcrecoverRatifierUtils_js_1 = require("./EcrecoverRatifierUtils.js");
9
10
  const Group_js_1 = require("./Group.js");
10
11
  const GroupUtils_js_1 = require("./GroupUtils.js");
12
+ const offerStructInternal_js_1 = require("./offerStructInternal.js");
11
13
  const Payload_js_1 = require("./Payload.js");
12
- const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
13
- const ZERO_BYTES32 = "0x0000000000000000000000000000000000000000000000000000000000000000";
14
- const EMPTY_OFFER_STRUCT = {
15
- market: {
16
- loanToken: ZERO_ADDRESS,
17
- collateralParams: [],
18
- maturity: 0n,
19
- rcfThreshold: 0n,
20
- enterGate: ZERO_ADDRESS,
21
- liquidatorGate: ZERO_ADDRESS,
22
- },
23
- buy: false,
24
- maker: ZERO_ADDRESS,
25
- start: 0n,
26
- expiry: 0n,
27
- tick: 0n,
28
- group: ZERO_BYTES32,
29
- callback: ZERO_ADDRESS,
30
- callbackData: "0x",
31
- receiverIfMakerIsSeller: ZERO_ADDRESS,
32
- ratifier: ZERO_ADDRESS,
33
- reduceOnly: false,
34
- maxUnits: 0n,
35
- maxAssets: 0n,
36
- continuousFeeCap: 0n,
37
- };
38
- const EMPTY_OFFER_DEFAULT_GROUP = index_js_1.OfferUtils.hashStruct(EMPTY_OFFER_STRUCT);
39
- function isEmptyOfferStruct(offer) {
40
- return (offer.market.loanToken === ZERO_ADDRESS &&
41
- offer.market.collateralParams.length === 0 &&
42
- offer.market.maturity === 0n &&
43
- offer.market.rcfThreshold === 0n &&
44
- offer.market.enterGate === ZERO_ADDRESS &&
45
- offer.market.liquidatorGate === ZERO_ADDRESS &&
46
- offer.buy === false &&
47
- offer.maker === ZERO_ADDRESS &&
48
- offer.start === 0n &&
49
- offer.expiry === 0n &&
50
- offer.tick === 0n &&
51
- (offer.group === ZERO_BYTES32 ||
52
- offer.group === EMPTY_OFFER_DEFAULT_GROUP) &&
53
- offer.callback === ZERO_ADDRESS &&
54
- offer.callbackData === "0x" &&
55
- offer.receiverIfMakerIsSeller === ZERO_ADDRESS &&
56
- offer.ratifier === ZERO_ADDRESS &&
57
- offer.reduceOnly === false &&
58
- offer.maxUnits === 0n &&
59
- offer.maxAssets === 0n &&
60
- offer.continuousFeeCap === 0n);
61
- }
14
+ const SetterRatifierUtils_js_1 = require("./SetterRatifierUtils.js");
62
15
  function isPowerOfTwo(value) {
63
16
  return value > 0 && (value & (value - 1)) === 0;
64
17
  }
@@ -71,13 +24,13 @@ function padOfferStructs(offers) {
71
24
  const paddedLength = nextPowerOfTwo(offers.length);
72
25
  return [
73
26
  ...offers,
74
- ...Array.from({ length: paddedLength - offers.length }, () => EMPTY_OFFER_STRUCT),
27
+ ...Array.from({ length: paddedLength - offers.length }, () => offerStructInternal_js_1.EMPTY_OFFER_STRUCT),
75
28
  ];
76
29
  }
77
30
  function assertLeafOffers(offers, leafHashes) {
78
31
  const seen = new Set();
79
32
  for (const [index, offer] of offers.entries()) {
80
- if (isEmptyOfferStruct(offer))
33
+ if ((0, offerStructInternal_js_1.isEmptyOfferStruct)(offer, { allowDefaultGroup: true }))
81
34
  continue;
82
35
  const leafHash = leafHashes[index];
83
36
  if (seen.has(leafHash)) {
@@ -109,24 +62,26 @@ var TreeUtils;
109
62
  /**
110
63
  * Validates a tree against Midnight mempool API policy.
111
64
  *
112
- * This is an API-backed convenience: it encodes each tree leaf with empty
113
- * `ratifierData`, then sends the temporary payload to the Midnight API
114
- * `POST /mempool/validate` endpoint. API policy only inspects offer contents,
115
- * so use this after `Tree.create` and before wallet signature or Setter root
116
- * approval.
65
+ * This is an API-backed convenience: by default it encodes each tree leaf
66
+ * with empty `ratifierData`, then sends the temporary payload to the Midnight
67
+ * API `POST /mempool/validate` endpoint. Pass `ratification` after signing or
68
+ * Setter root preparation to validate final payload bytes with real
69
+ * `ratifierData`.
117
70
  *
118
71
  * @param params.chainId - Chain id whose API policy should validate the tree.
119
- * @param params.tree - Offer tree to validate before ratifier data or payload publication exists.
72
+ * @param params.tree - Offer tree to validate.
120
73
  * @param params.apiUrl - Optional Midnight API URL override used for the validation HTTP request.
121
74
  * @param params.timestamp - Optional ISO-8601 timestamp or `Date` selecting the API policy snapshot.
122
75
  * @param params.fetch - Optional fetch implementation override used for the API call.
123
76
  * @param params.request - Optional fetch options forwarded to the API request.
124
- * @returns API issues and `valid` summary.
77
+ * @param params.ratification - Optional ratification inputs used to validate final payload bytes with real ratifier data.
78
+ * @returns Successful API validation result with `valid: true`.
125
79
  * @throws {InvalidTreeError} when the tree is empty, all padding, or duplicated.
126
80
  * @throws {InvalidTreeHeightError} when the resulting height is unsupported.
127
- * @throws {Payload.DecodeError} when validation payload encoding fails.
81
+ * @throws {PayloadDecodeError} when validation payload encoding fails.
128
82
  * @throws {MidnightApiError} when the API returns a non-2xx response.
129
83
  * @throws {InvalidMidnightApiResponseError} when the API returns malformed success JSON.
84
+ * @throws {MidnightMempoolValidationError} when the API returns validation issues.
130
85
  * @example
131
86
  * ```ts
132
87
  * import { Offer, TreeUtils } from "@morpho-org/midnight-sdk";
@@ -134,12 +89,14 @@ var TreeUtils;
134
89
  *
135
90
  * const offer = Offer.create({
136
91
  * market: {
92
+ * chainId: 8453,
93
+ * midnight: "0x0000000000000000000000000000000000001000",
137
94
  * loanToken: "0x0000000000000000000000000000000000006000",
138
95
  * collateralParams: [
139
96
  * {
140
97
  * token: "0x0000000000000000000000000000000000007000",
141
98
  * lltv: 770000000000000000n,
142
- * maxLif: 1061007957559681697n,
99
+ * liquidationCursor: 250000000000000000n,
143
100
  * oracle: "0x0000000000000000000000000000000000008000",
144
101
  * },
145
102
  * ],
@@ -155,20 +112,54 @@ var TreeUtils;
155
112
  * ratifier: "0x0000000000000000000000000000000000004000",
156
113
  * maxUnits: 100n,
157
114
  * });
158
- * const validation = await TreeUtils.mempoolValidate({
115
+ * await TreeUtils.mempoolValidate({
159
116
  * chainId: 8453,
160
117
  * tree: [offer],
161
118
  * });
162
- * console.log(validation.valid);
163
119
  * ```
164
120
  */
165
121
  async function mempoolValidate(params) {
166
- const offers = "offers" in params.tree
167
- ? params.tree.offers
168
- : params.tree.flatMap((entry) => "offers" in entry ? Group_js_1.Group.from(entry).offers : [index_js_1.Offer.from(entry)]);
169
- buildDescriptor(offers);
170
- const payload = await (0, Payload_js_1.encode)(offers.map((offer) => ({ offer, ratifierData: "0x" })));
171
- return MidnightApi_js_1.MidnightApi.validateMempoolPayload({
122
+ let items;
123
+ if (params.ratification == null) {
124
+ const offers = "paddedOffers" in params.tree
125
+ ? params.tree.offers
126
+ : params.tree.flatMap((entry) => GroupUtils_js_1.GroupUtils.isGroupInput(entry)
127
+ ? Group_js_1.Group.from(entry).offers
128
+ : [
129
+ new index_js_1.Offer({
130
+ ...index_js_1.Offer.from(entry),
131
+ group: index_js_1.OfferUtils.groupHash(entry),
132
+ }),
133
+ ]);
134
+ if (!("paddedOffers" in params.tree)) {
135
+ buildDescriptor(offers, { preserveStandaloneGroups: true });
136
+ }
137
+ items = offers.map((offer) => ({
138
+ offer,
139
+ ratifierData: "0x",
140
+ }));
141
+ }
142
+ else if (params.ratification.type === "ecrecover") {
143
+ if (params.ratification.signature != null) {
144
+ items = await EcrecoverRatifierUtils_js_1.EcrecoverRatifierUtils.ratify({
145
+ tree: params.tree,
146
+ signature: params.ratification.signature,
147
+ account: params.ratification.account,
148
+ });
149
+ }
150
+ else {
151
+ items = await EcrecoverRatifierUtils_js_1.EcrecoverRatifierUtils.ratify({
152
+ tree: params.tree,
153
+ client: params.ratification.client,
154
+ account: params.ratification.account,
155
+ });
156
+ }
157
+ }
158
+ else {
159
+ items = SetterRatifierUtils_js_1.SetterRatifierUtils.ratify({ tree: params.tree });
160
+ }
161
+ const payload = await Payload_js_1.Payload.encode(items);
162
+ const validation = await MidnightApi_js_1.MidnightApi.validateMempoolPayload({
172
163
  baseUrl: params.apiUrl,
173
164
  fetch: params.fetch,
174
165
  request: params.request,
@@ -176,6 +167,10 @@ var TreeUtils;
176
167
  timestamp: params.timestamp,
177
168
  payload,
178
169
  });
170
+ if (!validation.valid) {
171
+ throw new errors_js_1.MidnightMempoolValidationError(validation.issues);
172
+ }
173
+ return { valid: true, issues: validation.issues };
179
174
  }
180
175
  TreeUtils.mempoolValidate = mempoolValidate;
181
176
  /**
@@ -211,6 +206,7 @@ var TreeUtils;
211
206
  * make-side code.
212
207
  *
213
208
  * @param entries - Groups or standalone offers in leaf order.
209
+ * @param options.preserveStandaloneGroups - Whether standalone offer group ids should be preserved instead of normalized.
214
210
  * @returns Tree descriptor.
215
211
  * @throws {InvalidTreeError} when the offer count is empty, all padding, or duplicated.
216
212
  * @throws {InvalidTreeHeightError} when the padded tree exceeds supported ratifier typehashes.
@@ -221,12 +217,14 @@ var TreeUtils;
221
217
  *
222
218
  * const offer = Offer.create({
223
219
  * market: {
220
+ * chainId: 8453,
221
+ * midnight: "0x0000000000000000000000000000000000001000",
224
222
  * loanToken: "0x0000000000000000000000000000000000006000",
225
223
  * collateralParams: [
226
224
  * {
227
225
  * token: "0x0000000000000000000000000000000000007000",
228
226
  * lltv: 770000000000000000n,
229
- * maxLif: 1061007957559681697n,
227
+ * liquidationCursor: 250000000000000000n,
230
228
  * oracle: "0x0000000000000000000000000000000000008000",
231
229
  * },
232
230
  * ],
@@ -246,10 +244,17 @@ var TreeUtils;
246
244
  * console.log(tree.root);
247
245
  * ```
248
246
  */
249
- function buildDescriptor(entries) {
250
- const structs = entries.flatMap((entry) => "offers" in entry
247
+ function buildDescriptor(entries, options = {}) {
248
+ const structs = entries.flatMap((entry) => GroupUtils_js_1.GroupUtils.isGroupInput(entry)
251
249
  ? GroupUtils_js_1.GroupUtils.toStructs(entry)
252
- : [index_js_1.OfferUtils.toStruct({ offer: entry })]);
250
+ : [
251
+ index_js_1.OfferUtils.toStruct({
252
+ offer: entry,
253
+ group: options.preserveStandaloneGroups
254
+ ? undefined
255
+ : index_js_1.OfferUtils.groupHash(entry),
256
+ }),
257
+ ]);
253
258
  if (structs.length === 0) {
254
259
  throw new errors_js_1.InvalidTreeError("Tree must not be empty.");
255
260
  }
@@ -293,12 +298,14 @@ var TreeUtils;
293
298
  *
294
299
  * const offer = Offer.create({
295
300
  * market: {
301
+ * chainId: 8453,
302
+ * midnight: "0x0000000000000000000000000000000000001000",
296
303
  * loanToken: "0x0000000000000000000000000000000000006000",
297
304
  * collateralParams: [
298
305
  * {
299
306
  * token: "0x0000000000000000000000000000000000007000",
300
307
  * lltv: 770000000000000000n,
301
- * maxLif: 1061007957559681697n,
308
+ * liquidationCursor: 250000000000000000n,
302
309
  * oracle: "0x0000000000000000000000000000000000008000",
303
310
  * },
304
311
  * ],
@@ -329,7 +336,7 @@ var TreeUtils;
329
336
  * built-in Ecrecover and Setter helpers call this while generating
330
337
  * `ratifierData`.
331
338
  *
332
- * @param params.tree - Tree that contains the leaf.
339
+ * @param params.tree - Tree-like data with the root and leaves that contain the leaf.
333
340
  * @param params.leafIndex - Leaf index to prove.
334
341
  * @returns Proof descriptor.
335
342
  * @throws {InvalidTreeError} when leaf index is out of range.
@@ -340,12 +347,14 @@ var TreeUtils;
340
347
  *
341
348
  * const offer = Offer.create({
342
349
  * market: {
350
+ * chainId: 8453,
351
+ * midnight: "0x0000000000000000000000000000000000001000",
343
352
  * loanToken: "0x0000000000000000000000000000000000006000",
344
353
  * collateralParams: [
345
354
  * {
346
355
  * token: "0x0000000000000000000000000000000000007000",
347
356
  * lltv: 770000000000000000n,
348
- * maxLif: 1061007957559681697n,
357
+ * liquidationCursor: 250000000000000000n,
349
358
  * oracle: "0x0000000000000000000000000000000000008000",
350
359
  * },
351
360
  * ],
@@ -370,8 +379,7 @@ var TreeUtils;
370
379
  */
371
380
  function buildProof(params) {
372
381
  const leafIndex = BigInt(params.leafIndex);
373
- if (leafIndex < 0n ||
374
- leafIndex >= BigInt(params.tree.paddedOffers.length)) {
382
+ if (leafIndex < 0n || leafIndex >= BigInt(params.tree.leaves.length)) {
375
383
  throw new errors_js_1.InvalidTreeError(`Leaf index "${leafIndex}" is outside the tree.`);
376
384
  }
377
385
  let index = Number(leafIndex);
@@ -408,12 +416,14 @@ var TreeUtils;
408
416
  *
409
417
  * const offer = Offer.create({
410
418
  * market: {
419
+ * chainId: 8453,
420
+ * midnight: "0x0000000000000000000000000000000000001000",
411
421
  * loanToken: "0x0000000000000000000000000000000000006000",
412
422
  * collateralParams: [
413
423
  * {
414
424
  * token: "0x0000000000000000000000000000000000007000",
415
425
  * lltv: 770000000000000000n,
416
- * maxLif: 1061007957559681697n,
426
+ * liquidationCursor: 250000000000000000n,
417
427
  * oracle: "0x0000000000000000000000000000000000008000",
418
428
  * },
419
429
  * ],
@@ -0,0 +1,22 @@
1
+ import { type Hash } from "viem";
2
+ /**
3
+ * Hashes EIP-712 digest parts as `keccak256(0x1901 || domainSeparator || structHash)`.
4
+ *
5
+ * Use this when the domain separator and struct hash are already available and
6
+ * rebuilding full typed-data values would duplicate protocol-specific type maps.
7
+ *
8
+ * @param domainSeparator - EIP-712 domain separator hash.
9
+ * @param structHash - EIP-712 struct hash.
10
+ * @returns Canonical EIP-712 digest.
11
+ * @example
12
+ * ```ts
13
+ * import { eip712Digest } from "@morpho-org/midnight-sdk";
14
+ *
15
+ * const digest = eip712Digest(
16
+ * "0x0000000000000000000000000000000000000000000000000000000000000001",
17
+ * "0x0000000000000000000000000000000000000000000000000000000000000002",
18
+ * );
19
+ * console.log(digest);
20
+ * ```
21
+ */
22
+ export declare const eip712Digest: (domainSeparator: Hash, structHash: Hash) => Hash;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.eip712Digest = void 0;
4
+ const viem_1 = require("viem");
5
+ /**
6
+ * Hashes EIP-712 digest parts as `keccak256(0x1901 || domainSeparator || structHash)`.
7
+ *
8
+ * Use this when the domain separator and struct hash are already available and
9
+ * rebuilding full typed-data values would duplicate protocol-specific type maps.
10
+ *
11
+ * @param domainSeparator - EIP-712 domain separator hash.
12
+ * @param structHash - EIP-712 struct hash.
13
+ * @returns Canonical EIP-712 digest.
14
+ * @example
15
+ * ```ts
16
+ * import { eip712Digest } from "@morpho-org/midnight-sdk";
17
+ *
18
+ * const digest = eip712Digest(
19
+ * "0x0000000000000000000000000000000000000000000000000000000000000001",
20
+ * "0x0000000000000000000000000000000000000000000000000000000000000002",
21
+ * );
22
+ * console.log(digest);
23
+ * ```
24
+ */
25
+ const eip712Digest = (domainSeparator, structHash) => (0, viem_1.keccak256)((0, viem_1.concat)(["0x1901", domainSeparator, structHash]));
26
+ exports.eip712Digest = eip712Digest;
@@ -1,6 +1,8 @@
1
1
  export * from "./EcrecoverRatifierUtils.js";
2
+ export * from "./eip712.js";
2
3
  export * from "./Group.js";
3
4
  export * from "./GroupUtils.js";
5
+ export { Payload } from "./Payload.js";
4
6
  export * from "./RatifierUtils.js";
5
7
  export * from "./SetterRatifierUtils.js";
6
8
  export * from "./Tree.js";
@@ -14,9 +14,13 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.Payload = void 0;
17
18
  __exportStar(require("./EcrecoverRatifierUtils.js"), exports);
19
+ __exportStar(require("./eip712.js"), exports);
18
20
  __exportStar(require("./Group.js"), exports);
19
21
  __exportStar(require("./GroupUtils.js"), exports);
22
+ var Payload_js_1 = require("./Payload.js");
23
+ Object.defineProperty(exports, "Payload", { enumerable: true, get: function () { return Payload_js_1.Payload; } });
20
24
  __exportStar(require("./RatifierUtils.js"), exports);
21
25
  __exportStar(require("./SetterRatifierUtils.js"), exports);
22
26
  __exportStar(require("./Tree.js"), exports);
@@ -0,0 +1,14 @@
1
+ import { type OfferStruct } from "../offers/index.js";
2
+ /** @internal Empty protocol offer struct used for Merkle padding. */
3
+ export declare const EMPTY_OFFER_STRUCT: OfferStruct;
4
+ /** @internal Returns whether an address value is the zero address. */
5
+ export declare function isZeroAddress(value: string): boolean;
6
+ /**
7
+ * @internal Returns whether an offer struct is the protocol empty offer.
8
+ *
9
+ * Tree padding may carry the empty offer's derived default group, while payload
10
+ * decoding only treats the canonical zero-group empty struct as padding.
11
+ */
12
+ export declare function isEmptyOfferStruct(offer: OfferStruct, options?: {
13
+ readonly allowDefaultGroup?: boolean;
14
+ }): boolean;
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EMPTY_OFFER_STRUCT = void 0;
4
+ exports.isZeroAddress = isZeroAddress;
5
+ exports.isEmptyOfferStruct = isEmptyOfferStruct;
6
+ const viem_1 = require("viem");
7
+ const index_js_1 = require("../offers/index.js");
8
+ /** @internal Empty protocol offer struct used for Merkle padding. */
9
+ exports.EMPTY_OFFER_STRUCT = {
10
+ market: {
11
+ chainId: 0n,
12
+ midnight: viem_1.zeroAddress,
13
+ loanToken: viem_1.zeroAddress,
14
+ collateralParams: [],
15
+ maturity: 0n,
16
+ rcfThreshold: 0n,
17
+ enterGate: viem_1.zeroAddress,
18
+ liquidatorGate: viem_1.zeroAddress,
19
+ },
20
+ buy: false,
21
+ maker: viem_1.zeroAddress,
22
+ start: 0n,
23
+ expiry: 0n,
24
+ tick: 0n,
25
+ group: viem_1.zeroHash,
26
+ callback: viem_1.zeroAddress,
27
+ callbackData: "0x",
28
+ receiverIfMakerIsSeller: viem_1.zeroAddress,
29
+ ratifier: viem_1.zeroAddress,
30
+ reduceOnly: false,
31
+ maxUnits: 0n,
32
+ maxAssets: 0n,
33
+ continuousFeeCap: 0n,
34
+ };
35
+ const EMPTY_OFFER_DEFAULT_GROUP = index_js_1.OfferUtils.hashStruct(exports.EMPTY_OFFER_STRUCT);
36
+ /** @internal Returns whether an address value is the zero address. */
37
+ function isZeroAddress(value) {
38
+ return value.toLowerCase() === viem_1.zeroAddress;
39
+ }
40
+ /**
41
+ * @internal Returns whether an offer struct is the protocol empty offer.
42
+ *
43
+ * Tree padding may carry the empty offer's derived default group, while payload
44
+ * decoding only treats the canonical zero-group empty struct as padding.
45
+ */
46
+ function isEmptyOfferStruct(offer, options = {}) {
47
+ const hasEmptyGroup = offer.group === viem_1.zeroHash ||
48
+ (options.allowDefaultGroup === true &&
49
+ offer.group === EMPTY_OFFER_DEFAULT_GROUP);
50
+ return (offer.market.chainId === 0n &&
51
+ isZeroAddress(offer.market.midnight) &&
52
+ isZeroAddress(offer.market.loanToken) &&
53
+ offer.market.collateralParams.length === 0 &&
54
+ offer.market.maturity === 0n &&
55
+ offer.market.rcfThreshold === 0n &&
56
+ isZeroAddress(offer.market.enterGate) &&
57
+ isZeroAddress(offer.market.liquidatorGate) &&
58
+ offer.buy === false &&
59
+ isZeroAddress(offer.maker) &&
60
+ offer.start === 0n &&
61
+ offer.expiry === 0n &&
62
+ offer.tick === 0n &&
63
+ hasEmptyGroup &&
64
+ isZeroAddress(offer.callback) &&
65
+ offer.callbackData === "0x" &&
66
+ isZeroAddress(offer.receiverIfMakerIsSeller) &&
67
+ isZeroAddress(offer.ratifier) &&
68
+ offer.reduceOnly === false &&
69
+ offer.maxUnits === 0n &&
70
+ offer.maxAssets === 0n &&
71
+ offer.continuousFeeCap === 0n);
72
+ }