@morpho-dev/router 0.1.9 → 0.1.10
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/index.browser.d.cts +116 -3
- package/dist/index.browser.d.ts +116 -3
- package/dist/index.browser.js +128 -13
- package/dist/index.browser.js.map +1 -1
- package/dist/index.browser.mjs +128 -13
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.node.d.cts +116 -3
- package/dist/index.node.d.ts +116 -3
- package/dist/index.node.js +125 -8
- package/dist/index.node.js.map +1 -1
- package/dist/index.node.mjs +126 -9
- package/dist/index.node.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.node.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import { Errors, LLTV, Offer, Format, Utils, Chain, Maturity, Time, Mempool } fr
|
|
|
2
2
|
export * from '@morpho-dev/mempool';
|
|
3
3
|
import { z } from 'zod/v4';
|
|
4
4
|
import { createDocument } from 'zod-openapi';
|
|
5
|
-
import { parseUnits, maxUint256, publicActions, parseEventLogs, formatUnits, createWalletClient, http, erc20Abi, stringify } from 'viem';
|
|
5
|
+
import { parseUnits, maxUint256, encodeAbiParameters, publicActions, parseEventLogs, formatUnits, createWalletClient, http, decodeAbiParameters, erc20Abi, stringify } from 'viem';
|
|
6
6
|
import { Base64 } from 'js-base64';
|
|
7
7
|
import { getBlockNumber } from 'viem/actions';
|
|
8
8
|
import { AsyncLocalStorage } from 'async_hooks';
|
|
@@ -719,13 +719,25 @@ function fromResponse(offerResponse) {
|
|
|
719
719
|
var Callback_exports = {};
|
|
720
720
|
__export(Callback_exports, {
|
|
721
721
|
CallbackType: () => CallbackType,
|
|
722
|
+
WhitelistedCallbackAddresses: () => WhitelistedCallbackAddresses,
|
|
722
723
|
buildLiquidity: () => buildLiquidity,
|
|
724
|
+
decode: () => decode2,
|
|
725
|
+
encode: () => encode2,
|
|
723
726
|
getCallbackIdForOffer: () => getCallbackIdForOffer
|
|
724
727
|
});
|
|
725
728
|
var CallbackType = /* @__PURE__ */ ((CallbackType2) => {
|
|
726
729
|
CallbackType2["BuyWithEmptyCallback"] = "buy_with_empty_callback";
|
|
730
|
+
CallbackType2["SellWithdrawFromWallet"] = "sell_withdraw_from_wallet";
|
|
727
731
|
return CallbackType2;
|
|
728
732
|
})(CallbackType || {});
|
|
733
|
+
var WhitelistedCallbackAddresses = {
|
|
734
|
+
["buy_with_empty_callback" /* BuyWithEmptyCallback */]: [],
|
|
735
|
+
["sell_withdraw_from_wallet" /* SellWithdrawFromWallet */]: [
|
|
736
|
+
"0x1111111111111111111111111111111111111111",
|
|
737
|
+
"0x2222222222222222222222222222222222222222"
|
|
738
|
+
// @TODO: update once deployed and add mapping per chain if needed
|
|
739
|
+
]
|
|
740
|
+
};
|
|
729
741
|
function buildLiquidity(parameters) {
|
|
730
742
|
const { type, user, contract, chainId, amount, index: index2 = 0, updatedAt = /* @__PURE__ */ new Date() } = parameters;
|
|
731
743
|
if (type !== "buy_with_empty_callback" /* BuyWithEmptyCallback */)
|
|
@@ -767,6 +779,38 @@ function getCallbackIdForOffer(offer) {
|
|
|
767
779
|
}
|
|
768
780
|
return null;
|
|
769
781
|
}
|
|
782
|
+
function decodeSellWithdrawFromWalletData(data) {
|
|
783
|
+
if (!data || data === "0x") throw new Error("Empty callback data");
|
|
784
|
+
try {
|
|
785
|
+
const [collaterals, amounts] = decodeAbiParameters(
|
|
786
|
+
[{ type: "address[]" }, { type: "uint256[]" }],
|
|
787
|
+
data
|
|
788
|
+
);
|
|
789
|
+
if (collaterals.length !== amounts.length) {
|
|
790
|
+
throw new Error("Mismatched array lengths");
|
|
791
|
+
}
|
|
792
|
+
return collaterals.map((c, i) => ({ collateral: c, amount: amounts[i] }));
|
|
793
|
+
} catch (_) {
|
|
794
|
+
throw new Error("Invalid SellWithdrawFromWallet callback data");
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
function decode2(parameters) {
|
|
798
|
+
const { type, data } = parameters;
|
|
799
|
+
if (type === "sell_withdraw_from_wallet" /* SellWithdrawFromWallet */) {
|
|
800
|
+
return decodeSellWithdrawFromWalletData(data);
|
|
801
|
+
}
|
|
802
|
+
throw new Error(`CallbackType not implemented: ${type}`);
|
|
803
|
+
}
|
|
804
|
+
function encode2(parameters) {
|
|
805
|
+
const { type, data } = parameters;
|
|
806
|
+
if (type === "sell_withdraw_from_wallet" /* SellWithdrawFromWallet */) {
|
|
807
|
+
return encodeAbiParameters(
|
|
808
|
+
[{ type: "address[]" }, { type: "uint256[]" }],
|
|
809
|
+
[data.collaterals, data.amounts]
|
|
810
|
+
);
|
|
811
|
+
}
|
|
812
|
+
throw new Error(`CallbackType not implemented: ${type}`);
|
|
813
|
+
}
|
|
770
814
|
|
|
771
815
|
// src/core/Collector/index.ts
|
|
772
816
|
var Collector_exports = {};
|
|
@@ -1386,18 +1430,89 @@ function morpho() {
|
|
|
1386
1430
|
return { message: "Expiry mismatch" };
|
|
1387
1431
|
}
|
|
1388
1432
|
});
|
|
1389
|
-
const
|
|
1390
|
-
|
|
1391
|
-
|
|
1433
|
+
const sellEmptyCallback = single(
|
|
1434
|
+
"sell_offers_empty_callback",
|
|
1435
|
+
(offer, _) => {
|
|
1436
|
+
if (!offer.buy && offer.callback.data === "0x") {
|
|
1437
|
+
return { message: "Sell offers require a non-empty callback." };
|
|
1438
|
+
}
|
|
1392
1439
|
}
|
|
1393
|
-
|
|
1440
|
+
);
|
|
1441
|
+
const buyNonEmptyCallback = single(
|
|
1442
|
+
"buy_offers_non_empty_callback",
|
|
1443
|
+
(offer, _) => {
|
|
1444
|
+
if (offer.buy && offer.callback.data !== "0x") {
|
|
1445
|
+
return { message: "Buy offers must use an empty callback." };
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
);
|
|
1449
|
+
const sellNonWhitelistedCallback = single(
|
|
1450
|
+
"sell_offers_non_whitelisted_callback",
|
|
1451
|
+
(offer, _) => {
|
|
1452
|
+
if (!offer.buy && offer.callback.data !== "0x") {
|
|
1453
|
+
const allowed = new Set(
|
|
1454
|
+
WhitelistedCallbackAddresses["sell_withdraw_from_wallet" /* SellWithdrawFromWallet */].map(
|
|
1455
|
+
(a) => a.toLowerCase()
|
|
1456
|
+
)
|
|
1457
|
+
);
|
|
1458
|
+
const callbackAddress = offer.callback.address?.toLowerCase();
|
|
1459
|
+
if (!callbackAddress || !allowed.has(callbackAddress)) {
|
|
1460
|
+
return { message: "Sell offer callback address is not whitelisted." };
|
|
1461
|
+
}
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
);
|
|
1465
|
+
const sellCallbackDataInvalid = single(
|
|
1466
|
+
"sell_offers_callback_data_invalid",
|
|
1467
|
+
(offer, _) => {
|
|
1468
|
+
if (!offer.buy && offer.callback.data !== "0x") {
|
|
1469
|
+
try {
|
|
1470
|
+
const decoded = decode2({
|
|
1471
|
+
type: "sell_withdraw_from_wallet" /* SellWithdrawFromWallet */,
|
|
1472
|
+
data: offer.callback.data
|
|
1473
|
+
});
|
|
1474
|
+
if (decoded.length === 0) {
|
|
1475
|
+
return { message: "Sell offer callback data must include at least one collateral." };
|
|
1476
|
+
}
|
|
1477
|
+
} catch (_2) {
|
|
1478
|
+
return { message: "Sell offer callback data cannot be decoded." };
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1482
|
+
);
|
|
1483
|
+
const sellCallbackCollateralInvalid = single(
|
|
1484
|
+
"sell_offers_callback_collateral_invalid",
|
|
1485
|
+
(offer, _) => {
|
|
1486
|
+
if (!offer.buy && offer.callback.data !== "0x") {
|
|
1487
|
+
try {
|
|
1488
|
+
const decoded = decode2({
|
|
1489
|
+
type: "sell_withdraw_from_wallet" /* SellWithdrawFromWallet */,
|
|
1490
|
+
data: offer.callback.data
|
|
1491
|
+
});
|
|
1492
|
+
const offerCollaterals2 = new Set(
|
|
1493
|
+
offer.collaterals.map((c) => c.asset.toLowerCase())
|
|
1494
|
+
);
|
|
1495
|
+
for (const { collateral } of decoded) {
|
|
1496
|
+
if (!offerCollaterals2.has(collateral.toLowerCase())) {
|
|
1497
|
+
return { message: "Sell callback collateral is not part of offer collaterals." };
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
} catch (_2) {
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1503
|
+
}
|
|
1504
|
+
);
|
|
1394
1505
|
return [
|
|
1395
1506
|
chainId,
|
|
1396
1507
|
loanToken,
|
|
1397
1508
|
expiry,
|
|
1398
|
-
// note: callback
|
|
1509
|
+
// note: callback rules should be the last ones, since they do not mean that the offer is forever invalid
|
|
1399
1510
|
// integrators should be able to choose if they want to keep the offer or not
|
|
1400
|
-
|
|
1511
|
+
sellEmptyCallback,
|
|
1512
|
+
buyNonEmptyCallback,
|
|
1513
|
+
sellNonWhitelistedCallback,
|
|
1514
|
+
sellCallbackDataInvalid,
|
|
1515
|
+
sellCallbackCollateralInvalid
|
|
1401
1516
|
];
|
|
1402
1517
|
}
|
|
1403
1518
|
|
|
@@ -1446,9 +1561,11 @@ function createMempoolCollector(parameters) {
|
|
|
1446
1561
|
});
|
|
1447
1562
|
const invalidOffersToSave = [];
|
|
1448
1563
|
const issueToStatus = {
|
|
1449
|
-
empty_callback: "callback_not_supported",
|
|
1450
1564
|
sell_offers_empty_callback: "callback_not_supported",
|
|
1451
|
-
|
|
1565
|
+
buy_offers_non_empty_callback: "callback_not_supported",
|
|
1566
|
+
sell_offers_non_whitelisted_callback: "callback_not_supported",
|
|
1567
|
+
sell_offers_callback_data_invalid: "callback_error",
|
|
1568
|
+
sell_offers_callback_collateral_invalid: "callback_error"
|
|
1452
1569
|
};
|
|
1453
1570
|
for (const issue of issues) {
|
|
1454
1571
|
const status = issueToStatus[issue.ruleName];
|