@morpho-org/midnight-sdk 0.1.0 → 1.0.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.
- package/LICENSE +21 -0
- package/README.md +56 -46
- package/lib/cjs/abis.d.ts +1185 -996
- package/lib/cjs/abis.js +1445 -1211
- package/lib/cjs/api/MidnightApi.d.ts +22 -16
- package/lib/cjs/api/MidnightApi.js +22 -16
- package/lib/cjs/api/helpers.js +6 -3
- package/lib/cjs/api/types.d.ts +35 -9
- package/lib/cjs/constants.d.ts +12 -11
- package/lib/cjs/constants.js +14 -12
- package/lib/cjs/errors.d.ts +74 -1
- package/lib/cjs/errors.js +94 -3
- package/lib/cjs/fetch/Market.js +0 -1
- package/lib/cjs/fetch/index.d.ts +0 -1
- package/lib/cjs/fetch/index.js +0 -1
- package/lib/cjs/index.d.ts +1 -1
- package/lib/cjs/index.js +2 -23
- package/lib/cjs/market/Market.d.ts +99 -33
- package/lib/cjs/market/Market.js +137 -28
- package/lib/cjs/market/MarketUtils.d.ts +61 -41
- package/lib/cjs/market/MarketUtils.js +108 -48
- package/lib/cjs/market/Position.d.ts +16 -11
- package/lib/cjs/market/Position.js +18 -12
- package/lib/cjs/market/PositionUtils.d.ts +6 -4
- package/lib/cjs/market/PositionUtils.js +9 -6
- package/lib/cjs/math/TickLib.d.ts +22 -0
- package/lib/cjs/math/TickLib.js +30 -0
- package/lib/cjs/math/index.d.ts +0 -1
- package/lib/cjs/math/index.js +0 -1
- package/lib/cjs/offers/Offer.d.ts +217 -11
- package/lib/cjs/offers/Offer.js +215 -7
- package/lib/cjs/offers/OfferUtils.d.ts +245 -139
- package/lib/cjs/offers/OfferUtils.js +304 -36
- package/lib/cjs/queries/GetPosition.d.ts +1 -1
- package/lib/cjs/queries/GetPosition.js +1 -1
- package/lib/cjs/signatures/EcrecoverRatifierUtils.d.ts +66 -38
- package/lib/cjs/signatures/EcrecoverRatifierUtils.js +147 -79
- package/lib/cjs/signatures/Group.d.ts +12 -4
- package/lib/cjs/signatures/Group.js +12 -4
- package/lib/cjs/signatures/GroupUtils.d.ts +12 -4
- package/lib/cjs/signatures/GroupUtils.js +6 -2
- package/lib/cjs/signatures/Payload.d.ts +277 -277
- package/lib/cjs/signatures/Payload.js +517 -534
- package/lib/cjs/signatures/RatifierUtils.d.ts +57 -0
- package/lib/cjs/signatures/RatifierUtils.js +94 -0
- package/lib/cjs/signatures/SetterRatifierUtils.d.ts +21 -13
- package/lib/cjs/signatures/SetterRatifierUtils.js +25 -20
- package/lib/cjs/signatures/Tree.d.ts +28 -16
- package/lib/cjs/signatures/Tree.js +25 -13
- package/lib/cjs/signatures/TreeUtils.d.ts +181 -62
- package/lib/cjs/signatures/TreeUtils.js +73 -76
- package/lib/cjs/signatures/index.d.ts +1 -0
- package/lib/cjs/signatures/index.js +3 -0
- package/lib/cjs/signatures/offerStructInternal.d.ts +14 -0
- package/lib/cjs/signatures/offerStructInternal.js +72 -0
- package/lib/esm/abis.d.ts +1185 -996
- package/lib/esm/abis.js +1445 -1211
- package/lib/esm/api/MidnightApi.d.ts +22 -16
- package/lib/esm/api/MidnightApi.js +23 -17
- package/lib/esm/api/helpers.js +6 -3
- package/lib/esm/api/types.d.ts +35 -9
- package/lib/esm/constants.d.ts +12 -11
- package/lib/esm/constants.js +13 -11
- package/lib/esm/errors.d.ts +74 -1
- package/lib/esm/errors.js +89 -2
- package/lib/esm/fetch/Market.js +0 -1
- package/lib/esm/fetch/index.d.ts +0 -1
- package/lib/esm/fetch/index.js +0 -1
- package/lib/esm/index.d.ts +1 -1
- package/lib/esm/index.js +1 -1
- package/lib/esm/market/Market.d.ts +99 -33
- package/lib/esm/market/Market.js +137 -28
- package/lib/esm/market/MarketUtils.d.ts +61 -41
- package/lib/esm/market/MarketUtils.js +109 -49
- package/lib/esm/market/Position.d.ts +16 -11
- package/lib/esm/market/Position.js +19 -13
- package/lib/esm/market/PositionUtils.d.ts +6 -4
- package/lib/esm/market/PositionUtils.js +9 -6
- package/lib/esm/math/TickLib.d.ts +22 -0
- package/lib/esm/math/TickLib.js +31 -1
- package/lib/esm/math/index.d.ts +0 -1
- package/lib/esm/math/index.js +0 -1
- package/lib/esm/offers/Offer.d.ts +217 -11
- package/lib/esm/offers/Offer.js +216 -8
- package/lib/esm/offers/OfferUtils.d.ts +245 -139
- package/lib/esm/offers/OfferUtils.js +306 -38
- package/lib/esm/queries/GetPosition.d.ts +1 -1
- package/lib/esm/queries/GetPosition.js +1 -1
- package/lib/esm/signatures/EcrecoverRatifierUtils.d.ts +66 -38
- package/lib/esm/signatures/EcrecoverRatifierUtils.js +149 -81
- package/lib/esm/signatures/Group.d.ts +12 -4
- package/lib/esm/signatures/Group.js +12 -4
- package/lib/esm/signatures/GroupUtils.d.ts +12 -4
- package/lib/esm/signatures/GroupUtils.js +6 -2
- package/lib/esm/signatures/Payload.d.ts +277 -277
- package/lib/esm/signatures/Payload.js +517 -531
- package/lib/esm/signatures/RatifierUtils.d.ts +57 -0
- package/lib/esm/signatures/RatifierUtils.js +94 -0
- package/lib/esm/signatures/SetterRatifierUtils.d.ts +21 -13
- package/lib/esm/signatures/SetterRatifierUtils.js +25 -20
- package/lib/esm/signatures/Tree.d.ts +28 -16
- package/lib/esm/signatures/Tree.js +25 -13
- package/lib/esm/signatures/TreeUtils.d.ts +181 -62
- package/lib/esm/signatures/TreeUtils.js +75 -78
- package/lib/esm/signatures/index.d.ts +1 -0
- package/lib/esm/signatures/index.js +1 -0
- package/lib/esm/signatures/offerStructInternal.d.ts +14 -0
- package/lib/esm/signatures/offerStructInternal.js +67 -0
- package/package.json +28 -32
- package/src/index.ts +1 -1
- package/lib/cjs/fetch/Offer.d.ts +0 -74
- package/lib/cjs/fetch/Offer.js +0 -119
- package/lib/cjs/math/ConsumableUnitsLib.d.ts +0 -57
- package/lib/cjs/math/ConsumableUnitsLib.js +0 -77
- package/lib/esm/fetch/Offer.d.ts +0 -74
- package/lib/esm/fetch/Offer.js +0 -116
- package/lib/esm/math/ConsumableUnitsLib.d.ts +0 -57
- package/lib/esm/math/ConsumableUnitsLib.js +0 -74
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { assertNonNegative, DivisionByZeroError, MathLib, } from "@morpho-org/morpho-ts";
|
|
1
2
|
import { encodeAbiParameters, keccak256, zeroAddress, zeroHash } from "viem";
|
|
2
|
-
import { DEFAULT_TICK_SPACING, MAX_CONTINUOUS_FEE, MAX_TICK, OFFER_TYPEHASH, } from "../constants.js";
|
|
3
|
+
import { DEFAULT_TICK_SPACING, MAX_CONTINUOUS_FEE, MAX_OFFER_CAP, MAX_TICK, OFFER_TYPEHASH, } from "../constants.js";
|
|
3
4
|
import { InvalidOfferGroupError, InvalidOfferParameterError, } from "../errors.js";
|
|
4
|
-
import { MarketUtils } from "../market/index.js";
|
|
5
|
+
import { Market, MarketParams, MarketUtils } from "../market/index.js";
|
|
6
|
+
import { TakeAmountsLib, TickLib } from "../math/index.js";
|
|
5
7
|
import { Offer, } from "./Offer.js";
|
|
6
8
|
const comparableHex = (value) => value.toLowerCase();
|
|
7
9
|
const offerHashParams = [
|
|
@@ -18,8 +20,8 @@ const offerHashParams = [
|
|
|
18
20
|
{ name: "receiverIfMakerIsSeller", type: "address" },
|
|
19
21
|
{ name: "ratifier", type: "address" },
|
|
20
22
|
{ name: "reduceOnly", type: "bool" },
|
|
21
|
-
{ name: "maxUnits", type: "
|
|
22
|
-
{ name: "maxAssets", type: "
|
|
23
|
+
{ name: "maxUnits", type: "uint128" },
|
|
24
|
+
{ name: "maxAssets", type: "uint128" },
|
|
23
25
|
{ name: "continuousFeeCap", type: "uint256" },
|
|
24
26
|
];
|
|
25
27
|
/**
|
|
@@ -56,12 +58,14 @@ export var OfferUtils;
|
|
|
56
58
|
*
|
|
57
59
|
* const offer = Offer.create({
|
|
58
60
|
* market: {
|
|
61
|
+
* chainId: 8453,
|
|
62
|
+
* midnight: "0x0000000000000000000000000000000000001000",
|
|
59
63
|
* loanToken: "0x0000000000000000000000000000000000006000",
|
|
60
64
|
* collateralParams: [
|
|
61
65
|
* {
|
|
62
66
|
* token: "0x0000000000000000000000000000000000007000",
|
|
63
67
|
* lltv: 770000000000000000n,
|
|
64
|
-
*
|
|
68
|
+
* liquidationCursor: 250000000000000000n,
|
|
65
69
|
* oracle: "0x0000000000000000000000000000000000008000",
|
|
66
70
|
* },
|
|
67
71
|
* ],
|
|
@@ -120,12 +124,14 @@ export var OfferUtils;
|
|
|
120
124
|
*
|
|
121
125
|
* const offer = Offer.create({
|
|
122
126
|
* market: {
|
|
127
|
+
* chainId: 8453,
|
|
128
|
+
* midnight: "0x0000000000000000000000000000000000001000",
|
|
123
129
|
* loanToken: "0x0000000000000000000000000000000000006000",
|
|
124
130
|
* collateralParams: [
|
|
125
131
|
* {
|
|
126
132
|
* token: "0x0000000000000000000000000000000000007000",
|
|
127
133
|
* lltv: 770000000000000000n,
|
|
128
|
-
*
|
|
134
|
+
* liquidationCursor: 250000000000000000n,
|
|
129
135
|
* oracle: "0x0000000000000000000000000000000000008000",
|
|
130
136
|
* },
|
|
131
137
|
* ],
|
|
@@ -183,12 +189,14 @@ export var OfferUtils;
|
|
|
183
189
|
*
|
|
184
190
|
* const offer = Offer.create({
|
|
185
191
|
* market: {
|
|
192
|
+
* chainId: 8453,
|
|
193
|
+
* midnight: "0x0000000000000000000000000000000000001000",
|
|
186
194
|
* loanToken: "0x0000000000000000000000000000000000006000",
|
|
187
195
|
* collateralParams: [
|
|
188
196
|
* {
|
|
189
197
|
* token: "0x0000000000000000000000000000000000007000",
|
|
190
198
|
* lltv: 770000000000000000n,
|
|
191
|
-
*
|
|
199
|
+
* liquidationCursor: 250000000000000000n,
|
|
192
200
|
* oracle: "0x0000000000000000000000000000000000008000",
|
|
193
201
|
* },
|
|
194
202
|
* ],
|
|
@@ -229,12 +237,14 @@ export var OfferUtils;
|
|
|
229
237
|
*
|
|
230
238
|
* const offer = Offer.create({
|
|
231
239
|
* market: {
|
|
240
|
+
* chainId: 8453,
|
|
241
|
+
* midnight: "0x0000000000000000000000000000000000001000",
|
|
232
242
|
* loanToken: "0x0000000000000000000000000000000000006000",
|
|
233
243
|
* collateralParams: [
|
|
234
244
|
* {
|
|
235
245
|
* token: "0x0000000000000000000000000000000000007000",
|
|
236
246
|
* lltv: 770000000000000000n,
|
|
237
|
-
*
|
|
247
|
+
* liquidationCursor: 250000000000000000n,
|
|
238
248
|
* oracle: "0x0000000000000000000000000000000000008000",
|
|
239
249
|
* },
|
|
240
250
|
* ],
|
|
@@ -312,7 +322,7 @@ export var OfferUtils;
|
|
|
312
322
|
* @param params.start - Optional offer start timestamp; defaults to zero.
|
|
313
323
|
* @param params.expiry - Offer expiry timestamp.
|
|
314
324
|
* @returns Normalized start and expiry timestamps.
|
|
315
|
-
* @throws {InvalidOfferParameterError} when the range is negative or
|
|
325
|
+
* @throws {InvalidOfferParameterError} when the range is negative or expiry is before start.
|
|
316
326
|
* @example
|
|
317
327
|
* ```ts
|
|
318
328
|
* import { OfferUtils } from "@morpho-org/midnight-sdk";
|
|
@@ -331,11 +341,11 @@ export var OfferUtils;
|
|
|
331
341
|
instruction: "Use a non-negative timestamp.",
|
|
332
342
|
});
|
|
333
343
|
}
|
|
334
|
-
if (expiry < 0n || expiry
|
|
344
|
+
if (expiry < 0n || expiry < start) {
|
|
335
345
|
throw new InvalidOfferParameterError({
|
|
336
346
|
parameter: "expiry",
|
|
337
347
|
value: expiry,
|
|
338
|
-
instruction: `Use an expiry greater than start "${start}".`,
|
|
348
|
+
instruction: `Use an expiry greater than or equal to start "${start}".`,
|
|
339
349
|
});
|
|
340
350
|
}
|
|
341
351
|
return { start, expiry };
|
|
@@ -376,6 +386,20 @@ export var OfferUtils;
|
|
|
376
386
|
instruction: "Use a non-negative cap.",
|
|
377
387
|
});
|
|
378
388
|
}
|
|
389
|
+
if (maxUnits > MAX_OFFER_CAP) {
|
|
390
|
+
throw new InvalidOfferParameterError({
|
|
391
|
+
parameter: "maxUnits",
|
|
392
|
+
value: maxUnits,
|
|
393
|
+
instruction: `Use a cap less than or equal to "${MAX_OFFER_CAP}".`,
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
if (maxAssets > MAX_OFFER_CAP) {
|
|
397
|
+
throw new InvalidOfferParameterError({
|
|
398
|
+
parameter: "maxAssets",
|
|
399
|
+
value: maxAssets,
|
|
400
|
+
instruction: `Use a cap less than or equal to "${MAX_OFFER_CAP}".`,
|
|
401
|
+
});
|
|
402
|
+
}
|
|
379
403
|
if ((maxAssets === 0n) === (maxUnits === 0n)) {
|
|
380
404
|
throw new InvalidOfferParameterError({
|
|
381
405
|
parameter: "maxUnits/maxAssets",
|
|
@@ -458,22 +482,16 @@ export var OfferUtils;
|
|
|
458
482
|
* instantiating an `Offer`. `Offer.create` uses the same validation and then
|
|
459
483
|
* constructs the class instance for grouping and trees.
|
|
460
484
|
*
|
|
461
|
-
* @param params.market - Market params or hydrated market this offer trades.
|
|
462
485
|
* @param params.buy - Whether the maker buys loan assets.
|
|
463
486
|
* @param params.maker - Maker address.
|
|
464
487
|
* @param params.tick - Offer tick.
|
|
465
|
-
* @param params.group - Optional consumption group id for already-grouped offers.
|
|
466
488
|
* @param params.tickSpacing - Optional market tick spacing; defaults to `DEFAULT_TICK_SPACING`.
|
|
467
489
|
* @param params.maxUnits - Optional unit cap; defaults to zero.
|
|
468
490
|
* @param params.maxAssets - Optional buyer or seller asset cap; defaults to zero.
|
|
469
491
|
* @param params.continuousFeeCap - Optional maximum market continuous fee accepted by this offer; defaults to `MAX_CONTINUOUS_FEE`.
|
|
470
492
|
* @param params.start - Optional offer start timestamp; defaults to zero.
|
|
471
493
|
* @param params.expiry - Offer expiry timestamp.
|
|
472
|
-
* @param params.callback - Optional callback address; defaults to the zero address.
|
|
473
|
-
* @param params.callbackData - Optional callback payload; defaults to `0x`.
|
|
474
494
|
* @param params.receiverIfMakerIsSeller - Optional receiver used when maker is seller.
|
|
475
|
-
* @param params.ratifier - Ratifier contract address.
|
|
476
|
-
* @param params.reduceOnly - Optional flag restricting the offer to exposure-reducing execution.
|
|
477
495
|
* @returns Normalized deterministic offer parameters.
|
|
478
496
|
* @throws {InvalidOfferParameterError} when a deterministic offer parameter cannot satisfy protocol rules.
|
|
479
497
|
* @example
|
|
@@ -481,26 +499,10 @@ export var OfferUtils;
|
|
|
481
499
|
* import { OfferUtils } from "@morpho-org/midnight-sdk";
|
|
482
500
|
*
|
|
483
501
|
* const params = OfferUtils.validateOfferParams({
|
|
484
|
-
* market: {
|
|
485
|
-
* loanToken: "0x0000000000000000000000000000000000006000",
|
|
486
|
-
* collateralParams: [
|
|
487
|
-
* {
|
|
488
|
-
* token: "0x0000000000000000000000000000000000007000",
|
|
489
|
-
* lltv: 770000000000000000n,
|
|
490
|
-
* maxLif: 1061007957559681697n,
|
|
491
|
-
* oracle: "0x0000000000000000000000000000000000008000",
|
|
492
|
-
* },
|
|
493
|
-
* ],
|
|
494
|
-
* maturity: 54_000n,
|
|
495
|
-
* rcfThreshold: 0n,
|
|
496
|
-
* enterGate: "0x0000000000000000000000000000000000000000",
|
|
497
|
-
* liquidatorGate: "0x0000000000000000000000000000000000000000",
|
|
498
|
-
* },
|
|
499
502
|
* buy: true,
|
|
500
503
|
* maker: "0x0000000000000000000000000000000000009000",
|
|
501
504
|
* tick: 5_000n,
|
|
502
505
|
* expiry: 3_600n,
|
|
503
|
-
* ratifier: "0x0000000000000000000000000000000000004000",
|
|
504
506
|
* maxUnits: 100n,
|
|
505
507
|
* });
|
|
506
508
|
* console.log(params.maxAssets);
|
|
@@ -543,12 +545,14 @@ export var OfferUtils;
|
|
|
543
545
|
*
|
|
544
546
|
* const offer = Offer.create({
|
|
545
547
|
* market: {
|
|
548
|
+
* chainId: 8453,
|
|
549
|
+
* midnight: "0x0000000000000000000000000000000000001000",
|
|
546
550
|
* loanToken: "0x0000000000000000000000000000000000006000",
|
|
547
551
|
* collateralParams: [
|
|
548
552
|
* {
|
|
549
553
|
* token: "0x0000000000000000000000000000000000007000",
|
|
550
554
|
* lltv: 770000000000000000n,
|
|
551
|
-
*
|
|
555
|
+
* liquidationCursor: 250000000000000000n,
|
|
552
556
|
* oracle: "0x0000000000000000000000000000000000008000",
|
|
553
557
|
* },
|
|
554
558
|
* ],
|
|
@@ -577,7 +581,7 @@ export var OfferUtils;
|
|
|
577
581
|
const first = offers[0];
|
|
578
582
|
const expectedMaker = comparableHex(first.maker);
|
|
579
583
|
const expectedBuy = first.buy;
|
|
580
|
-
const expectedLoanToken = comparableHex(first.market.loanToken);
|
|
584
|
+
const expectedLoanToken = comparableHex(MarketParams.from(first.market).loanToken);
|
|
581
585
|
const expectedMaxUnits = first.maxUnits;
|
|
582
586
|
const expectedMaxAssets = first.maxAssets;
|
|
583
587
|
for (const offer of offers) {
|
|
@@ -588,11 +592,14 @@ export var OfferUtils;
|
|
|
588
592
|
throw new InvalidOfferGroupError("All offers in a group must use the same maker side.");
|
|
589
593
|
}
|
|
590
594
|
if (offer.maxUnits < 0n ||
|
|
595
|
+
offer.maxUnits > MAX_OFFER_CAP ||
|
|
591
596
|
offer.maxAssets < 0n ||
|
|
597
|
+
offer.maxAssets > MAX_OFFER_CAP ||
|
|
592
598
|
(offer.maxAssets === 0n) === (offer.maxUnits === 0n)) {
|
|
593
|
-
throw new InvalidOfferGroupError("Every offer must set exactly one non-zero
|
|
599
|
+
throw new InvalidOfferGroupError("Every offer must set exactly one non-zero uint128 cap.");
|
|
594
600
|
}
|
|
595
|
-
if (comparableHex(offer.market.loanToken) !==
|
|
601
|
+
if (comparableHex(MarketParams.from(offer.market).loanToken) !==
|
|
602
|
+
expectedLoanToken) {
|
|
596
603
|
throw new InvalidOfferGroupError("All offers in a group must use the same loan token.");
|
|
597
604
|
}
|
|
598
605
|
if (offer.maxUnits !== expectedMaxUnits ||
|
|
@@ -608,6 +615,265 @@ export var OfferUtils;
|
|
|
608
615
|
return [...offers];
|
|
609
616
|
}
|
|
610
617
|
OfferUtils.validateOfferGroup = validateOfferGroup;
|
|
618
|
+
/**
|
|
619
|
+
* Converts an offer tick into its WAD zero-coupon price.
|
|
620
|
+
*
|
|
621
|
+
* Use for display or local quote checks when accepting any plain object
|
|
622
|
+
* matching `IOffer` or an `Offer` instance.
|
|
623
|
+
*
|
|
624
|
+
* @param offer - Offer to inspect.
|
|
625
|
+
* @returns WAD price rounded to the protocol price quantum.
|
|
626
|
+
* @throws {NegativeValueError} when `offer.tick` is negative.
|
|
627
|
+
* @throws {TickOutOfRangeError} when `offer.tick` exceeds `MAX_TICK`.
|
|
628
|
+
* @example
|
|
629
|
+
* ```ts
|
|
630
|
+
* import { OfferUtils } from "@morpho-org/midnight-sdk";
|
|
631
|
+
*
|
|
632
|
+
* const price = OfferUtils.getPrice({ tick: 5_000n });
|
|
633
|
+
* console.log(price);
|
|
634
|
+
* ```
|
|
635
|
+
*/
|
|
636
|
+
function getPrice(offer) {
|
|
637
|
+
return TickLib.tickToPrice(offer.tick);
|
|
638
|
+
}
|
|
639
|
+
OfferUtils.getPrice = getPrice;
|
|
640
|
+
/**
|
|
641
|
+
* Converts an offer tick into a WAD per-second simple rate at a timestamp.
|
|
642
|
+
*
|
|
643
|
+
* The rate is the offer's fixed period rate divided by the market's remaining
|
|
644
|
+
* time to maturity at `timestamp`, rounded up.
|
|
645
|
+
*
|
|
646
|
+
* @param params.offer - Offer to inspect.
|
|
647
|
+
* @param params.timestamp - Timestamp at which the rate is calculated.
|
|
648
|
+
* @returns WAD per-second simple rate rounded up.
|
|
649
|
+
* @throws {NegativeValueError} when `market.maturity`, `timestamp`, or `tick` is negative.
|
|
650
|
+
* @throws {TickOutOfRangeError} when `tick` exceeds `MAX_TICK`.
|
|
651
|
+
* @throws {DivisionByZeroError} when the tick price is zero or `timestamp` is at or after maturity.
|
|
652
|
+
* @example
|
|
653
|
+
* ```ts
|
|
654
|
+
* import { Offer, OfferUtils } from "@morpho-org/midnight-sdk";
|
|
655
|
+
*
|
|
656
|
+
* const offer = Offer.from({
|
|
657
|
+
* market: {
|
|
658
|
+
* loanToken: "0x0000000000000000000000000000000000006000",
|
|
659
|
+
* collateralParams: [
|
|
660
|
+
* {
|
|
661
|
+
* token: "0x0000000000000000000000000000000000007000",
|
|
662
|
+
* lltv: 770000000000000000n,
|
|
663
|
+
* liquidationCursor: 250000000000000000n,
|
|
664
|
+
* oracle: "0x0000000000000000000000000000000000008000",
|
|
665
|
+
* },
|
|
666
|
+
* ],
|
|
667
|
+
* maturity: 54_000n,
|
|
668
|
+
* rcfThreshold: 0n,
|
|
669
|
+
* enterGate: "0x0000000000000000000000000000000000000000",
|
|
670
|
+
* liquidatorGate: "0x0000000000000000000000000000000000000000",
|
|
671
|
+
* },
|
|
672
|
+
* buy: true,
|
|
673
|
+
* maker: "0x0000000000000000000000000000000000009000",
|
|
674
|
+
* start: 0n,
|
|
675
|
+
* expiry: 3_600n,
|
|
676
|
+
* tick: 5_000n,
|
|
677
|
+
* callback: "0x0000000000000000000000000000000000000000",
|
|
678
|
+
* callbackData: "0x",
|
|
679
|
+
* receiverIfMakerIsSeller: "0x0000000000000000000000000000000000000000",
|
|
680
|
+
* ratifier: "0x0000000000000000000000000000000000004000",
|
|
681
|
+
* reduceOnly: false,
|
|
682
|
+
* maxUnits: 100n,
|
|
683
|
+
* maxAssets: 0n,
|
|
684
|
+
* continuousFeeCap: 317097919n,
|
|
685
|
+
* });
|
|
686
|
+
* const rate = OfferUtils.getRate({ offer, timestamp: 1_000n });
|
|
687
|
+
* console.log(rate);
|
|
688
|
+
* ```
|
|
689
|
+
*/
|
|
690
|
+
function getRate(params) {
|
|
691
|
+
const market = MarketParams.from(params.offer.market);
|
|
692
|
+
const timestamp = BigInt(params.timestamp);
|
|
693
|
+
assertNonNegative("market.maturity", market.maturity);
|
|
694
|
+
assertNonNegative("timestamp", timestamp);
|
|
695
|
+
const timeToMaturity = MathLib.zeroFloorSub(market.maturity, timestamp);
|
|
696
|
+
if (timeToMaturity === 0n) {
|
|
697
|
+
throw new DivisionByZeroError("timeToMaturity");
|
|
698
|
+
}
|
|
699
|
+
return MathLib.mulDiv(TickLib.tickToRate(params.offer.tick), 1n, timeToMaturity, "Up");
|
|
700
|
+
}
|
|
701
|
+
OfferUtils.getRate = getRate;
|
|
702
|
+
/**
|
|
703
|
+
* Converts an offer tick into a WAD simple annual percentage rate at a timestamp.
|
|
704
|
+
*
|
|
705
|
+
* It computes time to maturity from the offer market and delegates the final
|
|
706
|
+
* tick annualization to `TickLib.tickToApr`.
|
|
707
|
+
*
|
|
708
|
+
* @param params.offer - Offer to inspect.
|
|
709
|
+
* @param params.timestamp - Timestamp at which the APR is calculated.
|
|
710
|
+
* @returns WAD simple APR rounded up.
|
|
711
|
+
* @throws {NegativeValueError} when `market.maturity`, `timestamp`, or `tick` is negative.
|
|
712
|
+
* @throws {TickOutOfRangeError} when `tick` exceeds `MAX_TICK`.
|
|
713
|
+
* @throws {DivisionByZeroError} when the tick price is zero or `timestamp` is at or after maturity.
|
|
714
|
+
* @example
|
|
715
|
+
* ```ts
|
|
716
|
+
* import { Offer, OfferUtils } from "@morpho-org/midnight-sdk";
|
|
717
|
+
*
|
|
718
|
+
* const offer = Offer.from({
|
|
719
|
+
* market: {
|
|
720
|
+
* loanToken: "0x0000000000000000000000000000000000006000",
|
|
721
|
+
* collateralParams: [
|
|
722
|
+
* {
|
|
723
|
+
* token: "0x0000000000000000000000000000000000007000",
|
|
724
|
+
* lltv: 770000000000000000n,
|
|
725
|
+
* liquidationCursor: 250000000000000000n,
|
|
726
|
+
* oracle: "0x0000000000000000000000000000000000008000",
|
|
727
|
+
* },
|
|
728
|
+
* ],
|
|
729
|
+
* maturity: 54_000n,
|
|
730
|
+
* rcfThreshold: 0n,
|
|
731
|
+
* enterGate: "0x0000000000000000000000000000000000000000",
|
|
732
|
+
* liquidatorGate: "0x0000000000000000000000000000000000000000",
|
|
733
|
+
* },
|
|
734
|
+
* buy: true,
|
|
735
|
+
* maker: "0x0000000000000000000000000000000000009000",
|
|
736
|
+
* start: 0n,
|
|
737
|
+
* expiry: 3_600n,
|
|
738
|
+
* tick: 5_000n,
|
|
739
|
+
* callback: "0x0000000000000000000000000000000000000000",
|
|
740
|
+
* callbackData: "0x",
|
|
741
|
+
* receiverIfMakerIsSeller: "0x0000000000000000000000000000000000000000",
|
|
742
|
+
* ratifier: "0x0000000000000000000000000000000000004000",
|
|
743
|
+
* reduceOnly: false,
|
|
744
|
+
* maxUnits: 100n,
|
|
745
|
+
* maxAssets: 0n,
|
|
746
|
+
* continuousFeeCap: 317097919n,
|
|
747
|
+
* });
|
|
748
|
+
* const apr = OfferUtils.getApr({ offer, timestamp: 1_000n });
|
|
749
|
+
* console.log(apr);
|
|
750
|
+
* ```
|
|
751
|
+
*/
|
|
752
|
+
function getApr(params) {
|
|
753
|
+
const market = MarketParams.from(params.offer.market);
|
|
754
|
+
const timestamp = BigInt(params.timestamp);
|
|
755
|
+
assertNonNegative("market.maturity", market.maturity);
|
|
756
|
+
assertNonNegative("timestamp", timestamp);
|
|
757
|
+
return TickLib.tickToApr(params.offer.tick, MathLib.zeroFloorSub(market.maturity, timestamp));
|
|
758
|
+
}
|
|
759
|
+
OfferUtils.getApr = getApr;
|
|
760
|
+
/**
|
|
761
|
+
* Returns remaining units accepted by an offer's cap at a timestamp.
|
|
762
|
+
*
|
|
763
|
+
* The offer must carry a hydrated {@link Market} so the current market
|
|
764
|
+
* continuous fee and settlement-fee buckets are available locally. Fetch the
|
|
765
|
+
* current `consumed(maker, group)` value separately and pass it as input.
|
|
766
|
+
*
|
|
767
|
+
* @param params.offer - Offer to inspect. Its market must be hydrated.
|
|
768
|
+
* @param params.consumed - Amount already consumed from the offer group.
|
|
769
|
+
* @param params.timestamp - Timestamp used to compute market time to maturity.
|
|
770
|
+
* @returns Remaining consumable units accepted by Midnight `take`.
|
|
771
|
+
* @throws {InvalidOfferParameterError} when the offer does not carry hydrated market state or has invalid caps.
|
|
772
|
+
* @throws {NegativeValueError} when `consumed`, `timestamp`, offer limits, or delegated math inputs are negative.
|
|
773
|
+
* @throws {TickOutOfRangeError} when `tick` exceeds `MAX_TICK`.
|
|
774
|
+
* @throws {SettlementFeeExceedsPriceError} when settlement fee exceeds a buy-offer price.
|
|
775
|
+
* @example
|
|
776
|
+
* ```ts
|
|
777
|
+
* import { OfferUtils, midnightAbi } from "@morpho-org/midnight-sdk";
|
|
778
|
+
* import { createPublicClient, http } from "viem";
|
|
779
|
+
* import { base } from "viem/chains";
|
|
780
|
+
* import { readContract } from "viem/actions";
|
|
781
|
+
*
|
|
782
|
+
* const client = createPublicClient({ chain: base, transport: http() });
|
|
783
|
+
* const offer = {
|
|
784
|
+
* market: {
|
|
785
|
+
* params: {
|
|
786
|
+
* chainId: 8453,
|
|
787
|
+
* midnight: "0x0000000000000000000000000000000000001000",
|
|
788
|
+
* loanToken: "0x0000000000000000000000000000000000006000",
|
|
789
|
+
* collateralParams: [
|
|
790
|
+
* {
|
|
791
|
+
* token: "0x0000000000000000000000000000000000007000",
|
|
792
|
+
* lltv: 770000000000000000n,
|
|
793
|
+
* liquidationCursor: 250000000000000000n,
|
|
794
|
+
* oracle: "0x0000000000000000000000000000000000008000",
|
|
795
|
+
* },
|
|
796
|
+
* ],
|
|
797
|
+
* maturity: 54_000n,
|
|
798
|
+
* rcfThreshold: 0n,
|
|
799
|
+
* enterGate: "0x0000000000000000000000000000000000000000",
|
|
800
|
+
* liquidatorGate: "0x0000000000000000000000000000000000000000",
|
|
801
|
+
* },
|
|
802
|
+
* totalUnits: 1_000n,
|
|
803
|
+
* lossFactor: 0n,
|
|
804
|
+
* withdrawable: 500n,
|
|
805
|
+
* continuousFeeCredit: 0n,
|
|
806
|
+
* settlementFeeCbps: [1, 2, 3, 4, 5, 6, 7],
|
|
807
|
+
* continuousFee: 10,
|
|
808
|
+
* tickSpacing: 4,
|
|
809
|
+
* },
|
|
810
|
+
* buy: true,
|
|
811
|
+
* maker: "0x0000000000000000000000000000000000009000",
|
|
812
|
+
* start: 0n,
|
|
813
|
+
* expiry: 3_600n,
|
|
814
|
+
* tick: 5_000n,
|
|
815
|
+
* callback: "0x0000000000000000000000000000000000000000",
|
|
816
|
+
* callbackData: "0x",
|
|
817
|
+
* receiverIfMakerIsSeller: "0x0000000000000000000000000000000000000000",
|
|
818
|
+
* ratifier: "0x0000000000000000000000000000000000004000",
|
|
819
|
+
* reduceOnly: false,
|
|
820
|
+
* maxUnits: 100n,
|
|
821
|
+
* maxAssets: 0n,
|
|
822
|
+
* continuousFeeCap: 317097919n,
|
|
823
|
+
* } as const;
|
|
824
|
+
* const consumed = await readContract(client, {
|
|
825
|
+
* address: "0x0000000000000000000000000000000000001000",
|
|
826
|
+
* abi: midnightAbi,
|
|
827
|
+
* functionName: "consumed",
|
|
828
|
+
* args: [offer.maker, "0x1111111111111111111111111111111111111111111111111111111111111111"],
|
|
829
|
+
* });
|
|
830
|
+
* const units = OfferUtils.getConsumableUnits({ offer, consumed, timestamp: 1_000n });
|
|
831
|
+
* console.log(units);
|
|
832
|
+
* ```
|
|
833
|
+
*/
|
|
834
|
+
function getConsumableUnits(params) {
|
|
835
|
+
const offer = params.offer;
|
|
836
|
+
const consumed = BigInt(params.consumed);
|
|
837
|
+
const maxUnits = BigInt(offer.maxUnits);
|
|
838
|
+
const maxAssets = BigInt(offer.maxAssets);
|
|
839
|
+
const continuousFeeCap = BigInt(offer.continuousFeeCap);
|
|
840
|
+
assertNonNegative("consumed", consumed);
|
|
841
|
+
assertNonNegative("offer.maxUnits", maxUnits);
|
|
842
|
+
assertNonNegative("offer.maxAssets", maxAssets);
|
|
843
|
+
assertNonNegative("offer.continuousFeeCap", continuousFeeCap);
|
|
844
|
+
validateOfferCaps({ maxUnits, maxAssets });
|
|
845
|
+
if (!("params" in offer.market)) {
|
|
846
|
+
throw new InvalidOfferParameterError({
|
|
847
|
+
parameter: "market",
|
|
848
|
+
value: offer.market,
|
|
849
|
+
instruction: "Provide a hydrated Market with continuous fee and settlement fee buckets.",
|
|
850
|
+
});
|
|
851
|
+
}
|
|
852
|
+
const market = Market.from(offer.market);
|
|
853
|
+
if (continuousFeeCap < BigInt(market.continuousFee))
|
|
854
|
+
return 0n;
|
|
855
|
+
if (maxUnits > 0n)
|
|
856
|
+
return MathLib.zeroFloorSub(maxUnits, consumed);
|
|
857
|
+
const remainingAssets = MathLib.zeroFloorSub(maxAssets, consumed);
|
|
858
|
+
const settlementFee = market.getSettlementFee(market.timeToMaturity(params.timestamp));
|
|
859
|
+
if (!offer.buy) {
|
|
860
|
+
const { sellerPrice } = TakeAmountsLib.prices({
|
|
861
|
+
offer,
|
|
862
|
+
settlementFee,
|
|
863
|
+
});
|
|
864
|
+
if (sellerPrice === 0n)
|
|
865
|
+
return MathLib.MAX_UINT_256;
|
|
866
|
+
return MathLib.mulDivDown(remainingAssets, MathLib.WAD, sellerPrice);
|
|
867
|
+
}
|
|
868
|
+
const { buyerPrice } = TakeAmountsLib.prices({
|
|
869
|
+
offer,
|
|
870
|
+
settlementFee,
|
|
871
|
+
});
|
|
872
|
+
if (buyerPrice === 0n)
|
|
873
|
+
return MathLib.MAX_UINT_256;
|
|
874
|
+
return ((remainingAssets + 1n) * MathLib.WAD - 1n) / buyerPrice;
|
|
875
|
+
}
|
|
876
|
+
OfferUtils.getConsumableUnits = getConsumableUnits;
|
|
611
877
|
/**
|
|
612
878
|
* Returns an offer expiry timestamp.
|
|
613
879
|
*
|
|
@@ -624,12 +890,14 @@ export var OfferUtils;
|
|
|
624
890
|
*
|
|
625
891
|
* const offer = Offer.create({
|
|
626
892
|
* market: {
|
|
893
|
+
* chainId: 8453,
|
|
894
|
+
* midnight: "0x0000000000000000000000000000000000001000",
|
|
627
895
|
* loanToken: "0x0000000000000000000000000000000000006000",
|
|
628
896
|
* collateralParams: [
|
|
629
897
|
* {
|
|
630
898
|
* token: "0x0000000000000000000000000000000000007000",
|
|
631
899
|
* lltv: 770000000000000000n,
|
|
632
|
-
*
|
|
900
|
+
* liquidationCursor: 250000000000000000n,
|
|
633
901
|
* oracle: "0x0000000000000000000000000000000000008000",
|
|
634
902
|
* },
|
|
635
903
|
* ],
|
|
@@ -52,4 +52,4 @@ export declare const abi: readonly [{
|
|
|
52
52
|
readonly type: "function";
|
|
53
53
|
}];
|
|
54
54
|
/** @internal Deployless `GetPosition` query bytecode. */
|
|
55
|
-
export declare const code = "
|
|
55
|
+
export declare const code = "0x60808060405234601557610362908161001a8239f35b5f80fdfe6080806040526004361015610012575f80fd5b5f3560e01c63d8f172c414610025575f80fd5b346101b85760603660031901126101b8576004356001600160a01b03811691908290036101b857602435906044356001600160a01b038116908190036101b85760e0820182811067ffffffffffffffff8211176102e2576040525f825260208201925f845260408301925f8452606081015f8152608082015f815260a08301915f835260c0840196611000604051906100be81836102f6565b36823788526040516349e2903160e11b8152600481018790526024810188905260c0816044818e5afa9081156101c4575f905f925f91885f925f925f91610243575b506001600160801b039081169091529081168852908116865290811684529182168b521685525f5b60808110156101cf5760405163ecdcc72d60e01b8152600481018890526024810189905260448101829052906020826064818f5afa80156101c4575f90610187575b600192506001600160801b038b519116908260051b015201610128565b506020823d82116101bc575b816101a0602093836102f6565b810103126101b8576101b3600192610318565b61016a565b5f80fd5b3d9150610193565b6040513d5f823e3d90fd5b506001600160801b039283899593818094818e816040519c51168c52511660208b0152511660408901525116606087015251166080850152511660a08301525160c082015f905b60808210610224576110c084f35b6020806001926001600160801b03865116815201930191019091610216565b965050505050505060c0813d60c0116102da575b8161026460c093836102f6565b810103126101b857806001600160801b0361027f8193610318565b918161028d60208301610318565b938161029b60408501610318565b93816102a960608301610318565b938d826102c460a06102bd60808801610318565b9601610318565b929a989694929550509497509450509396610100565b3d9150610257565b634e487b7160e01b5f52604160045260245ffd5b90601f8019910116810190811067ffffffffffffffff8211176102e257604052565b51906001600160801b03821682036101b85756fea264697066735822122048ab3e1a986178f7e3c65d73416611318a31ef34d18800cb6a1f1ba4dad746b364736f6c63430008230033";
|
|
@@ -68,4 +68,4 @@ export const abi = [
|
|
|
68
68
|
},
|
|
69
69
|
];
|
|
70
70
|
/** @internal Deployless `GetPosition` query bytecode. */
|
|
71
|
-
export const code = "
|
|
71
|
+
export const code = "0x60808060405234601557610362908161001a8239f35b5f80fdfe6080806040526004361015610012575f80fd5b5f3560e01c63d8f172c414610025575f80fd5b346101b85760603660031901126101b8576004356001600160a01b03811691908290036101b857602435906044356001600160a01b038116908190036101b85760e0820182811067ffffffffffffffff8211176102e2576040525f825260208201925f845260408301925f8452606081015f8152608082015f815260a08301915f835260c0840196611000604051906100be81836102f6565b36823788526040516349e2903160e11b8152600481018790526024810188905260c0816044818e5afa9081156101c4575f905f925f91885f925f925f91610243575b506001600160801b039081169091529081168852908116865290811684529182168b521685525f5b60808110156101cf5760405163ecdcc72d60e01b8152600481018890526024810189905260448101829052906020826064818f5afa80156101c4575f90610187575b600192506001600160801b038b519116908260051b015201610128565b506020823d82116101bc575b816101a0602093836102f6565b810103126101b8576101b3600192610318565b61016a565b5f80fd5b3d9150610193565b6040513d5f823e3d90fd5b506001600160801b039283899593818094818e816040519c51168c52511660208b0152511660408901525116606087015251166080850152511660a08301525160c082015f905b60808210610224576110c084f35b6020806001926001600160801b03865116815201930191019091610216565b965050505050505060c0813d60c0116102da575b8161026460c093836102f6565b810103126101b857806001600160801b0361027f8193610318565b918161028d60208301610318565b938161029b60408501610318565b93816102a960608301610318565b938d826102c460a06102bd60808801610318565b9601610318565b929a989694929550509497509450509396610100565b3d9150610257565b634e487b7160e01b5f52604160045260245ffd5b90601f8019910116810190811067ffffffffffffffff8211176102e257604052565b51906001600160801b03821682036101b85756fea264697066735822122048ab3e1a986178f7e3c65d73416611318a31ef34d18800cb6a1f1ba4dad746b364736f6c63430008230033";
|