@morpho-org/midnight-sdk 1.6.0 → 1.7.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 (43) hide show
  1. package/lib/cjs/api/MidnightApi.d.ts +16 -14
  2. package/lib/cjs/api/MidnightApi.js +26 -16
  3. package/lib/cjs/api/helpers.d.ts +14 -2
  4. package/lib/cjs/api/helpers.js +71 -11
  5. package/lib/cjs/api/index.d.ts +1 -1
  6. package/lib/cjs/api/index.js +2 -1
  7. package/lib/cjs/api/types.d.ts +1 -1
  8. package/lib/cjs/api/version.generated.d.ts +1 -1
  9. package/lib/cjs/api/version.generated.js +1 -1
  10. package/lib/cjs/errors.d.ts +13 -0
  11. package/lib/cjs/errors.js +18 -1
  12. package/lib/cjs/market/Market.d.ts +6 -30
  13. package/lib/cjs/market/Market.js +7 -31
  14. package/lib/cjs/market/MarketUtils.d.ts +14 -0
  15. package/lib/cjs/market/MarketUtils.js +17 -1
  16. package/lib/cjs/offers/Offer.d.ts +1 -1
  17. package/lib/cjs/offers/Offer.js +1 -1
  18. package/lib/cjs/offers/OfferChainUtils.d.ts +6 -2
  19. package/lib/cjs/offers/OfferChainUtils.js +6 -2
  20. package/lib/cjs/position/Position.d.ts +5 -25
  21. package/lib/cjs/position/Position.js +5 -25
  22. package/lib/esm/api/MidnightApi.d.ts +16 -14
  23. package/lib/esm/api/MidnightApi.js +28 -18
  24. package/lib/esm/api/helpers.d.ts +14 -2
  25. package/lib/esm/api/helpers.js +71 -12
  26. package/lib/esm/api/index.d.ts +1 -1
  27. package/lib/esm/api/index.js +1 -1
  28. package/lib/esm/api/types.d.ts +1 -1
  29. package/lib/esm/api/version.generated.d.ts +1 -1
  30. package/lib/esm/api/version.generated.js +1 -1
  31. package/lib/esm/errors.d.ts +13 -0
  32. package/lib/esm/errors.js +16 -0
  33. package/lib/esm/market/Market.d.ts +6 -30
  34. package/lib/esm/market/Market.js +7 -31
  35. package/lib/esm/market/MarketUtils.d.ts +14 -0
  36. package/lib/esm/market/MarketUtils.js +18 -2
  37. package/lib/esm/offers/Offer.d.ts +1 -1
  38. package/lib/esm/offers/Offer.js +1 -1
  39. package/lib/esm/offers/OfferChainUtils.d.ts +6 -2
  40. package/lib/esm/offers/OfferChainUtils.js +6 -2
  41. package/lib/esm/position/Position.d.ts +5 -25
  42. package/lib/esm/position/Position.js +5 -25
  43. package/package.json +3 -6
@@ -65,9 +65,9 @@ export declare class MidnightApi {
65
65
  * @param params.baseUrl - Optional Midnight API base URL override.
66
66
  * @param params.fetch - Optional fetch implementation override.
67
67
  * @param params.request - Optional fetch options forwarded to this request.
68
- * @returns Paginated books mapped to SDK camelCase fields.
68
+ * @returns Paginated books mapped to SDK camelCase fields, with each book's price levels sorted best first (asks ascending tick, bids descending tick).
69
69
  * @throws {MidnightApiError} when the API returns a non-2xx response.
70
- * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON, when a returned book's `market_id` does not match, or cannot be derived from, its own market params, or when a returned book falls outside the supplied `marketIds` filter.
70
+ * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON, when a returned book's `market_id` does not match, or cannot be derived from, its own market params, or when a returned book falls outside the supplied `marketIds`, `chainIds`, `loanTokens`, `collateralTokens`, or `maturities` filters.
71
71
  * @example
72
72
  * ```ts
73
73
  * import { MidnightApi } from "@morpho-org/midnight-sdk/api";
@@ -90,7 +90,7 @@ export declare class MidnightApi {
90
90
  * @param params.baseUrl - Optional Midnight API base URL override.
91
91
  * @param params.fetch - Optional fetch implementation override.
92
92
  * @param params.request - Optional fetch options forwarded to this request.
93
- * @returns Book snapshot mapped to SDK camelCase fields.
93
+ * @returns Book snapshot mapped to SDK camelCase fields, with price levels sorted best first (asks ascending tick, bids descending tick).
94
94
  * @throws {MidnightApiError} when the API returns a non-2xx response.
95
95
  * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON, when the returned book's `market_id` does not match, or cannot be derived from, its own market params, or when it differs from the requested `marketId`.
96
96
  * @example
@@ -115,7 +115,7 @@ export declare class MidnightApi {
115
115
  * @param params.baseUrl - Optional Midnight API base URL override.
116
116
  * @param params.fetch - Optional fetch implementation override.
117
117
  * @param params.request - Optional fetch options forwarded to this request.
118
- * @returns Price levels mapped to SDK camelCase fields.
118
+ * @returns Price levels mapped to SDK camelCase fields, sorted best first (asks ascending tick, bids descending tick).
119
119
  * @throws {MidnightApiError} when the API returns a non-2xx response.
120
120
  * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON.
121
121
  * @example
@@ -142,7 +142,7 @@ export declare class MidnightApi {
142
142
  * @param params.request - Optional fetch options forwarded to this request.
143
143
  * @returns ABI-ready take objects mapped from the API response.
144
144
  * @throws {MidnightApiError} when the API returns a non-2xx response.
145
- * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON.
145
+ * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON, when a returned offer cannot be mapped (malformed numeric or hex fields), when its `market_id` does not match, or cannot be derived from, its embedded market, when it falls outside the requested filters, when its `receiverIfMakerIsSeller` is not a well-formed address, or when its caps or buy-side receiver are not executable.
146
146
  * @example
147
147
  * ```ts
148
148
  * import { MidnightApi } from "@morpho-org/midnight-sdk/api";
@@ -171,9 +171,10 @@ export declare class MidnightApi {
171
171
  * @param params.fetch - Optional fetch implementation override.
172
172
  * @param params.request - Optional fetch options forwarded to this request.
173
173
  * @returns Quote and signed ABI-ready take caps mapped from the API response.
174
+ * @throws {InvalidMidnightApiQuoteTargetError} when the runtime input does not set exactly one of `units` or `assets`.
174
175
  * @throws {NegativeValueError} when `settlementFee` is negative.
175
176
  * @throws {MidnightApiError} when the API returns a non-2xx response.
176
- * @throws {InvalidMidnightApiResponseError} when the API returns a malformed success response or the returned offers imply a rounded aggregate settlement price outside the effective average-worst-price guard.
177
+ * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON, when a returned offer cannot be mapped (malformed numeric or hex fields), when its `market_id` does not match, or cannot be derived from, its embedded market, when it falls outside the requested filters, when its `receiverIfMakerIsSeller` is not a well-formed address, when its caps or buy-side receiver are not executable, or when the returned offers imply a rounded aggregate settlement price outside the effective average-worst-price guard.
177
178
  * @throws {SettlementFeeExceedsPriceError} when a bid's settlement fee exceeds its offer price.
178
179
  * @example
179
180
  * ```ts
@@ -204,7 +205,7 @@ export declare class MidnightApi {
204
205
  * @param params.request - Optional fetch options forwarded to this request.
205
206
  * @returns Paginated ABI-ready take objects mapped from the API response.
206
207
  * @throws {MidnightApiError} when the API returns a non-2xx response.
207
- * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON.
208
+ * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON, when a returned offer cannot be mapped (malformed numeric or hex fields), when its `market_id` does not match, or cannot be derived from, its embedded market, when it falls outside the requested filters, when its `receiverIfMakerIsSeller` is not a well-formed address, or when its caps or buy-side receiver are not executable.
208
209
  * @example
209
210
  * ```ts
210
211
  * import { MidnightApi } from "@morpho-org/midnight-sdk/api";
@@ -321,9 +322,9 @@ export declare class MidnightApi {
321
322
  * @param params.marketIds - Optional market id filters.
322
323
  * @param params.limit - Optional maximum number of books to return.
323
324
  * @param params.cursor - Optional opaque pagination cursor from a previous response.
324
- * @returns Paginated books mapped to SDK camelCase fields.
325
+ * @returns Paginated books mapped to SDK camelCase fields, with each book's price levels sorted best first (asks ascending tick, bids descending tick).
325
326
  * @throws {MidnightApiError} when the API returns a non-2xx response.
326
- * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON, when a returned book's `market_id` does not match, or cannot be derived from, its own market params, or when a returned book falls outside the supplied `marketIds` filter.
327
+ * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON, when a returned book's `market_id` does not match, or cannot be derived from, its own market params, or when a returned book falls outside the supplied `marketIds`, `chainIds`, `loanTokens`, `collateralTokens`, or `maturities` filters.
327
328
  * @example
328
329
  * ```ts
329
330
  * import { MidnightApi } from "@morpho-org/midnight-sdk/api";
@@ -341,7 +342,7 @@ export declare class MidnightApi {
341
342
  *
342
343
  * @param params.marketId - Market id whose book to read.
343
344
  * @param params.depth - Optional maximum levels returned per side.
344
- * @returns Book snapshot mapped to SDK camelCase fields.
345
+ * @returns Book snapshot mapped to SDK camelCase fields, with price levels sorted best first (asks ascending tick, bids descending tick).
345
346
  * @throws {MidnightApiError} when the API returns a non-2xx response.
346
347
  * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON, when the returned book's `market_id` does not match, or cannot be derived from, its own market params, or when it differs from the requested `marketId`.
347
348
  * @example
@@ -364,7 +365,7 @@ export declare class MidnightApi {
364
365
  * @param params.marketId - Market id whose book side to read.
365
366
  * @param params.side - Book side to query.
366
367
  * @param params.depth - Optional maximum levels returned.
367
- * @returns Price levels mapped to SDK camelCase fields.
368
+ * @returns Price levels mapped to SDK camelCase fields, sorted best first (asks ascending tick, bids descending tick).
368
369
  * @throws {MidnightApiError} when the API returns a non-2xx response.
369
370
  * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON.
370
371
  * @example
@@ -389,7 +390,7 @@ export declare class MidnightApi {
389
390
  * @param params.side - Book side to query.
390
391
  * @returns ABI-ready take objects mapped from the API response.
391
392
  * @throws {MidnightApiError} when the API returns a non-2xx response.
392
- * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON.
393
+ * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON, when a returned offer cannot be mapped (malformed numeric or hex fields), when its `market_id` does not match, or cannot be derived from, its embedded market, when it falls outside the requested filters, when its `receiverIfMakerIsSeller` is not a well-formed address, or when its caps or buy-side receiver are not executable.
393
394
  * @example
394
395
  * ```ts
395
396
  * import { MidnightApi } from "@morpho-org/midnight-sdk/api";
@@ -416,9 +417,10 @@ export declare class MidnightApi {
416
417
  * @param params.slippage - Optional slippage percentage used to derive the guard. Mutually exclusive with `params.averageWorstPrice`.
417
418
  * @param params.settlementFee - Optional current WAD-scaled settlement fee used for local guard validation. Defaults to zero.
418
419
  * @returns Quote and signed ABI-ready take caps mapped from the API response.
420
+ * @throws {InvalidMidnightApiQuoteTargetError} when the runtime input does not set exactly one of `units` or `assets`.
419
421
  * @throws {NegativeValueError} when `settlementFee` is negative.
420
422
  * @throws {MidnightApiError} when the API returns a non-2xx response.
421
- * @throws {InvalidMidnightApiResponseError} when the API returns a malformed success response or the returned offers imply a rounded aggregate settlement price outside the effective average-worst-price guard.
423
+ * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON, when a returned offer cannot be mapped (malformed numeric or hex fields), when its `market_id` does not match, or cannot be derived from, its embedded market, when it falls outside the requested filters, when its `receiverIfMakerIsSeller` is not a well-formed address, when its caps or buy-side receiver are not executable, or when the returned offers imply a rounded aggregate settlement price outside the effective average-worst-price guard.
422
424
  * @throws {SettlementFeeExceedsPriceError} when a bid's settlement fee exceeds its offer price.
423
425
  * @example
424
426
  * ```ts
@@ -446,7 +448,7 @@ export declare class MidnightApi {
446
448
  * @param params.cursor - Optional opaque pagination cursor from a previous response.
447
449
  * @returns Paginated ABI-ready take objects mapped from the API response.
448
450
  * @throws {MidnightApiError} when the API returns a non-2xx response.
449
- * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON.
451
+ * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON, when a returned offer cannot be mapped (malformed numeric or hex fields), when its `market_id` does not match, or cannot be derived from, its embedded market, when it falls outside the requested filters, when its `receiverIfMakerIsSeller` is not a well-formed address, or when its caps or buy-side receiver are not executable.
450
452
  * @example
451
453
  * ```ts
452
454
  * import { MidnightApi } from "@morpho-org/midnight-sdk/api";
@@ -77,9 +77,9 @@ class MidnightApi {
77
77
  * @param params.baseUrl - Optional Midnight API base URL override.
78
78
  * @param params.fetch - Optional fetch implementation override.
79
79
  * @param params.request - Optional fetch options forwarded to this request.
80
- * @returns Paginated books mapped to SDK camelCase fields.
80
+ * @returns Paginated books mapped to SDK camelCase fields, with each book's price levels sorted best first (asks ascending tick, bids descending tick).
81
81
  * @throws {MidnightApiError} when the API returns a non-2xx response.
82
- * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON, when a returned book's `market_id` does not match, or cannot be derived from, its own market params, or when a returned book falls outside the supplied `marketIds` filter.
82
+ * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON, when a returned book's `market_id` does not match, or cannot be derived from, its own market params, or when a returned book falls outside the supplied `marketIds`, `chainIds`, `loanTokens`, `collateralTokens`, or `maturities` filters.
83
83
  * @example
84
84
  * ```ts
85
85
  * import { MidnightApi } from "@morpho-org/midnight-sdk/api";
@@ -110,7 +110,13 @@ class MidnightApi {
110
110
  });
111
111
  return {
112
112
  cursor: response.cursor,
113
- data: (0, helpers_js_1.mapBoundBooks)(response.data, input.marketIds),
113
+ data: (0, helpers_js_1.mapBoundBooks)(response.data, {
114
+ marketIds: input.marketIds,
115
+ chainIds: input.chainIds,
116
+ loanTokens: input.loanTokens,
117
+ collateralTokens: input.collateralTokens,
118
+ maturities: input.maturities,
119
+ }),
114
120
  };
115
121
  }
116
122
  /**
@@ -123,7 +129,7 @@ class MidnightApi {
123
129
  * @param params.baseUrl - Optional Midnight API base URL override.
124
130
  * @param params.fetch - Optional fetch implementation override.
125
131
  * @param params.request - Optional fetch options forwarded to this request.
126
- * @returns Book snapshot mapped to SDK camelCase fields.
132
+ * @returns Book snapshot mapped to SDK camelCase fields, with price levels sorted best first (asks ascending tick, bids descending tick).
127
133
  * @throws {MidnightApiError} when the API returns a non-2xx response.
128
134
  * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON, when the returned book's `market_id` does not match, or cannot be derived from, its own market params, or when it differs from the requested `marketId`.
129
135
  * @example
@@ -161,7 +167,7 @@ class MidnightApi {
161
167
  * @param params.baseUrl - Optional Midnight API base URL override.
162
168
  * @param params.fetch - Optional fetch implementation override.
163
169
  * @param params.request - Optional fetch options forwarded to this request.
164
- * @returns Price levels mapped to SDK camelCase fields.
170
+ * @returns Price levels mapped to SDK camelCase fields, sorted best first (asks ascending tick, bids descending tick).
165
171
  * @throws {MidnightApiError} when the API returns a non-2xx response.
166
172
  * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON.
167
173
  * @example
@@ -186,7 +192,7 @@ class MidnightApi {
186
192
  },
187
193
  });
188
194
  return {
189
- data: response.data.map(helpers_js_1.mapPriceLevel),
195
+ data: (0, helpers_js_1.mapPriceLevels)(response.data, input.side),
190
196
  };
191
197
  }
192
198
  /**
@@ -201,7 +207,7 @@ class MidnightApi {
201
207
  * @param params.request - Optional fetch options forwarded to this request.
202
208
  * @returns ABI-ready take objects mapped from the API response.
203
209
  * @throws {MidnightApiError} when the API returns a non-2xx response.
204
- * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON.
210
+ * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON, when a returned offer cannot be mapped (malformed numeric or hex fields), when its `market_id` does not match, or cannot be derived from, its embedded market, when it falls outside the requested filters, when its `receiverIfMakerIsSeller` is not a well-formed address, or when its caps or buy-side receiver are not executable.
205
211
  * @example
206
212
  * ```ts
207
213
  * import { MidnightApi } from "@morpho-org/midnight-sdk/api";
@@ -247,9 +253,10 @@ class MidnightApi {
247
253
  * @param params.fetch - Optional fetch implementation override.
248
254
  * @param params.request - Optional fetch options forwarded to this request.
249
255
  * @returns Quote and signed ABI-ready take caps mapped from the API response.
256
+ * @throws {InvalidMidnightApiQuoteTargetError} when the runtime input does not set exactly one of `units` or `assets`.
250
257
  * @throws {NegativeValueError} when `settlementFee` is negative.
251
258
  * @throws {MidnightApiError} when the API returns a non-2xx response.
252
- * @throws {InvalidMidnightApiResponseError} when the API returns a malformed success response or the returned offers imply a rounded aggregate settlement price outside the effective average-worst-price guard.
259
+ * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON, when a returned offer cannot be mapped (malformed numeric or hex fields), when its `market_id` does not match, or cannot be derived from, its embedded market, when it falls outside the requested filters, when its `receiverIfMakerIsSeller` is not a well-formed address, when its caps or buy-side receiver are not executable, or when the returned offers imply a rounded aggregate settlement price outside the effective average-worst-price guard.
253
260
  * @throws {SettlementFeeExceedsPriceError} when a bid's settlement fee exceeds its offer price.
254
261
  * @example
255
262
  * ```ts
@@ -266,6 +273,8 @@ class MidnightApi {
266
273
  */
267
274
  static async fetchBookQuote(params) {
268
275
  const input = params;
276
+ if ((input.units == null) === (input.assets == null))
277
+ throw new errors_js_1.InvalidMidnightApiQuoteTargetError();
269
278
  const settlementFee = BigInt(input.settlementFee ?? 0n);
270
279
  (0, morpho_ts_1.assertNonNegative)("settlementFee", settlementFee);
271
280
  const response = await (0, helpers_js_1.requestMidnightApi)({
@@ -372,7 +381,7 @@ class MidnightApi {
372
381
  * @param params.request - Optional fetch options forwarded to this request.
373
382
  * @returns Paginated ABI-ready take objects mapped from the API response.
374
383
  * @throws {MidnightApiError} when the API returns a non-2xx response.
375
- * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON.
384
+ * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON, when a returned offer cannot be mapped (malformed numeric or hex fields), when its `market_id` does not match, or cannot be derived from, its embedded market, when it falls outside the requested filters, when its `receiverIfMakerIsSeller` is not a well-formed address, or when its caps or buy-side receiver are not executable.
376
385
  * @example
377
386
  * ```ts
378
387
  * import { MidnightApi } from "@morpho-org/midnight-sdk/api";
@@ -537,9 +546,9 @@ class MidnightApi {
537
546
  * @param params.marketIds - Optional market id filters.
538
547
  * @param params.limit - Optional maximum number of books to return.
539
548
  * @param params.cursor - Optional opaque pagination cursor from a previous response.
540
- * @returns Paginated books mapped to SDK camelCase fields.
549
+ * @returns Paginated books mapped to SDK camelCase fields, with each book's price levels sorted best first (asks ascending tick, bids descending tick).
541
550
  * @throws {MidnightApiError} when the API returns a non-2xx response.
542
- * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON, when a returned book's `market_id` does not match, or cannot be derived from, its own market params, or when a returned book falls outside the supplied `marketIds` filter.
551
+ * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON, when a returned book's `market_id` does not match, or cannot be derived from, its own market params, or when a returned book falls outside the supplied `marketIds`, `chainIds`, `loanTokens`, `collateralTokens`, or `maturities` filters.
543
552
  * @example
544
553
  * ```ts
545
554
  * import { MidnightApi } from "@morpho-org/midnight-sdk/api";
@@ -562,7 +571,7 @@ class MidnightApi {
562
571
  *
563
572
  * @param params.marketId - Market id whose book to read.
564
573
  * @param params.depth - Optional maximum levels returned per side.
565
- * @returns Book snapshot mapped to SDK camelCase fields.
574
+ * @returns Book snapshot mapped to SDK camelCase fields, with price levels sorted best first (asks ascending tick, bids descending tick).
566
575
  * @throws {MidnightApiError} when the API returns a non-2xx response.
567
576
  * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON, when the returned book's `market_id` does not match, or cannot be derived from, its own market params, or when it differs from the requested `marketId`.
568
577
  * @example
@@ -590,7 +599,7 @@ class MidnightApi {
590
599
  * @param params.marketId - Market id whose book side to read.
591
600
  * @param params.side - Book side to query.
592
601
  * @param params.depth - Optional maximum levels returned.
593
- * @returns Price levels mapped to SDK camelCase fields.
602
+ * @returns Price levels mapped to SDK camelCase fields, sorted best first (asks ascending tick, bids descending tick).
594
603
  * @throws {MidnightApiError} when the API returns a non-2xx response.
595
604
  * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON.
596
605
  * @example
@@ -620,7 +629,7 @@ class MidnightApi {
620
629
  * @param params.side - Book side to query.
621
630
  * @returns ABI-ready take objects mapped from the API response.
622
631
  * @throws {MidnightApiError} when the API returns a non-2xx response.
623
- * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON.
632
+ * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON, when a returned offer cannot be mapped (malformed numeric or hex fields), when its `market_id` does not match, or cannot be derived from, its embedded market, when it falls outside the requested filters, when its `receiverIfMakerIsSeller` is not a well-formed address, or when its caps or buy-side receiver are not executable.
624
633
  * @example
625
634
  * ```ts
626
635
  * import { MidnightApi } from "@morpho-org/midnight-sdk/api";
@@ -652,9 +661,10 @@ class MidnightApi {
652
661
  * @param params.slippage - Optional slippage percentage used to derive the guard. Mutually exclusive with `params.averageWorstPrice`.
653
662
  * @param params.settlementFee - Optional current WAD-scaled settlement fee used for local guard validation. Defaults to zero.
654
663
  * @returns Quote and signed ABI-ready take caps mapped from the API response.
664
+ * @throws {InvalidMidnightApiQuoteTargetError} when the runtime input does not set exactly one of `units` or `assets`.
655
665
  * @throws {NegativeValueError} when `settlementFee` is negative.
656
666
  * @throws {MidnightApiError} when the API returns a non-2xx response.
657
- * @throws {InvalidMidnightApiResponseError} when the API returns a malformed success response or the returned offers imply a rounded aggregate settlement price outside the effective average-worst-price guard.
667
+ * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON, when a returned offer cannot be mapped (malformed numeric or hex fields), when its `market_id` does not match, or cannot be derived from, its embedded market, when it falls outside the requested filters, when its `receiverIfMakerIsSeller` is not a well-formed address, when its caps or buy-side receiver are not executable, or when the returned offers imply a rounded aggregate settlement price outside the effective average-worst-price guard.
658
668
  * @throws {SettlementFeeExceedsPriceError} when a bid's settlement fee exceeds its offer price.
659
669
  * @example
660
670
  * ```ts
@@ -687,7 +697,7 @@ class MidnightApi {
687
697
  * @param params.cursor - Optional opaque pagination cursor from a previous response.
688
698
  * @returns Paginated ABI-ready take objects mapped from the API response.
689
699
  * @throws {MidnightApiError} when the API returns a non-2xx response.
690
- * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON.
700
+ * @throws {InvalidMidnightApiResponseError} when the API success response is not JSON, when a returned offer cannot be mapped (malformed numeric or hex fields), when its `market_id` does not match, or cannot be derived from, its embedded market, when it falls outside the requested filters, when its `receiverIfMakerIsSeller` is not a well-formed address, or when its caps or buy-side receiver are not executable.
691
701
  * @example
692
702
  * ```ts
693
703
  * import { MidnightApi } from "@morpho-org/midnight-sdk/api";
@@ -14,16 +14,28 @@ export declare function buildBookPath(params: {
14
14
  * its own market params. Recomputing the id with `MarketUtils.toId` (mirroring the
15
15
  * takeable-offers path) stops a hostile API from pairing a trusted id with foreign
16
16
  * metadata; every book flows through here, so both bound paths reject the same substitution.
17
+ * Collaterals are returned in the protocol's canonical order so their array index matches
18
+ * the onchain `collateralIndex`.
17
19
  */
18
20
  export declare function mapBookMarket(book: ApiBookMarketResponse): MidnightApiBookMarket;
19
21
  /** @internal Maps a book market, binding its verified id to the requested market. */
20
22
  export declare function mapBoundBookMarket(book: ApiBookMarketResponse, requestedMarketId: Hash): MidnightApiBookMarket;
21
- /** @internal Maps listed book markets, binding each verified id to the requested market_ids filter when present. */
22
- export declare function mapBoundBooks(books: readonly ApiBookMarketResponse[], marketIds?: readonly Hash[]): MidnightApiBookMarket[];
23
+ /** @internal Requested `fetchBooks` filters that every returned book must satisfy. */
24
+ export interface BookFilterContext {
25
+ readonly marketIds?: readonly Hash[];
26
+ readonly chainIds?: readonly number[];
27
+ readonly loanTokens?: readonly Address[];
28
+ readonly collateralTokens?: readonly Address[];
29
+ readonly maturities?: readonly number[];
30
+ }
31
+ /** @internal Maps listed book markets, binding each verified id to requested filters when present. */
32
+ export declare function mapBoundBooks(books: readonly ApiBookMarketResponse[], context?: BookFilterContext): MidnightApiBookMarket[];
23
33
  /** @internal Maps a collateral API payload to the SDK response shape. */
24
34
  export declare function mapCollateral(collateral: ApiCollateralResponse): MidnightApiCollateral;
25
35
  /** @internal Maps a price-level API payload to the SDK response shape. */
26
36
  export declare function mapPriceLevel(level: ApiPriceLevelResponse): MidnightApiPriceLevel;
37
+ /** @internal Maps API price levels and sorts them best first: asks by ascending tick, bids by descending tick. */
38
+ export declare function mapPriceLevels(levels: readonly ApiPriceLevelResponse[], side: MidnightApiBookSide): MidnightApiPriceLevel[];
27
39
  /** @internal Maps a takeable-offer API payload to the SDK response shape. */
28
40
  export declare function mapTakeableOffer(takeableOffer: ApiTakeableOfferResponse): MidnightApiTake;
29
41
  /** @internal API response context required for a takeable offer to be executable for the caller's request. */
@@ -7,6 +7,7 @@ exports.mapBoundBookMarket = mapBoundBookMarket;
7
7
  exports.mapBoundBooks = mapBoundBooks;
8
8
  exports.mapCollateral = mapCollateral;
9
9
  exports.mapPriceLevel = mapPriceLevel;
10
+ exports.mapPriceLevels = mapPriceLevels;
10
11
  exports.mapTakeableOffer = mapTakeableOffer;
11
12
  exports.mapBoundTakeableOffers = mapBoundTakeableOffers;
12
13
  exports.parseValidationResponse = parseValidationResponse;
@@ -14,6 +15,7 @@ const morpho_ts_1 = require("@morpho-org/morpho-ts");
14
15
  const viem_1 = require("viem");
15
16
  const errors_js_1 = require("../errors.js");
16
17
  const index_js_1 = require("../market/index.js");
18
+ const index_js_2 = require("../offers/index.js");
17
19
  const types_js_1 = require("./types.js");
18
20
  const version_generated_js_1 = require("./version.generated.js");
19
21
  const DEFAULT_MIDNIGHT_API_URL = new URL("/v0/midnight", morpho_ts_1.BLUE_API_BASE_URL);
@@ -98,6 +100,8 @@ function buildBookPath(params) {
98
100
  * its own market params. Recomputing the id with `MarketUtils.toId` (mirroring the
99
101
  * takeable-offers path) stops a hostile API from pairing a trusted id with foreign
100
102
  * metadata; every book flows through here, so both bound paths reject the same substitution.
103
+ * Collaterals are returned in the protocol's canonical order so their array index matches
104
+ * the onchain `collateralIndex`.
101
105
  */
102
106
  function mapBookMarket(book) {
103
107
  let derivedMarketId;
@@ -133,13 +137,15 @@ function mapBookMarket(book) {
133
137
  chainId: book.chain_id,
134
138
  midnight: book.midnight,
135
139
  loanToken: book.loan_token,
136
- collaterals: book.collaterals.map(mapCollateral),
140
+ collaterals: [...book.collaterals]
141
+ .sort(index_js_1.MarketUtils.compareCollateralTokens)
142
+ .map(mapCollateral),
137
143
  maturity: book.maturity,
138
144
  rcfThreshold: book.rcf_threshold,
139
145
  enterGate: book.enter_gate,
140
146
  liquidatorGate: book.liquidator_gate,
141
- asks: book.asks.map(mapPriceLevel),
142
- bids: book.bids.map(mapPriceLevel),
147
+ asks: mapPriceLevels(book.asks, "asks"),
148
+ bids: mapPriceLevels(book.bids, "bids"),
143
149
  };
144
150
  }
145
151
  /** @internal Maps a book market, binding its verified id to the requested market. */
@@ -150,15 +156,36 @@ function mapBoundBookMarket(book, requestedMarketId) {
150
156
  }
151
157
  return market;
152
158
  }
153
- /** @internal Maps listed book markets, binding each verified id to the requested market_ids filter when present. */
154
- function mapBoundBooks(books, marketIds) {
159
+ /** @internal Maps listed book markets, binding each verified id to requested filters when present. */
160
+ function mapBoundBooks(books, context = {}) {
155
161
  return books.map((book) => {
156
162
  const market = mapBookMarket(book);
157
- if (marketIds != null &&
158
- marketIds.length > 0 &&
159
- !marketIds.some((marketId) => (0, morpho_ts_1.isHexEqual)(marketId, market.marketId))) {
163
+ if (context.marketIds != null &&
164
+ context.marketIds.length > 0 &&
165
+ !context.marketIds.some((marketId) => (0, morpho_ts_1.isHexEqual)(marketId, market.marketId))) {
160
166
  throw new errors_js_1.InvalidMidnightApiResponseError(`Midnight API book market_id "${market.marketId}" is outside the requested market_ids filter.`);
161
167
  }
168
+ if (context.chainIds != null &&
169
+ context.chainIds.length > 0 &&
170
+ !context.chainIds.includes(market.chainId)) {
171
+ throw new errors_js_1.InvalidMidnightApiResponseError(`Midnight API book market_id "${market.marketId}" is outside the requested chain_ids filter.`);
172
+ }
173
+ if (context.loanTokens != null &&
174
+ context.loanTokens.length > 0 &&
175
+ !context.loanTokens.some((token) => (0, viem_1.isAddressEqual)(token, market.loanToken))) {
176
+ throw new errors_js_1.InvalidMidnightApiResponseError(`Midnight API book market_id "${market.marketId}" is outside the requested loan_tokens filter.`);
177
+ }
178
+ const { collateralTokens } = context;
179
+ if (collateralTokens != null &&
180
+ collateralTokens.length > 0 &&
181
+ !market.collaterals.some((collateral) => collateralTokens.some((token) => (0, viem_1.isAddressEqual)(token, collateral.token)))) {
182
+ throw new errors_js_1.InvalidMidnightApiResponseError(`Midnight API book market_id "${market.marketId}" is outside the requested collateral_tokens filter.`);
183
+ }
184
+ if (context.maturities != null &&
185
+ context.maturities.length > 0 &&
186
+ !context.maturities.includes(market.maturity)) {
187
+ throw new errors_js_1.InvalidMidnightApiResponseError(`Midnight API book market_id "${market.marketId}" is outside the requested maturities filter.`);
188
+ }
162
189
  return market;
163
190
  });
164
191
  }
@@ -181,6 +208,12 @@ function mapPriceLevel(level) {
181
208
  count: level.count,
182
209
  };
183
210
  }
211
+ /** @internal Maps API price levels and sorts them best first: asks by ascending tick, bids by descending tick. */
212
+ function mapPriceLevels(levels, side) {
213
+ return levels
214
+ .map(mapPriceLevel)
215
+ .sort((a, b) => (side === "asks" ? a.tick - b.tick : b.tick - a.tick));
216
+ }
184
217
  /** @internal Maps a takeable-offer API payload to the SDK response shape. */
185
218
  function mapTakeableOffer(takeableOffer) {
186
219
  const offer = takeableOffer.offer;
@@ -224,11 +257,38 @@ function mapTakeableOffer(takeableOffer) {
224
257
  /** @internal Maps, validates, and best-price-sorts API takeable offers. */
225
258
  function mapBoundTakeableOffers(takeableOffers, context) {
226
259
  const mapped = takeableOffers.map((takeableOffer) => {
227
- const take = mapTakeableOffer(takeableOffer);
228
- const embeddedMarketId = index_js_1.MarketUtils.toId(take.offer.market);
229
- if (!(0, morpho_ts_1.isHexEqual)(embeddedMarketId, take.marketId)) {
260
+ let take;
261
+ let matchesAdvertisedId;
262
+ let embeddedMarketId;
263
+ try {
264
+ take = mapTakeableOffer(takeableOffer);
265
+ embeddedMarketId = index_js_1.MarketUtils.toId(take.offer.market);
266
+ matchesAdvertisedId = (0, morpho_ts_1.isHexEqual)(embeddedMarketId, take.marketId);
267
+ }
268
+ catch (cause) {
269
+ throw new errors_js_1.InvalidMidnightApiResponseError(`Midnight API takeable offer market_id "${takeableOffer.market_id}" could not be mapped or validated against its embedded offer market.`, { cause });
270
+ }
271
+ if (!matchesAdvertisedId) {
230
272
  throw new errors_js_1.InvalidMidnightApiResponseError(`Midnight API takeable offer market_id "${take.marketId}" does not match embedded offer market "${embeddedMarketId}".`);
231
273
  }
274
+ const { maxUnits, maxAssets, buy, maker, receiverIfMakerIsSeller } = take.offer;
275
+ if (!(0, viem_1.isAddress)(receiverIfMakerIsSeller)) {
276
+ throw new errors_js_1.InvalidMidnightApiResponseError(`Midnight API takeable offer receiverIfMakerIsSeller "${receiverIfMakerIsSeller}" is not an address.`);
277
+ }
278
+ try {
279
+ // Return values unused: called only to enforce the cap-shape and buy-receiver invariants.
280
+ index_js_2.OfferUtils.validateOfferCaps({ maxUnits, maxAssets });
281
+ index_js_2.OfferUtils.resolveReceiverIfMakerIsSeller({
282
+ buy,
283
+ maker,
284
+ receiverIfMakerIsSeller,
285
+ });
286
+ }
287
+ catch (cause) {
288
+ if (!(cause instanceof errors_js_1.InvalidOfferParameterError))
289
+ throw cause;
290
+ throw new errors_js_1.InvalidMidnightApiResponseError(`Midnight API takeable offer for market_id "${take.marketId}" is not executable: ${cause.message}`, { cause });
291
+ }
232
292
  if (context.marketId != null &&
233
293
  !(0, morpho_ts_1.isHexEqual)(take.marketId, context.marketId)) {
234
294
  throw new errors_js_1.InvalidMidnightApiResponseError(`Midnight API takeable offer market_id "${take.marketId}" does not match requested market "${context.marketId}".`);
@@ -1,2 +1,2 @@
1
- export { InvalidMidnightApiResponseError, MidnightApiError, } from "../errors.js";
1
+ export { InvalidMidnightApiQuoteTargetError, InvalidMidnightApiResponseError, MidnightApiError, } from "../errors.js";
2
2
  export * from "./MidnightApi.js";
@@ -14,8 +14,9 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.MidnightApiError = exports.InvalidMidnightApiResponseError = void 0;
17
+ exports.MidnightApiError = exports.InvalidMidnightApiResponseError = exports.InvalidMidnightApiQuoteTargetError = void 0;
18
18
  var errors_js_1 = require("../errors.js");
19
+ Object.defineProperty(exports, "InvalidMidnightApiQuoteTargetError", { enumerable: true, get: function () { return errors_js_1.InvalidMidnightApiQuoteTargetError; } });
19
20
  Object.defineProperty(exports, "InvalidMidnightApiResponseError", { enumerable: true, get: function () { return errors_js_1.InvalidMidnightApiResponseError; } });
20
21
  Object.defineProperty(exports, "MidnightApiError", { enumerable: true, get: function () { return errors_js_1.MidnightApiError; } });
21
22
  __exportStar(require("./MidnightApi.js"), exports);
@@ -341,7 +341,7 @@ export interface MidnightApiBookMarket {
341
341
  readonly midnight: Address;
342
342
  /** Loan token address. */
343
343
  readonly loanToken: Address;
344
- /** Collateral definitions for the market. */
344
+ /** Collateral definitions for the market, in canonical `collateralIndex` order. */
345
345
  readonly collaterals: readonly MidnightApiCollateral[];
346
346
  /** Market maturity timestamp in unix seconds. */
347
347
  readonly maturity: number;
@@ -1,2 +1,2 @@
1
1
  /** @internal Installed Midnight SDK package version. */
2
- export declare const MIDNIGHT_SDK_VERSION = "1.6.0";
2
+ export declare const MIDNIGHT_SDK_VERSION = "1.7.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 = "1.6.0";
6
+ exports.MIDNIGHT_SDK_VERSION = "1.7.0";
@@ -339,3 +339,16 @@ export declare class MidnightApiError extends Error {
339
339
  export declare class InvalidMidnightApiResponseError extends Error {
340
340
  constructor(message: string, options?: ErrorOptions);
341
341
  }
342
+ /**
343
+ * Thrown when a Midnight API quote request does not target exactly one of `units` or `assets`.
344
+ *
345
+ * @example
346
+ * ```ts
347
+ * import { InvalidMidnightApiQuoteTargetError } from "@morpho-org/midnight-sdk/api";
348
+ *
349
+ * throw new InvalidMidnightApiQuoteTargetError();
350
+ * ```
351
+ */
352
+ export declare class InvalidMidnightApiQuoteTargetError extends Error {
353
+ constructor(options?: ErrorOptions);
354
+ }
package/lib/cjs/errors.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.InvalidMidnightApiResponseError = exports.MidnightApiError = exports.InvalidEcrecoverSignatureVError = exports.InvalidTypedDataSignatureError = exports.MidnightMempoolValidationError = exports.ChainIdMismatchError = exports.InvalidTreeError = exports.InvalidTreeHeightError = exports.PayloadDecodeError = exports.InvalidOfferParameterError = exports.UnknownCollateralIndexError = exports.InvalidMarketParameterError = exports.InvalidPositionAccrualStateError = exports.InvalidPositionLossFactorError = exports.InvalidPositionAccrualTimestampError = exports.SettlementFeeExceedsPriceError = exports.InvalidTickSpacingError = exports.PriceGreaterThanOneError = exports.TickOutOfRangeError = exports.InvalidOfferGroupError = void 0;
3
+ exports.InvalidMidnightApiQuoteTargetError = exports.InvalidMidnightApiResponseError = exports.MidnightApiError = exports.InvalidEcrecoverSignatureVError = exports.InvalidTypedDataSignatureError = exports.MidnightMempoolValidationError = exports.ChainIdMismatchError = exports.InvalidTreeError = exports.InvalidTreeHeightError = exports.PayloadDecodeError = exports.InvalidOfferParameterError = exports.UnknownCollateralIndexError = exports.InvalidMarketParameterError = exports.InvalidPositionAccrualStateError = exports.InvalidPositionLossFactorError = exports.InvalidPositionAccrualTimestampError = exports.SettlementFeeExceedsPriceError = exports.InvalidTickSpacingError = exports.PriceGreaterThanOneError = exports.TickOutOfRangeError = exports.InvalidOfferGroupError = void 0;
4
4
  /**
5
5
  * Thrown when a Midnight offer group violates protocol-level group mechanics.
6
6
  *
@@ -418,3 +418,20 @@ class InvalidMidnightApiResponseError extends Error {
418
418
  }
419
419
  }
420
420
  exports.InvalidMidnightApiResponseError = InvalidMidnightApiResponseError;
421
+ /**
422
+ * Thrown when a Midnight API quote request does not target exactly one of `units` or `assets`.
423
+ *
424
+ * @example
425
+ * ```ts
426
+ * import { InvalidMidnightApiQuoteTargetError } from "@morpho-org/midnight-sdk/api";
427
+ *
428
+ * throw new InvalidMidnightApiQuoteTargetError();
429
+ * ```
430
+ */
431
+ class InvalidMidnightApiQuoteTargetError extends Error {
432
+ constructor(options) {
433
+ super("Midnight API quote requires exactly one of `units` or `assets`. Provide a single target amount.", options);
434
+ this.name = "InvalidMidnightApiQuoteTargetError";
435
+ }
436
+ }
437
+ exports.InvalidMidnightApiQuoteTargetError = InvalidMidnightApiQuoteTargetError;
@@ -292,11 +292,7 @@ export type MarketInput = IMarketParams | IMarket;
292
292
  * registerCustomAddresses({
293
293
  * addresses: {
294
294
  * 31337: {
295
- * morpho: "0x0000000000000000000000000000000000000001",
296
- * bundler3: {
297
- * bundler3: "0x0000000000000000000000000000000000000002",
298
- * generalAdapter1: "0x0000000000000000000000000000000000000003",
299
- * },
295
+ * blue: "0x0000000000000000000000000000000000000001",
300
296
  * adaptiveCurveIrm: "0x0000000000000000000000000000000000000004",
301
297
  * midnight: "0x0000000000000000000000000000000000001000",
302
298
  * },
@@ -412,11 +408,7 @@ export declare class Market {
412
408
  * registerCustomAddresses({
413
409
  * addresses: {
414
410
  * 31337: {
415
- * morpho: "0x0000000000000000000000000000000000000001",
416
- * bundler3: {
417
- * bundler3: "0x0000000000000000000000000000000000000002",
418
- * generalAdapter1: "0x0000000000000000000000000000000000000003",
419
- * },
411
+ * blue: "0x0000000000000000000000000000000000000001",
420
412
  * adaptiveCurveIrm: "0x0000000000000000000000000000000000000004",
421
413
  * midnight: "0x0000000000000000000000000000000000001000",
422
414
  * },
@@ -467,11 +459,7 @@ export declare class Market {
467
459
  * registerCustomAddresses({
468
460
  * addresses: {
469
461
  * 31337: {
470
- * morpho: "0x0000000000000000000000000000000000000001",
471
- * bundler3: {
472
- * bundler3: "0x0000000000000000000000000000000000000002",
473
- * generalAdapter1: "0x0000000000000000000000000000000000000003",
474
- * },
462
+ * blue: "0x0000000000000000000000000000000000000001",
475
463
  * adaptiveCurveIrm: "0x0000000000000000000000000000000000000004",
476
464
  * midnight: "0x0000000000000000000000000000000000001000",
477
465
  * },
@@ -522,11 +510,7 @@ export declare class Market {
522
510
  * registerCustomAddresses({
523
511
  * addresses: {
524
512
  * 31337: {
525
- * morpho: "0x0000000000000000000000000000000000000001",
526
- * bundler3: {
527
- * bundler3: "0x0000000000000000000000000000000000000002",
528
- * generalAdapter1: "0x0000000000000000000000000000000000000003",
529
- * },
513
+ * blue: "0x0000000000000000000000000000000000000001",
530
514
  * adaptiveCurveIrm: "0x0000000000000000000000000000000000000004",
531
515
  * midnight: "0x0000000000000000000000000000000000001000",
532
516
  * },
@@ -577,11 +561,7 @@ export declare class Market {
577
561
  * registerCustomAddresses({
578
562
  * addresses: {
579
563
  * 31337: {
580
- * morpho: "0x0000000000000000000000000000000000000001",
581
- * bundler3: {
582
- * bundler3: "0x0000000000000000000000000000000000000002",
583
- * generalAdapter1: "0x0000000000000000000000000000000000000003",
584
- * },
564
+ * blue: "0x0000000000000000000000000000000000000001",
585
565
  * adaptiveCurveIrm: "0x0000000000000000000000000000000000000004",
586
566
  * midnight: "0x0000000000000000000000000000000000001000",
587
567
  * },
@@ -633,11 +613,7 @@ export declare class Market {
633
613
  * registerCustomAddresses({
634
614
  * addresses: {
635
615
  * 31337: {
636
- * morpho: "0x0000000000000000000000000000000000000001",
637
- * bundler3: {
638
- * bundler3: "0x0000000000000000000000000000000000000002",
639
- * generalAdapter1: "0x0000000000000000000000000000000000000003",
640
- * },
616
+ * blue: "0x0000000000000000000000000000000000000001",
641
617
  * adaptiveCurveIrm: "0x0000000000000000000000000000000000000004",
642
618
  * midnight: "0x0000000000000000000000000000000000001000",
643
619
  * },