@morpho-dev/router 0.1.1 → 0.1.3

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.
@@ -1,7 +1,6 @@
1
1
  import { Errors, LLTV, Offer, Format, Time, Maturity } from '@morpho-dev/mempool';
2
2
  export * from '@morpho-dev/mempool';
3
- import { base, mainnet } from 'viem/chains';
4
- import { parseUnits, maxUint256, formatUnits, parseAbi } from 'viem';
3
+ import { parseUnits, maxUint256, formatUnits } from 'viem';
5
4
  import { z } from 'zod/v4';
6
5
  import { createDocument } from 'zod-openapi';
7
6
  import { Base64 } from 'js-base64';
@@ -14,85 +13,6 @@ var __export = (target, all) => {
14
13
  };
15
14
  var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value);
16
15
 
17
- // src/Chain.ts
18
- var Chain_exports = {};
19
- __export(Chain_exports, {
20
- ChainId: () => ChainId,
21
- chainIds: () => chainIds,
22
- chainNames: () => chainNames,
23
- chains: () => chains,
24
- getChain: () => getChain,
25
- getWhitelistedChains: () => getWhitelistedChains
26
- });
27
- var chainNames = ["ethereum", "base", "ethereum-virtual-testnet"];
28
- var ChainId = {
29
- ETHEREUM: BigInt(mainnet.id),
30
- BASE: BigInt(base.id),
31
- "ETHEREUM-VIRTUAL-TESTNET": 109111114n
32
- };
33
- var chainIds = new Set(Object.values(ChainId));
34
- var chainNameLookup = new Map(Object.entries(ChainId).map(([key, value]) => [value, key]));
35
- function getChain(chainId) {
36
- const chainName = chainNameLookup.get(chainId)?.toLowerCase();
37
- if (!chainName) {
38
- return void 0;
39
- }
40
- return chains[chainName];
41
- }
42
- var getWhitelistedChains = () => {
43
- return [chains.ethereum, chains.base, chains["ethereum-virtual-testnet"]];
44
- };
45
- var chains = {
46
- ethereum: {
47
- ...mainnet,
48
- id: ChainId.ETHEREUM,
49
- name: "ethereum",
50
- whitelistedAssets: new Set(
51
- [
52
- "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
53
- // USDC
54
- "0x6B175474E89094C44Da98b954EedeAC495271d0F"
55
- // DAI
56
- ].map((address) => address.toLowerCase())
57
- ),
58
- morpho: "0x0000000000000000000000000000000000000000"
59
- },
60
- base: {
61
- ...base,
62
- id: ChainId.BASE,
63
- name: "base",
64
- whitelistedAssets: new Set(
65
- [
66
- "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
67
- // USDC
68
- "0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb"
69
- // DAI
70
- ].map((address) => address.toLowerCase())
71
- ),
72
- morpho: "0x0000000000000000000000000000000000000000"
73
- },
74
- "ethereum-virtual-testnet": {
75
- ...mainnet,
76
- id: 109111114n,
77
- name: "ethereum-virtual-testnet",
78
- whitelistedAssets: new Set(
79
- [
80
- "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
81
- // USDC
82
- "0x6B175474E89094C44Da98b954EedeAC495271d0F"
83
- // DAI
84
- ].map((address) => address.toLowerCase())
85
- ),
86
- morpho: "0x11a002d45db720ed47a80d2f3489cba5b833eaf5",
87
- // @TODO: This is mock Consumed contract, update with Terms once stable
88
- mempool: {
89
- address: "0x7be3164eeee8b35092f6128ec32c2e6ff8f6c890",
90
- deploymentBlock: 23223727,
91
- reindexBuffer: 10
92
- }
93
- }
94
- };
95
-
96
16
  // src/core/router/Client.ts
97
17
  var Client_exports = {};
98
18
  __export(Client_exports, {
@@ -1080,7 +1000,6 @@ function memory(parameters) {
1080
1000
  const map = parameters.offers;
1081
1001
  const filled = parameters.filled;
1082
1002
  const consumedIds = /* @__PURE__ */ new Set();
1083
- const indexingProgress = /* @__PURE__ */ new Map();
1084
1003
  const create = async (parameters2) => {
1085
1004
  if (map.has(parameters2.offer.hash.toLowerCase())) return parameters2.offer.hash;
1086
1005
  map.set(parameters2.offer.hash.toLowerCase(), {
@@ -1151,7 +1070,7 @@ function memory(parameters) {
1151
1070
  let {
1152
1071
  creators,
1153
1072
  side,
1154
- chains: chains2,
1073
+ chains,
1155
1074
  loanTokens,
1156
1075
  status = ["valid"],
1157
1076
  callbackAddresses,
@@ -1222,7 +1141,7 @@ function memory(parameters) {
1222
1141
  offers = offers.filter((o) => o.expiry >= now);
1223
1142
  creators && (offers = offers.filter((o) => creators.includes(o.offering.toLowerCase())));
1224
1143
  side && (offers = offers.filter((o) => o.buy === buy));
1225
- chains2 && (offers = offers.filter((o) => chains2.includes(Number(o.chainId))));
1144
+ chains && (offers = offers.filter((o) => chains.includes(Number(o.chainId))));
1226
1145
  loanTokens && (offers = offers.filter((o) => loanTokens.includes(o.loanToken.toLowerCase())));
1227
1146
  status && (offers = offers.filter((o) => status.includes(o.status)));
1228
1147
  callbackAddresses && (offers = offers.filter(
@@ -1428,31 +1347,10 @@ function memory(parameters) {
1428
1347
  filledForOffering.set(nonce, current + parameters2.consumed);
1429
1348
  filledForChain.set(address, filledForOffering);
1430
1349
  filled.set(chainId, filledForChain);
1431
- },
1432
- saveLatestBlockNumberProcessed: async (parameters2) => {
1433
- const key = `${parameters2.chainId.toString()}:${parameters2.eventType}`;
1434
- indexingProgress.set(key, parameters2.latestBlockNumber);
1435
- },
1436
- getLatestBlockNumberProcessed: async (parameters2) => {
1437
- const key = `${parameters2.chainId.toString()}:${parameters2.eventType}`;
1438
- const value = indexingProgress.get(key);
1439
- return value === void 0 ? null : { latestBlockNumber: value };
1440
1350
  }
1441
1351
  };
1442
1352
  }
1443
1353
 
1444
- // src/RouterEvent.ts
1445
- var RouterEvent_exports = {};
1446
- __export(RouterEvent_exports, {
1447
- from: () => from2,
1448
- types: () => types
1449
- });
1450
- var types = ["offer_created", "offer_consumed", "offer_validation"];
1451
- function from2(base) {
1452
- const id = base.type === "offer_consumed" ? `${base.type}:${base.offerConsumed.id}` : `${base.type}:${base.offer.hash.toLowerCase()}`;
1453
- return { id, ...base };
1454
- }
1455
-
1456
1354
  // src/Validation.ts
1457
1355
  var Validation_exports = {};
1458
1356
  __export(Validation_exports, {
@@ -1513,25 +1411,19 @@ function single(name, run2) {
1513
1411
  function batch2(name, run2) {
1514
1412
  return { kind: "batch", name, run: run2 };
1515
1413
  }
1516
- function morpho(parameters) {
1517
- const { whitelistedChains } = parameters;
1518
- const whitelistedChainIds = new Set(whitelistedChains.map((chain) => chain.id));
1519
- const whitelistedLoanTokensPerChain = new Map(
1520
- whitelistedChains.map((chain) => [
1521
- chain.id,
1522
- new Set(Array.from(chain.whitelistedAssets).map((a) => a.toLowerCase()))
1523
- ])
1524
- );
1525
- const morphoPerChain = new Map(
1526
- whitelistedChains.map((chain) => [chain.id, chain.morpho.toLowerCase()])
1527
- );
1528
- const chainId = single("chain_id", (offer, _) => {
1529
- if (!whitelistedChainIds.has(offer.chainId)) {
1530
- return { message: `Chain ID ${offer.chainId} is not whitelisted` };
1414
+ function morpho() {
1415
+ const chainId = single("chain_id", (offer, { chain }) => {
1416
+ if (chain.id !== offer.chainId) {
1417
+ return {
1418
+ message: `Chain ID ${offer.chainId} is not the same as the chain ID in the context (${chain.id})`
1419
+ };
1531
1420
  }
1532
1421
  });
1533
- const loanToken = single("loan_token", (offer, _) => {
1534
- if (!whitelistedLoanTokensPerChain.get(offer.chainId)?.has(offer.loanToken.toLowerCase())) {
1422
+ const loanToken = single("loan_token", (offer, { chain }) => {
1423
+ const tokens = new Set(
1424
+ Array.from(chain.whitelistedAssets.values()).map((a) => a.toLowerCase())
1425
+ );
1426
+ if (!tokens.has(offer.loanToken.toLowerCase())) {
1535
1427
  return {
1536
1428
  message: `Loan token ${offer.loanToken} is not whitelisted on chain ${offer.chainId}`
1537
1429
  };
@@ -1542,130 +1434,21 @@ function morpho(parameters) {
1542
1434
  return { message: "Expiry mismatch" };
1543
1435
  }
1544
1436
  });
1545
- const emptyCallback = single("empty_callback", (offer, _) => {
1546
- if (offer.callback.data !== "0x") {
1547
- return { message: "Callback data is not empty. Not supported yet." };
1437
+ const callback = single("empty_callback", (offer, _) => {
1438
+ if (!offer.buy || offer.callback.data !== "0x") {
1439
+ return { message: "Callback not supported yet." };
1548
1440
  }
1549
1441
  });
1550
- const sellOffersEmptyCallback = single(
1551
- "sell_offers_empty_callback",
1552
- (offer, _) => {
1553
- if (!offer.buy && offer.callback.data === "0x") {
1554
- return { message: "Sell offers with empty callback are not supported yet." };
1555
- }
1556
- }
1557
- );
1558
- const buyOffersEmptyCallback = batch2(
1559
- "buy_offers_empty_callback",
1560
- async (offers, { publicClients }) => {
1561
- const issues = /* @__PURE__ */ new Map();
1562
- const hashToIndex = /* @__PURE__ */ new Map();
1563
- for (let i = 0; i < offers.length; i++) {
1564
- const offer = offers[i];
1565
- hashToIndex.set(offer.hash, i);
1566
- }
1567
- const { buyOffers, sellOffers: _sellOffers } = offers.reduce(
1568
- (acc, offer) => {
1569
- offer.buy ? acc.buyOffers.push(offer) : issues.set(hashToIndex.get(offer.hash), {
1570
- message: "Onchain callback for sell offers is not supported yet."
1571
- });
1572
- return acc;
1573
- },
1574
- { buyOffers: [], sellOffers: [] }
1575
- );
1576
- const buyOffersPerLoanAsset = /* @__PURE__ */ new Map();
1577
- for (const offer of buyOffers) {
1578
- const chainName = getChain(offer.chainId)?.name;
1579
- const loanTokens = buyOffersPerLoanAsset.get(chainName) ?? /* @__PURE__ */ new Map();
1580
- const offers2 = loanTokens.get(offer.loanToken.toLowerCase()) ?? [];
1581
- offers2.push(offer);
1582
- loanTokens.set(offer.loanToken.toLowerCase(), offers2);
1583
- buyOffersPerLoanAsset.set(chainName, loanTokens);
1584
- }
1585
- await Promise.all(
1586
- Array.from(buyOffersPerLoanAsset.entries()).map(async ([name, loanTokens]) => {
1587
- const chainName = name;
1588
- const publicClient = publicClients[chainName];
1589
- const morpho2 = morphoPerChain.get(chains[chainName].id);
1590
- if (!publicClient) {
1591
- const offers2 = Array.from(loanTokens.values()).flat();
1592
- for (const offer of offers2) {
1593
- issues.set(hashToIndex.get(offer.hash), {
1594
- message: `Public client for chain "${chainName}" is not available`
1595
- });
1596
- }
1597
- return;
1598
- }
1599
- const balances = /* @__PURE__ */ new Map();
1600
- const allowances = /* @__PURE__ */ new Map();
1601
- for (const [loanToken2, offers2] of loanTokens) {
1602
- const data = await Promise.all(
1603
- offers2.flatMap((offer) => [
1604
- publicClient.readContract({
1605
- address: loanToken2,
1606
- abi: parseAbi([
1607
- "function balanceOf(address owner) view returns (uint256 balance)"
1608
- ]),
1609
- functionName: "balanceOf",
1610
- args: [offer.offering]
1611
- }),
1612
- publicClient.readContract({
1613
- address: loanToken2,
1614
- abi: parseAbi([
1615
- "function allowance(address owner, address spender) public view returns (uint256 remaining)"
1616
- ]),
1617
- functionName: "allowance",
1618
- args: [offer.offering, morpho2]
1619
- })
1620
- ])
1621
- );
1622
- for (let i = 0; i < offers2.length; i++) {
1623
- const user = offers2[i].offering.toLowerCase();
1624
- const balance = data[i * 2] || 0n;
1625
- const allowance = data[i * 2 + 1] || 0n;
1626
- const userBalances = balances.get(user) ?? /* @__PURE__ */ new Map();
1627
- userBalances.set(loanToken2.toLowerCase(), balance);
1628
- const userAllowances = allowances.get(user) ?? /* @__PURE__ */ new Map();
1629
- userAllowances.set(loanToken2.toLowerCase(), allowance);
1630
- balances.set(user, userBalances);
1631
- allowances.set(user, userAllowances);
1632
- }
1633
- }
1634
- for (const offer of Array.from(loanTokens.values()).flat()) {
1635
- const user = offer.offering.toLowerCase();
1636
- const userBalances = balances.get(user);
1637
- const balance = userBalances?.get(offer.loanToken.toLowerCase());
1638
- if (balance < offer.assets) {
1639
- issues.set(hashToIndex.get(offer.hash), {
1640
- message: `Insufficient balance for ${offer.loanToken} on chain ${offer.chainId} (${balance.toString()} < ${offer.assets.toString()})`
1641
- });
1642
- continue;
1643
- }
1644
- const userAllowances = allowances.get(user);
1645
- const allowance = userAllowances?.get(offer.loanToken.toLowerCase());
1646
- if (allowance < offer.assets) {
1647
- issues.set(hashToIndex.get(offer.hash), {
1648
- message: `Insufficient allowance for ${offer.loanToken} on chain ${offer.chainId} (${allowance.toString()} < ${offer.assets.toString()})`
1649
- });
1650
- }
1651
- }
1652
- })
1653
- );
1654
- return issues;
1655
- }
1656
- );
1657
1442
  return [
1658
1443
  chainId,
1659
1444
  loanToken,
1660
1445
  expiry,
1661
- // note: callback onchain check should be done last since it does not mean that the offer is forever invalid
1662
- // integrators should be able to keep the offers that have an invalid callback onchain and be sure that is the only check that is not valid
1663
- emptyCallback,
1664
- sellOffersEmptyCallback,
1665
- buyOffersEmptyCallback
1446
+ // note: callback rule should be the last one, since it does not mean that the offer is forever invalid
1447
+ // integrators should be able to choose if they want to keep the offer or not
1448
+ callback
1666
1449
  ];
1667
1450
  }
1668
1451
 
1669
- export { Chain_exports as Chain, OfferStore_exports as OfferStore, Client_exports as Router, RouterEvent_exports as RouterEvent, RouterOffer_exports as RouterOffer, utils_exports as Utils, Validation_exports as Validation, ValidationRule_exports as ValidationRule };
1452
+ export { OfferStore_exports as OfferStore, Client_exports as Router, RouterOffer_exports as RouterOffer, utils_exports as Utils, Validation_exports as Validation, ValidationRule_exports as ValidationRule };
1670
1453
  //# sourceMappingURL=index.browser.mjs.map
1671
1454
  //# sourceMappingURL=index.browser.mjs.map