@continuumdao/ctm-mpc-defi 0.2.3 → 0.2.5

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.
@@ -90,9 +90,55 @@ var MAX_UINT160 = (1n << 160n) - 1n;
90
90
  var MAX_UINT48 = (1n << 48n) - 1n;
91
91
  var UNISWAP_UNIVERSAL_ROUTER_DEFAULT_GAS_UNITS = 1500000n;
92
92
  var UNISWAP_TRADE_BASE_DEFAULT = "https://trade-api.gateway.uniswap.org/v1";
93
+ var UNISWAP_LP_API_BASE_DEFAULT = "https://api.uniswap.org";
93
94
  var UNISWAP_UNIVERSAL_ROUTER_VERSION_DEFAULT = "2.0";
94
95
  var UNISWAP_SWAP_DEFAULT_EXPIRY_MINUTES = 30;
95
96
  var UNISWAP_SWAP_DEFAULT_DEADLINE_SEC_OFFSET = UNISWAP_SWAP_DEFAULT_EXPIRY_MINUTES * 60;
97
+ var UNISWAP_LP_DEFAULT_EXPIRY_MINUTES = 30;
98
+ var UNISWAP_LP_DEFAULT_DEADLINE_SEC_OFFSET = UNISWAP_LP_DEFAULT_EXPIRY_MINUTES * 60;
99
+ var UNISWAP_LP_DEFAULT_SLIPPAGE_PERCENT = 0.5;
100
+ var POSITION_MANAGER_BY_CHAIN = {
101
+ 1: "0xbd216513d74c8cf14cf4747e6aaa6420ff64ee9e",
102
+ 10: "0x3c3ea4b57a46241e54610e5f022e5c45859a1017",
103
+ 137: "0x1ec2ebf4f37e7363fdfe3551602425af0b3ceef9",
104
+ 42161: "0xd88f38f930b7952f2db2432cb002e7abbf3dd869",
105
+ 8453: "0x7C5f5A4bBd8fD63184577525326123B519429bDc",
106
+ 11155111: "0x4B2C77d209D3405F41a037Ec6c77F7F5b8e2ca80",
107
+ 130: "0x0d97dc33264bfc1c226207428a79b26757fb9dc3",
108
+ 1868: "0x0e2850543f69f678257266e0907ff9a58b3f13de",
109
+ 59144: "0x661e93cca42afacb172121ef892830ca3b70f08d"
110
+ };
111
+ function getUniswapV4PositionManagerOrThrow(chainId) {
112
+ const raw = POSITION_MANAGER_BY_CHAIN[chainId];
113
+ if (!raw || !raw.startsWith("0x") || raw.length !== 42) {
114
+ throw new Error(
115
+ `No Uniswap V4 PositionManager is configured for chainId ${chainId}. Add this chain to uniswap-v4/constants or pass position manager from LP API response.`
116
+ );
117
+ }
118
+ return viem.getAddress(raw);
119
+ }
120
+ function tryGetUniswapV4PositionManager(chainId) {
121
+ try {
122
+ return getUniswapV4PositionManagerOrThrow(chainId);
123
+ } catch {
124
+ return null;
125
+ }
126
+ }
127
+ var POSITION_MANAGER_DEPLOY_BLOCK_BY_CHAIN = {
128
+ /** Ethereum mainnet — Uniswap v4 launch (Jan 2025). */
129
+ 1: 22938741n
130
+ };
131
+ var UNISWAP_V4_LP_LOG_CHUNK_SIZE_DEFAULT = 200n;
132
+ var UNISWAP_V4_LP_LOG_CHUNK_SIZE_MIN = 10n;
133
+ function getUniswapV4PositionManagerDeployBlock(chainId) {
134
+ return POSITION_MANAGER_DEPLOY_BLOCK_BY_CHAIN[chainId];
135
+ }
136
+ var UNISWAP_V4_LP_MINT_DEFAULT_GAS_UNITS = 1800000n;
137
+ var UNISWAP_V4_LP_INCREASE_DEFAULT_GAS_UNITS = 1500000n;
138
+ var UNISWAP_V4_LP_DECREASE_DEFAULT_GAS_UNITS = 1200000n;
139
+ var UNISWAP_V4_LP_COLLECT_DEFAULT_GAS_UNITS = 900000n;
140
+ var UNISWAP_V4_LP_ERC20_APPROVE_FALLBACK = 100000n;
141
+ var UNISWAP_V4_LP_WETH_DEPOSIT_FALLBACK = 120000n;
96
142
  var DEFAULT_TRADE_BASE = "https://trade-api.gateway.uniswap.org/v1";
97
143
  var UNISWAP_QUOTE_HEADERS_BASE = {
98
144
  "Content-Type": "application/json",
@@ -345,7 +391,16 @@ function parseUniswapQuoteClassicInOut(res) {
345
391
  const input = q.input;
346
392
  const output = q.output;
347
393
  const inAm = input?.amount;
348
- const outAm = output?.amount;
394
+ let outAm = output?.amount;
395
+ if (typeof outAm !== "string" || !outAm) {
396
+ const agg = q.aggregatedOutputs;
397
+ if (Array.isArray(agg) && agg.length > 0) {
398
+ const first = agg[0];
399
+ if (typeof first?.amount === "string" && first.amount) {
400
+ outAm = first.amount;
401
+ }
402
+ }
403
+ }
349
404
  if (typeof inAm !== "string" || !inAm || typeof outAm !== "string" || !outAm) return null;
350
405
  try {
351
406
  return { inputWei: BigInt(inAm), outputWei: BigInt(outAm) };
@@ -1323,6 +1378,1075 @@ async function buildEvmMultisignBodyUniswapV4SkipPermit2Batch(args) {
1323
1378
  }
1324
1379
  });
1325
1380
  }
1381
+ var POOL_KEY_ABI = viem.parseAbiParameters(
1382
+ "address currency0, address currency1, uint24 fee, int24 tickSpacing, address hooks"
1383
+ );
1384
+ var ZERO_HOOKS = "0x0000000000000000000000000000000000000000";
1385
+ function sortUniswapV4PoolCurrencies(token0Address, token1Address) {
1386
+ const a = normalizePoolCurrency(token0Address);
1387
+ const b = normalizePoolCurrency(token1Address);
1388
+ if (a.toLowerCase() === b.toLowerCase()) {
1389
+ throw new Error("Pool tokens must be distinct.");
1390
+ }
1391
+ return a.toLowerCase() < b.toLowerCase() ? { currency0: a, currency1: b } : { currency0: b, currency1: a };
1392
+ }
1393
+ function normalizePoolCurrency(raw) {
1394
+ const trimmed = raw.trim();
1395
+ if (!trimmed) {
1396
+ throw new Error("Pool token address is required.");
1397
+ }
1398
+ const lower = trimmed.toLowerCase();
1399
+ if (lower === "eth" || lower === "native" || lower === "native_eth" || lower === viem.zeroAddress.toLowerCase()) {
1400
+ return viem.zeroAddress;
1401
+ }
1402
+ return viem.getAddress(trimmed);
1403
+ }
1404
+ function computeUniswapV4PoolReference(args) {
1405
+ const { currency0, currency1 } = sortUniswapV4PoolCurrencies(
1406
+ args.token0Address,
1407
+ args.token1Address
1408
+ );
1409
+ const hooks = args.hooks?.trim() && args.hooks.trim() !== "0x" ? viem.getAddress(args.hooks.trim()) : ZERO_HOOKS;
1410
+ return viem.keccak256(
1411
+ viem.encodeAbiParameters(POOL_KEY_ABI, [
1412
+ currency0,
1413
+ currency1,
1414
+ args.fee,
1415
+ args.tickSpacing,
1416
+ hooks
1417
+ ])
1418
+ );
1419
+ }
1420
+
1421
+ // src/protocols/evm/uniswap-v4/knownLpPools.ts
1422
+ var ZERO_HOOKS2 = "0x0000000000000000000000000000000000000000";
1423
+ var UNISWAP_V4_LP_POOL_LOOKUP_HINT = "Pool may not be initialized on this chain. Call ctm_uniswap_v4_list_lp_pools for other presets, pass a custom existingPool.poolReference, or use newPool to initialize a pool.";
1424
+ var FEE_TIERS = [
1425
+ { fee: 500, feeLabel: "0.05%", tickSpacing: 10 },
1426
+ { fee: 3e3, feeLabel: "0.3%", tickSpacing: 60 },
1427
+ { fee: 1e4, feeLabel: "1%", tickSpacing: 200 }
1428
+ ];
1429
+ var CHAIN_LP_CONFIGS = [
1430
+ {
1431
+ chainId: 1,
1432
+ chainLabel: "Ethereum",
1433
+ nativeWrapped: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
1434
+ tokens: {
1435
+ eth: { symbol: "ETH", address: "0x0000000000000000000000000000000000000000", native: true },
1436
+ usdc: { symbol: "USDC", address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" },
1437
+ usdt: { symbol: "USDT", address: "0xdAC17F958D2ee523a2206206994597C13D831ec7" },
1438
+ wbtc: { symbol: "WBTC", address: "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599" }
1439
+ },
1440
+ pairs: [
1441
+ { slug: "eth-usdc", label: "ETH/USDC", token0Key: "eth", token1Key: "usdc", tiers: [...FEE_TIERS] },
1442
+ { slug: "eth-usdt", label: "ETH/USDT", token0Key: "eth", token1Key: "usdt", tiers: [...FEE_TIERS] },
1443
+ { slug: "eth-wbtc", label: "ETH/WBTC", token0Key: "eth", token1Key: "wbtc", tiers: [...FEE_TIERS] }
1444
+ ]
1445
+ },
1446
+ {
1447
+ chainId: 8453,
1448
+ chainLabel: "Base",
1449
+ nativeWrapped: "0x4200000000000000000000000000000000000006",
1450
+ tokens: {
1451
+ eth: { symbol: "ETH", address: "0x0000000000000000000000000000000000000000", native: true },
1452
+ usdc: { symbol: "USDC", address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" }
1453
+ },
1454
+ pairs: [
1455
+ { slug: "eth-usdc", label: "ETH/USDC", token0Key: "eth", token1Key: "usdc", tiers: [...FEE_TIERS] }
1456
+ ]
1457
+ },
1458
+ {
1459
+ chainId: 42161,
1460
+ chainLabel: "Arbitrum",
1461
+ nativeWrapped: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
1462
+ tokens: {
1463
+ eth: { symbol: "ETH", address: "0x0000000000000000000000000000000000000000", native: true },
1464
+ usdc: { symbol: "USDC", address: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831" }
1465
+ },
1466
+ pairs: [
1467
+ { slug: "eth-usdc", label: "ETH/USDC", token0Key: "eth", token1Key: "usdc", tiers: [...FEE_TIERS] }
1468
+ ]
1469
+ },
1470
+ {
1471
+ chainId: 10,
1472
+ chainLabel: "Optimism",
1473
+ nativeWrapped: "0x4200000000000000000000000000000000000006",
1474
+ tokens: {
1475
+ eth: { symbol: "ETH", address: "0x0000000000000000000000000000000000000000", native: true },
1476
+ usdc: { symbol: "USDC", address: "0x0b2C639c533813f4Aa9D7837CAa646c993D1B7926" }
1477
+ },
1478
+ pairs: [
1479
+ { slug: "eth-usdc", label: "ETH/USDC", token0Key: "eth", token1Key: "usdc", tiers: [...FEE_TIERS] }
1480
+ ]
1481
+ },
1482
+ {
1483
+ chainId: 137,
1484
+ chainLabel: "Polygon",
1485
+ nativeWrapped: "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619",
1486
+ tokens: {
1487
+ eth: { symbol: "ETH", address: "0x0000000000000000000000000000000000000000", native: true },
1488
+ usdc: { symbol: "USDC", address: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359" }
1489
+ },
1490
+ pairs: [
1491
+ { slug: "eth-usdc", label: "ETH/USDC", token0Key: "eth", token1Key: "usdc", tiers: [...FEE_TIERS] }
1492
+ ]
1493
+ }
1494
+ ];
1495
+ function buildPresetId(pairSlug, feeLabel) {
1496
+ const feeSlug = feeLabel.replace("%", "").replace(".", "-");
1497
+ return `${pairSlug}-${feeSlug}`;
1498
+ }
1499
+ function buildPoolRows(config) {
1500
+ const rows = [];
1501
+ for (const pair of config.pairs) {
1502
+ const token0 = config.tokens[pair.token0Key];
1503
+ const token1 = config.tokens[pair.token1Key];
1504
+ if (!token0 || !token1) continue;
1505
+ for (const tier of pair.tiers) {
1506
+ const poolReference = computeUniswapV4PoolReference({
1507
+ token0Address: token0.address,
1508
+ token1Address: token1.address,
1509
+ fee: tier.fee,
1510
+ tickSpacing: tier.tickSpacing,
1511
+ hooks: ZERO_HOOKS2
1512
+ });
1513
+ const usesNativeEth = Boolean(token0.native || token1.native);
1514
+ rows.push({
1515
+ presetId: buildPresetId(pair.slug, tier.feeLabel),
1516
+ pairSlug: pair.slug,
1517
+ pairLabel: pair.label,
1518
+ fee: tier.fee,
1519
+ feeLabel: tier.feeLabel,
1520
+ tickSpacing: tier.tickSpacing,
1521
+ token0Symbol: token0.symbol,
1522
+ token1Symbol: token1.symbol,
1523
+ token0Address: viem.getAddress(token0.address),
1524
+ token1Address: viem.getAddress(token1.address),
1525
+ poolReference,
1526
+ hooks: ZERO_HOOKS2,
1527
+ nativeWrapped: usesNativeEth ? viem.getAddress(config.nativeWrapped) : void 0,
1528
+ usesNativeEth
1529
+ });
1530
+ }
1531
+ }
1532
+ return rows;
1533
+ }
1534
+ function chainConfigOrThrow(chainId) {
1535
+ const config = CHAIN_LP_CONFIGS.find((row) => row.chainId === chainId);
1536
+ if (!config) {
1537
+ throw new Error(
1538
+ `No standard Uniswap V4 LP pool catalog for chainId ${chainId}. Supported catalog chains: ${CHAIN_LP_CONFIGS.map((c) => c.chainId).join(", ")}.`
1539
+ );
1540
+ }
1541
+ if (!isUniswapV4ChainSupported(chainId)) {
1542
+ throw new Error(`chainId ${chainId} is not supported for Uniswap V4 MCP tools.`);
1543
+ }
1544
+ return config;
1545
+ }
1546
+ function listUniswapV4StandardLpPools(args) {
1547
+ const chainId = parseUniswapChainId(args.chainId);
1548
+ const config = chainConfigOrThrow(chainId);
1549
+ let pools = buildPoolRows(config);
1550
+ const pairFilter = args.pair?.trim().toLowerCase();
1551
+ if (pairFilter) {
1552
+ pools = pools.filter(
1553
+ (row) => row.pairSlug.includes(pairFilter) || row.pairLabel.toLowerCase().includes(pairFilter) || row.presetId.includes(pairFilter)
1554
+ );
1555
+ }
1556
+ return {
1557
+ chainId,
1558
+ chainLabel: config.chainLabel,
1559
+ pools,
1560
+ notes: "poolReference is derived from token addresses, fee, tickSpacing, and hooks (no-hook pools). Pass presetId to ctm_uniswap_v4_lp_create_position as poolPreset, or copy existingPool fields. If LP create fails, the pool may not exist on-chain \u2014 try another preset, pass poolReference manually, or use newPool."
1561
+ };
1562
+ }
1563
+ function resolveUniswapV4LpPoolPreset(args) {
1564
+ const chainId = parseUniswapChainId(args.chainId);
1565
+ const preset = args.presetId.trim().toLowerCase();
1566
+ const row = buildPoolRows(chainConfigOrThrow(chainId)).find(
1567
+ (pool) => pool.presetId.toLowerCase() === preset
1568
+ );
1569
+ if (!row) {
1570
+ throw new Error(
1571
+ `Unknown LP pool preset "${args.presetId}" on chainId ${chainId}. Call ctm_uniswap_v4_list_lp_pools to list standard presets.`
1572
+ );
1573
+ }
1574
+ return row;
1575
+ }
1576
+ function resolveUniswapV4LpExistingPoolFromKey(args) {
1577
+ const poolReference = args.poolReference?.trim() || computeUniswapV4PoolReference({
1578
+ token0Address: args.token0Address,
1579
+ token1Address: args.token1Address,
1580
+ fee: args.fee,
1581
+ tickSpacing: args.tickSpacing,
1582
+ hooks: args.hooks
1583
+ });
1584
+ const sorted = sortTokensForExistingPool(args.token0Address, args.token1Address);
1585
+ return {
1586
+ token0Address: sorted.token0Address,
1587
+ token1Address: sorted.token1Address,
1588
+ poolReference
1589
+ };
1590
+ }
1591
+ function sortTokensForExistingPool(token0Address, token1Address) {
1592
+ const sorted = sortUniswapV4PoolCurrencies(token0Address, token1Address);
1593
+ return { token0Address: sorted.currency0, token1Address: sorted.currency1 };
1594
+ }
1595
+ function uniswapV4ListStandardLpPools(args) {
1596
+ return listUniswapV4StandardLpPools(args);
1597
+ }
1598
+
1599
+ // src/protocols/evm/uniswap-v4/liquidityApi.ts
1600
+ var LP_HEADERS_BASE = {
1601
+ "Content-Type": "application/json",
1602
+ Accept: "application/json",
1603
+ "User-Agent": "ctm-mpc-defi uniswapLpApi/1.0 (TS)"
1604
+ };
1605
+ function trimAddr2(a) {
1606
+ return a.trim();
1607
+ }
1608
+ function lpDeadlineUnix(nowSec = Math.floor(Date.now() / 1e3)) {
1609
+ return nowSec + UNISWAP_LP_DEFAULT_DEADLINE_SEC_OFFSET;
1610
+ }
1611
+ function resolveLpBaseUrl(baseUrl) {
1612
+ const raw = (baseUrl ?? UNISWAP_TRADE_BASE_DEFAULT).replace(/\/$/, "");
1613
+ return raw;
1614
+ }
1615
+ function resolveLpPath(baseUrl, action) {
1616
+ const normalized = baseUrl.replace(/\/$/, "");
1617
+ if (normalized.includes("api.uniswap.org")) {
1618
+ return `${normalized}/lp/${action}`;
1619
+ }
1620
+ return `${normalized}/lp/${action}`;
1621
+ }
1622
+ async function postUniswapLpApi(args) {
1623
+ const useProxy = args.useServerProxy !== false && typeof globalThis !== "undefined" && typeof globalThis.window !== "undefined";
1624
+ if (useProxy && args.proxyPath) {
1625
+ const fn2 = args.fetchImpl ?? globalThis.fetch;
1626
+ const res2 = await fn2(args.proxyPath, {
1627
+ method: "POST",
1628
+ headers: { "Content-Type": "application/json" },
1629
+ body: JSON.stringify({
1630
+ uniswapApiKey: args.uniswapApiKey,
1631
+ baseUrl: args.baseUrl,
1632
+ body: args.body
1633
+ }),
1634
+ credentials: "same-origin"
1635
+ });
1636
+ const text2 = await res2.text();
1637
+ if (!res2.ok) {
1638
+ let errMsg = res2.statusText;
1639
+ try {
1640
+ const j = JSON.parse(text2);
1641
+ if (j?.error?.trim()) errMsg = j.error.trim();
1642
+ } catch {
1643
+ if (text2.trim()) errMsg = text2.slice(0, 500);
1644
+ }
1645
+ throw new Error(`Uniswap LP proxy failed: ${errMsg}`);
1646
+ }
1647
+ return JSON.parse(text2);
1648
+ }
1649
+ const base = resolveLpBaseUrl(args.baseUrl);
1650
+ const url = resolveLpPath(base, args.path);
1651
+ const fn = args.fetchImpl ?? globalThis.fetch;
1652
+ const res = await fn(url, {
1653
+ method: "POST",
1654
+ headers: {
1655
+ ...LP_HEADERS_BASE,
1656
+ "x-api-key": args.uniswapApiKey.trim()
1657
+ },
1658
+ body: JSON.stringify(args.body)
1659
+ });
1660
+ const text = await res.text();
1661
+ if (!res.ok) {
1662
+ const base2 = messageFromUniswapHttpResponseBody(text, res.status, res.statusText);
1663
+ const hint = args.path === "create" && args.body.existingPool ? ` ${UNISWAP_V4_LP_POOL_LOOKUP_HINT}` : "";
1664
+ throw new Error(`Uniswap LP POST /${args.path} failed: ${base2}${hint}`);
1665
+ }
1666
+ return JSON.parse(text);
1667
+ }
1668
+ function extractUniswapLpTransaction(response, field) {
1669
+ const tx = response[field];
1670
+ if (!tx || typeof tx !== "object" || Array.isArray(tx)) {
1671
+ throw new Error(`Uniswap LP response missing \`${field}\` transaction object.`);
1672
+ }
1673
+ const o = tx;
1674
+ const to = String(o.to ?? "").trim();
1675
+ const data = String(o.data ?? "").trim();
1676
+ if (!to.startsWith("0x") || !data.startsWith("0x") || data === "0x") {
1677
+ throw new Error(`Uniswap LP \`${field}\` transaction has invalid to/data.`);
1678
+ }
1679
+ return {
1680
+ to,
1681
+ from: o.from != null ? String(o.from) : void 0,
1682
+ data,
1683
+ value: String(o.value ?? "0"),
1684
+ chainId: typeof o.chainId === "number" ? o.chainId : void 0,
1685
+ gasLimit: o.gasLimit != null ? String(o.gasLimit) : void 0,
1686
+ gasPrice: o.gasPrice != null ? String(o.gasPrice) : void 0,
1687
+ maxFeePerGas: o.maxFeePerGas != null ? String(o.maxFeePerGas) : void 0,
1688
+ maxPriorityFeePerGas: o.maxPriorityFeePerGas != null ? String(o.maxPriorityFeePerGas) : void 0
1689
+ };
1690
+ }
1691
+ function extractUniswapLpTokenAmounts(response) {
1692
+ const read = (key) => {
1693
+ const raw = response[key];
1694
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
1695
+ const o = raw;
1696
+ const tokenAddress = String(o.tokenAddress ?? o.token ?? "").trim();
1697
+ const amount = String(o.amount ?? "").trim();
1698
+ if (!tokenAddress.startsWith("0x") || !amount) return void 0;
1699
+ return { tokenAddress, amount };
1700
+ };
1701
+ return { token0: read("token0"), token1: read("token1") };
1702
+ }
1703
+ async function uniswapLpCreatePosition(args) {
1704
+ const body = {
1705
+ protocol: "V4",
1706
+ walletAddress: trimAddr2(args.walletAddress),
1707
+ chainId: args.chainId,
1708
+ independentToken: {
1709
+ tokenAddress: trimAddr2(args.independentToken.tokenAddress),
1710
+ amount: String(args.independentToken.amount).trim()
1711
+ },
1712
+ slippageTolerance: args.slippageTolerance ?? UNISWAP_LP_DEFAULT_SLIPPAGE_PERCENT,
1713
+ deadline: args.deadline ?? lpDeadlineUnix(),
1714
+ simulateTransaction: args.simulateTransaction ?? false
1715
+ };
1716
+ if (args.existingPool) {
1717
+ body.existingPool = {
1718
+ token0Address: trimAddr2(args.existingPool.token0Address),
1719
+ token1Address: trimAddr2(args.existingPool.token1Address),
1720
+ poolReference: trimAddr2(args.existingPool.poolReference)
1721
+ };
1722
+ }
1723
+ if (args.newPool) {
1724
+ body.newPool = {
1725
+ token0Address: trimAddr2(args.newPool.token0Address),
1726
+ token1Address: trimAddr2(args.newPool.token1Address),
1727
+ fee: args.newPool.fee,
1728
+ tickSpacing: args.newPool.tickSpacing,
1729
+ initialPrice: String(args.newPool.initialPrice).trim(),
1730
+ ...args.newPool.hooks ? { hooks: trimAddr2(args.newPool.hooks) } : {}
1731
+ };
1732
+ }
1733
+ if (!args.existingPool && !args.newPool) {
1734
+ throw new Error("Provide existingPool or newPool for LP create.");
1735
+ }
1736
+ if (args.priceBounds) {
1737
+ body.priceBounds = {
1738
+ minPrice: String(args.priceBounds.minPrice).trim(),
1739
+ maxPrice: String(args.priceBounds.maxPrice).trim()
1740
+ };
1741
+ }
1742
+ if (args.tickBounds) {
1743
+ body.tickBounds = {
1744
+ tickLower: args.tickBounds.tickLower,
1745
+ tickUpper: args.tickBounds.tickUpper
1746
+ };
1747
+ }
1748
+ if (!args.priceBounds && !args.tickBounds) {
1749
+ throw new Error("Provide priceBounds or tickBounds for LP create.");
1750
+ }
1751
+ if (args.batchPermitData) body.batchPermitData = args.batchPermitData;
1752
+ if (args.signature) body.signature = args.signature;
1753
+ return postUniswapLpApi({
1754
+ uniswapApiKey: args.uniswapApiKey,
1755
+ path: "create",
1756
+ body,
1757
+ baseUrl: args.baseUrl,
1758
+ fetchImpl: args.fetchImpl,
1759
+ useServerProxy: args.useServerProxy,
1760
+ proxyPath: "/api/uniswap/liquidity/create"
1761
+ });
1762
+ }
1763
+ async function uniswapLpIncreasePosition(args) {
1764
+ const body = {
1765
+ protocol: "V4",
1766
+ walletAddress: trimAddr2(args.walletAddress),
1767
+ chainId: args.chainId,
1768
+ token0Address: trimAddr2(args.token0Address),
1769
+ token1Address: trimAddr2(args.token1Address),
1770
+ nftTokenId: String(args.nftTokenId),
1771
+ independentToken: {
1772
+ tokenAddress: trimAddr2(args.independentToken.tokenAddress),
1773
+ amount: String(args.independentToken.amount).trim()
1774
+ },
1775
+ slippageTolerance: args.slippageTolerance ?? UNISWAP_LP_DEFAULT_SLIPPAGE_PERCENT,
1776
+ deadline: args.deadline ?? lpDeadlineUnix(),
1777
+ simulateTransaction: args.simulateTransaction ?? false
1778
+ };
1779
+ if (args.v4BatchPermitData) body.v4BatchPermitData = args.v4BatchPermitData;
1780
+ if (args.signature) body.signature = args.signature;
1781
+ return postUniswapLpApi({
1782
+ uniswapApiKey: args.uniswapApiKey,
1783
+ path: "increase",
1784
+ body,
1785
+ baseUrl: args.baseUrl,
1786
+ fetchImpl: args.fetchImpl,
1787
+ useServerProxy: args.useServerProxy,
1788
+ proxyPath: "/api/uniswap/liquidity/increase"
1789
+ });
1790
+ }
1791
+ async function uniswapLpDecreasePosition(args) {
1792
+ const pct = Math.trunc(args.liquidityPercentageToDecrease);
1793
+ if (!Number.isFinite(pct) || pct < 1 || pct > 100) {
1794
+ throw new Error("liquidityPercentageToDecrease must be an integer from 1 to 100.");
1795
+ }
1796
+ const body = {
1797
+ protocol: "V4",
1798
+ walletAddress: trimAddr2(args.walletAddress),
1799
+ chainId: args.chainId,
1800
+ token0Address: trimAddr2(args.token0Address),
1801
+ token1Address: trimAddr2(args.token1Address),
1802
+ nftTokenId: String(args.nftTokenId),
1803
+ liquidityPercentageToDecrease: pct,
1804
+ slippageTolerance: args.slippageTolerance ?? UNISWAP_LP_DEFAULT_SLIPPAGE_PERCENT,
1805
+ deadline: args.deadline ?? lpDeadlineUnix(),
1806
+ simulateTransaction: args.simulateTransaction ?? false
1807
+ };
1808
+ return postUniswapLpApi({
1809
+ uniswapApiKey: args.uniswapApiKey,
1810
+ path: "decrease",
1811
+ body,
1812
+ baseUrl: args.baseUrl,
1813
+ fetchImpl: args.fetchImpl,
1814
+ useServerProxy: args.useServerProxy,
1815
+ proxyPath: "/api/uniswap/liquidity/decrease"
1816
+ });
1817
+ }
1818
+ async function uniswapLpClaimFees(args) {
1819
+ const body = {
1820
+ protocol: "V4",
1821
+ walletAddress: trimAddr2(args.walletAddress),
1822
+ chainId: args.chainId,
1823
+ tokenId: String(args.tokenId),
1824
+ simulateTransaction: args.simulateTransaction ?? false
1825
+ };
1826
+ return postUniswapLpApi({
1827
+ uniswapApiKey: args.uniswapApiKey,
1828
+ path: "claim",
1829
+ body,
1830
+ baseUrl: args.baseUrl,
1831
+ fetchImpl: args.fetchImpl,
1832
+ useServerProxy: args.useServerProxy,
1833
+ proxyPath: "/api/uniswap/liquidity/claim"
1834
+ });
1835
+ }
1836
+ var TX_FIELD_BY_ACTION = {
1837
+ mint: "create",
1838
+ increase: "increase",
1839
+ decrease: "decrease",
1840
+ collect: "claim"
1841
+ };
1842
+ function uniswapLpTxFieldForAction(action) {
1843
+ return TX_FIELD_BY_ACTION[action];
1844
+ }
1845
+ function parseUniswapLpApiSnapshot(args) {
1846
+ const field = TX_FIELD_BY_ACTION[args.action];
1847
+ const transaction = extractUniswapLpTransaction(args.lpResponse, field);
1848
+ const amounts = extractUniswapLpTokenAmounts(args.lpResponse);
1849
+ const tickLower = typeof args.lpResponse.tickLower === "number" ? args.lpResponse.tickLower : void 0;
1850
+ const tickUpper = typeof args.lpResponse.tickUpper === "number" ? args.lpResponse.tickUpper : void 0;
1851
+ const minPrice = typeof args.lpResponse.minPrice === "string" ? args.lpResponse.minPrice : void 0;
1852
+ const maxPrice = typeof args.lpResponse.maxPrice === "string" ? args.lpResponse.maxPrice : void 0;
1853
+ return {
1854
+ transaction,
1855
+ token0: amounts.token0,
1856
+ token1: amounts.token1,
1857
+ tickLower,
1858
+ tickUpper,
1859
+ minPrice,
1860
+ maxPrice
1861
+ };
1862
+ }
1863
+ function formatUniswapLpAmountHuman(amountWei, decimals) {
1864
+ try {
1865
+ return viem.formatUnits(BigInt(amountWei), decimals);
1866
+ } catch {
1867
+ return amountWei;
1868
+ }
1869
+ }
1870
+ var erc721BalanceAbi = viem.parseAbi([
1871
+ "function balanceOf(address owner) view returns (uint256)",
1872
+ "function ownerOf(uint256 tokenId) view returns (address)"
1873
+ ]);
1874
+ var positionInfoAbi = viem.parseAbi([
1875
+ "function positionInfo(uint256 tokenId) view returns (uint256 info)"
1876
+ ]);
1877
+ var UNISWAP_V4_LP_POSITION_REGISTRY_HINT = "Add the position NFT to the node token registry (tokenType ERC721: Uniswap V4 Position Manager contract + tokenId). MCP: call ctm_uniswap_v4_register_position_nft (by tokenId) or ctm_uniswap_v4_register_position_from_mint_tx (after mint execute). Or use add_to_token_registry. In the Continuum app: Add Token (ERC721), or Manage liquidity \u2192 Refresh positions (blockchain scan).";
1878
+ function formatUniswapV4PositionNotFoundError(args) {
1879
+ return `Uniswap V4 position #${args.tokenId} is not in the node token registry for chain ${args.chainId}. ` + UNISWAP_V4_LP_POSITION_REGISTRY_HINT;
1880
+ }
1881
+ var positionManagerTransferEvent = viem.parseAbiItem(
1882
+ "event Transfer(address indexed from, address indexed to, uint256 indexed tokenId)"
1883
+ );
1884
+ function uniswapV4PositionMintedTokenIdsFromReceipt(receipt, positionManager, owner) {
1885
+ const pm = viem.getAddress(positionManager);
1886
+ const wallet = viem.getAddress(owner);
1887
+ const ids = [];
1888
+ for (const log of receipt.logs) {
1889
+ try {
1890
+ if (viem.getAddress(log.address) !== pm) continue;
1891
+ const decoded = viem.decodeEventLog({
1892
+ abi: [positionManagerTransferEvent],
1893
+ data: log.data,
1894
+ topics: log.topics
1895
+ });
1896
+ if (decoded.eventName !== "Transfer") continue;
1897
+ const from = decoded.args.from;
1898
+ const to = decoded.args.to;
1899
+ const tokenId = decoded.args.tokenId;
1900
+ if (from === viem.zeroAddress && viem.getAddress(to) === wallet) {
1901
+ ids.push(tokenId);
1902
+ }
1903
+ } catch {
1904
+ }
1905
+ }
1906
+ return ids;
1907
+ }
1908
+ function uniswapV4ListPositionsFromRegistryForMcp(args) {
1909
+ const chainId = typeof args.chainId === "number" ? args.chainId : Number.parseInt(String(args.chainId), 10);
1910
+ if (!Number.isFinite(chainId) || chainId <= 0) {
1911
+ throw new Error("chainId must be a positive integer");
1912
+ }
1913
+ const wallet = viem.getAddress(args.walletAddress);
1914
+ const pm = viem.getAddress(
1915
+ args.positionManagerAddress ? String(args.positionManagerAddress) : getUniswapV4PositionManagerOrThrow(chainId)
1916
+ );
1917
+ const pmLower = pm.toLowerCase();
1918
+ const positions = [];
1919
+ for (const row of args.erc721Tokens) {
1920
+ const addr = (row.contractAddress ?? "").trim();
1921
+ const tokenId = (row.tokenId ?? "").trim();
1922
+ if (!addr || !tokenId) continue;
1923
+ try {
1924
+ if (viem.getAddress(addr).toLowerCase() !== pmLower) continue;
1925
+ } catch {
1926
+ continue;
1927
+ }
1928
+ positions.push({
1929
+ tokenId,
1930
+ positionManager: pm,
1931
+ owner: wallet,
1932
+ name: row.name,
1933
+ symbol: row.symbol
1934
+ });
1935
+ }
1936
+ positions.sort((a, b) => BigInt(a.tokenId) < BigInt(b.tokenId) ? -1 : 1);
1937
+ return { positions, source: "token_registry" };
1938
+ }
1939
+ function throwIfScanAborted(signal) {
1940
+ if (signal?.aborted) {
1941
+ throw new DOMException("Position scan aborted.", "AbortError");
1942
+ }
1943
+ }
1944
+ var TRANSFER_EVENT = {
1945
+ type: "event",
1946
+ name: "Transfer",
1947
+ inputs: [
1948
+ { indexed: true, name: "from", type: "address" },
1949
+ { indexed: true, name: "to", type: "address" },
1950
+ { indexed: true, name: "tokenId", type: "uint256" }
1951
+ ]
1952
+ };
1953
+ function isEthGetLogsBlockRangeTooLargeError(err) {
1954
+ const msg = (err instanceof Error ? err.message : String(err)).toLowerCase();
1955
+ return msg.includes("block range too large") || msg.includes("maximum allowed") || msg.includes("query returned more than") || msg.includes("exceed maximum block range") || msg.includes("block range is too large");
1956
+ }
1957
+ async function getTransferLogsForWalletInRange(args) {
1958
+ const { client, positionManager, wallet, fromBlock, toBlock } = args;
1959
+ let chunkSize = args.chunkSize < UNISWAP_V4_LP_LOG_CHUNK_SIZE_MIN ? UNISWAP_V4_LP_LOG_CHUNK_SIZE_MIN : args.chunkSize;
1960
+ const out = [];
1961
+ let from = fromBlock;
1962
+ while (from <= toBlock) {
1963
+ let to = from + chunkSize - 1n > toBlock ? toBlock : from + chunkSize - 1n;
1964
+ for (; ; ) {
1965
+ try {
1966
+ const [toLogs, fromLogs] = await Promise.all([
1967
+ client.getLogs({
1968
+ address: positionManager,
1969
+ event: TRANSFER_EVENT,
1970
+ args: { to: wallet },
1971
+ fromBlock: from,
1972
+ toBlock: to
1973
+ }),
1974
+ client.getLogs({
1975
+ address: positionManager,
1976
+ event: TRANSFER_EVENT,
1977
+ args: { from: wallet },
1978
+ fromBlock: from,
1979
+ toBlock: to
1980
+ })
1981
+ ]);
1982
+ out.push(...toLogs, ...fromLogs);
1983
+ from = to + 1n;
1984
+ break;
1985
+ } catch (err) {
1986
+ if (!isEthGetLogsBlockRangeTooLargeError(err) || chunkSize <= UNISWAP_V4_LP_LOG_CHUNK_SIZE_MIN) {
1987
+ throw err;
1988
+ }
1989
+ chunkSize = chunkSize / 2n;
1990
+ if (chunkSize < UNISWAP_V4_LP_LOG_CHUNK_SIZE_MIN) {
1991
+ chunkSize = UNISWAP_V4_LP_LOG_CHUNK_SIZE_MIN;
1992
+ }
1993
+ to = from + chunkSize - 1n > toBlock ? toBlock : from + chunkSize - 1n;
1994
+ }
1995
+ }
1996
+ }
1997
+ return out;
1998
+ }
1999
+ function parseUniswapV4ScanFromDateYmd(fromDate) {
2000
+ const trimmed = fromDate.trim();
2001
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(trimmed)) {
2002
+ throw new Error("fromDate must be YYYY-MM-DD");
2003
+ }
2004
+ const ms = Date.parse(`${trimmed}T00:00:00.000Z`);
2005
+ if (!Number.isFinite(ms)) {
2006
+ throw new Error(`Invalid fromDate: ${fromDate}`);
2007
+ }
2008
+ return Math.floor(ms / 1e3);
2009
+ }
2010
+ async function resolveBlockAtOrAfterUnixTime(client, unixTime, bounds) {
2011
+ let lo = bounds.minBlock;
2012
+ let hi = bounds.maxBlock;
2013
+ let ans = hi;
2014
+ while (lo <= hi) {
2015
+ const mid = (lo + hi) / 2n;
2016
+ const block = await client.getBlock({ blockNumber: mid });
2017
+ const ts = Number(block.timestamp);
2018
+ if (ts >= unixTime) {
2019
+ ans = mid;
2020
+ if (mid === 0n) break;
2021
+ hi = mid - 1n;
2022
+ } else {
2023
+ lo = mid + 1n;
2024
+ }
2025
+ }
2026
+ return ans;
2027
+ }
2028
+ async function resolveUniswapV4PositionScanFromDate(args) {
2029
+ const unixTime = parseUniswapV4ScanFromDateYmd(args.fromDate);
2030
+ const chain = viem.defineChain({
2031
+ id: args.chainId,
2032
+ name: `uniswap-v4-${args.chainId}`,
2033
+ nativeCurrency: { name: "ETH", symbol: "ETH", decimals: 18 },
2034
+ rpcUrls: { default: { http: [args.rpcUrl] } }
2035
+ });
2036
+ const client = viem.createPublicClient({ chain, transport: viem.http(args.rpcUrl) });
2037
+ const latest = await client.getBlockNumber();
2038
+ const deploy = getUniswapV4PositionManagerDeployBlock(args.chainId) ?? 0n;
2039
+ const resolved = await resolveBlockAtOrAfterUnixTime(client, unixTime, {
2040
+ minBlock: deploy,
2041
+ maxBlock: latest
2042
+ });
2043
+ return resolved < deploy ? deploy : resolved;
2044
+ }
2045
+ function defaultScanFromBlock(args) {
2046
+ if (args.fromBlock != null) return args.fromBlock;
2047
+ const deploy = getUniswapV4PositionManagerDeployBlock(args.chainId);
2048
+ if (deploy != null) return deploy;
2049
+ return args.latest > args.maxBlocksToScan ? args.latest - args.maxBlocksToScan : 0n;
2050
+ }
2051
+ async function listUniswapV4PositionsForWallet(args) {
2052
+ throwIfScanAborted(args.signal);
2053
+ const wallet = viem.getAddress(args.walletAddress);
2054
+ const pm = viem.getAddress(
2055
+ args.positionManagerAddress ? String(args.positionManagerAddress) : getUniswapV4PositionManagerOrThrow(args.chainId)
2056
+ );
2057
+ const chain = viem.defineChain({
2058
+ id: args.chainId,
2059
+ name: `uniswap-v4-${args.chainId}`,
2060
+ nativeCurrency: { name: "ETH", symbol: "ETH", decimals: 18 },
2061
+ rpcUrls: { default: { http: [args.rpcUrl] } }
2062
+ });
2063
+ const client = viem.createPublicClient({ chain, transport: viem.http(args.rpcUrl) });
2064
+ const latest = await client.getBlockNumber();
2065
+ const maxScan = args.maxBlocksToScan ?? 500000n;
2066
+ const chunkSize = args.chunkSize ?? UNISWAP_V4_LP_LOG_CHUNK_SIZE_DEFAULT;
2067
+ const scanFrom = defaultScanFromBlock({
2068
+ chainId: args.chainId,
2069
+ latest,
2070
+ fromBlock: args.fromBlock,
2071
+ maxBlocksToScan: maxScan
2072
+ });
2073
+ const balance = await client.readContract({
2074
+ address: pm,
2075
+ abi: erc721BalanceAbi,
2076
+ functionName: "balanceOf",
2077
+ args: [wallet]
2078
+ });
2079
+ const targetCount = Number(balance);
2080
+ const emitProgress = (scanningFromBlock, scanningToBlock, foundCount) => {
2081
+ args.onProgress?.({
2082
+ latestBlock: latest.toString(),
2083
+ scanFromBlock: scanFrom.toString(),
2084
+ scanningFromBlock: scanningFromBlock.toString(),
2085
+ scanningToBlock: scanningToBlock.toString(),
2086
+ foundCount,
2087
+ targetCount
2088
+ });
2089
+ };
2090
+ if (balance === 0n) {
2091
+ emitProgress(latest, latest, 0);
2092
+ return [];
2093
+ }
2094
+ const candidates = /* @__PURE__ */ new Set();
2095
+ const verified = /* @__PURE__ */ new Map();
2096
+ let toBlock = latest;
2097
+ while (toBlock >= scanFrom && verified.size < targetCount) {
2098
+ throwIfScanAborted(args.signal);
2099
+ let fromBlock = toBlock >= chunkSize - 1n ? toBlock - chunkSize + 1n : 0n;
2100
+ if (fromBlock < scanFrom) fromBlock = scanFrom;
2101
+ emitProgress(fromBlock, toBlock, verified.size);
2102
+ const logs = await getTransferLogsForWalletInRange({
2103
+ client,
2104
+ positionManager: pm,
2105
+ wallet,
2106
+ fromBlock,
2107
+ toBlock,
2108
+ chunkSize
2109
+ });
2110
+ for (const log of logs) {
2111
+ const tokenId = log.args.tokenId?.toString();
2112
+ if (!tokenId) continue;
2113
+ const to = log.args.to != null ? viem.getAddress(log.args.to) : null;
2114
+ const from = log.args.from != null ? viem.getAddress(log.args.from) : null;
2115
+ if (to === wallet) candidates.add(tokenId);
2116
+ if (from === wallet) candidates.delete(tokenId);
2117
+ }
2118
+ for (const tokenId of candidates) {
2119
+ if (verified.has(tokenId)) continue;
2120
+ try {
2121
+ const owner = await client.readContract({
2122
+ address: pm,
2123
+ abi: erc721BalanceAbi,
2124
+ functionName: "ownerOf",
2125
+ args: [BigInt(tokenId)]
2126
+ });
2127
+ if (viem.getAddress(owner) !== wallet) continue;
2128
+ verified.set(tokenId, { tokenId, positionManager: pm, owner: wallet });
2129
+ if (verified.size >= targetCount) break;
2130
+ } catch {
2131
+ }
2132
+ }
2133
+ if (verified.size >= targetCount) break;
2134
+ if (fromBlock <= scanFrom) break;
2135
+ toBlock = fromBlock - 1n;
2136
+ }
2137
+ const out = [...verified.values()];
2138
+ out.sort((a, b) => BigInt(a.tokenId) < BigInt(b.tokenId) ? -1 : 1);
2139
+ return out;
2140
+ }
2141
+ async function readUniswapV4PositionInfoRaw(args) {
2142
+ const pm = viem.getAddress(
2143
+ args.positionManagerAddress ? String(args.positionManagerAddress) : getUniswapV4PositionManagerOrThrow(args.chainId)
2144
+ );
2145
+ const chain = viem.defineChain({
2146
+ id: args.chainId,
2147
+ name: `uniswap-v4-${args.chainId}`,
2148
+ nativeCurrency: { name: "ETH", symbol: "ETH", decimals: 18 },
2149
+ rpcUrls: { default: { http: [args.rpcUrl] } }
2150
+ });
2151
+ const client = viem.createPublicClient({ chain, transport: viem.http(args.rpcUrl) });
2152
+ const info = await client.readContract({
2153
+ address: pm,
2154
+ abi: positionInfoAbi,
2155
+ functionName: "positionInfo",
2156
+ args: [BigInt(args.tokenId)]
2157
+ });
2158
+ return { info, positionManager: pm };
2159
+ }
2160
+ async function uniswapV4ListPositionsForMcp(args) {
2161
+ const chainId = typeof args.chainId === "number" ? args.chainId : Number.parseInt(String(args.chainId), 10);
2162
+ if (!Number.isFinite(chainId) || chainId <= 0) {
2163
+ throw new Error("chainId must be a positive integer");
2164
+ }
2165
+ const fromBlock = args.fromBlock != null && String(args.fromBlock).trim() !== "" ? BigInt(String(args.fromBlock).trim()) : void 0;
2166
+ const positions = await listUniswapV4PositionsForWallet({
2167
+ chainId,
2168
+ rpcUrl: args.rpcUrl,
2169
+ walletAddress: args.walletAddress,
2170
+ positionManagerAddress: args.positionManagerAddress,
2171
+ fromBlock,
2172
+ onProgress: args.onProgress,
2173
+ signal: args.signal
2174
+ });
2175
+ return { positions };
2176
+ }
2177
+ function uniswapV4ListPositionsRegistryMcpPlaceholder() {
2178
+ throw new Error(
2179
+ "ctm_uniswap_v4_lp_list_positions must run via continuum-node-sdk MCP (token registry, no RPC scan)."
2180
+ );
2181
+ }
2182
+ function uniswapV4RegisterPositionNftPlaceholder() {
2183
+ throw new Error(
2184
+ "ctm_uniswap_v4_register_position_nft must run via continuum-node-sdk MCP (management-signed addToken)."
2185
+ );
2186
+ }
2187
+ function uniswapV4RegisterPositionFromMintTxPlaceholder() {
2188
+ throw new Error(
2189
+ "ctm_uniswap_v4_register_position_from_mint_tx must run via continuum-node-sdk MCP (management-signed addToken)."
2190
+ );
2191
+ }
2192
+ function isNativeUniswapLpTokenAddress(token) {
2193
+ try {
2194
+ return viem.getAddress(token) === viem.zeroAddress;
2195
+ } catch {
2196
+ return token.toLowerCase() === viem.zeroAddress.toLowerCase();
2197
+ }
2198
+ }
2199
+
2200
+ // src/protocols/evm/uniswap-v4/liquidityMultisign.ts
2201
+ var wethDepositAbi = viem.parseAbi(["function deposit() payable"]);
2202
+ var erc20AllowanceAbi = viem.parseAbi([
2203
+ "function allowance(address owner, address spender) view returns (uint256)",
2204
+ "function decimals() view returns (uint8)"
2205
+ ]);
2206
+ function parseOptionalGasLimitString2(raw) {
2207
+ if (raw == null) return null;
2208
+ const s = String(raw).trim();
2209
+ if (!s) return null;
2210
+ try {
2211
+ if (/^0x[0-9a-fA-F]+$/.test(s)) return BigInt(s);
2212
+ return BigInt(s);
2213
+ } catch {
2214
+ return null;
2215
+ }
2216
+ }
2217
+ function parseTxValueWei(tx) {
2218
+ const raw = tx.value ?? "0";
2219
+ try {
2220
+ if (typeof raw === "string" && /^0x[0-9a-fA-F]+$/.test(raw.trim())) return BigInt(raw.trim());
2221
+ return BigInt(String(raw).trim() || "0");
2222
+ } catch {
2223
+ return 0n;
2224
+ }
2225
+ }
2226
+ function dataHexFromTx(tx) {
2227
+ const d = (tx.data ?? "0x").toString().trim();
2228
+ return d.startsWith("0x") ? d : `0x${d}`;
2229
+ }
2230
+ function parseExtraJsonObject2(detail) {
2231
+ if (!detail) return null;
2232
+ const raw = detail.ExtraJSON ?? detail.extraJSON;
2233
+ if (raw == null) return null;
2234
+ if (typeof raw === "object" && !Array.isArray(raw)) return raw;
2235
+ if (typeof raw === "string" && raw.trim()) {
2236
+ try {
2237
+ const p = JSON.parse(raw);
2238
+ if (p && typeof p === "object" && !Array.isArray(p)) return p;
2239
+ } catch {
2240
+ return null;
2241
+ }
2242
+ }
2243
+ return null;
2244
+ }
2245
+ function uniswapV4LiquidityEvmTypeFromBatchMeta(ex, batchIndex) {
2246
+ if (!ex) return false;
2247
+ const bm = ex.batchMeta;
2248
+ if (!Array.isArray(bm) || !bm[batchIndex] || typeof bm[batchIndex] !== "object" || Array.isArray(bm[batchIndex])) {
2249
+ return false;
2250
+ }
2251
+ const evm0 = bm[batchIndex].evm;
2252
+ if (!evm0 || typeof evm0 !== "object" || Array.isArray(evm0)) return false;
2253
+ return String(evm0.type ?? "") === "uniswap_v4_liquidity_tx";
2254
+ }
2255
+ function isUniswapV4LiquidityEvmSignRequest(detail, batchIndex) {
2256
+ const ex = parseExtraJsonObject2(detail);
2257
+ if (batchIndex != null && batchIndex >= 0) {
2258
+ if (uniswapV4LiquidityEvmTypeFromBatchMeta(ex, batchIndex)) return true;
2259
+ } else if (uniswapV4LiquidityEvmTypeFromBatchMeta(ex, 0)) {
2260
+ return true;
2261
+ }
2262
+ const evm = ex?.evm;
2263
+ if (!evm || typeof evm !== "object" || Array.isArray(evm)) return false;
2264
+ return String(evm.type ?? "") === "uniswap_v4_liquidity_tx";
2265
+ }
2266
+ function defaultGasForAction(action) {
2267
+ switch (action) {
2268
+ case "mint":
2269
+ return UNISWAP_V4_LP_MINT_DEFAULT_GAS_UNITS;
2270
+ case "increase":
2271
+ return UNISWAP_V4_LP_INCREASE_DEFAULT_GAS_UNITS;
2272
+ case "decrease":
2273
+ return UNISWAP_V4_LP_DECREASE_DEFAULT_GAS_UNITS;
2274
+ case "collect":
2275
+ return UNISWAP_V4_LP_COLLECT_DEFAULT_GAS_UNITS;
2276
+ default:
2277
+ return UNISWAP_V4_LP_MINT_DEFAULT_GAS_UNITS;
2278
+ }
2279
+ }
2280
+ async function resolveApproveTargets(args) {
2281
+ const out = [];
2282
+ const pairs = [args.token0, args.token1].filter(Boolean);
2283
+ for (const row of pairs) {
2284
+ const amt = BigInt(row.amount);
2285
+ if (amt <= 0n) continue;
2286
+ if (isNativeUniswapLpTokenAddress(row.tokenAddress)) {
2287
+ if (!args.nativeWrapped) {
2288
+ throw new Error("nativeWrapped is required when LP uses native ETH (0x0) token.");
2289
+ }
2290
+ out.push({ token: viem.getAddress(args.nativeWrapped), amount: amt, kind: "weth_deposit" });
2291
+ continue;
2292
+ }
2293
+ out.push({ token: viem.getAddress(row.tokenAddress), amount: amt, kind: "approve" });
2294
+ }
2295
+ const deduped = [];
2296
+ for (const row of out) {
2297
+ const existing = deduped.find((d) => d.token === row.token && d.kind === row.kind);
2298
+ if (existing) {
2299
+ if (row.amount > existing.amount) existing.amount = row.amount;
2300
+ } else {
2301
+ deduped.push({ ...row });
2302
+ }
2303
+ }
2304
+ const steps = [];
2305
+ for (const row of deduped) {
2306
+ if (row.kind === "weth_deposit") {
2307
+ steps.push(row);
2308
+ continue;
2309
+ }
2310
+ const allowance = await args.publicClient.readContract({
2311
+ address: row.token,
2312
+ abi: erc20AllowanceAbi,
2313
+ functionName: "allowance",
2314
+ args: [args.executor, args.spender]
2315
+ });
2316
+ if (allowance < row.amount) {
2317
+ steps.push(row);
2318
+ }
2319
+ }
2320
+ return steps;
2321
+ }
2322
+ async function buildEvmMultisignBodyUniswapV4LiquidityBatchInternal(args) {
2323
+ const parsed = parseUniswapLpApiSnapshot({ action: args.action, lpResponse: args.lpResponse });
2324
+ const tx = parsed.transaction;
2325
+ const to = viem.getAddress(tx.to);
2326
+ const dataHex = dataHexFromTx(tx);
2327
+ const valueWei = parseTxValueWei(tx);
2328
+ const executor = viem.getAddress(args.executorAddress);
2329
+ const spender = to;
2330
+ const chain = viem.defineChain({
2331
+ id: args.chainId,
2332
+ name: `uniswap-v4-lp-${args.chainId}`,
2333
+ nativeCurrency: { name: "ETH", symbol: "ETH", decimals: 18 },
2334
+ rpcUrls: { default: { http: [args.rpcUrl] } }
2335
+ });
2336
+ const publicClient = viem.createPublicClient({ chain, transport: viem.http(args.rpcUrl) });
2337
+ const approveTargets = await resolveApproveTargets({
2338
+ publicClient,
2339
+ executor,
2340
+ spender,
2341
+ token0: parsed.token0,
2342
+ token1: parsed.token1,
2343
+ nativeWrapped: args.nativeWrapped
2344
+ });
2345
+ const steps = [];
2346
+ for (const target of approveTargets) {
2347
+ if (target.kind === "weth_deposit") {
2348
+ steps.push({
2349
+ to: target.token,
2350
+ data: viem.encodeFunctionData({ abi: wethDepositAbi, functionName: "deposit" }),
2351
+ value: target.amount,
2352
+ fallbackGas: UNISWAP_V4_LP_WETH_DEPOSIT_FALLBACK
2353
+ });
2354
+ steps.push({
2355
+ to: target.token,
2356
+ data: viem.encodeFunctionData({
2357
+ abi: viem.erc20Abi,
2358
+ functionName: "approve",
2359
+ args: [spender, target.amount]
2360
+ }),
2361
+ value: 0n,
2362
+ fallbackGas: UNISWAP_V4_LP_ERC20_APPROVE_FALLBACK
2363
+ });
2364
+ } else {
2365
+ steps.push({
2366
+ to: target.token,
2367
+ data: viem.encodeFunctionData({
2368
+ abi: viem.erc20Abi,
2369
+ functionName: "approve",
2370
+ args: [spender, target.amount]
2371
+ }),
2372
+ value: 0n,
2373
+ fallbackGas: UNISWAP_V4_LP_ERC20_APPROVE_FALLBACK
2374
+ });
2375
+ }
2376
+ }
2377
+ const lpFallbackGas = defaultGasForAction(args.action);
2378
+ const fromTradeApi = parseOptionalGasLimitString2(tx.gasLimit) ?? parseOptionalGasLimitString2(tx.gas);
2379
+ steps.push({
2380
+ to,
2381
+ data: dataHex,
2382
+ value: valueWei,
2383
+ fallbackGas: fromTradeApi != null && fromTradeApi > 0n ? fromTradeApi : lpFallbackGas
2384
+ });
2385
+ const actionLabel = args.action === "mint" ? "mint liquidity" : args.action === "increase" ? "increase liquidity" : args.action === "decrease" ? "decrease liquidity" : "collect fees";
2386
+ const dataNo0x = dataHex.startsWith("0x") ? dataHex.slice(2) : dataHex;
2387
+ const lpIndex = steps.length - 1;
2388
+ return buildEvmMultisignBatch({
2389
+ context: {
2390
+ chainCategory: "evm",
2391
+ keyGen: args.keyGen,
2392
+ purposeText: args.purposeText,
2393
+ chainId: args.chainId,
2394
+ rpcUrl: args.rpcUrl,
2395
+ executorAddress: args.executorAddress,
2396
+ chainDetail: args.chainDetail,
2397
+ useCustomGas: args.useCustomGas,
2398
+ customGasChainDetails: args.customGasChainDetails
2399
+ },
2400
+ steps,
2401
+ purposeSuffix: `Uniswap V4: ${steps.length}-tx batch \u2014 ${actionLabel} (classic ERC-20 approve + Position Manager).`,
2402
+ firstMsgRawNo0x: dataNo0x,
2403
+ destinationAddress: to,
2404
+ buildBatchMeta: ({ index }) => {
2405
+ const isLpStep = index === lpIndex;
2406
+ return {
2407
+ signatureText: JSON.stringify({
2408
+ kind: "UniswapV4Liquidity",
2409
+ action: args.action,
2410
+ step: index,
2411
+ lpTx: isLpStep
2412
+ }),
2413
+ ...isLpStep ? {
2414
+ evm: { type: "uniswap_v4_liquidity_tx", version: 1, chainId: String(args.chainId) },
2415
+ uniswapV4Liquidity: {
2416
+ action: args.action,
2417
+ skipPermit2Batch: true,
2418
+ nftTokenId: args.nftTokenId != null ? String(args.nftTokenId) : void 0,
2419
+ poolReference: args.poolReference,
2420
+ lpResponseSnapshot: args.lpResponse,
2421
+ token0: parsed.token0,
2422
+ token1: parsed.token1,
2423
+ tickLower: parsed.tickLower,
2424
+ tickUpper: parsed.tickUpper,
2425
+ transaction: {
2426
+ to: tx.to,
2427
+ value: tx.value,
2428
+ dataNibbles: dataNo0x.length,
2429
+ gasLimit: tx.gasLimit
2430
+ },
2431
+ originalPurpose: args.purposeText
2432
+ }
2433
+ } : {}
2434
+ };
2435
+ }
2436
+ });
2437
+ }
2438
+ async function buildEvmMultisignBodyUniswapV4MintLiquidityBatch(args) {
2439
+ return buildEvmMultisignBodyUniswapV4LiquidityBatchInternal({ ...args, action: "mint" });
2440
+ }
2441
+ async function buildEvmMultisignBodyUniswapV4IncreaseLiquidityBatch(args) {
2442
+ return buildEvmMultisignBodyUniswapV4LiquidityBatchInternal({ ...args, action: "increase" });
2443
+ }
2444
+ async function buildEvmMultisignBodyUniswapV4DecreaseLiquidityBatch(args) {
2445
+ return buildEvmMultisignBodyUniswapV4LiquidityBatchInternal({ ...args, action: "decrease" });
2446
+ }
2447
+ async function buildEvmMultisignBodyUniswapV4CollectFeesBatch(args) {
2448
+ return buildEvmMultisignBodyUniswapV4LiquidityBatchInternal({ ...args, action: "collect" });
2449
+ }
1326
2450
 
1327
2451
  // src/protocols/evm/uniswap-v4/support.ts
1328
2452
  function computeUniswapV4Session(args) {
@@ -1427,6 +2551,52 @@ var uniswapV4ProtocolModule = {
1427
2551
  amount: { type: "string", required: true, description: "Amount for quote" },
1428
2552
  type: { type: "EXACT_INPUT | EXACT_OUTPUT", required: true, description: "Trade type" }
1429
2553
  }
2554
+ },
2555
+ {
2556
+ id: "uniswap-v4.mint-liquidity",
2557
+ protocolId: UNISWAP_V4_PROTOCOL_ID,
2558
+ chainCategory: "evm",
2559
+ description: "Mint a new Uniswap V4 concentrated liquidity position (Position Manager NFT)",
2560
+ commonParams: ["keyGen", "purposeText", "useCustomGas"],
2561
+ params: {
2562
+ lpResponse: { type: "object", required: true, description: "Full LP API create response" },
2563
+ nativeWrapped: { type: "address", required: false, description: "WETH when pool uses native ETH" },
2564
+ poolReference: { type: "string", required: false, description: "V4 pool id" },
2565
+ uniswapApiKey: { type: "string", required: true, description: "Uniswap API key" }
2566
+ }
2567
+ },
2568
+ {
2569
+ id: "uniswap-v4.increase-liquidity",
2570
+ protocolId: UNISWAP_V4_PROTOCOL_ID,
2571
+ chainCategory: "evm",
2572
+ description: "Increase liquidity on an existing Uniswap V4 position NFT",
2573
+ commonParams: ["keyGen", "purposeText", "useCustomGas"],
2574
+ params: {
2575
+ nftTokenId: { type: "string", required: true, description: "Position NFT token id" },
2576
+ lpResponse: { type: "object", required: true, description: "Full LP API increase response" }
2577
+ }
2578
+ },
2579
+ {
2580
+ id: "uniswap-v4.decrease-liquidity",
2581
+ protocolId: UNISWAP_V4_PROTOCOL_ID,
2582
+ chainCategory: "evm",
2583
+ description: "Decrease liquidity on an existing Uniswap V4 position NFT",
2584
+ commonParams: ["keyGen", "purposeText", "useCustomGas"],
2585
+ params: {
2586
+ nftTokenId: { type: "string", required: true, description: "Position NFT token id" },
2587
+ lpResponse: { type: "object", required: true, description: "Full LP API decrease response" }
2588
+ }
2589
+ },
2590
+ {
2591
+ id: "uniswap-v4.collect-fees",
2592
+ protocolId: UNISWAP_V4_PROTOCOL_ID,
2593
+ chainCategory: "evm",
2594
+ description: "Collect accrued fees from a Uniswap V4 position NFT",
2595
+ commonParams: ["keyGen", "purposeText", "useCustomGas"],
2596
+ params: {
2597
+ nftTokenId: { type: "string", required: true, description: "Position NFT token id" },
2598
+ lpResponse: { type: "object", required: true, description: "Full LP API claim response" }
2599
+ }
1430
2600
  }
1431
2601
  ]
1432
2602
  };
@@ -1438,48 +2608,108 @@ var uniswapV4 = {
1438
2608
  swapFromQuote,
1439
2609
  buildSwapMultisignBody: buildEvmMultisignBodyUniswapV4SkipPermit2Batch,
1440
2610
  quote: uniswapTradeQuote,
2611
+ createLiquidityPosition: uniswapLpCreatePosition,
2612
+ increaseLiquidityPosition: uniswapLpIncreasePosition,
2613
+ decreaseLiquidityPosition: uniswapLpDecreasePosition,
2614
+ claimLiquidityFees: uniswapLpClaimFees,
2615
+ buildMintLiquidityMultisignBody: buildEvmMultisignBodyUniswapV4MintLiquidityBatch,
2616
+ buildIncreaseLiquidityMultisignBody: buildEvmMultisignBodyUniswapV4IncreaseLiquidityBatch,
2617
+ buildDecreaseLiquidityMultisignBody: buildEvmMultisignBodyUniswapV4DecreaseLiquidityBatch,
2618
+ buildCollectFeesMultisignBody: buildEvmMultisignBodyUniswapV4CollectFeesBatch,
2619
+ listPositions: listUniswapV4PositionsForWallet,
1441
2620
  isChainSupported: isUniswapV4ChainSupported
1442
2621
  };
1443
2622
 
1444
2623
  exports.MAX_UINT160 = MAX_UINT160;
1445
2624
  exports.MAX_UINT48 = MAX_UINT48;
1446
2625
  exports.PERMIT2_ADDRESS = PERMIT2_ADDRESS;
2626
+ exports.UNISWAP_LP_API_BASE_DEFAULT = UNISWAP_LP_API_BASE_DEFAULT;
2627
+ exports.UNISWAP_LP_DEFAULT_DEADLINE_SEC_OFFSET = UNISWAP_LP_DEFAULT_DEADLINE_SEC_OFFSET;
2628
+ exports.UNISWAP_LP_DEFAULT_EXPIRY_MINUTES = UNISWAP_LP_DEFAULT_EXPIRY_MINUTES;
2629
+ exports.UNISWAP_LP_DEFAULT_SLIPPAGE_PERCENT = UNISWAP_LP_DEFAULT_SLIPPAGE_PERCENT;
1447
2630
  exports.UNISWAP_SWAP_DEFAULT_DEADLINE_SEC_OFFSET = UNISWAP_SWAP_DEFAULT_DEADLINE_SEC_OFFSET;
1448
2631
  exports.UNISWAP_SWAP_DEFAULT_EXPIRY_MINUTES = UNISWAP_SWAP_DEFAULT_EXPIRY_MINUTES;
1449
2632
  exports.UNISWAP_TRADE_BASE_DEFAULT = UNISWAP_TRADE_BASE_DEFAULT;
1450
2633
  exports.UNISWAP_UNIVERSAL_ROUTER_DEFAULT_GAS_UNITS = UNISWAP_UNIVERSAL_ROUTER_DEFAULT_GAS_UNITS;
1451
2634
  exports.UNISWAP_UNIVERSAL_ROUTER_VERSION_DEFAULT = UNISWAP_UNIVERSAL_ROUTER_VERSION_DEFAULT;
2635
+ exports.UNISWAP_V4_LP_COLLECT_DEFAULT_GAS_UNITS = UNISWAP_V4_LP_COLLECT_DEFAULT_GAS_UNITS;
2636
+ exports.UNISWAP_V4_LP_DECREASE_DEFAULT_GAS_UNITS = UNISWAP_V4_LP_DECREASE_DEFAULT_GAS_UNITS;
2637
+ exports.UNISWAP_V4_LP_ERC20_APPROVE_FALLBACK = UNISWAP_V4_LP_ERC20_APPROVE_FALLBACK;
2638
+ exports.UNISWAP_V4_LP_INCREASE_DEFAULT_GAS_UNITS = UNISWAP_V4_LP_INCREASE_DEFAULT_GAS_UNITS;
2639
+ exports.UNISWAP_V4_LP_LOG_CHUNK_SIZE_DEFAULT = UNISWAP_V4_LP_LOG_CHUNK_SIZE_DEFAULT;
2640
+ exports.UNISWAP_V4_LP_LOG_CHUNK_SIZE_MIN = UNISWAP_V4_LP_LOG_CHUNK_SIZE_MIN;
2641
+ exports.UNISWAP_V4_LP_MINT_DEFAULT_GAS_UNITS = UNISWAP_V4_LP_MINT_DEFAULT_GAS_UNITS;
2642
+ exports.UNISWAP_V4_LP_POOL_LOOKUP_HINT = UNISWAP_V4_LP_POOL_LOOKUP_HINT;
2643
+ exports.UNISWAP_V4_LP_POSITION_REGISTRY_HINT = UNISWAP_V4_LP_POSITION_REGISTRY_HINT;
2644
+ exports.UNISWAP_V4_LP_WETH_DEPOSIT_FALLBACK = UNISWAP_V4_LP_WETH_DEPOSIT_FALLBACK;
1452
2645
  exports.UNISWAP_V4_PROTOCOL_ID = UNISWAP_V4_PROTOCOL_ID;
1453
2646
  exports.applySlippagePercentToApproveWei = applySlippagePercentToApproveWei;
2647
+ exports.buildEvmMultisignBodyUniswapV4CollectFeesBatch = buildEvmMultisignBodyUniswapV4CollectFeesBatch;
2648
+ exports.buildEvmMultisignBodyUniswapV4DecreaseLiquidityBatch = buildEvmMultisignBodyUniswapV4DecreaseLiquidityBatch;
2649
+ exports.buildEvmMultisignBodyUniswapV4IncreaseLiquidityBatch = buildEvmMultisignBodyUniswapV4IncreaseLiquidityBatch;
2650
+ exports.buildEvmMultisignBodyUniswapV4MintLiquidityBatch = buildEvmMultisignBodyUniswapV4MintLiquidityBatch;
1454
2651
  exports.buildEvmMultisignBodyUniswapV4SkipPermit2Batch = buildEvmMultisignBodyUniswapV4SkipPermit2Batch;
1455
2652
  exports.buildUniswapQuoteRequestBody = buildUniswapQuoteRequestBody;
1456
2653
  exports.buildUniswapV4PurposePrefill = buildUniswapV4PurposePrefill;
2654
+ exports.computeUniswapV4PoolReference = computeUniswapV4PoolReference;
1457
2655
  exports.computeUniswapV4Session = computeUniswapV4Session;
1458
2656
  exports.createSwap = createSwap;
1459
2657
  exports.errorMessageFromUniswapJsonBody = errorMessageFromUniswapJsonBody;
2658
+ exports.extractUniswapLpTokenAmounts = extractUniswapLpTokenAmounts;
2659
+ exports.extractUniswapLpTransaction = extractUniswapLpTransaction;
1460
2660
  exports.fetchEthereumAddressForKeyGen = fetchEthereumAddressForKeyGen;
1461
2661
  exports.formatUniswapAmountFieldFromWei = formatUniswapAmountFieldFromWei;
2662
+ exports.formatUniswapLpAmountHuman = formatUniswapLpAmountHuman;
1462
2663
  exports.formatUniswapPercentForUi = formatUniswapPercentForUi;
1463
2664
  exports.formatUniswapQuoteForDisplay = formatUniswapQuoteForDisplay;
2665
+ exports.formatUniswapV4PositionNotFoundError = formatUniswapV4PositionNotFoundError;
1464
2666
  exports.getClassicQuoteFromStoredUniswapResponse = getClassicQuoteFromStoredUniswapResponse;
1465
2667
  exports.getUniswapUniversalRouterSpenderOrThrow = getUniswapUniversalRouterSpenderOrThrow;
2668
+ exports.getUniswapV4PositionManagerDeployBlock = getUniswapV4PositionManagerDeployBlock;
2669
+ exports.getUniswapV4PositionManagerOrThrow = getUniswapV4PositionManagerOrThrow;
2670
+ exports.isEthGetLogsBlockRangeTooLargeError = isEthGetLogsBlockRangeTooLargeError;
2671
+ exports.isNativeUniswapLpTokenAddress = isNativeUniswapLpTokenAddress;
1466
2672
  exports.isUniswapFullQuoteResponseNativeIn = isUniswapFullQuoteResponseNativeIn;
1467
2673
  exports.isUniswapTokenInAddressNative = isUniswapTokenInAddressNative;
1468
2674
  exports.isUniswapV4ChainSupported = isUniswapV4ChainSupported;
2675
+ exports.isUniswapV4LiquidityEvmSignRequest = isUniswapV4LiquidityEvmSignRequest;
1469
2676
  exports.isUniswapV4SwapEvmSignRequest = isUniswapV4SwapEvmSignRequest;
2677
+ exports.listUniswapV4PositionsForWallet = listUniswapV4PositionsForWallet;
2678
+ exports.listUniswapV4StandardLpPools = listUniswapV4StandardLpPools;
1470
2679
  exports.messageFromUniswapHttpResponseBody = messageFromUniswapHttpResponseBody;
1471
2680
  exports.parseUniswapChainId = parseUniswapChainId;
2681
+ exports.parseUniswapLpApiSnapshot = parseUniswapLpApiSnapshot;
1472
2682
  exports.parseUniswapQuoteClassicInOut = parseUniswapQuoteClassicInOut;
1473
2683
  exports.parseUniswapQuoteSlippageInfo = parseUniswapQuoteSlippageInfo;
2684
+ exports.parseUniswapV4ScanFromDateYmd = parseUniswapV4ScanFromDateYmd;
1474
2685
  exports.quoteSwap = quoteSwap;
2686
+ exports.readUniswapV4PositionInfoRaw = readUniswapV4PositionInfoRaw;
2687
+ exports.resolveBlockAtOrAfterUnixTime = resolveBlockAtOrAfterUnixTime;
1475
2688
  exports.resolveRouterSwapGasUnitsFromSignRequest = resolveRouterSwapGasUnitsFromSignRequest;
2689
+ exports.resolveUniswapV4LpExistingPoolFromKey = resolveUniswapV4LpExistingPoolFromKey;
2690
+ exports.resolveUniswapV4LpPoolPreset = resolveUniswapV4LpPoolPreset;
2691
+ exports.resolveUniswapV4PositionScanFromDate = resolveUniswapV4PositionScanFromDate;
2692
+ exports.sortUniswapV4PoolCurrencies = sortUniswapV4PoolCurrencies;
1476
2693
  exports.swapExactInput = swapExactInput;
1477
2694
  exports.swapFromQuote = swapFromQuote;
1478
2695
  exports.swapTransactionDeadlineUnixFromExpiryMinutes = swapTransactionDeadlineUnixFromExpiryMinutes;
2696
+ exports.tryGetUniswapV4PositionManager = tryGetUniswapV4PositionManager;
1479
2697
  exports.uniswapCreateSwap = uniswapCreateSwap;
2698
+ exports.uniswapLpClaimFees = uniswapLpClaimFees;
2699
+ exports.uniswapLpCreatePosition = uniswapLpCreatePosition;
2700
+ exports.uniswapLpDecreasePosition = uniswapLpDecreasePosition;
2701
+ exports.uniswapLpIncreasePosition = uniswapLpIncreasePosition;
2702
+ exports.uniswapLpTxFieldForAction = uniswapLpTxFieldForAction;
1480
2703
  exports.uniswapQuoteToJsonQuoteOneLine = uniswapQuoteToJsonQuoteOneLine;
1481
2704
  exports.uniswapTradeQuote = uniswapTradeQuote;
1482
2705
  exports.uniswapV4 = uniswapV4;
2706
+ exports.uniswapV4ListPositionsForMcp = uniswapV4ListPositionsForMcp;
2707
+ exports.uniswapV4ListPositionsFromRegistryForMcp = uniswapV4ListPositionsFromRegistryForMcp;
2708
+ exports.uniswapV4ListPositionsRegistryMcpPlaceholder = uniswapV4ListPositionsRegistryMcpPlaceholder;
2709
+ exports.uniswapV4ListStandardLpPools = uniswapV4ListStandardLpPools;
2710
+ exports.uniswapV4PositionMintedTokenIdsFromReceipt = uniswapV4PositionMintedTokenIdsFromReceipt;
1483
2711
  exports.uniswapV4ProtocolModule = uniswapV4ProtocolModule;
2712
+ exports.uniswapV4RegisterPositionFromMintTxPlaceholder = uniswapV4RegisterPositionFromMintTxPlaceholder;
2713
+ exports.uniswapV4RegisterPositionNftPlaceholder = uniswapV4RegisterPositionNftPlaceholder;
1484
2714
  //# sourceMappingURL=index.cjs.map
1485
2715
  //# sourceMappingURL=index.cjs.map