@continuumdao/ctm-mpc-defi 0.2.61 → 0.2.63

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 (32) hide show
  1. package/dist/agent/catalog.cjs +328 -78
  2. package/dist/agent/catalog.cjs.map +1 -1
  3. package/dist/agent/catalog.d.ts +217 -27
  4. package/dist/agent/catalog.js +324 -79
  5. package/dist/agent/catalog.js.map +1 -1
  6. package/dist/agent/skills/aerodrome/SKILL.md +8 -8
  7. package/dist/agent/skills/railgun/SKILL.md +10 -4
  8. package/dist/agent/skills/yield-compare/SKILL.md +5 -5
  9. package/dist/index.cjs +5 -4
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.js +5 -4
  12. package/dist/index.js.map +1 -1
  13. package/dist/protocols/evm/aerodrome/index.cjs +476 -282
  14. package/dist/protocols/evm/aerodrome/index.cjs.map +1 -1
  15. package/dist/protocols/evm/aerodrome/index.d.ts +38 -13
  16. package/dist/protocols/evm/aerodrome/index.js +473 -284
  17. package/dist/protocols/evm/aerodrome/index.js.map +1 -1
  18. package/dist/protocols/evm/curve-dao/index.cjs +54 -6
  19. package/dist/protocols/evm/curve-dao/index.cjs.map +1 -1
  20. package/dist/protocols/evm/curve-dao/index.js +54 -6
  21. package/dist/protocols/evm/curve-dao/index.js.map +1 -1
  22. package/dist/protocols/evm/euler-v2/index.cjs +45 -10
  23. package/dist/protocols/evm/euler-v2/index.cjs.map +1 -1
  24. package/dist/protocols/evm/euler-v2/index.d.ts +10 -2
  25. package/dist/protocols/evm/euler-v2/index.js +44 -11
  26. package/dist/protocols/evm/euler-v2/index.js.map +1 -1
  27. package/dist/protocols/evm/railgun/index.cjs +26 -9
  28. package/dist/protocols/evm/railgun/index.cjs.map +1 -1
  29. package/dist/protocols/evm/railgun/index.d.ts +1 -0
  30. package/dist/protocols/evm/railgun/index.js +26 -9
  31. package/dist/protocols/evm/railgun/index.js.map +1 -1
  32. package/package.json +1 -1
@@ -208,10 +208,10 @@ var init_defiProxy = __esm({
208
208
  "src/core/defiProxy.ts"() {
209
209
  }
210
210
  });
211
- function isConfiguredAddress(addr) {
212
- if (!addr?.trim()) return false;
211
+ function isConfiguredAddress(addr2) {
212
+ if (!addr2?.trim()) return false;
213
213
  try {
214
- return viem.getAddress(addr) !== viem.zeroAddress;
214
+ return viem.getAddress(addr2) !== viem.zeroAddress;
215
215
  } catch {
216
216
  return false;
217
217
  }
@@ -627,18 +627,81 @@ var init_midnightApi = __esm({
627
627
  });
628
628
  function isAerodromeChainSupported(chainId) {
629
629
  const n = typeof chainId === "number" ? chainId : Number.parseInt(String(chainId), 10);
630
- return n === AERODROME_CHAIN_ID;
630
+ return AERO_CHAIN_IDS.includes(n);
631
631
  }
632
- var AERODROME_PROTOCOL_ID, AERODROME_CHAIN_ID, AERODROME_WETH_BASE, AERODROME_USDC_BASE;
632
+ function aerodromeUnsupportedChainMessage(chainId) {
633
+ const listed = AERO_CHAIN_IDS.map((id) => `${AERO_CHAIN_LABEL[id]} ${id}`).join(", ");
634
+ return `Aero is not deployed on chain ${chainId}. Launch chains: ${listed}.`;
635
+ }
636
+ var AERODROME_PROTOCOL_ID, AERODROME_CHAIN_ID, AERO_CHAIN_IDS, AERO_CHAIN_LABEL, AERODROME_WETH_BASE, AERODROME_USDC_BASE;
633
637
  var init_support2 = __esm({
634
638
  "src/protocols/evm/aerodrome/support.ts"() {
635
639
  AERODROME_PROTOCOL_ID = "aerodrome";
636
640
  AERODROME_CHAIN_ID = 8453;
641
+ AERO_CHAIN_IDS = [8453, 1, 10, 42161, 4663, 5042, 57073];
642
+ AERO_CHAIN_LABEL = {
643
+ 1: "Ethereum",
644
+ 10: "OP Mainnet",
645
+ 42161: "Arbitrum",
646
+ 4663: "Robinhood Chain",
647
+ 5042: "Arc",
648
+ 8453: "Base",
649
+ 57073: "Ink"
650
+ };
637
651
  AERODROME_WETH_BASE = "0x4200000000000000000000000000000000000006";
638
652
  AERODROME_USDC_BASE = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
639
653
  }
640
654
  });
641
- var AERODROME_BASE_ADDRESSES_FALLBACK;
655
+ function addr(raw) {
656
+ return viem.getAddress(raw);
657
+ }
658
+ function aeroUsdcAddress(chainId) {
659
+ const raw = AERO_USDC_BY_CHAIN[chainId];
660
+ return raw ? addr(raw) : null;
661
+ }
662
+ function aeroWrappedNativeAddress(chainId) {
663
+ const raw = AERO_WETH_BY_CHAIN[chainId];
664
+ return raw ? addr(raw) : null;
665
+ }
666
+ function aeroAddressesForChain(chainId) {
667
+ const fb = AERODROME_BASE_ADDRESSES_FALLBACK;
668
+ const cl = addr(AERO_CL_FACTORY_BY_CHAIN[chainId] ?? AERO_CL_FACTORY_BY_CHAIN[AERODROME_CHAIN_ID]);
669
+ const receipt = addr(AERO_RECEIPT_BY_CHAIN[chainId] ?? AERO_RECEIPT_BY_CHAIN[AERODROME_CHAIN_ID]);
670
+ const weth = aeroWrappedNativeAddress(chainId) ?? addr("0x0000000000000000000000000000000000000000");
671
+ const token = chainId === AERODROME_CHAIN_ID ? addr(AERO_TOKEN_BASE) : receipt;
672
+ return {
673
+ chainId,
674
+ aero: token,
675
+ router: chainId === AERODROME_CHAIN_ID ? addr(fb.router) : addr(AERO_METAROUTER),
676
+ poolFactory: addr(AERO_VOLATILE_POOL_FACTORY),
677
+ factoryRegistry: addr(AERO_FACTORY_REGISTRY_BY_CHAIN[chainId] ?? AERO_FACTORY_REGISTRY_BY_CHAIN[AERODROME_CHAIN_ID]),
678
+ voter: addr(AERO_LEAF_VOTER),
679
+ votingEscrow: addr("0xBF7977E1521e9a3032bf7243Ee4712f311f13915"),
680
+ rewardsDistributor: addr(fb.rewardsDistributor),
681
+ mixedQuoter: addr(AERO_METAQUOTER),
682
+ mixedQuoterV3: addr(AERO_METAQUOTER),
683
+ nfpm: addr(AERO_NFPM),
684
+ clFactory: cl,
685
+ clFactory2: cl,
686
+ clFactory3: cl,
687
+ universalRouter: addr(fb.universalRouter),
688
+ swapRouter: addr(AERO_SWAP_ROUTER),
689
+ swapRouter2: addr(AERO_SWAP_ROUTER),
690
+ swapRouter3: addr(AERO_SWAP_ROUTER),
691
+ pricesOracle: addr(fb.pricesOracle),
692
+ slipstreamHelper: addr(fb.slipstreamHelper),
693
+ lpSugar: chainId === AERODROME_CHAIN_ID ? addr(fb.lpSugar) : addr("0x0000000000000000000000000000000000000000"),
694
+ sugarSlipstreamHelper: addr(fb.sugarSlipstreamHelper),
695
+ swapper: addr(fb.swapper),
696
+ weth,
697
+ stablePoolFactory: addr(AERO_STABLE_POOL_FACTORY),
698
+ volatilePoolFactory: addr(AERO_VOLATILE_POOL_FACTORY),
699
+ metarouter: addr(AERO_METAROUTER),
700
+ metaquoter: addr(AERO_METAQUOTER),
701
+ receiptToken: receipt
702
+ };
703
+ }
704
+ var AERODROME_BASE_ADDRESSES_FALLBACK, AERO_TOKEN_BASE, AERO_METAROUTER, AERO_METAQUOTER, AERO_STABLE_POOL_FACTORY, AERO_VOLATILE_POOL_FACTORY, AERO_NFPM, AERO_SWAP_ROUTER, AERO_LEAF_VOTER, AERO_RECEIPT_BY_CHAIN, AERO_FACTORY_REGISTRY_BY_CHAIN, AERO_CL_FACTORY_BY_CHAIN, OP_STACK_WETH, AERO_WETH_BY_CHAIN, AERO_USDC_BY_CHAIN;
642
705
  var init_addresses = __esm({
643
706
  "src/protocols/evm/aerodrome/addresses.ts"() {
644
707
  init_support2();
@@ -672,6 +735,56 @@ var init_addresses = __esm({
672
735
  swapper: "0x91616a7B9CF6D23f8C17845581051EBdC4BcB916",
673
736
  weth: AERODROME_WETH_BASE
674
737
  };
738
+ AERO_TOKEN_BASE = "0x3f5bF3EdAc59d650D8fDf9657a71F2f904A3a4Ee";
739
+ AERO_METAROUTER = "0x0fEf9e88A7b76BCDBF451780C6774FE32965Ee98";
740
+ AERO_METAQUOTER = "0x1dDfeC5058180C207F55BB77D95AcDd0d8227868";
741
+ AERO_STABLE_POOL_FACTORY = "0x78589E876edcEbdce72ee3436ab3c9AD3a7cEF2D";
742
+ AERO_VOLATILE_POOL_FACTORY = "0x8E6a9FCd1d638CC760Ffba397605Fe3355dE76D2";
743
+ AERO_NFPM = "0x4857DB576eE0e45F10525eC59527BfD10beeC60b";
744
+ AERO_SWAP_ROUTER = "0x9Ee35Bf1bd69a03c6F0393582030fCe8Bb93D418";
745
+ AERO_LEAF_VOTER = "0x382409fad8503FbCdbB27A4211551fa03e884078";
746
+ AERO_RECEIPT_BY_CHAIN = {
747
+ 8453: "0x6CdDa0E730744DC6fF67654B35350Adad05EceE7",
748
+ 10: "0xbdEaeA5205d16f34Cb40038052d91235D87B4C54",
749
+ 42161: "0x436a085B2751cB87db270FFa66f8d698F87bEC82",
750
+ 1: "0x9e148C5716b5aAdCFD3B71cEAE9EE7a9e22C29E2",
751
+ 57073: "0x9e148C5716b5aAdCFD3B71cEAE9EE7a9e22C29E2",
752
+ 4663: "0x9e148C5716b5aAdCFD3B71cEAE9EE7a9e22C29E2",
753
+ 5042: "0x20077cC0d5E385A0Fe9C91bbC7DC744f51559307"
754
+ };
755
+ AERO_FACTORY_REGISTRY_BY_CHAIN = {
756
+ 8453: "0x7b2A2c12dC5Ea2a31455952a05031C3E4BB28F3E",
757
+ 10: "0xb6F9705A631CC1C0E8570FFde48882C95E2Df408",
758
+ 42161: "0x9E635b2c689fC52201DF7eF1C9FA607c2F58f666",
759
+ 1: "0xdd1705e23762F4D6e44D8C31BD8Ea80c54612239",
760
+ 57073: "0xdd1705e23762F4D6e44D8C31BD8Ea80c54612239",
761
+ 4663: "0xdd1705e23762F4D6e44D8C31BD8Ea80c54612239",
762
+ 5042: "0xCe44907DC45D3BFa3f5f6035B0e6E8B22D780A42"
763
+ };
764
+ AERO_CL_FACTORY_BY_CHAIN = {
765
+ 8453: "0x9CB220581b91b0C83223012FE69688b92aD07a76",
766
+ 10: "0xfeaB42D90055db3a0616249f76B6002D72266778",
767
+ 42161: "0x88a60ee77392577c355C0acb2A8d476D5a4EC03a",
768
+ 1: "0xF4Fd2E6c5B60c5b365cd1B96DD6245E6D60414c2",
769
+ 57073: "0x7660BF2aDefC687C22906112ca323d60A00358cF",
770
+ 4663: "0xc63d7338c178e805c544B8f897066bD3BBcBE136",
771
+ 5042: "0x7F83235643181E440433400a027618Cd50879751"
772
+ };
773
+ OP_STACK_WETH = "0x4200000000000000000000000000000000000006";
774
+ AERO_WETH_BY_CHAIN = {
775
+ 1: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
776
+ 10: OP_STACK_WETH,
777
+ 42161: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
778
+ 8453: OP_STACK_WETH,
779
+ 57073: OP_STACK_WETH,
780
+ 4663: "0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73"
781
+ };
782
+ AERO_USDC_BY_CHAIN = {
783
+ 1: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
784
+ 10: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",
785
+ 42161: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
786
+ 8453: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
787
+ };
675
788
  }
676
789
  });
677
790
  var init_stockTokens = __esm({
@@ -2332,10 +2445,14 @@ var mcpCurveDaoBuildGaugeDepositMultisignInputSchema = withMultisignKeySourceRef
2332
2445
  withdraw: zod.z.boolean().optional().describe("If true, withdraw LP from the gauge instead of deposit")
2333
2446
  })
2334
2447
  );
2335
- var chain8453 = agentEvmChainIdSchema.describe("Must be 8453 (Base). Aerodrome is Base-only.");
2448
+ var aeroChainId = agentEvmChainIdSchema.describe(
2449
+ "Aero chain id. Base 8453 (default), Ethereum 1, OP Mainnet 10, Arbitrum 42161, Robinhood Chain 4663, Arc 5042, Ink 57073. Coinbase stock LP is Base only."
2450
+ ).refine((n) => [8453, 1, 10, 42161, 4663, 5042, 57073].includes(Number(n)), {
2451
+ message: "Aero chainId must be 8453, 1, 10, 42161, 4663, 5042, or 57073."
2452
+ });
2336
2453
  var rpcUrlOptional = zod.z.string().min(1).optional().describe("JSON-RPC URL; continuum-mcp-server injects from chain registry \u2014 do not pass a public RPC URL");
2337
2454
  var mcpAerodromeDiscoverPoolsInputSchema = zod.z.object({
2338
- chainId: chain8453,
2455
+ chainId: aeroChainId,
2339
2456
  rpcUrl: rpcUrlOptional,
2340
2457
  token: zod.z.string().min(1).describe("Ticker or 0x address to find pools for (AAPLc, USDC, ETH, WETH, AERO)."),
2341
2458
  tokenOut: zod.z.string().min(1).optional().describe("Optional counterpart. Defaults to USDC so B20 stocks resolve. Tickers OK.")
@@ -2344,7 +2461,7 @@ var mcpAerodromeDiscoverPoolsOutputSchema = jsonObjectSchema.describe(
2344
2461
  "{ token, tokenOut, pools[] (lp, kind, tickSpacing, factory), notes }. Factory getPool only \u2014 not LpSugar. Then call ctm_aerodrome_quote."
2345
2462
  );
2346
2463
  var mcpAerodromeFetchPoolsInputSchema = zod.z.object({
2347
- chainId: chain8453,
2464
+ chainId: aeroChainId,
2348
2465
  rpcUrl: rpcUrlOptional,
2349
2466
  query: zod.z.string().trim().min(1).optional().describe("Optional shrink filter. Does not expand beyond the ~100 important pools."),
2350
2467
  limit: zod.z.number().int().positive().max(100).optional(),
@@ -2354,7 +2471,7 @@ var mcpAerodromeFetchPoolsOutputSchema = jsonObjectSchema.describe(
2354
2471
  "{ chainId, pools[], notes }. At most ~100 important Base pairs \u2014 not an LpSugar.all dump."
2355
2472
  );
2356
2473
  var mcpAerodromeFetchLpYieldsInputSchema = zod.z.object({
2357
- chainId: chain8453,
2474
+ chainId: aeroChainId,
2358
2475
  rpcUrl: rpcUrlOptional,
2359
2476
  query: zod.z.string().trim().min(1).optional()
2360
2477
  });
@@ -2364,7 +2481,7 @@ var mcpAerodromeFetchLpYieldsOutputSchema = jsonObjectSchema.describe(
2364
2481
  var mcpAerodromeFetchStockLpYieldsInputSchema = mcpAerodromeFetchLpYieldsInputSchema;
2365
2482
  var mcpAerodromeFetchStockLpYieldsOutputSchema = mcpAerodromeFetchLpYieldsOutputSchema;
2366
2483
  var mcpAerodromeFetchPositionsInputSchema = zod.z.object({
2367
- chainId: chain8453,
2484
+ chainId: aeroChainId,
2368
2485
  rpcUrl: rpcUrlOptional,
2369
2486
  account: evmAddressSchema.optional(),
2370
2487
  executorAddress: evmAddressSchema.optional().describe("Server-filled from keyGenId when omitted")
@@ -2373,7 +2490,7 @@ var mcpAerodromeFetchPositionsOutputSchema = jsonObjectSchema.describe(
2373
2490
  "{ chainId, account, notes, positions[] } \u2014 each row has label (vAMM-USDC/AERO \xB7 #id), kind, gauge, stakedInGauge, claimFees.pool, claimEmissions (gauge + tokenId/cl for Slipstream, or null if no gauge). Dust v2 rows omitted."
2374
2491
  );
2375
2492
  var mcpAerodromeQuoteInputSchema = zod.z.object({
2376
- chainId: chain8453,
2493
+ chainId: aeroChainId,
2377
2494
  rpcUrl: rpcUrlOptional,
2378
2495
  tokenIn: zod.z.string().min(1).describe("Ticker (AAPLc, USDC, ETH, WETH, AERO) or 0x address. Native: 0x0 / eth. B20 stocks need no address lookup."),
2379
2496
  tokenOut: zod.z.string().min(1).describe("Ticker (AAPLc, USDC, ETH, WETH, AERO) or 0x address. Native: 0x0 / eth."),
@@ -2393,7 +2510,7 @@ var mcpAerodromeBuildSwapMultisignInputSchema = withMultisignKeySourceRefine(
2393
2510
  })
2394
2511
  );
2395
2512
  var mcpAerodromeQuoteAddLiquidityInputSchema = zod.z.object({
2396
- chainId: chain8453,
2513
+ chainId: aeroChainId,
2397
2514
  rpcUrl: rpcUrlOptional,
2398
2515
  tokenA: zod.z.string().min(1).describe("Ticker (AAPLc, USDC, ETH, WETH, AERO) or 0x / 0x0 native"),
2399
2516
  tokenB: zod.z.string().min(1).describe("Ticker (AAPLc, USDC, ETH, WETH, AERO) or 0x / 0x0 native"),
@@ -2409,7 +2526,7 @@ var mcpAerodromeQuoteAddLiquidityOutputSchema = jsonObjectSchema.describe(
2409
2526
  "{ tokenA, tokenB, amountAHuman, amountBHuman, kind (stable|volatile|cl), tickSpacing?, emptyPool, seedable, hint }. seedable:false = do not first-deposit (ETH/AAPLc has no pool \u2014 pair vs USDC). kind:cl is a Slipstream ratio; basic addLiquidity is v2 only."
2410
2527
  );
2411
2528
  var mcpAerodromeQuoteClDepositInputSchema = zod.z.object({
2412
- chainId: chain8453,
2529
+ chainId: aeroChainId,
2413
2530
  rpcUrl: rpcUrlOptional,
2414
2531
  token0: zod.z.string().min(1).describe("Ticker (AAPLc, USDC, ETH) or 0x / 0x0 native"),
2415
2532
  token1: zod.z.string().min(1).describe("Ticker (AAPLc, USDC, ETH) or 0x / 0x0 native"),
@@ -2968,8 +3085,8 @@ function shortAddr(value) {
2968
3085
  if (!trimmed) return "\u2026";
2969
3086
  try {
2970
3087
  if (!viem.isAddress(trimmed)) return trimmed;
2971
- const addr = viem.getAddress(trimmed);
2972
- return `${addr.slice(0, 6)}\u2026${addr.slice(-4)}`;
3088
+ const addr2 = viem.getAddress(trimmed);
3089
+ return `${addr2.slice(0, 6)}\u2026${addr2.slice(-4)}`;
2973
3090
  } catch {
2974
3091
  return trimmed;
2975
3092
  }
@@ -4523,7 +4640,7 @@ var mcpAaveV4FetchStockMarketsOutputSchema = mcpAaveV4FetchMarketsOutputSchema;
4523
4640
  var mcpEulerV2FetchLendVaultsInputSchema = zod.z.object({
4524
4641
  chainId: agentEvmChainIdSchema,
4525
4642
  underlyingAddress: evmAddressSchema.describe(
4526
- "Underlying asset address, or a Coinbase stock ticker (AAPLc) from the live catalog."
4643
+ "Underlying ERC-20 address, a ticker such as USDC or WETH (resolved from Euler vaults on chainId), or a Coinbase stock ticker (AAPLc)."
4527
4644
  ),
4528
4645
  limit: agentCoercedOptionalIntSchema(zod.z.number().int().min(1).max(100)).describe("Max vault rows (default 30).")
4529
4646
  });
@@ -4545,7 +4662,7 @@ var mcpEulerV2FetchLendVaultsOutputSchema = zod.z.object({
4545
4662
  var mcpEulerV2FetchEarnVaultsInputSchema = zod.z.object({
4546
4663
  chainId: agentEvmChainIdSchema,
4547
4664
  underlyingAddress: evmAddressSchema.describe(
4548
- "Underlying asset address, or a Coinbase stock ticker (AAPLc) from the live catalog."
4665
+ "Underlying ERC-20 address, a ticker such as USDC or WETH (resolved from Euler vaults on chainId), or a Coinbase stock ticker (AAPLc)."
4549
4666
  ),
4550
4667
  limit: agentCoercedOptionalIntSchema(zod.z.number().int().min(1).max(100)).describe("Max vault rows (default 30).")
4551
4668
  });
@@ -4572,6 +4689,7 @@ var mcpLidoFetchStethAprOutputSchema = zod.z.object({
4572
4689
  source: zod.z.string(),
4573
4690
  notes: zod.z.string()
4574
4691
  });
4692
+ var railgunKeyGenIdSchema = zod.z.string().min(1).optional().describe("KeyGen request id. Omit to use the node preferred KeyGen.");
4575
4693
  var mcpRailgunFetchPopularAssetsInputSchema = zod.z.object({
4576
4694
  chainId: agentEvmChainIdSchema,
4577
4695
  rpcUrl: zod.z.string().min(1).optional().describe("Server-filled from the chain registry. Agents should omit.")
@@ -4583,7 +4701,7 @@ var mcpRailgunFetchPopularAssetsOutputSchema = zod.z.object({
4583
4701
  notes: zod.z.string()
4584
4702
  }).strict();
4585
4703
  var mcpRailgunFetchPrivateBalancesInputSchema = zod.z.object({
4586
- keyGenId: zod.z.string().min(1).describe("KeyGen request id. The shielded wallet is stored on that KeyGen record."),
4704
+ keyGenId: railgunKeyGenIdSchema,
4587
4705
  chainId: agentEvmChainIdSchema,
4588
4706
  refresh: zod.z.boolean().optional().describe("Scan again and write the KeyGen record. Default reads the stored scan, and scans when none is stored.")
4589
4707
  }).strict();
@@ -4604,7 +4722,7 @@ var mcpRailgunFetchPrivateBalancesOutputSchema = zod.z.object({
4604
4722
  shieldSignature: zod.z.string().optional()
4605
4723
  }).strict();
4606
4724
  var mcpRailgunEnsureWalletInputSchema = zod.z.object({
4607
- keyGenId: zod.z.string().min(1),
4725
+ keyGenId: railgunKeyGenIdSchema,
4608
4726
  chainId: agentEvmChainIdSchema.optional()
4609
4727
  }).strict();
4610
4728
  var mcpRailgunEnsureWalletOutputSchema = zod.z.object({
@@ -4616,10 +4734,13 @@ var mcpRailgunShieldInputSchema = mcpMultisignInput({
4616
4734
  tokenAddress: evmAddressSchema.describe("ERC-20 contract to shield"),
4617
4735
  amountWei: zod.z.string().min(1).describe("Amount in wei"),
4618
4736
  railgunAddress: zod.z.string().min(1).describe("Recipient 0zk address"),
4737
+ wrapNative: agentOptionalBooleanSchema().describe(
4738
+ "Deposit this chain\u2019s native gas into the wrapped token, then shield it. tokenAddress must be that wrapped token, such as WETH on Ethereum. Set this when the user asks to shield ETH."
4739
+ ),
4619
4740
  shieldSignature: zod.z.string().min(1).optional().describe("Stored Railgun shield key. Omit this. The server reads it from the KeyGen.")
4620
4741
  });
4621
4742
  var mcpRailgunPrivateTransferInputSchema = zod.z.object({
4622
- keyGenId: zod.z.string().min(1),
4743
+ keyGenId: railgunKeyGenIdSchema,
4623
4744
  chainId: agentEvmChainIdSchema,
4624
4745
  tokenAddress: evmAddressSchema,
4625
4746
  amountWei: zod.z.string().min(1),
@@ -4629,20 +4750,49 @@ var mcpRailgunPrivateTransferInputSchema = zod.z.object({
4629
4750
  purpose: zod.z.string().max(256).optional().describe("Purpose shown on Join, Execute, and History. Same field as a normal sign request.")
4630
4751
  }).strict();
4631
4752
  var mcpRailgunUnshieldInputSchema = zod.z.object({
4632
- keyGenId: zod.z.string().min(1),
4753
+ keyGenId: railgunKeyGenIdSchema,
4633
4754
  chainId: agentEvmChainIdSchema,
4634
4755
  tokenAddress: evmAddressSchema,
4635
4756
  amountWei: zod.z.string().min(1),
4636
4757
  recipientAddress: evmAddressSchema.optional().describe("Public recipient. Defaults to this KeyGen Ethereum address."),
4637
4758
  purpose: zod.z.string().max(256).optional().describe("Purpose shown on Join, Execute, and History. Same field as a normal sign request.")
4638
4759
  }).strict();
4760
+ var mcpRailgunUnwrapInputSchema = mcpMultisignInput({
4761
+ amountWei: zod.z.string().min(1).describe("Amount of the wrapped gas token to withdraw back to native gas, in wei.")
4762
+ });
4763
+ var mcpRailgunListSpendsInputSchema = zod.z.object({
4764
+ keyGenId: zod.z.string().min(1).optional().describe("Limit the list to one KeyGen. Omit to include every KeyGen on this node.")
4765
+ }).strict();
4766
+ var mcpRailgunSpendSummarySchema = zod.z.object({
4767
+ requestId: zod.z.string(),
4768
+ keyGenId: zod.z.string(),
4769
+ spendId: zod.z.string(),
4770
+ status: zod.z.string().describe("pending, ready, executing, executed, failed, rejected, shelved, or expired."),
4771
+ kind: zod.z.string().describe("transfer or unshield."),
4772
+ chainId: zod.z.number().int(),
4773
+ tokenAddress: zod.z.string(),
4774
+ amountWei: zod.z.string(),
4775
+ recipientAddress: zod.z.string(),
4776
+ memoText: zod.z.string().optional(),
4777
+ purpose: zod.z.string().optional(),
4778
+ txHash: zod.z.string().optional(),
4779
+ error: zod.z.string().optional(),
4780
+ deadline: zod.z.string().optional(),
4781
+ proposedAt: zod.z.string().optional(),
4782
+ approvals: zod.z.number().int(),
4783
+ quorum: zod.z.number().int(),
4784
+ isOriginatorLocal: zod.z.boolean()
4785
+ }).strict();
4786
+ var mcpRailgunListSpendsOutputSchema = zod.z.object({
4787
+ spends: zod.z.array(mcpRailgunSpendSummarySchema)
4788
+ }).strict();
4639
4789
  var mcpRailgunAgreeSpendInputSchema = zod.z.object({
4640
- keyGenId: zod.z.string().min(1),
4790
+ keyGenId: railgunKeyGenIdSchema,
4641
4791
  spendId: zod.z.string().min(1),
4642
4792
  thoughts: zod.z.string().max(256).optional().describe("Optional comment stored for this node, the same thoughts field as sign_request_agree.")
4643
4793
  }).strict();
4644
4794
  var mcpRailgunFeeQuoteInputSchema = zod.z.object({
4645
- keyGenId: zod.z.string().min(1),
4795
+ keyGenId: railgunKeyGenIdSchema,
4646
4796
  chainId: agentEvmChainIdSchema,
4647
4797
  kind: zod.z.enum(["shield", "transfer", "unshield"]),
4648
4798
  tokenAddress: evmAddressSchema,
@@ -4650,6 +4800,25 @@ var mcpRailgunFeeQuoteInputSchema = zod.z.object({
4650
4800
  recipientAddress: zod.z.string().optional().describe("0zk address for a private transfer, or a public address for an unshield."),
4651
4801
  memoText: zod.z.string().optional()
4652
4802
  }).strict();
4803
+ var mcpRailgunListBroadcastersInputSchema = zod.z.object({
4804
+ chainId: agentEvmChainIdSchema,
4805
+ tokenAddress: evmAddressSchema,
4806
+ kind: zod.z.enum(["transfer", "unshield"]).describe("transfer for a private transfer, unshield for an unshield.")
4807
+ }).strict();
4808
+ var mcpRailgunBroadcasterSchema = zod.z.object({
4809
+ feesId: zod.z.string(),
4810
+ railgunAddress: zod.z.string(),
4811
+ feeWei: zod.z.string(),
4812
+ ratio: zod.z.string().nullable().describe("Fee compared with gas. 1.00 is 1:1. Null when prices are unavailable."),
4813
+ coversGas: zod.z.boolean().describe("True when the ratio is at least 1:1."),
4814
+ reliability: zod.z.number(),
4815
+ expiration: zod.z.number().describe("Unix milliseconds when this advertisement expires."),
4816
+ tokenDecimals: zod.z.number().int(),
4817
+ recommended: zod.z.boolean().describe("Cheapest advertisement whose ratio is at least 1:1.")
4818
+ }).strict();
4819
+ var mcpRailgunListBroadcastersOutputSchema = zod.z.object({
4820
+ broadcasters: zod.z.array(mcpRailgunBroadcasterSchema)
4821
+ }).strict();
4653
4822
  var mcpRailgunFeeQuoteSchema = zod.z.object({
4654
4823
  kind: zod.z.enum(["shield", "transfer", "unshield"]),
4655
4824
  amountWei: zod.z.string(),
@@ -8033,10 +8202,20 @@ var MCP_PROTOCOL_TOOL_DEFINITIONS = [
8033
8202
  actionId: "railgun.shield",
8034
8203
  protocolId: "railgun",
8035
8204
  chainCategory: "evm",
8036
- description: "Shield an ERC-20 into a Railgun 0zk address. Call ctm_railgun_fee_quote first and tell the user the Railgun fee taken from the amount. purposeText is the Purpose shown on the sign request. If this KeyGen already has a shield key, this builds the approve-and-shield transaction. Otherwise it returns a personal_sign. After that request is signed, the shield key is stored on the KeyGen. Call this tool again without shieldSignature. The result includes railgunFee.",
8205
+ description: "Shield an ERC-20 into a Railgun 0zk address. Call ctm_railgun_fee_quote first and tell the user the Railgun fee taken from the amount. purposeText is the Purpose shown on the sign request. Set wrapNative when the user asks to shield the chain\u2019s native gas: tokenAddress must be the wrapped gas token, and the transaction deposits native gas into it before the shield. If this KeyGen already has a shield key, this builds the approve-and-shield transaction. Otherwise it returns a personal_sign. After that request is signed, the shield key is stored on the KeyGen. Call this tool again without shieldSignature. The result includes railgunFee.",
8037
8206
  prerequisites: ["keyGen", "executorAddress", "RPC URL", "0zk recipient"],
8038
8207
  handler: { importPath: "protocols/evm/railgun", exportName: "buildEvmMultisignBodyRailgunShield" },
8039
8208
  inputZod: mcpRailgunShieldInputSchema
8209
+ }),
8210
+ defineProtocolMcpTool({
8211
+ name: "ctm_railgun_build_unwrap_multisign",
8212
+ actionId: "railgun.unwrap",
8213
+ protocolId: "railgun",
8214
+ chainCategory: "evm",
8215
+ description: "Withdraw this chain\u2019s wrapped gas token back to native gas on the KeyGen. On Ethereum that is WETH back to ETH. This is a normal sign request, not a private Railgun spend. There is no broadcaster and no 0zk recipient. After Join, use trigger_sign_result and then broadcast_sign_result.",
8216
+ prerequisites: ["keyGen", "executorAddress", "RPC URL", "amountWei"],
8217
+ handler: { importPath: "protocols/evm/railgun", exportName: "buildEvmMultisignBodyWethUnwrap" },
8218
+ inputZod: mcpRailgunUnwrapInputSchema
8040
8219
  })
8041
8220
  ];
8042
8221
  var catalogQuery = {
@@ -8865,8 +9044,8 @@ var CORE_MCP_TOOL_DEFINITIONS = [
8865
9044
  actionId: "aerodrome.discover-pools",
8866
9045
  protocolId: "aerodrome",
8867
9046
  chainCategory: "evm",
8868
- description: "Find Aerodrome v2 + Slipstream pools for one token (optional tokenOut, default USDC) via factory getPool. Tickers OK (AAPLc, USDC, ETH). Use this instead of dumping listed tokens or LpSugar.all. For a price, skip this and call ctm_aerodrome_quote. rpcUrl is injected.",
8869
- prerequisites: ["chainId 8453", "token (ticker or 0x)"],
9047
+ description: "Find Aero v2 + Slipstream pools for one token (optional tokenOut, default USDC) via factory getPool. Protocol id stays aerodrome. Chains: Base 8453 (default), Ethereum 1, OP Mainnet 10, Arbitrum 42161, Robinhood 4663, Arc 5042, Ink 57073. Tickers OK (AAPLc, USDC, ETH). Coinbase stock LP is Base only. Use this instead of dumping listed tokens or LpSugar.all. For a price, skip this and call ctm_aerodrome_quote. rpcUrl is injected.",
9048
+ prerequisites: ["chainId 8453 (Base, default), 1, 10, 42161, 4663, 5042, or 57073", "token (ticker or 0x)"],
8870
9049
  followUp: ["ctm_aerodrome_quote", "ctm_aerodrome_quote_add_liquidity"],
8871
9050
  handler: { importPath: "protocols/evm/aerodrome", exportName: "aerodromeDiscoverPoolsSummary" },
8872
9051
  inputZod: mcpAerodromeDiscoverPoolsInputSchema,
@@ -8877,8 +9056,8 @@ var CORE_MCP_TOOL_DEFINITIONS = [
8877
9056
  actionId: "aerodrome.fetch-pools",
8878
9057
  protocolId: "aerodrome",
8879
9058
  chainCategory: "evm",
8880
- description: "At most ~100 important Aerodrome pools on Base (ETH/WETH, USDC, AERO, major stables; TVL-ranked). Not an LpSugar.all dump. Optional query only shrinks the set. For B20 stock LPs use ctm_aerodrome_fetch_stock_lp_yields.",
8881
- prerequisites: ["chainId 8453"],
9059
+ description: "At most ~100 important Aero pools from the Base LpSugar index (ETH/WETH, USDC, AERO, major stables; TVL-ranked). Other launch chains have no Sugar index \u2014 use ctm_aerodrome_discover_pools. Optional query only shrinks the set. For B20 stock LPs use ctm_aerodrome_fetch_stock_lp_yields (Base only).",
9060
+ prerequisites: ["chainId 8453 (Base, default), 1, 10, 42161, 4663, 5042, or 57073"],
8882
9061
  followUp: ["ctm_aerodrome_quote_add_liquidity", "ctm_aerodrome_fetch_positions"],
8883
9062
  handler: { importPath: "protocols/evm/aerodrome", exportName: "aerodromeFetchPoolsSummary" },
8884
9063
  inputZod: mcpAerodromeFetchPoolsInputSchema,
@@ -8889,8 +9068,8 @@ var CORE_MCP_TOOL_DEFINITIONS = [
8889
9068
  actionId: "aerodrome.fetch-lp-yields",
8890
9069
  protocolId: "aerodrome",
8891
9070
  chainCategory: "evm",
8892
- description: "Fee tier + AERO emissions APR for the same ~100 important Aerodrome pairs. feeApr is null (Sugar has no volume). Not a factory dump. B20 stocks: ctm_aerodrome_fetch_stock_lp_yields.",
8893
- prerequisites: ["chainId 8453"],
9071
+ description: "Fee tier + AERO emissions APR for the same ~100 important Aero pairs on Base (protocol id aerodrome). feeApr is null (Sugar has no volume). Other launch chains return an empty Sugar list \u2014 discover a pair instead. B20 stocks on Base: ctm_aerodrome_fetch_stock_lp_yields.",
9072
+ prerequisites: ["chainId 8453 (Base, default), 1, 10, 42161, 4663, 5042, or 57073"],
8894
9073
  followUp: ["ctm_aerodrome_quote_add_liquidity", "ctm_aerodrome_build_gauge_stake_multisign"],
8895
9074
  handler: { importPath: "protocols/evm/aerodrome", exportName: "aerodromeFetchLpYieldsSummary" },
8896
9075
  inputZod: mcpAerodromeFetchLpYieldsInputSchema,
@@ -8901,8 +9080,8 @@ var CORE_MCP_TOOL_DEFINITIONS = [
8901
9080
  actionId: "aerodrome.fetch-stock-lp-yields",
8902
9081
  protocolId: "aerodrome",
8903
9082
  chainCategory: "evm",
8904
- description: "Coinbase B20 stock LP yields only (AAPLc/USDC, \u2026). Separate from main-pair fetch_lp_yields. Trading stocks is not this list.",
8905
- prerequisites: ["chainId 8453"],
9083
+ description: "Coinbase B20 stock LP yields on Base only (AAPLc/USDC, \u2026). Separate from main-pair fetch_lp_yields. Trading stocks is not this list.",
9084
+ prerequisites: ["chainId 8453 (Base only)"],
8906
9085
  followUp: ["ctm_aerodrome_quote_add_liquidity"],
8907
9086
  handler: { importPath: "protocols/evm/aerodrome", exportName: "aerodromeFetchStockLpYieldsSummary" },
8908
9087
  inputZod: mcpAerodromeFetchStockLpYieldsInputSchema,
@@ -8914,7 +9093,7 @@ var CORE_MCP_TOOL_DEFINITIONS = [
8914
9093
  protocolId: "aerodrome",
8915
9094
  chainCategory: "evm",
8916
9095
  description: "KeyGen Aerodrome positions (same picker as the Multi-Sign Rewards tab). Each row has label, kind (vAMM/sAMM/CL), gauge, stakedInGauge, claimFees.pool, and claimEmissions (gauge + tokenId/cl, or null). Dust v2 rows omitted. Read-only.",
8917
- prerequisites: ["chainId 8453", "account or keyGenId"],
9096
+ prerequisites: ["chainId 8453 (Base, default), 1, 10, 42161, 4663, 5042, or 57073", "account or keyGenId"],
8918
9097
  followUp: [
8919
9098
  "ctm_aerodrome_build_claim_fees_multisign",
8920
9099
  "ctm_aerodrome_build_claim_emissions_multisign",
@@ -8929,8 +9108,8 @@ var CORE_MCP_TOOL_DEFINITIONS = [
8929
9108
  actionId: "aerodrome.quote",
8930
9109
  protocolId: "aerodrome",
8931
9110
  chainCategory: "evm",
8932
- description: "Quote an Aerodrome swap on Base. tokenIn/tokenOut accept tickers (AAPLc, USDC, ETH, WETH, AERO) or 0x addresses. Coinbase B20 stocks are 8 decimals and route via Slipstream 3 (usually a USDC hop). Returns amountOutHuman and priceImpactPercent (0\u2013100 vs a tiny same-route probe). Call this directly \u2014 do not fetch_pools or ask the user for a stock address. Does NOT create a sign request.",
8933
- prerequisites: ["chainId 8453", "tokenIn + tokenOut + amountHuman (tickers OK)"],
9111
+ description: "Quote an Aero swap. Protocol id stays aerodrome. chainId is Base 8453 by default, or Ethereum 1, OP Mainnet 10, Arbitrum 42161, Robinhood 4663, Arc 5042, Ink 57073. tokenIn/tokenOut accept tickers (AAPLc, USDC, ETH, WETH, AERO) or 0x addresses. Coinbase B20 stocks are Base-only, 8 decimals, and route via Slipstream (usually a USDC hop). Returns amountOutHuman and priceImpactPercent (0\u2013100 vs a tiny same-route probe). Call this directly \u2014 do not fetch_pools or ask the user for a stock address. Does NOT create a sign request.",
9112
+ prerequisites: ["chainId 8453 (Base, default), 1, 10, 42161, 4663, 5042, or 57073", "tokenIn + tokenOut + amountHuman (tickers OK)"],
8934
9113
  followUp: ["ctm_aerodrome_build_swap_multisign"],
8935
9114
  handler: { importPath: "protocols/evm/aerodrome", exportName: "aerodromeQuote" },
8936
9115
  inputZod: mcpAerodromeQuoteInputSchema,
@@ -8941,11 +9120,11 @@ var CORE_MCP_TOOL_DEFINITIONS = [
8941
9120
  actionId: "aerodrome.swap",
8942
9121
  protocolId: "aerodrome",
8943
9122
  chainCategory: "evm",
8944
- description: "Create and submit mpc-auth multiSignRequest for an Aerodrome swap (optional ERC-20 approve + Router / Slipstream SwapRouter). Default deadline 30 minutes \u2014 ask the user to confirm that window and useCustomGas (via get_multi_sign_gas_options) before calling. Activate aerodrome:swap first.",
9123
+ description: "Create and submit mpc-auth multiSignRequest for an Aero swap (optional ERC-20 approve + Metarouter execute for v2, or Slipstream SwapRouter for a single CL hop). Default deadline 30 minutes \u2014 ask the user to confirm that window and useCustomGas (via get_multi_sign_gas_options) before calling. Activate aerodrome:swap first.",
8945
9124
  prerequisites: [
8946
9125
  "ctm_aerodrome_quote",
8947
9126
  "get_multi_sign_gas_options + user confirms useCustomGas and 30-minute deadline",
8948
- "keyGenId + chainId 8453 + purposeText + slippagePercent"
9127
+ "keyGenId + Aero chainId (8453 default, or 1, 10, 42161, 4663, 5042, 57073) + purposeText + slippagePercent"
8949
9128
  ],
8950
9129
  handler: { importPath: "protocols/evm/aerodrome", exportName: "buildEvmMultisignBodyAerodromeSwapBatch" },
8951
9130
  inputZod: mcpAerodromeBuildSwapMultisignInputSchema
@@ -8955,8 +9134,8 @@ var CORE_MCP_TOOL_DEFINITIONS = [
8955
9134
  actionId: "aerodrome.quote-add-liquidity",
8956
9135
  protocolId: "aerodrome",
8957
9136
  chainCategory: "evm",
8958
- description: "Quote an Aerodrome deposit on Base (same as the Liquidity tab). One-sided: pass amountAHuman or amountBHuman; the other side comes from the current vAMM/sAMM reserves or Slipstream slot0. Tickers OK (AAPLc, USDC, ETH). B20 stocks are 8 decimals. ETH/stock has no pool \u2014 seedable:false and hint says pair vs USDC. Do not first-deposit an empty vAMM. Read-only.",
8959
- prerequisites: ["chainId 8453", "tokenA + tokenB + amountAHuman or amountBHuman (tickers OK)"],
9137
+ description: "Quote an Aero deposit (same as the Liquidity tab). One-sided: pass amountAHuman or amountBHuman; the other side comes from the current vAMM/sAMM reserves or Slipstream slot0. Chains match ctm_aerodrome_quote. Tickers OK (AAPLc, USDC, ETH). B20 stocks are Base-only and 8 decimals. ETH/stock has no pool \u2014 seedable:false and hint says pair vs USDC. Do not first-deposit an empty vAMM. Read-only.",
9138
+ prerequisites: ["chainId 8453 (Base, default), 1, 10, 42161, 4663, 5042, or 57073", "tokenA + tokenB + amountAHuman or amountBHuman (tickers OK)"],
8960
9139
  followUp: ["ctm_aerodrome_build_add_liquidity_multisign"],
8961
9140
  handler: { importPath: "protocols/evm/aerodrome", exportName: "aerodromeQuoteAddLiquidity" },
8962
9141
  inputZod: mcpAerodromeQuoteAddLiquidityInputSchema,
@@ -8968,7 +9147,7 @@ var CORE_MCP_TOOL_DEFINITIONS = [
8968
9147
  protocolId: "aerodrome",
8969
9148
  chainCategory: "evm",
8970
9149
  description: "Quote a Slipstream CL deposit (SugarHelper estimate when one side is omitted). token0/token1 accept tickers (AAPLc, USDC, ETH). Use when quote_add_liquidity returns kind:cl. Read-only.",
8971
- prerequisites: ["chainId 8453", "ticks + sqrtPriceX96"],
9150
+ prerequisites: ["chainId 8453 (Base, default), 1, 10, 42161, 4663, 5042, or 57073", "ticks + sqrtPriceX96"],
8972
9151
  followUp: ["ctm_aerodrome_build_cl_mint_multisign"],
8973
9152
  handler: { importPath: "protocols/evm/aerodrome", exportName: "aerodromeQuoteClDeposit" },
8974
9153
  inputZod: mcpAerodromeQuoteClDepositInputSchema,
@@ -11085,7 +11264,7 @@ var CORE_MCP_TOOL_DEFINITIONS = [
11085
11264
  actionId: "railgun.ensure-wallet",
11086
11265
  protocolId: "railgun",
11087
11266
  chainCategory: "evm",
11088
- description: "Create the Railgun wallet on this KeyGen if it does not exist yet, and return its 0zk address. Returns shieldSignature when this KeyGen already has a shield key. The spending key is split across the KeyGen nodes. No node receives a key it can spend alone. Does not return a mnemonic. Use this from the node agent and from Telegram before shield, unshield, or private transfer.",
11267
+ description: "Create the Railgun wallet on this KeyGen if it does not exist yet, and return its 0zk address. Omit keyGenId to use the node preferred KeyGen. Returns shieldSignature when this KeyGen already has a shield key. The spending key is split across the KeyGen nodes. No node receives a key it can spend alone. Does not return a mnemonic. Use this from the node agent and from Telegram before shield, unshield, or private transfer.",
11089
11268
  prerequisites: ["keyGenId"],
11090
11269
  followUp: ["ctm_railgun_fetch_private_balances", "ctm_railgun_build_shield_multisign"],
11091
11270
  handler: { importPath: "protocols/evm/railgun", exportName: "railgunFetchPrivateBalancesSummary" },
@@ -11109,7 +11288,7 @@ var CORE_MCP_TOOL_DEFINITIONS = [
11109
11288
  actionId: "railgun.private-transfer",
11110
11289
  protocolId: "railgun",
11111
11290
  chainCategory: "evm",
11112
- description: "Propose a private Railgun transfer. This node signs it with its management key, then agrees its share. Call ctm_railgun_fee_quote first and tell the user the broadcaster fee. Pass toContactName to use that contact\u2019s saved 0zk address, or recipientAddress as a 0zk address. Do not pass the contact\u2019s Ethereum address. purpose is shown on Join the same way as a normal sign request. The other nodes accept on Join and can attach thoughts. The originator executes with broadcast_sign_result and the RailgunSpend request id. There is no Get Sig. Do not pass a mnemonic. The result includes fee.",
11291
+ description: "Propose a private Railgun transfer. This node signs it with its management key, then agrees its share. Call ctm_railgun_fee_quote first and tell the user the broadcaster fee. Pass toContactName to use that contact\u2019s saved 0zk address, or recipientAddress as a 0zk address. Do not pass the contact\u2019s Ethereum address. purpose is shown on Join the same way as a normal sign request. The other nodes accept on Join and can attach thoughts. The broadcaster is chosen at execute, not here. On the originator, call ctm_railgun_list_broadcasters and pass the chosen feesId and railgunAddress to broadcast_sign_result. Omit them to use the recommended row, the cheapest fee ratio that is at least 1:1. There is no Get Sig. Do not pass a mnemonic. The result includes fee.",
11113
11292
  prerequisites: ["keyGenId", "chainId", "0zk recipient or toContactName", "ctm_railgun_ensure_wallet"],
11114
11293
  followUp: ["ctm_railgun_fetch_private_balances"],
11115
11294
  handler: { importPath: "protocols/evm/railgun", exportName: "railgunPrivateTransfer" },
@@ -11121,7 +11300,7 @@ var CORE_MCP_TOOL_DEFINITIONS = [
11121
11300
  actionId: "railgun.unshield",
11122
11301
  protocolId: "railgun",
11123
11302
  chainCategory: "evm",
11124
- description: "Start an unshield to a public address. This node signs it with its management key, then agrees its share. Call ctm_railgun_fee_quote first and tell the user the Railgun fee and the broadcaster fee. purpose is shown on Join the same way as a normal sign request. It stays pending until the other nodes accept on Join. They can attach thoughts with sign_request_agree. Recipient defaults to the KeyGen Ethereum address. The originator executes with broadcast_sign_result. There is no Get Sig. Do not pass a mnemonic. The result includes fee.",
11303
+ description: "Start an unshield to a public address. This node signs it with its management key, then agrees its share. Call ctm_railgun_fee_quote first and tell the user the Railgun fee and the broadcaster fee. purpose is shown on Join the same way as a normal sign request. It stays pending until the other nodes accept on Join. They can attach thoughts with sign_request_agree. Recipient defaults to the KeyGen Ethereum address. The broadcaster is chosen at execute, not here. On the originator, call ctm_railgun_list_broadcasters and pass the chosen feesId and railgunAddress to broadcast_sign_result. Omit them to use the recommended row, the cheapest fee ratio that is at least 1:1. There is no Get Sig. Do not pass a mnemonic. The result includes fee.",
11125
11304
  prerequisites: ["keyGenId", "chainId", "ctm_railgun_ensure_wallet"],
11126
11305
  followUp: ["ctm_railgun_fetch_private_balances"],
11127
11306
  handler: { importPath: "protocols/evm/railgun", exportName: "railgunUnshield" },
@@ -11147,10 +11326,34 @@ var CORE_MCP_TOOL_DEFINITIONS = [
11147
11326
  chainCategory: "evm",
11148
11327
  description: "Quote the fee taken before a shield, private transfer, or unshield. Shield and unshield include the live Railgun basis points taken from the amount. Private transfer has no protocol fee. Unshield and private transfer also include the broadcaster fee, which is extra and comes out of the private balance. Tell the user these amounts before calling the shield, transfer, or unshield tool. broadcasterError is set when that fee cannot be estimated; the protocol numbers are still returned.",
11149
11328
  prerequisites: ["keyGenId", "chainId", "tokenAddress", "kind"],
11150
- followUp: ["ctm_railgun_build_shield_multisign", "ctm_railgun_private_transfer", "ctm_railgun_unshield"],
11329
+ followUp: ["ctm_railgun_list_broadcasters", "ctm_railgun_build_shield_multisign", "ctm_railgun_private_transfer", "ctm_railgun_unshield"],
11151
11330
  handler: { importPath: "protocols/evm/railgun", exportName: "railgunFetchPrivateBalancesSummary" },
11152
11331
  inputZod: mcpRailgunFeeQuoteInputSchema,
11153
11332
  outputZod: mcpRailgunFeeQuoteSchema
11333
+ }),
11334
+ defineMcpTool({
11335
+ name: "ctm_railgun_list_broadcasters",
11336
+ actionId: "railgun.list-broadcasters",
11337
+ protocolId: "railgun",
11338
+ chainCategory: "evm",
11339
+ description: "List Railgun broadcasters for a private transfer or unshield. Call this on the originator immediately before broadcast_sign_result. ratio is the fee compared with gas, and 1.00 is 1:1. recommended is the cheapest row whose ratio is at least 1:1. Pass that row\u2019s feesId as broadcasterFeesId and its railgunAddress as broadcasterAddress. A lower ratio is a discount the broadcaster may refuse. If prices are missing, coversGas is false and recommended is the cheapest fee. Advertisements expire, so list again if execute says the fee expired. Shield has no broadcaster.",
11340
+ prerequisites: ["chainId", "tokenAddress", "kind"],
11341
+ followUp: ["broadcast_sign_result"],
11342
+ handler: { importPath: "protocols/evm/railgun", exportName: "listRailgunBroadcasters" },
11343
+ inputZod: mcpRailgunListBroadcastersInputSchema,
11344
+ outputZod: mcpRailgunListBroadcastersOutputSchema
11345
+ }),
11346
+ defineMcpTool({
11347
+ name: "ctm_railgun_list_spends",
11348
+ actionId: "railgun.list-spends",
11349
+ protocolId: "railgun",
11350
+ chainCategory: "evm",
11351
+ description: "List private transfers and unshields stored on KeyGen records. This is the Railgun History list, and it also includes spends still on Join or Execute. status is pending, ready, executing, executed, failed, rejected, shelved, or expired. executed rows include txHash. failed rows include error. requestId is RailgunSpend:<keyGenId>:<spendId>. Shelve a ready or failed row with shelve_sign_request. Do not use list_sign_requests for these rows.",
11352
+ prerequisites: [],
11353
+ followUp: ["broadcast_sign_result", "shelve_sign_request"],
11354
+ handler: { importPath: "protocols/evm/railgun", exportName: "railgunFetchPrivateBalancesSummary" },
11355
+ inputZod: mcpRailgunListSpendsInputSchema,
11356
+ outputZod: mcpRailgunListSpendsOutputSchema
11154
11357
  })
11155
11358
  ];
11156
11359
  var MCP_TOOL_DEFINITIONS = [
@@ -11630,9 +11833,9 @@ function isMapleSyrupSupportedChain(chainId) {
11630
11833
  function matchesAssetFilter(opts) {
11631
11834
  const f = (opts.filter ?? "").trim();
11632
11835
  if (!f) return true;
11633
- const addr = (opts.address ?? "").trim();
11634
- if (viem.isAddress(f) && viem.isAddress(addr)) {
11635
- return viem.getAddress(addr) === viem.getAddress(f);
11836
+ const addr2 = (opts.address ?? "").trim();
11837
+ if (viem.isAddress(f) && viem.isAddress(addr2)) {
11838
+ return viem.getAddress(addr2) === viem.getAddress(f);
11636
11839
  }
11637
11840
  const sym = (opts.symbol ?? "").trim();
11638
11841
  if (!sym) return false;
@@ -11849,17 +12052,36 @@ async function fetchEulerV2ChainAssetCache(chainId) {
11849
12052
  fetchEulerV3EarnVaults({ chainId }).catch(() => [])
11850
12053
  ]);
11851
12054
  const modes = /* @__PURE__ */ new Map();
11852
- const bump = (addr, patch) => {
11853
- const cur = modes.get(addr) ?? { lend: false, borrow: false, earn: false };
11854
- modes.set(addr, {
12055
+ const symbols = /* @__PURE__ */ new Map();
12056
+ const ambiguousSymbols = /* @__PURE__ */ new Set();
12057
+ const bump = (addr2, patch) => {
12058
+ const cur = modes.get(addr2) ?? { lend: false, borrow: false, earn: false };
12059
+ modes.set(addr2, {
11855
12060
  lend: cur.lend || !!patch.lend,
11856
12061
  borrow: cur.borrow || !!patch.borrow,
11857
12062
  earn: cur.earn || !!patch.earn
11858
12063
  });
11859
12064
  };
12065
+ const noteSymbol = (symbol, addr2) => {
12066
+ const sym = (symbol ?? "").trim().toLowerCase();
12067
+ if (!sym || ambiguousSymbols.has(sym) || !viem.isAddress(addr2)) return;
12068
+ const checksum = viem.getAddress(addr2);
12069
+ const prev = symbols.get(sym);
12070
+ if (!prev) {
12071
+ symbols.set(sym, checksum);
12072
+ return;
12073
+ }
12074
+ if (prev.toLowerCase() !== checksum.toLowerCase()) {
12075
+ symbols.delete(sym);
12076
+ ambiguousSymbols.add(sym);
12077
+ }
12078
+ };
11860
12079
  for (const v of earnVaults) {
11861
12080
  const a = normAssetAddr(v.asset?.address ?? void 0);
11862
- if (a) bump(a, { earn: true });
12081
+ if (a) {
12082
+ bump(a, { earn: true });
12083
+ noteSymbol(v.asset?.symbol, a);
12084
+ }
11863
12085
  }
11864
12086
  for (const v of evkVaults) {
11865
12087
  const a = normAssetAddr(v.asset?.address ?? void 0);
@@ -11869,8 +12091,13 @@ async function fetchEulerV2ChainAssetCache(chainId) {
11869
12091
  lend: vis?.explorableLend !== false,
11870
12092
  borrow: v3VaultShowsBorrow(v.totalBorrows, vis?.explorableBorrow)
11871
12093
  });
12094
+ noteSymbol(v.asset?.symbol, a);
12095
+ }
12096
+ const weth = symbols.get("weth");
12097
+ if (weth && !symbols.has("eth") && !ambiguousSymbols.has("eth")) {
12098
+ symbols.set("eth", weth);
11872
12099
  }
11873
- return { nativeWrapped, modesByUnderlying: modes };
12100
+ return { nativeWrapped, modesByUnderlying: modes, symbolToAddress: symbols };
11874
12101
  }
11875
12102
  function ensureEulerV2ChainAssetCache(chainId) {
11876
12103
  const hit = eulerV2ChainAssetCache.get(chainId);
@@ -13031,10 +13258,10 @@ var aerodromeProtocolModule = {
13031
13258
  id: "aerodrome.quote",
13032
13259
  protocolId: AERODROME_PROTOCOL_ID,
13033
13260
  chainCategory: "evm",
13034
- description: "Quote an Aerodrome swap on Base via factory discovery + MixedRouteQuoterV3 / Router. Tickers (AAPLc, USDC, ETH) accepted.",
13261
+ description: "Quote an Aero swap (protocol id aerodrome) via factory discovery and pool getAmountOut / Metaquoter. Base 8453 by default; also Ethereum, OP Mainnet, Arbitrum, Robinhood, Arc, and Ink. Tickers (AAPLc, USDC, ETH) accepted. Stock tickers are Base only.",
13035
13262
  commonParams: [],
13036
13263
  params: {
13037
- chainId: { type: "number", required: true, description: `Must be ${AERODROME_CHAIN_ID}` },
13264
+ chainId: { type: "number", required: true, description: "Aero chain: 8453 (Base, default), 1, 10, 42161, 4663, 5042, or 57073." },
13038
13265
  tokenIn: { type: "address", required: true, description: "Ticker (AAPLc, USDC, ETH, WETH, AERO) or 0x / 0x0 native" },
13039
13266
  tokenOut: { type: "address", required: true, description: "Ticker (AAPLc, USDC, ETH, WETH, AERO) or 0x / 0x0 native" },
13040
13267
  amountHuman: { type: "string", required: true, description: "Human-readable input amount (B20 stocks are 8 decimals)" }
@@ -14794,41 +15021,58 @@ init_constants();
14794
15021
  function advisor(protocolId, tokenFilter, impl) {
14795
15022
  return { protocolId, tokenFilter, ...impl };
14796
15023
  }
14797
- async function aerodromeAdvisorPriorityTokens() {
14798
- const stocks = await ensureCoinbaseB20StockCatalog().catch(() => []);
14799
- return [
15024
+ async function aerodromeAdvisorPriorityTokens(chainId) {
15025
+ const addrs = aeroAddressesForChain(chainId);
15026
+ const usdc = aeroUsdcAddress(chainId);
15027
+ const stocks = chainId === 8453 ? await ensureCoinbaseB20StockCatalog().catch(() => []) : [];
15028
+ const rows = [
14800
15029
  {
14801
15030
  address: "0x0000000000000000000000000000000000000000",
14802
15031
  symbol: "ETH",
14803
15032
  decimals: 18,
14804
15033
  roles: ["native"]
14805
- },
14806
- {
14807
- address: AERODROME_WETH_BASE,
15034
+ }
15035
+ ];
15036
+ if (addrs.weth !== viem.zeroAddress) {
15037
+ rows.push({
15038
+ address: addrs.weth,
14808
15039
  symbol: "WETH",
14809
15040
  decimals: 18,
14810
15041
  roles: ["native_wrapped"]
14811
- },
14812
- {
14813
- address: AERODROME_USDC_BASE,
15042
+ });
15043
+ }
15044
+ if (usdc) {
15045
+ rows.push({
15046
+ address: usdc,
14814
15047
  symbol: "USDC",
14815
15048
  decimals: 6,
14816
15049
  roles: ["swappable", "listed"]
14817
- },
14818
- {
14819
- address: AERODROME_BASE_ADDRESSES_FALLBACK.aero,
14820
- symbol: "AERO",
15050
+ });
15051
+ }
15052
+ rows.push({
15053
+ address: addrs.aero,
15054
+ symbol: "AERO",
15055
+ decimals: 18,
15056
+ roles: ["swappable"]
15057
+ });
15058
+ if (addrs.receiptToken.toLowerCase() !== addrs.aero.toLowerCase()) {
15059
+ rows.push({
15060
+ address: addrs.receiptToken,
15061
+ symbol: "xAERO",
14821
15062
  decimals: 18,
14822
15063
  roles: ["swappable"]
14823
- },
14824
- ...stocks.map((t) => ({
15064
+ });
15065
+ }
15066
+ for (const t of stocks) {
15067
+ rows.push({
14825
15068
  address: t.address,
14826
15069
  symbol: t.symbol,
14827
15070
  name: t.name,
14828
15071
  decimals: t.decimals || COINBASE_B20_STOCK_DECIMALS,
14829
15072
  roles: ["swappable", "listed", "coinbase_b20"]
14830
- }))
14831
- ];
15073
+ });
15074
+ }
15075
+ return rows;
14832
15076
  }
14833
15077
  var PROTOCOL_SUPPORT_ADVISORS = {
14834
15078
  "aave-v4": advisor("aave-v4", "api_underlyings", {
@@ -15139,16 +15383,17 @@ var PROTOCOL_SUPPORT_ADVISORS = {
15139
15383
  }),
15140
15384
  [AERODROME_PROTOCOL_ID]: advisor(AERODROME_PROTOCOL_ID, "pool_graph", {
15141
15385
  async supportedChainIds() {
15142
- return [AERODROME_CHAIN_ID];
15386
+ return [...AERO_CHAIN_IDS];
15143
15387
  },
15144
15388
  async supportedTokens(chainId) {
15145
- if (chainId !== AERODROME_CHAIN_ID) {
15146
- return { tokens: [], notes: "Aerodrome is Base-only (chainId 8453)." };
15389
+ if (!isAerodromeChainSupported(chainId)) {
15390
+ return { tokens: [], notes: aerodromeUnsupportedChainMessage(chainId) };
15147
15391
  }
15392
+ const addrs = aeroAddressesForChain(chainId);
15148
15393
  return {
15149
- tokens: await aerodromeAdvisorPriorityTokens(),
15150
- nativeWrapped: AERODROME_WETH_BASE,
15151
- notes: "ETH, WETH, USDC, AERO, plus the live Coinbase B20 catalog. For a price call ctm_aerodrome_quote with a ticker. To see pools for one token call ctm_aerodrome_discover_pools. Do not dump LpSugar."
15394
+ tokens: await aerodromeAdvisorPriorityTokens(chainId),
15395
+ nativeWrapped: addrs.weth === viem.zeroAddress ? void 0 : addrs.weth,
15396
+ notes: chainId === 8453 ? "Aero on Base: ETH, WETH, USDC, AERO, xAERO, plus the live Coinbase B20 catalog. For a price call ctm_aerodrome_quote with a ticker. To see pools for one token call ctm_aerodrome_discover_pools. Do not dump LpSugar." : "Aero on this chain: ETH, WETH, USDC when deployed, and the xAERO receipt. Coinbase stock LP is Base only. For a price call ctm_aerodrome_quote. To see pools call ctm_aerodrome_discover_pools."
15152
15397
  };
15153
15398
  }
15154
15399
  }),
@@ -15882,10 +16127,15 @@ exports.mcpRailgunFetchPopularAssetsInputSchema = mcpRailgunFetchPopularAssetsIn
15882
16127
  exports.mcpRailgunFetchPopularAssetsOutputSchema = mcpRailgunFetchPopularAssetsOutputSchema;
15883
16128
  exports.mcpRailgunFetchPrivateBalancesInputSchema = mcpRailgunFetchPrivateBalancesInputSchema;
15884
16129
  exports.mcpRailgunFetchPrivateBalancesOutputSchema = mcpRailgunFetchPrivateBalancesOutputSchema;
16130
+ exports.mcpRailgunListBroadcastersInputSchema = mcpRailgunListBroadcastersInputSchema;
16131
+ exports.mcpRailgunListBroadcastersOutputSchema = mcpRailgunListBroadcastersOutputSchema;
16132
+ exports.mcpRailgunListSpendsInputSchema = mcpRailgunListSpendsInputSchema;
16133
+ exports.mcpRailgunListSpendsOutputSchema = mcpRailgunListSpendsOutputSchema;
15885
16134
  exports.mcpRailgunPrivateActionOutputSchema = mcpRailgunPrivateActionOutputSchema;
15886
16135
  exports.mcpRailgunPrivateTransferInputSchema = mcpRailgunPrivateTransferInputSchema;
15887
16136
  exports.mcpRailgunShieldInputSchema = mcpRailgunShieldInputSchema;
15888
16137
  exports.mcpRailgunUnshieldInputSchema = mcpRailgunUnshieldInputSchema;
16138
+ exports.mcpRailgunUnwrapInputSchema = mcpRailgunUnwrapInputSchema;
15889
16139
  exports.mcpSearchPredictionMarketsInputSchema = mcpSearchPredictionMarketsInputSchema;
15890
16140
  exports.mcpSearchPredictionMarketsOutputSchema = mcpSearchPredictionMarketsOutputSchema;
15891
16141
  exports.mcpServerCommonInputSchema = mcpServerCommonInputSchema;