@morpho-dev/router 0.6.0 → 0.7.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/dist/cli.js +191 -39
- package/dist/index.browser.d.mts +44 -8
- package/dist/index.browser.d.mts.map +1 -1
- package/dist/index.browser.d.ts +44 -8
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/index.browser.js +103 -13
- package/dist/index.browser.js.map +1 -1
- package/dist/index.browser.mjs +103 -13
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.node.d.mts +51 -15
- package/dist/index.node.d.mts.map +1 -1
- package/dist/index.node.d.ts +51 -15
- package/dist/index.node.d.ts.map +1 -1
- package/dist/index.node.js +130 -25
- package/dist/index.node.js.map +1 -1
- package/dist/index.node.mjs +130 -25
- package/dist/index.node.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -152,7 +152,7 @@ function startActiveSpan(tracer, name, fn) {
|
|
|
152
152
|
//#endregion
|
|
153
153
|
//#region package.json
|
|
154
154
|
var name = "@morpho-dev/router";
|
|
155
|
-
var version = "0.
|
|
155
|
+
var version = "0.7.0";
|
|
156
156
|
var description = "Router package for Morpho protocol";
|
|
157
157
|
|
|
158
158
|
//#endregion
|
|
@@ -1696,13 +1696,18 @@ const assets = {
|
|
|
1696
1696
|
"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
1697
1697
|
"0x6B175474E89094C44Da98b954EedeAC495271d0F",
|
|
1698
1698
|
"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
|
|
1699
|
-
"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"
|
|
1699
|
+
"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",
|
|
1700
|
+
"0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c",
|
|
1701
|
+
"0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0"
|
|
1700
1702
|
],
|
|
1701
1703
|
[ChainId.BASE.toString()]: [
|
|
1702
1704
|
"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
1703
1705
|
"0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb",
|
|
1704
1706
|
"0x4200000000000000000000000000000000000006",
|
|
1705
|
-
"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"
|
|
1707
|
+
"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",
|
|
1708
|
+
"0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf",
|
|
1709
|
+
"0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452",
|
|
1710
|
+
"0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42"
|
|
1706
1711
|
],
|
|
1707
1712
|
[ChainId["ETHEREUM-VIRTUAL-TESTNET"].toString()]: [
|
|
1708
1713
|
"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
@@ -1718,6 +1723,43 @@ const assets = {
|
|
|
1718
1723
|
"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"
|
|
1719
1724
|
]
|
|
1720
1725
|
};
|
|
1726
|
+
const oracles$1 = {
|
|
1727
|
+
[ChainId.ETHEREUM.toString()]: [
|
|
1728
|
+
"0xDddd770BADd886dF3864029e4B377B5F6a2B6b83",
|
|
1729
|
+
"0x9CB3f4276bcD149b3668e1a645a964bC12877b89",
|
|
1730
|
+
"0x48F7E36EB6B826B2dF4B2E630B62Cd25e89E40e2",
|
|
1731
|
+
"0x6Eb9F4128CeBc8B885A4d8562Db1Addf097f7348",
|
|
1732
|
+
"0xbD60A6770b27E084E8617335ddE769241B0e71D8",
|
|
1733
|
+
"0xAe12416c1F21B0698c27fe042D9309C83baC6597"
|
|
1734
|
+
],
|
|
1735
|
+
[ChainId.BASE.toString()]: [
|
|
1736
|
+
"0xD09048c8B568Dbf5f189302beA26c9edABFC4858",
|
|
1737
|
+
"0xFEa2D58cEfCb9fcb597723c6bAE66fFE4193aFE4",
|
|
1738
|
+
"0x05D2618404668D725B66c0f32B39e4EC15B393dC",
|
|
1739
|
+
"0xE1bb8E5b4930eC9FeC7f7943FCF6227649F14B37",
|
|
1740
|
+
"0x663BECd10daE6C4A3Dcd89F1d76c1174199639B9",
|
|
1741
|
+
"0x10b95702a0ce895972C91e432C4f7E19811D320E",
|
|
1742
|
+
"0x8C87DbD7A0c647A4291592Bc2994dbF95880fE2F",
|
|
1743
|
+
"0x4A11590e5326138B514E08A9B52202D42077Ca65",
|
|
1744
|
+
"0xa54122f0E0766258377Ffe732e454A3248f454F4"
|
|
1745
|
+
],
|
|
1746
|
+
[ChainId["ETHEREUM-VIRTUAL-TESTNET"].toString()]: [
|
|
1747
|
+
"0xDddd770BADd886dF3864029e4B377B5F6a2B6b83",
|
|
1748
|
+
"0x9CB3f4276bcD149b3668e1a645a964bC12877b89",
|
|
1749
|
+
"0x48F7E36EB6B826B2dF4B2E630B62Cd25e89E40e2",
|
|
1750
|
+
"0x6Eb9F4128CeBc8B885A4d8562Db1Addf097f7348",
|
|
1751
|
+
"0xbD60A6770b27E084E8617335ddE769241B0e71D8",
|
|
1752
|
+
"0xAe12416c1F21B0698c27fe042D9309C83baC6597"
|
|
1753
|
+
],
|
|
1754
|
+
[ChainId.ANVIL.toString()]: [
|
|
1755
|
+
"0xDddd770BADd886dF3864029e4B377B5F6a2B6b83",
|
|
1756
|
+
"0x9CB3f4276bcD149b3668e1a645a964bC12877b89",
|
|
1757
|
+
"0x48F7E36EB6B826B2dF4B2E630B62Cd25e89E40e2",
|
|
1758
|
+
"0x6Eb9F4128CeBc8B885A4d8562Db1Addf097f7348",
|
|
1759
|
+
"0xbD60A6770b27E084E8617335ddE769241B0e71D8",
|
|
1760
|
+
"0xAe12416c1F21B0698c27fe042D9309C83baC6597"
|
|
1761
|
+
]
|
|
1762
|
+
};
|
|
1721
1763
|
const configs = {
|
|
1722
1764
|
ethereum: {
|
|
1723
1765
|
callbacks: [
|
|
@@ -2916,6 +2958,16 @@ const token = ({ assetsByChainId }) => single("token", "Validates that offer loa
|
|
|
2916
2958
|
if (offer.collaterals.some((collateral) => !allowedAssets.includes(collateral.asset.toLowerCase()))) return { message: "Collateral is not allowed" };
|
|
2917
2959
|
});
|
|
2918
2960
|
/**
|
|
2961
|
+
* A validation rule that checks if the offer's oracle addresses are allowed for its chain.
|
|
2962
|
+
* @param oraclesByChainId - Allowed oracles indexed by chain id.
|
|
2963
|
+
* @returns The issue that was found. If the offer is valid, this will be undefined.
|
|
2964
|
+
*/
|
|
2965
|
+
const oracle = ({ oraclesByChainId }) => single("oracle", "Validates that offer collateral oracles are in the allowed oracle list for the offer chain", (offer) => {
|
|
2966
|
+
const allowedOracles = oraclesByChainId[offer.chainId]?.map((oracle) => oracle.toLowerCase());
|
|
2967
|
+
if (!allowedOracles || allowedOracles.length === 0) return { message: `No allowed oracles for chain ${offer.chainId}` };
|
|
2968
|
+
if (offer.collaterals.some((collateral) => !allowedOracles.includes(collateral.oracle.toLowerCase()))) return { message: "Oracle is not allowed" };
|
|
2969
|
+
});
|
|
2970
|
+
/**
|
|
2919
2971
|
* A batch validation rule that ensures all offers in a tree have the same maker address.
|
|
2920
2972
|
* Returns an issue only for the first non-conforming offer.
|
|
2921
2973
|
* This rule is signing-agnostic; signer verification is handled at the collector level.
|
|
@@ -2946,7 +2998,11 @@ const amountMutualExclusivity = () => single("amount_mutual_exclusivity", "Valid
|
|
|
2946
2998
|
//#region src/gatekeeper/morphoRules.ts
|
|
2947
2999
|
const morphoRules = (chains) => {
|
|
2948
3000
|
const assetsByChainId = {};
|
|
2949
|
-
|
|
3001
|
+
const oraclesByChainId = {};
|
|
3002
|
+
for (const chain of chains) {
|
|
3003
|
+
assetsByChainId[chain.id] = assets[chain.id.toString()] ?? [];
|
|
3004
|
+
oraclesByChainId[chain.id] = oracles$1[chain.id.toString()] ?? [];
|
|
3005
|
+
}
|
|
2950
3006
|
return [
|
|
2951
3007
|
sameMaker(),
|
|
2952
3008
|
amountMutualExclusivity(),
|
|
@@ -2960,14 +3016,15 @@ const morphoRules = (chains) => {
|
|
|
2960
3016
|
],
|
|
2961
3017
|
allowedAddresses: chains.flatMap((c) => getCallbackAddresses(c.name))
|
|
2962
3018
|
}),
|
|
2963
|
-
token({ assetsByChainId })
|
|
3019
|
+
token({ assetsByChainId }),
|
|
3020
|
+
oracle({ oraclesByChainId })
|
|
2964
3021
|
];
|
|
2965
3022
|
};
|
|
2966
3023
|
|
|
2967
3024
|
//#endregion
|
|
2968
3025
|
//#region src/gatekeeper/ConfigRules.ts
|
|
2969
3026
|
/**
|
|
2970
|
-
* Build the configured rules (maturities + callback addresses + loan tokens) for the provided chains.
|
|
3027
|
+
* Build the configured rules (maturities + callback addresses + loan tokens + oracles) for the provided chains.
|
|
2971
3028
|
* @param chains - Chains to include in the configured rules.
|
|
2972
3029
|
* @returns Sorted list of config rules.
|
|
2973
3030
|
*/
|
|
@@ -2999,6 +3056,12 @@ function buildConfigRules(chains) {
|
|
|
2999
3056
|
chain_id: chain.id,
|
|
3000
3057
|
address: normalizeAddress(address)
|
|
3001
3058
|
});
|
|
3059
|
+
const oracles = oracles$1[chain.id.toString()] ?? [];
|
|
3060
|
+
for (const address of oracles) rules.push({
|
|
3061
|
+
type: "oracle",
|
|
3062
|
+
chain_id: chain.id,
|
|
3063
|
+
address: normalizeAddress(address)
|
|
3064
|
+
});
|
|
3002
3065
|
}
|
|
3003
3066
|
rules.sort(compareConfigRules);
|
|
3004
3067
|
return rules;
|
|
@@ -3020,6 +3083,10 @@ function buildConfigRulesChecksum(rules) {
|
|
|
3020
3083
|
hash.update(`callback:${rule.chain_id}:${rule.callback_type}:${rule.address}\n`);
|
|
3021
3084
|
continue;
|
|
3022
3085
|
}
|
|
3086
|
+
if (rule.type === "oracle") {
|
|
3087
|
+
hash.update(`oracle:${rule.chain_id}:${rule.address}\n`);
|
|
3088
|
+
continue;
|
|
3089
|
+
}
|
|
3023
3090
|
hash.update(`loan_token:${rule.chain_id}:${rule.address}\n`);
|
|
3024
3091
|
}
|
|
3025
3092
|
return hash.digest("hex");
|
|
@@ -3036,6 +3103,7 @@ function compareConfigRules(left, right) {
|
|
|
3036
3103
|
return left.address.localeCompare(right.address);
|
|
3037
3104
|
}
|
|
3038
3105
|
if (left.type === "loan_token" && right.type === "loan_token") return left.address.localeCompare(right.address);
|
|
3106
|
+
if (left.type === "oracle" && right.type === "oracle") return left.address.localeCompare(right.address);
|
|
3039
3107
|
return 0;
|
|
3040
3108
|
}
|
|
3041
3109
|
|
|
@@ -3652,7 +3720,8 @@ var OfferListResponse = class extends SuccessResponse {};
|
|
|
3652
3720
|
__decorate([ApiProperty({
|
|
3653
3721
|
type: "string",
|
|
3654
3722
|
nullable: true,
|
|
3655
|
-
example: offerCursorExample
|
|
3723
|
+
example: offerCursorExample,
|
|
3724
|
+
description: "Pagination cursor. Offer hash (0x...) for maker queries; base64url-encoded cursor for obligation queries."
|
|
3656
3725
|
})], OfferListResponse.prototype, "cursor", void 0);
|
|
3657
3726
|
__decorate([ApiProperty({
|
|
3658
3727
|
type: () => [OfferListItemResponse],
|
|
@@ -4205,11 +4274,17 @@ const configRulesLoanTokenExample = {
|
|
|
4205
4274
|
chain_id: 1,
|
|
4206
4275
|
address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
|
|
4207
4276
|
};
|
|
4277
|
+
const configRulesOracleExample = {
|
|
4278
|
+
type: "oracle",
|
|
4279
|
+
chain_id: 1,
|
|
4280
|
+
address: "0xDddd770BADd886dF3864029e4B377B5F6a2B6b83"
|
|
4281
|
+
};
|
|
4208
4282
|
const configRulesChecksumExample = "f1d2d2f924e986ac86fdf7b36c94bcdf";
|
|
4209
4283
|
const configRulesPayloadExample = [
|
|
4210
4284
|
configRulesMaturityExample,
|
|
4211
4285
|
configRulesCallbackExample,
|
|
4212
|
-
configRulesLoanTokenExample
|
|
4286
|
+
configRulesLoanTokenExample,
|
|
4287
|
+
configRulesOracleExample
|
|
4213
4288
|
];
|
|
4214
4289
|
const configContractNames = [
|
|
4215
4290
|
"mempool",
|
|
@@ -4360,7 +4435,7 @@ __decorate([
|
|
|
4360
4435
|
name: "types",
|
|
4361
4436
|
type: ["string"],
|
|
4362
4437
|
required: false,
|
|
4363
|
-
example: "maturity,loan_token",
|
|
4438
|
+
example: "maturity,loan_token,oracle",
|
|
4364
4439
|
description: "Filter by rule types (comma-separated).",
|
|
4365
4440
|
style: "form",
|
|
4366
4441
|
explode: false
|
|
@@ -4590,6 +4665,9 @@ function isValidBase64urlJson(val) {
|
|
|
4590
4665
|
return false;
|
|
4591
4666
|
}
|
|
4592
4667
|
}
|
|
4668
|
+
function isValidOfferHashCursor(val) {
|
|
4669
|
+
return /^0x[a-f0-9]{64}$/i.test(val);
|
|
4670
|
+
}
|
|
4593
4671
|
const csvArray = (schema) => z$2.preprocess((value) => {
|
|
4594
4672
|
if (value === void 0) return void 0;
|
|
4595
4673
|
if (Array.isArray(value)) {
|
|
@@ -4615,10 +4693,11 @@ const PaginationQueryParams = z$2.object({
|
|
|
4615
4693
|
const ConfigRuleTypes = z$2.enum([
|
|
4616
4694
|
"maturity",
|
|
4617
4695
|
"callback",
|
|
4618
|
-
"loan_token"
|
|
4696
|
+
"loan_token",
|
|
4697
|
+
"oracle"
|
|
4619
4698
|
]);
|
|
4620
4699
|
const GetConfigRulesQueryParams = z$2.object({
|
|
4621
|
-
cursor: z$2.string().regex(/^(maturity|callback|loan_token):[1-9]\d*:.+$/, { message: "Cursor must be in the format type:chain_id:<value>" }).optional().meta({
|
|
4700
|
+
cursor: z$2.string().regex(/^(maturity|callback|loan_token|oracle):[1-9]\d*:.+$/, { message: "Cursor must be in the format type:chain_id:<value>" }).optional().meta({
|
|
4622
4701
|
description: "Pagination cursor in type:chain_id:<value> format",
|
|
4623
4702
|
example: "maturity:1:1730415600:end_of_next_month"
|
|
4624
4703
|
}),
|
|
@@ -4628,7 +4707,7 @@ const GetConfigRulesQueryParams = z$2.object({
|
|
|
4628
4707
|
}),
|
|
4629
4708
|
types: csvArray(ConfigRuleTypes).meta({
|
|
4630
4709
|
description: "Filter by rule types (comma-separated).",
|
|
4631
|
-
example: "maturity,loan_token"
|
|
4710
|
+
example: "maturity,loan_token,oracle"
|
|
4632
4711
|
}),
|
|
4633
4712
|
chains: csvArray(z$2.string().regex(/^[1-9]\d*$/, { message: "Chain must be a positive integer" }).transform((val) => Number.parseInt(val, 10))).meta({
|
|
4634
4713
|
description: "Filter by chain IDs (comma-separated).",
|
|
@@ -4649,8 +4728,11 @@ const GetConfigContractsQueryParams = z$2.object({
|
|
|
4649
4728
|
example: "1,8453"
|
|
4650
4729
|
})
|
|
4651
4730
|
});
|
|
4652
|
-
const GetOffersQueryParams =
|
|
4653
|
-
|
|
4731
|
+
const GetOffersQueryParams = PaginationQueryParams.omit({ cursor: true }).extend({
|
|
4732
|
+
cursor: z$2.string().optional().meta({
|
|
4733
|
+
description: "Pagination cursor. Use offer hash (0x...) for maker queries, base64url for obligation queries.",
|
|
4734
|
+
example: "eyJzaWRlIjoic2VsbCIsImN1cnJlbnRQcmljZSI6IjEwMDAwMDAwMDAwMDAwMDAwMDAiLCJibG9ja051bWJlciI6MSwiYXNzZXRzIjoiMTAwMDAwMDAwMDAwMDAwMDAwMCIsImhhc2giOiIweGRmZDY4NTllM2UwODJkMTkzODlhMWFlYzFiZGFkN2U4ZDkyZDk2YjFhYTc5NDBkYTkxYTMxMjVkMzFlM2JlNWIiLCJ0b3RhbFJldHVybmVkIjoxMCwibm93IjoxNjAwMDAwMDAwfQ"
|
|
4735
|
+
}),
|
|
4654
4736
|
side: z$2.enum(["buy", "sell"]).optional().meta({
|
|
4655
4737
|
description: "Side of the offer. Required when using obligation_id.",
|
|
4656
4738
|
example: "buy"
|
|
@@ -4674,11 +4756,29 @@ const GetOffersQueryParams = z$2.object({
|
|
|
4674
4756
|
});
|
|
4675
4757
|
return;
|
|
4676
4758
|
}
|
|
4677
|
-
if (hasMaker)
|
|
4759
|
+
if (hasMaker) {
|
|
4760
|
+
if (val.cursor !== void 0 && !isValidOfferHashCursor(val.cursor)) ctx.addIssue({
|
|
4761
|
+
code: "custom",
|
|
4762
|
+
path: ["cursor"],
|
|
4763
|
+
message: "Cursor must be a 32-byte hex offer hash when filtering by maker"
|
|
4764
|
+
});
|
|
4765
|
+
return;
|
|
4766
|
+
}
|
|
4678
4767
|
if (!hasObligation || !hasSide) ctx.addIssue({
|
|
4679
4768
|
code: "custom",
|
|
4680
4769
|
message: "Must provide either maker or both obligation_id and side"
|
|
4681
4770
|
});
|
|
4771
|
+
if (val.cursor !== void 0 && !isValidBase64urlJson(val.cursor)) ctx.addIssue({
|
|
4772
|
+
code: "custom",
|
|
4773
|
+
path: ["cursor"],
|
|
4774
|
+
message: "Invalid cursor format. Must be a valid base64url-encoded cursor object"
|
|
4775
|
+
});
|
|
4776
|
+
}).transform((val) => {
|
|
4777
|
+
if (val.maker && val.cursor) return {
|
|
4778
|
+
...val,
|
|
4779
|
+
cursor: val.cursor.toLowerCase()
|
|
4780
|
+
};
|
|
4781
|
+
return val;
|
|
4682
4782
|
});
|
|
4683
4783
|
const GetObligationsQueryParams = z$2.object({
|
|
4684
4784
|
...PaginationQueryParams.shape,
|
|
@@ -4827,6 +4927,7 @@ async function getConfigRules(query, chains) {
|
|
|
4827
4927
|
function formatCursor$1(rule) {
|
|
4828
4928
|
if (rule.type === "maturity") return `maturity:${rule.chain_id}:${rule.timestamp}:${rule.name}`;
|
|
4829
4929
|
if (rule.type === "callback") return `callback:${rule.chain_id}:${rule.callback_type}:${rule.address.toLowerCase()}`;
|
|
4930
|
+
if (rule.type === "oracle") return `oracle:${rule.chain_id}:${rule.address.toLowerCase()}`;
|
|
4830
4931
|
return `loan_token:${rule.chain_id}:${rule.address.toLowerCase()}`;
|
|
4831
4932
|
}
|
|
4832
4933
|
function parseCursor$1(cursor) {
|
|
@@ -4859,13 +4960,16 @@ function parseCursor$1(cursor) {
|
|
|
4859
4960
|
address: parseAddress(addressValue, "Cursor address")
|
|
4860
4961
|
};
|
|
4861
4962
|
}
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
|
|
4963
|
+
if (type === "loan_token" || type === "oracle") {
|
|
4964
|
+
const addressValue = rest.join(":");
|
|
4965
|
+
if (!addressValue) throw new BadRequestError(`Cursor must be in the format ${type}:chain_id:address`);
|
|
4966
|
+
return {
|
|
4967
|
+
type,
|
|
4968
|
+
chain_id,
|
|
4969
|
+
address: parseAddress(addressValue, "Cursor address")
|
|
4970
|
+
};
|
|
4971
|
+
}
|
|
4972
|
+
throw new BadRequestError("Cursor has an invalid rule type");
|
|
4869
4973
|
}
|
|
4870
4974
|
function findStartIndex$1(rules, cursor) {
|
|
4871
4975
|
let low = 0;
|
|
@@ -4883,7 +4987,7 @@ function parseAddress(address, label) {
|
|
|
4883
4987
|
return address.toLowerCase();
|
|
4884
4988
|
}
|
|
4885
4989
|
function isConfigRuleType(value) {
|
|
4886
|
-
return value === "maturity" || value === "callback" || value === "loan_token";
|
|
4990
|
+
return value === "maturity" || value === "callback" || value === "loan_token" || value === "oracle";
|
|
4887
4991
|
}
|
|
4888
4992
|
function isMaturityType(value) {
|
|
4889
4993
|
return Object.values(MaturityType).includes(value);
|
|
@@ -8266,9 +8370,9 @@ function create$6(db) {
|
|
|
8266
8370
|
blockNumber: r.blockNumber
|
|
8267
8371
|
}));
|
|
8268
8372
|
},
|
|
8269
|
-
upsert: async (oracles$
|
|
8270
|
-
if (oracles$
|
|
8271
|
-
const rows = oracles$
|
|
8373
|
+
upsert: async (oracles$2) => {
|
|
8374
|
+
if (oracles$2.length === 0) return;
|
|
8375
|
+
const rows = oracles$2.map((o) => ({
|
|
8272
8376
|
chainId: o.chainId,
|
|
8273
8377
|
address: o.address.toLowerCase(),
|
|
8274
8378
|
price: o.price !== null ? o.price.toString() : null,
|
|
@@ -10637,15 +10741,33 @@ async function seedMockOffers(parameters) {
|
|
|
10637
10741
|
const { db, gatekeeper, chainRegistry, count } = parameters;
|
|
10638
10742
|
if (count <= 0) return [];
|
|
10639
10743
|
const configuredChains = chainRegistry.list();
|
|
10640
|
-
const
|
|
10641
|
-
"
|
|
10642
|
-
"
|
|
10643
|
-
"
|
|
10644
|
-
"
|
|
10744
|
+
const assetsDecimals = {
|
|
10745
|
+
"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48": 6,
|
|
10746
|
+
"0x6b175474e89094c44da98b954eedeac495271d0f": 18,
|
|
10747
|
+
"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2": 18,
|
|
10748
|
+
"0x2260fac5e5542a773aa44fbcfedf7c193bc2c599": 8,
|
|
10749
|
+
"0x1abaea1f7c830bd89acc67ec4af516284b1bc33c": 6,
|
|
10750
|
+
"0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0": 18,
|
|
10751
|
+
"0x833589fcd6edb6e08f4c7c32d4f71b54bda02913": 6,
|
|
10752
|
+
"0x50c5725949a6f0c72e6c4a641f24049a917db0cb": 18,
|
|
10645
10753
|
"0x4200000000000000000000000000000000000006": 18,
|
|
10646
|
-
"
|
|
10647
|
-
"
|
|
10754
|
+
"0xcbb7c0000ab88b473b1f5afd9ef808440eed33bf": 8,
|
|
10755
|
+
"0xc1cba3fcea344f92d9239c08c0568f6f2f0ee452": 18,
|
|
10756
|
+
"0x60a3e35cc302bfa44cb288bc5a4f316fdb1adb42": 6,
|
|
10757
|
+
"0xce79ddb3152d52ff8fe65a4c7e058b035fcb560a": 18
|
|
10648
10758
|
};
|
|
10759
|
+
const assetsByChainId = {};
|
|
10760
|
+
const oraclesByChainId = {};
|
|
10761
|
+
for (const chain of configuredChains) {
|
|
10762
|
+
const assets$1 = assets[chain.id.toString()]?.map((asset) => asset.toLowerCase()) ?? [];
|
|
10763
|
+
if (assets$1.length === 0) throw new Error(`No gatekeeper assets configured for chain ${chain.id}`);
|
|
10764
|
+
const missingDecimals = assets$1.filter((asset) => assetsDecimals[asset] === void 0);
|
|
10765
|
+
if (missingDecimals.length > 0) throw new Error(`Missing decimals for assets on chain ${chain.id}: ${missingDecimals.join(", ")}`);
|
|
10766
|
+
assetsByChainId[chain.id] = assets$1;
|
|
10767
|
+
const oracles = oracles$1[chain.id.toString()]?.map((oracle) => oracle.toLowerCase()) ?? [];
|
|
10768
|
+
if (oracles.length === 0) throw new Error(`No gatekeeper oracles configured for chain ${chain.id}`);
|
|
10769
|
+
oraclesByChainId[chain.id] = oracles;
|
|
10770
|
+
}
|
|
10649
10771
|
const now = Math.floor(Date.now() / 1e3);
|
|
10650
10772
|
const offerBlockNumber = 1;
|
|
10651
10773
|
const positionBlockNumber = offerBlockNumber + 1;
|
|
@@ -10656,8 +10778,9 @@ async function seedMockOffers(parameters) {
|
|
|
10656
10778
|
const offers = createMockOffers({
|
|
10657
10779
|
count,
|
|
10658
10780
|
chains: configuredChains,
|
|
10659
|
-
|
|
10660
|
-
|
|
10781
|
+
assetsByChainId,
|
|
10782
|
+
oraclesByChainId,
|
|
10783
|
+
assetsDecimals,
|
|
10661
10784
|
start,
|
|
10662
10785
|
expiry,
|
|
10663
10786
|
maturity,
|
|
@@ -10683,24 +10806,53 @@ async function getOffersFromFile(filePath) {
|
|
|
10683
10806
|
return Array.isArray(data) ? data.map(from$12) : [from$12(data)];
|
|
10684
10807
|
}
|
|
10685
10808
|
function createMockOffers(parameters) {
|
|
10686
|
-
const { count, chains,
|
|
10809
|
+
const { count, chains, assetsByChainId, oraclesByChainId, assetsDecimals, start, expiry, maturity, chainRegistry } = parameters;
|
|
10810
|
+
if (chains.length === 0) throw new Error("No chains configured for mock offers");
|
|
10687
10811
|
return Array.from({ length: count }, () => {
|
|
10688
10812
|
const buy = Math.random() < .5;
|
|
10813
|
+
const chain = chains[Math.floor(Math.random() * chains.length)];
|
|
10814
|
+
const allowedAssets = assetsByChainId[chain.id] ?? [];
|
|
10815
|
+
if (allowedAssets.length === 0) throw new Error(`No allowed assets configured for chain ${chain.id}`);
|
|
10816
|
+
const loanToken = allowedAssets[Math.floor(Math.random() * allowedAssets.length)];
|
|
10689
10817
|
const offer = random({
|
|
10690
|
-
chains,
|
|
10691
|
-
loanTokens,
|
|
10818
|
+
chains: [chain],
|
|
10819
|
+
loanTokens: [loanToken],
|
|
10692
10820
|
assetsDecimals,
|
|
10693
10821
|
start,
|
|
10694
10822
|
expiry,
|
|
10695
10823
|
maturity,
|
|
10696
10824
|
buy
|
|
10697
10825
|
});
|
|
10826
|
+
const allowedOracles = oraclesByChainId[chain.id] ?? [];
|
|
10827
|
+
if (allowedOracles.length === 0) throw new Error(`No allowed oracles configured for chain ${chain.id}`);
|
|
10828
|
+
const collateralAssets = allowedAssets.filter((asset) => asset !== loanToken);
|
|
10829
|
+
if (collateralAssets.length === 0) throw new Error(`No collateral assets available for chain ${chain.id}`);
|
|
10830
|
+
const collateralCount = Math.min(collateralAssets.length, 1 + Math.floor(Math.random() * 3));
|
|
10831
|
+
const collateralPool = [...collateralAssets];
|
|
10832
|
+
const collateralSelections = [];
|
|
10833
|
+
while (collateralSelections.length < collateralCount && collateralPool.length > 0) {
|
|
10834
|
+
const index = Math.floor(Math.random() * collateralPool.length);
|
|
10835
|
+
const [value] = collateralPool.splice(index, 1);
|
|
10836
|
+
if (value !== void 0) collateralSelections.push(value);
|
|
10837
|
+
}
|
|
10838
|
+
collateralSelections.sort();
|
|
10839
|
+
const lltv = offer.collaterals[0]?.lltv ?? .86;
|
|
10840
|
+
const collaterals = collateralSelections.map((asset) => from$14({
|
|
10841
|
+
asset,
|
|
10842
|
+
oracle: allowedOracles[Math.floor(Math.random() * allowedOracles.length)],
|
|
10843
|
+
lltv
|
|
10844
|
+
}));
|
|
10698
10845
|
if (!chainRegistry.getById(offer.chainId)) throw new Error(`Missing chain config for id ${offer.chainId}`);
|
|
10699
10846
|
const callbackType = buy ? Type$1.BuyVaultV1Callback : Type$1.SellERC20Callback;
|
|
10700
10847
|
const callbackAddress = buy ? BUY_CALLBACK_ADDRESS : SELL_CALLBACK_ADDRESS;
|
|
10701
|
-
const callbackData = buildMockCallbackData(callbackType,
|
|
10848
|
+
const callbackData = buildMockCallbackData(callbackType, {
|
|
10849
|
+
...offer,
|
|
10850
|
+
collaterals
|
|
10851
|
+
});
|
|
10702
10852
|
return from$12({
|
|
10703
10853
|
...offer,
|
|
10854
|
+
loanToken,
|
|
10855
|
+
collaterals,
|
|
10704
10856
|
callback: {
|
|
10705
10857
|
address: callbackAddress,
|
|
10706
10858
|
data: callbackData
|
package/dist/index.browser.d.mts
CHANGED
|
@@ -1986,7 +1986,7 @@ interface paths {
|
|
|
1986
1986
|
chains?: number[];
|
|
1987
1987
|
/**
|
|
1988
1988
|
* @description Filter by rule types (comma-separated).
|
|
1989
|
-
* @example maturity,loan_token
|
|
1989
|
+
* @example maturity,loan_token,oracle
|
|
1990
1990
|
*/
|
|
1991
1991
|
types?: string[];
|
|
1992
1992
|
/**
|
|
@@ -2613,6 +2613,11 @@ interface components {
|
|
|
2613
2613
|
* "type": "loan_token",
|
|
2614
2614
|
* "chain_id": 1,
|
|
2615
2615
|
* "address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
|
|
2616
|
+
* },
|
|
2617
|
+
* {
|
|
2618
|
+
* "type": "oracle",
|
|
2619
|
+
* "chain_id": 1,
|
|
2620
|
+
* "address": "0xDddd770BADd886dF3864029e4B377B5F6a2B6b83"
|
|
2616
2621
|
* }
|
|
2617
2622
|
* ]
|
|
2618
2623
|
*/
|
|
@@ -2631,7 +2636,11 @@ interface components {
|
|
|
2631
2636
|
callback_type?: string;
|
|
2632
2637
|
};
|
|
2633
2638
|
OfferListResponse: {
|
|
2634
|
-
meta: components["schemas"]["Meta"];
|
|
2639
|
+
meta: components["schemas"]["Meta"];
|
|
2640
|
+
/**
|
|
2641
|
+
* @description Pagination cursor. Offer hash (0x...) for maker queries; base64url-encoded cursor for obligation queries.
|
|
2642
|
+
* @example eyJvZmZzZXQiOjEwMH0
|
|
2643
|
+
*/
|
|
2635
2644
|
cursor: string | null;
|
|
2636
2645
|
/**
|
|
2637
2646
|
* @description Offers matching the provided filters.
|
|
@@ -3219,19 +3228,32 @@ declare const schemas: {
|
|
|
3219
3228
|
maturity: "maturity";
|
|
3220
3229
|
callback: "callback";
|
|
3221
3230
|
loan_token: "loan_token";
|
|
3231
|
+
oracle: "oracle";
|
|
3222
3232
|
}>>>>;
|
|
3223
3233
|
chains: z$1.ZodOptional<z$1.ZodPipe<z$1.ZodTransform<{} | null | undefined, unknown>, z$1.ZodArray<z$1.ZodPipe<z$1.ZodString, z$1.ZodTransform<number, string>>>>>;
|
|
3224
3234
|
}, z$1.core.$strip>;
|
|
3225
|
-
readonly get_offers: z$1.ZodObject<{
|
|
3235
|
+
readonly get_offers: z$1.ZodPipe<z$1.ZodObject<{
|
|
3236
|
+
limit: z$1.ZodDefault<z$1.ZodOptional<z$1.ZodPipe<z$1.ZodPipe<z$1.ZodString, z$1.ZodTransform<number, string>>, z$1.ZodNumber>>>;
|
|
3237
|
+
cursor: z$1.ZodOptional<z$1.ZodString>;
|
|
3226
3238
|
side: z$1.ZodOptional<z$1.ZodEnum<{
|
|
3227
3239
|
buy: "buy";
|
|
3228
3240
|
sell: "sell";
|
|
3229
3241
|
}>>;
|
|
3230
3242
|
obligation_id: z$1.ZodOptional<z$1.ZodPipe<z$1.ZodString, z$1.ZodTransform<`0x${string}`, string>>>;
|
|
3231
3243
|
maker: z$1.ZodOptional<z$1.ZodPipe<z$1.ZodString, z$1.ZodTransform<`0x${string}`, string>>>;
|
|
3232
|
-
|
|
3233
|
-
limit:
|
|
3234
|
-
|
|
3244
|
+
}, z$1.core.$strip>, z$1.ZodTransform<{
|
|
3245
|
+
limit: number;
|
|
3246
|
+
cursor?: string | undefined;
|
|
3247
|
+
side?: "buy" | "sell" | undefined;
|
|
3248
|
+
obligation_id?: `0x${string}` | undefined;
|
|
3249
|
+
maker?: `0x${string}` | undefined;
|
|
3250
|
+
}, {
|
|
3251
|
+
limit: number;
|
|
3252
|
+
cursor?: string | undefined;
|
|
3253
|
+
side?: "buy" | "sell" | undefined;
|
|
3254
|
+
obligation_id?: `0x${string}` | undefined;
|
|
3255
|
+
maker?: `0x${string}` | undefined;
|
|
3256
|
+
}>>;
|
|
3235
3257
|
readonly get_obligations: z$1.ZodObject<{
|
|
3236
3258
|
cursor: z$1.ZodOptional<z$1.ZodString>;
|
|
3237
3259
|
chains: z$1.ZodOptional<z$1.ZodPipe<z$1.ZodTransform<{} | null | undefined, unknown>, z$1.ZodArray<z$1.ZodPipe<z$1.ZodString, z$1.ZodTransform<number, string>>>>>;
|
|
@@ -3485,6 +3507,10 @@ type ConfigRule = {
|
|
|
3485
3507
|
type: "loan_token";
|
|
3486
3508
|
chain_id: Id;
|
|
3487
3509
|
address: Address;
|
|
3510
|
+
} | {
|
|
3511
|
+
type: "oracle";
|
|
3512
|
+
chain_id: Id;
|
|
3513
|
+
address: Address;
|
|
3488
3514
|
};
|
|
3489
3515
|
type ValidationIssue = {
|
|
3490
3516
|
index: number;
|
|
@@ -3579,9 +3605,9 @@ type GatekeeperParameters = {
|
|
|
3579
3605
|
declare function create(parameters: GatekeeperParameters): Gatekeeper;
|
|
3580
3606
|
//#endregion
|
|
3581
3607
|
//#region src/gatekeeper/morphoRules.d.ts
|
|
3582
|
-
declare const morphoRules: (chains: Chain$1[]) => (Rule<Offer, "mixed_maker"> | Rule<Offer, "amount_mutual_exclusivity"> | Rule<Offer, "chain_ids"> | Rule<Offer, "maturity"> | Rule<Offer, "callback"> | Rule<Offer, "token">)[];
|
|
3608
|
+
declare const morphoRules: (chains: Chain$1[]) => (Rule<Offer, "mixed_maker"> | Rule<Offer, "amount_mutual_exclusivity"> | Rule<Offer, "chain_ids"> | Rule<Offer, "maturity"> | Rule<Offer, "callback"> | Rule<Offer, "token"> | Rule<Offer, "oracle">)[];
|
|
3583
3609
|
declare namespace Rules_d_exports {
|
|
3584
|
-
export { ValidityParameters, amountMutualExclusivity, callback, chains, maturity, sameMaker, token, validity };
|
|
3610
|
+
export { ValidityParameters, amountMutualExclusivity, callback, chains, maturity, oracle, sameMaker, token, validity };
|
|
3585
3611
|
}
|
|
3586
3612
|
type ValidityParameters = {
|
|
3587
3613
|
client: PublicClient<Transport, Chain$1>;
|
|
@@ -3620,6 +3646,16 @@ declare const token: ({
|
|
|
3620
3646
|
}: {
|
|
3621
3647
|
assetsByChainId: Partial<Record<Id, Address[]>>;
|
|
3622
3648
|
}) => Rule<Offer, "token">;
|
|
3649
|
+
/**
|
|
3650
|
+
* A validation rule that checks if the offer's oracle addresses are allowed for its chain.
|
|
3651
|
+
* @param oraclesByChainId - Allowed oracles indexed by chain id.
|
|
3652
|
+
* @returns The issue that was found. If the offer is valid, this will be undefined.
|
|
3653
|
+
*/
|
|
3654
|
+
declare const oracle: ({
|
|
3655
|
+
oraclesByChainId
|
|
3656
|
+
}: {
|
|
3657
|
+
oraclesByChainId: Partial<Record<Id, Address[]>>;
|
|
3658
|
+
}) => Rule<Offer, "oracle">;
|
|
3623
3659
|
/**
|
|
3624
3660
|
* A batch validation rule that ensures all offers in a tree have the same maker address.
|
|
3625
3661
|
* Returns an issue only for the first non-conforming offer.
|