@morpho-dev/router 0.11.0 → 0.12.1
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 +12198 -6809
- 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/0050_contract-sync-v1.16.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/0050_snapshot.json +2035 -0
- package/dist/drizzle/migrations/meta/_journal.json +119 -0
- package/dist/evm/bytecode/morpho.txt +1 -1
- package/dist/index.browser.d.mts +611 -282
- package/dist/index.browser.d.mts.map +1 -1
- package/dist/index.browser.mjs +735 -448
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.node.d.mts +1525 -614
- package/dist/index.node.d.mts.map +1 -1
- package/dist/index.node.mjs +9493 -5238
- package/dist/index.node.mjs.map +1 -1
- package/dist/server-DNFuP89-.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,8 +77,10 @@ var Tick_exports = /* @__PURE__ */ __exportAll({
|
|
|
77
77
|
InvalidTickError: () => InvalidTickError,
|
|
78
78
|
MAX_PRICE: () => MAX_PRICE,
|
|
79
79
|
TICK_RANGE: () => TICK_RANGE,
|
|
80
|
+
assetsToUnits: () => assetsToUnits,
|
|
80
81
|
priceToTick: () => priceToTick,
|
|
81
|
-
tickToPrice: () => tickToPrice
|
|
82
|
+
tickToPrice: () => tickToPrice,
|
|
83
|
+
unitsToAssets: () => unitsToAssets
|
|
82
84
|
});
|
|
83
85
|
/** ln(1 + 0.025), scaled by 1e18. Matches TickLib onchain constant. */
|
|
84
86
|
const LN_ONE_PLUS_DELTA = 24692612590371501n;
|
|
@@ -136,6 +138,81 @@ 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 units into maker-side assets using the raw tick price surface.
|
|
143
|
+
* This is the public forward conversion used by the router for lot sizing and other maker-facing capacity math.
|
|
144
|
+
* - `buy = true` -> `floor(units * price / WAD)`
|
|
145
|
+
* - `buy = false` -> `ceil(units * price / WAD)`
|
|
146
|
+
* @param units - The units to convert.
|
|
147
|
+
* @param tick - The offer tick.
|
|
148
|
+
* @param buy - Whether the maker side of the offer is buy (`true`) or sell (`false`).
|
|
149
|
+
* @returns The equivalent amount in maker-side assets.
|
|
150
|
+
*/
|
|
151
|
+
function unitsToAssets(units, tick, buy) {
|
|
152
|
+
const price = tickToPrice(tick);
|
|
153
|
+
return buy ? unitsToFloorAssets(units, price) : unitsToCeilAssets(units, price);
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Converts a maker-side asset cap into a safe units cap using the raw tick price.
|
|
157
|
+
* Buy offers use the max-safe inverse of `floor(units * price / WAD)`.
|
|
158
|
+
* Sell offers use the max-safe inverse of `ceil(units * price / WAD)`.
|
|
159
|
+
* The result is clamped to the remaining offer size because the asset cap may have been rounded before inversion.
|
|
160
|
+
* Zero integer asset caps can still admit positive units on floor-rounded sub-WAD buy ticks, and tick=0 keeps the
|
|
161
|
+
* whole remaining interval safe because the raw maker-asset surface stays at zero.
|
|
162
|
+
* @param assets - The integer maker-side asset cap.
|
|
163
|
+
* @param tick - The offer tick.
|
|
164
|
+
* @param buy - Whether the maker side of the offer is buy (`true`) or sell (`false`).
|
|
165
|
+
* @param remainingUnits - The maximum units still available on the offer.
|
|
166
|
+
* @returns The greatest safe units amount under the maker-side raw-price surface.
|
|
167
|
+
*/
|
|
168
|
+
function assetsToUnits(assets, tick, buy, remainingUnits) {
|
|
169
|
+
if (remainingUnits <= 0n) return 0n;
|
|
170
|
+
if (assets < 0n) return 0n;
|
|
171
|
+
const price = tickToPrice(tick);
|
|
172
|
+
if (price === 0n) return remainingUnits;
|
|
173
|
+
const units = buy ? floorAssetsToUnits(assets, price) : ceilAssetsToUnits(assets, price);
|
|
174
|
+
return units > remainingUnits ? remainingUnits : units;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Forward conversion for raw-price floor surfaces.
|
|
178
|
+
* This matches buy-side maker assets and the legacy floor-only helper.
|
|
179
|
+
* @param units - The units to convert.
|
|
180
|
+
* @param price - The raw tick price.
|
|
181
|
+
* @returns The floor-rounded maker-side assets.
|
|
182
|
+
*/
|
|
183
|
+
function unitsToFloorAssets(units, price) {
|
|
184
|
+
return units * price / WAD$1;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Forward conversion for raw-price ceil surfaces.
|
|
188
|
+
* This matches sell-side maker assets, where the maker receives `sellerAssets` rounded up onchain.
|
|
189
|
+
* @param units - The units to convert.
|
|
190
|
+
* @param price - The raw tick price.
|
|
191
|
+
* @returns The ceil-rounded maker-side assets.
|
|
192
|
+
*/
|
|
193
|
+
function unitsToCeilAssets(units, price) {
|
|
194
|
+
return (units * price + WAD$1 - 1n) / WAD$1;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Max-safe inverse for floor surfaces.
|
|
198
|
+
* It returns the greatest units value whose floor-rounded maker assets stay within `assets`.
|
|
199
|
+
* @param assets - The maker-side asset cap.
|
|
200
|
+
* @param price - The raw tick price.
|
|
201
|
+
* @returns The greatest safe obligation-units amount under `floor(units * price / WAD) <= assets`.
|
|
202
|
+
*/
|
|
203
|
+
function floorAssetsToUnits(assets, price) {
|
|
204
|
+
return ((assets + 1n) * WAD$1 - 1n) / price;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Max-safe inverse for ceil surfaces.
|
|
208
|
+
* It returns the greatest units value whose ceil-rounded maker assets stay within `assets`.
|
|
209
|
+
* @param assets - The maker-side asset cap.
|
|
210
|
+
* @param price - The raw tick price.
|
|
211
|
+
* @returns The greatest safe obligation-units amount under `ceil(units * price / WAD) <= assets`.
|
|
212
|
+
*/
|
|
213
|
+
function ceilAssetsToUnits(assets, price) {
|
|
214
|
+
return assets * WAD$1 / price;
|
|
215
|
+
}
|
|
139
216
|
var InvalidTickError = class extends BaseError {
|
|
140
217
|
name = "Tick.InvalidTickError";
|
|
141
218
|
constructor(tick) {
|
|
@@ -157,7 +234,7 @@ function from$15(level) {
|
|
|
157
234
|
return {
|
|
158
235
|
tick: level.tick,
|
|
159
236
|
price: price.toString(),
|
|
160
|
-
|
|
237
|
+
max_units: level.maxUnits.toString(),
|
|
161
238
|
count: level.count
|
|
162
239
|
};
|
|
163
240
|
}
|
|
@@ -215,9 +292,11 @@ function from$14(obligation, quote, chainId) {
|
|
|
215
292
|
collaterals: obligation.collaterals.map((c) => ({
|
|
216
293
|
token: c.asset,
|
|
217
294
|
lltv: c.lltv.toString(),
|
|
295
|
+
max_lif: c.maxLif.toString(),
|
|
218
296
|
oracle: c.oracle
|
|
219
297
|
})),
|
|
220
298
|
maturity: obligation.maturity,
|
|
299
|
+
rcf_threshold: obligation.rcfThreshold.toString(),
|
|
221
300
|
ask: {
|
|
222
301
|
tick: quote.ask.tick,
|
|
223
302
|
price: quote.ask.price.toString()
|
|
@@ -258,15 +337,15 @@ function from$13(input) {
|
|
|
258
337
|
collaterals: input.collaterals.map((c) => ({
|
|
259
338
|
token: c.asset,
|
|
260
339
|
lltv: c.lltv.toString(),
|
|
340
|
+
max_lif: c.maxLif.toString(),
|
|
261
341
|
oracle: c.oracle
|
|
262
342
|
})),
|
|
263
|
-
maturity: input.maturity
|
|
343
|
+
maturity: input.maturity,
|
|
344
|
+
rcf_threshold: input.rcfThreshold.toString()
|
|
264
345
|
},
|
|
265
346
|
buy: input.buy,
|
|
266
347
|
maker: input.maker,
|
|
267
|
-
|
|
268
|
-
obligation_units: input.obligationUnits.toString(),
|
|
269
|
-
obligation_shares: input.obligationShares.toString(),
|
|
348
|
+
max_units: input.maxUnits.toString(),
|
|
270
349
|
start: input.start,
|
|
271
350
|
expiry: input.expiry,
|
|
272
351
|
tick: input.tick,
|
|
@@ -274,7 +353,8 @@ function from$13(input) {
|
|
|
274
353
|
session: input.session,
|
|
275
354
|
callback: input.callback.address,
|
|
276
355
|
callback_data: input.callback.data,
|
|
277
|
-
receiver_if_maker_is_seller: input.receiverIfMakerIsSeller
|
|
356
|
+
receiver_if_maker_is_seller: input.receiverIfMakerIsSeller,
|
|
357
|
+
exit_only: input.exitOnly
|
|
278
358
|
},
|
|
279
359
|
offer_hash: input.hash,
|
|
280
360
|
obligation_id: input.obligationId,
|
|
@@ -327,15 +407,15 @@ const offerExample = {
|
|
|
327
407
|
collaterals: [{
|
|
328
408
|
token: "0x34Cf890dB685FC536E05652FB41f02090c3fb751",
|
|
329
409
|
lltv: "860000000000000000",
|
|
410
|
+
max_lif: "0",
|
|
330
411
|
oracle: "0x45093658BE7f90B63D7c359e8f408e503c2D9401"
|
|
331
412
|
}],
|
|
332
|
-
maturity: 1761922799
|
|
413
|
+
maturity: 1761922799,
|
|
414
|
+
rcf_threshold: "0"
|
|
333
415
|
},
|
|
334
416
|
buy: false,
|
|
335
417
|
maker: "0x7b093658BE7f90B63D7c359e8f408e503c2D9401",
|
|
336
|
-
|
|
337
|
-
obligation_units: "0",
|
|
338
|
-
obligation_shares: "0",
|
|
418
|
+
max_units: "369216000000000000000000",
|
|
339
419
|
start: 1761922790,
|
|
340
420
|
expiry: 1761922799,
|
|
341
421
|
tick: 495,
|
|
@@ -343,7 +423,8 @@ const offerExample = {
|
|
|
343
423
|
session: "0x0000000000000000000000000000000000000000000000000000000000000000",
|
|
344
424
|
callback: "0x0000000000000000000000000000000000000000",
|
|
345
425
|
callback_data: "0x",
|
|
346
|
-
receiver_if_maker_is_seller: "0x7b093658BE7f90B63D7c359e8f408e503c2D9401"
|
|
426
|
+
receiver_if_maker_is_seller: "0x7b093658BE7f90B63D7c359e8f408e503c2D9401",
|
|
427
|
+
exit_only: false
|
|
347
428
|
},
|
|
348
429
|
offer_hash: "0xac4bd8318ec914f89f8af913f162230575b0ac0696a19256bc12138c5cfe1427",
|
|
349
430
|
obligation_id: "0x25690ae1aee324a005be565f3bcdd16dbf8daf79",
|
|
@@ -377,11 +458,10 @@ const missingCollectorExample = {
|
|
|
377
458
|
};
|
|
378
459
|
const validateOfferExample = {
|
|
379
460
|
maker: "0x7b093658BE7f90B63D7c359e8f408e503c2D9401",
|
|
380
|
-
|
|
381
|
-
obligation_units: "0",
|
|
382
|
-
obligation_shares: "0",
|
|
461
|
+
max_units: "369216000000000000000000",
|
|
383
462
|
tick: 495,
|
|
384
463
|
maturity: 1761922799,
|
|
464
|
+
rcf_threshold: "0",
|
|
385
465
|
expiry: 1761922799,
|
|
386
466
|
start: 1761922790,
|
|
387
467
|
group: "0x000000000000000000000000000000000000000000000000000000000008b8f4",
|
|
@@ -392,13 +472,15 @@ const validateOfferExample = {
|
|
|
392
472
|
collaterals: [{
|
|
393
473
|
asset: "0x34Cf890dB685FC536E05652FB41f02090c3fb751",
|
|
394
474
|
oracle: "0x45093658BE7f90B63D7c359e8f408e503c2D9401",
|
|
395
|
-
lltv: "860000000000000000"
|
|
475
|
+
lltv: "860000000000000000",
|
|
476
|
+
max_lif: "0"
|
|
396
477
|
}],
|
|
397
478
|
callback: {
|
|
398
479
|
address: "0x0000000000000000000000000000000000000000",
|
|
399
480
|
data: "0x"
|
|
400
481
|
},
|
|
401
|
-
receiver_if_maker_is_seller: "0x7b093658BE7f90B63D7c359e8f408e503c2D9401"
|
|
482
|
+
receiver_if_maker_is_seller: "0x7b093658BE7f90B63D7c359e8f408e503c2D9401",
|
|
483
|
+
exit_only: false
|
|
402
484
|
};
|
|
403
485
|
const routerStatusExample = {
|
|
404
486
|
status: "live",
|
|
@@ -442,6 +524,10 @@ __decorate([ApiProperty({
|
|
|
442
524
|
type: "string",
|
|
443
525
|
example: "860000000000000000"
|
|
444
526
|
})], CollateralResponse.prototype, "lltv", void 0);
|
|
527
|
+
__decorate([ApiProperty({
|
|
528
|
+
type: "string",
|
|
529
|
+
example: "0"
|
|
530
|
+
})], CollateralResponse.prototype, "max_lif", void 0);
|
|
445
531
|
__decorate([ApiProperty({
|
|
446
532
|
type: "string",
|
|
447
533
|
example: "0x45093658BE7f90B63D7c359e8f408e503c2D9401"
|
|
@@ -459,6 +545,10 @@ __decorate([ApiProperty({
|
|
|
459
545
|
type: "string",
|
|
460
546
|
example: validateOfferExample.collaterals[0].lltv
|
|
461
547
|
})], ValidateCollateralRequest.prototype, "lltv", void 0);
|
|
548
|
+
__decorate([ApiProperty({
|
|
549
|
+
type: "string",
|
|
550
|
+
example: validateOfferExample.collaterals[0].max_lif
|
|
551
|
+
})], ValidateCollateralRequest.prototype, "max_lif", void 0);
|
|
462
552
|
var ValidateCallbackRequest = class {};
|
|
463
553
|
__decorate([ApiProperty({
|
|
464
554
|
type: "string",
|
|
@@ -503,6 +593,10 @@ __decorate([ApiProperty({
|
|
|
503
593
|
type: "number",
|
|
504
594
|
example: offerExample.offer.obligation.maturity
|
|
505
595
|
})], ObligationOfferResponse.prototype, "maturity", void 0);
|
|
596
|
+
__decorate([ApiProperty({
|
|
597
|
+
type: "string",
|
|
598
|
+
example: offerExample.offer.obligation.rcf_threshold
|
|
599
|
+
})], ObligationOfferResponse.prototype, "rcf_threshold", void 0);
|
|
506
600
|
var OfferDataResponse = class {};
|
|
507
601
|
__decorate([ApiProperty({
|
|
508
602
|
type: () => ObligationOfferResponse,
|
|
@@ -518,16 +612,8 @@ __decorate([ApiProperty({
|
|
|
518
612
|
})], OfferDataResponse.prototype, "maker", void 0);
|
|
519
613
|
__decorate([ApiProperty({
|
|
520
614
|
type: "string",
|
|
521
|
-
example: offerExample.offer.
|
|
522
|
-
})], OfferDataResponse.prototype, "
|
|
523
|
-
__decorate([ApiProperty({
|
|
524
|
-
type: "string",
|
|
525
|
-
example: offerExample.offer.obligation_units
|
|
526
|
-
})], 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);
|
|
615
|
+
example: offerExample.offer.max_units
|
|
616
|
+
})], OfferDataResponse.prototype, "max_units", void 0);
|
|
531
617
|
__decorate([ApiProperty({
|
|
532
618
|
type: "number",
|
|
533
619
|
example: offerExample.offer.start
|
|
@@ -562,6 +648,10 @@ __decorate([ApiProperty({
|
|
|
562
648
|
type: "string",
|
|
563
649
|
example: offerExample.offer.receiver_if_maker_is_seller
|
|
564
650
|
})], OfferDataResponse.prototype, "receiver_if_maker_is_seller", void 0);
|
|
651
|
+
__decorate([ApiProperty({
|
|
652
|
+
type: "boolean",
|
|
653
|
+
example: offerExample.offer.exit_only
|
|
654
|
+
})], OfferDataResponse.prototype, "exit_only", void 0);
|
|
565
655
|
var OfferListItemResponse = class {};
|
|
566
656
|
__decorate([ApiProperty({
|
|
567
657
|
type: () => OfferDataResponse,
|
|
@@ -624,6 +714,10 @@ __decorate([ApiProperty({
|
|
|
624
714
|
type: "number",
|
|
625
715
|
example: 1761922800
|
|
626
716
|
})], ObligationResponse.prototype, "maturity", void 0);
|
|
717
|
+
__decorate([ApiProperty({
|
|
718
|
+
type: "string",
|
|
719
|
+
example: "0"
|
|
720
|
+
})], ObligationResponse.prototype, "rcf_threshold", void 0);
|
|
627
721
|
__decorate([ApiProperty({ type: () => AskResponse })], ObligationResponse.prototype, "ask", void 0);
|
|
628
722
|
__decorate([ApiProperty({ type: () => BidResponse })], ObligationResponse.prototype, "bid", void 0);
|
|
629
723
|
var ObligationListResponse = class extends SuccessResponse {};
|
|
@@ -773,18 +867,9 @@ __decorate([ApiProperty({
|
|
|
773
867
|
})], ValidateOfferRequest.prototype, "maker", void 0);
|
|
774
868
|
__decorate([ApiProperty({
|
|
775
869
|
type: "string",
|
|
776
|
-
example: validateOfferExample.
|
|
777
|
-
})], ValidateOfferRequest.prototype, "assets", void 0);
|
|
778
|
-
__decorate([ApiProperty({
|
|
779
|
-
type: "string",
|
|
780
|
-
example: validateOfferExample.obligation_units,
|
|
781
|
-
required: false
|
|
782
|
-
})], ValidateOfferRequest.prototype, "obligation_units", void 0);
|
|
783
|
-
__decorate([ApiProperty({
|
|
784
|
-
type: "string",
|
|
785
|
-
example: validateOfferExample.obligation_shares,
|
|
870
|
+
example: validateOfferExample.max_units,
|
|
786
871
|
required: false
|
|
787
|
-
})], ValidateOfferRequest.prototype, "
|
|
872
|
+
})], ValidateOfferRequest.prototype, "max_units", void 0);
|
|
788
873
|
__decorate([ApiProperty({
|
|
789
874
|
type: "number",
|
|
790
875
|
example: validateOfferExample.tick,
|
|
@@ -795,6 +880,10 @@ __decorate([ApiProperty({
|
|
|
795
880
|
type: "number",
|
|
796
881
|
example: validateOfferExample.maturity
|
|
797
882
|
})], ValidateOfferRequest.prototype, "maturity", void 0);
|
|
883
|
+
__decorate([ApiProperty({
|
|
884
|
+
type: "string",
|
|
885
|
+
example: validateOfferExample.rcf_threshold
|
|
886
|
+
})], ValidateOfferRequest.prototype, "rcf_threshold", void 0);
|
|
798
887
|
__decorate([ApiProperty({
|
|
799
888
|
type: "number",
|
|
800
889
|
example: validateOfferExample.expiry
|
|
@@ -831,6 +920,11 @@ __decorate([ApiProperty({
|
|
|
831
920
|
type: "string",
|
|
832
921
|
example: validateOfferExample.receiver_if_maker_is_seller
|
|
833
922
|
})], ValidateOfferRequest.prototype, "receiver_if_maker_is_seller", void 0);
|
|
923
|
+
__decorate([ApiProperty({
|
|
924
|
+
type: "boolean",
|
|
925
|
+
example: false,
|
|
926
|
+
required: false
|
|
927
|
+
})], ValidateOfferRequest.prototype, "exit_only", void 0);
|
|
834
928
|
var ValidateOffersRequest = class {};
|
|
835
929
|
__decorate([ApiProperty({
|
|
836
930
|
type: "number",
|
|
@@ -909,7 +1003,7 @@ __decorate([ApiProperty({
|
|
|
909
1003
|
__decorate([ApiProperty({
|
|
910
1004
|
type: "string",
|
|
911
1005
|
example: "369216000000000000000000"
|
|
912
|
-
})], BookLevelResponse.prototype, "
|
|
1006
|
+
})], BookLevelResponse.prototype, "max_units", void 0);
|
|
913
1007
|
__decorate([ApiProperty({
|
|
914
1008
|
type: "number",
|
|
915
1009
|
example: 5
|
|
@@ -918,7 +1012,7 @@ const positionExample = {
|
|
|
918
1012
|
chain_id: 1,
|
|
919
1013
|
contract: "0xC9A9C45C0eB717f8b5F193Af6bAa05A1c0Ac5078",
|
|
920
1014
|
user: "0x7b093658BE7f90B63D7c359e8f408e503c2D9401",
|
|
921
|
-
obligation_id: "
|
|
1015
|
+
obligation_id: "0x12590ae1aee324a005be565f3bcdd16dbf8daf7969b26c181c8b8f467dad9f67",
|
|
922
1016
|
reserved: "200000000000000000000",
|
|
923
1017
|
block_number: 21345678
|
|
924
1018
|
};
|
|
@@ -1533,7 +1627,7 @@ const OpenApi = async () => {
|
|
|
1533
1627
|
info: {
|
|
1534
1628
|
title: "Router API",
|
|
1535
1629
|
version: "1.0.0",
|
|
1536
|
-
description: "API for the Morpho Router"
|
|
1630
|
+
description: process.env.COMMIT_SHA ? `API for the Morpho Router — version: ${process.env.COMMIT_SHA.slice(0, 7)}` : "API for the Morpho Router"
|
|
1537
1631
|
},
|
|
1538
1632
|
servers: [{
|
|
1539
1633
|
url: "https://router.morpho.dev",
|
|
@@ -1604,7 +1698,7 @@ function isValidOfferHashCursor(val) {
|
|
|
1604
1698
|
return /^0x[a-f0-9]{64}$/i.test(val);
|
|
1605
1699
|
}
|
|
1606
1700
|
function isValidObligationIdCursor(val) {
|
|
1607
|
-
return /^0x[a-f0-9]{
|
|
1701
|
+
return /^0x[a-f0-9]{64}$/i.test(val);
|
|
1608
1702
|
}
|
|
1609
1703
|
function isValidOfferCursor(val) {
|
|
1610
1704
|
const [hash, obligationId, ...rest] = val.split(":");
|
|
@@ -1686,9 +1780,9 @@ const GetOffersQueryParams = PaginationQueryParams.omit({ cursor: true }).extend
|
|
|
1686
1780
|
description: "Side of the offer. Required when using obligation_id.",
|
|
1687
1781
|
example: "buy"
|
|
1688
1782
|
}),
|
|
1689
|
-
obligation_id: z$1.string().regex(/^0x[a-fA-F0-9]{
|
|
1783
|
+
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
1784
|
description: "Offers obligation id. Required when not using maker.",
|
|
1691
|
-
example: "
|
|
1785
|
+
example: "0x1234567890123456789012345678901234567890123456789012345678901234"
|
|
1692
1786
|
}),
|
|
1693
1787
|
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
1788
|
description: "Maker address to filter offers by. Alternative to obligation_id + side.",
|
|
@@ -1773,9 +1867,9 @@ const GetObligationsQueryParams = z$1.object({
|
|
|
1773
1867
|
example: "-ask,bid,maturity"
|
|
1774
1868
|
})
|
|
1775
1869
|
});
|
|
1776
|
-
const GetObligationParams = z$1.object({ obligation_id: z$1.string({ error: "Obligation id is required and must be a valid
|
|
1870
|
+
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
1871
|
description: "Obligation id",
|
|
1778
|
-
example: "
|
|
1872
|
+
example: "0x1234567890123456789012345678901234567890123456789012345678901234"
|
|
1779
1873
|
}) });
|
|
1780
1874
|
/** Validate a book cursor format: {side, lastTick, offersCursor} */
|
|
1781
1875
|
function isValidBookCursor(cursorString) {
|
|
@@ -1810,9 +1904,9 @@ const HealthQueryParams = z$1.object({ strict: z$1.enum([
|
|
|
1810
1904
|
}) });
|
|
1811
1905
|
const GetBookParams = z$1.object({
|
|
1812
1906
|
...BookPaginationQueryParams.shape,
|
|
1813
|
-
obligation_id: z$1.string({ error: "Obligation id is required and must be a valid
|
|
1907
|
+
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
1908
|
description: "Obligation id",
|
|
1815
|
-
example: "
|
|
1909
|
+
example: "0x1234567890123456789012345678901234567890123456789012345678901234"
|
|
1816
1910
|
}),
|
|
1817
1911
|
side: z$1.enum(["buy", "sell"]).meta({
|
|
1818
1912
|
description: "Side of the book (buy or sell).",
|
|
@@ -1900,57 +1994,75 @@ const MetaMorphoFactory = parseAbi(["event CreateMetaMorpho(address indexed meta
|
|
|
1900
1994
|
//#region src/core/Abi/MorphoV2.ts
|
|
1901
1995
|
const MorphoV2 = parseAbi([
|
|
1902
1996
|
"constructor()",
|
|
1903
|
-
"function
|
|
1904
|
-
"function
|
|
1997
|
+
"function activatedCollaterals(bytes32 id, address user) view returns (uint128)",
|
|
1998
|
+
"function collateralOf(bytes32 id, address user, uint256 index) view returns (uint128)",
|
|
1905
1999
|
"function consumed(address user, bytes32 group) view returns (uint256)",
|
|
1906
|
-
"function
|
|
1907
|
-
"function
|
|
2000
|
+
"function creditAfterSlashing(bytes32 id, address user) view returns (uint256)",
|
|
2001
|
+
"function creditOf(bytes32 id, address user) view returns (uint256)",
|
|
2002
|
+
"function debtOf(bytes32 id, address user) view returns (uint256)",
|
|
2003
|
+
"function defaultFees(address loanToken, uint256) view returns (uint16)",
|
|
1908
2004
|
"function feeSetter() view returns (address)",
|
|
1909
|
-
"function fees(
|
|
2005
|
+
"function fees(bytes32 id) view returns (uint16[7])",
|
|
1910
2006
|
"function flashLoan(address token, uint256 assets, address callback, bytes data)",
|
|
1911
|
-
"function
|
|
1912
|
-
"function
|
|
2007
|
+
"function isAuthorized(address authorizer, address authorized) view returns (bool)",
|
|
2008
|
+
"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)",
|
|
2009
|
+
"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)",
|
|
2010
|
+
"function maxCollateralPerUser(address collateralToken) view returns (uint256)",
|
|
2011
|
+
"function maxLif(uint256 lltv, uint256 cursor) pure returns (uint256)",
|
|
2012
|
+
"function maxTakeableAssets(address loanToken) view returns (uint256)",
|
|
2013
|
+
"function maxTotalUnits(address loanToken) view returns (uint128)",
|
|
2014
|
+
"function maxTradingFee(uint256 index) pure returns (uint256)",
|
|
1913
2015
|
"function multicall(bytes[] calls)",
|
|
1914
|
-
"function obligationCreated(
|
|
1915
|
-
"function obligationState(
|
|
2016
|
+
"function obligationCreated(bytes32 id) view returns (bool)",
|
|
2017
|
+
"function obligationState(bytes32 id) view returns (uint128 totalUnits, uint256 withdrawable, uint128 lossIndex, bool created)",
|
|
1916
2018
|
"function owner() view returns (address)",
|
|
1917
|
-
"function repay((address loanToken, (address token, uint256 lltv, address oracle)[] collaterals, uint256 maturity, uint256
|
|
2019
|
+
"function repay((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation, uint256 units, address onBehalf)",
|
|
1918
2020
|
"function session(address user) view returns (bytes32)",
|
|
2021
|
+
"function setConsumed(bytes32 group, uint256 amount, address onBehalf)",
|
|
1919
2022
|
"function setDefaultTradingFee(address loanToken, uint256 index, uint256 newTradingFee)",
|
|
1920
2023
|
"function setFeeSetter(address newFeeSetter)",
|
|
1921
|
-
"function
|
|
2024
|
+
"function setIsAuthorized(address onBehalf, address authorized, bool newIsAuthorized)",
|
|
2025
|
+
"function setMaxCollateralPerUser(address collateralToken, uint256 newMaxCollateralPerUser)",
|
|
2026
|
+
"function setMaxTakeableAssets(address loanToken, uint256 newMaxTakeableAssets)",
|
|
2027
|
+
"function setMaxTotalUnits(address loanToken, uint128 newMaxTotalUnits)",
|
|
2028
|
+
"function setObligationTradingFee(bytes32 id, uint256 index, uint256 newTradingFee)",
|
|
1922
2029
|
"function setOwner(address newOwner)",
|
|
1923
2030
|
"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)",
|
|
2031
|
+
"function shuffleSession(address onBehalf)",
|
|
2032
|
+
"function slash(bytes32 id, address user)",
|
|
2033
|
+
"function supplyCollateral((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation, uint256 collateralIndex, uint256 assets, address onBehalf)",
|
|
2034
|
+
"function take(uint256 units, 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 maxUnits, 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)",
|
|
2035
|
+
"function toId((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation) view returns (bytes32)",
|
|
2036
|
+
"function toObligation(bytes32 id) view returns ((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold))",
|
|
2037
|
+
"function totalUnits(bytes32 id) view returns (uint256)",
|
|
2038
|
+
"function touchObligation((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation) returns (bytes32)",
|
|
2039
|
+
"function tradingFee(bytes32 id, uint256 timeToMaturity) view returns (uint256)",
|
|
1934
2040
|
"function tradingFeeRecipient() view returns (address)",
|
|
1935
|
-
"function
|
|
1936
|
-
"function
|
|
1937
|
-
"function
|
|
2041
|
+
"function userLossIndex(bytes32 id, address user) view returns (uint128)",
|
|
2042
|
+
"function withdraw((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation, uint256 units, address onBehalf, address receiver)",
|
|
2043
|
+
"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)",
|
|
2044
|
+
"function withdrawable(bytes32 id) view returns (uint256)",
|
|
1938
2045
|
"event Constructor(address indexed owner)",
|
|
1939
|
-
"event Consume(address indexed user, bytes32 indexed group, uint256 amount)",
|
|
1940
2046
|
"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,
|
|
2047
|
+
"event Liquidate(address indexed caller, bytes32 indexed id_, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address indexed borrower, uint256 badDebt, uint256 latestLossIndex)",
|
|
2048
|
+
"event ObligationCreated(bytes32 indexed id_, (address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation)",
|
|
2049
|
+
"event Repay(address indexed caller, bytes32 indexed id_, uint256 units, address indexed onBehalf)",
|
|
2050
|
+
"event SetConsumed(address indexed caller, address indexed onBehalf, bytes32 indexed group, uint256 amount)",
|
|
1944
2051
|
"event SetDefaultTradingFee(address indexed loanToken, uint256 indexed index, uint256 newTradingFee)",
|
|
1945
2052
|
"event SetFeeSetter(address indexed feeSetter)",
|
|
1946
|
-
"event
|
|
2053
|
+
"event SetIsAuthorized(address indexed caller, address indexed onBehalf, address indexed authorized, bool newIsAuthorized)",
|
|
2054
|
+
"event SetMaxCollateralPerUser(address indexed collateralToken, uint256 maxCollateralPerUser)",
|
|
2055
|
+
"event SetMaxTakeableAssets(address indexed loanToken, uint256 maxTakeableAssets)",
|
|
2056
|
+
"event SetMaxTotalUnits(address indexed loanToken, uint128 maxTotalUnits)",
|
|
2057
|
+
"event SetObligationTradingFee(bytes32 indexed id_, uint256 indexed index, uint256 newTradingFee)",
|
|
1947
2058
|
"event SetOwner(address indexed owner)",
|
|
1948
2059
|
"event SetTradingFeeRecipient(address indexed feeRecipient)",
|
|
1949
|
-
"event ShuffleSession(address indexed
|
|
1950
|
-
"event
|
|
1951
|
-
"event
|
|
1952
|
-
"event
|
|
1953
|
-
"event
|
|
2060
|
+
"event ShuffleSession(address indexed caller, address indexed onBehalf, bytes32 session)",
|
|
2061
|
+
"event Slash(address caller, bytes32 indexed id_, address indexed user, uint256 credit, uint256 latestLossIndex)",
|
|
2062
|
+
"event SupplyCollateral(address caller, bytes32 indexed id_, address indexed collateral, uint256 assets, address indexed onBehalf)",
|
|
2063
|
+
"event Take(address caller, bytes32 indexed id_, address indexed maker, address indexed taker, bool offerIsBuy, uint256 buyerAssets, uint256 sellerAssets, uint256 units, address sellerReceiver, bytes32 group, uint256 consumed, uint256 totalUnits)",
|
|
2064
|
+
"event Withdraw(address caller, bytes32 indexed id_, uint256 units, address indexed onBehalf, address indexed receiver)",
|
|
2065
|
+
"event WithdrawCollateral(address caller, bytes32 indexed id_, address indexed collateral, uint256 assets, address indexed onBehalf, address receiver)"
|
|
1954
2066
|
]);
|
|
1955
2067
|
|
|
1956
2068
|
//#endregion
|
|
@@ -2243,8 +2355,8 @@ const chains$1 = {
|
|
|
2243
2355
|
name: "base",
|
|
2244
2356
|
custom: {
|
|
2245
2357
|
morpho: {
|
|
2246
|
-
address: "
|
|
2247
|
-
blockCreated:
|
|
2358
|
+
address: "0x26378861d9c740fe86e7472752aef5b1a783c60b",
|
|
2359
|
+
blockCreated: 43606117
|
|
2248
2360
|
},
|
|
2249
2361
|
morphoBlue: {
|
|
2250
2362
|
address: "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb",
|
|
@@ -2273,8 +2385,8 @@ const chains$1 = {
|
|
|
2273
2385
|
name: "ethereum-virtual-testnet",
|
|
2274
2386
|
custom: {
|
|
2275
2387
|
morpho: {
|
|
2276
|
-
address: "
|
|
2277
|
-
blockCreated:
|
|
2388
|
+
address: "0x94c576ee728ee290116ee65c0d1e9fed4a1b5041",
|
|
2389
|
+
blockCreated: 23244323
|
|
2278
2390
|
},
|
|
2279
2391
|
morphoBlue: {
|
|
2280
2392
|
address: "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb",
|
|
@@ -2301,9 +2413,13 @@ const chains$1 = {
|
|
|
2301
2413
|
...anvil,
|
|
2302
2414
|
id: ChainId.ANVIL,
|
|
2303
2415
|
name: "anvil",
|
|
2416
|
+
contracts: { multicall3: {
|
|
2417
|
+
address: "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0",
|
|
2418
|
+
blockCreated: 0
|
|
2419
|
+
} },
|
|
2304
2420
|
custom: {
|
|
2305
2421
|
morpho: {
|
|
2306
|
-
address: "
|
|
2422
|
+
address: "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512",
|
|
2307
2423
|
blockCreated: 0
|
|
2308
2424
|
},
|
|
2309
2425
|
morphoBlue: {
|
|
@@ -2311,8 +2427,8 @@ const chains$1 = {
|
|
|
2311
2427
|
blockCreated: 0
|
|
2312
2428
|
},
|
|
2313
2429
|
mempool: {
|
|
2314
|
-
address: "
|
|
2315
|
-
blockCreated:
|
|
2430
|
+
address: "0x5FbDB2315678afecb367f032d93F642f64180aa3",
|
|
2431
|
+
blockCreated: 0
|
|
2316
2432
|
},
|
|
2317
2433
|
vaults: { factories: {
|
|
2318
2434
|
v1_0: {
|
|
@@ -2514,6 +2630,7 @@ var Random_exports = /* @__PURE__ */ __exportAll({
|
|
|
2514
2630
|
address: () => address,
|
|
2515
2631
|
bool: () => bool,
|
|
2516
2632
|
bytes: () => bytes,
|
|
2633
|
+
createRng: () => createRng,
|
|
2517
2634
|
float: () => float,
|
|
2518
2635
|
hex: () => hex,
|
|
2519
2636
|
int: () => int,
|
|
@@ -2531,7 +2648,19 @@ const hashSeed = (seed) => {
|
|
|
2531
2648
|
}
|
|
2532
2649
|
return hash >>> 0;
|
|
2533
2650
|
};
|
|
2534
|
-
|
|
2651
|
+
/**
|
|
2652
|
+
* Creates an isolated seeded RNG instance — safe for concurrent use.
|
|
2653
|
+
* @param seed - Seed string used to derive the initial RNG state.
|
|
2654
|
+
*/
|
|
2655
|
+
function createRng(seed) {
|
|
2656
|
+
const rng = createSeededRngFn(seed);
|
|
2657
|
+
return {
|
|
2658
|
+
float: () => rng(),
|
|
2659
|
+
int: (maxExclusive, min = 0) => Math.floor(rng() * (maxExclusive - min)) + min,
|
|
2660
|
+
bool: (probability = .5) => rng() < probability
|
|
2661
|
+
};
|
|
2662
|
+
}
|
|
2663
|
+
const createSeededRngFn = (seed) => {
|
|
2535
2664
|
let state = hashSeed(seed);
|
|
2536
2665
|
return () => {
|
|
2537
2666
|
state += 1831565813;
|
|
@@ -2545,7 +2674,7 @@ const createSeededRng = (seed) => {
|
|
|
2545
2674
|
*/
|
|
2546
2675
|
function withSeed(seed, fn) {
|
|
2547
2676
|
const previous = currentRng;
|
|
2548
|
-
currentRng =
|
|
2677
|
+
currentRng = createSeededRngFn(seed);
|
|
2549
2678
|
try {
|
|
2550
2679
|
return fn();
|
|
2551
2680
|
} finally {
|
|
@@ -2556,7 +2685,7 @@ function withSeed(seed, fn) {
|
|
|
2556
2685
|
* Seeds the global RNG for deterministic test runs.
|
|
2557
2686
|
*/
|
|
2558
2687
|
function seed(seed) {
|
|
2559
|
-
currentRng =
|
|
2688
|
+
currentRng = createSeededRngFn(seed);
|
|
2560
2689
|
}
|
|
2561
2690
|
/**
|
|
2562
2691
|
* Returns a deterministic random float in [0, 1).
|
|
@@ -2678,6 +2807,7 @@ const transformAddress = (val, ctx) => {
|
|
|
2678
2807
|
});
|
|
2679
2808
|
return z$1.NEVER;
|
|
2680
2809
|
};
|
|
2810
|
+
const AddressSchema = z$1.string().transform(transformAddress);
|
|
2681
2811
|
|
|
2682
2812
|
//#endregion
|
|
2683
2813
|
//#region src/core/LLTV.ts
|
|
@@ -2752,15 +2882,20 @@ const abi$1 = [
|
|
|
2752
2882
|
type: "uint256",
|
|
2753
2883
|
name: "lltv"
|
|
2754
2884
|
},
|
|
2885
|
+
{
|
|
2886
|
+
type: "uint256",
|
|
2887
|
+
name: "maxLif"
|
|
2888
|
+
},
|
|
2755
2889
|
{
|
|
2756
2890
|
type: "address",
|
|
2757
2891
|
name: "oracle"
|
|
2758
2892
|
}
|
|
2759
2893
|
];
|
|
2760
2894
|
const CollateralSchema = z$1.object({
|
|
2761
|
-
asset:
|
|
2762
|
-
oracle:
|
|
2763
|
-
lltv: LLTVSchema
|
|
2895
|
+
asset: AddressSchema,
|
|
2896
|
+
oracle: AddressSchema,
|
|
2897
|
+
lltv: LLTVSchema,
|
|
2898
|
+
maxLif: z$1.bigint({ coerce: true }).min(0n)
|
|
2764
2899
|
});
|
|
2765
2900
|
const CollateralsSchema = z$1.array(CollateralSchema).min(1, { message: "At least one collateral is required" }).refine((collaterals) => {
|
|
2766
2901
|
for (let i = 1; i < collaterals.length; i++) if (collaterals[i - 1].asset.toLowerCase() > collaterals[i].asset.toLowerCase()) return false;
|
|
@@ -2778,6 +2913,7 @@ const from$10 = (parameters) => {
|
|
|
2778
2913
|
return {
|
|
2779
2914
|
asset: parameters.asset.toLowerCase(),
|
|
2780
2915
|
lltv: from$11(parameters.lltv),
|
|
2916
|
+
maxLif: parameters.maxLif,
|
|
2781
2917
|
oracle: parameters.oracle.toLowerCase()
|
|
2782
2918
|
};
|
|
2783
2919
|
};
|
|
@@ -2794,7 +2930,8 @@ function random$3() {
|
|
|
2794
2930
|
return from$10({
|
|
2795
2931
|
asset: address(),
|
|
2796
2932
|
oracle: address(),
|
|
2797
|
-
lltv: .965
|
|
2933
|
+
lltv: .965,
|
|
2934
|
+
maxLif: 0n
|
|
2798
2935
|
});
|
|
2799
2936
|
}
|
|
2800
2937
|
|
|
@@ -2916,14 +3053,8 @@ var Maturity_exports = /* @__PURE__ */ __exportAll({
|
|
|
2916
3053
|
MaturityType: () => MaturityType,
|
|
2917
3054
|
from: () => from$9
|
|
2918
3055
|
});
|
|
2919
|
-
const
|
|
2920
|
-
|
|
2921
|
-
from$9(maturity);
|
|
2922
|
-
return true;
|
|
2923
|
-
} catch (_e) {
|
|
2924
|
-
return false;
|
|
2925
|
-
}
|
|
2926
|
-
}, { error: (issue) => {
|
|
3056
|
+
const MAX_TIMESTAMP_SECONDS = 999999999999;
|
|
3057
|
+
const MaturitySchema = z$1.number().int().max(MAX_TIMESTAMP_SECONDS).refine(isAt15UTC, { error: (issue) => {
|
|
2927
3058
|
try {
|
|
2928
3059
|
return `The maturity is set to ${/* @__PURE__ */ new Date(issue.input * 1e3)}. It must be at 15:00:00 UTC.`;
|
|
2929
3060
|
} catch (_) {
|
|
@@ -2958,7 +3089,7 @@ function from$9(ts) {
|
|
|
2958
3089
|
if (ts in MaturityOptions) return MaturityOptions[ts]();
|
|
2959
3090
|
throw new InvalidOptionError(ts);
|
|
2960
3091
|
}
|
|
2961
|
-
if (typeof ts === "number" && ts >
|
|
3092
|
+
if (typeof ts === "number" && ts > MAX_TIMESTAMP_SECONDS) throw new InvalidFormatError();
|
|
2962
3093
|
if (!isAt15UTC(ts)) throw new InvalidDateError(ts);
|
|
2963
3094
|
return ts;
|
|
2964
3095
|
}
|
|
@@ -3052,10 +3183,10 @@ var Obligation_exports = /* @__PURE__ */ __exportAll({
|
|
|
3052
3183
|
tupleAbi: () => tupleAbi
|
|
3053
3184
|
});
|
|
3054
3185
|
const ObligationSchema = z$1.object({
|
|
3055
|
-
loanToken:
|
|
3186
|
+
loanToken: AddressSchema,
|
|
3056
3187
|
collaterals: CollateralsSchema,
|
|
3057
3188
|
maturity: MaturitySchema,
|
|
3058
|
-
|
|
3189
|
+
rcfThreshold: z$1.bigint({ coerce: true }).min(0n)
|
|
3059
3190
|
});
|
|
3060
3191
|
const abi = [
|
|
3061
3192
|
{
|
|
@@ -3073,7 +3204,7 @@ const abi = [
|
|
|
3073
3204
|
},
|
|
3074
3205
|
{
|
|
3075
3206
|
type: "uint256",
|
|
3076
|
-
name: "
|
|
3207
|
+
name: "rcfThreshold"
|
|
3077
3208
|
}
|
|
3078
3209
|
];
|
|
3079
3210
|
const tupleAbi = [{
|
|
@@ -3095,10 +3226,12 @@ const tupleAbi = [{
|
|
|
3095
3226
|
* Collateral.from({
|
|
3096
3227
|
* asset: privateKeyToAccount(generatePrivateKey()).address,
|
|
3097
3228
|
* oracle: privateKeyToAccount(generatePrivateKey()).address,
|
|
3098
|
-
* lltv: 0.965
|
|
3229
|
+
* lltv: 0.965,
|
|
3230
|
+
* maxLif: 0n,
|
|
3099
3231
|
* }),
|
|
3100
3232
|
* ],
|
|
3101
3233
|
* maturity: Maturity.from("end_of_next_quarter"),
|
|
3234
|
+
* rcfThreshold: 0n,
|
|
3102
3235
|
* });
|
|
3103
3236
|
* ```
|
|
3104
3237
|
*/
|
|
@@ -3112,7 +3245,7 @@ function from$8(parameters) {
|
|
|
3112
3245
|
loanToken: parsedObligation.loanToken.toLowerCase(),
|
|
3113
3246
|
collaterals: parsedObligation.collaterals.sort((a, b) => a.asset.localeCompare(b.asset)),
|
|
3114
3247
|
maturity: parsedObligation.maturity,
|
|
3115
|
-
|
|
3248
|
+
rcfThreshold: parsedObligation.rcfThreshold
|
|
3116
3249
|
};
|
|
3117
3250
|
} catch (error) {
|
|
3118
3251
|
throw new InvalidObligationError(error);
|
|
@@ -3129,8 +3262,7 @@ function fromSnakeCase$2(input) {
|
|
|
3129
3262
|
}
|
|
3130
3263
|
/**
|
|
3131
3264
|
* 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`.
|
|
3265
|
+
* The key is computed as keccak256(abi.encode(loanToken, collaterals, maturity, rcfThreshold)).
|
|
3134
3266
|
* @throws If the collaterals are not sorted alphabetically by address. {@link CollateralsAreNotSortedError}
|
|
3135
3267
|
* @param parameters - {@link key.Parameters}
|
|
3136
3268
|
* @returns The obligation key as a 32-byte hex string. {@link key.ReturnType}
|
|
@@ -3154,10 +3286,11 @@ function key(parameters) {
|
|
|
3154
3286
|
parameters.collaterals.map((c) => ({
|
|
3155
3287
|
token: c.asset.toLowerCase(),
|
|
3156
3288
|
lltv: c.lltv,
|
|
3289
|
+
maxLif: c.maxLif,
|
|
3157
3290
|
oracle: c.oracle.toLowerCase()
|
|
3158
3291
|
})),
|
|
3159
3292
|
BigInt(parameters.maturity),
|
|
3160
|
-
parameters.
|
|
3293
|
+
parameters.rcfThreshold
|
|
3161
3294
|
]));
|
|
3162
3295
|
}
|
|
3163
3296
|
/**
|
|
@@ -3173,7 +3306,8 @@ function random$2() {
|
|
|
3173
3306
|
return from$8({
|
|
3174
3307
|
loanToken: address(),
|
|
3175
3308
|
collaterals: [random$3()],
|
|
3176
|
-
maturity: from$9("end_of_next_quarter")
|
|
3309
|
+
maturity: from$9("end_of_next_quarter"),
|
|
3310
|
+
rcfThreshold: 0n
|
|
3177
3311
|
});
|
|
3178
3312
|
}
|
|
3179
3313
|
/**
|
|
@@ -3187,7 +3321,8 @@ function fromOffer$1(offer) {
|
|
|
3187
3321
|
return from$8({
|
|
3188
3322
|
loanToken: offer.loanToken,
|
|
3189
3323
|
collaterals: offer.collaterals,
|
|
3190
|
-
maturity: offer.maturity
|
|
3324
|
+
maturity: offer.maturity,
|
|
3325
|
+
rcfThreshold: offer.rcfThreshold
|
|
3191
3326
|
});
|
|
3192
3327
|
}
|
|
3193
3328
|
var InvalidObligationError = class extends BaseError {
|
|
@@ -3224,27 +3359,27 @@ function creationCode(parameters) {
|
|
|
3224
3359
|
collaterals: parameters.obligation.collaterals.map((collateral) => ({
|
|
3225
3360
|
token: collateral.asset.toLowerCase(),
|
|
3226
3361
|
lltv: collateral.lltv,
|
|
3362
|
+
maxLif: collateral.maxLif,
|
|
3227
3363
|
oracle: collateral.oracle.toLowerCase()
|
|
3228
3364
|
})),
|
|
3229
3365
|
maturity: BigInt(parameters.obligation.maturity),
|
|
3230
|
-
|
|
3366
|
+
rcfThreshold: parameters.obligation.rcfThreshold
|
|
3231
3367
|
}])]);
|
|
3232
3368
|
}
|
|
3233
3369
|
/**
|
|
3234
3370
|
* 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.
|
|
3371
|
+
* `keccak256(0xff ++ morphoV2 ++ chainId ++ keccak256(creationCode))`.
|
|
3237
3372
|
*
|
|
3238
3373
|
* @param parameters - {@link toId.Parameters}
|
|
3239
|
-
* @returns The obligation id. {@link toId.ReturnType}
|
|
3374
|
+
* @returns The 32-byte obligation id. {@link toId.ReturnType}
|
|
3240
3375
|
*/
|
|
3241
3376
|
function toId(parameters) {
|
|
3242
|
-
return
|
|
3377
|
+
return keccak256(concatHex([
|
|
3243
3378
|
"0xff",
|
|
3244
3379
|
parameters.morphoV2.toLowerCase(),
|
|
3245
3380
|
numberToHex(BigInt(parameters.chainId), { size: 32 }),
|
|
3246
3381
|
keccak256(creationCode(parameters))
|
|
3247
|
-
]))
|
|
3382
|
+
]));
|
|
3248
3383
|
}
|
|
3249
3384
|
|
|
3250
3385
|
//#endregion
|
|
@@ -3334,7 +3469,6 @@ var Offer_exports = /* @__PURE__ */ __exportAll({
|
|
|
3334
3469
|
fromSnakeCase: () => fromSnakeCase$1,
|
|
3335
3470
|
hash: () => hash,
|
|
3336
3471
|
liquidateEvent: () => liquidateEvent,
|
|
3337
|
-
obligationId: () => obligationId,
|
|
3338
3472
|
random: () => random$1,
|
|
3339
3473
|
repayEvent: () => repayEvent,
|
|
3340
3474
|
serialize: () => serialize,
|
|
@@ -3352,12 +3486,11 @@ let Status = /* @__PURE__ */ function(Status) {
|
|
|
3352
3486
|
}({});
|
|
3353
3487
|
const OfferSchema = () => {
|
|
3354
3488
|
return z$1.object({
|
|
3355
|
-
maker:
|
|
3356
|
-
|
|
3357
|
-
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),
|
|
3489
|
+
maker: AddressSchema,
|
|
3490
|
+
maxUnits: z$1.bigint({ coerce: true }).min(0n).max(maxUint256).optional().default(0n),
|
|
3359
3491
|
tick: z$1.coerce.number().int().min(0).max(990),
|
|
3360
3492
|
maturity: MaturitySchema,
|
|
3493
|
+
rcfThreshold: z$1.bigint({ coerce: true }).min(0n).max(maxUint256),
|
|
3361
3494
|
expiry: z$1.number().int().max(Number.MAX_SAFE_INTEGER),
|
|
3362
3495
|
start: z$1.number().int().max(Number.MAX_SAFE_INTEGER),
|
|
3363
3496
|
group: z$1.union([
|
|
@@ -3371,13 +3504,14 @@ const OfferSchema = () => {
|
|
|
3371
3504
|
z$1.bigint()
|
|
3372
3505
|
]).optional().default("0x0000000000000000000000000000000000000000000000000000000000000000").transform(transformBytes32),
|
|
3373
3506
|
buy: z$1.boolean(),
|
|
3374
|
-
loanToken:
|
|
3507
|
+
loanToken: AddressSchema,
|
|
3375
3508
|
collaterals: CollateralsSchema,
|
|
3376
3509
|
callback: z$1.object({
|
|
3377
|
-
address:
|
|
3510
|
+
address: AddressSchema,
|
|
3378
3511
|
data: z$1.string().transform(transformHex)
|
|
3379
3512
|
}),
|
|
3380
|
-
receiverIfMakerIsSeller:
|
|
3513
|
+
receiverIfMakerIsSeller: AddressSchema,
|
|
3514
|
+
exitOnly: z$1.boolean().optional().default(false)
|
|
3381
3515
|
}).refine((data) => data.start < data.expiry, {
|
|
3382
3516
|
message: "start must be before expiry",
|
|
3383
3517
|
path: ["start"]
|
|
@@ -3429,11 +3563,10 @@ function toSnakeCase(offer) {
|
|
|
3429
3563
|
*/
|
|
3430
3564
|
const serialize = (offer) => ({
|
|
3431
3565
|
maker: offer.maker,
|
|
3432
|
-
|
|
3433
|
-
obligationUnits: offer.obligationUnits.toString(),
|
|
3434
|
-
obligationShares: offer.obligationShares.toString(),
|
|
3566
|
+
maxUnits: offer.maxUnits.toString(),
|
|
3435
3567
|
tick: offer.tick,
|
|
3436
3568
|
maturity: Number(offer.maturity),
|
|
3569
|
+
rcfThreshold: offer.rcfThreshold.toString(),
|
|
3437
3570
|
expiry: Number(offer.expiry),
|
|
3438
3571
|
start: Number(offer.start),
|
|
3439
3572
|
group: offer.group,
|
|
@@ -3443,13 +3576,15 @@ const serialize = (offer) => ({
|
|
|
3443
3576
|
collaterals: offer.collaterals.map((c) => ({
|
|
3444
3577
|
asset: c.asset,
|
|
3445
3578
|
oracle: c.oracle,
|
|
3446
|
-
lltv: c.lltv.toString()
|
|
3579
|
+
lltv: c.lltv.toString(),
|
|
3580
|
+
maxLif: c.maxLif.toString()
|
|
3447
3581
|
})),
|
|
3448
3582
|
callback: {
|
|
3449
3583
|
address: offer.callback.address,
|
|
3450
3584
|
data: offer.callback.data
|
|
3451
3585
|
},
|
|
3452
3586
|
receiverIfMakerIsSeller: offer.receiverIfMakerIsSeller,
|
|
3587
|
+
exitOnly: offer.exitOnly,
|
|
3453
3588
|
hash: hash(offer)
|
|
3454
3589
|
});
|
|
3455
3590
|
/**
|
|
@@ -3486,7 +3621,7 @@ function random$1(config) {
|
|
|
3486
3621
|
const loanTokenDecimals = config?.assetsDecimals?.[loanToken] ?? 18;
|
|
3487
3622
|
const unit = BigInt(10) ** BigInt(loanTokenDecimals);
|
|
3488
3623
|
const amountBase = BigInt(100 + int(999901));
|
|
3489
|
-
const
|
|
3624
|
+
const maxUnitsScaled = config?.maxUnits ?? amountBase * unit;
|
|
3490
3625
|
const emptyCallback = {
|
|
3491
3626
|
address: zeroAddress,
|
|
3492
3627
|
data: "0x"
|
|
@@ -3494,11 +3629,10 @@ function random$1(config) {
|
|
|
3494
3629
|
const maker = config?.maker ?? address();
|
|
3495
3630
|
return from$7({
|
|
3496
3631
|
maker,
|
|
3497
|
-
|
|
3498
|
-
obligationUnits: config?.obligationUnits ?? 0n,
|
|
3499
|
-
obligationShares: config?.obligationShares ?? 0n,
|
|
3632
|
+
maxUnits: maxUnitsScaled,
|
|
3500
3633
|
tick,
|
|
3501
3634
|
maturity,
|
|
3635
|
+
rcfThreshold: config?.rcfThreshold ?? 0n,
|
|
3502
3636
|
expiry: config?.expiry ?? maturity - 1,
|
|
3503
3637
|
start: config?.start ?? maturity - 10,
|
|
3504
3638
|
group: config?.group ?? hex(32),
|
|
@@ -3510,7 +3644,8 @@ function random$1(config) {
|
|
|
3510
3644
|
lltv
|
|
3511
3645
|
})).sort((a, b) => a.asset.localeCompare(b.asset)),
|
|
3512
3646
|
callback: config?.callback ?? emptyCallback,
|
|
3513
|
-
receiverIfMakerIsSeller: config?.receiverIfMakerIsSeller ?? maker
|
|
3647
|
+
receiverIfMakerIsSeller: config?.receiverIfMakerIsSeller ?? maker,
|
|
3648
|
+
exitOnly: config?.exitOnly ?? false
|
|
3514
3649
|
});
|
|
3515
3650
|
}
|
|
3516
3651
|
const weightedChoice = (pairs) => {
|
|
@@ -3537,124 +3672,150 @@ function hash(offer) {
|
|
|
3537
3672
|
return computed;
|
|
3538
3673
|
}
|
|
3539
3674
|
/**
|
|
3540
|
-
*
|
|
3541
|
-
*
|
|
3542
|
-
*
|
|
3543
|
-
*
|
|
3544
|
-
*
|
|
3675
|
+
* ABI layout matching the Solidity `Offer` struct used by `abi.encode(offer)` in the contract.
|
|
3676
|
+
*
|
|
3677
|
+
* This is a **single top-level tuple** — Solidity's `abi.encode(struct)` encodes the struct as one
|
|
3678
|
+
* tuple parameter, not as separate parameters per field. Field order and nesting must exactly
|
|
3679
|
+
* mirror `contracts/interfaces/IMidnight.sol`:
|
|
3680
|
+
*
|
|
3681
|
+
* ```
|
|
3682
|
+
* struct Offer {
|
|
3683
|
+
* Obligation obligation; // nested tuple
|
|
3684
|
+
* bool buy;
|
|
3685
|
+
* address maker;
|
|
3686
|
+
* uint256 maxUnits;
|
|
3687
|
+
* uint256 start;
|
|
3688
|
+
* uint256 expiry;
|
|
3689
|
+
* uint256 tick;
|
|
3690
|
+
* bytes32 group;
|
|
3691
|
+
* bytes32 session;
|
|
3692
|
+
* address callback;
|
|
3693
|
+
* bytes callbackData;
|
|
3694
|
+
* address receiverIfMakerIsSeller;
|
|
3695
|
+
* bool exitOnly;
|
|
3696
|
+
* }
|
|
3697
|
+
* ```
|
|
3545
3698
|
*/
|
|
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",
|
|
3699
|
+
const OfferAbi = [{
|
|
3700
|
+
name: "offer",
|
|
3701
|
+
type: "tuple",
|
|
3702
|
+
components: [
|
|
3703
|
+
{
|
|
3704
|
+
name: "obligation",
|
|
3705
|
+
type: "tuple",
|
|
3706
|
+
components: [
|
|
3707
|
+
{
|
|
3708
|
+
name: "loanToken",
|
|
3709
|
+
type: "address"
|
|
3710
|
+
},
|
|
3711
|
+
{
|
|
3712
|
+
name: "collaterals",
|
|
3713
|
+
type: "tuple[]",
|
|
3714
|
+
components: [
|
|
3715
|
+
{
|
|
3716
|
+
name: "token",
|
|
3717
|
+
type: "address"
|
|
3718
|
+
},
|
|
3719
|
+
{
|
|
3720
|
+
name: "lltv",
|
|
3721
|
+
type: "uint256"
|
|
3722
|
+
},
|
|
3723
|
+
{
|
|
3724
|
+
name: "maxLif",
|
|
3725
|
+
type: "uint256"
|
|
3726
|
+
},
|
|
3727
|
+
{
|
|
3728
|
+
name: "oracle",
|
|
3729
|
+
type: "address"
|
|
3730
|
+
}
|
|
3731
|
+
]
|
|
3732
|
+
},
|
|
3733
|
+
{
|
|
3734
|
+
name: "maturity",
|
|
3735
|
+
type: "uint256"
|
|
3736
|
+
},
|
|
3737
|
+
{
|
|
3738
|
+
name: "rcfThreshold",
|
|
3739
|
+
type: "uint256"
|
|
3740
|
+
}
|
|
3741
|
+
]
|
|
3742
|
+
},
|
|
3743
|
+
{
|
|
3744
|
+
name: "buy",
|
|
3745
|
+
type: "bool"
|
|
3746
|
+
},
|
|
3747
|
+
{
|
|
3748
|
+
name: "maker",
|
|
3629
3749
|
type: "address"
|
|
3630
|
-
},
|
|
3631
|
-
|
|
3750
|
+
},
|
|
3751
|
+
{
|
|
3752
|
+
name: "maxUnits",
|
|
3753
|
+
type: "uint256"
|
|
3754
|
+
},
|
|
3755
|
+
{
|
|
3756
|
+
name: "start",
|
|
3757
|
+
type: "uint256"
|
|
3758
|
+
},
|
|
3759
|
+
{
|
|
3760
|
+
name: "expiry",
|
|
3761
|
+
type: "uint256"
|
|
3762
|
+
},
|
|
3763
|
+
{
|
|
3764
|
+
name: "tick",
|
|
3765
|
+
type: "uint256"
|
|
3766
|
+
},
|
|
3767
|
+
{
|
|
3768
|
+
name: "group",
|
|
3769
|
+
type: "bytes32"
|
|
3770
|
+
},
|
|
3771
|
+
{
|
|
3772
|
+
name: "session",
|
|
3773
|
+
type: "bytes32"
|
|
3774
|
+
},
|
|
3775
|
+
{
|
|
3776
|
+
name: "callback",
|
|
3777
|
+
type: "address"
|
|
3778
|
+
},
|
|
3779
|
+
{
|
|
3780
|
+
name: "callbackData",
|
|
3632
3781
|
type: "bytes"
|
|
3633
|
-
}
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3782
|
+
},
|
|
3783
|
+
{
|
|
3784
|
+
name: "receiverIfMakerIsSeller",
|
|
3785
|
+
type: "address"
|
|
3786
|
+
},
|
|
3787
|
+
{
|
|
3788
|
+
name: "exitOnly",
|
|
3789
|
+
type: "bool"
|
|
3790
|
+
}
|
|
3791
|
+
]
|
|
3792
|
+
}];
|
|
3640
3793
|
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
|
-
|
|
3794
|
+
return encodeAbiParameters(OfferAbi, [{
|
|
3795
|
+
obligation: {
|
|
3796
|
+
loanToken: offer.loanToken,
|
|
3797
|
+
collaterals: offer.collaterals.map((c) => ({
|
|
3798
|
+
token: c.asset,
|
|
3799
|
+
lltv: c.lltv,
|
|
3800
|
+
maxLif: c.maxLif,
|
|
3801
|
+
oracle: c.oracle
|
|
3802
|
+
})),
|
|
3803
|
+
maturity: BigInt(offer.maturity),
|
|
3804
|
+
rcfThreshold: offer.rcfThreshold
|
|
3805
|
+
},
|
|
3806
|
+
buy: offer.buy,
|
|
3807
|
+
maker: offer.maker,
|
|
3808
|
+
maxUnits: offer.maxUnits,
|
|
3809
|
+
start: BigInt(offer.start),
|
|
3810
|
+
expiry: BigInt(offer.expiry),
|
|
3811
|
+
tick: BigInt(offer.tick),
|
|
3812
|
+
group: offer.group,
|
|
3813
|
+
session: offer.session,
|
|
3814
|
+
callback: offer.callback.address,
|
|
3815
|
+
callbackData: offer.callback.data,
|
|
3816
|
+
receiverIfMakerIsSeller: offer.receiverIfMakerIsSeller,
|
|
3817
|
+
exitOnly: offer.exitOnly
|
|
3818
|
+
}]);
|
|
3658
3819
|
}
|
|
3659
3820
|
function decode$1(data) {
|
|
3660
3821
|
let decoded;
|
|
@@ -3663,31 +3824,33 @@ function decode$1(data) {
|
|
|
3663
3824
|
} catch (error) {
|
|
3664
3825
|
throw new InvalidOfferError(error);
|
|
3665
3826
|
}
|
|
3827
|
+
const s = decoded[0];
|
|
3666
3828
|
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) => {
|
|
3829
|
+
loanToken: s.obligation.loanToken,
|
|
3830
|
+
collaterals: s.obligation.collaterals.map((c) => {
|
|
3680
3831
|
return from$10({
|
|
3681
|
-
asset: c.
|
|
3832
|
+
asset: c.token,
|
|
3682
3833
|
oracle: c.oracle,
|
|
3683
|
-
lltv: c.lltv
|
|
3834
|
+
lltv: c.lltv,
|
|
3835
|
+
maxLif: c.maxLif
|
|
3684
3836
|
});
|
|
3685
3837
|
}),
|
|
3838
|
+
maturity: from$9(Number(s.obligation.maturity)),
|
|
3839
|
+
rcfThreshold: s.obligation.rcfThreshold,
|
|
3840
|
+
buy: s.buy,
|
|
3841
|
+
maker: s.maker,
|
|
3842
|
+
maxUnits: s.maxUnits,
|
|
3843
|
+
start: Number(s.start),
|
|
3844
|
+
expiry: Number(s.expiry),
|
|
3845
|
+
tick: Number(s.tick),
|
|
3846
|
+
group: s.group,
|
|
3847
|
+
session: s.session,
|
|
3686
3848
|
callback: {
|
|
3687
|
-
address:
|
|
3688
|
-
data:
|
|
3849
|
+
address: s.callback,
|
|
3850
|
+
data: s.callbackData
|
|
3689
3851
|
},
|
|
3690
|
-
receiverIfMakerIsSeller:
|
|
3852
|
+
receiverIfMakerIsSeller: s.receiverIfMakerIsSeller,
|
|
3853
|
+
exitOnly: s.exitOnly
|
|
3691
3854
|
});
|
|
3692
3855
|
}
|
|
3693
3856
|
/**
|
|
@@ -3705,9 +3868,9 @@ const takeEvent = {
|
|
|
3705
3868
|
},
|
|
3706
3869
|
{
|
|
3707
3870
|
name: "id_",
|
|
3708
|
-
type: "
|
|
3871
|
+
type: "bytes32",
|
|
3709
3872
|
indexed: true,
|
|
3710
|
-
internalType: "
|
|
3873
|
+
internalType: "bytes32"
|
|
3711
3874
|
},
|
|
3712
3875
|
{
|
|
3713
3876
|
name: "maker",
|
|
@@ -3740,29 +3903,11 @@ const takeEvent = {
|
|
|
3740
3903
|
internalType: "uint256"
|
|
3741
3904
|
},
|
|
3742
3905
|
{
|
|
3743
|
-
name: "
|
|
3906
|
+
name: "units",
|
|
3744
3907
|
type: "uint256",
|
|
3745
3908
|
indexed: false,
|
|
3746
3909
|
internalType: "uint256"
|
|
3747
3910
|
},
|
|
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
3911
|
{
|
|
3767
3912
|
name: "sellerReceiver",
|
|
3768
3913
|
type: "address",
|
|
@@ -3780,19 +3925,31 @@ const takeEvent = {
|
|
|
3780
3925
|
type: "uint256",
|
|
3781
3926
|
indexed: false,
|
|
3782
3927
|
internalType: "uint256"
|
|
3928
|
+
},
|
|
3929
|
+
{
|
|
3930
|
+
name: "totalUnits",
|
|
3931
|
+
type: "uint256",
|
|
3932
|
+
indexed: false,
|
|
3933
|
+
internalType: "uint256"
|
|
3783
3934
|
}
|
|
3784
3935
|
],
|
|
3785
3936
|
anonymous: false
|
|
3786
3937
|
};
|
|
3787
3938
|
/**
|
|
3788
|
-
* ABI for the
|
|
3939
|
+
* ABI for the SetConsumed event emitted by the Morpho V2 contract.
|
|
3789
3940
|
*/
|
|
3790
3941
|
const consumedEvent = {
|
|
3791
3942
|
type: "event",
|
|
3792
|
-
name: "
|
|
3943
|
+
name: "SetConsumed",
|
|
3793
3944
|
inputs: [
|
|
3794
3945
|
{
|
|
3795
|
-
name: "
|
|
3946
|
+
name: "caller",
|
|
3947
|
+
type: "address",
|
|
3948
|
+
indexed: true,
|
|
3949
|
+
internalType: "address"
|
|
3950
|
+
},
|
|
3951
|
+
{
|
|
3952
|
+
name: "onBehalf",
|
|
3796
3953
|
type: "address",
|
|
3797
3954
|
indexed: true,
|
|
3798
3955
|
internalType: "address"
|
|
@@ -3827,12 +3984,12 @@ const repayEvent = {
|
|
|
3827
3984
|
},
|
|
3828
3985
|
{
|
|
3829
3986
|
name: "id_",
|
|
3830
|
-
type: "
|
|
3987
|
+
type: "bytes32",
|
|
3831
3988
|
indexed: true,
|
|
3832
|
-
internalType: "
|
|
3989
|
+
internalType: "bytes32"
|
|
3833
3990
|
},
|
|
3834
3991
|
{
|
|
3835
|
-
name: "
|
|
3992
|
+
name: "units",
|
|
3836
3993
|
type: "uint256",
|
|
3837
3994
|
indexed: false,
|
|
3838
3995
|
internalType: "uint256"
|
|
@@ -3861,9 +4018,9 @@ const liquidateEvent = {
|
|
|
3861
4018
|
},
|
|
3862
4019
|
{
|
|
3863
4020
|
name: "id_",
|
|
3864
|
-
type: "
|
|
4021
|
+
type: "bytes32",
|
|
3865
4022
|
indexed: true,
|
|
3866
|
-
internalType: "
|
|
4023
|
+
internalType: "bytes32"
|
|
3867
4024
|
},
|
|
3868
4025
|
{
|
|
3869
4026
|
name: "collateralIndex",
|
|
@@ -3894,6 +4051,12 @@ const liquidateEvent = {
|
|
|
3894
4051
|
type: "uint256",
|
|
3895
4052
|
indexed: false,
|
|
3896
4053
|
internalType: "uint256"
|
|
4054
|
+
},
|
|
4055
|
+
{
|
|
4056
|
+
name: "latestLossIndex",
|
|
4057
|
+
type: "uint256",
|
|
4058
|
+
indexed: false,
|
|
4059
|
+
internalType: "uint256"
|
|
3897
4060
|
}
|
|
3898
4061
|
],
|
|
3899
4062
|
anonymous: false
|
|
@@ -3913,9 +4076,9 @@ const supplyCollateralEvent = {
|
|
|
3913
4076
|
},
|
|
3914
4077
|
{
|
|
3915
4078
|
name: "id_",
|
|
3916
|
-
type: "
|
|
4079
|
+
type: "bytes32",
|
|
3917
4080
|
indexed: true,
|
|
3918
|
-
internalType: "
|
|
4081
|
+
internalType: "bytes32"
|
|
3919
4082
|
},
|
|
3920
4083
|
{
|
|
3921
4084
|
name: "collateral",
|
|
@@ -3953,9 +4116,9 @@ const withdrawCollateralEvent = {
|
|
|
3953
4116
|
},
|
|
3954
4117
|
{
|
|
3955
4118
|
name: "id_",
|
|
3956
|
-
type: "
|
|
4119
|
+
type: "bytes32",
|
|
3957
4120
|
indexed: true,
|
|
3958
|
-
internalType: "
|
|
4121
|
+
internalType: "bytes32"
|
|
3959
4122
|
},
|
|
3960
4123
|
{
|
|
3961
4124
|
name: "collateral",
|
|
@@ -4228,7 +4391,7 @@ var TradingFee_exports = /* @__PURE__ */ __exportAll({
|
|
|
4228
4391
|
});
|
|
4229
4392
|
/**
|
|
4230
4393
|
* Time breakpoints in seconds for piecewise linear fee interpolation.
|
|
4231
|
-
* Matches on-chain constants: 0d, 1d, 7d, 30d, 90d, 180d.
|
|
4394
|
+
* Matches on-chain constants: 0d, 1d, 7d, 30d, 90d, 180d, 360d.
|
|
4232
4395
|
*/
|
|
4233
4396
|
const BREAKPOINTS = [
|
|
4234
4397
|
0n,
|
|
@@ -4236,21 +4399,22 @@ const BREAKPOINTS = [
|
|
|
4236
4399
|
604800n,
|
|
4237
4400
|
2592000n,
|
|
4238
4401
|
7776000n,
|
|
4239
|
-
15552000n
|
|
4402
|
+
15552000n,
|
|
4403
|
+
31104000n
|
|
4240
4404
|
];
|
|
4241
4405
|
/** WAD constant (1e18) for fee scaling. */
|
|
4242
4406
|
const WAD = 10n ** 18n;
|
|
4243
4407
|
/**
|
|
4244
|
-
* Create a TradingFee from an activation flag and
|
|
4408
|
+
* Create a TradingFee from an activation flag and 7 fee values.
|
|
4245
4409
|
* @param activated - Whether the fee is active.
|
|
4246
|
-
* @param fees - Tuple of
|
|
4410
|
+
* @param fees - Tuple of 7 fee values in WAD (one per breakpoint: 0d, 1d, 7d, 30d, 90d, 180d, 360d).
|
|
4247
4411
|
* @returns A new TradingFee instance.
|
|
4248
4412
|
* @throws {@link InvalidFeeError} if any fee exceeds WAD (100%).
|
|
4249
|
-
* @throws {@link InvalidFeesLengthError} if fees array doesn't have exactly
|
|
4413
|
+
* @throws {@link InvalidFeesLengthError} if fees array doesn't have exactly 7 elements.
|
|
4250
4414
|
*/
|
|
4251
4415
|
function from$3(activated, fees) {
|
|
4252
|
-
if (fees.length !==
|
|
4253
|
-
for (let i = 0; i <
|
|
4416
|
+
if (fees.length !== 7) throw new InvalidFeesLengthError(fees.length);
|
|
4417
|
+
for (let i = 0; i < 7; i++) {
|
|
4254
4418
|
const fee = fees[i];
|
|
4255
4419
|
if (fee < 0n || fee > WAD) throw new InvalidFeeError(fee, i);
|
|
4256
4420
|
}
|
|
@@ -4269,7 +4433,9 @@ function from$3(activated, fees) {
|
|
|
4269
4433
|
function compute(tradingFee, timeToMaturity) {
|
|
4270
4434
|
if (!tradingFee._activated) return 0n;
|
|
4271
4435
|
const time = BigInt(Math.max(0, Math.floor(timeToMaturity)));
|
|
4272
|
-
|
|
4436
|
+
const maxBreakpoint = BREAKPOINTS[BREAKPOINTS.length - 1];
|
|
4437
|
+
const maxFee = tradingFee._fees[tradingFee._fees.length - 1];
|
|
4438
|
+
if (time >= maxBreakpoint) return maxFee;
|
|
4273
4439
|
const { index, start, end } = getSegment(time);
|
|
4274
4440
|
const feeLower = tradingFee._fees[index];
|
|
4275
4441
|
const feeUpper = tradingFee._fees[index + 1];
|
|
@@ -4309,7 +4475,7 @@ function deactivate(tradingFee) {
|
|
|
4309
4475
|
/**
|
|
4310
4476
|
* Get the fee values at each breakpoint.
|
|
4311
4477
|
* @param tradingFee - The TradingFee instance.
|
|
4312
|
-
* @returns The tuple of
|
|
4478
|
+
* @returns The tuple of 7 fee values.
|
|
4313
4479
|
*/
|
|
4314
4480
|
function getFees(tradingFee) {
|
|
4315
4481
|
return tradingFee._fees;
|
|
@@ -4320,30 +4486,21 @@ function getFees(tradingFee) {
|
|
|
4320
4486
|
* @returns Object with index, start, and end of the segment.
|
|
4321
4487
|
*/
|
|
4322
4488
|
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
|
-
};
|
|
4489
|
+
for (let segmentEndIndex = 1; segmentEndIndex < BREAKPOINTS.length; segmentEndIndex++) {
|
|
4490
|
+
const end = BREAKPOINTS[segmentEndIndex];
|
|
4491
|
+
if (timeToMaturity < end) {
|
|
4492
|
+
const index = segmentEndIndex - 1;
|
|
4493
|
+
return {
|
|
4494
|
+
index,
|
|
4495
|
+
start: BREAKPOINTS[index],
|
|
4496
|
+
end
|
|
4497
|
+
};
|
|
4498
|
+
}
|
|
4499
|
+
}
|
|
4343
4500
|
return {
|
|
4344
|
-
index:
|
|
4345
|
-
start: BREAKPOINTS[
|
|
4346
|
-
end: BREAKPOINTS[
|
|
4501
|
+
index: BREAKPOINTS.length - 2,
|
|
4502
|
+
start: BREAKPOINTS[BREAKPOINTS.length - 2],
|
|
4503
|
+
end: BREAKPOINTS[BREAKPOINTS.length - 1]
|
|
4347
4504
|
};
|
|
4348
4505
|
}
|
|
4349
4506
|
/** Error thrown when a fee value is invalid (negative or exceeds WAD). */
|
|
@@ -4353,11 +4510,11 @@ var InvalidFeeError = class extends BaseError {
|
|
|
4353
4510
|
super(`Invalid fee at index ${index}: ${fee}. Fee must be between 0 and ${WAD} (WAD).`);
|
|
4354
4511
|
}
|
|
4355
4512
|
};
|
|
4356
|
-
/** Error thrown when fees array doesn't have exactly
|
|
4513
|
+
/** Error thrown when fees array doesn't have exactly 7 elements. */
|
|
4357
4514
|
var InvalidFeesLengthError = class extends BaseError {
|
|
4358
4515
|
name = "TradingFee.InvalidFeesLengthError";
|
|
4359
4516
|
constructor(length) {
|
|
4360
|
-
super(`Invalid fees length: ${length}. Expected exactly
|
|
4517
|
+
super(`Invalid fees length: ${length}. Expected exactly 7 fee values.`);
|
|
4361
4518
|
}
|
|
4362
4519
|
};
|
|
4363
4520
|
|
|
@@ -4395,6 +4552,9 @@ function from$2(parameters) {
|
|
|
4395
4552
|
var Tree_exports = /* @__PURE__ */ __exportAll({
|
|
4396
4553
|
DecodeError: () => DecodeError,
|
|
4397
4554
|
EncodeError: () => EncodeError,
|
|
4555
|
+
MAX_COMPRESSED_OFFERS_BYTES: () => MAX_COMPRESSED_OFFERS_BYTES,
|
|
4556
|
+
MAX_DECOMPRESSED_OFFERS_BYTES: () => MAX_DECOMPRESSED_OFFERS_BYTES,
|
|
4557
|
+
MAX_OFFERS_PER_TREE: () => MAX_OFFERS_PER_TREE,
|
|
4398
4558
|
SignatureDomainError: () => SignatureDomainError,
|
|
4399
4559
|
TreeError: () => TreeError,
|
|
4400
4560
|
VERSION: () => VERSION$1,
|
|
@@ -4406,7 +4566,16 @@ var Tree_exports = /* @__PURE__ */ __exportAll({
|
|
|
4406
4566
|
signatureDomain: () => signatureDomain,
|
|
4407
4567
|
signatureTypes: () => signatureTypes
|
|
4408
4568
|
});
|
|
4409
|
-
const VERSION$1 =
|
|
4569
|
+
const VERSION$1 = 2;
|
|
4570
|
+
const MAX_COMPRESSED_OFFERS_BYTES = 1e6;
|
|
4571
|
+
const MAX_DECOMPRESSED_OFFERS_BYTES = 4e6;
|
|
4572
|
+
const MAX_OFFERS_PER_TREE = 100;
|
|
4573
|
+
const ROOT_BYTES = 32;
|
|
4574
|
+
const SIGNATURE_BYTES = 65;
|
|
4575
|
+
const MIN_SIGNED_PAYLOAD_BYTES = 1 + ROOT_BYTES + SIGNATURE_BYTES;
|
|
4576
|
+
const INFLATE_INPUT_CHUNK_BYTES = 64 * 1024;
|
|
4577
|
+
const UTF8_ENCODER = new TextEncoder();
|
|
4578
|
+
const UTF8_DECODER = new TextDecoder();
|
|
4410
4579
|
/**
|
|
4411
4580
|
* EIP-712 types for signing the tree root (Root(bytes32 root)).
|
|
4412
4581
|
*/
|
|
@@ -4423,29 +4592,83 @@ const signatureTypes = {
|
|
|
4423
4592
|
type: "bytes32"
|
|
4424
4593
|
}]
|
|
4425
4594
|
};
|
|
4426
|
-
const
|
|
4595
|
+
const gzipOffersPayload = (payload, errorFactory) => {
|
|
4596
|
+
const payloadBytes = UTF8_ENCODER.encode(payload);
|
|
4597
|
+
if (payloadBytes.length > MAX_DECOMPRESSED_OFFERS_BYTES) throw errorFactory(`decompressed offers exceed ${MAX_DECOMPRESSED_OFFERS_BYTES} bytes`);
|
|
4598
|
+
try {
|
|
4599
|
+
const compressed = gzip(payloadBytes);
|
|
4600
|
+
if (compressed.length > MAX_COMPRESSED_OFFERS_BYTES) throw errorFactory(`compressed offers exceed ${MAX_COMPRESSED_OFFERS_BYTES} bytes`);
|
|
4601
|
+
return compressed;
|
|
4602
|
+
} catch (error) {
|
|
4603
|
+
if (error instanceof BaseError) throw error;
|
|
4604
|
+
throw errorFactory("compression failed");
|
|
4605
|
+
}
|
|
4606
|
+
};
|
|
4607
|
+
const gunzipOffersPayload = (compressed, errorFactory) => {
|
|
4608
|
+
if (compressed.length === 0) throw errorFactory("decompression failed");
|
|
4609
|
+
if (compressed.length > MAX_COMPRESSED_OFFERS_BYTES) throw errorFactory(`compressed offers exceed ${MAX_COMPRESSED_OFFERS_BYTES} bytes`);
|
|
4610
|
+
let totalLength = 0;
|
|
4611
|
+
const inflate = new Inflate();
|
|
4612
|
+
const defaultOnData = inflate.onData.bind(inflate);
|
|
4613
|
+
inflate.onData = (chunk) => {
|
|
4614
|
+
totalLength += chunk.length;
|
|
4615
|
+
if (totalLength > MAX_DECOMPRESSED_OFFERS_BYTES) throw errorFactory(`decompressed offers exceed ${MAX_DECOMPRESSED_OFFERS_BYTES} bytes`);
|
|
4616
|
+
defaultOnData(chunk);
|
|
4617
|
+
};
|
|
4618
|
+
try {
|
|
4619
|
+
for (let offset = 0; offset < compressed.length; offset += INFLATE_INPUT_CHUNK_BYTES) {
|
|
4620
|
+
const end = Math.min(offset + INFLATE_INPUT_CHUNK_BYTES, compressed.length);
|
|
4621
|
+
inflate.push(compressed.subarray(offset, end), end === compressed.length);
|
|
4622
|
+
}
|
|
4623
|
+
} catch (error) {
|
|
4624
|
+
if (error instanceof BaseError) throw error;
|
|
4625
|
+
throw errorFactory("decompression failed");
|
|
4626
|
+
}
|
|
4627
|
+
if (inflate.err !== 0) throw errorFactory(inflate.msg || "decompression failed");
|
|
4628
|
+
if (!(inflate.result instanceof Uint8Array)) throw errorFactory("decompression failed");
|
|
4629
|
+
return UTF8_DECODER.decode(inflate.result);
|
|
4630
|
+
};
|
|
4631
|
+
const parseRawOffersPayload = (decoded, errorFactory) => {
|
|
4632
|
+
let rawOffers;
|
|
4633
|
+
try {
|
|
4634
|
+
rawOffers = JSON.parse(decoded);
|
|
4635
|
+
} catch {
|
|
4636
|
+
throw errorFactory("JSON parse failed");
|
|
4637
|
+
}
|
|
4638
|
+
if (!Array.isArray(rawOffers)) throw errorFactory("offers payload must be a JSON array");
|
|
4639
|
+
if (rawOffers.length > MAX_OFFERS_PER_TREE) throw errorFactory(`offers payload exceeds ${MAX_OFFERS_PER_TREE} offers`);
|
|
4640
|
+
return rawOffers;
|
|
4641
|
+
};
|
|
4642
|
+
const assertUniqueOfferHashes = (offers, errorFactory) => {
|
|
4643
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4644
|
+
for (const offer of offers) {
|
|
4645
|
+
const hash$1 = hash(offer);
|
|
4646
|
+
if (seen.has(hash$1)) throw errorFactory(`duplicate offer hash ${hash$1}`);
|
|
4647
|
+
seen.add(hash$1);
|
|
4648
|
+
}
|
|
4649
|
+
};
|
|
4427
4650
|
/**
|
|
4428
4651
|
* Builds a Merkle tree from a list of offers.
|
|
4429
4652
|
*
|
|
4430
4653
|
* Leaves are the offer `hash` values as `bytes32` and are deterministically
|
|
4431
|
-
* ordered
|
|
4432
|
-
* root is stable regardless of the input order.
|
|
4654
|
+
* ordered so that the resulting root is stable regardless of the input order.
|
|
4433
4655
|
*
|
|
4434
4656
|
* @param offers - Offers to include in the tree.
|
|
4435
|
-
* @returns A `
|
|
4657
|
+
* @returns A `SimpleMerkleTree` of offer hashes representing the offers.
|
|
4436
4658
|
* @throws {TreeError} If tree building fails due to offer inconsistencies.
|
|
4437
4659
|
*/
|
|
4438
4660
|
const from$1 = (offers) => {
|
|
4439
|
-
|
|
4440
|
-
const
|
|
4661
|
+
assertUniqueOfferHashes(offers, (reason) => new TreeError(reason));
|
|
4662
|
+
const leaves = offers.map((offer) => hash(offer));
|
|
4663
|
+
const tree = SimpleMerkleTree.of(leaves);
|
|
4441
4664
|
const orderedOffers = orderOffers(tree, offers);
|
|
4442
4665
|
return Object.assign(tree, { offers: orderedOffers });
|
|
4443
4666
|
};
|
|
4444
4667
|
const orderOffers = (tree, offers) => {
|
|
4445
4668
|
const offerByHash = /* @__PURE__ */ new Map();
|
|
4446
|
-
for (const offer of offers) offerByHash.set(
|
|
4669
|
+
for (const offer of offers) offerByHash.set(hash(offer), offer);
|
|
4447
4670
|
const entries = tree.dump().values.map((value) => {
|
|
4448
|
-
const hash =
|
|
4671
|
+
const hash = value.value;
|
|
4449
4672
|
const offer = offerByHash.get(hash);
|
|
4450
4673
|
if (!offer) throw new TreeError(`missing offer for leaf ${hash}`);
|
|
4451
4674
|
return {
|
|
@@ -4460,7 +4683,7 @@ const orderOffers = (tree, offers) => {
|
|
|
4460
4683
|
* Generates merkle proofs for all offers in a tree.
|
|
4461
4684
|
*
|
|
4462
4685
|
* Each proof allows independent verification that an offer is included in the tree
|
|
4463
|
-
* without requiring the full tree.
|
|
4686
|
+
* without requiring the full tree.
|
|
4464
4687
|
*
|
|
4465
4688
|
* @param tree - The {@link Tree} to generate proofs for.
|
|
4466
4689
|
* @returns Array of proofs - {@link Proof}
|
|
@@ -4469,7 +4692,7 @@ const proofs = (tree) => {
|
|
|
4469
4692
|
return tree.offers.map((offer) => {
|
|
4470
4693
|
return {
|
|
4471
4694
|
offer,
|
|
4472
|
-
path: tree.getProof(
|
|
4695
|
+
path: tree.getProof(hash(offer))
|
|
4473
4696
|
};
|
|
4474
4697
|
});
|
|
4475
4698
|
};
|
|
@@ -4601,14 +4824,15 @@ const encodeUnsigned = (tree) => {
|
|
|
4601
4824
|
};
|
|
4602
4825
|
const validateTreeForEncoding = (tree) => {
|
|
4603
4826
|
if (VERSION$1 > 255) throw new EncodeError(`version overflow: ${VERSION$1} exceeds 255`);
|
|
4827
|
+
if (tree.offers.length > MAX_OFFERS_PER_TREE) throw new EncodeError(`offers payload exceeds ${MAX_OFFERS_PER_TREE} offers`);
|
|
4604
4828
|
const computed = from$1(tree.offers);
|
|
4605
4829
|
if (tree.root !== computed.root) throw new EncodeError(`root mismatch: expected ${computed.root}, got ${tree.root}`);
|
|
4606
4830
|
};
|
|
4607
4831
|
const encodeUnsignedBytes = (tree) => {
|
|
4608
4832
|
const offersPayload = tree.offers.map(serialize);
|
|
4609
|
-
const compressed =
|
|
4833
|
+
const compressed = gzipOffersPayload(JSON.stringify(offersPayload), (reason) => new EncodeError(reason));
|
|
4610
4834
|
const rootBytes = hexToBytes(tree.root);
|
|
4611
|
-
const encoded = new Uint8Array(1 + compressed.length +
|
|
4835
|
+
const encoded = new Uint8Array(1 + compressed.length + ROOT_BYTES);
|
|
4612
4836
|
encoded[0] = VERSION$1;
|
|
4613
4837
|
encoded.set(compressed, 1);
|
|
4614
4838
|
encoded.set(rootBytes, 1 + compressed.length);
|
|
@@ -4621,10 +4845,11 @@ const encodeUnsignedBytes = (tree) => {
|
|
|
4621
4845
|
* Returns the tree with separately validated signature and recovered signer address.
|
|
4622
4846
|
*
|
|
4623
4847
|
* Validation order:
|
|
4624
|
-
* 1. Version
|
|
4848
|
+
* 1. Version and static size checks
|
|
4625
4849
|
* 2. Signature verification (fail-fast, before decompression)
|
|
4626
|
-
* 3.
|
|
4627
|
-
* 4.
|
|
4850
|
+
* 3. Streaming decompression with byte cap
|
|
4851
|
+
* 4. JSON array + offer count checks
|
|
4852
|
+
* 5. Root verification (computed from offers vs embedded root)
|
|
4628
4853
|
*
|
|
4629
4854
|
* @example
|
|
4630
4855
|
* ```typescript
|
|
@@ -4641,33 +4866,20 @@ const decode = async (encoded, domain) => {
|
|
|
4641
4866
|
const errorFactory = (reason) => new DecodeError(reason);
|
|
4642
4867
|
const normalizedDomain = normalizeSignatureDomain(domain, errorFactory);
|
|
4643
4868
|
const bytes = hexToBytes(encoded);
|
|
4644
|
-
if (bytes.length <
|
|
4869
|
+
if (bytes.length < MIN_SIGNED_PAYLOAD_BYTES) throw new DecodeError("payload too short");
|
|
4645
4870
|
const version = bytes[0];
|
|
4646
4871
|
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,
|
|
4872
|
+
const signature = bytesToHex(bytes.slice(-SIGNATURE_BYTES));
|
|
4873
|
+
const root = bytesToHex(bytes.slice(-(ROOT_BYTES + SIGNATURE_BYTES), -SIGNATURE_BYTES));
|
|
4874
|
+
assertHex(root, ROOT_BYTES, "root");
|
|
4875
|
+
assertHex(signature, SIGNATURE_BYTES, "signature");
|
|
4651
4876
|
const signer = await verifySignatureAndRecoverAddress({
|
|
4652
4877
|
root,
|
|
4653
4878
|
signature,
|
|
4654
4879
|
domain: normalizedDomain,
|
|
4655
4880
|
errorFactory
|
|
4656
4881
|
});
|
|
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)));
|
|
4882
|
+
const tree = from$1(parseRawOffersPayload(gunzipOffersPayload(bytes.slice(1, -(ROOT_BYTES + SIGNATURE_BYTES)), errorFactory), errorFactory).map((o) => OfferSchema().parse(o)));
|
|
4671
4883
|
if (root !== tree.root) throw new DecodeError(`root mismatch: expected ${tree.root}, got ${root}`);
|
|
4672
4884
|
return {
|
|
4673
4885
|
tree,
|
|
@@ -4786,11 +4998,10 @@ async function getOffers(apiClient, parameters) {
|
|
|
4786
4998
|
return {
|
|
4787
4999
|
...fromSnakeCase$1({
|
|
4788
5000
|
maker: offerData.maker,
|
|
4789
|
-
|
|
4790
|
-
obligation_units: offerData.obligation_units,
|
|
4791
|
-
obligation_shares: offerData.obligation_shares,
|
|
5001
|
+
max_units: offerData.max_units,
|
|
4792
5002
|
tick: offerData.tick,
|
|
4793
5003
|
maturity: from$9(offerData.obligation.maturity),
|
|
5004
|
+
rcf_threshold: offerData.obligation.rcf_threshold,
|
|
4794
5005
|
expiry: offerData.expiry,
|
|
4795
5006
|
start: offerData.start,
|
|
4796
5007
|
group: offerData.group,
|
|
@@ -4800,13 +5011,15 @@ async function getOffers(apiClient, parameters) {
|
|
|
4800
5011
|
collaterals: offerData.obligation.collaterals.map((collateral) => ({
|
|
4801
5012
|
asset: collateral.token,
|
|
4802
5013
|
oracle: collateral.oracle,
|
|
4803
|
-
lltv: collateral.lltv
|
|
5014
|
+
lltv: collateral.lltv,
|
|
5015
|
+
max_lif: collateral.max_lif
|
|
4804
5016
|
})),
|
|
4805
5017
|
callback: {
|
|
4806
5018
|
address: offerData.callback,
|
|
4807
5019
|
data: offerData.callback_data
|
|
4808
5020
|
},
|
|
4809
|
-
receiver_if_maker_is_seller: offerData.receiver_if_maker_is_seller
|
|
5021
|
+
receiver_if_maker_is_seller: offerData.receiver_if_maker_is_seller,
|
|
5022
|
+
exit_only: offerData.exit_only ?? false
|
|
4810
5023
|
}),
|
|
4811
5024
|
hash: item.offer_hash,
|
|
4812
5025
|
consumed: BigInt(item.consumed),
|
|
@@ -4847,9 +5060,11 @@ async function getObligations(apiClient, parameters) {
|
|
|
4847
5060
|
collaterals: item.collaterals.map((collateral) => ({
|
|
4848
5061
|
asset: collateral.token,
|
|
4849
5062
|
oracle: collateral.oracle,
|
|
4850
|
-
lltv: collateral.lltv
|
|
5063
|
+
lltv: collateral.lltv,
|
|
5064
|
+
max_lif: collateral.max_lif
|
|
4851
5065
|
})),
|
|
4852
|
-
maturity: from$9(item.maturity)
|
|
5066
|
+
maturity: from$9(item.maturity),
|
|
5067
|
+
rcf_threshold: item.rcf_threshold
|
|
4853
5068
|
});
|
|
4854
5069
|
const { obligationId: _, ...quote } = from$4({
|
|
4855
5070
|
obligationId: item.id,
|
|
@@ -5140,7 +5355,6 @@ const assets = {
|
|
|
5140
5355
|
"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
5141
5356
|
"0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb",
|
|
5142
5357
|
"0x4200000000000000000000000000000000000006",
|
|
5143
|
-
"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",
|
|
5144
5358
|
"0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf",
|
|
5145
5359
|
"0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452",
|
|
5146
5360
|
"0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42"
|
|
@@ -5337,6 +5551,34 @@ function lazy(pollFn) {
|
|
|
5337
5551
|
})();
|
|
5338
5552
|
}
|
|
5339
5553
|
|
|
5554
|
+
//#endregion
|
|
5555
|
+
//#region src/utils/mapWithConcurrency.ts
|
|
5556
|
+
/**
|
|
5557
|
+
* Map values with a bounded number of concurrent async workers.
|
|
5558
|
+
*
|
|
5559
|
+
* Result ordering always matches the input order.
|
|
5560
|
+
* @param parameters - Input values, concurrency limit, and async mapper.
|
|
5561
|
+
* @returns Mapped results in input order.
|
|
5562
|
+
*/
|
|
5563
|
+
async function mapWithConcurrency(parameters) {
|
|
5564
|
+
const { values, limit, run } = parameters;
|
|
5565
|
+
if (values.length === 0) return [];
|
|
5566
|
+
const normalizedLimit = Math.max(1, Math.floor(limit));
|
|
5567
|
+
const workerCount = Math.min(normalizedLimit, values.length);
|
|
5568
|
+
const results = new Array(values.length);
|
|
5569
|
+
let nextIndex = 0;
|
|
5570
|
+
const worker = async () => {
|
|
5571
|
+
while (true) {
|
|
5572
|
+
const index = nextIndex;
|
|
5573
|
+
if (index >= values.length) return;
|
|
5574
|
+
nextIndex += 1;
|
|
5575
|
+
results[index] = await run(values[index], index);
|
|
5576
|
+
}
|
|
5577
|
+
};
|
|
5578
|
+
await Promise.all(Array.from({ length: workerCount }, () => worker()));
|
|
5579
|
+
return results;
|
|
5580
|
+
}
|
|
5581
|
+
|
|
5340
5582
|
//#endregion
|
|
5341
5583
|
//#region src/utils/wait.ts
|
|
5342
5584
|
async function wait(time) {
|
|
@@ -5378,6 +5620,20 @@ function max() {
|
|
|
5378
5620
|
return 0x77e772392b600000;
|
|
5379
5621
|
}
|
|
5380
5622
|
|
|
5623
|
+
//#endregion
|
|
5624
|
+
//#region src/utils/trim.ts
|
|
5625
|
+
/**
|
|
5626
|
+
* Keep the last `keep` entries from an array.
|
|
5627
|
+
* @param array - Source array.
|
|
5628
|
+
* @param keep - Number of entries to keep.
|
|
5629
|
+
* @returns Trimmed copy.
|
|
5630
|
+
*/
|
|
5631
|
+
const trimTail = (array, keep) => {
|
|
5632
|
+
if (!Number.isInteger(keep) || keep < 0) throw new Error(`trimTail: expected non-negative integer keep, got ${keep}`);
|
|
5633
|
+
if (array.length <= keep) return array.slice();
|
|
5634
|
+
return array.slice(array.length - keep);
|
|
5635
|
+
};
|
|
5636
|
+
|
|
5381
5637
|
//#endregion
|
|
5382
5638
|
//#region src/utils/index.ts
|
|
5383
5639
|
var utils_exports = /* @__PURE__ */ __exportAll({
|
|
@@ -5391,18 +5647,20 @@ var utils_exports = /* @__PURE__ */ __exportAll({
|
|
|
5391
5647
|
batchMulticall: () => batchMulticall,
|
|
5392
5648
|
fromSnakeCase: () => fromSnakeCase$3,
|
|
5393
5649
|
lazy: () => lazy,
|
|
5650
|
+
mapWithConcurrency: () => mapWithConcurrency,
|
|
5394
5651
|
max: () => max$1,
|
|
5395
5652
|
min: () => min,
|
|
5396
5653
|
poll: () => poll,
|
|
5397
5654
|
retry: () => retry,
|
|
5398
5655
|
stringifyBigint: () => stringifyBigint,
|
|
5399
5656
|
toSnakeCase: () => toSnakeCase$1,
|
|
5657
|
+
trimTail: () => trimTail,
|
|
5400
5658
|
wait: () => wait
|
|
5401
5659
|
});
|
|
5402
5660
|
|
|
5403
5661
|
//#endregion
|
|
5404
5662
|
//#region src/database/drizzle/VERSION.ts
|
|
5405
|
-
const VERSION = "router_v1.
|
|
5663
|
+
const VERSION = "router_v1.16";
|
|
5406
5664
|
|
|
5407
5665
|
//#endregion
|
|
5408
5666
|
//#region src/database/drizzle/schema.ts
|
|
@@ -5422,6 +5680,7 @@ var EnumTableName = /* @__PURE__ */ function(EnumTableName) {
|
|
|
5422
5680
|
EnumTableName["VALIDATIONS"] = "validations";
|
|
5423
5681
|
EnumTableName["COLLECTORS"] = "collectors";
|
|
5424
5682
|
EnumTableName["CHAINS"] = "chains";
|
|
5683
|
+
EnumTableName["PENDING_LINKS"] = "pending_links";
|
|
5425
5684
|
EnumTableName["LOTS"] = "lots";
|
|
5426
5685
|
EnumTableName["LOTS_POSITIONS"] = "lots_positions";
|
|
5427
5686
|
EnumTableName["OFFSETS"] = "offsets";
|
|
@@ -5434,10 +5693,14 @@ const VERSIONED_TABLE_NAMES = TABLE_NAMES.map((table) => `"${VERSION}"."${table}
|
|
|
5434
5693
|
const obligations = s.table(EnumTableName.OBLIGATIONS, {
|
|
5435
5694
|
obligationKey: varchar("obligation_key", { length: 66 }).primaryKey(),
|
|
5436
5695
|
loanToken: varchar("loan_token", { length: 42 }).notNull(),
|
|
5437
|
-
maturity: integer("maturity").notNull()
|
|
5696
|
+
maturity: integer("maturity").notNull(),
|
|
5697
|
+
rcfThreshold: numeric("rcf_threshold", {
|
|
5698
|
+
precision: 78,
|
|
5699
|
+
scale: 0
|
|
5700
|
+
}).notNull()
|
|
5438
5701
|
});
|
|
5439
5702
|
const obligationIdKeys = s.table(EnumTableName.OBLIGATION_ID_KEYS, {
|
|
5440
|
-
obligationId: varchar("obligation_id", { length:
|
|
5703
|
+
obligationId: varchar("obligation_id", { length: 66 }).primaryKey(),
|
|
5441
5704
|
obligationKey: varchar("obligation_key", { length: 66 }).notNull().references(() => obligations.obligationKey, { onDelete: "cascade" }),
|
|
5442
5705
|
chainId: bigint("chain_id", { mode: "number" }).$type().notNull(),
|
|
5443
5706
|
morphoV2: varchar("morpho_v2", { length: 42 }).notNull()
|
|
@@ -5459,7 +5722,7 @@ const groups = s.table(EnumTableName.GROUPS, {
|
|
|
5459
5722
|
table.group
|
|
5460
5723
|
],
|
|
5461
5724
|
name: "groups_pk"
|
|
5462
|
-
})
|
|
5725
|
+
})]);
|
|
5463
5726
|
const consumedEvents = s.table(EnumTableName.CONSUMED_EVENTS, {
|
|
5464
5727
|
eventId: varchar("event_id", { length: 128 }).primaryKey(),
|
|
5465
5728
|
chainId: bigint("chain_id", { mode: "number" }).$type().notNull(),
|
|
@@ -5493,16 +5756,13 @@ const obligationCollateralsV2 = s.table(EnumTableName.OBLIGATION_COLLATERALS_V2,
|
|
|
5493
5756
|
asset: varchar("asset", { length: 42 }).notNull(),
|
|
5494
5757
|
oracleAddress: varchar("oracle_address", { length: 42 }).notNull(),
|
|
5495
5758
|
lltv: bigint("lltv", { mode: "bigint" }).notNull(),
|
|
5759
|
+
maxLif: bigint("max_lif", { mode: "bigint" }).notNull(),
|
|
5496
5760
|
collateralIndex: integer("collateral_index").notNull(),
|
|
5497
5761
|
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
|
-
]);
|
|
5762
|
+
}, (table) => [primaryKey({
|
|
5763
|
+
columns: [table.obligationKey, table.asset],
|
|
5764
|
+
name: "obligation_collaterals_v2_pk"
|
|
5765
|
+
})]);
|
|
5506
5766
|
const oracles = s.table(EnumTableName.ORACLES, {
|
|
5507
5767
|
chainId: bigint("chain_id", { mode: "number" }).$type().notNull(),
|
|
5508
5768
|
address: varchar("address", { length: 42 }).notNull(),
|
|
@@ -5518,16 +5778,8 @@ const oracles = s.table(EnumTableName.ORACLES, {
|
|
|
5518
5778
|
})]);
|
|
5519
5779
|
const offers = s.table(EnumTableName.OFFERS, {
|
|
5520
5780
|
hash: varchar("hash", { length: 66 }).notNull(),
|
|
5521
|
-
obligationId: varchar("obligation_id", { length:
|
|
5522
|
-
|
|
5523
|
-
precision: 78,
|
|
5524
|
-
scale: 0
|
|
5525
|
-
}).notNull(),
|
|
5526
|
-
obligationUnits: numeric("obligation_units", {
|
|
5527
|
-
precision: 78,
|
|
5528
|
-
scale: 0
|
|
5529
|
-
}).notNull().default("0"),
|
|
5530
|
-
obligationShares: numeric("obligation_shares", {
|
|
5781
|
+
obligationId: varchar("obligation_id", { length: 66 }).notNull().references(() => obligationIdKeys.obligationId, { onDelete: "cascade" }),
|
|
5782
|
+
maxUnits: numeric("max_units", {
|
|
5531
5783
|
precision: 78,
|
|
5532
5784
|
scale: 0
|
|
5533
5785
|
}).notNull().default("0"),
|
|
@@ -5543,6 +5795,7 @@ const offers = s.table(EnumTableName.OFFERS, {
|
|
|
5543
5795
|
callbackAddress: varchar("callback_address", { length: 42 }).notNull(),
|
|
5544
5796
|
callbackData: text("callback_data").notNull(),
|
|
5545
5797
|
receiverIfMakerIsSeller: varchar("receiver_if_maker_is_seller", { length: 42 }),
|
|
5798
|
+
exitOnly: boolean("exit_only").notNull().default(false),
|
|
5546
5799
|
blockNumber: bigint("block_number", { mode: "number" }).notNull(),
|
|
5547
5800
|
updatedAt: timestamp("updated_at").defaultNow().notNull()
|
|
5548
5801
|
}, (table) => [
|
|
@@ -5563,13 +5816,16 @@ const offers = s.table(EnumTableName.OFFERS, {
|
|
|
5563
5816
|
],
|
|
5564
5817
|
name: "offers_groups_fk"
|
|
5565
5818
|
}).onDelete("cascade"),
|
|
5566
|
-
index("offers_group_fk_idx").on(table.groupChainId, table.groupMaker, table.group),
|
|
5567
5819
|
index("offers_group_and_hash_idx").on(table.groupChainId, table.groupMaker, table.group, table.hash),
|
|
5568
|
-
index("
|
|
5820
|
+
index("offers_obligation_side_tick_idx").on(table.obligationId, table.buy, table.tick),
|
|
5821
|
+
index("offers_obligation_active_tick_idx").on(table.obligationId, table.buy, table.expiry, table.maturity, table.start, table.tick),
|
|
5822
|
+
index("offers_group_maker_idx").on(table.groupMaker, table.hash, table.obligationId),
|
|
5823
|
+
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`"max_units" DESC`, table.hash),
|
|
5824
|
+
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`"max_units" DESC`, table.hash)
|
|
5569
5825
|
]);
|
|
5570
5826
|
const offersCallbacks = s.table(EnumTableName.OFFERS_CALLBACKS, {
|
|
5571
5827
|
offerHash: varchar("offer_hash", { length: 66 }).notNull(),
|
|
5572
|
-
obligationId: varchar("obligation_id", { length:
|
|
5828
|
+
obligationId: varchar("obligation_id", { length: 66 }).notNull(),
|
|
5573
5829
|
callbackId: varchar("callback_id", { length: 66 })
|
|
5574
5830
|
}, (table) => [foreignKey({
|
|
5575
5831
|
columns: [table.offerHash, table.obligationId],
|
|
@@ -5610,7 +5866,7 @@ const lots = s.table(EnumTableName.LOTS, {
|
|
|
5610
5866
|
user: varchar("user", { length: 42 }).notNull(),
|
|
5611
5867
|
contract: varchar("contract", { length: 66 }).notNull(),
|
|
5612
5868
|
group: varchar("group", { length: 66 }).notNull(),
|
|
5613
|
-
obligationId: varchar("obligation_id", { length:
|
|
5869
|
+
obligationId: varchar("obligation_id", { length: 66 }).notNull(),
|
|
5614
5870
|
lower: numeric("lower", {
|
|
5615
5871
|
precision: 78,
|
|
5616
5872
|
scale: 0
|
|
@@ -5655,40 +5911,45 @@ const lots = s.table(EnumTableName.LOTS, {
|
|
|
5655
5911
|
groups.group
|
|
5656
5912
|
],
|
|
5657
5913
|
name: "lots_groups_fk"
|
|
5658
|
-
}).onDelete("cascade")
|
|
5914
|
+
}).onDelete("cascade"),
|
|
5915
|
+
index("lots_position_group_obligation_idx").on(table.chainId, table.user, table.group, table.obligationId)
|
|
5659
5916
|
]);
|
|
5660
5917
|
const offsets = s.table(EnumTableName.OFFSETS, {
|
|
5661
5918
|
chainId: bigint("chain_id", { mode: "number" }).$type().notNull(),
|
|
5662
5919
|
user: varchar("user", { length: 42 }).notNull(),
|
|
5663
5920
|
contract: varchar("contract", { length: 66 }).notNull(),
|
|
5664
5921
|
group: varchar("group", { length: 66 }).notNull(),
|
|
5665
|
-
obligationId: varchar("obligation_id", { length:
|
|
5922
|
+
obligationId: varchar("obligation_id", { length: 66 }).notNull(),
|
|
5666
5923
|
value: numeric("value", {
|
|
5667
5924
|
precision: 78,
|
|
5668
5925
|
scale: 0
|
|
5669
5926
|
}).notNull()
|
|
5670
|
-
}, (table) => [
|
|
5671
|
-
|
|
5672
|
-
|
|
5673
|
-
|
|
5674
|
-
|
|
5675
|
-
|
|
5676
|
-
|
|
5677
|
-
|
|
5678
|
-
|
|
5679
|
-
|
|
5680
|
-
|
|
5681
|
-
|
|
5682
|
-
|
|
5683
|
-
|
|
5684
|
-
|
|
5685
|
-
|
|
5686
|
-
|
|
5687
|
-
|
|
5688
|
-
|
|
5689
|
-
|
|
5690
|
-
|
|
5691
|
-
|
|
5927
|
+
}, (table) => [
|
|
5928
|
+
primaryKey({
|
|
5929
|
+
columns: [
|
|
5930
|
+
table.chainId,
|
|
5931
|
+
table.user,
|
|
5932
|
+
table.contract,
|
|
5933
|
+
table.group,
|
|
5934
|
+
table.obligationId
|
|
5935
|
+
],
|
|
5936
|
+
name: "offsets_pk"
|
|
5937
|
+
}),
|
|
5938
|
+
foreignKey({
|
|
5939
|
+
columns: [
|
|
5940
|
+
table.chainId,
|
|
5941
|
+
table.contract,
|
|
5942
|
+
table.user
|
|
5943
|
+
],
|
|
5944
|
+
foreignColumns: [
|
|
5945
|
+
lotsPositions.chainId,
|
|
5946
|
+
lotsPositions.contract,
|
|
5947
|
+
lotsPositions.user
|
|
5948
|
+
],
|
|
5949
|
+
name: "offsets_lots_positions_fk"
|
|
5950
|
+
}).onDelete("cascade"),
|
|
5951
|
+
index("offsets_position_obligation_idx").on(table.chainId, table.contract, table.user, table.obligationId)
|
|
5952
|
+
]);
|
|
5692
5953
|
const PositionTypes = s.enum("position_type", Object.values(Type));
|
|
5693
5954
|
const positionTypes = s.table("position_types", {
|
|
5694
5955
|
id: serial("id").primaryKey(),
|
|
@@ -5775,7 +6036,7 @@ const status = s.table("status", {
|
|
|
5775
6036
|
});
|
|
5776
6037
|
const validations = s.table("validations", {
|
|
5777
6038
|
offerHash: varchar("offer_hash", { length: 66 }).notNull(),
|
|
5778
|
-
obligationId: varchar("obligation_id", { length:
|
|
6039
|
+
obligationId: varchar("obligation_id", { length: 66 }).notNull(),
|
|
5779
6040
|
statusId: integer("status_id").notNull().references(() => status.id, { onDelete: "no action" }),
|
|
5780
6041
|
updatedAt: timestamp("updated_at").defaultNow().notNull()
|
|
5781
6042
|
}, (table) => [primaryKey({
|
|
@@ -5803,8 +6064,33 @@ const chains = s.table(EnumTableName.CHAINS, {
|
|
|
5803
6064
|
precision: 78,
|
|
5804
6065
|
scale: 0
|
|
5805
6066
|
}).default("0").notNull(),
|
|
6067
|
+
checkpoints: text("checkpoints").default("[]").notNull(),
|
|
6068
|
+
tipHash: text("tip_hash"),
|
|
6069
|
+
finalizedBlockNumber: bigint("finalized_block_number", { mode: "number" }),
|
|
6070
|
+
finalizedBlockHash: text("finalized_block_hash"),
|
|
5806
6071
|
updatedAt: timestamp("updated_at").defaultNow().notNull()
|
|
5807
6072
|
}, (table) => [uniqueIndex("chains_chain_id_idx").on(table.chainId)]);
|
|
6073
|
+
const pendingLinks = s.table(EnumTableName.PENDING_LINKS, {
|
|
6074
|
+
key: varchar("key", { length: 191 }).primaryKey(),
|
|
6075
|
+
type: text("type").notNull(),
|
|
6076
|
+
status: text("status").notNull(),
|
|
6077
|
+
chainId: bigint("chain_id", { mode: "number" }).$type().notNull(),
|
|
6078
|
+
eventId: varchar("event_id", { length: 128 }).notNull(),
|
|
6079
|
+
obligationId: varchar("obligation_id", { length: 66 }).notNull(),
|
|
6080
|
+
collateralIndex: integer("collateral_index").notNull(),
|
|
6081
|
+
user: varchar("user", { length: 42 }).notNull(),
|
|
6082
|
+
amount: numeric("amount", {
|
|
6083
|
+
precision: 78,
|
|
6084
|
+
scale: 0
|
|
6085
|
+
}).notNull(),
|
|
6086
|
+
blockNumber: bigint("block_number", { mode: "number" }).notNull(),
|
|
6087
|
+
firstSeenBlock: bigint("first_seen_block", { mode: "number" }).notNull(),
|
|
6088
|
+
lastTriedBlock: bigint("last_tried_block", { mode: "number" }),
|
|
6089
|
+
attempts: integer("attempts").notNull().default(0),
|
|
6090
|
+
ignoredReason: text("ignored_reason"),
|
|
6091
|
+
resolvedAt: timestamp("resolved_at"),
|
|
6092
|
+
updatedAt: timestamp("updated_at").defaultNow().notNull()
|
|
6093
|
+
}, (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
6094
|
const trees = s.table(EnumTableName.TREES, {
|
|
5809
6095
|
root: varchar("root", { length: 66 }).primaryKey(),
|
|
5810
6096
|
rootSignature: varchar("root_signature", { length: 132 }).notNull(),
|
|
@@ -5812,7 +6098,7 @@ const trees = s.table(EnumTableName.TREES, {
|
|
|
5812
6098
|
});
|
|
5813
6099
|
const merklePaths = s.table(EnumTableName.MERKLE_PATHS, {
|
|
5814
6100
|
offerHash: varchar("offer_hash", { length: 66 }).notNull(),
|
|
5815
|
-
obligationId: varchar("obligation_id", { length:
|
|
6101
|
+
obligationId: varchar("obligation_id", { length: 66 }).notNull(),
|
|
5816
6102
|
treeRoot: varchar("tree_root", { length: 66 }).notNull().references(() => trees.root, { onDelete: "cascade" }),
|
|
5817
6103
|
proofNodes: text("proof_nodes").notNull(),
|
|
5818
6104
|
createdAt: timestamp("created_at").defaultNow().notNull()
|
|
@@ -5839,7 +6125,7 @@ function compositeKey(g) {
|
|
|
5839
6125
|
//#endregion
|
|
5840
6126
|
//#region src/gatekeeper/Rules.ts
|
|
5841
6127
|
var Rules_exports = /* @__PURE__ */ __exportAll({
|
|
5842
|
-
|
|
6128
|
+
amountNonZero: () => amountNonZero,
|
|
5843
6129
|
callback: () => callback,
|
|
5844
6130
|
collateralToken: () => collateralToken,
|
|
5845
6131
|
groupConsistency: () => groupConsistency,
|
|
@@ -5910,11 +6196,6 @@ const sameMaker = () => batch("mixed_maker", "Validates that all offers in a bat
|
|
|
5910
6196
|
return issues;
|
|
5911
6197
|
});
|
|
5912
6198
|
/**
|
|
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
6199
|
* A validation rule that checks if the offer duration (expiry - start) meets a minimum threshold.
|
|
5919
6200
|
* @param minSeconds - Minimum required duration in seconds.
|
|
5920
6201
|
* @returns The issue that was found. If the offer is valid, this will be undefined.
|
|
@@ -5932,14 +6213,20 @@ const minDuration = ({ minSeconds }) => single("min_duration", `Validates that o
|
|
|
5932
6213
|
const maxCollaterals = ({ max }) => single("max_collaterals", `Validates that an offer has at most ${max} collaterals`, (offer) => {
|
|
5933
6214
|
if (offer.collaterals.length > max) return { message: `Offer has ${offer.collaterals.length} collaterals, exceeding the maximum of ${max}` };
|
|
5934
6215
|
});
|
|
5935
|
-
|
|
5936
|
-
|
|
6216
|
+
/**
|
|
6217
|
+
* A validation rule that checks if the offer's maxUnits is non-zero.
|
|
6218
|
+
* The contract requires a positive amount; this rule rejects early.
|
|
6219
|
+
* @returns The issue that was found. If the offer is valid, this will be undefined.
|
|
6220
|
+
*/
|
|
6221
|
+
const amountNonZero = () => single("amount_non_zero", "Validates that maxUnits is non-zero", (offer) => {
|
|
6222
|
+
if (offer.maxUnits === 0n) return { message: "maxUnits must be non-zero" };
|
|
5937
6223
|
});
|
|
5938
6224
|
/**
|
|
5939
6225
|
* 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,
|
|
6226
|
+
* All offers sharing the same group must have the same loan token, maxUnits,
|
|
6227
|
+
* and side (buy/sell). The contract tracks consumed per group and requires these to match.
|
|
5941
6228
|
*/
|
|
5942
|
-
const groupConsistency = () => batch("group_consistency", "Validates that all offers in a group have the same loan token,
|
|
6229
|
+
const groupConsistency = () => batch("group_consistency", "Validates that all offers in a group have the same loan token, obligation amounts, and side", (offers) => {
|
|
5943
6230
|
const issues = /* @__PURE__ */ new Map();
|
|
5944
6231
|
if (offers.length === 0) return issues;
|
|
5945
6232
|
const groupMap = /* @__PURE__ */ new Map();
|
|
@@ -5953,13 +6240,13 @@ const groupConsistency = () => batch("group_consistency", "Validates that all of
|
|
|
5953
6240
|
if (indices.length <= 1) continue;
|
|
5954
6241
|
const reference = offers[indices[0]];
|
|
5955
6242
|
const refLoanToken = reference.loanToken.toLowerCase();
|
|
5956
|
-
const
|
|
6243
|
+
const refUnits = reference.maxUnits;
|
|
5957
6244
|
const refBuy = reference.buy;
|
|
5958
6245
|
for (let j = 1; j < indices.length; j++) {
|
|
5959
6246
|
const idx = indices[j];
|
|
5960
6247
|
const offer = offers[idx];
|
|
5961
6248
|
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.
|
|
6249
|
+
else if (offer.maxUnits !== refUnits) issues.set(idx, { message: `All offers in a group must have the same maxUnits. Expected ${refUnits}, got ${offer.maxUnits}` });
|
|
5963
6250
|
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
6251
|
}
|
|
5965
6252
|
}
|
|
@@ -6016,7 +6303,7 @@ const morphoRules = (parameters) => {
|
|
|
6016
6303
|
}
|
|
6017
6304
|
const rules = [
|
|
6018
6305
|
sameMaker(),
|
|
6019
|
-
|
|
6306
|
+
amountNonZero(),
|
|
6020
6307
|
groupConsistency(),
|
|
6021
6308
|
...config?.minDuration != null ? [minDuration({ minSeconds: config.minDuration })] : [],
|
|
6022
6309
|
maturity({ maturities: [MaturityType.EndOfWeek, MaturityType.EndOfNextWeek] }),
|