@morpho-dev/router 0.10.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -5
- package/dist/cli.js +14944 -8994
- package/dist/drizzle/migrations/0031_sell-takeable-reindex.sql +254 -0
- package/dist/drizzle/migrations/0032_callback-type.sql +3 -0
- package/dist/drizzle/migrations/0033_obligation-id-bytes20.sql +255 -0
- package/dist/drizzle/migrations/0034_chain-checkpoints.sql +1 -0
- package/dist/drizzle/migrations/0035_chain-tip-hash-cas.sql +1 -0
- package/dist/drizzle/migrations/0036_pending-links.sql +22 -0
- package/dist/drizzle/migrations/0037_chain-finalized-anchor.sql +2 -0
- package/dist/drizzle/migrations/0038_add-obligation-rcf-threshold.sql +2 -0
- package/dist/drizzle/migrations/0039_add-offers-composite-indexes.sql +2 -0
- package/dist/drizzle/migrations/0040_drop-redundant-offers-indexes.sql +2 -0
- package/dist/drizzle/migrations/0041_add-group-winner-expression-index.sql +10 -0
- package/dist/drizzle/migrations/0042_contract-sync-v1.14.sql +284 -0
- package/dist/drizzle/migrations/0043_add-obligation-side-tick-index.sql +1 -0
- package/dist/drizzle/migrations/0044_index-audit-cleanup.sql +27 -0
- package/dist/drizzle/migrations/0045_add-lots-offsets-availability-indexes.sql +5 -0
- package/dist/drizzle/migrations/0046_add-offers-active-tick-index.sql +1 -0
- package/dist/drizzle/migrations/0047_add-offers-book-winners-index.sql +1 -0
- package/dist/drizzle/migrations/0048_covering-indexes-for-winners-queries.sql +34 -0
- package/dist/drizzle/migrations/0049_contract-sync-v1.15.sql +305 -0
- package/dist/drizzle/migrations/meta/0031_snapshot.json +1652 -0
- package/dist/drizzle/migrations/meta/0033_snapshot.json +1658 -0
- package/dist/drizzle/migrations/meta/0036_snapshot.json +1864 -0
- package/dist/drizzle/migrations/meta/0037_snapshot.json +1876 -0
- package/dist/drizzle/migrations/meta/0038_snapshot.json +1882 -0
- package/dist/drizzle/migrations/meta/0039_snapshot.json +1960 -0
- package/dist/drizzle/migrations/meta/0040_snapshot.json +1912 -0
- package/dist/drizzle/migrations/meta/0041_snapshot.json +1912 -0
- package/dist/drizzle/migrations/meta/0042_snapshot.json +1882 -0
- package/dist/drizzle/migrations/meta/0043_snapshot.json +1909 -0
- package/dist/drizzle/migrations/meta/0044_snapshot.json +1853 -0
- package/dist/drizzle/migrations/meta/0045_snapshot.json +1921 -0
- package/dist/drizzle/migrations/meta/0046_snapshot.json +1966 -0
- package/dist/drizzle/migrations/meta/0047_snapshot.json +2005 -0
- package/dist/drizzle/migrations/meta/0048_snapshot.json +2035 -0
- package/dist/drizzle/migrations/meta/0049_snapshot.json +2035 -0
- package/dist/drizzle/migrations/meta/_journal.json +133 -0
- package/dist/evm/bytecode/morpho.txt +1 -1
- package/dist/index.browser.d.mts +784 -282
- package/dist/index.browser.d.mts.map +1 -1
- package/dist/index.browser.mjs +1516 -675
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.node.d.mts +1676 -602
- package/dist/index.node.d.mts.map +1 -1
- package/dist/index.node.mjs +10121 -5251
- package/dist/index.node.mjs.map +1 -1
- package/dist/register-otel-hook.js +7 -0
- package/dist/server-D4xxddev.js +9573 -0
- package/dist/server.js +9617 -0
- package/docs/integrator.md +14 -24
- package/package.json +36 -29
- package/dist/index.browser.d.ts +0 -5007
- package/dist/index.browser.d.ts.map +0 -1
- package/dist/index.browser.js +0 -5825
- package/dist/index.browser.js.map +0 -1
- package/dist/index.node.d.ts +0 -8263
- package/dist/index.node.d.ts.map +0 -1
- package/dist/index.node.js +0 -12566
- package/dist/index.node.js.map +0 -1
package/dist/index.browser.mjs
CHANGED
|
@@ -6,53 +6,14 @@ import { ApiBody, ApiOperation, ApiParam, ApiProperty, ApiQuery, ApiResponse, Ap
|
|
|
6
6
|
import * as z$1 from "zod";
|
|
7
7
|
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
|
-
import {
|
|
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
|
+
import { context, propagation } from "@opentelemetry/api";
|
|
14
|
+
import { sql } from "drizzle-orm";
|
|
15
|
+
import { bigint, boolean, foreignKey, index, integer, numeric, pgSchema, primaryKey, serial, text, timestamp, uniqueIndex, varchar } from "drizzle-orm/pg-core";
|
|
13
16
|
|
|
14
|
-
//#region \0@oxc-project+runtime@0.110.0/helpers/typeof.js
|
|
15
|
-
function _typeof(o) {
|
|
16
|
-
"@babel/helpers - typeof";
|
|
17
|
-
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
|
|
18
|
-
return typeof o;
|
|
19
|
-
} : function(o) {
|
|
20
|
-
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
|
|
21
|
-
}, _typeof(o);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
//#endregion
|
|
25
|
-
//#region \0@oxc-project+runtime@0.110.0/helpers/toPrimitive.js
|
|
26
|
-
function toPrimitive(t, r) {
|
|
27
|
-
if ("object" != _typeof(t) || !t) return t;
|
|
28
|
-
var e = t[Symbol.toPrimitive];
|
|
29
|
-
if (void 0 !== e) {
|
|
30
|
-
var i = e.call(t, r || "default");
|
|
31
|
-
if ("object" != _typeof(i)) return i;
|
|
32
|
-
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
33
|
-
}
|
|
34
|
-
return ("string" === r ? String : Number)(t);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
//#endregion
|
|
38
|
-
//#region \0@oxc-project+runtime@0.110.0/helpers/toPropertyKey.js
|
|
39
|
-
function toPropertyKey(t) {
|
|
40
|
-
var i = toPrimitive(t, "string");
|
|
41
|
-
return "symbol" == _typeof(i) ? i : i + "";
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
//#endregion
|
|
45
|
-
//#region \0@oxc-project+runtime@0.110.0/helpers/defineProperty.js
|
|
46
|
-
function _defineProperty(e, r, t) {
|
|
47
|
-
return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
|
48
|
-
value: t,
|
|
49
|
-
enumerable: !0,
|
|
50
|
-
configurable: !0,
|
|
51
|
-
writable: !0
|
|
52
|
-
}) : e[r] = t, e;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
//#endregion
|
|
56
17
|
//#region src/utils/Errors.ts
|
|
57
18
|
var Errors_exports = /* @__PURE__ */ __exportAll({
|
|
58
19
|
BaseError: () => BaseError,
|
|
@@ -68,6 +29,10 @@ var Errors_exports = /* @__PURE__ */ __exportAll({
|
|
|
68
29
|
* ```
|
|
69
30
|
*/
|
|
70
31
|
var BaseError = class BaseError extends Error {
|
|
32
|
+
details;
|
|
33
|
+
shortMessage;
|
|
34
|
+
cause;
|
|
35
|
+
name = "BaseError";
|
|
71
36
|
constructor(shortMessage, options = {}) {
|
|
72
37
|
const details = (() => {
|
|
73
38
|
if (options.cause instanceof BaseError) {
|
|
@@ -84,10 +49,6 @@ var BaseError = class BaseError extends Error {
|
|
|
84
49
|
...details ? ["", details ? `Details: ${details}` : void 0] : []
|
|
85
50
|
].filter((x) => typeof x === "string").join("\n");
|
|
86
51
|
super(message, options.cause ? { cause: options.cause } : void 0);
|
|
87
|
-
_defineProperty(this, "details", void 0);
|
|
88
|
-
_defineProperty(this, "shortMessage", void 0);
|
|
89
|
-
_defineProperty(this, "cause", void 0);
|
|
90
|
-
_defineProperty(this, "name", "BaseError");
|
|
91
52
|
this.cause = options.cause;
|
|
92
53
|
this.details = details;
|
|
93
54
|
this.shortMessage = shortMessage;
|
|
@@ -103,9 +64,9 @@ function walk(err, fn) {
|
|
|
103
64
|
return fn ? null : err;
|
|
104
65
|
}
|
|
105
66
|
var ReorgError = class extends BaseError {
|
|
67
|
+
name = "ReorgError";
|
|
106
68
|
constructor(blockNumber) {
|
|
107
69
|
super(`Reorg detected at block number ${blockNumber}`);
|
|
108
|
-
_defineProperty(this, "name", "ReorgError");
|
|
109
70
|
}
|
|
110
71
|
};
|
|
111
72
|
|
|
@@ -116,6 +77,8 @@ var Tick_exports = /* @__PURE__ */ __exportAll({
|
|
|
116
77
|
InvalidTickError: () => InvalidTickError,
|
|
117
78
|
MAX_PRICE: () => MAX_PRICE,
|
|
118
79
|
TICK_RANGE: () => TICK_RANGE,
|
|
80
|
+
assetsToObligationUnits: () => assetsToObligationUnits,
|
|
81
|
+
obligationUnitsToAssets: () => obligationUnitsToAssets,
|
|
119
82
|
priceToTick: () => priceToTick,
|
|
120
83
|
tickToPrice: () => tickToPrice
|
|
121
84
|
});
|
|
@@ -175,16 +138,36 @@ function assertTick(tick) {
|
|
|
175
138
|
function assertPrice(price) {
|
|
176
139
|
if (price < 0n || price > MAX_PRICE) throw new InvalidPriceError(price);
|
|
177
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* Converts obligation units to assets using the tick price (mulDivDown).
|
|
143
|
+
* @param obligationUnits - The obligation units to convert.
|
|
144
|
+
* @param tick - The offer tick.
|
|
145
|
+
* @returns The equivalent amount in assets.
|
|
146
|
+
*/
|
|
147
|
+
function obligationUnitsToAssets(obligationUnits, tick) {
|
|
148
|
+
return obligationUnits * tickToPrice(tick) / WAD$1;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Converts assets to obligation units using the tick price (mulDivUp).
|
|
152
|
+
* @param assets - The asset amount to convert.
|
|
153
|
+
* @param tick - The offer tick.
|
|
154
|
+
* @returns The equivalent amount in obligation units.
|
|
155
|
+
*/
|
|
156
|
+
function assetsToObligationUnits(assets, tick) {
|
|
157
|
+
const price = tickToPrice(tick);
|
|
158
|
+
if (price === 0n) return 0n;
|
|
159
|
+
return (assets * WAD$1 + price - 1n) / price;
|
|
160
|
+
}
|
|
178
161
|
var InvalidTickError = class extends BaseError {
|
|
162
|
+
name = "Tick.InvalidTickError";
|
|
179
163
|
constructor(tick) {
|
|
180
164
|
super(`Invalid tick: ${tick}. Tick must be an integer between 0 and ${TICK_RANGE}.`);
|
|
181
|
-
_defineProperty(this, "name", "Tick.InvalidTickError");
|
|
182
165
|
}
|
|
183
166
|
};
|
|
184
167
|
var InvalidPriceError = class extends BaseError {
|
|
168
|
+
name = "Tick.InvalidPriceError";
|
|
185
169
|
constructor(price) {
|
|
186
170
|
super(`Invalid price: ${price}. Price must be between 0 and ${MAX_PRICE}.`);
|
|
187
|
-
_defineProperty(this, "name", "Tick.InvalidPriceError");
|
|
188
171
|
}
|
|
189
172
|
};
|
|
190
173
|
|
|
@@ -196,7 +179,7 @@ function from$15(level) {
|
|
|
196
179
|
return {
|
|
197
180
|
tick: level.tick,
|
|
198
181
|
price: price.toString(),
|
|
199
|
-
|
|
182
|
+
obligation_units: level.obligationUnits.toString(),
|
|
200
183
|
count: level.count
|
|
201
184
|
};
|
|
202
185
|
}
|
|
@@ -254,9 +237,11 @@ function from$14(obligation, quote, chainId) {
|
|
|
254
237
|
collaterals: obligation.collaterals.map((c) => ({
|
|
255
238
|
token: c.asset,
|
|
256
239
|
lltv: c.lltv.toString(),
|
|
240
|
+
max_lif: c.maxLif.toString(),
|
|
257
241
|
oracle: c.oracle
|
|
258
242
|
})),
|
|
259
243
|
maturity: obligation.maturity,
|
|
244
|
+
rcf_threshold: obligation.rcfThreshold.toString(),
|
|
260
245
|
ask: {
|
|
261
246
|
tick: quote.ask.tick,
|
|
262
247
|
price: quote.ask.price.toString()
|
|
@@ -297,15 +282,15 @@ function from$13(input) {
|
|
|
297
282
|
collaterals: input.collaterals.map((c) => ({
|
|
298
283
|
token: c.asset,
|
|
299
284
|
lltv: c.lltv.toString(),
|
|
285
|
+
max_lif: c.maxLif.toString(),
|
|
300
286
|
oracle: c.oracle
|
|
301
287
|
})),
|
|
302
|
-
maturity: input.maturity
|
|
288
|
+
maturity: input.maturity,
|
|
289
|
+
rcf_threshold: input.rcfThreshold.toString()
|
|
303
290
|
},
|
|
304
291
|
buy: input.buy,
|
|
305
292
|
maker: input.maker,
|
|
306
|
-
assets: input.assets.toString(),
|
|
307
293
|
obligation_units: input.obligationUnits.toString(),
|
|
308
|
-
obligation_shares: input.obligationShares.toString(),
|
|
309
294
|
start: input.start,
|
|
310
295
|
expiry: input.expiry,
|
|
311
296
|
tick: input.tick,
|
|
@@ -313,7 +298,8 @@ function from$13(input) {
|
|
|
313
298
|
session: input.session,
|
|
314
299
|
callback: input.callback.address,
|
|
315
300
|
callback_data: input.callback.data,
|
|
316
|
-
receiver_if_maker_is_seller: input.receiverIfMakerIsSeller
|
|
301
|
+
receiver_if_maker_is_seller: input.receiverIfMakerIsSeller,
|
|
302
|
+
exit_only: input.exitOnly
|
|
317
303
|
},
|
|
318
304
|
offer_hash: input.hash,
|
|
319
305
|
obligation_id: input.obligationId,
|
|
@@ -366,15 +352,15 @@ const offerExample = {
|
|
|
366
352
|
collaterals: [{
|
|
367
353
|
token: "0x34Cf890dB685FC536E05652FB41f02090c3fb751",
|
|
368
354
|
lltv: "860000000000000000",
|
|
355
|
+
max_lif: "0",
|
|
369
356
|
oracle: "0x45093658BE7f90B63D7c359e8f408e503c2D9401"
|
|
370
357
|
}],
|
|
371
|
-
maturity: 1761922799
|
|
358
|
+
maturity: 1761922799,
|
|
359
|
+
rcf_threshold: "0"
|
|
372
360
|
},
|
|
373
361
|
buy: false,
|
|
374
362
|
maker: "0x7b093658BE7f90B63D7c359e8f408e503c2D9401",
|
|
375
|
-
|
|
376
|
-
obligation_units: "0",
|
|
377
|
-
obligation_shares: "0",
|
|
363
|
+
obligation_units: "369216000000000000000000",
|
|
378
364
|
start: 1761922790,
|
|
379
365
|
expiry: 1761922799,
|
|
380
366
|
tick: 495,
|
|
@@ -382,10 +368,11 @@ const offerExample = {
|
|
|
382
368
|
session: "0x0000000000000000000000000000000000000000000000000000000000000000",
|
|
383
369
|
callback: "0x0000000000000000000000000000000000000000",
|
|
384
370
|
callback_data: "0x",
|
|
385
|
-
receiver_if_maker_is_seller: "0x7b093658BE7f90B63D7c359e8f408e503c2D9401"
|
|
371
|
+
receiver_if_maker_is_seller: "0x7b093658BE7f90B63D7c359e8f408e503c2D9401",
|
|
372
|
+
exit_only: false
|
|
386
373
|
},
|
|
387
374
|
offer_hash: "0xac4bd8318ec914f89f8af913f162230575b0ac0696a19256bc12138c5cfe1427",
|
|
388
|
-
obligation_id: "
|
|
375
|
+
obligation_id: "0x25690ae1aee324a005be565f3bcdd16dbf8daf79",
|
|
389
376
|
chain_id: 1,
|
|
390
377
|
consumed: "0",
|
|
391
378
|
takeable: "369216000000000000000000",
|
|
@@ -416,11 +403,10 @@ const missingCollectorExample = {
|
|
|
416
403
|
};
|
|
417
404
|
const validateOfferExample = {
|
|
418
405
|
maker: "0x7b093658BE7f90B63D7c359e8f408e503c2D9401",
|
|
419
|
-
|
|
420
|
-
obligation_units: "0",
|
|
421
|
-
obligation_shares: "0",
|
|
406
|
+
obligation_units: "369216000000000000000000",
|
|
422
407
|
tick: 495,
|
|
423
408
|
maturity: 1761922799,
|
|
409
|
+
rcf_threshold: "0",
|
|
424
410
|
expiry: 1761922799,
|
|
425
411
|
start: 1761922790,
|
|
426
412
|
group: "0x000000000000000000000000000000000000000000000000000000000008b8f4",
|
|
@@ -431,13 +417,15 @@ const validateOfferExample = {
|
|
|
431
417
|
collaterals: [{
|
|
432
418
|
asset: "0x34Cf890dB685FC536E05652FB41f02090c3fb751",
|
|
433
419
|
oracle: "0x45093658BE7f90B63D7c359e8f408e503c2D9401",
|
|
434
|
-
lltv: "860000000000000000"
|
|
420
|
+
lltv: "860000000000000000",
|
|
421
|
+
max_lif: "0"
|
|
435
422
|
}],
|
|
436
423
|
callback: {
|
|
437
424
|
address: "0x0000000000000000000000000000000000000000",
|
|
438
425
|
data: "0x"
|
|
439
426
|
},
|
|
440
|
-
receiver_if_maker_is_seller: "0x7b093658BE7f90B63D7c359e8f408e503c2D9401"
|
|
427
|
+
receiver_if_maker_is_seller: "0x7b093658BE7f90B63D7c359e8f408e503c2D9401",
|
|
428
|
+
exit_only: false
|
|
441
429
|
};
|
|
442
430
|
const routerStatusExample = {
|
|
443
431
|
status: "live",
|
|
@@ -481,6 +469,10 @@ __decorate([ApiProperty({
|
|
|
481
469
|
type: "string",
|
|
482
470
|
example: "860000000000000000"
|
|
483
471
|
})], CollateralResponse.prototype, "lltv", void 0);
|
|
472
|
+
__decorate([ApiProperty({
|
|
473
|
+
type: "string",
|
|
474
|
+
example: "0"
|
|
475
|
+
})], CollateralResponse.prototype, "max_lif", void 0);
|
|
484
476
|
__decorate([ApiProperty({
|
|
485
477
|
type: "string",
|
|
486
478
|
example: "0x45093658BE7f90B63D7c359e8f408e503c2D9401"
|
|
@@ -498,6 +490,10 @@ __decorate([ApiProperty({
|
|
|
498
490
|
type: "string",
|
|
499
491
|
example: validateOfferExample.collaterals[0].lltv
|
|
500
492
|
})], ValidateCollateralRequest.prototype, "lltv", void 0);
|
|
493
|
+
__decorate([ApiProperty({
|
|
494
|
+
type: "string",
|
|
495
|
+
example: validateOfferExample.collaterals[0].max_lif
|
|
496
|
+
})], ValidateCollateralRequest.prototype, "max_lif", void 0);
|
|
501
497
|
var ValidateCallbackRequest = class {};
|
|
502
498
|
__decorate([ApiProperty({
|
|
503
499
|
type: "string",
|
|
@@ -542,6 +538,10 @@ __decorate([ApiProperty({
|
|
|
542
538
|
type: "number",
|
|
543
539
|
example: offerExample.offer.obligation.maturity
|
|
544
540
|
})], ObligationOfferResponse.prototype, "maturity", void 0);
|
|
541
|
+
__decorate([ApiProperty({
|
|
542
|
+
type: "string",
|
|
543
|
+
example: offerExample.offer.obligation.rcf_threshold
|
|
544
|
+
})], ObligationOfferResponse.prototype, "rcf_threshold", void 0);
|
|
545
545
|
var OfferDataResponse = class {};
|
|
546
546
|
__decorate([ApiProperty({
|
|
547
547
|
type: () => ObligationOfferResponse,
|
|
@@ -555,18 +555,10 @@ __decorate([ApiProperty({
|
|
|
555
555
|
type: "string",
|
|
556
556
|
example: offerExample.offer.maker
|
|
557
557
|
})], OfferDataResponse.prototype, "maker", void 0);
|
|
558
|
-
__decorate([ApiProperty({
|
|
559
|
-
type: "string",
|
|
560
|
-
example: offerExample.offer.assets
|
|
561
|
-
})], OfferDataResponse.prototype, "assets", void 0);
|
|
562
558
|
__decorate([ApiProperty({
|
|
563
559
|
type: "string",
|
|
564
560
|
example: offerExample.offer.obligation_units
|
|
565
561
|
})], OfferDataResponse.prototype, "obligation_units", void 0);
|
|
566
|
-
__decorate([ApiProperty({
|
|
567
|
-
type: "string",
|
|
568
|
-
example: offerExample.offer.obligation_shares
|
|
569
|
-
})], OfferDataResponse.prototype, "obligation_shares", void 0);
|
|
570
562
|
__decorate([ApiProperty({
|
|
571
563
|
type: "number",
|
|
572
564
|
example: offerExample.offer.start
|
|
@@ -601,6 +593,10 @@ __decorate([ApiProperty({
|
|
|
601
593
|
type: "string",
|
|
602
594
|
example: offerExample.offer.receiver_if_maker_is_seller
|
|
603
595
|
})], OfferDataResponse.prototype, "receiver_if_maker_is_seller", void 0);
|
|
596
|
+
__decorate([ApiProperty({
|
|
597
|
+
type: "boolean",
|
|
598
|
+
example: offerExample.offer.exit_only
|
|
599
|
+
})], OfferDataResponse.prototype, "exit_only", void 0);
|
|
604
600
|
var OfferListItemResponse = class {};
|
|
605
601
|
__decorate([ApiProperty({
|
|
606
602
|
type: () => OfferDataResponse,
|
|
@@ -663,6 +659,10 @@ __decorate([ApiProperty({
|
|
|
663
659
|
type: "number",
|
|
664
660
|
example: 1761922800
|
|
665
661
|
})], ObligationResponse.prototype, "maturity", void 0);
|
|
662
|
+
__decorate([ApiProperty({
|
|
663
|
+
type: "string",
|
|
664
|
+
example: "0"
|
|
665
|
+
})], ObligationResponse.prototype, "rcf_threshold", void 0);
|
|
666
666
|
__decorate([ApiProperty({ type: () => AskResponse })], ObligationResponse.prototype, "ask", void 0);
|
|
667
667
|
__decorate([ApiProperty({ type: () => BidResponse })], ObligationResponse.prototype, "bid", void 0);
|
|
668
668
|
var ObligationListResponse = class extends SuccessResponse {};
|
|
@@ -810,20 +810,11 @@ __decorate([ApiProperty({
|
|
|
810
810
|
type: "string",
|
|
811
811
|
example: validateOfferExample.maker
|
|
812
812
|
})], ValidateOfferRequest.prototype, "maker", void 0);
|
|
813
|
-
__decorate([ApiProperty({
|
|
814
|
-
type: "string",
|
|
815
|
-
example: validateOfferExample.assets
|
|
816
|
-
})], ValidateOfferRequest.prototype, "assets", void 0);
|
|
817
813
|
__decorate([ApiProperty({
|
|
818
814
|
type: "string",
|
|
819
815
|
example: validateOfferExample.obligation_units,
|
|
820
816
|
required: false
|
|
821
817
|
})], ValidateOfferRequest.prototype, "obligation_units", void 0);
|
|
822
|
-
__decorate([ApiProperty({
|
|
823
|
-
type: "string",
|
|
824
|
-
example: validateOfferExample.obligation_shares,
|
|
825
|
-
required: false
|
|
826
|
-
})], ValidateOfferRequest.prototype, "obligation_shares", void 0);
|
|
827
818
|
__decorate([ApiProperty({
|
|
828
819
|
type: "number",
|
|
829
820
|
example: validateOfferExample.tick,
|
|
@@ -834,6 +825,10 @@ __decorate([ApiProperty({
|
|
|
834
825
|
type: "number",
|
|
835
826
|
example: validateOfferExample.maturity
|
|
836
827
|
})], ValidateOfferRequest.prototype, "maturity", void 0);
|
|
828
|
+
__decorate([ApiProperty({
|
|
829
|
+
type: "string",
|
|
830
|
+
example: validateOfferExample.rcf_threshold
|
|
831
|
+
})], ValidateOfferRequest.prototype, "rcf_threshold", void 0);
|
|
837
832
|
__decorate([ApiProperty({
|
|
838
833
|
type: "number",
|
|
839
834
|
example: validateOfferExample.expiry
|
|
@@ -870,6 +865,11 @@ __decorate([ApiProperty({
|
|
|
870
865
|
type: "string",
|
|
871
866
|
example: validateOfferExample.receiver_if_maker_is_seller
|
|
872
867
|
})], ValidateOfferRequest.prototype, "receiver_if_maker_is_seller", void 0);
|
|
868
|
+
__decorate([ApiProperty({
|
|
869
|
+
type: "boolean",
|
|
870
|
+
example: false,
|
|
871
|
+
required: false
|
|
872
|
+
})], ValidateOfferRequest.prototype, "exit_only", void 0);
|
|
873
873
|
var ValidateOffersRequest = class {};
|
|
874
874
|
__decorate([ApiProperty({
|
|
875
875
|
type: "number",
|
|
@@ -948,7 +948,7 @@ __decorate([ApiProperty({
|
|
|
948
948
|
__decorate([ApiProperty({
|
|
949
949
|
type: "string",
|
|
950
950
|
example: "369216000000000000000000"
|
|
951
|
-
})], BookLevelResponse.prototype, "
|
|
951
|
+
})], BookLevelResponse.prototype, "obligation_units", void 0);
|
|
952
952
|
__decorate([ApiProperty({
|
|
953
953
|
type: "number",
|
|
954
954
|
example: 5
|
|
@@ -1572,7 +1572,7 @@ const OpenApi = async () => {
|
|
|
1572
1572
|
info: {
|
|
1573
1573
|
title: "Router API",
|
|
1574
1574
|
version: "1.0.0",
|
|
1575
|
-
description: "API for the Morpho Router"
|
|
1575
|
+
description: process.env.COMMIT_SHA ? `API for the Morpho Router — version: ${process.env.COMMIT_SHA.slice(0, 7)}` : "API for the Morpho Router"
|
|
1576
1576
|
},
|
|
1577
1577
|
servers: [{
|
|
1578
1578
|
url: "https://router.morpho.dev",
|
|
@@ -1642,11 +1642,14 @@ function isValidBase64urlJson(val) {
|
|
|
1642
1642
|
function isValidOfferHashCursor(val) {
|
|
1643
1643
|
return /^0x[a-f0-9]{64}$/i.test(val);
|
|
1644
1644
|
}
|
|
1645
|
+
function isValidObligationIdCursor(val) {
|
|
1646
|
+
return /^0x[a-f0-9]{64}$/i.test(val);
|
|
1647
|
+
}
|
|
1645
1648
|
function isValidOfferCursor(val) {
|
|
1646
1649
|
const [hash, obligationId, ...rest] = val.split(":");
|
|
1647
1650
|
if (rest.length !== 0) return false;
|
|
1648
1651
|
if (!hash || !obligationId) return false;
|
|
1649
|
-
return isValidOfferHashCursor(hash) &&
|
|
1652
|
+
return isValidOfferHashCursor(hash) && isValidObligationIdCursor(obligationId);
|
|
1650
1653
|
}
|
|
1651
1654
|
const csvArray = (schema) => z$1.preprocess((value) => {
|
|
1652
1655
|
if (value === void 0) return void 0;
|
|
@@ -1675,10 +1678,14 @@ const ConfigRuleTypes = z$1.enum([
|
|
|
1675
1678
|
"callback",
|
|
1676
1679
|
"loan_token",
|
|
1677
1680
|
"collateral_token",
|
|
1678
|
-
"oracle"
|
|
1681
|
+
"oracle",
|
|
1682
|
+
"group_consistency",
|
|
1683
|
+
"group_immutability",
|
|
1684
|
+
"max_collaterals",
|
|
1685
|
+
"min_duration"
|
|
1679
1686
|
]);
|
|
1680
1687
|
const GetConfigRulesQueryParams = z$1.object({
|
|
1681
|
-
cursor: z$1.string().regex(/^(maturity|callback|loan_token|collateral_token|oracle):[1-9]\d*:.+$/, { message: "Cursor must be in the format type:chain_id:<value>" }).optional().meta({
|
|
1688
|
+
cursor: z$1.string().regex(/^(maturity|callback|loan_token|collateral_token|oracle|group_consistency|group_immutability|max_collaterals|min_duration):[1-9]\d*:.+$/, { message: "Cursor must be in the format type:chain_id:<value>" }).optional().meta({
|
|
1682
1689
|
description: "Pagination cursor in type:chain_id:<value> format",
|
|
1683
1690
|
example: "maturity:1:1730415600:end_of_next_month"
|
|
1684
1691
|
}),
|
|
@@ -1932,55 +1939,75 @@ const MetaMorphoFactory = parseAbi(["event CreateMetaMorpho(address indexed meta
|
|
|
1932
1939
|
//#region src/core/Abi/MorphoV2.ts
|
|
1933
1940
|
const MorphoV2 = parseAbi([
|
|
1934
1941
|
"constructor()",
|
|
1935
|
-
"function
|
|
1936
|
-
"function
|
|
1942
|
+
"function activatedCollaterals(bytes32 id, address user) view returns (uint128)",
|
|
1943
|
+
"function collateralOf(bytes32 id, address user, uint256 index) view returns (uint128)",
|
|
1937
1944
|
"function consumed(address user, bytes32 group) view returns (uint256)",
|
|
1945
|
+
"function creditAfterSlashing(bytes32 id, address user) view returns (uint256)",
|
|
1946
|
+
"function creditOf(bytes32 id, address user) view returns (uint256)",
|
|
1938
1947
|
"function debtOf(bytes32 id, address user) view returns (uint256)",
|
|
1939
|
-
"function defaultFees(address loanToken, uint256
|
|
1948
|
+
"function defaultFees(address loanToken, uint256) view returns (uint16)",
|
|
1940
1949
|
"function feeSetter() view returns (address)",
|
|
1941
|
-
"function fees(bytes32 id) view returns (uint16[
|
|
1950
|
+
"function fees(bytes32 id) view returns (uint16[7])",
|
|
1942
1951
|
"function flashLoan(address token, uint256 assets, address callback, bytes data)",
|
|
1943
|
-
"function
|
|
1944
|
-
"function
|
|
1952
|
+
"function isAuthorized(address authorizer, address authorized) view returns (bool)",
|
|
1953
|
+
"function isHealthy((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation, bytes32 id, address borrower) view returns (bool)",
|
|
1954
|
+
"function liquidate((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address borrower, bytes data) returns (uint256, uint256)",
|
|
1955
|
+
"function maxCollateralPerUser(address collateralToken) view returns (uint256)",
|
|
1956
|
+
"function maxLif(uint256 lltv, uint256 cursor) pure returns (uint256)",
|
|
1957
|
+
"function maxTakeableAssets(address loanToken) view returns (uint256)",
|
|
1958
|
+
"function maxTotalUnits(address loanToken) view returns (uint128)",
|
|
1959
|
+
"function maxTradingFee(uint256 index) pure returns (uint256)",
|
|
1945
1960
|
"function multicall(bytes[] calls)",
|
|
1946
1961
|
"function obligationCreated(bytes32 id) view returns (bool)",
|
|
1947
|
-
"function obligationState(bytes32 id) view returns (uint128 totalUnits,
|
|
1962
|
+
"function obligationState(bytes32 id) view returns (uint128 totalUnits, uint256 withdrawable, uint128 lossIndex, bool created)",
|
|
1948
1963
|
"function owner() view returns (address)",
|
|
1949
|
-
"function repay((address loanToken, (address token, uint256 lltv, address oracle)[] collaterals, uint256 maturity) obligation, uint256 obligationUnits, address onBehalf)",
|
|
1964
|
+
"function repay((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation, uint256 obligationUnits, address onBehalf)",
|
|
1950
1965
|
"function session(address user) view returns (bytes32)",
|
|
1966
|
+
"function setConsumed(bytes32 group, uint256 amount, address onBehalf)",
|
|
1951
1967
|
"function setDefaultTradingFee(address loanToken, uint256 index, uint256 newTradingFee)",
|
|
1952
1968
|
"function setFeeSetter(address newFeeSetter)",
|
|
1969
|
+
"function setIsAuthorized(address onBehalf, address authorized, bool newIsAuthorized)",
|
|
1970
|
+
"function setMaxCollateralPerUser(address collateralToken, uint256 newMaxCollateralPerUser)",
|
|
1971
|
+
"function setMaxTakeableAssets(address loanToken, uint256 newMaxTakeableAssets)",
|
|
1972
|
+
"function setMaxTotalUnits(address loanToken, uint128 newMaxTotalUnits)",
|
|
1953
1973
|
"function setObligationTradingFee(bytes32 id, uint256 index, uint256 newTradingFee)",
|
|
1954
1974
|
"function setOwner(address newOwner)",
|
|
1955
1975
|
"function setTradingFeeRecipient(address feeRecipient)",
|
|
1956
|
-
"function
|
|
1957
|
-
"function
|
|
1958
|
-
"function supplyCollateral((address loanToken, (address token, uint256 lltv, address oracle)[] collaterals, uint256 maturity) obligation,
|
|
1959
|
-
"function take(uint256
|
|
1960
|
-
"function
|
|
1976
|
+
"function shuffleSession(address onBehalf)",
|
|
1977
|
+
"function slash(bytes32 id, address user)",
|
|
1978
|
+
"function supplyCollateral((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation, uint256 collateralIndex, uint256 assets, address onBehalf)",
|
|
1979
|
+
"function take(uint256 obligationUnits, address taker, address takerCallback, bytes takerCallbackData, address receiverIfTakerIsSeller, ((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation, bool buy, address maker, uint256 obligationUnits, uint256 start, uint256 expiry, uint256 tick, bytes32 group, bytes32 session, address callback, bytes callbackData, address receiverIfMakerIsSeller, bool exitOnly) offer, (uint8 v, bytes32 r, bytes32 s) sig, bytes32 root, bytes32[] proof) returns (uint256, uint256, uint256)",
|
|
1980
|
+
"function toId((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation) view returns (bytes32)",
|
|
1981
|
+
"function toObligation(bytes32 id) view returns ((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold))",
|
|
1961
1982
|
"function totalUnits(bytes32 id) view returns (uint256)",
|
|
1962
|
-
"function touchObligation((address loanToken, (address token, uint256 lltv, address oracle)[] collaterals, uint256 maturity) obligation) returns (bytes32)",
|
|
1983
|
+
"function touchObligation((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation) returns (bytes32)",
|
|
1963
1984
|
"function tradingFee(bytes32 id, uint256 timeToMaturity) view returns (uint256)",
|
|
1964
1985
|
"function tradingFeeRecipient() view returns (address)",
|
|
1965
|
-
"function
|
|
1966
|
-
"function
|
|
1986
|
+
"function userLossIndex(bytes32 id, address user) view returns (uint128)",
|
|
1987
|
+
"function withdraw((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation, uint256 obligationUnits, address onBehalf, address receiver)",
|
|
1988
|
+
"function withdrawCollateral((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation, uint256 collateralIndex, uint256 assets, address onBehalf, address receiver)",
|
|
1967
1989
|
"function withdrawable(bytes32 id) view returns (uint256)",
|
|
1968
1990
|
"event Constructor(address indexed owner)",
|
|
1969
|
-
"event Consume(address indexed user, bytes32 indexed group, uint256 amount)",
|
|
1970
1991
|
"event FlashLoan(address indexed caller, address indexed token, uint256 assets)",
|
|
1971
|
-
"event Liquidate(address indexed caller, bytes32 indexed
|
|
1972
|
-
"event ObligationCreated(bytes32 indexed
|
|
1973
|
-
"event Repay(address indexed caller, bytes32 indexed
|
|
1992
|
+
"event Liquidate(address indexed caller, bytes32 indexed id_, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address indexed borrower, uint256 badDebt, uint256 latestLossIndex)",
|
|
1993
|
+
"event ObligationCreated(bytes32 indexed id_, (address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation)",
|
|
1994
|
+
"event Repay(address indexed caller, bytes32 indexed id_, uint256 obligationUnits, address indexed onBehalf)",
|
|
1995
|
+
"event SetConsumed(address indexed caller, address indexed onBehalf, bytes32 indexed group, uint256 amount)",
|
|
1974
1996
|
"event SetDefaultTradingFee(address indexed loanToken, uint256 indexed index, uint256 newTradingFee)",
|
|
1975
1997
|
"event SetFeeSetter(address indexed feeSetter)",
|
|
1976
|
-
"event
|
|
1998
|
+
"event SetIsAuthorized(address indexed caller, address indexed onBehalf, address indexed authorized, bool newIsAuthorized)",
|
|
1999
|
+
"event SetMaxCollateralPerUser(address indexed collateralToken, uint256 maxCollateralPerUser)",
|
|
2000
|
+
"event SetMaxTakeableAssets(address indexed loanToken, uint256 maxTakeableAssets)",
|
|
2001
|
+
"event SetMaxTotalUnits(address indexed loanToken, uint128 maxTotalUnits)",
|
|
2002
|
+
"event SetObligationTradingFee(bytes32 indexed id_, uint256 indexed index, uint256 newTradingFee)",
|
|
1977
2003
|
"event SetOwner(address indexed owner)",
|
|
1978
2004
|
"event SetTradingFeeRecipient(address indexed feeRecipient)",
|
|
1979
|
-
"event ShuffleSession(address indexed
|
|
1980
|
-
"event
|
|
1981
|
-
"event
|
|
1982
|
-
"event
|
|
1983
|
-
"event
|
|
2005
|
+
"event ShuffleSession(address indexed caller, address indexed onBehalf, bytes32 session)",
|
|
2006
|
+
"event Slash(address caller, bytes32 indexed id_, address indexed user, uint256 credit, uint256 latestLossIndex)",
|
|
2007
|
+
"event SupplyCollateral(address caller, bytes32 indexed id_, address indexed collateral, uint256 assets, address indexed onBehalf)",
|
|
2008
|
+
"event Take(address caller, bytes32 indexed id_, address indexed maker, address indexed taker, bool offerIsBuy, uint256 buyerAssets, uint256 sellerAssets, uint256 obligationUnits, address sellerReceiver, bytes32 group, uint256 consumed, uint256 totalUnits)",
|
|
2009
|
+
"event Withdraw(address caller, bytes32 indexed id_, uint256 obligationUnits, address indexed onBehalf, address indexed receiver)",
|
|
2010
|
+
"event WithdrawCollateral(address caller, bytes32 indexed id_, address indexed collateral, uint256 assets, address indexed onBehalf, address receiver)"
|
|
1984
2011
|
]);
|
|
1985
2012
|
|
|
1986
2013
|
//#endregion
|
|
@@ -2138,6 +2165,7 @@ const Morpho = [
|
|
|
2138
2165
|
//#endregion
|
|
2139
2166
|
//#region src/core/Callback.ts
|
|
2140
2167
|
var Callback_exports = /* @__PURE__ */ __exportAll({
|
|
2168
|
+
CallbackType: () => CallbackType,
|
|
2141
2169
|
Type: () => Type$1,
|
|
2142
2170
|
isEmptyCallback: () => isEmptyCallback
|
|
2143
2171
|
});
|
|
@@ -2146,30 +2174,12 @@ let Type$1 = /* @__PURE__ */ function(Type) {
|
|
|
2146
2174
|
Type["SellWithEmptyCallback"] = "sell_with_empty_callback";
|
|
2147
2175
|
return Type;
|
|
2148
2176
|
}({});
|
|
2177
|
+
let CallbackType = /* @__PURE__ */ function(CallbackType) {
|
|
2178
|
+
CallbackType["Empty"] = "empty";
|
|
2179
|
+
return CallbackType;
|
|
2180
|
+
}({});
|
|
2149
2181
|
const isEmptyCallback = (offer) => offer.callback.data === "0x";
|
|
2150
2182
|
|
|
2151
|
-
//#endregion
|
|
2152
|
-
//#region src/utils/BigMath.ts
|
|
2153
|
-
function max$1(a, b) {
|
|
2154
|
-
return a > b ? a : b;
|
|
2155
|
-
}
|
|
2156
|
-
function min(a, b) {
|
|
2157
|
-
return a < b ? a : b;
|
|
2158
|
-
}
|
|
2159
|
-
/**
|
|
2160
|
-
* Checks if at most one of the given values is non-zero.
|
|
2161
|
-
* @param values - The bigint values to check.
|
|
2162
|
-
* @returns True if zero or one value is non-zero, false if two or more are non-zero.
|
|
2163
|
-
*/
|
|
2164
|
-
function atMostOneNonZero(...values) {
|
|
2165
|
-
let nonZeroCount = 0;
|
|
2166
|
-
for (const value of values) if (value !== 0n) {
|
|
2167
|
-
nonZeroCount++;
|
|
2168
|
-
if (nonZeroCount > 1) return false;
|
|
2169
|
-
}
|
|
2170
|
-
return true;
|
|
2171
|
-
}
|
|
2172
|
-
|
|
2173
2183
|
//#endregion
|
|
2174
2184
|
//#region src/utils/batch.ts
|
|
2175
2185
|
/**
|
|
@@ -2193,6 +2203,28 @@ function* batch$1(array, batchSize) {
|
|
|
2193
2203
|
for (let i = 0; i < array.length; i += batchSize) yield array.slice(i, i + batchSize);
|
|
2194
2204
|
}
|
|
2195
2205
|
|
|
2206
|
+
//#endregion
|
|
2207
|
+
//#region src/utils/BigMath.ts
|
|
2208
|
+
function max$1(a, b) {
|
|
2209
|
+
return a > b ? a : b;
|
|
2210
|
+
}
|
|
2211
|
+
function min(a, b) {
|
|
2212
|
+
return a < b ? a : b;
|
|
2213
|
+
}
|
|
2214
|
+
/**
|
|
2215
|
+
* Checks if at most one of the given values is non-zero.
|
|
2216
|
+
* @param values - The bigint values to check.
|
|
2217
|
+
* @returns True if zero or one value is non-zero, false if two or more are non-zero.
|
|
2218
|
+
*/
|
|
2219
|
+
function atMostOneNonZero(...values) {
|
|
2220
|
+
let nonZeroCount = 0;
|
|
2221
|
+
for (const value of values) if (value !== 0n) {
|
|
2222
|
+
nonZeroCount++;
|
|
2223
|
+
if (nonZeroCount > 1) return false;
|
|
2224
|
+
}
|
|
2225
|
+
return true;
|
|
2226
|
+
}
|
|
2227
|
+
|
|
2196
2228
|
//#endregion
|
|
2197
2229
|
//#region src/core/Chain.ts
|
|
2198
2230
|
var Chain_exports = /* @__PURE__ */ __exportAll({
|
|
@@ -2201,9 +2233,10 @@ var Chain_exports = /* @__PURE__ */ __exportAll({
|
|
|
2201
2233
|
InvalidBlockRangeError: () => InvalidBlockRangeError,
|
|
2202
2234
|
InvalidBlockWindowError: () => InvalidBlockWindowError,
|
|
2203
2235
|
MissingBlockNumberError: () => MissingBlockNumberError,
|
|
2236
|
+
UnrecoverableLogsResponseSizeError: () => UnrecoverableLogsResponseSizeError,
|
|
2204
2237
|
chainIds: () => chainIds,
|
|
2205
2238
|
chainNames: () => chainNames,
|
|
2206
|
-
chains: () => chains,
|
|
2239
|
+
chains: () => chains$1,
|
|
2207
2240
|
getChain: () => getChain,
|
|
2208
2241
|
getWhitelistedChains: () => getWhitelistedChains,
|
|
2209
2242
|
streamLogs: () => streamLogs
|
|
@@ -2220,17 +2253,17 @@ const chainNameLookup = new Map(Object.entries(ChainId).map(([key, value]) => [v
|
|
|
2220
2253
|
function getChain(chainId) {
|
|
2221
2254
|
const chainName = chainNameLookup.get(chainId);
|
|
2222
2255
|
if (!chainName) return void 0;
|
|
2223
|
-
return chains[chainName];
|
|
2256
|
+
return chains$1[chainName];
|
|
2224
2257
|
}
|
|
2225
2258
|
const getWhitelistedChains = () => {
|
|
2226
2259
|
return [
|
|
2227
|
-
chains.ethereum,
|
|
2228
|
-
chains.base,
|
|
2229
|
-
chains["ethereum-virtual-testnet"],
|
|
2230
|
-
chains.anvil
|
|
2260
|
+
chains$1.ethereum,
|
|
2261
|
+
chains$1.base,
|
|
2262
|
+
chains$1["ethereum-virtual-testnet"],
|
|
2263
|
+
chains$1.anvil
|
|
2231
2264
|
];
|
|
2232
2265
|
};
|
|
2233
|
-
const chains = {
|
|
2266
|
+
const chains$1 = {
|
|
2234
2267
|
ethereum: {
|
|
2235
2268
|
...mainnet,
|
|
2236
2269
|
id: ChainId.ETHEREUM,
|
|
@@ -2267,8 +2300,8 @@ const chains = {
|
|
|
2267
2300
|
name: "base",
|
|
2268
2301
|
custom: {
|
|
2269
2302
|
morpho: {
|
|
2270
|
-
address: "
|
|
2271
|
-
blockCreated:
|
|
2303
|
+
address: "0xee437005ba0a3d0e9bc6510775c41f23ed2909e1",
|
|
2304
|
+
blockCreated: 43515847
|
|
2272
2305
|
},
|
|
2273
2306
|
morphoBlue: {
|
|
2274
2307
|
address: "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb",
|
|
@@ -2297,8 +2330,8 @@ const chains = {
|
|
|
2297
2330
|
name: "ethereum-virtual-testnet",
|
|
2298
2331
|
custom: {
|
|
2299
2332
|
morpho: {
|
|
2300
|
-
address: "
|
|
2301
|
-
blockCreated:
|
|
2333
|
+
address: "0xc1c6e6fa308eeef18e96be420d8ccb218215a26c",
|
|
2334
|
+
blockCreated: 23244321
|
|
2302
2335
|
},
|
|
2303
2336
|
morphoBlue: {
|
|
2304
2337
|
address: "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb",
|
|
@@ -2325,9 +2358,13 @@ const chains = {
|
|
|
2325
2358
|
...anvil,
|
|
2326
2359
|
id: ChainId.ANVIL,
|
|
2327
2360
|
name: "anvil",
|
|
2361
|
+
contracts: { multicall3: {
|
|
2362
|
+
address: "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0",
|
|
2363
|
+
blockCreated: 0
|
|
2364
|
+
} },
|
|
2328
2365
|
custom: {
|
|
2329
2366
|
morpho: {
|
|
2330
|
-
address: "
|
|
2367
|
+
address: "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512",
|
|
2331
2368
|
blockCreated: 0
|
|
2332
2369
|
},
|
|
2333
2370
|
morphoBlue: {
|
|
@@ -2335,8 +2372,8 @@ const chains = {
|
|
|
2335
2372
|
blockCreated: 0
|
|
2336
2373
|
},
|
|
2337
2374
|
mempool: {
|
|
2338
|
-
address: "
|
|
2339
|
-
blockCreated:
|
|
2375
|
+
address: "0x5FbDB2315678afecb367f032d93F642f64180aa3",
|
|
2376
|
+
blockCreated: 0
|
|
2340
2377
|
},
|
|
2341
2378
|
vaults: { factories: {
|
|
2342
2379
|
v1_0: {
|
|
@@ -2356,33 +2393,72 @@ const MAX_BATCH_SIZE = 1e4;
|
|
|
2356
2393
|
const DEFAULT_BATCH_SIZE$1 = 2500;
|
|
2357
2394
|
const MAX_BLOCK_WINDOW = 1e4;
|
|
2358
2395
|
const DEFAULT_BLOCK_WINDOW = 8e3;
|
|
2396
|
+
const MIN_BLOCK_WINDOW = 0n;
|
|
2397
|
+
const oversizedLogsErrorPatterns = [
|
|
2398
|
+
"cannot create a string longer than",
|
|
2399
|
+
"response is too big",
|
|
2400
|
+
"response size exceeded",
|
|
2401
|
+
"log response size exceeded",
|
|
2402
|
+
"query returned more than",
|
|
2403
|
+
"too many results"
|
|
2404
|
+
];
|
|
2405
|
+
const getLatestBlockNumber = async (client) => {
|
|
2406
|
+
return await getBlockNumber(client, { cacheTime: 0 });
|
|
2407
|
+
};
|
|
2359
2408
|
async function* streamLogs(parameters) {
|
|
2360
2409
|
const { client, contractAddress, event, blockNumberGte, blockNumberLte, order = "desc", options: { maxBatchSize = DEFAULT_BATCH_SIZE$1, blockWindow = DEFAULT_BLOCK_WINDOW } = {} } = parameters;
|
|
2361
2410
|
if (maxBatchSize > MAX_BATCH_SIZE) throw new InvalidBatchSizeError(maxBatchSize);
|
|
2362
2411
|
if (blockWindow > MAX_BLOCK_WINDOW) throw new InvalidBlockWindowError(blockWindow);
|
|
2363
2412
|
if (order === "asc" && blockNumberGte === void 0) throw new MissingBlockNumberError();
|
|
2364
|
-
const
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2413
|
+
const ascendingLowerBound = order === "asc" ? BigInt(blockNumberGte) : void 0;
|
|
2414
|
+
const latestBlock = await getLatestBlockNumber(client);
|
|
2415
|
+
let upperBound = blockNumberLte === void 0 ? latestBlock : min(BigInt(blockNumberLte), latestBlock);
|
|
2416
|
+
const lowerBound = BigInt(blockNumberGte || 0);
|
|
2417
|
+
const configuredBlockWindow = BigInt(blockWindow);
|
|
2418
|
+
let adaptiveBlockWindow = configuredBlockWindow;
|
|
2368
2419
|
let toBlock = 0n;
|
|
2369
|
-
if (order === "asc") toBlock = min(
|
|
2370
|
-
if (order === "desc") toBlock =
|
|
2420
|
+
if (order === "asc") toBlock = min(ascendingLowerBound + adaptiveBlockWindow, upperBound);
|
|
2421
|
+
if (order === "desc") toBlock = upperBound;
|
|
2371
2422
|
let fromBlock = 0n;
|
|
2372
|
-
if (order === "asc") fromBlock =
|
|
2373
|
-
if (order === "desc") fromBlock = max$1(BigInt(blockNumberGte || toBlock -
|
|
2374
|
-
if (order === "asc") toBlock = min(toBlock, fromBlock +
|
|
2375
|
-
if (order === "desc") fromBlock = max$1(fromBlock, toBlock -
|
|
2423
|
+
if (order === "asc") fromBlock = ascendingLowerBound;
|
|
2424
|
+
if (order === "desc") fromBlock = max$1(BigInt(blockNumberGte || toBlock - adaptiveBlockWindow), 0n);
|
|
2425
|
+
if (order === "asc") toBlock = min(toBlock, fromBlock + adaptiveBlockWindow);
|
|
2426
|
+
if (order === "desc") fromBlock = max$1(fromBlock, toBlock - adaptiveBlockWindow);
|
|
2376
2427
|
if (fromBlock > toBlock) throw new InvalidBlockRangeError(fromBlock, toBlock);
|
|
2377
2428
|
let streaming = true;
|
|
2378
2429
|
while (streaming) {
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2430
|
+
let logs;
|
|
2431
|
+
try {
|
|
2432
|
+
logs = await getLogs(client, {
|
|
2433
|
+
address: contractAddress,
|
|
2434
|
+
event,
|
|
2435
|
+
fromBlock,
|
|
2436
|
+
toBlock
|
|
2437
|
+
});
|
|
2438
|
+
} catch (err) {
|
|
2439
|
+
if (order === "asc" && isBlockOutOfRangeError(err)) {
|
|
2440
|
+
const previousUpperBound = upperBound;
|
|
2441
|
+
const previousFromBlock = fromBlock;
|
|
2442
|
+
const previousToBlock = toBlock;
|
|
2443
|
+
const latestBlockOnRetry = await getLatestBlockNumber(client);
|
|
2444
|
+
upperBound = min(upperBound, latestBlockOnRetry);
|
|
2445
|
+
if (upperBound < ascendingLowerBound) throw new InvalidBlockRangeError(ascendingLowerBound, upperBound);
|
|
2446
|
+
toBlock = min(toBlock, upperBound);
|
|
2447
|
+
fromBlock = max$1(min(fromBlock, upperBound), ascendingLowerBound);
|
|
2448
|
+
if (fromBlock > toBlock) throw new InvalidBlockRangeError(fromBlock, toBlock);
|
|
2449
|
+
if (!(upperBound < previousUpperBound || fromBlock < previousFromBlock || toBlock < previousToBlock)) throw err;
|
|
2450
|
+
continue;
|
|
2451
|
+
}
|
|
2452
|
+
if (isOversizedLogsError(err)) {
|
|
2453
|
+
if (fromBlock === toBlock) throw new UnrecoverableLogsResponseSizeError(fromBlock, err);
|
|
2454
|
+
adaptiveBlockWindow = max$1((toBlock - fromBlock) / 2n, MIN_BLOCK_WINDOW);
|
|
2455
|
+
if (order === "asc") toBlock = min(fromBlock + adaptiveBlockWindow, upperBound);
|
|
2456
|
+
else fromBlock = max$1(toBlock - adaptiveBlockWindow, lowerBound);
|
|
2457
|
+
continue;
|
|
2458
|
+
}
|
|
2459
|
+
throw err;
|
|
2460
|
+
}
|
|
2461
|
+
streaming = order === "asc" ? toBlock < upperBound : fromBlock > lowerBound;
|
|
2386
2462
|
if (logs.length === 0 && !streaming) break;
|
|
2387
2463
|
if (logs.length === 0 && streaming) yield {
|
|
2388
2464
|
logs: [],
|
|
@@ -2397,17 +2473,19 @@ async function* streamLogs(parameters) {
|
|
|
2397
2473
|
logs: logBatch,
|
|
2398
2474
|
blockNumber: logBatch.length === maxBatchSize ? Number(logBatch[logBatch.length - 1]?.blockNumber) : order === "asc" ? Number(toBlock) : Number(fromBlock)
|
|
2399
2475
|
};
|
|
2476
|
+
if (adaptiveBlockWindow < configuredBlockWindow) {
|
|
2477
|
+
const expandedBlockWindow = adaptiveBlockWindow === 0n ? 1n : adaptiveBlockWindow * 2n;
|
|
2478
|
+
adaptiveBlockWindow = min(expandedBlockWindow, configuredBlockWindow);
|
|
2479
|
+
}
|
|
2400
2480
|
if (order === "asc") {
|
|
2401
|
-
const upperBound = BigInt(blockNumberLte || latestBlock);
|
|
2402
2481
|
const nextFromBlock = min(BigInt(toBlock) + 1n, upperBound);
|
|
2403
|
-
const nextToBlock = min(toBlock +
|
|
2482
|
+
const nextToBlock = min(toBlock + adaptiveBlockWindow + 1n, upperBound);
|
|
2404
2483
|
fromBlock = nextFromBlock;
|
|
2405
2484
|
toBlock = nextToBlock;
|
|
2406
2485
|
}
|
|
2407
2486
|
if (order === "desc") {
|
|
2408
|
-
const lowerBound = BigInt(blockNumberGte || 0);
|
|
2409
2487
|
const nextToBlock = max$1(fromBlock - 1n, lowerBound);
|
|
2410
|
-
const nextFromBlock = max$1(fromBlock -
|
|
2488
|
+
const nextFromBlock = max$1(fromBlock - adaptiveBlockWindow - 1n, lowerBound);
|
|
2411
2489
|
toBlock = nextToBlock;
|
|
2412
2490
|
fromBlock = nextFromBlock;
|
|
2413
2491
|
}
|
|
@@ -2417,30 +2495,62 @@ async function* streamLogs(parameters) {
|
|
|
2417
2495
|
blockNumber: order === "asc" ? Number(toBlock) : Number(fromBlock)
|
|
2418
2496
|
};
|
|
2419
2497
|
}
|
|
2498
|
+
const isBlockOutOfRangeError = (error) => {
|
|
2499
|
+
let cause = error;
|
|
2500
|
+
while (cause && typeof cause === "object") {
|
|
2501
|
+
const candidate = cause;
|
|
2502
|
+
if (typeof candidate.message === "string" && candidate.message.includes("BlockOutOfRangeError") || typeof candidate.details === "string" && candidate.details.includes("BlockOutOfRangeError")) return true;
|
|
2503
|
+
cause = candidate.cause;
|
|
2504
|
+
}
|
|
2505
|
+
return false;
|
|
2506
|
+
};
|
|
2420
2507
|
var InvalidBlockRangeError = class extends BaseError {
|
|
2508
|
+
name = "Chain.InvalidBlockRangeError";
|
|
2509
|
+
fromBlock;
|
|
2510
|
+
toBlock;
|
|
2421
2511
|
constructor(fromBlock, toBlock) {
|
|
2422
2512
|
super(`Invalid block range while streaming data from chain. From block ${fromBlock} to block ${toBlock}.`);
|
|
2423
|
-
|
|
2513
|
+
this.fromBlock = fromBlock;
|
|
2514
|
+
this.toBlock = toBlock;
|
|
2424
2515
|
}
|
|
2425
2516
|
};
|
|
2426
2517
|
var InvalidBlockWindowError = class extends BaseError {
|
|
2518
|
+
name = "Chain.InvalidBlockWindowError";
|
|
2427
2519
|
constructor(blockWindow) {
|
|
2428
2520
|
super(`Invalid block window while streaming data from chain. Maximum is ${MAX_BLOCK_WINDOW}. Got ${blockWindow}.`);
|
|
2429
|
-
_defineProperty(this, "name", "Chain.InvalidBlockWindowError");
|
|
2430
2521
|
}
|
|
2431
2522
|
};
|
|
2432
2523
|
var InvalidBatchSizeError = class extends BaseError {
|
|
2524
|
+
name = "Chain.InvalidBatchSizeError";
|
|
2433
2525
|
constructor(maxBatchSize) {
|
|
2434
2526
|
super(`Invalid batch size while streaming data from chain. Maximum is ${MAX_BATCH_SIZE}. Got ${maxBatchSize}.`);
|
|
2435
|
-
_defineProperty(this, "name", "Chain.InvalidBatchSizeError");
|
|
2436
2527
|
}
|
|
2437
2528
|
};
|
|
2438
2529
|
var MissingBlockNumberError = class extends BaseError {
|
|
2530
|
+
name = "Chain.MissingBlockNumberError";
|
|
2439
2531
|
constructor() {
|
|
2440
2532
|
super("Missing block number when streaming data from chain in ascending order.");
|
|
2441
|
-
_defineProperty(this, "name", "Chain.MissingBlockNumberError");
|
|
2442
2533
|
}
|
|
2443
2534
|
};
|
|
2535
|
+
var UnrecoverableLogsResponseSizeError = class extends BaseError {
|
|
2536
|
+
name = "Chain.UnrecoverableLogsResponseSizeError";
|
|
2537
|
+
constructor(blockNumber, cause) {
|
|
2538
|
+
const rootCause = cause instanceof Error ? cause : cause === void 0 ? void 0 : new Error(String(cause));
|
|
2539
|
+
super(`Failed to stream logs because even a single-block query exceeded the RPC response size limit at block ${blockNumber}.`, { cause: rootCause });
|
|
2540
|
+
}
|
|
2541
|
+
};
|
|
2542
|
+
function isOversizedLogsError(err) {
|
|
2543
|
+
return oversizedLogsErrorPatterns.some((pattern) => collectErrorMessages(err).includes(pattern));
|
|
2544
|
+
}
|
|
2545
|
+
function collectErrorMessages(err) {
|
|
2546
|
+
if (!(err instanceof Error)) return "";
|
|
2547
|
+
const fragments = [err.message];
|
|
2548
|
+
const candidate = err;
|
|
2549
|
+
if (typeof candidate.details === "string") fragments.push(candidate.details);
|
|
2550
|
+
if (typeof candidate.shortMessage === "string") fragments.push(candidate.shortMessage);
|
|
2551
|
+
if (candidate.cause instanceof Error) fragments.push(collectErrorMessages(candidate.cause));
|
|
2552
|
+
return fragments.join(" ").toLowerCase();
|
|
2553
|
+
}
|
|
2444
2554
|
|
|
2445
2555
|
//#endregion
|
|
2446
2556
|
//#region src/core/ChainRegistry.ts
|
|
@@ -2465,6 +2575,7 @@ var Random_exports = /* @__PURE__ */ __exportAll({
|
|
|
2465
2575
|
address: () => address,
|
|
2466
2576
|
bool: () => bool,
|
|
2467
2577
|
bytes: () => bytes,
|
|
2578
|
+
createRng: () => createRng,
|
|
2468
2579
|
float: () => float,
|
|
2469
2580
|
hex: () => hex,
|
|
2470
2581
|
int: () => int,
|
|
@@ -2482,7 +2593,19 @@ const hashSeed = (seed) => {
|
|
|
2482
2593
|
}
|
|
2483
2594
|
return hash >>> 0;
|
|
2484
2595
|
};
|
|
2485
|
-
|
|
2596
|
+
/**
|
|
2597
|
+
* Creates an isolated seeded RNG instance — safe for concurrent use.
|
|
2598
|
+
* @param seed - Seed string used to derive the initial RNG state.
|
|
2599
|
+
*/
|
|
2600
|
+
function createRng(seed) {
|
|
2601
|
+
const rng = createSeededRngFn(seed);
|
|
2602
|
+
return {
|
|
2603
|
+
float: () => rng(),
|
|
2604
|
+
int: (maxExclusive, min = 0) => Math.floor(rng() * (maxExclusive - min)) + min,
|
|
2605
|
+
bool: (probability = .5) => rng() < probability
|
|
2606
|
+
};
|
|
2607
|
+
}
|
|
2608
|
+
const createSeededRngFn = (seed) => {
|
|
2486
2609
|
let state = hashSeed(seed);
|
|
2487
2610
|
return () => {
|
|
2488
2611
|
state += 1831565813;
|
|
@@ -2496,7 +2619,7 @@ const createSeededRng = (seed) => {
|
|
|
2496
2619
|
*/
|
|
2497
2620
|
function withSeed(seed, fn) {
|
|
2498
2621
|
const previous = currentRng;
|
|
2499
|
-
currentRng =
|
|
2622
|
+
currentRng = createSeededRngFn(seed);
|
|
2500
2623
|
try {
|
|
2501
2624
|
return fn();
|
|
2502
2625
|
} finally {
|
|
@@ -2507,7 +2630,7 @@ function withSeed(seed, fn) {
|
|
|
2507
2630
|
* Seeds the global RNG for deterministic test runs.
|
|
2508
2631
|
*/
|
|
2509
2632
|
function seed(seed) {
|
|
2510
|
-
currentRng =
|
|
2633
|
+
currentRng = createSeededRngFn(seed);
|
|
2511
2634
|
}
|
|
2512
2635
|
/**
|
|
2513
2636
|
* Returns a deterministic random float in [0, 1).
|
|
@@ -2663,15 +2786,15 @@ function from$11(lltv) {
|
|
|
2663
2786
|
return BigInt(lltv * 10 ** 18);
|
|
2664
2787
|
}
|
|
2665
2788
|
var InvalidOptionError$1 = class extends BaseError {
|
|
2789
|
+
name = "LLTV.InvalidOptionError";
|
|
2666
2790
|
constructor(input) {
|
|
2667
2791
|
super(`Invalid LLTV option. Input: "${input}". Accepted values are: ${Options.map((option) => `"${option}"`).join(", ")}.`);
|
|
2668
|
-
_defineProperty(this, "name", "LLTV.InvalidOptionError");
|
|
2669
2792
|
}
|
|
2670
2793
|
};
|
|
2671
2794
|
var InvalidLLTVError = class extends BaseError {
|
|
2795
|
+
name = "LLTV.InvalidLLTVError";
|
|
2672
2796
|
constructor(input) {
|
|
2673
2797
|
super(`Invalid LLTV. Input: "${input}". Accepted values are: ${LLTV_SCALED.map((option) => `"${option}"`).join(", ")}.`);
|
|
2674
|
-
_defineProperty(this, "name", "LLTV.InvalidLLTVError");
|
|
2675
2798
|
}
|
|
2676
2799
|
};
|
|
2677
2800
|
const LLTVSchema = z$1.bigint({ coerce: true }).refine((lltv) => {
|
|
@@ -2703,6 +2826,10 @@ const abi$1 = [
|
|
|
2703
2826
|
type: "uint256",
|
|
2704
2827
|
name: "lltv"
|
|
2705
2828
|
},
|
|
2829
|
+
{
|
|
2830
|
+
type: "uint256",
|
|
2831
|
+
name: "maxLif"
|
|
2832
|
+
},
|
|
2706
2833
|
{
|
|
2707
2834
|
type: "address",
|
|
2708
2835
|
name: "oracle"
|
|
@@ -2711,7 +2838,8 @@ const abi$1 = [
|
|
|
2711
2838
|
const CollateralSchema = z$1.object({
|
|
2712
2839
|
asset: z$1.string().transform(transformAddress),
|
|
2713
2840
|
oracle: z$1.string().transform(transformAddress),
|
|
2714
|
-
lltv: LLTVSchema
|
|
2841
|
+
lltv: LLTVSchema,
|
|
2842
|
+
maxLif: z$1.bigint({ coerce: true }).min(0n).optional().default(0n)
|
|
2715
2843
|
});
|
|
2716
2844
|
const CollateralsSchema = z$1.array(CollateralSchema).min(1, { message: "At least one collateral is required" }).refine((collaterals) => {
|
|
2717
2845
|
for (let i = 1; i < collaterals.length; i++) if (collaterals[i - 1].asset.toLowerCase() > collaterals[i].asset.toLowerCase()) return false;
|
|
@@ -2729,6 +2857,7 @@ const from$10 = (parameters) => {
|
|
|
2729
2857
|
return {
|
|
2730
2858
|
asset: parameters.asset.toLowerCase(),
|
|
2731
2859
|
lltv: from$11(parameters.lltv),
|
|
2860
|
+
maxLif: parameters.maxLif ?? 0n,
|
|
2732
2861
|
oracle: parameters.oracle.toLowerCase()
|
|
2733
2862
|
};
|
|
2734
2863
|
};
|
|
@@ -2745,7 +2874,8 @@ function random$3() {
|
|
|
2745
2874
|
return from$10({
|
|
2746
2875
|
asset: address(),
|
|
2747
2876
|
oracle: address(),
|
|
2748
|
-
lltv: .965
|
|
2877
|
+
lltv: .965,
|
|
2878
|
+
maxLif: 0n
|
|
2749
2879
|
});
|
|
2750
2880
|
}
|
|
2751
2881
|
|
|
@@ -2806,9 +2936,9 @@ function convertToShares(parameters) {
|
|
|
2806
2936
|
return parameters.assets * (parameters.totalSupply + 10n ** BigInt(parameters.decimalsOffset)) / denominator;
|
|
2807
2937
|
}
|
|
2808
2938
|
var DenominatorIsZeroError = class extends BaseError {
|
|
2939
|
+
name = "ERC4626.DenominatorIsZeroError";
|
|
2809
2940
|
constructor() {
|
|
2810
2941
|
super("Denominator is 0.");
|
|
2811
|
-
_defineProperty(this, "name", "ERC4626.DenominatorIsZeroError");
|
|
2812
2942
|
}
|
|
2813
2943
|
};
|
|
2814
2944
|
|
|
@@ -2876,9 +3006,9 @@ const MaturitySchema = z$1.number().int().refine((maturity) => {
|
|
|
2876
3006
|
}
|
|
2877
3007
|
}, { error: (issue) => {
|
|
2878
3008
|
try {
|
|
2879
|
-
return `The maturity is set to ${/* @__PURE__ */ new Date(issue.input * 1e3)}. It must
|
|
3009
|
+
return `The maturity is set to ${/* @__PURE__ */ new Date(issue.input * 1e3)}. It must be at 15:00:00 UTC.`;
|
|
2880
3010
|
} catch (_) {
|
|
2881
|
-
return `The maturity is set to ${issue.input}. It must
|
|
3011
|
+
return `The maturity is set to ${issue.input}. It must be at 15:00:00 UTC.`;
|
|
2882
3012
|
}
|
|
2883
3013
|
} }).transform((maturity) => maturity);
|
|
2884
3014
|
let MaturityType = /* @__PURE__ */ function(MaturityType) {
|
|
@@ -2910,9 +3040,14 @@ function from$9(ts) {
|
|
|
2910
3040
|
throw new InvalidOptionError(ts);
|
|
2911
3041
|
}
|
|
2912
3042
|
if (typeof ts === "number" && ts > 0xe8d4a51000) throw new InvalidFormatError();
|
|
2913
|
-
if (!
|
|
3043
|
+
if (!isAt15UTC(ts)) throw new InvalidDateError(ts);
|
|
2914
3044
|
return ts;
|
|
2915
3045
|
}
|
|
3046
|
+
/** Checks whether a timestamp (in seconds) falls at exactly 15:00:00 UTC. */
|
|
3047
|
+
function isAt15UTC(ts) {
|
|
3048
|
+
const date = /* @__PURE__ */ new Date(ts * 1e3);
|
|
3049
|
+
return date.getUTCHours() === 15 && date.getUTCMinutes() === 0 && date.getUTCSeconds() === 0 && date.getUTCMilliseconds() === 0;
|
|
3050
|
+
}
|
|
2916
3051
|
/** Returns the end of the current week (friday at 15:00:00 UTC) */
|
|
2917
3052
|
const endOfWeek = () => fridayOfWeek(0);
|
|
2918
3053
|
/** Returns the end of the next week (friday at 15:00:00 UTC) */
|
|
@@ -2965,21 +3100,21 @@ const lastFridayOfQuarter = (quartersAhead = 0) => {
|
|
|
2965
3100
|
return lastFridayOfMonth(now.getUTCFullYear() + Math.floor(quarterIndex / 4), quarterIndex % 4 * 3 + 2);
|
|
2966
3101
|
};
|
|
2967
3102
|
var InvalidFormatError = class extends BaseError {
|
|
3103
|
+
name = "Maturity.InvalidFormatError";
|
|
2968
3104
|
constructor() {
|
|
2969
3105
|
super("Invalid maturity format. Maturity should be expressed in seconds.");
|
|
2970
|
-
_defineProperty(this, "name", "Maturity.InvalidFormatError");
|
|
2971
3106
|
}
|
|
2972
3107
|
};
|
|
2973
3108
|
var InvalidDateError = class extends BaseError {
|
|
3109
|
+
name = "Maturity.InvalidDateError";
|
|
2974
3110
|
constructor(input) {
|
|
2975
|
-
super(`Invalid maturity date. Input: "${input}".
|
|
2976
|
-
_defineProperty(this, "name", "Maturity.InvalidDateError");
|
|
3111
|
+
super(`Invalid maturity date. Input: "${input}". Maturity must be at 15:00:00 UTC.`);
|
|
2977
3112
|
}
|
|
2978
3113
|
};
|
|
2979
3114
|
var InvalidOptionError = class extends BaseError {
|
|
3115
|
+
name = "Maturity.InvalidOptionError";
|
|
2980
3116
|
constructor(input) {
|
|
2981
3117
|
super(`Invalid maturity option. Input: "${input}". Accepted values are: ${Object.keys(MaturityOptions).map((option) => `"${option}"`).join(", ")}.`);
|
|
2982
|
-
_defineProperty(this, "name", "Maturity.InvalidOptionError");
|
|
2983
3118
|
}
|
|
2984
3119
|
};
|
|
2985
3120
|
|
|
@@ -3000,7 +3135,8 @@ var Obligation_exports = /* @__PURE__ */ __exportAll({
|
|
|
3000
3135
|
const ObligationSchema = z$1.object({
|
|
3001
3136
|
loanToken: z$1.string().transform(transformAddress),
|
|
3002
3137
|
collaterals: CollateralsSchema,
|
|
3003
|
-
maturity: MaturitySchema
|
|
3138
|
+
maturity: MaturitySchema,
|
|
3139
|
+
rcfThreshold: z$1.bigint({ coerce: true }).min(0n)
|
|
3004
3140
|
});
|
|
3005
3141
|
const abi = [
|
|
3006
3142
|
{
|
|
@@ -3015,6 +3151,10 @@ const abi = [
|
|
|
3015
3151
|
{
|
|
3016
3152
|
type: "uint256",
|
|
3017
3153
|
name: "maturity"
|
|
3154
|
+
},
|
|
3155
|
+
{
|
|
3156
|
+
type: "uint256",
|
|
3157
|
+
name: "rcfThreshold"
|
|
3018
3158
|
}
|
|
3019
3159
|
];
|
|
3020
3160
|
const tupleAbi = [{
|
|
@@ -3040,6 +3180,7 @@ const tupleAbi = [{
|
|
|
3040
3180
|
* }),
|
|
3041
3181
|
* ],
|
|
3042
3182
|
* maturity: Maturity.from("end_of_next_quarter"),
|
|
3183
|
+
* rcfThreshold: 0n,
|
|
3043
3184
|
* });
|
|
3044
3185
|
* ```
|
|
3045
3186
|
*/
|
|
@@ -3052,7 +3193,8 @@ function from$8(parameters) {
|
|
|
3052
3193
|
return {
|
|
3053
3194
|
loanToken: parsedObligation.loanToken.toLowerCase(),
|
|
3054
3195
|
collaterals: parsedObligation.collaterals.sort((a, b) => a.asset.localeCompare(b.asset)),
|
|
3055
|
-
maturity: parsedObligation.maturity
|
|
3196
|
+
maturity: parsedObligation.maturity,
|
|
3197
|
+
rcfThreshold: parsedObligation.rcfThreshold
|
|
3056
3198
|
};
|
|
3057
3199
|
} catch (error) {
|
|
3058
3200
|
throw new InvalidObligationError(error);
|
|
@@ -3069,7 +3211,7 @@ function fromSnakeCase$2(input) {
|
|
|
3069
3211
|
}
|
|
3070
3212
|
/**
|
|
3071
3213
|
* Calculates a canonical key for an obligation payload.
|
|
3072
|
-
* The key is computed as keccak256(abi.encode(loanToken, collaterals, maturity)).
|
|
3214
|
+
* The key is computed as keccak256(abi.encode(loanToken, collaterals, maturity, rcfThreshold)).
|
|
3073
3215
|
* @throws If the collaterals are not sorted alphabetically by address. {@link CollateralsAreNotSortedError}
|
|
3074
3216
|
* @param parameters - {@link key.Parameters}
|
|
3075
3217
|
* @returns The obligation key as a 32-byte hex string. {@link key.ReturnType}
|
|
@@ -3093,9 +3235,11 @@ function key(parameters) {
|
|
|
3093
3235
|
parameters.collaterals.map((c) => ({
|
|
3094
3236
|
token: c.asset.toLowerCase(),
|
|
3095
3237
|
lltv: c.lltv,
|
|
3238
|
+
maxLif: c.maxLif ?? 0n,
|
|
3096
3239
|
oracle: c.oracle.toLowerCase()
|
|
3097
3240
|
})),
|
|
3098
|
-
BigInt(parameters.maturity)
|
|
3241
|
+
BigInt(parameters.maturity),
|
|
3242
|
+
parameters.rcfThreshold
|
|
3099
3243
|
]));
|
|
3100
3244
|
}
|
|
3101
3245
|
/**
|
|
@@ -3111,7 +3255,8 @@ function random$2() {
|
|
|
3111
3255
|
return from$8({
|
|
3112
3256
|
loanToken: address(),
|
|
3113
3257
|
collaterals: [random$3()],
|
|
3114
|
-
maturity: from$9("end_of_next_quarter")
|
|
3258
|
+
maturity: from$9("end_of_next_quarter"),
|
|
3259
|
+
rcfThreshold: 0n
|
|
3115
3260
|
});
|
|
3116
3261
|
}
|
|
3117
3262
|
/**
|
|
@@ -3125,19 +3270,20 @@ function fromOffer$1(offer) {
|
|
|
3125
3270
|
return from$8({
|
|
3126
3271
|
loanToken: offer.loanToken,
|
|
3127
3272
|
collaterals: offer.collaterals,
|
|
3128
|
-
maturity: offer.maturity
|
|
3273
|
+
maturity: offer.maturity,
|
|
3274
|
+
rcfThreshold: offer.rcfThreshold
|
|
3129
3275
|
});
|
|
3130
3276
|
}
|
|
3131
3277
|
var InvalidObligationError = class extends BaseError {
|
|
3278
|
+
name = "Obligation.InvalidObligationError";
|
|
3132
3279
|
constructor(error) {
|
|
3133
3280
|
super("Invalid obligation.", { cause: error });
|
|
3134
|
-
_defineProperty(this, "name", "Obligation.InvalidObligationError");
|
|
3135
3281
|
}
|
|
3136
3282
|
};
|
|
3137
3283
|
var CollateralsAreNotSortedError = class extends BaseError {
|
|
3284
|
+
name = "Obligation.CollateralsAreNotSortedError";
|
|
3138
3285
|
constructor() {
|
|
3139
3286
|
super("Collaterals are not sorted alphabetically by address.");
|
|
3140
|
-
_defineProperty(this, "name", "Obligation.CollateralsAreNotSortedError");
|
|
3141
3287
|
}
|
|
3142
3288
|
};
|
|
3143
3289
|
|
|
@@ -3147,39 +3293,42 @@ var Id_exports = /* @__PURE__ */ __exportAll({
|
|
|
3147
3293
|
creationCode: () => creationCode,
|
|
3148
3294
|
toId: () => toId
|
|
3149
3295
|
});
|
|
3150
|
-
const CREATION_CODE_PREFIX = "
|
|
3296
|
+
const CREATION_CODE_PREFIX = "0x600b380380600b5f395ff3";
|
|
3151
3297
|
/**
|
|
3152
3298
|
* Builds the same creation code as `IdLib.creationCode` in Solidity.
|
|
3153
3299
|
*
|
|
3154
|
-
* Layout: `prefix (11 bytes) +
|
|
3300
|
+
* Layout: `prefix (11 bytes) + abi.encode(obligation)`.
|
|
3155
3301
|
*
|
|
3156
3302
|
* @param parameters - {@link creationCode.Parameters}
|
|
3157
3303
|
* @returns The CREATE2 init code bytes. {@link creationCode.ReturnType}
|
|
3158
3304
|
*/
|
|
3159
3305
|
function creationCode(parameters) {
|
|
3160
|
-
|
|
3306
|
+
return concatHex([CREATION_CODE_PREFIX, encodeAbiParameters(tupleAbi, [{
|
|
3161
3307
|
loanToken: parameters.obligation.loanToken.toLowerCase(),
|
|
3162
3308
|
collaterals: parameters.obligation.collaterals.map((collateral) => ({
|
|
3163
3309
|
token: collateral.asset.toLowerCase(),
|
|
3164
3310
|
lltv: collateral.lltv,
|
|
3311
|
+
maxLif: collateral.maxLif ?? 0n,
|
|
3165
3312
|
oracle: collateral.oracle.toLowerCase()
|
|
3166
3313
|
})),
|
|
3167
|
-
maturity: BigInt(parameters.obligation.maturity)
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
CREATION_CODE_PREFIX,
|
|
3171
|
-
numberToHex(BigInt(parameters.chainId), { size: 32 }),
|
|
3172
|
-
parameters.morphoV2.toLowerCase(),
|
|
3173
|
-
encodedObligation
|
|
3174
|
-
]);
|
|
3314
|
+
maturity: BigInt(parameters.obligation.maturity),
|
|
3315
|
+
rcfThreshold: parameters.obligation.rcfThreshold
|
|
3316
|
+
}])]);
|
|
3175
3317
|
}
|
|
3176
3318
|
/**
|
|
3177
|
-
* Computes the same id as `IdLib.toId` in Solidity
|
|
3319
|
+
* Computes the same id as `IdLib.toId` in Solidity using the CREATE2 preimage:
|
|
3320
|
+
* `keccak256(0xff ++ morphoV2 ++ chainId ++ keccak256(creationCode))`.
|
|
3321
|
+
*
|
|
3178
3322
|
* @param parameters - {@link toId.Parameters}
|
|
3179
|
-
* @returns The obligation id. {@link toId.ReturnType}
|
|
3323
|
+
* @returns The 32-byte obligation id. {@link toId.ReturnType}
|
|
3180
3324
|
*/
|
|
3181
3325
|
function toId(parameters) {
|
|
3182
|
-
return keccak256(
|
|
3326
|
+
return keccak256(concatHex([
|
|
3327
|
+
"0xff",
|
|
3328
|
+
parameters.morphoV2.toLowerCase(),
|
|
3329
|
+
numberToHex(BigInt(parameters.chainId), { size: 32 }),
|
|
3330
|
+
keccak256(creationCode(parameters))
|
|
3331
|
+
]));
|
|
3183
3332
|
}
|
|
3184
3333
|
|
|
3185
3334
|
//#endregion
|
|
@@ -3269,7 +3418,6 @@ var Offer_exports = /* @__PURE__ */ __exportAll({
|
|
|
3269
3418
|
fromSnakeCase: () => fromSnakeCase$1,
|
|
3270
3419
|
hash: () => hash,
|
|
3271
3420
|
liquidateEvent: () => liquidateEvent,
|
|
3272
|
-
obligationId: () => obligationId,
|
|
3273
3421
|
random: () => random$1,
|
|
3274
3422
|
repayEvent: () => repayEvent,
|
|
3275
3423
|
serialize: () => serialize,
|
|
@@ -3288,11 +3436,10 @@ let Status = /* @__PURE__ */ function(Status) {
|
|
|
3288
3436
|
const OfferSchema = () => {
|
|
3289
3437
|
return z$1.object({
|
|
3290
3438
|
maker: z$1.string().transform(transformAddress),
|
|
3291
|
-
assets: z$1.bigint({ coerce: true }).min(0n).max(maxUint256),
|
|
3292
3439
|
obligationUnits: z$1.bigint({ coerce: true }).min(0n).max(maxUint256).optional().default(0n),
|
|
3293
|
-
obligationShares: z$1.bigint({ coerce: true }).min(0n).max(maxUint256).optional().default(0n),
|
|
3294
3440
|
tick: z$1.coerce.number().int().min(0).max(990),
|
|
3295
3441
|
maturity: MaturitySchema,
|
|
3442
|
+
rcfThreshold: z$1.bigint({ coerce: true }).min(0n).max(maxUint256),
|
|
3296
3443
|
expiry: z$1.number().int().max(Number.MAX_SAFE_INTEGER),
|
|
3297
3444
|
start: z$1.number().int().max(Number.MAX_SAFE_INTEGER),
|
|
3298
3445
|
group: z$1.union([
|
|
@@ -3312,7 +3459,8 @@ const OfferSchema = () => {
|
|
|
3312
3459
|
address: z$1.string().transform(transformAddress),
|
|
3313
3460
|
data: z$1.string().transform(transformHex)
|
|
3314
3461
|
}),
|
|
3315
|
-
receiverIfMakerIsSeller: z$1.string().transform(transformAddress)
|
|
3462
|
+
receiverIfMakerIsSeller: z$1.string().transform(transformAddress),
|
|
3463
|
+
exitOnly: z$1.boolean().optional().default(false)
|
|
3316
3464
|
}).refine((data) => data.start < data.expiry, {
|
|
3317
3465
|
message: "start must be before expiry",
|
|
3318
3466
|
path: ["start"]
|
|
@@ -3364,11 +3512,10 @@ function toSnakeCase(offer) {
|
|
|
3364
3512
|
*/
|
|
3365
3513
|
const serialize = (offer) => ({
|
|
3366
3514
|
maker: offer.maker,
|
|
3367
|
-
assets: offer.assets.toString(),
|
|
3368
3515
|
obligationUnits: offer.obligationUnits.toString(),
|
|
3369
|
-
obligationShares: offer.obligationShares.toString(),
|
|
3370
3516
|
tick: offer.tick,
|
|
3371
3517
|
maturity: Number(offer.maturity),
|
|
3518
|
+
rcfThreshold: offer.rcfThreshold.toString(),
|
|
3372
3519
|
expiry: Number(offer.expiry),
|
|
3373
3520
|
start: Number(offer.start),
|
|
3374
3521
|
group: offer.group,
|
|
@@ -3378,13 +3525,15 @@ const serialize = (offer) => ({
|
|
|
3378
3525
|
collaterals: offer.collaterals.map((c) => ({
|
|
3379
3526
|
asset: c.asset,
|
|
3380
3527
|
oracle: c.oracle,
|
|
3381
|
-
lltv: c.lltv.toString()
|
|
3528
|
+
lltv: c.lltv.toString(),
|
|
3529
|
+
maxLif: c.maxLif.toString()
|
|
3382
3530
|
})),
|
|
3383
3531
|
callback: {
|
|
3384
3532
|
address: offer.callback.address,
|
|
3385
3533
|
data: offer.callback.data
|
|
3386
3534
|
},
|
|
3387
3535
|
receiverIfMakerIsSeller: offer.receiverIfMakerIsSeller,
|
|
3536
|
+
exitOnly: offer.exitOnly,
|
|
3388
3537
|
hash: hash(offer)
|
|
3389
3538
|
});
|
|
3390
3539
|
/**
|
|
@@ -3421,7 +3570,7 @@ function random$1(config) {
|
|
|
3421
3570
|
const loanTokenDecimals = config?.assetsDecimals?.[loanToken] ?? 18;
|
|
3422
3571
|
const unit = BigInt(10) ** BigInt(loanTokenDecimals);
|
|
3423
3572
|
const amountBase = BigInt(100 + int(999901));
|
|
3424
|
-
const
|
|
3573
|
+
const obligationUnitsScaled = config?.obligationUnits ?? amountBase * unit;
|
|
3425
3574
|
const emptyCallback = {
|
|
3426
3575
|
address: zeroAddress,
|
|
3427
3576
|
data: "0x"
|
|
@@ -3429,11 +3578,10 @@ function random$1(config) {
|
|
|
3429
3578
|
const maker = config?.maker ?? address();
|
|
3430
3579
|
return from$7({
|
|
3431
3580
|
maker,
|
|
3432
|
-
|
|
3433
|
-
obligationUnits: config?.obligationUnits ?? 0n,
|
|
3434
|
-
obligationShares: config?.obligationShares ?? 0n,
|
|
3581
|
+
obligationUnits: obligationUnitsScaled,
|
|
3435
3582
|
tick,
|
|
3436
3583
|
maturity,
|
|
3584
|
+
rcfThreshold: config?.rcfThreshold ?? 0n,
|
|
3437
3585
|
expiry: config?.expiry ?? maturity - 1,
|
|
3438
3586
|
start: config?.start ?? maturity - 10,
|
|
3439
3587
|
group: config?.group ?? hex(32),
|
|
@@ -3445,7 +3593,8 @@ function random$1(config) {
|
|
|
3445
3593
|
lltv
|
|
3446
3594
|
})).sort((a, b) => a.asset.localeCompare(b.asset)),
|
|
3447
3595
|
callback: config?.callback ?? emptyCallback,
|
|
3448
|
-
receiverIfMakerIsSeller: config?.receiverIfMakerIsSeller ?? maker
|
|
3596
|
+
receiverIfMakerIsSeller: config?.receiverIfMakerIsSeller ?? maker,
|
|
3597
|
+
exitOnly: config?.exitOnly ?? false
|
|
3449
3598
|
});
|
|
3450
3599
|
}
|
|
3451
3600
|
const weightedChoice = (pairs) => {
|
|
@@ -3472,124 +3621,150 @@ function hash(offer) {
|
|
|
3472
3621
|
return computed;
|
|
3473
3622
|
}
|
|
3474
3623
|
/**
|
|
3475
|
-
*
|
|
3476
|
-
*
|
|
3477
|
-
*
|
|
3478
|
-
*
|
|
3479
|
-
*
|
|
3624
|
+
* ABI layout matching the Solidity `Offer` struct used by `abi.encode(offer)` in the contract.
|
|
3625
|
+
*
|
|
3626
|
+
* This is a **single top-level tuple** — Solidity's `abi.encode(struct)` encodes the struct as one
|
|
3627
|
+
* tuple parameter, not as separate parameters per field. Field order and nesting must exactly
|
|
3628
|
+
* mirror `contracts/interfaces/IMidnight.sol`:
|
|
3629
|
+
*
|
|
3630
|
+
* ```
|
|
3631
|
+
* struct Offer {
|
|
3632
|
+
* Obligation obligation; // nested tuple
|
|
3633
|
+
* bool buy;
|
|
3634
|
+
* address maker;
|
|
3635
|
+
* uint256 obligationUnits;
|
|
3636
|
+
* uint256 start;
|
|
3637
|
+
* uint256 expiry;
|
|
3638
|
+
* uint256 tick;
|
|
3639
|
+
* bytes32 group;
|
|
3640
|
+
* bytes32 session;
|
|
3641
|
+
* address callback;
|
|
3642
|
+
* bytes callbackData;
|
|
3643
|
+
* address receiverIfMakerIsSeller;
|
|
3644
|
+
* bool exitOnly;
|
|
3645
|
+
* }
|
|
3646
|
+
* ```
|
|
3480
3647
|
*/
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
type: "bool"
|
|
3532
|
-
},
|
|
3533
|
-
{
|
|
3534
|
-
name: "loanToken",
|
|
3535
|
-
type: "address"
|
|
3536
|
-
},
|
|
3537
|
-
{
|
|
3538
|
-
name: "start",
|
|
3539
|
-
type: "uint256"
|
|
3540
|
-
},
|
|
3541
|
-
{
|
|
3542
|
-
name: "collaterals",
|
|
3543
|
-
type: "tuple[]",
|
|
3544
|
-
components: [
|
|
3545
|
-
{
|
|
3546
|
-
name: "asset",
|
|
3547
|
-
type: "address"
|
|
3548
|
-
},
|
|
3549
|
-
{
|
|
3550
|
-
name: "oracle",
|
|
3551
|
-
type: "address"
|
|
3552
|
-
},
|
|
3553
|
-
{
|
|
3554
|
-
name: "lltv",
|
|
3555
|
-
type: "uint256"
|
|
3556
|
-
}
|
|
3557
|
-
]
|
|
3558
|
-
},
|
|
3559
|
-
{
|
|
3560
|
-
name: "callback",
|
|
3561
|
-
type: "tuple",
|
|
3562
|
-
components: [{
|
|
3563
|
-
name: "address",
|
|
3648
|
+
const OfferAbi = [{
|
|
3649
|
+
name: "offer",
|
|
3650
|
+
type: "tuple",
|
|
3651
|
+
components: [
|
|
3652
|
+
{
|
|
3653
|
+
name: "obligation",
|
|
3654
|
+
type: "tuple",
|
|
3655
|
+
components: [
|
|
3656
|
+
{
|
|
3657
|
+
name: "loanToken",
|
|
3658
|
+
type: "address"
|
|
3659
|
+
},
|
|
3660
|
+
{
|
|
3661
|
+
name: "collaterals",
|
|
3662
|
+
type: "tuple[]",
|
|
3663
|
+
components: [
|
|
3664
|
+
{
|
|
3665
|
+
name: "token",
|
|
3666
|
+
type: "address"
|
|
3667
|
+
},
|
|
3668
|
+
{
|
|
3669
|
+
name: "lltv",
|
|
3670
|
+
type: "uint256"
|
|
3671
|
+
},
|
|
3672
|
+
{
|
|
3673
|
+
name: "maxLif",
|
|
3674
|
+
type: "uint256"
|
|
3675
|
+
},
|
|
3676
|
+
{
|
|
3677
|
+
name: "oracle",
|
|
3678
|
+
type: "address"
|
|
3679
|
+
}
|
|
3680
|
+
]
|
|
3681
|
+
},
|
|
3682
|
+
{
|
|
3683
|
+
name: "maturity",
|
|
3684
|
+
type: "uint256"
|
|
3685
|
+
},
|
|
3686
|
+
{
|
|
3687
|
+
name: "rcfThreshold",
|
|
3688
|
+
type: "uint256"
|
|
3689
|
+
}
|
|
3690
|
+
]
|
|
3691
|
+
},
|
|
3692
|
+
{
|
|
3693
|
+
name: "buy",
|
|
3694
|
+
type: "bool"
|
|
3695
|
+
},
|
|
3696
|
+
{
|
|
3697
|
+
name: "maker",
|
|
3564
3698
|
type: "address"
|
|
3565
|
-
},
|
|
3566
|
-
|
|
3699
|
+
},
|
|
3700
|
+
{
|
|
3701
|
+
name: "obligationUnits",
|
|
3702
|
+
type: "uint256"
|
|
3703
|
+
},
|
|
3704
|
+
{
|
|
3705
|
+
name: "start",
|
|
3706
|
+
type: "uint256"
|
|
3707
|
+
},
|
|
3708
|
+
{
|
|
3709
|
+
name: "expiry",
|
|
3710
|
+
type: "uint256"
|
|
3711
|
+
},
|
|
3712
|
+
{
|
|
3713
|
+
name: "tick",
|
|
3714
|
+
type: "uint256"
|
|
3715
|
+
},
|
|
3716
|
+
{
|
|
3717
|
+
name: "group",
|
|
3718
|
+
type: "bytes32"
|
|
3719
|
+
},
|
|
3720
|
+
{
|
|
3721
|
+
name: "session",
|
|
3722
|
+
type: "bytes32"
|
|
3723
|
+
},
|
|
3724
|
+
{
|
|
3725
|
+
name: "callback",
|
|
3726
|
+
type: "address"
|
|
3727
|
+
},
|
|
3728
|
+
{
|
|
3729
|
+
name: "callbackData",
|
|
3567
3730
|
type: "bytes"
|
|
3568
|
-
}
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3731
|
+
},
|
|
3732
|
+
{
|
|
3733
|
+
name: "receiverIfMakerIsSeller",
|
|
3734
|
+
type: "address"
|
|
3735
|
+
},
|
|
3736
|
+
{
|
|
3737
|
+
name: "exitOnly",
|
|
3738
|
+
type: "bool"
|
|
3739
|
+
}
|
|
3740
|
+
]
|
|
3741
|
+
}];
|
|
3575
3742
|
function encode$1(offer) {
|
|
3576
|
-
return encodeAbiParameters(OfferAbi, [
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
offer.
|
|
3590
|
-
offer.
|
|
3591
|
-
offer.
|
|
3592
|
-
|
|
3743
|
+
return encodeAbiParameters(OfferAbi, [{
|
|
3744
|
+
obligation: {
|
|
3745
|
+
loanToken: offer.loanToken,
|
|
3746
|
+
collaterals: offer.collaterals.map((c) => ({
|
|
3747
|
+
token: c.asset,
|
|
3748
|
+
lltv: c.lltv,
|
|
3749
|
+
maxLif: c.maxLif ?? 0n,
|
|
3750
|
+
oracle: c.oracle
|
|
3751
|
+
})),
|
|
3752
|
+
maturity: BigInt(offer.maturity),
|
|
3753
|
+
rcfThreshold: offer.rcfThreshold
|
|
3754
|
+
},
|
|
3755
|
+
buy: offer.buy,
|
|
3756
|
+
maker: offer.maker,
|
|
3757
|
+
obligationUnits: offer.obligationUnits,
|
|
3758
|
+
start: BigInt(offer.start),
|
|
3759
|
+
expiry: BigInt(offer.expiry),
|
|
3760
|
+
tick: BigInt(offer.tick),
|
|
3761
|
+
group: offer.group,
|
|
3762
|
+
session: offer.session,
|
|
3763
|
+
callback: offer.callback.address,
|
|
3764
|
+
callbackData: offer.callback.data,
|
|
3765
|
+
receiverIfMakerIsSeller: offer.receiverIfMakerIsSeller,
|
|
3766
|
+
exitOnly: offer.exitOnly
|
|
3767
|
+
}]);
|
|
3593
3768
|
}
|
|
3594
3769
|
function decode$1(data) {
|
|
3595
3770
|
let decoded;
|
|
@@ -3598,31 +3773,33 @@ function decode$1(data) {
|
|
|
3598
3773
|
} catch (error) {
|
|
3599
3774
|
throw new InvalidOfferError(error);
|
|
3600
3775
|
}
|
|
3776
|
+
const s = decoded[0];
|
|
3601
3777
|
return from$7({
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
obligationUnits: decoded[2],
|
|
3605
|
-
obligationShares: decoded[3],
|
|
3606
|
-
tick: Number(decoded[4]),
|
|
3607
|
-
maturity: from$9(Number(decoded[5])),
|
|
3608
|
-
expiry: Number(decoded[6]),
|
|
3609
|
-
group: decoded[7],
|
|
3610
|
-
session: decoded[8],
|
|
3611
|
-
buy: decoded[9],
|
|
3612
|
-
loanToken: decoded[10],
|
|
3613
|
-
start: Number(decoded[11]),
|
|
3614
|
-
collaterals: decoded[12].map((c) => {
|
|
3778
|
+
loanToken: s.obligation.loanToken,
|
|
3779
|
+
collaterals: s.obligation.collaterals.map((c) => {
|
|
3615
3780
|
return from$10({
|
|
3616
|
-
asset: c.
|
|
3781
|
+
asset: c.token,
|
|
3617
3782
|
oracle: c.oracle,
|
|
3618
|
-
lltv: c.lltv
|
|
3783
|
+
lltv: c.lltv,
|
|
3784
|
+
maxLif: c.maxLif
|
|
3619
3785
|
});
|
|
3620
3786
|
}),
|
|
3787
|
+
maturity: from$9(Number(s.obligation.maturity)),
|
|
3788
|
+
rcfThreshold: s.obligation.rcfThreshold,
|
|
3789
|
+
buy: s.buy,
|
|
3790
|
+
maker: s.maker,
|
|
3791
|
+
obligationUnits: s.obligationUnits,
|
|
3792
|
+
start: Number(s.start),
|
|
3793
|
+
expiry: Number(s.expiry),
|
|
3794
|
+
tick: Number(s.tick),
|
|
3795
|
+
group: s.group,
|
|
3796
|
+
session: s.session,
|
|
3621
3797
|
callback: {
|
|
3622
|
-
address:
|
|
3623
|
-
data:
|
|
3798
|
+
address: s.callback,
|
|
3799
|
+
data: s.callbackData
|
|
3624
3800
|
},
|
|
3625
|
-
receiverIfMakerIsSeller:
|
|
3801
|
+
receiverIfMakerIsSeller: s.receiverIfMakerIsSeller,
|
|
3802
|
+
exitOnly: s.exitOnly
|
|
3626
3803
|
});
|
|
3627
3804
|
}
|
|
3628
3805
|
/**
|
|
@@ -3639,7 +3816,7 @@ const takeEvent = {
|
|
|
3639
3816
|
internalType: "address"
|
|
3640
3817
|
},
|
|
3641
3818
|
{
|
|
3642
|
-
name: "
|
|
3819
|
+
name: "id_",
|
|
3643
3820
|
type: "bytes32",
|
|
3644
3821
|
indexed: true,
|
|
3645
3822
|
internalType: "bytes32"
|
|
@@ -3680,24 +3857,6 @@ const takeEvent = {
|
|
|
3680
3857
|
indexed: false,
|
|
3681
3858
|
internalType: "uint256"
|
|
3682
3859
|
},
|
|
3683
|
-
{
|
|
3684
|
-
name: "obligationShares",
|
|
3685
|
-
type: "uint256",
|
|
3686
|
-
indexed: false,
|
|
3687
|
-
internalType: "uint256"
|
|
3688
|
-
},
|
|
3689
|
-
{
|
|
3690
|
-
name: "buyerIsLender",
|
|
3691
|
-
type: "bool",
|
|
3692
|
-
indexed: false,
|
|
3693
|
-
internalType: "bool"
|
|
3694
|
-
},
|
|
3695
|
-
{
|
|
3696
|
-
name: "sellerIsBorrower",
|
|
3697
|
-
type: "bool",
|
|
3698
|
-
indexed: false,
|
|
3699
|
-
internalType: "bool"
|
|
3700
|
-
},
|
|
3701
3860
|
{
|
|
3702
3861
|
name: "sellerReceiver",
|
|
3703
3862
|
type: "address",
|
|
@@ -3715,19 +3874,31 @@ const takeEvent = {
|
|
|
3715
3874
|
type: "uint256",
|
|
3716
3875
|
indexed: false,
|
|
3717
3876
|
internalType: "uint256"
|
|
3718
|
-
}
|
|
3719
|
-
|
|
3720
|
-
|
|
3877
|
+
},
|
|
3878
|
+
{
|
|
3879
|
+
name: "totalUnits",
|
|
3880
|
+
type: "uint256",
|
|
3881
|
+
indexed: false,
|
|
3882
|
+
internalType: "uint256"
|
|
3883
|
+
}
|
|
3884
|
+
],
|
|
3885
|
+
anonymous: false
|
|
3721
3886
|
};
|
|
3722
3887
|
/**
|
|
3723
|
-
* ABI for the
|
|
3888
|
+
* ABI for the SetConsumed event emitted by the Morpho V2 contract.
|
|
3724
3889
|
*/
|
|
3725
3890
|
const consumedEvent = {
|
|
3726
3891
|
type: "event",
|
|
3727
|
-
name: "
|
|
3892
|
+
name: "SetConsumed",
|
|
3728
3893
|
inputs: [
|
|
3729
3894
|
{
|
|
3730
|
-
name: "
|
|
3895
|
+
name: "caller",
|
|
3896
|
+
type: "address",
|
|
3897
|
+
indexed: true,
|
|
3898
|
+
internalType: "address"
|
|
3899
|
+
},
|
|
3900
|
+
{
|
|
3901
|
+
name: "onBehalf",
|
|
3731
3902
|
type: "address",
|
|
3732
3903
|
indexed: true,
|
|
3733
3904
|
internalType: "address"
|
|
@@ -3761,7 +3932,7 @@ const repayEvent = {
|
|
|
3761
3932
|
internalType: "address"
|
|
3762
3933
|
},
|
|
3763
3934
|
{
|
|
3764
|
-
name: "
|
|
3935
|
+
name: "id_",
|
|
3765
3936
|
type: "bytes32",
|
|
3766
3937
|
indexed: true,
|
|
3767
3938
|
internalType: "bytes32"
|
|
@@ -3795,33 +3966,28 @@ const liquidateEvent = {
|
|
|
3795
3966
|
internalType: "address"
|
|
3796
3967
|
},
|
|
3797
3968
|
{
|
|
3798
|
-
name: "
|
|
3969
|
+
name: "id_",
|
|
3799
3970
|
type: "bytes32",
|
|
3800
3971
|
indexed: true,
|
|
3801
3972
|
internalType: "bytes32"
|
|
3802
3973
|
},
|
|
3803
3974
|
{
|
|
3804
|
-
name: "
|
|
3805
|
-
type: "
|
|
3975
|
+
name: "collateralIndex",
|
|
3976
|
+
type: "uint256",
|
|
3806
3977
|
indexed: false,
|
|
3807
|
-
internalType: "
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
3811
|
-
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
name: "seized",
|
|
3821
|
-
type: "uint256",
|
|
3822
|
-
internalType: "uint256"
|
|
3823
|
-
}
|
|
3824
|
-
]
|
|
3978
|
+
internalType: "uint256"
|
|
3979
|
+
},
|
|
3980
|
+
{
|
|
3981
|
+
name: "seizedAssets",
|
|
3982
|
+
type: "uint256",
|
|
3983
|
+
indexed: false,
|
|
3984
|
+
internalType: "uint256"
|
|
3985
|
+
},
|
|
3986
|
+
{
|
|
3987
|
+
name: "repaidUnits",
|
|
3988
|
+
type: "uint256",
|
|
3989
|
+
indexed: false,
|
|
3990
|
+
internalType: "uint256"
|
|
3825
3991
|
},
|
|
3826
3992
|
{
|
|
3827
3993
|
name: "borrower",
|
|
@@ -3830,13 +3996,13 @@ const liquidateEvent = {
|
|
|
3830
3996
|
internalType: "address"
|
|
3831
3997
|
},
|
|
3832
3998
|
{
|
|
3833
|
-
name: "
|
|
3999
|
+
name: "badDebt",
|
|
3834
4000
|
type: "uint256",
|
|
3835
4001
|
indexed: false,
|
|
3836
4002
|
internalType: "uint256"
|
|
3837
4003
|
},
|
|
3838
4004
|
{
|
|
3839
|
-
name: "
|
|
4005
|
+
name: "latestLossIndex",
|
|
3840
4006
|
type: "uint256",
|
|
3841
4007
|
indexed: false,
|
|
3842
4008
|
internalType: "uint256"
|
|
@@ -3858,7 +4024,7 @@ const supplyCollateralEvent = {
|
|
|
3858
4024
|
internalType: "address"
|
|
3859
4025
|
},
|
|
3860
4026
|
{
|
|
3861
|
-
name: "
|
|
4027
|
+
name: "id_",
|
|
3862
4028
|
type: "bytes32",
|
|
3863
4029
|
indexed: true,
|
|
3864
4030
|
internalType: "bytes32"
|
|
@@ -3898,7 +4064,7 @@ const withdrawCollateralEvent = {
|
|
|
3898
4064
|
internalType: "address"
|
|
3899
4065
|
},
|
|
3900
4066
|
{
|
|
3901
|
-
name: "
|
|
4067
|
+
name: "id_",
|
|
3902
4068
|
type: "bytes32",
|
|
3903
4069
|
indexed: true,
|
|
3904
4070
|
internalType: "bytes32"
|
|
@@ -3931,9 +4097,9 @@ const withdrawCollateralEvent = {
|
|
|
3931
4097
|
anonymous: false
|
|
3932
4098
|
};
|
|
3933
4099
|
var InvalidOfferError = class InvalidOfferError extends BaseError {
|
|
4100
|
+
name = "Offer.InvalidOfferError";
|
|
3934
4101
|
constructor(error) {
|
|
3935
4102
|
super("Invalid offer.", { cause: error });
|
|
3936
|
-
_defineProperty(this, "name", "Offer.InvalidOfferError");
|
|
3937
4103
|
}
|
|
3938
4104
|
/**
|
|
3939
4105
|
* Formats ZodError issues into a human-readable string with line breaks.
|
|
@@ -4146,9 +4312,9 @@ function random() {
|
|
|
4146
4312
|
});
|
|
4147
4313
|
}
|
|
4148
4314
|
var InvalidQuoteError = class extends BaseError {
|
|
4315
|
+
name = "Quote.InvalidQuoteError";
|
|
4149
4316
|
constructor(error) {
|
|
4150
4317
|
super("Invalid quote.", { cause: error });
|
|
4151
|
-
_defineProperty(this, "name", "Quote.InvalidQuoteError");
|
|
4152
4318
|
}
|
|
4153
4319
|
};
|
|
4154
4320
|
function sideFromTick(side) {
|
|
@@ -4174,7 +4340,7 @@ var TradingFee_exports = /* @__PURE__ */ __exportAll({
|
|
|
4174
4340
|
});
|
|
4175
4341
|
/**
|
|
4176
4342
|
* Time breakpoints in seconds for piecewise linear fee interpolation.
|
|
4177
|
-
* Matches on-chain constants: 0d, 1d, 7d, 30d, 90d, 180d.
|
|
4343
|
+
* Matches on-chain constants: 0d, 1d, 7d, 30d, 90d, 180d, 360d.
|
|
4178
4344
|
*/
|
|
4179
4345
|
const BREAKPOINTS = [
|
|
4180
4346
|
0n,
|
|
@@ -4182,21 +4348,22 @@ const BREAKPOINTS = [
|
|
|
4182
4348
|
604800n,
|
|
4183
4349
|
2592000n,
|
|
4184
4350
|
7776000n,
|
|
4185
|
-
15552000n
|
|
4351
|
+
15552000n,
|
|
4352
|
+
31104000n
|
|
4186
4353
|
];
|
|
4187
4354
|
/** WAD constant (1e18) for fee scaling. */
|
|
4188
4355
|
const WAD = 10n ** 18n;
|
|
4189
4356
|
/**
|
|
4190
|
-
* Create a TradingFee from an activation flag and
|
|
4357
|
+
* Create a TradingFee from an activation flag and 7 fee values.
|
|
4191
4358
|
* @param activated - Whether the fee is active.
|
|
4192
|
-
* @param fees - Tuple of
|
|
4359
|
+
* @param fees - Tuple of 7 fee values in WAD (one per breakpoint: 0d, 1d, 7d, 30d, 90d, 180d, 360d).
|
|
4193
4360
|
* @returns A new TradingFee instance.
|
|
4194
4361
|
* @throws {@link InvalidFeeError} if any fee exceeds WAD (100%).
|
|
4195
|
-
* @throws {@link InvalidFeesLengthError} if fees array doesn't have exactly
|
|
4362
|
+
* @throws {@link InvalidFeesLengthError} if fees array doesn't have exactly 7 elements.
|
|
4196
4363
|
*/
|
|
4197
4364
|
function from$3(activated, fees) {
|
|
4198
|
-
if (fees.length !==
|
|
4199
|
-
for (let i = 0; i <
|
|
4365
|
+
if (fees.length !== 7) throw new InvalidFeesLengthError(fees.length);
|
|
4366
|
+
for (let i = 0; i < 7; i++) {
|
|
4200
4367
|
const fee = fees[i];
|
|
4201
4368
|
if (fee < 0n || fee > WAD) throw new InvalidFeeError(fee, i);
|
|
4202
4369
|
}
|
|
@@ -4215,7 +4382,9 @@ function from$3(activated, fees) {
|
|
|
4215
4382
|
function compute(tradingFee, timeToMaturity) {
|
|
4216
4383
|
if (!tradingFee._activated) return 0n;
|
|
4217
4384
|
const time = BigInt(Math.max(0, Math.floor(timeToMaturity)));
|
|
4218
|
-
|
|
4385
|
+
const maxBreakpoint = BREAKPOINTS[BREAKPOINTS.length - 1];
|
|
4386
|
+
const maxFee = tradingFee._fees[tradingFee._fees.length - 1];
|
|
4387
|
+
if (time >= maxBreakpoint) return maxFee;
|
|
4219
4388
|
const { index, start, end } = getSegment(time);
|
|
4220
4389
|
const feeLower = tradingFee._fees[index];
|
|
4221
4390
|
const feeUpper = tradingFee._fees[index + 1];
|
|
@@ -4255,7 +4424,7 @@ function deactivate(tradingFee) {
|
|
|
4255
4424
|
/**
|
|
4256
4425
|
* Get the fee values at each breakpoint.
|
|
4257
4426
|
* @param tradingFee - The TradingFee instance.
|
|
4258
|
-
* @returns The tuple of
|
|
4427
|
+
* @returns The tuple of 7 fee values.
|
|
4259
4428
|
*/
|
|
4260
4429
|
function getFees(tradingFee) {
|
|
4261
4430
|
return tradingFee._fees;
|
|
@@ -4266,44 +4435,35 @@ function getFees(tradingFee) {
|
|
|
4266
4435
|
* @returns Object with index, start, and end of the segment.
|
|
4267
4436
|
*/
|
|
4268
4437
|
function getSegment(timeToMaturity) {
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
index: 2,
|
|
4281
|
-
start: BREAKPOINTS[2],
|
|
4282
|
-
end: BREAKPOINTS[3]
|
|
4283
|
-
};
|
|
4284
|
-
if (timeToMaturity < BREAKPOINTS[4]) return {
|
|
4285
|
-
index: 3,
|
|
4286
|
-
start: BREAKPOINTS[3],
|
|
4287
|
-
end: BREAKPOINTS[4]
|
|
4288
|
-
};
|
|
4438
|
+
for (let segmentEndIndex = 1; segmentEndIndex < BREAKPOINTS.length; segmentEndIndex++) {
|
|
4439
|
+
const end = BREAKPOINTS[segmentEndIndex];
|
|
4440
|
+
if (timeToMaturity < end) {
|
|
4441
|
+
const index = segmentEndIndex - 1;
|
|
4442
|
+
return {
|
|
4443
|
+
index,
|
|
4444
|
+
start: BREAKPOINTS[index],
|
|
4445
|
+
end
|
|
4446
|
+
};
|
|
4447
|
+
}
|
|
4448
|
+
}
|
|
4289
4449
|
return {
|
|
4290
|
-
index:
|
|
4291
|
-
start: BREAKPOINTS[
|
|
4292
|
-
end: BREAKPOINTS[
|
|
4450
|
+
index: BREAKPOINTS.length - 2,
|
|
4451
|
+
start: BREAKPOINTS[BREAKPOINTS.length - 2],
|
|
4452
|
+
end: BREAKPOINTS[BREAKPOINTS.length - 1]
|
|
4293
4453
|
};
|
|
4294
4454
|
}
|
|
4295
4455
|
/** Error thrown when a fee value is invalid (negative or exceeds WAD). */
|
|
4296
4456
|
var InvalidFeeError = class extends BaseError {
|
|
4457
|
+
name = "TradingFee.InvalidFeeError";
|
|
4297
4458
|
constructor(fee, index) {
|
|
4298
4459
|
super(`Invalid fee at index ${index}: ${fee}. Fee must be between 0 and ${WAD} (WAD).`);
|
|
4299
|
-
_defineProperty(this, "name", "TradingFee.InvalidFeeError");
|
|
4300
4460
|
}
|
|
4301
4461
|
};
|
|
4302
|
-
/** Error thrown when fees array doesn't have exactly
|
|
4462
|
+
/** Error thrown when fees array doesn't have exactly 7 elements. */
|
|
4303
4463
|
var InvalidFeesLengthError = class extends BaseError {
|
|
4464
|
+
name = "TradingFee.InvalidFeesLengthError";
|
|
4304
4465
|
constructor(length) {
|
|
4305
|
-
super(`Invalid fees length: ${length}. Expected exactly
|
|
4306
|
-
_defineProperty(this, "name", "TradingFee.InvalidFeesLengthError");
|
|
4466
|
+
super(`Invalid fees length: ${length}. Expected exactly 7 fee values.`);
|
|
4307
4467
|
}
|
|
4308
4468
|
};
|
|
4309
4469
|
|
|
@@ -4341,9 +4501,12 @@ function from$2(parameters) {
|
|
|
4341
4501
|
var Tree_exports = /* @__PURE__ */ __exportAll({
|
|
4342
4502
|
DecodeError: () => DecodeError,
|
|
4343
4503
|
EncodeError: () => EncodeError,
|
|
4504
|
+
MAX_COMPRESSED_OFFERS_BYTES: () => MAX_COMPRESSED_OFFERS_BYTES,
|
|
4505
|
+
MAX_DECOMPRESSED_OFFERS_BYTES: () => MAX_DECOMPRESSED_OFFERS_BYTES,
|
|
4506
|
+
MAX_OFFERS_PER_TREE: () => MAX_OFFERS_PER_TREE,
|
|
4344
4507
|
SignatureDomainError: () => SignatureDomainError,
|
|
4345
4508
|
TreeError: () => TreeError,
|
|
4346
|
-
VERSION: () => VERSION,
|
|
4509
|
+
VERSION: () => VERSION$1,
|
|
4347
4510
|
decode: () => decode,
|
|
4348
4511
|
encode: () => encode,
|
|
4349
4512
|
encodeUnsigned: () => encodeUnsigned,
|
|
@@ -4352,7 +4515,16 @@ var Tree_exports = /* @__PURE__ */ __exportAll({
|
|
|
4352
4515
|
signatureDomain: () => signatureDomain,
|
|
4353
4516
|
signatureTypes: () => signatureTypes
|
|
4354
4517
|
});
|
|
4355
|
-
const VERSION =
|
|
4518
|
+
const VERSION$1 = 2;
|
|
4519
|
+
const MAX_COMPRESSED_OFFERS_BYTES = 1e6;
|
|
4520
|
+
const MAX_DECOMPRESSED_OFFERS_BYTES = 4e6;
|
|
4521
|
+
const MAX_OFFERS_PER_TREE = 100;
|
|
4522
|
+
const ROOT_BYTES = 32;
|
|
4523
|
+
const SIGNATURE_BYTES = 65;
|
|
4524
|
+
const MIN_SIGNED_PAYLOAD_BYTES = 1 + ROOT_BYTES + SIGNATURE_BYTES;
|
|
4525
|
+
const INFLATE_INPUT_CHUNK_BYTES = 64 * 1024;
|
|
4526
|
+
const UTF8_ENCODER = new TextEncoder();
|
|
4527
|
+
const UTF8_DECODER = new TextDecoder();
|
|
4356
4528
|
/**
|
|
4357
4529
|
* EIP-712 types for signing the tree root (Root(bytes32 root)).
|
|
4358
4530
|
*/
|
|
@@ -4369,29 +4541,83 @@ const signatureTypes = {
|
|
|
4369
4541
|
type: "bytes32"
|
|
4370
4542
|
}]
|
|
4371
4543
|
};
|
|
4372
|
-
const
|
|
4544
|
+
const gzipOffersPayload = (payload, errorFactory) => {
|
|
4545
|
+
const payloadBytes = UTF8_ENCODER.encode(payload);
|
|
4546
|
+
if (payloadBytes.length > MAX_DECOMPRESSED_OFFERS_BYTES) throw errorFactory(`decompressed offers exceed ${MAX_DECOMPRESSED_OFFERS_BYTES} bytes`);
|
|
4547
|
+
try {
|
|
4548
|
+
const compressed = gzip(payloadBytes);
|
|
4549
|
+
if (compressed.length > MAX_COMPRESSED_OFFERS_BYTES) throw errorFactory(`compressed offers exceed ${MAX_COMPRESSED_OFFERS_BYTES} bytes`);
|
|
4550
|
+
return compressed;
|
|
4551
|
+
} catch (error) {
|
|
4552
|
+
if (error instanceof BaseError) throw error;
|
|
4553
|
+
throw errorFactory("compression failed");
|
|
4554
|
+
}
|
|
4555
|
+
};
|
|
4556
|
+
const gunzipOffersPayload = (compressed, errorFactory) => {
|
|
4557
|
+
if (compressed.length === 0) throw errorFactory("decompression failed");
|
|
4558
|
+
if (compressed.length > MAX_COMPRESSED_OFFERS_BYTES) throw errorFactory(`compressed offers exceed ${MAX_COMPRESSED_OFFERS_BYTES} bytes`);
|
|
4559
|
+
let totalLength = 0;
|
|
4560
|
+
const inflate = new Inflate();
|
|
4561
|
+
const defaultOnData = inflate.onData.bind(inflate);
|
|
4562
|
+
inflate.onData = (chunk) => {
|
|
4563
|
+
totalLength += chunk.length;
|
|
4564
|
+
if (totalLength > MAX_DECOMPRESSED_OFFERS_BYTES) throw errorFactory(`decompressed offers exceed ${MAX_DECOMPRESSED_OFFERS_BYTES} bytes`);
|
|
4565
|
+
defaultOnData(chunk);
|
|
4566
|
+
};
|
|
4567
|
+
try {
|
|
4568
|
+
for (let offset = 0; offset < compressed.length; offset += INFLATE_INPUT_CHUNK_BYTES) {
|
|
4569
|
+
const end = Math.min(offset + INFLATE_INPUT_CHUNK_BYTES, compressed.length);
|
|
4570
|
+
inflate.push(compressed.subarray(offset, end), end === compressed.length);
|
|
4571
|
+
}
|
|
4572
|
+
} catch (error) {
|
|
4573
|
+
if (error instanceof BaseError) throw error;
|
|
4574
|
+
throw errorFactory("decompression failed");
|
|
4575
|
+
}
|
|
4576
|
+
if (inflate.err !== 0) throw errorFactory(inflate.msg || "decompression failed");
|
|
4577
|
+
if (!(inflate.result instanceof Uint8Array)) throw errorFactory("decompression failed");
|
|
4578
|
+
return UTF8_DECODER.decode(inflate.result);
|
|
4579
|
+
};
|
|
4580
|
+
const parseRawOffersPayload = (decoded, errorFactory) => {
|
|
4581
|
+
let rawOffers;
|
|
4582
|
+
try {
|
|
4583
|
+
rawOffers = JSON.parse(decoded);
|
|
4584
|
+
} catch {
|
|
4585
|
+
throw errorFactory("JSON parse failed");
|
|
4586
|
+
}
|
|
4587
|
+
if (!Array.isArray(rawOffers)) throw errorFactory("offers payload must be a JSON array");
|
|
4588
|
+
if (rawOffers.length > MAX_OFFERS_PER_TREE) throw errorFactory(`offers payload exceeds ${MAX_OFFERS_PER_TREE} offers`);
|
|
4589
|
+
return rawOffers;
|
|
4590
|
+
};
|
|
4591
|
+
const assertUniqueOfferHashes = (offers, errorFactory) => {
|
|
4592
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4593
|
+
for (const offer of offers) {
|
|
4594
|
+
const hash$1 = hash(offer);
|
|
4595
|
+
if (seen.has(hash$1)) throw errorFactory(`duplicate offer hash ${hash$1}`);
|
|
4596
|
+
seen.add(hash$1);
|
|
4597
|
+
}
|
|
4598
|
+
};
|
|
4373
4599
|
/**
|
|
4374
4600
|
* Builds a Merkle tree from a list of offers.
|
|
4375
4601
|
*
|
|
4376
4602
|
* Leaves are the offer `hash` values as `bytes32` and are deterministically
|
|
4377
|
-
* ordered
|
|
4378
|
-
* root is stable regardless of the input order.
|
|
4603
|
+
* ordered so that the resulting root is stable regardless of the input order.
|
|
4379
4604
|
*
|
|
4380
4605
|
* @param offers - Offers to include in the tree.
|
|
4381
|
-
* @returns A `
|
|
4606
|
+
* @returns A `SimpleMerkleTree` of offer hashes representing the offers.
|
|
4382
4607
|
* @throws {TreeError} If tree building fails due to offer inconsistencies.
|
|
4383
4608
|
*/
|
|
4384
4609
|
const from$1 = (offers) => {
|
|
4385
|
-
|
|
4386
|
-
const
|
|
4610
|
+
assertUniqueOfferHashes(offers, (reason) => new TreeError(reason));
|
|
4611
|
+
const leaves = offers.map((offer) => hash(offer));
|
|
4612
|
+
const tree = SimpleMerkleTree.of(leaves);
|
|
4387
4613
|
const orderedOffers = orderOffers(tree, offers);
|
|
4388
4614
|
return Object.assign(tree, { offers: orderedOffers });
|
|
4389
4615
|
};
|
|
4390
4616
|
const orderOffers = (tree, offers) => {
|
|
4391
4617
|
const offerByHash = /* @__PURE__ */ new Map();
|
|
4392
|
-
for (const offer of offers) offerByHash.set(
|
|
4618
|
+
for (const offer of offers) offerByHash.set(hash(offer), offer);
|
|
4393
4619
|
const entries = tree.dump().values.map((value) => {
|
|
4394
|
-
const hash =
|
|
4620
|
+
const hash = value.value;
|
|
4395
4621
|
const offer = offerByHash.get(hash);
|
|
4396
4622
|
if (!offer) throw new TreeError(`missing offer for leaf ${hash}`);
|
|
4397
4623
|
return {
|
|
@@ -4406,7 +4632,7 @@ const orderOffers = (tree, offers) => {
|
|
|
4406
4632
|
* Generates merkle proofs for all offers in a tree.
|
|
4407
4633
|
*
|
|
4408
4634
|
* Each proof allows independent verification that an offer is included in the tree
|
|
4409
|
-
* without requiring the full tree.
|
|
4635
|
+
* without requiring the full tree.
|
|
4410
4636
|
*
|
|
4411
4637
|
* @param tree - The {@link Tree} to generate proofs for.
|
|
4412
4638
|
* @returns Array of proofs - {@link Proof}
|
|
@@ -4415,7 +4641,7 @@ const proofs = (tree) => {
|
|
|
4415
4641
|
return tree.offers.map((offer) => {
|
|
4416
4642
|
return {
|
|
4417
4643
|
offer,
|
|
4418
|
-
path: tree.getProof(
|
|
4644
|
+
path: tree.getProof(hash(offer))
|
|
4419
4645
|
};
|
|
4420
4646
|
});
|
|
4421
4647
|
};
|
|
@@ -4546,16 +4772,17 @@ const encodeUnsigned = (tree) => {
|
|
|
4546
4772
|
return bytesToHex(encodeUnsignedBytes(tree));
|
|
4547
4773
|
};
|
|
4548
4774
|
const validateTreeForEncoding = (tree) => {
|
|
4549
|
-
if (VERSION > 255) throw new EncodeError(`version overflow: ${VERSION} exceeds 255`);
|
|
4775
|
+
if (VERSION$1 > 255) throw new EncodeError(`version overflow: ${VERSION$1} exceeds 255`);
|
|
4776
|
+
if (tree.offers.length > MAX_OFFERS_PER_TREE) throw new EncodeError(`offers payload exceeds ${MAX_OFFERS_PER_TREE} offers`);
|
|
4550
4777
|
const computed = from$1(tree.offers);
|
|
4551
4778
|
if (tree.root !== computed.root) throw new EncodeError(`root mismatch: expected ${computed.root}, got ${tree.root}`);
|
|
4552
4779
|
};
|
|
4553
4780
|
const encodeUnsignedBytes = (tree) => {
|
|
4554
4781
|
const offersPayload = tree.offers.map(serialize);
|
|
4555
|
-
const compressed =
|
|
4782
|
+
const compressed = gzipOffersPayload(JSON.stringify(offersPayload), (reason) => new EncodeError(reason));
|
|
4556
4783
|
const rootBytes = hexToBytes(tree.root);
|
|
4557
|
-
const encoded = new Uint8Array(1 + compressed.length +
|
|
4558
|
-
encoded[0] = VERSION;
|
|
4784
|
+
const encoded = new Uint8Array(1 + compressed.length + ROOT_BYTES);
|
|
4785
|
+
encoded[0] = VERSION$1;
|
|
4559
4786
|
encoded.set(compressed, 1);
|
|
4560
4787
|
encoded.set(rootBytes, 1 + compressed.length);
|
|
4561
4788
|
return encoded;
|
|
@@ -4567,10 +4794,11 @@ const encodeUnsignedBytes = (tree) => {
|
|
|
4567
4794
|
* Returns the tree with separately validated signature and recovered signer address.
|
|
4568
4795
|
*
|
|
4569
4796
|
* Validation order:
|
|
4570
|
-
* 1. Version
|
|
4797
|
+
* 1. Version and static size checks
|
|
4571
4798
|
* 2. Signature verification (fail-fast, before decompression)
|
|
4572
|
-
* 3.
|
|
4573
|
-
* 4.
|
|
4799
|
+
* 3. Streaming decompression with byte cap
|
|
4800
|
+
* 4. JSON array + offer count checks
|
|
4801
|
+
* 5. Root verification (computed from offers vs embedded root)
|
|
4574
4802
|
*
|
|
4575
4803
|
* @example
|
|
4576
4804
|
* ```typescript
|
|
@@ -4587,33 +4815,20 @@ const decode = async (encoded, domain) => {
|
|
|
4587
4815
|
const errorFactory = (reason) => new DecodeError(reason);
|
|
4588
4816
|
const normalizedDomain = normalizeSignatureDomain(domain, errorFactory);
|
|
4589
4817
|
const bytes = hexToBytes(encoded);
|
|
4590
|
-
if (bytes.length <
|
|
4818
|
+
if (bytes.length < MIN_SIGNED_PAYLOAD_BYTES) throw new DecodeError("payload too short");
|
|
4591
4819
|
const version = bytes[0];
|
|
4592
|
-
if (version !== (VERSION & 255)) throw new DecodeError(`invalid version: expected ${VERSION}, got ${version ?? 0}`);
|
|
4593
|
-
const signature = bytesToHex(bytes.slice(-
|
|
4594
|
-
const root = bytesToHex(bytes.slice(-
|
|
4595
|
-
assertHex(root,
|
|
4596
|
-
assertHex(signature,
|
|
4820
|
+
if (version !== (VERSION$1 & 255)) throw new DecodeError(`invalid version: expected ${VERSION$1}, got ${version ?? 0}`);
|
|
4821
|
+
const signature = bytesToHex(bytes.slice(-SIGNATURE_BYTES));
|
|
4822
|
+
const root = bytesToHex(bytes.slice(-(ROOT_BYTES + SIGNATURE_BYTES), -SIGNATURE_BYTES));
|
|
4823
|
+
assertHex(root, ROOT_BYTES, "root");
|
|
4824
|
+
assertHex(signature, SIGNATURE_BYTES, "signature");
|
|
4597
4825
|
const signer = await verifySignatureAndRecoverAddress({
|
|
4598
4826
|
root,
|
|
4599
4827
|
signature,
|
|
4600
4828
|
domain: normalizedDomain,
|
|
4601
4829
|
errorFactory
|
|
4602
4830
|
});
|
|
4603
|
-
const
|
|
4604
|
-
let decoded;
|
|
4605
|
-
try {
|
|
4606
|
-
decoded = ungzip(compressed, { to: "string" });
|
|
4607
|
-
} catch {
|
|
4608
|
-
throw new DecodeError("decompression failed");
|
|
4609
|
-
}
|
|
4610
|
-
let rawOffers;
|
|
4611
|
-
try {
|
|
4612
|
-
rawOffers = JSON.parse(decoded);
|
|
4613
|
-
} catch {
|
|
4614
|
-
throw new DecodeError("JSON parse failed");
|
|
4615
|
-
}
|
|
4616
|
-
const tree = from$1(rawOffers.map((o) => OfferSchema().parse(o)));
|
|
4831
|
+
const tree = from$1(parseRawOffersPayload(gunzipOffersPayload(bytes.slice(1, -(ROOT_BYTES + SIGNATURE_BYTES)), errorFactory), errorFactory).map((o) => OfferSchema().parse(o)));
|
|
4617
4832
|
if (root !== tree.root) throw new DecodeError(`root mismatch: expected ${tree.root}, got ${root}`);
|
|
4618
4833
|
return {
|
|
4619
4834
|
tree,
|
|
@@ -4626,9 +4841,9 @@ const decode = async (encoded, domain) => {
|
|
|
4626
4841
|
* Indicates structural issues with the tree (missing offers, inconsistent state).
|
|
4627
4842
|
*/
|
|
4628
4843
|
var TreeError = class extends BaseError {
|
|
4844
|
+
name = "Tree.TreeError";
|
|
4629
4845
|
constructor(reason) {
|
|
4630
4846
|
super(`Tree error: ${reason}`);
|
|
4631
|
-
_defineProperty(this, "name", "Tree.TreeError");
|
|
4632
4847
|
}
|
|
4633
4848
|
};
|
|
4634
4849
|
/**
|
|
@@ -4636,9 +4851,9 @@ var TreeError = class extends BaseError {
|
|
|
4636
4851
|
* Indicates validation failures (signature, root mismatch, mixed makers).
|
|
4637
4852
|
*/
|
|
4638
4853
|
var EncodeError = class extends BaseError {
|
|
4854
|
+
name = "Tree.EncodeError";
|
|
4639
4855
|
constructor(reason) {
|
|
4640
4856
|
super(`Failed to encode tree: ${reason}`);
|
|
4641
|
-
_defineProperty(this, "name", "Tree.EncodeError");
|
|
4642
4857
|
}
|
|
4643
4858
|
};
|
|
4644
4859
|
/**
|
|
@@ -4646,18 +4861,18 @@ var EncodeError = class extends BaseError {
|
|
|
4646
4861
|
* Indicates payload corruption, version mismatch, or validation failures.
|
|
4647
4862
|
*/
|
|
4648
4863
|
var DecodeError = class extends BaseError {
|
|
4864
|
+
name = "Tree.DecodeError";
|
|
4649
4865
|
constructor(reason) {
|
|
4650
4866
|
super(`Failed to decode tree: ${reason}`);
|
|
4651
|
-
_defineProperty(this, "name", "Tree.DecodeError");
|
|
4652
4867
|
}
|
|
4653
4868
|
};
|
|
4654
4869
|
/**
|
|
4655
4870
|
* Error thrown when an invalid signature domain is supplied.
|
|
4656
4871
|
*/
|
|
4657
4872
|
var SignatureDomainError = class extends BaseError {
|
|
4873
|
+
name = "Tree.SignatureDomainError";
|
|
4658
4874
|
constructor(reason) {
|
|
4659
4875
|
super(`Invalid signature domain: ${reason}`);
|
|
4660
|
-
_defineProperty(this, "name", "Tree.SignatureDomainError");
|
|
4661
4876
|
}
|
|
4662
4877
|
};
|
|
4663
4878
|
|
|
@@ -4732,11 +4947,10 @@ async function getOffers(apiClient, parameters) {
|
|
|
4732
4947
|
return {
|
|
4733
4948
|
...fromSnakeCase$1({
|
|
4734
4949
|
maker: offerData.maker,
|
|
4735
|
-
assets: offerData.assets,
|
|
4736
4950
|
obligation_units: offerData.obligation_units,
|
|
4737
|
-
obligation_shares: offerData.obligation_shares,
|
|
4738
4951
|
tick: offerData.tick,
|
|
4739
4952
|
maturity: from$9(offerData.obligation.maturity),
|
|
4953
|
+
rcf_threshold: offerData.obligation.rcf_threshold,
|
|
4740
4954
|
expiry: offerData.expiry,
|
|
4741
4955
|
start: offerData.start,
|
|
4742
4956
|
group: offerData.group,
|
|
@@ -4746,13 +4960,15 @@ async function getOffers(apiClient, parameters) {
|
|
|
4746
4960
|
collaterals: offerData.obligation.collaterals.map((collateral) => ({
|
|
4747
4961
|
asset: collateral.token,
|
|
4748
4962
|
oracle: collateral.oracle,
|
|
4749
|
-
lltv: collateral.lltv
|
|
4963
|
+
lltv: collateral.lltv,
|
|
4964
|
+
max_lif: collateral.max_lif
|
|
4750
4965
|
})),
|
|
4751
4966
|
callback: {
|
|
4752
4967
|
address: offerData.callback,
|
|
4753
4968
|
data: offerData.callback_data
|
|
4754
4969
|
},
|
|
4755
|
-
receiver_if_maker_is_seller: offerData.receiver_if_maker_is_seller
|
|
4970
|
+
receiver_if_maker_is_seller: offerData.receiver_if_maker_is_seller,
|
|
4971
|
+
exit_only: offerData.exit_only ?? false
|
|
4756
4972
|
}),
|
|
4757
4973
|
hash: item.offer_hash,
|
|
4758
4974
|
consumed: BigInt(item.consumed),
|
|
@@ -4793,9 +5009,11 @@ async function getObligations(apiClient, parameters) {
|
|
|
4793
5009
|
collaterals: item.collaterals.map((collateral) => ({
|
|
4794
5010
|
asset: collateral.token,
|
|
4795
5011
|
oracle: collateral.oracle,
|
|
4796
|
-
lltv: collateral.lltv
|
|
5012
|
+
lltv: collateral.lltv,
|
|
5013
|
+
max_lif: collateral.max_lif
|
|
4797
5014
|
})),
|
|
4798
|
-
maturity: from$9(item.maturity)
|
|
5015
|
+
maturity: from$9(item.maturity),
|
|
5016
|
+
rcf_threshold: item.rcf_threshold
|
|
4799
5017
|
});
|
|
4800
5018
|
const { obligationId: _, ...quote } = from$4({
|
|
4801
5019
|
obligationId: item.id,
|
|
@@ -4815,36 +5033,51 @@ async function getObligations(apiClient, parameters) {
|
|
|
4815
5033
|
};
|
|
4816
5034
|
}
|
|
4817
5035
|
var InvalidUrlError = class extends BaseError {
|
|
5036
|
+
name = "Router.InvalidUrlError";
|
|
4818
5037
|
constructor(url) {
|
|
4819
5038
|
super(`URL "${url}" is not http/https.`);
|
|
4820
|
-
_defineProperty(this, "name", "Router.InvalidUrlError");
|
|
4821
5039
|
}
|
|
4822
5040
|
};
|
|
4823
5041
|
var HttpUnauthorizedError = class extends BaseError {
|
|
5042
|
+
name = "Router.HttpUnauthorizedError";
|
|
4824
5043
|
constructor() {
|
|
4825
5044
|
super("Unauthorized.", { metaMessages: ["Ensure that an API key is provided."] });
|
|
4826
|
-
_defineProperty(this, "name", "Router.HttpUnauthorizedError");
|
|
4827
5045
|
}
|
|
4828
5046
|
};
|
|
4829
5047
|
var HttpForbiddenError = class extends BaseError {
|
|
5048
|
+
name = "Router.HttpForbiddenError";
|
|
4830
5049
|
constructor() {
|
|
4831
5050
|
super("Forbidden.", { metaMessages: ["Ensure that the API key is valid."] });
|
|
4832
|
-
_defineProperty(this, "name", "Router.HttpForbiddenError");
|
|
4833
5051
|
}
|
|
4834
5052
|
};
|
|
4835
5053
|
var HttpRateLimitError = class extends BaseError {
|
|
5054
|
+
name = "Router.HttpRateLimitError";
|
|
4836
5055
|
constructor() {
|
|
4837
5056
|
super("Rate limit exceeded.", { metaMessages: ["The number of allowed requests has been exceeded. You must wait for the rate limit to reset."] });
|
|
4838
|
-
_defineProperty(this, "name", "Router.HttpRateLimitError");
|
|
4839
5057
|
}
|
|
4840
5058
|
};
|
|
4841
5059
|
var HttpGetApiFailedError = class extends BaseError {
|
|
5060
|
+
name = "Router.HttpGetApiFailedError";
|
|
4842
5061
|
constructor(message, { details } = {}) {
|
|
4843
5062
|
super(message, { metaMessages: [details] });
|
|
4844
|
-
_defineProperty(this, "name", "Router.HttpGetApiFailedError");
|
|
4845
5063
|
}
|
|
4846
5064
|
};
|
|
4847
5065
|
|
|
5066
|
+
//#endregion
|
|
5067
|
+
//#region src/observability/TraceHeaders.ts
|
|
5068
|
+
/**
|
|
5069
|
+
* Inject active trace context headers into outgoing HTTP headers.
|
|
5070
|
+
* @param headers - Existing headers for the outgoing request.
|
|
5071
|
+
* @returns Headers enriched with active trace context.
|
|
5072
|
+
*/
|
|
5073
|
+
function withActiveTraceHeaders(headers) {
|
|
5074
|
+
const enrichedHeaders = new Headers(headers);
|
|
5075
|
+
const carrier = {};
|
|
5076
|
+
propagation.inject(context.active(), carrier);
|
|
5077
|
+
for (const [key, value] of Object.entries(carrier)) enrichedHeaders.set(key, value);
|
|
5078
|
+
return enrichedHeaders;
|
|
5079
|
+
}
|
|
5080
|
+
|
|
4848
5081
|
//#endregion
|
|
4849
5082
|
//#region src/gatekeeper/Client.ts
|
|
4850
5083
|
var Client_exports = /* @__PURE__ */ __exportAll({ createHttpClient: () => createHttpClient });
|
|
@@ -4865,7 +5098,7 @@ function createHttpClient(config) {
|
|
|
4865
5098
|
try {
|
|
4866
5099
|
return await fetchFn(`${baseUrl}${path}`, {
|
|
4867
5100
|
...init,
|
|
4868
|
-
headers: mergeHeaders(baseHeaders, init.headers),
|
|
5101
|
+
headers: withActiveTraceHeaders(mergeHeaders(baseHeaders, init.headers)),
|
|
4869
5102
|
signal: controller.signal
|
|
4870
5103
|
});
|
|
4871
5104
|
} finally {
|
|
@@ -5117,7 +5350,7 @@ const collateralAssets = {
|
|
|
5117
5350
|
"0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0"
|
|
5118
5351
|
]
|
|
5119
5352
|
};
|
|
5120
|
-
const oracles = {
|
|
5353
|
+
const oracles$1 = {
|
|
5121
5354
|
[ChainId.ETHEREUM.toString()]: [
|
|
5122
5355
|
"0xDddd770BADd886dF3864029e4B377B5F6a2B6b83",
|
|
5123
5356
|
"0x9CB3f4276bcD149b3668e1a645a964bC12877b89",
|
|
@@ -5139,6 +5372,7 @@ const oracles = {
|
|
|
5139
5372
|
],
|
|
5140
5373
|
[ChainId["ETHEREUM-VIRTUAL-TESTNET"].toString()]: [
|
|
5141
5374
|
"0xDddd770BADd886dF3864029e4B377B5F6a2B6b83",
|
|
5375
|
+
"0xEeee770BADd886dF3864029e4B377B5F6a2B6b83",
|
|
5142
5376
|
"0x9CB3f4276bcD149b3668e1a645a964bC12877b89",
|
|
5143
5377
|
"0x48F7E36EB6B826B2dF4B2E630B62Cd25e89E40e2",
|
|
5144
5378
|
"0x6Eb9F4128CeBc8B885A4d8562Db1Addf097f7348",
|
|
@@ -5147,6 +5381,7 @@ const oracles = {
|
|
|
5147
5381
|
],
|
|
5148
5382
|
[ChainId.ANVIL.toString()]: [
|
|
5149
5383
|
"0xDddd770BADd886dF3864029e4B377B5F6a2B6b83",
|
|
5384
|
+
"0xEeee770BADd886dF3864029e4B377B5F6a2B6b83",
|
|
5150
5385
|
"0x9CB3f4276bcD149b3668e1a645a964bC12877b89",
|
|
5151
5386
|
"0x48F7E36EB6B826B2dF4B2E630B62Cd25e89E40e2",
|
|
5152
5387
|
"0x6Eb9F4128CeBc8B885A4d8562Db1Addf097f7348",
|
|
@@ -5157,30 +5392,698 @@ const oracles = {
|
|
|
5157
5392
|
const configs = {
|
|
5158
5393
|
ethereum: {
|
|
5159
5394
|
callbacks: [{ type: Type$1.BuyWithEmptyCallback }, { type: Type$1.SellWithEmptyCallback }],
|
|
5160
|
-
maturities: [MaturityType.EndOfWeek, MaturityType.EndOfNextWeek]
|
|
5395
|
+
maturities: [MaturityType.EndOfWeek, MaturityType.EndOfNextWeek],
|
|
5396
|
+
minDuration: 10
|
|
5161
5397
|
},
|
|
5162
5398
|
base: {
|
|
5163
5399
|
callbacks: [{ type: Type$1.BuyWithEmptyCallback }, { type: Type$1.SellWithEmptyCallback }],
|
|
5164
|
-
maturities: [MaturityType.EndOfWeek, MaturityType.EndOfNextWeek]
|
|
5400
|
+
maturities: [MaturityType.EndOfWeek, MaturityType.EndOfNextWeek],
|
|
5401
|
+
minDuration: 10
|
|
5165
5402
|
},
|
|
5166
5403
|
"ethereum-virtual-testnet": {
|
|
5167
5404
|
callbacks: [{ type: Type$1.BuyWithEmptyCallback }, { type: Type$1.SellWithEmptyCallback }],
|
|
5168
|
-
maturities: [MaturityType.EndOfWeek, MaturityType.EndOfNextWeek]
|
|
5405
|
+
maturities: [MaturityType.EndOfWeek, MaturityType.EndOfNextWeek],
|
|
5406
|
+
minDuration: 10
|
|
5169
5407
|
},
|
|
5170
5408
|
anvil: {
|
|
5171
5409
|
callbacks: [{ type: Type$1.BuyWithEmptyCallback }, { type: Type$1.SellWithEmptyCallback }],
|
|
5172
|
-
maturities: [MaturityType.EndOfWeek, MaturityType.EndOfNextWeek]
|
|
5410
|
+
maturities: [MaturityType.EndOfWeek, MaturityType.EndOfNextWeek],
|
|
5411
|
+
minDuration: 10
|
|
5412
|
+
}
|
|
5413
|
+
};
|
|
5414
|
+
|
|
5415
|
+
//#endregion
|
|
5416
|
+
//#region src/utils/retry.ts
|
|
5417
|
+
const retry = async (fn, attempts = 3, delayMs = 50) => {
|
|
5418
|
+
let lastErr;
|
|
5419
|
+
for (let i = 0; i < attempts; i++) try {
|
|
5420
|
+
return await fn();
|
|
5421
|
+
} catch (err) {
|
|
5422
|
+
lastErr = err;
|
|
5423
|
+
if (i < attempts - 1) await new Promise((r) => setTimeout(r, delayMs));
|
|
5424
|
+
}
|
|
5425
|
+
throw lastErr;
|
|
5426
|
+
};
|
|
5427
|
+
|
|
5428
|
+
//#endregion
|
|
5429
|
+
//#region src/utils/batchMulticall.ts
|
|
5430
|
+
/**
|
|
5431
|
+
* Helper function to execute multicall in batches with retry logic.
|
|
5432
|
+
* Abstracts the common pattern of batching calls, retrying, and collecting results.
|
|
5433
|
+
*
|
|
5434
|
+
* @param parameters - Configuration for batched multicall
|
|
5435
|
+
* @returns Promise resolving to flattened array of results
|
|
5436
|
+
*/
|
|
5437
|
+
async function batchMulticall(parameters) {
|
|
5438
|
+
const { client, calls, batchSize, retryAttempts, retryDelayMs, blockNumber } = parameters;
|
|
5439
|
+
const results = [];
|
|
5440
|
+
for (const callsBatch of batch$1(calls, batchSize)) {
|
|
5441
|
+
const batchResults = await retry(() => multicall(client, {
|
|
5442
|
+
allowFailure: false,
|
|
5443
|
+
contracts: callsBatch,
|
|
5444
|
+
...blockNumber ? { blockNumber } : {}
|
|
5445
|
+
}), retryAttempts, retryDelayMs);
|
|
5446
|
+
results.push(...batchResults);
|
|
5173
5447
|
}
|
|
5448
|
+
return results;
|
|
5449
|
+
}
|
|
5450
|
+
|
|
5451
|
+
//#endregion
|
|
5452
|
+
//#region src/utils/Group.ts
|
|
5453
|
+
var Group_exports = /* @__PURE__ */ __exportAll({ fromNumber: () => fromNumber });
|
|
5454
|
+
/**
|
|
5455
|
+
* Creates a bytes32 group identifier from a number.
|
|
5456
|
+
* @param n - A non-negative integer.
|
|
5457
|
+
* @throws {Error} If n is negative or not an integer.
|
|
5458
|
+
*/
|
|
5459
|
+
const fromNumber = (n) => {
|
|
5460
|
+
if (!Number.isInteger(n)) throw new Error(`Group.fromNumber: expected integer, got ${n}`);
|
|
5461
|
+
if (n < 0) throw new Error(`Group.fromNumber: expected non-negative, got ${n}`);
|
|
5462
|
+
return pad(`0x${n.toString(16)}`, { size: 32 });
|
|
5463
|
+
};
|
|
5464
|
+
|
|
5465
|
+
//#endregion
|
|
5466
|
+
//#region src/utils/lazy.ts
|
|
5467
|
+
/**
|
|
5468
|
+
* Transform a polling function into an async generator.
|
|
5469
|
+
* @param fn - The polling function to transform.
|
|
5470
|
+
* @returns An async generator.
|
|
5471
|
+
*/
|
|
5472
|
+
function lazy(pollFn) {
|
|
5473
|
+
return () => (async function* () {
|
|
5474
|
+
let active = true;
|
|
5475
|
+
let resolveNext = null;
|
|
5476
|
+
const queue = [];
|
|
5477
|
+
const wait = () => new Promise((resolve) => {
|
|
5478
|
+
resolveNext = resolve;
|
|
5479
|
+
});
|
|
5480
|
+
const emit = (item) => {
|
|
5481
|
+
queue.push(item);
|
|
5482
|
+
resolveNext?.();
|
|
5483
|
+
resolveNext = null;
|
|
5484
|
+
};
|
|
5485
|
+
let unpoll = null;
|
|
5486
|
+
const stop = () => {
|
|
5487
|
+
active = false;
|
|
5488
|
+
unpoll?.();
|
|
5489
|
+
resolveNext?.();
|
|
5490
|
+
resolveNext = null;
|
|
5491
|
+
};
|
|
5492
|
+
unpoll = pollFn(emit, { stop });
|
|
5493
|
+
try {
|
|
5494
|
+
while (active) {
|
|
5495
|
+
if (queue.length === 0) await wait();
|
|
5496
|
+
while (queue.length > 0 && active) yield queue.shift();
|
|
5497
|
+
}
|
|
5498
|
+
} finally {
|
|
5499
|
+
stop();
|
|
5500
|
+
}
|
|
5501
|
+
})();
|
|
5502
|
+
}
|
|
5503
|
+
|
|
5504
|
+
//#endregion
|
|
5505
|
+
//#region src/utils/mapWithConcurrency.ts
|
|
5506
|
+
/**
|
|
5507
|
+
* Map values with a bounded number of concurrent async workers.
|
|
5508
|
+
*
|
|
5509
|
+
* Result ordering always matches the input order.
|
|
5510
|
+
* @param parameters - Input values, concurrency limit, and async mapper.
|
|
5511
|
+
* @returns Mapped results in input order.
|
|
5512
|
+
*/
|
|
5513
|
+
async function mapWithConcurrency(parameters) {
|
|
5514
|
+
const { values, limit, run } = parameters;
|
|
5515
|
+
if (values.length === 0) return [];
|
|
5516
|
+
const normalizedLimit = Math.max(1, Math.floor(limit));
|
|
5517
|
+
const workerCount = Math.min(normalizedLimit, values.length);
|
|
5518
|
+
const results = new Array(values.length);
|
|
5519
|
+
let nextIndex = 0;
|
|
5520
|
+
const worker = async () => {
|
|
5521
|
+
while (true) {
|
|
5522
|
+
const index = nextIndex;
|
|
5523
|
+
if (index >= values.length) return;
|
|
5524
|
+
nextIndex += 1;
|
|
5525
|
+
results[index] = await run(values[index], index);
|
|
5526
|
+
}
|
|
5527
|
+
};
|
|
5528
|
+
await Promise.all(Array.from({ length: workerCount }, () => worker()));
|
|
5529
|
+
return results;
|
|
5530
|
+
}
|
|
5531
|
+
|
|
5532
|
+
//#endregion
|
|
5533
|
+
//#region src/utils/wait.ts
|
|
5534
|
+
async function wait(time) {
|
|
5535
|
+
return new Promise((res) => setTimeout(res, time));
|
|
5536
|
+
}
|
|
5537
|
+
|
|
5538
|
+
//#endregion
|
|
5539
|
+
//#region src/utils/poll.ts
|
|
5540
|
+
/**
|
|
5541
|
+
* Polls a function at a specified interval.
|
|
5542
|
+
* Inspired by https://github.com/wevm/viem/blob/845994d20275d08ff892018e237a4b599eeefb6a/src/utils/poll.ts
|
|
5543
|
+
*/
|
|
5544
|
+
function poll(fn, { interval }) {
|
|
5545
|
+
let active = true;
|
|
5546
|
+
const unwatch = () => active = false;
|
|
5547
|
+
const watch = async () => {
|
|
5548
|
+
while (active) {
|
|
5549
|
+
const delay = await interval();
|
|
5550
|
+
if (!active) break;
|
|
5551
|
+
await wait(delay);
|
|
5552
|
+
if (!active) break;
|
|
5553
|
+
await fn({ unpoll: unwatch });
|
|
5554
|
+
}
|
|
5555
|
+
};
|
|
5556
|
+
watch();
|
|
5557
|
+
return unwatch;
|
|
5558
|
+
}
|
|
5559
|
+
|
|
5560
|
+
//#endregion
|
|
5561
|
+
//#region src/utils/time.ts
|
|
5562
|
+
var time_exports = /* @__PURE__ */ __exportAll({
|
|
5563
|
+
max: () => max,
|
|
5564
|
+
now: () => now
|
|
5565
|
+
});
|
|
5566
|
+
function now() {
|
|
5567
|
+
return Math.floor(Date.now() / 1e3);
|
|
5568
|
+
}
|
|
5569
|
+
function max() {
|
|
5570
|
+
return 0x77e772392b600000;
|
|
5571
|
+
}
|
|
5572
|
+
|
|
5573
|
+
//#endregion
|
|
5574
|
+
//#region src/utils/trim.ts
|
|
5575
|
+
/**
|
|
5576
|
+
* Keep the last `keep` entries from an array.
|
|
5577
|
+
* @param array - Source array.
|
|
5578
|
+
* @param keep - Number of entries to keep.
|
|
5579
|
+
* @returns Trimmed copy.
|
|
5580
|
+
*/
|
|
5581
|
+
const trimTail = (array, keep) => {
|
|
5582
|
+
if (!Number.isInteger(keep) || keep < 0) throw new Error(`trimTail: expected non-negative integer keep, got ${keep}`);
|
|
5583
|
+
if (array.length <= keep) return array.slice();
|
|
5584
|
+
return array.slice(array.length - keep);
|
|
5174
5585
|
};
|
|
5175
5586
|
|
|
5587
|
+
//#endregion
|
|
5588
|
+
//#region src/utils/index.ts
|
|
5589
|
+
var utils_exports = /* @__PURE__ */ __exportAll({
|
|
5590
|
+
BaseError: () => BaseError,
|
|
5591
|
+
Group: () => Group_exports,
|
|
5592
|
+
Random: () => Random_exports,
|
|
5593
|
+
ReorgError: () => ReorgError,
|
|
5594
|
+
Time: () => time_exports,
|
|
5595
|
+
atMostOneNonZero: () => atMostOneNonZero,
|
|
5596
|
+
batch: () => batch$1,
|
|
5597
|
+
batchMulticall: () => batchMulticall,
|
|
5598
|
+
fromSnakeCase: () => fromSnakeCase$3,
|
|
5599
|
+
lazy: () => lazy,
|
|
5600
|
+
mapWithConcurrency: () => mapWithConcurrency,
|
|
5601
|
+
max: () => max$1,
|
|
5602
|
+
min: () => min,
|
|
5603
|
+
poll: () => poll,
|
|
5604
|
+
retry: () => retry,
|
|
5605
|
+
stringifyBigint: () => stringifyBigint,
|
|
5606
|
+
toSnakeCase: () => toSnakeCase$1,
|
|
5607
|
+
trimTail: () => trimTail,
|
|
5608
|
+
wait: () => wait
|
|
5609
|
+
});
|
|
5610
|
+
|
|
5611
|
+
//#endregion
|
|
5612
|
+
//#region src/database/drizzle/VERSION.ts
|
|
5613
|
+
const VERSION = "router_v1.15";
|
|
5614
|
+
|
|
5615
|
+
//#endregion
|
|
5616
|
+
//#region src/database/drizzle/schema.ts
|
|
5617
|
+
const s = pgSchema(VERSION);
|
|
5618
|
+
var EnumTableName = /* @__PURE__ */ function(EnumTableName) {
|
|
5619
|
+
EnumTableName["OBLIGATIONS"] = "obligations";
|
|
5620
|
+
EnumTableName["OBLIGATION_ID_KEYS"] = "obligation_id_keys";
|
|
5621
|
+
EnumTableName["GROUPS"] = "groups";
|
|
5622
|
+
EnumTableName["CONSUMED_EVENTS"] = "consumed_events";
|
|
5623
|
+
EnumTableName["OBLIGATION_COLLATERALS_V2"] = "obligation_collaterals_v2";
|
|
5624
|
+
EnumTableName["ORACLES"] = "oracles";
|
|
5625
|
+
EnumTableName["OFFERS"] = "offers";
|
|
5626
|
+
EnumTableName["OFFERS_CALLBACKS"] = "offers_callbacks";
|
|
5627
|
+
EnumTableName["CALLBACKS"] = "callbacks";
|
|
5628
|
+
EnumTableName["POSITIONS"] = "positions";
|
|
5629
|
+
EnumTableName["TRANSFERS"] = "transfers";
|
|
5630
|
+
EnumTableName["VALIDATIONS"] = "validations";
|
|
5631
|
+
EnumTableName["COLLECTORS"] = "collectors";
|
|
5632
|
+
EnumTableName["CHAINS"] = "chains";
|
|
5633
|
+
EnumTableName["PENDING_LINKS"] = "pending_links";
|
|
5634
|
+
EnumTableName["LOTS"] = "lots";
|
|
5635
|
+
EnumTableName["LOTS_POSITIONS"] = "lots_positions";
|
|
5636
|
+
EnumTableName["OFFSETS"] = "offsets";
|
|
5637
|
+
EnumTableName["TREES"] = "trees";
|
|
5638
|
+
EnumTableName["MERKLE_PATHS"] = "merkle_paths";
|
|
5639
|
+
return EnumTableName;
|
|
5640
|
+
}(EnumTableName || {});
|
|
5641
|
+
const TABLE_NAMES = Object.values(EnumTableName);
|
|
5642
|
+
const VERSIONED_TABLE_NAMES = TABLE_NAMES.map((table) => `"${VERSION}"."${table}"`);
|
|
5643
|
+
const obligations = s.table(EnumTableName.OBLIGATIONS, {
|
|
5644
|
+
obligationKey: varchar("obligation_key", { length: 66 }).primaryKey(),
|
|
5645
|
+
loanToken: varchar("loan_token", { length: 42 }).notNull(),
|
|
5646
|
+
maturity: integer("maturity").notNull(),
|
|
5647
|
+
rcfThreshold: numeric("rcf_threshold", {
|
|
5648
|
+
precision: 78,
|
|
5649
|
+
scale: 0
|
|
5650
|
+
}).notNull()
|
|
5651
|
+
});
|
|
5652
|
+
const obligationIdKeys = s.table(EnumTableName.OBLIGATION_ID_KEYS, {
|
|
5653
|
+
obligationId: varchar("obligation_id", { length: 66 }).primaryKey(),
|
|
5654
|
+
obligationKey: varchar("obligation_key", { length: 66 }).notNull().references(() => obligations.obligationKey, { onDelete: "cascade" }),
|
|
5655
|
+
chainId: bigint("chain_id", { mode: "number" }).$type().notNull(),
|
|
5656
|
+
morphoV2: varchar("morpho_v2", { length: 42 }).notNull()
|
|
5657
|
+
}, (table) => [index("obligation_id_keys_obligation_key_idx").on(table.obligationKey), index("obligation_id_keys_chain_id_idx").on(table.chainId)]);
|
|
5658
|
+
const groups = s.table(EnumTableName.GROUPS, {
|
|
5659
|
+
chainId: bigint("chain_id", { mode: "number" }).$type().notNull(),
|
|
5660
|
+
maker: varchar("maker", { length: 42 }).notNull(),
|
|
5661
|
+
group: varchar("group", { length: 66 }).notNull(),
|
|
5662
|
+
consumed: numeric("consumed", {
|
|
5663
|
+
precision: 78,
|
|
5664
|
+
scale: 0
|
|
5665
|
+
}).notNull(),
|
|
5666
|
+
blockNumber: bigint("block_number", { mode: "number" }).notNull(),
|
|
5667
|
+
updatedAt: timestamp("updated_at").defaultNow().notNull()
|
|
5668
|
+
}, (table) => [primaryKey({
|
|
5669
|
+
columns: [
|
|
5670
|
+
table.chainId,
|
|
5671
|
+
table.maker,
|
|
5672
|
+
table.group
|
|
5673
|
+
],
|
|
5674
|
+
name: "groups_pk"
|
|
5675
|
+
})]);
|
|
5676
|
+
const consumedEvents = s.table(EnumTableName.CONSUMED_EVENTS, {
|
|
5677
|
+
eventId: varchar("event_id", { length: 128 }).primaryKey(),
|
|
5678
|
+
chainId: bigint("chain_id", { mode: "number" }).$type().notNull(),
|
|
5679
|
+
maker: varchar("maker", { length: 42 }).notNull(),
|
|
5680
|
+
group: varchar("group", { length: 66 }).notNull(),
|
|
5681
|
+
amount: numeric("amount", {
|
|
5682
|
+
precision: 78,
|
|
5683
|
+
scale: 0
|
|
5684
|
+
}).notNull(),
|
|
5685
|
+
blockNumber: bigint("block_number", { mode: "number" }).notNull(),
|
|
5686
|
+
createdAt: timestamp("created_at").defaultNow().notNull()
|
|
5687
|
+
}, (t) => [
|
|
5688
|
+
foreignKey({
|
|
5689
|
+
columns: [
|
|
5690
|
+
t.chainId,
|
|
5691
|
+
t.maker,
|
|
5692
|
+
t.group
|
|
5693
|
+
],
|
|
5694
|
+
foreignColumns: [
|
|
5695
|
+
groups.chainId,
|
|
5696
|
+
groups.maker,
|
|
5697
|
+
groups.group
|
|
5698
|
+
],
|
|
5699
|
+
name: "consumed_events_groups_fk"
|
|
5700
|
+
}).onDelete("cascade"),
|
|
5701
|
+
index("consumed_events_group_idx").on(t.chainId, t.maker, t.group),
|
|
5702
|
+
index("consumed_events_block_number_idx").on(t.blockNumber)
|
|
5703
|
+
]);
|
|
5704
|
+
const obligationCollateralsV2 = s.table(EnumTableName.OBLIGATION_COLLATERALS_V2, {
|
|
5705
|
+
obligationKey: varchar("obligation_key", { length: 66 }).notNull().references(() => obligations.obligationKey, { onDelete: "cascade" }),
|
|
5706
|
+
asset: varchar("asset", { length: 42 }).notNull(),
|
|
5707
|
+
oracleAddress: varchar("oracle_address", { length: 42 }).notNull(),
|
|
5708
|
+
lltv: bigint("lltv", { mode: "bigint" }).notNull(),
|
|
5709
|
+
maxLif: bigint("max_lif", { mode: "bigint" }).notNull(),
|
|
5710
|
+
collateralIndex: integer("collateral_index").notNull(),
|
|
5711
|
+
updatedAt: timestamp("updated_at").defaultNow().notNull()
|
|
5712
|
+
}, (table) => [primaryKey({
|
|
5713
|
+
columns: [table.obligationKey, table.asset],
|
|
5714
|
+
name: "obligation_collaterals_v2_pk"
|
|
5715
|
+
})]);
|
|
5716
|
+
const oracles = s.table(EnumTableName.ORACLES, {
|
|
5717
|
+
chainId: bigint("chain_id", { mode: "number" }).$type().notNull(),
|
|
5718
|
+
address: varchar("address", { length: 42 }).notNull(),
|
|
5719
|
+
price: numeric("price", {
|
|
5720
|
+
precision: 78,
|
|
5721
|
+
scale: 0
|
|
5722
|
+
}),
|
|
5723
|
+
blockNumber: bigint("block_number", { mode: "number" }).notNull(),
|
|
5724
|
+
updatedAt: timestamp("updated_at").defaultNow().notNull()
|
|
5725
|
+
}, (table) => [primaryKey({
|
|
5726
|
+
columns: [table.chainId, table.address],
|
|
5727
|
+
name: "oracles_pk"
|
|
5728
|
+
})]);
|
|
5729
|
+
const offers = s.table(EnumTableName.OFFERS, {
|
|
5730
|
+
hash: varchar("hash", { length: 66 }).notNull(),
|
|
5731
|
+
obligationId: varchar("obligation_id", { length: 66 }).notNull().references(() => obligationIdKeys.obligationId, { onDelete: "cascade" }),
|
|
5732
|
+
obligationUnits: numeric("obligation_units", {
|
|
5733
|
+
precision: 78,
|
|
5734
|
+
scale: 0
|
|
5735
|
+
}).notNull().default("0"),
|
|
5736
|
+
tick: integer("tick").notNull(),
|
|
5737
|
+
maturity: integer("maturity").notNull(),
|
|
5738
|
+
expiry: integer("expiry").notNull(),
|
|
5739
|
+
start: integer("start").notNull(),
|
|
5740
|
+
groupChainId: bigint("group_chain_id", { mode: "number" }).$type().notNull(),
|
|
5741
|
+
groupMaker: varchar("group_maker", { length: 42 }).notNull(),
|
|
5742
|
+
group: varchar("group_group", { length: 66 }).notNull(),
|
|
5743
|
+
session: varchar("session", { length: 66 }).notNull(),
|
|
5744
|
+
buy: boolean("buy").notNull(),
|
|
5745
|
+
callbackAddress: varchar("callback_address", { length: 42 }).notNull(),
|
|
5746
|
+
callbackData: text("callback_data").notNull(),
|
|
5747
|
+
receiverIfMakerIsSeller: varchar("receiver_if_maker_is_seller", { length: 42 }),
|
|
5748
|
+
exitOnly: boolean("exit_only").notNull().default(false),
|
|
5749
|
+
blockNumber: bigint("block_number", { mode: "number" }).notNull(),
|
|
5750
|
+
updatedAt: timestamp("updated_at").defaultNow().notNull()
|
|
5751
|
+
}, (table) => [
|
|
5752
|
+
primaryKey({
|
|
5753
|
+
columns: [table.hash, table.obligationId],
|
|
5754
|
+
name: "offers_pk"
|
|
5755
|
+
}),
|
|
5756
|
+
foreignKey({
|
|
5757
|
+
columns: [
|
|
5758
|
+
table.groupChainId,
|
|
5759
|
+
table.groupMaker,
|
|
5760
|
+
table.group
|
|
5761
|
+
],
|
|
5762
|
+
foreignColumns: [
|
|
5763
|
+
groups.chainId,
|
|
5764
|
+
groups.maker,
|
|
5765
|
+
groups.group
|
|
5766
|
+
],
|
|
5767
|
+
name: "offers_groups_fk"
|
|
5768
|
+
}).onDelete("cascade"),
|
|
5769
|
+
index("offers_group_and_hash_idx").on(table.groupChainId, table.groupMaker, table.group, table.hash),
|
|
5770
|
+
index("offers_obligation_side_tick_idx").on(table.obligationId, table.buy, table.tick),
|
|
5771
|
+
index("offers_obligation_active_tick_idx").on(table.obligationId, table.buy, table.expiry, table.maturity, table.start, table.tick),
|
|
5772
|
+
index("offers_group_maker_idx").on(table.groupMaker, table.hash, table.obligationId),
|
|
5773
|
+
index("offers_group_winner_expr_idx").on(table.groupChainId, table.groupMaker, table.group, table.obligationId, table.buy, sql`(CASE WHEN "buy" THEN -"tick" ELSE "tick" END)`, table.blockNumber, sql`"obligation_units" DESC`, table.hash),
|
|
5774
|
+
index("offers_book_winners_covering_idx").on(table.obligationId, table.buy, table.groupChainId, table.groupMaker, table.group, sql`(CASE WHEN "buy" THEN -"tick" ELSE "tick" END)`, table.blockNumber, sql`"obligation_units" DESC`, table.hash)
|
|
5775
|
+
]);
|
|
5776
|
+
const offersCallbacks = s.table(EnumTableName.OFFERS_CALLBACKS, {
|
|
5777
|
+
offerHash: varchar("offer_hash", { length: 66 }).notNull(),
|
|
5778
|
+
obligationId: varchar("obligation_id", { length: 66 }).notNull(),
|
|
5779
|
+
callbackId: varchar("callback_id", { length: 66 })
|
|
5780
|
+
}, (table) => [foreignKey({
|
|
5781
|
+
columns: [table.offerHash, table.obligationId],
|
|
5782
|
+
foreignColumns: [offers.hash, offers.obligationId],
|
|
5783
|
+
name: "offers_callbacks_offer_fk"
|
|
5784
|
+
}).onDelete("cascade"), primaryKey({
|
|
5785
|
+
columns: [
|
|
5786
|
+
table.offerHash,
|
|
5787
|
+
table.obligationId,
|
|
5788
|
+
table.callbackId
|
|
5789
|
+
],
|
|
5790
|
+
name: "offers_callbacks_pk"
|
|
5791
|
+
})]);
|
|
5792
|
+
const CallbackTypes = s.enum("callback_type", Object.values(CallbackType));
|
|
5793
|
+
const callbacks = s.table(EnumTableName.CALLBACKS, {
|
|
5794
|
+
id: varchar("id", { length: 66 }).primaryKey(),
|
|
5795
|
+
positionChainId: bigint("position_chain_id", { mode: "number" }).$type().notNull(),
|
|
5796
|
+
positionContract: varchar("position_contract", { length: 66 }).notNull(),
|
|
5797
|
+
positionUser: varchar("position_user", { length: 42 }).notNull(),
|
|
5798
|
+
positionTypeId: integer("position_type_id").notNull().references(() => positionTypes.id, { onDelete: "no action" }),
|
|
5799
|
+
type: CallbackTypes("type").notNull()
|
|
5800
|
+
});
|
|
5801
|
+
const lotsPositions = s.table(EnumTableName.LOTS_POSITIONS, {
|
|
5802
|
+
chainId: bigint("chain_id", { mode: "number" }).$type().notNull(),
|
|
5803
|
+
contract: varchar("contract", { length: 66 }).notNull(),
|
|
5804
|
+
user: varchar("user", { length: 42 }).notNull(),
|
|
5805
|
+
positionTypeId: integer("position_type_id").notNull().references(() => positionTypes.id, { onDelete: "no action" })
|
|
5806
|
+
}, (table) => [primaryKey({
|
|
5807
|
+
columns: [
|
|
5808
|
+
table.chainId,
|
|
5809
|
+
table.contract,
|
|
5810
|
+
table.user
|
|
5811
|
+
],
|
|
5812
|
+
name: "lots_positions_pk"
|
|
5813
|
+
})]);
|
|
5814
|
+
const lots = s.table(EnumTableName.LOTS, {
|
|
5815
|
+
chainId: bigint("chain_id", { mode: "number" }).$type().notNull(),
|
|
5816
|
+
user: varchar("user", { length: 42 }).notNull(),
|
|
5817
|
+
contract: varchar("contract", { length: 66 }).notNull(),
|
|
5818
|
+
group: varchar("group", { length: 66 }).notNull(),
|
|
5819
|
+
obligationId: varchar("obligation_id", { length: 66 }).notNull(),
|
|
5820
|
+
lower: numeric("lower", {
|
|
5821
|
+
precision: 78,
|
|
5822
|
+
scale: 0
|
|
5823
|
+
}).notNull(),
|
|
5824
|
+
upper: numeric("upper", {
|
|
5825
|
+
precision: 78,
|
|
5826
|
+
scale: 0
|
|
5827
|
+
}).notNull()
|
|
5828
|
+
}, (table) => [
|
|
5829
|
+
primaryKey({
|
|
5830
|
+
columns: [
|
|
5831
|
+
table.chainId,
|
|
5832
|
+
table.user,
|
|
5833
|
+
table.contract,
|
|
5834
|
+
table.group,
|
|
5835
|
+
table.obligationId
|
|
5836
|
+
],
|
|
5837
|
+
name: "lots_pk"
|
|
5838
|
+
}),
|
|
5839
|
+
foreignKey({
|
|
5840
|
+
columns: [
|
|
5841
|
+
table.chainId,
|
|
5842
|
+
table.contract,
|
|
5843
|
+
table.user
|
|
5844
|
+
],
|
|
5845
|
+
foreignColumns: [
|
|
5846
|
+
lotsPositions.chainId,
|
|
5847
|
+
lotsPositions.contract,
|
|
5848
|
+
lotsPositions.user
|
|
5849
|
+
],
|
|
5850
|
+
name: "lots_lots_positions_fk"
|
|
5851
|
+
}).onDelete("cascade"),
|
|
5852
|
+
foreignKey({
|
|
5853
|
+
columns: [
|
|
5854
|
+
table.chainId,
|
|
5855
|
+
table.user,
|
|
5856
|
+
table.group
|
|
5857
|
+
],
|
|
5858
|
+
foreignColumns: [
|
|
5859
|
+
groups.chainId,
|
|
5860
|
+
groups.maker,
|
|
5861
|
+
groups.group
|
|
5862
|
+
],
|
|
5863
|
+
name: "lots_groups_fk"
|
|
5864
|
+
}).onDelete("cascade"),
|
|
5865
|
+
index("lots_position_group_obligation_idx").on(table.chainId, table.user, table.group, table.obligationId)
|
|
5866
|
+
]);
|
|
5867
|
+
const offsets = s.table(EnumTableName.OFFSETS, {
|
|
5868
|
+
chainId: bigint("chain_id", { mode: "number" }).$type().notNull(),
|
|
5869
|
+
user: varchar("user", { length: 42 }).notNull(),
|
|
5870
|
+
contract: varchar("contract", { length: 66 }).notNull(),
|
|
5871
|
+
group: varchar("group", { length: 66 }).notNull(),
|
|
5872
|
+
obligationId: varchar("obligation_id", { length: 66 }).notNull(),
|
|
5873
|
+
value: numeric("value", {
|
|
5874
|
+
precision: 78,
|
|
5875
|
+
scale: 0
|
|
5876
|
+
}).notNull()
|
|
5877
|
+
}, (table) => [
|
|
5878
|
+
primaryKey({
|
|
5879
|
+
columns: [
|
|
5880
|
+
table.chainId,
|
|
5881
|
+
table.user,
|
|
5882
|
+
table.contract,
|
|
5883
|
+
table.group,
|
|
5884
|
+
table.obligationId
|
|
5885
|
+
],
|
|
5886
|
+
name: "offsets_pk"
|
|
5887
|
+
}),
|
|
5888
|
+
foreignKey({
|
|
5889
|
+
columns: [
|
|
5890
|
+
table.chainId,
|
|
5891
|
+
table.contract,
|
|
5892
|
+
table.user
|
|
5893
|
+
],
|
|
5894
|
+
foreignColumns: [
|
|
5895
|
+
lotsPositions.chainId,
|
|
5896
|
+
lotsPositions.contract,
|
|
5897
|
+
lotsPositions.user
|
|
5898
|
+
],
|
|
5899
|
+
name: "offsets_lots_positions_fk"
|
|
5900
|
+
}).onDelete("cascade"),
|
|
5901
|
+
index("offsets_position_obligation_idx").on(table.chainId, table.contract, table.user, table.obligationId)
|
|
5902
|
+
]);
|
|
5903
|
+
const PositionTypes = s.enum("position_type", Object.values(Type));
|
|
5904
|
+
const positionTypes = s.table("position_types", {
|
|
5905
|
+
id: serial("id").primaryKey(),
|
|
5906
|
+
type: PositionTypes("type").notNull()
|
|
5907
|
+
});
|
|
5908
|
+
const positions = s.table(EnumTableName.POSITIONS, {
|
|
5909
|
+
chainId: bigint("chain_id", { mode: "number" }).$type().notNull(),
|
|
5910
|
+
contract: varchar("contract", { length: 66 }).notNull(),
|
|
5911
|
+
user: varchar("user", { length: 42 }).notNull(),
|
|
5912
|
+
positionTypeId: integer("position_type_id").notNull().references(() => positionTypes.id, { onDelete: "no action" }),
|
|
5913
|
+
balance: numeric("balance", {
|
|
5914
|
+
precision: 78,
|
|
5915
|
+
scale: 0
|
|
5916
|
+
}),
|
|
5917
|
+
asset: varchar("asset", { length: 42 }).notNull(),
|
|
5918
|
+
blockNumber: bigint("block_number", { mode: "number" }).notNull(),
|
|
5919
|
+
updatedAt: timestamp("updated_at").defaultNow().notNull()
|
|
5920
|
+
}, (table) => [primaryKey({
|
|
5921
|
+
columns: [
|
|
5922
|
+
table.chainId,
|
|
5923
|
+
table.contract,
|
|
5924
|
+
table.user,
|
|
5925
|
+
table.positionTypeId,
|
|
5926
|
+
table.asset
|
|
5927
|
+
],
|
|
5928
|
+
name: "positions_pk"
|
|
5929
|
+
})]);
|
|
5930
|
+
const transfers = s.table(EnumTableName.TRANSFERS, {
|
|
5931
|
+
eventId: varchar("event_id", { length: 128 }).primaryKey(),
|
|
5932
|
+
chainId: bigint("chain_id", { mode: "number" }).$type().notNull(),
|
|
5933
|
+
contract: varchar("contract", { length: 66 }).notNull(),
|
|
5934
|
+
from: varchar("from", { length: 42 }).notNull(),
|
|
5935
|
+
to: varchar("to", { length: 42 }).notNull(),
|
|
5936
|
+
value: numeric("value", {
|
|
5937
|
+
precision: 78,
|
|
5938
|
+
scale: 0
|
|
5939
|
+
}).notNull(),
|
|
5940
|
+
positionTypeId: integer("position_type_id").notNull().references(() => positionTypes.id, { onDelete: "no action" }),
|
|
5941
|
+
asset: varchar("asset", { length: 42 }).notNull(),
|
|
5942
|
+
blockNumber: bigint("block_number", { mode: "number" }).notNull(),
|
|
5943
|
+
createdAt: timestamp("created_at").defaultNow().notNull()
|
|
5944
|
+
}, (table) => [
|
|
5945
|
+
foreignKey({
|
|
5946
|
+
columns: [
|
|
5947
|
+
table.chainId,
|
|
5948
|
+
table.contract,
|
|
5949
|
+
table.from,
|
|
5950
|
+
table.positionTypeId,
|
|
5951
|
+
table.asset
|
|
5952
|
+
],
|
|
5953
|
+
foreignColumns: [
|
|
5954
|
+
positions.chainId,
|
|
5955
|
+
positions.contract,
|
|
5956
|
+
positions.user,
|
|
5957
|
+
positions.positionTypeId,
|
|
5958
|
+
positions.asset
|
|
5959
|
+
],
|
|
5960
|
+
name: "transfers_positions_from_fk"
|
|
5961
|
+
}).onDelete("cascade"),
|
|
5962
|
+
foreignKey({
|
|
5963
|
+
columns: [
|
|
5964
|
+
table.chainId,
|
|
5965
|
+
table.contract,
|
|
5966
|
+
table.to,
|
|
5967
|
+
table.positionTypeId,
|
|
5968
|
+
table.asset
|
|
5969
|
+
],
|
|
5970
|
+
foreignColumns: [
|
|
5971
|
+
positions.chainId,
|
|
5972
|
+
positions.contract,
|
|
5973
|
+
positions.user,
|
|
5974
|
+
positions.positionTypeId,
|
|
5975
|
+
positions.asset
|
|
5976
|
+
],
|
|
5977
|
+
name: "transfers_positions_to_fk"
|
|
5978
|
+
}).onDelete("cascade"),
|
|
5979
|
+
index("transfers_chain_contract_user_idx").on(table.chainId, table.contract, table.from, table.to, table.blockNumber),
|
|
5980
|
+
index("transfers_chain_type_block_idx").on(table.chainId, table.positionTypeId, table.blockNumber)
|
|
5981
|
+
]);
|
|
5982
|
+
const StatusCode = s.enum("status_code", Object.values(Status));
|
|
5983
|
+
const status = s.table("status", {
|
|
5984
|
+
id: serial("id").primaryKey(),
|
|
5985
|
+
code: StatusCode("code").unique()
|
|
5986
|
+
});
|
|
5987
|
+
const validations = s.table("validations", {
|
|
5988
|
+
offerHash: varchar("offer_hash", { length: 66 }).notNull(),
|
|
5989
|
+
obligationId: varchar("obligation_id", { length: 66 }).notNull(),
|
|
5990
|
+
statusId: integer("status_id").notNull().references(() => status.id, { onDelete: "no action" }),
|
|
5991
|
+
updatedAt: timestamp("updated_at").defaultNow().notNull()
|
|
5992
|
+
}, (table) => [primaryKey({
|
|
5993
|
+
columns: [table.offerHash, table.obligationId],
|
|
5994
|
+
name: "validations_pk"
|
|
5995
|
+
}), foreignKey({
|
|
5996
|
+
columns: [table.offerHash, table.obligationId],
|
|
5997
|
+
foreignColumns: [offers.hash, offers.obligationId],
|
|
5998
|
+
name: "validations_offer_fk"
|
|
5999
|
+
}).onDelete("cascade")]);
|
|
6000
|
+
const collectors = s.table(EnumTableName.COLLECTORS, {
|
|
6001
|
+
chainId: bigint("chain_id", { mode: "number" }).$type().notNull().references(() => chains.chainId, { onDelete: "no action" }),
|
|
6002
|
+
name: text("name").$type().notNull(),
|
|
6003
|
+
blockNumber: bigint("block_number", { mode: "number" }).notNull(),
|
|
6004
|
+
epoch: numeric("epoch", {
|
|
6005
|
+
precision: 78,
|
|
6006
|
+
scale: 0
|
|
6007
|
+
}).default("0").notNull(),
|
|
6008
|
+
updatedAt: timestamp("updated_at").defaultNow().notNull()
|
|
6009
|
+
}, (table) => [uniqueIndex("collectors_chain_name_idx").on(table.chainId, table.name)]);
|
|
6010
|
+
const chains = s.table(EnumTableName.CHAINS, {
|
|
6011
|
+
chainId: bigint("chain_id", { mode: "number" }).$type().notNull(),
|
|
6012
|
+
blockNumber: bigint("block_number", { mode: "number" }).notNull(),
|
|
6013
|
+
epoch: numeric("epoch", {
|
|
6014
|
+
precision: 78,
|
|
6015
|
+
scale: 0
|
|
6016
|
+
}).default("0").notNull(),
|
|
6017
|
+
checkpoints: text("checkpoints").default("[]").notNull(),
|
|
6018
|
+
tipHash: text("tip_hash"),
|
|
6019
|
+
finalizedBlockNumber: bigint("finalized_block_number", { mode: "number" }),
|
|
6020
|
+
finalizedBlockHash: text("finalized_block_hash"),
|
|
6021
|
+
updatedAt: timestamp("updated_at").defaultNow().notNull()
|
|
6022
|
+
}, (table) => [uniqueIndex("chains_chain_id_idx").on(table.chainId)]);
|
|
6023
|
+
const pendingLinks = s.table(EnumTableName.PENDING_LINKS, {
|
|
6024
|
+
key: varchar("key", { length: 191 }).primaryKey(),
|
|
6025
|
+
type: text("type").notNull(),
|
|
6026
|
+
status: text("status").notNull(),
|
|
6027
|
+
chainId: bigint("chain_id", { mode: "number" }).$type().notNull(),
|
|
6028
|
+
eventId: varchar("event_id", { length: 128 }).notNull(),
|
|
6029
|
+
obligationId: varchar("obligation_id", { length: 66 }).notNull(),
|
|
6030
|
+
collateralIndex: integer("collateral_index").notNull(),
|
|
6031
|
+
user: varchar("user", { length: 42 }).notNull(),
|
|
6032
|
+
amount: numeric("amount", {
|
|
6033
|
+
precision: 78,
|
|
6034
|
+
scale: 0
|
|
6035
|
+
}).notNull(),
|
|
6036
|
+
blockNumber: bigint("block_number", { mode: "number" }).notNull(),
|
|
6037
|
+
firstSeenBlock: bigint("first_seen_block", { mode: "number" }).notNull(),
|
|
6038
|
+
lastTriedBlock: bigint("last_tried_block", { mode: "number" }),
|
|
6039
|
+
attempts: integer("attempts").notNull().default(0),
|
|
6040
|
+
ignoredReason: text("ignored_reason"),
|
|
6041
|
+
resolvedAt: timestamp("resolved_at"),
|
|
6042
|
+
updatedAt: timestamp("updated_at").defaultNow().notNull()
|
|
6043
|
+
}, (table) => [index("pending_links_pending_scan_idx").on(table.chainId, table.type, table.status, table.firstSeenBlock), index("pending_links_event_id_idx").on(table.chainId, table.eventId)]);
|
|
6044
|
+
const trees = s.table(EnumTableName.TREES, {
|
|
6045
|
+
root: varchar("root", { length: 66 }).primaryKey(),
|
|
6046
|
+
rootSignature: varchar("root_signature", { length: 132 }).notNull(),
|
|
6047
|
+
createdAt: timestamp("created_at").defaultNow().notNull()
|
|
6048
|
+
});
|
|
6049
|
+
const merklePaths = s.table(EnumTableName.MERKLE_PATHS, {
|
|
6050
|
+
offerHash: varchar("offer_hash", { length: 66 }).notNull(),
|
|
6051
|
+
obligationId: varchar("obligation_id", { length: 66 }).notNull(),
|
|
6052
|
+
treeRoot: varchar("tree_root", { length: 66 }).notNull().references(() => trees.root, { onDelete: "cascade" }),
|
|
6053
|
+
proofNodes: text("proof_nodes").notNull(),
|
|
6054
|
+
createdAt: timestamp("created_at").defaultNow().notNull()
|
|
6055
|
+
}, (table) => [
|
|
6056
|
+
primaryKey({
|
|
6057
|
+
columns: [table.offerHash, table.obligationId],
|
|
6058
|
+
name: "merkle_paths_pk"
|
|
6059
|
+
}),
|
|
6060
|
+
foreignKey({
|
|
6061
|
+
columns: [table.offerHash, table.obligationId],
|
|
6062
|
+
foreignColumns: [offers.hash, offers.obligationId],
|
|
6063
|
+
name: "merkle_paths_offer_fk"
|
|
6064
|
+
}).onDelete("cascade"),
|
|
6065
|
+
index("merkle_paths_tree_root_idx").on(table.treeRoot)
|
|
6066
|
+
]);
|
|
6067
|
+
|
|
6068
|
+
//#endregion
|
|
6069
|
+
//#region src/database/domains/Groups.ts
|
|
6070
|
+
/** Build composite key for a group. */
|
|
6071
|
+
function compositeKey(g) {
|
|
6072
|
+
return `${g.chainId}-${g.maker.toLowerCase()}-${g.group.toLowerCase()}`;
|
|
6073
|
+
}
|
|
6074
|
+
|
|
5176
6075
|
//#endregion
|
|
5177
6076
|
//#region src/gatekeeper/Rules.ts
|
|
5178
6077
|
var Rules_exports = /* @__PURE__ */ __exportAll({
|
|
5179
|
-
|
|
6078
|
+
amountNonZero: () => amountNonZero,
|
|
5180
6079
|
callback: () => callback,
|
|
5181
6080
|
collateralToken: () => collateralToken,
|
|
6081
|
+
groupConsistency: () => groupConsistency,
|
|
6082
|
+
groupImmutability: () => groupImmutability,
|
|
5182
6083
|
loanToken: () => loanToken,
|
|
5183
6084
|
maturity: () => maturity,
|
|
6085
|
+
maxCollaterals: () => maxCollaterals,
|
|
6086
|
+
minDuration: () => minDuration,
|
|
5184
6087
|
oracle: () => oracle,
|
|
5185
6088
|
sameMaker: () => sameMaker
|
|
5186
6089
|
});
|
|
@@ -5243,29 +6146,116 @@ const sameMaker = () => batch("mixed_maker", "Validates that all offers in a bat
|
|
|
5243
6146
|
return issues;
|
|
5244
6147
|
});
|
|
5245
6148
|
/**
|
|
5246
|
-
* A validation rule that
|
|
5247
|
-
*
|
|
5248
|
-
*
|
|
6149
|
+
* A validation rule that checks if the offer duration (expiry - start) meets a minimum threshold.
|
|
6150
|
+
* @param minSeconds - Minimum required duration in seconds.
|
|
6151
|
+
* @returns The issue that was found. If the offer is valid, this will be undefined.
|
|
6152
|
+
*/
|
|
6153
|
+
const minDuration = ({ minSeconds }) => single("min_duration", `Validates that offer duration (expiry - start) is at least ${minSeconds}s`, (offer) => {
|
|
6154
|
+
const duration = offer.expiry - offer.start;
|
|
6155
|
+
if (duration < minSeconds) return { message: `Duration ${duration}s is below minimum ${minSeconds}s` };
|
|
6156
|
+
});
|
|
6157
|
+
/**
|
|
6158
|
+
* A validation rule that checks if an offer exceeds the maximum number of collaterals.
|
|
6159
|
+
* The contract enforces this limit; this rule rejects early to avoid on-chain reverts.
|
|
6160
|
+
* @param max - Maximum allowed collaterals per offer.
|
|
6161
|
+
* @returns The issue that was found. If the offer is valid, this will be undefined.
|
|
6162
|
+
*/
|
|
6163
|
+
const maxCollaterals = ({ max }) => single("max_collaterals", `Validates that an offer has at most ${max} collaterals`, (offer) => {
|
|
6164
|
+
if (offer.collaterals.length > max) return { message: `Offer has ${offer.collaterals.length} collaterals, exceeding the maximum of ${max}` };
|
|
6165
|
+
});
|
|
6166
|
+
/**
|
|
6167
|
+
* A validation rule that checks if the offer's obligationUnits is non-zero.
|
|
6168
|
+
* The contract requires a positive amount; this rule rejects early.
|
|
6169
|
+
* @returns The issue that was found. If the offer is valid, this will be undefined.
|
|
6170
|
+
*/
|
|
6171
|
+
const amountNonZero = () => single("amount_non_zero", "Validates that obligationUnits is non-zero", (offer) => {
|
|
6172
|
+
if (offer.obligationUnits === 0n) return { message: "obligationUnits must be non-zero" };
|
|
6173
|
+
});
|
|
6174
|
+
/**
|
|
6175
|
+
* A batch validation rule that ensures all offers within the same group are consistent.
|
|
6176
|
+
* All offers sharing the same group must have the same loan token, obligationUnits,
|
|
6177
|
+
* and side (buy/sell). The contract tracks consumed per group and requires these to match.
|
|
6178
|
+
*/
|
|
6179
|
+
const groupConsistency = () => batch("group_consistency", "Validates that all offers in a group have the same loan token, obligation amounts, and side", (offers) => {
|
|
6180
|
+
const issues = /* @__PURE__ */ new Map();
|
|
6181
|
+
if (offers.length === 0) return issues;
|
|
6182
|
+
const groupMap = /* @__PURE__ */ new Map();
|
|
6183
|
+
for (let i = 0; i < offers.length; i++) {
|
|
6184
|
+
const key = offers[i].group.toLowerCase();
|
|
6185
|
+
const indices = groupMap.get(key);
|
|
6186
|
+
if (indices) indices.push(i);
|
|
6187
|
+
else groupMap.set(key, [i]);
|
|
6188
|
+
}
|
|
6189
|
+
for (const indices of groupMap.values()) {
|
|
6190
|
+
if (indices.length <= 1) continue;
|
|
6191
|
+
const reference = offers[indices[0]];
|
|
6192
|
+
const refLoanToken = reference.loanToken.toLowerCase();
|
|
6193
|
+
const refUnits = reference.obligationUnits;
|
|
6194
|
+
const refBuy = reference.buy;
|
|
6195
|
+
for (let j = 1; j < indices.length; j++) {
|
|
6196
|
+
const idx = indices[j];
|
|
6197
|
+
const offer = offers[idx];
|
|
6198
|
+
if (offer.loanToken.toLowerCase() !== refLoanToken) issues.set(idx, { message: `All offers in a group must have the same loan token. Expected ${reference.loanToken}, got ${offer.loanToken}` });
|
|
6199
|
+
else if (offer.obligationUnits !== refUnits) issues.set(idx, { message: `All offers in a group must have the same obligationUnits. Expected ${refUnits}, got ${offer.obligationUnits}` });
|
|
6200
|
+
else if (offer.buy !== refBuy) issues.set(idx, { message: `All offers in a group must be on the same side. Expected ${refBuy ? "buy" : "sell"}, got ${offer.buy ? "buy" : "sell"}` });
|
|
6201
|
+
}
|
|
6202
|
+
}
|
|
6203
|
+
return issues;
|
|
6204
|
+
});
|
|
6205
|
+
/**
|
|
6206
|
+
* A batch validation rule that prevents adding offers to groups that already exist in the database.
|
|
6207
|
+
* Groups are immutable after creation — new offers cannot be added to an existing group.
|
|
5249
6208
|
*/
|
|
5250
|
-
const
|
|
5251
|
-
|
|
6209
|
+
const groupImmutability = ({ db, chainId }) => batch("group_immutability", "Validates that offers do not target groups that already exist", async (offers) => {
|
|
6210
|
+
const issues = /* @__PURE__ */ new Map();
|
|
6211
|
+
if (offers.length === 0) return issues;
|
|
6212
|
+
const uniqueGroups = /* @__PURE__ */ new Map();
|
|
6213
|
+
for (const offer of offers) {
|
|
6214
|
+
const key = compositeKey({
|
|
6215
|
+
chainId,
|
|
6216
|
+
maker: offer.maker,
|
|
6217
|
+
group: offer.group
|
|
6218
|
+
});
|
|
6219
|
+
if (!uniqueGroups.has(key)) uniqueGroups.set(key, {
|
|
6220
|
+
chainId,
|
|
6221
|
+
maker: offer.maker,
|
|
6222
|
+
group: offer.group
|
|
6223
|
+
});
|
|
6224
|
+
}
|
|
6225
|
+
const existingKeys = await db.groups.exists(Array.from(uniqueGroups.values()));
|
|
6226
|
+
if (existingKeys.length === 0) return issues;
|
|
6227
|
+
const existingSet = new Set(existingKeys.map((k) => compositeKey(k)));
|
|
6228
|
+
for (let i = 0; i < offers.length; i++) {
|
|
6229
|
+
const offer = offers[i];
|
|
6230
|
+
const key = compositeKey({
|
|
6231
|
+
chainId,
|
|
6232
|
+
maker: offer.maker,
|
|
6233
|
+
group: offer.group
|
|
6234
|
+
});
|
|
6235
|
+
if (existingSet.has(key)) issues.set(i, { message: `Cannot add offers to existing group ${offer.group}` });
|
|
6236
|
+
}
|
|
6237
|
+
return issues;
|
|
5252
6238
|
});
|
|
5253
6239
|
|
|
5254
6240
|
//#endregion
|
|
5255
6241
|
//#region src/gatekeeper/morphoRules.ts
|
|
5256
6242
|
const morphoRules = (parameters) => {
|
|
5257
|
-
const { chains, chainId } = parameters;
|
|
6243
|
+
const { chains, chainId, db } = parameters;
|
|
6244
|
+
const requestChain = chains.find((c) => c.id === chainId);
|
|
6245
|
+
const config = requestChain ? configs[requestChain.name] : void 0;
|
|
5258
6246
|
const assetsByChainId = {};
|
|
5259
6247
|
const collateralAssetsByChainId = {};
|
|
5260
6248
|
const oraclesByChainId = {};
|
|
5261
6249
|
for (const chain of chains) {
|
|
5262
6250
|
assetsByChainId[chain.id] = assets[chain.id.toString()] ?? [];
|
|
5263
6251
|
collateralAssetsByChainId[chain.id] = collateralAssets[chain.id.toString()] ?? [];
|
|
5264
|
-
oraclesByChainId[chain.id] = oracles[chain.id.toString()] ?? [];
|
|
6252
|
+
oraclesByChainId[chain.id] = oracles$1[chain.id.toString()] ?? [];
|
|
5265
6253
|
}
|
|
5266
|
-
|
|
6254
|
+
const rules = [
|
|
5267
6255
|
sameMaker(),
|
|
5268
|
-
|
|
6256
|
+
amountNonZero(),
|
|
6257
|
+
groupConsistency(),
|
|
6258
|
+
...config?.minDuration != null ? [minDuration({ minSeconds: config.minDuration })] : [],
|
|
5269
6259
|
maturity({ maturities: [MaturityType.EndOfWeek, MaturityType.EndOfNextWeek] }),
|
|
5270
6260
|
callback({
|
|
5271
6261
|
callbacks: [Type$1.BuyWithEmptyCallback, Type$1.SellWithEmptyCallback],
|
|
@@ -5275,6 +6265,7 @@ const morphoRules = (parameters) => {
|
|
|
5275
6265
|
assetsByChainId,
|
|
5276
6266
|
chainId
|
|
5277
6267
|
}),
|
|
6268
|
+
maxCollaterals({ max: 128 }),
|
|
5278
6269
|
collateralToken({
|
|
5279
6270
|
collateralAssetsByChainId,
|
|
5280
6271
|
chainId
|
|
@@ -5284,6 +6275,11 @@ const morphoRules = (parameters) => {
|
|
|
5284
6275
|
chainId
|
|
5285
6276
|
})
|
|
5286
6277
|
];
|
|
6278
|
+
if (db) rules.push(groupImmutability({
|
|
6279
|
+
db,
|
|
6280
|
+
chainId
|
|
6281
|
+
}));
|
|
6282
|
+
return rules;
|
|
5287
6283
|
};
|
|
5288
6284
|
|
|
5289
6285
|
//#endregion
|
|
@@ -5409,16 +6405,13 @@ async function* streamOffers(config, parameters) {
|
|
|
5409
6405
|
};
|
|
5410
6406
|
}
|
|
5411
6407
|
var WalletAccountNotSetError = class extends BaseError {
|
|
6408
|
+
name = "Mempool.WalletAccountNotSetError";
|
|
5412
6409
|
constructor() {
|
|
5413
6410
|
super("Wallet account is not set.");
|
|
5414
|
-
_defineProperty(this, "name", "Mempool.WalletAccountNotSetError");
|
|
5415
6411
|
}
|
|
5416
6412
|
};
|
|
5417
6413
|
var ViemClientError = class extends BaseError {
|
|
5418
|
-
|
|
5419
|
-
super(..._args);
|
|
5420
|
-
_defineProperty(this, "name", "Mempool.ViemClientError");
|
|
5421
|
-
}
|
|
6414
|
+
name = "Mempool.ViemClientError";
|
|
5422
6415
|
};
|
|
5423
6416
|
const resolveSignatureDomain = (config, chainId) => {
|
|
5424
6417
|
const chain = config.client.chain;
|
|
@@ -5430,9 +6423,9 @@ const resolveSignatureDomain = (config, chainId) => {
|
|
|
5430
6423
|
};
|
|
5431
6424
|
};
|
|
5432
6425
|
var MissingMorphoAddressError = class extends BaseError {
|
|
6426
|
+
name = "Mempool.MissingMorphoAddressError";
|
|
5433
6427
|
constructor() {
|
|
5434
6428
|
super("Morpho address is required to verify root signatures (zero address is invalid).");
|
|
5435
|
-
_defineProperty(this, "name", "Mempool.MissingMorphoAddressError");
|
|
5436
6429
|
}
|
|
5437
6430
|
};
|
|
5438
6431
|
|
|
@@ -5446,158 +6439,6 @@ function connect(parameters) {
|
|
|
5446
6439
|
return from(parameters);
|
|
5447
6440
|
}
|
|
5448
6441
|
|
|
5449
|
-
//#endregion
|
|
5450
|
-
//#region src/utils/retry.ts
|
|
5451
|
-
const retry = async (fn, attempts = 3, delayMs = 50) => {
|
|
5452
|
-
let lastErr;
|
|
5453
|
-
for (let i = 0; i < attempts; i++) try {
|
|
5454
|
-
return await fn();
|
|
5455
|
-
} catch (err) {
|
|
5456
|
-
lastErr = err;
|
|
5457
|
-
if (i < attempts - 1) await new Promise((r) => setTimeout(r, delayMs));
|
|
5458
|
-
}
|
|
5459
|
-
throw lastErr;
|
|
5460
|
-
};
|
|
5461
|
-
|
|
5462
|
-
//#endregion
|
|
5463
|
-
//#region src/utils/batchMulticall.ts
|
|
5464
|
-
/**
|
|
5465
|
-
* Helper function to execute multicall in batches with retry logic.
|
|
5466
|
-
* Abstracts the common pattern of batching calls, retrying, and collecting results.
|
|
5467
|
-
*
|
|
5468
|
-
* @param parameters - Configuration for batched multicall
|
|
5469
|
-
* @returns Promise resolving to flattened array of results
|
|
5470
|
-
*/
|
|
5471
|
-
async function batchMulticall(parameters) {
|
|
5472
|
-
const { client, calls, batchSize, retryAttempts, retryDelayMs, blockNumber } = parameters;
|
|
5473
|
-
const results = [];
|
|
5474
|
-
for (const callsBatch of batch$1(calls, batchSize)) {
|
|
5475
|
-
const batchResults = await retry(() => multicall(client, {
|
|
5476
|
-
allowFailure: false,
|
|
5477
|
-
contracts: callsBatch,
|
|
5478
|
-
...blockNumber ? { blockNumber } : {}
|
|
5479
|
-
}), retryAttempts, retryDelayMs);
|
|
5480
|
-
results.push(...batchResults);
|
|
5481
|
-
}
|
|
5482
|
-
return results;
|
|
5483
|
-
}
|
|
5484
|
-
|
|
5485
|
-
//#endregion
|
|
5486
|
-
//#region src/utils/Group.ts
|
|
5487
|
-
var Group_exports = /* @__PURE__ */ __exportAll({ fromNumber: () => fromNumber });
|
|
5488
|
-
/**
|
|
5489
|
-
* Creates a bytes32 group identifier from a number.
|
|
5490
|
-
* @param n - A non-negative integer.
|
|
5491
|
-
* @throws {Error} If n is negative or not an integer.
|
|
5492
|
-
*/
|
|
5493
|
-
const fromNumber = (n) => {
|
|
5494
|
-
if (!Number.isInteger(n)) throw new Error(`Group.fromNumber: expected integer, got ${n}`);
|
|
5495
|
-
if (n < 0) throw new Error(`Group.fromNumber: expected non-negative, got ${n}`);
|
|
5496
|
-
return pad(`0x${n.toString(16)}`, { size: 32 });
|
|
5497
|
-
};
|
|
5498
|
-
|
|
5499
|
-
//#endregion
|
|
5500
|
-
//#region src/utils/lazy.ts
|
|
5501
|
-
/**
|
|
5502
|
-
* Transform a polling function into an async generator.
|
|
5503
|
-
* @param fn - The polling function to transform.
|
|
5504
|
-
* @returns An async generator.
|
|
5505
|
-
*/
|
|
5506
|
-
function lazy(pollFn) {
|
|
5507
|
-
return () => (async function* () {
|
|
5508
|
-
let active = true;
|
|
5509
|
-
let resolveNext = null;
|
|
5510
|
-
const queue = [];
|
|
5511
|
-
const wait = () => new Promise((resolve) => {
|
|
5512
|
-
resolveNext = resolve;
|
|
5513
|
-
});
|
|
5514
|
-
const emit = (item) => {
|
|
5515
|
-
queue.push(item);
|
|
5516
|
-
resolveNext?.();
|
|
5517
|
-
resolveNext = null;
|
|
5518
|
-
};
|
|
5519
|
-
let unpoll = null;
|
|
5520
|
-
const stop = () => {
|
|
5521
|
-
active = false;
|
|
5522
|
-
unpoll?.();
|
|
5523
|
-
resolveNext?.();
|
|
5524
|
-
resolveNext = null;
|
|
5525
|
-
};
|
|
5526
|
-
unpoll = pollFn(emit, { stop });
|
|
5527
|
-
try {
|
|
5528
|
-
while (active) {
|
|
5529
|
-
if (queue.length === 0) await wait();
|
|
5530
|
-
while (queue.length > 0 && active) yield queue.shift();
|
|
5531
|
-
}
|
|
5532
|
-
} finally {
|
|
5533
|
-
stop();
|
|
5534
|
-
}
|
|
5535
|
-
})();
|
|
5536
|
-
}
|
|
5537
|
-
|
|
5538
|
-
//#endregion
|
|
5539
|
-
//#region src/utils/wait.ts
|
|
5540
|
-
async function wait(time) {
|
|
5541
|
-
return new Promise((res) => setTimeout(res, time));
|
|
5542
|
-
}
|
|
5543
|
-
|
|
5544
|
-
//#endregion
|
|
5545
|
-
//#region src/utils/poll.ts
|
|
5546
|
-
/**
|
|
5547
|
-
* Polls a function at a specified interval.
|
|
5548
|
-
* Inspired by https://github.com/wevm/viem/blob/845994d20275d08ff892018e237a4b599eeefb6a/src/utils/poll.ts
|
|
5549
|
-
*/
|
|
5550
|
-
function poll(fn, { interval }) {
|
|
5551
|
-
let active = true;
|
|
5552
|
-
const unwatch = () => active = false;
|
|
5553
|
-
const watch = async () => {
|
|
5554
|
-
while (active) {
|
|
5555
|
-
const delay = await interval();
|
|
5556
|
-
if (!active) break;
|
|
5557
|
-
await wait(delay);
|
|
5558
|
-
if (!active) break;
|
|
5559
|
-
await fn({ unpoll: unwatch });
|
|
5560
|
-
}
|
|
5561
|
-
};
|
|
5562
|
-
watch();
|
|
5563
|
-
return unwatch;
|
|
5564
|
-
}
|
|
5565
|
-
|
|
5566
|
-
//#endregion
|
|
5567
|
-
//#region src/utils/time.ts
|
|
5568
|
-
var time_exports = /* @__PURE__ */ __exportAll({
|
|
5569
|
-
max: () => max,
|
|
5570
|
-
now: () => now
|
|
5571
|
-
});
|
|
5572
|
-
function now() {
|
|
5573
|
-
return Math.floor(Date.now() / 1e3);
|
|
5574
|
-
}
|
|
5575
|
-
function max() {
|
|
5576
|
-
return 0x77e772392b600000;
|
|
5577
|
-
}
|
|
5578
|
-
|
|
5579
|
-
//#endregion
|
|
5580
|
-
//#region src/utils/index.ts
|
|
5581
|
-
var utils_exports = /* @__PURE__ */ __exportAll({
|
|
5582
|
-
BaseError: () => BaseError,
|
|
5583
|
-
Group: () => Group_exports,
|
|
5584
|
-
Random: () => Random_exports,
|
|
5585
|
-
ReorgError: () => ReorgError,
|
|
5586
|
-
Time: () => time_exports,
|
|
5587
|
-
atMostOneNonZero: () => atMostOneNonZero,
|
|
5588
|
-
batch: () => batch$1,
|
|
5589
|
-
batchMulticall: () => batchMulticall,
|
|
5590
|
-
fromSnakeCase: () => fromSnakeCase$3,
|
|
5591
|
-
lazy: () => lazy,
|
|
5592
|
-
max: () => max$1,
|
|
5593
|
-
min: () => min,
|
|
5594
|
-
poll: () => poll,
|
|
5595
|
-
retry: () => retry,
|
|
5596
|
-
stringifyBigint: () => stringifyBigint,
|
|
5597
|
-
toSnakeCase: () => toSnakeCase$1,
|
|
5598
|
-
wait: () => wait
|
|
5599
|
-
});
|
|
5600
|
-
|
|
5601
6442
|
//#endregion
|
|
5602
6443
|
export { Abi_exports as Abi, BrandTypeId, Callback_exports as Callback, Chain_exports as Chain, ChainRegistry_exports as ChainRegistry, Collateral_exports as Collateral, ERC4626_exports as ERC4626, Errors_exports as Errors, Format_exports as Format, Gatekeeper_exports as Gatekeeper, Client_exports as GatekeeperClient, Id_exports as Id, LLTV_exports as LLTV, Liquidity_exports as Liquidity, Maturity_exports as Maturity, MempoolClient_exports as Mempool, Obligation_exports as Obligation, Offer_exports as Offer, Oracle_exports as Oracle, Position_exports as Position, Quote_exports as Quote, Schema_exports as RouterApi, Client_exports$1 as RouterClient, Rules_exports as Rules, Tick_exports as Tick, time_exports as Time, TradingFee_exports as TradingFee, Transfer_exports as Transfer, Tree_exports as Tree, utils_exports as Utils, Gate_exports as Validation, morphoRules };
|
|
5603
6444
|
//# sourceMappingURL=index.browser.mjs.map
|