@morpho-dev/router 0.6.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +2040 -2156
- package/dist/index.browser.d.mts +154 -290
- package/dist/index.browser.d.mts.map +1 -1
- package/dist/index.browser.d.ts +154 -290
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/index.browser.js +223 -464
- package/dist/index.browser.js.map +1 -1
- package/dist/index.browser.mjs +223 -464
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.node.d.mts +155 -301
- package/dist/index.node.d.mts.map +1 -1
- package/dist/index.node.d.ts +154 -300
- package/dist/index.node.d.ts.map +1 -1
- package/dist/index.node.js +1966 -2190
- package/dist/index.node.js.map +1 -1
- package/dist/index.node.mjs +1970 -2188
- package/dist/index.node.mjs.map +1 -1
- package/docs/integrator.md +5 -6
- package/package.json +1 -1
package/dist/index.browser.js
CHANGED
|
@@ -294,107 +294,14 @@ const Morpho = [
|
|
|
294
294
|
//#region src/core/Callback.ts
|
|
295
295
|
var Callback_exports = /* @__PURE__ */ __exportAll({
|
|
296
296
|
Type: () => Type$1,
|
|
297
|
-
decode: () => decode$2,
|
|
298
|
-
decodeBuyERC20: () => decodeBuyERC20,
|
|
299
|
-
decodeBuyVaultV1Callback: () => decodeBuyVaultV1Callback,
|
|
300
|
-
decodeSellERC20Callback: () => decodeSellERC20Callback,
|
|
301
|
-
encode: () => encode$2,
|
|
302
|
-
encodeBuyERC20: () => encodeBuyERC20,
|
|
303
|
-
encodeBuyVaultV1Callback: () => encodeBuyVaultV1Callback,
|
|
304
|
-
encodeSellERC20Callback: () => encodeSellERC20Callback,
|
|
305
297
|
isEmptyCallback: () => isEmptyCallback
|
|
306
298
|
});
|
|
307
299
|
let Type$1 = /* @__PURE__ */ function(Type) {
|
|
308
300
|
Type["BuyWithEmptyCallback"] = "buy_with_empty_callback";
|
|
309
|
-
Type["
|
|
310
|
-
Type["BuyVaultV1Callback"] = "buy_vault_v1_callback";
|
|
311
|
-
Type["SellERC20Callback"] = "sell_erc20_callback";
|
|
301
|
+
Type["SellWithEmptyCallback"] = "sell_with_empty_callback";
|
|
312
302
|
return Type;
|
|
313
303
|
}({});
|
|
314
304
|
const isEmptyCallback = (offer) => offer.callback.data === "0x";
|
|
315
|
-
function decode$2(type, data) {
|
|
316
|
-
switch (type) {
|
|
317
|
-
case Type$1.BuyERC20: return decodeBuyERC20(data);
|
|
318
|
-
case Type$1.BuyVaultV1Callback: return decodeBuyVaultV1Callback(data);
|
|
319
|
-
case Type$1.SellERC20Callback: return decodeSellERC20Callback(data);
|
|
320
|
-
default: throw new Error("Invalid callback type");
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
function encode$2(type, data) {
|
|
324
|
-
switch (type) {
|
|
325
|
-
case Type$1.BuyERC20:
|
|
326
|
-
if (!("tokens" in data)) throw new Error("Invalid callback data");
|
|
327
|
-
return encodeBuyERC20(data);
|
|
328
|
-
case Type$1.BuyVaultV1Callback:
|
|
329
|
-
if (!("vaults" in data)) throw new Error("Invalid callback data");
|
|
330
|
-
return encodeBuyVaultV1Callback(data);
|
|
331
|
-
case Type$1.SellERC20Callback:
|
|
332
|
-
if (!("collaterals" in data)) throw new Error("Invalid callback data");
|
|
333
|
-
return encodeSellERC20Callback(data);
|
|
334
|
-
default: throw new Error("Invalid callback type");
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
/**
|
|
338
|
-
* Decodes BuyERC20 callback data into positions.
|
|
339
|
-
* @param data - The ABI-encoded callback data containing token addresses and amounts.
|
|
340
|
-
* @returns Array of positions with contract address and amount.
|
|
341
|
-
* @throws If data is empty, malformed, or arrays have mismatched lengths.
|
|
342
|
-
*/
|
|
343
|
-
function decodeBuyERC20(data) {
|
|
344
|
-
if (!data || data === "0x") throw new Error("Empty callback data");
|
|
345
|
-
let tokens;
|
|
346
|
-
let amounts;
|
|
347
|
-
try {
|
|
348
|
-
[tokens, amounts] = (0, viem.decodeAbiParameters)([{ type: "address[]" }, { type: "uint256[]" }], data);
|
|
349
|
-
} catch (_) {
|
|
350
|
-
throw new Error("Invalid BuyERC20 callback data");
|
|
351
|
-
}
|
|
352
|
-
if (tokens.length !== amounts.length) throw new Error("Mismatched array lengths");
|
|
353
|
-
return tokens.map((token, index) => ({
|
|
354
|
-
contract: token,
|
|
355
|
-
amount: amounts[index]
|
|
356
|
-
}));
|
|
357
|
-
}
|
|
358
|
-
/**
|
|
359
|
-
* Encodes BuyERC20 callback parameters into ABI-encoded data.
|
|
360
|
-
* @param parameters - The tokens and amounts to encode.
|
|
361
|
-
* @returns ABI-encoded hex string.
|
|
362
|
-
*/
|
|
363
|
-
function encodeBuyERC20(parameters) {
|
|
364
|
-
return (0, viem.encodeAbiParameters)([{ type: "address[]" }, { type: "uint256[]" }], [parameters.tokens, parameters.amounts]);
|
|
365
|
-
}
|
|
366
|
-
function decodeBuyVaultV1Callback(data) {
|
|
367
|
-
if (!data || data === "0x") throw new Error("Empty callback data");
|
|
368
|
-
try {
|
|
369
|
-
const [vaults, amounts] = (0, viem.decodeAbiParameters)([{ type: "address[]" }, { type: "uint256[]" }], data);
|
|
370
|
-
if (vaults.length !== amounts.length) throw new Error("Mismatched array lengths");
|
|
371
|
-
return vaults.map((v, i) => ({
|
|
372
|
-
contract: v,
|
|
373
|
-
amount: amounts[i]
|
|
374
|
-
}));
|
|
375
|
-
} catch (_) {
|
|
376
|
-
throw new Error("Invalid BuyVaultV1Callback callback data");
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
function decodeSellERC20Callback(data) {
|
|
380
|
-
if (!data || data === "0x") throw new Error("Empty callback data");
|
|
381
|
-
try {
|
|
382
|
-
const [collaterals, amounts] = (0, viem.decodeAbiParameters)([{ type: "address[]" }, { type: "uint256[]" }], data);
|
|
383
|
-
if (collaterals.length !== amounts.length) throw new Error("Mismatched array lengths");
|
|
384
|
-
return collaterals.map((c, i) => ({
|
|
385
|
-
contract: c,
|
|
386
|
-
amount: amounts[i]
|
|
387
|
-
}));
|
|
388
|
-
} catch (_) {
|
|
389
|
-
throw new Error("Invalid SellERC20Callback callback data");
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
function encodeBuyVaultV1Callback(parameters) {
|
|
393
|
-
return (0, viem.encodeAbiParameters)([{ type: "address[]" }, { type: "uint256[]" }], [parameters.vaults, parameters.amounts]);
|
|
394
|
-
}
|
|
395
|
-
function encodeSellERC20Callback(parameters) {
|
|
396
|
-
return (0, viem.encodeAbiParameters)([{ type: "address[]" }, { type: "uint256[]" }], [parameters.collaterals, parameters.amounts]);
|
|
397
|
-
}
|
|
398
305
|
|
|
399
306
|
//#endregion
|
|
400
307
|
//#region src/utils/BigMath.ts
|
|
@@ -1150,11 +1057,9 @@ var Liquidity_exports = /* @__PURE__ */ __exportAll({
|
|
|
1150
1057
|
calculateMaxDebt: () => calculateMaxDebt,
|
|
1151
1058
|
generateAllowancePoolId: () => generateAllowancePoolId,
|
|
1152
1059
|
generateBalancePoolId: () => generateBalancePoolId,
|
|
1153
|
-
generateBuyVaultCallbackPoolId: () => generateBuyVaultCallbackPoolId,
|
|
1154
1060
|
generateDebtPoolId: () => generateDebtPoolId,
|
|
1155
1061
|
generateMarketLiquidityPoolId: () => generateMarketLiquidityPoolId,
|
|
1156
1062
|
generateObligationCollateralPoolId: () => generateObligationCollateralPoolId,
|
|
1157
|
-
generateSellERC20CallbackPoolId: () => generateSellERC20CallbackPoolId,
|
|
1158
1063
|
generateUserVaultPositionPoolId: () => generateUserVaultPositionPoolId,
|
|
1159
1064
|
generateVaultPositionPoolId: () => generateVaultPositionPoolId
|
|
1160
1065
|
});
|
|
@@ -1183,14 +1088,6 @@ function generateAllowancePoolId(parameters) {
|
|
|
1183
1088
|
return `${user}-${chainId.toString()}-${token}-allowance`.toLowerCase();
|
|
1184
1089
|
}
|
|
1185
1090
|
/**
|
|
1186
|
-
* Generate pool ID for sell ERC20 callback pools.
|
|
1187
|
-
* Each offer has its own callback pool to prevent liquidity conflicts.
|
|
1188
|
-
*/
|
|
1189
|
-
function generateSellERC20CallbackPoolId(parameters) {
|
|
1190
|
-
const { user, chainId, obligationId, token, offerHash } = parameters;
|
|
1191
|
-
return `${user}-${chainId.toString()}-${obligationId}-${token}-${offerHash}-sell_erc20_callback`.toLowerCase();
|
|
1192
|
-
}
|
|
1193
|
-
/**
|
|
1194
1091
|
* Generate pool ID for obligation collateral pools.
|
|
1195
1092
|
* Obligation collateral pools represent collateral already deposited in the obligation.
|
|
1196
1093
|
* These pools are shared across all offers with the same obligation.
|
|
@@ -1200,13 +1097,6 @@ function generateObligationCollateralPoolId(parameters) {
|
|
|
1200
1097
|
return `${user}-${chainId.toString()}-${obligationId}-${token}-obligation-collateral`.toLowerCase();
|
|
1201
1098
|
}
|
|
1202
1099
|
/**
|
|
1203
|
-
* Generate pool ID for buy vault callback pools.
|
|
1204
|
-
*/
|
|
1205
|
-
function generateBuyVaultCallbackPoolId(parameters) {
|
|
1206
|
-
const { user, chainId, vault, offerHash } = parameters;
|
|
1207
|
-
return `${user}-${chainId.toString()}-${vault}-${offerHash}-${Type$1.BuyVaultV1Callback}`.toLowerCase();
|
|
1208
|
-
}
|
|
1209
|
-
/**
|
|
1210
1100
|
* Generate pool ID for debt pools.
|
|
1211
1101
|
*/
|
|
1212
1102
|
function generateDebtPoolId(parameters) {
|
|
@@ -1586,6 +1476,7 @@ var Offer_exports = /* @__PURE__ */ __exportAll({
|
|
|
1586
1476
|
obligationId: () => obligationId,
|
|
1587
1477
|
random: () => random$1,
|
|
1588
1478
|
serialize: () => serialize,
|
|
1479
|
+
takeEvent: () => takeEvent,
|
|
1589
1480
|
toSnakeCase: () => toSnakeCase,
|
|
1590
1481
|
types: () => types
|
|
1591
1482
|
});
|
|
@@ -1704,7 +1595,7 @@ function random$1(config) {
|
|
|
1704
1595
|
const chain = config?.chains ? config.chains[int(config.chains.length)] : chains$1.ethereum;
|
|
1705
1596
|
const loanToken = config?.loanTokens ? config.loanTokens[int(config.loanTokens.length)] : address();
|
|
1706
1597
|
const collateralCandidates = config?.collateralTokens ? config.collateralTokens.filter((a) => a !== loanToken) : [address()];
|
|
1707
|
-
|
|
1598
|
+
collateralCandidates[int(collateralCandidates.length)];
|
|
1708
1599
|
const maturityOption = weightedChoice([["end_of_month", 1], ["end_of_next_month", 1]]);
|
|
1709
1600
|
const maturity = config?.maturity ?? from$11(maturityOption);
|
|
1710
1601
|
const lltv = from$13(weightedChoice([
|
|
@@ -1731,21 +1622,10 @@ function random$1(config) {
|
|
|
1731
1622
|
const unit = BigInt(10) ** BigInt(loanTokenDecimals);
|
|
1732
1623
|
const amountBase = BigInt(100 + int(999901));
|
|
1733
1624
|
const assetsScaled = config?.assets ?? amountBase * unit;
|
|
1734
|
-
const
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
};
|
|
1739
|
-
const sellCallbackAddress = "0x3333333333333333333333333333333333333333";
|
|
1740
|
-
const amount = assetsScaled * 1000000000000000000000n;
|
|
1741
|
-
return {
|
|
1742
|
-
address: sellCallbackAddress,
|
|
1743
|
-
data: encodeSellERC20Callback({
|
|
1744
|
-
collaterals: [collateralAsset],
|
|
1745
|
-
amounts: [amount]
|
|
1746
|
-
})
|
|
1747
|
-
};
|
|
1748
|
-
})();
|
|
1625
|
+
const emptyCallback = {
|
|
1626
|
+
address: viem.zeroAddress,
|
|
1627
|
+
data: "0x"
|
|
1628
|
+
};
|
|
1749
1629
|
return from$9({
|
|
1750
1630
|
maker: config?.maker ?? address(),
|
|
1751
1631
|
assets: assetsScaled,
|
|
@@ -1764,7 +1644,7 @@ function random$1(config) {
|
|
|
1764
1644
|
...random$3(),
|
|
1765
1645
|
lltv
|
|
1766
1646
|
})).sort((a, b) => a.asset.localeCompare(b.asset)),
|
|
1767
|
-
callback: config?.callback ??
|
|
1647
|
+
callback: config?.callback ?? emptyCallback
|
|
1768
1648
|
});
|
|
1769
1649
|
}
|
|
1770
1650
|
const weightedChoice = (pairs) => {
|
|
@@ -2054,6 +1934,94 @@ function decode$1(data) {
|
|
|
2054
1934
|
});
|
|
2055
1935
|
}
|
|
2056
1936
|
/**
|
|
1937
|
+
* ABI for the Take event emitted by the Morpho V2 contract.
|
|
1938
|
+
*/
|
|
1939
|
+
const takeEvent = {
|
|
1940
|
+
type: "event",
|
|
1941
|
+
name: "Take",
|
|
1942
|
+
inputs: [
|
|
1943
|
+
{
|
|
1944
|
+
name: "caller",
|
|
1945
|
+
type: "address",
|
|
1946
|
+
indexed: false,
|
|
1947
|
+
internalType: "address"
|
|
1948
|
+
},
|
|
1949
|
+
{
|
|
1950
|
+
name: "id",
|
|
1951
|
+
type: "bytes32",
|
|
1952
|
+
indexed: true,
|
|
1953
|
+
internalType: "bytes32"
|
|
1954
|
+
},
|
|
1955
|
+
{
|
|
1956
|
+
name: "maker",
|
|
1957
|
+
type: "address",
|
|
1958
|
+
indexed: true,
|
|
1959
|
+
internalType: "address"
|
|
1960
|
+
},
|
|
1961
|
+
{
|
|
1962
|
+
name: "taker",
|
|
1963
|
+
type: "address",
|
|
1964
|
+
indexed: true,
|
|
1965
|
+
internalType: "address"
|
|
1966
|
+
},
|
|
1967
|
+
{
|
|
1968
|
+
name: "offerIsBuy",
|
|
1969
|
+
type: "bool",
|
|
1970
|
+
indexed: false,
|
|
1971
|
+
internalType: "bool"
|
|
1972
|
+
},
|
|
1973
|
+
{
|
|
1974
|
+
name: "buyerAssets",
|
|
1975
|
+
type: "uint256",
|
|
1976
|
+
indexed: false,
|
|
1977
|
+
internalType: "uint256"
|
|
1978
|
+
},
|
|
1979
|
+
{
|
|
1980
|
+
name: "sellerAssets",
|
|
1981
|
+
type: "uint256",
|
|
1982
|
+
indexed: false,
|
|
1983
|
+
internalType: "uint256"
|
|
1984
|
+
},
|
|
1985
|
+
{
|
|
1986
|
+
name: "obligationUnits",
|
|
1987
|
+
type: "uint256",
|
|
1988
|
+
indexed: false,
|
|
1989
|
+
internalType: "uint256"
|
|
1990
|
+
},
|
|
1991
|
+
{
|
|
1992
|
+
name: "obligationShares",
|
|
1993
|
+
type: "uint256",
|
|
1994
|
+
indexed: false,
|
|
1995
|
+
internalType: "uint256"
|
|
1996
|
+
},
|
|
1997
|
+
{
|
|
1998
|
+
name: "buyerIsLender",
|
|
1999
|
+
type: "bool",
|
|
2000
|
+
indexed: false,
|
|
2001
|
+
internalType: "bool"
|
|
2002
|
+
},
|
|
2003
|
+
{
|
|
2004
|
+
name: "sellerIsBorrower",
|
|
2005
|
+
type: "bool",
|
|
2006
|
+
indexed: false,
|
|
2007
|
+
internalType: "bool"
|
|
2008
|
+
},
|
|
2009
|
+
{
|
|
2010
|
+
name: "group",
|
|
2011
|
+
type: "bytes32",
|
|
2012
|
+
indexed: false,
|
|
2013
|
+
internalType: "bytes32"
|
|
2014
|
+
},
|
|
2015
|
+
{
|
|
2016
|
+
name: "consumed",
|
|
2017
|
+
type: "uint256",
|
|
2018
|
+
indexed: false,
|
|
2019
|
+
internalType: "uint256"
|
|
2020
|
+
}
|
|
2021
|
+
],
|
|
2022
|
+
anonymous: false
|
|
2023
|
+
};
|
|
2024
|
+
/**
|
|
2057
2025
|
* ABI for the Consume event emitted by the Obligation contract.
|
|
2058
2026
|
*/
|
|
2059
2027
|
const consumedEvent = {
|
|
@@ -2908,8 +2876,8 @@ const offerExample = {
|
|
|
2908
2876
|
price: "2750000000000000000",
|
|
2909
2877
|
group: "0x000000000000000000000000000000000000000000000000000000000008b8f4",
|
|
2910
2878
|
session: "0x0000000000000000000000000000000000000000000000000000000000000000",
|
|
2911
|
-
callback: "
|
|
2912
|
-
callback_data: "
|
|
2879
|
+
callback: "0x0000000000000000000000000000000000000000",
|
|
2880
|
+
callback_data: "0x"
|
|
2913
2881
|
},
|
|
2914
2882
|
offer_hash: "0xac4bd8318ec914f89f8af913f162230575b0ac0696a19256bc12138c5cfe1427",
|
|
2915
2883
|
obligation_id: "0x25690ae1aee324a005be565f3bcdd16dbf8daf7969b26c181c8b8f467dad9abc",
|
|
@@ -2961,25 +2929,10 @@ const validateOfferExample = {
|
|
|
2961
2929
|
lltv: "860000000000000000"
|
|
2962
2930
|
}],
|
|
2963
2931
|
callback: {
|
|
2964
|
-
address: "
|
|
2965
|
-
data: "
|
|
2932
|
+
address: "0x0000000000000000000000000000000000000000",
|
|
2933
|
+
data: "0x"
|
|
2966
2934
|
}
|
|
2967
2935
|
};
|
|
2968
|
-
const callbackTypesRequestExample = { callbacks: [{
|
|
2969
|
-
chain_id: 1,
|
|
2970
|
-
addresses: [
|
|
2971
|
-
"0x1111111111111111111111111111111111111111",
|
|
2972
|
-
"0x3333333333333333333333333333333333333333",
|
|
2973
|
-
"0x9999999999999999999999999999999999999999"
|
|
2974
|
-
]
|
|
2975
|
-
}] };
|
|
2976
|
-
const callbackTypesResponseExample = [{
|
|
2977
|
-
chain_id: 1,
|
|
2978
|
-
sell_erc20_callback: ["0x1111111111111111111111111111111111111111"],
|
|
2979
|
-
buy_erc20: ["0x5555555555555555555555555555555555555555"],
|
|
2980
|
-
buy_vault_v1_callback: ["0x3333333333333333333333333333333333333333"],
|
|
2981
|
-
not_supported: ["0x9999999999999999999999999999999999999999"]
|
|
2982
|
-
}];
|
|
2983
2936
|
const routerStatusExample = {
|
|
2984
2937
|
status: "live",
|
|
2985
2938
|
initialized: true,
|
|
@@ -3048,55 +3001,6 @@ __decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
|
3048
3001
|
type: "string",
|
|
3049
3002
|
example: validateOfferExample.callback.data
|
|
3050
3003
|
})], ValidateCallbackRequest.prototype, "data", void 0);
|
|
3051
|
-
var CallbackTypesChainRequest = class {};
|
|
3052
|
-
__decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
3053
|
-
type: "number",
|
|
3054
|
-
example: callbackTypesRequestExample.callbacks[0].chain_id
|
|
3055
|
-
})], CallbackTypesChainRequest.prototype, "chain_id", void 0);
|
|
3056
|
-
__decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
3057
|
-
type: () => [String],
|
|
3058
|
-
example: callbackTypesRequestExample.callbacks[0].addresses
|
|
3059
|
-
})], CallbackTypesChainRequest.prototype, "addresses", void 0);
|
|
3060
|
-
var CallbackTypesRequest = class {};
|
|
3061
|
-
__decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
3062
|
-
type: () => [CallbackTypesChainRequest],
|
|
3063
|
-
example: callbackTypesRequestExample.callbacks
|
|
3064
|
-
})], CallbackTypesRequest.prototype, "callbacks", void 0);
|
|
3065
|
-
var CallbackTypesChainResponse = class {};
|
|
3066
|
-
__decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
3067
|
-
type: "number",
|
|
3068
|
-
example: callbackTypesResponseExample[0].chain_id
|
|
3069
|
-
})], CallbackTypesChainResponse.prototype, "chain_id", void 0);
|
|
3070
|
-
__decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
3071
|
-
type: () => [String],
|
|
3072
|
-
required: false,
|
|
3073
|
-
example: callbackTypesResponseExample[0].buy_vault_v1_callback
|
|
3074
|
-
})], CallbackTypesChainResponse.prototype, "buy_vault_v1_callback", void 0);
|
|
3075
|
-
__decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
3076
|
-
type: () => [String],
|
|
3077
|
-
required: false,
|
|
3078
|
-
example: callbackTypesResponseExample[0].sell_erc20_callback
|
|
3079
|
-
})], CallbackTypesChainResponse.prototype, "sell_erc20_callback", void 0);
|
|
3080
|
-
__decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
3081
|
-
type: () => [String],
|
|
3082
|
-
required: false,
|
|
3083
|
-
example: callbackTypesResponseExample[0].buy_erc20
|
|
3084
|
-
})], CallbackTypesChainResponse.prototype, "buy_erc20", void 0);
|
|
3085
|
-
__decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
3086
|
-
type: () => [String],
|
|
3087
|
-
example: callbackTypesResponseExample[0].not_supported
|
|
3088
|
-
})], CallbackTypesChainResponse.prototype, "not_supported", void 0);
|
|
3089
|
-
var CallbackTypesSuccessResponse = class extends SuccessResponse {};
|
|
3090
|
-
__decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
3091
|
-
type: "string",
|
|
3092
|
-
nullable: true,
|
|
3093
|
-
example: "maturity:1:1730415600:end_of_next_month"
|
|
3094
|
-
})], CallbackTypesSuccessResponse.prototype, "cursor", void 0);
|
|
3095
|
-
__decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
3096
|
-
type: () => [CallbackTypesChainResponse],
|
|
3097
|
-
description: "Callback types grouped by chain.",
|
|
3098
|
-
example: callbackTypesResponseExample
|
|
3099
|
-
})], CallbackTypesSuccessResponse.prototype, "data", void 0);
|
|
3100
3004
|
var AskResponse = class {};
|
|
3101
3005
|
__decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
3102
3006
|
type: "string",
|
|
@@ -3261,7 +3165,8 @@ var OfferListResponse = class extends SuccessResponse {};
|
|
|
3261
3165
|
__decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
3262
3166
|
type: "string",
|
|
3263
3167
|
nullable: true,
|
|
3264
|
-
example: offerCursorExample
|
|
3168
|
+
example: offerCursorExample,
|
|
3169
|
+
description: "Pagination cursor. Offer hash (0x...) for maker queries; base64url-encoded cursor for obligation queries."
|
|
3265
3170
|
})], OfferListResponse.prototype, "cursor", void 0);
|
|
3266
3171
|
__decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
3267
3172
|
type: () => [OfferListItemResponse],
|
|
@@ -3613,7 +3518,7 @@ __decorate([
|
|
|
3613
3518
|
methods: ["post"],
|
|
3614
3519
|
path: "/v1/validate",
|
|
3615
3520
|
summary: "Validate offers",
|
|
3616
|
-
description: "Validates offers against router validation rules. Returns unsigned payload + root on success, or issues only on validation failure."
|
|
3521
|
+
description: "Validates offers against router validation rules. Only empty callbacks (zero address, 0x data) are accepted. Returns unsigned payload + root on success, or issues only on validation failure."
|
|
3617
3522
|
}),
|
|
3618
3523
|
(0, openapi_metadata_decorators.ApiBody)({ type: ValidateOffersRequest }),
|
|
3619
3524
|
(0, openapi_metadata_decorators.ApiResponse)({
|
|
@@ -3632,28 +3537,6 @@ ValidateController = __decorate([(0, openapi_metadata_decorators.ApiTags)("Make"
|
|
|
3632
3537
|
description: "Bad Request",
|
|
3633
3538
|
type: BadRequestResponse
|
|
3634
3539
|
})], ValidateController);
|
|
3635
|
-
let CallbacksController = class CallbacksController {
|
|
3636
|
-
async resolveCallbackTypes() {}
|
|
3637
|
-
};
|
|
3638
|
-
__decorate([
|
|
3639
|
-
(0, openapi_metadata_decorators.ApiOperation)({
|
|
3640
|
-
methods: ["post"],
|
|
3641
|
-
path: "/v1/callbacks",
|
|
3642
|
-
summary: "Resolve callback types",
|
|
3643
|
-
description: "Returns callback types for callback addresses grouped by chain."
|
|
3644
|
-
}),
|
|
3645
|
-
(0, openapi_metadata_decorators.ApiBody)({ type: CallbackTypesRequest }),
|
|
3646
|
-
(0, openapi_metadata_decorators.ApiResponse)({
|
|
3647
|
-
status: 200,
|
|
3648
|
-
description: "Success",
|
|
3649
|
-
type: CallbackTypesSuccessResponse
|
|
3650
|
-
})
|
|
3651
|
-
], CallbacksController.prototype, "resolveCallbackTypes", null);
|
|
3652
|
-
CallbacksController = __decorate([(0, openapi_metadata_decorators.ApiTags)("Make"), (0, openapi_metadata_decorators.ApiResponse)({
|
|
3653
|
-
status: 400,
|
|
3654
|
-
description: "Bad Request",
|
|
3655
|
-
type: BadRequestResponse
|
|
3656
|
-
})], CallbacksController);
|
|
3657
3540
|
let OffersController = class OffersController {
|
|
3658
3541
|
async getOffers() {}
|
|
3659
3542
|
};
|
|
@@ -3803,22 +3686,21 @@ const configRulesMaturityExample = {
|
|
|
3803
3686
|
name: "end_of_next_month",
|
|
3804
3687
|
timestamp: 1730415600
|
|
3805
3688
|
};
|
|
3806
|
-
const configRulesCallbackExample = {
|
|
3807
|
-
type: "callback",
|
|
3808
|
-
chain_id: 1,
|
|
3809
|
-
address: "0x1111111111111111111111111111111111111111",
|
|
3810
|
-
callback_type: "sell_erc20_callback"
|
|
3811
|
-
};
|
|
3812
3689
|
const configRulesLoanTokenExample = {
|
|
3813
3690
|
type: "loan_token",
|
|
3814
3691
|
chain_id: 1,
|
|
3815
3692
|
address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
|
|
3816
3693
|
};
|
|
3694
|
+
const configRulesOracleExample = {
|
|
3695
|
+
type: "oracle",
|
|
3696
|
+
chain_id: 1,
|
|
3697
|
+
address: "0xDddd770BADd886dF3864029e4B377B5F6a2B6b83"
|
|
3698
|
+
};
|
|
3817
3699
|
const configRulesChecksumExample = "f1d2d2f924e986ac86fdf7b36c94bcdf";
|
|
3818
3700
|
const configRulesPayloadExample = [
|
|
3819
3701
|
configRulesMaturityExample,
|
|
3820
|
-
|
|
3821
|
-
|
|
3702
|
+
configRulesLoanTokenExample,
|
|
3703
|
+
configRulesOracleExample
|
|
3822
3704
|
];
|
|
3823
3705
|
const configContractNames = [
|
|
3824
3706
|
"mempool",
|
|
@@ -3881,14 +3763,9 @@ __decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
|
3881
3763
|
})], ConfigRulesRuleResponse.prototype, "timestamp", void 0);
|
|
3882
3764
|
__decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
3883
3765
|
type: "string",
|
|
3884
|
-
example:
|
|
3766
|
+
example: configRulesLoanTokenExample.address,
|
|
3885
3767
|
required: false
|
|
3886
3768
|
})], ConfigRulesRuleResponse.prototype, "address", void 0);
|
|
3887
|
-
__decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
3888
|
-
type: "string",
|
|
3889
|
-
example: configRulesCallbackExample.callback_type,
|
|
3890
|
-
required: false
|
|
3891
|
-
})], ConfigRulesRuleResponse.prototype, "callback_type", void 0);
|
|
3892
3769
|
var ConfigRulesSuccessResponse = class {};
|
|
3893
3770
|
__decorate([(0, openapi_metadata_decorators.ApiProperty)({ type: () => ConfigRulesMeta })], ConfigRulesSuccessResponse.prototype, "meta", void 0);
|
|
3894
3771
|
__decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
@@ -3949,7 +3826,7 @@ __decorate([
|
|
|
3949
3826
|
methods: ["get"],
|
|
3950
3827
|
path: "/v1/config/rules",
|
|
3951
3828
|
summary: "Get config rules",
|
|
3952
|
-
description: "Returns configured rules for supported chains."
|
|
3829
|
+
description: "Returns configured rules (maturities, loan tokens, oracles) for supported chains."
|
|
3953
3830
|
}),
|
|
3954
3831
|
(0, openapi_metadata_decorators.ApiQuery)({
|
|
3955
3832
|
name: "cursor",
|
|
@@ -3969,7 +3846,7 @@ __decorate([
|
|
|
3969
3846
|
name: "types",
|
|
3970
3847
|
type: ["string"],
|
|
3971
3848
|
required: false,
|
|
3972
|
-
example: "maturity,loan_token",
|
|
3849
|
+
example: "maturity,loan_token,oracle",
|
|
3973
3850
|
description: "Filter by rule types (comma-separated).",
|
|
3974
3851
|
style: "form",
|
|
3975
3852
|
explode: false
|
|
@@ -4128,8 +4005,7 @@ const OpenApi = async () => {
|
|
|
4128
4005
|
ObligationsController,
|
|
4129
4006
|
HealthController,
|
|
4130
4007
|
UsersController,
|
|
4131
|
-
ValidateController
|
|
4132
|
-
CallbacksController
|
|
4008
|
+
ValidateController
|
|
4133
4009
|
],
|
|
4134
4010
|
document: {
|
|
4135
4011
|
openapi: "3.1.0",
|
|
@@ -4200,6 +4076,9 @@ function isValidBase64urlJson(val) {
|
|
|
4200
4076
|
return false;
|
|
4201
4077
|
}
|
|
4202
4078
|
}
|
|
4079
|
+
function isValidOfferHashCursor(val) {
|
|
4080
|
+
return /^0x[a-f0-9]{64}$/i.test(val);
|
|
4081
|
+
}
|
|
4203
4082
|
const csvArray = (schema) => zod.preprocess((value) => {
|
|
4204
4083
|
if (value === void 0) return void 0;
|
|
4205
4084
|
if (Array.isArray(value)) {
|
|
@@ -4225,10 +4104,11 @@ const PaginationQueryParams = zod.object({
|
|
|
4225
4104
|
const ConfigRuleTypes = zod.enum([
|
|
4226
4105
|
"maturity",
|
|
4227
4106
|
"callback",
|
|
4228
|
-
"loan_token"
|
|
4107
|
+
"loan_token",
|
|
4108
|
+
"oracle"
|
|
4229
4109
|
]);
|
|
4230
4110
|
const GetConfigRulesQueryParams = zod.object({
|
|
4231
|
-
cursor: zod.string().regex(/^(maturity|callback|loan_token):[1-9]\d*:.+$/, { message: "Cursor must be in the format type:chain_id:<value>" }).optional().meta({
|
|
4111
|
+
cursor: zod.string().regex(/^(maturity|callback|loan_token|oracle):[1-9]\d*:.+$/, { message: "Cursor must be in the format type:chain_id:<value>" }).optional().meta({
|
|
4232
4112
|
description: "Pagination cursor in type:chain_id:<value> format",
|
|
4233
4113
|
example: "maturity:1:1730415600:end_of_next_month"
|
|
4234
4114
|
}),
|
|
@@ -4238,7 +4118,7 @@ const GetConfigRulesQueryParams = zod.object({
|
|
|
4238
4118
|
}),
|
|
4239
4119
|
types: csvArray(ConfigRuleTypes).meta({
|
|
4240
4120
|
description: "Filter by rule types (comma-separated).",
|
|
4241
|
-
example: "maturity,loan_token"
|
|
4121
|
+
example: "maturity,loan_token,oracle"
|
|
4242
4122
|
}),
|
|
4243
4123
|
chains: csvArray(zod.string().regex(/^[1-9]\d*$/, { message: "Chain must be a positive integer" }).transform((val) => Number.parseInt(val, 10))).meta({
|
|
4244
4124
|
description: "Filter by chain IDs (comma-separated).",
|
|
@@ -4259,8 +4139,11 @@ const GetConfigContractsQueryParams = zod.object({
|
|
|
4259
4139
|
example: "1,8453"
|
|
4260
4140
|
})
|
|
4261
4141
|
});
|
|
4262
|
-
const GetOffersQueryParams =
|
|
4263
|
-
|
|
4142
|
+
const GetOffersQueryParams = PaginationQueryParams.omit({ cursor: true }).extend({
|
|
4143
|
+
cursor: zod.string().optional().meta({
|
|
4144
|
+
description: "Pagination cursor. Use offer hash (0x...) for maker queries, base64url for obligation queries.",
|
|
4145
|
+
example: "eyJzaWRlIjoic2VsbCIsImN1cnJlbnRQcmljZSI6IjEwMDAwMDAwMDAwMDAwMDAwMDAiLCJibG9ja051bWJlciI6MSwiYXNzZXRzIjoiMTAwMDAwMDAwMDAwMDAwMDAwMCIsImhhc2giOiIweGRmZDY4NTllM2UwODJkMTkzODlhMWFlYzFiZGFkN2U4ZDkyZDk2YjFhYTc5NDBkYTkxYTMxMjVkMzFlM2JlNWIiLCJ0b3RhbFJldHVybmVkIjoxMCwibm93IjoxNjAwMDAwMDAwfQ"
|
|
4146
|
+
}),
|
|
4264
4147
|
side: zod.enum(["buy", "sell"]).optional().meta({
|
|
4265
4148
|
description: "Side of the offer. Required when using obligation_id.",
|
|
4266
4149
|
example: "buy"
|
|
@@ -4284,11 +4167,29 @@ const GetOffersQueryParams = zod.object({
|
|
|
4284
4167
|
});
|
|
4285
4168
|
return;
|
|
4286
4169
|
}
|
|
4287
|
-
if (hasMaker)
|
|
4170
|
+
if (hasMaker) {
|
|
4171
|
+
if (val.cursor !== void 0 && !isValidOfferHashCursor(val.cursor)) ctx.addIssue({
|
|
4172
|
+
code: "custom",
|
|
4173
|
+
path: ["cursor"],
|
|
4174
|
+
message: "Cursor must be a 32-byte hex offer hash when filtering by maker"
|
|
4175
|
+
});
|
|
4176
|
+
return;
|
|
4177
|
+
}
|
|
4288
4178
|
if (!hasObligation || !hasSide) ctx.addIssue({
|
|
4289
4179
|
code: "custom",
|
|
4290
4180
|
message: "Must provide either maker or both obligation_id and side"
|
|
4291
4181
|
});
|
|
4182
|
+
if (val.cursor !== void 0 && !isValidBase64urlJson(val.cursor)) ctx.addIssue({
|
|
4183
|
+
code: "custom",
|
|
4184
|
+
path: ["cursor"],
|
|
4185
|
+
message: "Invalid cursor format. Must be a valid base64url-encoded cursor object"
|
|
4186
|
+
});
|
|
4187
|
+
}).transform((val) => {
|
|
4188
|
+
if (val.maker && val.cursor) return {
|
|
4189
|
+
...val,
|
|
4190
|
+
cursor: val.cursor.toLowerCase()
|
|
4191
|
+
};
|
|
4192
|
+
return val;
|
|
4292
4193
|
});
|
|
4293
4194
|
const GetObligationsQueryParams = zod.object({
|
|
4294
4195
|
...PaginationQueryParams.shape,
|
|
@@ -4361,16 +4262,6 @@ const GetBookParams = zod.object({
|
|
|
4361
4262
|
})
|
|
4362
4263
|
});
|
|
4363
4264
|
const ValidateOffersBody = zod.object({ offers: zod.array(zod.unknown()).min(1, { message: "'offers' must contain at least 1 offer" }) }).strict();
|
|
4364
|
-
const CallbackTypesBody = zod.object({ callbacks: zod.array(zod.object({
|
|
4365
|
-
chain_id: zod.number().int().positive().meta({
|
|
4366
|
-
description: "Chain id.",
|
|
4367
|
-
example: 1
|
|
4368
|
-
}),
|
|
4369
|
-
addresses: zod.array(zod.string().regex(/^0x[a-fA-F0-9]{40}$/, { error: "Callback address must be a valid 20-byte address" }).transform((val) => val.toLowerCase())).meta({
|
|
4370
|
-
description: "Callback contract addresses.",
|
|
4371
|
-
example: ["0x1111111111111111111111111111111111111111", "0x3333333333333333333333333333333333333333"]
|
|
4372
|
-
})
|
|
4373
|
-
}).strict()) }).strict();
|
|
4374
4265
|
const GetUserPositionsParams = zod.object({
|
|
4375
4266
|
...PaginationQueryParams.shape,
|
|
4376
4267
|
user_address: zod.string().regex(/^0x[a-fA-F0-9]{40}$/, { error: "User address must be a valid 20-byte address" }).transform((val) => val.toLowerCase()).meta({
|
|
@@ -4389,7 +4280,6 @@ const schemas = {
|
|
|
4389
4280
|
get_obligation: GetObligationParams,
|
|
4390
4281
|
get_book: GetBookParams,
|
|
4391
4282
|
validate_offers: ValidateOffersBody,
|
|
4392
|
-
callback_types: CallbackTypesBody,
|
|
4393
4283
|
get_user_positions: GetUserPositionsParams
|
|
4394
4284
|
};
|
|
4395
4285
|
function parse(action, query) {
|
|
@@ -4404,7 +4294,6 @@ function safeParse(action, query, error) {
|
|
|
4404
4294
|
var Schema_exports = /* @__PURE__ */ __exportAll({
|
|
4405
4295
|
BookResponse: () => BookResponse_exports,
|
|
4406
4296
|
BooksController: () => BooksController,
|
|
4407
|
-
CallbacksController: () => CallbacksController,
|
|
4408
4297
|
ChainHealth: () => ChainHealth,
|
|
4409
4298
|
ChainsHealthResponse: () => ChainsHealthResponse,
|
|
4410
4299
|
CollectorHealth: () => CollectorHealth,
|
|
@@ -4683,23 +4572,11 @@ function createHttpClient(config) {
|
|
|
4683
4572
|
issues: []
|
|
4684
4573
|
};
|
|
4685
4574
|
};
|
|
4686
|
-
const getCallbackTypes = async (requestPayload) => {
|
|
4687
|
-
const response = await request("/v1/callbacks", {
|
|
4688
|
-
method: "POST",
|
|
4689
|
-
headers: { "content-type": "application/json" },
|
|
4690
|
-
body: JSON.stringify(requestPayload)
|
|
4691
|
-
});
|
|
4692
|
-
const json = await response.json();
|
|
4693
|
-
if (!response.ok) throw new Error(`Gatekeeper callbacks request failed: ${extractErrorMessage(json) ?? response.statusText}`);
|
|
4694
|
-
if (!("data" in json) || !Array.isArray(json.data)) throw new Error("Gatekeeper callbacks response is invalid.");
|
|
4695
|
-
return json.data;
|
|
4696
|
-
};
|
|
4697
4575
|
return {
|
|
4698
4576
|
baseUrl,
|
|
4699
4577
|
validate,
|
|
4700
4578
|
getConfigRules,
|
|
4701
|
-
isAllowed
|
|
4702
|
-
getCallbackTypes
|
|
4579
|
+
isAllowed
|
|
4703
4580
|
};
|
|
4704
4581
|
}
|
|
4705
4582
|
function mergeHeaders(base, extra) {
|
|
@@ -4823,48 +4700,23 @@ function create(parameters) {
|
|
|
4823
4700
|
|
|
4824
4701
|
//#endregion
|
|
4825
4702
|
//#region src/gatekeeper/GateConfig.ts
|
|
4826
|
-
/**
|
|
4827
|
-
* Returns the callback configuration for a given chain and callback type, if it exists.
|
|
4828
|
-
*
|
|
4829
|
-
* @param chain - Chain name for which to read the validation configuration
|
|
4830
|
-
* @param type - Callback type to retrieve
|
|
4831
|
-
* @returns The matching callback configuration or undefined if not configured
|
|
4832
|
-
*/
|
|
4833
|
-
function getCallback(chain, type) {
|
|
4834
|
-
return configs[chain].callbacks?.find((c) => c.type === type);
|
|
4835
|
-
}
|
|
4836
|
-
/**
|
|
4837
|
-
* Attempts to infer the configured callback type from a callback address on a chain.
|
|
4838
|
-
* Skips the empty callback type as it does not carry addresses.
|
|
4839
|
-
*
|
|
4840
|
-
* @param chain - Chain name for which to infer the callback type
|
|
4841
|
-
* @param address - Callback contract address
|
|
4842
|
-
* @returns The callback type when found, otherwise undefined
|
|
4843
|
-
*/
|
|
4844
|
-
function getCallbackType(chain, address) {
|
|
4845
|
-
return configs[chain].callbacks?.find((c) => c.type !== Type$1.BuyWithEmptyCallback && c.addresses.includes(address?.toLowerCase()))?.type;
|
|
4846
|
-
}
|
|
4847
|
-
/**
|
|
4848
|
-
* Returns the list of allowed non-empty callback addresses for a chain.
|
|
4849
|
-
*
|
|
4850
|
-
* @param chain - Chain name
|
|
4851
|
-
* @returns Array of allowed callback addresses (lowercased). Empty when none configured
|
|
4852
|
-
*/
|
|
4853
|
-
const getCallbackAddresses = (chain) => {
|
|
4854
|
-
return configs[chain].callbacks?.filter((c) => c.type !== Type$1.BuyWithEmptyCallback).flatMap((c) => c.addresses) ?? [];
|
|
4855
|
-
};
|
|
4856
4703
|
const assets = {
|
|
4857
4704
|
[ChainId.ETHEREUM.toString()]: [
|
|
4858
4705
|
"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
4859
4706
|
"0x6B175474E89094C44Da98b954EedeAC495271d0F",
|
|
4860
4707
|
"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
|
|
4861
|
-
"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"
|
|
4708
|
+
"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",
|
|
4709
|
+
"0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c",
|
|
4710
|
+
"0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0"
|
|
4862
4711
|
],
|
|
4863
4712
|
[ChainId.BASE.toString()]: [
|
|
4864
4713
|
"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
4865
4714
|
"0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb",
|
|
4866
4715
|
"0x4200000000000000000000000000000000000006",
|
|
4867
|
-
"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"
|
|
4716
|
+
"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",
|
|
4717
|
+
"0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf",
|
|
4718
|
+
"0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452",
|
|
4719
|
+
"0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42"
|
|
4868
4720
|
],
|
|
4869
4721
|
[ChainId["ETHEREUM-VIRTUAL-TESTNET"].toString()]: [
|
|
4870
4722
|
"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
@@ -4880,65 +4732,58 @@ const assets = {
|
|
|
4880
4732
|
"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"
|
|
4881
4733
|
]
|
|
4882
4734
|
};
|
|
4735
|
+
const oracles = {
|
|
4736
|
+
[ChainId.ETHEREUM.toString()]: [
|
|
4737
|
+
"0xDddd770BADd886dF3864029e4B377B5F6a2B6b83",
|
|
4738
|
+
"0x9CB3f4276bcD149b3668e1a645a964bC12877b89",
|
|
4739
|
+
"0x48F7E36EB6B826B2dF4B2E630B62Cd25e89E40e2",
|
|
4740
|
+
"0x6Eb9F4128CeBc8B885A4d8562Db1Addf097f7348",
|
|
4741
|
+
"0xbD60A6770b27E084E8617335ddE769241B0e71D8",
|
|
4742
|
+
"0xAe12416c1F21B0698c27fe042D9309C83baC6597"
|
|
4743
|
+
],
|
|
4744
|
+
[ChainId.BASE.toString()]: [
|
|
4745
|
+
"0xD09048c8B568Dbf5f189302beA26c9edABFC4858",
|
|
4746
|
+
"0xFEa2D58cEfCb9fcb597723c6bAE66fFE4193aFE4",
|
|
4747
|
+
"0x05D2618404668D725B66c0f32B39e4EC15B393dC",
|
|
4748
|
+
"0xE1bb8E5b4930eC9FeC7f7943FCF6227649F14B37",
|
|
4749
|
+
"0x663BECd10daE6C4A3Dcd89F1d76c1174199639B9",
|
|
4750
|
+
"0x10b95702a0ce895972C91e432C4f7E19811D320E",
|
|
4751
|
+
"0x8C87DbD7A0c647A4291592Bc2994dbF95880fE2F",
|
|
4752
|
+
"0x4A11590e5326138B514E08A9B52202D42077Ca65",
|
|
4753
|
+
"0xa54122f0E0766258377Ffe732e454A3248f454F4"
|
|
4754
|
+
],
|
|
4755
|
+
[ChainId["ETHEREUM-VIRTUAL-TESTNET"].toString()]: [
|
|
4756
|
+
"0xDddd770BADd886dF3864029e4B377B5F6a2B6b83",
|
|
4757
|
+
"0x9CB3f4276bcD149b3668e1a645a964bC12877b89",
|
|
4758
|
+
"0x48F7E36EB6B826B2dF4B2E630B62Cd25e89E40e2",
|
|
4759
|
+
"0x6Eb9F4128CeBc8B885A4d8562Db1Addf097f7348",
|
|
4760
|
+
"0xbD60A6770b27E084E8617335ddE769241B0e71D8",
|
|
4761
|
+
"0xAe12416c1F21B0698c27fe042D9309C83baC6597"
|
|
4762
|
+
],
|
|
4763
|
+
[ChainId.ANVIL.toString()]: [
|
|
4764
|
+
"0xDddd770BADd886dF3864029e4B377B5F6a2B6b83",
|
|
4765
|
+
"0x9CB3f4276bcD149b3668e1a645a964bC12877b89",
|
|
4766
|
+
"0x48F7E36EB6B826B2dF4B2E630B62Cd25e89E40e2",
|
|
4767
|
+
"0x6Eb9F4128CeBc8B885A4d8562Db1Addf097f7348",
|
|
4768
|
+
"0xbD60A6770b27E084E8617335ddE769241B0e71D8",
|
|
4769
|
+
"0xAe12416c1F21B0698c27fe042D9309C83baC6597"
|
|
4770
|
+
]
|
|
4771
|
+
};
|
|
4883
4772
|
const configs = {
|
|
4884
4773
|
ethereum: {
|
|
4885
|
-
callbacks: [
|
|
4886
|
-
{
|
|
4887
|
-
type: Type$1.BuyVaultV1Callback,
|
|
4888
|
-
addresses: ["0x3333333333333333333333333333333333333333", "0x4444444444444444444444444444444444444444"],
|
|
4889
|
-
vaultFactories: ["0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101", "0x1897A8997241C1cD4bD0698647e4EB7213535c24"]
|
|
4890
|
-
},
|
|
4891
|
-
{
|
|
4892
|
-
type: Type$1.SellERC20Callback,
|
|
4893
|
-
addresses: ["0x1111111111111111111111111111111111111111", "0x2222222222222222222222222222222222222222"]
|
|
4894
|
-
},
|
|
4895
|
-
{ type: Type$1.BuyWithEmptyCallback }
|
|
4896
|
-
],
|
|
4774
|
+
callbacks: [{ type: Type$1.BuyWithEmptyCallback }, { type: Type$1.SellWithEmptyCallback }],
|
|
4897
4775
|
maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth]
|
|
4898
4776
|
},
|
|
4899
4777
|
base: {
|
|
4900
|
-
callbacks: [
|
|
4901
|
-
{
|
|
4902
|
-
type: Type$1.BuyVaultV1Callback,
|
|
4903
|
-
addresses: ["0x3333333333333333333333333333333333333333", "0x4444444444444444444444444444444444444444"],
|
|
4904
|
-
vaultFactories: ["0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101", "0xFf62A7c278C62eD665133147129245053Bbf5918"]
|
|
4905
|
-
},
|
|
4906
|
-
{
|
|
4907
|
-
type: Type$1.SellERC20Callback,
|
|
4908
|
-
addresses: ["0x1111111111111111111111111111111111111111", "0x2222222222222222222222222222222222222222"]
|
|
4909
|
-
},
|
|
4910
|
-
{ type: Type$1.BuyWithEmptyCallback }
|
|
4911
|
-
],
|
|
4778
|
+
callbacks: [{ type: Type$1.BuyWithEmptyCallback }, { type: Type$1.SellWithEmptyCallback }],
|
|
4912
4779
|
maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth]
|
|
4913
4780
|
},
|
|
4914
4781
|
"ethereum-virtual-testnet": {
|
|
4915
|
-
callbacks: [
|
|
4916
|
-
{
|
|
4917
|
-
type: Type$1.BuyVaultV1Callback,
|
|
4918
|
-
addresses: ["0x3333333333333333333333333333333333333333", "0x4444444444444444444444444444444444444444"],
|
|
4919
|
-
vaultFactories: ["0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101", "0x1897A8997241C1cD4bD0698647e4EB7213535c24"]
|
|
4920
|
-
},
|
|
4921
|
-
{
|
|
4922
|
-
type: Type$1.SellERC20Callback,
|
|
4923
|
-
addresses: ["0x1111111111111111111111111111111111111111", "0x2222222222222222222222222222222222222222"]
|
|
4924
|
-
},
|
|
4925
|
-
{ type: Type$1.BuyWithEmptyCallback }
|
|
4926
|
-
],
|
|
4782
|
+
callbacks: [{ type: Type$1.BuyWithEmptyCallback }, { type: Type$1.SellWithEmptyCallback }],
|
|
4927
4783
|
maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth]
|
|
4928
4784
|
},
|
|
4929
4785
|
anvil: {
|
|
4930
|
-
callbacks: [
|
|
4931
|
-
{
|
|
4932
|
-
type: Type$1.BuyVaultV1Callback,
|
|
4933
|
-
addresses: ["0x3333333333333333333333333333333333333333", "0x4444444444444444444444444444444444444444"],
|
|
4934
|
-
vaultFactories: ["0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101", "0x1897A8997241C1cD4bD0698647e4EB7213535c24"]
|
|
4935
|
-
},
|
|
4936
|
-
{
|
|
4937
|
-
type: Type$1.SellERC20Callback,
|
|
4938
|
-
addresses: ["0x1111111111111111111111111111111111111111", "0x2222222222222222222222222222222222222222"]
|
|
4939
|
-
},
|
|
4940
|
-
{ type: Type$1.BuyWithEmptyCallback }
|
|
4941
|
-
],
|
|
4786
|
+
callbacks: [{ type: Type$1.BuyWithEmptyCallback }, { type: Type$1.SellWithEmptyCallback }],
|
|
4942
4787
|
maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth]
|
|
4943
4788
|
}
|
|
4944
4789
|
};
|
|
@@ -4950,6 +4795,7 @@ var Rules_exports = /* @__PURE__ */ __exportAll({
|
|
|
4950
4795
|
callback: () => callback,
|
|
4951
4796
|
chains: () => chains,
|
|
4952
4797
|
maturity: () => maturity,
|
|
4798
|
+
oracle: () => oracle,
|
|
4953
4799
|
sameMaker: () => sameMaker,
|
|
4954
4800
|
token: () => token,
|
|
4955
4801
|
validity: () => validity
|
|
@@ -4957,109 +4803,13 @@ var Rules_exports = /* @__PURE__ */ __exportAll({
|
|
|
4957
4803
|
/**
|
|
4958
4804
|
* set of rules to validate offers.
|
|
4959
4805
|
*
|
|
4960
|
-
* @param
|
|
4806
|
+
* @param _parameters - Validity parameters with chain and client
|
|
4961
4807
|
* @returns Array of validation rules to evaluate against offers
|
|
4962
4808
|
*/
|
|
4963
|
-
function validity(
|
|
4964
|
-
|
|
4965
|
-
|
|
4966
|
-
|
|
4967
|
-
if (callbackType !== Type$1.SellERC20Callback) return;
|
|
4968
|
-
const decoded = decode$2(callbackType, offer.callback.data);
|
|
4969
|
-
if (decoded.length === 0) return { message: "Callback data cannot be decoded or is empty." };
|
|
4970
|
-
if (callbackType === Type$1.SellERC20Callback) {
|
|
4971
|
-
const offerCollaterals = new Set(offer.collaterals.map((c) => c.asset.toLowerCase()));
|
|
4972
|
-
if (decoded.length !== offer.collaterals.length) return { message: `Sell callback collateral length mismatch. Expected ${offer.collaterals.length}, got ${decoded.length}.` };
|
|
4973
|
-
for (const { contract } of decoded) if (!offerCollaterals.has(contract.toLowerCase())) return { message: "Sell callback collateral is not part of offer collaterals." };
|
|
4974
|
-
}
|
|
4975
|
-
});
|
|
4976
|
-
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) => {
|
|
4977
|
-
const validationIssues = /* @__PURE__ */ new Map();
|
|
4978
|
-
const offersByVaultAddress = /* @__PURE__ */ new Map();
|
|
4979
|
-
for (let i = 0; i < offers.length; i++) {
|
|
4980
|
-
const offer = offers[i];
|
|
4981
|
-
if (getCallbackType(client.chain.name, offer.callback.address) !== Type$1.BuyVaultV1Callback) continue;
|
|
4982
|
-
try {
|
|
4983
|
-
const callbackVaults = decodeBuyVaultV1Callback(offer.callback.data);
|
|
4984
|
-
for (const { contract } of callbackVaults) {
|
|
4985
|
-
const normalizedVaultAddress = contract.toLowerCase();
|
|
4986
|
-
if (!offersByVaultAddress.has(normalizedVaultAddress)) offersByVaultAddress.set(normalizedVaultAddress, []);
|
|
4987
|
-
offersByVaultAddress.get(normalizedVaultAddress).push({
|
|
4988
|
-
index: i,
|
|
4989
|
-
offer
|
|
4990
|
-
});
|
|
4991
|
-
}
|
|
4992
|
-
} catch (_) {}
|
|
4993
|
-
}
|
|
4994
|
-
const uniqueVaultAddresses = Array.from(offersByVaultAddress.keys());
|
|
4995
|
-
if (uniqueVaultAddresses.length === 0) return validationIssues;
|
|
4996
|
-
const allowedFactories = getCallback(client.chain.name, Type$1.BuyVaultV1Callback)?.vaultFactories.map((f) => f.toLowerCase());
|
|
4997
|
-
if (!allowedFactories) return validationIssues;
|
|
4998
|
-
const multicallContracts = [];
|
|
4999
|
-
for (const vaultAddress of uniqueVaultAddresses) {
|
|
5000
|
-
multicallContracts.push({
|
|
5001
|
-
address: vaultAddress,
|
|
5002
|
-
abi: ERC4626,
|
|
5003
|
-
functionName: "asset"
|
|
5004
|
-
});
|
|
5005
|
-
for (const factoryAddress of allowedFactories) multicallContracts.push({
|
|
5006
|
-
address: factoryAddress,
|
|
5007
|
-
abi: MetaMorphoFactory,
|
|
5008
|
-
functionName: "isMetaMorpho",
|
|
5009
|
-
args: [vaultAddress]
|
|
5010
|
-
});
|
|
5011
|
-
}
|
|
5012
|
-
const multicallResults = await (0, viem_actions.multicall)(client, {
|
|
5013
|
-
contracts: multicallContracts,
|
|
5014
|
-
allowFailure: true
|
|
5015
|
-
});
|
|
5016
|
-
const vaultAssetByAddress = /* @__PURE__ */ new Map();
|
|
5017
|
-
const registeredVaults = /* @__PURE__ */ new Set();
|
|
5018
|
-
const numberOfFactories = allowedFactories.length;
|
|
5019
|
-
let resultIndex = 0;
|
|
5020
|
-
for (const vaultAddress of uniqueVaultAddresses) {
|
|
5021
|
-
const assetCallResult = multicallResults[resultIndex++];
|
|
5022
|
-
const assetAddress = assetCallResult.status === "success" ? assetCallResult.result : null;
|
|
5023
|
-
vaultAssetByAddress.set(vaultAddress, assetAddress);
|
|
5024
|
-
let isRegisteredInFactory = false;
|
|
5025
|
-
for (let factoryIndex = 0; factoryIndex < numberOfFactories; factoryIndex++) {
|
|
5026
|
-
const factoryCallResult = multicallResults[resultIndex++];
|
|
5027
|
-
if (factoryCallResult.status === "success" && factoryCallResult.result === true) isRegisteredInFactory = true;
|
|
5028
|
-
}
|
|
5029
|
-
if (isRegisteredInFactory) registeredVaults.add(vaultAddress);
|
|
5030
|
-
}
|
|
5031
|
-
const uniqueOffers = /* @__PURE__ */ new Map();
|
|
5032
|
-
for (const offersArray of offersByVaultAddress.values()) for (const { index, offer } of offersArray) uniqueOffers.set(index, offer);
|
|
5033
|
-
for (const [index, offer] of uniqueOffers) try {
|
|
5034
|
-
const callbackVaults = decodeBuyVaultV1Callback(offer.callback.data);
|
|
5035
|
-
const vaultsWithIssues = [];
|
|
5036
|
-
for (const { contract } of callbackVaults) {
|
|
5037
|
-
const normalizedVaultAddress = contract.toLowerCase();
|
|
5038
|
-
const assetAddress = vaultAssetByAddress.get(normalizedVaultAddress);
|
|
5039
|
-
const isRegistered = registeredVaults.has(normalizedVaultAddress);
|
|
5040
|
-
const failureReasons = [];
|
|
5041
|
-
if (assetAddress === null) failureReasons.push("asset call failed");
|
|
5042
|
-
else if (assetAddress && assetAddress.toLowerCase() !== offer.loanToken.toLowerCase()) failureReasons.push("asset mismatch");
|
|
5043
|
-
if (!isRegistered) failureReasons.push("not registered in factory");
|
|
5044
|
-
if (failureReasons.length > 0) vaultsWithIssues.push({
|
|
5045
|
-
vaultAddress: contract,
|
|
5046
|
-
failureReasons: failureReasons.join(", ")
|
|
5047
|
-
});
|
|
5048
|
-
}
|
|
5049
|
-
if (vaultsWithIssues.length > 0) {
|
|
5050
|
-
const failureDetails = vaultsWithIssues.map((v) => `${v.vaultAddress} (${v.failureReasons})`).join("; ");
|
|
5051
|
-
validationIssues.set(index, { message: `Buy offer callback vaults are invalid: ${failureDetails}` });
|
|
5052
|
-
}
|
|
5053
|
-
} catch (_) {}
|
|
5054
|
-
return validationIssues;
|
|
5055
|
-
});
|
|
5056
|
-
return [
|
|
5057
|
-
single("expiry", "Validates that offer has not expired", (offer) => {
|
|
5058
|
-
if (offer.expiry < Math.floor(Date.now() / 1e3)) return { message: "Expiry mismatch" };
|
|
5059
|
-
}),
|
|
5060
|
-
sellErc20CallbackInvalid,
|
|
5061
|
-
buyCallbackVaultInvalid
|
|
5062
|
-
];
|
|
4809
|
+
function validity(_parameters) {
|
|
4810
|
+
return [single("expiry", "Validates that offer has not expired", (offer) => {
|
|
4811
|
+
if (offer.expiry < Math.floor(Date.now() / 1e3)) return { message: "Expiry mismatch" };
|
|
4812
|
+
})];
|
|
5063
4813
|
}
|
|
5064
4814
|
const chains = ({ chains }) => single("chain_ids", `Validates that offer chain is one of: [${chains.map((c) => c.id).join(", ")}]`, (offer) => {
|
|
5065
4815
|
const allowedChainIds = chains.map((c) => c.id);
|
|
@@ -5069,12 +4819,10 @@ const maturity = ({ maturities }) => single("maturity", `Validates that offer ma
|
|
|
5069
4819
|
const allowedMaturities = maturities.map((m) => from$11(m));
|
|
5070
4820
|
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}` };
|
|
5071
4821
|
});
|
|
5072
|
-
const callback = ({ callbacks
|
|
5073
|
-
if (isEmptyCallback(offer)
|
|
5074
|
-
if (isEmptyCallback(offer) &&
|
|
5075
|
-
if (
|
|
5076
|
-
if (!allowedAddresses.includes(offer.callback.address?.toLowerCase())) return { message: `Callback address ${offer.callback.address} is not allowed.` };
|
|
5077
|
-
}
|
|
4822
|
+
const callback = ({ callbacks }) => single("callback", `Validates callbacks: buy empty callback is ${callbacks.includes(Type$1.BuyWithEmptyCallback) ? "allowed" : "not allowed"}; sell empty callback is ${callbacks.includes(Type$1.SellWithEmptyCallback) ? "allowed" : "not allowed"}; non-empty callbacks are rejected`, (offer) => {
|
|
4823
|
+
if (!isEmptyCallback(offer)) return { message: "Non-empty callbacks are not supported." };
|
|
4824
|
+
if (isEmptyCallback(offer) && offer.buy && !callbacks.includes(Type$1.BuyWithEmptyCallback)) return { message: "Buy offers with empty callback not allowed." };
|
|
4825
|
+
if (isEmptyCallback(offer) && !offer.buy && !callbacks.includes(Type$1.SellWithEmptyCallback)) return { message: "Sell offers with empty callback not allowed." };
|
|
5078
4826
|
});
|
|
5079
4827
|
/**
|
|
5080
4828
|
* A validation rule that checks if the offer's tokens are allowed for its chain.
|
|
@@ -5088,6 +4836,16 @@ const token = ({ assetsByChainId }) => single("token", "Validates that offer loa
|
|
|
5088
4836
|
if (offer.collaterals.some((collateral) => !allowedAssets.includes(collateral.asset.toLowerCase()))) return { message: "Collateral is not allowed" };
|
|
5089
4837
|
});
|
|
5090
4838
|
/**
|
|
4839
|
+
* A validation rule that checks if the offer's oracle addresses are allowed for its chain.
|
|
4840
|
+
* @param oraclesByChainId - Allowed oracles indexed by chain id.
|
|
4841
|
+
* @returns The issue that was found. If the offer is valid, this will be undefined.
|
|
4842
|
+
*/
|
|
4843
|
+
const oracle = ({ oraclesByChainId }) => single("oracle", "Validates that offer collateral oracles are in the allowed oracle list for the offer chain", (offer) => {
|
|
4844
|
+
const allowedOracles = oraclesByChainId[offer.chainId]?.map((oracle) => oracle.toLowerCase());
|
|
4845
|
+
if (!allowedOracles || allowedOracles.length === 0) return { message: `No allowed oracles for chain ${offer.chainId}` };
|
|
4846
|
+
if (offer.collaterals.some((collateral) => !allowedOracles.includes(collateral.oracle.toLowerCase()))) return { message: "Oracle is not allowed" };
|
|
4847
|
+
});
|
|
4848
|
+
/**
|
|
5091
4849
|
* A batch validation rule that ensures all offers in a tree have the same maker address.
|
|
5092
4850
|
* Returns an issue only for the first non-conforming offer.
|
|
5093
4851
|
* This rule is signing-agnostic; signer verification is handled at the collector level.
|
|
@@ -5118,21 +4876,22 @@ const amountMutualExclusivity = () => single("amount_mutual_exclusivity", "Valid
|
|
|
5118
4876
|
//#region src/gatekeeper/morphoRules.ts
|
|
5119
4877
|
const morphoRules = (chains$2) => {
|
|
5120
4878
|
const assetsByChainId = {};
|
|
5121
|
-
|
|
4879
|
+
const oraclesByChainId = {};
|
|
4880
|
+
for (const chain of chains$2) {
|
|
4881
|
+
assetsByChainId[chain.id] = assets[chain.id.toString()] ?? [];
|
|
4882
|
+
oraclesByChainId[chain.id] = oracles[chain.id.toString()] ?? [];
|
|
4883
|
+
}
|
|
5122
4884
|
return [
|
|
5123
4885
|
sameMaker(),
|
|
5124
4886
|
amountMutualExclusivity(),
|
|
5125
4887
|
chains({ chains: chains$2 }),
|
|
5126
4888
|
maturity({ maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth] }),
|
|
5127
4889
|
callback({
|
|
5128
|
-
callbacks: [
|
|
5129
|
-
|
|
5130
|
-
Type$1.BuyVaultV1Callback,
|
|
5131
|
-
Type$1.SellERC20Callback
|
|
5132
|
-
],
|
|
5133
|
-
allowedAddresses: chains$2.flatMap((c) => getCallbackAddresses(c.name))
|
|
4890
|
+
callbacks: [Type$1.BuyWithEmptyCallback, Type$1.SellWithEmptyCallback],
|
|
4891
|
+
allowedAddresses: []
|
|
5134
4892
|
}),
|
|
5135
|
-
token({ assetsByChainId })
|
|
4893
|
+
token({ assetsByChainId }),
|
|
4894
|
+
oracle({ oraclesByChainId })
|
|
5136
4895
|
];
|
|
5137
4896
|
};
|
|
5138
4897
|
|