@morpho-dev/router 0.4.2 → 0.6.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 +18 -5
- package/dist/chunk-Bo1DHCg-.mjs +18 -0
- package/dist/cli.js +5927 -4450
- package/dist/drizzle/migrations/0023_remove-block-number-for-collaterals.sql +1 -0
- package/dist/drizzle/migrations/meta/0023_snapshot.json +1436 -0
- package/dist/drizzle/migrations/meta/_journal.json +7 -0
- package/dist/index.browser.d.mts +875 -566
- package/dist/index.browser.d.mts.map +1 -1
- package/dist/index.browser.d.ts +875 -566
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/index.browser.js +1441 -667
- package/dist/index.browser.js.map +1 -1
- package/dist/index.browser.mjs +1421 -662
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.node.d.mts +1149 -807
- package/dist/index.node.d.mts.map +1 -1
- package/dist/index.node.d.ts +1148 -806
- package/dist/index.node.d.ts.map +1 -1
- package/dist/index.node.js +4666 -3264
- package/dist/index.node.js.map +1 -1
- package/dist/index.node.mjs +4540 -3165
- package/dist/index.node.mjs.map +1 -1
- package/docs/integrator.md +7 -1
- package/package.json +6 -6
- package/dist/chunk-jass6xSI.mjs +0 -13
package/dist/index.browser.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { t as
|
|
1
|
+
import { t as __exportAll } from "./chunk-Bo1DHCg-.mjs";
|
|
2
2
|
import { z } from "zod/v4";
|
|
3
|
-
import { bytesToHex, decodeAbiParameters, encodeAbiParameters, getAddress,
|
|
3
|
+
import { bytesToHex, decodeAbiParameters, encodeAbiParameters, getAddress, hashTypedData, hexToBytes, isAddress, isHex, keccak256, maxUint256, numberToHex, pad, parseAbi, publicActions, recoverAddress, zeroAddress } from "viem";
|
|
4
4
|
import { getBlock, getLogs, multicall } from "viem/actions";
|
|
5
5
|
import { anvil, base, mainnet } from "viem/chains";
|
|
6
6
|
import * as z$1 from "zod";
|
|
@@ -12,8 +12,8 @@ import { ApiBody, ApiOperation, ApiParam, ApiProperty, ApiQuery, ApiResponse, Ap
|
|
|
12
12
|
import createOpenApiFetchClient from "openapi-fetch";
|
|
13
13
|
|
|
14
14
|
//#region src/api/Schema/BookResponse.ts
|
|
15
|
-
var BookResponse_exports = /* @__PURE__ */
|
|
16
|
-
function from$
|
|
15
|
+
var BookResponse_exports = /* @__PURE__ */ __exportAll({ from: () => from$15 });
|
|
16
|
+
function from$15(level) {
|
|
17
17
|
return {
|
|
18
18
|
price: level.price.toString(),
|
|
19
19
|
assets: level.assets.toString(),
|
|
@@ -57,14 +57,14 @@ const RouterStatusResponse = z.object({
|
|
|
57
57
|
|
|
58
58
|
//#endregion
|
|
59
59
|
//#region src/api/Schema/ObligationResponse.ts
|
|
60
|
-
var ObligationResponse_exports = /* @__PURE__ */
|
|
60
|
+
var ObligationResponse_exports = /* @__PURE__ */ __exportAll({ from: () => from$14 });
|
|
61
61
|
/**
|
|
62
62
|
* Creates an `ObligationResponse` from a `Obligation`.
|
|
63
63
|
* @constructor
|
|
64
64
|
* @param obligation - {@link Obligation}
|
|
65
65
|
* @returns The created `ObligationResponse`. {@link ObligationResponse}
|
|
66
66
|
*/
|
|
67
|
-
function from$
|
|
67
|
+
function from$14(obligation, quote) {
|
|
68
68
|
return {
|
|
69
69
|
id: quote.obligationId,
|
|
70
70
|
chain_id: obligation.chainId,
|
|
@@ -100,7 +100,7 @@ const MetaMorphoFactory = parseAbi(["event CreateMetaMorpho(address indexed meta
|
|
|
100
100
|
|
|
101
101
|
//#endregion
|
|
102
102
|
//#region src/core/Abi/index.ts
|
|
103
|
-
var Abi_exports = /* @__PURE__ */
|
|
103
|
+
var Abi_exports = /* @__PURE__ */ __exportAll({
|
|
104
104
|
ERC4626: () => ERC4626,
|
|
105
105
|
MetaMorpho: () => MetaMorpho,
|
|
106
106
|
MetaMorphoFactory: () => MetaMorphoFactory,
|
|
@@ -251,41 +251,77 @@ const Morpho = [
|
|
|
251
251
|
|
|
252
252
|
//#endregion
|
|
253
253
|
//#region src/core/Callback.ts
|
|
254
|
-
var Callback_exports = /* @__PURE__ */
|
|
255
|
-
|
|
254
|
+
var Callback_exports = /* @__PURE__ */ __exportAll({
|
|
255
|
+
Type: () => Type$1,
|
|
256
256
|
decode: () => decode$2,
|
|
257
|
+
decodeBuyERC20: () => decodeBuyERC20,
|
|
257
258
|
decodeBuyVaultV1Callback: () => decodeBuyVaultV1Callback,
|
|
258
259
|
decodeSellERC20Callback: () => decodeSellERC20Callback,
|
|
259
260
|
encode: () => encode$2,
|
|
261
|
+
encodeBuyERC20: () => encodeBuyERC20,
|
|
260
262
|
encodeBuyVaultV1Callback: () => encodeBuyVaultV1Callback,
|
|
261
263
|
encodeSellERC20Callback: () => encodeSellERC20Callback,
|
|
262
264
|
isEmptyCallback: () => isEmptyCallback
|
|
263
265
|
});
|
|
264
|
-
let
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
266
|
+
let Type$1 = /* @__PURE__ */ function(Type) {
|
|
267
|
+
Type["BuyWithEmptyCallback"] = "buy_with_empty_callback";
|
|
268
|
+
Type["BuyERC20"] = "buy_erc20";
|
|
269
|
+
Type["BuyVaultV1Callback"] = "buy_vault_v1_callback";
|
|
270
|
+
Type["SellERC20Callback"] = "sell_erc20_callback";
|
|
271
|
+
return Type;
|
|
269
272
|
}({});
|
|
270
273
|
const isEmptyCallback = (offer) => offer.callback.data === "0x";
|
|
271
274
|
function decode$2(type, data) {
|
|
272
275
|
switch (type) {
|
|
273
|
-
case
|
|
274
|
-
case
|
|
276
|
+
case Type$1.BuyERC20: return decodeBuyERC20(data);
|
|
277
|
+
case Type$1.BuyVaultV1Callback: return decodeBuyVaultV1Callback(data);
|
|
278
|
+
case Type$1.SellERC20Callback: return decodeSellERC20Callback(data);
|
|
275
279
|
default: throw new Error("Invalid callback type");
|
|
276
280
|
}
|
|
277
281
|
}
|
|
278
282
|
function encode$2(type, data) {
|
|
279
283
|
switch (type) {
|
|
280
|
-
case
|
|
284
|
+
case Type$1.BuyERC20:
|
|
285
|
+
if (!("tokens" in data)) throw new Error("Invalid callback data");
|
|
286
|
+
return encodeBuyERC20(data);
|
|
287
|
+
case Type$1.BuyVaultV1Callback:
|
|
281
288
|
if (!("vaults" in data)) throw new Error("Invalid callback data");
|
|
282
289
|
return encodeBuyVaultV1Callback(data);
|
|
283
|
-
case
|
|
290
|
+
case Type$1.SellERC20Callback:
|
|
284
291
|
if (!("collaterals" in data)) throw new Error("Invalid callback data");
|
|
285
292
|
return encodeSellERC20Callback(data);
|
|
286
293
|
default: throw new Error("Invalid callback type");
|
|
287
294
|
}
|
|
288
295
|
}
|
|
296
|
+
/**
|
|
297
|
+
* Decodes BuyERC20 callback data into positions.
|
|
298
|
+
* @param data - The ABI-encoded callback data containing token addresses and amounts.
|
|
299
|
+
* @returns Array of positions with contract address and amount.
|
|
300
|
+
* @throws If data is empty, malformed, or arrays have mismatched lengths.
|
|
301
|
+
*/
|
|
302
|
+
function decodeBuyERC20(data) {
|
|
303
|
+
if (!data || data === "0x") throw new Error("Empty callback data");
|
|
304
|
+
let tokens;
|
|
305
|
+
let amounts;
|
|
306
|
+
try {
|
|
307
|
+
[tokens, amounts] = decodeAbiParameters([{ type: "address[]" }, { type: "uint256[]" }], data);
|
|
308
|
+
} catch (_) {
|
|
309
|
+
throw new Error("Invalid BuyERC20 callback data");
|
|
310
|
+
}
|
|
311
|
+
if (tokens.length !== amounts.length) throw new Error("Mismatched array lengths");
|
|
312
|
+
return tokens.map((token, index) => ({
|
|
313
|
+
contract: token,
|
|
314
|
+
amount: amounts[index]
|
|
315
|
+
}));
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Encodes BuyERC20 callback parameters into ABI-encoded data.
|
|
319
|
+
* @param parameters - The tokens and amounts to encode.
|
|
320
|
+
* @returns ABI-encoded hex string.
|
|
321
|
+
*/
|
|
322
|
+
function encodeBuyERC20(parameters) {
|
|
323
|
+
return encodeAbiParameters([{ type: "address[]" }, { type: "uint256[]" }], [parameters.tokens, parameters.amounts]);
|
|
324
|
+
}
|
|
289
325
|
function decodeBuyVaultV1Callback(data) {
|
|
290
326
|
if (!data || data === "0x") throw new Error("Empty callback data");
|
|
291
327
|
try {
|
|
@@ -360,23 +396,23 @@ function atMostOneNonZero(...values) {
|
|
|
360
396
|
* // [5]
|
|
361
397
|
* ```
|
|
362
398
|
*/
|
|
363
|
-
function* batch(array, batchSize) {
|
|
399
|
+
function* batch$1(array, batchSize) {
|
|
364
400
|
for (let i = 0; i < array.length; i += batchSize) yield array.slice(i, i + batchSize);
|
|
365
401
|
}
|
|
366
402
|
|
|
367
403
|
//#endregion
|
|
368
|
-
//#region \0@oxc-project+runtime@0.
|
|
404
|
+
//#region \0@oxc-project+runtime@0.110.0/helpers/typeof.js
|
|
369
405
|
function _typeof(o) {
|
|
370
406
|
"@babel/helpers - typeof";
|
|
371
|
-
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o
|
|
372
|
-
return typeof o
|
|
373
|
-
} : function(o
|
|
374
|
-
return o
|
|
407
|
+
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
|
|
408
|
+
return typeof o;
|
|
409
|
+
} : function(o) {
|
|
410
|
+
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
|
|
375
411
|
}, _typeof(o);
|
|
376
412
|
}
|
|
377
413
|
|
|
378
414
|
//#endregion
|
|
379
|
-
//#region \0@oxc-project+runtime@0.
|
|
415
|
+
//#region \0@oxc-project+runtime@0.110.0/helpers/toPrimitive.js
|
|
380
416
|
function toPrimitive(t, r) {
|
|
381
417
|
if ("object" != _typeof(t) || !t) return t;
|
|
382
418
|
var e = t[Symbol.toPrimitive];
|
|
@@ -389,14 +425,14 @@ function toPrimitive(t, r) {
|
|
|
389
425
|
}
|
|
390
426
|
|
|
391
427
|
//#endregion
|
|
392
|
-
//#region \0@oxc-project+runtime@0.
|
|
428
|
+
//#region \0@oxc-project+runtime@0.110.0/helpers/toPropertyKey.js
|
|
393
429
|
function toPropertyKey(t) {
|
|
394
430
|
var i = toPrimitive(t, "string");
|
|
395
431
|
return "symbol" == _typeof(i) ? i : i + "";
|
|
396
432
|
}
|
|
397
433
|
|
|
398
434
|
//#endregion
|
|
399
|
-
//#region \0@oxc-project+runtime@0.
|
|
435
|
+
//#region \0@oxc-project+runtime@0.110.0/helpers/defineProperty.js
|
|
400
436
|
function _defineProperty(e, r, t) {
|
|
401
437
|
return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
|
402
438
|
value: t,
|
|
@@ -408,7 +444,7 @@ function _defineProperty(e, r, t) {
|
|
|
408
444
|
|
|
409
445
|
//#endregion
|
|
410
446
|
//#region src/utils/Errors.ts
|
|
411
|
-
var Errors_exports = /* @__PURE__ */
|
|
447
|
+
var Errors_exports = /* @__PURE__ */ __exportAll({
|
|
412
448
|
BaseError: () => BaseError,
|
|
413
449
|
ReorgError: () => ReorgError
|
|
414
450
|
});
|
|
@@ -465,7 +501,7 @@ var ReorgError = class extends BaseError {
|
|
|
465
501
|
|
|
466
502
|
//#endregion
|
|
467
503
|
//#region src/core/Chain.ts
|
|
468
|
-
var Chain_exports = /* @__PURE__ */
|
|
504
|
+
var Chain_exports = /* @__PURE__ */ __exportAll({
|
|
469
505
|
ChainId: () => ChainId,
|
|
470
506
|
InvalidBatchSizeError: () => InvalidBatchSizeError,
|
|
471
507
|
InvalidBlockRangeError: () => InvalidBlockRangeError,
|
|
@@ -527,7 +563,8 @@ const chains$1 = {
|
|
|
527
563
|
address: "0x1897A8997241C1cD4bD0698647e4EB7213535c24",
|
|
528
564
|
blockCreated: 21439510
|
|
529
565
|
}
|
|
530
|
-
} }
|
|
566
|
+
} },
|
|
567
|
+
callbacks: []
|
|
531
568
|
}
|
|
532
569
|
},
|
|
533
570
|
base: {
|
|
@@ -556,7 +593,8 @@ const chains$1 = {
|
|
|
556
593
|
address: "0xFf62A7c278C62eD665133147129245053Bbf5918",
|
|
557
594
|
blockCreated: 23928808
|
|
558
595
|
}
|
|
559
|
-
} }
|
|
596
|
+
} },
|
|
597
|
+
callbacks: []
|
|
560
598
|
}
|
|
561
599
|
},
|
|
562
600
|
"ethereum-virtual-testnet": {
|
|
@@ -585,7 +623,8 @@ const chains$1 = {
|
|
|
585
623
|
address: "0x1897A8997241C1cD4bD0698647e4EB7213535c24",
|
|
586
624
|
blockCreated: 21439510
|
|
587
625
|
}
|
|
588
|
-
} }
|
|
626
|
+
} },
|
|
627
|
+
callbacks: []
|
|
589
628
|
}
|
|
590
629
|
},
|
|
591
630
|
anvil: {
|
|
@@ -614,7 +653,8 @@ const chains$1 = {
|
|
|
614
653
|
address: "0x0000000000000000000000000000000000000000",
|
|
615
654
|
blockCreated: 0
|
|
616
655
|
}
|
|
617
|
-
} }
|
|
656
|
+
} },
|
|
657
|
+
callbacks: []
|
|
618
658
|
}
|
|
619
659
|
}
|
|
620
660
|
};
|
|
@@ -659,7 +699,7 @@ async function* streamLogs(parameters) {
|
|
|
659
699
|
if (a.transactionIndex !== b.transactionIndex) return order === "asc" ? a.transactionIndex - b.transactionIndex : b.transactionIndex - a.transactionIndex;
|
|
660
700
|
return order === "asc" ? a.logIndex - b.logIndex : b.logIndex - a.logIndex;
|
|
661
701
|
});
|
|
662
|
-
for (const logBatch of batch(logs, maxBatchSize)) yield {
|
|
702
|
+
for (const logBatch of batch$1(logs, maxBatchSize)) yield {
|
|
663
703
|
logs: logBatch,
|
|
664
704
|
blockNumber: logBatch.length === maxBatchSize ? Number(logBatch[logBatch.length - 1]?.blockNumber) : order === "asc" ? Number(toBlock) : Number(fromBlock)
|
|
665
705
|
};
|
|
@@ -710,10 +750,15 @@ var MissingBlockNumberError = class extends BaseError {
|
|
|
710
750
|
|
|
711
751
|
//#endregion
|
|
712
752
|
//#region src/core/ChainRegistry.ts
|
|
713
|
-
var ChainRegistry_exports = /* @__PURE__ */
|
|
714
|
-
|
|
753
|
+
var ChainRegistry_exports = /* @__PURE__ */ __exportAll({ create: () => create$1 });
|
|
754
|
+
/**
|
|
755
|
+
* Creates a chain registry from a list of chains.
|
|
756
|
+
* @param chains - Array of chain objects to register.
|
|
757
|
+
* @returns A registry for looking up chains by ID. {@link ChainRegistry}
|
|
758
|
+
*/
|
|
759
|
+
function create$1(chains) {
|
|
715
760
|
const byId = /* @__PURE__ */ new Map();
|
|
716
|
-
for (const chain of chains
|
|
761
|
+
for (const chain of chains) byId.set(chain.id, chain);
|
|
717
762
|
return {
|
|
718
763
|
getById: (chainId) => byId.get(chainId),
|
|
719
764
|
list: () => Array.from(byId.values())
|
|
@@ -722,7 +767,7 @@ function create$1(chains$2) {
|
|
|
722
767
|
|
|
723
768
|
//#endregion
|
|
724
769
|
//#region src/utils/Random.ts
|
|
725
|
-
var Random_exports = /* @__PURE__ */
|
|
770
|
+
var Random_exports = /* @__PURE__ */ __exportAll({
|
|
726
771
|
address: () => address,
|
|
727
772
|
bool: () => bool,
|
|
728
773
|
bytes: () => bytes,
|
|
@@ -735,16 +780,16 @@ var Random_exports = /* @__PURE__ */ __export({
|
|
|
735
780
|
let currentRng = Math.random;
|
|
736
781
|
const FNV_OFFSET_BASIS = 2166136261;
|
|
737
782
|
const FNV_PRIME = 16777619;
|
|
738
|
-
const hashSeed = (seed
|
|
739
|
-
let hash
|
|
740
|
-
for (let i = 0; i < seed
|
|
741
|
-
hash
|
|
742
|
-
hash
|
|
783
|
+
const hashSeed = (seed) => {
|
|
784
|
+
let hash = FNV_OFFSET_BASIS;
|
|
785
|
+
for (let i = 0; i < seed.length; i += 1) {
|
|
786
|
+
hash ^= seed.charCodeAt(i);
|
|
787
|
+
hash = Math.imul(hash, FNV_PRIME);
|
|
743
788
|
}
|
|
744
|
-
return hash
|
|
789
|
+
return hash >>> 0;
|
|
745
790
|
};
|
|
746
|
-
const createSeededRng = (seed
|
|
747
|
-
let state = hashSeed(seed
|
|
791
|
+
const createSeededRng = (seed) => {
|
|
792
|
+
let state = hashSeed(seed);
|
|
748
793
|
return () => {
|
|
749
794
|
state += 1831565813;
|
|
750
795
|
let t = Math.imul(state ^ state >>> 15, state | 1);
|
|
@@ -755,9 +800,9 @@ const createSeededRng = (seed$1) => {
|
|
|
755
800
|
/**
|
|
756
801
|
* Runs a function with a deterministic RNG derived from the given seed.
|
|
757
802
|
*/
|
|
758
|
-
function withSeed(seed
|
|
803
|
+
function withSeed(seed, fn) {
|
|
759
804
|
const previous = currentRng;
|
|
760
|
-
currentRng = createSeededRng(seed
|
|
805
|
+
currentRng = createSeededRng(seed);
|
|
761
806
|
try {
|
|
762
807
|
return fn();
|
|
763
808
|
} finally {
|
|
@@ -767,8 +812,8 @@ function withSeed(seed$1, fn) {
|
|
|
767
812
|
/**
|
|
768
813
|
* Seeds the global RNG for deterministic test runs.
|
|
769
814
|
*/
|
|
770
|
-
function seed(seed
|
|
771
|
-
currentRng = createSeededRng(seed
|
|
815
|
+
function seed(seed) {
|
|
816
|
+
currentRng = createSeededRng(seed);
|
|
772
817
|
}
|
|
773
818
|
/**
|
|
774
819
|
* Returns a deterministic random float in [0, 1).
|
|
@@ -779,8 +824,8 @@ function float() {
|
|
|
779
824
|
/**
|
|
780
825
|
* Returns a deterministic random integer in [min, maxExclusive).
|
|
781
826
|
*/
|
|
782
|
-
function int(maxExclusive, min
|
|
783
|
-
return Math.floor(float() * (maxExclusive - min
|
|
827
|
+
function int(maxExclusive, min = 0) {
|
|
828
|
+
return Math.floor(float() * (maxExclusive - min)) + min;
|
|
784
829
|
}
|
|
785
830
|
/**
|
|
786
831
|
* Returns a deterministic random boolean.
|
|
@@ -893,12 +938,12 @@ const transformAddress = (val, ctx) => {
|
|
|
893
938
|
|
|
894
939
|
//#endregion
|
|
895
940
|
//#region src/core/LLTV.ts
|
|
896
|
-
var LLTV_exports = /* @__PURE__ */
|
|
941
|
+
var LLTV_exports = /* @__PURE__ */ __exportAll({
|
|
897
942
|
InvalidLLTVError: () => InvalidLLTVError,
|
|
898
943
|
InvalidOptionError: () => InvalidOptionError$1,
|
|
899
944
|
LLTVSchema: () => LLTVSchema,
|
|
900
945
|
Options: () => Options,
|
|
901
|
-
from: () => from$
|
|
946
|
+
from: () => from$13
|
|
902
947
|
});
|
|
903
948
|
const Options = [
|
|
904
949
|
.385,
|
|
@@ -917,7 +962,7 @@ const LLTV_SCALED = Options.map((lltv) => BigInt(lltv * 10 ** 18));
|
|
|
917
962
|
* @param lltv - The LLTV option or the scaled LLTV.
|
|
918
963
|
* @returns The LLTV.
|
|
919
964
|
*/
|
|
920
|
-
function from$
|
|
965
|
+
function from$13(lltv) {
|
|
921
966
|
if (typeof lltv === "bigint" && !LLTV_SCALED.includes(lltv)) throw new InvalidLLTVError(lltv);
|
|
922
967
|
if (typeof lltv === "bigint") return lltv;
|
|
923
968
|
if (typeof lltv === "number" && !Options.includes(lltv)) throw new InvalidOptionError$1(lltv);
|
|
@@ -937,21 +982,21 @@ var InvalidLLTVError = class extends BaseError {
|
|
|
937
982
|
};
|
|
938
983
|
const LLTVSchema = z$1.bigint({ coerce: true }).refine((lltv) => {
|
|
939
984
|
try {
|
|
940
|
-
from$
|
|
985
|
+
from$13(lltv);
|
|
941
986
|
return true;
|
|
942
987
|
} catch (_) {
|
|
943
988
|
return false;
|
|
944
989
|
}
|
|
945
990
|
}, { error: () => {
|
|
946
991
|
return "Invalid LLTV: must be one of 0.385, 0.625, 0.77, 0.86, 0.915, 0.945, 0.965 or 0.98 (scaled by 1e18)";
|
|
947
|
-
} }).transform((lltv) => from$
|
|
992
|
+
} }).transform((lltv) => from$13(lltv));
|
|
948
993
|
|
|
949
994
|
//#endregion
|
|
950
995
|
//#region src/core/Collateral.ts
|
|
951
|
-
var Collateral_exports = /* @__PURE__ */
|
|
996
|
+
var Collateral_exports = /* @__PURE__ */ __exportAll({
|
|
952
997
|
CollateralSchema: () => CollateralSchema,
|
|
953
998
|
CollateralsSchema: () => CollateralsSchema,
|
|
954
|
-
from: () => from$
|
|
999
|
+
from: () => from$12,
|
|
955
1000
|
random: () => random$3
|
|
956
1001
|
});
|
|
957
1002
|
const CollateralSchema = z$1.object({
|
|
@@ -971,10 +1016,10 @@ const CollateralsSchema = z$1.array(CollateralSchema).min(1, { message: "At leas
|
|
|
971
1016
|
}
|
|
972
1017
|
return true;
|
|
973
1018
|
}, { message: "Collaterals must not contain duplicate assets" });
|
|
974
|
-
const from$
|
|
1019
|
+
const from$12 = (parameters) => {
|
|
975
1020
|
return {
|
|
976
1021
|
asset: parameters.asset.toLowerCase(),
|
|
977
|
-
lltv: from$
|
|
1022
|
+
lltv: from$13(parameters.lltv),
|
|
978
1023
|
oracle: parameters.oracle.toLowerCase()
|
|
979
1024
|
};
|
|
980
1025
|
};
|
|
@@ -988,7 +1033,7 @@ const from$11 = (parameters) => {
|
|
|
988
1033
|
* ```
|
|
989
1034
|
*/
|
|
990
1035
|
function random$3() {
|
|
991
|
-
return from$
|
|
1036
|
+
return from$12({
|
|
992
1037
|
asset: address(),
|
|
993
1038
|
oracle: address(),
|
|
994
1039
|
lltv: .965
|
|
@@ -997,7 +1042,7 @@ function random$3() {
|
|
|
997
1042
|
|
|
998
1043
|
//#endregion
|
|
999
1044
|
//#region src/core/ERC4626.ts
|
|
1000
|
-
var ERC4626_exports = /* @__PURE__ */
|
|
1045
|
+
var ERC4626_exports = /* @__PURE__ */ __exportAll({
|
|
1001
1046
|
DenominatorIsZeroError: () => DenominatorIsZeroError,
|
|
1002
1047
|
convertToAssets: () => convertToAssets,
|
|
1003
1048
|
convertToShares: () => convertToShares,
|
|
@@ -1060,7 +1105,7 @@ var DenominatorIsZeroError = class extends BaseError {
|
|
|
1060
1105
|
|
|
1061
1106
|
//#endregion
|
|
1062
1107
|
//#region src/core/Liquidity.ts
|
|
1063
|
-
var Liquidity_exports = /* @__PURE__ */
|
|
1108
|
+
var Liquidity_exports = /* @__PURE__ */ __exportAll({
|
|
1064
1109
|
calculateMaxDebt: () => calculateMaxDebt,
|
|
1065
1110
|
generateAllowancePoolId: () => generateAllowancePoolId,
|
|
1066
1111
|
generateBalancePoolId: () => generateBalancePoolId,
|
|
@@ -1086,23 +1131,23 @@ function calculateMaxDebt(amount, oraclePrice, lltv) {
|
|
|
1086
1131
|
* Generate pool ID for balance pools.
|
|
1087
1132
|
*/
|
|
1088
1133
|
function generateBalancePoolId(parameters) {
|
|
1089
|
-
const { user, chainId, token
|
|
1090
|
-
return `${user}-${chainId.toString()}-${token
|
|
1134
|
+
const { user, chainId, token } = parameters;
|
|
1135
|
+
return `${user}-${chainId.toString()}-${token}-balance`.toLowerCase();
|
|
1091
1136
|
}
|
|
1092
1137
|
/**
|
|
1093
1138
|
* Generate pool ID for allowance pools.
|
|
1094
1139
|
*/
|
|
1095
1140
|
function generateAllowancePoolId(parameters) {
|
|
1096
|
-
const { user, chainId, token
|
|
1097
|
-
return `${user}-${chainId.toString()}-${token
|
|
1141
|
+
const { user, chainId, token } = parameters;
|
|
1142
|
+
return `${user}-${chainId.toString()}-${token}-allowance`.toLowerCase();
|
|
1098
1143
|
}
|
|
1099
1144
|
/**
|
|
1100
1145
|
* Generate pool ID for sell ERC20 callback pools.
|
|
1101
1146
|
* Each offer has its own callback pool to prevent liquidity conflicts.
|
|
1102
1147
|
*/
|
|
1103
1148
|
function generateSellERC20CallbackPoolId(parameters) {
|
|
1104
|
-
const { user, chainId, obligationId
|
|
1105
|
-
return `${user}-${chainId.toString()}-${obligationId
|
|
1149
|
+
const { user, chainId, obligationId, token, offerHash } = parameters;
|
|
1150
|
+
return `${user}-${chainId.toString()}-${obligationId}-${token}-${offerHash}-sell_erc20_callback`.toLowerCase();
|
|
1106
1151
|
}
|
|
1107
1152
|
/**
|
|
1108
1153
|
* Generate pool ID for obligation collateral pools.
|
|
@@ -1110,22 +1155,22 @@ function generateSellERC20CallbackPoolId(parameters) {
|
|
|
1110
1155
|
* These pools are shared across all offers with the same obligation.
|
|
1111
1156
|
*/
|
|
1112
1157
|
function generateObligationCollateralPoolId(parameters) {
|
|
1113
|
-
const { user, chainId, obligationId
|
|
1114
|
-
return `${user}-${chainId.toString()}-${obligationId
|
|
1158
|
+
const { user, chainId, obligationId, token } = parameters;
|
|
1159
|
+
return `${user}-${chainId.toString()}-${obligationId}-${token}-obligation-collateral`.toLowerCase();
|
|
1115
1160
|
}
|
|
1116
1161
|
/**
|
|
1117
1162
|
* Generate pool ID for buy vault callback pools.
|
|
1118
1163
|
*/
|
|
1119
1164
|
function generateBuyVaultCallbackPoolId(parameters) {
|
|
1120
1165
|
const { user, chainId, vault, offerHash } = parameters;
|
|
1121
|
-
return `${user}-${chainId.toString()}-${vault}-${offerHash}-${
|
|
1166
|
+
return `${user}-${chainId.toString()}-${vault}-${offerHash}-${Type$1.BuyVaultV1Callback}`.toLowerCase();
|
|
1122
1167
|
}
|
|
1123
1168
|
/**
|
|
1124
1169
|
* Generate pool ID for debt pools.
|
|
1125
1170
|
*/
|
|
1126
1171
|
function generateDebtPoolId(parameters) {
|
|
1127
|
-
const { user, chainId, obligationId
|
|
1128
|
-
return `${user}-${chainId.toString()}-${obligationId
|
|
1172
|
+
const { user, chainId, obligationId } = parameters;
|
|
1173
|
+
return `${user}-${chainId.toString()}-${obligationId}-debt`.toLowerCase();
|
|
1129
1174
|
}
|
|
1130
1175
|
/**
|
|
1131
1176
|
* Generate pool ID for user position in a vault.
|
|
@@ -1151,17 +1196,17 @@ function generateMarketLiquidityPoolId(parameters) {
|
|
|
1151
1196
|
|
|
1152
1197
|
//#endregion
|
|
1153
1198
|
//#region src/core/Maturity.ts
|
|
1154
|
-
var Maturity_exports = /* @__PURE__ */
|
|
1199
|
+
var Maturity_exports = /* @__PURE__ */ __exportAll({
|
|
1155
1200
|
InvalidDateError: () => InvalidDateError,
|
|
1156
1201
|
InvalidFormatError: () => InvalidFormatError,
|
|
1157
1202
|
InvalidOptionError: () => InvalidOptionError,
|
|
1158
1203
|
MaturitySchema: () => MaturitySchema,
|
|
1159
1204
|
MaturityType: () => MaturityType,
|
|
1160
|
-
from: () => from$
|
|
1205
|
+
from: () => from$11
|
|
1161
1206
|
});
|
|
1162
|
-
const MaturitySchema = z$1.number().int().refine((maturity
|
|
1207
|
+
const MaturitySchema = z$1.number().int().refine((maturity) => {
|
|
1163
1208
|
try {
|
|
1164
|
-
from$
|
|
1209
|
+
from$11(maturity);
|
|
1165
1210
|
return true;
|
|
1166
1211
|
} catch (_e) {
|
|
1167
1212
|
return false;
|
|
@@ -1172,15 +1217,15 @@ const MaturitySchema = z$1.number().int().refine((maturity$1) => {
|
|
|
1172
1217
|
} catch (_) {
|
|
1173
1218
|
return `The maturity is set to ${issue.input}. It must fall on the allowed settlement cycles (Friday 15:00 UTC at the end of week/month/quarter).`;
|
|
1174
1219
|
}
|
|
1175
|
-
} }).transform((maturity
|
|
1176
|
-
let MaturityType = /* @__PURE__ */ function(MaturityType
|
|
1177
|
-
MaturityType
|
|
1178
|
-
MaturityType
|
|
1179
|
-
MaturityType
|
|
1180
|
-
MaturityType
|
|
1181
|
-
MaturityType
|
|
1182
|
-
MaturityType
|
|
1183
|
-
return MaturityType
|
|
1220
|
+
} }).transform((maturity) => maturity);
|
|
1221
|
+
let MaturityType = /* @__PURE__ */ function(MaturityType) {
|
|
1222
|
+
MaturityType["EndOfWeek"] = "end_of_week";
|
|
1223
|
+
MaturityType["EndOfNextWeek"] = "end_of_next_week";
|
|
1224
|
+
MaturityType["EndOfMonth"] = "end_of_month";
|
|
1225
|
+
MaturityType["EndOfNextMonth"] = "end_of_next_month";
|
|
1226
|
+
MaturityType["EndOfQuarter"] = "end_of_quarter";
|
|
1227
|
+
MaturityType["EndOfNextQuarter"] = "end_of_next_quarter";
|
|
1228
|
+
return MaturityType;
|
|
1184
1229
|
}({});
|
|
1185
1230
|
const MaturityOptions = {
|
|
1186
1231
|
end_of_week: () => endOfWeek(),
|
|
@@ -1196,7 +1241,7 @@ const MaturityOptions = {
|
|
|
1196
1241
|
* @throws {InvalidDateError} If the maturity is in seconds but not a valid date.
|
|
1197
1242
|
* @throws {InvalidOptionError} If the maturity is not a valid option.
|
|
1198
1243
|
*/
|
|
1199
|
-
function from$
|
|
1244
|
+
function from$11(ts) {
|
|
1200
1245
|
if (typeof ts === "string") {
|
|
1201
1246
|
if (ts in MaturityOptions) return MaturityOptions[ts]();
|
|
1202
1247
|
throw new InvalidOptionError(ts);
|
|
@@ -1214,23 +1259,23 @@ const endOfNextWeek = () => fridayOfWeek(1);
|
|
|
1214
1259
|
* on that Friday), roll to the next month's last Friday.
|
|
1215
1260
|
*/
|
|
1216
1261
|
const endOfMonth = () => {
|
|
1217
|
-
const now
|
|
1218
|
-
const year = now
|
|
1219
|
-
const month = now
|
|
1220
|
-
const endOfMonth
|
|
1221
|
-
if (now
|
|
1222
|
-
return endOfMonth
|
|
1262
|
+
const now = /* @__PURE__ */ new Date();
|
|
1263
|
+
const year = now.getUTCFullYear();
|
|
1264
|
+
const month = now.getUTCMonth();
|
|
1265
|
+
const endOfMonth = lastFridayOfMonth(year, month);
|
|
1266
|
+
if (now.getTime() > endOfMonth * 1e3) return lastFridayOfMonth(year, month + 1);
|
|
1267
|
+
return endOfMonth;
|
|
1223
1268
|
};
|
|
1224
1269
|
/** Returns the end of the next month (last friday of the next month at 15:00:00 UTC)
|
|
1225
1270
|
* Business rule: if we are after the last Friday of the current month (strictly after 15:00 UTC
|
|
1226
1271
|
* on that Friday), we consider being in the next month already, so "next month" becomes month+2.
|
|
1227
1272
|
*/
|
|
1228
1273
|
const endOfNextMonth = () => {
|
|
1229
|
-
const now
|
|
1230
|
-
const year = now
|
|
1231
|
-
const month = now
|
|
1232
|
-
const endOfMonth
|
|
1233
|
-
if (now
|
|
1274
|
+
const now = /* @__PURE__ */ new Date();
|
|
1275
|
+
const year = now.getUTCFullYear();
|
|
1276
|
+
const month = now.getUTCMonth();
|
|
1277
|
+
const endOfMonth = lastFridayOfMonth(year, month);
|
|
1278
|
+
if (now.getTime() > endOfMonth * 1e3) return lastFridayOfMonth(year, month + 2);
|
|
1234
1279
|
return lastFridayOfMonth(year, month + 1);
|
|
1235
1280
|
};
|
|
1236
1281
|
/** Returns the end of the current quarter (last friday of the quarter at 15:00:00 UTC) */
|
|
@@ -1238,10 +1283,10 @@ const endOfQuarter = () => lastFridayOfQuarter(0);
|
|
|
1238
1283
|
/** Returns the end of the next quarter (last friday of the next quarter at 15:00:00 UTC) */
|
|
1239
1284
|
const endOfNextQuarter = () => lastFridayOfQuarter(1);
|
|
1240
1285
|
const fridayOfWeek = (weeksAhead = 0) => {
|
|
1241
|
-
const now
|
|
1242
|
-
const today15H = new Date(Date.UTC(now
|
|
1286
|
+
const now = /* @__PURE__ */ new Date();
|
|
1287
|
+
const today15H = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), 15));
|
|
1243
1288
|
let daysUntilFriday = (5 - today15H.getUTCDay() + 7) % 7;
|
|
1244
|
-
if (daysUntilFriday === 0 && now
|
|
1289
|
+
if (daysUntilFriday === 0 && now.getTime() >= today15H.getTime()) daysUntilFriday = 7;
|
|
1245
1290
|
const friday = new Date(today15H);
|
|
1246
1291
|
friday.setUTCDate(friday.getUTCDate() + daysUntilFriday + weeksAhead * 7);
|
|
1247
1292
|
return friday.getTime() / 1e3;
|
|
@@ -1252,9 +1297,9 @@ const lastFridayOfMonth = (year, month) => {
|
|
|
1252
1297
|
return lastDayOfMonth15H.setUTCDate(lastDayOfMonth15H.getUTCDate()) / 1e3;
|
|
1253
1298
|
};
|
|
1254
1299
|
const lastFridayOfQuarter = (quartersAhead = 0) => {
|
|
1255
|
-
const now
|
|
1256
|
-
const quarterIndex = Math.floor(now
|
|
1257
|
-
return lastFridayOfMonth(now
|
|
1300
|
+
const now = /* @__PURE__ */ new Date();
|
|
1301
|
+
const quarterIndex = Math.floor(now.getUTCMonth() / 3) + quartersAhead;
|
|
1302
|
+
return lastFridayOfMonth(now.getUTCFullYear() + Math.floor(quarterIndex / 4), quarterIndex % 4 * 3 + 2);
|
|
1258
1303
|
};
|
|
1259
1304
|
var InvalidFormatError = class extends BaseError {
|
|
1260
1305
|
constructor() {
|
|
@@ -1277,7 +1322,7 @@ var InvalidOptionError = class extends BaseError {
|
|
|
1277
1322
|
|
|
1278
1323
|
//#endregion
|
|
1279
1324
|
//#region src/utils/Format.ts
|
|
1280
|
-
var Format_exports = /* @__PURE__ */
|
|
1325
|
+
var Format_exports = /* @__PURE__ */ __exportAll({
|
|
1281
1326
|
fromSnakeCase: () => fromSnakeCase$3,
|
|
1282
1327
|
stringifyBigint: () => stringifyBigint,
|
|
1283
1328
|
toSnakeCase: () => toSnakeCase$1
|
|
@@ -1322,11 +1367,12 @@ function stringifyBigint(value) {
|
|
|
1322
1367
|
|
|
1323
1368
|
//#endregion
|
|
1324
1369
|
//#region src/core/Obligation.ts
|
|
1325
|
-
var Obligation_exports = /* @__PURE__ */
|
|
1370
|
+
var Obligation_exports = /* @__PURE__ */ __exportAll({
|
|
1326
1371
|
CollateralsAreNotSortedError: () => CollateralsAreNotSortedError,
|
|
1327
1372
|
InvalidObligationError: () => InvalidObligationError,
|
|
1328
1373
|
ObligationSchema: () => ObligationSchema,
|
|
1329
|
-
from: () => from$
|
|
1374
|
+
from: () => from$10,
|
|
1375
|
+
fromOffer: () => fromOffer$1,
|
|
1330
1376
|
fromSnakeCase: () => fromSnakeCase$2,
|
|
1331
1377
|
id: () => id,
|
|
1332
1378
|
random: () => random$2
|
|
@@ -1360,11 +1406,11 @@ const ObligationSchema = z$1.object({
|
|
|
1360
1406
|
* });
|
|
1361
1407
|
* ```
|
|
1362
1408
|
*/
|
|
1363
|
-
function from$
|
|
1409
|
+
function from$10(parameters) {
|
|
1364
1410
|
try {
|
|
1365
1411
|
const parsedObligation = ObligationSchema.parse({
|
|
1366
1412
|
...parameters,
|
|
1367
|
-
maturity: from$
|
|
1413
|
+
maturity: from$11(parameters.maturity)
|
|
1368
1414
|
});
|
|
1369
1415
|
return {
|
|
1370
1416
|
chainId: parsedObligation.chainId,
|
|
@@ -1383,7 +1429,7 @@ function from$9(parameters) {
|
|
|
1383
1429
|
* @returns The created obligation. {@link fromSnakeCase.ReturnType}
|
|
1384
1430
|
*/
|
|
1385
1431
|
function fromSnakeCase$2(input) {
|
|
1386
|
-
return from$
|
|
1432
|
+
return from$10(fromSnakeCase$3(input));
|
|
1387
1433
|
}
|
|
1388
1434
|
/**
|
|
1389
1435
|
* Calculates the obligation id based on the smart contract's Obligation struct.
|
|
@@ -1448,11 +1494,26 @@ function id(parameters) {
|
|
|
1448
1494
|
* ```
|
|
1449
1495
|
*/
|
|
1450
1496
|
function random$2() {
|
|
1451
|
-
return from$
|
|
1497
|
+
return from$10({
|
|
1452
1498
|
chainId: 1,
|
|
1453
1499
|
loanToken: address(),
|
|
1454
1500
|
collaterals: [random$3()],
|
|
1455
|
-
maturity: from$
|
|
1501
|
+
maturity: from$11("end_of_next_quarter")
|
|
1502
|
+
});
|
|
1503
|
+
}
|
|
1504
|
+
/**
|
|
1505
|
+
* Creates an obligation from an offer.
|
|
1506
|
+
* @constructor
|
|
1507
|
+
*
|
|
1508
|
+
* @param offer - The offer to create the obligation from.
|
|
1509
|
+
* @returns The created obligation. {@link fromOffer.ReturnType}
|
|
1510
|
+
*/
|
|
1511
|
+
function fromOffer$1(offer) {
|
|
1512
|
+
return from$10({
|
|
1513
|
+
chainId: offer.chainId,
|
|
1514
|
+
loanToken: offer.loanToken,
|
|
1515
|
+
collaterals: offer.collaterals,
|
|
1516
|
+
maturity: offer.maturity
|
|
1456
1517
|
});
|
|
1457
1518
|
}
|
|
1458
1519
|
var InvalidObligationError = class extends BaseError {
|
|
@@ -1468,282 +1529,31 @@ var CollateralsAreNotSortedError = class extends BaseError {
|
|
|
1468
1529
|
}
|
|
1469
1530
|
};
|
|
1470
1531
|
|
|
1471
|
-
//#endregion
|
|
1472
|
-
//#region src/core/Tree.ts
|
|
1473
|
-
var Tree_exports = /* @__PURE__ */ __export({
|
|
1474
|
-
DecodeError: () => DecodeError,
|
|
1475
|
-
EncodeError: () => EncodeError,
|
|
1476
|
-
TreeError: () => TreeError,
|
|
1477
|
-
VERSION: () => VERSION,
|
|
1478
|
-
decode: () => decode$1,
|
|
1479
|
-
encode: () => encode$1,
|
|
1480
|
-
encodeUnsigned: () => encodeUnsigned,
|
|
1481
|
-
from: () => from$8,
|
|
1482
|
-
proofs: () => proofs
|
|
1483
|
-
});
|
|
1484
|
-
const VERSION = 1;
|
|
1485
|
-
const normalizeHash = (hash$1) => hash$1.toLowerCase();
|
|
1486
|
-
/**
|
|
1487
|
-
* Builds a Merkle tree from a list of offers.
|
|
1488
|
-
*
|
|
1489
|
-
* Leaves are the offer `hash` values as `bytes32` and are deterministically
|
|
1490
|
-
* ordered following the StandardMerkleTree leaf ordering so that the resulting
|
|
1491
|
-
* root is stable regardless of the input order.
|
|
1492
|
-
*
|
|
1493
|
-
* @param offers - Offers to include in the tree.
|
|
1494
|
-
* @returns A `StandardMerkleTree` of `bytes32` leaves representing the offers.
|
|
1495
|
-
* @throws {TreeError} If tree building fails due to offer inconsistencies.
|
|
1496
|
-
*/
|
|
1497
|
-
const from$8 = (offers) => {
|
|
1498
|
-
const leaves = offers.map((offer) => [hash(offer)]);
|
|
1499
|
-
const tree = StandardMerkleTree.of(leaves, ["bytes32"]);
|
|
1500
|
-
const orderedOffers = orderOffers(tree, offers);
|
|
1501
|
-
return Object.assign(tree, { offers: orderedOffers });
|
|
1502
|
-
};
|
|
1503
|
-
const orderOffers = (tree, offers) => {
|
|
1504
|
-
const offerByHash = /* @__PURE__ */ new Map();
|
|
1505
|
-
for (const offer of offers) offerByHash.set(normalizeHash(hash(offer)), offer);
|
|
1506
|
-
const entries = tree.dump().values.map((value) => {
|
|
1507
|
-
const hash$1 = normalizeHash(value.value[0]);
|
|
1508
|
-
const offer = offerByHash.get(hash$1);
|
|
1509
|
-
if (!offer) throw new TreeError(`missing offer for leaf ${hash$1}`);
|
|
1510
|
-
return {
|
|
1511
|
-
offer,
|
|
1512
|
-
treeIndex: value.treeIndex
|
|
1513
|
-
};
|
|
1514
|
-
});
|
|
1515
|
-
entries.sort((a, b) => b.treeIndex - a.treeIndex);
|
|
1516
|
-
return entries.map((item) => item.offer);
|
|
1517
|
-
};
|
|
1518
|
-
/**
|
|
1519
|
-
* Generates merkle proofs for all offers in a tree.
|
|
1520
|
-
*
|
|
1521
|
-
* Each proof allows independent verification that an offer is included in the tree
|
|
1522
|
-
* without requiring the full tree. Proofs are ordered by StandardMerkleTree leaf ordering.
|
|
1523
|
-
*
|
|
1524
|
-
* @param tree - The {@link Tree} to generate proofs for.
|
|
1525
|
-
* @returns Array of proofs - {@link Proof}
|
|
1526
|
-
*/
|
|
1527
|
-
const proofs = (tree) => {
|
|
1528
|
-
return tree.offers.map((offer) => {
|
|
1529
|
-
return {
|
|
1530
|
-
offer,
|
|
1531
|
-
path: tree.getProof([hash(offer)])
|
|
1532
|
-
};
|
|
1533
|
-
});
|
|
1534
|
-
};
|
|
1535
|
-
const assertHex = (value, expectedBytes, name) => {
|
|
1536
|
-
if (typeof value !== "string" || !isHex(value)) throw new DecodeError(`${name} is not a valid hex string`);
|
|
1537
|
-
if (hexToBytes(value).length !== expectedBytes) throw new DecodeError(`${name}: expected ${expectedBytes} bytes`);
|
|
1538
|
-
};
|
|
1539
|
-
const verifySignatureAndRecoverAddress = async (params) => {
|
|
1540
|
-
const { root, signature } = params;
|
|
1541
|
-
assertHex(signature, 65, "signature");
|
|
1542
|
-
const hash$1 = hashMessage({ raw: root });
|
|
1543
|
-
try {
|
|
1544
|
-
return await recoverAddress({
|
|
1545
|
-
hash: hash$1,
|
|
1546
|
-
signature
|
|
1547
|
-
});
|
|
1548
|
-
} catch {
|
|
1549
|
-
throw new DecodeError("signature recovery failed");
|
|
1550
|
-
}
|
|
1551
|
-
};
|
|
1552
|
-
/**
|
|
1553
|
-
* Encodes a merkle tree with signature into hex calldata for onchain broadcast.
|
|
1554
|
-
*
|
|
1555
|
-
* Layout: `0x{vv}{gzip([...offers])}{root}{signature}` where:
|
|
1556
|
-
* - `{vv}`: 1-byte version (currently 0x01)
|
|
1557
|
-
* - `{gzip([...offers])}`: gzipped JSON array of serialized offers
|
|
1558
|
-
* - `{root}`: 32-byte merkle root
|
|
1559
|
-
* - `{signature}`: 65-byte EIP-191 signature over raw root bytes
|
|
1560
|
-
*
|
|
1561
|
-
* Validates signature authenticity and root integrity before encoding.
|
|
1562
|
-
*
|
|
1563
|
-
* @example
|
|
1564
|
-
* ```typescript
|
|
1565
|
-
* const tree = Tree.from(offers);
|
|
1566
|
-
* const signature = await wallet.signMessage({ message: { raw: tree.root } });
|
|
1567
|
-
* const calldata = await Tree.encode(tree, signature);
|
|
1568
|
-
* await broadcast(calldata);
|
|
1569
|
-
* ```
|
|
1570
|
-
*
|
|
1571
|
-
* @example
|
|
1572
|
-
* Manual construction (for advanced users):
|
|
1573
|
-
* ```typescript
|
|
1574
|
-
* const tree = Tree.from(offers);
|
|
1575
|
-
* const compressed = gzip(JSON.stringify(tree.offers.map(Offer.serialize)));
|
|
1576
|
-
* const partial = `0x01${bytesToHex(compressed)}${tree.root.slice(2)}`;
|
|
1577
|
-
* const signature = await wallet.signMessage({ message: { raw: tree.root } });
|
|
1578
|
-
* const calldata = `${partial}${signature.slice(2)}`;
|
|
1579
|
-
* ```
|
|
1580
|
-
*
|
|
1581
|
-
* @param tree - Merkle tree of offers
|
|
1582
|
-
* @param signature - EIP-191 signature over raw root bytes
|
|
1583
|
-
* @returns Hex-encoded calldata ready for onchain broadcast
|
|
1584
|
-
* @throws {EncodeError} If signature verification fails or root mismatch
|
|
1585
|
-
*/
|
|
1586
|
-
const encode$1 = async (tree, signature) => {
|
|
1587
|
-
validateTreeForEncoding(tree);
|
|
1588
|
-
await verifySignatureAndRecoverAddress({
|
|
1589
|
-
root: tree.root,
|
|
1590
|
-
signature
|
|
1591
|
-
});
|
|
1592
|
-
const unsigned = encodeUnsignedBytes(tree);
|
|
1593
|
-
const sigBytes = hexToBytes(signature);
|
|
1594
|
-
const encoded = new Uint8Array(unsigned.length + sigBytes.length);
|
|
1595
|
-
encoded.set(unsigned, 0);
|
|
1596
|
-
encoded.set(sigBytes, unsigned.length);
|
|
1597
|
-
return bytesToHex(encoded);
|
|
1598
|
-
};
|
|
1599
|
-
/**
|
|
1600
|
-
* Encodes a merkle tree without a signature into hex payload for client-side signing.
|
|
1601
|
-
*
|
|
1602
|
-
* Layout: `0x{vv}{gzip([...offers])}{root}` where:
|
|
1603
|
-
* - `{vv}`: 1-byte version (currently 0x01)
|
|
1604
|
-
* - `{gzip([...offers])}`: gzipped JSON array of serialized offers
|
|
1605
|
-
* - `{root}`: 32-byte merkle root
|
|
1606
|
-
*
|
|
1607
|
-
* Validates root integrity before encoding.
|
|
1608
|
-
*
|
|
1609
|
-
* @param tree - Merkle tree of offers
|
|
1610
|
-
* @returns Hex-encoded unsigned payload
|
|
1611
|
-
* @throws {EncodeError} If root mismatch
|
|
1612
|
-
*/
|
|
1613
|
-
const encodeUnsigned = (tree) => {
|
|
1614
|
-
validateTreeForEncoding(tree);
|
|
1615
|
-
return bytesToHex(encodeUnsignedBytes(tree));
|
|
1616
|
-
};
|
|
1617
|
-
const validateTreeForEncoding = (tree) => {
|
|
1618
|
-
if (VERSION > 255) throw new EncodeError(`version overflow: ${VERSION} exceeds 255`);
|
|
1619
|
-
const computed = from$8(tree.offers);
|
|
1620
|
-
if (tree.root !== computed.root) throw new EncodeError(`root mismatch: expected ${computed.root}, got ${tree.root}`);
|
|
1621
|
-
};
|
|
1622
|
-
const encodeUnsignedBytes = (tree) => {
|
|
1623
|
-
const offersPayload = tree.offers.map(serialize);
|
|
1624
|
-
const compressed = gzip(JSON.stringify(offersPayload));
|
|
1625
|
-
const rootBytes = hexToBytes(tree.root);
|
|
1626
|
-
const encoded = new Uint8Array(1 + compressed.length + 32);
|
|
1627
|
-
encoded[0] = VERSION;
|
|
1628
|
-
encoded.set(compressed, 1);
|
|
1629
|
-
encoded.set(rootBytes, 1 + compressed.length);
|
|
1630
|
-
return encoded;
|
|
1631
|
-
};
|
|
1632
|
-
/**
|
|
1633
|
-
* Decodes hex calldata into a validated merkle tree.
|
|
1634
|
-
*
|
|
1635
|
-
* Validates signature before decompression for fail-fast rejection of invalid payloads.
|
|
1636
|
-
* Returns the tree with separately validated signature and recovered signer address.
|
|
1637
|
-
*
|
|
1638
|
-
* Validation order:
|
|
1639
|
-
* 1. Version check
|
|
1640
|
-
* 2. Signature verification (fail-fast, before decompression)
|
|
1641
|
-
* 3. Decompression (only if signature valid)
|
|
1642
|
-
* 4. Root verification (computed from offers vs embedded root)
|
|
1643
|
-
*
|
|
1644
|
-
* @example
|
|
1645
|
-
* ```typescript
|
|
1646
|
-
* const { tree, signature, signer } = await Tree.decode(calldata);
|
|
1647
|
-
* console.log(`Tree signed by ${signer} with ${tree.offers.length} offers`);
|
|
1648
|
-
* ```
|
|
1649
|
-
*
|
|
1650
|
-
* @param encoded - Hex calldata in format `0x{vv}{gzip}{root}{signature}`
|
|
1651
|
-
* @returns Validated tree, signature, and recovered signer address
|
|
1652
|
-
* @throws {DecodeError} If version invalid, signature invalid, or root mismatch
|
|
1653
|
-
*/
|
|
1654
|
-
const decode$1 = async (encoded) => {
|
|
1655
|
-
const bytes$1 = hexToBytes(encoded);
|
|
1656
|
-
if (bytes$1.length < 98) throw new DecodeError("payload too short");
|
|
1657
|
-
const version = bytes$1[0];
|
|
1658
|
-
if (version !== (VERSION & 255)) throw new DecodeError(`invalid version: expected ${VERSION}, got ${version ?? 0}`);
|
|
1659
|
-
const signature = bytesToHex(bytes$1.slice(-65));
|
|
1660
|
-
const root = bytesToHex(bytes$1.slice(-97, -65));
|
|
1661
|
-
assertHex(root, 32, "root");
|
|
1662
|
-
assertHex(signature, 65, "signature");
|
|
1663
|
-
const signer = await verifySignatureAndRecoverAddress({
|
|
1664
|
-
root,
|
|
1665
|
-
signature
|
|
1666
|
-
});
|
|
1667
|
-
const compressed = bytes$1.slice(1, -97);
|
|
1668
|
-
let decoded;
|
|
1669
|
-
try {
|
|
1670
|
-
decoded = ungzip(compressed, { to: "string" });
|
|
1671
|
-
} catch {
|
|
1672
|
-
throw new DecodeError("decompression failed");
|
|
1673
|
-
}
|
|
1674
|
-
let rawOffers;
|
|
1675
|
-
try {
|
|
1676
|
-
rawOffers = JSON.parse(decoded);
|
|
1677
|
-
} catch {
|
|
1678
|
-
throw new DecodeError("JSON parse failed");
|
|
1679
|
-
}
|
|
1680
|
-
const tree = from$8(rawOffers.map((o) => OfferSchema().parse(o)));
|
|
1681
|
-
if (root !== tree.root) throw new DecodeError(`root mismatch: expected ${tree.root}, got ${root}`);
|
|
1682
|
-
return {
|
|
1683
|
-
tree,
|
|
1684
|
-
signature,
|
|
1685
|
-
signer
|
|
1686
|
-
};
|
|
1687
|
-
};
|
|
1688
|
-
/**
|
|
1689
|
-
* Error thrown during tree building operations.
|
|
1690
|
-
* Indicates structural issues with the tree (missing offers, inconsistent state).
|
|
1691
|
-
*/
|
|
1692
|
-
var TreeError = class extends BaseError {
|
|
1693
|
-
constructor(reason) {
|
|
1694
|
-
super(`Tree error: ${reason}`);
|
|
1695
|
-
_defineProperty(this, "name", "Tree.TreeError");
|
|
1696
|
-
}
|
|
1697
|
-
};
|
|
1698
|
-
/**
|
|
1699
|
-
* Error thrown during tree encoding.
|
|
1700
|
-
* Indicates validation failures (signature, root mismatch, mixed makers).
|
|
1701
|
-
*/
|
|
1702
|
-
var EncodeError = class extends BaseError {
|
|
1703
|
-
constructor(reason) {
|
|
1704
|
-
super(`Failed to encode tree: ${reason}`);
|
|
1705
|
-
_defineProperty(this, "name", "Tree.EncodeError");
|
|
1706
|
-
}
|
|
1707
|
-
};
|
|
1708
|
-
/**
|
|
1709
|
-
* Error thrown during tree decoding.
|
|
1710
|
-
* Indicates payload corruption, version mismatch, or validation failures.
|
|
1711
|
-
*/
|
|
1712
|
-
var DecodeError = class extends BaseError {
|
|
1713
|
-
constructor(reason) {
|
|
1714
|
-
super(`Failed to decode tree: ${reason}`);
|
|
1715
|
-
_defineProperty(this, "name", "Tree.DecodeError");
|
|
1716
|
-
}
|
|
1717
|
-
};
|
|
1718
|
-
|
|
1719
1532
|
//#endregion
|
|
1720
1533
|
//#region src/core/Offer.ts
|
|
1721
|
-
var Offer_exports = /* @__PURE__ */
|
|
1722
|
-
AccountNotSetError: () => AccountNotSetError,
|
|
1534
|
+
var Offer_exports = /* @__PURE__ */ __exportAll({
|
|
1723
1535
|
InvalidOfferError: () => InvalidOfferError,
|
|
1724
1536
|
OfferSchema: () => OfferSchema,
|
|
1725
1537
|
Status: () => Status,
|
|
1726
1538
|
consumedEvent: () => consumedEvent,
|
|
1727
|
-
decode: () => decode,
|
|
1539
|
+
decode: () => decode$1,
|
|
1728
1540
|
domain: () => domain,
|
|
1729
|
-
encode: () => encode,
|
|
1730
|
-
from: () => from$
|
|
1541
|
+
encode: () => encode$1,
|
|
1542
|
+
from: () => from$9,
|
|
1731
1543
|
fromSnakeCase: () => fromSnakeCase$1,
|
|
1732
1544
|
hash: () => hash,
|
|
1733
1545
|
obligationId: () => obligationId,
|
|
1734
1546
|
random: () => random$1,
|
|
1735
1547
|
serialize: () => serialize,
|
|
1736
|
-
sign: () => sign,
|
|
1737
|
-
signatureMsg: () => signatureMsg,
|
|
1738
1548
|
toSnakeCase: () => toSnakeCase,
|
|
1739
1549
|
types: () => types
|
|
1740
1550
|
});
|
|
1741
1551
|
/** Internal symbol for caching the computed hash. */
|
|
1742
1552
|
const HASH_CACHE = Symbol("offer.hash");
|
|
1743
|
-
let Status = /* @__PURE__ */ function(Status
|
|
1744
|
-
Status
|
|
1745
|
-
Status
|
|
1746
|
-
return Status
|
|
1553
|
+
let Status = /* @__PURE__ */ function(Status) {
|
|
1554
|
+
Status["VALID"] = "VALID";
|
|
1555
|
+
Status["SIMULATION_ERROR"] = "SIMULATION_ERROR";
|
|
1556
|
+
return Status;
|
|
1747
1557
|
}({});
|
|
1748
1558
|
const OfferSchema = () => {
|
|
1749
1559
|
return z$1.object({
|
|
@@ -1787,7 +1597,7 @@ const OfferSchema = () => {
|
|
|
1787
1597
|
* @param input - The offer to create.
|
|
1788
1598
|
* @returns The created offer.
|
|
1789
1599
|
*/
|
|
1790
|
-
function from$
|
|
1600
|
+
function from$9(input) {
|
|
1791
1601
|
try {
|
|
1792
1602
|
return OfferSchema().parse(input);
|
|
1793
1603
|
} catch (error) {
|
|
@@ -1801,7 +1611,7 @@ function from$7(input) {
|
|
|
1801
1611
|
* @returns The created offer.
|
|
1802
1612
|
*/
|
|
1803
1613
|
function fromSnakeCase$1(input) {
|
|
1804
|
-
return from$
|
|
1614
|
+
return from$9(fromSnakeCase$3(input));
|
|
1805
1615
|
}
|
|
1806
1616
|
/**
|
|
1807
1617
|
* Converts an offer to a snake case object.
|
|
@@ -1855,8 +1665,8 @@ function random$1(config) {
|
|
|
1855
1665
|
const collateralCandidates = config?.collateralTokens ? config.collateralTokens.filter((a) => a !== loanToken) : [address()];
|
|
1856
1666
|
const collateralAsset = collateralCandidates[int(collateralCandidates.length)];
|
|
1857
1667
|
const maturityOption = weightedChoice([["end_of_month", 1], ["end_of_next_month", 1]]);
|
|
1858
|
-
const maturity
|
|
1859
|
-
const lltv = from$
|
|
1668
|
+
const maturity = config?.maturity ?? from$11(maturityOption);
|
|
1669
|
+
const lltv = from$13(weightedChoice([
|
|
1860
1670
|
[.385, 1],
|
|
1861
1671
|
[.5, 1],
|
|
1862
1672
|
[.625, 2],
|
|
@@ -1895,15 +1705,15 @@ function random$1(config) {
|
|
|
1895
1705
|
})
|
|
1896
1706
|
};
|
|
1897
1707
|
})();
|
|
1898
|
-
return from$
|
|
1708
|
+
return from$9({
|
|
1899
1709
|
maker: config?.maker ?? address(),
|
|
1900
1710
|
assets: assetsScaled,
|
|
1901
1711
|
obligationUnits: config?.obligationUnits ?? 0n,
|
|
1902
1712
|
obligationShares: config?.obligationShares ?? 0n,
|
|
1903
1713
|
price,
|
|
1904
|
-
maturity
|
|
1905
|
-
expiry: config?.expiry ?? maturity
|
|
1906
|
-
start: config?.start ?? maturity
|
|
1714
|
+
maturity,
|
|
1715
|
+
expiry: config?.expiry ?? maturity - 1,
|
|
1716
|
+
start: config?.start ?? maturity - 10,
|
|
1907
1717
|
group: config?.group ?? hex(32),
|
|
1908
1718
|
session: config?.session ?? hex(32),
|
|
1909
1719
|
buy,
|
|
@@ -2023,23 +1833,6 @@ const types = {
|
|
|
2023
1833
|
type: "bytes"
|
|
2024
1834
|
}]
|
|
2025
1835
|
};
|
|
2026
|
-
/**
|
|
2027
|
-
* Signs an array of offers.
|
|
2028
|
-
* @throws {Error} If the wallet account is not set.
|
|
2029
|
-
* @param offers - The offers to sign.
|
|
2030
|
-
* @param wallet - The wallet to sign the offers with.
|
|
2031
|
-
* @returns The signed offers.
|
|
2032
|
-
*/
|
|
2033
|
-
async function sign(offers, wallet) {
|
|
2034
|
-
if (!wallet.account) throw new AccountNotSetError();
|
|
2035
|
-
return wallet.signMessage({
|
|
2036
|
-
account: wallet.account,
|
|
2037
|
-
message: { raw: signatureMsg(offers) }
|
|
2038
|
-
});
|
|
2039
|
-
}
|
|
2040
|
-
function signatureMsg(offers) {
|
|
2041
|
-
return from$8(offers).root;
|
|
2042
|
-
}
|
|
2043
1836
|
function hash(offer) {
|
|
2044
1837
|
const cached = offer[HASH_CACHE];
|
|
2045
1838
|
if (cached) return cached;
|
|
@@ -2076,7 +1869,7 @@ function hash(offer) {
|
|
|
2076
1869
|
* @returns The obligation id as a 32-byte hex string.
|
|
2077
1870
|
*/
|
|
2078
1871
|
function obligationId(offer) {
|
|
2079
|
-
return id(from$
|
|
1872
|
+
return id(from$10({
|
|
2080
1873
|
chainId: offer.chainId,
|
|
2081
1874
|
loanToken: offer.loanToken,
|
|
2082
1875
|
collaterals: offer.collaterals,
|
|
@@ -2166,7 +1959,7 @@ const OfferAbi = [
|
|
|
2166
1959
|
}]
|
|
2167
1960
|
}
|
|
2168
1961
|
];
|
|
2169
|
-
function encode(offer) {
|
|
1962
|
+
function encode$1(offer) {
|
|
2170
1963
|
return encodeAbiParameters(OfferAbi, [
|
|
2171
1964
|
offer.maker,
|
|
2172
1965
|
offer.assets,
|
|
@@ -2185,20 +1978,20 @@ function encode(offer) {
|
|
|
2185
1978
|
offer.callback
|
|
2186
1979
|
]);
|
|
2187
1980
|
}
|
|
2188
|
-
function decode(data) {
|
|
1981
|
+
function decode$1(data) {
|
|
2189
1982
|
let decoded;
|
|
2190
1983
|
try {
|
|
2191
1984
|
decoded = decodeAbiParameters(OfferAbi, data);
|
|
2192
1985
|
} catch (error) {
|
|
2193
1986
|
throw new InvalidOfferError(error);
|
|
2194
1987
|
}
|
|
2195
|
-
return from$
|
|
1988
|
+
return from$9({
|
|
2196
1989
|
maker: decoded[0],
|
|
2197
1990
|
assets: decoded[1],
|
|
2198
1991
|
obligationUnits: decoded[2],
|
|
2199
1992
|
obligationShares: decoded[3],
|
|
2200
1993
|
price: decoded[4],
|
|
2201
|
-
maturity: from$
|
|
1994
|
+
maturity: from$11(Number(decoded[5])),
|
|
2202
1995
|
expiry: Number(decoded[6]),
|
|
2203
1996
|
group: decoded[7],
|
|
2204
1997
|
session: decoded[8],
|
|
@@ -2207,7 +2000,7 @@ function decode(data) {
|
|
|
2207
2000
|
loanToken: decoded[11],
|
|
2208
2001
|
start: Number(decoded[12]),
|
|
2209
2002
|
collaterals: decoded[13].map((c) => {
|
|
2210
|
-
return from$
|
|
2003
|
+
return from$12({
|
|
2211
2004
|
asset: c.asset,
|
|
2212
2005
|
oracle: c.oracle,
|
|
2213
2006
|
lltv: c.lltv
|
|
@@ -2271,25 +2064,22 @@ var InvalidOfferError = class InvalidOfferError extends BaseError {
|
|
|
2271
2064
|
return `Invalid offer. ${InvalidOfferError.formatDetails(this.cause)}`;
|
|
2272
2065
|
}
|
|
2273
2066
|
};
|
|
2274
|
-
var AccountNotSetError = class extends BaseError {
|
|
2275
|
-
constructor() {
|
|
2276
|
-
super("Account not set.");
|
|
2277
|
-
_defineProperty(this, "name", "Offer.AccountNotSetError");
|
|
2278
|
-
}
|
|
2279
|
-
};
|
|
2280
2067
|
|
|
2281
2068
|
//#endregion
|
|
2282
2069
|
//#region src/core/Oracle.ts
|
|
2283
|
-
var Oracle_exports = /* @__PURE__ */
|
|
2070
|
+
var Oracle_exports = /* @__PURE__ */ __exportAll({
|
|
2284
2071
|
Conversion: () => Conversion,
|
|
2285
|
-
from: () => from$
|
|
2072
|
+
from: () => from$8,
|
|
2073
|
+
fromCollateral: () => fromCollateral,
|
|
2074
|
+
fromOffer: () => fromOffer,
|
|
2075
|
+
fromOffers: () => fromOffers
|
|
2286
2076
|
});
|
|
2287
2077
|
/**
|
|
2288
2078
|
* Create an Oracle from a plain object.
|
|
2289
2079
|
* @param data - The data to create the oracle from.
|
|
2290
2080
|
* @returns The created oracle.
|
|
2291
2081
|
*/
|
|
2292
|
-
function from$
|
|
2082
|
+
function from$8(data) {
|
|
2293
2083
|
return {
|
|
2294
2084
|
chainId: data.chainId,
|
|
2295
2085
|
address: data.address.toLowerCase(),
|
|
@@ -2297,6 +2087,59 @@ function from$6(data) {
|
|
|
2297
2087
|
blockNumber: data.blockNumber
|
|
2298
2088
|
};
|
|
2299
2089
|
}
|
|
2090
|
+
/**
|
|
2091
|
+
* Creates an oracle from a collateral.
|
|
2092
|
+
* @constructor
|
|
2093
|
+
*
|
|
2094
|
+
* @param parameters - {@link fromCollateral.Parameters}
|
|
2095
|
+
* @returns The created oracle. {@link fromCollateral.ReturnType}
|
|
2096
|
+
*/
|
|
2097
|
+
function fromCollateral(parameters) {
|
|
2098
|
+
const { chainId, collateral, blockNumber, price = null } = parameters;
|
|
2099
|
+
return {
|
|
2100
|
+
chainId,
|
|
2101
|
+
address: collateral.oracle.toLowerCase(),
|
|
2102
|
+
price,
|
|
2103
|
+
blockNumber
|
|
2104
|
+
};
|
|
2105
|
+
}
|
|
2106
|
+
/**
|
|
2107
|
+
* Creates oracles from a single offer.
|
|
2108
|
+
* @constructor
|
|
2109
|
+
*
|
|
2110
|
+
* @param parameters - {@link fromOffer.Parameters}
|
|
2111
|
+
* @returns The created oracles. {@link fromOffer.ReturnType}
|
|
2112
|
+
*/
|
|
2113
|
+
function fromOffer(parameters) {
|
|
2114
|
+
const { offer, blockNumber, price = null } = parameters;
|
|
2115
|
+
return fromOffers({
|
|
2116
|
+
offers: [offer],
|
|
2117
|
+
blockNumber,
|
|
2118
|
+
price
|
|
2119
|
+
});
|
|
2120
|
+
}
|
|
2121
|
+
/**
|
|
2122
|
+
* Creates oracles from a list of offers.
|
|
2123
|
+
* @constructor
|
|
2124
|
+
*
|
|
2125
|
+
* @param parameters - {@link fromOffers.Parameters}
|
|
2126
|
+
* @returns The created oracles. {@link fromOffers.ReturnType}
|
|
2127
|
+
*/
|
|
2128
|
+
function fromOffers(parameters) {
|
|
2129
|
+
const { offers, blockNumber, price = null } = parameters;
|
|
2130
|
+
const rowsByKey = /* @__PURE__ */ new Map();
|
|
2131
|
+
for (const offer of offers) for (const collateral of offer.collaterals) {
|
|
2132
|
+
const key = `${offer.chainId}-${collateral.oracle}`.toLowerCase();
|
|
2133
|
+
if (rowsByKey.has(key)) continue;
|
|
2134
|
+
rowsByKey.set(key, fromCollateral({
|
|
2135
|
+
chainId: offer.chainId,
|
|
2136
|
+
collateral,
|
|
2137
|
+
blockNumber,
|
|
2138
|
+
price
|
|
2139
|
+
}));
|
|
2140
|
+
}
|
|
2141
|
+
return Array.from(rowsByKey.values());
|
|
2142
|
+
}
|
|
2300
2143
|
let Conversion;
|
|
2301
2144
|
(function(_Conversion) {
|
|
2302
2145
|
function collateralToLoan(amount, params) {
|
|
@@ -2312,14 +2155,14 @@ let Conversion;
|
|
|
2312
2155
|
|
|
2313
2156
|
//#endregion
|
|
2314
2157
|
//#region src/core/Position.ts
|
|
2315
|
-
var Position_exports = /* @__PURE__ */
|
|
2158
|
+
var Position_exports = /* @__PURE__ */ __exportAll({
|
|
2316
2159
|
Type: () => Type,
|
|
2317
|
-
from: () => from$
|
|
2160
|
+
from: () => from$7
|
|
2318
2161
|
});
|
|
2319
|
-
let Type = /* @__PURE__ */ function(Type
|
|
2320
|
-
Type
|
|
2321
|
-
Type
|
|
2322
|
-
return Type
|
|
2162
|
+
let Type = /* @__PURE__ */ function(Type) {
|
|
2163
|
+
Type["ERC20"] = "erc20";
|
|
2164
|
+
Type["VAULT_V1"] = "vault_v1";
|
|
2165
|
+
return Type;
|
|
2323
2166
|
}({});
|
|
2324
2167
|
/**
|
|
2325
2168
|
* @constructor
|
|
@@ -2327,7 +2170,7 @@ let Type = /* @__PURE__ */ function(Type$1) {
|
|
|
2327
2170
|
* @param parameters - {@link from.Parameters}
|
|
2328
2171
|
* @returns The created Position. {@link from.ReturnType}
|
|
2329
2172
|
*/
|
|
2330
|
-
function from$
|
|
2173
|
+
function from$7(parameters) {
|
|
2331
2174
|
return {
|
|
2332
2175
|
chainId: parameters.chainId,
|
|
2333
2176
|
contract: parameters.contract.toLowerCase(),
|
|
@@ -2341,10 +2184,10 @@ function from$5(parameters) {
|
|
|
2341
2184
|
|
|
2342
2185
|
//#endregion
|
|
2343
2186
|
//#region src/core/Quote.ts
|
|
2344
|
-
var Quote_exports = /* @__PURE__ */
|
|
2187
|
+
var Quote_exports = /* @__PURE__ */ __exportAll({
|
|
2345
2188
|
InvalidQuoteError: () => InvalidQuoteError,
|
|
2346
2189
|
QuoteSchema: () => QuoteSchema,
|
|
2347
|
-
from: () => from$
|
|
2190
|
+
from: () => from$6,
|
|
2348
2191
|
fromSnakeCase: () => fromSnakeCase,
|
|
2349
2192
|
random: () => random
|
|
2350
2193
|
});
|
|
@@ -2365,7 +2208,7 @@ const QuoteSchema = z$1.object({
|
|
|
2365
2208
|
* const quote = Quote.from({ obligationId: "0x123", ask: { price: 100n }, bid: { price: 100n } });
|
|
2366
2209
|
* ```
|
|
2367
2210
|
*/
|
|
2368
|
-
function from$
|
|
2211
|
+
function from$6(parameters) {
|
|
2369
2212
|
try {
|
|
2370
2213
|
const parsedQuote = QuoteSchema.parse(parameters);
|
|
2371
2214
|
return {
|
|
@@ -2384,57 +2227,537 @@ function from$4(parameters) {
|
|
|
2384
2227
|
* @returns The created quote. {@link fromSnakeCase.ReturnType}
|
|
2385
2228
|
*/
|
|
2386
2229
|
function fromSnakeCase(snake) {
|
|
2387
|
-
return from$
|
|
2230
|
+
return from$6(fromSnakeCase$3(snake));
|
|
2231
|
+
}
|
|
2232
|
+
/**
|
|
2233
|
+
* Generates a random quote.
|
|
2234
|
+
* @returns A randomly generated quote. {@link random.ReturnType}
|
|
2235
|
+
*
|
|
2236
|
+
* @example
|
|
2237
|
+
* ```ts
|
|
2238
|
+
* const quote = Quote.random();
|
|
2239
|
+
* ```
|
|
2240
|
+
*/
|
|
2241
|
+
function random() {
|
|
2242
|
+
return from$6({
|
|
2243
|
+
obligationId: id(random$2()),
|
|
2244
|
+
ask: { price: BigInt(int(1e6)) },
|
|
2245
|
+
bid: { price: BigInt(int(1e6)) }
|
|
2246
|
+
});
|
|
2247
|
+
}
|
|
2248
|
+
var InvalidQuoteError = class extends BaseError {
|
|
2249
|
+
constructor(error) {
|
|
2250
|
+
super("Invalid quote.", { cause: error });
|
|
2251
|
+
_defineProperty(this, "name", "Quote.InvalidQuoteError");
|
|
2252
|
+
}
|
|
2253
|
+
};
|
|
2254
|
+
|
|
2255
|
+
//#endregion
|
|
2256
|
+
//#region src/core/TradingFee.ts
|
|
2257
|
+
var TradingFee_exports = /* @__PURE__ */ __exportAll({
|
|
2258
|
+
BREAKPOINTS: () => BREAKPOINTS,
|
|
2259
|
+
InvalidFeeError: () => InvalidFeeError,
|
|
2260
|
+
InvalidFeesLengthError: () => InvalidFeesLengthError,
|
|
2261
|
+
WAD: () => WAD,
|
|
2262
|
+
activate: () => activate,
|
|
2263
|
+
compute: () => compute,
|
|
2264
|
+
deactivate: () => deactivate,
|
|
2265
|
+
from: () => from$5,
|
|
2266
|
+
getFees: () => getFees,
|
|
2267
|
+
isActivated: () => isActivated
|
|
2268
|
+
});
|
|
2269
|
+
/**
|
|
2270
|
+
* Time breakpoints in seconds for piecewise linear fee interpolation.
|
|
2271
|
+
* Matches on-chain constants: 0d, 1d, 7d, 30d, 90d, 180d.
|
|
2272
|
+
*/
|
|
2273
|
+
const BREAKPOINTS = [
|
|
2274
|
+
0n,
|
|
2275
|
+
86400n,
|
|
2276
|
+
604800n,
|
|
2277
|
+
2592000n,
|
|
2278
|
+
7776000n,
|
|
2279
|
+
15552000n
|
|
2280
|
+
];
|
|
2281
|
+
/** WAD constant (1e18) for fee scaling. */
|
|
2282
|
+
const WAD = 10n ** 18n;
|
|
2283
|
+
/**
|
|
2284
|
+
* Create a TradingFee from an activation flag and 6 fee values.
|
|
2285
|
+
* @param activated - Whether the fee is active.
|
|
2286
|
+
* @param fees - Tuple of 6 fee values in WAD (one per breakpoint: 0d, 1d, 7d, 30d, 90d, 180d).
|
|
2287
|
+
* @returns A new TradingFee instance.
|
|
2288
|
+
* @throws {@link InvalidFeeError} if any fee exceeds WAD (100%).
|
|
2289
|
+
* @throws {@link InvalidFeesLengthError} if fees array doesn't have exactly 6 elements.
|
|
2290
|
+
*/
|
|
2291
|
+
function from$5(activated, fees) {
|
|
2292
|
+
if (fees.length !== 6) throw new InvalidFeesLengthError(fees.length);
|
|
2293
|
+
for (let i = 0; i < 6; i++) {
|
|
2294
|
+
const fee = fees[i];
|
|
2295
|
+
if (fee < 0n || fee > WAD) throw new InvalidFeeError(fee, i);
|
|
2296
|
+
}
|
|
2297
|
+
const frozenFees = Object.freeze([...fees]);
|
|
2298
|
+
return Object.freeze({
|
|
2299
|
+
_activated: activated,
|
|
2300
|
+
_fees: frozenFees
|
|
2301
|
+
});
|
|
2302
|
+
}
|
|
2303
|
+
/**
|
|
2304
|
+
* Compute the trading fee for a given time to maturity using piecewise linear interpolation.
|
|
2305
|
+
* @param tradingFee - The TradingFee instance.
|
|
2306
|
+
* @param timeToMaturity - Time to maturity in seconds.
|
|
2307
|
+
* @returns The interpolated fee in WAD. Returns 0n if not activated.
|
|
2308
|
+
*/
|
|
2309
|
+
function compute(tradingFee, timeToMaturity) {
|
|
2310
|
+
if (!tradingFee._activated) return 0n;
|
|
2311
|
+
const time = BigInt(Math.max(0, Math.floor(timeToMaturity)));
|
|
2312
|
+
if (time >= BREAKPOINTS[5]) return tradingFee._fees[5];
|
|
2313
|
+
const { index, start, end } = getSegment(time);
|
|
2314
|
+
const feeLower = tradingFee._fees[index];
|
|
2315
|
+
const feeUpper = tradingFee._fees[index + 1];
|
|
2316
|
+
const segmentLength = end - start;
|
|
2317
|
+
return (feeLower * (end - time) + feeUpper * (time - start)) / segmentLength;
|
|
2318
|
+
}
|
|
2319
|
+
/**
|
|
2320
|
+
* Check if the trading fee is activated.
|
|
2321
|
+
* @param tradingFee - The TradingFee instance.
|
|
2322
|
+
* @returns True if activated, false otherwise.
|
|
2323
|
+
*/
|
|
2324
|
+
function isActivated(tradingFee) {
|
|
2325
|
+
return tradingFee._activated;
|
|
2326
|
+
}
|
|
2327
|
+
/**
|
|
2328
|
+
* Create a new TradingFee with activation enabled.
|
|
2329
|
+
* @param tradingFee - The TradingFee instance.
|
|
2330
|
+
* @returns A new TradingFee with activated set to true.
|
|
2331
|
+
*/
|
|
2332
|
+
function activate(tradingFee) {
|
|
2333
|
+
return Object.freeze({
|
|
2334
|
+
_activated: true,
|
|
2335
|
+
_fees: tradingFee._fees
|
|
2336
|
+
});
|
|
2337
|
+
}
|
|
2338
|
+
/**
|
|
2339
|
+
* Create a new TradingFee with activation disabled.
|
|
2340
|
+
* @param tradingFee - The TradingFee instance.
|
|
2341
|
+
* @returns A new TradingFee with activated set to false.
|
|
2342
|
+
*/
|
|
2343
|
+
function deactivate(tradingFee) {
|
|
2344
|
+
return Object.freeze({
|
|
2345
|
+
_activated: false,
|
|
2346
|
+
_fees: tradingFee._fees
|
|
2347
|
+
});
|
|
2348
|
+
}
|
|
2349
|
+
/**
|
|
2350
|
+
* Get the fee values at each breakpoint.
|
|
2351
|
+
* @param tradingFee - The TradingFee instance.
|
|
2352
|
+
* @returns The tuple of 6 fee values.
|
|
2353
|
+
*/
|
|
2354
|
+
function getFees(tradingFee) {
|
|
2355
|
+
return tradingFee._fees;
|
|
2356
|
+
}
|
|
2357
|
+
/**
|
|
2358
|
+
* Determine which segment a timeToMaturity falls into for interpolation.
|
|
2359
|
+
* @param timeToMaturity - Time to maturity in seconds.
|
|
2360
|
+
* @returns Object with index, start, and end of the segment.
|
|
2361
|
+
*/
|
|
2362
|
+
function getSegment(timeToMaturity) {
|
|
2363
|
+
if (timeToMaturity < BREAKPOINTS[1]) return {
|
|
2364
|
+
index: 0,
|
|
2365
|
+
start: BREAKPOINTS[0],
|
|
2366
|
+
end: BREAKPOINTS[1]
|
|
2367
|
+
};
|
|
2368
|
+
if (timeToMaturity < BREAKPOINTS[2]) return {
|
|
2369
|
+
index: 1,
|
|
2370
|
+
start: BREAKPOINTS[1],
|
|
2371
|
+
end: BREAKPOINTS[2]
|
|
2372
|
+
};
|
|
2373
|
+
if (timeToMaturity < BREAKPOINTS[3]) return {
|
|
2374
|
+
index: 2,
|
|
2375
|
+
start: BREAKPOINTS[2],
|
|
2376
|
+
end: BREAKPOINTS[3]
|
|
2377
|
+
};
|
|
2378
|
+
if (timeToMaturity < BREAKPOINTS[4]) return {
|
|
2379
|
+
index: 3,
|
|
2380
|
+
start: BREAKPOINTS[3],
|
|
2381
|
+
end: BREAKPOINTS[4]
|
|
2382
|
+
};
|
|
2383
|
+
return {
|
|
2384
|
+
index: 4,
|
|
2385
|
+
start: BREAKPOINTS[4],
|
|
2386
|
+
end: BREAKPOINTS[5]
|
|
2387
|
+
};
|
|
2388
|
+
}
|
|
2389
|
+
/** Error thrown when a fee value is invalid (negative or exceeds WAD). */
|
|
2390
|
+
var InvalidFeeError = class extends BaseError {
|
|
2391
|
+
constructor(fee, index) {
|
|
2392
|
+
super(`Invalid fee at index ${index}: ${fee}. Fee must be between 0 and ${WAD} (WAD).`);
|
|
2393
|
+
_defineProperty(this, "name", "TradingFee.InvalidFeeError");
|
|
2394
|
+
}
|
|
2395
|
+
};
|
|
2396
|
+
/** Error thrown when fees array doesn't have exactly 6 elements. */
|
|
2397
|
+
var InvalidFeesLengthError = class extends BaseError {
|
|
2398
|
+
constructor(length) {
|
|
2399
|
+
super(`Invalid fees length: ${length}. Expected exactly 6 fee values.`);
|
|
2400
|
+
_defineProperty(this, "name", "TradingFee.InvalidFeesLengthError");
|
|
2401
|
+
}
|
|
2402
|
+
};
|
|
2403
|
+
|
|
2404
|
+
//#endregion
|
|
2405
|
+
//#region src/core/Transfer.ts
|
|
2406
|
+
var Transfer_exports = /* @__PURE__ */ __exportAll({ from: () => from$4 });
|
|
2407
|
+
/**
|
|
2408
|
+
* @constructor
|
|
2409
|
+
*
|
|
2410
|
+
* Creates a {@link Transfer}.
|
|
2411
|
+
* @param parameters - {@link from.Parameters}
|
|
2412
|
+
* @returns The created Transfer. {@link from.ReturnType}
|
|
2413
|
+
*
|
|
2414
|
+
* @example
|
|
2415
|
+
* ```ts
|
|
2416
|
+
* const transfer = Transfer.from({ id: "1", chainId: 1, contract: "0x123", from: "0x456", to: "0x789", value: 100n, blockNumber: 100n });
|
|
2417
|
+
* ```
|
|
2418
|
+
*/
|
|
2419
|
+
function from$4(parameters) {
|
|
2420
|
+
return {
|
|
2421
|
+
id: parameters.id,
|
|
2422
|
+
chainId: parameters.chainId,
|
|
2423
|
+
contract: parameters.contract.toLowerCase(),
|
|
2424
|
+
from: parameters.from.toLowerCase(),
|
|
2425
|
+
to: parameters.to.toLowerCase(),
|
|
2426
|
+
value: parameters.value,
|
|
2427
|
+
blockNumber: parameters.blockNumber
|
|
2428
|
+
};
|
|
2388
2429
|
}
|
|
2430
|
+
|
|
2431
|
+
//#endregion
|
|
2432
|
+
//#region src/core/Tree.ts
|
|
2433
|
+
var Tree_exports = /* @__PURE__ */ __exportAll({
|
|
2434
|
+
DecodeError: () => DecodeError,
|
|
2435
|
+
EncodeError: () => EncodeError,
|
|
2436
|
+
SignatureDomainError: () => SignatureDomainError,
|
|
2437
|
+
TreeError: () => TreeError,
|
|
2438
|
+
VERSION: () => VERSION,
|
|
2439
|
+
decode: () => decode,
|
|
2440
|
+
encode: () => encode,
|
|
2441
|
+
encodeUnsigned: () => encodeUnsigned,
|
|
2442
|
+
from: () => from$3,
|
|
2443
|
+
proofs: () => proofs,
|
|
2444
|
+
signatureDomain: () => signatureDomain,
|
|
2445
|
+
signatureTypes: () => signatureTypes
|
|
2446
|
+
});
|
|
2447
|
+
const VERSION = 1;
|
|
2448
|
+
/**
|
|
2449
|
+
* EIP-712 types for signing the tree root (Root(bytes32 root)).
|
|
2450
|
+
*/
|
|
2451
|
+
const signatureTypes = {
|
|
2452
|
+
EIP712Domain: [{
|
|
2453
|
+
name: "chainId",
|
|
2454
|
+
type: "uint256"
|
|
2455
|
+
}, {
|
|
2456
|
+
name: "verifyingContract",
|
|
2457
|
+
type: "address"
|
|
2458
|
+
}],
|
|
2459
|
+
Root: [{
|
|
2460
|
+
name: "root",
|
|
2461
|
+
type: "bytes32"
|
|
2462
|
+
}]
|
|
2463
|
+
};
|
|
2464
|
+
const normalizeHash = (hash) => hash.toLowerCase();
|
|
2465
|
+
/**
|
|
2466
|
+
* Builds a Merkle tree from a list of offers.
|
|
2467
|
+
*
|
|
2468
|
+
* Leaves are the offer `hash` values as `bytes32` and are deterministically
|
|
2469
|
+
* ordered following the StandardMerkleTree leaf ordering so that the resulting
|
|
2470
|
+
* root is stable regardless of the input order.
|
|
2471
|
+
*
|
|
2472
|
+
* @param offers - Offers to include in the tree.
|
|
2473
|
+
* @returns A `StandardMerkleTree` of `bytes32` leaves representing the offers.
|
|
2474
|
+
* @throws {TreeError} If tree building fails due to offer inconsistencies.
|
|
2475
|
+
*/
|
|
2476
|
+
const from$3 = (offers) => {
|
|
2477
|
+
const leaves = offers.map((offer) => [hash(offer)]);
|
|
2478
|
+
const tree = StandardMerkleTree.of(leaves, ["bytes32"]);
|
|
2479
|
+
const orderedOffers = orderOffers(tree, offers);
|
|
2480
|
+
return Object.assign(tree, { offers: orderedOffers });
|
|
2481
|
+
};
|
|
2482
|
+
const orderOffers = (tree, offers) => {
|
|
2483
|
+
const offerByHash = /* @__PURE__ */ new Map();
|
|
2484
|
+
for (const offer of offers) offerByHash.set(normalizeHash(hash(offer)), offer);
|
|
2485
|
+
const entries = tree.dump().values.map((value) => {
|
|
2486
|
+
const hash = normalizeHash(value.value[0]);
|
|
2487
|
+
const offer = offerByHash.get(hash);
|
|
2488
|
+
if (!offer) throw new TreeError(`missing offer for leaf ${hash}`);
|
|
2489
|
+
return {
|
|
2490
|
+
offer,
|
|
2491
|
+
treeIndex: value.treeIndex
|
|
2492
|
+
};
|
|
2493
|
+
});
|
|
2494
|
+
entries.sort((a, b) => b.treeIndex - a.treeIndex);
|
|
2495
|
+
return entries.map((item) => item.offer);
|
|
2496
|
+
};
|
|
2497
|
+
/**
|
|
2498
|
+
* Generates merkle proofs for all offers in a tree.
|
|
2499
|
+
*
|
|
2500
|
+
* Each proof allows independent verification that an offer is included in the tree
|
|
2501
|
+
* without requiring the full tree. Proofs are ordered by StandardMerkleTree leaf ordering.
|
|
2502
|
+
*
|
|
2503
|
+
* @param tree - The {@link Tree} to generate proofs for.
|
|
2504
|
+
* @returns Array of proofs - {@link Proof}
|
|
2505
|
+
*/
|
|
2506
|
+
const proofs = (tree) => {
|
|
2507
|
+
return tree.offers.map((offer) => {
|
|
2508
|
+
return {
|
|
2509
|
+
offer,
|
|
2510
|
+
path: tree.getProof([hash(offer)])
|
|
2511
|
+
};
|
|
2512
|
+
});
|
|
2513
|
+
};
|
|
2514
|
+
/**
|
|
2515
|
+
* Normalizes a Root signature domain (BigInt chain id, lowercase address).
|
|
2516
|
+
* @throws {SignatureDomainError} When the domain is invalid.
|
|
2517
|
+
*/
|
|
2518
|
+
const signatureDomain = (domain) => {
|
|
2519
|
+
return normalizeSignatureDomain(domain, (reason) => new SignatureDomainError(reason));
|
|
2520
|
+
};
|
|
2521
|
+
const normalizeSignatureDomain = (domain, errorFactory) => {
|
|
2522
|
+
let chainId;
|
|
2523
|
+
try {
|
|
2524
|
+
chainId = typeof domain.chainId === "bigint" ? domain.chainId : BigInt(domain.chainId);
|
|
2525
|
+
} catch {
|
|
2526
|
+
throw errorFactory("invalid chainId");
|
|
2527
|
+
}
|
|
2528
|
+
if (chainId < 0n) throw errorFactory("invalid chainId");
|
|
2529
|
+
if (!isAddress(domain.verifyingContract)) throw errorFactory("invalid verifyingContract");
|
|
2530
|
+
return {
|
|
2531
|
+
chainId,
|
|
2532
|
+
verifyingContract: domain.verifyingContract.toLowerCase()
|
|
2533
|
+
};
|
|
2534
|
+
};
|
|
2535
|
+
const assertHex = (value, expectedBytes, name, errorFactory = (reason) => new DecodeError(reason)) => {
|
|
2536
|
+
if (typeof value !== "string" || !isHex(value)) throw errorFactory(`${name} is not a valid hex string`);
|
|
2537
|
+
if (hexToBytes(value).length !== expectedBytes) throw errorFactory(`${name}: expected ${expectedBytes} bytes`);
|
|
2538
|
+
};
|
|
2539
|
+
const verifySignatureAndRecoverAddress = async (params) => {
|
|
2540
|
+
const { root, signature, domain, errorFactory } = params;
|
|
2541
|
+
assertHex(root, 32, "root", errorFactory);
|
|
2542
|
+
assertHex(signature, 65, "signature", errorFactory);
|
|
2543
|
+
const hash = hashTypedData({
|
|
2544
|
+
domain,
|
|
2545
|
+
types: signatureTypes,
|
|
2546
|
+
primaryType: "Root",
|
|
2547
|
+
message: { root }
|
|
2548
|
+
});
|
|
2549
|
+
try {
|
|
2550
|
+
return await recoverAddress({
|
|
2551
|
+
hash,
|
|
2552
|
+
signature
|
|
2553
|
+
});
|
|
2554
|
+
} catch {
|
|
2555
|
+
throw errorFactory("signature recovery failed");
|
|
2556
|
+
}
|
|
2557
|
+
};
|
|
2558
|
+
/**
|
|
2559
|
+
* Encodes a merkle tree with signature into hex calldata for onchain broadcast.
|
|
2560
|
+
*
|
|
2561
|
+
* Layout: `0x{vv}{gzip([...offers])}{root}{signature}` where:
|
|
2562
|
+
* - `{vv}`: 1-byte version (currently 0x01)
|
|
2563
|
+
* - `{gzip([...offers])}`: gzipped JSON array of serialized offers
|
|
2564
|
+
* - `{root}`: 32-byte merkle root
|
|
2565
|
+
* - `{signature}`: 65-byte EIP-712 signature over Root(bytes32 root)
|
|
2566
|
+
*
|
|
2567
|
+
* Validates signature authenticity and root integrity before encoding.
|
|
2568
|
+
*
|
|
2569
|
+
* @example
|
|
2570
|
+
* ```typescript
|
|
2571
|
+
* const tree = Tree.from(offers);
|
|
2572
|
+
* const signature = await wallet.signTypedData({
|
|
2573
|
+
* account: wallet.account,
|
|
2574
|
+
* domain: Tree.signatureDomain({ chainId, verifyingContract }),
|
|
2575
|
+
* types: Tree.signatureTypes,
|
|
2576
|
+
* primaryType: "Root",
|
|
2577
|
+
* message: { root: tree.root },
|
|
2578
|
+
* });
|
|
2579
|
+
* const calldata = await Tree.encode(tree, signature, { chainId, verifyingContract });
|
|
2580
|
+
* await broadcast(calldata);
|
|
2581
|
+
* ```
|
|
2582
|
+
*
|
|
2583
|
+
* @example
|
|
2584
|
+
* Manual construction (for advanced users):
|
|
2585
|
+
* ```typescript
|
|
2586
|
+
* const tree = Tree.from(offers);
|
|
2587
|
+
* const compressed = gzip(JSON.stringify(tree.offers.map(Offer.serialize)));
|
|
2588
|
+
* const partial = `0x01${bytesToHex(compressed)}${tree.root.slice(2)}`;
|
|
2589
|
+
* const signature = await wallet.signTypedData({
|
|
2590
|
+
* account: wallet.account,
|
|
2591
|
+
* domain: Tree.signatureDomain({ chainId, verifyingContract }),
|
|
2592
|
+
* types: Tree.signatureTypes,
|
|
2593
|
+
* primaryType: "Root",
|
|
2594
|
+
* message: { root: tree.root },
|
|
2595
|
+
* });
|
|
2596
|
+
* const calldata = `${partial}${signature.slice(2)}`;
|
|
2597
|
+
* ```
|
|
2598
|
+
*
|
|
2599
|
+
* @param tree - Merkle tree of offers
|
|
2600
|
+
* @param signature - EIP-712 signature over Root(bytes32 root)
|
|
2601
|
+
* @param domain - EIP-712 domain with chain id and verifying contract
|
|
2602
|
+
* @returns Hex-encoded calldata ready for onchain broadcast
|
|
2603
|
+
* @throws {EncodeError} If signature verification fails or root mismatch
|
|
2604
|
+
*/
|
|
2605
|
+
const encode = async (tree, signature, domain) => {
|
|
2606
|
+
const errorFactory = (reason) => new EncodeError(reason);
|
|
2607
|
+
const normalizedDomain = normalizeSignatureDomain(domain, errorFactory);
|
|
2608
|
+
validateTreeForEncoding(tree, normalizedDomain);
|
|
2609
|
+
await verifySignatureAndRecoverAddress({
|
|
2610
|
+
root: tree.root,
|
|
2611
|
+
signature,
|
|
2612
|
+
domain: normalizedDomain,
|
|
2613
|
+
errorFactory
|
|
2614
|
+
});
|
|
2615
|
+
const unsigned = encodeUnsignedBytes(tree);
|
|
2616
|
+
const sigBytes = hexToBytes(signature);
|
|
2617
|
+
const encoded = new Uint8Array(unsigned.length + sigBytes.length);
|
|
2618
|
+
encoded.set(unsigned, 0);
|
|
2619
|
+
encoded.set(sigBytes, unsigned.length);
|
|
2620
|
+
return bytesToHex(encoded);
|
|
2621
|
+
};
|
|
2622
|
+
/**
|
|
2623
|
+
* Encodes a merkle tree without a signature into hex payload for client-side signing.
|
|
2624
|
+
*
|
|
2625
|
+
* Layout: `0x{vv}{gzip([...offers])}{root}` where:
|
|
2626
|
+
* - `{vv}`: 1-byte version (currently 0x01)
|
|
2627
|
+
* - `{gzip([...offers])}`: gzipped JSON array of serialized offers
|
|
2628
|
+
* - `{root}`: 32-byte merkle root
|
|
2629
|
+
*
|
|
2630
|
+
* Validates root integrity before encoding.
|
|
2631
|
+
*
|
|
2632
|
+
* @param tree - Merkle tree of offers
|
|
2633
|
+
* @returns Hex-encoded unsigned payload
|
|
2634
|
+
* @throws {EncodeError} If root mismatch
|
|
2635
|
+
*/
|
|
2636
|
+
const encodeUnsigned = (tree) => {
|
|
2637
|
+
validateTreeForEncoding(tree);
|
|
2638
|
+
return bytesToHex(encodeUnsignedBytes(tree));
|
|
2639
|
+
};
|
|
2640
|
+
const validateTreeForEncoding = (tree, domain) => {
|
|
2641
|
+
if (VERSION > 255) throw new EncodeError(`version overflow: ${VERSION} exceeds 255`);
|
|
2642
|
+
const computed = from$3(tree.offers);
|
|
2643
|
+
if (tree.root !== computed.root) throw new EncodeError(`root mismatch: expected ${computed.root}, got ${tree.root}`);
|
|
2644
|
+
if (domain) {
|
|
2645
|
+
const mismatched = tree.offers.find((offer) => BigInt(offer.chainId) !== domain.chainId);
|
|
2646
|
+
if (mismatched) throw new EncodeError(`chainId mismatch: expected ${domain.chainId}, got ${mismatched.chainId}`);
|
|
2647
|
+
}
|
|
2648
|
+
};
|
|
2649
|
+
const encodeUnsignedBytes = (tree) => {
|
|
2650
|
+
const offersPayload = tree.offers.map(serialize);
|
|
2651
|
+
const compressed = gzip(JSON.stringify(offersPayload));
|
|
2652
|
+
const rootBytes = hexToBytes(tree.root);
|
|
2653
|
+
const encoded = new Uint8Array(1 + compressed.length + 32);
|
|
2654
|
+
encoded[0] = VERSION;
|
|
2655
|
+
encoded.set(compressed, 1);
|
|
2656
|
+
encoded.set(rootBytes, 1 + compressed.length);
|
|
2657
|
+
return encoded;
|
|
2658
|
+
};
|
|
2659
|
+
/**
|
|
2660
|
+
* Decodes hex calldata into a validated merkle tree.
|
|
2661
|
+
*
|
|
2662
|
+
* Validates signature before decompression for fail-fast rejection of invalid payloads.
|
|
2663
|
+
* Returns the tree with separately validated signature and recovered signer address.
|
|
2664
|
+
*
|
|
2665
|
+
* Validation order:
|
|
2666
|
+
* 1. Version check
|
|
2667
|
+
* 2. Signature verification (fail-fast, before decompression)
|
|
2668
|
+
* 3. Decompression (only if signature valid)
|
|
2669
|
+
* 4. Root verification (computed from offers vs embedded root)
|
|
2670
|
+
*
|
|
2671
|
+
* @example
|
|
2672
|
+
* ```typescript
|
|
2673
|
+
* const { tree, signature, signer } = await Tree.decode(calldata, { chainId, verifyingContract });
|
|
2674
|
+
* console.log(`Tree signed by ${signer} with ${tree.offers.length} offers`);
|
|
2675
|
+
* ```
|
|
2676
|
+
*
|
|
2677
|
+
* @param encoded - Hex calldata in format `0x{vv}{gzip}{root}{signature}`
|
|
2678
|
+
* @param domain - EIP-712 domain with chain id and verifying contract
|
|
2679
|
+
* @returns Validated tree, signature, and recovered signer address
|
|
2680
|
+
* @throws {DecodeError} If version invalid, signature invalid, or root mismatch
|
|
2681
|
+
*/
|
|
2682
|
+
const decode = async (encoded, domain) => {
|
|
2683
|
+
const errorFactory = (reason) => new DecodeError(reason);
|
|
2684
|
+
const normalizedDomain = normalizeSignatureDomain(domain, errorFactory);
|
|
2685
|
+
const bytes = hexToBytes(encoded);
|
|
2686
|
+
if (bytes.length < 98) throw new DecodeError("payload too short");
|
|
2687
|
+
const version = bytes[0];
|
|
2688
|
+
if (version !== (VERSION & 255)) throw new DecodeError(`invalid version: expected ${VERSION}, got ${version ?? 0}`);
|
|
2689
|
+
const signature = bytesToHex(bytes.slice(-65));
|
|
2690
|
+
const root = bytesToHex(bytes.slice(-97, -65));
|
|
2691
|
+
assertHex(root, 32, "root");
|
|
2692
|
+
assertHex(signature, 65, "signature");
|
|
2693
|
+
const signer = await verifySignatureAndRecoverAddress({
|
|
2694
|
+
root,
|
|
2695
|
+
signature,
|
|
2696
|
+
domain: normalizedDomain,
|
|
2697
|
+
errorFactory
|
|
2698
|
+
});
|
|
2699
|
+
const compressed = bytes.slice(1, -97);
|
|
2700
|
+
let decoded;
|
|
2701
|
+
try {
|
|
2702
|
+
decoded = ungzip(compressed, { to: "string" });
|
|
2703
|
+
} catch {
|
|
2704
|
+
throw new DecodeError("decompression failed");
|
|
2705
|
+
}
|
|
2706
|
+
let rawOffers;
|
|
2707
|
+
try {
|
|
2708
|
+
rawOffers = JSON.parse(decoded);
|
|
2709
|
+
} catch {
|
|
2710
|
+
throw new DecodeError("JSON parse failed");
|
|
2711
|
+
}
|
|
2712
|
+
const tree = from$3(rawOffers.map((o) => OfferSchema().parse(o)));
|
|
2713
|
+
if (root !== tree.root) throw new DecodeError(`root mismatch: expected ${tree.root}, got ${root}`);
|
|
2714
|
+
const chainIdMismatch = tree.offers.find((offer) => BigInt(offer.chainId) !== normalizedDomain.chainId);
|
|
2715
|
+
if (chainIdMismatch) throw new DecodeError(`chainId mismatch: expected ${normalizedDomain.chainId}, got ${chainIdMismatch.chainId}`);
|
|
2716
|
+
return {
|
|
2717
|
+
tree,
|
|
2718
|
+
signature,
|
|
2719
|
+
signer
|
|
2720
|
+
};
|
|
2721
|
+
};
|
|
2722
|
+
/**
|
|
2723
|
+
* Error thrown during tree building operations.
|
|
2724
|
+
* Indicates structural issues with the tree (missing offers, inconsistent state).
|
|
2725
|
+
*/
|
|
2726
|
+
var TreeError = class extends BaseError {
|
|
2727
|
+
constructor(reason) {
|
|
2728
|
+
super(`Tree error: ${reason}`);
|
|
2729
|
+
_defineProperty(this, "name", "Tree.TreeError");
|
|
2730
|
+
}
|
|
2731
|
+
};
|
|
2732
|
+
/**
|
|
2733
|
+
* Error thrown during tree encoding.
|
|
2734
|
+
* Indicates validation failures (signature, root mismatch, mixed makers).
|
|
2735
|
+
*/
|
|
2736
|
+
var EncodeError = class extends BaseError {
|
|
2737
|
+
constructor(reason) {
|
|
2738
|
+
super(`Failed to encode tree: ${reason}`);
|
|
2739
|
+
_defineProperty(this, "name", "Tree.EncodeError");
|
|
2740
|
+
}
|
|
2741
|
+
};
|
|
2389
2742
|
/**
|
|
2390
|
-
*
|
|
2391
|
-
*
|
|
2392
|
-
*
|
|
2393
|
-
* @example
|
|
2394
|
-
* ```ts
|
|
2395
|
-
* const quote = Quote.random();
|
|
2396
|
-
* ```
|
|
2743
|
+
* Error thrown during tree decoding.
|
|
2744
|
+
* Indicates payload corruption, version mismatch, or validation failures.
|
|
2397
2745
|
*/
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
bid: { price: BigInt(int(1e6)) }
|
|
2403
|
-
});
|
|
2404
|
-
}
|
|
2405
|
-
var InvalidQuoteError = class extends BaseError {
|
|
2406
|
-
constructor(error) {
|
|
2407
|
-
super("Invalid quote.", { cause: error });
|
|
2408
|
-
_defineProperty(this, "name", "Quote.InvalidQuoteError");
|
|
2746
|
+
var DecodeError = class extends BaseError {
|
|
2747
|
+
constructor(reason) {
|
|
2748
|
+
super(`Failed to decode tree: ${reason}`);
|
|
2749
|
+
_defineProperty(this, "name", "Tree.DecodeError");
|
|
2409
2750
|
}
|
|
2410
2751
|
};
|
|
2411
|
-
|
|
2412
|
-
//#endregion
|
|
2413
|
-
//#region src/core/Transfer.ts
|
|
2414
|
-
var Transfer_exports = /* @__PURE__ */ __export({ from: () => from$3 });
|
|
2415
2752
|
/**
|
|
2416
|
-
*
|
|
2417
|
-
*
|
|
2418
|
-
* Creates a {@link Transfer}.
|
|
2419
|
-
* @param parameters - {@link from.Parameters}
|
|
2420
|
-
* @returns The created Transfer. {@link from.ReturnType}
|
|
2421
|
-
*
|
|
2422
|
-
* @example
|
|
2423
|
-
* ```ts
|
|
2424
|
-
* const transfer = Transfer.from({ id: "1", chainId: 1, contract: "0x123", from: "0x456", to: "0x789", value: 100n, blockNumber: 100n });
|
|
2425
|
-
* ```
|
|
2753
|
+
* Error thrown when an invalid signature domain is supplied.
|
|
2426
2754
|
*/
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
to: parameters.to.toLowerCase(),
|
|
2434
|
-
value: parameters.value,
|
|
2435
|
-
blockNumber: parameters.blockNumber
|
|
2436
|
-
};
|
|
2437
|
-
}
|
|
2755
|
+
var SignatureDomainError = class extends BaseError {
|
|
2756
|
+
constructor(reason) {
|
|
2757
|
+
super(`Invalid signature domain: ${reason}`);
|
|
2758
|
+
_defineProperty(this, "name", "Tree.SignatureDomainError");
|
|
2759
|
+
}
|
|
2760
|
+
};
|
|
2438
2761
|
|
|
2439
2762
|
//#endregion
|
|
2440
2763
|
//#region src/core/types.ts
|
|
@@ -2442,7 +2765,7 @@ const BrandTypeId = Symbol.for("mempool/Brand");
|
|
|
2442
2765
|
|
|
2443
2766
|
//#endregion
|
|
2444
2767
|
//#region src/api/Schema/OfferResponse.ts
|
|
2445
|
-
var OfferResponse_exports = /* @__PURE__ */
|
|
2768
|
+
var OfferResponse_exports = /* @__PURE__ */ __exportAll({ from: () => from$2 });
|
|
2446
2769
|
/**
|
|
2447
2770
|
* Creates an `OfferResponse` matching the Solidity Offer struct layout.
|
|
2448
2771
|
* @constructor
|
|
@@ -2450,7 +2773,7 @@ var OfferResponse_exports = /* @__PURE__ */ __export({ from: () => from$2 });
|
|
|
2450
2773
|
* @returns The created `OfferResponse`. {@link OfferResponse}
|
|
2451
2774
|
*/
|
|
2452
2775
|
function from$2(input) {
|
|
2453
|
-
const base
|
|
2776
|
+
const base = {
|
|
2454
2777
|
offer: {
|
|
2455
2778
|
obligation: {
|
|
2456
2779
|
loan_token: input.loanToken,
|
|
@@ -2487,13 +2810,13 @@ function from$2(input) {
|
|
|
2487
2810
|
block_number: input.blockNumber
|
|
2488
2811
|
};
|
|
2489
2812
|
if (!input.proof || !input.root || !input.signature) return {
|
|
2490
|
-
...base
|
|
2813
|
+
...base,
|
|
2491
2814
|
root: null,
|
|
2492
2815
|
proof: null,
|
|
2493
2816
|
signature: null
|
|
2494
2817
|
};
|
|
2495
2818
|
return {
|
|
2496
|
-
...base
|
|
2819
|
+
...base,
|
|
2497
2820
|
root: input.root.toLowerCase(),
|
|
2498
2821
|
proof: input.proof.map((p) => p.toLowerCase()),
|
|
2499
2822
|
signature: input.signature.toLowerCase()
|
|
@@ -2510,7 +2833,7 @@ const API_ERROR_CODES = [
|
|
|
2510
2833
|
];
|
|
2511
2834
|
|
|
2512
2835
|
//#endregion
|
|
2513
|
-
//#region \0@oxc-project+runtime@0.
|
|
2836
|
+
//#region \0@oxc-project+runtime@0.110.0/helpers/decorate.js
|
|
2514
2837
|
function __decorate(decorators, target, key, desc) {
|
|
2515
2838
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2516
2839
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -2601,6 +2924,21 @@ const validateOfferExample = {
|
|
|
2601
2924
|
data: "0x00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000100000000000000000000000034cf890db685fc536e05652fb41f02090c3fb751000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000108e644e3ab01184155270aa92a00000000000"
|
|
2602
2925
|
}
|
|
2603
2926
|
};
|
|
2927
|
+
const callbackTypesRequestExample = { callbacks: [{
|
|
2928
|
+
chain_id: 1,
|
|
2929
|
+
addresses: [
|
|
2930
|
+
"0x1111111111111111111111111111111111111111",
|
|
2931
|
+
"0x3333333333333333333333333333333333333333",
|
|
2932
|
+
"0x9999999999999999999999999999999999999999"
|
|
2933
|
+
]
|
|
2934
|
+
}] };
|
|
2935
|
+
const callbackTypesResponseExample = [{
|
|
2936
|
+
chain_id: 1,
|
|
2937
|
+
sell_erc20_callback: ["0x1111111111111111111111111111111111111111"],
|
|
2938
|
+
buy_erc20: ["0x5555555555555555555555555555555555555555"],
|
|
2939
|
+
buy_vault_v1_callback: ["0x3333333333333333333333333333333333333333"],
|
|
2940
|
+
not_supported: ["0x9999999999999999999999999999999999999999"]
|
|
2941
|
+
}];
|
|
2604
2942
|
const routerStatusExample = {
|
|
2605
2943
|
status: "live",
|
|
2606
2944
|
initialized: true,
|
|
@@ -2669,6 +3007,55 @@ __decorate([ApiProperty({
|
|
|
2669
3007
|
type: "string",
|
|
2670
3008
|
example: validateOfferExample.callback.data
|
|
2671
3009
|
})], ValidateCallbackRequest.prototype, "data", void 0);
|
|
3010
|
+
var CallbackTypesChainRequest = class {};
|
|
3011
|
+
__decorate([ApiProperty({
|
|
3012
|
+
type: "number",
|
|
3013
|
+
example: callbackTypesRequestExample.callbacks[0].chain_id
|
|
3014
|
+
})], CallbackTypesChainRequest.prototype, "chain_id", void 0);
|
|
3015
|
+
__decorate([ApiProperty({
|
|
3016
|
+
type: () => [String],
|
|
3017
|
+
example: callbackTypesRequestExample.callbacks[0].addresses
|
|
3018
|
+
})], CallbackTypesChainRequest.prototype, "addresses", void 0);
|
|
3019
|
+
var CallbackTypesRequest = class {};
|
|
3020
|
+
__decorate([ApiProperty({
|
|
3021
|
+
type: () => [CallbackTypesChainRequest],
|
|
3022
|
+
example: callbackTypesRequestExample.callbacks
|
|
3023
|
+
})], CallbackTypesRequest.prototype, "callbacks", void 0);
|
|
3024
|
+
var CallbackTypesChainResponse = class {};
|
|
3025
|
+
__decorate([ApiProperty({
|
|
3026
|
+
type: "number",
|
|
3027
|
+
example: callbackTypesResponseExample[0].chain_id
|
|
3028
|
+
})], CallbackTypesChainResponse.prototype, "chain_id", void 0);
|
|
3029
|
+
__decorate([ApiProperty({
|
|
3030
|
+
type: () => [String],
|
|
3031
|
+
required: false,
|
|
3032
|
+
example: callbackTypesResponseExample[0].buy_vault_v1_callback
|
|
3033
|
+
})], CallbackTypesChainResponse.prototype, "buy_vault_v1_callback", void 0);
|
|
3034
|
+
__decorate([ApiProperty({
|
|
3035
|
+
type: () => [String],
|
|
3036
|
+
required: false,
|
|
3037
|
+
example: callbackTypesResponseExample[0].sell_erc20_callback
|
|
3038
|
+
})], CallbackTypesChainResponse.prototype, "sell_erc20_callback", void 0);
|
|
3039
|
+
__decorate([ApiProperty({
|
|
3040
|
+
type: () => [String],
|
|
3041
|
+
required: false,
|
|
3042
|
+
example: callbackTypesResponseExample[0].buy_erc20
|
|
3043
|
+
})], CallbackTypesChainResponse.prototype, "buy_erc20", void 0);
|
|
3044
|
+
__decorate([ApiProperty({
|
|
3045
|
+
type: () => [String],
|
|
3046
|
+
example: callbackTypesResponseExample[0].not_supported
|
|
3047
|
+
})], CallbackTypesChainResponse.prototype, "not_supported", void 0);
|
|
3048
|
+
var CallbackTypesSuccessResponse = class extends SuccessResponse {};
|
|
3049
|
+
__decorate([ApiProperty({
|
|
3050
|
+
type: "string",
|
|
3051
|
+
nullable: true,
|
|
3052
|
+
example: "maturity:1:1730415600:end_of_next_month"
|
|
3053
|
+
})], CallbackTypesSuccessResponse.prototype, "cursor", void 0);
|
|
3054
|
+
__decorate([ApiProperty({
|
|
3055
|
+
type: () => [CallbackTypesChainResponse],
|
|
3056
|
+
description: "Callback types grouped by chain.",
|
|
3057
|
+
example: callbackTypesResponseExample
|
|
3058
|
+
})], CallbackTypesSuccessResponse.prototype, "data", void 0);
|
|
2672
3059
|
var AskResponse = class {};
|
|
2673
3060
|
__decorate([ApiProperty({
|
|
2674
3061
|
type: "string",
|
|
@@ -3131,7 +3518,7 @@ __decorate([ApiProperty({
|
|
|
3131
3518
|
type: () => [BookLevelResponse],
|
|
3132
3519
|
description: "Aggregated book levels grouped by computed price."
|
|
3133
3520
|
})], BookListResponse.prototype, "data", void 0);
|
|
3134
|
-
let BooksController = class BooksController
|
|
3521
|
+
let BooksController = class BooksController {
|
|
3135
3522
|
async getBook() {}
|
|
3136
3523
|
};
|
|
3137
3524
|
__decorate([
|
|
@@ -3177,7 +3564,7 @@ BooksController = __decorate([ApiTags("Markets"), ApiResponse({
|
|
|
3177
3564
|
description: "Bad Request",
|
|
3178
3565
|
type: BadRequestResponse
|
|
3179
3566
|
})], BooksController);
|
|
3180
|
-
let ValidateController = class ValidateController
|
|
3567
|
+
let ValidateController = class ValidateController {
|
|
3181
3568
|
async validateOffers() {}
|
|
3182
3569
|
};
|
|
3183
3570
|
__decorate([
|
|
@@ -3204,7 +3591,29 @@ ValidateController = __decorate([ApiTags("Make"), ApiResponse({
|
|
|
3204
3591
|
description: "Bad Request",
|
|
3205
3592
|
type: BadRequestResponse
|
|
3206
3593
|
})], ValidateController);
|
|
3207
|
-
let
|
|
3594
|
+
let CallbacksController = class CallbacksController {
|
|
3595
|
+
async resolveCallbackTypes() {}
|
|
3596
|
+
};
|
|
3597
|
+
__decorate([
|
|
3598
|
+
ApiOperation({
|
|
3599
|
+
methods: ["post"],
|
|
3600
|
+
path: "/v1/callbacks",
|
|
3601
|
+
summary: "Resolve callback types",
|
|
3602
|
+
description: "Returns callback types for callback addresses grouped by chain."
|
|
3603
|
+
}),
|
|
3604
|
+
ApiBody({ type: CallbackTypesRequest }),
|
|
3605
|
+
ApiResponse({
|
|
3606
|
+
status: 200,
|
|
3607
|
+
description: "Success",
|
|
3608
|
+
type: CallbackTypesSuccessResponse
|
|
3609
|
+
})
|
|
3610
|
+
], CallbacksController.prototype, "resolveCallbackTypes", null);
|
|
3611
|
+
CallbacksController = __decorate([ApiTags("Make"), ApiResponse({
|
|
3612
|
+
status: 400,
|
|
3613
|
+
description: "Bad Request",
|
|
3614
|
+
type: BadRequestResponse
|
|
3615
|
+
})], CallbacksController);
|
|
3616
|
+
let OffersController = class OffersController {
|
|
3208
3617
|
async getOffers() {}
|
|
3209
3618
|
};
|
|
3210
3619
|
__decorate([
|
|
@@ -3259,7 +3668,7 @@ OffersController = __decorate([ApiTags("Markets"), ApiResponse({
|
|
|
3259
3668
|
description: "Bad Request",
|
|
3260
3669
|
type: BadRequestResponse
|
|
3261
3670
|
})], OffersController);
|
|
3262
|
-
let HealthController = class HealthController
|
|
3671
|
+
let HealthController = class HealthController {
|
|
3263
3672
|
async getRouterStatus() {}
|
|
3264
3673
|
async getCollectorsHealth() {}
|
|
3265
3674
|
async getChainsHealth() {}
|
|
@@ -3325,68 +3734,222 @@ __decorate([
|
|
|
3325
3734
|
})
|
|
3326
3735
|
], HealthController.prototype, "getChainsHealth", null);
|
|
3327
3736
|
HealthController = __decorate([ApiTags("System")], HealthController);
|
|
3328
|
-
const
|
|
3329
|
-
end_of_month: 1738335600,
|
|
3330
|
-
end_of_next_month: 1740754800
|
|
3331
|
-
};
|
|
3332
|
-
const chainConfigExample = {
|
|
3737
|
+
const configContractsExample = {
|
|
3333
3738
|
chain_id: 505050505,
|
|
3334
|
-
|
|
3335
|
-
|
|
3739
|
+
address: "0xD946246695A9259F3B33a78629026F61B3Ab40aF",
|
|
3740
|
+
name: "mempool"
|
|
3741
|
+
};
|
|
3742
|
+
const configContractsPayloadExample = [
|
|
3743
|
+
{
|
|
3744
|
+
chain_id: 505050505,
|
|
3745
|
+
address: "0xD946246695A9259F3B33a78629026F61B3Ab40aF",
|
|
3746
|
+
name: "mempool"
|
|
3747
|
+
},
|
|
3748
|
+
{
|
|
3749
|
+
chain_id: 505050505,
|
|
3750
|
+
address: "0x8A409D5D6394fC197c596d4E6E2c35e5d13f8a4d",
|
|
3751
|
+
name: "multicall"
|
|
3752
|
+
},
|
|
3753
|
+
{
|
|
3754
|
+
chain_id: 505050505,
|
|
3755
|
+
address: "0x23DFBc4B8B80C14CC5e25011B8491f268395BAd6",
|
|
3756
|
+
name: "v2"
|
|
3757
|
+
}
|
|
3758
|
+
];
|
|
3759
|
+
const configRulesMaturityExample = {
|
|
3760
|
+
type: "maturity",
|
|
3761
|
+
chain_id: 1,
|
|
3762
|
+
name: "end_of_next_month",
|
|
3763
|
+
timestamp: 1730415600
|
|
3764
|
+
};
|
|
3765
|
+
const configRulesCallbackExample = {
|
|
3766
|
+
type: "callback",
|
|
3767
|
+
chain_id: 1,
|
|
3768
|
+
address: "0x1111111111111111111111111111111111111111",
|
|
3769
|
+
callback_type: "sell_erc20_callback"
|
|
3770
|
+
};
|
|
3771
|
+
const configRulesLoanTokenExample = {
|
|
3772
|
+
type: "loan_token",
|
|
3773
|
+
chain_id: 1,
|
|
3774
|
+
address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
|
|
3336
3775
|
};
|
|
3337
|
-
|
|
3776
|
+
const configRulesChecksumExample = "f1d2d2f924e986ac86fdf7b36c94bcdf";
|
|
3777
|
+
const configRulesPayloadExample = [
|
|
3778
|
+
configRulesMaturityExample,
|
|
3779
|
+
configRulesCallbackExample,
|
|
3780
|
+
configRulesLoanTokenExample
|
|
3781
|
+
];
|
|
3782
|
+
const configContractNames = [
|
|
3783
|
+
"mempool",
|
|
3784
|
+
"multicall",
|
|
3785
|
+
"v2"
|
|
3786
|
+
];
|
|
3787
|
+
const configContractsCursorExample = "505050505:0xd946246695a9259f3b33a78629026f61b3ab40af";
|
|
3788
|
+
var ConfigContractResponse = class {};
|
|
3789
|
+
__decorate([ApiProperty({
|
|
3790
|
+
type: "number",
|
|
3791
|
+
example: configContractsExample.chain_id
|
|
3792
|
+
})], ConfigContractResponse.prototype, "chain_id", void 0);
|
|
3338
3793
|
__decorate([ApiProperty({
|
|
3339
3794
|
type: "string",
|
|
3340
|
-
example:
|
|
3341
|
-
})],
|
|
3342
|
-
var MaturitiesResponse = class {};
|
|
3795
|
+
example: configContractsExample.address
|
|
3796
|
+
})], ConfigContractResponse.prototype, "address", void 0);
|
|
3343
3797
|
__decorate([ApiProperty({
|
|
3344
|
-
type: "
|
|
3345
|
-
|
|
3346
|
-
example:
|
|
3347
|
-
})],
|
|
3798
|
+
type: "string",
|
|
3799
|
+
enum: configContractNames,
|
|
3800
|
+
example: configContractsExample.name
|
|
3801
|
+
})], ConfigContractResponse.prototype, "name", void 0);
|
|
3802
|
+
var ConfigContractsSuccessResponse = class extends SuccessResponse {};
|
|
3803
|
+
__decorate([ApiProperty({
|
|
3804
|
+
type: "string",
|
|
3805
|
+
nullable: true,
|
|
3806
|
+
example: null
|
|
3807
|
+
})], ConfigContractsSuccessResponse.prototype, "cursor", void 0);
|
|
3808
|
+
__decorate([ApiProperty({
|
|
3809
|
+
type: () => [ConfigContractResponse],
|
|
3810
|
+
description: "Indexer contract configuration for all indexed chains.",
|
|
3811
|
+
example: configContractsPayloadExample
|
|
3812
|
+
})], ConfigContractsSuccessResponse.prototype, "data", void 0);
|
|
3813
|
+
var ConfigRulesMeta = class {};
|
|
3814
|
+
__decorate([ApiProperty({
|
|
3815
|
+
type: "string",
|
|
3816
|
+
example: timestampExample
|
|
3817
|
+
})], ConfigRulesMeta.prototype, "timestamp", void 0);
|
|
3818
|
+
__decorate([ApiProperty({
|
|
3819
|
+
type: "string",
|
|
3820
|
+
example: configRulesChecksumExample
|
|
3821
|
+
})], ConfigRulesMeta.prototype, "checksum", void 0);
|
|
3822
|
+
var ConfigRulesRuleResponse = class {};
|
|
3823
|
+
__decorate([ApiProperty({
|
|
3824
|
+
type: "string",
|
|
3825
|
+
example: configRulesMaturityExample.type
|
|
3826
|
+
})], ConfigRulesRuleResponse.prototype, "type", void 0);
|
|
3348
3827
|
__decorate([ApiProperty({
|
|
3349
3828
|
type: "number",
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3829
|
+
example: configRulesMaturityExample.chain_id
|
|
3830
|
+
})], ConfigRulesRuleResponse.prototype, "chain_id", void 0);
|
|
3831
|
+
__decorate([ApiProperty({
|
|
3832
|
+
type: "string",
|
|
3833
|
+
example: configRulesMaturityExample.name,
|
|
3834
|
+
required: false
|
|
3835
|
+
})], ConfigRulesRuleResponse.prototype, "name", void 0);
|
|
3354
3836
|
__decorate([ApiProperty({
|
|
3355
3837
|
type: "number",
|
|
3356
|
-
example:
|
|
3357
|
-
|
|
3358
|
-
|
|
3838
|
+
example: configRulesMaturityExample.timestamp,
|
|
3839
|
+
required: false
|
|
3840
|
+
})], ConfigRulesRuleResponse.prototype, "timestamp", void 0);
|
|
3841
|
+
__decorate([ApiProperty({
|
|
3842
|
+
type: "string",
|
|
3843
|
+
example: configRulesCallbackExample.address,
|
|
3844
|
+
required: false
|
|
3845
|
+
})], ConfigRulesRuleResponse.prototype, "address", void 0);
|
|
3359
3846
|
__decorate([ApiProperty({
|
|
3360
|
-
type:
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
})],
|
|
3364
|
-
var
|
|
3847
|
+
type: "string",
|
|
3848
|
+
example: configRulesCallbackExample.callback_type,
|
|
3849
|
+
required: false
|
|
3850
|
+
})], ConfigRulesRuleResponse.prototype, "callback_type", void 0);
|
|
3851
|
+
var ConfigRulesSuccessResponse = class {};
|
|
3852
|
+
__decorate([ApiProperty({ type: () => ConfigRulesMeta })], ConfigRulesSuccessResponse.prototype, "meta", void 0);
|
|
3365
3853
|
__decorate([ApiProperty({
|
|
3366
3854
|
type: "string",
|
|
3367
3855
|
nullable: true,
|
|
3368
3856
|
example: null
|
|
3369
|
-
})],
|
|
3370
|
-
__decorate([ApiProperty({
|
|
3371
|
-
type: () => [
|
|
3372
|
-
description: "
|
|
3373
|
-
example:
|
|
3374
|
-
})],
|
|
3375
|
-
let
|
|
3376
|
-
async
|
|
3857
|
+
})], ConfigRulesSuccessResponse.prototype, "cursor", void 0);
|
|
3858
|
+
__decorate([ApiProperty({
|
|
3859
|
+
type: () => [ConfigRulesRuleResponse],
|
|
3860
|
+
description: "Configured rules returned by the router API.",
|
|
3861
|
+
example: configRulesPayloadExample
|
|
3862
|
+
})], ConfigRulesSuccessResponse.prototype, "data", void 0);
|
|
3863
|
+
let ConfigContractsController = class ConfigContractsController {
|
|
3864
|
+
async getConfigContracts() {}
|
|
3865
|
+
};
|
|
3866
|
+
__decorate([
|
|
3867
|
+
ApiOperation({
|
|
3868
|
+
methods: ["get"],
|
|
3869
|
+
path: "/v1/config/contracts",
|
|
3870
|
+
summary: "Get indexer contract configuration",
|
|
3871
|
+
description: "Returns contract addresses used by indexers (mempool, v2) and multicall for indexed chains."
|
|
3872
|
+
}),
|
|
3873
|
+
ApiQuery({
|
|
3874
|
+
name: "cursor",
|
|
3875
|
+
type: "string",
|
|
3876
|
+
required: false,
|
|
3877
|
+
example: configContractsCursorExample,
|
|
3878
|
+
description: "Pagination cursor in chain_id:address format (lowercase address)."
|
|
3879
|
+
}),
|
|
3880
|
+
ApiQuery({
|
|
3881
|
+
name: "limit",
|
|
3882
|
+
type: "number",
|
|
3883
|
+
required: false,
|
|
3884
|
+
example: 1e3,
|
|
3885
|
+
description: "Maximum number of contracts to return (max 1000)."
|
|
3886
|
+
}),
|
|
3887
|
+
ApiQuery({
|
|
3888
|
+
name: "chains",
|
|
3889
|
+
type: ["number"],
|
|
3890
|
+
required: false,
|
|
3891
|
+
example: "1,8453",
|
|
3892
|
+
description: "Filter by chain IDs (comma-separated).",
|
|
3893
|
+
style: "form",
|
|
3894
|
+
explode: false
|
|
3895
|
+
}),
|
|
3896
|
+
ApiResponse({
|
|
3897
|
+
status: 200,
|
|
3898
|
+
description: "Success",
|
|
3899
|
+
type: ConfigContractsSuccessResponse
|
|
3900
|
+
})
|
|
3901
|
+
], ConfigContractsController.prototype, "getConfigContracts", null);
|
|
3902
|
+
ConfigContractsController = __decorate([ApiTags("System")], ConfigContractsController);
|
|
3903
|
+
let ConfigRulesController = class ConfigRulesController {
|
|
3904
|
+
async getConfigRules() {}
|
|
3377
3905
|
};
|
|
3378
|
-
__decorate([
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3906
|
+
__decorate([
|
|
3907
|
+
ApiOperation({
|
|
3908
|
+
methods: ["get"],
|
|
3909
|
+
path: "/v1/config/rules",
|
|
3910
|
+
summary: "Get config rules",
|
|
3911
|
+
description: "Returns configured rules for supported chains."
|
|
3912
|
+
}),
|
|
3913
|
+
ApiQuery({
|
|
3914
|
+
name: "cursor",
|
|
3915
|
+
type: "string",
|
|
3916
|
+
required: false,
|
|
3917
|
+
example: "maturity:1:1730415600:end_of_next_month",
|
|
3918
|
+
description: "Pagination cursor in type:chain_id:<value> format."
|
|
3919
|
+
}),
|
|
3920
|
+
ApiQuery({
|
|
3921
|
+
name: "limit",
|
|
3922
|
+
type: "number",
|
|
3923
|
+
required: false,
|
|
3924
|
+
example: 100,
|
|
3925
|
+
description: "Maximum number of rules to return (max 1000)."
|
|
3926
|
+
}),
|
|
3927
|
+
ApiQuery({
|
|
3928
|
+
name: "types",
|
|
3929
|
+
type: ["string"],
|
|
3930
|
+
required: false,
|
|
3931
|
+
example: "maturity,loan_token",
|
|
3932
|
+
description: "Filter by rule types (comma-separated).",
|
|
3933
|
+
style: "form",
|
|
3934
|
+
explode: false
|
|
3935
|
+
}),
|
|
3936
|
+
ApiQuery({
|
|
3937
|
+
name: "chains",
|
|
3938
|
+
type: ["number"],
|
|
3939
|
+
required: false,
|
|
3940
|
+
example: "1,8453",
|
|
3941
|
+
description: "Filter by chain IDs (comma-separated).",
|
|
3942
|
+
style: "form",
|
|
3943
|
+
explode: false
|
|
3944
|
+
}),
|
|
3945
|
+
ApiResponse({
|
|
3946
|
+
status: 200,
|
|
3947
|
+
description: "Success",
|
|
3948
|
+
type: ConfigRulesSuccessResponse
|
|
3949
|
+
})
|
|
3950
|
+
], ConfigRulesController.prototype, "getConfigRules", null);
|
|
3951
|
+
ConfigRulesController = __decorate([ApiTags("System")], ConfigRulesController);
|
|
3952
|
+
let ObligationsController = class ObligationsController {
|
|
3390
3953
|
async getObligations() {}
|
|
3391
3954
|
async getObligation() {}
|
|
3392
3955
|
};
|
|
@@ -3410,32 +3973,40 @@ __decorate([
|
|
|
3410
3973
|
description: "Maximum number of obligations to return."
|
|
3411
3974
|
}),
|
|
3412
3975
|
ApiQuery({
|
|
3413
|
-
name: "
|
|
3414
|
-
type: "number",
|
|
3976
|
+
name: "chains",
|
|
3977
|
+
type: ["number"],
|
|
3415
3978
|
required: false,
|
|
3416
|
-
example: 1,
|
|
3417
|
-
description: "Filter by chain
|
|
3979
|
+
example: "1,8453",
|
|
3980
|
+
description: "Filter by chain IDs (comma-separated).",
|
|
3981
|
+
style: "form",
|
|
3982
|
+
explode: false
|
|
3418
3983
|
}),
|
|
3419
3984
|
ApiQuery({
|
|
3420
|
-
name: "
|
|
3421
|
-
type: "string",
|
|
3985
|
+
name: "loan_tokens",
|
|
3986
|
+
type: ["string"],
|
|
3422
3987
|
required: false,
|
|
3423
|
-
example: "0xC9A9C45C0eB717f8b5F193Af6bAa05A1c0Ac5078",
|
|
3424
|
-
description: "Filter by loan token
|
|
3988
|
+
example: "0xC9A9C45C0eB717f8b5F193Af6bAa05A1c0Ac5078,0x34Cf890dB685FC536E05652FB41f02090c3fb751",
|
|
3989
|
+
description: "Filter by loan token addresses (comma-separated).",
|
|
3990
|
+
style: "form",
|
|
3991
|
+
explode: false
|
|
3425
3992
|
}),
|
|
3426
3993
|
ApiQuery({
|
|
3427
|
-
name: "
|
|
3428
|
-
type: "string",
|
|
3994
|
+
name: "collateral_tokens",
|
|
3995
|
+
type: ["string"],
|
|
3429
3996
|
required: false,
|
|
3430
|
-
example: "0x34Cf890dB685FC536E05652FB41f02090c3fb751",
|
|
3431
|
-
description: "Filter by collateral
|
|
3997
|
+
example: "0x34Cf890dB685FC536E05652FB41f02090c3fb751,0xC9A9C45C0eB717f8b5F193Af6bAa05A1c0Ac5078",
|
|
3998
|
+
description: "Filter by collateral tokens (comma-separated, matches any collateral).",
|
|
3999
|
+
style: "form",
|
|
4000
|
+
explode: false
|
|
3432
4001
|
}),
|
|
3433
4002
|
ApiQuery({
|
|
3434
|
-
name: "
|
|
3435
|
-
type: "number",
|
|
4003
|
+
name: "maturities",
|
|
4004
|
+
type: ["number"],
|
|
3436
4005
|
required: false,
|
|
3437
|
-
example: 1761922800,
|
|
3438
|
-
description: "Filter by exact maturity
|
|
4006
|
+
example: "1761922800,1764524800",
|
|
4007
|
+
description: "Filter by exact maturity timestamps (comma-separated, unix seconds).",
|
|
4008
|
+
style: "form",
|
|
4009
|
+
explode: false
|
|
3439
4010
|
}),
|
|
3440
4011
|
ApiResponse({
|
|
3441
4012
|
status: 200,
|
|
@@ -3467,7 +4038,7 @@ ObligationsController = __decorate([ApiTags("Markets"), ApiResponse({
|
|
|
3467
4038
|
description: "Bad Request",
|
|
3468
4039
|
type: BadRequestResponse
|
|
3469
4040
|
})], ObligationsController);
|
|
3470
|
-
let UsersController = class UsersController
|
|
4041
|
+
let UsersController = class UsersController {
|
|
3471
4042
|
async getUserPositions() {}
|
|
3472
4043
|
};
|
|
3473
4044
|
__decorate([
|
|
@@ -3506,16 +4077,18 @@ UsersController = __decorate([ApiTags("Make"), ApiResponse({
|
|
|
3506
4077
|
description: "Bad Request",
|
|
3507
4078
|
type: BadRequestResponse
|
|
3508
4079
|
})], UsersController);
|
|
3509
|
-
const OpenApi = async (
|
|
3510
|
-
|
|
4080
|
+
const OpenApi = async () => {
|
|
4081
|
+
return await generateDocument({
|
|
3511
4082
|
controllers: [
|
|
3512
4083
|
BooksController,
|
|
3513
|
-
|
|
4084
|
+
ConfigContractsController,
|
|
4085
|
+
ConfigRulesController,
|
|
3514
4086
|
OffersController,
|
|
3515
4087
|
ObligationsController,
|
|
3516
4088
|
HealthController,
|
|
3517
4089
|
UsersController,
|
|
3518
|
-
ValidateController
|
|
4090
|
+
ValidateController,
|
|
4091
|
+
CallbacksController
|
|
3519
4092
|
],
|
|
3520
4093
|
document: {
|
|
3521
4094
|
openapi: "3.1.0",
|
|
@@ -3547,17 +4120,11 @@ const OpenApi = async (options = {}) => {
|
|
|
3547
4120
|
]
|
|
3548
4121
|
}
|
|
3549
4122
|
});
|
|
3550
|
-
if (options.rules && options.rules.length > 0) {
|
|
3551
|
-
const rulesDescription = options.rules.map((rule) => `- **${rule.name}**: ${rule.description}`).join("\n");
|
|
3552
|
-
const validatePath = document.paths?.["/v1/validate"];
|
|
3553
|
-
if (validatePath && "post" in validatePath && validatePath.post) validatePath.post.description = `Validates offers against router validation rules. Returns unsigned payload + root on success, or issues only on validation failure.\n\n**Available validation rules:**\n${rulesDescription}`;
|
|
3554
|
-
}
|
|
3555
|
-
return document;
|
|
3556
4123
|
};
|
|
3557
4124
|
|
|
3558
4125
|
//#endregion
|
|
3559
4126
|
//#region src/api/Schema/PositionResponse.ts
|
|
3560
|
-
var PositionResponse_exports = /* @__PURE__ */
|
|
4127
|
+
var PositionResponse_exports = /* @__PURE__ */ __exportAll({ from: () => from$1 });
|
|
3561
4128
|
/**
|
|
3562
4129
|
* Creates a `PositionResponse` from a `PositionWithReserved`.
|
|
3563
4130
|
* @param position - {@link PositionWithReserved}
|
|
@@ -3577,6 +4144,10 @@ function from$1(position) {
|
|
|
3577
4144
|
//#region src/api/Schema/requests.ts
|
|
3578
4145
|
const MAX_LIMIT = 100;
|
|
3579
4146
|
const DEFAULT_LIMIT = 20;
|
|
4147
|
+
const CONFIG_RULES_MAX_LIMIT = 1e3;
|
|
4148
|
+
const CONFIG_RULES_DEFAULT_LIMIT = 100;
|
|
4149
|
+
const CONFIG_CONTRACTS_MAX_LIMIT = 1e3;
|
|
4150
|
+
const CONFIG_CONTRACTS_DEFAULT_LIMIT = 1e3;
|
|
3580
4151
|
/** Validate cursor is a valid base64url-encoded JSON object.
|
|
3581
4152
|
* Domain layer handles semantic validation of cursor fields. */
|
|
3582
4153
|
function isValidBase64urlJson(val) {
|
|
@@ -3588,6 +4159,15 @@ function isValidBase64urlJson(val) {
|
|
|
3588
4159
|
return false;
|
|
3589
4160
|
}
|
|
3590
4161
|
}
|
|
4162
|
+
const csvArray = (schema) => z$1.preprocess((value) => {
|
|
4163
|
+
if (value === void 0) return void 0;
|
|
4164
|
+
if (Array.isArray(value)) {
|
|
4165
|
+
if (value.some((item) => typeof item !== "string")) return value;
|
|
4166
|
+
return value.flatMap((item) => item.split(",")).map((item) => item.trim()).filter((item) => item.length > 0);
|
|
4167
|
+
}
|
|
4168
|
+
if (typeof value === "string") return value.split(",").map((item) => item.trim()).filter((item) => item.length > 0);
|
|
4169
|
+
return value;
|
|
4170
|
+
}, z$1.array(schema)).optional();
|
|
3591
4171
|
const PaginationQueryParams = z$1.object({
|
|
3592
4172
|
cursor: z$1.string().optional().refine((val) => {
|
|
3593
4173
|
if (!val) return true;
|
|
@@ -3601,6 +4181,43 @@ const PaginationQueryParams = z$1.object({
|
|
|
3601
4181
|
example: 10
|
|
3602
4182
|
})
|
|
3603
4183
|
});
|
|
4184
|
+
const ConfigRuleTypes = z$1.enum([
|
|
4185
|
+
"maturity",
|
|
4186
|
+
"callback",
|
|
4187
|
+
"loan_token"
|
|
4188
|
+
]);
|
|
4189
|
+
const GetConfigRulesQueryParams = z$1.object({
|
|
4190
|
+
cursor: z$1.string().regex(/^(maturity|callback|loan_token):[1-9]\d*:.+$/, { message: "Cursor must be in the format type:chain_id:<value>" }).optional().meta({
|
|
4191
|
+
description: "Pagination cursor in type:chain_id:<value> format",
|
|
4192
|
+
example: "maturity:1:1730415600:end_of_next_month"
|
|
4193
|
+
}),
|
|
4194
|
+
limit: z$1.string().regex(/^[1-9]\d*$/, { message: "Limit must be a positive integer" }).transform((val) => Number.parseInt(val, 10)).pipe(z$1.number().max(CONFIG_RULES_MAX_LIMIT, { message: `Limit cannot exceed ${CONFIG_RULES_MAX_LIMIT}` })).optional().default(CONFIG_RULES_DEFAULT_LIMIT).meta({
|
|
4195
|
+
description: `Limit maximum: ${CONFIG_RULES_MAX_LIMIT}. Default: ${CONFIG_RULES_DEFAULT_LIMIT}`,
|
|
4196
|
+
example: 100
|
|
4197
|
+
}),
|
|
4198
|
+
types: csvArray(ConfigRuleTypes).meta({
|
|
4199
|
+
description: "Filter by rule types (comma-separated).",
|
|
4200
|
+
example: "maturity,loan_token"
|
|
4201
|
+
}),
|
|
4202
|
+
chains: csvArray(z$1.string().regex(/^[1-9]\d*$/, { message: "Chain must be a positive integer" }).transform((val) => Number.parseInt(val, 10))).meta({
|
|
4203
|
+
description: "Filter by chain IDs (comma-separated).",
|
|
4204
|
+
example: "1,8453"
|
|
4205
|
+
})
|
|
4206
|
+
});
|
|
4207
|
+
const GetConfigContractsQueryParams = z$1.object({
|
|
4208
|
+
cursor: z$1.string().regex(/^[1-9]\d*:0x[a-fA-F0-9]{40}$/, { message: "Cursor must be in the format chain_id:0x..." }).optional().meta({
|
|
4209
|
+
description: "Pagination cursor in chain_id:address format (lowercase address).",
|
|
4210
|
+
example: "1:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
|
|
4211
|
+
}),
|
|
4212
|
+
limit: z$1.string().regex(/^[1-9]\d*$/, { message: "Limit must be a positive integer" }).transform((val) => Number.parseInt(val, 10)).pipe(z$1.number().max(CONFIG_CONTRACTS_MAX_LIMIT, { message: `Limit cannot exceed ${CONFIG_CONTRACTS_MAX_LIMIT}` })).optional().default(CONFIG_CONTRACTS_DEFAULT_LIMIT).meta({
|
|
4213
|
+
description: `Limit maximum: ${CONFIG_CONTRACTS_MAX_LIMIT}. Default: ${CONFIG_CONTRACTS_DEFAULT_LIMIT}`,
|
|
4214
|
+
example: 1e3
|
|
4215
|
+
}),
|
|
4216
|
+
chains: csvArray(z$1.string().regex(/^[1-9]\d*$/, { message: "Chain must be a positive integer" }).transform((val) => Number.parseInt(val, 10))).meta({
|
|
4217
|
+
description: "Filter by chain IDs (comma-separated).",
|
|
4218
|
+
example: "1,8453"
|
|
4219
|
+
})
|
|
4220
|
+
});
|
|
3604
4221
|
const GetOffersQueryParams = z$1.object({
|
|
3605
4222
|
...PaginationQueryParams.shape,
|
|
3606
4223
|
side: z$1.enum(["buy", "sell"]).optional().meta({
|
|
@@ -3638,21 +4255,21 @@ const GetObligationsQueryParams = z$1.object({
|
|
|
3638
4255
|
description: "Obligation id cursor",
|
|
3639
4256
|
example: "0x1234567890123456789012345678901234567890123456789012345678901234"
|
|
3640
4257
|
}),
|
|
3641
|
-
|
|
3642
|
-
description: "Filter by chain
|
|
3643
|
-
example: "1"
|
|
4258
|
+
chains: csvArray(z$1.string().regex(/^[1-9]\d*$/, { message: "Chain must be a positive integer" }).transform((val) => Number.parseInt(val, 10))).meta({
|
|
4259
|
+
description: "Filter by chain IDs (comma-separated).",
|
|
4260
|
+
example: "1,8453"
|
|
3644
4261
|
}),
|
|
3645
|
-
|
|
3646
|
-
description: "Filter by loan token
|
|
3647
|
-
example: "0xC9A9C45C0eB717f8b5F193Af6bAa05A1c0Ac5078"
|
|
4262
|
+
loan_tokens: csvArray(z$1.string().regex(/^0x[a-fA-F0-9]{40}$/, { error: "Loan token must be a valid 20-byte address" }).transform((val) => val.toLowerCase())).meta({
|
|
4263
|
+
description: "Filter by loan token addresses (comma-separated).",
|
|
4264
|
+
example: "0xC9A9C45C0eB717f8b5F193Af6bAa05A1c0Ac5078,0x34Cf890dB685FC536E05652FB41f02090c3fb751"
|
|
3648
4265
|
}),
|
|
3649
|
-
|
|
3650
|
-
description: "Filter by collateral
|
|
3651
|
-
example: "0x34Cf890dB685FC536E05652FB41f02090c3fb751"
|
|
4266
|
+
collateral_tokens: csvArray(z$1.string().regex(/^0x[a-fA-F0-9]{40}$/, { error: "Collateral token must be a valid 20-byte address" }).transform((val) => val.toLowerCase())).meta({
|
|
4267
|
+
description: "Filter by collateral tokens (comma-separated, matches any collateral).",
|
|
4268
|
+
example: "0x34Cf890dB685FC536E05652FB41f02090c3fb751,0xC9A9C45C0eB717f8b5F193Af6bAa05A1c0Ac5078"
|
|
3652
4269
|
}),
|
|
3653
|
-
|
|
3654
|
-
description: "Filter by exact maturity
|
|
3655
|
-
example: "1761922800"
|
|
4270
|
+
maturities: csvArray(z$1.string().regex(/^[1-9]\d*$/, { message: "Maturity must be a positive integer" }).transform((val) => Number.parseInt(val, 10))).meta({
|
|
4271
|
+
description: "Filter by exact maturity timestamps (comma-separated, unix seconds).",
|
|
4272
|
+
example: "1761922800,1764524800"
|
|
3656
4273
|
})
|
|
3657
4274
|
});
|
|
3658
4275
|
const GetObligationParams = z$1.object({ obligation_id: z$1.string({ error: "Obligation id is required and must be a valid 32-byte hex string" }).regex(/^0x[a-fA-F0-9]{64}$/, { error: "Obligation id must be a valid 32-byte hex string" }).transform((val) => val.toLowerCase()).meta({
|
|
@@ -3703,6 +4320,16 @@ const GetBookParams = z$1.object({
|
|
|
3703
4320
|
})
|
|
3704
4321
|
});
|
|
3705
4322
|
const ValidateOffersBody = z$1.object({ offers: z$1.array(z$1.unknown()).min(1, { message: "'offers' must contain at least 1 offer" }) }).strict();
|
|
4323
|
+
const CallbackTypesBody = z$1.object({ callbacks: z$1.array(z$1.object({
|
|
4324
|
+
chain_id: z$1.number().int().positive().meta({
|
|
4325
|
+
description: "Chain id.",
|
|
4326
|
+
example: 1
|
|
4327
|
+
}),
|
|
4328
|
+
addresses: z$1.array(z$1.string().regex(/^0x[a-fA-F0-9]{40}$/, { error: "Callback address must be a valid 20-byte address" }).transform((val) => val.toLowerCase())).meta({
|
|
4329
|
+
description: "Callback contract addresses.",
|
|
4330
|
+
example: ["0x1111111111111111111111111111111111111111", "0x3333333333333333333333333333333333333333"]
|
|
4331
|
+
})
|
|
4332
|
+
}).strict()) }).strict();
|
|
3706
4333
|
const GetUserPositionsParams = z$1.object({
|
|
3707
4334
|
...PaginationQueryParams.shape,
|
|
3708
4335
|
user_address: z$1.string().regex(/^0x[a-fA-F0-9]{40}$/, { error: "User address must be a valid 20-byte address" }).transform((val) => val.toLowerCase()).meta({
|
|
@@ -3714,11 +4341,14 @@ const schemas = {
|
|
|
3714
4341
|
get_health: HealthQueryParams,
|
|
3715
4342
|
get_health_collectors: HealthQueryParams,
|
|
3716
4343
|
get_health_chains: HealthQueryParams,
|
|
4344
|
+
get_config_contracts: GetConfigContractsQueryParams,
|
|
4345
|
+
get_config_rules: GetConfigRulesQueryParams,
|
|
3717
4346
|
get_offers: GetOffersQueryParams,
|
|
3718
4347
|
get_obligations: GetObligationsQueryParams,
|
|
3719
4348
|
get_obligation: GetObligationParams,
|
|
3720
4349
|
get_book: GetBookParams,
|
|
3721
4350
|
validate_offers: ValidateOffersBody,
|
|
4351
|
+
callback_types: CallbackTypesBody,
|
|
3722
4352
|
get_user_positions: GetUserPositionsParams
|
|
3723
4353
|
};
|
|
3724
4354
|
function parse(action, query) {
|
|
@@ -3730,14 +4360,16 @@ function safeParse(action, query, error) {
|
|
|
3730
4360
|
|
|
3731
4361
|
//#endregion
|
|
3732
4362
|
//#region src/api/Schema/index.ts
|
|
3733
|
-
var Schema_exports = /* @__PURE__ */
|
|
4363
|
+
var Schema_exports = /* @__PURE__ */ __exportAll({
|
|
3734
4364
|
BookResponse: () => BookResponse_exports,
|
|
3735
4365
|
BooksController: () => BooksController,
|
|
4366
|
+
CallbacksController: () => CallbacksController,
|
|
3736
4367
|
ChainHealth: () => ChainHealth,
|
|
3737
4368
|
ChainsHealthResponse: () => ChainsHealthResponse,
|
|
3738
4369
|
CollectorHealth: () => CollectorHealth,
|
|
3739
4370
|
CollectorsHealthResponse: () => CollectorsHealthResponse,
|
|
3740
|
-
|
|
4371
|
+
ConfigContractsController: () => ConfigContractsController,
|
|
4372
|
+
ConfigRulesController: () => ConfigRulesController,
|
|
3741
4373
|
HealthController: () => HealthController,
|
|
3742
4374
|
ObligationResponse: () => ObligationResponse_exports,
|
|
3743
4375
|
ObligationsController: () => ObligationsController,
|
|
@@ -3754,7 +4386,7 @@ var Schema_exports = /* @__PURE__ */ __export({
|
|
|
3754
4386
|
|
|
3755
4387
|
//#endregion
|
|
3756
4388
|
//#region src/client/Client.ts
|
|
3757
|
-
var Client_exports = /* @__PURE__ */
|
|
4389
|
+
var Client_exports$1 = /* @__PURE__ */ __exportAll({
|
|
3758
4390
|
HttpForbiddenError: () => HttpForbiddenError,
|
|
3759
4391
|
HttpGetApiFailedError: () => HttpGetApiFailedError,
|
|
3760
4392
|
HttpRateLimitError: () => HttpRateLimitError,
|
|
@@ -3787,12 +4419,16 @@ function connect$1(parameters) {
|
|
|
3787
4419
|
};
|
|
3788
4420
|
const apiClient = createOpenApiFetchClient({
|
|
3789
4421
|
baseUrl: config.url.toString(),
|
|
3790
|
-
headers: config.headers
|
|
4422
|
+
headers: config.headers,
|
|
4423
|
+
querySerializer: { array: {
|
|
4424
|
+
style: "form",
|
|
4425
|
+
explode: false
|
|
4426
|
+
} }
|
|
3791
4427
|
});
|
|
3792
4428
|
return {
|
|
3793
4429
|
...config,
|
|
3794
|
-
getOffers: (parameters
|
|
3795
|
-
getObligations: (parameters
|
|
4430
|
+
getOffers: (parameters) => getOffers(apiClient, parameters),
|
|
4431
|
+
getObligations: (parameters) => getObligations(apiClient, parameters)
|
|
3796
4432
|
};
|
|
3797
4433
|
}
|
|
3798
4434
|
async function getOffers(apiClient, parameters) {
|
|
@@ -3819,7 +4455,7 @@ async function getOffers(apiClient, parameters) {
|
|
|
3819
4455
|
obligation_units: offerData.obligation_units,
|
|
3820
4456
|
obligation_shares: offerData.obligation_shares,
|
|
3821
4457
|
price: offerData.price,
|
|
3822
|
-
maturity: from$
|
|
4458
|
+
maturity: from$11(offerData.obligation.maturity),
|
|
3823
4459
|
expiry: offerData.expiry,
|
|
3824
4460
|
start: offerData.start,
|
|
3825
4461
|
group: offerData.group,
|
|
@@ -3855,10 +4491,10 @@ async function getObligations(apiClient, parameters) {
|
|
|
3855
4491
|
const { data, error, response } = await apiClient.GET("/v1/obligations", { params: { query: {
|
|
3856
4492
|
cursor: parameters?.cursor,
|
|
3857
4493
|
limit: parameters?.limit,
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
4494
|
+
chains: parameters?.chainIds,
|
|
4495
|
+
loan_tokens: parameters?.loanTokens,
|
|
4496
|
+
collateral_tokens: parameters?.collateralTokens,
|
|
4497
|
+
maturities: parameters?.maturities
|
|
3862
4498
|
} } });
|
|
3863
4499
|
if (error !== void 0) {
|
|
3864
4500
|
switch (response.status) {
|
|
@@ -3877,7 +4513,7 @@ async function getObligations(apiClient, parameters) {
|
|
|
3877
4513
|
oracle: collateral.oracle,
|
|
3878
4514
|
lltv: collateral.lltv
|
|
3879
4515
|
})),
|
|
3880
|
-
maturity: from$
|
|
4516
|
+
maturity: from$11(item.maturity)
|
|
3881
4517
|
});
|
|
3882
4518
|
const { obligationId: _, ...returned } = {
|
|
3883
4519
|
id: () => id(obligation),
|
|
@@ -3926,10 +4562,125 @@ var HttpGetApiFailedError = class extends BaseError {
|
|
|
3926
4562
|
}
|
|
3927
4563
|
};
|
|
3928
4564
|
|
|
4565
|
+
//#endregion
|
|
4566
|
+
//#region src/gatekeeper/Client.ts
|
|
4567
|
+
var Client_exports = /* @__PURE__ */ __exportAll({ createHttpClient: () => createHttpClient });
|
|
4568
|
+
const DEFAULT_TIMEOUT_MS = 1e4;
|
|
4569
|
+
/**
|
|
4570
|
+
* Create an HTTP client for a gatekeeper service.
|
|
4571
|
+
* @param config - Gatekeeper client configuration. {@link ClientConfig}
|
|
4572
|
+
* @returns An HTTP-backed gatekeeper client. {@link GatekeeperClient}
|
|
4573
|
+
*/
|
|
4574
|
+
function createHttpClient(config) {
|
|
4575
|
+
const fetchFn = config.fetchFn ?? fetch;
|
|
4576
|
+
const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
4577
|
+
const baseUrl = normalizeBaseUrl(config.baseUrl);
|
|
4578
|
+
const baseHeaders = config.originSecret ? { "x-origin-verify": config.originSecret } : void 0;
|
|
4579
|
+
const request = async (path, init) => {
|
|
4580
|
+
const controller = new AbortController();
|
|
4581
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
4582
|
+
try {
|
|
4583
|
+
return await fetchFn(`${baseUrl}${path}`, {
|
|
4584
|
+
...init,
|
|
4585
|
+
headers: mergeHeaders(baseHeaders, init.headers),
|
|
4586
|
+
signal: controller.signal
|
|
4587
|
+
});
|
|
4588
|
+
} finally {
|
|
4589
|
+
clearTimeout(timeout);
|
|
4590
|
+
}
|
|
4591
|
+
};
|
|
4592
|
+
const validate = async (body) => {
|
|
4593
|
+
const response = await request("/v1/validate", {
|
|
4594
|
+
method: "POST",
|
|
4595
|
+
headers: { "content-type": "application/json" },
|
|
4596
|
+
body: JSON.stringify(body)
|
|
4597
|
+
});
|
|
4598
|
+
const json = await response.json();
|
|
4599
|
+
return {
|
|
4600
|
+
statusCode: response.status,
|
|
4601
|
+
body: json
|
|
4602
|
+
};
|
|
4603
|
+
};
|
|
4604
|
+
const getConfigRules = async (query) => {
|
|
4605
|
+
const params = new URLSearchParams();
|
|
4606
|
+
if (query?.cursor) params.set("cursor", query.cursor);
|
|
4607
|
+
if (query?.limit !== void 0) params.set("limit", query.limit.toString());
|
|
4608
|
+
if (query?.types !== void 0) {
|
|
4609
|
+
const typesValue = Array.isArray(query.types) ? query.types.join(",") : query.types;
|
|
4610
|
+
if (typesValue.length > 0) params.set("types", typesValue);
|
|
4611
|
+
}
|
|
4612
|
+
const response = await request(params.size > 0 ? `/v1/config/rules?${params.toString()}` : "/v1/config/rules", { method: "GET" });
|
|
4613
|
+
const json = await response.json();
|
|
4614
|
+
return {
|
|
4615
|
+
statusCode: response.status,
|
|
4616
|
+
body: json
|
|
4617
|
+
};
|
|
4618
|
+
};
|
|
4619
|
+
const isAllowed = async (offers) => {
|
|
4620
|
+
const { statusCode, body } = await validate({ offers: offers.map((offer) => toSnakeCase(offer)) });
|
|
4621
|
+
if (statusCode !== 200) {
|
|
4622
|
+
const errorMessage = extractErrorMessage(body);
|
|
4623
|
+
throw new Error(`Gatekeeper validation failed: ${errorMessage ?? `status ${statusCode}`}`);
|
|
4624
|
+
}
|
|
4625
|
+
const data = body.data;
|
|
4626
|
+
if (!data || typeof data !== "object") throw new Error("Gatekeeper validation response is invalid.");
|
|
4627
|
+
if ("issues" in data) {
|
|
4628
|
+
const issues = data.issues.map((issue) => ({
|
|
4629
|
+
ruleName: issue.rule,
|
|
4630
|
+
message: issue.message,
|
|
4631
|
+
item: offers[issue.index]
|
|
4632
|
+
}));
|
|
4633
|
+
const invalidIndices = new Set(data.issues.map((issue) => issue.index));
|
|
4634
|
+
return {
|
|
4635
|
+
valid: offers.filter((_, index) => !invalidIndices.has(index)),
|
|
4636
|
+
issues
|
|
4637
|
+
};
|
|
4638
|
+
}
|
|
4639
|
+
if (!("payload" in data) || !("root" in data)) throw new Error("Gatekeeper validation response is missing payload data.");
|
|
4640
|
+
return {
|
|
4641
|
+
valid: offers.slice(),
|
|
4642
|
+
issues: []
|
|
4643
|
+
};
|
|
4644
|
+
};
|
|
4645
|
+
const getCallbackTypes = async (requestPayload) => {
|
|
4646
|
+
const response = await request("/v1/callbacks", {
|
|
4647
|
+
method: "POST",
|
|
4648
|
+
headers: { "content-type": "application/json" },
|
|
4649
|
+
body: JSON.stringify(requestPayload)
|
|
4650
|
+
});
|
|
4651
|
+
const json = await response.json();
|
|
4652
|
+
if (!response.ok) throw new Error(`Gatekeeper callbacks request failed: ${extractErrorMessage(json) ?? response.statusText}`);
|
|
4653
|
+
if (!("data" in json) || !Array.isArray(json.data)) throw new Error("Gatekeeper callbacks response is invalid.");
|
|
4654
|
+
return json.data;
|
|
4655
|
+
};
|
|
4656
|
+
return {
|
|
4657
|
+
baseUrl,
|
|
4658
|
+
validate,
|
|
4659
|
+
getConfigRules,
|
|
4660
|
+
isAllowed,
|
|
4661
|
+
getCallbackTypes
|
|
4662
|
+
};
|
|
4663
|
+
}
|
|
4664
|
+
function mergeHeaders(base, extra) {
|
|
4665
|
+
if (!base && !extra) return void 0;
|
|
4666
|
+
const merged = new Headers(base ?? void 0);
|
|
4667
|
+
if (extra) for (const [key, value] of new Headers(extra).entries()) merged.set(key, value);
|
|
4668
|
+
return merged;
|
|
4669
|
+
}
|
|
4670
|
+
function normalizeBaseUrl(url) {
|
|
4671
|
+
return url.trim().replace(/\/+$/, "");
|
|
4672
|
+
}
|
|
4673
|
+
function extractErrorMessage(payload) {
|
|
4674
|
+
if (!payload || typeof payload !== "object") return void 0;
|
|
4675
|
+
const error = payload.error;
|
|
4676
|
+
if (!error || typeof error !== "object") return void 0;
|
|
4677
|
+
return typeof error.message === "string" ? error.message : void 0;
|
|
4678
|
+
}
|
|
4679
|
+
|
|
3929
4680
|
//#endregion
|
|
3930
4681
|
//#region src/gatekeeper/Gate.ts
|
|
3931
|
-
var Gate_exports = /* @__PURE__ */
|
|
3932
|
-
batch: () => batch
|
|
4682
|
+
var Gate_exports = /* @__PURE__ */ __exportAll({
|
|
4683
|
+
batch: () => batch,
|
|
3933
4684
|
run: () => run,
|
|
3934
4685
|
single: () => single
|
|
3935
4686
|
});
|
|
@@ -3940,12 +4691,12 @@ var Gate_exports = /* @__PURE__ */ __export({
|
|
|
3940
4691
|
* @param run - The function that validates the rule.
|
|
3941
4692
|
* @returns The created rule.
|
|
3942
4693
|
*/
|
|
3943
|
-
function single(name, description, run
|
|
4694
|
+
function single(name, description, run) {
|
|
3944
4695
|
return {
|
|
3945
4696
|
kind: "single",
|
|
3946
4697
|
name,
|
|
3947
4698
|
description,
|
|
3948
|
-
run
|
|
4699
|
+
run
|
|
3949
4700
|
};
|
|
3950
4701
|
}
|
|
3951
4702
|
/**
|
|
@@ -3955,12 +4706,12 @@ function single(name, description, run$1) {
|
|
|
3955
4706
|
* @param run - The function that validates the rule.
|
|
3956
4707
|
* @returns The created rule.
|
|
3957
4708
|
*/
|
|
3958
|
-
function batch
|
|
4709
|
+
function batch(name, description, run) {
|
|
3959
4710
|
return {
|
|
3960
4711
|
kind: "batch",
|
|
3961
4712
|
name,
|
|
3962
4713
|
description,
|
|
3963
|
-
run
|
|
4714
|
+
run
|
|
3964
4715
|
};
|
|
3965
4716
|
}
|
|
3966
4717
|
async function run(parameters) {
|
|
@@ -4011,16 +4762,26 @@ async function run(parameters) {
|
|
|
4011
4762
|
};
|
|
4012
4763
|
}
|
|
4013
4764
|
|
|
4765
|
+
//#endregion
|
|
4766
|
+
//#region src/gatekeeper/Gatekeeper.ts
|
|
4767
|
+
var Gatekeeper_exports = /* @__PURE__ */ __exportAll({ create: () => create });
|
|
4768
|
+
/**
|
|
4769
|
+
* Create a gatekeeper instance with the provided rules.
|
|
4770
|
+
* @param parameters - Gatekeeper parameters. {@link GatekeeperParameters}
|
|
4771
|
+
* @returns Gatekeeper instance. {@link Gatekeeper}
|
|
4772
|
+
*/
|
|
4773
|
+
function create(parameters) {
|
|
4774
|
+
const { rules } = parameters;
|
|
4775
|
+
return { isAllowed: async (offers) => {
|
|
4776
|
+
return await run({
|
|
4777
|
+
items: offers,
|
|
4778
|
+
rules
|
|
4779
|
+
});
|
|
4780
|
+
} };
|
|
4781
|
+
}
|
|
4782
|
+
|
|
4014
4783
|
//#endregion
|
|
4015
4784
|
//#region src/gatekeeper/GateConfig.ts
|
|
4016
|
-
var GateConfig_exports = /* @__PURE__ */ __export({
|
|
4017
|
-
assets: () => assets,
|
|
4018
|
-
configs: () => configs,
|
|
4019
|
-
getCallback: () => getCallback,
|
|
4020
|
-
getCallbackAddresses: () => getCallbackAddresses,
|
|
4021
|
-
getCallbackType: () => getCallbackType,
|
|
4022
|
-
getCallbackTypeAddresses: () => getCallbackTypeAddresses
|
|
4023
|
-
});
|
|
4024
4785
|
/**
|
|
4025
4786
|
* Returns the callback configuration for a given chain and callback type, if it exists.
|
|
4026
4787
|
*
|
|
@@ -4039,19 +4800,8 @@ function getCallback(chain, type) {
|
|
|
4039
4800
|
* @param address - Callback contract address
|
|
4040
4801
|
* @returns The callback type when found, otherwise undefined
|
|
4041
4802
|
*/
|
|
4042
|
-
function getCallbackType(chain, address
|
|
4043
|
-
return configs[chain].callbacks?.find((c) => c.type !==
|
|
4044
|
-
}
|
|
4045
|
-
/**
|
|
4046
|
-
* Returns the callback addresses for a given chain and callback type, if it exists.
|
|
4047
|
-
* @param chain - Chain name for which to read the validation configuration
|
|
4048
|
-
* @param type - Callback type to retrieve
|
|
4049
|
-
* @returns The matching callback addresses or an empty array if not configured
|
|
4050
|
-
*/
|
|
4051
|
-
function getCallbackTypeAddresses(chain, type) {
|
|
4052
|
-
if (type === CallbackType.BuyWithEmptyCallback) return [];
|
|
4053
|
-
const match = configs[chain].callbacks?.find((c) => c.type === type);
|
|
4054
|
-
return match && "addresses" in match ? match.addresses : [];
|
|
4803
|
+
function getCallbackType(chain, address) {
|
|
4804
|
+
return configs[chain].callbacks?.find((c) => c.type !== Type$1.BuyWithEmptyCallback && c.addresses.includes(address?.toLowerCase()))?.type;
|
|
4055
4805
|
}
|
|
4056
4806
|
/**
|
|
4057
4807
|
* Returns the list of allowed non-empty callback addresses for a chain.
|
|
@@ -4060,7 +4810,7 @@ function getCallbackTypeAddresses(chain, type) {
|
|
|
4060
4810
|
* @returns Array of allowed callback addresses (lowercased). Empty when none configured
|
|
4061
4811
|
*/
|
|
4062
4812
|
const getCallbackAddresses = (chain) => {
|
|
4063
|
-
return configs[chain].callbacks?.filter((c) => c.type !==
|
|
4813
|
+
return configs[chain].callbacks?.filter((c) => c.type !== Type$1.BuyWithEmptyCallback).flatMap((c) => c.addresses) ?? [];
|
|
4064
4814
|
};
|
|
4065
4815
|
const assets = {
|
|
4066
4816
|
[ChainId.ETHEREUM.toString()]: [
|
|
@@ -4093,83 +4843,68 @@ const configs = {
|
|
|
4093
4843
|
ethereum: {
|
|
4094
4844
|
callbacks: [
|
|
4095
4845
|
{
|
|
4096
|
-
type:
|
|
4846
|
+
type: Type$1.BuyVaultV1Callback,
|
|
4097
4847
|
addresses: ["0x3333333333333333333333333333333333333333", "0x4444444444444444444444444444444444444444"],
|
|
4098
4848
|
vaultFactories: ["0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101", "0x1897A8997241C1cD4bD0698647e4EB7213535c24"]
|
|
4099
4849
|
},
|
|
4100
4850
|
{
|
|
4101
|
-
type:
|
|
4851
|
+
type: Type$1.SellERC20Callback,
|
|
4102
4852
|
addresses: ["0x1111111111111111111111111111111111111111", "0x2222222222222222222222222222222222222222"]
|
|
4103
4853
|
},
|
|
4104
|
-
{ type:
|
|
4854
|
+
{ type: Type$1.BuyWithEmptyCallback }
|
|
4105
4855
|
],
|
|
4106
4856
|
maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth]
|
|
4107
4857
|
},
|
|
4108
4858
|
base: {
|
|
4109
4859
|
callbacks: [
|
|
4110
4860
|
{
|
|
4111
|
-
type:
|
|
4861
|
+
type: Type$1.BuyVaultV1Callback,
|
|
4112
4862
|
addresses: ["0x3333333333333333333333333333333333333333", "0x4444444444444444444444444444444444444444"],
|
|
4113
4863
|
vaultFactories: ["0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101", "0xFf62A7c278C62eD665133147129245053Bbf5918"]
|
|
4114
4864
|
},
|
|
4115
4865
|
{
|
|
4116
|
-
type:
|
|
4866
|
+
type: Type$1.SellERC20Callback,
|
|
4117
4867
|
addresses: ["0x1111111111111111111111111111111111111111", "0x2222222222222222222222222222222222222222"]
|
|
4118
4868
|
},
|
|
4119
|
-
{ type:
|
|
4869
|
+
{ type: Type$1.BuyWithEmptyCallback }
|
|
4120
4870
|
],
|
|
4121
4871
|
maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth]
|
|
4122
4872
|
},
|
|
4123
4873
|
"ethereum-virtual-testnet": {
|
|
4124
4874
|
callbacks: [
|
|
4125
4875
|
{
|
|
4126
|
-
type:
|
|
4876
|
+
type: Type$1.BuyVaultV1Callback,
|
|
4127
4877
|
addresses: ["0x3333333333333333333333333333333333333333", "0x4444444444444444444444444444444444444444"],
|
|
4128
4878
|
vaultFactories: ["0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101", "0x1897A8997241C1cD4bD0698647e4EB7213535c24"]
|
|
4129
4879
|
},
|
|
4130
4880
|
{
|
|
4131
|
-
type:
|
|
4881
|
+
type: Type$1.SellERC20Callback,
|
|
4132
4882
|
addresses: ["0x1111111111111111111111111111111111111111", "0x2222222222222222222222222222222222222222"]
|
|
4133
4883
|
},
|
|
4134
|
-
{ type:
|
|
4884
|
+
{ type: Type$1.BuyWithEmptyCallback }
|
|
4135
4885
|
],
|
|
4136
4886
|
maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth]
|
|
4137
4887
|
},
|
|
4138
4888
|
anvil: {
|
|
4139
4889
|
callbacks: [
|
|
4140
4890
|
{
|
|
4141
|
-
type:
|
|
4891
|
+
type: Type$1.BuyVaultV1Callback,
|
|
4142
4892
|
addresses: ["0x3333333333333333333333333333333333333333", "0x4444444444444444444444444444444444444444"],
|
|
4143
4893
|
vaultFactories: ["0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101", "0x1897A8997241C1cD4bD0698647e4EB7213535c24"]
|
|
4144
4894
|
},
|
|
4145
4895
|
{
|
|
4146
|
-
type:
|
|
4896
|
+
type: Type$1.SellERC20Callback,
|
|
4147
4897
|
addresses: ["0x1111111111111111111111111111111111111111", "0x2222222222222222222222222222222222222222"]
|
|
4148
4898
|
},
|
|
4149
|
-
{ type:
|
|
4899
|
+
{ type: Type$1.BuyWithEmptyCallback }
|
|
4150
4900
|
],
|
|
4151
4901
|
maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth]
|
|
4152
4902
|
}
|
|
4153
4903
|
};
|
|
4154
4904
|
|
|
4155
|
-
//#endregion
|
|
4156
|
-
//#region src/gatekeeper/Gatekeeper.ts
|
|
4157
|
-
var Gatekeeper_exports = /* @__PURE__ */ __export({ create: () => create });
|
|
4158
|
-
function create(parameters) {
|
|
4159
|
-
return {
|
|
4160
|
-
rules: parameters.rules,
|
|
4161
|
-
isAllowed: async (offers) => {
|
|
4162
|
-
return await run({
|
|
4163
|
-
items: offers,
|
|
4164
|
-
rules: parameters.rules
|
|
4165
|
-
});
|
|
4166
|
-
}
|
|
4167
|
-
};
|
|
4168
|
-
}
|
|
4169
|
-
|
|
4170
4905
|
//#endregion
|
|
4171
4906
|
//#region src/gatekeeper/Rules.ts
|
|
4172
|
-
var Rules_exports = /* @__PURE__ */
|
|
4907
|
+
var Rules_exports = /* @__PURE__ */ __exportAll({
|
|
4173
4908
|
amountMutualExclusivity: () => amountMutualExclusivity,
|
|
4174
4909
|
callback: () => callback,
|
|
4175
4910
|
chains: () => chains,
|
|
@@ -4188,21 +4923,21 @@ function validity(parameters) {
|
|
|
4188
4923
|
const { client } = parameters;
|
|
4189
4924
|
const sellErc20CallbackInvalid = single("sell_erc20_callback_invalid", "Validates that sell offers have valid ERC20 callback data matching offer collaterals", (offer) => {
|
|
4190
4925
|
const callbackType = getCallbackType(client.chain.name, offer.callback.address);
|
|
4191
|
-
if (callbackType !==
|
|
4926
|
+
if (callbackType !== Type$1.SellERC20Callback) return;
|
|
4192
4927
|
const decoded = decode$2(callbackType, offer.callback.data);
|
|
4193
4928
|
if (decoded.length === 0) return { message: "Callback data cannot be decoded or is empty." };
|
|
4194
|
-
if (callbackType ===
|
|
4929
|
+
if (callbackType === Type$1.SellERC20Callback) {
|
|
4195
4930
|
const offerCollaterals = new Set(offer.collaterals.map((c) => c.asset.toLowerCase()));
|
|
4196
4931
|
if (decoded.length !== offer.collaterals.length) return { message: `Sell callback collateral length mismatch. Expected ${offer.collaterals.length}, got ${decoded.length}.` };
|
|
4197
4932
|
for (const { contract } of decoded) if (!offerCollaterals.has(contract.toLowerCase())) return { message: "Sell callback collateral is not part of offer collaterals." };
|
|
4198
4933
|
}
|
|
4199
4934
|
});
|
|
4200
|
-
const buyCallbackVaultInvalid = batch
|
|
4935
|
+
const buyCallbackVaultInvalid = batch("buy_offers_callback_vault_invalid", "Validates that buy offers have valid vault callbacks registered in allowed factories with matching assets", async (offers) => {
|
|
4201
4936
|
const validationIssues = /* @__PURE__ */ new Map();
|
|
4202
4937
|
const offersByVaultAddress = /* @__PURE__ */ new Map();
|
|
4203
4938
|
for (let i = 0; i < offers.length; i++) {
|
|
4204
4939
|
const offer = offers[i];
|
|
4205
|
-
if (getCallbackType(client.chain.name, offer.callback.address) !==
|
|
4940
|
+
if (getCallbackType(client.chain.name, offer.callback.address) !== Type$1.BuyVaultV1Callback) continue;
|
|
4206
4941
|
try {
|
|
4207
4942
|
const callbackVaults = decodeBuyVaultV1Callback(offer.callback.data);
|
|
4208
4943
|
for (const { contract } of callbackVaults) {
|
|
@@ -4217,7 +4952,7 @@ function validity(parameters) {
|
|
|
4217
4952
|
}
|
|
4218
4953
|
const uniqueVaultAddresses = Array.from(offersByVaultAddress.keys());
|
|
4219
4954
|
if (uniqueVaultAddresses.length === 0) return validationIssues;
|
|
4220
|
-
const allowedFactories = getCallback(client.chain.name,
|
|
4955
|
+
const allowedFactories = getCallback(client.chain.name, Type$1.BuyVaultV1Callback)?.vaultFactories.map((f) => f.toLowerCase());
|
|
4221
4956
|
if (!allowedFactories) return validationIssues;
|
|
4222
4957
|
const multicallContracts = [];
|
|
4223
4958
|
for (const vaultAddress of uniqueVaultAddresses) {
|
|
@@ -4285,16 +5020,16 @@ function validity(parameters) {
|
|
|
4285
5020
|
buyCallbackVaultInvalid
|
|
4286
5021
|
];
|
|
4287
5022
|
}
|
|
4288
|
-
const chains = ({ chains
|
|
4289
|
-
const allowedChainIds = chains
|
|
4290
|
-
if (!allowedChainIds.some((id
|
|
5023
|
+
const chains = ({ chains }) => single("chain_ids", `Validates that offer chain is one of: [${chains.map((c) => c.id).join(", ")}]`, (offer) => {
|
|
5024
|
+
const allowedChainIds = chains.map((c) => c.id);
|
|
5025
|
+
if (!allowedChainIds.some((id) => id === offer.chainId)) return { message: `Chain ID ${offer.chainId} is not in the allowed chains (${allowedChainIds.join(", ")})` };
|
|
4291
5026
|
});
|
|
4292
5027
|
const maturity = ({ maturities }) => single("maturity", `Validates that offer maturity is one of: [${maturities.join(", ")}]`, (offer) => {
|
|
4293
|
-
const allowedMaturities = maturities.map((m) => from$
|
|
5028
|
+
const allowedMaturities = maturities.map((m) => from$11(m));
|
|
4294
5029
|
if (!allowedMaturities.includes(offer.maturity)) return { message: `Maturity must be end of current month (${allowedMaturities[0]}) or end of next month (${allowedMaturities[1]}). Got: ${offer.maturity}` };
|
|
4295
5030
|
});
|
|
4296
|
-
const callback = ({ callbacks, allowedAddresses }) => single("callback", `Validates callbacks: buy empty callback is ${callbacks.includes(
|
|
4297
|
-
if (isEmptyCallback(offer) && offer.buy && !callbacks?.find((c) => c ===
|
|
5031
|
+
const callback = ({ callbacks, allowedAddresses }) => single("callback", `Validates callbacks: buy empty callback is ${callbacks.includes(Type$1.BuyWithEmptyCallback) ? "allowed" : "not allowed"}; sell offers must use a non-empty callback; non-empty callbacks must target one of [${allowedAddresses.map((a) => a.toLowerCase()).join(", ")}]`, (offer) => {
|
|
5032
|
+
if (isEmptyCallback(offer) && offer.buy && !callbacks?.find((c) => c === Type$1.BuyWithEmptyCallback)) return { message: "Buy offers with empty callback not allowed." };
|
|
4298
5033
|
if (isEmptyCallback(offer) && !offer.buy) return { message: "Sell offers require a non-empty callback." };
|
|
4299
5034
|
if (!isEmptyCallback(offer)) {
|
|
4300
5035
|
if (!allowedAddresses.includes(offer.callback.address?.toLowerCase())) return { message: `Callback address ${offer.callback.address} is not allowed.` };
|
|
@@ -4316,7 +5051,7 @@ const token = ({ assetsByChainId }) => single("token", "Validates that offer loa
|
|
|
4316
5051
|
* Returns an issue only for the first non-conforming offer.
|
|
4317
5052
|
* This rule is signing-agnostic; signer verification is handled at the collector level.
|
|
4318
5053
|
*/
|
|
4319
|
-
const sameMaker = () => batch
|
|
5054
|
+
const sameMaker = () => batch("mixed_maker", "Validates that all offers in a batch have the same maker address", (offers) => {
|
|
4320
5055
|
const issues = /* @__PURE__ */ new Map();
|
|
4321
5056
|
if (offers.length === 0) return issues;
|
|
4322
5057
|
const firstMaker = offers[0].maker.toLowerCase();
|
|
@@ -4350,9 +5085,9 @@ const morphoRules = (chains$2) => {
|
|
|
4350
5085
|
maturity({ maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth] }),
|
|
4351
5086
|
callback({
|
|
4352
5087
|
callbacks: [
|
|
4353
|
-
|
|
4354
|
-
|
|
4355
|
-
|
|
5088
|
+
Type$1.BuyWithEmptyCallback,
|
|
5089
|
+
Type$1.BuyVaultV1Callback,
|
|
5090
|
+
Type$1.SellERC20Callback
|
|
4356
5091
|
],
|
|
4357
5092
|
allowedAddresses: chains$2.flatMap((c) => getCallbackAddresses(c.name))
|
|
4358
5093
|
}),
|
|
@@ -4367,12 +5102,13 @@ function from(parameters) {
|
|
|
4367
5102
|
const config = {
|
|
4368
5103
|
client: parameters.client,
|
|
4369
5104
|
mempoolAddress: parameters.mempoolAddress,
|
|
5105
|
+
morphoAddress: parameters.morphoAddress,
|
|
4370
5106
|
blockWindow: parameters.blockWindow
|
|
4371
5107
|
};
|
|
4372
5108
|
return {
|
|
4373
|
-
add: (parameters
|
|
4374
|
-
get: (parameters
|
|
4375
|
-
stream: (parameters
|
|
5109
|
+
add: (parameters) => add(config, parameters),
|
|
5110
|
+
get: (parameters) => get(config, parameters),
|
|
5111
|
+
stream: (parameters) => streamOffers(config, parameters)
|
|
4376
5112
|
};
|
|
4377
5113
|
}
|
|
4378
5114
|
/**
|
|
@@ -4384,11 +5120,18 @@ function from(parameters) {
|
|
|
4384
5120
|
*/
|
|
4385
5121
|
async function add(config, offers) {
|
|
4386
5122
|
if (!config.client.account) throw new WalletAccountNotSetError();
|
|
4387
|
-
const tree = from$
|
|
5123
|
+
const tree = from$3(offers.map((o) => from$9(o)));
|
|
4388
5124
|
const chainId = await getChainId(config.client);
|
|
4389
5125
|
for (const offer of tree.offers) if (chainId !== offer.chainId) throw new ChainIdMismatchError(offer.chainId, chainId);
|
|
4390
|
-
const
|
|
4391
|
-
const
|
|
5126
|
+
const signatureDomain$1 = resolveSignatureDomain(config, chainId);
|
|
5127
|
+
const signature = await config.client.signTypedData({
|
|
5128
|
+
account: config.client.account,
|
|
5129
|
+
domain: signatureDomain(signatureDomain$1),
|
|
5130
|
+
types: signatureTypes,
|
|
5131
|
+
primaryType: "Root",
|
|
5132
|
+
message: { root: tree.root }
|
|
5133
|
+
});
|
|
5134
|
+
const encoded = await encode(tree, signature, signatureDomain$1);
|
|
4392
5135
|
try {
|
|
4393
5136
|
return await config.client.sendTransaction({
|
|
4394
5137
|
chain: config.client.chain,
|
|
@@ -4427,6 +5170,7 @@ const getChainId = async (client) => {
|
|
|
4427
5170
|
};
|
|
4428
5171
|
async function* streamOffers(config, parameters) {
|
|
4429
5172
|
const { loanToken, blockNumberGte, blockNumberLte, order = "desc", options: { maxBatchSize = DEFAULT_BATCH_SIZE, blockWindow = config.blockWindow } = {} } = parameters;
|
|
5173
|
+
const signatureDomain = resolveSignatureDomain(config, await getChainId(config.client));
|
|
4430
5174
|
const stream = streamLogs({
|
|
4431
5175
|
client: config.client.extend(publicActions),
|
|
4432
5176
|
contractAddress: config.mempoolAddress,
|
|
@@ -4458,7 +5202,7 @@ async function* streamOffers(config, parameters) {
|
|
|
4458
5202
|
if (!log) continue;
|
|
4459
5203
|
const [payload] = decodeAbiParameters([{ type: "bytes" }], log.data);
|
|
4460
5204
|
try {
|
|
4461
|
-
const { tree } = await decode
|
|
5205
|
+
const { tree } = await decode(payload, signatureDomain);
|
|
4462
5206
|
for (const offer of tree.offers) {
|
|
4463
5207
|
if (loanToken && offer.loanToken.toLowerCase() !== loanToken.toLowerCase()) continue;
|
|
4464
5208
|
offers.push(offer);
|
|
@@ -4493,10 +5237,25 @@ var ChainIdMismatchError = class extends BaseError {
|
|
|
4493
5237
|
_defineProperty(this, "name", "Mempool.ChainIdMismatchError");
|
|
4494
5238
|
}
|
|
4495
5239
|
};
|
|
5240
|
+
const resolveSignatureDomain = (config, chainId) => {
|
|
5241
|
+
const chain = config.client.chain;
|
|
5242
|
+
const verifyingContract = config.morphoAddress ?? chain?.custom?.morpho?.address ?? getChain(chainId)?.custom.morpho.address;
|
|
5243
|
+
if (!verifyingContract || verifyingContract.toLowerCase() === zeroAddress) throw new MissingMorphoAddressError();
|
|
5244
|
+
return {
|
|
5245
|
+
chainId,
|
|
5246
|
+
verifyingContract
|
|
5247
|
+
};
|
|
5248
|
+
};
|
|
5249
|
+
var MissingMorphoAddressError = class extends BaseError {
|
|
5250
|
+
constructor() {
|
|
5251
|
+
super("Morpho address is required to verify root signatures (zero address is invalid).");
|
|
5252
|
+
_defineProperty(this, "name", "Mempool.MissingMorphoAddressError");
|
|
5253
|
+
}
|
|
5254
|
+
};
|
|
4496
5255
|
|
|
4497
5256
|
//#endregion
|
|
4498
5257
|
//#region src/mempool/MempoolClient.ts
|
|
4499
|
-
var MempoolClient_exports = /* @__PURE__ */
|
|
5258
|
+
var MempoolClient_exports = /* @__PURE__ */ __exportAll({ connect: () => connect });
|
|
4500
5259
|
/**
|
|
4501
5260
|
* Client to interact with the Mempool contract on a specific chain.
|
|
4502
5261
|
*/
|
|
@@ -4529,7 +5288,7 @@ const retry = async (fn, attempts = 3, delayMs = 50) => {
|
|
|
4529
5288
|
async function batchMulticall(parameters) {
|
|
4530
5289
|
const { client, calls, batchSize, retryAttempts, retryDelayMs, blockNumber } = parameters;
|
|
4531
5290
|
const results = [];
|
|
4532
|
-
for (const callsBatch of batch(calls, batchSize)) {
|
|
5291
|
+
for (const callsBatch of batch$1(calls, batchSize)) {
|
|
4533
5292
|
const batchResults = await retry(() => multicall(client, {
|
|
4534
5293
|
allowFailure: false,
|
|
4535
5294
|
contracts: callsBatch,
|
|
@@ -4542,7 +5301,7 @@ async function batchMulticall(parameters) {
|
|
|
4542
5301
|
|
|
4543
5302
|
//#endregion
|
|
4544
5303
|
//#region src/utils/Group.ts
|
|
4545
|
-
var Group_exports = /* @__PURE__ */
|
|
5304
|
+
var Group_exports = /* @__PURE__ */ __exportAll({ fromNumber: () => fromNumber });
|
|
4546
5305
|
/**
|
|
4547
5306
|
* Creates a bytes32 group identifier from a number.
|
|
4548
5307
|
* @param n - A non-negative integer.
|
|
@@ -4566,7 +5325,7 @@ function lazy(pollFn) {
|
|
|
4566
5325
|
let active = true;
|
|
4567
5326
|
let resolveNext = null;
|
|
4568
5327
|
const queue = [];
|
|
4569
|
-
const wait
|
|
5328
|
+
const wait = () => new Promise((resolve) => {
|
|
4570
5329
|
resolveNext = resolve;
|
|
4571
5330
|
});
|
|
4572
5331
|
const emit = (item) => {
|
|
@@ -4584,7 +5343,7 @@ function lazy(pollFn) {
|
|
|
4584
5343
|
unpoll = pollFn(emit, { stop });
|
|
4585
5344
|
try {
|
|
4586
5345
|
while (active) {
|
|
4587
|
-
if (queue.length === 0) await wait
|
|
5346
|
+
if (queue.length === 0) await wait();
|
|
4588
5347
|
while (queue.length > 0 && active) yield queue.shift();
|
|
4589
5348
|
}
|
|
4590
5349
|
} finally {
|
|
@@ -4623,7 +5382,7 @@ function poll(fn, { interval }) {
|
|
|
4623
5382
|
|
|
4624
5383
|
//#endregion
|
|
4625
5384
|
//#region src/utils/time.ts
|
|
4626
|
-
var time_exports = /* @__PURE__ */
|
|
5385
|
+
var time_exports = /* @__PURE__ */ __exportAll({
|
|
4627
5386
|
max: () => max,
|
|
4628
5387
|
now: () => now
|
|
4629
5388
|
});
|
|
@@ -4636,14 +5395,14 @@ function max() {
|
|
|
4636
5395
|
|
|
4637
5396
|
//#endregion
|
|
4638
5397
|
//#region src/utils/index.ts
|
|
4639
|
-
var utils_exports = /* @__PURE__ */
|
|
5398
|
+
var utils_exports = /* @__PURE__ */ __exportAll({
|
|
4640
5399
|
BaseError: () => BaseError,
|
|
4641
5400
|
Group: () => Group_exports,
|
|
4642
5401
|
Random: () => Random_exports,
|
|
4643
5402
|
ReorgError: () => ReorgError,
|
|
4644
5403
|
Time: () => time_exports,
|
|
4645
5404
|
atMostOneNonZero: () => atMostOneNonZero,
|
|
4646
|
-
batch: () => batch,
|
|
5405
|
+
batch: () => batch$1,
|
|
4647
5406
|
batchMulticall: () => batchMulticall,
|
|
4648
5407
|
fromSnakeCase: () => fromSnakeCase$3,
|
|
4649
5408
|
lazy: () => lazy,
|
|
@@ -4657,5 +5416,5 @@ var utils_exports = /* @__PURE__ */ __export({
|
|
|
4657
5416
|
});
|
|
4658
5417
|
|
|
4659
5418
|
//#endregion
|
|
4660
|
-
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,
|
|
5419
|
+
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, 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, 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 };
|
|
4661
5420
|
//# sourceMappingURL=index.browser.mjs.map
|