@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.mjs
CHANGED
|
@@ -253,107 +253,14 @@ const Morpho = [
|
|
|
253
253
|
//#region src/core/Callback.ts
|
|
254
254
|
var Callback_exports = /* @__PURE__ */ __exportAll({
|
|
255
255
|
Type: () => Type$1,
|
|
256
|
-
decode: () => decode$2,
|
|
257
|
-
decodeBuyERC20: () => decodeBuyERC20,
|
|
258
|
-
decodeBuyVaultV1Callback: () => decodeBuyVaultV1Callback,
|
|
259
|
-
decodeSellERC20Callback: () => decodeSellERC20Callback,
|
|
260
|
-
encode: () => encode$2,
|
|
261
|
-
encodeBuyERC20: () => encodeBuyERC20,
|
|
262
|
-
encodeBuyVaultV1Callback: () => encodeBuyVaultV1Callback,
|
|
263
|
-
encodeSellERC20Callback: () => encodeSellERC20Callback,
|
|
264
256
|
isEmptyCallback: () => isEmptyCallback
|
|
265
257
|
});
|
|
266
258
|
let Type$1 = /* @__PURE__ */ function(Type) {
|
|
267
259
|
Type["BuyWithEmptyCallback"] = "buy_with_empty_callback";
|
|
268
|
-
Type["
|
|
269
|
-
Type["BuyVaultV1Callback"] = "buy_vault_v1_callback";
|
|
270
|
-
Type["SellERC20Callback"] = "sell_erc20_callback";
|
|
260
|
+
Type["SellWithEmptyCallback"] = "sell_with_empty_callback";
|
|
271
261
|
return Type;
|
|
272
262
|
}({});
|
|
273
263
|
const isEmptyCallback = (offer) => offer.callback.data === "0x";
|
|
274
|
-
function decode$2(type, data) {
|
|
275
|
-
switch (type) {
|
|
276
|
-
case Type$1.BuyERC20: return decodeBuyERC20(data);
|
|
277
|
-
case Type$1.BuyVaultV1Callback: return decodeBuyVaultV1Callback(data);
|
|
278
|
-
case Type$1.SellERC20Callback: return decodeSellERC20Callback(data);
|
|
279
|
-
default: throw new Error("Invalid callback type");
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
function encode$2(type, data) {
|
|
283
|
-
switch (type) {
|
|
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:
|
|
288
|
-
if (!("vaults" in data)) throw new Error("Invalid callback data");
|
|
289
|
-
return encodeBuyVaultV1Callback(data);
|
|
290
|
-
case Type$1.SellERC20Callback:
|
|
291
|
-
if (!("collaterals" in data)) throw new Error("Invalid callback data");
|
|
292
|
-
return encodeSellERC20Callback(data);
|
|
293
|
-
default: throw new Error("Invalid callback type");
|
|
294
|
-
}
|
|
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
|
-
}
|
|
325
|
-
function decodeBuyVaultV1Callback(data) {
|
|
326
|
-
if (!data || data === "0x") throw new Error("Empty callback data");
|
|
327
|
-
try {
|
|
328
|
-
const [vaults, amounts] = decodeAbiParameters([{ type: "address[]" }, { type: "uint256[]" }], data);
|
|
329
|
-
if (vaults.length !== amounts.length) throw new Error("Mismatched array lengths");
|
|
330
|
-
return vaults.map((v, i) => ({
|
|
331
|
-
contract: v,
|
|
332
|
-
amount: amounts[i]
|
|
333
|
-
}));
|
|
334
|
-
} catch (_) {
|
|
335
|
-
throw new Error("Invalid BuyVaultV1Callback callback data");
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
function decodeSellERC20Callback(data) {
|
|
339
|
-
if (!data || data === "0x") throw new Error("Empty callback data");
|
|
340
|
-
try {
|
|
341
|
-
const [collaterals, amounts] = decodeAbiParameters([{ type: "address[]" }, { type: "uint256[]" }], data);
|
|
342
|
-
if (collaterals.length !== amounts.length) throw new Error("Mismatched array lengths");
|
|
343
|
-
return collaterals.map((c, i) => ({
|
|
344
|
-
contract: c,
|
|
345
|
-
amount: amounts[i]
|
|
346
|
-
}));
|
|
347
|
-
} catch (_) {
|
|
348
|
-
throw new Error("Invalid SellERC20Callback callback data");
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
function encodeBuyVaultV1Callback(parameters) {
|
|
352
|
-
return encodeAbiParameters([{ type: "address[]" }, { type: "uint256[]" }], [parameters.vaults, parameters.amounts]);
|
|
353
|
-
}
|
|
354
|
-
function encodeSellERC20Callback(parameters) {
|
|
355
|
-
return encodeAbiParameters([{ type: "address[]" }, { type: "uint256[]" }], [parameters.collaterals, parameters.amounts]);
|
|
356
|
-
}
|
|
357
264
|
|
|
358
265
|
//#endregion
|
|
359
266
|
//#region src/utils/BigMath.ts
|
|
@@ -1109,11 +1016,9 @@ var Liquidity_exports = /* @__PURE__ */ __exportAll({
|
|
|
1109
1016
|
calculateMaxDebt: () => calculateMaxDebt,
|
|
1110
1017
|
generateAllowancePoolId: () => generateAllowancePoolId,
|
|
1111
1018
|
generateBalancePoolId: () => generateBalancePoolId,
|
|
1112
|
-
generateBuyVaultCallbackPoolId: () => generateBuyVaultCallbackPoolId,
|
|
1113
1019
|
generateDebtPoolId: () => generateDebtPoolId,
|
|
1114
1020
|
generateMarketLiquidityPoolId: () => generateMarketLiquidityPoolId,
|
|
1115
1021
|
generateObligationCollateralPoolId: () => generateObligationCollateralPoolId,
|
|
1116
|
-
generateSellERC20CallbackPoolId: () => generateSellERC20CallbackPoolId,
|
|
1117
1022
|
generateUserVaultPositionPoolId: () => generateUserVaultPositionPoolId,
|
|
1118
1023
|
generateVaultPositionPoolId: () => generateVaultPositionPoolId
|
|
1119
1024
|
});
|
|
@@ -1142,14 +1047,6 @@ function generateAllowancePoolId(parameters) {
|
|
|
1142
1047
|
return `${user}-${chainId.toString()}-${token}-allowance`.toLowerCase();
|
|
1143
1048
|
}
|
|
1144
1049
|
/**
|
|
1145
|
-
* Generate pool ID for sell ERC20 callback pools.
|
|
1146
|
-
* Each offer has its own callback pool to prevent liquidity conflicts.
|
|
1147
|
-
*/
|
|
1148
|
-
function generateSellERC20CallbackPoolId(parameters) {
|
|
1149
|
-
const { user, chainId, obligationId, token, offerHash } = parameters;
|
|
1150
|
-
return `${user}-${chainId.toString()}-${obligationId}-${token}-${offerHash}-sell_erc20_callback`.toLowerCase();
|
|
1151
|
-
}
|
|
1152
|
-
/**
|
|
1153
1050
|
* Generate pool ID for obligation collateral pools.
|
|
1154
1051
|
* Obligation collateral pools represent collateral already deposited in the obligation.
|
|
1155
1052
|
* These pools are shared across all offers with the same obligation.
|
|
@@ -1159,13 +1056,6 @@ function generateObligationCollateralPoolId(parameters) {
|
|
|
1159
1056
|
return `${user}-${chainId.toString()}-${obligationId}-${token}-obligation-collateral`.toLowerCase();
|
|
1160
1057
|
}
|
|
1161
1058
|
/**
|
|
1162
|
-
* Generate pool ID for buy vault callback pools.
|
|
1163
|
-
*/
|
|
1164
|
-
function generateBuyVaultCallbackPoolId(parameters) {
|
|
1165
|
-
const { user, chainId, vault, offerHash } = parameters;
|
|
1166
|
-
return `${user}-${chainId.toString()}-${vault}-${offerHash}-${Type$1.BuyVaultV1Callback}`.toLowerCase();
|
|
1167
|
-
}
|
|
1168
|
-
/**
|
|
1169
1059
|
* Generate pool ID for debt pools.
|
|
1170
1060
|
*/
|
|
1171
1061
|
function generateDebtPoolId(parameters) {
|
|
@@ -1545,6 +1435,7 @@ var Offer_exports = /* @__PURE__ */ __exportAll({
|
|
|
1545
1435
|
obligationId: () => obligationId,
|
|
1546
1436
|
random: () => random$1,
|
|
1547
1437
|
serialize: () => serialize,
|
|
1438
|
+
takeEvent: () => takeEvent,
|
|
1548
1439
|
toSnakeCase: () => toSnakeCase,
|
|
1549
1440
|
types: () => types
|
|
1550
1441
|
});
|
|
@@ -1663,7 +1554,7 @@ function random$1(config) {
|
|
|
1663
1554
|
const chain = config?.chains ? config.chains[int(config.chains.length)] : chains$1.ethereum;
|
|
1664
1555
|
const loanToken = config?.loanTokens ? config.loanTokens[int(config.loanTokens.length)] : address();
|
|
1665
1556
|
const collateralCandidates = config?.collateralTokens ? config.collateralTokens.filter((a) => a !== loanToken) : [address()];
|
|
1666
|
-
|
|
1557
|
+
collateralCandidates[int(collateralCandidates.length)];
|
|
1667
1558
|
const maturityOption = weightedChoice([["end_of_month", 1], ["end_of_next_month", 1]]);
|
|
1668
1559
|
const maturity = config?.maturity ?? from$11(maturityOption);
|
|
1669
1560
|
const lltv = from$13(weightedChoice([
|
|
@@ -1690,21 +1581,10 @@ function random$1(config) {
|
|
|
1690
1581
|
const unit = BigInt(10) ** BigInt(loanTokenDecimals);
|
|
1691
1582
|
const amountBase = BigInt(100 + int(999901));
|
|
1692
1583
|
const assetsScaled = config?.assets ?? amountBase * unit;
|
|
1693
|
-
const
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
};
|
|
1698
|
-
const sellCallbackAddress = "0x3333333333333333333333333333333333333333";
|
|
1699
|
-
const amount = assetsScaled * 1000000000000000000000n;
|
|
1700
|
-
return {
|
|
1701
|
-
address: sellCallbackAddress,
|
|
1702
|
-
data: encodeSellERC20Callback({
|
|
1703
|
-
collaterals: [collateralAsset],
|
|
1704
|
-
amounts: [amount]
|
|
1705
|
-
})
|
|
1706
|
-
};
|
|
1707
|
-
})();
|
|
1584
|
+
const emptyCallback = {
|
|
1585
|
+
address: zeroAddress,
|
|
1586
|
+
data: "0x"
|
|
1587
|
+
};
|
|
1708
1588
|
return from$9({
|
|
1709
1589
|
maker: config?.maker ?? address(),
|
|
1710
1590
|
assets: assetsScaled,
|
|
@@ -1723,7 +1603,7 @@ function random$1(config) {
|
|
|
1723
1603
|
...random$3(),
|
|
1724
1604
|
lltv
|
|
1725
1605
|
})).sort((a, b) => a.asset.localeCompare(b.asset)),
|
|
1726
|
-
callback: config?.callback ??
|
|
1606
|
+
callback: config?.callback ?? emptyCallback
|
|
1727
1607
|
});
|
|
1728
1608
|
}
|
|
1729
1609
|
const weightedChoice = (pairs) => {
|
|
@@ -2013,6 +1893,94 @@ function decode$1(data) {
|
|
|
2013
1893
|
});
|
|
2014
1894
|
}
|
|
2015
1895
|
/**
|
|
1896
|
+
* ABI for the Take event emitted by the Morpho V2 contract.
|
|
1897
|
+
*/
|
|
1898
|
+
const takeEvent = {
|
|
1899
|
+
type: "event",
|
|
1900
|
+
name: "Take",
|
|
1901
|
+
inputs: [
|
|
1902
|
+
{
|
|
1903
|
+
name: "caller",
|
|
1904
|
+
type: "address",
|
|
1905
|
+
indexed: false,
|
|
1906
|
+
internalType: "address"
|
|
1907
|
+
},
|
|
1908
|
+
{
|
|
1909
|
+
name: "id",
|
|
1910
|
+
type: "bytes32",
|
|
1911
|
+
indexed: true,
|
|
1912
|
+
internalType: "bytes32"
|
|
1913
|
+
},
|
|
1914
|
+
{
|
|
1915
|
+
name: "maker",
|
|
1916
|
+
type: "address",
|
|
1917
|
+
indexed: true,
|
|
1918
|
+
internalType: "address"
|
|
1919
|
+
},
|
|
1920
|
+
{
|
|
1921
|
+
name: "taker",
|
|
1922
|
+
type: "address",
|
|
1923
|
+
indexed: true,
|
|
1924
|
+
internalType: "address"
|
|
1925
|
+
},
|
|
1926
|
+
{
|
|
1927
|
+
name: "offerIsBuy",
|
|
1928
|
+
type: "bool",
|
|
1929
|
+
indexed: false,
|
|
1930
|
+
internalType: "bool"
|
|
1931
|
+
},
|
|
1932
|
+
{
|
|
1933
|
+
name: "buyerAssets",
|
|
1934
|
+
type: "uint256",
|
|
1935
|
+
indexed: false,
|
|
1936
|
+
internalType: "uint256"
|
|
1937
|
+
},
|
|
1938
|
+
{
|
|
1939
|
+
name: "sellerAssets",
|
|
1940
|
+
type: "uint256",
|
|
1941
|
+
indexed: false,
|
|
1942
|
+
internalType: "uint256"
|
|
1943
|
+
},
|
|
1944
|
+
{
|
|
1945
|
+
name: "obligationUnits",
|
|
1946
|
+
type: "uint256",
|
|
1947
|
+
indexed: false,
|
|
1948
|
+
internalType: "uint256"
|
|
1949
|
+
},
|
|
1950
|
+
{
|
|
1951
|
+
name: "obligationShares",
|
|
1952
|
+
type: "uint256",
|
|
1953
|
+
indexed: false,
|
|
1954
|
+
internalType: "uint256"
|
|
1955
|
+
},
|
|
1956
|
+
{
|
|
1957
|
+
name: "buyerIsLender",
|
|
1958
|
+
type: "bool",
|
|
1959
|
+
indexed: false,
|
|
1960
|
+
internalType: "bool"
|
|
1961
|
+
},
|
|
1962
|
+
{
|
|
1963
|
+
name: "sellerIsBorrower",
|
|
1964
|
+
type: "bool",
|
|
1965
|
+
indexed: false,
|
|
1966
|
+
internalType: "bool"
|
|
1967
|
+
},
|
|
1968
|
+
{
|
|
1969
|
+
name: "group",
|
|
1970
|
+
type: "bytes32",
|
|
1971
|
+
indexed: false,
|
|
1972
|
+
internalType: "bytes32"
|
|
1973
|
+
},
|
|
1974
|
+
{
|
|
1975
|
+
name: "consumed",
|
|
1976
|
+
type: "uint256",
|
|
1977
|
+
indexed: false,
|
|
1978
|
+
internalType: "uint256"
|
|
1979
|
+
}
|
|
1980
|
+
],
|
|
1981
|
+
anonymous: false
|
|
1982
|
+
};
|
|
1983
|
+
/**
|
|
2016
1984
|
* ABI for the Consume event emitted by the Obligation contract.
|
|
2017
1985
|
*/
|
|
2018
1986
|
const consumedEvent = {
|
|
@@ -2867,8 +2835,8 @@ const offerExample = {
|
|
|
2867
2835
|
price: "2750000000000000000",
|
|
2868
2836
|
group: "0x000000000000000000000000000000000000000000000000000000000008b8f4",
|
|
2869
2837
|
session: "0x0000000000000000000000000000000000000000000000000000000000000000",
|
|
2870
|
-
callback: "
|
|
2871
|
-
callback_data: "
|
|
2838
|
+
callback: "0x0000000000000000000000000000000000000000",
|
|
2839
|
+
callback_data: "0x"
|
|
2872
2840
|
},
|
|
2873
2841
|
offer_hash: "0xac4bd8318ec914f89f8af913f162230575b0ac0696a19256bc12138c5cfe1427",
|
|
2874
2842
|
obligation_id: "0x25690ae1aee324a005be565f3bcdd16dbf8daf7969b26c181c8b8f467dad9abc",
|
|
@@ -2920,25 +2888,10 @@ const validateOfferExample = {
|
|
|
2920
2888
|
lltv: "860000000000000000"
|
|
2921
2889
|
}],
|
|
2922
2890
|
callback: {
|
|
2923
|
-
address: "
|
|
2924
|
-
data: "
|
|
2891
|
+
address: "0x0000000000000000000000000000000000000000",
|
|
2892
|
+
data: "0x"
|
|
2925
2893
|
}
|
|
2926
2894
|
};
|
|
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
|
-
}];
|
|
2942
2895
|
const routerStatusExample = {
|
|
2943
2896
|
status: "live",
|
|
2944
2897
|
initialized: true,
|
|
@@ -3007,55 +2960,6 @@ __decorate([ApiProperty({
|
|
|
3007
2960
|
type: "string",
|
|
3008
2961
|
example: validateOfferExample.callback.data
|
|
3009
2962
|
})], 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);
|
|
3059
2963
|
var AskResponse = class {};
|
|
3060
2964
|
__decorate([ApiProperty({
|
|
3061
2965
|
type: "string",
|
|
@@ -3220,7 +3124,8 @@ var OfferListResponse = class extends SuccessResponse {};
|
|
|
3220
3124
|
__decorate([ApiProperty({
|
|
3221
3125
|
type: "string",
|
|
3222
3126
|
nullable: true,
|
|
3223
|
-
example: offerCursorExample
|
|
3127
|
+
example: offerCursorExample,
|
|
3128
|
+
description: "Pagination cursor. Offer hash (0x...) for maker queries; base64url-encoded cursor for obligation queries."
|
|
3224
3129
|
})], OfferListResponse.prototype, "cursor", void 0);
|
|
3225
3130
|
__decorate([ApiProperty({
|
|
3226
3131
|
type: () => [OfferListItemResponse],
|
|
@@ -3572,7 +3477,7 @@ __decorate([
|
|
|
3572
3477
|
methods: ["post"],
|
|
3573
3478
|
path: "/v1/validate",
|
|
3574
3479
|
summary: "Validate offers",
|
|
3575
|
-
description: "Validates offers against router validation rules. Returns unsigned payload + root on success, or issues only on validation failure."
|
|
3480
|
+
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."
|
|
3576
3481
|
}),
|
|
3577
3482
|
ApiBody({ type: ValidateOffersRequest }),
|
|
3578
3483
|
ApiResponse({
|
|
@@ -3591,28 +3496,6 @@ ValidateController = __decorate([ApiTags("Make"), ApiResponse({
|
|
|
3591
3496
|
description: "Bad Request",
|
|
3592
3497
|
type: BadRequestResponse
|
|
3593
3498
|
})], ValidateController);
|
|
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
3499
|
let OffersController = class OffersController {
|
|
3617
3500
|
async getOffers() {}
|
|
3618
3501
|
};
|
|
@@ -3762,22 +3645,21 @@ const configRulesMaturityExample = {
|
|
|
3762
3645
|
name: "end_of_next_month",
|
|
3763
3646
|
timestamp: 1730415600
|
|
3764
3647
|
};
|
|
3765
|
-
const configRulesCallbackExample = {
|
|
3766
|
-
type: "callback",
|
|
3767
|
-
chain_id: 1,
|
|
3768
|
-
address: "0x1111111111111111111111111111111111111111",
|
|
3769
|
-
callback_type: "sell_erc20_callback"
|
|
3770
|
-
};
|
|
3771
3648
|
const configRulesLoanTokenExample = {
|
|
3772
3649
|
type: "loan_token",
|
|
3773
3650
|
chain_id: 1,
|
|
3774
3651
|
address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
|
|
3775
3652
|
};
|
|
3653
|
+
const configRulesOracleExample = {
|
|
3654
|
+
type: "oracle",
|
|
3655
|
+
chain_id: 1,
|
|
3656
|
+
address: "0xDddd770BADd886dF3864029e4B377B5F6a2B6b83"
|
|
3657
|
+
};
|
|
3776
3658
|
const configRulesChecksumExample = "f1d2d2f924e986ac86fdf7b36c94bcdf";
|
|
3777
3659
|
const configRulesPayloadExample = [
|
|
3778
3660
|
configRulesMaturityExample,
|
|
3779
|
-
|
|
3780
|
-
|
|
3661
|
+
configRulesLoanTokenExample,
|
|
3662
|
+
configRulesOracleExample
|
|
3781
3663
|
];
|
|
3782
3664
|
const configContractNames = [
|
|
3783
3665
|
"mempool",
|
|
@@ -3840,14 +3722,9 @@ __decorate([ApiProperty({
|
|
|
3840
3722
|
})], ConfigRulesRuleResponse.prototype, "timestamp", void 0);
|
|
3841
3723
|
__decorate([ApiProperty({
|
|
3842
3724
|
type: "string",
|
|
3843
|
-
example:
|
|
3725
|
+
example: configRulesLoanTokenExample.address,
|
|
3844
3726
|
required: false
|
|
3845
3727
|
})], ConfigRulesRuleResponse.prototype, "address", void 0);
|
|
3846
|
-
__decorate([ApiProperty({
|
|
3847
|
-
type: "string",
|
|
3848
|
-
example: configRulesCallbackExample.callback_type,
|
|
3849
|
-
required: false
|
|
3850
|
-
})], ConfigRulesRuleResponse.prototype, "callback_type", void 0);
|
|
3851
3728
|
var ConfigRulesSuccessResponse = class {};
|
|
3852
3729
|
__decorate([ApiProperty({ type: () => ConfigRulesMeta })], ConfigRulesSuccessResponse.prototype, "meta", void 0);
|
|
3853
3730
|
__decorate([ApiProperty({
|
|
@@ -3908,7 +3785,7 @@ __decorate([
|
|
|
3908
3785
|
methods: ["get"],
|
|
3909
3786
|
path: "/v1/config/rules",
|
|
3910
3787
|
summary: "Get config rules",
|
|
3911
|
-
description: "Returns configured rules for supported chains."
|
|
3788
|
+
description: "Returns configured rules (maturities, loan tokens, oracles) for supported chains."
|
|
3912
3789
|
}),
|
|
3913
3790
|
ApiQuery({
|
|
3914
3791
|
name: "cursor",
|
|
@@ -3928,7 +3805,7 @@ __decorate([
|
|
|
3928
3805
|
name: "types",
|
|
3929
3806
|
type: ["string"],
|
|
3930
3807
|
required: false,
|
|
3931
|
-
example: "maturity,loan_token",
|
|
3808
|
+
example: "maturity,loan_token,oracle",
|
|
3932
3809
|
description: "Filter by rule types (comma-separated).",
|
|
3933
3810
|
style: "form",
|
|
3934
3811
|
explode: false
|
|
@@ -4087,8 +3964,7 @@ const OpenApi = async () => {
|
|
|
4087
3964
|
ObligationsController,
|
|
4088
3965
|
HealthController,
|
|
4089
3966
|
UsersController,
|
|
4090
|
-
ValidateController
|
|
4091
|
-
CallbacksController
|
|
3967
|
+
ValidateController
|
|
4092
3968
|
],
|
|
4093
3969
|
document: {
|
|
4094
3970
|
openapi: "3.1.0",
|
|
@@ -4159,6 +4035,9 @@ function isValidBase64urlJson(val) {
|
|
|
4159
4035
|
return false;
|
|
4160
4036
|
}
|
|
4161
4037
|
}
|
|
4038
|
+
function isValidOfferHashCursor(val) {
|
|
4039
|
+
return /^0x[a-f0-9]{64}$/i.test(val);
|
|
4040
|
+
}
|
|
4162
4041
|
const csvArray = (schema) => z$1.preprocess((value) => {
|
|
4163
4042
|
if (value === void 0) return void 0;
|
|
4164
4043
|
if (Array.isArray(value)) {
|
|
@@ -4184,10 +4063,11 @@ const PaginationQueryParams = z$1.object({
|
|
|
4184
4063
|
const ConfigRuleTypes = z$1.enum([
|
|
4185
4064
|
"maturity",
|
|
4186
4065
|
"callback",
|
|
4187
|
-
"loan_token"
|
|
4066
|
+
"loan_token",
|
|
4067
|
+
"oracle"
|
|
4188
4068
|
]);
|
|
4189
4069
|
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({
|
|
4070
|
+
cursor: z$1.string().regex(/^(maturity|callback|loan_token|oracle):[1-9]\d*:.+$/, { message: "Cursor must be in the format type:chain_id:<value>" }).optional().meta({
|
|
4191
4071
|
description: "Pagination cursor in type:chain_id:<value> format",
|
|
4192
4072
|
example: "maturity:1:1730415600:end_of_next_month"
|
|
4193
4073
|
}),
|
|
@@ -4197,7 +4077,7 @@ const GetConfigRulesQueryParams = z$1.object({
|
|
|
4197
4077
|
}),
|
|
4198
4078
|
types: csvArray(ConfigRuleTypes).meta({
|
|
4199
4079
|
description: "Filter by rule types (comma-separated).",
|
|
4200
|
-
example: "maturity,loan_token"
|
|
4080
|
+
example: "maturity,loan_token,oracle"
|
|
4201
4081
|
}),
|
|
4202
4082
|
chains: csvArray(z$1.string().regex(/^[1-9]\d*$/, { message: "Chain must be a positive integer" }).transform((val) => Number.parseInt(val, 10))).meta({
|
|
4203
4083
|
description: "Filter by chain IDs (comma-separated).",
|
|
@@ -4218,8 +4098,11 @@ const GetConfigContractsQueryParams = z$1.object({
|
|
|
4218
4098
|
example: "1,8453"
|
|
4219
4099
|
})
|
|
4220
4100
|
});
|
|
4221
|
-
const GetOffersQueryParams =
|
|
4222
|
-
|
|
4101
|
+
const GetOffersQueryParams = PaginationQueryParams.omit({ cursor: true }).extend({
|
|
4102
|
+
cursor: z$1.string().optional().meta({
|
|
4103
|
+
description: "Pagination cursor. Use offer hash (0x...) for maker queries, base64url for obligation queries.",
|
|
4104
|
+
example: "eyJzaWRlIjoic2VsbCIsImN1cnJlbnRQcmljZSI6IjEwMDAwMDAwMDAwMDAwMDAwMDAiLCJibG9ja051bWJlciI6MSwiYXNzZXRzIjoiMTAwMDAwMDAwMDAwMDAwMDAwMCIsImhhc2giOiIweGRmZDY4NTllM2UwODJkMTkzODlhMWFlYzFiZGFkN2U4ZDkyZDk2YjFhYTc5NDBkYTkxYTMxMjVkMzFlM2JlNWIiLCJ0b3RhbFJldHVybmVkIjoxMCwibm93IjoxNjAwMDAwMDAwfQ"
|
|
4105
|
+
}),
|
|
4223
4106
|
side: z$1.enum(["buy", "sell"]).optional().meta({
|
|
4224
4107
|
description: "Side of the offer. Required when using obligation_id.",
|
|
4225
4108
|
example: "buy"
|
|
@@ -4243,11 +4126,29 @@ const GetOffersQueryParams = z$1.object({
|
|
|
4243
4126
|
});
|
|
4244
4127
|
return;
|
|
4245
4128
|
}
|
|
4246
|
-
if (hasMaker)
|
|
4129
|
+
if (hasMaker) {
|
|
4130
|
+
if (val.cursor !== void 0 && !isValidOfferHashCursor(val.cursor)) ctx.addIssue({
|
|
4131
|
+
code: "custom",
|
|
4132
|
+
path: ["cursor"],
|
|
4133
|
+
message: "Cursor must be a 32-byte hex offer hash when filtering by maker"
|
|
4134
|
+
});
|
|
4135
|
+
return;
|
|
4136
|
+
}
|
|
4247
4137
|
if (!hasObligation || !hasSide) ctx.addIssue({
|
|
4248
4138
|
code: "custom",
|
|
4249
4139
|
message: "Must provide either maker or both obligation_id and side"
|
|
4250
4140
|
});
|
|
4141
|
+
if (val.cursor !== void 0 && !isValidBase64urlJson(val.cursor)) ctx.addIssue({
|
|
4142
|
+
code: "custom",
|
|
4143
|
+
path: ["cursor"],
|
|
4144
|
+
message: "Invalid cursor format. Must be a valid base64url-encoded cursor object"
|
|
4145
|
+
});
|
|
4146
|
+
}).transform((val) => {
|
|
4147
|
+
if (val.maker && val.cursor) return {
|
|
4148
|
+
...val,
|
|
4149
|
+
cursor: val.cursor.toLowerCase()
|
|
4150
|
+
};
|
|
4151
|
+
return val;
|
|
4251
4152
|
});
|
|
4252
4153
|
const GetObligationsQueryParams = z$1.object({
|
|
4253
4154
|
...PaginationQueryParams.shape,
|
|
@@ -4320,16 +4221,6 @@ const GetBookParams = z$1.object({
|
|
|
4320
4221
|
})
|
|
4321
4222
|
});
|
|
4322
4223
|
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();
|
|
4333
4224
|
const GetUserPositionsParams = z$1.object({
|
|
4334
4225
|
...PaginationQueryParams.shape,
|
|
4335
4226
|
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({
|
|
@@ -4348,7 +4239,6 @@ const schemas = {
|
|
|
4348
4239
|
get_obligation: GetObligationParams,
|
|
4349
4240
|
get_book: GetBookParams,
|
|
4350
4241
|
validate_offers: ValidateOffersBody,
|
|
4351
|
-
callback_types: CallbackTypesBody,
|
|
4352
4242
|
get_user_positions: GetUserPositionsParams
|
|
4353
4243
|
};
|
|
4354
4244
|
function parse(action, query) {
|
|
@@ -4363,7 +4253,6 @@ function safeParse(action, query, error) {
|
|
|
4363
4253
|
var Schema_exports = /* @__PURE__ */ __exportAll({
|
|
4364
4254
|
BookResponse: () => BookResponse_exports,
|
|
4365
4255
|
BooksController: () => BooksController,
|
|
4366
|
-
CallbacksController: () => CallbacksController,
|
|
4367
4256
|
ChainHealth: () => ChainHealth,
|
|
4368
4257
|
ChainsHealthResponse: () => ChainsHealthResponse,
|
|
4369
4258
|
CollectorHealth: () => CollectorHealth,
|
|
@@ -4642,23 +4531,11 @@ function createHttpClient(config) {
|
|
|
4642
4531
|
issues: []
|
|
4643
4532
|
};
|
|
4644
4533
|
};
|
|
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
4534
|
return {
|
|
4657
4535
|
baseUrl,
|
|
4658
4536
|
validate,
|
|
4659
4537
|
getConfigRules,
|
|
4660
|
-
isAllowed
|
|
4661
|
-
getCallbackTypes
|
|
4538
|
+
isAllowed
|
|
4662
4539
|
};
|
|
4663
4540
|
}
|
|
4664
4541
|
function mergeHeaders(base, extra) {
|
|
@@ -4782,48 +4659,23 @@ function create(parameters) {
|
|
|
4782
4659
|
|
|
4783
4660
|
//#endregion
|
|
4784
4661
|
//#region src/gatekeeper/GateConfig.ts
|
|
4785
|
-
/**
|
|
4786
|
-
* Returns the callback configuration for a given chain and callback type, if it exists.
|
|
4787
|
-
*
|
|
4788
|
-
* @param chain - Chain name for which to read the validation configuration
|
|
4789
|
-
* @param type - Callback type to retrieve
|
|
4790
|
-
* @returns The matching callback configuration or undefined if not configured
|
|
4791
|
-
*/
|
|
4792
|
-
function getCallback(chain, type) {
|
|
4793
|
-
return configs[chain].callbacks?.find((c) => c.type === type);
|
|
4794
|
-
}
|
|
4795
|
-
/**
|
|
4796
|
-
* Attempts to infer the configured callback type from a callback address on a chain.
|
|
4797
|
-
* Skips the empty callback type as it does not carry addresses.
|
|
4798
|
-
*
|
|
4799
|
-
* @param chain - Chain name for which to infer the callback type
|
|
4800
|
-
* @param address - Callback contract address
|
|
4801
|
-
* @returns The callback type when found, otherwise undefined
|
|
4802
|
-
*/
|
|
4803
|
-
function getCallbackType(chain, address) {
|
|
4804
|
-
return configs[chain].callbacks?.find((c) => c.type !== Type$1.BuyWithEmptyCallback && c.addresses.includes(address?.toLowerCase()))?.type;
|
|
4805
|
-
}
|
|
4806
|
-
/**
|
|
4807
|
-
* Returns the list of allowed non-empty callback addresses for a chain.
|
|
4808
|
-
*
|
|
4809
|
-
* @param chain - Chain name
|
|
4810
|
-
* @returns Array of allowed callback addresses (lowercased). Empty when none configured
|
|
4811
|
-
*/
|
|
4812
|
-
const getCallbackAddresses = (chain) => {
|
|
4813
|
-
return configs[chain].callbacks?.filter((c) => c.type !== Type$1.BuyWithEmptyCallback).flatMap((c) => c.addresses) ?? [];
|
|
4814
|
-
};
|
|
4815
4662
|
const assets = {
|
|
4816
4663
|
[ChainId.ETHEREUM.toString()]: [
|
|
4817
4664
|
"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
4818
4665
|
"0x6B175474E89094C44Da98b954EedeAC495271d0F",
|
|
4819
4666
|
"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
|
|
4820
|
-
"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"
|
|
4667
|
+
"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",
|
|
4668
|
+
"0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c",
|
|
4669
|
+
"0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0"
|
|
4821
4670
|
],
|
|
4822
4671
|
[ChainId.BASE.toString()]: [
|
|
4823
4672
|
"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
4824
4673
|
"0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb",
|
|
4825
4674
|
"0x4200000000000000000000000000000000000006",
|
|
4826
|
-
"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"
|
|
4675
|
+
"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",
|
|
4676
|
+
"0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf",
|
|
4677
|
+
"0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452",
|
|
4678
|
+
"0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42"
|
|
4827
4679
|
],
|
|
4828
4680
|
[ChainId["ETHEREUM-VIRTUAL-TESTNET"].toString()]: [
|
|
4829
4681
|
"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
@@ -4839,65 +4691,58 @@ const assets = {
|
|
|
4839
4691
|
"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"
|
|
4840
4692
|
]
|
|
4841
4693
|
};
|
|
4694
|
+
const oracles = {
|
|
4695
|
+
[ChainId.ETHEREUM.toString()]: [
|
|
4696
|
+
"0xDddd770BADd886dF3864029e4B377B5F6a2B6b83",
|
|
4697
|
+
"0x9CB3f4276bcD149b3668e1a645a964bC12877b89",
|
|
4698
|
+
"0x48F7E36EB6B826B2dF4B2E630B62Cd25e89E40e2",
|
|
4699
|
+
"0x6Eb9F4128CeBc8B885A4d8562Db1Addf097f7348",
|
|
4700
|
+
"0xbD60A6770b27E084E8617335ddE769241B0e71D8",
|
|
4701
|
+
"0xAe12416c1F21B0698c27fe042D9309C83baC6597"
|
|
4702
|
+
],
|
|
4703
|
+
[ChainId.BASE.toString()]: [
|
|
4704
|
+
"0xD09048c8B568Dbf5f189302beA26c9edABFC4858",
|
|
4705
|
+
"0xFEa2D58cEfCb9fcb597723c6bAE66fFE4193aFE4",
|
|
4706
|
+
"0x05D2618404668D725B66c0f32B39e4EC15B393dC",
|
|
4707
|
+
"0xE1bb8E5b4930eC9FeC7f7943FCF6227649F14B37",
|
|
4708
|
+
"0x663BECd10daE6C4A3Dcd89F1d76c1174199639B9",
|
|
4709
|
+
"0x10b95702a0ce895972C91e432C4f7E19811D320E",
|
|
4710
|
+
"0x8C87DbD7A0c647A4291592Bc2994dbF95880fE2F",
|
|
4711
|
+
"0x4A11590e5326138B514E08A9B52202D42077Ca65",
|
|
4712
|
+
"0xa54122f0E0766258377Ffe732e454A3248f454F4"
|
|
4713
|
+
],
|
|
4714
|
+
[ChainId["ETHEREUM-VIRTUAL-TESTNET"].toString()]: [
|
|
4715
|
+
"0xDddd770BADd886dF3864029e4B377B5F6a2B6b83",
|
|
4716
|
+
"0x9CB3f4276bcD149b3668e1a645a964bC12877b89",
|
|
4717
|
+
"0x48F7E36EB6B826B2dF4B2E630B62Cd25e89E40e2",
|
|
4718
|
+
"0x6Eb9F4128CeBc8B885A4d8562Db1Addf097f7348",
|
|
4719
|
+
"0xbD60A6770b27E084E8617335ddE769241B0e71D8",
|
|
4720
|
+
"0xAe12416c1F21B0698c27fe042D9309C83baC6597"
|
|
4721
|
+
],
|
|
4722
|
+
[ChainId.ANVIL.toString()]: [
|
|
4723
|
+
"0xDddd770BADd886dF3864029e4B377B5F6a2B6b83",
|
|
4724
|
+
"0x9CB3f4276bcD149b3668e1a645a964bC12877b89",
|
|
4725
|
+
"0x48F7E36EB6B826B2dF4B2E630B62Cd25e89E40e2",
|
|
4726
|
+
"0x6Eb9F4128CeBc8B885A4d8562Db1Addf097f7348",
|
|
4727
|
+
"0xbD60A6770b27E084E8617335ddE769241B0e71D8",
|
|
4728
|
+
"0xAe12416c1F21B0698c27fe042D9309C83baC6597"
|
|
4729
|
+
]
|
|
4730
|
+
};
|
|
4842
4731
|
const configs = {
|
|
4843
4732
|
ethereum: {
|
|
4844
|
-
callbacks: [
|
|
4845
|
-
{
|
|
4846
|
-
type: Type$1.BuyVaultV1Callback,
|
|
4847
|
-
addresses: ["0x3333333333333333333333333333333333333333", "0x4444444444444444444444444444444444444444"],
|
|
4848
|
-
vaultFactories: ["0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101", "0x1897A8997241C1cD4bD0698647e4EB7213535c24"]
|
|
4849
|
-
},
|
|
4850
|
-
{
|
|
4851
|
-
type: Type$1.SellERC20Callback,
|
|
4852
|
-
addresses: ["0x1111111111111111111111111111111111111111", "0x2222222222222222222222222222222222222222"]
|
|
4853
|
-
},
|
|
4854
|
-
{ type: Type$1.BuyWithEmptyCallback }
|
|
4855
|
-
],
|
|
4733
|
+
callbacks: [{ type: Type$1.BuyWithEmptyCallback }, { type: Type$1.SellWithEmptyCallback }],
|
|
4856
4734
|
maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth]
|
|
4857
4735
|
},
|
|
4858
4736
|
base: {
|
|
4859
|
-
callbacks: [
|
|
4860
|
-
{
|
|
4861
|
-
type: Type$1.BuyVaultV1Callback,
|
|
4862
|
-
addresses: ["0x3333333333333333333333333333333333333333", "0x4444444444444444444444444444444444444444"],
|
|
4863
|
-
vaultFactories: ["0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101", "0xFf62A7c278C62eD665133147129245053Bbf5918"]
|
|
4864
|
-
},
|
|
4865
|
-
{
|
|
4866
|
-
type: Type$1.SellERC20Callback,
|
|
4867
|
-
addresses: ["0x1111111111111111111111111111111111111111", "0x2222222222222222222222222222222222222222"]
|
|
4868
|
-
},
|
|
4869
|
-
{ type: Type$1.BuyWithEmptyCallback }
|
|
4870
|
-
],
|
|
4737
|
+
callbacks: [{ type: Type$1.BuyWithEmptyCallback }, { type: Type$1.SellWithEmptyCallback }],
|
|
4871
4738
|
maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth]
|
|
4872
4739
|
},
|
|
4873
4740
|
"ethereum-virtual-testnet": {
|
|
4874
|
-
callbacks: [
|
|
4875
|
-
{
|
|
4876
|
-
type: Type$1.BuyVaultV1Callback,
|
|
4877
|
-
addresses: ["0x3333333333333333333333333333333333333333", "0x4444444444444444444444444444444444444444"],
|
|
4878
|
-
vaultFactories: ["0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101", "0x1897A8997241C1cD4bD0698647e4EB7213535c24"]
|
|
4879
|
-
},
|
|
4880
|
-
{
|
|
4881
|
-
type: Type$1.SellERC20Callback,
|
|
4882
|
-
addresses: ["0x1111111111111111111111111111111111111111", "0x2222222222222222222222222222222222222222"]
|
|
4883
|
-
},
|
|
4884
|
-
{ type: Type$1.BuyWithEmptyCallback }
|
|
4885
|
-
],
|
|
4741
|
+
callbacks: [{ type: Type$1.BuyWithEmptyCallback }, { type: Type$1.SellWithEmptyCallback }],
|
|
4886
4742
|
maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth]
|
|
4887
4743
|
},
|
|
4888
4744
|
anvil: {
|
|
4889
|
-
callbacks: [
|
|
4890
|
-
{
|
|
4891
|
-
type: Type$1.BuyVaultV1Callback,
|
|
4892
|
-
addresses: ["0x3333333333333333333333333333333333333333", "0x4444444444444444444444444444444444444444"],
|
|
4893
|
-
vaultFactories: ["0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101", "0x1897A8997241C1cD4bD0698647e4EB7213535c24"]
|
|
4894
|
-
},
|
|
4895
|
-
{
|
|
4896
|
-
type: Type$1.SellERC20Callback,
|
|
4897
|
-
addresses: ["0x1111111111111111111111111111111111111111", "0x2222222222222222222222222222222222222222"]
|
|
4898
|
-
},
|
|
4899
|
-
{ type: Type$1.BuyWithEmptyCallback }
|
|
4900
|
-
],
|
|
4745
|
+
callbacks: [{ type: Type$1.BuyWithEmptyCallback }, { type: Type$1.SellWithEmptyCallback }],
|
|
4901
4746
|
maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth]
|
|
4902
4747
|
}
|
|
4903
4748
|
};
|
|
@@ -4909,6 +4754,7 @@ var Rules_exports = /* @__PURE__ */ __exportAll({
|
|
|
4909
4754
|
callback: () => callback,
|
|
4910
4755
|
chains: () => chains,
|
|
4911
4756
|
maturity: () => maturity,
|
|
4757
|
+
oracle: () => oracle,
|
|
4912
4758
|
sameMaker: () => sameMaker,
|
|
4913
4759
|
token: () => token,
|
|
4914
4760
|
validity: () => validity
|
|
@@ -4916,109 +4762,13 @@ var Rules_exports = /* @__PURE__ */ __exportAll({
|
|
|
4916
4762
|
/**
|
|
4917
4763
|
* set of rules to validate offers.
|
|
4918
4764
|
*
|
|
4919
|
-
* @param
|
|
4765
|
+
* @param _parameters - Validity parameters with chain and client
|
|
4920
4766
|
* @returns Array of validation rules to evaluate against offers
|
|
4921
4767
|
*/
|
|
4922
|
-
function validity(
|
|
4923
|
-
|
|
4924
|
-
|
|
4925
|
-
|
|
4926
|
-
if (callbackType !== Type$1.SellERC20Callback) return;
|
|
4927
|
-
const decoded = decode$2(callbackType, offer.callback.data);
|
|
4928
|
-
if (decoded.length === 0) return { message: "Callback data cannot be decoded or is empty." };
|
|
4929
|
-
if (callbackType === Type$1.SellERC20Callback) {
|
|
4930
|
-
const offerCollaterals = new Set(offer.collaterals.map((c) => c.asset.toLowerCase()));
|
|
4931
|
-
if (decoded.length !== offer.collaterals.length) return { message: `Sell callback collateral length mismatch. Expected ${offer.collaterals.length}, got ${decoded.length}.` };
|
|
4932
|
-
for (const { contract } of decoded) if (!offerCollaterals.has(contract.toLowerCase())) return { message: "Sell callback collateral is not part of offer collaterals." };
|
|
4933
|
-
}
|
|
4934
|
-
});
|
|
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) => {
|
|
4936
|
-
const validationIssues = /* @__PURE__ */ new Map();
|
|
4937
|
-
const offersByVaultAddress = /* @__PURE__ */ new Map();
|
|
4938
|
-
for (let i = 0; i < offers.length; i++) {
|
|
4939
|
-
const offer = offers[i];
|
|
4940
|
-
if (getCallbackType(client.chain.name, offer.callback.address) !== Type$1.BuyVaultV1Callback) continue;
|
|
4941
|
-
try {
|
|
4942
|
-
const callbackVaults = decodeBuyVaultV1Callback(offer.callback.data);
|
|
4943
|
-
for (const { contract } of callbackVaults) {
|
|
4944
|
-
const normalizedVaultAddress = contract.toLowerCase();
|
|
4945
|
-
if (!offersByVaultAddress.has(normalizedVaultAddress)) offersByVaultAddress.set(normalizedVaultAddress, []);
|
|
4946
|
-
offersByVaultAddress.get(normalizedVaultAddress).push({
|
|
4947
|
-
index: i,
|
|
4948
|
-
offer
|
|
4949
|
-
});
|
|
4950
|
-
}
|
|
4951
|
-
} catch (_) {}
|
|
4952
|
-
}
|
|
4953
|
-
const uniqueVaultAddresses = Array.from(offersByVaultAddress.keys());
|
|
4954
|
-
if (uniqueVaultAddresses.length === 0) return validationIssues;
|
|
4955
|
-
const allowedFactories = getCallback(client.chain.name, Type$1.BuyVaultV1Callback)?.vaultFactories.map((f) => f.toLowerCase());
|
|
4956
|
-
if (!allowedFactories) return validationIssues;
|
|
4957
|
-
const multicallContracts = [];
|
|
4958
|
-
for (const vaultAddress of uniqueVaultAddresses) {
|
|
4959
|
-
multicallContracts.push({
|
|
4960
|
-
address: vaultAddress,
|
|
4961
|
-
abi: ERC4626,
|
|
4962
|
-
functionName: "asset"
|
|
4963
|
-
});
|
|
4964
|
-
for (const factoryAddress of allowedFactories) multicallContracts.push({
|
|
4965
|
-
address: factoryAddress,
|
|
4966
|
-
abi: MetaMorphoFactory,
|
|
4967
|
-
functionName: "isMetaMorpho",
|
|
4968
|
-
args: [vaultAddress]
|
|
4969
|
-
});
|
|
4970
|
-
}
|
|
4971
|
-
const multicallResults = await multicall(client, {
|
|
4972
|
-
contracts: multicallContracts,
|
|
4973
|
-
allowFailure: true
|
|
4974
|
-
});
|
|
4975
|
-
const vaultAssetByAddress = /* @__PURE__ */ new Map();
|
|
4976
|
-
const registeredVaults = /* @__PURE__ */ new Set();
|
|
4977
|
-
const numberOfFactories = allowedFactories.length;
|
|
4978
|
-
let resultIndex = 0;
|
|
4979
|
-
for (const vaultAddress of uniqueVaultAddresses) {
|
|
4980
|
-
const assetCallResult = multicallResults[resultIndex++];
|
|
4981
|
-
const assetAddress = assetCallResult.status === "success" ? assetCallResult.result : null;
|
|
4982
|
-
vaultAssetByAddress.set(vaultAddress, assetAddress);
|
|
4983
|
-
let isRegisteredInFactory = false;
|
|
4984
|
-
for (let factoryIndex = 0; factoryIndex < numberOfFactories; factoryIndex++) {
|
|
4985
|
-
const factoryCallResult = multicallResults[resultIndex++];
|
|
4986
|
-
if (factoryCallResult.status === "success" && factoryCallResult.result === true) isRegisteredInFactory = true;
|
|
4987
|
-
}
|
|
4988
|
-
if (isRegisteredInFactory) registeredVaults.add(vaultAddress);
|
|
4989
|
-
}
|
|
4990
|
-
const uniqueOffers = /* @__PURE__ */ new Map();
|
|
4991
|
-
for (const offersArray of offersByVaultAddress.values()) for (const { index, offer } of offersArray) uniqueOffers.set(index, offer);
|
|
4992
|
-
for (const [index, offer] of uniqueOffers) try {
|
|
4993
|
-
const callbackVaults = decodeBuyVaultV1Callback(offer.callback.data);
|
|
4994
|
-
const vaultsWithIssues = [];
|
|
4995
|
-
for (const { contract } of callbackVaults) {
|
|
4996
|
-
const normalizedVaultAddress = contract.toLowerCase();
|
|
4997
|
-
const assetAddress = vaultAssetByAddress.get(normalizedVaultAddress);
|
|
4998
|
-
const isRegistered = registeredVaults.has(normalizedVaultAddress);
|
|
4999
|
-
const failureReasons = [];
|
|
5000
|
-
if (assetAddress === null) failureReasons.push("asset call failed");
|
|
5001
|
-
else if (assetAddress && assetAddress.toLowerCase() !== offer.loanToken.toLowerCase()) failureReasons.push("asset mismatch");
|
|
5002
|
-
if (!isRegistered) failureReasons.push("not registered in factory");
|
|
5003
|
-
if (failureReasons.length > 0) vaultsWithIssues.push({
|
|
5004
|
-
vaultAddress: contract,
|
|
5005
|
-
failureReasons: failureReasons.join(", ")
|
|
5006
|
-
});
|
|
5007
|
-
}
|
|
5008
|
-
if (vaultsWithIssues.length > 0) {
|
|
5009
|
-
const failureDetails = vaultsWithIssues.map((v) => `${v.vaultAddress} (${v.failureReasons})`).join("; ");
|
|
5010
|
-
validationIssues.set(index, { message: `Buy offer callback vaults are invalid: ${failureDetails}` });
|
|
5011
|
-
}
|
|
5012
|
-
} catch (_) {}
|
|
5013
|
-
return validationIssues;
|
|
5014
|
-
});
|
|
5015
|
-
return [
|
|
5016
|
-
single("expiry", "Validates that offer has not expired", (offer) => {
|
|
5017
|
-
if (offer.expiry < Math.floor(Date.now() / 1e3)) return { message: "Expiry mismatch" };
|
|
5018
|
-
}),
|
|
5019
|
-
sellErc20CallbackInvalid,
|
|
5020
|
-
buyCallbackVaultInvalid
|
|
5021
|
-
];
|
|
4768
|
+
function validity(_parameters) {
|
|
4769
|
+
return [single("expiry", "Validates that offer has not expired", (offer) => {
|
|
4770
|
+
if (offer.expiry < Math.floor(Date.now() / 1e3)) return { message: "Expiry mismatch" };
|
|
4771
|
+
})];
|
|
5022
4772
|
}
|
|
5023
4773
|
const chains = ({ chains }) => single("chain_ids", `Validates that offer chain is one of: [${chains.map((c) => c.id).join(", ")}]`, (offer) => {
|
|
5024
4774
|
const allowedChainIds = chains.map((c) => c.id);
|
|
@@ -5028,12 +4778,10 @@ const maturity = ({ maturities }) => single("maturity", `Validates that offer ma
|
|
|
5028
4778
|
const allowedMaturities = maturities.map((m) => from$11(m));
|
|
5029
4779
|
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}` };
|
|
5030
4780
|
});
|
|
5031
|
-
const callback = ({ callbacks
|
|
5032
|
-
if (isEmptyCallback(offer)
|
|
5033
|
-
if (isEmptyCallback(offer) &&
|
|
5034
|
-
if (
|
|
5035
|
-
if (!allowedAddresses.includes(offer.callback.address?.toLowerCase())) return { message: `Callback address ${offer.callback.address} is not allowed.` };
|
|
5036
|
-
}
|
|
4781
|
+
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) => {
|
|
4782
|
+
if (!isEmptyCallback(offer)) return { message: "Non-empty callbacks are not supported." };
|
|
4783
|
+
if (isEmptyCallback(offer) && offer.buy && !callbacks.includes(Type$1.BuyWithEmptyCallback)) return { message: "Buy offers with empty callback not allowed." };
|
|
4784
|
+
if (isEmptyCallback(offer) && !offer.buy && !callbacks.includes(Type$1.SellWithEmptyCallback)) return { message: "Sell offers with empty callback not allowed." };
|
|
5037
4785
|
});
|
|
5038
4786
|
/**
|
|
5039
4787
|
* A validation rule that checks if the offer's tokens are allowed for its chain.
|
|
@@ -5047,6 +4795,16 @@ const token = ({ assetsByChainId }) => single("token", "Validates that offer loa
|
|
|
5047
4795
|
if (offer.collaterals.some((collateral) => !allowedAssets.includes(collateral.asset.toLowerCase()))) return { message: "Collateral is not allowed" };
|
|
5048
4796
|
});
|
|
5049
4797
|
/**
|
|
4798
|
+
* A validation rule that checks if the offer's oracle addresses are allowed for its chain.
|
|
4799
|
+
* @param oraclesByChainId - Allowed oracles indexed by chain id.
|
|
4800
|
+
* @returns The issue that was found. If the offer is valid, this will be undefined.
|
|
4801
|
+
*/
|
|
4802
|
+
const oracle = ({ oraclesByChainId }) => single("oracle", "Validates that offer collateral oracles are in the allowed oracle list for the offer chain", (offer) => {
|
|
4803
|
+
const allowedOracles = oraclesByChainId[offer.chainId]?.map((oracle) => oracle.toLowerCase());
|
|
4804
|
+
if (!allowedOracles || allowedOracles.length === 0) return { message: `No allowed oracles for chain ${offer.chainId}` };
|
|
4805
|
+
if (offer.collaterals.some((collateral) => !allowedOracles.includes(collateral.oracle.toLowerCase()))) return { message: "Oracle is not allowed" };
|
|
4806
|
+
});
|
|
4807
|
+
/**
|
|
5050
4808
|
* A batch validation rule that ensures all offers in a tree have the same maker address.
|
|
5051
4809
|
* Returns an issue only for the first non-conforming offer.
|
|
5052
4810
|
* This rule is signing-agnostic; signer verification is handled at the collector level.
|
|
@@ -5077,21 +4835,22 @@ const amountMutualExclusivity = () => single("amount_mutual_exclusivity", "Valid
|
|
|
5077
4835
|
//#region src/gatekeeper/morphoRules.ts
|
|
5078
4836
|
const morphoRules = (chains$2) => {
|
|
5079
4837
|
const assetsByChainId = {};
|
|
5080
|
-
|
|
4838
|
+
const oraclesByChainId = {};
|
|
4839
|
+
for (const chain of chains$2) {
|
|
4840
|
+
assetsByChainId[chain.id] = assets[chain.id.toString()] ?? [];
|
|
4841
|
+
oraclesByChainId[chain.id] = oracles[chain.id.toString()] ?? [];
|
|
4842
|
+
}
|
|
5081
4843
|
return [
|
|
5082
4844
|
sameMaker(),
|
|
5083
4845
|
amountMutualExclusivity(),
|
|
5084
4846
|
chains({ chains: chains$2 }),
|
|
5085
4847
|
maturity({ maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth] }),
|
|
5086
4848
|
callback({
|
|
5087
|
-
callbacks: [
|
|
5088
|
-
|
|
5089
|
-
Type$1.BuyVaultV1Callback,
|
|
5090
|
-
Type$1.SellERC20Callback
|
|
5091
|
-
],
|
|
5092
|
-
allowedAddresses: chains$2.flatMap((c) => getCallbackAddresses(c.name))
|
|
4849
|
+
callbacks: [Type$1.BuyWithEmptyCallback, Type$1.SellWithEmptyCallback],
|
|
4850
|
+
allowedAddresses: []
|
|
5093
4851
|
}),
|
|
5094
|
-
token({ assetsByChainId })
|
|
4852
|
+
token({ assetsByChainId }),
|
|
4853
|
+
oracle({ oraclesByChainId })
|
|
5095
4854
|
];
|
|
5096
4855
|
};
|
|
5097
4856
|
|