@t402/mcp 2.7.0 → 2.8.0

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.
package/dist/cjs/index.js CHANGED
@@ -519,7 +519,8 @@ var payInputSchema = import_zod3.z.object({
519
519
  "berachain",
520
520
  "unichain"
521
521
  ]).describe("Network to execute payment on"),
522
- memo: import_zod3.z.string().optional().describe("Optional memo/reference for the payment")
522
+ memo: import_zod3.z.string().optional().describe("Optional memo/reference for the payment"),
523
+ confirmed: import_zod3.z.boolean().optional().describe("Set to true to confirm and execute this payment")
523
524
  });
524
525
  function getViemChain2(network) {
525
526
  switch (network) {
@@ -548,6 +549,13 @@ function getViemChain2(network) {
548
549
  async function executePay(input, options) {
549
550
  const { to, amount, token, network, memo: _memo } = input;
550
551
  const { privateKey, rpcUrl, demoMode } = options;
552
+ if (!input.confirmed) {
553
+ return {
554
+ needsConfirmation: true,
555
+ summary: `Send ${amount} ${token} on ${network} to ${to}`,
556
+ details: { to, amount, token, network }
557
+ };
558
+ }
551
559
  if (!supportsToken(network, token)) {
552
560
  throw new Error(`Token ${token} is not supported on ${network}`);
553
561
  }
@@ -632,7 +640,8 @@ var payGaslessInputSchema = import_zod4.z.object({
632
640
  to: import_zod4.z.string().regex(/^0x[a-fA-F0-9]{40}$/).describe("Recipient address"),
633
641
  amount: import_zod4.z.string().regex(/^\d+(\.\d+)?$/).describe("Amount to pay (e.g., '10.50' for 10.50 USDC)"),
634
642
  token: import_zod4.z.enum(["USDC", "USDT", "USDT0"]).describe("Token to use for payment"),
635
- network: import_zod4.z.enum(["ethereum", "base", "arbitrum", "optimism", "polygon", "avalanche"]).describe("Network to execute gasless payment on (must support ERC-4337)")
643
+ network: import_zod4.z.enum(["ethereum", "base", "arbitrum", "optimism", "polygon", "avalanche"]).describe("Network to execute gasless payment on (must support ERC-4337)"),
644
+ confirmed: import_zod4.z.boolean().optional().describe("Set to true to confirm and execute this payment")
636
645
  });
637
646
  var GASLESS_SUPPORTED_NETWORKS = [
638
647
  "ethereum",
@@ -669,6 +678,13 @@ function getViemChain3(network) {
669
678
  async function executePayGasless(input, options) {
670
679
  const { to, amount, token, network } = input;
671
680
  const { privateKey, bundlerUrl, paymasterUrl: _paymasterUrl, rpcUrl, demoMode } = options;
681
+ if (!input.confirmed) {
682
+ return {
683
+ needsConfirmation: true,
684
+ summary: `Send ${amount} ${token} gasless on ${network} to ${to}`,
685
+ details: { to, amount, token, network }
686
+ };
687
+ }
672
688
  if (!GASLESS_SUPPORTED_NETWORKS.includes(network)) {
673
689
  throw new Error(
674
690
  `Network ${network} does not support ERC-4337 gasless transactions. Supported: ${GASLESS_SUPPORTED_NETWORKS.join(", ")}`
@@ -954,7 +970,8 @@ var bridgeInputSchema = import_zod6.z.object({
954
970
  fromChain: import_zod6.z.enum(["ethereum", "arbitrum", "ink", "berachain", "unichain"]).describe("Source chain to bridge from"),
955
971
  toChain: import_zod6.z.enum(["ethereum", "arbitrum", "ink", "berachain", "unichain"]).describe("Destination chain to bridge to"),
956
972
  amount: import_zod6.z.string().regex(/^\d+(\.\d+)?$/).describe("Amount of USDT0 to bridge (e.g., '100' for 100 USDT0)"),
957
- recipient: import_zod6.z.string().regex(/^0x[a-fA-F0-9]{40}$/).describe("Recipient address on destination chain")
973
+ recipient: import_zod6.z.string().regex(/^0x[a-fA-F0-9]{40}$/).describe("Recipient address on destination chain"),
974
+ confirmed: import_zod6.z.boolean().optional().describe("Set to true to confirm and execute this bridge")
958
975
  });
959
976
  var LAYERZERO_ENDPOINT_IDS2 = {
960
977
  ethereum: 30101,
@@ -1081,6 +1098,13 @@ function addressToBytes322(address) {
1081
1098
  async function executeBridge(input, options) {
1082
1099
  const { fromChain, toChain, amount, recipient } = input;
1083
1100
  const { privateKey, rpcUrl, demoMode, slippageTolerance = 0.5 } = options;
1101
+ if (!input.confirmed) {
1102
+ return {
1103
+ needsConfirmation: true,
1104
+ summary: `Bridge ${amount} USDT0 from ${fromChain} to ${toChain}`,
1105
+ details: { fromChain, toChain, amount, recipient }
1106
+ };
1107
+ }
1084
1108
  if (fromChain === toChain) {
1085
1109
  throw new Error("Source and destination chains must be different");
1086
1110
  }
@@ -1210,10 +1234,10 @@ var import_zod7 = require("zod");
1210
1234
  var wdkGetWalletInputSchema = import_zod7.z.object({});
1211
1235
  async function executeWdkGetWallet(_input, wdk) {
1212
1236
  const signer = await wdk.getSigner("ethereum");
1213
- const chains7 = wdk.getConfiguredChains();
1237
+ const chains9 = wdk.getConfiguredChains();
1214
1238
  return {
1215
1239
  evmAddress: signer.address,
1216
- chains: chains7.length > 0 ? chains7 : ["ethereum"]
1240
+ chains: chains9.length > 0 ? chains9 : ["ethereum"]
1217
1241
  };
1218
1242
  }
1219
1243
  function executeWdkGetWalletDemo() {
@@ -1245,14 +1269,14 @@ function findTokenFormatted(tokens, symbol) {
1245
1269
  }
1246
1270
  async function executeWdkGetBalances(input, wdk) {
1247
1271
  const balances = await wdk.getAggregatedBalances();
1248
- const chains7 = balances.chains.filter((c) => !input.chains || input.chains.includes(c.chain)).map((c) => ({
1272
+ const chains9 = balances.chains.filter((c) => !input.chains || input.chains.includes(c.chain)).map((c) => ({
1249
1273
  chain: c.chain,
1250
1274
  usdt0: findTokenFormatted(c.tokens, "USDT0"),
1251
1275
  usdc: findTokenFormatted(c.tokens, "USDC"),
1252
1276
  native: (0, import_viem6.formatUnits)(c.native, 18)
1253
1277
  }));
1254
1278
  return {
1255
- chains: chains7,
1279
+ chains: chains9,
1256
1280
  totalUsdt0: (0, import_viem6.formatUnits)(balances.totalUsdt0, 6),
1257
1281
  totalUsdc: (0, import_viem6.formatUnits)(balances.totalUsdc, 6)
1258
1282
  };
@@ -1294,9 +1318,17 @@ var wdkTransferInputSchema = import_zod9.z.object({
1294
1318
  to: import_zod9.z.string().describe("Recipient address"),
1295
1319
  amount: import_zod9.z.string().regex(/^\d+(\.\d+)?$/).describe("Amount to send (e.g., '10.50')"),
1296
1320
  token: import_zod9.z.enum(["USDC", "USDT", "USDT0"]).describe("Token to transfer"),
1297
- chain: import_zod9.z.string().describe('Chain to execute transfer on (e.g., "ethereum", "arbitrum")')
1321
+ chain: import_zod9.z.string().describe('Chain to execute transfer on (e.g., "ethereum", "arbitrum")'),
1322
+ confirmed: import_zod9.z.boolean().optional().describe("Set to true to confirm and execute this transfer")
1298
1323
  });
1299
1324
  async function executeWdkTransfer(input, wdk) {
1325
+ if (!input.confirmed) {
1326
+ return {
1327
+ needsConfirmation: true,
1328
+ summary: `Transfer ${input.amount} ${input.token} on ${input.chain} to ${input.to}`,
1329
+ details: { to: input.to, amount: input.amount, token: input.token, chain: input.chain }
1330
+ };
1331
+ }
1300
1332
  const signer = await wdk.getSigner(input.chain);
1301
1333
  const result = await signer.sendTransaction({
1302
1334
  to: input.to
@@ -1313,6 +1345,13 @@ async function executeWdkTransfer(input, wdk) {
1313
1345
  };
1314
1346
  }
1315
1347
  function executeWdkTransferDemo(input) {
1348
+ if (!input.confirmed) {
1349
+ return {
1350
+ needsConfirmation: true,
1351
+ summary: `Transfer ${input.amount} ${input.token} on ${input.chain} to ${input.to}`,
1352
+ details: { to: input.to, amount: input.amount, token: input.token, chain: input.chain }
1353
+ };
1354
+ }
1316
1355
  const demoTxHash = "0xdemo" + Math.random().toString(16).slice(2, 10);
1317
1356
  return {
1318
1357
  txHash: demoTxHash,
@@ -1342,9 +1381,22 @@ var wdkSwapInputSchema = import_zod10.z.object({
1342
1381
  fromToken: import_zod10.z.string().describe('Token to swap from (e.g., "ETH", "USDC")'),
1343
1382
  toToken: import_zod10.z.string().describe('Token to swap to (e.g., "USDT0", "USDC")'),
1344
1383
  amount: import_zod10.z.string().regex(/^\d+(\.\d+)?$/).describe("Amount to swap (e.g., '1.0')"),
1345
- chain: import_zod10.z.string().describe('Chain to execute swap on (e.g., "ethereum", "arbitrum")')
1384
+ chain: import_zod10.z.string().describe('Chain to execute swap on (e.g., "ethereum", "arbitrum")'),
1385
+ confirmed: import_zod10.z.boolean().optional().describe("Set to true to confirm and execute this swap")
1346
1386
  });
1347
1387
  async function executeWdkSwap(input, wdk) {
1388
+ if (!input.confirmed) {
1389
+ return {
1390
+ needsConfirmation: true,
1391
+ summary: `Swap ${input.amount} ${input.fromToken} to ${input.toToken} on ${input.chain}`,
1392
+ details: {
1393
+ fromToken: input.fromToken,
1394
+ toToken: input.toToken,
1395
+ amount: input.amount,
1396
+ chain: input.chain
1397
+ }
1398
+ };
1399
+ }
1348
1400
  const decimals = ["USDC", "USDT", "USDT0"].includes(input.fromToken.toUpperCase()) ? 6 : 18;
1349
1401
  const amountBigInt = (0, import_viem7.parseUnits)(input.amount, decimals);
1350
1402
  const quote = await wdk.getSwapQuote(input.chain, input.fromToken, amountBigInt);
@@ -1365,6 +1417,18 @@ async function executeWdkSwap(input, wdk) {
1365
1417
  };
1366
1418
  }
1367
1419
  function executeWdkSwapDemo(input) {
1420
+ if (!input.confirmed) {
1421
+ return {
1422
+ needsConfirmation: true,
1423
+ summary: `Swap ${input.amount} ${input.fromToken} to ${input.toToken} on ${input.chain}`,
1424
+ details: {
1425
+ fromToken: input.fromToken,
1426
+ toToken: input.toToken,
1427
+ amount: input.amount,
1428
+ chain: input.chain
1429
+ }
1430
+ };
1431
+ }
1368
1432
  const inputAmount = parseFloat(input.amount);
1369
1433
  const outputAmount = (inputAmount * 0.997).toFixed(6);
1370
1434
  return {
@@ -1397,12 +1461,24 @@ var autoPayInputSchema = import_zod11.z.object({
1397
1461
  maxAmount: import_zod11.z.string().regex(/^\d+(\.\d+)?$/).optional().describe('Maximum amount willing to pay (e.g., "10.00"). If not set, pays any amount.'),
1398
1462
  preferredChain: import_zod11.z.string().optional().describe(
1399
1463
  'Preferred chain for payment (e.g., "arbitrum"). If not specified, uses first available.'
1400
- )
1464
+ ),
1465
+ confirmed: import_zod11.z.boolean().optional().describe("Set to true to confirm and execute this payment")
1401
1466
  });
1402
1467
  async function executeAutoPay(input, wdk) {
1403
- const chains7 = input.preferredChain ? [input.preferredChain] : ["ethereum", "arbitrum", "base"];
1468
+ if (!input.confirmed) {
1469
+ return {
1470
+ needsConfirmation: true,
1471
+ summary: `Auto-pay for ${input.url}${input.maxAmount ? ` (max ${input.maxAmount})` : ""}`,
1472
+ details: {
1473
+ url: input.url,
1474
+ ...input.maxAmount ? { maxAmount: input.maxAmount } : {},
1475
+ ...input.preferredChain ? { preferredChain: input.preferredChain } : {}
1476
+ }
1477
+ };
1478
+ }
1479
+ const chains9 = input.preferredChain ? [input.preferredChain] : ["ethereum", "arbitrum", "base"];
1404
1480
  const { T402Protocol } = await import("@t402/wdk-protocol");
1405
- const protocol = await T402Protocol.create(wdk, { chains: chains7 });
1481
+ const protocol = await T402Protocol.create(wdk, { chains: chains9 });
1406
1482
  const { response, receipt } = await protocol.fetch(input.url);
1407
1483
  if (receipt && input.maxAmount) {
1408
1484
  const paidAmount = parseFloat(receipt.amount) / 1e6;
@@ -1440,6 +1516,17 @@ async function executeAutoPay(input, wdk) {
1440
1516
  };
1441
1517
  }
1442
1518
  function executeAutoPayDemo(input) {
1519
+ if (!input.confirmed) {
1520
+ return {
1521
+ needsConfirmation: true,
1522
+ summary: `Auto-pay for ${input.url}${input.maxAmount ? ` (max ${input.maxAmount})` : ""}`,
1523
+ details: {
1524
+ url: input.url,
1525
+ ...input.maxAmount ? { maxAmount: input.maxAmount } : {},
1526
+ ...input.preferredChain ? { preferredChain: input.preferredChain } : {}
1527
+ }
1528
+ };
1529
+ }
1443
1530
  return {
1444
1531
  success: true,
1445
1532
  statusCode: 200,
@@ -1883,197 +1970,939 @@ function formatErc8004VerifyWalletResult(result) {
1883
1970
  return lines.join("\n");
1884
1971
  }
1885
1972
 
1886
- // src/tools/unified.ts
1887
- var import_zod15 = require("zod");
1888
- var smartPayInputSchema = import_zod15.z.object({
1889
- url: import_zod15.z.string().url().describe("URL of the 402-protected resource"),
1890
- maxBridgeFee: import_zod15.z.string().regex(/^\d+(\.\d+)?$/).optional().describe("Maximum acceptable bridge fee in native token (optional)"),
1891
- preferredNetwork: import_zod15.z.string().optional().describe("Preferred network for payment (optional)")
1892
- });
1893
- var paymentPlanInputSchema = import_zod15.z.object({
1894
- paymentRequired: import_zod15.z.object({
1895
- scheme: import_zod15.z.string().optional(),
1896
- network: import_zod15.z.string().optional(),
1897
- maxAmountRequired: import_zod15.z.string().optional(),
1898
- resource: import_zod15.z.string().optional(),
1899
- description: import_zod15.z.string().optional(),
1900
- payTo: import_zod15.z.string().optional(),
1901
- maxDeadline: import_zod15.z.number().optional()
1902
- }).passthrough().describe("The 402 PaymentRequired response")
1903
- });
1904
- var UNIFIED_TOOL_DEFINITIONS = {
1905
- "t402/smartPay": {
1906
- name: "t402/smartPay",
1907
- description: "Intelligent payment that automatically checks balance, bridges if needed, and pays. Handles the entire payment flow for 402-protected resources.",
1908
- inputSchema: {
1909
- type: "object",
1910
- properties: {
1911
- url: { type: "string", description: "URL of the 402-protected resource" },
1912
- maxBridgeFee: {
1913
- type: "string",
1914
- description: "Maximum acceptable bridge fee in native token (optional)"
1915
- },
1916
- preferredNetwork: {
1917
- type: "string",
1918
- description: "Preferred network for payment (optional)"
1919
- }
1920
- },
1921
- required: ["url"]
1922
- }
1923
- },
1924
- "t402/paymentPlan": {
1925
- name: "t402/paymentPlan",
1926
- description: "Analyze a 402 response and create an optimal payment plan considering balances across all chains. Returns recommended network, bridge requirements, and balance overview.",
1927
- inputSchema: {
1928
- type: "object",
1929
- properties: {
1930
- paymentRequired: {
1931
- type: "object",
1932
- description: "The 402 PaymentRequired response"
1933
- }
1934
- },
1935
- required: ["paymentRequired"]
1936
- }
1937
- }
1973
+ // src/tools/priceService.ts
1974
+ var CACHE_TTL_MS = 5 * 60 * 1e3;
1975
+ var COINGECKO_API = "https://api.coingecko.com/api/v3/simple/price";
1976
+ var TOKEN_TO_COINGECKO_ID = {
1977
+ ETH: "ethereum",
1978
+ MATIC: "matic-network",
1979
+ AVAX: "avalanche-2",
1980
+ BERA: "berachain-bera",
1981
+ USDC: "usd-coin",
1982
+ USDT: "tether",
1983
+ USDT0: "tether"
1938
1984
  };
1939
- async function executeSmartPay(input, wdk) {
1940
- const steps = [];
1941
- const chains7 = input.preferredNetwork ? [input.preferredNetwork] : ["ethereum", "arbitrum", "base"];
1942
- steps.push({
1943
- action: "check_balance",
1944
- status: "success",
1945
- detail: `Checking balances on ${chains7.join(", ")}`
1946
- });
1947
- const { T402Protocol } = await import("@t402/wdk-protocol");
1948
- const protocol = await T402Protocol.create(wdk, { chains: chains7 });
1949
- steps.push({
1950
- action: "fetch",
1951
- status: "success",
1952
- detail: `Fetching ${input.url}`
1953
- });
1954
- const { response, receipt } = await protocol.fetch(input.url);
1955
- if (receipt) {
1956
- steps.push({
1957
- action: "pay",
1958
- status: "success",
1959
- detail: `Payment made: ${receipt.amount} on ${receipt.network}`
1960
- });
1985
+ var cache = /* @__PURE__ */ new Map();
1986
+ async function getTokenPrices(tokens, currency = "usd") {
1987
+ const cacheKey = `${currency}:${tokens.sort().join(",")}`;
1988
+ const cached = cache.get(cacheKey);
1989
+ if (cached && Date.now() - cached.timestamp < CACHE_TTL_MS) {
1990
+ return cached.prices;
1961
1991
  }
1962
- const contentType = response.headers.get("content-type") ?? void 0;
1963
- let body = "";
1964
- try {
1965
- body = await response.text();
1966
- if (body.length > 1e4) {
1967
- body = body.slice(0, 1e4) + "\n... (truncated)";
1968
- }
1969
- } catch {
1970
- body = "[Could not read response body]";
1992
+ const coinIds = /* @__PURE__ */ new Set();
1993
+ const tokenToCoinId = /* @__PURE__ */ new Map();
1994
+ for (const token of tokens) {
1995
+ const coinId = TOKEN_TO_COINGECKO_ID[token.toUpperCase()] ?? token.toLowerCase();
1996
+ coinIds.add(coinId);
1997
+ tokenToCoinId.set(token.toUpperCase(), coinId);
1971
1998
  }
1972
- return {
1973
- success: response.ok,
1974
- statusCode: response.status,
1975
- body,
1976
- contentType,
1977
- steps,
1978
- payment: receipt ? {
1979
- network: receipt.network,
1980
- scheme: receipt.scheme,
1981
- amount: receipt.amount,
1982
- payTo: receipt.payTo
1983
- } : void 0
1999
+ const url = `${COINGECKO_API}?ids=${[...coinIds].join(",")}&vs_currencies=${currency}`;
2000
+ const response = await fetch(url);
2001
+ if (!response.ok) {
2002
+ throw new Error(`CoinGecko API error: ${response.status} ${response.statusText}`);
2003
+ }
2004
+ const data = await response.json();
2005
+ const prices = {};
2006
+ for (const token of tokens) {
2007
+ const coinId = tokenToCoinId.get(token.toUpperCase()) ?? token.toLowerCase();
2008
+ prices[token.toUpperCase()] = data[coinId]?.[currency] ?? 0;
2009
+ }
2010
+ cache.set(cacheKey, { prices, timestamp: Date.now() });
2011
+ return prices;
2012
+ }
2013
+ function getTokenPricesDemo(tokens) {
2014
+ const demoPrices = {
2015
+ ETH: 3250.42,
2016
+ MATIC: 0.58,
2017
+ AVAX: 24.15,
2018
+ BERA: 3.82,
2019
+ USDC: 1,
2020
+ USDT: 1,
2021
+ USDT0: 1
1984
2022
  };
2023
+ const prices = {};
2024
+ for (const token of tokens) {
2025
+ prices[token.toUpperCase()] = demoPrices[token.toUpperCase()] ?? 0;
2026
+ }
2027
+ return prices;
1985
2028
  }
1986
- function executeSmartPayDemo(input) {
1987
- const network = input.preferredNetwork ?? "arbitrum";
1988
- return {
1989
- success: true,
1990
- statusCode: 200,
1991
- body: `[Demo] Premium content from ${input.url}
1992
2029
 
1993
- This is simulated content returned after smart payment.`,
1994
- contentType: "text/plain",
1995
- steps: [
1996
- { action: "check_balance", status: "success", detail: `Checked balances on ${network}` },
1997
- { action: "check_price", status: "success", detail: "Resource costs 1.00 USDT0" },
1998
- { action: "pay", status: "success", detail: `Paid 1000000 USDT0 on eip155:42161` },
1999
- { action: "fetch", status: "success", detail: `Fetched ${input.url}` }
2000
- ],
2001
- payment: {
2002
- network: "eip155:42161",
2003
- scheme: "exact",
2004
- amount: "1000000",
2005
- payTo: "0xC88f67e776f16DcFBf42e6bDda1B82604448899B"
2030
+ // src/tools/getTokenPrice.ts
2031
+ var import_zod15 = require("zod");
2032
+ var getTokenPriceInputSchema = import_zod15.z.object({
2033
+ tokens: import_zod15.z.array(import_zod15.z.string()).min(1).describe('Token symbols to get prices for (e.g., ["ETH", "MATIC", "USDC"])'),
2034
+ currency: import_zod15.z.string().optional().describe('Target currency (default: "usd"). Supports: usd, eur, gbp, etc.')
2035
+ });
2036
+ async function executeGetTokenPrice(input, options) {
2037
+ const currency = input.currency ?? "usd";
2038
+ const prices = options.demoMode ? getTokenPricesDemo(input.tokens) : await getTokenPrices(input.tokens, currency);
2039
+ return { prices, currency };
2040
+ }
2041
+ function formatTokenPriceResult(result) {
2042
+ const lines = ["## Token Prices", ""];
2043
+ const currencyUpper = result.currency.toUpperCase();
2044
+ for (const [token, price] of Object.entries(result.prices)) {
2045
+ if (price > 0) {
2046
+ lines.push(`- **${token}:** ${price.toLocaleString()} ${currencyUpper}`);
2047
+ } else {
2048
+ lines.push(`- **${token}:** Price unavailable`);
2006
2049
  }
2007
- };
2050
+ }
2051
+ return lines.join("\n");
2008
2052
  }
2009
- async function executePaymentPlan(input, wdk) {
2010
- const targetNetwork = input.paymentRequired.network;
2011
- const requiredAmount = input.paymentRequired.maxAmountRequired;
2012
- const aggregated = await wdk.getAggregatedBalances();
2013
- const balances = aggregated.chains.map((chain) => {
2014
- const usdt0 = chain.tokens.find((t) => t.symbol === "USDT0");
2015
- const usdc = chain.tokens.find((t) => t.symbol === "USDC");
2016
- return {
2017
- chain: chain.chain,
2018
- usdt0: usdt0?.formatted ?? "0",
2019
- usdc: usdc?.formatted ?? "0"
2053
+
2054
+ // src/tools/getGasPrice.ts
2055
+ var import_zod16 = require("zod");
2056
+ var import_viem9 = require("viem");
2057
+ var chains7 = __toESM(require("viem/chains"));
2058
+ var getGasPriceInputSchema = import_zod16.z.object({
2059
+ network: import_zod16.z.enum([
2060
+ "ethereum",
2061
+ "base",
2062
+ "arbitrum",
2063
+ "optimism",
2064
+ "polygon",
2065
+ "avalanche",
2066
+ "ink",
2067
+ "berachain",
2068
+ "unichain"
2069
+ ]).describe("Blockchain network to check gas price on")
2070
+ });
2071
+ function getViemChain6(network) {
2072
+ switch (network) {
2073
+ case "ethereum":
2074
+ return chains7.mainnet;
2075
+ case "base":
2076
+ return chains7.base;
2077
+ case "arbitrum":
2078
+ return chains7.arbitrum;
2079
+ case "optimism":
2080
+ return chains7.optimism;
2081
+ case "polygon":
2082
+ return chains7.polygon;
2083
+ case "avalanche":
2084
+ return chains7.avalanche;
2085
+ case "ink":
2086
+ return chains7.ink;
2087
+ case "berachain":
2088
+ return chains7.berachain;
2089
+ case "unichain":
2090
+ return chains7.unichain;
2091
+ default:
2092
+ return chains7.mainnet;
2093
+ }
2094
+ }
2095
+ async function executeGetGasPrice(input, options) {
2096
+ const { network } = input;
2097
+ if (options.demoMode) {
2098
+ const demoGasPrices = {
2099
+ ethereum: 25000000000n,
2100
+ // 25 gwei
2101
+ base: 50000000n,
2102
+ // 0.05 gwei
2103
+ arbitrum: 100000000n,
2104
+ // 0.1 gwei
2105
+ optimism: 50000000n,
2106
+ // 0.05 gwei
2107
+ polygon: 30000000000n,
2108
+ // 30 gwei
2109
+ avalanche: 25000000000n,
2110
+ // 25 nAVAX
2111
+ ink: 50000000n,
2112
+ // 0.05 gwei
2113
+ berachain: 1000000000n,
2114
+ // 1 gwei
2115
+ unichain: 50000000n
2116
+ // 0.05 gwei
2020
2117
  };
2021
- });
2022
- const requiredBigint = requiredAmount ? BigInt(requiredAmount) : 0n;
2023
- const bestChain = await wdk.findBestChainForPayment(requiredBigint);
2024
- if (bestChain) {
2025
- const needsBridge = targetNetwork ? !bestChain.chain.includes(targetNetwork) : false;
2118
+ const gasPrice2 = demoGasPrices[network] ?? 1000000000n;
2026
2119
  return {
2027
- viable: true,
2028
- recommendedNetwork: bestChain.chain,
2029
- availableBalance: bestChain.balance.toString(),
2030
- bridgeRequired: needsBridge,
2031
- bridgeDetails: needsBridge ? {
2032
- fromChain: bestChain.chain,
2033
- toChain: targetNetwork ?? bestChain.chain,
2034
- amount: requiredAmount ?? "0",
2035
- estimatedFee: "0.001"
2036
- } : void 0,
2037
- balances
2120
+ network,
2121
+ gasPriceWei: gasPrice2.toString(),
2122
+ gasPriceGwei: (0, import_viem9.formatGwei)(gasPrice2),
2123
+ nativeSymbol: NATIVE_SYMBOLS[network]
2038
2124
  };
2039
2125
  }
2126
+ const chain = getViemChain6(network);
2127
+ const transport = (0, import_viem9.http)(options.rpcUrl ?? DEFAULT_RPC_URLS[network]);
2128
+ const client = (0, import_viem9.createPublicClient)({ chain, transport });
2129
+ const gasPrice = await client.getGasPrice();
2040
2130
  return {
2041
- viable: false,
2042
- bridgeRequired: false,
2043
- balances,
2044
- reason: "Insufficient balance across all chains"
2131
+ network,
2132
+ gasPriceWei: gasPrice.toString(),
2133
+ gasPriceGwei: (0, import_viem9.formatGwei)(gasPrice),
2134
+ nativeSymbol: NATIVE_SYMBOLS[network]
2045
2135
  };
2046
2136
  }
2047
- function executePaymentPlanDemo(_input) {
2048
- return {
2049
- viable: true,
2050
- recommendedNetwork: "arbitrum",
2051
- availableBalance: "500000000",
2052
- bridgeRequired: false,
2053
- balances: [
2054
- { chain: "ethereum", usdt0: "100.00", usdc: "250.00" },
2055
- { chain: "arbitrum", usdt0: "500.00", usdc: "0" },
2056
- { chain: "base", usdt0: "50.00", usdc: "100.00" }
2057
- ]
2058
- };
2137
+ function formatGasPriceResult(result) {
2138
+ return [
2139
+ "## Gas Price",
2140
+ "",
2141
+ `- **Network:** ${result.network}`,
2142
+ `- **Gas Price:** ${result.gasPriceGwei} gwei`,
2143
+ `- **Native Token:** ${result.nativeSymbol}`
2144
+ ].join("\n");
2059
2145
  }
2060
- function formatSmartPayResult(result) {
2061
- const lines = ["## SmartPay Result", ""];
2062
- if (result.success) {
2063
- lines.push(`**Status:** Success (${result.statusCode})`);
2064
- } else {
2065
- lines.push(`**Status:** Failed (${result.statusCode})`);
2146
+
2147
+ // src/tools/estimatePaymentFee.ts
2148
+ var import_zod17 = require("zod");
2149
+ var import_viem10 = require("viem");
2150
+ var chains8 = __toESM(require("viem/chains"));
2151
+ var estimatePaymentFeeInputSchema = import_zod17.z.object({
2152
+ network: import_zod17.z.enum([
2153
+ "ethereum",
2154
+ "base",
2155
+ "arbitrum",
2156
+ "optimism",
2157
+ "polygon",
2158
+ "avalanche",
2159
+ "ink",
2160
+ "berachain",
2161
+ "unichain"
2162
+ ]).describe("Network to estimate fee on"),
2163
+ amount: import_zod17.z.string().regex(/^\d+(\.\d+)?$/).describe("Payment amount (e.g., '100')"),
2164
+ token: import_zod17.z.enum(["USDC", "USDT", "USDT0"]).describe("Token to use for payment")
2165
+ });
2166
+ function getViemChain7(network) {
2167
+ switch (network) {
2168
+ case "ethereum":
2169
+ return chains8.mainnet;
2170
+ case "base":
2171
+ return chains8.base;
2172
+ case "arbitrum":
2173
+ return chains8.arbitrum;
2174
+ case "optimism":
2175
+ return chains8.optimism;
2176
+ case "polygon":
2177
+ return chains8.polygon;
2178
+ case "avalanche":
2179
+ return chains8.avalanche;
2180
+ case "ink":
2181
+ return chains8.ink;
2182
+ case "berachain":
2183
+ return chains8.berachain;
2184
+ case "unichain":
2185
+ return chains8.unichain;
2186
+ default:
2187
+ return chains8.mainnet;
2066
2188
  }
2067
- if (result.steps.length > 0) {
2068
- lines.push("");
2069
- lines.push("### Steps");
2070
- for (const step of result.steps) {
2071
- const icon = step.status === "success" ? "[OK]" : step.status === "skipped" ? "[SKIP]" : "[FAIL]";
2072
- lines.push(`- ${icon} **${step.action}**: ${step.detail}`);
2073
- }
2189
+ }
2190
+ async function executeEstimatePaymentFee(input, options) {
2191
+ const { network, amount, token } = input;
2192
+ const nativeSymbol = NATIVE_SYMBOLS[network];
2193
+ if (options.demoMode) {
2194
+ const demoEstimates = {
2195
+ ethereum: { gasLimit: 65000n, gasPrice: 25000000000n, nativePrice: 3250.42 },
2196
+ base: { gasLimit: 65000n, gasPrice: 50000000n, nativePrice: 3250.42 },
2197
+ arbitrum: { gasLimit: 65000n, gasPrice: 100000000n, nativePrice: 3250.42 },
2198
+ optimism: { gasLimit: 65000n, gasPrice: 50000000n, nativePrice: 3250.42 },
2199
+ polygon: { gasLimit: 65000n, gasPrice: 30000000000n, nativePrice: 0.58 },
2200
+ avalanche: { gasLimit: 65000n, gasPrice: 25000000000n, nativePrice: 24.15 },
2201
+ ink: { gasLimit: 65000n, gasPrice: 50000000n, nativePrice: 3250.42 },
2202
+ berachain: { gasLimit: 65000n, gasPrice: 1000000000n, nativePrice: 3.82 },
2203
+ unichain: { gasLimit: 65000n, gasPrice: 50000000n, nativePrice: 3250.42 }
2204
+ };
2205
+ const est = demoEstimates[network] ?? demoEstimates["ethereum"];
2206
+ const nativeCost2 = est.gasLimit * est.gasPrice;
2207
+ const usdCost2 = Number(nativeCost2) / 1e18 * est.nativePrice;
2208
+ return {
2209
+ network,
2210
+ gasLimit: est.gasLimit.toString(),
2211
+ gasPriceGwei: (0, import_viem10.formatGwei)(est.gasPrice),
2212
+ nativeCost: (0, import_viem10.formatEther)(nativeCost2),
2213
+ nativeSymbol,
2214
+ usdCost: `$${usdCost2.toFixed(4)}`
2215
+ };
2074
2216
  }
2075
- if (result.payment) {
2076
- lines.push("");
2217
+ const tokenAddress = getTokenAddress(network, token);
2218
+ if (!tokenAddress) {
2219
+ throw new Error(`Token ${token} is not supported on ${network}`);
2220
+ }
2221
+ const chain = getViemChain7(network);
2222
+ const transport = (0, import_viem10.http)(options.rpcUrl ?? DEFAULT_RPC_URLS[network]);
2223
+ const client = (0, import_viem10.createPublicClient)({ chain, transport });
2224
+ const amountBigInt = (0, import_viem10.parseUnits)(amount, 6);
2225
+ const dummyTo = "0x000000000000000000000000000000000000dEaD";
2226
+ let gasLimit;
2227
+ try {
2228
+ gasLimit = await client.estimateGas({
2229
+ to: tokenAddress,
2230
+ data: `0xa9059cbb${dummyTo.slice(2).padStart(64, "0")}${amountBigInt.toString(16).padStart(64, "0")}`
2231
+ });
2232
+ } catch {
2233
+ gasLimit = 65000n;
2234
+ }
2235
+ const gasPrice = await client.getGasPrice();
2236
+ const nativeCost = gasLimit * gasPrice;
2237
+ let usdCost;
2238
+ try {
2239
+ const prices = await getTokenPrices([nativeSymbol]);
2240
+ const nativePrice = prices[nativeSymbol] ?? 0;
2241
+ const cost = Number(nativeCost) / 1e18 * nativePrice;
2242
+ usdCost = `$${cost.toFixed(4)}`;
2243
+ } catch {
2244
+ usdCost = "N/A";
2245
+ }
2246
+ return {
2247
+ network,
2248
+ gasLimit: gasLimit.toString(),
2249
+ gasPriceGwei: (0, import_viem10.formatGwei)(gasPrice),
2250
+ nativeCost: (0, import_viem10.formatEther)(nativeCost),
2251
+ nativeSymbol,
2252
+ usdCost
2253
+ };
2254
+ }
2255
+ function formatPaymentFeeEstimate(result) {
2256
+ return [
2257
+ "## Payment Fee Estimate",
2258
+ "",
2259
+ `- **Network:** ${result.network}`,
2260
+ `- **Estimated Gas:** ${result.gasLimit}`,
2261
+ `- **Gas Price:** ${result.gasPriceGwei} gwei`,
2262
+ `- **Native Cost:** ${result.nativeCost} ${result.nativeSymbol}`,
2263
+ `- **USD Cost:** ${result.usdCost}`
2264
+ ].join("\n");
2265
+ }
2266
+
2267
+ // src/tools/compareNetworkFees.ts
2268
+ var import_zod18 = require("zod");
2269
+ var compareNetworkFeesInputSchema = import_zod18.z.object({
2270
+ amount: import_zod18.z.string().regex(/^\d+(\.\d+)?$/).describe("Payment amount (e.g., '100')"),
2271
+ token: import_zod18.z.enum(["USDC", "USDT", "USDT0"]).describe("Token to use for payment"),
2272
+ networks: import_zod18.z.array(import_zod18.z.string()).optional().describe(
2273
+ "Networks to compare. If not provided, compares all networks that support the token."
2274
+ )
2275
+ });
2276
+ var ALL_NETWORKS2 = [
2277
+ "ethereum",
2278
+ "base",
2279
+ "arbitrum",
2280
+ "optimism",
2281
+ "polygon",
2282
+ "avalanche",
2283
+ "ink",
2284
+ "berachain",
2285
+ "unichain"
2286
+ ];
2287
+ async function executeCompareNetworkFees(input, options) {
2288
+ const { amount, token } = input;
2289
+ const requestedNetworks = input.networks ? input.networks : ALL_NETWORKS2;
2290
+ const networks = requestedNetworks.filter((n) => supportsToken(n, token));
2291
+ if (networks.length === 0) {
2292
+ throw new Error(`No supported networks found for token ${token}`);
2293
+ }
2294
+ const results = await Promise.allSettled(
2295
+ networks.map(
2296
+ (network) => executeEstimatePaymentFee(
2297
+ { network, amount, token },
2298
+ {
2299
+ rpcUrl: options.rpcUrls?.[network],
2300
+ demoMode: options.demoMode
2301
+ }
2302
+ )
2303
+ )
2304
+ );
2305
+ const fees = [];
2306
+ for (const result of results) {
2307
+ if (result.status === "fulfilled") {
2308
+ fees.push(result.value);
2309
+ }
2310
+ }
2311
+ if (fees.length === 0) {
2312
+ throw new Error("Failed to estimate fees on any network");
2313
+ }
2314
+ fees.sort((a, b) => {
2315
+ const costA = parseFloat(a.nativeCost) || Infinity;
2316
+ const costB = parseFloat(b.nativeCost) || Infinity;
2317
+ const usdA = parseFloat(a.usdCost.replace("$", "")) || Infinity;
2318
+ const usdB = parseFloat(b.usdCost.replace("$", "")) || Infinity;
2319
+ return usdA - usdB || costA - costB;
2320
+ });
2321
+ return {
2322
+ token,
2323
+ amount,
2324
+ fees,
2325
+ cheapest: fees[0].network
2326
+ };
2327
+ }
2328
+ function formatNetworkFeeComparison(result) {
2329
+ const lines = [
2330
+ "## Network Fee Comparison",
2331
+ "",
2332
+ `**Token:** ${result.token} | **Amount:** ${result.amount}`,
2333
+ `**Cheapest:** ${result.cheapest}`,
2334
+ "",
2335
+ "| Network | Gas Price | Native Cost | USD Cost |",
2336
+ "|---------|----------|-------------|----------|"
2337
+ ];
2338
+ for (const fee of result.fees) {
2339
+ const marker = fee.network === result.cheapest ? " *" : "";
2340
+ lines.push(
2341
+ `| ${fee.network}${marker} | ${fee.gasPriceGwei} gwei | ${fee.nativeCost} ${fee.nativeSymbol} | ${fee.usdCost} |`
2342
+ );
2343
+ }
2344
+ return lines.join("\n");
2345
+ }
2346
+
2347
+ // src/tools/quoteStore.ts
2348
+ var import_crypto = require("crypto");
2349
+ var DEFAULT_TTL_MS = 5 * 60 * 1e3;
2350
+ var quotes = /* @__PURE__ */ new Map();
2351
+ var cleanupInterval = null;
2352
+ function ensureCleanup() {
2353
+ if (cleanupInterval) return;
2354
+ cleanupInterval = setInterval(() => {
2355
+ const now = Date.now();
2356
+ for (const [id, quote] of quotes) {
2357
+ if (now > quote.expiresAt) {
2358
+ quotes.delete(id);
2359
+ }
2360
+ }
2361
+ }, 6e4);
2362
+ if (cleanupInterval.unref) {
2363
+ cleanupInterval.unref();
2364
+ }
2365
+ }
2366
+ function createQuote(type, data, ttlMs = DEFAULT_TTL_MS) {
2367
+ ensureCleanup();
2368
+ const id = (0, import_crypto.randomUUID)();
2369
+ const now = Date.now();
2370
+ quotes.set(id, {
2371
+ id,
2372
+ type,
2373
+ createdAt: now,
2374
+ expiresAt: now + ttlMs,
2375
+ data
2376
+ });
2377
+ return id;
2378
+ }
2379
+ function getQuote(quoteId) {
2380
+ const quote = quotes.get(quoteId);
2381
+ if (!quote) return null;
2382
+ if (Date.now() > quote.expiresAt) {
2383
+ quotes.delete(quoteId);
2384
+ return null;
2385
+ }
2386
+ return quote;
2387
+ }
2388
+ function deleteQuote(quoteId) {
2389
+ quotes.delete(quoteId);
2390
+ }
2391
+
2392
+ // src/tools/wdkQuoteSwap.ts
2393
+ var import_zod19 = require("zod");
2394
+ var import_viem11 = require("viem");
2395
+ var wdkQuoteSwapInputSchema = import_zod19.z.object({
2396
+ fromToken: import_zod19.z.string().describe('Token to swap from (e.g., "ETH", "USDC")'),
2397
+ toToken: import_zod19.z.string().describe('Token to swap to (e.g., "USDT0", "USDC")'),
2398
+ amount: import_zod19.z.string().regex(/^\d+(\.\d+)?$/).describe("Amount to swap (e.g., '1.0')"),
2399
+ chain: import_zod19.z.string().describe('Chain to execute swap on (e.g., "ethereum", "arbitrum")')
2400
+ });
2401
+ async function executeWdkQuoteSwap(input, wdk) {
2402
+ const decimals = ["USDC", "USDT", "USDT0"].includes(input.fromToken.toUpperCase()) ? 6 : 18;
2403
+ const amountBigInt = (0, import_viem11.parseUnits)(input.amount, decimals);
2404
+ const quote = await wdk.getSwapQuote(input.chain, input.fromToken, amountBigInt);
2405
+ const outputDecimals = ["USDC", "USDT", "USDT0"].includes(input.toToken.toUpperCase()) ? 6 : 18;
2406
+ const outputDivisor = 10 ** outputDecimals;
2407
+ const toAmount = (Number(quote.outputAmount) / outputDivisor).toFixed(outputDecimals === 6 ? 6 : 8);
2408
+ const inputAmount = parseFloat(input.amount);
2409
+ const outputAmount = parseFloat(toAmount);
2410
+ const exchangeRate = inputAmount > 0 ? (outputAmount / inputAmount).toFixed(6) : "0";
2411
+ const expiresAt = new Date(Date.now() + 5 * 60 * 1e3).toISOString();
2412
+ const quoteId = createQuote("swap", {
2413
+ fromToken: input.fromToken,
2414
+ toToken: input.toToken,
2415
+ fromAmount: input.amount,
2416
+ toAmount,
2417
+ chain: input.chain,
2418
+ exchangeRate
2419
+ });
2420
+ return {
2421
+ quoteId,
2422
+ fromToken: input.fromToken,
2423
+ toToken: input.toToken,
2424
+ fromAmount: input.amount,
2425
+ toAmount,
2426
+ exchangeRate,
2427
+ fee: "0.3%",
2428
+ priceImpact: "< 0.1%",
2429
+ expiresAt,
2430
+ chain: input.chain
2431
+ };
2432
+ }
2433
+ function executeWdkQuoteSwapDemo(input) {
2434
+ const inputAmount = parseFloat(input.amount);
2435
+ const toAmount = (inputAmount * 0.997).toFixed(6);
2436
+ const exchangeRate = 0.997.toFixed(6);
2437
+ const expiresAt = new Date(Date.now() + 5 * 60 * 1e3).toISOString();
2438
+ const quoteId = createQuote("swap", {
2439
+ fromToken: input.fromToken,
2440
+ toToken: input.toToken,
2441
+ fromAmount: input.amount,
2442
+ toAmount,
2443
+ chain: input.chain,
2444
+ exchangeRate
2445
+ });
2446
+ return {
2447
+ quoteId,
2448
+ fromToken: input.fromToken,
2449
+ toToken: input.toToken,
2450
+ fromAmount: input.amount,
2451
+ toAmount,
2452
+ exchangeRate,
2453
+ fee: "0.3%",
2454
+ priceImpact: "< 0.1%",
2455
+ expiresAt,
2456
+ chain: input.chain
2457
+ };
2458
+ }
2459
+ function formatSwapQuoteResult(result) {
2460
+ return [
2461
+ "## Swap Quote",
2462
+ "",
2463
+ `- **Quote ID:** \`${result.quoteId}\``,
2464
+ `- **From:** ${result.fromAmount} ${result.fromToken}`,
2465
+ `- **To:** ${result.toAmount} ${result.toToken}`,
2466
+ `- **Exchange Rate:** ${result.exchangeRate}`,
2467
+ `- **Fee:** ${result.fee}`,
2468
+ `- **Price Impact:** ${result.priceImpact}`,
2469
+ `- **Chain:** ${result.chain}`,
2470
+ `- **Expires:** ${result.expiresAt}`,
2471
+ "",
2472
+ "_Call `wdk/executeSwap` with the quoteId to execute this swap._"
2473
+ ].join("\n");
2474
+ }
2475
+
2476
+ // src/tools/wdkExecuteSwap.ts
2477
+ var import_zod20 = require("zod");
2478
+ var import_viem12 = require("viem");
2479
+ var wdkExecuteSwapInputSchema = import_zod20.z.object({
2480
+ quoteId: import_zod20.z.string().uuid().describe("Quote ID from wdk/quoteSwap"),
2481
+ confirmed: import_zod20.z.boolean().optional().describe("Set to true to confirm and execute this swap")
2482
+ });
2483
+ async function executeWdkExecuteSwap(input, wdk) {
2484
+ const quote = getQuote(input.quoteId);
2485
+ if (!quote) {
2486
+ throw new Error("Quote not found or expired. Please request a new quote.");
2487
+ }
2488
+ if (quote.type !== "swap") {
2489
+ throw new Error("Invalid quote type. Expected a swap quote.");
2490
+ }
2491
+ const { fromToken, toToken, fromAmount, toAmount, chain } = quote.data;
2492
+ if (!input.confirmed) {
2493
+ return {
2494
+ needsConfirmation: true,
2495
+ summary: `Swap ${fromAmount} ${fromToken} to ${toAmount} ${toToken} on ${chain}`,
2496
+ details: { fromToken, toToken, fromAmount, toAmount, chain, quoteId: input.quoteId }
2497
+ };
2498
+ }
2499
+ const decimals = ["USDC", "USDT", "USDT0"].includes(fromToken.toUpperCase()) ? 6 : 18;
2500
+ const amountBigInt = (0, import_viem12.parseUnits)(fromAmount, decimals);
2501
+ const result = await wdk.swapAndPay({
2502
+ chain,
2503
+ fromToken,
2504
+ amount: amountBigInt
2505
+ });
2506
+ deleteQuote(input.quoteId);
2507
+ return {
2508
+ fromAmount,
2509
+ fromToken,
2510
+ toAmount,
2511
+ toToken,
2512
+ chain,
2513
+ txHash: result?.txHash ?? "0x"
2514
+ };
2515
+ }
2516
+ function executeWdkExecuteSwapDemo(input) {
2517
+ const quote = getQuote(input.quoteId);
2518
+ if (!quote) {
2519
+ throw new Error("Quote not found or expired. Please request a new quote.");
2520
+ }
2521
+ if (quote.type !== "swap") {
2522
+ throw new Error("Invalid quote type. Expected a swap quote.");
2523
+ }
2524
+ const { fromToken, toToken, fromAmount, toAmount, chain } = quote.data;
2525
+ if (!input.confirmed) {
2526
+ return {
2527
+ needsConfirmation: true,
2528
+ summary: `Swap ${fromAmount} ${fromToken} to ${toAmount} ${toToken} on ${chain}`,
2529
+ details: { fromToken, toToken, fromAmount, toAmount, chain, quoteId: input.quoteId }
2530
+ };
2531
+ }
2532
+ deleteQuote(input.quoteId);
2533
+ return {
2534
+ fromAmount,
2535
+ fromToken,
2536
+ toAmount,
2537
+ toToken,
2538
+ chain,
2539
+ txHash: "0xdemo" + Math.random().toString(16).slice(2, 10)
2540
+ };
2541
+ }
2542
+ function formatExecuteSwapResult(result) {
2543
+ return [
2544
+ "## Swap Executed",
2545
+ "",
2546
+ `- **From:** ${result.fromAmount} ${result.fromToken}`,
2547
+ `- **To:** ${result.toAmount} ${result.toToken}`,
2548
+ `- **Chain:** ${result.chain}`,
2549
+ `- **Tx Hash:** \`${result.txHash}\``
2550
+ ].join("\n");
2551
+ }
2552
+
2553
+ // src/tools/quoteBridge.ts
2554
+ var import_zod21 = require("zod");
2555
+ var quoteBridgeInputSchema = import_zod21.z.object({
2556
+ fromChain: import_zod21.z.enum(["ethereum", "arbitrum", "ink", "berachain", "unichain"]).describe("Source chain to bridge from"),
2557
+ toChain: import_zod21.z.enum(["ethereum", "arbitrum", "ink", "berachain", "unichain"]).describe("Destination chain to bridge to"),
2558
+ amount: import_zod21.z.string().regex(/^\d+(\.\d+)?$/).describe("Amount of USDT0 to bridge (e.g., '100' for 100 USDT0)"),
2559
+ recipient: import_zod21.z.string().regex(/^0x[a-fA-F0-9]{40}$/).describe("Recipient address on destination chain")
2560
+ });
2561
+ async function executeQuoteBridge(input, rpcUrls) {
2562
+ const feeResult = await executeGetBridgeFee(input, rpcUrls);
2563
+ const expiresAt = new Date(Date.now() + 5 * 60 * 1e3).toISOString();
2564
+ const quoteId = createQuote("bridge", {
2565
+ fromChain: input.fromChain,
2566
+ toChain: input.toChain,
2567
+ amount: input.amount,
2568
+ recipient: input.recipient,
2569
+ nativeFee: feeResult.nativeFee,
2570
+ nativeFeeFormatted: feeResult.nativeFeeFormatted,
2571
+ estimatedTime: feeResult.estimatedTime
2572
+ });
2573
+ return {
2574
+ quoteId,
2575
+ fromChain: input.fromChain,
2576
+ toChain: input.toChain,
2577
+ amount: input.amount,
2578
+ recipient: input.recipient,
2579
+ nativeFee: feeResult.nativeFee,
2580
+ nativeFeeFormatted: feeResult.nativeFeeFormatted,
2581
+ estimatedTime: feeResult.estimatedTime,
2582
+ expiresAt
2583
+ };
2584
+ }
2585
+ function executeQuoteBridgeDemo(input) {
2586
+ const expiresAt = new Date(Date.now() + 5 * 60 * 1e3).toISOString();
2587
+ const estimatedTime = input.toChain === "ethereum" ? 900 : 300;
2588
+ const quoteId = createQuote("bridge", {
2589
+ fromChain: input.fromChain,
2590
+ toChain: input.toChain,
2591
+ amount: input.amount,
2592
+ recipient: input.recipient,
2593
+ nativeFee: "1000000000000000",
2594
+ nativeFeeFormatted: "0.001 ETH",
2595
+ estimatedTime
2596
+ });
2597
+ return {
2598
+ quoteId,
2599
+ fromChain: input.fromChain,
2600
+ toChain: input.toChain,
2601
+ amount: input.amount,
2602
+ recipient: input.recipient,
2603
+ nativeFee: "1000000000000000",
2604
+ nativeFeeFormatted: "0.001 ETH",
2605
+ estimatedTime,
2606
+ expiresAt
2607
+ };
2608
+ }
2609
+ function formatBridgeQuoteResult(result) {
2610
+ const minutes = Math.ceil(result.estimatedTime / 60);
2611
+ return [
2612
+ "## Bridge Quote",
2613
+ "",
2614
+ `- **Quote ID:** \`${result.quoteId}\``,
2615
+ `- **Route:** ${result.fromChain} -> ${result.toChain}`,
2616
+ `- **Amount:** ${result.amount} USDT0`,
2617
+ `- **Recipient:** \`${result.recipient}\``,
2618
+ `- **Fee:** ${result.nativeFeeFormatted}`,
2619
+ `- **Estimated Time:** ~${minutes} minutes`,
2620
+ `- **Expires:** ${result.expiresAt}`,
2621
+ "",
2622
+ "_Call `t402/executeBridge` with the quoteId to execute this bridge._"
2623
+ ].join("\n");
2624
+ }
2625
+
2626
+ // src/tools/executeBridgeFromQuote.ts
2627
+ var import_zod22 = require("zod");
2628
+ var executeBridgeFromQuoteInputSchema = import_zod22.z.object({
2629
+ quoteId: import_zod22.z.string().uuid().describe("Quote ID from t402/quoteBridge"),
2630
+ confirmed: import_zod22.z.boolean().optional().describe("Set to true to confirm and execute this bridge")
2631
+ });
2632
+ async function executeExecuteBridgeFromQuote(input, options) {
2633
+ const quote = getQuote(input.quoteId);
2634
+ if (!quote) {
2635
+ throw new Error("Quote not found or expired. Please request a new quote.");
2636
+ }
2637
+ if (quote.type !== "bridge") {
2638
+ throw new Error("Invalid quote type. Expected a bridge quote.");
2639
+ }
2640
+ const { fromChain, toChain, amount, recipient } = quote.data;
2641
+ if (!input.confirmed) {
2642
+ return {
2643
+ needsConfirmation: true,
2644
+ summary: `Bridge ${amount} USDT0 from ${fromChain} to ${toChain}`,
2645
+ details: { fromChain, toChain, amount, recipient, quoteId: input.quoteId }
2646
+ };
2647
+ }
2648
+ const result = await executeBridge(
2649
+ { fromChain, toChain, amount, recipient, confirmed: true },
2650
+ options
2651
+ );
2652
+ if ("needsConfirmation" in result) {
2653
+ return result;
2654
+ }
2655
+ deleteQuote(input.quoteId);
2656
+ return result;
2657
+ }
2658
+ function executeExecuteBridgeFromQuoteDemo(input) {
2659
+ const quote = getQuote(input.quoteId);
2660
+ if (!quote) {
2661
+ throw new Error("Quote not found or expired. Please request a new quote.");
2662
+ }
2663
+ if (quote.type !== "bridge") {
2664
+ throw new Error("Invalid quote type. Expected a bridge quote.");
2665
+ }
2666
+ const { fromChain, toChain, amount, recipient } = quote.data;
2667
+ if (!input.confirmed) {
2668
+ return {
2669
+ needsConfirmation: true,
2670
+ summary: `Bridge ${amount} USDT0 from ${fromChain} to ${toChain}`,
2671
+ details: { fromChain, toChain, amount, recipient, quoteId: input.quoteId }
2672
+ };
2673
+ }
2674
+ deleteQuote(input.quoteId);
2675
+ const fakeTxHash = `0x${"a".repeat(64)}`;
2676
+ const fakeGuid = `0x${"b".repeat(64)}`;
2677
+ return {
2678
+ txHash: fakeTxHash,
2679
+ messageGuid: fakeGuid,
2680
+ amount,
2681
+ fromChain,
2682
+ toChain,
2683
+ estimatedTime: quote.data.estimatedTime ?? 300,
2684
+ trackingUrl: `https://layerzeroscan.com/tx/${fakeGuid}`
2685
+ };
2686
+ }
2687
+
2688
+ // src/tools/unified.ts
2689
+ var import_zod23 = require("zod");
2690
+ var smartPayInputSchema = import_zod23.z.object({
2691
+ url: import_zod23.z.string().url().describe("URL of the 402-protected resource"),
2692
+ maxBridgeFee: import_zod23.z.string().regex(/^\d+(\.\d+)?$/).optional().describe("Maximum acceptable bridge fee in native token (optional)"),
2693
+ preferredNetwork: import_zod23.z.string().optional().describe("Preferred network for payment (optional)"),
2694
+ confirmed: import_zod23.z.boolean().optional().describe("Set to true to confirm and execute this payment")
2695
+ });
2696
+ var paymentPlanInputSchema = import_zod23.z.object({
2697
+ paymentRequired: import_zod23.z.object({
2698
+ scheme: import_zod23.z.string().optional(),
2699
+ network: import_zod23.z.string().optional(),
2700
+ maxAmountRequired: import_zod23.z.string().optional(),
2701
+ resource: import_zod23.z.string().optional(),
2702
+ description: import_zod23.z.string().optional(),
2703
+ payTo: import_zod23.z.string().optional(),
2704
+ maxDeadline: import_zod23.z.number().optional()
2705
+ }).passthrough().describe("The 402 PaymentRequired response")
2706
+ });
2707
+ var UNIFIED_TOOL_DEFINITIONS = {
2708
+ "t402/smartPay": {
2709
+ name: "t402/smartPay",
2710
+ description: "Intelligent payment that automatically checks balance, bridges if needed, and pays. Handles the entire payment flow for 402-protected resources.",
2711
+ inputSchema: {
2712
+ type: "object",
2713
+ properties: {
2714
+ url: { type: "string", description: "URL of the 402-protected resource" },
2715
+ maxBridgeFee: {
2716
+ type: "string",
2717
+ description: "Maximum acceptable bridge fee in native token (optional)"
2718
+ },
2719
+ preferredNetwork: {
2720
+ type: "string",
2721
+ description: "Preferred network for payment (optional)"
2722
+ },
2723
+ confirmed: {
2724
+ type: "boolean",
2725
+ description: "Set to true to confirm and execute. Omit for a preview/confirmation prompt."
2726
+ }
2727
+ },
2728
+ required: ["url"]
2729
+ }
2730
+ },
2731
+ "t402/paymentPlan": {
2732
+ name: "t402/paymentPlan",
2733
+ description: "Analyze a 402 response and create an optimal payment plan considering balances across all chains. Returns recommended network, bridge requirements, and balance overview.",
2734
+ inputSchema: {
2735
+ type: "object",
2736
+ properties: {
2737
+ paymentRequired: {
2738
+ type: "object",
2739
+ description: "The 402 PaymentRequired response"
2740
+ }
2741
+ },
2742
+ required: ["paymentRequired"]
2743
+ }
2744
+ }
2745
+ };
2746
+ async function executeSmartPay(input, wdk) {
2747
+ if (!input.confirmed) {
2748
+ return {
2749
+ needsConfirmation: true,
2750
+ summary: `Smart-pay for ${input.url}${input.preferredNetwork ? ` on ${input.preferredNetwork}` : ""}`,
2751
+ details: {
2752
+ url: input.url,
2753
+ ...input.maxBridgeFee ? { maxBridgeFee: input.maxBridgeFee } : {},
2754
+ ...input.preferredNetwork ? { preferredNetwork: input.preferredNetwork } : {}
2755
+ }
2756
+ };
2757
+ }
2758
+ const steps = [];
2759
+ const chains9 = input.preferredNetwork ? [input.preferredNetwork] : ["ethereum", "arbitrum", "base"];
2760
+ steps.push({
2761
+ action: "check_balance",
2762
+ status: "success",
2763
+ detail: `Checking balances on ${chains9.join(", ")}`
2764
+ });
2765
+ const { T402Protocol } = await import("@t402/wdk-protocol");
2766
+ const protocol = await T402Protocol.create(wdk, { chains: chains9 });
2767
+ steps.push({
2768
+ action: "fetch",
2769
+ status: "success",
2770
+ detail: `Fetching ${input.url}`
2771
+ });
2772
+ const { response, receipt } = await protocol.fetch(input.url);
2773
+ if (receipt) {
2774
+ steps.push({
2775
+ action: "pay",
2776
+ status: "success",
2777
+ detail: `Payment made: ${receipt.amount} on ${receipt.network}`
2778
+ });
2779
+ }
2780
+ const contentType = response.headers.get("content-type") ?? void 0;
2781
+ let body = "";
2782
+ try {
2783
+ body = await response.text();
2784
+ if (body.length > 1e4) {
2785
+ body = body.slice(0, 1e4) + "\n... (truncated)";
2786
+ }
2787
+ } catch {
2788
+ body = "[Could not read response body]";
2789
+ }
2790
+ return {
2791
+ success: response.ok,
2792
+ statusCode: response.status,
2793
+ body,
2794
+ contentType,
2795
+ steps,
2796
+ payment: receipt ? {
2797
+ network: receipt.network,
2798
+ scheme: receipt.scheme,
2799
+ amount: receipt.amount,
2800
+ payTo: receipt.payTo
2801
+ } : void 0
2802
+ };
2803
+ }
2804
+ function executeSmartPayDemo(input) {
2805
+ if (!input.confirmed) {
2806
+ return {
2807
+ needsConfirmation: true,
2808
+ summary: `Smart-pay for ${input.url}${input.preferredNetwork ? ` on ${input.preferredNetwork}` : ""}`,
2809
+ details: {
2810
+ url: input.url,
2811
+ ...input.maxBridgeFee ? { maxBridgeFee: input.maxBridgeFee } : {},
2812
+ ...input.preferredNetwork ? { preferredNetwork: input.preferredNetwork } : {}
2813
+ }
2814
+ };
2815
+ }
2816
+ const network = input.preferredNetwork ?? "arbitrum";
2817
+ return {
2818
+ success: true,
2819
+ statusCode: 200,
2820
+ body: `[Demo] Premium content from ${input.url}
2821
+
2822
+ This is simulated content returned after smart payment.`,
2823
+ contentType: "text/plain",
2824
+ steps: [
2825
+ { action: "check_balance", status: "success", detail: `Checked balances on ${network}` },
2826
+ { action: "check_price", status: "success", detail: "Resource costs 1.00 USDT0" },
2827
+ { action: "pay", status: "success", detail: `Paid 1000000 USDT0 on eip155:42161` },
2828
+ { action: "fetch", status: "success", detail: `Fetched ${input.url}` }
2829
+ ],
2830
+ payment: {
2831
+ network: "eip155:42161",
2832
+ scheme: "exact",
2833
+ amount: "1000000",
2834
+ payTo: "0xC88f67e776f16DcFBf42e6bDda1B82604448899B"
2835
+ }
2836
+ };
2837
+ }
2838
+ async function executePaymentPlan(input, wdk) {
2839
+ const targetNetwork = input.paymentRequired.network;
2840
+ const requiredAmount = input.paymentRequired.maxAmountRequired;
2841
+ const aggregated = await wdk.getAggregatedBalances();
2842
+ const balances = aggregated.chains.map((chain) => {
2843
+ const usdt0 = chain.tokens.find((t) => t.symbol === "USDT0");
2844
+ const usdc = chain.tokens.find((t) => t.symbol === "USDC");
2845
+ return {
2846
+ chain: chain.chain,
2847
+ usdt0: usdt0?.formatted ?? "0",
2848
+ usdc: usdc?.formatted ?? "0"
2849
+ };
2850
+ });
2851
+ const requiredBigint = requiredAmount ? BigInt(requiredAmount) : 0n;
2852
+ const bestChain = await wdk.findBestChainForPayment(requiredBigint);
2853
+ if (bestChain) {
2854
+ const needsBridge = targetNetwork ? !bestChain.chain.includes(targetNetwork) : false;
2855
+ return {
2856
+ viable: true,
2857
+ recommendedNetwork: bestChain.chain,
2858
+ availableBalance: bestChain.balance.toString(),
2859
+ bridgeRequired: needsBridge,
2860
+ bridgeDetails: needsBridge ? {
2861
+ fromChain: bestChain.chain,
2862
+ toChain: targetNetwork ?? bestChain.chain,
2863
+ amount: requiredAmount ?? "0",
2864
+ estimatedFee: "0.001"
2865
+ } : void 0,
2866
+ balances
2867
+ };
2868
+ }
2869
+ return {
2870
+ viable: false,
2871
+ bridgeRequired: false,
2872
+ balances,
2873
+ reason: "Insufficient balance across all chains"
2874
+ };
2875
+ }
2876
+ function executePaymentPlanDemo(_input) {
2877
+ return {
2878
+ viable: true,
2879
+ recommendedNetwork: "arbitrum",
2880
+ availableBalance: "500000000",
2881
+ bridgeRequired: false,
2882
+ balances: [
2883
+ { chain: "ethereum", usdt0: "100.00", usdc: "250.00" },
2884
+ { chain: "arbitrum", usdt0: "500.00", usdc: "0" },
2885
+ { chain: "base", usdt0: "50.00", usdc: "100.00" }
2886
+ ]
2887
+ };
2888
+ }
2889
+ function formatSmartPayResult(result) {
2890
+ const lines = ["## SmartPay Result", ""];
2891
+ if (result.success) {
2892
+ lines.push(`**Status:** Success (${result.statusCode})`);
2893
+ } else {
2894
+ lines.push(`**Status:** Failed (${result.statusCode})`);
2895
+ }
2896
+ if (result.steps.length > 0) {
2897
+ lines.push("");
2898
+ lines.push("### Steps");
2899
+ for (const step of result.steps) {
2900
+ const icon = step.status === "success" ? "[OK]" : step.status === "skipped" ? "[SKIP]" : "[FAIL]";
2901
+ lines.push(`- ${icon} **${step.action}**: ${step.detail}`);
2902
+ }
2903
+ }
2904
+ if (result.payment) {
2905
+ lines.push("");
2077
2906
  lines.push("### Payment Details");
2078
2907
  lines.push(`- **Network:** ${result.payment.network}`);
2079
2908
  lines.push(`- **Scheme:** ${result.payment.scheme}`);
@@ -2237,6 +3066,10 @@ var TOOL_DEFINITIONS = {
2237
3066
  memo: {
2238
3067
  type: "string",
2239
3068
  description: "Optional memo/reference for the payment"
3069
+ },
3070
+ confirmed: {
3071
+ type: "boolean",
3072
+ description: "Set to true to confirm and execute. Omit for a preview/confirmation prompt."
2240
3073
  }
2241
3074
  },
2242
3075
  required: ["to", "amount", "token", "network"]
@@ -2267,6 +3100,10 @@ var TOOL_DEFINITIONS = {
2267
3100
  type: "string",
2268
3101
  enum: ["ethereum", "base", "arbitrum", "optimism", "polygon", "avalanche"],
2269
3102
  description: "Network to execute gasless payment on (must support ERC-4337)"
3103
+ },
3104
+ confirmed: {
3105
+ type: "boolean",
3106
+ description: "Set to true to confirm and execute. Omit for a preview/confirmation prompt."
2270
3107
  }
2271
3108
  },
2272
3109
  required: ["to", "amount", "token", "network"]
@@ -2305,6 +3142,144 @@ var TOOL_DEFINITIONS = {
2305
3142
  "t402/bridge": {
2306
3143
  name: "t402/bridge",
2307
3144
  description: "Bridge USDT0 between chains using LayerZero OFT standard. Executes a cross-chain transfer and returns the LayerZero message GUID for tracking. Supported chains: ethereum, arbitrum, ink, berachain, unichain.",
3145
+ inputSchema: {
3146
+ type: "object",
3147
+ properties: {
3148
+ fromChain: {
3149
+ type: "string",
3150
+ enum: ["ethereum", "arbitrum", "ink", "berachain", "unichain"],
3151
+ description: "Source chain to bridge from"
3152
+ },
3153
+ toChain: {
3154
+ type: "string",
3155
+ enum: ["ethereum", "arbitrum", "ink", "berachain", "unichain"],
3156
+ description: "Destination chain to bridge to"
3157
+ },
3158
+ amount: {
3159
+ type: "string",
3160
+ pattern: "^\\d+(\\.\\d+)?$",
3161
+ description: "Amount of USDT0 to bridge (e.g., '100' for 100 USDT0)"
3162
+ },
3163
+ recipient: {
3164
+ type: "string",
3165
+ pattern: "^0x[a-fA-F0-9]{40}$",
3166
+ description: "Recipient address on destination chain"
3167
+ },
3168
+ confirmed: {
3169
+ type: "boolean",
3170
+ description: "Set to true to confirm and execute. Omit for a preview/confirmation prompt."
3171
+ }
3172
+ },
3173
+ required: ["fromChain", "toChain", "amount", "recipient"]
3174
+ }
3175
+ },
3176
+ "t402/getTokenPrice": {
3177
+ name: "t402/getTokenPrice",
3178
+ description: "Get current market prices for tokens (ETH, MATIC, AVAX, USDC, etc.) via CoinGecko. Cached for 5 minutes.",
3179
+ inputSchema: {
3180
+ type: "object",
3181
+ properties: {
3182
+ tokens: {
3183
+ type: "array",
3184
+ items: { type: "string" },
3185
+ description: 'Token symbols to get prices for (e.g., ["ETH", "MATIC", "USDC"])'
3186
+ },
3187
+ currency: {
3188
+ type: "string",
3189
+ description: 'Target currency (default: "usd")'
3190
+ }
3191
+ },
3192
+ required: ["tokens"]
3193
+ }
3194
+ },
3195
+ "t402/getGasPrice": {
3196
+ name: "t402/getGasPrice",
3197
+ description: "Get the current gas price on a specific blockchain network. Returns the price in gwei.",
3198
+ inputSchema: {
3199
+ type: "object",
3200
+ properties: {
3201
+ network: {
3202
+ type: "string",
3203
+ enum: [
3204
+ "ethereum",
3205
+ "base",
3206
+ "arbitrum",
3207
+ "optimism",
3208
+ "polygon",
3209
+ "avalanche",
3210
+ "ink",
3211
+ "berachain",
3212
+ "unichain"
3213
+ ],
3214
+ description: "Blockchain network to check gas price on"
3215
+ }
3216
+ },
3217
+ required: ["network"]
3218
+ }
3219
+ },
3220
+ "t402/estimatePaymentFee": {
3221
+ name: "t402/estimatePaymentFee",
3222
+ description: "Estimate the gas cost (in native token and USD) for a stablecoin payment on a specific network.",
3223
+ inputSchema: {
3224
+ type: "object",
3225
+ properties: {
3226
+ network: {
3227
+ type: "string",
3228
+ enum: [
3229
+ "ethereum",
3230
+ "base",
3231
+ "arbitrum",
3232
+ "optimism",
3233
+ "polygon",
3234
+ "avalanche",
3235
+ "ink",
3236
+ "berachain",
3237
+ "unichain"
3238
+ ],
3239
+ description: "Network to estimate fee on"
3240
+ },
3241
+ amount: {
3242
+ type: "string",
3243
+ pattern: "^\\d+(\\.\\d+)?$",
3244
+ description: "Payment amount (e.g., '100')"
3245
+ },
3246
+ token: {
3247
+ type: "string",
3248
+ enum: ["USDC", "USDT", "USDT0"],
3249
+ description: "Token to use for payment"
3250
+ }
3251
+ },
3252
+ required: ["network", "amount", "token"]
3253
+ }
3254
+ },
3255
+ "t402/compareNetworkFees": {
3256
+ name: "t402/compareNetworkFees",
3257
+ description: "Compare payment fees across multiple networks for the same token. Returns a sorted table from cheapest to most expensive.",
3258
+ inputSchema: {
3259
+ type: "object",
3260
+ properties: {
3261
+ amount: {
3262
+ type: "string",
3263
+ pattern: "^\\d+(\\.\\d+)?$",
3264
+ description: "Payment amount (e.g., '100')"
3265
+ },
3266
+ token: {
3267
+ type: "string",
3268
+ enum: ["USDC", "USDT", "USDT0"],
3269
+ description: "Token to use for payment"
3270
+ },
3271
+ networks: {
3272
+ type: "array",
3273
+ items: { type: "string" },
3274
+ description: "Networks to compare. If not provided, compares all networks that support the token."
3275
+ }
3276
+ },
3277
+ required: ["amount", "token"]
3278
+ }
3279
+ },
3280
+ "t402/quoteBridge": {
3281
+ name: "t402/quoteBridge",
3282
+ description: "Get a bridge fee quote with a quoteId for later execution. Like getBridgeFee but returns a reusable quoteId. Call t402/executeBridge with the quoteId to execute.",
2308
3283
  inputSchema: {
2309
3284
  type: "object",
2310
3285
  properties: {
@@ -2331,6 +3306,24 @@ var TOOL_DEFINITIONS = {
2331
3306
  },
2332
3307
  required: ["fromChain", "toChain", "amount", "recipient"]
2333
3308
  }
3309
+ },
3310
+ "t402/executeBridgeQuote": {
3311
+ name: "t402/executeBridgeQuote",
3312
+ description: "Execute a bridge using a quoteId from t402/quoteBridge. Requires confirmation.",
3313
+ inputSchema: {
3314
+ type: "object",
3315
+ properties: {
3316
+ quoteId: {
3317
+ type: "string",
3318
+ description: "Quote ID from t402/quoteBridge"
3319
+ },
3320
+ confirmed: {
3321
+ type: "boolean",
3322
+ description: "Set to true to confirm and execute. Omit for a preview/confirmation prompt."
3323
+ }
3324
+ },
3325
+ required: ["quoteId"]
3326
+ }
2334
3327
  }
2335
3328
  };
2336
3329
  var WDK_TOOL_DEFINITIONS = {
@@ -2381,6 +3374,10 @@ var WDK_TOOL_DEFINITIONS = {
2381
3374
  chain: {
2382
3375
  type: "string",
2383
3376
  description: 'Chain to execute transfer on (e.g., "ethereum", "arbitrum")'
3377
+ },
3378
+ confirmed: {
3379
+ type: "boolean",
3380
+ description: "Set to true to confirm and execute. Omit for a preview/confirmation prompt."
2384
3381
  }
2385
3382
  },
2386
3383
  required: ["to", "amount", "token", "chain"]
@@ -2408,6 +3405,10 @@ var WDK_TOOL_DEFINITIONS = {
2408
3405
  chain: {
2409
3406
  type: "string",
2410
3407
  description: 'Chain to execute swap on (e.g., "ethereum", "arbitrum")'
3408
+ },
3409
+ confirmed: {
3410
+ type: "boolean",
3411
+ description: "Set to true to confirm and execute. Omit for a preview/confirmation prompt."
2411
3412
  }
2412
3413
  },
2413
3414
  required: ["fromToken", "toToken", "amount", "chain"]
@@ -2431,10 +3432,59 @@ var WDK_TOOL_DEFINITIONS = {
2431
3432
  preferredChain: {
2432
3433
  type: "string",
2433
3434
  description: 'Preferred chain for payment (e.g., "arbitrum"). If not specified, uses first available.'
3435
+ },
3436
+ confirmed: {
3437
+ type: "boolean",
3438
+ description: "Set to true to confirm and execute. Omit for a preview/confirmation prompt."
2434
3439
  }
2435
3440
  },
2436
3441
  required: ["url"]
2437
3442
  }
3443
+ },
3444
+ "wdk/quoteSwap": {
3445
+ name: "wdk/quoteSwap",
3446
+ description: "Get a swap quote with a quoteId for later execution. Returns exchange rate, fee, and price impact. Call wdk/executeSwap with the quoteId to execute.",
3447
+ inputSchema: {
3448
+ type: "object",
3449
+ properties: {
3450
+ fromToken: {
3451
+ type: "string",
3452
+ description: 'Token to swap from (e.g., "ETH", "USDC")'
3453
+ },
3454
+ toToken: {
3455
+ type: "string",
3456
+ description: 'Token to swap to (e.g., "USDT0", "USDC")'
3457
+ },
3458
+ amount: {
3459
+ type: "string",
3460
+ pattern: "^\\d+(\\.\\d+)?$",
3461
+ description: "Amount to swap (e.g., '1.0')"
3462
+ },
3463
+ chain: {
3464
+ type: "string",
3465
+ description: 'Chain to execute swap on (e.g., "ethereum", "arbitrum")'
3466
+ }
3467
+ },
3468
+ required: ["fromToken", "toToken", "amount", "chain"]
3469
+ }
3470
+ },
3471
+ "wdk/executeSwap": {
3472
+ name: "wdk/executeSwap",
3473
+ description: "Execute a swap using a quoteId from wdk/quoteSwap. Requires confirmation.",
3474
+ inputSchema: {
3475
+ type: "object",
3476
+ properties: {
3477
+ quoteId: {
3478
+ type: "string",
3479
+ description: "Quote ID from wdk/quoteSwap"
3480
+ },
3481
+ confirmed: {
3482
+ type: "boolean",
3483
+ description: "Set to true to confirm and execute. Omit for a preview/confirmation prompt."
3484
+ }
3485
+ },
3486
+ required: ["quoteId"]
3487
+ }
2438
3488
  }
2439
3489
  };
2440
3490
  var ERC8004_TOOL_DEFINITIONS = {
@@ -2618,6 +3668,24 @@ var T402McpServer = class {
2618
3668
  return await this.handleSmartPay(args);
2619
3669
  case "t402/paymentPlan":
2620
3670
  return await this.handlePaymentPlan(args);
3671
+ // Price and fee tools
3672
+ case "t402/getTokenPrice":
3673
+ return await this.handleGetTokenPrice(args);
3674
+ case "t402/getGasPrice":
3675
+ return await this.handleGetGasPrice(args);
3676
+ case "t402/estimatePaymentFee":
3677
+ return await this.handleEstimatePaymentFee(args);
3678
+ case "t402/compareNetworkFees":
3679
+ return await this.handleCompareNetworkFees(args);
3680
+ // Quote-based tools
3681
+ case "t402/quoteBridge":
3682
+ return await this.handleQuoteBridge(args);
3683
+ case "t402/executeBridgeQuote":
3684
+ return await this.handleExecuteBridgeQuote(args);
3685
+ case "wdk/quoteSwap":
3686
+ return await this.handleWdkQuoteSwap(args);
3687
+ case "wdk/executeSwap":
3688
+ return await this.handleWdkExecuteSwap(args);
2621
3689
  // ERC-8004 tools
2622
3690
  case "erc8004/resolveAgent":
2623
3691
  return await this.handleErc8004ResolveAgent(args);
@@ -2679,6 +3747,28 @@ var T402McpServer = class {
2679
3747
  ]
2680
3748
  };
2681
3749
  }
3750
+ /**
3751
+ * Format a confirmation prompt for elicitation
3752
+ */
3753
+ formatConfirmation(result) {
3754
+ const detailLines = Object.entries(result.details).map(([key, value]) => `- **${key}:** ${value}`).join("\n");
3755
+ return {
3756
+ content: [
3757
+ {
3758
+ type: "text",
3759
+ text: [
3760
+ "## Confirmation Required",
3761
+ "",
3762
+ result.summary,
3763
+ "",
3764
+ detailLines,
3765
+ "",
3766
+ "_Call this tool again with `confirmed: true` to execute._"
3767
+ ].join("\n")
3768
+ }
3769
+ ]
3770
+ };
3771
+ }
2682
3772
  /**
2683
3773
  * Handle t402/pay
2684
3774
  */
@@ -2694,6 +3784,9 @@ var T402McpServer = class {
2694
3784
  rpcUrl: this.config.rpcUrls?.[input.network],
2695
3785
  demoMode: this.config.demoMode
2696
3786
  });
3787
+ if ("needsConfirmation" in result) {
3788
+ return this.formatConfirmation(result);
3789
+ }
2697
3790
  return {
2698
3791
  content: [
2699
3792
  {
@@ -2730,6 +3823,9 @@ var T402McpServer = class {
2730
3823
  rpcUrl: this.config.rpcUrls?.[input.network],
2731
3824
  demoMode: this.config.demoMode
2732
3825
  });
3826
+ if ("needsConfirmation" in result) {
3827
+ return this.formatConfirmation(result);
3828
+ }
2733
3829
  return {
2734
3830
  content: [
2735
3831
  {
@@ -2769,6 +3865,9 @@ var T402McpServer = class {
2769
3865
  rpcUrl: this.config.rpcUrls?.[input.fromChain],
2770
3866
  demoMode: this.config.demoMode
2771
3867
  });
3868
+ if ("needsConfirmation" in result) {
3869
+ return this.formatConfirmation(result);
3870
+ }
2772
3871
  return {
2773
3872
  content: [
2774
3873
  {
@@ -2805,6 +3904,9 @@ var T402McpServer = class {
2805
3904
  async handleWdkTransfer(args) {
2806
3905
  const input = wdkTransferInputSchema.parse(args);
2807
3906
  const result = this.config.demoMode || !this.wdk ? executeWdkTransferDemo(input) : await executeWdkTransfer(input, this.wdk);
3907
+ if ("needsConfirmation" in result) {
3908
+ return this.formatConfirmation(result);
3909
+ }
2808
3910
  return {
2809
3911
  content: [{ type: "text", text: formatWdkTransferResult(result) }]
2810
3912
  };
@@ -2815,6 +3917,9 @@ var T402McpServer = class {
2815
3917
  async handleWdkSwap(args) {
2816
3918
  const input = wdkSwapInputSchema.parse(args);
2817
3919
  const result = this.config.demoMode || !this.wdk ? executeWdkSwapDemo(input) : await executeWdkSwap(input, this.wdk);
3920
+ if ("needsConfirmation" in result) {
3921
+ return this.formatConfirmation(result);
3922
+ }
2818
3923
  return {
2819
3924
  content: [{ type: "text", text: formatWdkSwapResult(result) }]
2820
3925
  };
@@ -2825,6 +3930,9 @@ var T402McpServer = class {
2825
3930
  async handleAutoPay(args) {
2826
3931
  const input = autoPayInputSchema.parse(args);
2827
3932
  const result = this.config.demoMode || !this.wdk ? executeAutoPayDemo(input) : await executeAutoPay(input, this.wdk);
3933
+ if ("needsConfirmation" in result) {
3934
+ return this.formatConfirmation(result);
3935
+ }
2828
3936
  return {
2829
3937
  content: [{ type: "text", text: formatAutoPayResult(result) }]
2830
3938
  };
@@ -2836,6 +3944,9 @@ var T402McpServer = class {
2836
3944
  async handleSmartPay(args) {
2837
3945
  const input = smartPayInputSchema.parse(args);
2838
3946
  const result = this.config.demoMode || !this.wdk ? executeSmartPayDemo(input) : await executeSmartPay(input, this.wdk);
3947
+ if ("needsConfirmation" in result) {
3948
+ return this.formatConfirmation(result);
3949
+ }
2839
3950
  return {
2840
3951
  content: [{ type: "text", text: formatSmartPayResult(result) }]
2841
3952
  };
@@ -2850,6 +3961,111 @@ var T402McpServer = class {
2850
3961
  content: [{ type: "text", text: formatPaymentPlanResult(result) }]
2851
3962
  };
2852
3963
  }
3964
+ // ---- Price and Fee Tool Handlers ----
3965
+ /**
3966
+ * Handle t402/getTokenPrice
3967
+ */
3968
+ async handleGetTokenPrice(args) {
3969
+ const input = getTokenPriceInputSchema.parse(args);
3970
+ const result = await executeGetTokenPrice(input, { demoMode: this.config.demoMode });
3971
+ return {
3972
+ content: [{ type: "text", text: formatTokenPriceResult(result) }]
3973
+ };
3974
+ }
3975
+ /**
3976
+ * Handle t402/getGasPrice
3977
+ */
3978
+ async handleGetGasPrice(args) {
3979
+ const input = getGasPriceInputSchema.parse(args);
3980
+ const result = await executeGetGasPrice(input, {
3981
+ rpcUrl: this.config.rpcUrls?.[input.network],
3982
+ demoMode: this.config.demoMode
3983
+ });
3984
+ return {
3985
+ content: [{ type: "text", text: formatGasPriceResult(result) }]
3986
+ };
3987
+ }
3988
+ /**
3989
+ * Handle t402/estimatePaymentFee
3990
+ */
3991
+ async handleEstimatePaymentFee(args) {
3992
+ const input = estimatePaymentFeeInputSchema.parse(args);
3993
+ const result = await executeEstimatePaymentFee(input, {
3994
+ rpcUrl: this.config.rpcUrls?.[input.network],
3995
+ demoMode: this.config.demoMode
3996
+ });
3997
+ return {
3998
+ content: [{ type: "text", text: formatPaymentFeeEstimate(result) }]
3999
+ };
4000
+ }
4001
+ /**
4002
+ * Handle t402/compareNetworkFees
4003
+ */
4004
+ async handleCompareNetworkFees(args) {
4005
+ const input = compareNetworkFeesInputSchema.parse(args);
4006
+ const result = await executeCompareNetworkFees(input, {
4007
+ rpcUrls: this.config.rpcUrls,
4008
+ demoMode: this.config.demoMode
4009
+ });
4010
+ return {
4011
+ content: [{ type: "text", text: formatNetworkFeeComparison(result) }]
4012
+ };
4013
+ }
4014
+ // ---- Quote-based Tool Handlers ----
4015
+ /**
4016
+ * Handle t402/quoteBridge
4017
+ */
4018
+ async handleQuoteBridge(args) {
4019
+ const input = quoteBridgeInputSchema.parse(args);
4020
+ const result = this.config.demoMode ? executeQuoteBridgeDemo(input) : await executeQuoteBridge(input, this.config.rpcUrls);
4021
+ return {
4022
+ content: [{ type: "text", text: formatBridgeQuoteResult(result) }]
4023
+ };
4024
+ }
4025
+ /**
4026
+ * Handle t402/executeBridgeQuote
4027
+ */
4028
+ async handleExecuteBridgeQuote(args) {
4029
+ if (!this.config.privateKey && !this.config.demoMode) {
4030
+ throw new Error(
4031
+ "Private key not configured. Set T402_PRIVATE_KEY environment variable or enable demo mode."
4032
+ );
4033
+ }
4034
+ const input = executeBridgeFromQuoteInputSchema.parse(args);
4035
+ const result = this.config.demoMode ? executeExecuteBridgeFromQuoteDemo(input) : await executeExecuteBridgeFromQuote(input, {
4036
+ privateKey: this.config.privateKey || "0x",
4037
+ demoMode: this.config.demoMode
4038
+ });
4039
+ if ("needsConfirmation" in result) {
4040
+ return this.formatConfirmation(result);
4041
+ }
4042
+ return {
4043
+ content: [{ type: "text", text: formatBridgeResult(result) }]
4044
+ };
4045
+ }
4046
+ /**
4047
+ * Handle wdk/quoteSwap
4048
+ */
4049
+ async handleWdkQuoteSwap(args) {
4050
+ const input = wdkQuoteSwapInputSchema.parse(args);
4051
+ const result = this.config.demoMode || !this.wdk ? executeWdkQuoteSwapDemo(input) : await executeWdkQuoteSwap(input, this.wdk);
4052
+ return {
4053
+ content: [{ type: "text", text: formatSwapQuoteResult(result) }]
4054
+ };
4055
+ }
4056
+ /**
4057
+ * Handle wdk/executeSwap
4058
+ */
4059
+ async handleWdkExecuteSwap(args) {
4060
+ const input = wdkExecuteSwapInputSchema.parse(args);
4061
+ const result = this.config.demoMode || !this.wdk ? executeWdkExecuteSwapDemo(input) : await executeWdkExecuteSwap(input, this.wdk);
4062
+ if ("needsConfirmation" in result) {
4063
+ return this.formatConfirmation(result);
4064
+ }
4065
+ return {
4066
+ content: [{ type: "text", text: formatExecuteSwapResult(result) }]
4067
+ };
4068
+ }
2853
4069
  // ---- ERC-8004 Tool Handlers ----
2854
4070
  /**
2855
4071
  * Handle erc8004/resolveAgent