@morpho-org/midnight-sdk 2.1.0-next.0 → 2.2.0-next.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.
@@ -1,2 +1,2 @@
1
1
  /** @internal Installed Midnight SDK package version. */
2
- export declare const MIDNIGHT_SDK_VERSION = "2.1.0-next.0";
2
+ export declare const MIDNIGHT_SDK_VERSION = "2.2.0-next.0";
@@ -3,4 +3,4 @@
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.MIDNIGHT_SDK_VERSION = void 0;
5
5
  /** @internal Installed Midnight SDK package version. */
6
- exports.MIDNIGHT_SDK_VERSION = "2.1.0-next.0";
6
+ exports.MIDNIGHT_SDK_VERSION = "2.2.0-next.0";
@@ -150,6 +150,7 @@ export declare class Offer {
150
150
  readonly tick: bigint;
151
151
  private cachedGroup;
152
152
  private cachedHash;
153
+ private cachedOnchainHash;
153
154
  /**
154
155
  * Whether the group id was supplied at construction rather than derived.
155
156
  *
@@ -329,6 +330,55 @@ export declare class Offer {
329
330
  * ```
330
331
  */
331
332
  get hash(): Hash;
333
+ /**
334
+ * Returns the on-chain offer identifier emitted by Midnight's `Take` event.
335
+ *
336
+ * This `keccak256(abi.encode(offer))` hash identifies offers on-chain and is
337
+ * distinct from `hash`, the typehash-prefixed ratifier hash.
338
+ * It matches a `Take` event only for the offer exactly as published. For
339
+ * RateRatifierV1 and PriceRatifierV1, hash the offers in the descriptor's
340
+ * `offers`: `buildDescriptor` replaces both the default group and a
341
+ * `Group.create` group.
342
+ *
343
+ * @returns The cached on-chain offer hash.
344
+ * @throws {viem.InvalidAddressError} when an address has an invalid mixed-case checksum.
345
+ * @throws {viem.IntegerOutOfRangeError} when a uint field overflows its ABI size.
346
+ * @example
347
+ * ```ts
348
+ * import { Offer } from "@morpho-org/midnight-sdk";
349
+ * import { zeroAddress } from "viem";
350
+ *
351
+ * const offer = Offer.create({
352
+ * market: {
353
+ * chainId: 8453,
354
+ * midnight: "0x0000000000000000000000000000000000001000",
355
+ * loanToken: "0x0000000000000000000000000000000000006000",
356
+ * collateralParams: [
357
+ * {
358
+ * token: "0x0000000000000000000000000000000000007000",
359
+ * lltv: 770000000000000000n,
360
+ * liquidationCursor: 250000000000000000n,
361
+ * oracle: "0x0000000000000000000000000000000000008000",
362
+ * },
363
+ * ],
364
+ * maturity: 54_000n,
365
+ * rcfThreshold: 0n,
366
+ * enterGate: zeroAddress,
367
+ * liquidatorGate: zeroAddress,
368
+ * },
369
+ * buy: true,
370
+ * maker: "0x0000000000000000000000000000000000009000",
371
+ * tick: 5_000n,
372
+ * group: "0x1111111111111111111111111111111111111111111111111111111111111111",
373
+ * expiry: 3_600n,
374
+ * ratifier: "0x0000000000000000000000000000000000004000",
375
+ * maxUnits: 100n,
376
+ * });
377
+ * const offerHash = offer.onchainHash;
378
+ * console.log(offerHash);
379
+ * ```
380
+ */
381
+ get onchainHash(): Hash;
332
382
  /**
333
383
  * WAD zero-coupon price at this offer's tick.
334
384
  *
@@ -71,6 +71,7 @@ class Offer {
71
71
  tick;
72
72
  cachedGroup;
73
73
  cachedHash;
74
+ cachedOnchainHash;
74
75
  /**
75
76
  * Whether the group id was supplied at construction rather than derived.
76
77
  *
@@ -281,6 +282,58 @@ class Offer {
281
282
  this.cachedHash ??= OfferUtils_js_1.OfferUtils.hash(this);
282
283
  return this.cachedHash;
283
284
  }
285
+ /**
286
+ * Returns the on-chain offer identifier emitted by Midnight's `Take` event.
287
+ *
288
+ * This `keccak256(abi.encode(offer))` hash identifies offers on-chain and is
289
+ * distinct from `hash`, the typehash-prefixed ratifier hash.
290
+ * It matches a `Take` event only for the offer exactly as published. For
291
+ * RateRatifierV1 and PriceRatifierV1, hash the offers in the descriptor's
292
+ * `offers`: `buildDescriptor` replaces both the default group and a
293
+ * `Group.create` group.
294
+ *
295
+ * @returns The cached on-chain offer hash.
296
+ * @throws {viem.InvalidAddressError} when an address has an invalid mixed-case checksum.
297
+ * @throws {viem.IntegerOutOfRangeError} when a uint field overflows its ABI size.
298
+ * @example
299
+ * ```ts
300
+ * import { Offer } from "@morpho-org/midnight-sdk";
301
+ * import { zeroAddress } from "viem";
302
+ *
303
+ * const offer = Offer.create({
304
+ * market: {
305
+ * chainId: 8453,
306
+ * midnight: "0x0000000000000000000000000000000000001000",
307
+ * loanToken: "0x0000000000000000000000000000000000006000",
308
+ * collateralParams: [
309
+ * {
310
+ * token: "0x0000000000000000000000000000000000007000",
311
+ * lltv: 770000000000000000n,
312
+ * liquidationCursor: 250000000000000000n,
313
+ * oracle: "0x0000000000000000000000000000000000008000",
314
+ * },
315
+ * ],
316
+ * maturity: 54_000n,
317
+ * rcfThreshold: 0n,
318
+ * enterGate: zeroAddress,
319
+ * liquidatorGate: zeroAddress,
320
+ * },
321
+ * buy: true,
322
+ * maker: "0x0000000000000000000000000000000000009000",
323
+ * tick: 5_000n,
324
+ * group: "0x1111111111111111111111111111111111111111111111111111111111111111",
325
+ * expiry: 3_600n,
326
+ * ratifier: "0x0000000000000000000000000000000000004000",
327
+ * maxUnits: 100n,
328
+ * });
329
+ * const offerHash = offer.onchainHash;
330
+ * console.log(offerHash);
331
+ * ```
332
+ */
333
+ get onchainHash() {
334
+ this.cachedOnchainHash ??= OfferUtils_js_1.OfferUtils.onchainHash(this);
335
+ return this.cachedOnchainHash;
336
+ }
284
337
  /**
285
338
  * WAD zero-coupon price at this offer's tick.
286
339
  *
@@ -160,6 +160,114 @@ export declare namespace OfferUtils {
160
160
  * ```
161
161
  */
162
162
  function hash(offer: IOffer & Required<Pick<IOffer, "group">>): Hash;
163
+ /**
164
+ * Computes the on-chain offer identifier from the supplied offer struct.
165
+ *
166
+ * This is `keccak256(abi.encode(offer))`, the hash emitted by Midnight's
167
+ * `Take` event and used to identify offers on-chain. It is distinct from
168
+ * `hashStruct` and `hash`, which produce the typehash-prefixed ratifier hash.
169
+ * Collaterals are hashed in the supplied order; Midnight rejects unsorted
170
+ * collateral params with `CollateralParamsNotSorted`, so pass a sorted struct,
171
+ * for example one returned by `toStruct`.
172
+ * It matches a `Take` event only for the offer exactly as published. For
173
+ * RateRatifierV1 and PriceRatifierV1, hash the offers in the descriptor's
174
+ * `offers`: `buildDescriptor` replaces both the default group and a
175
+ * `Group.create` group.
176
+ *
177
+ * @param offerStruct - ABI-compatible offer to hash without normalization.
178
+ * @returns The offer hash emitted by Midnight's `Take` event.
179
+ * @throws {viem.InvalidAddressError} when an address has an invalid mixed-case checksum.
180
+ * @throws {viem.IntegerOutOfRangeError} when a uint field overflows its ABI size.
181
+ * @example
182
+ * ```ts
183
+ * import { Offer, OfferUtils } from "@morpho-org/midnight-sdk";
184
+ * import { zeroAddress } from "viem";
185
+ *
186
+ * const offer = Offer.create({
187
+ * market: {
188
+ * chainId: 8453,
189
+ * midnight: "0x0000000000000000000000000000000000001000",
190
+ * loanToken: "0x0000000000000000000000000000000000006000",
191
+ * collateralParams: [
192
+ * {
193
+ * token: "0x0000000000000000000000000000000000007000",
194
+ * lltv: 770000000000000000n,
195
+ * liquidationCursor: 250000000000000000n,
196
+ * oracle: "0x0000000000000000000000000000000000008000",
197
+ * },
198
+ * ],
199
+ * maturity: 54_000n,
200
+ * rcfThreshold: 0n,
201
+ * enterGate: zeroAddress,
202
+ * liquidatorGate: zeroAddress,
203
+ * },
204
+ * buy: true,
205
+ * maker: "0x0000000000000000000000000000000000009000",
206
+ * tick: 5_000n,
207
+ * group: "0x1111111111111111111111111111111111111111111111111111111111111111",
208
+ * expiry: 3_600n,
209
+ * ratifier: "0x0000000000000000000000000000000000004000",
210
+ * maxUnits: 100n,
211
+ * });
212
+ * const offerHash = OfferUtils.onchainHashStruct(
213
+ * OfferUtils.toStruct({ offer }),
214
+ * );
215
+ * console.log(offerHash);
216
+ * ```
217
+ */
218
+ function onchainHashStruct(offerStruct: OfferStruct): Hash;
219
+ /**
220
+ * Computes the on-chain offer identifier from an offer with a group id.
221
+ *
222
+ * This is `keccak256(abi.encode(offer))`, the hash emitted by Midnight's
223
+ * `Take` event and used to identify offers on-chain. It is distinct from
224
+ * `hash`, which returns the typehash-prefixed ratifier hash. `toStruct`
225
+ * normalizes the offer and sorts collateral params as required by Midnight.
226
+ * It matches a `Take` event only for the offer exactly as published. For
227
+ * RateRatifierV1 and PriceRatifierV1, hash the offers in the descriptor's
228
+ * `offers`: `buildDescriptor` replaces both the default group and a
229
+ * `Group.create` group.
230
+ *
231
+ * @param offer - Offer with the protocol group id encoded in its struct.
232
+ * @returns The offer hash emitted by Midnight's `Take` event.
233
+ * @throws {viem.InvalidAddressError} when an address has an invalid mixed-case checksum.
234
+ * @throws {viem.IntegerOutOfRangeError} when a uint field overflows its ABI size.
235
+ * @example
236
+ * ```ts
237
+ * import { Offer, OfferUtils } from "@morpho-org/midnight-sdk";
238
+ * import { zeroAddress } from "viem";
239
+ *
240
+ * const offer = Offer.create({
241
+ * market: {
242
+ * chainId: 8453,
243
+ * midnight: "0x0000000000000000000000000000000000001000",
244
+ * loanToken: "0x0000000000000000000000000000000000006000",
245
+ * collateralParams: [
246
+ * {
247
+ * token: "0x0000000000000000000000000000000000007000",
248
+ * lltv: 770000000000000000n,
249
+ * liquidationCursor: 250000000000000000n,
250
+ * oracle: "0x0000000000000000000000000000000000008000",
251
+ * },
252
+ * ],
253
+ * maturity: 54_000n,
254
+ * rcfThreshold: 0n,
255
+ * enterGate: zeroAddress,
256
+ * liquidatorGate: zeroAddress,
257
+ * },
258
+ * buy: true,
259
+ * maker: "0x0000000000000000000000000000000000009000",
260
+ * tick: 5_000n,
261
+ * group: "0x1111111111111111111111111111111111111111111111111111111111111111",
262
+ * expiry: 3_600n,
263
+ * ratifier: "0x0000000000000000000000000000000000004000",
264
+ * maxUnits: 100n,
265
+ * });
266
+ * const offerHash = OfferUtils.onchainHash(offer);
267
+ * console.log(offerHash);
268
+ * ```
269
+ */
270
+ function onchainHash(offer: IOffer & Required<Pick<IOffer, "group">>): Hash;
163
271
  /**
164
272
  * Computes the offer hash used to derive a content-addressed group id.
165
273
  *
@@ -3,11 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.OfferUtils = void 0;
4
4
  const morpho_ts_1 = require("@morpho-org/morpho-ts");
5
5
  const viem_1 = require("viem");
6
+ const abis_js_1 = require("../abis.js");
6
7
  const constants_js_1 = require("../constants.js");
7
8
  const errors_js_1 = require("../errors.js");
8
9
  const index_js_1 = require("../market/index.js");
9
10
  const index_js_2 = require("../math/index.js");
10
11
  const Offer_js_1 = require("./Offer.js");
12
+ const takeOfferParam = (0, viem_1.getAbiItem)({ abi: abis_js_1.midnightAbi, name: "take" }).inputs[0];
11
13
  const offerHashParams = [
12
14
  { name: "typehash", type: "bytes32" },
13
15
  { name: "marketHash", type: "bytes32" },
@@ -226,6 +228,120 @@ var OfferUtils;
226
228
  return hashStruct(toStruct({ offer }));
227
229
  }
228
230
  OfferUtils.hash = hash;
231
+ /**
232
+ * Computes the on-chain offer identifier from the supplied offer struct.
233
+ *
234
+ * This is `keccak256(abi.encode(offer))`, the hash emitted by Midnight's
235
+ * `Take` event and used to identify offers on-chain. It is distinct from
236
+ * `hashStruct` and `hash`, which produce the typehash-prefixed ratifier hash.
237
+ * Collaterals are hashed in the supplied order; Midnight rejects unsorted
238
+ * collateral params with `CollateralParamsNotSorted`, so pass a sorted struct,
239
+ * for example one returned by `toStruct`.
240
+ * It matches a `Take` event only for the offer exactly as published. For
241
+ * RateRatifierV1 and PriceRatifierV1, hash the offers in the descriptor's
242
+ * `offers`: `buildDescriptor` replaces both the default group and a
243
+ * `Group.create` group.
244
+ *
245
+ * @param offerStruct - ABI-compatible offer to hash without normalization.
246
+ * @returns The offer hash emitted by Midnight's `Take` event.
247
+ * @throws {viem.InvalidAddressError} when an address has an invalid mixed-case checksum.
248
+ * @throws {viem.IntegerOutOfRangeError} when a uint field overflows its ABI size.
249
+ * @example
250
+ * ```ts
251
+ * import { Offer, OfferUtils } from "@morpho-org/midnight-sdk";
252
+ * import { zeroAddress } from "viem";
253
+ *
254
+ * const offer = Offer.create({
255
+ * market: {
256
+ * chainId: 8453,
257
+ * midnight: "0x0000000000000000000000000000000000001000",
258
+ * loanToken: "0x0000000000000000000000000000000000006000",
259
+ * collateralParams: [
260
+ * {
261
+ * token: "0x0000000000000000000000000000000000007000",
262
+ * lltv: 770000000000000000n,
263
+ * liquidationCursor: 250000000000000000n,
264
+ * oracle: "0x0000000000000000000000000000000000008000",
265
+ * },
266
+ * ],
267
+ * maturity: 54_000n,
268
+ * rcfThreshold: 0n,
269
+ * enterGate: zeroAddress,
270
+ * liquidatorGate: zeroAddress,
271
+ * },
272
+ * buy: true,
273
+ * maker: "0x0000000000000000000000000000000000009000",
274
+ * tick: 5_000n,
275
+ * group: "0x1111111111111111111111111111111111111111111111111111111111111111",
276
+ * expiry: 3_600n,
277
+ * ratifier: "0x0000000000000000000000000000000000004000",
278
+ * maxUnits: 100n,
279
+ * });
280
+ * const offerHash = OfferUtils.onchainHashStruct(
281
+ * OfferUtils.toStruct({ offer }),
282
+ * );
283
+ * console.log(offerHash);
284
+ * ```
285
+ */
286
+ function onchainHashStruct(offerStruct) {
287
+ return (0, viem_1.keccak256)((0, viem_1.encodeAbiParameters)([takeOfferParam], [offerStruct]));
288
+ }
289
+ OfferUtils.onchainHashStruct = onchainHashStruct;
290
+ /**
291
+ * Computes the on-chain offer identifier from an offer with a group id.
292
+ *
293
+ * This is `keccak256(abi.encode(offer))`, the hash emitted by Midnight's
294
+ * `Take` event and used to identify offers on-chain. It is distinct from
295
+ * `hash`, which returns the typehash-prefixed ratifier hash. `toStruct`
296
+ * normalizes the offer and sorts collateral params as required by Midnight.
297
+ * It matches a `Take` event only for the offer exactly as published. For
298
+ * RateRatifierV1 and PriceRatifierV1, hash the offers in the descriptor's
299
+ * `offers`: `buildDescriptor` replaces both the default group and a
300
+ * `Group.create` group.
301
+ *
302
+ * @param offer - Offer with the protocol group id encoded in its struct.
303
+ * @returns The offer hash emitted by Midnight's `Take` event.
304
+ * @throws {viem.InvalidAddressError} when an address has an invalid mixed-case checksum.
305
+ * @throws {viem.IntegerOutOfRangeError} when a uint field overflows its ABI size.
306
+ * @example
307
+ * ```ts
308
+ * import { Offer, OfferUtils } from "@morpho-org/midnight-sdk";
309
+ * import { zeroAddress } from "viem";
310
+ *
311
+ * const offer = Offer.create({
312
+ * market: {
313
+ * chainId: 8453,
314
+ * midnight: "0x0000000000000000000000000000000000001000",
315
+ * loanToken: "0x0000000000000000000000000000000000006000",
316
+ * collateralParams: [
317
+ * {
318
+ * token: "0x0000000000000000000000000000000000007000",
319
+ * lltv: 770000000000000000n,
320
+ * liquidationCursor: 250000000000000000n,
321
+ * oracle: "0x0000000000000000000000000000000000008000",
322
+ * },
323
+ * ],
324
+ * maturity: 54_000n,
325
+ * rcfThreshold: 0n,
326
+ * enterGate: zeroAddress,
327
+ * liquidatorGate: zeroAddress,
328
+ * },
329
+ * buy: true,
330
+ * maker: "0x0000000000000000000000000000000000009000",
331
+ * tick: 5_000n,
332
+ * group: "0x1111111111111111111111111111111111111111111111111111111111111111",
333
+ * expiry: 3_600n,
334
+ * ratifier: "0x0000000000000000000000000000000000004000",
335
+ * maxUnits: 100n,
336
+ * });
337
+ * const offerHash = OfferUtils.onchainHash(offer);
338
+ * console.log(offerHash);
339
+ * ```
340
+ */
341
+ function onchainHash(offer) {
342
+ return onchainHashStruct(toStruct({ offer }));
343
+ }
344
+ OfferUtils.onchainHash = onchainHash;
229
345
  /**
230
346
  * Computes the offer hash used to derive a content-addressed group id.
231
347
  *
@@ -1,2 +1,2 @@
1
1
  /** @internal Installed Midnight SDK package version. */
2
- export declare const MIDNIGHT_SDK_VERSION = "2.1.0-next.0";
2
+ export declare const MIDNIGHT_SDK_VERSION = "2.2.0-next.0";
@@ -1,3 +1,3 @@
1
1
  // Generated by scripts/generate-midnight-package-version.ts. Do not edit.
2
2
  /** @internal Installed Midnight SDK package version. */
3
- export const MIDNIGHT_SDK_VERSION = "2.1.0-next.0";
3
+ export const MIDNIGHT_SDK_VERSION = "2.2.0-next.0";
@@ -150,6 +150,7 @@ export declare class Offer {
150
150
  readonly tick: bigint;
151
151
  private cachedGroup;
152
152
  private cachedHash;
153
+ private cachedOnchainHash;
153
154
  /**
154
155
  * Whether the group id was supplied at construction rather than derived.
155
156
  *
@@ -329,6 +330,55 @@ export declare class Offer {
329
330
  * ```
330
331
  */
331
332
  get hash(): Hash;
333
+ /**
334
+ * Returns the on-chain offer identifier emitted by Midnight's `Take` event.
335
+ *
336
+ * This `keccak256(abi.encode(offer))` hash identifies offers on-chain and is
337
+ * distinct from `hash`, the typehash-prefixed ratifier hash.
338
+ * It matches a `Take` event only for the offer exactly as published. For
339
+ * RateRatifierV1 and PriceRatifierV1, hash the offers in the descriptor's
340
+ * `offers`: `buildDescriptor` replaces both the default group and a
341
+ * `Group.create` group.
342
+ *
343
+ * @returns The cached on-chain offer hash.
344
+ * @throws {viem.InvalidAddressError} when an address has an invalid mixed-case checksum.
345
+ * @throws {viem.IntegerOutOfRangeError} when a uint field overflows its ABI size.
346
+ * @example
347
+ * ```ts
348
+ * import { Offer } from "@morpho-org/midnight-sdk";
349
+ * import { zeroAddress } from "viem";
350
+ *
351
+ * const offer = Offer.create({
352
+ * market: {
353
+ * chainId: 8453,
354
+ * midnight: "0x0000000000000000000000000000000000001000",
355
+ * loanToken: "0x0000000000000000000000000000000000006000",
356
+ * collateralParams: [
357
+ * {
358
+ * token: "0x0000000000000000000000000000000000007000",
359
+ * lltv: 770000000000000000n,
360
+ * liquidationCursor: 250000000000000000n,
361
+ * oracle: "0x0000000000000000000000000000000000008000",
362
+ * },
363
+ * ],
364
+ * maturity: 54_000n,
365
+ * rcfThreshold: 0n,
366
+ * enterGate: zeroAddress,
367
+ * liquidatorGate: zeroAddress,
368
+ * },
369
+ * buy: true,
370
+ * maker: "0x0000000000000000000000000000000000009000",
371
+ * tick: 5_000n,
372
+ * group: "0x1111111111111111111111111111111111111111111111111111111111111111",
373
+ * expiry: 3_600n,
374
+ * ratifier: "0x0000000000000000000000000000000000004000",
375
+ * maxUnits: 100n,
376
+ * });
377
+ * const offerHash = offer.onchainHash;
378
+ * console.log(offerHash);
379
+ * ```
380
+ */
381
+ get onchainHash(): Hash;
332
382
  /**
333
383
  * WAD zero-coupon price at this offer's tick.
334
384
  *
@@ -68,6 +68,7 @@ export class Offer {
68
68
  tick;
69
69
  cachedGroup;
70
70
  cachedHash;
71
+ cachedOnchainHash;
71
72
  /**
72
73
  * Whether the group id was supplied at construction rather than derived.
73
74
  *
@@ -278,6 +279,58 @@ export class Offer {
278
279
  this.cachedHash ??= OfferUtils.hash(this);
279
280
  return this.cachedHash;
280
281
  }
282
+ /**
283
+ * Returns the on-chain offer identifier emitted by Midnight's `Take` event.
284
+ *
285
+ * This `keccak256(abi.encode(offer))` hash identifies offers on-chain and is
286
+ * distinct from `hash`, the typehash-prefixed ratifier hash.
287
+ * It matches a `Take` event only for the offer exactly as published. For
288
+ * RateRatifierV1 and PriceRatifierV1, hash the offers in the descriptor's
289
+ * `offers`: `buildDescriptor` replaces both the default group and a
290
+ * `Group.create` group.
291
+ *
292
+ * @returns The cached on-chain offer hash.
293
+ * @throws {viem.InvalidAddressError} when an address has an invalid mixed-case checksum.
294
+ * @throws {viem.IntegerOutOfRangeError} when a uint field overflows its ABI size.
295
+ * @example
296
+ * ```ts
297
+ * import { Offer } from "@morpho-org/midnight-sdk";
298
+ * import { zeroAddress } from "viem";
299
+ *
300
+ * const offer = Offer.create({
301
+ * market: {
302
+ * chainId: 8453,
303
+ * midnight: "0x0000000000000000000000000000000000001000",
304
+ * loanToken: "0x0000000000000000000000000000000000006000",
305
+ * collateralParams: [
306
+ * {
307
+ * token: "0x0000000000000000000000000000000000007000",
308
+ * lltv: 770000000000000000n,
309
+ * liquidationCursor: 250000000000000000n,
310
+ * oracle: "0x0000000000000000000000000000000000008000",
311
+ * },
312
+ * ],
313
+ * maturity: 54_000n,
314
+ * rcfThreshold: 0n,
315
+ * enterGate: zeroAddress,
316
+ * liquidatorGate: zeroAddress,
317
+ * },
318
+ * buy: true,
319
+ * maker: "0x0000000000000000000000000000000000009000",
320
+ * tick: 5_000n,
321
+ * group: "0x1111111111111111111111111111111111111111111111111111111111111111",
322
+ * expiry: 3_600n,
323
+ * ratifier: "0x0000000000000000000000000000000000004000",
324
+ * maxUnits: 100n,
325
+ * });
326
+ * const offerHash = offer.onchainHash;
327
+ * console.log(offerHash);
328
+ * ```
329
+ */
330
+ get onchainHash() {
331
+ this.cachedOnchainHash ??= OfferUtils.onchainHash(this);
332
+ return this.cachedOnchainHash;
333
+ }
281
334
  /**
282
335
  * WAD zero-coupon price at this offer's tick.
283
336
  *
@@ -160,6 +160,114 @@ export declare namespace OfferUtils {
160
160
  * ```
161
161
  */
162
162
  function hash(offer: IOffer & Required<Pick<IOffer, "group">>): Hash;
163
+ /**
164
+ * Computes the on-chain offer identifier from the supplied offer struct.
165
+ *
166
+ * This is `keccak256(abi.encode(offer))`, the hash emitted by Midnight's
167
+ * `Take` event and used to identify offers on-chain. It is distinct from
168
+ * `hashStruct` and `hash`, which produce the typehash-prefixed ratifier hash.
169
+ * Collaterals are hashed in the supplied order; Midnight rejects unsorted
170
+ * collateral params with `CollateralParamsNotSorted`, so pass a sorted struct,
171
+ * for example one returned by `toStruct`.
172
+ * It matches a `Take` event only for the offer exactly as published. For
173
+ * RateRatifierV1 and PriceRatifierV1, hash the offers in the descriptor's
174
+ * `offers`: `buildDescriptor` replaces both the default group and a
175
+ * `Group.create` group.
176
+ *
177
+ * @param offerStruct - ABI-compatible offer to hash without normalization.
178
+ * @returns The offer hash emitted by Midnight's `Take` event.
179
+ * @throws {viem.InvalidAddressError} when an address has an invalid mixed-case checksum.
180
+ * @throws {viem.IntegerOutOfRangeError} when a uint field overflows its ABI size.
181
+ * @example
182
+ * ```ts
183
+ * import { Offer, OfferUtils } from "@morpho-org/midnight-sdk";
184
+ * import { zeroAddress } from "viem";
185
+ *
186
+ * const offer = Offer.create({
187
+ * market: {
188
+ * chainId: 8453,
189
+ * midnight: "0x0000000000000000000000000000000000001000",
190
+ * loanToken: "0x0000000000000000000000000000000000006000",
191
+ * collateralParams: [
192
+ * {
193
+ * token: "0x0000000000000000000000000000000000007000",
194
+ * lltv: 770000000000000000n,
195
+ * liquidationCursor: 250000000000000000n,
196
+ * oracle: "0x0000000000000000000000000000000000008000",
197
+ * },
198
+ * ],
199
+ * maturity: 54_000n,
200
+ * rcfThreshold: 0n,
201
+ * enterGate: zeroAddress,
202
+ * liquidatorGate: zeroAddress,
203
+ * },
204
+ * buy: true,
205
+ * maker: "0x0000000000000000000000000000000000009000",
206
+ * tick: 5_000n,
207
+ * group: "0x1111111111111111111111111111111111111111111111111111111111111111",
208
+ * expiry: 3_600n,
209
+ * ratifier: "0x0000000000000000000000000000000000004000",
210
+ * maxUnits: 100n,
211
+ * });
212
+ * const offerHash = OfferUtils.onchainHashStruct(
213
+ * OfferUtils.toStruct({ offer }),
214
+ * );
215
+ * console.log(offerHash);
216
+ * ```
217
+ */
218
+ function onchainHashStruct(offerStruct: OfferStruct): Hash;
219
+ /**
220
+ * Computes the on-chain offer identifier from an offer with a group id.
221
+ *
222
+ * This is `keccak256(abi.encode(offer))`, the hash emitted by Midnight's
223
+ * `Take` event and used to identify offers on-chain. It is distinct from
224
+ * `hash`, which returns the typehash-prefixed ratifier hash. `toStruct`
225
+ * normalizes the offer and sorts collateral params as required by Midnight.
226
+ * It matches a `Take` event only for the offer exactly as published. For
227
+ * RateRatifierV1 and PriceRatifierV1, hash the offers in the descriptor's
228
+ * `offers`: `buildDescriptor` replaces both the default group and a
229
+ * `Group.create` group.
230
+ *
231
+ * @param offer - Offer with the protocol group id encoded in its struct.
232
+ * @returns The offer hash emitted by Midnight's `Take` event.
233
+ * @throws {viem.InvalidAddressError} when an address has an invalid mixed-case checksum.
234
+ * @throws {viem.IntegerOutOfRangeError} when a uint field overflows its ABI size.
235
+ * @example
236
+ * ```ts
237
+ * import { Offer, OfferUtils } from "@morpho-org/midnight-sdk";
238
+ * import { zeroAddress } from "viem";
239
+ *
240
+ * const offer = Offer.create({
241
+ * market: {
242
+ * chainId: 8453,
243
+ * midnight: "0x0000000000000000000000000000000000001000",
244
+ * loanToken: "0x0000000000000000000000000000000000006000",
245
+ * collateralParams: [
246
+ * {
247
+ * token: "0x0000000000000000000000000000000000007000",
248
+ * lltv: 770000000000000000n,
249
+ * liquidationCursor: 250000000000000000n,
250
+ * oracle: "0x0000000000000000000000000000000000008000",
251
+ * },
252
+ * ],
253
+ * maturity: 54_000n,
254
+ * rcfThreshold: 0n,
255
+ * enterGate: zeroAddress,
256
+ * liquidatorGate: zeroAddress,
257
+ * },
258
+ * buy: true,
259
+ * maker: "0x0000000000000000000000000000000000009000",
260
+ * tick: 5_000n,
261
+ * group: "0x1111111111111111111111111111111111111111111111111111111111111111",
262
+ * expiry: 3_600n,
263
+ * ratifier: "0x0000000000000000000000000000000000004000",
264
+ * maxUnits: 100n,
265
+ * });
266
+ * const offerHash = OfferUtils.onchainHash(offer);
267
+ * console.log(offerHash);
268
+ * ```
269
+ */
270
+ function onchainHash(offer: IOffer & Required<Pick<IOffer, "group">>): Hash;
163
271
  /**
164
272
  * Computes the offer hash used to derive a content-addressed group id.
165
273
  *
@@ -1,10 +1,12 @@
1
1
  import { assertNonNegative, DivisionByZeroError, MathLib, } from "@morpho-org/morpho-ts";
2
- import { encodeAbiParameters, isAddressEqual, keccak256, zeroAddress, zeroHash, } from "viem";
2
+ import { encodeAbiParameters, getAbiItem, isAddressEqual, keccak256, zeroAddress, zeroHash, } from "viem";
3
+ import { midnightAbi } from "../abis.js";
3
4
  import { DEFAULT_TICK_SPACING, MAX_OFFER_CAP, MAX_TICK, OFFER_TYPEHASH, } from "../constants.js";
4
5
  import { InvalidOfferGroupError, InvalidOfferParameterError, } from "../errors.js";
5
6
  import { Market, MarketParams, MarketUtils } from "../market/index.js";
6
7
  import { TakeAmountsLib, TickLib } from "../math/index.js";
7
8
  import { Offer, } from "./Offer.js";
9
+ const takeOfferParam = getAbiItem({ abi: midnightAbi, name: "take" }).inputs[0];
8
10
  const offerHashParams = [
9
11
  { name: "typehash", type: "bytes32" },
10
12
  { name: "marketHash", type: "bytes32" },
@@ -223,6 +225,120 @@ export var OfferUtils;
223
225
  return hashStruct(toStruct({ offer }));
224
226
  }
225
227
  OfferUtils.hash = hash;
228
+ /**
229
+ * Computes the on-chain offer identifier from the supplied offer struct.
230
+ *
231
+ * This is `keccak256(abi.encode(offer))`, the hash emitted by Midnight's
232
+ * `Take` event and used to identify offers on-chain. It is distinct from
233
+ * `hashStruct` and `hash`, which produce the typehash-prefixed ratifier hash.
234
+ * Collaterals are hashed in the supplied order; Midnight rejects unsorted
235
+ * collateral params with `CollateralParamsNotSorted`, so pass a sorted struct,
236
+ * for example one returned by `toStruct`.
237
+ * It matches a `Take` event only for the offer exactly as published. For
238
+ * RateRatifierV1 and PriceRatifierV1, hash the offers in the descriptor's
239
+ * `offers`: `buildDescriptor` replaces both the default group and a
240
+ * `Group.create` group.
241
+ *
242
+ * @param offerStruct - ABI-compatible offer to hash without normalization.
243
+ * @returns The offer hash emitted by Midnight's `Take` event.
244
+ * @throws {viem.InvalidAddressError} when an address has an invalid mixed-case checksum.
245
+ * @throws {viem.IntegerOutOfRangeError} when a uint field overflows its ABI size.
246
+ * @example
247
+ * ```ts
248
+ * import { Offer, OfferUtils } from "@morpho-org/midnight-sdk";
249
+ * import { zeroAddress } from "viem";
250
+ *
251
+ * const offer = Offer.create({
252
+ * market: {
253
+ * chainId: 8453,
254
+ * midnight: "0x0000000000000000000000000000000000001000",
255
+ * loanToken: "0x0000000000000000000000000000000000006000",
256
+ * collateralParams: [
257
+ * {
258
+ * token: "0x0000000000000000000000000000000000007000",
259
+ * lltv: 770000000000000000n,
260
+ * liquidationCursor: 250000000000000000n,
261
+ * oracle: "0x0000000000000000000000000000000000008000",
262
+ * },
263
+ * ],
264
+ * maturity: 54_000n,
265
+ * rcfThreshold: 0n,
266
+ * enterGate: zeroAddress,
267
+ * liquidatorGate: zeroAddress,
268
+ * },
269
+ * buy: true,
270
+ * maker: "0x0000000000000000000000000000000000009000",
271
+ * tick: 5_000n,
272
+ * group: "0x1111111111111111111111111111111111111111111111111111111111111111",
273
+ * expiry: 3_600n,
274
+ * ratifier: "0x0000000000000000000000000000000000004000",
275
+ * maxUnits: 100n,
276
+ * });
277
+ * const offerHash = OfferUtils.onchainHashStruct(
278
+ * OfferUtils.toStruct({ offer }),
279
+ * );
280
+ * console.log(offerHash);
281
+ * ```
282
+ */
283
+ function onchainHashStruct(offerStruct) {
284
+ return keccak256(encodeAbiParameters([takeOfferParam], [offerStruct]));
285
+ }
286
+ OfferUtils.onchainHashStruct = onchainHashStruct;
287
+ /**
288
+ * Computes the on-chain offer identifier from an offer with a group id.
289
+ *
290
+ * This is `keccak256(abi.encode(offer))`, the hash emitted by Midnight's
291
+ * `Take` event and used to identify offers on-chain. It is distinct from
292
+ * `hash`, which returns the typehash-prefixed ratifier hash. `toStruct`
293
+ * normalizes the offer and sorts collateral params as required by Midnight.
294
+ * It matches a `Take` event only for the offer exactly as published. For
295
+ * RateRatifierV1 and PriceRatifierV1, hash the offers in the descriptor's
296
+ * `offers`: `buildDescriptor` replaces both the default group and a
297
+ * `Group.create` group.
298
+ *
299
+ * @param offer - Offer with the protocol group id encoded in its struct.
300
+ * @returns The offer hash emitted by Midnight's `Take` event.
301
+ * @throws {viem.InvalidAddressError} when an address has an invalid mixed-case checksum.
302
+ * @throws {viem.IntegerOutOfRangeError} when a uint field overflows its ABI size.
303
+ * @example
304
+ * ```ts
305
+ * import { Offer, OfferUtils } from "@morpho-org/midnight-sdk";
306
+ * import { zeroAddress } from "viem";
307
+ *
308
+ * const offer = Offer.create({
309
+ * market: {
310
+ * chainId: 8453,
311
+ * midnight: "0x0000000000000000000000000000000000001000",
312
+ * loanToken: "0x0000000000000000000000000000000000006000",
313
+ * collateralParams: [
314
+ * {
315
+ * token: "0x0000000000000000000000000000000000007000",
316
+ * lltv: 770000000000000000n,
317
+ * liquidationCursor: 250000000000000000n,
318
+ * oracle: "0x0000000000000000000000000000000000008000",
319
+ * },
320
+ * ],
321
+ * maturity: 54_000n,
322
+ * rcfThreshold: 0n,
323
+ * enterGate: zeroAddress,
324
+ * liquidatorGate: zeroAddress,
325
+ * },
326
+ * buy: true,
327
+ * maker: "0x0000000000000000000000000000000000009000",
328
+ * tick: 5_000n,
329
+ * group: "0x1111111111111111111111111111111111111111111111111111111111111111",
330
+ * expiry: 3_600n,
331
+ * ratifier: "0x0000000000000000000000000000000000004000",
332
+ * maxUnits: 100n,
333
+ * });
334
+ * const offerHash = OfferUtils.onchainHash(offer);
335
+ * console.log(offerHash);
336
+ * ```
337
+ */
338
+ function onchainHash(offer) {
339
+ return onchainHashStruct(toStruct({ offer }));
340
+ }
341
+ OfferUtils.onchainHash = onchainHash;
226
342
  /**
227
343
  * Computes the offer hash used to derive a content-addressed group id.
228
344
  *
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@morpho-org/midnight-sdk",
3
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": "2.1.0-next.0",
4
+ "version": "2.2.0-next.0",
5
5
  "author": "Morpho Association <contact@morpho.org>",
6
6
  "repository": {
7
7
  "type": "git",
@@ -46,7 +46,7 @@
46
46
  },
47
47
  "devDependencies": {
48
48
  "@morpho-org/morpho-ts": "^4.1.0-next.0",
49
- "@morpho-org/test": "^2.11.0-next.0",
49
+ "@morpho-org/test": "^2.12.0-next.0",
50
50
  "fast-check": "^4.9.0",
51
51
  "typescript": "7.0.2",
52
52
  "viem": "^2.55.10",