@morpho-dev/router 0.11.0 → 0.12.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/README.md +20 -5
- package/dist/cli.js +11700 -6794
- package/dist/drizzle/migrations/0034_chain-checkpoints.sql +1 -0
- package/dist/drizzle/migrations/0035_chain-tip-hash-cas.sql +1 -0
- package/dist/drizzle/migrations/0036_pending-links.sql +22 -0
- package/dist/drizzle/migrations/0037_chain-finalized-anchor.sql +2 -0
- package/dist/drizzle/migrations/0038_add-obligation-rcf-threshold.sql +2 -0
- package/dist/drizzle/migrations/0039_add-offers-composite-indexes.sql +2 -0
- package/dist/drizzle/migrations/0040_drop-redundant-offers-indexes.sql +2 -0
- package/dist/drizzle/migrations/0041_add-group-winner-expression-index.sql +10 -0
- package/dist/drizzle/migrations/0042_contract-sync-v1.14.sql +284 -0
- package/dist/drizzle/migrations/0043_add-obligation-side-tick-index.sql +1 -0
- package/dist/drizzle/migrations/0044_index-audit-cleanup.sql +27 -0
- package/dist/drizzle/migrations/0045_add-lots-offsets-availability-indexes.sql +5 -0
- package/dist/drizzle/migrations/0046_add-offers-active-tick-index.sql +1 -0
- package/dist/drizzle/migrations/0047_add-offers-book-winners-index.sql +1 -0
- package/dist/drizzle/migrations/0048_covering-indexes-for-winners-queries.sql +34 -0
- package/dist/drizzle/migrations/0049_contract-sync-v1.15.sql +305 -0
- package/dist/drizzle/migrations/meta/0036_snapshot.json +1864 -0
- package/dist/drizzle/migrations/meta/0037_snapshot.json +1876 -0
- package/dist/drizzle/migrations/meta/0038_snapshot.json +1882 -0
- package/dist/drizzle/migrations/meta/0039_snapshot.json +1960 -0
- package/dist/drizzle/migrations/meta/0040_snapshot.json +1912 -0
- package/dist/drizzle/migrations/meta/0041_snapshot.json +1912 -0
- package/dist/drizzle/migrations/meta/0042_snapshot.json +1882 -0
- package/dist/drizzle/migrations/meta/0043_snapshot.json +1909 -0
- package/dist/drizzle/migrations/meta/0044_snapshot.json +1853 -0
- package/dist/drizzle/migrations/meta/0045_snapshot.json +1921 -0
- package/dist/drizzle/migrations/meta/0046_snapshot.json +1966 -0
- package/dist/drizzle/migrations/meta/0047_snapshot.json +2005 -0
- package/dist/drizzle/migrations/meta/0048_snapshot.json +2035 -0
- package/dist/drizzle/migrations/meta/0049_snapshot.json +2035 -0
- package/dist/drizzle/migrations/meta/_journal.json +112 -0
- package/dist/evm/bytecode/morpho.txt +1 -1
- package/dist/index.browser.d.mts +587 -271
- package/dist/index.browser.d.mts.map +1 -1
- package/dist/index.browser.mjs +656 -419
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.node.d.mts +1454 -583
- package/dist/index.node.d.mts.map +1 -1
- package/dist/index.node.mjs +9064 -5228
- package/dist/index.node.mjs.map +1 -1
- package/dist/server-D4xxddev.js +9573 -0
- package/dist/server.js +9617 -0
- package/docs/integrator.md +14 -24
- package/package.json +7 -4
package/dist/index.browser.mjs
CHANGED
|
@@ -8,10 +8,10 @@ import createOpenApiFetchClient from "openapi-fetch";
|
|
|
8
8
|
import { bytesToHex, concatHex, decodeAbiParameters, encodeAbiParameters, getAddress, hashTypedData, hexToBytes, isAddress, isHex, keccak256, maxUint256, numberToHex, pad, parseAbi, publicActions, recoverAddress, zeroAddress } from "viem";
|
|
9
9
|
import { getBlockNumber, getLogs, multicall } from "viem/actions";
|
|
10
10
|
import { anvil, base, mainnet } from "viem/chains";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
11
|
+
import { SimpleMerkleTree } from "@openzeppelin/merkle-tree";
|
|
12
|
+
import { Inflate, gzip } from "pako";
|
|
13
13
|
import { context, propagation } from "@opentelemetry/api";
|
|
14
|
-
import "drizzle-orm";
|
|
14
|
+
import { sql } from "drizzle-orm";
|
|
15
15
|
import { bigint, boolean, foreignKey, index, integer, numeric, pgSchema, primaryKey, serial, text, timestamp, uniqueIndex, varchar } from "drizzle-orm/pg-core";
|
|
16
16
|
|
|
17
17
|
//#region src/utils/Errors.ts
|
|
@@ -77,6 +77,8 @@ var Tick_exports = /* @__PURE__ */ __exportAll({
|
|
|
77
77
|
InvalidTickError: () => InvalidTickError,
|
|
78
78
|
MAX_PRICE: () => MAX_PRICE,
|
|
79
79
|
TICK_RANGE: () => TICK_RANGE,
|
|
80
|
+
assetsToObligationUnits: () => assetsToObligationUnits,
|
|
81
|
+
obligationUnitsToAssets: () => obligationUnitsToAssets,
|
|
80
82
|
priceToTick: () => priceToTick,
|
|
81
83
|
tickToPrice: () => tickToPrice
|
|
82
84
|
});
|
|
@@ -136,6 +138,26 @@ function assertTick(tick) {
|
|
|
136
138
|
function assertPrice(price) {
|
|
137
139
|
if (price < 0n || price > MAX_PRICE) throw new InvalidPriceError(price);
|
|
138
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* Converts obligation units to assets using the tick price (mulDivDown).
|
|
143
|
+
* @param obligationUnits - The obligation units to convert.
|
|
144
|
+
* @param tick - The offer tick.
|
|
145
|
+
* @returns The equivalent amount in assets.
|
|
146
|
+
*/
|
|
147
|
+
function obligationUnitsToAssets(obligationUnits, tick) {
|
|
148
|
+
return obligationUnits * tickToPrice(tick) / WAD$1;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Converts assets to obligation units using the tick price (mulDivUp).
|
|
152
|
+
* @param assets - The asset amount to convert.
|
|
153
|
+
* @param tick - The offer tick.
|
|
154
|
+
* @returns The equivalent amount in obligation units.
|
|
155
|
+
*/
|
|
156
|
+
function assetsToObligationUnits(assets, tick) {
|
|
157
|
+
const price = tickToPrice(tick);
|
|
158
|
+
if (price === 0n) return 0n;
|
|
159
|
+
return (assets * WAD$1 + price - 1n) / price;
|
|
160
|
+
}
|
|
139
161
|
var InvalidTickError = class extends BaseError {
|
|
140
162
|
name = "Tick.InvalidTickError";
|
|
141
163
|
constructor(tick) {
|
|
@@ -157,7 +179,7 @@ function from$15(level) {
|
|
|
157
179
|
return {
|
|
158
180
|
tick: level.tick,
|
|
159
181
|
price: price.toString(),
|
|
160
|
-
|
|
182
|
+
obligation_units: level.obligationUnits.toString(),
|
|
161
183
|
count: level.count
|
|
162
184
|
};
|
|
163
185
|
}
|
|
@@ -215,9 +237,11 @@ function from$14(obligation, quote, chainId) {
|
|
|
215
237
|
collaterals: obligation.collaterals.map((c) => ({
|
|
216
238
|
token: c.asset,
|
|
217
239
|
lltv: c.lltv.toString(),
|
|
240
|
+
max_lif: c.maxLif.toString(),
|
|
218
241
|
oracle: c.oracle
|
|
219
242
|
})),
|
|
220
243
|
maturity: obligation.maturity,
|
|
244
|
+
rcf_threshold: obligation.rcfThreshold.toString(),
|
|
221
245
|
ask: {
|
|
222
246
|
tick: quote.ask.tick,
|
|
223
247
|
price: quote.ask.price.toString()
|
|
@@ -258,15 +282,15 @@ function from$13(input) {
|
|
|
258
282
|
collaterals: input.collaterals.map((c) => ({
|
|
259
283
|
token: c.asset,
|
|
260
284
|
lltv: c.lltv.toString(),
|
|
285
|
+
max_lif: c.maxLif.toString(),
|
|
261
286
|
oracle: c.oracle
|
|
262
287
|
})),
|
|
263
|
-
maturity: input.maturity
|
|
288
|
+
maturity: input.maturity,
|
|
289
|
+
rcf_threshold: input.rcfThreshold.toString()
|
|
264
290
|
},
|
|
265
291
|
buy: input.buy,
|
|
266
292
|
maker: input.maker,
|
|
267
|
-
assets: input.assets.toString(),
|
|
268
293
|
obligation_units: input.obligationUnits.toString(),
|
|
269
|
-
obligation_shares: input.obligationShares.toString(),
|
|
270
294
|
start: input.start,
|
|
271
295
|
expiry: input.expiry,
|
|
272
296
|
tick: input.tick,
|
|
@@ -274,7 +298,8 @@ function from$13(input) {
|
|
|
274
298
|
session: input.session,
|
|
275
299
|
callback: input.callback.address,
|
|
276
300
|
callback_data: input.callback.data,
|
|
277
|
-
receiver_if_maker_is_seller: input.receiverIfMakerIsSeller
|
|
301
|
+
receiver_if_maker_is_seller: input.receiverIfMakerIsSeller,
|
|
302
|
+
exit_only: input.exitOnly
|
|
278
303
|
},
|
|
279
304
|
offer_hash: input.hash,
|
|
280
305
|
obligation_id: input.obligationId,
|
|
@@ -327,15 +352,15 @@ const offerExample = {
|
|
|
327
352
|
collaterals: [{
|
|
328
353
|
token: "0x34Cf890dB685FC536E05652FB41f02090c3fb751",
|
|
329
354
|
lltv: "860000000000000000",
|
|
355
|
+
max_lif: "0",
|
|
330
356
|
oracle: "0x45093658BE7f90B63D7c359e8f408e503c2D9401"
|
|
331
357
|
}],
|
|
332
|
-
maturity: 1761922799
|
|
358
|
+
maturity: 1761922799,
|
|
359
|
+
rcf_threshold: "0"
|
|
333
360
|
},
|
|
334
361
|
buy: false,
|
|
335
362
|
maker: "0x7b093658BE7f90B63D7c359e8f408e503c2D9401",
|
|
336
|
-
|
|
337
|
-
obligation_units: "0",
|
|
338
|
-
obligation_shares: "0",
|
|
363
|
+
obligation_units: "369216000000000000000000",
|
|
339
364
|
start: 1761922790,
|
|
340
365
|
expiry: 1761922799,
|
|
341
366
|
tick: 495,
|
|
@@ -343,7 +368,8 @@ const offerExample = {
|
|
|
343
368
|
session: "0x0000000000000000000000000000000000000000000000000000000000000000",
|
|
344
369
|
callback: "0x0000000000000000000000000000000000000000",
|
|
345
370
|
callback_data: "0x",
|
|
346
|
-
receiver_if_maker_is_seller: "0x7b093658BE7f90B63D7c359e8f408e503c2D9401"
|
|
371
|
+
receiver_if_maker_is_seller: "0x7b093658BE7f90B63D7c359e8f408e503c2D9401",
|
|
372
|
+
exit_only: false
|
|
347
373
|
},
|
|
348
374
|
offer_hash: "0xac4bd8318ec914f89f8af913f162230575b0ac0696a19256bc12138c5cfe1427",
|
|
349
375
|
obligation_id: "0x25690ae1aee324a005be565f3bcdd16dbf8daf79",
|
|
@@ -377,11 +403,10 @@ const missingCollectorExample = {
|
|
|
377
403
|
};
|
|
378
404
|
const validateOfferExample = {
|
|
379
405
|
maker: "0x7b093658BE7f90B63D7c359e8f408e503c2D9401",
|
|
380
|
-
|
|
381
|
-
obligation_units: "0",
|
|
382
|
-
obligation_shares: "0",
|
|
406
|
+
obligation_units: "369216000000000000000000",
|
|
383
407
|
tick: 495,
|
|
384
408
|
maturity: 1761922799,
|
|
409
|
+
rcf_threshold: "0",
|
|
385
410
|
expiry: 1761922799,
|
|
386
411
|
start: 1761922790,
|
|
387
412
|
group: "0x000000000000000000000000000000000000000000000000000000000008b8f4",
|
|
@@ -392,13 +417,15 @@ const validateOfferExample = {
|
|
|
392
417
|
collaterals: [{
|
|
393
418
|
asset: "0x34Cf890dB685FC536E05652FB41f02090c3fb751",
|
|
394
419
|
oracle: "0x45093658BE7f90B63D7c359e8f408e503c2D9401",
|
|
395
|
-
lltv: "860000000000000000"
|
|
420
|
+
lltv: "860000000000000000",
|
|
421
|
+
max_lif: "0"
|
|
396
422
|
}],
|
|
397
423
|
callback: {
|
|
398
424
|
address: "0x0000000000000000000000000000000000000000",
|
|
399
425
|
data: "0x"
|
|
400
426
|
},
|
|
401
|
-
receiver_if_maker_is_seller: "0x7b093658BE7f90B63D7c359e8f408e503c2D9401"
|
|
427
|
+
receiver_if_maker_is_seller: "0x7b093658BE7f90B63D7c359e8f408e503c2D9401",
|
|
428
|
+
exit_only: false
|
|
402
429
|
};
|
|
403
430
|
const routerStatusExample = {
|
|
404
431
|
status: "live",
|
|
@@ -442,6 +469,10 @@ __decorate([ApiProperty({
|
|
|
442
469
|
type: "string",
|
|
443
470
|
example: "860000000000000000"
|
|
444
471
|
})], CollateralResponse.prototype, "lltv", void 0);
|
|
472
|
+
__decorate([ApiProperty({
|
|
473
|
+
type: "string",
|
|
474
|
+
example: "0"
|
|
475
|
+
})], CollateralResponse.prototype, "max_lif", void 0);
|
|
445
476
|
__decorate([ApiProperty({
|
|
446
477
|
type: "string",
|
|
447
478
|
example: "0x45093658BE7f90B63D7c359e8f408e503c2D9401"
|
|
@@ -459,6 +490,10 @@ __decorate([ApiProperty({
|
|
|
459
490
|
type: "string",
|
|
460
491
|
example: validateOfferExample.collaterals[0].lltv
|
|
461
492
|
})], ValidateCollateralRequest.prototype, "lltv", void 0);
|
|
493
|
+
__decorate([ApiProperty({
|
|
494
|
+
type: "string",
|
|
495
|
+
example: validateOfferExample.collaterals[0].max_lif
|
|
496
|
+
})], ValidateCollateralRequest.prototype, "max_lif", void 0);
|
|
462
497
|
var ValidateCallbackRequest = class {};
|
|
463
498
|
__decorate([ApiProperty({
|
|
464
499
|
type: "string",
|
|
@@ -503,6 +538,10 @@ __decorate([ApiProperty({
|
|
|
503
538
|
type: "number",
|
|
504
539
|
example: offerExample.offer.obligation.maturity
|
|
505
540
|
})], ObligationOfferResponse.prototype, "maturity", void 0);
|
|
541
|
+
__decorate([ApiProperty({
|
|
542
|
+
type: "string",
|
|
543
|
+
example: offerExample.offer.obligation.rcf_threshold
|
|
544
|
+
})], ObligationOfferResponse.prototype, "rcf_threshold", void 0);
|
|
506
545
|
var OfferDataResponse = class {};
|
|
507
546
|
__decorate([ApiProperty({
|
|
508
547
|
type: () => ObligationOfferResponse,
|
|
@@ -516,18 +555,10 @@ __decorate([ApiProperty({
|
|
|
516
555
|
type: "string",
|
|
517
556
|
example: offerExample.offer.maker
|
|
518
557
|
})], OfferDataResponse.prototype, "maker", void 0);
|
|
519
|
-
__decorate([ApiProperty({
|
|
520
|
-
type: "string",
|
|
521
|
-
example: offerExample.offer.assets
|
|
522
|
-
})], OfferDataResponse.prototype, "assets", void 0);
|
|
523
558
|
__decorate([ApiProperty({
|
|
524
559
|
type: "string",
|
|
525
560
|
example: offerExample.offer.obligation_units
|
|
526
561
|
})], OfferDataResponse.prototype, "obligation_units", void 0);
|
|
527
|
-
__decorate([ApiProperty({
|
|
528
|
-
type: "string",
|
|
529
|
-
example: offerExample.offer.obligation_shares
|
|
530
|
-
})], OfferDataResponse.prototype, "obligation_shares", void 0);
|
|
531
562
|
__decorate([ApiProperty({
|
|
532
563
|
type: "number",
|
|
533
564
|
example: offerExample.offer.start
|
|
@@ -562,6 +593,10 @@ __decorate([ApiProperty({
|
|
|
562
593
|
type: "string",
|
|
563
594
|
example: offerExample.offer.receiver_if_maker_is_seller
|
|
564
595
|
})], OfferDataResponse.prototype, "receiver_if_maker_is_seller", void 0);
|
|
596
|
+
__decorate([ApiProperty({
|
|
597
|
+
type: "boolean",
|
|
598
|
+
example: offerExample.offer.exit_only
|
|
599
|
+
})], OfferDataResponse.prototype, "exit_only", void 0);
|
|
565
600
|
var OfferListItemResponse = class {};
|
|
566
601
|
__decorate([ApiProperty({
|
|
567
602
|
type: () => OfferDataResponse,
|
|
@@ -624,6 +659,10 @@ __decorate([ApiProperty({
|
|
|
624
659
|
type: "number",
|
|
625
660
|
example: 1761922800
|
|
626
661
|
})], ObligationResponse.prototype, "maturity", void 0);
|
|
662
|
+
__decorate([ApiProperty({
|
|
663
|
+
type: "string",
|
|
664
|
+
example: "0"
|
|
665
|
+
})], ObligationResponse.prototype, "rcf_threshold", void 0);
|
|
627
666
|
__decorate([ApiProperty({ type: () => AskResponse })], ObligationResponse.prototype, "ask", void 0);
|
|
628
667
|
__decorate([ApiProperty({ type: () => BidResponse })], ObligationResponse.prototype, "bid", void 0);
|
|
629
668
|
var ObligationListResponse = class extends SuccessResponse {};
|
|
@@ -771,20 +810,11 @@ __decorate([ApiProperty({
|
|
|
771
810
|
type: "string",
|
|
772
811
|
example: validateOfferExample.maker
|
|
773
812
|
})], ValidateOfferRequest.prototype, "maker", void 0);
|
|
774
|
-
__decorate([ApiProperty({
|
|
775
|
-
type: "string",
|
|
776
|
-
example: validateOfferExample.assets
|
|
777
|
-
})], ValidateOfferRequest.prototype, "assets", void 0);
|
|
778
813
|
__decorate([ApiProperty({
|
|
779
814
|
type: "string",
|
|
780
815
|
example: validateOfferExample.obligation_units,
|
|
781
816
|
required: false
|
|
782
817
|
})], ValidateOfferRequest.prototype, "obligation_units", void 0);
|
|
783
|
-
__decorate([ApiProperty({
|
|
784
|
-
type: "string",
|
|
785
|
-
example: validateOfferExample.obligation_shares,
|
|
786
|
-
required: false
|
|
787
|
-
})], ValidateOfferRequest.prototype, "obligation_shares", void 0);
|
|
788
818
|
__decorate([ApiProperty({
|
|
789
819
|
type: "number",
|
|
790
820
|
example: validateOfferExample.tick,
|
|
@@ -795,6 +825,10 @@ __decorate([ApiProperty({
|
|
|
795
825
|
type: "number",
|
|
796
826
|
example: validateOfferExample.maturity
|
|
797
827
|
})], ValidateOfferRequest.prototype, "maturity", void 0);
|
|
828
|
+
__decorate([ApiProperty({
|
|
829
|
+
type: "string",
|
|
830
|
+
example: validateOfferExample.rcf_threshold
|
|
831
|
+
})], ValidateOfferRequest.prototype, "rcf_threshold", void 0);
|
|
798
832
|
__decorate([ApiProperty({
|
|
799
833
|
type: "number",
|
|
800
834
|
example: validateOfferExample.expiry
|
|
@@ -831,6 +865,11 @@ __decorate([ApiProperty({
|
|
|
831
865
|
type: "string",
|
|
832
866
|
example: validateOfferExample.receiver_if_maker_is_seller
|
|
833
867
|
})], ValidateOfferRequest.prototype, "receiver_if_maker_is_seller", void 0);
|
|
868
|
+
__decorate([ApiProperty({
|
|
869
|
+
type: "boolean",
|
|
870
|
+
example: false,
|
|
871
|
+
required: false
|
|
872
|
+
})], ValidateOfferRequest.prototype, "exit_only", void 0);
|
|
834
873
|
var ValidateOffersRequest = class {};
|
|
835
874
|
__decorate([ApiProperty({
|
|
836
875
|
type: "number",
|
|
@@ -909,7 +948,7 @@ __decorate([ApiProperty({
|
|
|
909
948
|
__decorate([ApiProperty({
|
|
910
949
|
type: "string",
|
|
911
950
|
example: "369216000000000000000000"
|
|
912
|
-
})], BookLevelResponse.prototype, "
|
|
951
|
+
})], BookLevelResponse.prototype, "obligation_units", void 0);
|
|
913
952
|
__decorate([ApiProperty({
|
|
914
953
|
type: "number",
|
|
915
954
|
example: 5
|
|
@@ -918,7 +957,7 @@ const positionExample = {
|
|
|
918
957
|
chain_id: 1,
|
|
919
958
|
contract: "0xC9A9C45C0eB717f8b5F193Af6bAa05A1c0Ac5078",
|
|
920
959
|
user: "0x7b093658BE7f90B63D7c359e8f408e503c2D9401",
|
|
921
|
-
obligation_id: "
|
|
960
|
+
obligation_id: "0x12590ae1aee324a005be565f3bcdd16dbf8daf7969b26c181c8b8f467dad9f67",
|
|
922
961
|
reserved: "200000000000000000000",
|
|
923
962
|
block_number: 21345678
|
|
924
963
|
};
|
|
@@ -1533,7 +1572,7 @@ const OpenApi = async () => {
|
|
|
1533
1572
|
info: {
|
|
1534
1573
|
title: "Router API",
|
|
1535
1574
|
version: "1.0.0",
|
|
1536
|
-
description: "API for the Morpho Router"
|
|
1575
|
+
description: process.env.COMMIT_SHA ? `API for the Morpho Router — version: ${process.env.COMMIT_SHA.slice(0, 7)}` : "API for the Morpho Router"
|
|
1537
1576
|
},
|
|
1538
1577
|
servers: [{
|
|
1539
1578
|
url: "https://router.morpho.dev",
|
|
@@ -1604,7 +1643,7 @@ function isValidOfferHashCursor(val) {
|
|
|
1604
1643
|
return /^0x[a-f0-9]{64}$/i.test(val);
|
|
1605
1644
|
}
|
|
1606
1645
|
function isValidObligationIdCursor(val) {
|
|
1607
|
-
return /^0x[a-f0-9]{
|
|
1646
|
+
return /^0x[a-f0-9]{64}$/i.test(val);
|
|
1608
1647
|
}
|
|
1609
1648
|
function isValidOfferCursor(val) {
|
|
1610
1649
|
const [hash, obligationId, ...rest] = val.split(":");
|
|
@@ -1686,9 +1725,9 @@ const GetOffersQueryParams = PaginationQueryParams.omit({ cursor: true }).extend
|
|
|
1686
1725
|
description: "Side of the offer. Required when using obligation_id.",
|
|
1687
1726
|
example: "buy"
|
|
1688
1727
|
}),
|
|
1689
|
-
obligation_id: z$1.string().regex(/^0x[a-fA-F0-9]{
|
|
1728
|
+
obligation_id: z$1.string().regex(/^0x[a-fA-F0-9]{64}$/, { error: "Obligation id must be a valid 32-byte hex string" }).transform((val) => val.toLowerCase()).optional().meta({
|
|
1690
1729
|
description: "Offers obligation id. Required when not using maker.",
|
|
1691
|
-
example: "
|
|
1730
|
+
example: "0x1234567890123456789012345678901234567890123456789012345678901234"
|
|
1692
1731
|
}),
|
|
1693
1732
|
maker: z$1.string().regex(/^0x[a-fA-F0-9]{40}$/, { error: "Maker must be a valid 20-byte address" }).transform((val) => val.toLowerCase()).optional().meta({
|
|
1694
1733
|
description: "Maker address to filter offers by. Alternative to obligation_id + side.",
|
|
@@ -1773,9 +1812,9 @@ const GetObligationsQueryParams = z$1.object({
|
|
|
1773
1812
|
example: "-ask,bid,maturity"
|
|
1774
1813
|
})
|
|
1775
1814
|
});
|
|
1776
|
-
const GetObligationParams = z$1.object({ obligation_id: z$1.string({ error: "Obligation id is required and must be a valid
|
|
1815
|
+
const GetObligationParams = z$1.object({ obligation_id: z$1.string({ error: "Obligation id is required and must be a valid 32-byte hex string" }).regex(/^0x[a-fA-F0-9]{64}$/, { error: "Obligation id must be a valid 32-byte hex string" }).transform((val) => val.toLowerCase()).meta({
|
|
1777
1816
|
description: "Obligation id",
|
|
1778
|
-
example: "
|
|
1817
|
+
example: "0x1234567890123456789012345678901234567890123456789012345678901234"
|
|
1779
1818
|
}) });
|
|
1780
1819
|
/** Validate a book cursor format: {side, lastTick, offersCursor} */
|
|
1781
1820
|
function isValidBookCursor(cursorString) {
|
|
@@ -1810,9 +1849,9 @@ const HealthQueryParams = z$1.object({ strict: z$1.enum([
|
|
|
1810
1849
|
}) });
|
|
1811
1850
|
const GetBookParams = z$1.object({
|
|
1812
1851
|
...BookPaginationQueryParams.shape,
|
|
1813
|
-
obligation_id: z$1.string({ error: "Obligation id is required and must be a valid
|
|
1852
|
+
obligation_id: z$1.string({ error: "Obligation id is required and must be a valid 32-byte hex string" }).regex(/^0x[a-fA-F0-9]{64}$/, { error: "Obligation id must be a valid 32-byte hex string" }).transform((val) => val.toLowerCase()).meta({
|
|
1814
1853
|
description: "Obligation id",
|
|
1815
|
-
example: "
|
|
1854
|
+
example: "0x1234567890123456789012345678901234567890123456789012345678901234"
|
|
1816
1855
|
}),
|
|
1817
1856
|
side: z$1.enum(["buy", "sell"]).meta({
|
|
1818
1857
|
description: "Side of the book (buy or sell).",
|
|
@@ -1900,57 +1939,75 @@ const MetaMorphoFactory = parseAbi(["event CreateMetaMorpho(address indexed meta
|
|
|
1900
1939
|
//#region src/core/Abi/MorphoV2.ts
|
|
1901
1940
|
const MorphoV2 = parseAbi([
|
|
1902
1941
|
"constructor()",
|
|
1903
|
-
"function
|
|
1904
|
-
"function
|
|
1942
|
+
"function activatedCollaterals(bytes32 id, address user) view returns (uint128)",
|
|
1943
|
+
"function collateralOf(bytes32 id, address user, uint256 index) view returns (uint128)",
|
|
1905
1944
|
"function consumed(address user, bytes32 group) view returns (uint256)",
|
|
1906
|
-
"function
|
|
1907
|
-
"function
|
|
1945
|
+
"function creditAfterSlashing(bytes32 id, address user) view returns (uint256)",
|
|
1946
|
+
"function creditOf(bytes32 id, address user) view returns (uint256)",
|
|
1947
|
+
"function debtOf(bytes32 id, address user) view returns (uint256)",
|
|
1948
|
+
"function defaultFees(address loanToken, uint256) view returns (uint16)",
|
|
1908
1949
|
"function feeSetter() view returns (address)",
|
|
1909
|
-
"function fees(
|
|
1950
|
+
"function fees(bytes32 id) view returns (uint16[7])",
|
|
1910
1951
|
"function flashLoan(address token, uint256 assets, address callback, bytes data)",
|
|
1911
|
-
"function
|
|
1912
|
-
"function
|
|
1952
|
+
"function isAuthorized(address authorizer, address authorized) view returns (bool)",
|
|
1953
|
+
"function isHealthy((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation, bytes32 id, address borrower) view returns (bool)",
|
|
1954
|
+
"function liquidate((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address borrower, bytes data) returns (uint256, uint256)",
|
|
1955
|
+
"function maxCollateralPerUser(address collateralToken) view returns (uint256)",
|
|
1956
|
+
"function maxLif(uint256 lltv, uint256 cursor) pure returns (uint256)",
|
|
1957
|
+
"function maxTakeableAssets(address loanToken) view returns (uint256)",
|
|
1958
|
+
"function maxTotalUnits(address loanToken) view returns (uint128)",
|
|
1959
|
+
"function maxTradingFee(uint256 index) pure returns (uint256)",
|
|
1913
1960
|
"function multicall(bytes[] calls)",
|
|
1914
|
-
"function obligationCreated(
|
|
1915
|
-
"function obligationState(
|
|
1961
|
+
"function obligationCreated(bytes32 id) view returns (bool)",
|
|
1962
|
+
"function obligationState(bytes32 id) view returns (uint128 totalUnits, uint256 withdrawable, uint128 lossIndex, bool created)",
|
|
1916
1963
|
"function owner() view returns (address)",
|
|
1917
|
-
"function repay((address loanToken, (address token, uint256 lltv, address oracle)[] collaterals, uint256 maturity, uint256
|
|
1964
|
+
"function repay((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation, uint256 obligationUnits, address onBehalf)",
|
|
1918
1965
|
"function session(address user) view returns (bytes32)",
|
|
1966
|
+
"function setConsumed(bytes32 group, uint256 amount, address onBehalf)",
|
|
1919
1967
|
"function setDefaultTradingFee(address loanToken, uint256 index, uint256 newTradingFee)",
|
|
1920
1968
|
"function setFeeSetter(address newFeeSetter)",
|
|
1921
|
-
"function
|
|
1969
|
+
"function setIsAuthorized(address onBehalf, address authorized, bool newIsAuthorized)",
|
|
1970
|
+
"function setMaxCollateralPerUser(address collateralToken, uint256 newMaxCollateralPerUser)",
|
|
1971
|
+
"function setMaxTakeableAssets(address loanToken, uint256 newMaxTakeableAssets)",
|
|
1972
|
+
"function setMaxTotalUnits(address loanToken, uint128 newMaxTotalUnits)",
|
|
1973
|
+
"function setObligationTradingFee(bytes32 id, uint256 index, uint256 newTradingFee)",
|
|
1922
1974
|
"function setOwner(address newOwner)",
|
|
1923
1975
|
"function setTradingFeeRecipient(address feeRecipient)",
|
|
1924
|
-
"function
|
|
1925
|
-
"function
|
|
1926
|
-
"function supplyCollateral((address loanToken, (address token, uint256 lltv, address oracle)[] collaterals, uint256 maturity, uint256
|
|
1927
|
-
"function take(uint256
|
|
1928
|
-
"function toId((address loanToken, (address token, uint256 lltv, address oracle)[] collaterals, uint256 maturity, uint256
|
|
1929
|
-
"function toObligation(
|
|
1930
|
-
"function
|
|
1931
|
-
"function
|
|
1932
|
-
"function
|
|
1933
|
-
"function tradingFee(bytes20 id, uint256 timeToMaturity) view returns (uint256)",
|
|
1976
|
+
"function shuffleSession(address onBehalf)",
|
|
1977
|
+
"function slash(bytes32 id, address user)",
|
|
1978
|
+
"function supplyCollateral((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation, uint256 collateralIndex, uint256 assets, address onBehalf)",
|
|
1979
|
+
"function take(uint256 obligationUnits, address taker, address takerCallback, bytes takerCallbackData, address receiverIfTakerIsSeller, ((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation, bool buy, address maker, uint256 obligationUnits, uint256 start, uint256 expiry, uint256 tick, bytes32 group, bytes32 session, address callback, bytes callbackData, address receiverIfMakerIsSeller, bool exitOnly) offer, (uint8 v, bytes32 r, bytes32 s) sig, bytes32 root, bytes32[] proof) returns (uint256, uint256, uint256)",
|
|
1980
|
+
"function toId((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation) view returns (bytes32)",
|
|
1981
|
+
"function toObligation(bytes32 id) view returns ((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold))",
|
|
1982
|
+
"function totalUnits(bytes32 id) view returns (uint256)",
|
|
1983
|
+
"function touchObligation((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation) returns (bytes32)",
|
|
1984
|
+
"function tradingFee(bytes32 id, uint256 timeToMaturity) view returns (uint256)",
|
|
1934
1985
|
"function tradingFeeRecipient() view returns (address)",
|
|
1935
|
-
"function
|
|
1936
|
-
"function
|
|
1937
|
-
"function
|
|
1986
|
+
"function userLossIndex(bytes32 id, address user) view returns (uint128)",
|
|
1987
|
+
"function withdraw((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation, uint256 obligationUnits, address onBehalf, address receiver)",
|
|
1988
|
+
"function withdrawCollateral((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation, uint256 collateralIndex, uint256 assets, address onBehalf, address receiver)",
|
|
1989
|
+
"function withdrawable(bytes32 id) view returns (uint256)",
|
|
1938
1990
|
"event Constructor(address indexed owner)",
|
|
1939
|
-
"event Consume(address indexed user, bytes32 indexed group, uint256 amount)",
|
|
1940
1991
|
"event FlashLoan(address indexed caller, address indexed token, uint256 assets)",
|
|
1941
|
-
"event Liquidate(address indexed caller,
|
|
1942
|
-
"event ObligationCreated(
|
|
1943
|
-
"event Repay(address indexed caller,
|
|
1992
|
+
"event Liquidate(address indexed caller, bytes32 indexed id_, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address indexed borrower, uint256 badDebt, uint256 latestLossIndex)",
|
|
1993
|
+
"event ObligationCreated(bytes32 indexed id_, (address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation)",
|
|
1994
|
+
"event Repay(address indexed caller, bytes32 indexed id_, uint256 obligationUnits, address indexed onBehalf)",
|
|
1995
|
+
"event SetConsumed(address indexed caller, address indexed onBehalf, bytes32 indexed group, uint256 amount)",
|
|
1944
1996
|
"event SetDefaultTradingFee(address indexed loanToken, uint256 indexed index, uint256 newTradingFee)",
|
|
1945
1997
|
"event SetFeeSetter(address indexed feeSetter)",
|
|
1946
|
-
"event
|
|
1998
|
+
"event SetIsAuthorized(address indexed caller, address indexed onBehalf, address indexed authorized, bool newIsAuthorized)",
|
|
1999
|
+
"event SetMaxCollateralPerUser(address indexed collateralToken, uint256 maxCollateralPerUser)",
|
|
2000
|
+
"event SetMaxTakeableAssets(address indexed loanToken, uint256 maxTakeableAssets)",
|
|
2001
|
+
"event SetMaxTotalUnits(address indexed loanToken, uint128 maxTotalUnits)",
|
|
2002
|
+
"event SetObligationTradingFee(bytes32 indexed id_, uint256 indexed index, uint256 newTradingFee)",
|
|
1947
2003
|
"event SetOwner(address indexed owner)",
|
|
1948
2004
|
"event SetTradingFeeRecipient(address indexed feeRecipient)",
|
|
1949
|
-
"event ShuffleSession(address indexed
|
|
1950
|
-
"event
|
|
1951
|
-
"event
|
|
1952
|
-
"event
|
|
1953
|
-
"event
|
|
2005
|
+
"event ShuffleSession(address indexed caller, address indexed onBehalf, bytes32 session)",
|
|
2006
|
+
"event Slash(address caller, bytes32 indexed id_, address indexed user, uint256 credit, uint256 latestLossIndex)",
|
|
2007
|
+
"event SupplyCollateral(address caller, bytes32 indexed id_, address indexed collateral, uint256 assets, address indexed onBehalf)",
|
|
2008
|
+
"event Take(address caller, bytes32 indexed id_, address indexed maker, address indexed taker, bool offerIsBuy, uint256 buyerAssets, uint256 sellerAssets, uint256 obligationUnits, address sellerReceiver, bytes32 group, uint256 consumed, uint256 totalUnits)",
|
|
2009
|
+
"event Withdraw(address caller, bytes32 indexed id_, uint256 obligationUnits, address indexed onBehalf, address indexed receiver)",
|
|
2010
|
+
"event WithdrawCollateral(address caller, bytes32 indexed id_, address indexed collateral, uint256 assets, address indexed onBehalf, address receiver)"
|
|
1954
2011
|
]);
|
|
1955
2012
|
|
|
1956
2013
|
//#endregion
|
|
@@ -2243,8 +2300,8 @@ const chains$1 = {
|
|
|
2243
2300
|
name: "base",
|
|
2244
2301
|
custom: {
|
|
2245
2302
|
morpho: {
|
|
2246
|
-
address: "
|
|
2247
|
-
blockCreated:
|
|
2303
|
+
address: "0xee437005ba0a3d0e9bc6510775c41f23ed2909e1",
|
|
2304
|
+
blockCreated: 43515847
|
|
2248
2305
|
},
|
|
2249
2306
|
morphoBlue: {
|
|
2250
2307
|
address: "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb",
|
|
@@ -2273,8 +2330,8 @@ const chains$1 = {
|
|
|
2273
2330
|
name: "ethereum-virtual-testnet",
|
|
2274
2331
|
custom: {
|
|
2275
2332
|
morpho: {
|
|
2276
|
-
address: "
|
|
2277
|
-
blockCreated:
|
|
2333
|
+
address: "0xc1c6e6fa308eeef18e96be420d8ccb218215a26c",
|
|
2334
|
+
blockCreated: 23244321
|
|
2278
2335
|
},
|
|
2279
2336
|
morphoBlue: {
|
|
2280
2337
|
address: "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb",
|
|
@@ -2301,9 +2358,13 @@ const chains$1 = {
|
|
|
2301
2358
|
...anvil,
|
|
2302
2359
|
id: ChainId.ANVIL,
|
|
2303
2360
|
name: "anvil",
|
|
2361
|
+
contracts: { multicall3: {
|
|
2362
|
+
address: "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0",
|
|
2363
|
+
blockCreated: 0
|
|
2364
|
+
} },
|
|
2304
2365
|
custom: {
|
|
2305
2366
|
morpho: {
|
|
2306
|
-
address: "
|
|
2367
|
+
address: "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512",
|
|
2307
2368
|
blockCreated: 0
|
|
2308
2369
|
},
|
|
2309
2370
|
morphoBlue: {
|
|
@@ -2311,8 +2372,8 @@ const chains$1 = {
|
|
|
2311
2372
|
blockCreated: 0
|
|
2312
2373
|
},
|
|
2313
2374
|
mempool: {
|
|
2314
|
-
address: "
|
|
2315
|
-
blockCreated:
|
|
2375
|
+
address: "0x5FbDB2315678afecb367f032d93F642f64180aa3",
|
|
2376
|
+
blockCreated: 0
|
|
2316
2377
|
},
|
|
2317
2378
|
vaults: { factories: {
|
|
2318
2379
|
v1_0: {
|
|
@@ -2514,6 +2575,7 @@ var Random_exports = /* @__PURE__ */ __exportAll({
|
|
|
2514
2575
|
address: () => address,
|
|
2515
2576
|
bool: () => bool,
|
|
2516
2577
|
bytes: () => bytes,
|
|
2578
|
+
createRng: () => createRng,
|
|
2517
2579
|
float: () => float,
|
|
2518
2580
|
hex: () => hex,
|
|
2519
2581
|
int: () => int,
|
|
@@ -2531,7 +2593,19 @@ const hashSeed = (seed) => {
|
|
|
2531
2593
|
}
|
|
2532
2594
|
return hash >>> 0;
|
|
2533
2595
|
};
|
|
2534
|
-
|
|
2596
|
+
/**
|
|
2597
|
+
* Creates an isolated seeded RNG instance — safe for concurrent use.
|
|
2598
|
+
* @param seed - Seed string used to derive the initial RNG state.
|
|
2599
|
+
*/
|
|
2600
|
+
function createRng(seed) {
|
|
2601
|
+
const rng = createSeededRngFn(seed);
|
|
2602
|
+
return {
|
|
2603
|
+
float: () => rng(),
|
|
2604
|
+
int: (maxExclusive, min = 0) => Math.floor(rng() * (maxExclusive - min)) + min,
|
|
2605
|
+
bool: (probability = .5) => rng() < probability
|
|
2606
|
+
};
|
|
2607
|
+
}
|
|
2608
|
+
const createSeededRngFn = (seed) => {
|
|
2535
2609
|
let state = hashSeed(seed);
|
|
2536
2610
|
return () => {
|
|
2537
2611
|
state += 1831565813;
|
|
@@ -2545,7 +2619,7 @@ const createSeededRng = (seed) => {
|
|
|
2545
2619
|
*/
|
|
2546
2620
|
function withSeed(seed, fn) {
|
|
2547
2621
|
const previous = currentRng;
|
|
2548
|
-
currentRng =
|
|
2622
|
+
currentRng = createSeededRngFn(seed);
|
|
2549
2623
|
try {
|
|
2550
2624
|
return fn();
|
|
2551
2625
|
} finally {
|
|
@@ -2556,7 +2630,7 @@ function withSeed(seed, fn) {
|
|
|
2556
2630
|
* Seeds the global RNG for deterministic test runs.
|
|
2557
2631
|
*/
|
|
2558
2632
|
function seed(seed) {
|
|
2559
|
-
currentRng =
|
|
2633
|
+
currentRng = createSeededRngFn(seed);
|
|
2560
2634
|
}
|
|
2561
2635
|
/**
|
|
2562
2636
|
* Returns a deterministic random float in [0, 1).
|
|
@@ -2752,6 +2826,10 @@ const abi$1 = [
|
|
|
2752
2826
|
type: "uint256",
|
|
2753
2827
|
name: "lltv"
|
|
2754
2828
|
},
|
|
2829
|
+
{
|
|
2830
|
+
type: "uint256",
|
|
2831
|
+
name: "maxLif"
|
|
2832
|
+
},
|
|
2755
2833
|
{
|
|
2756
2834
|
type: "address",
|
|
2757
2835
|
name: "oracle"
|
|
@@ -2760,7 +2838,8 @@ const abi$1 = [
|
|
|
2760
2838
|
const CollateralSchema = z$1.object({
|
|
2761
2839
|
asset: z$1.string().transform(transformAddress),
|
|
2762
2840
|
oracle: z$1.string().transform(transformAddress),
|
|
2763
|
-
lltv: LLTVSchema
|
|
2841
|
+
lltv: LLTVSchema,
|
|
2842
|
+
maxLif: z$1.bigint({ coerce: true }).min(0n).optional().default(0n)
|
|
2764
2843
|
});
|
|
2765
2844
|
const CollateralsSchema = z$1.array(CollateralSchema).min(1, { message: "At least one collateral is required" }).refine((collaterals) => {
|
|
2766
2845
|
for (let i = 1; i < collaterals.length; i++) if (collaterals[i - 1].asset.toLowerCase() > collaterals[i].asset.toLowerCase()) return false;
|
|
@@ -2778,6 +2857,7 @@ const from$10 = (parameters) => {
|
|
|
2778
2857
|
return {
|
|
2779
2858
|
asset: parameters.asset.toLowerCase(),
|
|
2780
2859
|
lltv: from$11(parameters.lltv),
|
|
2860
|
+
maxLif: parameters.maxLif ?? 0n,
|
|
2781
2861
|
oracle: parameters.oracle.toLowerCase()
|
|
2782
2862
|
};
|
|
2783
2863
|
};
|
|
@@ -2794,7 +2874,8 @@ function random$3() {
|
|
|
2794
2874
|
return from$10({
|
|
2795
2875
|
asset: address(),
|
|
2796
2876
|
oracle: address(),
|
|
2797
|
-
lltv: .965
|
|
2877
|
+
lltv: .965,
|
|
2878
|
+
maxLif: 0n
|
|
2798
2879
|
});
|
|
2799
2880
|
}
|
|
2800
2881
|
|
|
@@ -3055,7 +3136,7 @@ const ObligationSchema = z$1.object({
|
|
|
3055
3136
|
loanToken: z$1.string().transform(transformAddress),
|
|
3056
3137
|
collaterals: CollateralsSchema,
|
|
3057
3138
|
maturity: MaturitySchema,
|
|
3058
|
-
|
|
3139
|
+
rcfThreshold: z$1.bigint({ coerce: true }).min(0n)
|
|
3059
3140
|
});
|
|
3060
3141
|
const abi = [
|
|
3061
3142
|
{
|
|
@@ -3073,7 +3154,7 @@ const abi = [
|
|
|
3073
3154
|
},
|
|
3074
3155
|
{
|
|
3075
3156
|
type: "uint256",
|
|
3076
|
-
name: "
|
|
3157
|
+
name: "rcfThreshold"
|
|
3077
3158
|
}
|
|
3078
3159
|
];
|
|
3079
3160
|
const tupleAbi = [{
|
|
@@ -3099,6 +3180,7 @@ const tupleAbi = [{
|
|
|
3099
3180
|
* }),
|
|
3100
3181
|
* ],
|
|
3101
3182
|
* maturity: Maturity.from("end_of_next_quarter"),
|
|
3183
|
+
* rcfThreshold: 0n,
|
|
3102
3184
|
* });
|
|
3103
3185
|
* ```
|
|
3104
3186
|
*/
|
|
@@ -3112,7 +3194,7 @@ function from$8(parameters) {
|
|
|
3112
3194
|
loanToken: parsedObligation.loanToken.toLowerCase(),
|
|
3113
3195
|
collaterals: parsedObligation.collaterals.sort((a, b) => a.asset.localeCompare(b.asset)),
|
|
3114
3196
|
maturity: parsedObligation.maturity,
|
|
3115
|
-
|
|
3197
|
+
rcfThreshold: parsedObligation.rcfThreshold
|
|
3116
3198
|
};
|
|
3117
3199
|
} catch (error) {
|
|
3118
3200
|
throw new InvalidObligationError(error);
|
|
@@ -3129,8 +3211,7 @@ function fromSnakeCase$2(input) {
|
|
|
3129
3211
|
}
|
|
3130
3212
|
/**
|
|
3131
3213
|
* Calculates a canonical key for an obligation payload.
|
|
3132
|
-
* The key is computed as keccak256(abi.encode(loanToken, collaterals, maturity,
|
|
3133
|
-
* If omitted, `minCollatValue` defaults to `0`.
|
|
3214
|
+
* The key is computed as keccak256(abi.encode(loanToken, collaterals, maturity, rcfThreshold)).
|
|
3134
3215
|
* @throws If the collaterals are not sorted alphabetically by address. {@link CollateralsAreNotSortedError}
|
|
3135
3216
|
* @param parameters - {@link key.Parameters}
|
|
3136
3217
|
* @returns The obligation key as a 32-byte hex string. {@link key.ReturnType}
|
|
@@ -3154,10 +3235,11 @@ function key(parameters) {
|
|
|
3154
3235
|
parameters.collaterals.map((c) => ({
|
|
3155
3236
|
token: c.asset.toLowerCase(),
|
|
3156
3237
|
lltv: c.lltv,
|
|
3238
|
+
maxLif: c.maxLif ?? 0n,
|
|
3157
3239
|
oracle: c.oracle.toLowerCase()
|
|
3158
3240
|
})),
|
|
3159
3241
|
BigInt(parameters.maturity),
|
|
3160
|
-
parameters.
|
|
3242
|
+
parameters.rcfThreshold
|
|
3161
3243
|
]));
|
|
3162
3244
|
}
|
|
3163
3245
|
/**
|
|
@@ -3173,7 +3255,8 @@ function random$2() {
|
|
|
3173
3255
|
return from$8({
|
|
3174
3256
|
loanToken: address(),
|
|
3175
3257
|
collaterals: [random$3()],
|
|
3176
|
-
maturity: from$9("end_of_next_quarter")
|
|
3258
|
+
maturity: from$9("end_of_next_quarter"),
|
|
3259
|
+
rcfThreshold: 0n
|
|
3177
3260
|
});
|
|
3178
3261
|
}
|
|
3179
3262
|
/**
|
|
@@ -3187,7 +3270,8 @@ function fromOffer$1(offer) {
|
|
|
3187
3270
|
return from$8({
|
|
3188
3271
|
loanToken: offer.loanToken,
|
|
3189
3272
|
collaterals: offer.collaterals,
|
|
3190
|
-
maturity: offer.maturity
|
|
3273
|
+
maturity: offer.maturity,
|
|
3274
|
+
rcfThreshold: offer.rcfThreshold
|
|
3191
3275
|
});
|
|
3192
3276
|
}
|
|
3193
3277
|
var InvalidObligationError = class extends BaseError {
|
|
@@ -3224,27 +3308,27 @@ function creationCode(parameters) {
|
|
|
3224
3308
|
collaterals: parameters.obligation.collaterals.map((collateral) => ({
|
|
3225
3309
|
token: collateral.asset.toLowerCase(),
|
|
3226
3310
|
lltv: collateral.lltv,
|
|
3311
|
+
maxLif: collateral.maxLif ?? 0n,
|
|
3227
3312
|
oracle: collateral.oracle.toLowerCase()
|
|
3228
3313
|
})),
|
|
3229
3314
|
maturity: BigInt(parameters.obligation.maturity),
|
|
3230
|
-
|
|
3315
|
+
rcfThreshold: parameters.obligation.rcfThreshold
|
|
3231
3316
|
}])]);
|
|
3232
3317
|
}
|
|
3233
3318
|
/**
|
|
3234
3319
|
* Computes the same id as `IdLib.toId` in Solidity using the CREATE2 preimage:
|
|
3235
|
-
* `keccak256(0xff ++ morphoV2 ++ chainId ++ keccak256(creationCode))
|
|
3236
|
-
* then truncates to the lower 20 bytes.
|
|
3320
|
+
* `keccak256(0xff ++ morphoV2 ++ chainId ++ keccak256(creationCode))`.
|
|
3237
3321
|
*
|
|
3238
3322
|
* @param parameters - {@link toId.Parameters}
|
|
3239
|
-
* @returns The obligation id. {@link toId.ReturnType}
|
|
3323
|
+
* @returns The 32-byte obligation id. {@link toId.ReturnType}
|
|
3240
3324
|
*/
|
|
3241
3325
|
function toId(parameters) {
|
|
3242
|
-
return
|
|
3326
|
+
return keccak256(concatHex([
|
|
3243
3327
|
"0xff",
|
|
3244
3328
|
parameters.morphoV2.toLowerCase(),
|
|
3245
3329
|
numberToHex(BigInt(parameters.chainId), { size: 32 }),
|
|
3246
3330
|
keccak256(creationCode(parameters))
|
|
3247
|
-
]))
|
|
3331
|
+
]));
|
|
3248
3332
|
}
|
|
3249
3333
|
|
|
3250
3334
|
//#endregion
|
|
@@ -3334,7 +3418,6 @@ var Offer_exports = /* @__PURE__ */ __exportAll({
|
|
|
3334
3418
|
fromSnakeCase: () => fromSnakeCase$1,
|
|
3335
3419
|
hash: () => hash,
|
|
3336
3420
|
liquidateEvent: () => liquidateEvent,
|
|
3337
|
-
obligationId: () => obligationId,
|
|
3338
3421
|
random: () => random$1,
|
|
3339
3422
|
repayEvent: () => repayEvent,
|
|
3340
3423
|
serialize: () => serialize,
|
|
@@ -3353,11 +3436,10 @@ let Status = /* @__PURE__ */ function(Status) {
|
|
|
3353
3436
|
const OfferSchema = () => {
|
|
3354
3437
|
return z$1.object({
|
|
3355
3438
|
maker: z$1.string().transform(transformAddress),
|
|
3356
|
-
assets: z$1.bigint({ coerce: true }).min(0n).max(maxUint256),
|
|
3357
3439
|
obligationUnits: z$1.bigint({ coerce: true }).min(0n).max(maxUint256).optional().default(0n),
|
|
3358
|
-
obligationShares: z$1.bigint({ coerce: true }).min(0n).max(maxUint256).optional().default(0n),
|
|
3359
3440
|
tick: z$1.coerce.number().int().min(0).max(990),
|
|
3360
3441
|
maturity: MaturitySchema,
|
|
3442
|
+
rcfThreshold: z$1.bigint({ coerce: true }).min(0n).max(maxUint256),
|
|
3361
3443
|
expiry: z$1.number().int().max(Number.MAX_SAFE_INTEGER),
|
|
3362
3444
|
start: z$1.number().int().max(Number.MAX_SAFE_INTEGER),
|
|
3363
3445
|
group: z$1.union([
|
|
@@ -3377,7 +3459,8 @@ const OfferSchema = () => {
|
|
|
3377
3459
|
address: z$1.string().transform(transformAddress),
|
|
3378
3460
|
data: z$1.string().transform(transformHex)
|
|
3379
3461
|
}),
|
|
3380
|
-
receiverIfMakerIsSeller: z$1.string().transform(transformAddress)
|
|
3462
|
+
receiverIfMakerIsSeller: z$1.string().transform(transformAddress),
|
|
3463
|
+
exitOnly: z$1.boolean().optional().default(false)
|
|
3381
3464
|
}).refine((data) => data.start < data.expiry, {
|
|
3382
3465
|
message: "start must be before expiry",
|
|
3383
3466
|
path: ["start"]
|
|
@@ -3429,11 +3512,10 @@ function toSnakeCase(offer) {
|
|
|
3429
3512
|
*/
|
|
3430
3513
|
const serialize = (offer) => ({
|
|
3431
3514
|
maker: offer.maker,
|
|
3432
|
-
assets: offer.assets.toString(),
|
|
3433
3515
|
obligationUnits: offer.obligationUnits.toString(),
|
|
3434
|
-
obligationShares: offer.obligationShares.toString(),
|
|
3435
3516
|
tick: offer.tick,
|
|
3436
3517
|
maturity: Number(offer.maturity),
|
|
3518
|
+
rcfThreshold: offer.rcfThreshold.toString(),
|
|
3437
3519
|
expiry: Number(offer.expiry),
|
|
3438
3520
|
start: Number(offer.start),
|
|
3439
3521
|
group: offer.group,
|
|
@@ -3443,13 +3525,15 @@ const serialize = (offer) => ({
|
|
|
3443
3525
|
collaterals: offer.collaterals.map((c) => ({
|
|
3444
3526
|
asset: c.asset,
|
|
3445
3527
|
oracle: c.oracle,
|
|
3446
|
-
lltv: c.lltv.toString()
|
|
3528
|
+
lltv: c.lltv.toString(),
|
|
3529
|
+
maxLif: c.maxLif.toString()
|
|
3447
3530
|
})),
|
|
3448
3531
|
callback: {
|
|
3449
3532
|
address: offer.callback.address,
|
|
3450
3533
|
data: offer.callback.data
|
|
3451
3534
|
},
|
|
3452
3535
|
receiverIfMakerIsSeller: offer.receiverIfMakerIsSeller,
|
|
3536
|
+
exitOnly: offer.exitOnly,
|
|
3453
3537
|
hash: hash(offer)
|
|
3454
3538
|
});
|
|
3455
3539
|
/**
|
|
@@ -3486,7 +3570,7 @@ function random$1(config) {
|
|
|
3486
3570
|
const loanTokenDecimals = config?.assetsDecimals?.[loanToken] ?? 18;
|
|
3487
3571
|
const unit = BigInt(10) ** BigInt(loanTokenDecimals);
|
|
3488
3572
|
const amountBase = BigInt(100 + int(999901));
|
|
3489
|
-
const
|
|
3573
|
+
const obligationUnitsScaled = config?.obligationUnits ?? amountBase * unit;
|
|
3490
3574
|
const emptyCallback = {
|
|
3491
3575
|
address: zeroAddress,
|
|
3492
3576
|
data: "0x"
|
|
@@ -3494,11 +3578,10 @@ function random$1(config) {
|
|
|
3494
3578
|
const maker = config?.maker ?? address();
|
|
3495
3579
|
return from$7({
|
|
3496
3580
|
maker,
|
|
3497
|
-
|
|
3498
|
-
obligationUnits: config?.obligationUnits ?? 0n,
|
|
3499
|
-
obligationShares: config?.obligationShares ?? 0n,
|
|
3581
|
+
obligationUnits: obligationUnitsScaled,
|
|
3500
3582
|
tick,
|
|
3501
3583
|
maturity,
|
|
3584
|
+
rcfThreshold: config?.rcfThreshold ?? 0n,
|
|
3502
3585
|
expiry: config?.expiry ?? maturity - 1,
|
|
3503
3586
|
start: config?.start ?? maturity - 10,
|
|
3504
3587
|
group: config?.group ?? hex(32),
|
|
@@ -3510,7 +3593,8 @@ function random$1(config) {
|
|
|
3510
3593
|
lltv
|
|
3511
3594
|
})).sort((a, b) => a.asset.localeCompare(b.asset)),
|
|
3512
3595
|
callback: config?.callback ?? emptyCallback,
|
|
3513
|
-
receiverIfMakerIsSeller: config?.receiverIfMakerIsSeller ?? maker
|
|
3596
|
+
receiverIfMakerIsSeller: config?.receiverIfMakerIsSeller ?? maker,
|
|
3597
|
+
exitOnly: config?.exitOnly ?? false
|
|
3514
3598
|
});
|
|
3515
3599
|
}
|
|
3516
3600
|
const weightedChoice = (pairs) => {
|
|
@@ -3537,124 +3621,150 @@ function hash(offer) {
|
|
|
3537
3621
|
return computed;
|
|
3538
3622
|
}
|
|
3539
3623
|
/**
|
|
3540
|
-
*
|
|
3541
|
-
*
|
|
3542
|
-
*
|
|
3543
|
-
*
|
|
3544
|
-
*
|
|
3624
|
+
* ABI layout matching the Solidity `Offer` struct used by `abi.encode(offer)` in the contract.
|
|
3625
|
+
*
|
|
3626
|
+
* This is a **single top-level tuple** — Solidity's `abi.encode(struct)` encodes the struct as one
|
|
3627
|
+
* tuple parameter, not as separate parameters per field. Field order and nesting must exactly
|
|
3628
|
+
* mirror `contracts/interfaces/IMidnight.sol`:
|
|
3629
|
+
*
|
|
3630
|
+
* ```
|
|
3631
|
+
* struct Offer {
|
|
3632
|
+
* Obligation obligation; // nested tuple
|
|
3633
|
+
* bool buy;
|
|
3634
|
+
* address maker;
|
|
3635
|
+
* uint256 obligationUnits;
|
|
3636
|
+
* uint256 start;
|
|
3637
|
+
* uint256 expiry;
|
|
3638
|
+
* uint256 tick;
|
|
3639
|
+
* bytes32 group;
|
|
3640
|
+
* bytes32 session;
|
|
3641
|
+
* address callback;
|
|
3642
|
+
* bytes callbackData;
|
|
3643
|
+
* address receiverIfMakerIsSeller;
|
|
3644
|
+
* bool exitOnly;
|
|
3645
|
+
* }
|
|
3646
|
+
* ```
|
|
3545
3647
|
*/
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
type: "bool"
|
|
3597
|
-
},
|
|
3598
|
-
{
|
|
3599
|
-
name: "loanToken",
|
|
3600
|
-
type: "address"
|
|
3601
|
-
},
|
|
3602
|
-
{
|
|
3603
|
-
name: "start",
|
|
3604
|
-
type: "uint256"
|
|
3605
|
-
},
|
|
3606
|
-
{
|
|
3607
|
-
name: "collaterals",
|
|
3608
|
-
type: "tuple[]",
|
|
3609
|
-
components: [
|
|
3610
|
-
{
|
|
3611
|
-
name: "asset",
|
|
3612
|
-
type: "address"
|
|
3613
|
-
},
|
|
3614
|
-
{
|
|
3615
|
-
name: "oracle",
|
|
3616
|
-
type: "address"
|
|
3617
|
-
},
|
|
3618
|
-
{
|
|
3619
|
-
name: "lltv",
|
|
3620
|
-
type: "uint256"
|
|
3621
|
-
}
|
|
3622
|
-
]
|
|
3623
|
-
},
|
|
3624
|
-
{
|
|
3625
|
-
name: "callback",
|
|
3626
|
-
type: "tuple",
|
|
3627
|
-
components: [{
|
|
3628
|
-
name: "address",
|
|
3648
|
+
const OfferAbi = [{
|
|
3649
|
+
name: "offer",
|
|
3650
|
+
type: "tuple",
|
|
3651
|
+
components: [
|
|
3652
|
+
{
|
|
3653
|
+
name: "obligation",
|
|
3654
|
+
type: "tuple",
|
|
3655
|
+
components: [
|
|
3656
|
+
{
|
|
3657
|
+
name: "loanToken",
|
|
3658
|
+
type: "address"
|
|
3659
|
+
},
|
|
3660
|
+
{
|
|
3661
|
+
name: "collaterals",
|
|
3662
|
+
type: "tuple[]",
|
|
3663
|
+
components: [
|
|
3664
|
+
{
|
|
3665
|
+
name: "token",
|
|
3666
|
+
type: "address"
|
|
3667
|
+
},
|
|
3668
|
+
{
|
|
3669
|
+
name: "lltv",
|
|
3670
|
+
type: "uint256"
|
|
3671
|
+
},
|
|
3672
|
+
{
|
|
3673
|
+
name: "maxLif",
|
|
3674
|
+
type: "uint256"
|
|
3675
|
+
},
|
|
3676
|
+
{
|
|
3677
|
+
name: "oracle",
|
|
3678
|
+
type: "address"
|
|
3679
|
+
}
|
|
3680
|
+
]
|
|
3681
|
+
},
|
|
3682
|
+
{
|
|
3683
|
+
name: "maturity",
|
|
3684
|
+
type: "uint256"
|
|
3685
|
+
},
|
|
3686
|
+
{
|
|
3687
|
+
name: "rcfThreshold",
|
|
3688
|
+
type: "uint256"
|
|
3689
|
+
}
|
|
3690
|
+
]
|
|
3691
|
+
},
|
|
3692
|
+
{
|
|
3693
|
+
name: "buy",
|
|
3694
|
+
type: "bool"
|
|
3695
|
+
},
|
|
3696
|
+
{
|
|
3697
|
+
name: "maker",
|
|
3629
3698
|
type: "address"
|
|
3630
|
-
},
|
|
3631
|
-
|
|
3699
|
+
},
|
|
3700
|
+
{
|
|
3701
|
+
name: "obligationUnits",
|
|
3702
|
+
type: "uint256"
|
|
3703
|
+
},
|
|
3704
|
+
{
|
|
3705
|
+
name: "start",
|
|
3706
|
+
type: "uint256"
|
|
3707
|
+
},
|
|
3708
|
+
{
|
|
3709
|
+
name: "expiry",
|
|
3710
|
+
type: "uint256"
|
|
3711
|
+
},
|
|
3712
|
+
{
|
|
3713
|
+
name: "tick",
|
|
3714
|
+
type: "uint256"
|
|
3715
|
+
},
|
|
3716
|
+
{
|
|
3717
|
+
name: "group",
|
|
3718
|
+
type: "bytes32"
|
|
3719
|
+
},
|
|
3720
|
+
{
|
|
3721
|
+
name: "session",
|
|
3722
|
+
type: "bytes32"
|
|
3723
|
+
},
|
|
3724
|
+
{
|
|
3725
|
+
name: "callback",
|
|
3726
|
+
type: "address"
|
|
3727
|
+
},
|
|
3728
|
+
{
|
|
3729
|
+
name: "callbackData",
|
|
3632
3730
|
type: "bytes"
|
|
3633
|
-
}
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3731
|
+
},
|
|
3732
|
+
{
|
|
3733
|
+
name: "receiverIfMakerIsSeller",
|
|
3734
|
+
type: "address"
|
|
3735
|
+
},
|
|
3736
|
+
{
|
|
3737
|
+
name: "exitOnly",
|
|
3738
|
+
type: "bool"
|
|
3739
|
+
}
|
|
3740
|
+
]
|
|
3741
|
+
}];
|
|
3640
3742
|
function encode$1(offer) {
|
|
3641
|
-
return encodeAbiParameters(OfferAbi, [
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
offer.
|
|
3655
|
-
offer.
|
|
3656
|
-
offer.
|
|
3657
|
-
|
|
3743
|
+
return encodeAbiParameters(OfferAbi, [{
|
|
3744
|
+
obligation: {
|
|
3745
|
+
loanToken: offer.loanToken,
|
|
3746
|
+
collaterals: offer.collaterals.map((c) => ({
|
|
3747
|
+
token: c.asset,
|
|
3748
|
+
lltv: c.lltv,
|
|
3749
|
+
maxLif: c.maxLif ?? 0n,
|
|
3750
|
+
oracle: c.oracle
|
|
3751
|
+
})),
|
|
3752
|
+
maturity: BigInt(offer.maturity),
|
|
3753
|
+
rcfThreshold: offer.rcfThreshold
|
|
3754
|
+
},
|
|
3755
|
+
buy: offer.buy,
|
|
3756
|
+
maker: offer.maker,
|
|
3757
|
+
obligationUnits: offer.obligationUnits,
|
|
3758
|
+
start: BigInt(offer.start),
|
|
3759
|
+
expiry: BigInt(offer.expiry),
|
|
3760
|
+
tick: BigInt(offer.tick),
|
|
3761
|
+
group: offer.group,
|
|
3762
|
+
session: offer.session,
|
|
3763
|
+
callback: offer.callback.address,
|
|
3764
|
+
callbackData: offer.callback.data,
|
|
3765
|
+
receiverIfMakerIsSeller: offer.receiverIfMakerIsSeller,
|
|
3766
|
+
exitOnly: offer.exitOnly
|
|
3767
|
+
}]);
|
|
3658
3768
|
}
|
|
3659
3769
|
function decode$1(data) {
|
|
3660
3770
|
let decoded;
|
|
@@ -3663,31 +3773,33 @@ function decode$1(data) {
|
|
|
3663
3773
|
} catch (error) {
|
|
3664
3774
|
throw new InvalidOfferError(error);
|
|
3665
3775
|
}
|
|
3776
|
+
const s = decoded[0];
|
|
3666
3777
|
return from$7({
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
obligationUnits: decoded[2],
|
|
3670
|
-
obligationShares: decoded[3],
|
|
3671
|
-
tick: Number(decoded[4]),
|
|
3672
|
-
maturity: from$9(Number(decoded[5])),
|
|
3673
|
-
expiry: Number(decoded[6]),
|
|
3674
|
-
group: decoded[7],
|
|
3675
|
-
session: decoded[8],
|
|
3676
|
-
buy: decoded[9],
|
|
3677
|
-
loanToken: decoded[10],
|
|
3678
|
-
start: Number(decoded[11]),
|
|
3679
|
-
collaterals: decoded[12].map((c) => {
|
|
3778
|
+
loanToken: s.obligation.loanToken,
|
|
3779
|
+
collaterals: s.obligation.collaterals.map((c) => {
|
|
3680
3780
|
return from$10({
|
|
3681
|
-
asset: c.
|
|
3781
|
+
asset: c.token,
|
|
3682
3782
|
oracle: c.oracle,
|
|
3683
|
-
lltv: c.lltv
|
|
3783
|
+
lltv: c.lltv,
|
|
3784
|
+
maxLif: c.maxLif
|
|
3684
3785
|
});
|
|
3685
3786
|
}),
|
|
3787
|
+
maturity: from$9(Number(s.obligation.maturity)),
|
|
3788
|
+
rcfThreshold: s.obligation.rcfThreshold,
|
|
3789
|
+
buy: s.buy,
|
|
3790
|
+
maker: s.maker,
|
|
3791
|
+
obligationUnits: s.obligationUnits,
|
|
3792
|
+
start: Number(s.start),
|
|
3793
|
+
expiry: Number(s.expiry),
|
|
3794
|
+
tick: Number(s.tick),
|
|
3795
|
+
group: s.group,
|
|
3796
|
+
session: s.session,
|
|
3686
3797
|
callback: {
|
|
3687
|
-
address:
|
|
3688
|
-
data:
|
|
3798
|
+
address: s.callback,
|
|
3799
|
+
data: s.callbackData
|
|
3689
3800
|
},
|
|
3690
|
-
receiverIfMakerIsSeller:
|
|
3801
|
+
receiverIfMakerIsSeller: s.receiverIfMakerIsSeller,
|
|
3802
|
+
exitOnly: s.exitOnly
|
|
3691
3803
|
});
|
|
3692
3804
|
}
|
|
3693
3805
|
/**
|
|
@@ -3705,9 +3817,9 @@ const takeEvent = {
|
|
|
3705
3817
|
},
|
|
3706
3818
|
{
|
|
3707
3819
|
name: "id_",
|
|
3708
|
-
type: "
|
|
3820
|
+
type: "bytes32",
|
|
3709
3821
|
indexed: true,
|
|
3710
|
-
internalType: "
|
|
3822
|
+
internalType: "bytes32"
|
|
3711
3823
|
},
|
|
3712
3824
|
{
|
|
3713
3825
|
name: "maker",
|
|
@@ -3745,24 +3857,6 @@ const takeEvent = {
|
|
|
3745
3857
|
indexed: false,
|
|
3746
3858
|
internalType: "uint256"
|
|
3747
3859
|
},
|
|
3748
|
-
{
|
|
3749
|
-
name: "obligationShares",
|
|
3750
|
-
type: "uint256",
|
|
3751
|
-
indexed: false,
|
|
3752
|
-
internalType: "uint256"
|
|
3753
|
-
},
|
|
3754
|
-
{
|
|
3755
|
-
name: "buyerIsLender",
|
|
3756
|
-
type: "bool",
|
|
3757
|
-
indexed: false,
|
|
3758
|
-
internalType: "bool"
|
|
3759
|
-
},
|
|
3760
|
-
{
|
|
3761
|
-
name: "sellerIsBorrower",
|
|
3762
|
-
type: "bool",
|
|
3763
|
-
indexed: false,
|
|
3764
|
-
internalType: "bool"
|
|
3765
|
-
},
|
|
3766
3860
|
{
|
|
3767
3861
|
name: "sellerReceiver",
|
|
3768
3862
|
type: "address",
|
|
@@ -3780,19 +3874,31 @@ const takeEvent = {
|
|
|
3780
3874
|
type: "uint256",
|
|
3781
3875
|
indexed: false,
|
|
3782
3876
|
internalType: "uint256"
|
|
3877
|
+
},
|
|
3878
|
+
{
|
|
3879
|
+
name: "totalUnits",
|
|
3880
|
+
type: "uint256",
|
|
3881
|
+
indexed: false,
|
|
3882
|
+
internalType: "uint256"
|
|
3783
3883
|
}
|
|
3784
3884
|
],
|
|
3785
3885
|
anonymous: false
|
|
3786
3886
|
};
|
|
3787
3887
|
/**
|
|
3788
|
-
* ABI for the
|
|
3888
|
+
* ABI for the SetConsumed event emitted by the Morpho V2 contract.
|
|
3789
3889
|
*/
|
|
3790
3890
|
const consumedEvent = {
|
|
3791
3891
|
type: "event",
|
|
3792
|
-
name: "
|
|
3892
|
+
name: "SetConsumed",
|
|
3793
3893
|
inputs: [
|
|
3794
3894
|
{
|
|
3795
|
-
name: "
|
|
3895
|
+
name: "caller",
|
|
3896
|
+
type: "address",
|
|
3897
|
+
indexed: true,
|
|
3898
|
+
internalType: "address"
|
|
3899
|
+
},
|
|
3900
|
+
{
|
|
3901
|
+
name: "onBehalf",
|
|
3796
3902
|
type: "address",
|
|
3797
3903
|
indexed: true,
|
|
3798
3904
|
internalType: "address"
|
|
@@ -3827,9 +3933,9 @@ const repayEvent = {
|
|
|
3827
3933
|
},
|
|
3828
3934
|
{
|
|
3829
3935
|
name: "id_",
|
|
3830
|
-
type: "
|
|
3936
|
+
type: "bytes32",
|
|
3831
3937
|
indexed: true,
|
|
3832
|
-
internalType: "
|
|
3938
|
+
internalType: "bytes32"
|
|
3833
3939
|
},
|
|
3834
3940
|
{
|
|
3835
3941
|
name: "obligationUnits",
|
|
@@ -3861,9 +3967,9 @@ const liquidateEvent = {
|
|
|
3861
3967
|
},
|
|
3862
3968
|
{
|
|
3863
3969
|
name: "id_",
|
|
3864
|
-
type: "
|
|
3970
|
+
type: "bytes32",
|
|
3865
3971
|
indexed: true,
|
|
3866
|
-
internalType: "
|
|
3972
|
+
internalType: "bytes32"
|
|
3867
3973
|
},
|
|
3868
3974
|
{
|
|
3869
3975
|
name: "collateralIndex",
|
|
@@ -3894,6 +4000,12 @@ const liquidateEvent = {
|
|
|
3894
4000
|
type: "uint256",
|
|
3895
4001
|
indexed: false,
|
|
3896
4002
|
internalType: "uint256"
|
|
4003
|
+
},
|
|
4004
|
+
{
|
|
4005
|
+
name: "latestLossIndex",
|
|
4006
|
+
type: "uint256",
|
|
4007
|
+
indexed: false,
|
|
4008
|
+
internalType: "uint256"
|
|
3897
4009
|
}
|
|
3898
4010
|
],
|
|
3899
4011
|
anonymous: false
|
|
@@ -3913,9 +4025,9 @@ const supplyCollateralEvent = {
|
|
|
3913
4025
|
},
|
|
3914
4026
|
{
|
|
3915
4027
|
name: "id_",
|
|
3916
|
-
type: "
|
|
4028
|
+
type: "bytes32",
|
|
3917
4029
|
indexed: true,
|
|
3918
|
-
internalType: "
|
|
4030
|
+
internalType: "bytes32"
|
|
3919
4031
|
},
|
|
3920
4032
|
{
|
|
3921
4033
|
name: "collateral",
|
|
@@ -3953,9 +4065,9 @@ const withdrawCollateralEvent = {
|
|
|
3953
4065
|
},
|
|
3954
4066
|
{
|
|
3955
4067
|
name: "id_",
|
|
3956
|
-
type: "
|
|
4068
|
+
type: "bytes32",
|
|
3957
4069
|
indexed: true,
|
|
3958
|
-
internalType: "
|
|
4070
|
+
internalType: "bytes32"
|
|
3959
4071
|
},
|
|
3960
4072
|
{
|
|
3961
4073
|
name: "collateral",
|
|
@@ -4228,7 +4340,7 @@ var TradingFee_exports = /* @__PURE__ */ __exportAll({
|
|
|
4228
4340
|
});
|
|
4229
4341
|
/**
|
|
4230
4342
|
* Time breakpoints in seconds for piecewise linear fee interpolation.
|
|
4231
|
-
* Matches on-chain constants: 0d, 1d, 7d, 30d, 90d, 180d.
|
|
4343
|
+
* Matches on-chain constants: 0d, 1d, 7d, 30d, 90d, 180d, 360d.
|
|
4232
4344
|
*/
|
|
4233
4345
|
const BREAKPOINTS = [
|
|
4234
4346
|
0n,
|
|
@@ -4236,21 +4348,22 @@ const BREAKPOINTS = [
|
|
|
4236
4348
|
604800n,
|
|
4237
4349
|
2592000n,
|
|
4238
4350
|
7776000n,
|
|
4239
|
-
15552000n
|
|
4351
|
+
15552000n,
|
|
4352
|
+
31104000n
|
|
4240
4353
|
];
|
|
4241
4354
|
/** WAD constant (1e18) for fee scaling. */
|
|
4242
4355
|
const WAD = 10n ** 18n;
|
|
4243
4356
|
/**
|
|
4244
|
-
* Create a TradingFee from an activation flag and
|
|
4357
|
+
* Create a TradingFee from an activation flag and 7 fee values.
|
|
4245
4358
|
* @param activated - Whether the fee is active.
|
|
4246
|
-
* @param fees - Tuple of
|
|
4359
|
+
* @param fees - Tuple of 7 fee values in WAD (one per breakpoint: 0d, 1d, 7d, 30d, 90d, 180d, 360d).
|
|
4247
4360
|
* @returns A new TradingFee instance.
|
|
4248
4361
|
* @throws {@link InvalidFeeError} if any fee exceeds WAD (100%).
|
|
4249
|
-
* @throws {@link InvalidFeesLengthError} if fees array doesn't have exactly
|
|
4362
|
+
* @throws {@link InvalidFeesLengthError} if fees array doesn't have exactly 7 elements.
|
|
4250
4363
|
*/
|
|
4251
4364
|
function from$3(activated, fees) {
|
|
4252
|
-
if (fees.length !==
|
|
4253
|
-
for (let i = 0; i <
|
|
4365
|
+
if (fees.length !== 7) throw new InvalidFeesLengthError(fees.length);
|
|
4366
|
+
for (let i = 0; i < 7; i++) {
|
|
4254
4367
|
const fee = fees[i];
|
|
4255
4368
|
if (fee < 0n || fee > WAD) throw new InvalidFeeError(fee, i);
|
|
4256
4369
|
}
|
|
@@ -4269,7 +4382,9 @@ function from$3(activated, fees) {
|
|
|
4269
4382
|
function compute(tradingFee, timeToMaturity) {
|
|
4270
4383
|
if (!tradingFee._activated) return 0n;
|
|
4271
4384
|
const time = BigInt(Math.max(0, Math.floor(timeToMaturity)));
|
|
4272
|
-
|
|
4385
|
+
const maxBreakpoint = BREAKPOINTS[BREAKPOINTS.length - 1];
|
|
4386
|
+
const maxFee = tradingFee._fees[tradingFee._fees.length - 1];
|
|
4387
|
+
if (time >= maxBreakpoint) return maxFee;
|
|
4273
4388
|
const { index, start, end } = getSegment(time);
|
|
4274
4389
|
const feeLower = tradingFee._fees[index];
|
|
4275
4390
|
const feeUpper = tradingFee._fees[index + 1];
|
|
@@ -4309,7 +4424,7 @@ function deactivate(tradingFee) {
|
|
|
4309
4424
|
/**
|
|
4310
4425
|
* Get the fee values at each breakpoint.
|
|
4311
4426
|
* @param tradingFee - The TradingFee instance.
|
|
4312
|
-
* @returns The tuple of
|
|
4427
|
+
* @returns The tuple of 7 fee values.
|
|
4313
4428
|
*/
|
|
4314
4429
|
function getFees(tradingFee) {
|
|
4315
4430
|
return tradingFee._fees;
|
|
@@ -4320,30 +4435,21 @@ function getFees(tradingFee) {
|
|
|
4320
4435
|
* @returns Object with index, start, and end of the segment.
|
|
4321
4436
|
*/
|
|
4322
4437
|
function getSegment(timeToMaturity) {
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
index: 2,
|
|
4335
|
-
start: BREAKPOINTS[2],
|
|
4336
|
-
end: BREAKPOINTS[3]
|
|
4337
|
-
};
|
|
4338
|
-
if (timeToMaturity < BREAKPOINTS[4]) return {
|
|
4339
|
-
index: 3,
|
|
4340
|
-
start: BREAKPOINTS[3],
|
|
4341
|
-
end: BREAKPOINTS[4]
|
|
4342
|
-
};
|
|
4438
|
+
for (let segmentEndIndex = 1; segmentEndIndex < BREAKPOINTS.length; segmentEndIndex++) {
|
|
4439
|
+
const end = BREAKPOINTS[segmentEndIndex];
|
|
4440
|
+
if (timeToMaturity < end) {
|
|
4441
|
+
const index = segmentEndIndex - 1;
|
|
4442
|
+
return {
|
|
4443
|
+
index,
|
|
4444
|
+
start: BREAKPOINTS[index],
|
|
4445
|
+
end
|
|
4446
|
+
};
|
|
4447
|
+
}
|
|
4448
|
+
}
|
|
4343
4449
|
return {
|
|
4344
|
-
index:
|
|
4345
|
-
start: BREAKPOINTS[
|
|
4346
|
-
end: BREAKPOINTS[
|
|
4450
|
+
index: BREAKPOINTS.length - 2,
|
|
4451
|
+
start: BREAKPOINTS[BREAKPOINTS.length - 2],
|
|
4452
|
+
end: BREAKPOINTS[BREAKPOINTS.length - 1]
|
|
4347
4453
|
};
|
|
4348
4454
|
}
|
|
4349
4455
|
/** Error thrown when a fee value is invalid (negative or exceeds WAD). */
|
|
@@ -4353,11 +4459,11 @@ var InvalidFeeError = class extends BaseError {
|
|
|
4353
4459
|
super(`Invalid fee at index ${index}: ${fee}. Fee must be between 0 and ${WAD} (WAD).`);
|
|
4354
4460
|
}
|
|
4355
4461
|
};
|
|
4356
|
-
/** Error thrown when fees array doesn't have exactly
|
|
4462
|
+
/** Error thrown when fees array doesn't have exactly 7 elements. */
|
|
4357
4463
|
var InvalidFeesLengthError = class extends BaseError {
|
|
4358
4464
|
name = "TradingFee.InvalidFeesLengthError";
|
|
4359
4465
|
constructor(length) {
|
|
4360
|
-
super(`Invalid fees length: ${length}. Expected exactly
|
|
4466
|
+
super(`Invalid fees length: ${length}. Expected exactly 7 fee values.`);
|
|
4361
4467
|
}
|
|
4362
4468
|
};
|
|
4363
4469
|
|
|
@@ -4395,6 +4501,9 @@ function from$2(parameters) {
|
|
|
4395
4501
|
var Tree_exports = /* @__PURE__ */ __exportAll({
|
|
4396
4502
|
DecodeError: () => DecodeError,
|
|
4397
4503
|
EncodeError: () => EncodeError,
|
|
4504
|
+
MAX_COMPRESSED_OFFERS_BYTES: () => MAX_COMPRESSED_OFFERS_BYTES,
|
|
4505
|
+
MAX_DECOMPRESSED_OFFERS_BYTES: () => MAX_DECOMPRESSED_OFFERS_BYTES,
|
|
4506
|
+
MAX_OFFERS_PER_TREE: () => MAX_OFFERS_PER_TREE,
|
|
4398
4507
|
SignatureDomainError: () => SignatureDomainError,
|
|
4399
4508
|
TreeError: () => TreeError,
|
|
4400
4509
|
VERSION: () => VERSION$1,
|
|
@@ -4406,7 +4515,16 @@ var Tree_exports = /* @__PURE__ */ __exportAll({
|
|
|
4406
4515
|
signatureDomain: () => signatureDomain,
|
|
4407
4516
|
signatureTypes: () => signatureTypes
|
|
4408
4517
|
});
|
|
4409
|
-
const VERSION$1 =
|
|
4518
|
+
const VERSION$1 = 2;
|
|
4519
|
+
const MAX_COMPRESSED_OFFERS_BYTES = 1e6;
|
|
4520
|
+
const MAX_DECOMPRESSED_OFFERS_BYTES = 4e6;
|
|
4521
|
+
const MAX_OFFERS_PER_TREE = 100;
|
|
4522
|
+
const ROOT_BYTES = 32;
|
|
4523
|
+
const SIGNATURE_BYTES = 65;
|
|
4524
|
+
const MIN_SIGNED_PAYLOAD_BYTES = 1 + ROOT_BYTES + SIGNATURE_BYTES;
|
|
4525
|
+
const INFLATE_INPUT_CHUNK_BYTES = 64 * 1024;
|
|
4526
|
+
const UTF8_ENCODER = new TextEncoder();
|
|
4527
|
+
const UTF8_DECODER = new TextDecoder();
|
|
4410
4528
|
/**
|
|
4411
4529
|
* EIP-712 types for signing the tree root (Root(bytes32 root)).
|
|
4412
4530
|
*/
|
|
@@ -4423,29 +4541,83 @@ const signatureTypes = {
|
|
|
4423
4541
|
type: "bytes32"
|
|
4424
4542
|
}]
|
|
4425
4543
|
};
|
|
4426
|
-
const
|
|
4544
|
+
const gzipOffersPayload = (payload, errorFactory) => {
|
|
4545
|
+
const payloadBytes = UTF8_ENCODER.encode(payload);
|
|
4546
|
+
if (payloadBytes.length > MAX_DECOMPRESSED_OFFERS_BYTES) throw errorFactory(`decompressed offers exceed ${MAX_DECOMPRESSED_OFFERS_BYTES} bytes`);
|
|
4547
|
+
try {
|
|
4548
|
+
const compressed = gzip(payloadBytes);
|
|
4549
|
+
if (compressed.length > MAX_COMPRESSED_OFFERS_BYTES) throw errorFactory(`compressed offers exceed ${MAX_COMPRESSED_OFFERS_BYTES} bytes`);
|
|
4550
|
+
return compressed;
|
|
4551
|
+
} catch (error) {
|
|
4552
|
+
if (error instanceof BaseError) throw error;
|
|
4553
|
+
throw errorFactory("compression failed");
|
|
4554
|
+
}
|
|
4555
|
+
};
|
|
4556
|
+
const gunzipOffersPayload = (compressed, errorFactory) => {
|
|
4557
|
+
if (compressed.length === 0) throw errorFactory("decompression failed");
|
|
4558
|
+
if (compressed.length > MAX_COMPRESSED_OFFERS_BYTES) throw errorFactory(`compressed offers exceed ${MAX_COMPRESSED_OFFERS_BYTES} bytes`);
|
|
4559
|
+
let totalLength = 0;
|
|
4560
|
+
const inflate = new Inflate();
|
|
4561
|
+
const defaultOnData = inflate.onData.bind(inflate);
|
|
4562
|
+
inflate.onData = (chunk) => {
|
|
4563
|
+
totalLength += chunk.length;
|
|
4564
|
+
if (totalLength > MAX_DECOMPRESSED_OFFERS_BYTES) throw errorFactory(`decompressed offers exceed ${MAX_DECOMPRESSED_OFFERS_BYTES} bytes`);
|
|
4565
|
+
defaultOnData(chunk);
|
|
4566
|
+
};
|
|
4567
|
+
try {
|
|
4568
|
+
for (let offset = 0; offset < compressed.length; offset += INFLATE_INPUT_CHUNK_BYTES) {
|
|
4569
|
+
const end = Math.min(offset + INFLATE_INPUT_CHUNK_BYTES, compressed.length);
|
|
4570
|
+
inflate.push(compressed.subarray(offset, end), end === compressed.length);
|
|
4571
|
+
}
|
|
4572
|
+
} catch (error) {
|
|
4573
|
+
if (error instanceof BaseError) throw error;
|
|
4574
|
+
throw errorFactory("decompression failed");
|
|
4575
|
+
}
|
|
4576
|
+
if (inflate.err !== 0) throw errorFactory(inflate.msg || "decompression failed");
|
|
4577
|
+
if (!(inflate.result instanceof Uint8Array)) throw errorFactory("decompression failed");
|
|
4578
|
+
return UTF8_DECODER.decode(inflate.result);
|
|
4579
|
+
};
|
|
4580
|
+
const parseRawOffersPayload = (decoded, errorFactory) => {
|
|
4581
|
+
let rawOffers;
|
|
4582
|
+
try {
|
|
4583
|
+
rawOffers = JSON.parse(decoded);
|
|
4584
|
+
} catch {
|
|
4585
|
+
throw errorFactory("JSON parse failed");
|
|
4586
|
+
}
|
|
4587
|
+
if (!Array.isArray(rawOffers)) throw errorFactory("offers payload must be a JSON array");
|
|
4588
|
+
if (rawOffers.length > MAX_OFFERS_PER_TREE) throw errorFactory(`offers payload exceeds ${MAX_OFFERS_PER_TREE} offers`);
|
|
4589
|
+
return rawOffers;
|
|
4590
|
+
};
|
|
4591
|
+
const assertUniqueOfferHashes = (offers, errorFactory) => {
|
|
4592
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4593
|
+
for (const offer of offers) {
|
|
4594
|
+
const hash$1 = hash(offer);
|
|
4595
|
+
if (seen.has(hash$1)) throw errorFactory(`duplicate offer hash ${hash$1}`);
|
|
4596
|
+
seen.add(hash$1);
|
|
4597
|
+
}
|
|
4598
|
+
};
|
|
4427
4599
|
/**
|
|
4428
4600
|
* Builds a Merkle tree from a list of offers.
|
|
4429
4601
|
*
|
|
4430
4602
|
* Leaves are the offer `hash` values as `bytes32` and are deterministically
|
|
4431
|
-
* ordered
|
|
4432
|
-
* root is stable regardless of the input order.
|
|
4603
|
+
* ordered so that the resulting root is stable regardless of the input order.
|
|
4433
4604
|
*
|
|
4434
4605
|
* @param offers - Offers to include in the tree.
|
|
4435
|
-
* @returns A `
|
|
4606
|
+
* @returns A `SimpleMerkleTree` of offer hashes representing the offers.
|
|
4436
4607
|
* @throws {TreeError} If tree building fails due to offer inconsistencies.
|
|
4437
4608
|
*/
|
|
4438
4609
|
const from$1 = (offers) => {
|
|
4439
|
-
|
|
4440
|
-
const
|
|
4610
|
+
assertUniqueOfferHashes(offers, (reason) => new TreeError(reason));
|
|
4611
|
+
const leaves = offers.map((offer) => hash(offer));
|
|
4612
|
+
const tree = SimpleMerkleTree.of(leaves);
|
|
4441
4613
|
const orderedOffers = orderOffers(tree, offers);
|
|
4442
4614
|
return Object.assign(tree, { offers: orderedOffers });
|
|
4443
4615
|
};
|
|
4444
4616
|
const orderOffers = (tree, offers) => {
|
|
4445
4617
|
const offerByHash = /* @__PURE__ */ new Map();
|
|
4446
|
-
for (const offer of offers) offerByHash.set(
|
|
4618
|
+
for (const offer of offers) offerByHash.set(hash(offer), offer);
|
|
4447
4619
|
const entries = tree.dump().values.map((value) => {
|
|
4448
|
-
const hash =
|
|
4620
|
+
const hash = value.value;
|
|
4449
4621
|
const offer = offerByHash.get(hash);
|
|
4450
4622
|
if (!offer) throw new TreeError(`missing offer for leaf ${hash}`);
|
|
4451
4623
|
return {
|
|
@@ -4460,7 +4632,7 @@ const orderOffers = (tree, offers) => {
|
|
|
4460
4632
|
* Generates merkle proofs for all offers in a tree.
|
|
4461
4633
|
*
|
|
4462
4634
|
* Each proof allows independent verification that an offer is included in the tree
|
|
4463
|
-
* without requiring the full tree.
|
|
4635
|
+
* without requiring the full tree.
|
|
4464
4636
|
*
|
|
4465
4637
|
* @param tree - The {@link Tree} to generate proofs for.
|
|
4466
4638
|
* @returns Array of proofs - {@link Proof}
|
|
@@ -4469,7 +4641,7 @@ const proofs = (tree) => {
|
|
|
4469
4641
|
return tree.offers.map((offer) => {
|
|
4470
4642
|
return {
|
|
4471
4643
|
offer,
|
|
4472
|
-
path: tree.getProof(
|
|
4644
|
+
path: tree.getProof(hash(offer))
|
|
4473
4645
|
};
|
|
4474
4646
|
});
|
|
4475
4647
|
};
|
|
@@ -4601,14 +4773,15 @@ const encodeUnsigned = (tree) => {
|
|
|
4601
4773
|
};
|
|
4602
4774
|
const validateTreeForEncoding = (tree) => {
|
|
4603
4775
|
if (VERSION$1 > 255) throw new EncodeError(`version overflow: ${VERSION$1} exceeds 255`);
|
|
4776
|
+
if (tree.offers.length > MAX_OFFERS_PER_TREE) throw new EncodeError(`offers payload exceeds ${MAX_OFFERS_PER_TREE} offers`);
|
|
4604
4777
|
const computed = from$1(tree.offers);
|
|
4605
4778
|
if (tree.root !== computed.root) throw new EncodeError(`root mismatch: expected ${computed.root}, got ${tree.root}`);
|
|
4606
4779
|
};
|
|
4607
4780
|
const encodeUnsignedBytes = (tree) => {
|
|
4608
4781
|
const offersPayload = tree.offers.map(serialize);
|
|
4609
|
-
const compressed =
|
|
4782
|
+
const compressed = gzipOffersPayload(JSON.stringify(offersPayload), (reason) => new EncodeError(reason));
|
|
4610
4783
|
const rootBytes = hexToBytes(tree.root);
|
|
4611
|
-
const encoded = new Uint8Array(1 + compressed.length +
|
|
4784
|
+
const encoded = new Uint8Array(1 + compressed.length + ROOT_BYTES);
|
|
4612
4785
|
encoded[0] = VERSION$1;
|
|
4613
4786
|
encoded.set(compressed, 1);
|
|
4614
4787
|
encoded.set(rootBytes, 1 + compressed.length);
|
|
@@ -4621,10 +4794,11 @@ const encodeUnsignedBytes = (tree) => {
|
|
|
4621
4794
|
* Returns the tree with separately validated signature and recovered signer address.
|
|
4622
4795
|
*
|
|
4623
4796
|
* Validation order:
|
|
4624
|
-
* 1. Version
|
|
4797
|
+
* 1. Version and static size checks
|
|
4625
4798
|
* 2. Signature verification (fail-fast, before decompression)
|
|
4626
|
-
* 3.
|
|
4627
|
-
* 4.
|
|
4799
|
+
* 3. Streaming decompression with byte cap
|
|
4800
|
+
* 4. JSON array + offer count checks
|
|
4801
|
+
* 5. Root verification (computed from offers vs embedded root)
|
|
4628
4802
|
*
|
|
4629
4803
|
* @example
|
|
4630
4804
|
* ```typescript
|
|
@@ -4641,33 +4815,20 @@ const decode = async (encoded, domain) => {
|
|
|
4641
4815
|
const errorFactory = (reason) => new DecodeError(reason);
|
|
4642
4816
|
const normalizedDomain = normalizeSignatureDomain(domain, errorFactory);
|
|
4643
4817
|
const bytes = hexToBytes(encoded);
|
|
4644
|
-
if (bytes.length <
|
|
4818
|
+
if (bytes.length < MIN_SIGNED_PAYLOAD_BYTES) throw new DecodeError("payload too short");
|
|
4645
4819
|
const version = bytes[0];
|
|
4646
4820
|
if (version !== (VERSION$1 & 255)) throw new DecodeError(`invalid version: expected ${VERSION$1}, got ${version ?? 0}`);
|
|
4647
|
-
const signature = bytesToHex(bytes.slice(-
|
|
4648
|
-
const root = bytesToHex(bytes.slice(-
|
|
4649
|
-
assertHex(root,
|
|
4650
|
-
assertHex(signature,
|
|
4821
|
+
const signature = bytesToHex(bytes.slice(-SIGNATURE_BYTES));
|
|
4822
|
+
const root = bytesToHex(bytes.slice(-(ROOT_BYTES + SIGNATURE_BYTES), -SIGNATURE_BYTES));
|
|
4823
|
+
assertHex(root, ROOT_BYTES, "root");
|
|
4824
|
+
assertHex(signature, SIGNATURE_BYTES, "signature");
|
|
4651
4825
|
const signer = await verifySignatureAndRecoverAddress({
|
|
4652
4826
|
root,
|
|
4653
4827
|
signature,
|
|
4654
4828
|
domain: normalizedDomain,
|
|
4655
4829
|
errorFactory
|
|
4656
4830
|
});
|
|
4657
|
-
const
|
|
4658
|
-
let decoded;
|
|
4659
|
-
try {
|
|
4660
|
-
decoded = ungzip(compressed, { to: "string" });
|
|
4661
|
-
} catch {
|
|
4662
|
-
throw new DecodeError("decompression failed");
|
|
4663
|
-
}
|
|
4664
|
-
let rawOffers;
|
|
4665
|
-
try {
|
|
4666
|
-
rawOffers = JSON.parse(decoded);
|
|
4667
|
-
} catch {
|
|
4668
|
-
throw new DecodeError("JSON parse failed");
|
|
4669
|
-
}
|
|
4670
|
-
const tree = from$1(rawOffers.map((o) => OfferSchema().parse(o)));
|
|
4831
|
+
const tree = from$1(parseRawOffersPayload(gunzipOffersPayload(bytes.slice(1, -(ROOT_BYTES + SIGNATURE_BYTES)), errorFactory), errorFactory).map((o) => OfferSchema().parse(o)));
|
|
4671
4832
|
if (root !== tree.root) throw new DecodeError(`root mismatch: expected ${tree.root}, got ${root}`);
|
|
4672
4833
|
return {
|
|
4673
4834
|
tree,
|
|
@@ -4786,11 +4947,10 @@ async function getOffers(apiClient, parameters) {
|
|
|
4786
4947
|
return {
|
|
4787
4948
|
...fromSnakeCase$1({
|
|
4788
4949
|
maker: offerData.maker,
|
|
4789
|
-
assets: offerData.assets,
|
|
4790
4950
|
obligation_units: offerData.obligation_units,
|
|
4791
|
-
obligation_shares: offerData.obligation_shares,
|
|
4792
4951
|
tick: offerData.tick,
|
|
4793
4952
|
maturity: from$9(offerData.obligation.maturity),
|
|
4953
|
+
rcf_threshold: offerData.obligation.rcf_threshold,
|
|
4794
4954
|
expiry: offerData.expiry,
|
|
4795
4955
|
start: offerData.start,
|
|
4796
4956
|
group: offerData.group,
|
|
@@ -4800,13 +4960,15 @@ async function getOffers(apiClient, parameters) {
|
|
|
4800
4960
|
collaterals: offerData.obligation.collaterals.map((collateral) => ({
|
|
4801
4961
|
asset: collateral.token,
|
|
4802
4962
|
oracle: collateral.oracle,
|
|
4803
|
-
lltv: collateral.lltv
|
|
4963
|
+
lltv: collateral.lltv,
|
|
4964
|
+
max_lif: collateral.max_lif
|
|
4804
4965
|
})),
|
|
4805
4966
|
callback: {
|
|
4806
4967
|
address: offerData.callback,
|
|
4807
4968
|
data: offerData.callback_data
|
|
4808
4969
|
},
|
|
4809
|
-
receiver_if_maker_is_seller: offerData.receiver_if_maker_is_seller
|
|
4970
|
+
receiver_if_maker_is_seller: offerData.receiver_if_maker_is_seller,
|
|
4971
|
+
exit_only: offerData.exit_only ?? false
|
|
4810
4972
|
}),
|
|
4811
4973
|
hash: item.offer_hash,
|
|
4812
4974
|
consumed: BigInt(item.consumed),
|
|
@@ -4847,9 +5009,11 @@ async function getObligations(apiClient, parameters) {
|
|
|
4847
5009
|
collaterals: item.collaterals.map((collateral) => ({
|
|
4848
5010
|
asset: collateral.token,
|
|
4849
5011
|
oracle: collateral.oracle,
|
|
4850
|
-
lltv: collateral.lltv
|
|
5012
|
+
lltv: collateral.lltv,
|
|
5013
|
+
max_lif: collateral.max_lif
|
|
4851
5014
|
})),
|
|
4852
|
-
maturity: from$9(item.maturity)
|
|
5015
|
+
maturity: from$9(item.maturity),
|
|
5016
|
+
rcf_threshold: item.rcf_threshold
|
|
4853
5017
|
});
|
|
4854
5018
|
const { obligationId: _, ...quote } = from$4({
|
|
4855
5019
|
obligationId: item.id,
|
|
@@ -5337,6 +5501,34 @@ function lazy(pollFn) {
|
|
|
5337
5501
|
})();
|
|
5338
5502
|
}
|
|
5339
5503
|
|
|
5504
|
+
//#endregion
|
|
5505
|
+
//#region src/utils/mapWithConcurrency.ts
|
|
5506
|
+
/**
|
|
5507
|
+
* Map values with a bounded number of concurrent async workers.
|
|
5508
|
+
*
|
|
5509
|
+
* Result ordering always matches the input order.
|
|
5510
|
+
* @param parameters - Input values, concurrency limit, and async mapper.
|
|
5511
|
+
* @returns Mapped results in input order.
|
|
5512
|
+
*/
|
|
5513
|
+
async function mapWithConcurrency(parameters) {
|
|
5514
|
+
const { values, limit, run } = parameters;
|
|
5515
|
+
if (values.length === 0) return [];
|
|
5516
|
+
const normalizedLimit = Math.max(1, Math.floor(limit));
|
|
5517
|
+
const workerCount = Math.min(normalizedLimit, values.length);
|
|
5518
|
+
const results = new Array(values.length);
|
|
5519
|
+
let nextIndex = 0;
|
|
5520
|
+
const worker = async () => {
|
|
5521
|
+
while (true) {
|
|
5522
|
+
const index = nextIndex;
|
|
5523
|
+
if (index >= values.length) return;
|
|
5524
|
+
nextIndex += 1;
|
|
5525
|
+
results[index] = await run(values[index], index);
|
|
5526
|
+
}
|
|
5527
|
+
};
|
|
5528
|
+
await Promise.all(Array.from({ length: workerCount }, () => worker()));
|
|
5529
|
+
return results;
|
|
5530
|
+
}
|
|
5531
|
+
|
|
5340
5532
|
//#endregion
|
|
5341
5533
|
//#region src/utils/wait.ts
|
|
5342
5534
|
async function wait(time) {
|
|
@@ -5378,6 +5570,20 @@ function max() {
|
|
|
5378
5570
|
return 0x77e772392b600000;
|
|
5379
5571
|
}
|
|
5380
5572
|
|
|
5573
|
+
//#endregion
|
|
5574
|
+
//#region src/utils/trim.ts
|
|
5575
|
+
/**
|
|
5576
|
+
* Keep the last `keep` entries from an array.
|
|
5577
|
+
* @param array - Source array.
|
|
5578
|
+
* @param keep - Number of entries to keep.
|
|
5579
|
+
* @returns Trimmed copy.
|
|
5580
|
+
*/
|
|
5581
|
+
const trimTail = (array, keep) => {
|
|
5582
|
+
if (!Number.isInteger(keep) || keep < 0) throw new Error(`trimTail: expected non-negative integer keep, got ${keep}`);
|
|
5583
|
+
if (array.length <= keep) return array.slice();
|
|
5584
|
+
return array.slice(array.length - keep);
|
|
5585
|
+
};
|
|
5586
|
+
|
|
5381
5587
|
//#endregion
|
|
5382
5588
|
//#region src/utils/index.ts
|
|
5383
5589
|
var utils_exports = /* @__PURE__ */ __exportAll({
|
|
@@ -5391,18 +5597,20 @@ var utils_exports = /* @__PURE__ */ __exportAll({
|
|
|
5391
5597
|
batchMulticall: () => batchMulticall,
|
|
5392
5598
|
fromSnakeCase: () => fromSnakeCase$3,
|
|
5393
5599
|
lazy: () => lazy,
|
|
5600
|
+
mapWithConcurrency: () => mapWithConcurrency,
|
|
5394
5601
|
max: () => max$1,
|
|
5395
5602
|
min: () => min,
|
|
5396
5603
|
poll: () => poll,
|
|
5397
5604
|
retry: () => retry,
|
|
5398
5605
|
stringifyBigint: () => stringifyBigint,
|
|
5399
5606
|
toSnakeCase: () => toSnakeCase$1,
|
|
5607
|
+
trimTail: () => trimTail,
|
|
5400
5608
|
wait: () => wait
|
|
5401
5609
|
});
|
|
5402
5610
|
|
|
5403
5611
|
//#endregion
|
|
5404
5612
|
//#region src/database/drizzle/VERSION.ts
|
|
5405
|
-
const VERSION = "router_v1.
|
|
5613
|
+
const VERSION = "router_v1.15";
|
|
5406
5614
|
|
|
5407
5615
|
//#endregion
|
|
5408
5616
|
//#region src/database/drizzle/schema.ts
|
|
@@ -5422,6 +5630,7 @@ var EnumTableName = /* @__PURE__ */ function(EnumTableName) {
|
|
|
5422
5630
|
EnumTableName["VALIDATIONS"] = "validations";
|
|
5423
5631
|
EnumTableName["COLLECTORS"] = "collectors";
|
|
5424
5632
|
EnumTableName["CHAINS"] = "chains";
|
|
5633
|
+
EnumTableName["PENDING_LINKS"] = "pending_links";
|
|
5425
5634
|
EnumTableName["LOTS"] = "lots";
|
|
5426
5635
|
EnumTableName["LOTS_POSITIONS"] = "lots_positions";
|
|
5427
5636
|
EnumTableName["OFFSETS"] = "offsets";
|
|
@@ -5434,10 +5643,14 @@ const VERSIONED_TABLE_NAMES = TABLE_NAMES.map((table) => `"${VERSION}"."${table}
|
|
|
5434
5643
|
const obligations = s.table(EnumTableName.OBLIGATIONS, {
|
|
5435
5644
|
obligationKey: varchar("obligation_key", { length: 66 }).primaryKey(),
|
|
5436
5645
|
loanToken: varchar("loan_token", { length: 42 }).notNull(),
|
|
5437
|
-
maturity: integer("maturity").notNull()
|
|
5646
|
+
maturity: integer("maturity").notNull(),
|
|
5647
|
+
rcfThreshold: numeric("rcf_threshold", {
|
|
5648
|
+
precision: 78,
|
|
5649
|
+
scale: 0
|
|
5650
|
+
}).notNull()
|
|
5438
5651
|
});
|
|
5439
5652
|
const obligationIdKeys = s.table(EnumTableName.OBLIGATION_ID_KEYS, {
|
|
5440
|
-
obligationId: varchar("obligation_id", { length:
|
|
5653
|
+
obligationId: varchar("obligation_id", { length: 66 }).primaryKey(),
|
|
5441
5654
|
obligationKey: varchar("obligation_key", { length: 66 }).notNull().references(() => obligations.obligationKey, { onDelete: "cascade" }),
|
|
5442
5655
|
chainId: bigint("chain_id", { mode: "number" }).$type().notNull(),
|
|
5443
5656
|
morphoV2: varchar("morpho_v2", { length: 42 }).notNull()
|
|
@@ -5459,7 +5672,7 @@ const groups = s.table(EnumTableName.GROUPS, {
|
|
|
5459
5672
|
table.group
|
|
5460
5673
|
],
|
|
5461
5674
|
name: "groups_pk"
|
|
5462
|
-
})
|
|
5675
|
+
})]);
|
|
5463
5676
|
const consumedEvents = s.table(EnumTableName.CONSUMED_EVENTS, {
|
|
5464
5677
|
eventId: varchar("event_id", { length: 128 }).primaryKey(),
|
|
5465
5678
|
chainId: bigint("chain_id", { mode: "number" }).$type().notNull(),
|
|
@@ -5493,16 +5706,13 @@ const obligationCollateralsV2 = s.table(EnumTableName.OBLIGATION_COLLATERALS_V2,
|
|
|
5493
5706
|
asset: varchar("asset", { length: 42 }).notNull(),
|
|
5494
5707
|
oracleAddress: varchar("oracle_address", { length: 42 }).notNull(),
|
|
5495
5708
|
lltv: bigint("lltv", { mode: "bigint" }).notNull(),
|
|
5709
|
+
maxLif: bigint("max_lif", { mode: "bigint" }).notNull(),
|
|
5496
5710
|
collateralIndex: integer("collateral_index").notNull(),
|
|
5497
5711
|
updatedAt: timestamp("updated_at").defaultNow().notNull()
|
|
5498
|
-
}, (table) => [
|
|
5499
|
-
|
|
5500
|
-
|
|
5501
|
-
|
|
5502
|
-
}),
|
|
5503
|
-
index("obligation_collaterals_v2_obligation_key_idx").on(table.obligationKey),
|
|
5504
|
-
index("obligation_collaterals_v2_oracle_address_idx").on(table.oracleAddress)
|
|
5505
|
-
]);
|
|
5712
|
+
}, (table) => [primaryKey({
|
|
5713
|
+
columns: [table.obligationKey, table.asset],
|
|
5714
|
+
name: "obligation_collaterals_v2_pk"
|
|
5715
|
+
})]);
|
|
5506
5716
|
const oracles = s.table(EnumTableName.ORACLES, {
|
|
5507
5717
|
chainId: bigint("chain_id", { mode: "number" }).$type().notNull(),
|
|
5508
5718
|
address: varchar("address", { length: 42 }).notNull(),
|
|
@@ -5518,19 +5728,11 @@ const oracles = s.table(EnumTableName.ORACLES, {
|
|
|
5518
5728
|
})]);
|
|
5519
5729
|
const offers = s.table(EnumTableName.OFFERS, {
|
|
5520
5730
|
hash: varchar("hash", { length: 66 }).notNull(),
|
|
5521
|
-
obligationId: varchar("obligation_id", { length:
|
|
5522
|
-
assets: numeric("assets", {
|
|
5523
|
-
precision: 78,
|
|
5524
|
-
scale: 0
|
|
5525
|
-
}).notNull(),
|
|
5731
|
+
obligationId: varchar("obligation_id", { length: 66 }).notNull().references(() => obligationIdKeys.obligationId, { onDelete: "cascade" }),
|
|
5526
5732
|
obligationUnits: numeric("obligation_units", {
|
|
5527
5733
|
precision: 78,
|
|
5528
5734
|
scale: 0
|
|
5529
5735
|
}).notNull().default("0"),
|
|
5530
|
-
obligationShares: numeric("obligation_shares", {
|
|
5531
|
-
precision: 78,
|
|
5532
|
-
scale: 0
|
|
5533
|
-
}).notNull().default("0"),
|
|
5534
5736
|
tick: integer("tick").notNull(),
|
|
5535
5737
|
maturity: integer("maturity").notNull(),
|
|
5536
5738
|
expiry: integer("expiry").notNull(),
|
|
@@ -5543,6 +5745,7 @@ const offers = s.table(EnumTableName.OFFERS, {
|
|
|
5543
5745
|
callbackAddress: varchar("callback_address", { length: 42 }).notNull(),
|
|
5544
5746
|
callbackData: text("callback_data").notNull(),
|
|
5545
5747
|
receiverIfMakerIsSeller: varchar("receiver_if_maker_is_seller", { length: 42 }),
|
|
5748
|
+
exitOnly: boolean("exit_only").notNull().default(false),
|
|
5546
5749
|
blockNumber: bigint("block_number", { mode: "number" }).notNull(),
|
|
5547
5750
|
updatedAt: timestamp("updated_at").defaultNow().notNull()
|
|
5548
5751
|
}, (table) => [
|
|
@@ -5563,13 +5766,16 @@ const offers = s.table(EnumTableName.OFFERS, {
|
|
|
5563
5766
|
],
|
|
5564
5767
|
name: "offers_groups_fk"
|
|
5565
5768
|
}).onDelete("cascade"),
|
|
5566
|
-
index("offers_group_fk_idx").on(table.groupChainId, table.groupMaker, table.group),
|
|
5567
5769
|
index("offers_group_and_hash_idx").on(table.groupChainId, table.groupMaker, table.group, table.hash),
|
|
5568
|
-
index("
|
|
5770
|
+
index("offers_obligation_side_tick_idx").on(table.obligationId, table.buy, table.tick),
|
|
5771
|
+
index("offers_obligation_active_tick_idx").on(table.obligationId, table.buy, table.expiry, table.maturity, table.start, table.tick),
|
|
5772
|
+
index("offers_group_maker_idx").on(table.groupMaker, table.hash, table.obligationId),
|
|
5773
|
+
index("offers_group_winner_expr_idx").on(table.groupChainId, table.groupMaker, table.group, table.obligationId, table.buy, sql`(CASE WHEN "buy" THEN -"tick" ELSE "tick" END)`, table.blockNumber, sql`"obligation_units" DESC`, table.hash),
|
|
5774
|
+
index("offers_book_winners_covering_idx").on(table.obligationId, table.buy, table.groupChainId, table.groupMaker, table.group, sql`(CASE WHEN "buy" THEN -"tick" ELSE "tick" END)`, table.blockNumber, sql`"obligation_units" DESC`, table.hash)
|
|
5569
5775
|
]);
|
|
5570
5776
|
const offersCallbacks = s.table(EnumTableName.OFFERS_CALLBACKS, {
|
|
5571
5777
|
offerHash: varchar("offer_hash", { length: 66 }).notNull(),
|
|
5572
|
-
obligationId: varchar("obligation_id", { length:
|
|
5778
|
+
obligationId: varchar("obligation_id", { length: 66 }).notNull(),
|
|
5573
5779
|
callbackId: varchar("callback_id", { length: 66 })
|
|
5574
5780
|
}, (table) => [foreignKey({
|
|
5575
5781
|
columns: [table.offerHash, table.obligationId],
|
|
@@ -5610,7 +5816,7 @@ const lots = s.table(EnumTableName.LOTS, {
|
|
|
5610
5816
|
user: varchar("user", { length: 42 }).notNull(),
|
|
5611
5817
|
contract: varchar("contract", { length: 66 }).notNull(),
|
|
5612
5818
|
group: varchar("group", { length: 66 }).notNull(),
|
|
5613
|
-
obligationId: varchar("obligation_id", { length:
|
|
5819
|
+
obligationId: varchar("obligation_id", { length: 66 }).notNull(),
|
|
5614
5820
|
lower: numeric("lower", {
|
|
5615
5821
|
precision: 78,
|
|
5616
5822
|
scale: 0
|
|
@@ -5655,40 +5861,45 @@ const lots = s.table(EnumTableName.LOTS, {
|
|
|
5655
5861
|
groups.group
|
|
5656
5862
|
],
|
|
5657
5863
|
name: "lots_groups_fk"
|
|
5658
|
-
}).onDelete("cascade")
|
|
5864
|
+
}).onDelete("cascade"),
|
|
5865
|
+
index("lots_position_group_obligation_idx").on(table.chainId, table.user, table.group, table.obligationId)
|
|
5659
5866
|
]);
|
|
5660
5867
|
const offsets = s.table(EnumTableName.OFFSETS, {
|
|
5661
5868
|
chainId: bigint("chain_id", { mode: "number" }).$type().notNull(),
|
|
5662
5869
|
user: varchar("user", { length: 42 }).notNull(),
|
|
5663
5870
|
contract: varchar("contract", { length: 66 }).notNull(),
|
|
5664
5871
|
group: varchar("group", { length: 66 }).notNull(),
|
|
5665
|
-
obligationId: varchar("obligation_id", { length:
|
|
5872
|
+
obligationId: varchar("obligation_id", { length: 66 }).notNull(),
|
|
5666
5873
|
value: numeric("value", {
|
|
5667
5874
|
precision: 78,
|
|
5668
5875
|
scale: 0
|
|
5669
5876
|
}).notNull()
|
|
5670
|
-
}, (table) => [
|
|
5671
|
-
|
|
5672
|
-
|
|
5673
|
-
|
|
5674
|
-
|
|
5675
|
-
|
|
5676
|
-
|
|
5677
|
-
|
|
5678
|
-
|
|
5679
|
-
|
|
5680
|
-
|
|
5681
|
-
|
|
5682
|
-
|
|
5683
|
-
|
|
5684
|
-
|
|
5685
|
-
|
|
5686
|
-
|
|
5687
|
-
|
|
5688
|
-
|
|
5689
|
-
|
|
5690
|
-
|
|
5691
|
-
|
|
5877
|
+
}, (table) => [
|
|
5878
|
+
primaryKey({
|
|
5879
|
+
columns: [
|
|
5880
|
+
table.chainId,
|
|
5881
|
+
table.user,
|
|
5882
|
+
table.contract,
|
|
5883
|
+
table.group,
|
|
5884
|
+
table.obligationId
|
|
5885
|
+
],
|
|
5886
|
+
name: "offsets_pk"
|
|
5887
|
+
}),
|
|
5888
|
+
foreignKey({
|
|
5889
|
+
columns: [
|
|
5890
|
+
table.chainId,
|
|
5891
|
+
table.contract,
|
|
5892
|
+
table.user
|
|
5893
|
+
],
|
|
5894
|
+
foreignColumns: [
|
|
5895
|
+
lotsPositions.chainId,
|
|
5896
|
+
lotsPositions.contract,
|
|
5897
|
+
lotsPositions.user
|
|
5898
|
+
],
|
|
5899
|
+
name: "offsets_lots_positions_fk"
|
|
5900
|
+
}).onDelete("cascade"),
|
|
5901
|
+
index("offsets_position_obligation_idx").on(table.chainId, table.contract, table.user, table.obligationId)
|
|
5902
|
+
]);
|
|
5692
5903
|
const PositionTypes = s.enum("position_type", Object.values(Type));
|
|
5693
5904
|
const positionTypes = s.table("position_types", {
|
|
5694
5905
|
id: serial("id").primaryKey(),
|
|
@@ -5775,7 +5986,7 @@ const status = s.table("status", {
|
|
|
5775
5986
|
});
|
|
5776
5987
|
const validations = s.table("validations", {
|
|
5777
5988
|
offerHash: varchar("offer_hash", { length: 66 }).notNull(),
|
|
5778
|
-
obligationId: varchar("obligation_id", { length:
|
|
5989
|
+
obligationId: varchar("obligation_id", { length: 66 }).notNull(),
|
|
5779
5990
|
statusId: integer("status_id").notNull().references(() => status.id, { onDelete: "no action" }),
|
|
5780
5991
|
updatedAt: timestamp("updated_at").defaultNow().notNull()
|
|
5781
5992
|
}, (table) => [primaryKey({
|
|
@@ -5803,8 +6014,33 @@ const chains = s.table(EnumTableName.CHAINS, {
|
|
|
5803
6014
|
precision: 78,
|
|
5804
6015
|
scale: 0
|
|
5805
6016
|
}).default("0").notNull(),
|
|
6017
|
+
checkpoints: text("checkpoints").default("[]").notNull(),
|
|
6018
|
+
tipHash: text("tip_hash"),
|
|
6019
|
+
finalizedBlockNumber: bigint("finalized_block_number", { mode: "number" }),
|
|
6020
|
+
finalizedBlockHash: text("finalized_block_hash"),
|
|
5806
6021
|
updatedAt: timestamp("updated_at").defaultNow().notNull()
|
|
5807
6022
|
}, (table) => [uniqueIndex("chains_chain_id_idx").on(table.chainId)]);
|
|
6023
|
+
const pendingLinks = s.table(EnumTableName.PENDING_LINKS, {
|
|
6024
|
+
key: varchar("key", { length: 191 }).primaryKey(),
|
|
6025
|
+
type: text("type").notNull(),
|
|
6026
|
+
status: text("status").notNull(),
|
|
6027
|
+
chainId: bigint("chain_id", { mode: "number" }).$type().notNull(),
|
|
6028
|
+
eventId: varchar("event_id", { length: 128 }).notNull(),
|
|
6029
|
+
obligationId: varchar("obligation_id", { length: 66 }).notNull(),
|
|
6030
|
+
collateralIndex: integer("collateral_index").notNull(),
|
|
6031
|
+
user: varchar("user", { length: 42 }).notNull(),
|
|
6032
|
+
amount: numeric("amount", {
|
|
6033
|
+
precision: 78,
|
|
6034
|
+
scale: 0
|
|
6035
|
+
}).notNull(),
|
|
6036
|
+
blockNumber: bigint("block_number", { mode: "number" }).notNull(),
|
|
6037
|
+
firstSeenBlock: bigint("first_seen_block", { mode: "number" }).notNull(),
|
|
6038
|
+
lastTriedBlock: bigint("last_tried_block", { mode: "number" }),
|
|
6039
|
+
attempts: integer("attempts").notNull().default(0),
|
|
6040
|
+
ignoredReason: text("ignored_reason"),
|
|
6041
|
+
resolvedAt: timestamp("resolved_at"),
|
|
6042
|
+
updatedAt: timestamp("updated_at").defaultNow().notNull()
|
|
6043
|
+
}, (table) => [index("pending_links_pending_scan_idx").on(table.chainId, table.type, table.status, table.firstSeenBlock), index("pending_links_event_id_idx").on(table.chainId, table.eventId)]);
|
|
5808
6044
|
const trees = s.table(EnumTableName.TREES, {
|
|
5809
6045
|
root: varchar("root", { length: 66 }).primaryKey(),
|
|
5810
6046
|
rootSignature: varchar("root_signature", { length: 132 }).notNull(),
|
|
@@ -5812,7 +6048,7 @@ const trees = s.table(EnumTableName.TREES, {
|
|
|
5812
6048
|
});
|
|
5813
6049
|
const merklePaths = s.table(EnumTableName.MERKLE_PATHS, {
|
|
5814
6050
|
offerHash: varchar("offer_hash", { length: 66 }).notNull(),
|
|
5815
|
-
obligationId: varchar("obligation_id", { length:
|
|
6051
|
+
obligationId: varchar("obligation_id", { length: 66 }).notNull(),
|
|
5816
6052
|
treeRoot: varchar("tree_root", { length: 66 }).notNull().references(() => trees.root, { onDelete: "cascade" }),
|
|
5817
6053
|
proofNodes: text("proof_nodes").notNull(),
|
|
5818
6054
|
createdAt: timestamp("created_at").defaultNow().notNull()
|
|
@@ -5839,7 +6075,7 @@ function compositeKey(g) {
|
|
|
5839
6075
|
//#endregion
|
|
5840
6076
|
//#region src/gatekeeper/Rules.ts
|
|
5841
6077
|
var Rules_exports = /* @__PURE__ */ __exportAll({
|
|
5842
|
-
|
|
6078
|
+
amountNonZero: () => amountNonZero,
|
|
5843
6079
|
callback: () => callback,
|
|
5844
6080
|
collateralToken: () => collateralToken,
|
|
5845
6081
|
groupConsistency: () => groupConsistency,
|
|
@@ -5910,11 +6146,6 @@ const sameMaker = () => batch("mixed_maker", "Validates that all offers in a bat
|
|
|
5910
6146
|
return issues;
|
|
5911
6147
|
});
|
|
5912
6148
|
/**
|
|
5913
|
-
* A validation rule that ensures mutual exclusivity of offer amount fields.
|
|
5914
|
-
* At most one of (assets, obligationUnits, obligationShares) can be non-zero.
|
|
5915
|
-
* Matches contract requirement: `atMostOneNonZero(offer.assets, offer.obligationUnits, offer.obligationShares)`.
|
|
5916
|
-
*/
|
|
5917
|
-
/**
|
|
5918
6149
|
* A validation rule that checks if the offer duration (expiry - start) meets a minimum threshold.
|
|
5919
6150
|
* @param minSeconds - Minimum required duration in seconds.
|
|
5920
6151
|
* @returns The issue that was found. If the offer is valid, this will be undefined.
|
|
@@ -5932,14 +6163,20 @@ const minDuration = ({ minSeconds }) => single("min_duration", `Validates that o
|
|
|
5932
6163
|
const maxCollaterals = ({ max }) => single("max_collaterals", `Validates that an offer has at most ${max} collaterals`, (offer) => {
|
|
5933
6164
|
if (offer.collaterals.length > max) return { message: `Offer has ${offer.collaterals.length} collaterals, exceeding the maximum of ${max}` };
|
|
5934
6165
|
});
|
|
5935
|
-
|
|
5936
|
-
|
|
6166
|
+
/**
|
|
6167
|
+
* A validation rule that checks if the offer's obligationUnits is non-zero.
|
|
6168
|
+
* The contract requires a positive amount; this rule rejects early.
|
|
6169
|
+
* @returns The issue that was found. If the offer is valid, this will be undefined.
|
|
6170
|
+
*/
|
|
6171
|
+
const amountNonZero = () => single("amount_non_zero", "Validates that obligationUnits is non-zero", (offer) => {
|
|
6172
|
+
if (offer.obligationUnits === 0n) return { message: "obligationUnits must be non-zero" };
|
|
5937
6173
|
});
|
|
5938
6174
|
/**
|
|
5939
6175
|
* A batch validation rule that ensures all offers within the same group are consistent.
|
|
5940
|
-
* All offers sharing the same group must have the same loan token,
|
|
6176
|
+
* All offers sharing the same group must have the same loan token, obligationUnits,
|
|
6177
|
+
* and side (buy/sell). The contract tracks consumed per group and requires these to match.
|
|
5941
6178
|
*/
|
|
5942
|
-
const groupConsistency = () => batch("group_consistency", "Validates that all offers in a group have the same loan token,
|
|
6179
|
+
const groupConsistency = () => batch("group_consistency", "Validates that all offers in a group have the same loan token, obligation amounts, and side", (offers) => {
|
|
5943
6180
|
const issues = /* @__PURE__ */ new Map();
|
|
5944
6181
|
if (offers.length === 0) return issues;
|
|
5945
6182
|
const groupMap = /* @__PURE__ */ new Map();
|
|
@@ -5953,13 +6190,13 @@ const groupConsistency = () => batch("group_consistency", "Validates that all of
|
|
|
5953
6190
|
if (indices.length <= 1) continue;
|
|
5954
6191
|
const reference = offers[indices[0]];
|
|
5955
6192
|
const refLoanToken = reference.loanToken.toLowerCase();
|
|
5956
|
-
const
|
|
6193
|
+
const refUnits = reference.obligationUnits;
|
|
5957
6194
|
const refBuy = reference.buy;
|
|
5958
6195
|
for (let j = 1; j < indices.length; j++) {
|
|
5959
6196
|
const idx = indices[j];
|
|
5960
6197
|
const offer = offers[idx];
|
|
5961
6198
|
if (offer.loanToken.toLowerCase() !== refLoanToken) issues.set(idx, { message: `All offers in a group must have the same loan token. Expected ${reference.loanToken}, got ${offer.loanToken}` });
|
|
5962
|
-
else if (offer.
|
|
6199
|
+
else if (offer.obligationUnits !== refUnits) issues.set(idx, { message: `All offers in a group must have the same obligationUnits. Expected ${refUnits}, got ${offer.obligationUnits}` });
|
|
5963
6200
|
else if (offer.buy !== refBuy) issues.set(idx, { message: `All offers in a group must be on the same side. Expected ${refBuy ? "buy" : "sell"}, got ${offer.buy ? "buy" : "sell"}` });
|
|
5964
6201
|
}
|
|
5965
6202
|
}
|
|
@@ -6016,7 +6253,7 @@ const morphoRules = (parameters) => {
|
|
|
6016
6253
|
}
|
|
6017
6254
|
const rules = [
|
|
6018
6255
|
sameMaker(),
|
|
6019
|
-
|
|
6256
|
+
amountNonZero(),
|
|
6020
6257
|
groupConsistency(),
|
|
6021
6258
|
...config?.minDuration != null ? [minDuration({ minSeconds: config.minDuration })] : [],
|
|
6022
6259
|
maturity({ maturities: [MaturityType.EndOfWeek, MaturityType.EndOfNextWeek] }),
|