@morpho-dev/router 0.7.1 → 0.7.2

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.
@@ -949,6 +949,61 @@ const MetaMorpho = parseAbi([
949
949
  //#region src/core/Abi/MetaMorphoFactory.ts
950
950
  const MetaMorphoFactory = parseAbi(["event CreateMetaMorpho(address indexed metaMorpho,address indexed caller,address initialOwner,uint256 initialTimelock,address indexed asset,string name,string symbol,bytes32 salt)", "function isMetaMorpho(address) view returns (bool)"]);
951
951
 
952
+ //#endregion
953
+ //#region src/core/Abi/MorphoV2.ts
954
+ const MorphoV2 = parseAbi([
955
+ "constructor()",
956
+ "function collateralOf(bytes32 id, address user, address collateralToken) view returns (uint256)",
957
+ "function consume(bytes32 group, uint256 amount)",
958
+ "function consumed(address user, bytes32 group) view returns (uint256)",
959
+ "function debtOf(bytes32 id, address user) view returns (uint256)",
960
+ "function defaultFees(address loanToken, uint256 index) view returns (uint16)",
961
+ "function feeSetter() view returns (address)",
962
+ "function fees(bytes32 id) view returns (uint16[6])",
963
+ "function flashLoan(address token, uint256 assets, address callback, bytes data)",
964
+ "function isHealthy((address loanToken, (address token, uint256 lltv, address oracle)[] collaterals, uint256 maturity) obligation, bytes32 id, address borrower) view returns (bool)",
965
+ "function liquidate((address loanToken, (address token, uint256 lltv, address oracle)[] collaterals, uint256 maturity) obligation, (uint256 collateralIndex, uint256 repaid, uint256 seized)[] seizures, address borrower, bytes data) returns ((uint256 collateralIndex, uint256 repaid, uint256 seized)[])",
966
+ "function multicall(bytes[] calls)",
967
+ "function obligationCreated(bytes32 id) view returns (bool)",
968
+ "function obligationState(bytes32 id) view returns (uint128 totalUnits, uint128 totalShares, uint256 withdrawable, bool created)",
969
+ "function owner() view returns (address)",
970
+ "function repay((address loanToken, (address token, uint256 lltv, address oracle)[] collaterals, uint256 maturity) obligation, uint256 obligationUnits, address onBehalf)",
971
+ "function session(address user) view returns (bytes32)",
972
+ "function setDefaultTradingFee(address loanToken, uint256 index, uint256 newTradingFee)",
973
+ "function setFeeSetter(address newFeeSetter)",
974
+ "function setObligationTradingFee(bytes32 id, uint256 index, uint256 newTradingFee)",
975
+ "function setOwner(address newOwner)",
976
+ "function setTradingFeeRecipient(address recipient)",
977
+ "function sharesOf(bytes32 id, address user) view returns (uint256)",
978
+ "function shuffleSession()",
979
+ "function supplyCollateral((address loanToken, (address token, uint256 lltv, address oracle)[] collaterals, uint256 maturity) obligation, address collateral, uint256 assets, address onBehalf)",
980
+ "function take(uint256 buyerAssets, uint256 sellerAssets, uint256 obligationUnits, uint256 obligationShares, address taker, ((address loanToken, (address token, uint256 lltv, address oracle)[] collaterals, uint256 maturity) obligation, bool buy, address maker, uint256 assets, uint256 obligationUnits, uint256 obligationShares, uint256 start, uint256 expiry, uint256 tick, bytes32 group, bytes32 session, address callback, bytes callbackData) offer, (uint8 v, bytes32 r, bytes32 s) sig, bytes32 root, bytes32[] proof, address takerCallback, bytes takerCallbackData) returns (uint256, uint256, uint256, uint256)",
981
+ "function totalShares(bytes32 id) view returns (uint256)",
982
+ "function totalUnits(bytes32 id) view returns (uint256)",
983
+ "function touchObligation((address loanToken, (address token, uint256 lltv, address oracle)[] collaterals, uint256 maturity) obligation) returns (bytes32)",
984
+ "function tradingFee(bytes32 id, uint256 timeToMaturity) view returns (uint256)",
985
+ "function tradingFeeRecipient() view returns (address)",
986
+ "function withdraw((address loanToken, (address token, uint256 lltv, address oracle)[] collaterals, uint256 maturity) obligation, uint256 obligationUnits, uint256 shares, address onBehalf) returns (uint256, uint256)",
987
+ "function withdrawCollateral((address loanToken, (address token, uint256 lltv, address oracle)[] collaterals, uint256 maturity) obligation, address collateral, uint256 assets, address onBehalf)",
988
+ "function withdrawable(bytes32 id) view returns (uint256)",
989
+ "event Constructor(address indexed owner)",
990
+ "event Consume(address indexed user, bytes32 indexed group, uint256 amount)",
991
+ "event FlashLoan(address indexed caller, address indexed token, uint256 assets)",
992
+ "event Liquidate(address indexed caller, bytes32 indexed id, (uint256 collateralIndex, uint256 repaid, uint256 seized)[] seizures, address indexed borrower, uint256 totalRepaid, uint256 badDebt)",
993
+ "event ObligationCreated(bytes32 indexed id, (address loanToken, (address token, uint256 lltv, address oracle)[] collaterals, uint256 maturity) obligation)",
994
+ "event Repay(address indexed caller, bytes32 indexed id, uint256 obligationUnits, address indexed onBehalf)",
995
+ "event SetDefaultTradingFee(address indexed loanToken, uint256 indexed index, uint256 newTradingFee)",
996
+ "event SetFeeSetter(address indexed feeSetter)",
997
+ "event SetObligationTradingFee(bytes32 indexed id, uint256 indexed index, uint256 newTradingFee)",
998
+ "event SetOwner(address indexed owner)",
999
+ "event SetTradingFeeRecipient(address indexed recipient)",
1000
+ "event ShuffleSession(address indexed user, bytes32 session)",
1001
+ "event SupplyCollateral(address caller, bytes32 indexed id, address indexed collateral, uint256 assets, address indexed onBehalf)",
1002
+ "event Take(address caller, bytes32 indexed id, address indexed maker, address indexed taker, bool offerIsBuy, uint256 buyerAssets, uint256 sellerAssets, uint256 obligationUnits, uint256 obligationShares, bool buyerIsLender, bool sellerIsBorrower, bytes32 group, uint256 consumed)",
1003
+ "event Withdraw(address indexed caller, bytes32 indexed id, uint256 obligationUnits, uint256 shares, address indexed onBehalf)",
1004
+ "event WithdrawCollateral(address caller, bytes32 indexed id, address indexed collateral, uint256 assets, address indexed onBehalf)"
1005
+ ]);
1006
+
952
1007
  //#endregion
953
1008
  //#region src/core/Abi/index.ts
954
1009
  var Abi_exports = /* @__PURE__ */ __exportAll({
@@ -956,6 +1011,7 @@ var Abi_exports = /* @__PURE__ */ __exportAll({
956
1011
  MetaMorpho: () => MetaMorpho,
957
1012
  MetaMorphoFactory: () => MetaMorphoFactory,
958
1013
  Morpho: () => Morpho,
1014
+ MorphoV2: () => MorphoV2,
959
1015
  Oracle: () => Oracle
960
1016
  });
961
1017
  const Oracle = [{
@@ -1217,8 +1273,8 @@ const chains$2 = {
1217
1273
  name: "ethereum-virtual-testnet",
1218
1274
  custom: {
1219
1275
  morpho: {
1220
- address: "0x11a002d45db720ed47a80d2f3489cba5b833eaf5",
1221
- blockCreated: 0
1276
+ address: "0x634b095371e4e45feed94c1a45c37798e173ea50",
1277
+ blockCreated: 23226700
1222
1278
  },
1223
1279
  morphoBlue: {
1224
1280
  address: "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb",
@@ -5182,6 +5238,16 @@ function from$4(obligation, quote) {
5182
5238
  //#endregion
5183
5239
  //#region src/api/Schema/OfferResponse.ts
5184
5240
  var OfferResponse_exports = /* @__PURE__ */ __exportAll({ from: () => from$3 });
5241
+ function normalizeChainId(chainId) {
5242
+ const parsedChainId = Number(chainId);
5243
+ if (!Number.isInteger(parsedChainId) || parsedChainId <= 0) throw new Error(`Invalid chain id: ${String(chainId)}`);
5244
+ return parsedChainId;
5245
+ }
5246
+ function normalizeBlockNumber(blockNumber) {
5247
+ const parsedBlockNumber = Number(blockNumber);
5248
+ if (!Number.isInteger(parsedBlockNumber) || parsedBlockNumber < 0) throw new Error(`Invalid block number: ${String(blockNumber)}`);
5249
+ return parsedBlockNumber;
5250
+ }
5185
5251
  /**
5186
5252
  * Creates an `OfferResponse` matching the Solidity Offer struct layout.
5187
5253
  * @constructor
@@ -5189,6 +5255,8 @@ var OfferResponse_exports = /* @__PURE__ */ __exportAll({ from: () => from$3 });
5189
5255
  * @returns The created `OfferResponse`. {@link OfferResponse}
5190
5256
  */
5191
5257
  function from$3(input) {
5258
+ const chainId = normalizeChainId(input.chainId);
5259
+ const blockNumber = normalizeBlockNumber(input.blockNumber);
5192
5260
  const base = {
5193
5261
  offer: {
5194
5262
  obligation: {
@@ -5215,15 +5283,15 @@ function from$3(input) {
5215
5283
  },
5216
5284
  offer_hash: input.hash,
5217
5285
  obligation_id: id({
5218
- chainId: input.chainId,
5286
+ chainId,
5219
5287
  loanToken: input.loanToken,
5220
5288
  collaterals: [...input.collaterals],
5221
5289
  maturity: input.maturity
5222
5290
  }),
5223
- chain_id: input.chainId,
5291
+ chain_id: chainId,
5224
5292
  consumed: input.consumed.toString(),
5225
5293
  takeable: input.takeable.toString(),
5226
- block_number: input.blockNumber
5294
+ block_number: blockNumber
5227
5295
  };
5228
5296
  if (!input.proof || !input.root || !input.signature) return {
5229
5297
  ...base,
@@ -6793,12 +6861,34 @@ async function getBook(params, db) {
6793
6861
  if (!result.success) return failure(result.error);
6794
6862
  const query = result.data;
6795
6863
  try {
6864
+ logger.debug({
6865
+ service: "api_controller",
6866
+ endpoint: "get_book",
6867
+ msg: "Loading book levels",
6868
+ obligation_id: query.obligation_id,
6869
+ side: query.side,
6870
+ limit: query.limit ?? null,
6871
+ has_cursor: query.cursor != null
6872
+ });
6796
6873
  const { levels, nextCursor } = await db.book.get({
6797
6874
  side: query.side,
6798
6875
  obligationId: query.obligation_id,
6799
6876
  cursor: query.cursor,
6800
6877
  limit: query.limit
6801
6878
  });
6879
+ const firstLevel = levels[0];
6880
+ logger.debug({
6881
+ service: "api_controller",
6882
+ endpoint: "get_book",
6883
+ msg: "Loaded book levels",
6884
+ obligation_id: query.obligation_id,
6885
+ side: query.side,
6886
+ levels_count: levels.length,
6887
+ has_next_cursor: nextCursor != null,
6888
+ first_level_price: firstLevel?.price.toString() ?? null,
6889
+ first_level_assets: firstLevel?.assets.toString() ?? null,
6890
+ first_level_count: firstLevel?.count ?? null
6891
+ });
6802
6892
  return success({
6803
6893
  data: levels.map(from$5),
6804
6894
  cursor: nextCursor
@@ -7686,16 +7776,57 @@ async function getOffersQuery(db, parameters) {
7686
7776
  '[]'::jsonb
7687
7777
  )`.as("collaterals") }).from(obligationCollateralsV2).innerJoin(oracles$1, sql`${obligationCollateralsV2.oracleChainId} = ${oracles$1.chainId}
7688
7778
  AND ${obligationCollateralsV2.oracleAddress} = ${oracles$1.address}`).where(eq(obligationCollateralsV2.obligationId, offers.obligationId)).as("collaterals_lateral");
7689
- const availableLateral = db.select({ available: sql`COALESCE(SUM(
7690
- CASE
7691
- WHEN ${positions.asset} IS NULL THEN 0
7692
- ELSE
7693
- CASE
7694
- WHEN ${callbacks.amount} IS NULL THEN COALESCE(${positions.balance}, 0)::numeric
7695
- ELSE LEAST(${callbacks.amount}::numeric, COALESCE(${positions.balance}, 0)::numeric)
7696
- END
7697
- END
7698
- ), 0)`.as("available") }).from(offersCallbacks).innerJoin(callbacks, eq(offersCallbacks.callbackId, callbacks.id)).innerJoin(positions, and(eq(callbacks.positionChainId, positions.chainId), eq(callbacks.positionContract, positions.contract), eq(callbacks.positionUser, positions.user))).where(eq(offersCallbacks.offerHash, offers.hash)).as("available_lateral");
7779
+ const lotBalanceExpr = sql`GREATEST(0, LEAST(
7780
+ COALESCE(${positions.balance}, 0)::numeric
7781
+ + COALESCE((
7782
+ SELECT SUM(${offsets.value}::numeric)
7783
+ FROM ${offsets}
7784
+ WHERE ${offsets.chainId} = ${callbacks.positionChainId}
7785
+ AND LOWER(${offsets.contract}) = LOWER(${callbacks.positionContract})
7786
+ AND LOWER(${offsets.user}) = LOWER(${callbacks.positionUser})
7787
+ ), 0)
7788
+ - COALESCE(${lots.lower}::numeric, 0),
7789
+ (COALESCE(${lots.upper}::numeric, 0) - COALESCE(${lots.lower}::numeric, 0))
7790
+ - CASE
7791
+ WHEN ${offers.assets}::numeric > 0
7792
+ THEN COALESCE(${groups.consumed}::numeric, 0)
7793
+ * (COALESCE(${lots.upper}::numeric, 0) - COALESCE(${lots.lower}::numeric, 0))
7794
+ / ${offers.assets}::numeric
7795
+ ELSE 0
7796
+ END
7797
+ ))`;
7798
+ const contributionExpr = sql`CASE
7799
+ WHEN ${positions.asset} IS NULL OR ${lots.lower} IS NULL THEN 0
7800
+ ELSE LEAST(COALESCE(${callbacks.amount}::numeric, ${lotBalanceExpr}), ${lotBalanceExpr})
7801
+ END`;
7802
+ const availableExpr = sql`COALESCE((
7803
+ SELECT SUM(deduped.contribution)
7804
+ FROM (
7805
+ SELECT DISTINCT ON (
7806
+ ${callbacks.positionChainId},
7807
+ LOWER(${callbacks.positionContract}),
7808
+ LOWER(${callbacks.positionUser})
7809
+ )
7810
+ ${contributionExpr} AS contribution
7811
+ FROM ${offersCallbacks}
7812
+ INNER JOIN ${callbacks} ON ${offersCallbacks.callbackId} = ${callbacks.id}
7813
+ LEFT JOIN ${positions}
7814
+ ON ${positions.chainId} = ${callbacks.positionChainId}
7815
+ AND LOWER(${positions.contract}) = LOWER(${callbacks.positionContract})
7816
+ AND LOWER(${positions.user}) = LOWER(${callbacks.positionUser})
7817
+ LEFT JOIN ${lots}
7818
+ ON ${lots.chainId} = ${callbacks.positionChainId}
7819
+ AND LOWER(${lots.contract}) = LOWER(${callbacks.positionContract})
7820
+ AND LOWER(${lots.user}) = LOWER(${callbacks.positionUser})
7821
+ AND LOWER(${lots.group}) = LOWER(${offers.group})
7822
+ WHERE ${offersCallbacks.offerHash} = ${offers.hash}
7823
+ ORDER BY
7824
+ ${callbacks.positionChainId},
7825
+ LOWER(${callbacks.positionContract}),
7826
+ LOWER(${callbacks.positionUser}),
7827
+ ${contributionExpr} DESC
7828
+ ) deduped
7829
+ ), 0)`;
7699
7830
  const rows = (await db.select({
7700
7831
  hash: offers.hash,
7701
7832
  maker: offers.groupMaker,
@@ -7716,22 +7847,22 @@ async function getOffersQuery(db, parameters) {
7716
7847
  callbackData: offers.callbackData,
7717
7848
  collaterals: collateralsLateral.collaterals,
7718
7849
  blockNumber: offers.blockNumber,
7719
- available: sql`COALESCE(${availableLateral.available}::numeric, 0)`.as("available"),
7850
+ available: sql`${availableExpr}::numeric`.as("available"),
7720
7851
  takeable: sql`FLOOR(GREATEST(0,
7721
7852
  CASE WHEN ${offers.buy} = false
7722
7853
  THEN ${offers.assets}::numeric - ${groups.consumed}::numeric
7723
7854
  ELSE LEAST(
7724
7855
  ${offers.assets}::numeric - ${groups.consumed}::numeric,
7725
- COALESCE(${availableLateral.available}::numeric, 0)
7856
+ ${availableExpr}::numeric
7726
7857
  )
7727
7858
  END
7728
7859
  ))`.as("takeable")
7729
- }).from(offers).innerJoin(obligations, eq(offers.obligationId, obligations.obligationId)).innerJoin(groups, and(eq(offers.groupChainId, groups.chainId), eq(offers.groupMaker, groups.maker), eq(offers.group, groups.group))).innerJoinLateral(collateralsLateral, sql`true`).leftJoinLateral(availableLateral, sql`true`).where(and(cursor !== null && cursor !== void 0 ? gt(offers.hash, cursor) : void 0, maker !== void 0 ? eq(offers.groupMaker, maker.toLowerCase()) : void 0, gte(offers.expiry, now), gte(offers.maturity, now), maker === void 0 ? sql`GREATEST(0,
7860
+ }).from(offers).innerJoin(obligations, eq(offers.obligationId, obligations.obligationId)).innerJoin(groups, and(eq(offers.groupChainId, groups.chainId), eq(offers.groupMaker, groups.maker), eq(offers.group, groups.group))).innerJoinLateral(collateralsLateral, sql`true`).where(and(cursor !== null && cursor !== void 0 ? gt(offers.hash, cursor) : void 0, maker !== void 0 ? eq(offers.groupMaker, maker.toLowerCase()) : void 0, gte(offers.expiry, now), gte(offers.maturity, now), maker === void 0 ? sql`GREATEST(0,
7730
7861
  CASE WHEN ${offers.buy} = false
7731
7862
  THEN ${offers.assets}::numeric - ${groups.consumed}::numeric
7732
7863
  ELSE LEAST(
7733
7864
  ${offers.assets}::numeric - ${groups.consumed}::numeric,
7734
- COALESCE(${availableLateral.available}::numeric, 0)
7865
+ ${availableExpr}::numeric
7735
7866
  )
7736
7867
  END
7737
7868
  ) > 0` : void 0)).orderBy(asc(offers.hash)).limit(limit)).map((row) => {