@morpho-org/midnight-sdk 0.1.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 (157) hide show
  1. package/README.md +252 -0
  2. package/lib/cjs/abis.d.ts +3170 -0
  3. package/lib/cjs/abis.js +4073 -0
  4. package/lib/cjs/api/MidnightApi.d.ts +532 -0
  5. package/lib/cjs/api/MidnightApi.js +713 -0
  6. package/lib/cjs/api/helpers.d.ts +20 -0
  7. package/lib/cjs/api/helpers.js +189 -0
  8. package/lib/cjs/api/index.d.ts +2 -0
  9. package/lib/cjs/api/index.js +21 -0
  10. package/lib/cjs/api/types.d.ts +453 -0
  11. package/lib/cjs/api/types.js +2 -0
  12. package/lib/cjs/constants.d.ts +168 -0
  13. package/lib/cjs/constants.js +187 -0
  14. package/lib/cjs/errors.d.ts +253 -0
  15. package/lib/cjs/errors.js +309 -0
  16. package/lib/cjs/fetch/Market.d.ts +65 -0
  17. package/lib/cjs/fetch/Market.js +117 -0
  18. package/lib/cjs/fetch/Offer.d.ts +74 -0
  19. package/lib/cjs/fetch/Offer.js +119 -0
  20. package/lib/cjs/fetch/Position.d.ts +85 -0
  21. package/lib/cjs/fetch/Position.js +148 -0
  22. package/lib/cjs/fetch/Ratifier.d.ts +38 -0
  23. package/lib/cjs/fetch/Ratifier.js +57 -0
  24. package/lib/cjs/fetch/index.d.ts +5 -0
  25. package/lib/cjs/fetch/index.js +21 -0
  26. package/lib/cjs/fetch/types.d.ts +57 -0
  27. package/lib/cjs/fetch/types.js +2 -0
  28. package/lib/cjs/fetch/utils.d.ts +8 -0
  29. package/lib/cjs/fetch/utils.js +18 -0
  30. package/lib/cjs/index.d.ts +18 -0
  31. package/lib/cjs/index.js +57 -0
  32. package/lib/cjs/market/Market.d.ts +613 -0
  33. package/lib/cjs/market/Market.js +503 -0
  34. package/lib/cjs/market/MarketUtils.d.ts +189 -0
  35. package/lib/cjs/market/MarketUtils.js +303 -0
  36. package/lib/cjs/market/Position.d.ts +424 -0
  37. package/lib/cjs/market/Position.js +425 -0
  38. package/lib/cjs/market/PositionUtils.d.ts +115 -0
  39. package/lib/cjs/market/PositionUtils.js +194 -0
  40. package/lib/cjs/market/index.d.ts +4 -0
  41. package/lib/cjs/market/index.js +20 -0
  42. package/lib/cjs/math/ConsumableUnitsLib.d.ts +57 -0
  43. package/lib/cjs/math/ConsumableUnitsLib.js +77 -0
  44. package/lib/cjs/math/TakeAmountsLib.d.ts +175 -0
  45. package/lib/cjs/math/TakeAmountsLib.js +199 -0
  46. package/lib/cjs/math/TickLib.d.ts +200 -0
  47. package/lib/cjs/math/TickLib.js +272 -0
  48. package/lib/cjs/math/index.d.ts +3 -0
  49. package/lib/cjs/math/index.js +19 -0
  50. package/lib/cjs/offers/Offer.d.ts +534 -0
  51. package/lib/cjs/offers/Offer.js +343 -0
  52. package/lib/cjs/offers/OfferUtils.d.ts +565 -0
  53. package/lib/cjs/offers/OfferUtils.js +659 -0
  54. package/lib/cjs/offers/index.d.ts +2 -0
  55. package/lib/cjs/offers/index.js +18 -0
  56. package/lib/cjs/package.json +1 -0
  57. package/lib/cjs/queries/GetPosition.d.ts +55 -0
  58. package/lib/cjs/queries/GetPosition.js +74 -0
  59. package/lib/cjs/queries/index.d.ts +1 -0
  60. package/lib/cjs/queries/index.js +37 -0
  61. package/lib/cjs/signatures/EcrecoverRatifierUtils.d.ts +733 -0
  62. package/lib/cjs/signatures/EcrecoverRatifierUtils.js +618 -0
  63. package/lib/cjs/signatures/Group.d.ts +178 -0
  64. package/lib/cjs/signatures/Group.js +193 -0
  65. package/lib/cjs/signatures/GroupUtils.d.ts +191 -0
  66. package/lib/cjs/signatures/GroupUtils.js +127 -0
  67. package/lib/cjs/signatures/Payload.d.ts +283 -0
  68. package/lib/cjs/signatures/Payload.js +570 -0
  69. package/lib/cjs/signatures/RatifierUtils.d.ts +109 -0
  70. package/lib/cjs/signatures/RatifierUtils.js +76 -0
  71. package/lib/cjs/signatures/SetterRatifierUtils.d.ts +243 -0
  72. package/lib/cjs/signatures/SetterRatifierUtils.js +217 -0
  73. package/lib/cjs/signatures/Tree.d.ts +241 -0
  74. package/lib/cjs/signatures/Tree.js +263 -0
  75. package/lib/cjs/signatures/TreeUtils.d.ts +573 -0
  76. package/lib/cjs/signatures/TreeUtils.js +461 -0
  77. package/lib/cjs/signatures/index.d.ts +7 -0
  78. package/lib/cjs/signatures/index.js +23 -0
  79. package/lib/esm/abis.d.ts +3170 -0
  80. package/lib/esm/abis.js +4070 -0
  81. package/lib/esm/api/MidnightApi.d.ts +532 -0
  82. package/lib/esm/api/MidnightApi.js +709 -0
  83. package/lib/esm/api/helpers.d.ts +20 -0
  84. package/lib/esm/api/helpers.js +180 -0
  85. package/lib/esm/api/index.d.ts +2 -0
  86. package/lib/esm/api/index.js +2 -0
  87. package/lib/esm/api/types.d.ts +453 -0
  88. package/lib/esm/api/types.js +1 -0
  89. package/lib/esm/constants.d.ts +168 -0
  90. package/lib/esm/constants.js +184 -0
  91. package/lib/esm/errors.d.ts +253 -0
  92. package/lib/esm/errors.js +291 -0
  93. package/lib/esm/fetch/Market.d.ts +65 -0
  94. package/lib/esm/fetch/Market.js +113 -0
  95. package/lib/esm/fetch/Offer.d.ts +74 -0
  96. package/lib/esm/fetch/Offer.js +116 -0
  97. package/lib/esm/fetch/Position.d.ts +85 -0
  98. package/lib/esm/fetch/Position.js +144 -0
  99. package/lib/esm/fetch/Ratifier.d.ts +38 -0
  100. package/lib/esm/fetch/Ratifier.js +54 -0
  101. package/lib/esm/fetch/index.d.ts +5 -0
  102. package/lib/esm/fetch/index.js +5 -0
  103. package/lib/esm/fetch/types.d.ts +57 -0
  104. package/lib/esm/fetch/types.js +1 -0
  105. package/lib/esm/fetch/utils.d.ts +8 -0
  106. package/lib/esm/fetch/utils.js +12 -0
  107. package/lib/esm/index.d.ts +18 -0
  108. package/lib/esm/index.js +18 -0
  109. package/lib/esm/market/Market.d.ts +613 -0
  110. package/lib/esm/market/Market.js +498 -0
  111. package/lib/esm/market/MarketUtils.d.ts +189 -0
  112. package/lib/esm/market/MarketUtils.js +300 -0
  113. package/lib/esm/market/Position.d.ts +424 -0
  114. package/lib/esm/market/Position.js +420 -0
  115. package/lib/esm/market/PositionUtils.d.ts +115 -0
  116. package/lib/esm/market/PositionUtils.js +191 -0
  117. package/lib/esm/market/index.d.ts +4 -0
  118. package/lib/esm/market/index.js +4 -0
  119. package/lib/esm/math/ConsumableUnitsLib.d.ts +57 -0
  120. package/lib/esm/math/ConsumableUnitsLib.js +74 -0
  121. package/lib/esm/math/TakeAmountsLib.d.ts +175 -0
  122. package/lib/esm/math/TakeAmountsLib.js +196 -0
  123. package/lib/esm/math/TickLib.d.ts +200 -0
  124. package/lib/esm/math/TickLib.js +269 -0
  125. package/lib/esm/math/index.d.ts +3 -0
  126. package/lib/esm/math/index.js +3 -0
  127. package/lib/esm/offers/Offer.d.ts +534 -0
  128. package/lib/esm/offers/Offer.js +339 -0
  129. package/lib/esm/offers/OfferUtils.d.ts +565 -0
  130. package/lib/esm/offers/OfferUtils.js +656 -0
  131. package/lib/esm/offers/index.d.ts +2 -0
  132. package/lib/esm/offers/index.js +2 -0
  133. package/lib/esm/package.json +1 -0
  134. package/lib/esm/queries/GetPosition.d.ts +55 -0
  135. package/lib/esm/queries/GetPosition.js +71 -0
  136. package/lib/esm/queries/index.d.ts +1 -0
  137. package/lib/esm/queries/index.js +1 -0
  138. package/lib/esm/signatures/EcrecoverRatifierUtils.d.ts +733 -0
  139. package/lib/esm/signatures/EcrecoverRatifierUtils.js +615 -0
  140. package/lib/esm/signatures/Group.d.ts +178 -0
  141. package/lib/esm/signatures/Group.js +189 -0
  142. package/lib/esm/signatures/GroupUtils.d.ts +191 -0
  143. package/lib/esm/signatures/GroupUtils.js +124 -0
  144. package/lib/esm/signatures/Payload.d.ts +283 -0
  145. package/lib/esm/signatures/Payload.js +564 -0
  146. package/lib/esm/signatures/RatifierUtils.d.ts +109 -0
  147. package/lib/esm/signatures/RatifierUtils.js +73 -0
  148. package/lib/esm/signatures/SetterRatifierUtils.d.ts +243 -0
  149. package/lib/esm/signatures/SetterRatifierUtils.js +214 -0
  150. package/lib/esm/signatures/Tree.d.ts +241 -0
  151. package/lib/esm/signatures/Tree.js +259 -0
  152. package/lib/esm/signatures/TreeUtils.d.ts +573 -0
  153. package/lib/esm/signatures/TreeUtils.js +458 -0
  154. package/lib/esm/signatures/index.d.ts +7 -0
  155. package/lib/esm/signatures/index.js +7 -0
  156. package/package.json +69 -0
  157. package/src/index.ts +19 -0
@@ -0,0 +1,458 @@
1
+ import { deepFreeze } from "@morpho-org/morpho-ts";
2
+ import { concat, keccak256 } from "viem";
3
+ import { MidnightApi } from "../api/MidnightApi.js";
4
+ import { InvalidTreeError, InvalidTreeHeightError } from "../errors.js";
5
+ import { Offer, OfferUtils, } from "../offers/index.js";
6
+ import { Group } from "./Group.js";
7
+ import { GroupUtils } from "./GroupUtils.js";
8
+ import { encode as encodePayload } from "./Payload.js";
9
+ const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
10
+ const ZERO_BYTES32 = "0x0000000000000000000000000000000000000000000000000000000000000000";
11
+ const EMPTY_OFFER_STRUCT = {
12
+ market: {
13
+ loanToken: ZERO_ADDRESS,
14
+ collateralParams: [],
15
+ maturity: 0n,
16
+ rcfThreshold: 0n,
17
+ enterGate: ZERO_ADDRESS,
18
+ liquidatorGate: ZERO_ADDRESS,
19
+ },
20
+ buy: false,
21
+ maker: ZERO_ADDRESS,
22
+ start: 0n,
23
+ expiry: 0n,
24
+ tick: 0n,
25
+ group: ZERO_BYTES32,
26
+ callback: ZERO_ADDRESS,
27
+ callbackData: "0x",
28
+ receiverIfMakerIsSeller: ZERO_ADDRESS,
29
+ ratifier: ZERO_ADDRESS,
30
+ reduceOnly: false,
31
+ maxUnits: 0n,
32
+ maxAssets: 0n,
33
+ continuousFeeCap: 0n,
34
+ };
35
+ const EMPTY_OFFER_DEFAULT_GROUP = OfferUtils.hashStruct(EMPTY_OFFER_STRUCT);
36
+ function isEmptyOfferStruct(offer) {
37
+ return (offer.market.loanToken === ZERO_ADDRESS &&
38
+ offer.market.collateralParams.length === 0 &&
39
+ offer.market.maturity === 0n &&
40
+ offer.market.rcfThreshold === 0n &&
41
+ offer.market.enterGate === ZERO_ADDRESS &&
42
+ offer.market.liquidatorGate === ZERO_ADDRESS &&
43
+ offer.buy === false &&
44
+ offer.maker === ZERO_ADDRESS &&
45
+ offer.start === 0n &&
46
+ offer.expiry === 0n &&
47
+ offer.tick === 0n &&
48
+ (offer.group === ZERO_BYTES32 ||
49
+ offer.group === EMPTY_OFFER_DEFAULT_GROUP) &&
50
+ offer.callback === ZERO_ADDRESS &&
51
+ offer.callbackData === "0x" &&
52
+ offer.receiverIfMakerIsSeller === ZERO_ADDRESS &&
53
+ offer.ratifier === ZERO_ADDRESS &&
54
+ offer.reduceOnly === false &&
55
+ offer.maxUnits === 0n &&
56
+ offer.maxAssets === 0n &&
57
+ offer.continuousFeeCap === 0n);
58
+ }
59
+ function isPowerOfTwo(value) {
60
+ return value > 0 && (value & (value - 1)) === 0;
61
+ }
62
+ function nextPowerOfTwo(value) {
63
+ return 2 ** Math.ceil(Math.log2(value));
64
+ }
65
+ function padOfferStructs(offers) {
66
+ if (isPowerOfTwo(offers.length))
67
+ return [...offers];
68
+ const paddedLength = nextPowerOfTwo(offers.length);
69
+ return [
70
+ ...offers,
71
+ ...Array.from({ length: paddedLength - offers.length }, () => EMPTY_OFFER_STRUCT),
72
+ ];
73
+ }
74
+ function assertLeafOffers(offers, leafHashes) {
75
+ const seen = new Set();
76
+ for (const [index, offer] of offers.entries()) {
77
+ if (isEmptyOfferStruct(offer))
78
+ continue;
79
+ const leafHash = leafHashes[index];
80
+ if (seen.has(leafHash)) {
81
+ throw new InvalidTreeError(`Duplicate offer hash "${leafHash}" in tree.`);
82
+ }
83
+ seen.add(leafHash);
84
+ }
85
+ if (seen.size === 0) {
86
+ throw new InvalidTreeError("Tree must not be empty.");
87
+ }
88
+ }
89
+ /**
90
+ * Object-compatible tree hashing, root, proof, and verification helpers.
91
+ *
92
+ * Use these when you need pure tree hashing, descriptor construction, or proof
93
+ * verification. In the normal make-side flow, `Tree.create` wraps descriptor
94
+ * construction; proof helpers accept the built `Tree` so cached leaves/root are
95
+ * reused.
96
+ *
97
+ * @example
98
+ * ```ts
99
+ * import { TreeUtils } from "@morpho-org/midnight-sdk";
100
+ *
101
+ * console.log(typeof TreeUtils.buildRoot);
102
+ * ```
103
+ */
104
+ export var TreeUtils;
105
+ (function (TreeUtils) {
106
+ /**
107
+ * Validates a tree against Midnight mempool API policy.
108
+ *
109
+ * This is an API-backed convenience: it encodes each tree leaf with empty
110
+ * `ratifierData`, then sends the temporary payload to the Midnight API
111
+ * `POST /mempool/validate` endpoint. API policy only inspects offer contents,
112
+ * so use this after `Tree.create` and before wallet signature or Setter root
113
+ * approval.
114
+ *
115
+ * @param params.chainId - Chain id whose API policy should validate the tree.
116
+ * @param params.tree - Offer tree to validate before ratifier data or payload publication exists.
117
+ * @param params.apiUrl - Optional Midnight API URL override used for the validation HTTP request.
118
+ * @param params.timestamp - Optional ISO-8601 timestamp or `Date` selecting the API policy snapshot.
119
+ * @param params.fetch - Optional fetch implementation override used for the API call.
120
+ * @param params.request - Optional fetch options forwarded to the API request.
121
+ * @returns API issues and `valid` summary.
122
+ * @throws {InvalidTreeError} when the tree is empty, all padding, or duplicated.
123
+ * @throws {InvalidTreeHeightError} when the resulting height is unsupported.
124
+ * @throws {Payload.DecodeError} when validation payload encoding fails.
125
+ * @throws {MidnightApiError} when the API returns a non-2xx response.
126
+ * @throws {InvalidMidnightApiResponseError} when the API returns malformed success JSON.
127
+ * @example
128
+ * ```ts
129
+ * import { Offer, TreeUtils } from "@morpho-org/midnight-sdk";
130
+ * import { zeroAddress } from "viem";
131
+ *
132
+ * const offer = Offer.create({
133
+ * market: {
134
+ * loanToken: "0x0000000000000000000000000000000000006000",
135
+ * collateralParams: [
136
+ * {
137
+ * token: "0x0000000000000000000000000000000000007000",
138
+ * lltv: 770000000000000000n,
139
+ * maxLif: 1061007957559681697n,
140
+ * oracle: "0x0000000000000000000000000000000000008000",
141
+ * },
142
+ * ],
143
+ * maturity: 54_000n,
144
+ * rcfThreshold: 0n,
145
+ * enterGate: zeroAddress,
146
+ * liquidatorGate: zeroAddress,
147
+ * },
148
+ * buy: true,
149
+ * maker: "0x0000000000000000000000000000000000009000",
150
+ * tick: 5_000n,
151
+ * expiry: 3_600n,
152
+ * ratifier: "0x0000000000000000000000000000000000004000",
153
+ * maxUnits: 100n,
154
+ * });
155
+ * const validation = await TreeUtils.mempoolValidate({
156
+ * chainId: 8453,
157
+ * tree: [offer],
158
+ * });
159
+ * console.log(validation.valid);
160
+ * ```
161
+ */
162
+ async function mempoolValidate(params) {
163
+ const offers = "offers" in params.tree
164
+ ? params.tree.offers
165
+ : params.tree.flatMap((entry) => "offers" in entry ? Group.from(entry).offers : [Offer.from(entry)]);
166
+ buildDescriptor(offers);
167
+ const payload = await encodePayload(offers.map((offer) => ({ offer, ratifierData: "0x" })));
168
+ return MidnightApi.validateMempoolPayload({
169
+ baseUrl: params.apiUrl,
170
+ fetch: params.fetch,
171
+ request: params.request,
172
+ chainId: params.chainId,
173
+ timestamp: params.timestamp,
174
+ payload,
175
+ });
176
+ }
177
+ TreeUtils.mempoolValidate = mempoolValidate;
178
+ /**
179
+ * Computes HashLib node hash from left and right child hashes.
180
+ *
181
+ * @param left - Left child hash.
182
+ * @param right - Right child hash.
183
+ * @returns Node hash.
184
+ * @example
185
+ * ```ts
186
+ * import { TreeUtils } from "@morpho-org/midnight-sdk";
187
+ *
188
+ * const root = TreeUtils.hashNode(
189
+ * "0x0000000000000000000000000000000000000000000000000000000000000000",
190
+ * "0x0000000000000000000000000000000000000000000000000000000000000000",
191
+ * );
192
+ * console.log(root);
193
+ * ```
194
+ */
195
+ function hashNode(left, right) {
196
+ return keccak256(concat([left, right]));
197
+ }
198
+ TreeUtils.hashNode = hashNode;
199
+ /**
200
+ * Builds a tree descriptor and Merkle root. Non-power-of-two batches are
201
+ * padded with protocol-zero offers at the highest leaf indices.
202
+ *
203
+ * Use after `Group.create` or standalone `Offer.create` when you need the
204
+ * padded leaves for custom signing, root approval, or proof construction.
205
+ * Groups are encoded with their derived shared group id, and standalone
206
+ * offers are encoded with their own group id.
207
+ * `Tree.create` calls this internally and is the simpler API for most
208
+ * make-side code.
209
+ *
210
+ * @param entries - Groups or standalone offers in leaf order.
211
+ * @returns Tree descriptor.
212
+ * @throws {InvalidTreeError} when the offer count is empty, all padding, or duplicated.
213
+ * @throws {InvalidTreeHeightError} when the padded tree exceeds supported ratifier typehashes.
214
+ * @example
215
+ * ```ts
216
+ * import { Offer, TreeUtils } from "@morpho-org/midnight-sdk";
217
+ * import { zeroAddress } from "viem";
218
+ *
219
+ * const offer = Offer.create({
220
+ * market: {
221
+ * loanToken: "0x0000000000000000000000000000000000006000",
222
+ * collateralParams: [
223
+ * {
224
+ * token: "0x0000000000000000000000000000000000007000",
225
+ * lltv: 770000000000000000n,
226
+ * maxLif: 1061007957559681697n,
227
+ * oracle: "0x0000000000000000000000000000000000008000",
228
+ * },
229
+ * ],
230
+ * maturity: 54_000n,
231
+ * rcfThreshold: 0n,
232
+ * enterGate: zeroAddress,
233
+ * liquidatorGate: zeroAddress,
234
+ * },
235
+ * buy: true,
236
+ * maker: "0x0000000000000000000000000000000000009000",
237
+ * tick: 5_000n,
238
+ * expiry: 3_600n,
239
+ * ratifier: "0x0000000000000000000000000000000000004000",
240
+ * maxUnits: 100n,
241
+ * });
242
+ * const tree = TreeUtils.buildDescriptor([offer]);
243
+ * console.log(tree.root);
244
+ * ```
245
+ */
246
+ function buildDescriptor(entries) {
247
+ const structs = entries.flatMap((entry) => "offers" in entry
248
+ ? GroupUtils.toStructs(entry)
249
+ : [OfferUtils.toStruct({ offer: entry })]);
250
+ if (structs.length === 0) {
251
+ throw new InvalidTreeError("Tree must not be empty.");
252
+ }
253
+ const offerStructs = padOfferStructs(structs);
254
+ const leaves = offerStructs.map(OfferUtils.hashStruct);
255
+ assertLeafOffers(offerStructs, leaves);
256
+ const height = Math.log2(offerStructs.length);
257
+ if (height > 20)
258
+ throw new InvalidTreeHeightError(height);
259
+ let level = [...leaves];
260
+ while (level.length > 1) {
261
+ const next = [];
262
+ for (let i = 0; i < level.length; i += 2) {
263
+ next.push(hashNode(level[i], level[i + 1]));
264
+ }
265
+ level = next;
266
+ }
267
+ return deepFreeze({
268
+ offers: offerStructs,
269
+ leaves,
270
+ root: level[0],
271
+ height,
272
+ });
273
+ }
274
+ TreeUtils.buildDescriptor = buildDescriptor;
275
+ /**
276
+ * Builds only the tree root.
277
+ *
278
+ * Use when only the root is needed, for example to compare a locally built
279
+ * tree with an approved root. Use `Tree.create` or `buildDescriptor` if later
280
+ * proof generation is required.
281
+ *
282
+ * @param entries - Groups or standalone offers in leaf order.
283
+ * @returns Merkle root.
284
+ * @throws {InvalidTreeError} when the offer count is empty, all padding, or duplicated.
285
+ * @throws {InvalidTreeHeightError} when the padded tree exceeds supported ratifier typehashes.
286
+ * @example
287
+ * ```ts
288
+ * import { Offer, TreeUtils } from "@morpho-org/midnight-sdk";
289
+ * import { zeroAddress } from "viem";
290
+ *
291
+ * const offer = Offer.create({
292
+ * market: {
293
+ * loanToken: "0x0000000000000000000000000000000000006000",
294
+ * collateralParams: [
295
+ * {
296
+ * token: "0x0000000000000000000000000000000000007000",
297
+ * lltv: 770000000000000000n,
298
+ * maxLif: 1061007957559681697n,
299
+ * oracle: "0x0000000000000000000000000000000000008000",
300
+ * },
301
+ * ],
302
+ * maturity: 54_000n,
303
+ * rcfThreshold: 0n,
304
+ * enterGate: zeroAddress,
305
+ * liquidatorGate: zeroAddress,
306
+ * },
307
+ * buy: true,
308
+ * maker: "0x0000000000000000000000000000000000009000",
309
+ * tick: 5_000n,
310
+ * expiry: 3_600n,
311
+ * ratifier: "0x0000000000000000000000000000000000004000",
312
+ * maxUnits: 100n,
313
+ * });
314
+ * const root = TreeUtils.buildRoot([offer]);
315
+ * console.log(root);
316
+ * ```
317
+ */
318
+ function buildRoot(entries) {
319
+ return buildDescriptor(entries).root;
320
+ }
321
+ TreeUtils.buildRoot = buildRoot;
322
+ /**
323
+ * Builds a Merkle proof for one offer.
324
+ *
325
+ * Use after tree construction when a custom ratifier needs one proof. The
326
+ * built-in Ecrecover and Setter helpers call this while generating
327
+ * `ratifierData`.
328
+ *
329
+ * @param params.tree - Tree that contains the leaf.
330
+ * @param params.leafIndex - Leaf index to prove.
331
+ * @returns Proof descriptor.
332
+ * @throws {InvalidTreeError} when leaf index is out of range.
333
+ * @example
334
+ * ```ts
335
+ * import { Offer, Tree, TreeUtils } from "@morpho-org/midnight-sdk";
336
+ * import { zeroAddress } from "viem";
337
+ *
338
+ * const offer = Offer.create({
339
+ * market: {
340
+ * loanToken: "0x0000000000000000000000000000000000006000",
341
+ * collateralParams: [
342
+ * {
343
+ * token: "0x0000000000000000000000000000000000007000",
344
+ * lltv: 770000000000000000n,
345
+ * maxLif: 1061007957559681697n,
346
+ * oracle: "0x0000000000000000000000000000000000008000",
347
+ * },
348
+ * ],
349
+ * maturity: 54_000n,
350
+ * rcfThreshold: 0n,
351
+ * enterGate: zeroAddress,
352
+ * liquidatorGate: zeroAddress,
353
+ * },
354
+ * buy: true,
355
+ * maker: "0x0000000000000000000000000000000000009000",
356
+ * tick: 5_000n,
357
+ * expiry: 3_600n,
358
+ * ratifier: "0x0000000000000000000000000000000000004000",
359
+ * maxUnits: 100n,
360
+ * });
361
+ * const proof = TreeUtils.buildProof({
362
+ * tree: Tree.create([offer]),
363
+ * leafIndex: 0n,
364
+ * });
365
+ * console.log(proof.proof.length);
366
+ * ```
367
+ */
368
+ function buildProof(params) {
369
+ const leafIndex = BigInt(params.leafIndex);
370
+ if (leafIndex < 0n ||
371
+ leafIndex >= BigInt(params.tree.paddedOffers.length)) {
372
+ throw new InvalidTreeError(`Leaf index "${leafIndex}" is outside the tree.`);
373
+ }
374
+ let index = Number(leafIndex);
375
+ let level = [...params.tree.leaves];
376
+ const proof = [];
377
+ while (level.length > 1) {
378
+ proof.push(level[index ^ 1]);
379
+ const next = [];
380
+ for (let i = 0; i < level.length; i += 2) {
381
+ next.push(hashNode(level[i], level[i + 1]));
382
+ }
383
+ index = Math.floor(index / 2);
384
+ level = next;
385
+ }
386
+ return deepFreeze({ root: params.tree.root, leafIndex, proof });
387
+ }
388
+ TreeUtils.buildProof = buildProof;
389
+ /**
390
+ * Verifies a local Merkle proof against a root.
391
+ *
392
+ * Use on the take-side or in tests to inspect decoded payload or ratifier
393
+ * data before forwarding it to a transaction builder. Onchain ratifiers still
394
+ * perform the authoritative verification.
395
+ *
396
+ * @param params.offer - Offer whose hash starts proof reconstruction.
397
+ * @param params.root - Expected Merkle root.
398
+ * @param params.leafIndex - Leaf index proven by `params.proof`.
399
+ * @param params.proof - Merkle proof siblings for the leaf.
400
+ * @returns Whether the proof reconstructs the supplied root.
401
+ * @example
402
+ * ```ts
403
+ * import { Offer, Tree, TreeUtils } from "@morpho-org/midnight-sdk";
404
+ * import { zeroAddress } from "viem";
405
+ *
406
+ * const offer = Offer.create({
407
+ * market: {
408
+ * loanToken: "0x0000000000000000000000000000000000006000",
409
+ * collateralParams: [
410
+ * {
411
+ * token: "0x0000000000000000000000000000000000007000",
412
+ * lltv: 770000000000000000n,
413
+ * maxLif: 1061007957559681697n,
414
+ * oracle: "0x0000000000000000000000000000000000008000",
415
+ * },
416
+ * ],
417
+ * maturity: 54_000n,
418
+ * rcfThreshold: 0n,
419
+ * enterGate: zeroAddress,
420
+ * liquidatorGate: zeroAddress,
421
+ * },
422
+ * buy: true,
423
+ * maker: "0x0000000000000000000000000000000000009000",
424
+ * tick: 5_000n,
425
+ * expiry: 3_600n,
426
+ * ratifier: "0x0000000000000000000000000000000000004000",
427
+ * maxUnits: 100n,
428
+ * });
429
+ * const tree = Tree.create([offer]);
430
+ * const proof = tree.proof(0n);
431
+ * const valid = TreeUtils.verifyProof({
432
+ * offer: tree.offers[0]!,
433
+ * root: proof.root,
434
+ * leafIndex: proof.leafIndex,
435
+ * proof: proof.proof,
436
+ * });
437
+ * console.log(valid);
438
+ * ```
439
+ */
440
+ function verifyProof(params) {
441
+ const offer = Offer.from(params.offer);
442
+ let node = OfferUtils.hash(offer);
443
+ const leafIndex = BigInt(params.leafIndex);
444
+ if (leafIndex < 0n || leafIndex >> BigInt(params.proof.length) !== 0n) {
445
+ return false;
446
+ }
447
+ let remainingLeafIndex = leafIndex;
448
+ for (const sibling of params.proof) {
449
+ node =
450
+ (remainingLeafIndex & 1n) === 0n
451
+ ? hashNode(node, sibling)
452
+ : hashNode(sibling, node);
453
+ remainingLeafIndex >>= 1n;
454
+ }
455
+ return node === params.root;
456
+ }
457
+ TreeUtils.verifyProof = verifyProof;
458
+ })(TreeUtils || (TreeUtils = {}));
@@ -0,0 +1,7 @@
1
+ export * from "./EcrecoverRatifierUtils.js";
2
+ export * from "./Group.js";
3
+ export * from "./GroupUtils.js";
4
+ export * from "./RatifierUtils.js";
5
+ export * from "./SetterRatifierUtils.js";
6
+ export * from "./Tree.js";
7
+ export * from "./TreeUtils.js";
@@ -0,0 +1,7 @@
1
+ export * from "./EcrecoverRatifierUtils.js";
2
+ export * from "./Group.js";
3
+ export * from "./GroupUtils.js";
4
+ export * from "./RatifierUtils.js";
5
+ export * from "./SetterRatifierUtils.js";
6
+ export * from "./Tree.js";
7
+ export * from "./TreeUtils.js";
package/package.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "@morpho-org/midnight-sdk",
3
+ "description": "Viem-based package for Morpho Midnight that exports protocol utilities, fetch helpers, and Midnight API utilities under a dedicated API subpath.",
4
+ "version": "0.1.0",
5
+ "author": "Morpho Association <contact@morpho.org>",
6
+ "contributors": [
7
+ "Rubilmax <rmilon@gmail.com>"
8
+ ],
9
+ "repository": "github:morpho-org/sdks",
10
+ "homepage": "https://github.com/morpho-org/sdks",
11
+ "bugs": {
12
+ "url": "https://github.com/morpho-org/sdks/issues",
13
+ "email": "contact@morpho.org"
14
+ },
15
+ "license": "MIT",
16
+ "type": "module",
17
+ "main": "src/index.ts",
18
+ "exports": {
19
+ ".": "./src/index.ts",
20
+ "./api": "./src/api/index.ts",
21
+ "./package.json": "./package.json"
22
+ },
23
+ "typesVersions": {
24
+ "*": {
25
+ "api": [
26
+ "src/api/index.ts"
27
+ ]
28
+ }
29
+ },
30
+ "sideEffects": false,
31
+ "files": [
32
+ "lib"
33
+ ],
34
+ "scripts": {
35
+ "prepublish": "$npm_execpath build",
36
+ "compile": "node ../../scripts/compile-solidity.js midnight-sdk",
37
+ "build": "tsc --noEmit && $npm_execpath build:cjs && $npm_execpath build:esm",
38
+ "build:cjs": "tsc --build tsconfig.build.cjs.json && echo '{\"type\":\"commonjs\"}' > lib/cjs/package.json",
39
+ "build:esm": "tsc --build tsconfig.build.esm.json && echo '{\"type\":\"module\"}' > lib/esm/package.json",
40
+ "test": "vitest --root ../.. --project midnight-sdk"
41
+ },
42
+ "peerDependencies": {
43
+ "@morpho-org/morpho-ts": "^2.7.0",
44
+ "viem": "^2.0.0"
45
+ },
46
+ "devDependencies": {
47
+ "@morpho-org/morpho-ts": "workspace:^",
48
+ "@morpho-org/test": "workspace:^",
49
+ "fast-check": "^4.4.0",
50
+ "typescript": "^6.0.3",
51
+ "viem": "2.52.2",
52
+ "vitest": "^4.1.6"
53
+ },
54
+ "publishConfig": {
55
+ "exports": {
56
+ ".": {
57
+ "types": "./lib/esm/index.d.ts",
58
+ "import": "./lib/esm/index.js",
59
+ "require": "./lib/cjs/index.js"
60
+ },
61
+ "./api": {
62
+ "types": "./lib/esm/api/index.d.ts",
63
+ "import": "./lib/esm/api/index.js",
64
+ "require": "./lib/cjs/api/index.js"
65
+ },
66
+ "./package.json": "./package.json"
67
+ }
68
+ }
69
+ }
package/src/index.ts ADDED
@@ -0,0 +1,19 @@
1
+ export * from "./abis.js";
2
+ export * from "./constants.js";
3
+ export * from "./errors.js";
4
+ export * from "./fetch/index.js";
5
+ export * from "./market/index.js";
6
+ export * from "./math/index.js";
7
+ export * from "./offers/index.js";
8
+ export * from "./signatures/index.js";
9
+
10
+ /**
11
+ * Namespace for Midnight mempool payload utilities.
12
+ *
13
+ * Use `Payload.encode` to turn ratified offer items into wire bytes for mempool
14
+ * publication or raw payload API validation, and `Payload.decode` to inspect
15
+ * published maker offers, ratifier data, or attribution-tagged payloads.
16
+ * Encoded payloads are always `Hex` strings ready to be included in onchain
17
+ * mempool submission calldata.
18
+ */
19
+ export * as Payload from "./signatures/Payload.js";