@morpho-dev/router 0.7.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.
@@ -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["BuyERC20"] = "buy_erc20";
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
- const collateralAsset = collateralCandidates[int(collateralCandidates.length)];
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 callbackBySide = (() => {
1735
- if (buy) return {
1736
- address: viem.zeroAddress,
1737
- data: "0x"
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 ?? callbackBySide
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: "0x1111111111111111111111111111111111111111",
2912
- callback_data: "0x00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000100000000000000000000000034cf890db685fc536e05652fb41f02090c3fb751000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000108e644e3ab01184155270aa92a00000000000"
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: "0x1111111111111111111111111111111111111111",
2965
- data: "0x00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000100000000000000000000000034cf890db685fc536e05652fb41f02090c3fb751000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000108e644e3ab01184155270aa92a00000000000"
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",
@@ -3614,7 +3518,7 @@ __decorate([
3614
3518
  methods: ["post"],
3615
3519
  path: "/v1/validate",
3616
3520
  summary: "Validate offers",
3617
- 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."
3618
3522
  }),
3619
3523
  (0, openapi_metadata_decorators.ApiBody)({ type: ValidateOffersRequest }),
3620
3524
  (0, openapi_metadata_decorators.ApiResponse)({
@@ -3633,28 +3537,6 @@ ValidateController = __decorate([(0, openapi_metadata_decorators.ApiTags)("Make"
3633
3537
  description: "Bad Request",
3634
3538
  type: BadRequestResponse
3635
3539
  })], ValidateController);
3636
- let CallbacksController = class CallbacksController {
3637
- async resolveCallbackTypes() {}
3638
- };
3639
- __decorate([
3640
- (0, openapi_metadata_decorators.ApiOperation)({
3641
- methods: ["post"],
3642
- path: "/v1/callbacks",
3643
- summary: "Resolve callback types",
3644
- description: "Returns callback types for callback addresses grouped by chain."
3645
- }),
3646
- (0, openapi_metadata_decorators.ApiBody)({ type: CallbackTypesRequest }),
3647
- (0, openapi_metadata_decorators.ApiResponse)({
3648
- status: 200,
3649
- description: "Success",
3650
- type: CallbackTypesSuccessResponse
3651
- })
3652
- ], CallbacksController.prototype, "resolveCallbackTypes", null);
3653
- CallbacksController = __decorate([(0, openapi_metadata_decorators.ApiTags)("Make"), (0, openapi_metadata_decorators.ApiResponse)({
3654
- status: 400,
3655
- description: "Bad Request",
3656
- type: BadRequestResponse
3657
- })], CallbacksController);
3658
3540
  let OffersController = class OffersController {
3659
3541
  async getOffers() {}
3660
3542
  };
@@ -3804,12 +3686,6 @@ const configRulesMaturityExample = {
3804
3686
  name: "end_of_next_month",
3805
3687
  timestamp: 1730415600
3806
3688
  };
3807
- const configRulesCallbackExample = {
3808
- type: "callback",
3809
- chain_id: 1,
3810
- address: "0x1111111111111111111111111111111111111111",
3811
- callback_type: "sell_erc20_callback"
3812
- };
3813
3689
  const configRulesLoanTokenExample = {
3814
3690
  type: "loan_token",
3815
3691
  chain_id: 1,
@@ -3823,7 +3699,6 @@ const configRulesOracleExample = {
3823
3699
  const configRulesChecksumExample = "f1d2d2f924e986ac86fdf7b36c94bcdf";
3824
3700
  const configRulesPayloadExample = [
3825
3701
  configRulesMaturityExample,
3826
- configRulesCallbackExample,
3827
3702
  configRulesLoanTokenExample,
3828
3703
  configRulesOracleExample
3829
3704
  ];
@@ -3888,14 +3763,9 @@ __decorate([(0, openapi_metadata_decorators.ApiProperty)({
3888
3763
  })], ConfigRulesRuleResponse.prototype, "timestamp", void 0);
3889
3764
  __decorate([(0, openapi_metadata_decorators.ApiProperty)({
3890
3765
  type: "string",
3891
- example: configRulesCallbackExample.address,
3766
+ example: configRulesLoanTokenExample.address,
3892
3767
  required: false
3893
3768
  })], ConfigRulesRuleResponse.prototype, "address", void 0);
3894
- __decorate([(0, openapi_metadata_decorators.ApiProperty)({
3895
- type: "string",
3896
- example: configRulesCallbackExample.callback_type,
3897
- required: false
3898
- })], ConfigRulesRuleResponse.prototype, "callback_type", void 0);
3899
3769
  var ConfigRulesSuccessResponse = class {};
3900
3770
  __decorate([(0, openapi_metadata_decorators.ApiProperty)({ type: () => ConfigRulesMeta })], ConfigRulesSuccessResponse.prototype, "meta", void 0);
3901
3771
  __decorate([(0, openapi_metadata_decorators.ApiProperty)({
@@ -3956,7 +3826,7 @@ __decorate([
3956
3826
  methods: ["get"],
3957
3827
  path: "/v1/config/rules",
3958
3828
  summary: "Get config rules",
3959
- description: "Returns configured rules for supported chains."
3829
+ description: "Returns configured rules (maturities, loan tokens, oracles) for supported chains."
3960
3830
  }),
3961
3831
  (0, openapi_metadata_decorators.ApiQuery)({
3962
3832
  name: "cursor",
@@ -4135,8 +4005,7 @@ const OpenApi = async () => {
4135
4005
  ObligationsController,
4136
4006
  HealthController,
4137
4007
  UsersController,
4138
- ValidateController,
4139
- CallbacksController
4008
+ ValidateController
4140
4009
  ],
4141
4010
  document: {
4142
4011
  openapi: "3.1.0",
@@ -4393,16 +4262,6 @@ const GetBookParams = zod.object({
4393
4262
  })
4394
4263
  });
4395
4264
  const ValidateOffersBody = zod.object({ offers: zod.array(zod.unknown()).min(1, { message: "'offers' must contain at least 1 offer" }) }).strict();
4396
- const CallbackTypesBody = zod.object({ callbacks: zod.array(zod.object({
4397
- chain_id: zod.number().int().positive().meta({
4398
- description: "Chain id.",
4399
- example: 1
4400
- }),
4401
- 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({
4402
- description: "Callback contract addresses.",
4403
- example: ["0x1111111111111111111111111111111111111111", "0x3333333333333333333333333333333333333333"]
4404
- })
4405
- }).strict()) }).strict();
4406
4265
  const GetUserPositionsParams = zod.object({
4407
4266
  ...PaginationQueryParams.shape,
4408
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({
@@ -4421,7 +4280,6 @@ const schemas = {
4421
4280
  get_obligation: GetObligationParams,
4422
4281
  get_book: GetBookParams,
4423
4282
  validate_offers: ValidateOffersBody,
4424
- callback_types: CallbackTypesBody,
4425
4283
  get_user_positions: GetUserPositionsParams
4426
4284
  };
4427
4285
  function parse(action, query) {
@@ -4436,7 +4294,6 @@ function safeParse(action, query, error) {
4436
4294
  var Schema_exports = /* @__PURE__ */ __exportAll({
4437
4295
  BookResponse: () => BookResponse_exports,
4438
4296
  BooksController: () => BooksController,
4439
- CallbacksController: () => CallbacksController,
4440
4297
  ChainHealth: () => ChainHealth,
4441
4298
  ChainsHealthResponse: () => ChainsHealthResponse,
4442
4299
  CollectorHealth: () => CollectorHealth,
@@ -4715,23 +4572,11 @@ function createHttpClient(config) {
4715
4572
  issues: []
4716
4573
  };
4717
4574
  };
4718
- const getCallbackTypes = async (requestPayload) => {
4719
- const response = await request("/v1/callbacks", {
4720
- method: "POST",
4721
- headers: { "content-type": "application/json" },
4722
- body: JSON.stringify(requestPayload)
4723
- });
4724
- const json = await response.json();
4725
- if (!response.ok) throw new Error(`Gatekeeper callbacks request failed: ${extractErrorMessage(json) ?? response.statusText}`);
4726
- if (!("data" in json) || !Array.isArray(json.data)) throw new Error("Gatekeeper callbacks response is invalid.");
4727
- return json.data;
4728
- };
4729
4575
  return {
4730
4576
  baseUrl,
4731
4577
  validate,
4732
4578
  getConfigRules,
4733
- isAllowed,
4734
- getCallbackTypes
4579
+ isAllowed
4735
4580
  };
4736
4581
  }
4737
4582
  function mergeHeaders(base, extra) {
@@ -4855,36 +4700,6 @@ function create(parameters) {
4855
4700
 
4856
4701
  //#endregion
4857
4702
  //#region src/gatekeeper/GateConfig.ts
4858
- /**
4859
- * Returns the callback configuration for a given chain and callback type, if it exists.
4860
- *
4861
- * @param chain - Chain name for which to read the validation configuration
4862
- * @param type - Callback type to retrieve
4863
- * @returns The matching callback configuration or undefined if not configured
4864
- */
4865
- function getCallback(chain, type) {
4866
- return configs[chain].callbacks?.find((c) => c.type === type);
4867
- }
4868
- /**
4869
- * Attempts to infer the configured callback type from a callback address on a chain.
4870
- * Skips the empty callback type as it does not carry addresses.
4871
- *
4872
- * @param chain - Chain name for which to infer the callback type
4873
- * @param address - Callback contract address
4874
- * @returns The callback type when found, otherwise undefined
4875
- */
4876
- function getCallbackType(chain, address) {
4877
- return configs[chain].callbacks?.find((c) => c.type !== Type$1.BuyWithEmptyCallback && c.addresses.includes(address?.toLowerCase()))?.type;
4878
- }
4879
- /**
4880
- * Returns the list of allowed non-empty callback addresses for a chain.
4881
- *
4882
- * @param chain - Chain name
4883
- * @returns Array of allowed callback addresses (lowercased). Empty when none configured
4884
- */
4885
- const getCallbackAddresses = (chain) => {
4886
- return configs[chain].callbacks?.filter((c) => c.type !== Type$1.BuyWithEmptyCallback).flatMap((c) => c.addresses) ?? [];
4887
- };
4888
4703
  const assets = {
4889
4704
  [ChainId.ETHEREUM.toString()]: [
4890
4705
  "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
@@ -4956,63 +4771,19 @@ const oracles = {
4956
4771
  };
4957
4772
  const configs = {
4958
4773
  ethereum: {
4959
- callbacks: [
4960
- {
4961
- type: Type$1.BuyVaultV1Callback,
4962
- addresses: ["0x3333333333333333333333333333333333333333", "0x4444444444444444444444444444444444444444"],
4963
- vaultFactories: ["0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101", "0x1897A8997241C1cD4bD0698647e4EB7213535c24"]
4964
- },
4965
- {
4966
- type: Type$1.SellERC20Callback,
4967
- addresses: ["0x1111111111111111111111111111111111111111", "0x2222222222222222222222222222222222222222"]
4968
- },
4969
- { type: Type$1.BuyWithEmptyCallback }
4970
- ],
4774
+ callbacks: [{ type: Type$1.BuyWithEmptyCallback }, { type: Type$1.SellWithEmptyCallback }],
4971
4775
  maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth]
4972
4776
  },
4973
4777
  base: {
4974
- callbacks: [
4975
- {
4976
- type: Type$1.BuyVaultV1Callback,
4977
- addresses: ["0x3333333333333333333333333333333333333333", "0x4444444444444444444444444444444444444444"],
4978
- vaultFactories: ["0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101", "0xFf62A7c278C62eD665133147129245053Bbf5918"]
4979
- },
4980
- {
4981
- type: Type$1.SellERC20Callback,
4982
- addresses: ["0x1111111111111111111111111111111111111111", "0x2222222222222222222222222222222222222222"]
4983
- },
4984
- { type: Type$1.BuyWithEmptyCallback }
4985
- ],
4778
+ callbacks: [{ type: Type$1.BuyWithEmptyCallback }, { type: Type$1.SellWithEmptyCallback }],
4986
4779
  maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth]
4987
4780
  },
4988
4781
  "ethereum-virtual-testnet": {
4989
- callbacks: [
4990
- {
4991
- type: Type$1.BuyVaultV1Callback,
4992
- addresses: ["0x3333333333333333333333333333333333333333", "0x4444444444444444444444444444444444444444"],
4993
- vaultFactories: ["0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101", "0x1897A8997241C1cD4bD0698647e4EB7213535c24"]
4994
- },
4995
- {
4996
- type: Type$1.SellERC20Callback,
4997
- addresses: ["0x1111111111111111111111111111111111111111", "0x2222222222222222222222222222222222222222"]
4998
- },
4999
- { type: Type$1.BuyWithEmptyCallback }
5000
- ],
4782
+ callbacks: [{ type: Type$1.BuyWithEmptyCallback }, { type: Type$1.SellWithEmptyCallback }],
5001
4783
  maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth]
5002
4784
  },
5003
4785
  anvil: {
5004
- callbacks: [
5005
- {
5006
- type: Type$1.BuyVaultV1Callback,
5007
- addresses: ["0x3333333333333333333333333333333333333333", "0x4444444444444444444444444444444444444444"],
5008
- vaultFactories: ["0xA9c3D3a366466Fa809d1Ae982Fb2c46E5fC41101", "0x1897A8997241C1cD4bD0698647e4EB7213535c24"]
5009
- },
5010
- {
5011
- type: Type$1.SellERC20Callback,
5012
- addresses: ["0x1111111111111111111111111111111111111111", "0x2222222222222222222222222222222222222222"]
5013
- },
5014
- { type: Type$1.BuyWithEmptyCallback }
5015
- ],
4786
+ callbacks: [{ type: Type$1.BuyWithEmptyCallback }, { type: Type$1.SellWithEmptyCallback }],
5016
4787
  maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth]
5017
4788
  }
5018
4789
  };
@@ -5032,109 +4803,13 @@ var Rules_exports = /* @__PURE__ */ __exportAll({
5032
4803
  /**
5033
4804
  * set of rules to validate offers.
5034
4805
  *
5035
- * @param parameters - Validity parameters with chain and client
4806
+ * @param _parameters - Validity parameters with chain and client
5036
4807
  * @returns Array of validation rules to evaluate against offers
5037
4808
  */
5038
- function validity(parameters) {
5039
- const { client } = parameters;
5040
- const sellErc20CallbackInvalid = single("sell_erc20_callback_invalid", "Validates that sell offers have valid ERC20 callback data matching offer collaterals", (offer) => {
5041
- const callbackType = getCallbackType(client.chain.name, offer.callback.address);
5042
- if (callbackType !== Type$1.SellERC20Callback) return;
5043
- const decoded = decode$2(callbackType, offer.callback.data);
5044
- if (decoded.length === 0) return { message: "Callback data cannot be decoded or is empty." };
5045
- if (callbackType === Type$1.SellERC20Callback) {
5046
- const offerCollaterals = new Set(offer.collaterals.map((c) => c.asset.toLowerCase()));
5047
- if (decoded.length !== offer.collaterals.length) return { message: `Sell callback collateral length mismatch. Expected ${offer.collaterals.length}, got ${decoded.length}.` };
5048
- for (const { contract } of decoded) if (!offerCollaterals.has(contract.toLowerCase())) return { message: "Sell callback collateral is not part of offer collaterals." };
5049
- }
5050
- });
5051
- 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) => {
5052
- const validationIssues = /* @__PURE__ */ new Map();
5053
- const offersByVaultAddress = /* @__PURE__ */ new Map();
5054
- for (let i = 0; i < offers.length; i++) {
5055
- const offer = offers[i];
5056
- if (getCallbackType(client.chain.name, offer.callback.address) !== Type$1.BuyVaultV1Callback) continue;
5057
- try {
5058
- const callbackVaults = decodeBuyVaultV1Callback(offer.callback.data);
5059
- for (const { contract } of callbackVaults) {
5060
- const normalizedVaultAddress = contract.toLowerCase();
5061
- if (!offersByVaultAddress.has(normalizedVaultAddress)) offersByVaultAddress.set(normalizedVaultAddress, []);
5062
- offersByVaultAddress.get(normalizedVaultAddress).push({
5063
- index: i,
5064
- offer
5065
- });
5066
- }
5067
- } catch (_) {}
5068
- }
5069
- const uniqueVaultAddresses = Array.from(offersByVaultAddress.keys());
5070
- if (uniqueVaultAddresses.length === 0) return validationIssues;
5071
- const allowedFactories = getCallback(client.chain.name, Type$1.BuyVaultV1Callback)?.vaultFactories.map((f) => f.toLowerCase());
5072
- if (!allowedFactories) return validationIssues;
5073
- const multicallContracts = [];
5074
- for (const vaultAddress of uniqueVaultAddresses) {
5075
- multicallContracts.push({
5076
- address: vaultAddress,
5077
- abi: ERC4626,
5078
- functionName: "asset"
5079
- });
5080
- for (const factoryAddress of allowedFactories) multicallContracts.push({
5081
- address: factoryAddress,
5082
- abi: MetaMorphoFactory,
5083
- functionName: "isMetaMorpho",
5084
- args: [vaultAddress]
5085
- });
5086
- }
5087
- const multicallResults = await (0, viem_actions.multicall)(client, {
5088
- contracts: multicallContracts,
5089
- allowFailure: true
5090
- });
5091
- const vaultAssetByAddress = /* @__PURE__ */ new Map();
5092
- const registeredVaults = /* @__PURE__ */ new Set();
5093
- const numberOfFactories = allowedFactories.length;
5094
- let resultIndex = 0;
5095
- for (const vaultAddress of uniqueVaultAddresses) {
5096
- const assetCallResult = multicallResults[resultIndex++];
5097
- const assetAddress = assetCallResult.status === "success" ? assetCallResult.result : null;
5098
- vaultAssetByAddress.set(vaultAddress, assetAddress);
5099
- let isRegisteredInFactory = false;
5100
- for (let factoryIndex = 0; factoryIndex < numberOfFactories; factoryIndex++) {
5101
- const factoryCallResult = multicallResults[resultIndex++];
5102
- if (factoryCallResult.status === "success" && factoryCallResult.result === true) isRegisteredInFactory = true;
5103
- }
5104
- if (isRegisteredInFactory) registeredVaults.add(vaultAddress);
5105
- }
5106
- const uniqueOffers = /* @__PURE__ */ new Map();
5107
- for (const offersArray of offersByVaultAddress.values()) for (const { index, offer } of offersArray) uniqueOffers.set(index, offer);
5108
- for (const [index, offer] of uniqueOffers) try {
5109
- const callbackVaults = decodeBuyVaultV1Callback(offer.callback.data);
5110
- const vaultsWithIssues = [];
5111
- for (const { contract } of callbackVaults) {
5112
- const normalizedVaultAddress = contract.toLowerCase();
5113
- const assetAddress = vaultAssetByAddress.get(normalizedVaultAddress);
5114
- const isRegistered = registeredVaults.has(normalizedVaultAddress);
5115
- const failureReasons = [];
5116
- if (assetAddress === null) failureReasons.push("asset call failed");
5117
- else if (assetAddress && assetAddress.toLowerCase() !== offer.loanToken.toLowerCase()) failureReasons.push("asset mismatch");
5118
- if (!isRegistered) failureReasons.push("not registered in factory");
5119
- if (failureReasons.length > 0) vaultsWithIssues.push({
5120
- vaultAddress: contract,
5121
- failureReasons: failureReasons.join(", ")
5122
- });
5123
- }
5124
- if (vaultsWithIssues.length > 0) {
5125
- const failureDetails = vaultsWithIssues.map((v) => `${v.vaultAddress} (${v.failureReasons})`).join("; ");
5126
- validationIssues.set(index, { message: `Buy offer callback vaults are invalid: ${failureDetails}` });
5127
- }
5128
- } catch (_) {}
5129
- return validationIssues;
5130
- });
5131
- return [
5132
- single("expiry", "Validates that offer has not expired", (offer) => {
5133
- if (offer.expiry < Math.floor(Date.now() / 1e3)) return { message: "Expiry mismatch" };
5134
- }),
5135
- sellErc20CallbackInvalid,
5136
- buyCallbackVaultInvalid
5137
- ];
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
+ })];
5138
4813
  }
5139
4814
  const chains = ({ chains }) => single("chain_ids", `Validates that offer chain is one of: [${chains.map((c) => c.id).join(", ")}]`, (offer) => {
5140
4815
  const allowedChainIds = chains.map((c) => c.id);
@@ -5144,12 +4819,10 @@ const maturity = ({ maturities }) => single("maturity", `Validates that offer ma
5144
4819
  const allowedMaturities = maturities.map((m) => from$11(m));
5145
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}` };
5146
4821
  });
5147
- const callback = ({ callbacks, allowedAddresses }) => single("callback", `Validates callbacks: buy empty callback is ${callbacks.includes(Type$1.BuyWithEmptyCallback) ? "allowed" : "not allowed"}; sell offers must use a non-empty callback; non-empty callbacks must target one of [${allowedAddresses.map((a) => a.toLowerCase()).join(", ")}]`, (offer) => {
5148
- if (isEmptyCallback(offer) && offer.buy && !callbacks?.find((c) => c === Type$1.BuyWithEmptyCallback)) return { message: "Buy offers with empty callback not allowed." };
5149
- if (isEmptyCallback(offer) && !offer.buy) return { message: "Sell offers require a non-empty callback." };
5150
- if (!isEmptyCallback(offer)) {
5151
- if (!allowedAddresses.includes(offer.callback.address?.toLowerCase())) return { message: `Callback address ${offer.callback.address} is not allowed.` };
5152
- }
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." };
5153
4826
  });
5154
4827
  /**
5155
4828
  * A validation rule that checks if the offer's tokens are allowed for its chain.
@@ -5214,12 +4887,8 @@ const morphoRules = (chains$2) => {
5214
4887
  chains({ chains: chains$2 }),
5215
4888
  maturity({ maturities: [MaturityType.EndOfMonth, MaturityType.EndOfNextMonth] }),
5216
4889
  callback({
5217
- callbacks: [
5218
- Type$1.BuyWithEmptyCallback,
5219
- Type$1.BuyVaultV1Callback,
5220
- Type$1.SellERC20Callback
5221
- ],
5222
- allowedAddresses: chains$2.flatMap((c) => getCallbackAddresses(c.name))
4890
+ callbacks: [Type$1.BuyWithEmptyCallback, Type$1.SellWithEmptyCallback],
4891
+ allowedAddresses: []
5223
4892
  }),
5224
4893
  token({ assetsByChainId }),
5225
4894
  oracle({ oraclesByChainId })