@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
@@ -72,11 +72,23 @@ var UNIVERSAL_ROUTER_SPENDER = {
72
72
  /** Robinhood Chain mainnet — Universal Router v2.1.1 (Trade API / interface) */
73
73
  4663: "0x8876789976decbfcbbbe364623c63652db8c0904"
74
74
  };
75
+ var UNIVERSAL_ROUTER_V2_2_SPENDER = {
76
+ 1: "0xCb640A86855f1A828c27241bA364348de28abe66",
77
+ 11155111: "0xB0C89059d7190EDb17eFF19829cc009cEe923916"
78
+ };
75
79
  var UNIVERSAL_ROUTER_VERSION_BY_CHAIN = {
76
80
  /** Robinhood has UR 2.1.1 only in the supported-chains table (no 2.0 Trade API column). */
77
81
  4663: "2.1.1"
78
82
  };
79
- function getUniswapUniversalRouterVersion(chainId) {
83
+ var UNISWAP_UNIVERSAL_ROUTER_VERSION_DEFAULT = "2.0";
84
+ var UNISWAP_UNIVERSAL_ROUTER_VERSION_PERMISSIONED = "2.2.0";
85
+ function getUniswapUniversalRouterVersion(chainId, opts) {
86
+ if (opts?.permissioned) {
87
+ const v22 = UNIVERSAL_ROUTER_V2_2_SPENDER[chainId];
88
+ if (typeof v22 === "string" && v22.startsWith("0x")) {
89
+ return UNISWAP_UNIVERSAL_ROUTER_VERSION_PERMISSIONED;
90
+ }
91
+ }
80
92
  const v = UNIVERSAL_ROUTER_VERSION_BY_CHAIN[chainId];
81
93
  return typeof v === "string" && v.trim() ? v.trim() : UNISWAP_UNIVERSAL_ROUTER_VERSION_DEFAULT;
82
94
  }
@@ -87,7 +99,11 @@ function isUniswapV4ChainSupported(chainId) {
87
99
  const a = UNIVERSAL_ROUTER_SPENDER[n];
88
100
  return typeof a === "string" && a.startsWith("0x");
89
101
  }
90
- function getUniswapUniversalRouterSpenderOrThrow(chainId) {
102
+ function getUniswapUniversalRouterSpenderOrThrow(chainId, opts) {
103
+ if (opts?.permissioned) {
104
+ const raw22 = UNIVERSAL_ROUTER_V2_2_SPENDER[chainId];
105
+ if (raw22 && raw22.startsWith("0x")) return viem.getAddress(raw22);
106
+ }
91
107
  const raw = UNIVERSAL_ROUTER_SPENDER[chainId];
92
108
  if (!raw || !raw.startsWith("0x")) {
93
109
  throw new Error(
@@ -96,12 +112,16 @@ function getUniswapUniversalRouterSpenderOrThrow(chainId) {
96
112
  }
97
113
  return viem.getAddress(raw);
98
114
  }
115
+ function tryGetUniswapUniversalRouterV22(chainId) {
116
+ const raw = UNIVERSAL_ROUTER_V2_2_SPENDER[chainId];
117
+ if (!raw || !raw.startsWith("0x")) return null;
118
+ return viem.getAddress(raw);
119
+ }
99
120
  var MAX_UINT160 = (1n << 160n) - 1n;
100
121
  var MAX_UINT48 = (1n << 48n) - 1n;
101
122
  var UNISWAP_UNIVERSAL_ROUTER_DEFAULT_GAS_UNITS = 1500000n;
102
123
  var UNISWAP_TRADE_BASE_DEFAULT = "https://trade-api.gateway.uniswap.org/v1";
103
124
  var UNISWAP_LP_API_BASE_DEFAULT = "https://api.uniswap.org";
104
- var UNISWAP_UNIVERSAL_ROUTER_VERSION_DEFAULT = "2.0";
105
125
  var UNISWAP_SWAP_DEFAULT_EXPIRY_MINUTES = 30;
106
126
  var UNISWAP_SWAP_DEFAULT_DEADLINE_SEC_OFFSET = UNISWAP_SWAP_DEFAULT_EXPIRY_MINUTES * 60;
107
127
  var UNISWAP_LP_DEFAULT_EXPIRY_MINUTES = 30;
@@ -120,6 +140,18 @@ var POSITION_MANAGER_BY_CHAIN = {
120
140
  /** Robinhood Chain mainnet */
121
141
  4663: "0x58daec3116aae6D93017bAAea7749052E8a04fA7"
122
142
  };
143
+ var PERMISSIONED_POSITION_MANAGER_BY_CHAIN = {
144
+ 1: "0x89628C9B4CE81951a9BC1F36F0688Fad6A6ee248",
145
+ 11155111: "0x68fC145BB20b388965bED184Df5ef912215bb3C7"
146
+ };
147
+ var PERMISSIONED_HOOKS_BY_CHAIN = {
148
+ 1: "0x69603ab16110Eb0bB5f5E9C8019749eE41A128C0",
149
+ 11155111: "0x8B0E8d467af81D9F5B49165e104a2fe1b98328C0"
150
+ };
151
+ var PERMISSIONS_ADAPTER_FACTORY_BY_CHAIN = {
152
+ 1: "0x38f9Ab57FBE2704EbB727cB20e33201aF0E5F961",
153
+ 11155111: "0xEe258C31574fb59660C23534E76AF6497c2e5683"
154
+ };
123
155
  var ROBINHOOD_CHAIN_ID = 4663;
124
156
  var ROBINHOOD_WETH_ADDRESS = "0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73";
125
157
  function getUniswapV4PositionManagerOrThrow(chainId) {
@@ -138,6 +170,76 @@ function tryGetUniswapV4PositionManager(chainId) {
138
170
  return null;
139
171
  }
140
172
  }
173
+ function getUniswapV4PermissionedPositionManagerOrThrow(chainId) {
174
+ const raw = PERMISSIONED_POSITION_MANAGER_BY_CHAIN[chainId];
175
+ if (!raw || !raw.startsWith("0x") || raw.length !== 42) {
176
+ throw new Error(
177
+ `No Uniswap V4 Permissioned PositionManager is configured for chainId ${chainId}.`
178
+ );
179
+ }
180
+ return viem.getAddress(raw);
181
+ }
182
+ function tryGetUniswapV4PermissionedPositionManager(chainId) {
183
+ try {
184
+ return getUniswapV4PermissionedPositionManagerOrThrow(chainId);
185
+ } catch {
186
+ return null;
187
+ }
188
+ }
189
+ function getUniswapV4PermissionedHooksOrThrow(chainId) {
190
+ const raw = PERMISSIONED_HOOKS_BY_CHAIN[chainId];
191
+ if (!raw || !raw.startsWith("0x") || raw.length !== 42) {
192
+ throw new Error(`No Uniswap V4 PermissionedHooks is configured for chainId ${chainId}.`);
193
+ }
194
+ return viem.getAddress(raw);
195
+ }
196
+ function tryGetUniswapV4PermissionedHooks(chainId) {
197
+ try {
198
+ return getUniswapV4PermissionedHooksOrThrow(chainId);
199
+ } catch {
200
+ return null;
201
+ }
202
+ }
203
+ function getUniswapV4PermissionsAdapterFactoryOrThrow(chainId) {
204
+ const raw = PERMISSIONS_ADAPTER_FACTORY_BY_CHAIN[chainId];
205
+ if (!raw || !raw.startsWith("0x") || raw.length !== 42) {
206
+ throw new Error(
207
+ `No Uniswap V4 PermissionsAdapterFactory is configured for chainId ${chainId}.`
208
+ );
209
+ }
210
+ return viem.getAddress(raw);
211
+ }
212
+ function tryGetUniswapV4PermissionsAdapterFactory(chainId) {
213
+ try {
214
+ return getUniswapV4PermissionsAdapterFactoryOrThrow(chainId);
215
+ } catch {
216
+ return null;
217
+ }
218
+ }
219
+ function isUniswapV4PermissionedPositionManager(chainId, address) {
220
+ if (!address?.toString().trim()) return false;
221
+ const perm = tryGetUniswapV4PermissionedPositionManager(chainId);
222
+ if (!perm) return false;
223
+ try {
224
+ return viem.getAddress(address) === perm;
225
+ } catch {
226
+ return false;
227
+ }
228
+ }
229
+ function isUniswapV4AnyPositionManager(chainId, address) {
230
+ if (!address?.toString().trim()) return false;
231
+ try {
232
+ const a = viem.getAddress(address);
233
+ const std = tryGetUniswapV4PositionManager(chainId);
234
+ const perm = tryGetUniswapV4PermissionedPositionManager(chainId);
235
+ return std != null && a === std || perm != null && a === perm;
236
+ } catch {
237
+ return false;
238
+ }
239
+ }
240
+ function resolveUniswapV4PositionManager(chainId, kind = "standard") {
241
+ return kind === "permissioned" ? getUniswapV4PermissionedPositionManagerOrThrow(chainId) : getUniswapV4PositionManagerOrThrow(chainId);
242
+ }
141
243
  var POSITION_MANAGER_DEPLOY_BLOCK_BY_CHAIN = {
142
244
  /** Ethereum mainnet — Uniswap v4 launch (Jan 2025). */
143
245
  1: 22938741n
@@ -153,6 +255,231 @@ var UNISWAP_V4_LP_DECREASE_DEFAULT_GAS_UNITS = 1200000n;
153
255
  var UNISWAP_V4_LP_COLLECT_DEFAULT_GAS_UNITS = 900000n;
154
256
  var UNISWAP_V4_LP_ERC20_APPROVE_FALLBACK = 100000n;
155
257
  var UNISWAP_V4_LP_WETH_DEPOSIT_FALLBACK = 120000n;
258
+ var UNISWAP_V4_LP_PERMIT2_APPROVE_FALLBACK = 100000n;
259
+ var UNISWAP_V4_PERMISSION_FLAG_SWAP = 1;
260
+ var UNISWAP_V4_PERMISSION_FLAG_LIQUIDITY = 2;
261
+ var permissionsAdapterAbi = viem.parseAbi([
262
+ "function isAllowed(address account, uint8 permission) view returns (bool)",
263
+ "function PERMISSIONED_TOKEN() view returns (address)"
264
+ ]);
265
+ var factoryAbi = viem.parseAbi([
266
+ "function verifiedPermissionsAdapterOf(address permissionsAdapter) view returns (address)"
267
+ ]);
268
+ function normalizeTokenList(tokens) {
269
+ const out = [];
270
+ const seen = /* @__PURE__ */ new Set();
271
+ for (const raw of tokens) {
272
+ const t = (raw ?? "").toString().trim();
273
+ if (!t) continue;
274
+ if (isUniswapNativeTokenAddress(t)) continue;
275
+ let addr;
276
+ try {
277
+ addr = viem.getAddress(t);
278
+ } catch {
279
+ continue;
280
+ }
281
+ if (addr === viem.zeroAddress) continue;
282
+ const key = addr.toLowerCase();
283
+ if (seen.has(key)) continue;
284
+ seen.add(key);
285
+ out.push(addr);
286
+ if (out.length >= 2) break;
287
+ }
288
+ return out;
289
+ }
290
+ function parsePermissionRow(raw) {
291
+ const tokenRaw = (raw.token ?? raw.address ?? "").toString().trim();
292
+ if (!tokenRaw) return null;
293
+ let token;
294
+ try {
295
+ token = viem.getAddress(tokenRaw);
296
+ } catch {
297
+ return null;
298
+ }
299
+ const isPermissioned = Boolean(raw.isPermissioned);
300
+ const isAllowlisted = isPermissioned ? Boolean(raw.isAllowlisted) : true;
301
+ let adapterTokenAddress;
302
+ const adapterRaw = (raw.adapterTokenAddress ?? "").toString().trim();
303
+ if (adapterRaw) {
304
+ try {
305
+ adapterTokenAddress = viem.getAddress(adapterRaw);
306
+ } catch {
307
+ }
308
+ }
309
+ const kycUrl = typeof raw.kycUrl === "string" && raw.kycUrl.trim() ? raw.kycUrl.trim() : void 0;
310
+ const issuer = typeof raw.issuer === "string" && raw.issuer.trim() ? raw.issuer.trim() : void 0;
311
+ return { token, isPermissioned, isAllowlisted, adapterTokenAddress, kycUrl, issuer };
312
+ }
313
+ async function uniswapV4CheckPermissions(args) {
314
+ const apiKey = args.uniswapApiKey?.trim();
315
+ if (!apiKey) throw new Error("uniswapApiKey is required for POST /v1/permissions");
316
+ const walletAddress = viem.getAddress(args.walletAddress.trim());
317
+ const chainId = parseUniswapChainId(args.chainId);
318
+ const tokens = normalizeTokenList(args.tokens);
319
+ if (tokens.length === 0) {
320
+ return {
321
+ results: [],
322
+ anyPermissioned: false,
323
+ allAllowlisted: true,
324
+ requiresUniversalRouterV22: false
325
+ };
326
+ }
327
+ const base = (args.baseUrl?.trim() || UNISWAP_TRADE_BASE_DEFAULT).replace(/\/$/, "");
328
+ const url = `${base}/permissions`;
329
+ const fetchFn = args.fetchImpl ?? globalThis.fetch;
330
+ const res = await fetchFn(url, {
331
+ method: "POST",
332
+ headers: {
333
+ "Content-Type": "application/json",
334
+ "User-Agent": "ctm-mpc-defi uniswapPermissions/1.0 (TS)",
335
+ "x-api-key": apiKey
336
+ },
337
+ body: JSON.stringify({
338
+ walletAddress,
339
+ tokens,
340
+ chainId
341
+ }),
342
+ signal: args.signal
343
+ });
344
+ const text = await res.text();
345
+ if (!res.ok) {
346
+ throw new Error(
347
+ `Uniswap POST /permissions failed: ${messageFromUniswapHttpResponseBody(text, res.status, res.statusText)}`
348
+ );
349
+ }
350
+ let parsed;
351
+ try {
352
+ parsed = JSON.parse(text.replace(/^\uFEFF/, ""));
353
+ } catch {
354
+ throw new Error(
355
+ `Uniswap POST /permissions: ${messageFromUniswapHttpResponseBody(text, res.status, res.statusText)}`
356
+ );
357
+ }
358
+ const rawResults = Array.isArray(parsed.results) ? parsed.results : [];
359
+ const results = [];
360
+ for (const row of rawResults) {
361
+ if (!row || typeof row !== "object" || Array.isArray(row)) continue;
362
+ const parsedRow = parsePermissionRow(row);
363
+ if (parsedRow) results.push(parsedRow);
364
+ }
365
+ for (const token of tokens) {
366
+ if (!results.some((r) => r.token === token)) {
367
+ results.push({ token, isPermissioned: false, isAllowlisted: true });
368
+ }
369
+ }
370
+ const anyPermissioned = results.some((r) => r.isPermissioned);
371
+ const allAllowlisted = results.every((r) => !r.isPermissioned || r.isAllowlisted);
372
+ return {
373
+ requestId: typeof parsed.requestId === "string" ? parsed.requestId : void 0,
374
+ results,
375
+ anyPermissioned,
376
+ allAllowlisted,
377
+ requiresUniversalRouterV22: anyPermissioned
378
+ };
379
+ }
380
+ var UniswapV4PermissionDeniedError = class extends Error {
381
+ code = "UNISWAP_V4_PERMISSION_DENIED";
382
+ permissions;
383
+ blocked;
384
+ constructor(permissions) {
385
+ const blocked = permissions.results.filter((r) => r.isPermissioned && !r.isAllowlisted);
386
+ const issuer = blocked.find((b) => b.issuer)?.issuer;
387
+ const kycUrl = blocked.find((b) => b.kycUrl)?.kycUrl;
388
+ const parts = [
389
+ "Wallet is not allowlisted for one or more permissioned Uniswap V4 tokens.",
390
+ issuer ? `Issuer: ${issuer}.` : null,
391
+ kycUrl ? `Complete KYC at: ${kycUrl}` : "Open the issuer KYC URL from check_permissions."
392
+ ].filter(Boolean);
393
+ super(parts.join(" "));
394
+ this.name = "UniswapV4PermissionDeniedError";
395
+ this.permissions = permissions;
396
+ this.blocked = blocked;
397
+ }
398
+ };
399
+ function assertUniswapV4PermissionsAllowlisted(permissions) {
400
+ if (!permissions.allAllowlisted) {
401
+ throw new UniswapV4PermissionDeniedError(permissions);
402
+ }
403
+ }
404
+ async function readUniswapV4OnChainPermissionFlags(args) {
405
+ const factory = tryGetUniswapV4PermissionsAdapterFactory(args.chainId);
406
+ if (!factory) return [];
407
+ const client = args.publicClient ?? viem.createPublicClient({
408
+ chain: viem.defineChain({
409
+ id: args.chainId,
410
+ name: `uniswap-perm-${args.chainId}`,
411
+ nativeCurrency: { name: "ETH", symbol: "ETH", decimals: 18 },
412
+ rpcUrls: { default: { http: [args.rpcUrl] } }
413
+ }),
414
+ transport: viem.http(args.rpcUrl)
415
+ });
416
+ const wallet = viem.getAddress(args.walletAddress);
417
+ const out = [];
418
+ for (const raw of args.currencyOrAdapterAddresses) {
419
+ let address;
420
+ try {
421
+ address = viem.getAddress(raw);
422
+ } catch {
423
+ continue;
424
+ }
425
+ if (address === viem.zeroAddress) continue;
426
+ let underlying;
427
+ try {
428
+ underlying = viem.getAddress(
429
+ await client.readContract({
430
+ address: factory,
431
+ abi: factoryAbi,
432
+ functionName: "verifiedPermissionsAdapterOf",
433
+ args: [address]
434
+ })
435
+ );
436
+ } catch {
437
+ out.push({
438
+ address,
439
+ isVerifiedAdapter: false,
440
+ swapAllowed: true,
441
+ liquidityAllowed: true
442
+ });
443
+ continue;
444
+ }
445
+ if (underlying === viem.zeroAddress) {
446
+ out.push({
447
+ address,
448
+ isVerifiedAdapter: false,
449
+ swapAllowed: true,
450
+ liquidityAllowed: true
451
+ });
452
+ continue;
453
+ }
454
+ const [swapAllowed, liquidityAllowed] = await Promise.all([
455
+ client.readContract({
456
+ address,
457
+ abi: permissionsAdapterAbi,
458
+ functionName: "isAllowed",
459
+ args: [wallet, UNISWAP_V4_PERMISSION_FLAG_SWAP]
460
+ }),
461
+ client.readContract({
462
+ address,
463
+ abi: permissionsAdapterAbi,
464
+ functionName: "isAllowed",
465
+ args: [wallet, UNISWAP_V4_PERMISSION_FLAG_LIQUIDITY]
466
+ })
467
+ ]);
468
+ out.push({
469
+ address,
470
+ isVerifiedAdapter: true,
471
+ underlyingToken: underlying,
472
+ swapAllowed: Boolean(swapAllowed),
473
+ liquidityAllowed: Boolean(liquidityAllowed)
474
+ });
475
+ }
476
+ return out;
477
+ }
478
+ async function uniswapV4CheckPermissionsMcp(args) {
479
+ return uniswapV4CheckPermissions(args);
480
+ }
481
+
482
+ // src/protocols/evm/uniswap-v4/quote.ts
156
483
  var DEFAULT_TRADE_BASE = "https://trade-api.gateway.uniswap.org/v1";
157
484
  var UNISWAP_QUOTE_HEADERS_BASE = {
158
485
  "Content-Type": "application/json",
@@ -402,7 +729,25 @@ async function uniswapTradeQuote(args) {
402
729
  const base = args.baseUrl && args.baseUrl.trim() ? args.baseUrl.trim().replace(/\/$/, "") : DEFAULT_TRADE_BASE;
403
730
  const quoteUrl = `${base}/quote`;
404
731
  const chainIdForRouter = parseUniswapChainId(resolveInputChainId(args));
405
- const urv = args.universalRouterVersion && args.universalRouterVersion.trim() || getUniswapUniversalRouterVersion(chainIdForRouter);
732
+ let permissions;
733
+ const shouldCheckPermissions = args.forcePermissionedRouter !== true && args.skipPermissionCheck !== true && args.checkPermissions !== false;
734
+ if (shouldCheckPermissions) {
735
+ try {
736
+ permissions = await uniswapV4CheckPermissions({
737
+ walletAddress: swapper,
738
+ tokens: [args.tokenIn, args.tokenOut],
739
+ chainId: chainIdForRouter,
740
+ uniswapApiKey: apiKey,
741
+ baseUrl: base,
742
+ signal: args.signal,
743
+ fetchImpl: args.fetchImpl
744
+ });
745
+ } catch {
746
+ permissions = void 0;
747
+ }
748
+ }
749
+ const permissionedRouter = args.forcePermissionedRouter === true || Boolean(permissions?.requiresUniversalRouterV22);
750
+ const urv = args.universalRouterVersion && args.universalRouterVersion.trim() || getUniswapUniversalRouterVersion(chainIdForRouter, { permissioned: permissionedRouter });
406
751
  const body = buildUniswapQuoteRequestBody({ ...args, swapper });
407
752
  const nativeIn = isUniswapNativeTokenAddress(args.tokenIn);
408
753
  const nativeOut = isUniswapNativeTokenAddress(args.tokenOut);
@@ -431,13 +776,27 @@ async function uniswapTradeQuote(args) {
431
776
  }
432
777
  const forParse = text.replace(/^\uFEFF/, "");
433
778
  try {
434
- return JSON.parse(forParse);
779
+ const parsed = JSON.parse(forParse);
780
+ if (permissionedRouter || urv === UNISWAP_UNIVERSAL_ROUTER_VERSION_PERMISSIONED) {
781
+ parsed._continuumPermissioned = true;
782
+ parsed._continuumUniversalRouterVersion = urv;
783
+ }
784
+ if (permissions) {
785
+ parsed._continuumPermissions = permissions;
786
+ }
787
+ return parsed;
435
788
  } catch {
436
789
  throw new Error(
437
790
  `Trade API: ${messageFromUniswapHttpResponseBody(text, res.status, res.statusText)}`
438
791
  );
439
792
  }
440
793
  }
794
+ function isUniswapStoredQuotePermissioned(stored) {
795
+ if (!stored) return false;
796
+ if (stored._continuumPermissioned === true) return true;
797
+ const v = stored._continuumUniversalRouterVersion;
798
+ return typeof v === "string" && v.trim() === UNISWAP_UNIVERSAL_ROUTER_VERSION_PERMISSIONED;
799
+ }
441
800
  function uniswapQuoteToJsonQuoteOneLine(quote) {
442
801
  return JSON.stringify(quote);
443
802
  }
@@ -991,7 +1350,9 @@ async function uniswapCreateSwap(args) {
991
1350
  quote: classic,
992
1351
  deadline
993
1352
  };
994
- const urv = (args.universalRouterVersion ?? "").trim() || getUniswapUniversalRouterVersion(resolveChainIdFromStoredUniswapQuote(args.fullQuoteFromPermit));
1353
+ const chainIdForRouter = resolveChainIdFromStoredUniswapQuote(args.fullQuoteFromPermit);
1354
+ const permissioned = isUniswapStoredQuotePermissioned(args.fullQuoteFromPermit);
1355
+ const urv = (args.universalRouterVersion ?? "").trim() || getUniswapUniversalRouterVersion(chainIdForRouter, { permissioned });
995
1356
  const fn = args.fetchImpl ?? globalThis.fetch;
996
1357
  const nativeIn = isUniswapFullQuoteResponseNativeIn(args.fullQuoteFromPermit);
997
1358
  const nativeOut = isUniswapFullQuoteResponseNativeOut(args.fullQuoteFromPermit);
@@ -1119,8 +1480,8 @@ function applySlippagePercentToApproveWei(baseWei, slippagePercent) {
1119
1480
  if (bps <= 0) return baseWei;
1120
1481
  return (baseWei * BigInt(1e4 + bps) + 9999n) / 10000n;
1121
1482
  }
1122
- function permit2SpenderAndApproveWeiFromSwapCalldata(dataHex, tokenIn, quoteInputWei, chainId) {
1123
- const canonical = getUniswapUniversalRouterSpenderOrThrow(chainId);
1483
+ function permit2SpenderAndApproveWeiFromSwapCalldata(dataHex, tokenIn, quoteInputWei, chainId, permissioned = false) {
1484
+ const canonical = getUniswapUniversalRouterSpenderOrThrow(chainId, { permissioned });
1124
1485
  try {
1125
1486
  const d = viem.decodeFunctionData({ abi: uniswapDispatchExecuteAbi, data: dataHex });
1126
1487
  if (d.functionName !== "execute") {
@@ -1256,6 +1617,27 @@ async function buildEvmMultisignBodyUniswapV4SkipPermit2Batch(args) {
1256
1617
  "Could not read a positive input amount from the quote. Refresh the quote and ensure the Trade API returned classic quote.input.amount."
1257
1618
  );
1258
1619
  }
1620
+ const permissioned = isUniswapStoredQuotePermissioned(args.fullQuoteSnapshot);
1621
+ if (args.skipPermissionCheck !== true) {
1622
+ const cached = args.fullQuoteSnapshot._continuumPermissions;
1623
+ if (cached && typeof cached === "object" && cached.allAllowlisted === false) {
1624
+ assertUniswapV4PermissionsAllowlisted({
1625
+ results: cached.results ?? [],
1626
+ anyPermissioned: Boolean(cached.anyPermissioned),
1627
+ allAllowlisted: false,
1628
+ requiresUniversalRouterV22: Boolean(cached.requiresUniversalRouterV22)
1629
+ });
1630
+ } else if (args.uniswapApiKey?.trim() && (permissioned || args.tokenOut)) {
1631
+ const tokens = [args.tokenIn, args.tokenOut].filter(Boolean);
1632
+ const permissions = await uniswapV4CheckPermissions({
1633
+ walletAddress: args.executorAddress,
1634
+ tokens,
1635
+ chainId: args.chainId,
1636
+ uniswapApiKey: args.uniswapApiKey.trim()
1637
+ });
1638
+ assertUniswapV4PermissionsAllowlisted(permissions);
1639
+ }
1640
+ }
1259
1641
  if (tokenIn === viem.zeroAddress) {
1260
1642
  return buildEvmMultisignBodyUniswapV4NativeInOnly(args, quoteInputWei);
1261
1643
  }
@@ -1266,12 +1648,15 @@ async function buildEvmMultisignBodyUniswapV4SkipPermit2Batch(args) {
1266
1648
  const d = (args.swap.data ?? "0x").toString().trim();
1267
1649
  return d.startsWith("0x") ? d : `0x${d}`;
1268
1650
  })();
1269
- const canonicalUniversalRouter = getUniswapUniversalRouterSpenderOrThrow(args.chainId);
1651
+ const canonicalUniversalRouter = getUniswapUniversalRouterSpenderOrThrow(args.chainId, {
1652
+ permissioned
1653
+ });
1270
1654
  const { permit2Spender, approveWei: baseApproveWei, calldataAmountWei } = permit2SpenderAndApproveWeiFromSwapCalldata(
1271
1655
  dataHex,
1272
1656
  tokenIn,
1273
1657
  quoteInputWei,
1274
- args.chainId
1658
+ args.chainId,
1659
+ permissioned
1275
1660
  );
1276
1661
  const approveAmountWei = applySlippagePercentToApproveWei(baseApproveWei, args.slippagePercent);
1277
1662
  const usePermit2Triple = toRouter.toLowerCase() === permit2Spender.toLowerCase();
@@ -2321,6 +2706,9 @@ var erc20AllowanceAbi2 = viem.parseAbi([
2321
2706
  "function allowance(address owner, address spender) view returns (uint256)",
2322
2707
  "function decimals() view returns (uint8)"
2323
2708
  ]);
2709
+ var permit2ApproveAbi = viem.parseAbi([
2710
+ "function approve(address token, address spender, uint160 amount, uint48 expiration)"
2711
+ ]);
2324
2712
  function parseOptionalGasLimitString2(raw) {
2325
2713
  if (raw == null) return null;
2326
2714
  const s = String(raw).trim();
@@ -2444,7 +2832,9 @@ async function buildEvmMultisignBodyUniswapV4LiquidityBatchInternal(args) {
2444
2832
  const dataHex = dataHexFromTx(tx);
2445
2833
  const valueWei = parseTxValueWei(tx);
2446
2834
  const executor = viem.getAddress(args.executorAddress);
2447
- const spender = to;
2835
+ const positionManagerKind = args.positionManagerKind === "permissioned" || args.positionManagerKind === "standard" ? args.positionManagerKind : isUniswapV4PermissionedPositionManager(args.chainId, to) ? "permissioned" : "standard";
2836
+ const usePermit2 = args.usePermit2Approvals === true || args.usePermit2Approvals !== false && positionManagerKind === "permissioned";
2837
+ const erc20Spender = usePermit2 ? PERMIT2_ADDRESS : to;
2448
2838
  const chain = viem.defineChain({
2449
2839
  id: args.chainId,
2450
2840
  name: `uniswap-v4-lp-${args.chainId}`,
@@ -2452,15 +2842,21 @@ async function buildEvmMultisignBodyUniswapV4LiquidityBatchInternal(args) {
2452
2842
  rpcUrls: { default: { http: [args.rpcUrl] } }
2453
2843
  });
2454
2844
  const publicClient = viem.createPublicClient({ chain, transport: viem.http(args.rpcUrl) });
2455
- const approveTargets = await resolveApproveTargets({
2845
+ const needsTokenApproves = args.action === "mint" || args.action === "increase";
2846
+ const approveTargets = needsTokenApproves ? await resolveApproveTargets({
2456
2847
  publicClient,
2457
2848
  executor,
2458
- spender,
2849
+ spender: erc20Spender,
2459
2850
  token0: parsed.token0,
2460
2851
  token1: parsed.token1,
2461
2852
  nativeWrapped: args.nativeWrapped
2462
- });
2853
+ }) : [];
2463
2854
  const steps = [];
2855
+ let permit2Expiration48 = 0n;
2856
+ if (usePermit2 && needsTokenApproves) {
2857
+ permit2Expiration48 = BigInt(Math.floor(Date.now() / 1e3) + UNISWAP_LP_DEFAULT_DEADLINE_SEC_OFFSET);
2858
+ if (permit2Expiration48 > MAX_UINT48) permit2Expiration48 = MAX_UINT48;
2859
+ }
2464
2860
  for (const target of approveTargets) {
2465
2861
  if (target.kind === "weth_deposit") {
2466
2862
  steps.push({
@@ -2473,13 +2869,17 @@ async function buildEvmMultisignBodyUniswapV4LiquidityBatchInternal(args) {
2473
2869
  address: target.token,
2474
2870
  abi: erc20AllowanceAbi2,
2475
2871
  functionName: "allowance",
2476
- args: [executor, spender]
2872
+ args: [executor, erc20Spender]
2477
2873
  });
2478
2874
  if (wethAllowance < target.amount) {
2479
- if (wethAllowance > 0n) {
2875
+ if (wethAllowance > 0n && !usePermit2) {
2480
2876
  steps.push({
2481
2877
  to: target.token,
2482
- data: viem.encodeFunctionData({ abi: viem.erc20Abi, functionName: "approve", args: [spender, 0n] }),
2878
+ data: viem.encodeFunctionData({
2879
+ abi: viem.erc20Abi,
2880
+ functionName: "approve",
2881
+ args: [erc20Spender, 0n]
2882
+ }),
2483
2883
  value: 0n,
2484
2884
  fallbackGas: UNISWAP_V4_LP_ERC20_APPROVE_FALLBACK
2485
2885
  });
@@ -2489,7 +2889,7 @@ async function buildEvmMultisignBodyUniswapV4LiquidityBatchInternal(args) {
2489
2889
  data: viem.encodeFunctionData({
2490
2890
  abi: viem.erc20Abi,
2491
2891
  functionName: "approve",
2492
- args: [spender, target.amount]
2892
+ args: [erc20Spender, target.amount]
2493
2893
  }),
2494
2894
  value: 0n,
2495
2895
  fallbackGas: UNISWAP_V4_LP_ERC20_APPROVE_FALLBACK
@@ -2501,13 +2901,66 @@ async function buildEvmMultisignBodyUniswapV4LiquidityBatchInternal(args) {
2501
2901
  data: viem.encodeFunctionData({
2502
2902
  abi: viem.erc20Abi,
2503
2903
  functionName: "approve",
2504
- args: [spender, target.amount]
2904
+ args: [erc20Spender, target.amount]
2505
2905
  }),
2506
2906
  value: 0n,
2507
2907
  fallbackGas: UNISWAP_V4_LP_ERC20_APPROVE_FALLBACK
2508
2908
  });
2509
2909
  }
2510
2910
  }
2911
+ if (usePermit2 && needsTokenApproves) {
2912
+ const pairs = [parsed.token0, parsed.token1].filter(Boolean);
2913
+ for (const row of pairs) {
2914
+ const amt = BigInt(row.amount);
2915
+ if (amt <= 0n) continue;
2916
+ let token;
2917
+ if (isNativeUniswapLpTokenAddress(row.tokenAddress)) {
2918
+ if (!args.nativeWrapped) {
2919
+ throw new Error("nativeWrapped is required when LP uses native ETH (0x0) token.");
2920
+ }
2921
+ token = viem.getAddress(args.nativeWrapped);
2922
+ if (!approveTargets.some((a) => a.token === token && a.kind === "weth_deposit")) {
2923
+ steps.push({
2924
+ to: token,
2925
+ data: viem.encodeFunctionData({ abi: wethDepositAbi, functionName: "deposit" }),
2926
+ value: amt,
2927
+ fallbackGas: UNISWAP_V4_LP_WETH_DEPOSIT_FALLBACK
2928
+ });
2929
+ const wethAllowance = await publicClient.readContract({
2930
+ address: token,
2931
+ abi: erc20AllowanceAbi2,
2932
+ functionName: "allowance",
2933
+ args: [executor, PERMIT2_ADDRESS]
2934
+ });
2935
+ if (wethAllowance < amt) {
2936
+ steps.push({
2937
+ to: token,
2938
+ data: viem.encodeFunctionData({
2939
+ abi: viem.erc20Abi,
2940
+ functionName: "approve",
2941
+ args: [PERMIT2_ADDRESS, amt]
2942
+ }),
2943
+ value: 0n,
2944
+ fallbackGas: UNISWAP_V4_LP_ERC20_APPROVE_FALLBACK
2945
+ });
2946
+ }
2947
+ }
2948
+ } else {
2949
+ token = viem.getAddress(row.tokenAddress);
2950
+ }
2951
+ const amount160 = amt > MAX_UINT160 ? MAX_UINT160 : amt;
2952
+ steps.push({
2953
+ to: PERMIT2_ADDRESS,
2954
+ data: viem.encodeFunctionData({
2955
+ abi: permit2ApproveAbi,
2956
+ functionName: "approve",
2957
+ args: [token, to, amount160, Number(permit2Expiration48)]
2958
+ }),
2959
+ value: 0n,
2960
+ fallbackGas: UNISWAP_V4_LP_PERMIT2_APPROVE_FALLBACK
2961
+ });
2962
+ }
2963
+ }
2511
2964
  const lpFallbackGas = defaultGasForAction(args.action);
2512
2965
  const fromTradeApi = parseOptionalGasLimitString2(tx.gasLimit) ?? parseOptionalGasLimitString2(tx.gas);
2513
2966
  steps.push({
@@ -2519,6 +2972,7 @@ async function buildEvmMultisignBodyUniswapV4LiquidityBatchInternal(args) {
2519
2972
  const actionLabel = args.action === "mint" ? "mint liquidity" : args.action === "increase" ? "increase liquidity" : args.action === "decrease" ? "decrease liquidity" : "collect fees";
2520
2973
  const dataNo0x = dataHex.startsWith("0x") ? dataHex.slice(2) : dataHex;
2521
2974
  const lpIndex = steps.length - 1;
2975
+ 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).`;
2522
2976
  return buildEvmMultisignBatch({
2523
2977
  context: {
2524
2978
  chainCategory: "evm",
@@ -2532,7 +2986,7 @@ async function buildEvmMultisignBodyUniswapV4LiquidityBatchInternal(args) {
2532
2986
  customGasChainDetails: args.customGasChainDetails
2533
2987
  },
2534
2988
  steps,
2535
- purposeSuffix: `Uniswap V4: ${steps.length}-tx batch \u2014 ${actionLabel} (classic ERC-20 approve + Position Manager).`,
2989
+ purposeSuffix,
2536
2990
  firstMsgRawNo0x: dataNo0x,
2537
2991
  destinationAddress: to,
2538
2992
  buildBatchMeta: ({ index }) => {
@@ -2542,13 +2996,17 @@ async function buildEvmMultisignBodyUniswapV4LiquidityBatchInternal(args) {
2542
2996
  kind: "UniswapV4Liquidity",
2543
2997
  action: args.action,
2544
2998
  step: index,
2545
- lpTx: isLpStep
2999
+ lpTx: isLpStep,
3000
+ positionManagerKind,
3001
+ usePermit2
2546
3002
  }),
2547
3003
  ...isLpStep ? {
2548
3004
  evm: { type: "uniswap_v4_liquidity_tx", version: 1, chainId: String(args.chainId) },
2549
3005
  uniswapV4Liquidity: {
2550
3006
  action: args.action,
2551
- skipPermit2Batch: true,
3007
+ skipPermit2Batch: !usePermit2,
3008
+ usePermit2Approvals: usePermit2,
3009
+ positionManagerKind,
2552
3010
  nftTokenId: args.nftTokenId != null ? String(args.nftTokenId) : void 0,
2553
3011
  poolReference: args.poolReference,
2554
3012
  lpResponseSnapshot: args.lpResponse,
@@ -2581,6 +3039,260 @@ async function buildEvmMultisignBodyUniswapV4DecreaseLiquidityBatch(args) {
2581
3039
  async function buildEvmMultisignBodyUniswapV4CollectFeesBatch(args) {
2582
3040
  return buildEvmMultisignBodyUniswapV4LiquidityBatchInternal({ ...args, action: "collect" });
2583
3041
  }
3042
+ var PERMISSIONED_LP_PRESETS = [
3043
+ // No public launch-partner presets hard-coded yet — use custom existingPool with hooks.
3044
+ ];
3045
+ function buildUniswapV4PermissionedLpPoolRow(args) {
3046
+ const chainId = parseUniswapChainId(args.chainId);
3047
+ const hooks = (args.hooks?.trim() ? viem.getAddress(args.hooks.trim()) : tryGetUniswapV4PermissionedHooks(chainId)) ?? (() => {
3048
+ throw new Error(`No PermissionedHooks for chainId ${chainId}; pass hooks explicitly.`);
3049
+ })();
3050
+ const positionManager = tryGetUniswapV4PermissionedPositionManager(chainId);
3051
+ if (!positionManager) {
3052
+ throw new Error(`No Permissioned PositionManager for chainId ${chainId}.`);
3053
+ }
3054
+ const adapter = viem.getAddress(args.adapterAddress);
3055
+ const other = viem.getAddress(args.otherCurrencyAddress);
3056
+ const sorted = sortUniswapV4PoolCurrencies(adapter, other);
3057
+ const poolReference = computeUniswapV4PoolReference({
3058
+ token0Address: sorted.currency0,
3059
+ token1Address: sorted.currency1,
3060
+ fee: args.fee,
3061
+ tickSpacing: args.tickSpacing,
3062
+ hooks
3063
+ });
3064
+ return {
3065
+ presetId: args.presetId,
3066
+ pairSlug: args.pairSlug,
3067
+ pairLabel: args.pairLabel,
3068
+ fee: args.fee,
3069
+ feeLabel: args.feeLabel,
3070
+ tickSpacing: args.tickSpacing,
3071
+ token0Symbol: sorted.currency0 === adapter ? args.adapterSymbol ?? "v4PT" : args.otherSymbol ?? "TOKEN",
3072
+ token1Symbol: sorted.currency1 === adapter ? args.adapterSymbol ?? "v4PT" : args.otherSymbol ?? "TOKEN",
3073
+ token0Address: sorted.currency0,
3074
+ token1Address: sorted.currency1,
3075
+ poolReference,
3076
+ hooks,
3077
+ nativeWrapped: args.nativeWrapped ? viem.getAddress(args.nativeWrapped) : void 0,
3078
+ usesNativeEth: Boolean(args.usesNativeEth),
3079
+ positionManagerKind: "permissioned",
3080
+ positionManager,
3081
+ underlyingPermissionedToken: args.underlyingPermissionedToken ? viem.getAddress(args.underlyingPermissionedToken) : void 0,
3082
+ adapterAddress: adapter,
3083
+ issuer: args.issuer
3084
+ };
3085
+ }
3086
+ function listUniswapV4PermissionedLpPools(args) {
3087
+ const chainId = parseUniswapChainId(args.chainId);
3088
+ const positionManager = tryGetUniswapV4PermissionedPositionManager(chainId);
3089
+ const hooks = tryGetUniswapV4PermissionedHooks(chainId);
3090
+ if (!positionManager || !hooks) {
3091
+ return {
3092
+ chainId,
3093
+ chainLabel: `chain ${chainId}`,
3094
+ pools: [],
3095
+ positionManagerKind: "permissioned",
3096
+ notes: "No Permissioned PositionManager / PermissionedHooks configured for this chain. Ethereum mainnet (1) and Sepolia (11155111) are supported. Pass custom existingPool with adapter currency + hooks."
3097
+ };
3098
+ }
3099
+ let pools = PERMISSIONED_LP_PRESETS.filter(
3100
+ (p) => p.chainId === chainId
3101
+ ).map(
3102
+ (p) => buildUniswapV4PermissionedLpPoolRow({
3103
+ chainId,
3104
+ presetId: p.presetId,
3105
+ pairSlug: p.pairSlug,
3106
+ pairLabel: p.pairLabel,
3107
+ fee: p.fee,
3108
+ feeLabel: p.feeLabel,
3109
+ tickSpacing: p.tickSpacing,
3110
+ adapterAddress: p.adapterAddress,
3111
+ otherCurrencyAddress: p.otherCurrency,
3112
+ adapterSymbol: p.adapterSymbol,
3113
+ otherSymbol: p.otherSymbol,
3114
+ underlyingPermissionedToken: p.underlyingPermissionedToken,
3115
+ usesNativeEth: p.usesNativeEth,
3116
+ nativeWrapped: p.nativeWrapped,
3117
+ issuer: p.issuer,
3118
+ hooks
3119
+ })
3120
+ );
3121
+ const pairFilter = args.pair?.trim().toLowerCase();
3122
+ if (pairFilter) {
3123
+ pools = pools.filter(
3124
+ (row) => row.pairSlug.includes(pairFilter) || row.pairLabel.toLowerCase().includes(pairFilter) || row.presetId.includes(pairFilter)
3125
+ );
3126
+ }
3127
+ const chainLabel = PERMISSIONED_LP_PRESETS.find((p) => p.chainId === chainId)?.chainLabel ?? (chainId === 1 ? "Ethereum" : chainId === 11155111 ? "Sepolia" : `chain ${chainId}`);
3128
+ return {
3129
+ chainId,
3130
+ chainLabel,
3131
+ pools,
3132
+ positionManagerKind: "permissioned",
3133
+ notes: `Permissioned LP uses Permissioned Position Manager (UNI-V4-PERM-POSM) and PermissionedHooks. Pool currencies use the Permissions Adapter address, not the underlying token. Requires LIQUIDITY_ALLOWED on the wallet. Curated presets may be empty \u2014 pass existingPool with adapter + hooks + fee/tickSpacing. positionManager=${positionManager} hooks=${hooks}`
3134
+ };
3135
+ }
3136
+ function resolveUniswapV4PermissionedLpPoolPreset(args) {
3137
+ const listed = listUniswapV4PermissionedLpPools({ chainId: args.chainId });
3138
+ const preset = args.presetId.trim().toLowerCase();
3139
+ const row = listed.pools.find((p) => p.presetId.toLowerCase() === preset);
3140
+ if (!row) {
3141
+ throw new Error(
3142
+ `Unknown permissioned LP pool preset "${args.presetId}" on chainId ${listed.chainId}. Call ctm_uniswap_v4_list_lp_pools with permissioned=true, or pass custom existingPool.`
3143
+ );
3144
+ }
3145
+ return row;
3146
+ }
3147
+ function uniswapV4ListLpPools(args) {
3148
+ if (args.permissioned) {
3149
+ return listUniswapV4PermissionedLpPools(args);
3150
+ }
3151
+ const std = listUniswapV4StandardLpPools(args);
3152
+ return {
3153
+ ...std,
3154
+ positionManagerKind: "standard"
3155
+ };
3156
+ }
3157
+ function buildUniswapV4KycApplyLink(args) {
3158
+ const walletAddress = viem.getAddress(args.walletAddress.trim());
3159
+ const chainId = parseUniswapChainId(args.chainId);
3160
+ const kycUrl = args.kycUrl.trim();
3161
+ if (!kycUrl) throw new Error("kycUrl is required");
3162
+ let token;
3163
+ let adapterTokenAddress;
3164
+ if (args.token?.trim()) {
3165
+ try {
3166
+ token = viem.getAddress(args.token.trim());
3167
+ } catch {
3168
+ }
3169
+ }
3170
+ if (args.adapterTokenAddress?.trim()) {
3171
+ try {
3172
+ adapterTokenAddress = viem.getAddress(args.adapterTokenAddress.trim());
3173
+ } catch {
3174
+ }
3175
+ }
3176
+ let applyUrl = kycUrl;
3177
+ try {
3178
+ const u = new URL(kycUrl);
3179
+ if (!u.searchParams.has("wallet") && !u.searchParams.has("address")) {
3180
+ u.searchParams.set("wallet", walletAddress);
3181
+ u.searchParams.set("address", walletAddress);
3182
+ }
3183
+ if (!u.searchParams.has("chainId")) u.searchParams.set("chainId", String(chainId));
3184
+ if (token && !u.searchParams.has("token")) u.searchParams.set("token", token);
3185
+ applyUrl = u.toString();
3186
+ } catch {
3187
+ applyUrl = kycUrl;
3188
+ }
3189
+ return {
3190
+ walletAddress,
3191
+ chainId,
3192
+ issuer: args.issuer?.trim() || void 0,
3193
+ kycUrl,
3194
+ applyUrl,
3195
+ token,
3196
+ adapterTokenAddress
3197
+ };
3198
+ }
3199
+ function pickUniswapV4KycTarget(results) {
3200
+ return results.find((r) => r.isPermissioned && !r.isAllowlisted && r.kycUrl) ?? results.find((r) => r.isPermissioned && r.kycUrl) ?? null;
3201
+ }
3202
+ function uniswapV4KycApplyLinkMcp(args) {
3203
+ return buildUniswapV4KycApplyLink(args);
3204
+ }
3205
+ var ALLOWLIST_FINALIZE_FALLBACK_GAS = 250000n;
3206
+ async function buildEvmMultisignBodyUniswapV4PermissionedAllowlistFinalize(args) {
3207
+ const to = viem.getAddress(args.to.trim());
3208
+ let dataHex = (args.data ?? "0x").toString().trim();
3209
+ if (!dataHex.startsWith("0x")) dataHex = `0x${dataHex}`;
3210
+ if (dataHex.length < 10) {
3211
+ throw new Error("allowlist finalize `data` must be non-empty ABI-encoded calldata");
3212
+ }
3213
+ let value = 0n;
3214
+ if (args.valueWei != null && String(args.valueWei).trim() !== "") {
3215
+ try {
3216
+ value = BigInt(String(args.valueWei).trim());
3217
+ } catch {
3218
+ value = 0n;
3219
+ }
3220
+ }
3221
+ const steps = [
3222
+ {
3223
+ to,
3224
+ data: dataHex,
3225
+ value,
3226
+ fallbackGas: ALLOWLIST_FINALIZE_FALLBACK_GAS
3227
+ }
3228
+ ];
3229
+ const dataNo0x = dataHex.slice(2);
3230
+ const issuerLabel = args.issuer?.trim() || "issuer";
3231
+ return buildEvmMultisignBatch({
3232
+ context: {
3233
+ chainCategory: "evm",
3234
+ keyGen: args.keyGen,
3235
+ purposeText: args.purposeText,
3236
+ chainId: args.chainId,
3237
+ rpcUrl: args.rpcUrl,
3238
+ executorAddress: args.executorAddress,
3239
+ chainDetail: args.chainDetail,
3240
+ useCustomGas: args.useCustomGas,
3241
+ customGasChainDetails: args.customGasChainDetails
3242
+ },
3243
+ steps,
3244
+ purposeSuffix: `Uniswap V4 permissioned: 1-tx allowlist finalize (${issuerLabel}).`,
3245
+ firstMsgRawNo0x: dataNo0x,
3246
+ destinationAddress: to,
3247
+ buildBatchMeta: () => ({
3248
+ signatureText: JSON.stringify({
3249
+ kind: "UniswapV4PermissionedAllowlist",
3250
+ issuer: args.issuer,
3251
+ entityId: args.entityId != null ? String(args.entityId) : void 0
3252
+ }),
3253
+ evm: {
3254
+ type: "uniswap_v4_permissioned_allowlist",
3255
+ version: 1,
3256
+ chainId: String(args.chainId)
3257
+ },
3258
+ uniswapV4PermissionedAllowlist: {
3259
+ to,
3260
+ dataNibbles: dataNo0x.length,
3261
+ issuer: args.issuer,
3262
+ entityId: args.entityId != null ? String(args.entityId) : void 0,
3263
+ tokenAddress: args.tokenAddress,
3264
+ originalPurpose: args.purposeText
3265
+ }
3266
+ })
3267
+ });
3268
+ }
3269
+ function isUniswapV4PermissionedAllowlistEvmSignRequest(detail) {
3270
+ if (!detail) return false;
3271
+ const raw = detail.ExtraJSON ?? detail.extraJSON;
3272
+ let ex = null;
3273
+ if (raw && typeof raw === "object" && !Array.isArray(raw)) ex = raw;
3274
+ else if (typeof raw === "string" && raw.trim()) {
3275
+ try {
3276
+ const p = JSON.parse(raw);
3277
+ if (p && typeof p === "object" && !Array.isArray(p)) ex = p;
3278
+ } catch {
3279
+ return false;
3280
+ }
3281
+ }
3282
+ if (!ex) return false;
3283
+ const bm = ex.batchMeta;
3284
+ if (Array.isArray(bm) && bm[0] && typeof bm[0] === "object" && !Array.isArray(bm[0])) {
3285
+ const evm0 = bm[0].evm;
3286
+ if (evm0 && typeof evm0 === "object" && !Array.isArray(evm0)) {
3287
+ if (String(evm0.type ?? "") === "uniswap_v4_permissioned_allowlist") {
3288
+ return true;
3289
+ }
3290
+ }
3291
+ }
3292
+ const evm = ex.evm;
3293
+ if (!evm || typeof evm !== "object" || Array.isArray(evm)) return false;
3294
+ return String(evm.type ?? "") === "uniswap_v4_permissioned_allowlist";
3295
+ }
2584
3296
 
2585
3297
  // src/protocols/evm/uniswap-v4/support.ts
2586
3298
  function computeUniswapV4Session(args) {
@@ -2599,7 +3311,12 @@ function computeUniswapV4Session(args) {
2599
3311
  chainId: chainIdNum,
2600
3312
  rpcUrl,
2601
3313
  chainSupported,
2602
- universalRouter
3314
+ universalRouter,
3315
+ universalRouterV22: tryGetUniswapUniversalRouterV22(chainIdNum) ?? void 0,
3316
+ positionManager: tryGetUniswapV4PositionManager(chainIdNum) ?? void 0,
3317
+ permissionedPositionManager: tryGetUniswapV4PermissionedPositionManager(chainIdNum) ?? void 0,
3318
+ permissionedHooks: tryGetUniswapV4PermissionedHooks(chainIdNum) ?? void 0,
3319
+ permissionsAdapterFactory: tryGetUniswapV4PermissionsAdapterFactory(chainIdNum) ?? void 0
2603
3320
  };
2604
3321
  }
2605
3322
 
@@ -2890,6 +3607,28 @@ async function fetchUniswapV4PoolMeta(args) {
2890
3607
  );
2891
3608
  return data.pool ?? null;
2892
3609
  }
3610
+ var LATEST_SWAP_GQL = `
3611
+ query UniswapV4LatestSwap($pool: String!) {
3612
+ swaps(
3613
+ where: { pool: $pool }
3614
+ orderBy: timestamp
3615
+ orderDirection: desc
3616
+ first: 1
3617
+ ) {
3618
+ token0Price
3619
+ sqrtPriceX96
3620
+ }
3621
+ }`;
3622
+ async function fetchUniswapV4LatestSwap(args) {
3623
+ const pool = normalizePoolId(args.poolReference);
3624
+ const data = await postUniswapV4SubgraphGql(
3625
+ args.chainId,
3626
+ LATEST_SWAP_GQL,
3627
+ { pool },
3628
+ args.theGraphApiKey
3629
+ );
3630
+ return data.swaps?.[0] ?? null;
3631
+ }
2893
3632
 
2894
3633
  // src/protocols/evm/uniswap-v4/bitqueryApiKey.ts
2895
3634
  var BITQUERY_API_KEY_ENV = "BITQUERY_API_KEY";
@@ -3178,7 +3917,7 @@ function parseDecimal(raw) {
3178
3917
  const n = Number(raw);
3179
3918
  return Number.isFinite(n) && n > 0 ? n : null;
3180
3919
  }
3181
- function priceFromSwapRow(row) {
3920
+ function priceFromUniswapV4SwapRow(row) {
3182
3921
  const fromToken0 = parseDecimal(row.token0Price);
3183
3922
  if (fromToken0 != null) return fromToken0;
3184
3923
  const sqrt = row.sqrtPriceX96?.trim();
@@ -3200,7 +3939,7 @@ function bucketUniswapV4SwapsIntoCandles(args) {
3200
3939
  const buckets = /* @__PURE__ */ new Map();
3201
3940
  for (const swap of args.swaps) {
3202
3941
  const ts = Number(swap.timestamp);
3203
- const price = priceFromSwapRow(swap);
3942
+ const price = priceFromUniswapV4SwapRow(swap);
3204
3943
  if (!Number.isFinite(ts) || price == null) continue;
3205
3944
  const bucket = bucketStartSec(Math.floor(ts), args.bucketSec);
3206
3945
  const vol = parseDecimal(swap.amountUSD) ?? 0;
@@ -3541,6 +4280,74 @@ async function uniswapV4FetchOhlcv(args) {
3541
4280
  };
3542
4281
  }
3543
4282
 
4283
+ // src/protocols/evm/uniswap-v4/livePrice.ts
4284
+ function applyPriceQuote(price, quote) {
4285
+ if (!Number.isFinite(price) || price <= 0) return null;
4286
+ if (quote === "token1PerToken0") {
4287
+ const inverted = 1 / price;
4288
+ return Number.isFinite(inverted) && inverted > 0 ? inverted : null;
4289
+ }
4290
+ return price;
4291
+ }
4292
+ function bitqueryFilterFromPoolReference(poolReference) {
4293
+ const ref = poolReference.trim();
4294
+ if (!ref) return null;
4295
+ if (ref.startsWith("symbol:")) {
4296
+ return { kind: "symbol", symbol: ref.slice("symbol:".length).trim() };
4297
+ }
4298
+ if (ref.startsWith("0x")) {
4299
+ return { kind: "address", address: ref };
4300
+ }
4301
+ return null;
4302
+ }
4303
+ async function fetchUniswapV4BitqueryLatestClose(args) {
4304
+ const filter = bitqueryFilterFromPoolReference(args.poolReference);
4305
+ if (!filter) return null;
4306
+ const apiKey = resolveBitqueryApiKey(args.bitqueryApiKey);
4307
+ if (!apiKey) return null;
4308
+ const interval = args.interval?.trim() || "15m";
4309
+ const endTimeMs = Date.now();
4310
+ const startTimeMs = endTimeMs - 6 * 3600 * 1e3;
4311
+ const { candles } = await fetchRobinhoodBitqueryOhlcv({
4312
+ filter,
4313
+ interval,
4314
+ startTimeMs,
4315
+ endTimeMs,
4316
+ apiKey,
4317
+ limit: 5
4318
+ });
4319
+ if (candles.length === 0) return null;
4320
+ const last = candles[candles.length - 1];
4321
+ const close = Number(last.close);
4322
+ return Number.isFinite(close) && close > 0 ? close : null;
4323
+ }
4324
+ async function fetchUniswapV4ChartLivePrice(args) {
4325
+ const chainId = Math.floor(Number(args.chainId));
4326
+ if (!Number.isFinite(chainId) || chainId <= 0) return null;
4327
+ const poolReference = args.poolReference.trim();
4328
+ if (!poolReference) return null;
4329
+ const dataSource = String(args.dataSource ?? "").trim().toLowerCase();
4330
+ if (dataSource === "bitquery" || isRobinhoodOhlcvChain(chainId)) {
4331
+ return fetchUniswapV4BitqueryLatestClose({
4332
+ poolReference,
4333
+ interval: args.interval,
4334
+ bitqueryApiKey: args.bitqueryApiKey
4335
+ });
4336
+ }
4337
+ if (!uniswapV4SubgraphSupportedChainIds().includes(chainId)) {
4338
+ return null;
4339
+ }
4340
+ const row = await fetchUniswapV4LatestSwap({
4341
+ chainId,
4342
+ poolReference,
4343
+ theGraphApiKey: resolveTheGraphApiKey(args.theGraphApiKey)
4344
+ });
4345
+ if (!row) return null;
4346
+ const raw = priceFromUniswapV4SwapRow(row);
4347
+ if (raw == null) return null;
4348
+ return applyPriceQuote(raw, args.priceQuote);
4349
+ }
4350
+
3544
4351
  // src/protocols/evm/uniswap-v4/limitOrder.ts
3545
4352
  function trimAddr3(a) {
3546
4353
  return a.trim();
@@ -4059,6 +4866,7 @@ exports.UNISWAP_SWAP_DEFAULT_EXPIRY_MINUTES = UNISWAP_SWAP_DEFAULT_EXPIRY_MINUTE
4059
4866
  exports.UNISWAP_TRADE_BASE_DEFAULT = UNISWAP_TRADE_BASE_DEFAULT;
4060
4867
  exports.UNISWAP_UNIVERSAL_ROUTER_DEFAULT_GAS_UNITS = UNISWAP_UNIVERSAL_ROUTER_DEFAULT_GAS_UNITS;
4061
4868
  exports.UNISWAP_UNIVERSAL_ROUTER_VERSION_DEFAULT = UNISWAP_UNIVERSAL_ROUTER_VERSION_DEFAULT;
4869
+ exports.UNISWAP_UNIVERSAL_ROUTER_VERSION_PERMISSIONED = UNISWAP_UNIVERSAL_ROUTER_VERSION_PERMISSIONED;
4062
4870
  exports.UNISWAP_V4_LP_COLLECT_DEFAULT_GAS_UNITS = UNISWAP_V4_LP_COLLECT_DEFAULT_GAS_UNITS;
4063
4871
  exports.UNISWAP_V4_LP_DECREASE_DEFAULT_GAS_UNITS = UNISWAP_V4_LP_DECREASE_DEFAULT_GAS_UNITS;
4064
4872
  exports.UNISWAP_V4_LP_ERC20_APPROVE_FALLBACK = UNISWAP_V4_LP_ERC20_APPROVE_FALLBACK;
@@ -4066,16 +4874,21 @@ exports.UNISWAP_V4_LP_INCREASE_DEFAULT_GAS_UNITS = UNISWAP_V4_LP_INCREASE_DEFAUL
4066
4874
  exports.UNISWAP_V4_LP_LOG_CHUNK_SIZE_DEFAULT = UNISWAP_V4_LP_LOG_CHUNK_SIZE_DEFAULT;
4067
4875
  exports.UNISWAP_V4_LP_LOG_CHUNK_SIZE_MIN = UNISWAP_V4_LP_LOG_CHUNK_SIZE_MIN;
4068
4876
  exports.UNISWAP_V4_LP_MINT_DEFAULT_GAS_UNITS = UNISWAP_V4_LP_MINT_DEFAULT_GAS_UNITS;
4877
+ exports.UNISWAP_V4_LP_PERMIT2_APPROVE_FALLBACK = UNISWAP_V4_LP_PERMIT2_APPROVE_FALLBACK;
4069
4878
  exports.UNISWAP_V4_LP_POOL_LOOKUP_HINT = UNISWAP_V4_LP_POOL_LOOKUP_HINT;
4070
4879
  exports.UNISWAP_V4_LP_POSITION_REGISTRY_HINT = UNISWAP_V4_LP_POSITION_REGISTRY_HINT;
4071
4880
  exports.UNISWAP_V4_LP_WETH_DEPOSIT_FALLBACK = UNISWAP_V4_LP_WETH_DEPOSIT_FALLBACK;
4072
4881
  exports.UNISWAP_V4_OHLCV_INTERVALS = UNISWAP_V4_OHLCV_INTERVALS;
4882
+ exports.UNISWAP_V4_PERMISSION_FLAG_LIQUIDITY = UNISWAP_V4_PERMISSION_FLAG_LIQUIDITY;
4883
+ exports.UNISWAP_V4_PERMISSION_FLAG_SWAP = UNISWAP_V4_PERMISSION_FLAG_SWAP;
4073
4884
  exports.UNISWAP_V4_PROTOCOL_ID = UNISWAP_V4_PROTOCOL_ID;
4074
4885
  exports.UNISWAP_V4_SUBGRAPH_ID_BY_CHAIN_ID = UNISWAP_V4_SUBGRAPH_ID_BY_CHAIN_ID;
4886
+ exports.UniswapV4PermissionDeniedError = UniswapV4PermissionDeniedError;
4075
4887
  exports.aggregateOhlcvCandles = aggregateOhlcvCandles;
4076
4888
  exports.applySlippagePercentToApproveWei = applySlippagePercentToApproveWei;
4077
4889
  exports.assertUniswapLimitOrderChain = assertUniswapLimitOrderChain;
4078
4890
  exports.assertUniswapV4OhlcvInterval = assertUniswapV4OhlcvInterval;
4891
+ exports.assertUniswapV4PermissionsAllowlisted = assertUniswapV4PermissionsAllowlisted;
4079
4892
  exports.bitqueryApiKeyVariablesHint = bitqueryApiKeyVariablesHint;
4080
4893
  exports.bitqueryAuthErrorMessage = bitqueryAuthErrorMessage;
4081
4894
  exports.buildEvmMultisignBodyUniswapV4CollectFeesBatch = buildEvmMultisignBodyUniswapV4CollectFeesBatch;
@@ -4084,9 +4897,12 @@ exports.buildEvmMultisignBodyUniswapV4IncreaseLiquidityBatch = buildEvmMultisign
4084
4897
  exports.buildEvmMultisignBodyUniswapV4LimitOrderBatch = buildEvmMultisignBodyUniswapV4LimitOrderBatch;
4085
4898
  exports.buildEvmMultisignBodyUniswapV4LimitOrderBatchFromMcp = buildEvmMultisignBodyUniswapV4LimitOrderBatchFromMcp;
4086
4899
  exports.buildEvmMultisignBodyUniswapV4MintLiquidityBatch = buildEvmMultisignBodyUniswapV4MintLiquidityBatch;
4900
+ exports.buildEvmMultisignBodyUniswapV4PermissionedAllowlistFinalize = buildEvmMultisignBodyUniswapV4PermissionedAllowlistFinalize;
4087
4901
  exports.buildEvmMultisignBodyUniswapV4SkipPermit2Batch = buildEvmMultisignBodyUniswapV4SkipPermit2Batch;
4088
4902
  exports.buildLimitOrderQuoteRequestBody = buildLimitOrderQuoteRequestBody;
4089
4903
  exports.buildUniswapQuoteRequestBody = buildUniswapQuoteRequestBody;
4904
+ exports.buildUniswapV4KycApplyLink = buildUniswapV4KycApplyLink;
4905
+ exports.buildUniswapV4PermissionedLpPoolRow = buildUniswapV4PermissionedLpPoolRow;
4090
4906
  exports.buildUniswapV4PurposePrefill = buildUniswapV4PurposePrefill;
4091
4907
  exports.buildUniswapXLimitOrderSubmitBody = buildUniswapXLimitOrderSubmitBody;
4092
4908
  exports.computeUniswapV4PoolReference = computeUniswapV4PoolReference;
@@ -4099,6 +4915,8 @@ exports.extractUniswapLpTokenAmounts = extractUniswapLpTokenAmounts;
4099
4915
  exports.extractUniswapLpTransaction = extractUniswapLpTransaction;
4100
4916
  exports.fetchEthereumAddressForKeyGen = fetchEthereumAddressForKeyGen;
4101
4917
  exports.fetchRobinhoodBitqueryOhlcv = fetchRobinhoodBitqueryOhlcv;
4918
+ exports.fetchUniswapV4ChartLivePrice = fetchUniswapV4ChartLivePrice;
4919
+ exports.fetchUniswapV4LatestSwap = fetchUniswapV4LatestSwap;
4102
4920
  exports.fetchUniswapV4PoolDayDatas = fetchUniswapV4PoolDayDatas;
4103
4921
  exports.fetchUniswapV4PoolHourDatas = fetchUniswapV4PoolHourDatas;
4104
4922
  exports.fetchUniswapV4PoolMeta = fetchUniswapV4PoolMeta;
@@ -4112,6 +4930,9 @@ exports.formatUniswapV4PositionNotFoundError = formatUniswapV4PositionNotFoundEr
4112
4930
  exports.getClassicQuoteFromStoredUniswapResponse = getClassicQuoteFromStoredUniswapResponse;
4113
4931
  exports.getUniswapUniversalRouterSpenderOrThrow = getUniswapUniversalRouterSpenderOrThrow;
4114
4932
  exports.getUniswapUniversalRouterVersion = getUniswapUniversalRouterVersion;
4933
+ exports.getUniswapV4PermissionedHooksOrThrow = getUniswapV4PermissionedHooksOrThrow;
4934
+ exports.getUniswapV4PermissionedPositionManagerOrThrow = getUniswapV4PermissionedPositionManagerOrThrow;
4935
+ exports.getUniswapV4PermissionsAdapterFactoryOrThrow = getUniswapV4PermissionsAdapterFactoryOrThrow;
4115
4936
  exports.getUniswapV4PositionManagerDeployBlock = getUniswapV4PositionManagerDeployBlock;
4116
4937
  exports.getUniswapV4PositionManagerOrThrow = getUniswapV4PositionManagerOrThrow;
4117
4938
  exports.isBitqueryAuthOrRateLimitError = isBitqueryAuthOrRateLimitError;
@@ -4123,10 +4944,15 @@ exports.isUniswapFullQuoteResponseNativeIn = isUniswapFullQuoteResponseNativeIn;
4123
4944
  exports.isUniswapFullQuoteResponseNativeOut = isUniswapFullQuoteResponseNativeOut;
4124
4945
  exports.isUniswapLimitOrderChainSupported = isUniswapLimitOrderChainSupported;
4125
4946
  exports.isUniswapNativeTokenAddress = isUniswapNativeTokenAddress;
4947
+ exports.isUniswapStoredQuotePermissioned = isUniswapStoredQuotePermissioned;
4126
4948
  exports.isUniswapTokenInAddressNative = isUniswapTokenInAddressNative;
4949
+ exports.isUniswapV4AnyPositionManager = isUniswapV4AnyPositionManager;
4127
4950
  exports.isUniswapV4ChainSupported = isUniswapV4ChainSupported;
4128
4951
  exports.isUniswapV4LiquidityEvmSignRequest = isUniswapV4LiquidityEvmSignRequest;
4952
+ exports.isUniswapV4PermissionedAllowlistEvmSignRequest = isUniswapV4PermissionedAllowlistEvmSignRequest;
4953
+ exports.isUniswapV4PermissionedPositionManager = isUniswapV4PermissionedPositionManager;
4129
4954
  exports.isUniswapV4SwapEvmSignRequest = isUniswapV4SwapEvmSignRequest;
4955
+ exports.listUniswapV4PermissionedLpPools = listUniswapV4PermissionedLpPools;
4130
4956
  exports.listUniswapV4PositionsForWallet = listUniswapV4PositionsForWallet;
4131
4957
  exports.listUniswapV4StandardLpPools = listUniswapV4StandardLpPools;
4132
4958
  exports.mapBitqueryOhlcvRowsToCandles = mapBitqueryOhlcvRowsToCandles;
@@ -4137,7 +4963,9 @@ exports.parseUniswapQuoteClassicInOut = parseUniswapQuoteClassicInOut;
4137
4963
  exports.parseUniswapQuoteSlippageInfo = parseUniswapQuoteSlippageInfo;
4138
4964
  exports.parseUniswapV4ScanFromDateYmd = parseUniswapV4ScanFromDateYmd;
4139
4965
  exports.permitDataToEip712Payload = permitDataToEip712Payload;
4966
+ exports.pickUniswapV4KycTarget = pickUniswapV4KycTarget;
4140
4967
  exports.quoteSwap = quoteSwap;
4968
+ exports.readUniswapV4OnChainPermissionFlags = readUniswapV4OnChainPermissionFlags;
4141
4969
  exports.readUniswapV4PositionInfoRaw = readUniswapV4PositionInfoRaw;
4142
4970
  exports.requireBitqueryApiKey = requireBitqueryApiKey;
4143
4971
  exports.resolveBitqueryApiKey = resolveBitqueryApiKey;
@@ -4151,6 +4979,8 @@ exports.resolveUniswapV4LpExistingPoolFromKey = resolveUniswapV4LpExistingPoolFr
4151
4979
  exports.resolveUniswapV4LpPoolPreset = resolveUniswapV4LpPoolPreset;
4152
4980
  exports.resolveUniswapV4OhlcvDataTier = resolveUniswapV4OhlcvDataTier;
4153
4981
  exports.resolveUniswapV4OhlcvPool = resolveUniswapV4OhlcvPool;
4982
+ exports.resolveUniswapV4PermissionedLpPoolPreset = resolveUniswapV4PermissionedLpPoolPreset;
4983
+ exports.resolveUniswapV4PositionManager = resolveUniswapV4PositionManager;
4154
4984
  exports.resolveUniswapV4PositionScanFromDate = resolveUniswapV4PositionScanFromDate;
4155
4985
  exports.sortUniswapV4PoolCurrencies = sortUniswapV4PoolCurrencies;
4156
4986
  exports.submitUniswapXLimitOrder = submitUniswapXLimitOrder;
@@ -4159,6 +4989,10 @@ exports.swapFromQuote = swapFromQuote;
4159
4989
  exports.swapTransactionDeadlineUnixFromExpiryMinutes = swapTransactionDeadlineUnixFromExpiryMinutes;
4160
4990
  exports.theGraphApiKeyVariablesHint = theGraphApiKeyVariablesHint;
4161
4991
  exports.theGraphRateLimitErrorMessage = theGraphRateLimitErrorMessage;
4992
+ exports.tryGetUniswapUniversalRouterV22 = tryGetUniswapUniversalRouterV22;
4993
+ exports.tryGetUniswapV4PermissionedHooks = tryGetUniswapV4PermissionedHooks;
4994
+ exports.tryGetUniswapV4PermissionedPositionManager = tryGetUniswapV4PermissionedPositionManager;
4995
+ exports.tryGetUniswapV4PermissionsAdapterFactory = tryGetUniswapV4PermissionsAdapterFactory;
4162
4996
  exports.tryGetUniswapV4PositionManager = tryGetUniswapV4PositionManager;
4163
4997
  exports.uniswapCreateSwap = uniswapCreateSwap;
4164
4998
  exports.uniswapFetchLimitOrdersMcp = uniswapFetchLimitOrdersMcp;
@@ -4171,7 +5005,11 @@ exports.uniswapLpTxFieldForAction = uniswapLpTxFieldForAction;
4171
5005
  exports.uniswapQuoteToJsonQuoteOneLine = uniswapQuoteToJsonQuoteOneLine;
4172
5006
  exports.uniswapTradeQuote = uniswapTradeQuote;
4173
5007
  exports.uniswapV4 = uniswapV4;
5008
+ exports.uniswapV4CheckPermissions = uniswapV4CheckPermissions;
5009
+ exports.uniswapV4CheckPermissionsMcp = uniswapV4CheckPermissionsMcp;
4174
5010
  exports.uniswapV4FetchOhlcv = uniswapV4FetchOhlcv;
5011
+ exports.uniswapV4KycApplyLinkMcp = uniswapV4KycApplyLinkMcp;
5012
+ exports.uniswapV4ListLpPools = uniswapV4ListLpPools;
4175
5013
  exports.uniswapV4ListPositionsForMcp = uniswapV4ListPositionsForMcp;
4176
5014
  exports.uniswapV4ListPositionsFromRegistryForMcp = uniswapV4ListPositionsFromRegistryForMcp;
4177
5015
  exports.uniswapV4ListPositionsRegistryMcpPlaceholder = uniswapV4ListPositionsRegistryMcpPlaceholder;