@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
@@ -1,4 +1,5 @@
1
1
  import type { Address, Hex } from "viem";
2
+ import type { RatifierTreeInput, TreeLike } from "./TreeUtils.js";
2
3
  /**
3
4
  * Parameters for {@link RatifierUtils.getRatifierInfo}.
4
5
  *
@@ -65,6 +66,62 @@ export interface RatifierInfo {
65
66
  * ```
66
67
  */
67
68
  export declare namespace RatifierUtils {
69
+ /**
70
+ * Normalizes a ratifier tree input and asserts it uses one ratifier address.
71
+ *
72
+ * Pass an existing `Tree` or `TreeLike` object to reuse cached offers,
73
+ * leaves, root, and height. Pass raw offer/group input when the caller has
74
+ * not materialized a tree yet.
75
+ *
76
+ * @param params.tree - Tree-like object or raw offer/group input.
77
+ * @param params.label - Ratifier label used in validation errors.
78
+ * @returns Normalized tree-like data and its shared ratifier.
79
+ * @throws {InvalidTreeError} when the tree is empty or contains multiple ratifiers.
80
+ * @throws {InvalidTreeHeightError} when normalized raw input exceeds the supported tree height.
81
+ * @example
82
+ * ```ts
83
+ * import { Offer, RatifierUtils } from "@morpho-org/midnight-sdk";
84
+ * import { zeroAddress } from "viem";
85
+ *
86
+ * const offer = Offer.create({
87
+ * market: {
88
+ * chainId: 8453,
89
+ * midnight: "0x0000000000000000000000000000000000001000",
90
+ * loanToken: "0x0000000000000000000000000000000000006000",
91
+ * collateralParams: [
92
+ * {
93
+ * token: "0x0000000000000000000000000000000000007000",
94
+ * lltv: 770000000000000000n,
95
+ * liquidationCursor: 250000000000000000n,
96
+ * oracle: "0x0000000000000000000000000000000000008000",
97
+ * },
98
+ * ],
99
+ * maturity: 54_000n,
100
+ * rcfThreshold: 0n,
101
+ * enterGate: zeroAddress,
102
+ * liquidatorGate: zeroAddress,
103
+ * },
104
+ * buy: true,
105
+ * maker: "0x0000000000000000000000000000000000009000",
106
+ * tick: 5_000n,
107
+ * expiry: 3_600n,
108
+ * ratifier: "0x0000000000000000000000000000000000004000",
109
+ * maxUnits: 100n,
110
+ * });
111
+ * const { tree, ratifier } = RatifierUtils.normalizeRatifierTree({
112
+ * tree: [offer],
113
+ * label: "Ecrecover",
114
+ * });
115
+ * console.log(tree.root, ratifier);
116
+ * ```
117
+ */
118
+ function normalizeRatifierTree(params: {
119
+ readonly tree: RatifierTreeInput;
120
+ readonly label: "Ecrecover" | "Setter";
121
+ }): {
122
+ readonly tree: TreeLike;
123
+ readonly ratifier: Address;
124
+ };
68
125
  /**
69
126
  * Checks whether bytecode is an EIP-7702 designator.
70
127
  *
@@ -1,3 +1,53 @@
1
+ import { InvalidTreeError } from "../errors.js";
2
+ import { Offer, OfferUtils } from "../offers/index.js";
3
+ import { Group } from "./Group.js";
4
+ import { GroupUtils } from "./GroupUtils.js";
5
+ import { TreeUtils } from "./TreeUtils.js";
6
+ function isTreeLike(tree) {
7
+ return (!Array.isArray(tree) &&
8
+ "offers" in tree &&
9
+ "paddedOffers" in tree &&
10
+ "leaves" in tree &&
11
+ "root" in tree &&
12
+ "height" in tree);
13
+ }
14
+ function normalizeTree(tree) {
15
+ if (isTreeLike(tree)) {
16
+ return tree;
17
+ }
18
+ const offers = tree.flatMap((entry) => GroupUtils.isGroupInput(entry)
19
+ ? Group.from(entry).offers
20
+ : [
21
+ new Offer({
22
+ ...Offer.from(entry),
23
+ group: OfferUtils.groupHash(entry),
24
+ }),
25
+ ]);
26
+ const descriptor = TreeUtils.buildDescriptor(offers, {
27
+ preserveStandaloneGroups: true,
28
+ });
29
+ return {
30
+ offers,
31
+ paddedOffers: descriptor.offers,
32
+ leaves: descriptor.leaves,
33
+ root: descriptor.root,
34
+ height: descriptor.height,
35
+ };
36
+ }
37
+ function assertRatifierTree(params) {
38
+ const firstOffer = params.tree.offers[0];
39
+ if (firstOffer == null) {
40
+ throw new InvalidTreeError("Tree must contain at least one offer.");
41
+ }
42
+ const ratifier = firstOffer.ratifier;
43
+ const comparableRatifier = ratifier.toLowerCase();
44
+ for (const offer of params.tree.offers.slice(1)) {
45
+ if (offer.ratifier.toLowerCase() !== comparableRatifier) {
46
+ throw new InvalidTreeError(`All offers in a ${params.label} tree must use one ratifier; expected "${ratifier}", got "${offer.ratifier}". Build separate trees per ratifier.`);
47
+ }
48
+ }
49
+ return ratifier;
50
+ }
1
51
  /**
2
52
  * Utilities for selecting Midnight ratifier routes.
3
53
  *
@@ -15,6 +65,61 @@
15
65
  */
16
66
  export var RatifierUtils;
17
67
  (function (RatifierUtils) {
68
+ /**
69
+ * Normalizes a ratifier tree input and asserts it uses one ratifier address.
70
+ *
71
+ * Pass an existing `Tree` or `TreeLike` object to reuse cached offers,
72
+ * leaves, root, and height. Pass raw offer/group input when the caller has
73
+ * not materialized a tree yet.
74
+ *
75
+ * @param params.tree - Tree-like object or raw offer/group input.
76
+ * @param params.label - Ratifier label used in validation errors.
77
+ * @returns Normalized tree-like data and its shared ratifier.
78
+ * @throws {InvalidTreeError} when the tree is empty or contains multiple ratifiers.
79
+ * @throws {InvalidTreeHeightError} when normalized raw input exceeds the supported tree height.
80
+ * @example
81
+ * ```ts
82
+ * import { Offer, RatifierUtils } from "@morpho-org/midnight-sdk";
83
+ * import { zeroAddress } from "viem";
84
+ *
85
+ * const offer = Offer.create({
86
+ * market: {
87
+ * chainId: 8453,
88
+ * midnight: "0x0000000000000000000000000000000000001000",
89
+ * loanToken: "0x0000000000000000000000000000000000006000",
90
+ * collateralParams: [
91
+ * {
92
+ * token: "0x0000000000000000000000000000000000007000",
93
+ * lltv: 770000000000000000n,
94
+ * liquidationCursor: 250000000000000000n,
95
+ * oracle: "0x0000000000000000000000000000000000008000",
96
+ * },
97
+ * ],
98
+ * maturity: 54_000n,
99
+ * rcfThreshold: 0n,
100
+ * enterGate: zeroAddress,
101
+ * liquidatorGate: zeroAddress,
102
+ * },
103
+ * buy: true,
104
+ * maker: "0x0000000000000000000000000000000000009000",
105
+ * tick: 5_000n,
106
+ * expiry: 3_600n,
107
+ * ratifier: "0x0000000000000000000000000000000000004000",
108
+ * maxUnits: 100n,
109
+ * });
110
+ * const { tree, ratifier } = RatifierUtils.normalizeRatifierTree({
111
+ * tree: [offer],
112
+ * label: "Ecrecover",
113
+ * });
114
+ * console.log(tree.root, ratifier);
115
+ * ```
116
+ */
117
+ function normalizeRatifierTree(params) {
118
+ const tree = normalizeTree(params.tree);
119
+ const ratifier = assertRatifierTree({ tree, label: params.label });
120
+ return { tree, ratifier };
121
+ }
122
+ RatifierUtils.normalizeRatifierTree = normalizeRatifierTree;
18
123
  /**
19
124
  * Checks whether bytecode is an EIP-7702 designator.
20
125
  *
@@ -1,8 +1,8 @@
1
1
  import { type BigIntish } from "@morpho-org/morpho-ts";
2
2
  import { type Hash, type Hex } from "viem";
3
- import type { Item as PayloadItem } from "./Payload.js";
4
- import type { Tree } from "./Tree.js";
5
- import type { TreeProof } from "./TreeUtils.js";
3
+ import { type IOffer } from "../offers/index.js";
4
+ import type { Payload } from "./Payload.js";
5
+ import { type RatifierTreeInput, type TreeProof } from "./TreeUtils.js";
6
6
  /**
7
7
  * Decoded SetterRatifier ratifier data.
8
8
  *
@@ -39,12 +39,14 @@ export type DecodedSetterRatifierData = TreeProof;
39
39
  *
40
40
  * const offer = Offer.create({
41
41
  * market: {
42
+ * chainId: 8453,
43
+ * midnight: "0x0000000000000000000000000000000000001000",
42
44
  * loanToken: "0x0000000000000000000000000000000000006000",
43
45
  * collateralParams: [
44
46
  * {
45
47
  * token: "0x0000000000000000000000000000000000007000",
46
48
  * lltv: 770000000000000000n,
47
- * maxLif: 1061007957559681697n,
49
+ * liquidationCursor: 250000000000000000n,
48
50
  * oracle: "0x0000000000000000000000000000000000008000",
49
51
  * },
50
52
  * ],
@@ -68,11 +70,18 @@ export type DecodedSetterRatifierData = TreeProof;
68
70
  * ```
69
71
  */
70
72
  export interface SetterRatifierDataParams {
71
- /** Tree that produced the proof. */
72
- readonly tree: Tree;
73
+ /** Tree-like input that produced the proof. Existing `Tree` instances reuse cached hashes and proofs. */
74
+ readonly tree: RatifierTreeInput;
73
75
  /** Leaf index to prove. */
74
76
  readonly leafIndex: BigIntish;
75
77
  }
78
+ /** Parameters for locally verifying Setter ratifier data attached to one payload item. */
79
+ export interface SetterRatifierDataVerificationParams {
80
+ /** Offer carried by the payload item. */
81
+ readonly offer: IOffer;
82
+ /** ABI-encoded Setter ratifier data carried by the payload item. */
83
+ readonly ratifierData: Hex;
84
+ }
76
85
  /**
77
86
  * SetterRatifier-specific pure utilities.
78
87
  *
@@ -80,6 +89,9 @@ export interface SetterRatifierDataParams {
80
89
  * offers with the Setter ratifier address, build the group/tree, validate the
81
90
  * tree, approve the root onchain for every maker in the tree, call `ratify`,
82
91
  * then pass the returned items to `Payload.encode`.
92
+ * Ratifier helpers accept tree-like inputs rather than requiring the `Tree`
93
+ * class. Passing an existing `Tree` remains the optimal path because its
94
+ * cached offers, leaves, root, and height are reused when proofs are encoded.
83
95
  *
84
96
  * @example
85
97
  * ```ts
@@ -140,6 +152,29 @@ export declare namespace SetterRatifierUtils {
140
152
  * ```
141
153
  */
142
154
  function decodeRatifierData(data: Hex): DecodedSetterRatifierData;
155
+ /**
156
+ * Verifies that Setter ratifier data proves one payload offer belongs to its root.
157
+ *
158
+ * This helper intentionally does not check `SetterRatifier.isRootRatified` or
159
+ * `Midnight.isAuthorized` state. Consumers can query those values at their
160
+ * own block context after local proof verification.
161
+ *
162
+ * @param params.offer - Offer carried by the payload item.
163
+ * @param params.ratifierData - ABI-encoded Setter ratifier data.
164
+ * @returns Decoded Setter ratifier data after proof verification.
165
+ * @throws {InvalidTreeError} when the proof does not include `offer` in `root`.
166
+ * @example
167
+ * ```ts
168
+ * import { SetterRatifierUtils } from "@morpho-org/midnight-sdk";
169
+ *
170
+ * const decoded = SetterRatifierUtils.verifyRatifierData({
171
+ * offer,
172
+ * ratifierData,
173
+ * });
174
+ * console.log(decoded.root);
175
+ * ```
176
+ */
177
+ function verifyRatifierData(params: SetterRatifierDataVerificationParams): DecodedSetterRatifierData;
143
178
  /**
144
179
  * Builds one ratifier-data value for a tree leaf.
145
180
  *
@@ -148,10 +183,10 @@ export declare namespace SetterRatifierUtils {
148
183
  * approvals are keyed by maker and root, so the maker for this leaf must have
149
184
  * approved the tree root onchain.
150
185
  *
151
- * @param params.tree - Setter-ratified offer tree that produced the proof.
186
+ * @param params.tree - Setter-ratified offer tree-like input that produced the proof.
152
187
  * @param params.leafIndex - Leaf index to prove.
153
188
  * @returns ABI-encoded SetterRatifier data.
154
- * @throws {InvalidTreeError} when the leaf index is outside the tree.
189
+ * @throws {InvalidTreeError} when the leaf index is outside the tree or the tree contains multiple ratifiers.
155
190
  * @example
156
191
  * ```ts
157
192
  * import { Offer, SetterRatifierUtils, Tree } from "@morpho-org/midnight-sdk";
@@ -159,12 +194,14 @@ export declare namespace SetterRatifierUtils {
159
194
  *
160
195
  * const offer = Offer.create({
161
196
  * market: {
197
+ * chainId: 8453,
198
+ * midnight: "0x0000000000000000000000000000000000001000",
162
199
  * loanToken: "0x0000000000000000000000000000000000006000",
163
200
  * collateralParams: [
164
201
  * {
165
202
  * token: "0x0000000000000000000000000000000000007000",
166
203
  * lltv: 770000000000000000n,
167
- * maxLif: 1061007957559681697n,
204
+ * liquidationCursor: 250000000000000000n,
168
205
  * oracle: "0x0000000000000000000000000000000000008000",
169
206
  * },
170
207
  * ],
@@ -198,7 +235,7 @@ export declare namespace SetterRatifierUtils {
198
235
  * directly to `Payload.encode`. All offers in the tree must use one ratifier
199
236
  * address; build separate trees per ratifier.
200
237
  *
201
- * @param params.tree - Setter-ratified offer tree whose root has already been approved onchain.
238
+ * @param params.tree - Setter-ratified offer tree-like input whose root has already been approved onchain.
202
239
  * @returns Items containing each offer and its ratifier data.
203
240
  * @throws {InvalidTreeError} when the tree is invalid or contains multiple ratifiers.
204
241
  * @example
@@ -209,12 +246,14 @@ export declare namespace SetterRatifierUtils {
209
246
  *
210
247
  * const offer = Offer.create({
211
248
  * market: {
249
+ * chainId: 8453,
250
+ * midnight: "0x0000000000000000000000000000000000001000",
212
251
  * loanToken: "0x0000000000000000000000000000000000006000",
213
252
  * collateralParams: [
214
253
  * {
215
254
  * token: "0x0000000000000000000000000000000000007000",
216
255
  * lltv: 770000000000000000n,
217
- * maxLif: 1061007957559681697n,
256
+ * liquidationCursor: 250000000000000000n,
218
257
  * oracle: "0x0000000000000000000000000000000000008000",
219
258
  * },
220
259
  * ],
@@ -238,6 +277,6 @@ export declare namespace SetterRatifierUtils {
238
277
  * ```
239
278
  */
240
279
  function ratify(params: {
241
- readonly tree: Tree;
242
- }): readonly PayloadItem[];
280
+ readonly tree: RatifierTreeInput;
281
+ }): readonly Payload.Item[];
243
282
  }
@@ -1,6 +1,9 @@
1
1
  import { deepFreeze } from "@morpho-org/morpho-ts";
2
2
  import { decodeAbiParameters, encodeAbiParameters, } from "viem";
3
3
  import { InvalidTreeError } from "../errors.js";
4
+ import { Offer } from "../offers/index.js";
5
+ import { RatifierUtils } from "./RatifierUtils.js";
6
+ import { TreeUtils, } from "./TreeUtils.js";
4
7
  const setterRatifierDataAbi = [
5
8
  { name: "root", type: "bytes32" },
6
9
  { name: "leafIndex", type: "uint256" },
@@ -13,6 +16,9 @@ const setterRatifierDataAbi = [
13
16
  * offers with the Setter ratifier address, build the group/tree, validate the
14
17
  * tree, approve the root onchain for every maker in the tree, call `ratify`,
15
18
  * then pass the returned items to `Payload.encode`.
19
+ * Ratifier helpers accept tree-like inputs rather than requiring the `Tree`
20
+ * class. Passing an existing `Tree` remains the optimal path because its
21
+ * cached offers, leaves, root, and height are reused when proofs are encoded.
16
22
  *
17
23
  * @example
18
24
  * ```ts
@@ -81,6 +87,42 @@ export var SetterRatifierUtils;
81
87
  return deepFreeze({ root, leafIndex, proof: [...proof] });
82
88
  }
83
89
  SetterRatifierUtils.decodeRatifierData = decodeRatifierData;
90
+ /**
91
+ * Verifies that Setter ratifier data proves one payload offer belongs to its root.
92
+ *
93
+ * This helper intentionally does not check `SetterRatifier.isRootRatified` or
94
+ * `Midnight.isAuthorized` state. Consumers can query those values at their
95
+ * own block context after local proof verification.
96
+ *
97
+ * @param params.offer - Offer carried by the payload item.
98
+ * @param params.ratifierData - ABI-encoded Setter ratifier data.
99
+ * @returns Decoded Setter ratifier data after proof verification.
100
+ * @throws {InvalidTreeError} when the proof does not include `offer` in `root`.
101
+ * @example
102
+ * ```ts
103
+ * import { SetterRatifierUtils } from "@morpho-org/midnight-sdk";
104
+ *
105
+ * const decoded = SetterRatifierUtils.verifyRatifierData({
106
+ * offer,
107
+ * ratifierData,
108
+ * });
109
+ * console.log(decoded.root);
110
+ * ```
111
+ */
112
+ function verifyRatifierData(params) {
113
+ const offer = Offer.from(params.offer);
114
+ const decoded = decodeRatifierData(params.ratifierData);
115
+ if (!TreeUtils.verifyProof({
116
+ offer,
117
+ root: decoded.root,
118
+ leafIndex: decoded.leafIndex,
119
+ proof: decoded.proof,
120
+ })) {
121
+ throw new InvalidTreeError("Ratifier data proof does not include offer.");
122
+ }
123
+ return decoded;
124
+ }
125
+ SetterRatifierUtils.verifyRatifierData = verifyRatifierData;
84
126
  /**
85
127
  * Builds one ratifier-data value for a tree leaf.
86
128
  *
@@ -89,10 +131,10 @@ export var SetterRatifierUtils;
89
131
  * approvals are keyed by maker and root, so the maker for this leaf must have
90
132
  * approved the tree root onchain.
91
133
  *
92
- * @param params.tree - Setter-ratified offer tree that produced the proof.
134
+ * @param params.tree - Setter-ratified offer tree-like input that produced the proof.
93
135
  * @param params.leafIndex - Leaf index to prove.
94
136
  * @returns ABI-encoded SetterRatifier data.
95
- * @throws {InvalidTreeError} when the leaf index is outside the tree.
137
+ * @throws {InvalidTreeError} when the leaf index is outside the tree or the tree contains multiple ratifiers.
96
138
  * @example
97
139
  * ```ts
98
140
  * import { Offer, SetterRatifierUtils, Tree } from "@morpho-org/midnight-sdk";
@@ -100,12 +142,14 @@ export var SetterRatifierUtils;
100
142
  *
101
143
  * const offer = Offer.create({
102
144
  * market: {
145
+ * chainId: 8453,
146
+ * midnight: "0x0000000000000000000000000000000000001000",
103
147
  * loanToken: "0x0000000000000000000000000000000000006000",
104
148
  * collateralParams: [
105
149
  * {
106
150
  * token: "0x0000000000000000000000000000000000007000",
107
151
  * lltv: 770000000000000000n,
108
- * maxLif: 1061007957559681697n,
152
+ * liquidationCursor: 250000000000000000n,
109
153
  * oracle: "0x0000000000000000000000000000000000008000",
110
154
  * },
111
155
  * ],
@@ -129,7 +173,11 @@ export var SetterRatifierUtils;
129
173
  * ```
130
174
  */
131
175
  function ratifierData(params) {
132
- const proof = params.tree.proof(params.leafIndex);
176
+ const { tree } = RatifierUtils.normalizeRatifierTree({
177
+ tree: params.tree,
178
+ label: "Setter",
179
+ });
180
+ const proof = TreeUtils.buildProof({ tree, leafIndex: params.leafIndex });
133
181
  return encodeRatifierData({
134
182
  root: proof.root,
135
183
  leafIndex: proof.leafIndex,
@@ -147,7 +195,7 @@ export var SetterRatifierUtils;
147
195
  * directly to `Payload.encode`. All offers in the tree must use one ratifier
148
196
  * address; build separate trees per ratifier.
149
197
  *
150
- * @param params.tree - Setter-ratified offer tree whose root has already been approved onchain.
198
+ * @param params.tree - Setter-ratified offer tree-like input whose root has already been approved onchain.
151
199
  * @returns Items containing each offer and its ratifier data.
152
200
  * @throws {InvalidTreeError} when the tree is invalid or contains multiple ratifiers.
153
201
  * @example
@@ -158,12 +206,14 @@ export var SetterRatifierUtils;
158
206
  *
159
207
  * const offer = Offer.create({
160
208
  * market: {
209
+ * chainId: 8453,
210
+ * midnight: "0x0000000000000000000000000000000000001000",
161
211
  * loanToken: "0x0000000000000000000000000000000000006000",
162
212
  * collateralParams: [
163
213
  * {
164
214
  * token: "0x0000000000000000000000000000000000007000",
165
215
  * lltv: 770000000000000000n,
166
- * maxLif: 1061007957559681697n,
216
+ * liquidationCursor: 250000000000000000n,
167
217
  * oracle: "0x0000000000000000000000000000000000008000",
168
218
  * },
169
219
  * ],
@@ -187,23 +237,16 @@ export var SetterRatifierUtils;
187
237
  * ```
188
238
  */
189
239
  function ratify(params) {
190
- const firstOffer = params.tree.offers[0];
191
- if (firstOffer == null) {
192
- throw new InvalidTreeError("Tree must contain at least one offer.");
193
- }
194
- const ratifier = firstOffer.ratifier;
195
- const comparableRatifier = ratifier.toLowerCase();
196
- for (const offer of params.tree.offers.slice(1)) {
197
- if (offer.ratifier.toLowerCase() !== comparableRatifier) {
198
- throw new InvalidTreeError(`All offers in a Setter tree must use one ratifier; expected "${ratifier}", got "${offer.ratifier}". Build separate trees per ratifier.`);
199
- }
200
- }
240
+ const { tree } = RatifierUtils.normalizeRatifierTree({
241
+ tree: params.tree,
242
+ label: "Setter",
243
+ });
201
244
  const items = [];
202
- for (const offer of params.tree.offers) {
245
+ for (const offer of tree.offers) {
203
246
  items.push({
204
247
  offer,
205
248
  ratifierData: ratifierData({
206
- tree: params.tree,
249
+ tree,
207
250
  leafIndex: items.length,
208
251
  }),
209
252
  });
@@ -1,9 +1,9 @@
1
1
  import type { BigIntish } from "@morpho-org/morpho-ts";
2
2
  import type { Hash } from "viem";
3
- import type { MempoolPayloadValidationResult } from "../api/types.js";
3
+ import type { MempoolPayloadValidationSuccess } from "../api/types.js";
4
4
  import { Offer, type OfferStruct } from "../offers/index.js";
5
5
  import { type TreeCreateParams, type TreeInput, type TreeMempoolValidateParams, type TreeProof } from "./TreeUtils.js";
6
- export type { TreeCreateParams, TreeDescriptor, TreeInput, TreeMempoolValidateParams, TreeProof, TreeUtilsMempoolValidateParams, } from "./TreeUtils.js";
6
+ export type { RatifierTreeInput, TreeCreateParams, TreeDescriptor, TreeInput, TreeLike, TreeMempoolValidateParams, TreeMempoolValidateRatification, TreeProof, } from "./TreeUtils.js";
7
7
  /**
8
8
  * Maker-side Merkle tree used by Midnight ratifiers.
9
9
  *
@@ -18,12 +18,14 @@ export type { TreeCreateParams, TreeDescriptor, TreeInput, TreeMempoolValidatePa
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
  * ],
@@ -73,12 +75,14 @@ export declare class Tree {
73
75
  *
74
76
  * const offer = Offer.create({
75
77
  * market: {
78
+ * chainId: 8453,
79
+ * midnight: "0x0000000000000000000000000000000000001000",
76
80
  * loanToken: "0x0000000000000000000000000000000000006000",
77
81
  * collateralParams: [
78
82
  * {
79
83
  * token: "0x0000000000000000000000000000000000007000",
80
84
  * lltv: 770000000000000000n,
81
- * maxLif: 1061007957559681697n,
85
+ * liquidationCursor: 250000000000000000n,
82
86
  * oracle: "0x0000000000000000000000000000000000008000",
83
87
  * },
84
88
  * ],
@@ -118,12 +122,14 @@ export declare class Tree {
118
122
  *
119
123
  * const offer = Offer.create({
120
124
  * market: {
125
+ * chainId: 8453,
126
+ * midnight: "0x0000000000000000000000000000000000001000",
121
127
  * loanToken: "0x0000000000000000000000000000000000006000",
122
128
  * collateralParams: [
123
129
  * {
124
130
  * token: "0x0000000000000000000000000000000000007000",
125
131
  * lltv: 770000000000000000n,
126
- * maxLif: 1061007957559681697n,
132
+ * liquidationCursor: 250000000000000000n,
127
133
  * oracle: "0x0000000000000000000000000000000000008000",
128
134
  * },
129
135
  * ],
@@ -147,20 +153,23 @@ export declare class Tree {
147
153
  /**
148
154
  * Validates this tree against Midnight mempool API policy.
149
155
  *
150
- * This is an API-backed convenience: it encodes each tree leaf with empty
151
- * `ratifierData`, then sends the temporary payload to the Midnight API
152
- * `POST /mempool/validate` endpoint. API policy only inspects offer contents,
153
- * so use this before wallet signature or Setter root approval.
156
+ * This is an API-backed convenience: by default it encodes each tree leaf
157
+ * with empty `ratifierData`, then sends the temporary payload to the Midnight
158
+ * API `POST /mempool/validate` endpoint. Pass `ratification` after signing or
159
+ * Setter root preparation to validate final payload bytes with real
160
+ * `ratifierData`.
154
161
  *
155
162
  * @param params.chainId - Chain id whose API policy should validate this tree.
156
163
  * @param params.apiUrl - Optional Midnight API URL override used for the validation HTTP request.
157
164
  * @param params.timestamp - Optional ISO-8601 timestamp or `Date` selecting the API policy snapshot.
158
165
  * @param params.fetch - Optional fetch implementation override used for the API call.
159
166
  * @param params.request - Optional fetch options forwarded to the API request.
160
- * @returns API issues and `valid` summary.
161
- * @throws {Payload.DecodeError} when validation payload encoding fails.
167
+ * @param params.ratification - Optional ratification inputs used to validate final payload bytes with real ratifier data.
168
+ * @returns Successful API validation result with `valid: true`.
169
+ * @throws {PayloadDecodeError} when validation payload encoding fails.
162
170
  * @throws {MidnightApiError} when the API returns a non-2xx response.
163
171
  * @throws {InvalidMidnightApiResponseError} when the API returns malformed success JSON.
172
+ * @throws {MidnightMempoolValidationError} when the API returns validation issues.
164
173
  * @example
165
174
  * ```ts
166
175
  * import { Offer, Tree } from "@morpho-org/midnight-sdk";
@@ -168,12 +177,14 @@ export declare class Tree {
168
177
  *
169
178
  * const offer = Offer.create({
170
179
  * market: {
180
+ * chainId: 8453,
181
+ * midnight: "0x0000000000000000000000000000000000001000",
171
182
  * loanToken: "0x0000000000000000000000000000000000006000",
172
183
  * collateralParams: [
173
184
  * {
174
185
  * token: "0x0000000000000000000000000000000000007000",
175
186
  * lltv: 770000000000000000n,
176
- * maxLif: 1061007957559681697n,
187
+ * liquidationCursor: 250000000000000000n,
177
188
  * oracle: "0x0000000000000000000000000000000000008000",
178
189
  * },
179
190
  * ],
@@ -189,13 +200,12 @@ export declare class Tree {
189
200
  * ratifier: "0x0000000000000000000000000000000000004000",
190
201
  * maxUnits: 100n,
191
202
  * });
192
- * const validation = await Tree.create([offer]).mempoolValidate({
203
+ * await Tree.create([offer]).mempoolValidate({
193
204
  * chainId: 8453,
194
205
  * });
195
- * console.log(validation.valid);
196
206
  * ```
197
207
  */
198
- mempoolValidate(params: TreeMempoolValidateParams): Promise<MempoolPayloadValidationResult>;
208
+ mempoolValidate(params: TreeMempoolValidateParams): Promise<MempoolPayloadValidationSuccess>;
199
209
  /**
200
210
  * Builds a Merkle proof for one leaf.
201
211
  *
@@ -212,12 +222,14 @@ export declare class Tree {
212
222
  *
213
223
  * const offer = Offer.create({
214
224
  * market: {
225
+ * chainId: 8453,
226
+ * midnight: "0x0000000000000000000000000000000000001000",
215
227
  * loanToken: "0x0000000000000000000000000000000000006000",
216
228
  * collateralParams: [
217
229
  * {
218
230
  * token: "0x0000000000000000000000000000000000007000",
219
231
  * lltv: 770000000000000000n,
220
- * maxLif: 1061007957559681697n,
232
+ * liquidationCursor: 250000000000000000n,
221
233
  * oracle: "0x0000000000000000000000000000000000008000",
222
234
  * },
223
235
  * ],