@continuumdao/ctm-mpc-defi 0.2.26 → 0.2.28

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.
Files changed (38) hide show
  1. package/dist/agent/catalog.cjs +681 -46
  2. package/dist/agent/catalog.cjs.map +1 -1
  3. package/dist/agent/catalog.d.ts +1209 -21
  4. package/dist/agent/catalog.js +668 -47
  5. package/dist/agent/catalog.js.map +1 -1
  6. package/dist/agent/skills/morpho/SKILL.md +38 -6
  7. package/dist/agent/skills/uniswap-v4/SKILL.md +15 -0
  8. package/dist/core/index.cjs +19 -0
  9. package/dist/core/index.cjs.map +1 -1
  10. package/dist/core/index.d.ts +8 -1
  11. package/dist/core/index.js +17 -1
  12. package/dist/core/index.js.map +1 -1
  13. package/dist/index.cjs +363 -22
  14. package/dist/index.cjs.map +1 -1
  15. package/dist/index.d.ts +1 -1
  16. package/dist/index.js +361 -23
  17. package/dist/index.js.map +1 -1
  18. package/dist/protocols/evm/aave-v4/index.cjs.map +1 -1
  19. package/dist/protocols/evm/aave-v4/index.js.map +1 -1
  20. package/dist/protocols/evm/euler-v2/index.cjs.map +1 -1
  21. package/dist/protocols/evm/euler-v2/index.js.map +1 -1
  22. package/dist/protocols/evm/maple/index.cjs.map +1 -1
  23. package/dist/protocols/evm/maple/index.js.map +1 -1
  24. package/dist/protocols/evm/morpho/index.cjs +1153 -142
  25. package/dist/protocols/evm/morpho/index.cjs.map +1 -1
  26. package/dist/protocols/evm/morpho/index.d.ts +314 -8
  27. package/dist/protocols/evm/morpho/index.js +1131 -144
  28. package/dist/protocols/evm/morpho/index.js.map +1 -1
  29. package/dist/protocols/evm/permit2/index.cjs.map +1 -1
  30. package/dist/protocols/evm/permit2/index.js.map +1 -1
  31. package/dist/protocols/evm/sky/index.cjs.map +1 -1
  32. package/dist/protocols/evm/sky/index.js.map +1 -1
  33. package/dist/protocols/evm/uniswap-v4/index.cjs +863 -25
  34. package/dist/protocols/evm/uniswap-v4/index.cjs.map +1 -1
  35. package/dist/protocols/evm/uniswap-v4/index.d.ts +266 -9
  36. package/dist/protocols/evm/uniswap-v4/index.js +834 -27
  37. package/dist/protocols/evm/uniswap-v4/index.js.map +1 -1
  38. package/package.json +2 -1
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { C as ChainCategory, a as ChainSupportContext, E as EvmTokenKind, K as KeyGenSubset, b as KeyGenSubsetForPermit, M as MultisignBuildResult, c as MultisignCommonArgs, N as NearTokenKind, P as ParamDoc, d as ProtocolActionDescriptor, e as ProtocolModule, S as SolanaTokenKind, T as TokenRef } from './types-PZrvtjv8.js';
2
2
  export { getClientIdFromKeyGenResult as firstClientIdFromKeyGen } from '@continuumdao/continuum-node-sdk';
3
- export { BuildPayloadSignEd25519MultisignBodyArgs, DEFAULT_DEFI_MULTISIGN_EXPIRY_SECONDS, DEFI_PROTOCOLS_WITH_30MIN_EXPIRY, PAYLOAD_SIGN_ED25519_REQUEST_KIND, PayloadSignEd25519Delivery, buildPayloadSignEd25519MultisignBody, defiMultisignExpiryUnixSeconds, getAaveGraphqlProxyUrl, getCoingeckoProxyUrl, getEulerGraphqlProxyUrl, getMapleGraphqlProxyUrl, getMorphoGraphqlProxyUrl, mergePurposeText, postJsonViaOptionalProxy, setAaveGraphqlProxyUrl, setCoingeckoProxyUrl, setEulerGraphqlProxyUrl, setMapleGraphqlProxyUrl, setMorphoGraphqlProxyUrl } from './core/index.js';
3
+ export { BuildPayloadSignEd25519MultisignBodyArgs, DEFAULT_DEFI_MULTISIGN_EXPIRY_SECONDS, DEFI_PROTOCOLS_WITH_30MIN_EXPIRY, PAYLOAD_SIGN_ED25519_REQUEST_KIND, PayloadSignEd25519Delivery, buildPayloadSignEd25519MultisignBody, defiMultisignExpiryUnixSeconds, getAaveGraphqlProxyUrl, getCoingeckoProxyUrl, getEulerGraphqlProxyUrl, getJsonViaOptionalProxy, getMapleGraphqlProxyUrl, getMorphoGraphqlProxyUrl, getMorphoMidnightRestProxyUrl, mergePurposeText, postJsonViaOptionalProxy, setAaveGraphqlProxyUrl, setCoingeckoProxyUrl, setEulerGraphqlProxyUrl, setMapleGraphqlProxyUrl, setMorphoGraphqlProxyUrl, setMorphoMidnightRestProxyUrl } from './core/index.js';
4
4
  export { C as ChainCategoryBuildInput, a as ChainCategoryModule, M as MultisignLeg, c as coreChainCategoryModule, f as finalizeMultisign } from './envelope-C_bfuKab.js';
5
5
  export { g as getActionsByChainCategory, a as getProtocolModule, b as getProtocolModules, r as registerProtocolModule } from './registry-DxDSPQ-p.js';
6
6
  export { B as BuildEip712MultisignBodyArgs, E as EIP712_SIGN_REQUEST_KIND, a as Eip712MultisignDelivery, b as Eip712TypedDataField, c as Eip712TypedDataPayload, d as buildEip712MultisignBody } from './eip712Multisign-xhXpUYp3.js';
package/dist/index.js CHANGED
@@ -120,6 +120,13 @@ function setMorphoGraphqlProxyUrl(url) {
120
120
  function getMorphoGraphqlProxyUrl() {
121
121
  return morphoGraphqlProxyUrl;
122
122
  }
123
+ var morphoMidnightRestProxyUrl;
124
+ function setMorphoMidnightRestProxyUrl(url) {
125
+ morphoMidnightRestProxyUrl = url?.trim() || void 0;
126
+ }
127
+ function getMorphoMidnightRestProxyUrl() {
128
+ return morphoMidnightRestProxyUrl;
129
+ }
123
130
  function setCoingeckoProxyUrl(url) {
124
131
  coingeckoProxyUrl = url?.trim() || void 0;
125
132
  }
@@ -151,6 +158,15 @@ async function postJsonViaOptionalProxy(args) {
151
158
  }
152
159
  return await r.json();
153
160
  }
161
+ async function getJsonViaOptionalProxy(args) {
162
+ const url = args.proxyUrl?.trim() || args.directUrl;
163
+ const r = await fetch(url, { method: "GET", headers: { accept: "application/json" } });
164
+ if (!r.ok) {
165
+ const t = await r.text().catch(() => "");
166
+ throw new Error(t ? `HTTP ${r.status}: ${t.slice(0, 200)}` : `HTTP ${r.status}`);
167
+ }
168
+ return await r.json();
169
+ }
154
170
  var EIP712_SIGN_REQUEST_KIND = "eip712";
155
171
  function msgHashNo0x(digest) {
156
172
  return digest.startsWith("0x") ? digest.slice(2) : digest;
@@ -672,11 +688,23 @@ var UNIVERSAL_ROUTER_SPENDER = {
672
688
  /** Robinhood Chain mainnet — Universal Router v2.1.1 (Trade API / interface) */
673
689
  4663: "0x8876789976decbfcbbbe364623c63652db8c0904"
674
690
  };
691
+ var UNIVERSAL_ROUTER_V2_2_SPENDER = {
692
+ 1: "0xCb640A86855f1A828c27241bA364348de28abe66",
693
+ 11155111: "0xB0C89059d7190EDb17eFF19829cc009cEe923916"
694
+ };
675
695
  var UNIVERSAL_ROUTER_VERSION_BY_CHAIN = {
676
696
  /** Robinhood has UR 2.1.1 only in the supported-chains table (no 2.0 Trade API column). */
677
697
  4663: "2.1.1"
678
698
  };
679
- function getUniswapUniversalRouterVersion(chainId) {
699
+ var UNISWAP_UNIVERSAL_ROUTER_VERSION_DEFAULT = "2.0";
700
+ var UNISWAP_UNIVERSAL_ROUTER_VERSION_PERMISSIONED = "2.2.0";
701
+ function getUniswapUniversalRouterVersion(chainId, opts) {
702
+ if (opts?.permissioned) {
703
+ const v22 = UNIVERSAL_ROUTER_V2_2_SPENDER[chainId];
704
+ if (typeof v22 === "string" && v22.startsWith("0x")) {
705
+ return UNISWAP_UNIVERSAL_ROUTER_VERSION_PERMISSIONED;
706
+ }
707
+ }
680
708
  const v = UNIVERSAL_ROUTER_VERSION_BY_CHAIN[chainId];
681
709
  return typeof v === "string" && v.trim() ? v.trim() : UNISWAP_UNIVERSAL_ROUTER_VERSION_DEFAULT;
682
710
  }
@@ -687,7 +715,11 @@ function isUniswapV4ChainSupported(chainId) {
687
715
  const a = UNIVERSAL_ROUTER_SPENDER[n];
688
716
  return typeof a === "string" && a.startsWith("0x");
689
717
  }
690
- function getUniswapUniversalRouterSpenderOrThrow(chainId) {
718
+ function getUniswapUniversalRouterSpenderOrThrow(chainId, opts) {
719
+ if (opts?.permissioned) {
720
+ const raw22 = UNIVERSAL_ROUTER_V2_2_SPENDER[chainId];
721
+ if (raw22 && raw22.startsWith("0x")) return getAddress(raw22);
722
+ }
691
723
  const raw = UNIVERSAL_ROUTER_SPENDER[chainId];
692
724
  if (!raw || !raw.startsWith("0x")) {
693
725
  throw new Error(
@@ -700,7 +732,6 @@ var MAX_UINT160 = (1n << 160n) - 1n;
700
732
  var MAX_UINT48 = (1n << 48n) - 1n;
701
733
  var UNISWAP_UNIVERSAL_ROUTER_DEFAULT_GAS_UNITS = 1500000n;
702
734
  var UNISWAP_TRADE_BASE_DEFAULT = "https://trade-api.gateway.uniswap.org/v1";
703
- var UNISWAP_UNIVERSAL_ROUTER_VERSION_DEFAULT = "2.0";
704
735
  var UNISWAP_SWAP_DEFAULT_EXPIRY_MINUTES = 30;
705
736
  var UNISWAP_LP_DEFAULT_EXPIRY_MINUTES = 30;
706
737
  var UNISWAP_LP_DEFAULT_DEADLINE_SEC_OFFSET = UNISWAP_LP_DEFAULT_EXPIRY_MINUTES * 60;
@@ -718,6 +749,10 @@ var POSITION_MANAGER_BY_CHAIN = {
718
749
  /** Robinhood Chain mainnet */
719
750
  4663: "0x58daec3116aae6D93017bAAea7749052E8a04fA7"
720
751
  };
752
+ var PERMISSIONED_POSITION_MANAGER_BY_CHAIN = {
753
+ 1: "0x89628C9B4CE81951a9BC1F36F0688Fad6A6ee248",
754
+ 11155111: "0x68fC145BB20b388965bED184Df5ef912215bb3C7"
755
+ };
721
756
  function getUniswapV4PositionManagerOrThrow(chainId) {
722
757
  const raw = POSITION_MANAGER_BY_CHAIN[chainId];
723
758
  if (!raw || !raw.startsWith("0x") || raw.length !== 42) {
@@ -727,6 +762,32 @@ function getUniswapV4PositionManagerOrThrow(chainId) {
727
762
  }
728
763
  return getAddress(raw);
729
764
  }
765
+ function getUniswapV4PermissionedPositionManagerOrThrow(chainId) {
766
+ const raw = PERMISSIONED_POSITION_MANAGER_BY_CHAIN[chainId];
767
+ if (!raw || !raw.startsWith("0x") || raw.length !== 42) {
768
+ throw new Error(
769
+ `No Uniswap V4 Permissioned PositionManager is configured for chainId ${chainId}.`
770
+ );
771
+ }
772
+ return getAddress(raw);
773
+ }
774
+ function tryGetUniswapV4PermissionedPositionManager(chainId) {
775
+ try {
776
+ return getUniswapV4PermissionedPositionManagerOrThrow(chainId);
777
+ } catch {
778
+ return null;
779
+ }
780
+ }
781
+ function isUniswapV4PermissionedPositionManager(chainId, address) {
782
+ if (!address?.toString().trim()) return false;
783
+ const perm = tryGetUniswapV4PermissionedPositionManager(chainId);
784
+ if (!perm) return false;
785
+ try {
786
+ return getAddress(address) === perm;
787
+ } catch {
788
+ return false;
789
+ }
790
+ }
730
791
  var POSITION_MANAGER_DEPLOY_BLOCK_BY_CHAIN = {
731
792
  /** Ethereum mainnet — Uniswap v4 launch (Jan 2025). */
732
793
  1: 22938741n
@@ -742,6 +803,152 @@ var UNISWAP_V4_LP_DECREASE_DEFAULT_GAS_UNITS = 1200000n;
742
803
  var UNISWAP_V4_LP_COLLECT_DEFAULT_GAS_UNITS = 900000n;
743
804
  var UNISWAP_V4_LP_ERC20_APPROVE_FALLBACK = 100000n;
744
805
  var UNISWAP_V4_LP_WETH_DEPOSIT_FALLBACK = 120000n;
806
+ var UNISWAP_V4_LP_PERMIT2_APPROVE_FALLBACK = 100000n;
807
+ parseAbi([
808
+ "function isAllowed(address account, uint8 permission) view returns (bool)",
809
+ "function PERMISSIONED_TOKEN() view returns (address)"
810
+ ]);
811
+ parseAbi([
812
+ "function verifiedPermissionsAdapterOf(address permissionsAdapter) view returns (address)"
813
+ ]);
814
+ function normalizeTokenList(tokens) {
815
+ const out = [];
816
+ const seen = /* @__PURE__ */ new Set();
817
+ for (const raw of tokens) {
818
+ const t = (raw ?? "").toString().trim();
819
+ if (!t) continue;
820
+ if (isUniswapNativeTokenAddress(t)) continue;
821
+ let addr;
822
+ try {
823
+ addr = getAddress(t);
824
+ } catch {
825
+ continue;
826
+ }
827
+ if (addr === zeroAddress) continue;
828
+ const key = addr.toLowerCase();
829
+ if (seen.has(key)) continue;
830
+ seen.add(key);
831
+ out.push(addr);
832
+ if (out.length >= 2) break;
833
+ }
834
+ return out;
835
+ }
836
+ function parsePermissionRow(raw) {
837
+ const tokenRaw = (raw.token ?? raw.address ?? "").toString().trim();
838
+ if (!tokenRaw) return null;
839
+ let token;
840
+ try {
841
+ token = getAddress(tokenRaw);
842
+ } catch {
843
+ return null;
844
+ }
845
+ const isPermissioned = Boolean(raw.isPermissioned);
846
+ const isAllowlisted = isPermissioned ? Boolean(raw.isAllowlisted) : true;
847
+ let adapterTokenAddress;
848
+ const adapterRaw = (raw.adapterTokenAddress ?? "").toString().trim();
849
+ if (adapterRaw) {
850
+ try {
851
+ adapterTokenAddress = getAddress(adapterRaw);
852
+ } catch {
853
+ }
854
+ }
855
+ const kycUrl = typeof raw.kycUrl === "string" && raw.kycUrl.trim() ? raw.kycUrl.trim() : void 0;
856
+ const issuer = typeof raw.issuer === "string" && raw.issuer.trim() ? raw.issuer.trim() : void 0;
857
+ return { token, isPermissioned, isAllowlisted, adapterTokenAddress, kycUrl, issuer };
858
+ }
859
+ async function uniswapV4CheckPermissions(args) {
860
+ const apiKey = args.uniswapApiKey?.trim();
861
+ if (!apiKey) throw new Error("uniswapApiKey is required for POST /v1/permissions");
862
+ const walletAddress = getAddress(args.walletAddress.trim());
863
+ const chainId = parseUniswapChainId(args.chainId);
864
+ const tokens = normalizeTokenList(args.tokens);
865
+ if (tokens.length === 0) {
866
+ return {
867
+ results: [],
868
+ anyPermissioned: false,
869
+ allAllowlisted: true,
870
+ requiresUniversalRouterV22: false
871
+ };
872
+ }
873
+ const base = (args.baseUrl?.trim() || UNISWAP_TRADE_BASE_DEFAULT).replace(/\/$/, "");
874
+ const url = `${base}/permissions`;
875
+ const fetchFn = args.fetchImpl ?? globalThis.fetch;
876
+ const res = await fetchFn(url, {
877
+ method: "POST",
878
+ headers: {
879
+ "Content-Type": "application/json",
880
+ "User-Agent": "ctm-mpc-defi uniswapPermissions/1.0 (TS)",
881
+ "x-api-key": apiKey
882
+ },
883
+ body: JSON.stringify({
884
+ walletAddress,
885
+ tokens,
886
+ chainId
887
+ }),
888
+ signal: args.signal
889
+ });
890
+ const text = await res.text();
891
+ if (!res.ok) {
892
+ throw new Error(
893
+ `Uniswap POST /permissions failed: ${messageFromUniswapHttpResponseBody(text, res.status, res.statusText)}`
894
+ );
895
+ }
896
+ let parsed;
897
+ try {
898
+ parsed = JSON.parse(text.replace(/^\uFEFF/, ""));
899
+ } catch {
900
+ throw new Error(
901
+ `Uniswap POST /permissions: ${messageFromUniswapHttpResponseBody(text, res.status, res.statusText)}`
902
+ );
903
+ }
904
+ const rawResults = Array.isArray(parsed.results) ? parsed.results : [];
905
+ const results = [];
906
+ for (const row of rawResults) {
907
+ if (!row || typeof row !== "object" || Array.isArray(row)) continue;
908
+ const parsedRow = parsePermissionRow(row);
909
+ if (parsedRow) results.push(parsedRow);
910
+ }
911
+ for (const token of tokens) {
912
+ if (!results.some((r) => r.token === token)) {
913
+ results.push({ token, isPermissioned: false, isAllowlisted: true });
914
+ }
915
+ }
916
+ const anyPermissioned = results.some((r) => r.isPermissioned);
917
+ const allAllowlisted = results.every((r) => !r.isPermissioned || r.isAllowlisted);
918
+ return {
919
+ requestId: typeof parsed.requestId === "string" ? parsed.requestId : void 0,
920
+ results,
921
+ anyPermissioned,
922
+ allAllowlisted,
923
+ requiresUniversalRouterV22: anyPermissioned
924
+ };
925
+ }
926
+ var UniswapV4PermissionDeniedError = class extends Error {
927
+ code = "UNISWAP_V4_PERMISSION_DENIED";
928
+ permissions;
929
+ blocked;
930
+ constructor(permissions) {
931
+ const blocked = permissions.results.filter((r) => r.isPermissioned && !r.isAllowlisted);
932
+ const issuer = blocked.find((b) => b.issuer)?.issuer;
933
+ const kycUrl = blocked.find((b) => b.kycUrl)?.kycUrl;
934
+ const parts = [
935
+ "Wallet is not allowlisted for one or more permissioned Uniswap V4 tokens.",
936
+ issuer ? `Issuer: ${issuer}.` : null,
937
+ kycUrl ? `Complete KYC at: ${kycUrl}` : "Open the issuer KYC URL from check_permissions."
938
+ ].filter(Boolean);
939
+ super(parts.join(" "));
940
+ this.name = "UniswapV4PermissionDeniedError";
941
+ this.permissions = permissions;
942
+ this.blocked = blocked;
943
+ }
944
+ };
945
+ function assertUniswapV4PermissionsAllowlisted(permissions) {
946
+ if (!permissions.allAllowlisted) {
947
+ throw new UniswapV4PermissionDeniedError(permissions);
948
+ }
949
+ }
950
+
951
+ // src/protocols/evm/uniswap-v4/quote.ts
745
952
  var DEFAULT_TRADE_BASE = "https://trade-api.gateway.uniswap.org/v1";
746
953
  var UNISWAP_QUOTE_HEADERS_BASE = {
747
954
  "Content-Type": "application/json",
@@ -988,7 +1195,25 @@ async function uniswapTradeQuote(args) {
988
1195
  const base = args.baseUrl && args.baseUrl.trim() ? args.baseUrl.trim().replace(/\/$/, "") : DEFAULT_TRADE_BASE;
989
1196
  const quoteUrl = `${base}/quote`;
990
1197
  const chainIdForRouter = parseUniswapChainId(resolveInputChainId(args));
991
- const urv = args.universalRouterVersion && args.universalRouterVersion.trim() || getUniswapUniversalRouterVersion(chainIdForRouter);
1198
+ let permissions;
1199
+ const shouldCheckPermissions = args.forcePermissionedRouter !== true && args.skipPermissionCheck !== true && args.checkPermissions !== false;
1200
+ if (shouldCheckPermissions) {
1201
+ try {
1202
+ permissions = await uniswapV4CheckPermissions({
1203
+ walletAddress: swapper,
1204
+ tokens: [args.tokenIn, args.tokenOut],
1205
+ chainId: chainIdForRouter,
1206
+ uniswapApiKey: apiKey,
1207
+ baseUrl: base,
1208
+ signal: args.signal,
1209
+ fetchImpl: args.fetchImpl
1210
+ });
1211
+ } catch {
1212
+ permissions = void 0;
1213
+ }
1214
+ }
1215
+ const permissionedRouter = args.forcePermissionedRouter === true || Boolean(permissions?.requiresUniversalRouterV22);
1216
+ const urv = args.universalRouterVersion && args.universalRouterVersion.trim() || getUniswapUniversalRouterVersion(chainIdForRouter, { permissioned: permissionedRouter });
992
1217
  const body = buildUniswapQuoteRequestBody({ ...args, swapper });
993
1218
  const nativeIn = isUniswapNativeTokenAddress(args.tokenIn);
994
1219
  const nativeOut = isUniswapNativeTokenAddress(args.tokenOut);
@@ -1017,13 +1242,27 @@ async function uniswapTradeQuote(args) {
1017
1242
  }
1018
1243
  const forParse = text.replace(/^\uFEFF/, "");
1019
1244
  try {
1020
- return JSON.parse(forParse);
1245
+ const parsed = JSON.parse(forParse);
1246
+ if (permissionedRouter || urv === UNISWAP_UNIVERSAL_ROUTER_VERSION_PERMISSIONED) {
1247
+ parsed._continuumPermissioned = true;
1248
+ parsed._continuumUniversalRouterVersion = urv;
1249
+ }
1250
+ if (permissions) {
1251
+ parsed._continuumPermissions = permissions;
1252
+ }
1253
+ return parsed;
1021
1254
  } catch {
1022
1255
  throw new Error(
1023
1256
  `Trade API: ${messageFromUniswapHttpResponseBody(text, res.status, res.statusText)}`
1024
1257
  );
1025
1258
  }
1026
1259
  }
1260
+ function isUniswapStoredQuotePermissioned(stored) {
1261
+ if (!stored) return false;
1262
+ if (stored._continuumPermissioned === true) return true;
1263
+ const v = stored._continuumUniversalRouterVersion;
1264
+ return typeof v === "string" && v.trim() === UNISWAP_UNIVERSAL_ROUTER_VERSION_PERMISSIONED;
1265
+ }
1027
1266
  function parseUniswapQuoteClassicInOut(res) {
1028
1267
  const inner = res.quote;
1029
1268
  if (!inner || typeof inner !== "object" || Array.isArray(inner)) return null;
@@ -1120,7 +1359,9 @@ async function uniswapCreateSwap(args) {
1120
1359
  quote: classic,
1121
1360
  deadline
1122
1361
  };
1123
- const urv = (args.universalRouterVersion ?? "").trim() || getUniswapUniversalRouterVersion(resolveChainIdFromStoredUniswapQuote(args.fullQuoteFromPermit));
1362
+ const chainIdForRouter = resolveChainIdFromStoredUniswapQuote(args.fullQuoteFromPermit);
1363
+ const permissioned = isUniswapStoredQuotePermissioned(args.fullQuoteFromPermit);
1364
+ const urv = (args.universalRouterVersion ?? "").trim() || getUniswapUniversalRouterVersion(chainIdForRouter, { permissioned });
1124
1365
  const fn = args.fetchImpl ?? globalThis.fetch;
1125
1366
  const nativeIn = isUniswapFullQuoteResponseNativeIn(args.fullQuoteFromPermit);
1126
1367
  const nativeOut = isUniswapFullQuoteResponseNativeOut(args.fullQuoteFromPermit);
@@ -1248,8 +1489,8 @@ function applySlippagePercentToApproveWei(baseWei, slippagePercent) {
1248
1489
  if (bps <= 0) return baseWei;
1249
1490
  return (baseWei * BigInt(1e4 + bps) + 9999n) / 10000n;
1250
1491
  }
1251
- function permit2SpenderAndApproveWeiFromSwapCalldata(dataHex, tokenIn, quoteInputWei, chainId) {
1252
- const canonical = getUniswapUniversalRouterSpenderOrThrow(chainId);
1492
+ function permit2SpenderAndApproveWeiFromSwapCalldata(dataHex, tokenIn, quoteInputWei, chainId, permissioned = false) {
1493
+ const canonical = getUniswapUniversalRouterSpenderOrThrow(chainId, { permissioned });
1253
1494
  try {
1254
1495
  const d = decodeFunctionData({ abi: uniswapDispatchExecuteAbi, data: dataHex });
1255
1496
  if (d.functionName !== "execute") {
@@ -1385,6 +1626,27 @@ async function buildEvmMultisignBodyUniswapV4SkipPermit2Batch(args) {
1385
1626
  "Could not read a positive input amount from the quote. Refresh the quote and ensure the Trade API returned classic quote.input.amount."
1386
1627
  );
1387
1628
  }
1629
+ const permissioned = isUniswapStoredQuotePermissioned(args.fullQuoteSnapshot);
1630
+ if (args.skipPermissionCheck !== true) {
1631
+ const cached = args.fullQuoteSnapshot._continuumPermissions;
1632
+ if (cached && typeof cached === "object" && cached.allAllowlisted === false) {
1633
+ assertUniswapV4PermissionsAllowlisted({
1634
+ results: cached.results ?? [],
1635
+ anyPermissioned: Boolean(cached.anyPermissioned),
1636
+ allAllowlisted: false,
1637
+ requiresUniversalRouterV22: Boolean(cached.requiresUniversalRouterV22)
1638
+ });
1639
+ } else if (args.uniswapApiKey?.trim() && (permissioned || args.tokenOut)) {
1640
+ const tokens = [args.tokenIn, args.tokenOut].filter(Boolean);
1641
+ const permissions = await uniswapV4CheckPermissions({
1642
+ walletAddress: args.executorAddress,
1643
+ tokens,
1644
+ chainId: args.chainId,
1645
+ uniswapApiKey: args.uniswapApiKey.trim()
1646
+ });
1647
+ assertUniswapV4PermissionsAllowlisted(permissions);
1648
+ }
1649
+ }
1388
1650
  if (tokenIn === zeroAddress) {
1389
1651
  return buildEvmMultisignBodyUniswapV4NativeInOnly(args, quoteInputWei);
1390
1652
  }
@@ -1395,12 +1657,15 @@ async function buildEvmMultisignBodyUniswapV4SkipPermit2Batch(args) {
1395
1657
  const d = (args.swap.data ?? "0x").toString().trim();
1396
1658
  return d.startsWith("0x") ? d : `0x${d}`;
1397
1659
  })();
1398
- const canonicalUniversalRouter = getUniswapUniversalRouterSpenderOrThrow(args.chainId);
1660
+ const canonicalUniversalRouter = getUniswapUniversalRouterSpenderOrThrow(args.chainId, {
1661
+ permissioned
1662
+ });
1399
1663
  const { permit2Spender, approveWei: baseApproveWei, calldataAmountWei } = permit2SpenderAndApproveWeiFromSwapCalldata(
1400
1664
  dataHex,
1401
1665
  tokenIn,
1402
1666
  quoteInputWei,
1403
- args.chainId
1667
+ args.chainId,
1668
+ permissioned
1404
1669
  );
1405
1670
  const approveAmountWei = applySlippagePercentToApproveWei(baseApproveWei, args.slippagePercent);
1406
1671
  const usePermit2Triple = toRouter.toLowerCase() === permit2Spender.toLowerCase();
@@ -2068,6 +2333,9 @@ var erc20AllowanceAbi2 = parseAbi([
2068
2333
  "function allowance(address owner, address spender) view returns (uint256)",
2069
2334
  "function decimals() view returns (uint8)"
2070
2335
  ]);
2336
+ var permit2ApproveAbi = parseAbi([
2337
+ "function approve(address token, address spender, uint160 amount, uint48 expiration)"
2338
+ ]);
2071
2339
  function parseOptionalGasLimitString2(raw) {
2072
2340
  if (raw == null) return null;
2073
2341
  const s = String(raw).trim();
@@ -2155,7 +2423,9 @@ async function buildEvmMultisignBodyUniswapV4LiquidityBatchInternal(args) {
2155
2423
  const dataHex = dataHexFromTx(tx);
2156
2424
  const valueWei = parseTxValueWei(tx);
2157
2425
  const executor = getAddress(args.executorAddress);
2158
- const spender = to;
2426
+ const positionManagerKind = args.positionManagerKind === "permissioned" || args.positionManagerKind === "standard" ? args.positionManagerKind : isUniswapV4PermissionedPositionManager(args.chainId, to) ? "permissioned" : "standard";
2427
+ const usePermit2 = args.usePermit2Approvals === true || args.usePermit2Approvals !== false && positionManagerKind === "permissioned";
2428
+ const erc20Spender = usePermit2 ? PERMIT2_ADDRESS : to;
2159
2429
  const chain = defineChain({
2160
2430
  id: args.chainId,
2161
2431
  name: `uniswap-v4-lp-${args.chainId}`,
@@ -2163,15 +2433,21 @@ async function buildEvmMultisignBodyUniswapV4LiquidityBatchInternal(args) {
2163
2433
  rpcUrls: { default: { http: [args.rpcUrl] } }
2164
2434
  });
2165
2435
  const publicClient = createPublicClient({ chain, transport: http(args.rpcUrl) });
2166
- const approveTargets = await resolveApproveTargets({
2436
+ const needsTokenApproves = args.action === "mint" || args.action === "increase";
2437
+ const approveTargets = needsTokenApproves ? await resolveApproveTargets({
2167
2438
  publicClient,
2168
2439
  executor,
2169
- spender,
2440
+ spender: erc20Spender,
2170
2441
  token0: parsed.token0,
2171
2442
  token1: parsed.token1,
2172
2443
  nativeWrapped: args.nativeWrapped
2173
- });
2444
+ }) : [];
2174
2445
  const steps = [];
2446
+ let permit2Expiration48 = 0n;
2447
+ if (usePermit2 && needsTokenApproves) {
2448
+ permit2Expiration48 = BigInt(Math.floor(Date.now() / 1e3) + UNISWAP_LP_DEFAULT_DEADLINE_SEC_OFFSET);
2449
+ if (permit2Expiration48 > MAX_UINT48) permit2Expiration48 = MAX_UINT48;
2450
+ }
2175
2451
  for (const target of approveTargets) {
2176
2452
  if (target.kind === "weth_deposit") {
2177
2453
  steps.push({
@@ -2184,13 +2460,17 @@ async function buildEvmMultisignBodyUniswapV4LiquidityBatchInternal(args) {
2184
2460
  address: target.token,
2185
2461
  abi: erc20AllowanceAbi2,
2186
2462
  functionName: "allowance",
2187
- args: [executor, spender]
2463
+ args: [executor, erc20Spender]
2188
2464
  });
2189
2465
  if (wethAllowance < target.amount) {
2190
- if (wethAllowance > 0n) {
2466
+ if (wethAllowance > 0n && !usePermit2) {
2191
2467
  steps.push({
2192
2468
  to: target.token,
2193
- data: encodeFunctionData({ abi: erc20Abi, functionName: "approve", args: [spender, 0n] }),
2469
+ data: encodeFunctionData({
2470
+ abi: erc20Abi,
2471
+ functionName: "approve",
2472
+ args: [erc20Spender, 0n]
2473
+ }),
2194
2474
  value: 0n,
2195
2475
  fallbackGas: UNISWAP_V4_LP_ERC20_APPROVE_FALLBACK
2196
2476
  });
@@ -2200,7 +2480,7 @@ async function buildEvmMultisignBodyUniswapV4LiquidityBatchInternal(args) {
2200
2480
  data: encodeFunctionData({
2201
2481
  abi: erc20Abi,
2202
2482
  functionName: "approve",
2203
- args: [spender, target.amount]
2483
+ args: [erc20Spender, target.amount]
2204
2484
  }),
2205
2485
  value: 0n,
2206
2486
  fallbackGas: UNISWAP_V4_LP_ERC20_APPROVE_FALLBACK
@@ -2212,13 +2492,66 @@ async function buildEvmMultisignBodyUniswapV4LiquidityBatchInternal(args) {
2212
2492
  data: encodeFunctionData({
2213
2493
  abi: erc20Abi,
2214
2494
  functionName: "approve",
2215
- args: [spender, target.amount]
2495
+ args: [erc20Spender, target.amount]
2216
2496
  }),
2217
2497
  value: 0n,
2218
2498
  fallbackGas: UNISWAP_V4_LP_ERC20_APPROVE_FALLBACK
2219
2499
  });
2220
2500
  }
2221
2501
  }
2502
+ if (usePermit2 && needsTokenApproves) {
2503
+ const pairs = [parsed.token0, parsed.token1].filter(Boolean);
2504
+ for (const row of pairs) {
2505
+ const amt = BigInt(row.amount);
2506
+ if (amt <= 0n) continue;
2507
+ let token;
2508
+ if (isNativeUniswapLpTokenAddress(row.tokenAddress)) {
2509
+ if (!args.nativeWrapped) {
2510
+ throw new Error("nativeWrapped is required when LP uses native ETH (0x0) token.");
2511
+ }
2512
+ token = getAddress(args.nativeWrapped);
2513
+ if (!approveTargets.some((a) => a.token === token && a.kind === "weth_deposit")) {
2514
+ steps.push({
2515
+ to: token,
2516
+ data: encodeFunctionData({ abi: wethDepositAbi, functionName: "deposit" }),
2517
+ value: amt,
2518
+ fallbackGas: UNISWAP_V4_LP_WETH_DEPOSIT_FALLBACK
2519
+ });
2520
+ const wethAllowance = await publicClient.readContract({
2521
+ address: token,
2522
+ abi: erc20AllowanceAbi2,
2523
+ functionName: "allowance",
2524
+ args: [executor, PERMIT2_ADDRESS]
2525
+ });
2526
+ if (wethAllowance < amt) {
2527
+ steps.push({
2528
+ to: token,
2529
+ data: encodeFunctionData({
2530
+ abi: erc20Abi,
2531
+ functionName: "approve",
2532
+ args: [PERMIT2_ADDRESS, amt]
2533
+ }),
2534
+ value: 0n,
2535
+ fallbackGas: UNISWAP_V4_LP_ERC20_APPROVE_FALLBACK
2536
+ });
2537
+ }
2538
+ }
2539
+ } else {
2540
+ token = getAddress(row.tokenAddress);
2541
+ }
2542
+ const amount160 = amt > MAX_UINT160 ? MAX_UINT160 : amt;
2543
+ steps.push({
2544
+ to: PERMIT2_ADDRESS,
2545
+ data: encodeFunctionData({
2546
+ abi: permit2ApproveAbi,
2547
+ functionName: "approve",
2548
+ args: [token, to, amount160, Number(permit2Expiration48)]
2549
+ }),
2550
+ value: 0n,
2551
+ fallbackGas: UNISWAP_V4_LP_PERMIT2_APPROVE_FALLBACK
2552
+ });
2553
+ }
2554
+ }
2222
2555
  const lpFallbackGas = defaultGasForAction(args.action);
2223
2556
  const fromTradeApi = parseOptionalGasLimitString2(tx.gasLimit) ?? parseOptionalGasLimitString2(tx.gas);
2224
2557
  steps.push({
@@ -2230,6 +2563,7 @@ async function buildEvmMultisignBodyUniswapV4LiquidityBatchInternal(args) {
2230
2563
  const actionLabel = args.action === "mint" ? "mint liquidity" : args.action === "increase" ? "increase liquidity" : args.action === "decrease" ? "decrease liquidity" : "collect fees";
2231
2564
  const dataNo0x = dataHex.startsWith("0x") ? dataHex.slice(2) : dataHex;
2232
2565
  const lpIndex = steps.length - 1;
2566
+ const purposeSuffix = usePermit2 ? `Uniswap V4 permissioned: ${steps.length}-tx batch \u2014 ${actionLabel} (ERC-20\u2192Permit2, Permit2\u2192PosM, Position Manager).` : `Uniswap V4: ${steps.length}-tx batch \u2014 ${actionLabel} (classic ERC-20 approve + Position Manager).`;
2233
2567
  return buildEvmMultisignBatch({
2234
2568
  context: {
2235
2569
  chainCategory: "evm",
@@ -2243,7 +2577,7 @@ async function buildEvmMultisignBodyUniswapV4LiquidityBatchInternal(args) {
2243
2577
  customGasChainDetails: args.customGasChainDetails
2244
2578
  },
2245
2579
  steps,
2246
- purposeSuffix: `Uniswap V4: ${steps.length}-tx batch \u2014 ${actionLabel} (classic ERC-20 approve + Position Manager).`,
2580
+ purposeSuffix,
2247
2581
  firstMsgRawNo0x: dataNo0x,
2248
2582
  destinationAddress: to,
2249
2583
  buildBatchMeta: ({ index }) => {
@@ -2253,13 +2587,17 @@ async function buildEvmMultisignBodyUniswapV4LiquidityBatchInternal(args) {
2253
2587
  kind: "UniswapV4Liquidity",
2254
2588
  action: args.action,
2255
2589
  step: index,
2256
- lpTx: isLpStep
2590
+ lpTx: isLpStep,
2591
+ positionManagerKind,
2592
+ usePermit2
2257
2593
  }),
2258
2594
  ...isLpStep ? {
2259
2595
  evm: { type: "uniswap_v4_liquidity_tx", version: 1, chainId: String(args.chainId) },
2260
2596
  uniswapV4Liquidity: {
2261
2597
  action: args.action,
2262
- skipPermit2Batch: true,
2598
+ skipPermit2Batch: !usePermit2,
2599
+ usePermit2Approvals: usePermit2,
2600
+ positionManagerKind,
2263
2601
  nftTokenId: args.nftTokenId != null ? String(args.nftTokenId) : void 0,
2264
2602
  poolReference: args.poolReference,
2265
2603
  lpResponseSnapshot: args.lpResponse,
@@ -3090,6 +3428,6 @@ var curveDao = {
3090
3428
  registerProtocolModule(uniswapV4ProtocolModule);
3091
3429
  registerProtocolModule(curveDaoProtocolModule);
3092
3430
 
3093
- export { COINGECKO_PLATFORM_BY_CHAIN_ID, DEFAULT_DEFI_MULTISIGN_EXPIRY_SECONDS, DEFI_PROTOCOLS_WITH_30MIN_EXPIRY, EIP712_SIGN_REQUEST_KIND, NEAR_CHAIN_CATEGORY, PAYLOAD_SIGN_ED25519_REQUEST_KIND, SOLANA_CHAIN_CATEGORY, approveStepsToEvmTxSteps, buildConditionalErc20ApproveSteps, buildEip712MultisignBody, buildEvmMultisignBatch, buildPayloadSignEd25519MultisignBody, coingeckoPlatformForChainId, coreChainCategoryModule, curveDao, curveDaoProtocolModule, defiMultisignExpiryUnixSeconds, evmChainCategoryModule, finalizeMultisign, getAaveGraphqlProxyUrl, getActionsByChainCategory, getCoingeckoProxyUrl, getEulerGraphqlProxyUrl, getMapleGraphqlProxyUrl, getMorphoGraphqlProxyUrl, getProtocolModule, getProtocolModules, isEvmNativeToken, matchEvmTokenKind, mergePurposeText, nearChainCategoryModule, normalizeCurveRouterAmountString, normalizeHumanDecimalAmount, parseEvmChainIdToNumber, postJsonViaOptionalProxy, publicClientForRpc, registerProtocolModule, resolveErc20Decimals, routerSwapGasLimitFromEstimate, setAaveGraphqlProxyUrl, setCoingeckoProxyUrl, setEulerGraphqlProxyUrl, setMapleGraphqlProxyUrl, setMorphoGraphqlProxyUrl, solanaChainCategoryModule, uniswapV4, uniswapV4ProtocolModule };
3431
+ export { COINGECKO_PLATFORM_BY_CHAIN_ID, DEFAULT_DEFI_MULTISIGN_EXPIRY_SECONDS, DEFI_PROTOCOLS_WITH_30MIN_EXPIRY, EIP712_SIGN_REQUEST_KIND, NEAR_CHAIN_CATEGORY, PAYLOAD_SIGN_ED25519_REQUEST_KIND, SOLANA_CHAIN_CATEGORY, approveStepsToEvmTxSteps, buildConditionalErc20ApproveSteps, buildEip712MultisignBody, buildEvmMultisignBatch, buildPayloadSignEd25519MultisignBody, coingeckoPlatformForChainId, coreChainCategoryModule, curveDao, curveDaoProtocolModule, defiMultisignExpiryUnixSeconds, evmChainCategoryModule, finalizeMultisign, getAaveGraphqlProxyUrl, getActionsByChainCategory, getCoingeckoProxyUrl, getEulerGraphqlProxyUrl, getJsonViaOptionalProxy, getMapleGraphqlProxyUrl, getMorphoGraphqlProxyUrl, getMorphoMidnightRestProxyUrl, getProtocolModule, getProtocolModules, isEvmNativeToken, matchEvmTokenKind, mergePurposeText, nearChainCategoryModule, normalizeCurveRouterAmountString, normalizeHumanDecimalAmount, parseEvmChainIdToNumber, postJsonViaOptionalProxy, publicClientForRpc, registerProtocolModule, resolveErc20Decimals, routerSwapGasLimitFromEstimate, setAaveGraphqlProxyUrl, setCoingeckoProxyUrl, setEulerGraphqlProxyUrl, setMapleGraphqlProxyUrl, setMorphoGraphqlProxyUrl, setMorphoMidnightRestProxyUrl, solanaChainCategoryModule, uniswapV4, uniswapV4ProtocolModule };
3094
3432
  //# sourceMappingURL=index.js.map
3095
3433
  //# sourceMappingURL=index.js.map