@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.
@@ -80,8 +80,10 @@ declare namespace Liquidity$1 {
80
80
  }
81
81
 
82
82
  declare enum CallbackType {
83
- BuyWithEmptyCallback = "buy_with_empty_callback"
83
+ BuyWithEmptyCallback = "buy_with_empty_callback",
84
+ SellWithdrawFromWallet = "sell_withdraw_from_wallet"
84
85
  }
86
+ declare const WhitelistedCallbackAddresses: Record<CallbackType, readonly string[]>;
85
87
  declare function buildLiquidity(parameters: {
86
88
  type: CallbackType;
87
89
  user: string;
@@ -92,13 +94,28 @@ declare function buildLiquidity(parameters: {
92
94
  updatedAt?: Date;
93
95
  }): Liquidity;
94
96
  declare function getCallbackIdForOffer(offer: Offer.Offer): string | null;
97
+ declare function decode$1(parameters: {
98
+ type: CallbackType;
99
+ data: Hex;
100
+ }): Array<{
101
+ collateral: Address;
102
+ amount: bigint;
103
+ }>;
104
+ declare function encode$1(parameters: {
105
+ type: CallbackType;
106
+ data: {
107
+ collaterals: Address[];
108
+ amounts: bigint[];
109
+ };
110
+ }): Hex;
95
111
 
96
112
  type Callback_CallbackType = CallbackType;
97
113
  declare const Callback_CallbackType: typeof CallbackType;
114
+ declare const Callback_WhitelistedCallbackAddresses: typeof WhitelistedCallbackAddresses;
98
115
  declare const Callback_buildLiquidity: typeof buildLiquidity;
99
116
  declare const Callback_getCallbackIdForOffer: typeof getCallbackIdForOffer;
100
117
  declare namespace Callback {
101
- export { Callback_CallbackType as CallbackType, Callback_buildLiquidity as buildLiquidity, Callback_getCallbackIdForOffer as getCallbackIdForOffer };
118
+ export { Callback_CallbackType as CallbackType, Callback_WhitelistedCallbackAddresses as WhitelistedCallbackAddresses, Callback_buildLiquidity as buildLiquidity, decode$1 as decode, encode$1 as encode, Callback_getCallbackIdForOffer as getCallbackIdForOffer };
102
119
  }
103
120
 
104
121
  type Cursor = {
@@ -578,7 +595,103 @@ declare function morpho(): (Rule<{
578
595
  readonly hash: viem.Hex;
579
596
  signature?: viem.Hex;
580
597
  createdAt?: number;
581
- }, "empty_callback", MorphoContext>)[];
598
+ }, "sell_offers_empty_callback", MorphoContext> | Rule<{
599
+ readonly offering: Address;
600
+ readonly assets: bigint;
601
+ readonly rate: bigint;
602
+ readonly maturity: number & _morpho_dev_mempool.Brand<"Maturity">;
603
+ readonly expiry: number;
604
+ readonly nonce: bigint;
605
+ readonly buy: boolean;
606
+ readonly chainId: bigint;
607
+ readonly loanToken: Address;
608
+ readonly start: number;
609
+ readonly collaterals: readonly {
610
+ asset: Address;
611
+ oracle: Address;
612
+ lltv: bigint & _morpho_dev_mempool.Brand<"LLTV">;
613
+ }[];
614
+ readonly callback: {
615
+ readonly address: Address;
616
+ readonly data: viem.Hex;
617
+ readonly gasLimit: bigint;
618
+ };
619
+ readonly hash: viem.Hex;
620
+ signature?: viem.Hex;
621
+ createdAt?: number;
622
+ }, "buy_offers_non_empty_callback", MorphoContext> | Rule<{
623
+ readonly offering: Address;
624
+ readonly assets: bigint;
625
+ readonly rate: bigint;
626
+ readonly maturity: number & _morpho_dev_mempool.Brand<"Maturity">;
627
+ readonly expiry: number;
628
+ readonly nonce: bigint;
629
+ readonly buy: boolean;
630
+ readonly chainId: bigint;
631
+ readonly loanToken: Address;
632
+ readonly start: number;
633
+ readonly collaterals: readonly {
634
+ asset: Address;
635
+ oracle: Address;
636
+ lltv: bigint & _morpho_dev_mempool.Brand<"LLTV">;
637
+ }[];
638
+ readonly callback: {
639
+ readonly address: Address;
640
+ readonly data: viem.Hex;
641
+ readonly gasLimit: bigint;
642
+ };
643
+ readonly hash: viem.Hex;
644
+ signature?: viem.Hex;
645
+ createdAt?: number;
646
+ }, "sell_offers_non_whitelisted_callback", MorphoContext> | Rule<{
647
+ readonly offering: Address;
648
+ readonly assets: bigint;
649
+ readonly rate: bigint;
650
+ readonly maturity: number & _morpho_dev_mempool.Brand<"Maturity">;
651
+ readonly expiry: number;
652
+ readonly nonce: bigint;
653
+ readonly buy: boolean;
654
+ readonly chainId: bigint;
655
+ readonly loanToken: Address;
656
+ readonly start: number;
657
+ readonly collaterals: readonly {
658
+ asset: Address;
659
+ oracle: Address;
660
+ lltv: bigint & _morpho_dev_mempool.Brand<"LLTV">;
661
+ }[];
662
+ readonly callback: {
663
+ readonly address: Address;
664
+ readonly data: viem.Hex;
665
+ readonly gasLimit: bigint;
666
+ };
667
+ readonly hash: viem.Hex;
668
+ signature?: viem.Hex;
669
+ createdAt?: number;
670
+ }, "sell_offers_callback_data_invalid", MorphoContext> | Rule<{
671
+ readonly offering: Address;
672
+ readonly assets: bigint;
673
+ readonly rate: bigint;
674
+ readonly maturity: number & _morpho_dev_mempool.Brand<"Maturity">;
675
+ readonly expiry: number;
676
+ readonly nonce: bigint;
677
+ readonly buy: boolean;
678
+ readonly chainId: bigint;
679
+ readonly loanToken: Address;
680
+ readonly start: number;
681
+ readonly collaterals: readonly {
682
+ asset: Address;
683
+ oracle: Address;
684
+ lltv: bigint & _morpho_dev_mempool.Brand<"LLTV">;
685
+ }[];
686
+ readonly callback: {
687
+ readonly address: Address;
688
+ readonly data: viem.Hex;
689
+ readonly gasLimit: bigint;
690
+ };
691
+ readonly hash: viem.Hex;
692
+ signature?: viem.Hex;
693
+ createdAt?: number;
694
+ }, "sell_offers_callback_collateral_invalid", MorphoContext>)[];
582
695
 
583
696
  type ValidationRule_Batch<T, RuleName extends string, Ctx = void> = Batch<T, RuleName, Ctx>;
584
697
  type ValidationRule_MorphoContext = MorphoContext;
@@ -80,8 +80,10 @@ declare namespace Liquidity$1 {
80
80
  }
81
81
 
82
82
  declare enum CallbackType {
83
- BuyWithEmptyCallback = "buy_with_empty_callback"
83
+ BuyWithEmptyCallback = "buy_with_empty_callback",
84
+ SellWithdrawFromWallet = "sell_withdraw_from_wallet"
84
85
  }
86
+ declare const WhitelistedCallbackAddresses: Record<CallbackType, readonly string[]>;
85
87
  declare function buildLiquidity(parameters: {
86
88
  type: CallbackType;
87
89
  user: string;
@@ -92,13 +94,28 @@ declare function buildLiquidity(parameters: {
92
94
  updatedAt?: Date;
93
95
  }): Liquidity;
94
96
  declare function getCallbackIdForOffer(offer: Offer.Offer): string | null;
97
+ declare function decode$1(parameters: {
98
+ type: CallbackType;
99
+ data: Hex;
100
+ }): Array<{
101
+ collateral: Address;
102
+ amount: bigint;
103
+ }>;
104
+ declare function encode$1(parameters: {
105
+ type: CallbackType;
106
+ data: {
107
+ collaterals: Address[];
108
+ amounts: bigint[];
109
+ };
110
+ }): Hex;
95
111
 
96
112
  type Callback_CallbackType = CallbackType;
97
113
  declare const Callback_CallbackType: typeof CallbackType;
114
+ declare const Callback_WhitelistedCallbackAddresses: typeof WhitelistedCallbackAddresses;
98
115
  declare const Callback_buildLiquidity: typeof buildLiquidity;
99
116
  declare const Callback_getCallbackIdForOffer: typeof getCallbackIdForOffer;
100
117
  declare namespace Callback {
101
- export { Callback_CallbackType as CallbackType, Callback_buildLiquidity as buildLiquidity, Callback_getCallbackIdForOffer as getCallbackIdForOffer };
118
+ export { Callback_CallbackType as CallbackType, Callback_WhitelistedCallbackAddresses as WhitelistedCallbackAddresses, Callback_buildLiquidity as buildLiquidity, decode$1 as decode, encode$1 as encode, Callback_getCallbackIdForOffer as getCallbackIdForOffer };
102
119
  }
103
120
 
104
121
  type Cursor = {
@@ -578,7 +595,103 @@ declare function morpho(): (Rule<{
578
595
  readonly hash: viem.Hex;
579
596
  signature?: viem.Hex;
580
597
  createdAt?: number;
581
- }, "empty_callback", MorphoContext>)[];
598
+ }, "sell_offers_empty_callback", MorphoContext> | Rule<{
599
+ readonly offering: Address;
600
+ readonly assets: bigint;
601
+ readonly rate: bigint;
602
+ readonly maturity: number & _morpho_dev_mempool.Brand<"Maturity">;
603
+ readonly expiry: number;
604
+ readonly nonce: bigint;
605
+ readonly buy: boolean;
606
+ readonly chainId: bigint;
607
+ readonly loanToken: Address;
608
+ readonly start: number;
609
+ readonly collaterals: readonly {
610
+ asset: Address;
611
+ oracle: Address;
612
+ lltv: bigint & _morpho_dev_mempool.Brand<"LLTV">;
613
+ }[];
614
+ readonly callback: {
615
+ readonly address: Address;
616
+ readonly data: viem.Hex;
617
+ readonly gasLimit: bigint;
618
+ };
619
+ readonly hash: viem.Hex;
620
+ signature?: viem.Hex;
621
+ createdAt?: number;
622
+ }, "buy_offers_non_empty_callback", MorphoContext> | Rule<{
623
+ readonly offering: Address;
624
+ readonly assets: bigint;
625
+ readonly rate: bigint;
626
+ readonly maturity: number & _morpho_dev_mempool.Brand<"Maturity">;
627
+ readonly expiry: number;
628
+ readonly nonce: bigint;
629
+ readonly buy: boolean;
630
+ readonly chainId: bigint;
631
+ readonly loanToken: Address;
632
+ readonly start: number;
633
+ readonly collaterals: readonly {
634
+ asset: Address;
635
+ oracle: Address;
636
+ lltv: bigint & _morpho_dev_mempool.Brand<"LLTV">;
637
+ }[];
638
+ readonly callback: {
639
+ readonly address: Address;
640
+ readonly data: viem.Hex;
641
+ readonly gasLimit: bigint;
642
+ };
643
+ readonly hash: viem.Hex;
644
+ signature?: viem.Hex;
645
+ createdAt?: number;
646
+ }, "sell_offers_non_whitelisted_callback", MorphoContext> | Rule<{
647
+ readonly offering: Address;
648
+ readonly assets: bigint;
649
+ readonly rate: bigint;
650
+ readonly maturity: number & _morpho_dev_mempool.Brand<"Maturity">;
651
+ readonly expiry: number;
652
+ readonly nonce: bigint;
653
+ readonly buy: boolean;
654
+ readonly chainId: bigint;
655
+ readonly loanToken: Address;
656
+ readonly start: number;
657
+ readonly collaterals: readonly {
658
+ asset: Address;
659
+ oracle: Address;
660
+ lltv: bigint & _morpho_dev_mempool.Brand<"LLTV">;
661
+ }[];
662
+ readonly callback: {
663
+ readonly address: Address;
664
+ readonly data: viem.Hex;
665
+ readonly gasLimit: bigint;
666
+ };
667
+ readonly hash: viem.Hex;
668
+ signature?: viem.Hex;
669
+ createdAt?: number;
670
+ }, "sell_offers_callback_data_invalid", MorphoContext> | Rule<{
671
+ readonly offering: Address;
672
+ readonly assets: bigint;
673
+ readonly rate: bigint;
674
+ readonly maturity: number & _morpho_dev_mempool.Brand<"Maturity">;
675
+ readonly expiry: number;
676
+ readonly nonce: bigint;
677
+ readonly buy: boolean;
678
+ readonly chainId: bigint;
679
+ readonly loanToken: Address;
680
+ readonly start: number;
681
+ readonly collaterals: readonly {
682
+ asset: Address;
683
+ oracle: Address;
684
+ lltv: bigint & _morpho_dev_mempool.Brand<"LLTV">;
685
+ }[];
686
+ readonly callback: {
687
+ readonly address: Address;
688
+ readonly data: viem.Hex;
689
+ readonly gasLimit: bigint;
690
+ };
691
+ readonly hash: viem.Hex;
692
+ signature?: viem.Hex;
693
+ createdAt?: number;
694
+ }, "sell_offers_callback_collateral_invalid", MorphoContext>)[];
582
695
 
583
696
  type ValidationRule_Batch<T, RuleName extends string, Ctx = void> = Batch<T, RuleName, Ctx>;
584
697
  type ValidationRule_MorphoContext = MorphoContext;
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  var mempool = require('@morpho-dev/mempool');
4
- var jsBase64 = require('js-base64');
5
4
  var viem = require('viem');
5
+ var jsBase64 = require('js-base64');
6
6
  var v4 = require('zod/v4');
7
7
  var zodOpenapi = require('zod-openapi');
8
8
 
@@ -18,13 +18,25 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value);
18
18
  var Callback_exports = {};
19
19
  __export(Callback_exports, {
20
20
  CallbackType: () => CallbackType,
21
+ WhitelistedCallbackAddresses: () => WhitelistedCallbackAddresses,
21
22
  buildLiquidity: () => buildLiquidity,
23
+ decode: () => decode,
24
+ encode: () => encode,
22
25
  getCallbackIdForOffer: () => getCallbackIdForOffer
23
26
  });
24
27
  var CallbackType = /* @__PURE__ */ ((CallbackType2) => {
25
28
  CallbackType2["BuyWithEmptyCallback"] = "buy_with_empty_callback";
29
+ CallbackType2["SellWithdrawFromWallet"] = "sell_withdraw_from_wallet";
26
30
  return CallbackType2;
27
31
  })(CallbackType || {});
32
+ var WhitelistedCallbackAddresses = {
33
+ ["buy_with_empty_callback" /* BuyWithEmptyCallback */]: [],
34
+ ["sell_withdraw_from_wallet" /* SellWithdrawFromWallet */]: [
35
+ "0x1111111111111111111111111111111111111111",
36
+ "0x2222222222222222222222222222222222222222"
37
+ // @TODO: update once deployed and add mapping per chain if needed
38
+ ]
39
+ };
28
40
  function buildLiquidity(parameters) {
29
41
  const { type, user, contract, chainId, amount, index = 0, updatedAt = /* @__PURE__ */ new Date() } = parameters;
30
42
  if (type !== "buy_with_empty_callback" /* BuyWithEmptyCallback */)
@@ -66,12 +78,44 @@ function getCallbackIdForOffer(offer) {
66
78
  }
67
79
  return null;
68
80
  }
81
+ function decodeSellWithdrawFromWalletData(data) {
82
+ if (!data || data === "0x") throw new Error("Empty callback data");
83
+ try {
84
+ const [collaterals, amounts] = viem.decodeAbiParameters(
85
+ [{ type: "address[]" }, { type: "uint256[]" }],
86
+ data
87
+ );
88
+ if (collaterals.length !== amounts.length) {
89
+ throw new Error("Mismatched array lengths");
90
+ }
91
+ return collaterals.map((c, i) => ({ collateral: c, amount: amounts[i] }));
92
+ } catch (_) {
93
+ throw new Error("Invalid SellWithdrawFromWallet callback data");
94
+ }
95
+ }
96
+ function decode(parameters) {
97
+ const { type, data } = parameters;
98
+ if (type === "sell_withdraw_from_wallet" /* SellWithdrawFromWallet */) {
99
+ return decodeSellWithdrawFromWalletData(data);
100
+ }
101
+ throw new Error(`CallbackType not implemented: ${type}`);
102
+ }
103
+ function encode(parameters) {
104
+ const { type, data } = parameters;
105
+ if (type === "sell_withdraw_from_wallet" /* SellWithdrawFromWallet */) {
106
+ return viem.encodeAbiParameters(
107
+ [{ type: "address[]" }, { type: "uint256[]" }],
108
+ [data.collaterals, data.amounts]
109
+ );
110
+ }
111
+ throw new Error(`CallbackType not implemented: ${type}`);
112
+ }
69
113
 
70
114
  // src/core/Cursor.ts
71
115
  var Cursor_exports = {};
72
116
  __export(Cursor_exports, {
73
- decode: () => decode,
74
- encode: () => encode,
117
+ decode: () => decode2,
118
+ encode: () => encode2,
75
119
  validate: () => validate
76
120
  });
77
121
  function validate(cursor) {
@@ -143,10 +187,10 @@ function validate(cursor) {
143
187
  }
144
188
  return true;
145
189
  }
146
- function encode(c) {
190
+ function encode2(c) {
147
191
  return jsBase64.Base64.encodeURL(JSON.stringify(c));
148
192
  }
149
- function decode(token) {
193
+ function decode2(token) {
150
194
  if (!token) return null;
151
195
  const decoded = JSON.parse(jsBase64.Base64.decode(token));
152
196
  validate(decoded);
@@ -555,7 +599,7 @@ var GetOffersQueryParams = v4.z.object({
555
599
  (val) => {
556
600
  if (!val) return true;
557
601
  try {
558
- const decoded = decode(val);
602
+ const decoded = decode2(val);
559
603
  return decoded !== null;
560
604
  } catch (_error) {
561
605
  return false;
@@ -727,7 +771,7 @@ var MatchOffersQueryParams = v4.z.object({
727
771
  (val) => {
728
772
  if (!val) return true;
729
773
  try {
730
- const decoded = decode(val);
774
+ const decoded = decode2(val);
731
775
  return decoded !== null;
732
776
  } catch (_error) {
733
777
  return false;
@@ -1203,18 +1247,89 @@ function morpho() {
1203
1247
  return { message: "Expiry mismatch" };
1204
1248
  }
1205
1249
  });
1206
- const callback = single("empty_callback", (offer, _) => {
1207
- if (!offer.buy || offer.callback.data !== "0x") {
1208
- return { message: "Callback not supported yet." };
1250
+ const sellEmptyCallback = single(
1251
+ "sell_offers_empty_callback",
1252
+ (offer, _) => {
1253
+ if (!offer.buy && offer.callback.data === "0x") {
1254
+ return { message: "Sell offers require a non-empty callback." };
1255
+ }
1209
1256
  }
1210
- });
1257
+ );
1258
+ const buyNonEmptyCallback = single(
1259
+ "buy_offers_non_empty_callback",
1260
+ (offer, _) => {
1261
+ if (offer.buy && offer.callback.data !== "0x") {
1262
+ return { message: "Buy offers must use an empty callback." };
1263
+ }
1264
+ }
1265
+ );
1266
+ const sellNonWhitelistedCallback = single(
1267
+ "sell_offers_non_whitelisted_callback",
1268
+ (offer, _) => {
1269
+ if (!offer.buy && offer.callback.data !== "0x") {
1270
+ const allowed = new Set(
1271
+ WhitelistedCallbackAddresses["sell_withdraw_from_wallet" /* SellWithdrawFromWallet */].map(
1272
+ (a) => a.toLowerCase()
1273
+ )
1274
+ );
1275
+ const callbackAddress = offer.callback.address?.toLowerCase();
1276
+ if (!callbackAddress || !allowed.has(callbackAddress)) {
1277
+ return { message: "Sell offer callback address is not whitelisted." };
1278
+ }
1279
+ }
1280
+ }
1281
+ );
1282
+ const sellCallbackDataInvalid = single(
1283
+ "sell_offers_callback_data_invalid",
1284
+ (offer, _) => {
1285
+ if (!offer.buy && offer.callback.data !== "0x") {
1286
+ try {
1287
+ const decoded = decode({
1288
+ type: "sell_withdraw_from_wallet" /* SellWithdrawFromWallet */,
1289
+ data: offer.callback.data
1290
+ });
1291
+ if (decoded.length === 0) {
1292
+ return { message: "Sell offer callback data must include at least one collateral." };
1293
+ }
1294
+ } catch (_2) {
1295
+ return { message: "Sell offer callback data cannot be decoded." };
1296
+ }
1297
+ }
1298
+ }
1299
+ );
1300
+ const sellCallbackCollateralInvalid = single(
1301
+ "sell_offers_callback_collateral_invalid",
1302
+ (offer, _) => {
1303
+ if (!offer.buy && offer.callback.data !== "0x") {
1304
+ try {
1305
+ const decoded = decode({
1306
+ type: "sell_withdraw_from_wallet" /* SellWithdrawFromWallet */,
1307
+ data: offer.callback.data
1308
+ });
1309
+ const offerCollaterals = new Set(
1310
+ offer.collaterals.map((c) => c.asset.toLowerCase())
1311
+ );
1312
+ for (const { collateral } of decoded) {
1313
+ if (!offerCollaterals.has(collateral.toLowerCase())) {
1314
+ return { message: "Sell callback collateral is not part of offer collaterals." };
1315
+ }
1316
+ }
1317
+ } catch (_2) {
1318
+ }
1319
+ }
1320
+ }
1321
+ );
1211
1322
  return [
1212
1323
  chainId,
1213
1324
  loanToken,
1214
1325
  expiry,
1215
- // note: callback rule should be the last one, since it does not mean that the offer is forever invalid
1326
+ // note: callback rules should be the last ones, since they do not mean that the offer is forever invalid
1216
1327
  // integrators should be able to choose if they want to keep the offer or not
1217
- callback
1328
+ sellEmptyCallback,
1329
+ buyNonEmptyCallback,
1330
+ sellNonWhitelistedCallback,
1331
+ sellCallbackDataInvalid,
1332
+ sellCallbackCollateralInvalid
1218
1333
  ];
1219
1334
  }
1220
1335