@t402/mcp 2.7.1 → 2.8.1

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.
@@ -465,7 +465,8 @@ var payInputSchema = import_zod3.z.object({
465
465
  "berachain",
466
466
  "unichain"
467
467
  ]).describe("Network to execute payment on"),
468
- memo: import_zod3.z.string().optional().describe("Optional memo/reference for the payment")
468
+ memo: import_zod3.z.string().optional().describe("Optional memo/reference for the payment"),
469
+ confirmed: import_zod3.z.boolean().optional().describe("Set to true to confirm and execute this payment")
469
470
  });
470
471
  function getViemChain2(network) {
471
472
  switch (network) {
@@ -494,6 +495,13 @@ function getViemChain2(network) {
494
495
  async function executePay(input, options) {
495
496
  const { to, amount, token, network, memo: _memo } = input;
496
497
  const { privateKey, rpcUrl, demoMode } = options;
498
+ if (!input.confirmed) {
499
+ return {
500
+ needsConfirmation: true,
501
+ summary: `Send ${amount} ${token} on ${network} to ${to}`,
502
+ details: { to, amount, token, network }
503
+ };
504
+ }
497
505
  if (!supportsToken(network, token)) {
498
506
  throw new Error(`Token ${token} is not supported on ${network}`);
499
507
  }
@@ -578,7 +586,8 @@ var payGaslessInputSchema = import_zod4.z.object({
578
586
  to: import_zod4.z.string().regex(/^0x[a-fA-F0-9]{40}$/).describe("Recipient address"),
579
587
  amount: import_zod4.z.string().regex(/^\d+(\.\d+)?$/).describe("Amount to pay (e.g., '10.50' for 10.50 USDC)"),
580
588
  token: import_zod4.z.enum(["USDC", "USDT", "USDT0"]).describe("Token to use for payment"),
581
- network: import_zod4.z.enum(["ethereum", "base", "arbitrum", "optimism", "polygon", "avalanche"]).describe("Network to execute gasless payment on (must support ERC-4337)")
589
+ network: import_zod4.z.enum(["ethereum", "base", "arbitrum", "optimism", "polygon", "avalanche"]).describe("Network to execute gasless payment on (must support ERC-4337)"),
590
+ confirmed: import_zod4.z.boolean().optional().describe("Set to true to confirm and execute this payment")
582
591
  });
583
592
  var GASLESS_SUPPORTED_NETWORKS = [
584
593
  "ethereum",
@@ -615,6 +624,13 @@ function getViemChain3(network) {
615
624
  async function executePayGasless(input, options) {
616
625
  const { to, amount, token, network } = input;
617
626
  const { privateKey, bundlerUrl, paymasterUrl: _paymasterUrl, rpcUrl, demoMode } = options;
627
+ if (!input.confirmed) {
628
+ return {
629
+ needsConfirmation: true,
630
+ summary: `Send ${amount} ${token} gasless on ${network} to ${to}`,
631
+ details: { to, amount, token, network }
632
+ };
633
+ }
618
634
  if (!GASLESS_SUPPORTED_NETWORKS.includes(network)) {
619
635
  throw new Error(
620
636
  `Network ${network} does not support ERC-4337 gasless transactions. Supported: ${GASLESS_SUPPORTED_NETWORKS.join(", ")}`
@@ -900,7 +916,8 @@ var bridgeInputSchema = import_zod6.z.object({
900
916
  fromChain: import_zod6.z.enum(["ethereum", "arbitrum", "ink", "berachain", "unichain"]).describe("Source chain to bridge from"),
901
917
  toChain: import_zod6.z.enum(["ethereum", "arbitrum", "ink", "berachain", "unichain"]).describe("Destination chain to bridge to"),
902
918
  amount: import_zod6.z.string().regex(/^\d+(\.\d+)?$/).describe("Amount of USDT0 to bridge (e.g., '100' for 100 USDT0)"),
903
- recipient: import_zod6.z.string().regex(/^0x[a-fA-F0-9]{40}$/).describe("Recipient address on destination chain")
919
+ recipient: import_zod6.z.string().regex(/^0x[a-fA-F0-9]{40}$/).describe("Recipient address on destination chain"),
920
+ confirmed: import_zod6.z.boolean().optional().describe("Set to true to confirm and execute this bridge")
904
921
  });
905
922
  var LAYERZERO_ENDPOINT_IDS2 = {
906
923
  ethereum: 30101,
@@ -1027,6 +1044,13 @@ function addressToBytes322(address) {
1027
1044
  async function executeBridge(input, options) {
1028
1045
  const { fromChain, toChain, amount, recipient } = input;
1029
1046
  const { privateKey, rpcUrl, demoMode, slippageTolerance = 0.5 } = options;
1047
+ if (!input.confirmed) {
1048
+ return {
1049
+ needsConfirmation: true,
1050
+ summary: `Bridge ${amount} USDT0 from ${fromChain} to ${toChain}`,
1051
+ details: { fromChain, toChain, amount, recipient }
1052
+ };
1053
+ }
1030
1054
  if (fromChain === toChain) {
1031
1055
  throw new Error("Source and destination chains must be different");
1032
1056
  }
@@ -1156,10 +1180,10 @@ var import_zod7 = require("zod");
1156
1180
  var wdkGetWalletInputSchema = import_zod7.z.object({});
1157
1181
  async function executeWdkGetWallet(_input, wdk) {
1158
1182
  const signer = await wdk.getSigner("ethereum");
1159
- const chains7 = wdk.getConfiguredChains();
1183
+ const chains10 = wdk.getConfiguredChains();
1160
1184
  return {
1161
1185
  evmAddress: signer.address,
1162
- chains: chains7.length > 0 ? chains7 : ["ethereum"]
1186
+ chains: chains10.length > 0 ? chains10 : ["ethereum"]
1163
1187
  };
1164
1188
  }
1165
1189
  function executeWdkGetWalletDemo() {
@@ -1191,14 +1215,14 @@ function findTokenFormatted(tokens, symbol) {
1191
1215
  }
1192
1216
  async function executeWdkGetBalances(input, wdk) {
1193
1217
  const balances = await wdk.getAggregatedBalances();
1194
- const chains7 = balances.chains.filter((c) => !input.chains || input.chains.includes(c.chain)).map((c) => ({
1218
+ const chains10 = balances.chains.filter((c) => !input.chains || input.chains.includes(c.chain)).map((c) => ({
1195
1219
  chain: c.chain,
1196
1220
  usdt0: findTokenFormatted(c.tokens, "USDT0"),
1197
1221
  usdc: findTokenFormatted(c.tokens, "USDC"),
1198
1222
  native: (0, import_viem6.formatUnits)(c.native, 18)
1199
1223
  }));
1200
1224
  return {
1201
- chains: chains7,
1225
+ chains: chains10,
1202
1226
  totalUsdt0: (0, import_viem6.formatUnits)(balances.totalUsdt0, 6),
1203
1227
  totalUsdc: (0, import_viem6.formatUnits)(balances.totalUsdc, 6)
1204
1228
  };
@@ -1240,9 +1264,17 @@ var wdkTransferInputSchema = import_zod9.z.object({
1240
1264
  to: import_zod9.z.string().describe("Recipient address"),
1241
1265
  amount: import_zod9.z.string().regex(/^\d+(\.\d+)?$/).describe("Amount to send (e.g., '10.50')"),
1242
1266
  token: import_zod9.z.enum(["USDC", "USDT", "USDT0"]).describe("Token to transfer"),
1243
- chain: import_zod9.z.string().describe('Chain to execute transfer on (e.g., "ethereum", "arbitrum")')
1267
+ chain: import_zod9.z.string().describe('Chain to execute transfer on (e.g., "ethereum", "arbitrum")'),
1268
+ confirmed: import_zod9.z.boolean().optional().describe("Set to true to confirm and execute this transfer")
1244
1269
  });
1245
1270
  async function executeWdkTransfer(input, wdk) {
1271
+ if (!input.confirmed) {
1272
+ return {
1273
+ needsConfirmation: true,
1274
+ summary: `Transfer ${input.amount} ${input.token} on ${input.chain} to ${input.to}`,
1275
+ details: { to: input.to, amount: input.amount, token: input.token, chain: input.chain }
1276
+ };
1277
+ }
1246
1278
  const signer = await wdk.getSigner(input.chain);
1247
1279
  const result = await signer.sendTransaction({
1248
1280
  to: input.to
@@ -1259,6 +1291,13 @@ async function executeWdkTransfer(input, wdk) {
1259
1291
  };
1260
1292
  }
1261
1293
  function executeWdkTransferDemo(input) {
1294
+ if (!input.confirmed) {
1295
+ return {
1296
+ needsConfirmation: true,
1297
+ summary: `Transfer ${input.amount} ${input.token} on ${input.chain} to ${input.to}`,
1298
+ details: { to: input.to, amount: input.amount, token: input.token, chain: input.chain }
1299
+ };
1300
+ }
1262
1301
  const demoTxHash = "0xdemo" + Math.random().toString(16).slice(2, 10);
1263
1302
  return {
1264
1303
  txHash: demoTxHash,
@@ -1288,9 +1327,22 @@ var wdkSwapInputSchema = import_zod10.z.object({
1288
1327
  fromToken: import_zod10.z.string().describe('Token to swap from (e.g., "ETH", "USDC")'),
1289
1328
  toToken: import_zod10.z.string().describe('Token to swap to (e.g., "USDT0", "USDC")'),
1290
1329
  amount: import_zod10.z.string().regex(/^\d+(\.\d+)?$/).describe("Amount to swap (e.g., '1.0')"),
1291
- chain: import_zod10.z.string().describe('Chain to execute swap on (e.g., "ethereum", "arbitrum")')
1330
+ chain: import_zod10.z.string().describe('Chain to execute swap on (e.g., "ethereum", "arbitrum")'),
1331
+ confirmed: import_zod10.z.boolean().optional().describe("Set to true to confirm and execute this swap")
1292
1332
  });
1293
1333
  async function executeWdkSwap(input, wdk) {
1334
+ if (!input.confirmed) {
1335
+ return {
1336
+ needsConfirmation: true,
1337
+ summary: `Swap ${input.amount} ${input.fromToken} to ${input.toToken} on ${input.chain}`,
1338
+ details: {
1339
+ fromToken: input.fromToken,
1340
+ toToken: input.toToken,
1341
+ amount: input.amount,
1342
+ chain: input.chain
1343
+ }
1344
+ };
1345
+ }
1294
1346
  const decimals = ["USDC", "USDT", "USDT0"].includes(input.fromToken.toUpperCase()) ? 6 : 18;
1295
1347
  const amountBigInt = (0, import_viem7.parseUnits)(input.amount, decimals);
1296
1348
  const quote = await wdk.getSwapQuote(input.chain, input.fromToken, amountBigInt);
@@ -1311,6 +1363,18 @@ async function executeWdkSwap(input, wdk) {
1311
1363
  };
1312
1364
  }
1313
1365
  function executeWdkSwapDemo(input) {
1366
+ if (!input.confirmed) {
1367
+ return {
1368
+ needsConfirmation: true,
1369
+ summary: `Swap ${input.amount} ${input.fromToken} to ${input.toToken} on ${input.chain}`,
1370
+ details: {
1371
+ fromToken: input.fromToken,
1372
+ toToken: input.toToken,
1373
+ amount: input.amount,
1374
+ chain: input.chain
1375
+ }
1376
+ };
1377
+ }
1314
1378
  const inputAmount = parseFloat(input.amount);
1315
1379
  const outputAmount = (inputAmount * 0.997).toFixed(6);
1316
1380
  return {
@@ -1343,25 +1407,52 @@ var autoPayInputSchema = import_zod11.z.object({
1343
1407
  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.'),
1344
1408
  preferredChain: import_zod11.z.string().optional().describe(
1345
1409
  'Preferred chain for payment (e.g., "arbitrum"). If not specified, uses first available.'
1346
- )
1410
+ ),
1411
+ confirmed: import_zod11.z.boolean().optional().describe("Set to true to confirm and execute this payment")
1347
1412
  });
1348
1413
  async function executeAutoPay(input, wdk) {
1349
- const chains7 = input.preferredChain ? [input.preferredChain] : ["ethereum", "arbitrum", "base"];
1414
+ if (!input.confirmed) {
1415
+ return {
1416
+ needsConfirmation: true,
1417
+ summary: `Auto-pay for ${input.url}${input.maxAmount ? ` (max ${input.maxAmount})` : ""}`,
1418
+ details: {
1419
+ url: input.url,
1420
+ ...input.maxAmount ? { maxAmount: input.maxAmount } : {},
1421
+ ...input.preferredChain ? { preferredChain: input.preferredChain } : {}
1422
+ }
1423
+ };
1424
+ }
1425
+ const chains10 = input.preferredChain ? [input.preferredChain] : ["ethereum", "arbitrum", "base"];
1350
1426
  const { T402Protocol } = await import("@t402/wdk-protocol");
1351
- const protocol = await T402Protocol.create(wdk, { chains: chains7 });
1352
- const { response, receipt } = await protocol.fetch(input.url);
1353
- if (receipt && input.maxAmount) {
1354
- const paidAmount = parseFloat(receipt.amount) / 1e6;
1427
+ const protocol = await T402Protocol.create(wdk, { chains: chains10 });
1428
+ if (input.maxAmount) {
1355
1429
  const maxAmount = parseFloat(input.maxAmount);
1356
- if (paidAmount > maxAmount) {
1357
- return {
1358
- success: false,
1359
- statusCode: 402,
1360
- body: "",
1361
- error: `Payment amount (${paidAmount}) exceeds max allowed (${maxAmount})`
1362
- };
1430
+ const preflightResponse = await fetch(input.url);
1431
+ if (preflightResponse.status === 402) {
1432
+ const requirementsHeader = preflightResponse.headers.get("x-payment") || preflightResponse.headers.get("x-payment-requirements");
1433
+ if (requirementsHeader) {
1434
+ try {
1435
+ const requirements = JSON.parse(requirementsHeader);
1436
+ const reqArray = Array.isArray(requirements) ? requirements : [requirements];
1437
+ for (const req of reqArray) {
1438
+ if (req.amount) {
1439
+ const reqAmount = parseFloat(req.amount) / 1e6;
1440
+ if (reqAmount > maxAmount) {
1441
+ return {
1442
+ success: false,
1443
+ statusCode: 402,
1444
+ body: "",
1445
+ error: `Required payment amount (${reqAmount}) exceeds max allowed (${maxAmount})`
1446
+ };
1447
+ }
1448
+ }
1449
+ }
1450
+ } catch {
1451
+ }
1452
+ }
1363
1453
  }
1364
1454
  }
1455
+ const { response, receipt } = await protocol.fetch(input.url);
1365
1456
  const contentType = response.headers.get("content-type") ?? void 0;
1366
1457
  let body = "";
1367
1458
  try {
@@ -1386,6 +1477,17 @@ async function executeAutoPay(input, wdk) {
1386
1477
  };
1387
1478
  }
1388
1479
  function executeAutoPayDemo(input) {
1480
+ if (!input.confirmed) {
1481
+ return {
1482
+ needsConfirmation: true,
1483
+ summary: `Auto-pay for ${input.url}${input.maxAmount ? ` (max ${input.maxAmount})` : ""}`,
1484
+ details: {
1485
+ url: input.url,
1486
+ ...input.maxAmount ? { maxAmount: input.maxAmount } : {},
1487
+ ...input.preferredChain ? { preferredChain: input.preferredChain } : {}
1488
+ }
1489
+ };
1490
+ }
1389
1491
  return {
1390
1492
  success: true,
1391
1493
  statusCode: 200,
@@ -1829,174 +1931,981 @@ function formatErc8004VerifyWalletResult(result) {
1829
1931
  return lines.join("\n");
1830
1932
  }
1831
1933
 
1832
- // src/tools/unified.ts
1934
+ // src/tools/priceService.ts
1935
+ var CACHE_TTL_MS = 5 * 60 * 1e3;
1936
+ var COINGECKO_API = "https://api.coingecko.com/api/v3/simple/price";
1937
+ var TOKEN_TO_COINGECKO_ID = {
1938
+ ETH: "ethereum",
1939
+ MATIC: "matic-network",
1940
+ AVAX: "avalanche-2",
1941
+ BERA: "berachain-bera",
1942
+ USDC: "usd-coin",
1943
+ USDT: "tether",
1944
+ USDT0: "tether"
1945
+ };
1946
+ var cache = /* @__PURE__ */ new Map();
1947
+ async function getTokenPrices(tokens, currency = "usd") {
1948
+ const cacheKey = `${currency}:${tokens.sort().join(",")}`;
1949
+ const cached = cache.get(cacheKey);
1950
+ if (cached && Date.now() - cached.timestamp < CACHE_TTL_MS) {
1951
+ return cached.prices;
1952
+ }
1953
+ const coinIds = /* @__PURE__ */ new Set();
1954
+ const tokenToCoinId = /* @__PURE__ */ new Map();
1955
+ for (const token of tokens) {
1956
+ const coinId = TOKEN_TO_COINGECKO_ID[token.toUpperCase()] ?? token.toLowerCase();
1957
+ coinIds.add(coinId);
1958
+ tokenToCoinId.set(token.toUpperCase(), coinId);
1959
+ }
1960
+ const url = `${COINGECKO_API}?ids=${[...coinIds].join(",")}&vs_currencies=${currency}`;
1961
+ const response = await fetch(url);
1962
+ if (!response.ok) {
1963
+ throw new Error(`CoinGecko API error: ${response.status} ${response.statusText}`);
1964
+ }
1965
+ const data = await response.json();
1966
+ const prices = {};
1967
+ for (const token of tokens) {
1968
+ const coinId = tokenToCoinId.get(token.toUpperCase()) ?? token.toLowerCase();
1969
+ prices[token.toUpperCase()] = data[coinId]?.[currency] ?? 0;
1970
+ }
1971
+ cache.set(cacheKey, { prices, timestamp: Date.now() });
1972
+ return prices;
1973
+ }
1974
+ function getTokenPricesDemo(tokens) {
1975
+ const demoPrices = {
1976
+ ETH: 3250.42,
1977
+ MATIC: 0.58,
1978
+ AVAX: 24.15,
1979
+ BERA: 3.82,
1980
+ USDC: 1,
1981
+ USDT: 1,
1982
+ USDT0: 1
1983
+ };
1984
+ const prices = {};
1985
+ for (const token of tokens) {
1986
+ prices[token.toUpperCase()] = demoPrices[token.toUpperCase()] ?? 0;
1987
+ }
1988
+ return prices;
1989
+ }
1990
+
1991
+ // src/tools/getTokenPrice.ts
1833
1992
  var import_zod15 = require("zod");
1834
- var smartPayInputSchema = import_zod15.z.object({
1835
- url: import_zod15.z.string().url().describe("URL of the 402-protected resource"),
1836
- maxBridgeFee: import_zod15.z.string().regex(/^\d+(\.\d+)?$/).optional().describe("Maximum acceptable bridge fee in native token (optional)"),
1837
- preferredNetwork: import_zod15.z.string().optional().describe("Preferred network for payment (optional)")
1993
+ var getTokenPriceInputSchema = import_zod15.z.object({
1994
+ tokens: import_zod15.z.array(import_zod15.z.string()).min(1).describe('Token symbols to get prices for (e.g., ["ETH", "MATIC", "USDC"])'),
1995
+ currency: import_zod15.z.string().optional().describe('Target currency (default: "usd"). Supports: usd, eur, gbp, etc.')
1838
1996
  });
1839
- var paymentPlanInputSchema = import_zod15.z.object({
1840
- paymentRequired: import_zod15.z.object({
1841
- scheme: import_zod15.z.string().optional(),
1842
- network: import_zod15.z.string().optional(),
1843
- maxAmountRequired: import_zod15.z.string().optional(),
1844
- resource: import_zod15.z.string().optional(),
1845
- description: import_zod15.z.string().optional(),
1846
- payTo: import_zod15.z.string().optional(),
1847
- maxDeadline: import_zod15.z.number().optional()
1848
- }).passthrough().describe("The 402 PaymentRequired response")
1849
- });
1850
- var UNIFIED_TOOL_DEFINITIONS = {
1851
- "t402/smartPay": {
1852
- name: "t402/smartPay",
1853
- description: "Intelligent payment that automatically checks balance, bridges if needed, and pays. Handles the entire payment flow for 402-protected resources.",
1854
- inputSchema: {
1855
- type: "object",
1856
- properties: {
1857
- url: { type: "string", description: "URL of the 402-protected resource" },
1858
- maxBridgeFee: {
1859
- type: "string",
1860
- description: "Maximum acceptable bridge fee in native token (optional)"
1861
- },
1862
- preferredNetwork: {
1863
- type: "string",
1864
- description: "Preferred network for payment (optional)"
1865
- }
1866
- },
1867
- required: ["url"]
1868
- }
1869
- },
1870
- "t402/paymentPlan": {
1871
- name: "t402/paymentPlan",
1872
- description: "Analyze a 402 response and create an optimal payment plan considering balances across all chains. Returns recommended network, bridge requirements, and balance overview.",
1873
- inputSchema: {
1874
- type: "object",
1875
- properties: {
1876
- paymentRequired: {
1877
- type: "object",
1878
- description: "The 402 PaymentRequired response"
1879
- }
1880
- },
1881
- required: ["paymentRequired"]
1997
+ async function executeGetTokenPrice(input, options) {
1998
+ const currency = input.currency ?? "usd";
1999
+ const prices = options.demoMode ? getTokenPricesDemo(input.tokens) : await getTokenPrices(input.tokens, currency);
2000
+ return { prices, currency };
2001
+ }
2002
+ function formatTokenPriceResult(result) {
2003
+ const lines = ["## Token Prices", ""];
2004
+ const currencyUpper = result.currency.toUpperCase();
2005
+ for (const [token, price] of Object.entries(result.prices)) {
2006
+ if (price > 0) {
2007
+ lines.push(`- **${token}:** ${price.toLocaleString()} ${currencyUpper}`);
2008
+ } else {
2009
+ lines.push(`- **${token}:** Price unavailable`);
1882
2010
  }
1883
2011
  }
1884
- };
1885
- async function executeSmartPay(input, wdk) {
1886
- const steps = [];
1887
- const chains7 = input.preferredNetwork ? [input.preferredNetwork] : ["ethereum", "arbitrum", "base"];
1888
- steps.push({
1889
- action: "check_balance",
1890
- status: "success",
1891
- detail: `Checking balances on ${chains7.join(", ")}`
1892
- });
1893
- const { T402Protocol } = await import("@t402/wdk-protocol");
1894
- const protocol = await T402Protocol.create(wdk, { chains: chains7 });
1895
- steps.push({
1896
- action: "fetch",
1897
- status: "success",
1898
- detail: `Fetching ${input.url}`
1899
- });
1900
- const { response, receipt } = await protocol.fetch(input.url);
1901
- if (receipt) {
1902
- steps.push({
1903
- action: "pay",
1904
- status: "success",
1905
- detail: `Payment made: ${receipt.amount} on ${receipt.network}`
1906
- });
2012
+ return lines.join("\n");
2013
+ }
2014
+
2015
+ // src/tools/getGasPrice.ts
2016
+ var import_zod16 = require("zod");
2017
+ var import_viem9 = require("viem");
2018
+ var chains7 = __toESM(require("viem/chains"));
2019
+ var getGasPriceInputSchema = import_zod16.z.object({
2020
+ network: import_zod16.z.enum([
2021
+ "ethereum",
2022
+ "base",
2023
+ "arbitrum",
2024
+ "optimism",
2025
+ "polygon",
2026
+ "avalanche",
2027
+ "ink",
2028
+ "berachain",
2029
+ "unichain"
2030
+ ]).describe("Blockchain network to check gas price on")
2031
+ });
2032
+ function getViemChain6(network) {
2033
+ switch (network) {
2034
+ case "ethereum":
2035
+ return chains7.mainnet;
2036
+ case "base":
2037
+ return chains7.base;
2038
+ case "arbitrum":
2039
+ return chains7.arbitrum;
2040
+ case "optimism":
2041
+ return chains7.optimism;
2042
+ case "polygon":
2043
+ return chains7.polygon;
2044
+ case "avalanche":
2045
+ return chains7.avalanche;
2046
+ case "ink":
2047
+ return chains7.ink;
2048
+ case "berachain":
2049
+ return chains7.berachain;
2050
+ case "unichain":
2051
+ return chains7.unichain;
2052
+ default:
2053
+ return chains7.mainnet;
1907
2054
  }
1908
- const contentType = response.headers.get("content-type") ?? void 0;
1909
- let body = "";
1910
- try {
1911
- body = await response.text();
1912
- if (body.length > 1e4) {
1913
- body = body.slice(0, 1e4) + "\n... (truncated)";
1914
- }
1915
- } catch {
1916
- body = "[Could not read response body]";
2055
+ }
2056
+ async function executeGetGasPrice(input, options) {
2057
+ const { network } = input;
2058
+ if (options.demoMode) {
2059
+ const demoGasPrices = {
2060
+ ethereum: 25000000000n,
2061
+ // 25 gwei
2062
+ base: 50000000n,
2063
+ // 0.05 gwei
2064
+ arbitrum: 100000000n,
2065
+ // 0.1 gwei
2066
+ optimism: 50000000n,
2067
+ // 0.05 gwei
2068
+ polygon: 30000000000n,
2069
+ // 30 gwei
2070
+ avalanche: 25000000000n,
2071
+ // 25 nAVAX
2072
+ ink: 50000000n,
2073
+ // 0.05 gwei
2074
+ berachain: 1000000000n,
2075
+ // 1 gwei
2076
+ unichain: 50000000n
2077
+ // 0.05 gwei
2078
+ };
2079
+ const gasPrice2 = demoGasPrices[network] ?? 1000000000n;
2080
+ return {
2081
+ network,
2082
+ gasPriceWei: gasPrice2.toString(),
2083
+ gasPriceGwei: (0, import_viem9.formatGwei)(gasPrice2),
2084
+ nativeSymbol: NATIVE_SYMBOLS[network]
2085
+ };
1917
2086
  }
2087
+ const chain = getViemChain6(network);
2088
+ const transport = (0, import_viem9.http)(options.rpcUrl ?? DEFAULT_RPC_URLS[network]);
2089
+ const client = (0, import_viem9.createPublicClient)({ chain, transport });
2090
+ const gasPrice = await client.getGasPrice();
1918
2091
  return {
1919
- success: response.ok,
1920
- statusCode: response.status,
1921
- body,
1922
- contentType,
1923
- steps,
1924
- payment: receipt ? {
1925
- network: receipt.network,
1926
- scheme: receipt.scheme,
1927
- amount: receipt.amount,
1928
- payTo: receipt.payTo
1929
- } : void 0
2092
+ network,
2093
+ gasPriceWei: gasPrice.toString(),
2094
+ gasPriceGwei: (0, import_viem9.formatGwei)(gasPrice),
2095
+ nativeSymbol: NATIVE_SYMBOLS[network]
1930
2096
  };
1931
2097
  }
1932
- function executeSmartPayDemo(input) {
1933
- const network = input.preferredNetwork ?? "arbitrum";
1934
- return {
1935
- success: true,
1936
- statusCode: 200,
1937
- body: `[Demo] Premium content from ${input.url}
2098
+ function formatGasPriceResult(result) {
2099
+ return [
2100
+ "## Gas Price",
2101
+ "",
2102
+ `- **Network:** ${result.network}`,
2103
+ `- **Gas Price:** ${result.gasPriceGwei} gwei`,
2104
+ `- **Native Token:** ${result.nativeSymbol}`
2105
+ ].join("\n");
2106
+ }
1938
2107
 
1939
- This is simulated content returned after smart payment.`,
1940
- contentType: "text/plain",
1941
- steps: [
1942
- { action: "check_balance", status: "success", detail: `Checked balances on ${network}` },
1943
- { action: "check_price", status: "success", detail: "Resource costs 1.00 USDT0" },
1944
- { action: "pay", status: "success", detail: `Paid 1000000 USDT0 on eip155:42161` },
1945
- { action: "fetch", status: "success", detail: `Fetched ${input.url}` }
1946
- ],
1947
- payment: {
1948
- network: "eip155:42161",
1949
- scheme: "exact",
1950
- amount: "1000000",
1951
- payTo: "0xC88f67e776f16DcFBf42e6bDda1B82604448899B"
1952
- }
1953
- };
2108
+ // src/tools/estimatePaymentFee.ts
2109
+ var import_zod17 = require("zod");
2110
+ var import_viem10 = require("viem");
2111
+ var chains8 = __toESM(require("viem/chains"));
2112
+ var estimatePaymentFeeInputSchema = import_zod17.z.object({
2113
+ network: import_zod17.z.enum([
2114
+ "ethereum",
2115
+ "base",
2116
+ "arbitrum",
2117
+ "optimism",
2118
+ "polygon",
2119
+ "avalanche",
2120
+ "ink",
2121
+ "berachain",
2122
+ "unichain"
2123
+ ]).describe("Network to estimate fee on"),
2124
+ amount: import_zod17.z.string().regex(/^\d+(\.\d+)?$/).describe("Payment amount (e.g., '100')"),
2125
+ token: import_zod17.z.enum(["USDC", "USDT", "USDT0"]).describe("Token to use for payment")
2126
+ });
2127
+ function getViemChain7(network) {
2128
+ switch (network) {
2129
+ case "ethereum":
2130
+ return chains8.mainnet;
2131
+ case "base":
2132
+ return chains8.base;
2133
+ case "arbitrum":
2134
+ return chains8.arbitrum;
2135
+ case "optimism":
2136
+ return chains8.optimism;
2137
+ case "polygon":
2138
+ return chains8.polygon;
2139
+ case "avalanche":
2140
+ return chains8.avalanche;
2141
+ case "ink":
2142
+ return chains8.ink;
2143
+ case "berachain":
2144
+ return chains8.berachain;
2145
+ case "unichain":
2146
+ return chains8.unichain;
2147
+ default:
2148
+ return chains8.mainnet;
2149
+ }
1954
2150
  }
1955
- async function executePaymentPlan(input, wdk) {
1956
- const targetNetwork = input.paymentRequired.network;
1957
- const requiredAmount = input.paymentRequired.maxAmountRequired;
1958
- const aggregated = await wdk.getAggregatedBalances();
1959
- const balances = aggregated.chains.map((chain) => {
1960
- const usdt0 = chain.tokens.find((t) => t.symbol === "USDT0");
1961
- const usdc = chain.tokens.find((t) => t.symbol === "USDC");
1962
- return {
1963
- chain: chain.chain,
1964
- usdt0: usdt0?.formatted ?? "0",
1965
- usdc: usdc?.formatted ?? "0"
2151
+ async function executeEstimatePaymentFee(input, options) {
2152
+ const { network, amount, token } = input;
2153
+ const nativeSymbol = NATIVE_SYMBOLS[network];
2154
+ if (options.demoMode) {
2155
+ const demoEstimates = {
2156
+ ethereum: { gasLimit: 65000n, gasPrice: 25000000000n, nativePrice: 3250.42 },
2157
+ base: { gasLimit: 65000n, gasPrice: 50000000n, nativePrice: 3250.42 },
2158
+ arbitrum: { gasLimit: 65000n, gasPrice: 100000000n, nativePrice: 3250.42 },
2159
+ optimism: { gasLimit: 65000n, gasPrice: 50000000n, nativePrice: 3250.42 },
2160
+ polygon: { gasLimit: 65000n, gasPrice: 30000000000n, nativePrice: 0.58 },
2161
+ avalanche: { gasLimit: 65000n, gasPrice: 25000000000n, nativePrice: 24.15 },
2162
+ ink: { gasLimit: 65000n, gasPrice: 50000000n, nativePrice: 3250.42 },
2163
+ berachain: { gasLimit: 65000n, gasPrice: 1000000000n, nativePrice: 3.82 },
2164
+ unichain: { gasLimit: 65000n, gasPrice: 50000000n, nativePrice: 3250.42 }
1966
2165
  };
1967
- });
1968
- const requiredBigint = requiredAmount ? BigInt(requiredAmount) : 0n;
1969
- const bestChain = await wdk.findBestChainForPayment(requiredBigint);
1970
- if (bestChain) {
1971
- const needsBridge = targetNetwork ? !bestChain.chain.includes(targetNetwork) : false;
2166
+ const est = demoEstimates[network] ?? demoEstimates["ethereum"];
2167
+ const nativeCost2 = est.gasLimit * est.gasPrice;
2168
+ const usdCost2 = Number(nativeCost2) / 1e18 * est.nativePrice;
1972
2169
  return {
1973
- viable: true,
1974
- recommendedNetwork: bestChain.chain,
1975
- availableBalance: bestChain.balance.toString(),
1976
- bridgeRequired: needsBridge,
1977
- bridgeDetails: needsBridge ? {
1978
- fromChain: bestChain.chain,
1979
- toChain: targetNetwork ?? bestChain.chain,
1980
- amount: requiredAmount ?? "0",
1981
- estimatedFee: "0.001"
1982
- } : void 0,
1983
- balances
2170
+ network,
2171
+ gasLimit: est.gasLimit.toString(),
2172
+ gasPriceGwei: (0, import_viem10.formatGwei)(est.gasPrice),
2173
+ nativeCost: (0, import_viem10.formatEther)(nativeCost2),
2174
+ nativeSymbol,
2175
+ usdCost: `$${usdCost2.toFixed(4)}`
1984
2176
  };
1985
2177
  }
2178
+ const tokenAddress = getTokenAddress(network, token);
2179
+ if (!tokenAddress) {
2180
+ throw new Error(`Token ${token} is not supported on ${network}`);
2181
+ }
2182
+ const chain = getViemChain7(network);
2183
+ const transport = (0, import_viem10.http)(options.rpcUrl ?? DEFAULT_RPC_URLS[network]);
2184
+ const client = (0, import_viem10.createPublicClient)({ chain, transport });
2185
+ const amountBigInt = (0, import_viem10.parseUnits)(amount, 6);
2186
+ const dummyTo = "0x000000000000000000000000000000000000dEaD";
2187
+ let gasLimit;
2188
+ try {
2189
+ gasLimit = await client.estimateGas({
2190
+ to: tokenAddress,
2191
+ data: `0xa9059cbb${dummyTo.slice(2).padStart(64, "0")}${amountBigInt.toString(16).padStart(64, "0")}`
2192
+ });
2193
+ } catch {
2194
+ gasLimit = 65000n;
2195
+ }
2196
+ const gasPrice = await client.getGasPrice();
2197
+ const nativeCost = gasLimit * gasPrice;
2198
+ let usdCost;
2199
+ try {
2200
+ const prices = await getTokenPrices([nativeSymbol]);
2201
+ const nativePrice = prices[nativeSymbol] ?? 0;
2202
+ const cost = Number(nativeCost) / 1e18 * nativePrice;
2203
+ usdCost = `$${cost.toFixed(4)}`;
2204
+ } catch {
2205
+ usdCost = "N/A";
2206
+ }
1986
2207
  return {
1987
- viable: false,
1988
- bridgeRequired: false,
1989
- balances,
1990
- reason: "Insufficient balance across all chains"
2208
+ network,
2209
+ gasLimit: gasLimit.toString(),
2210
+ gasPriceGwei: (0, import_viem10.formatGwei)(gasPrice),
2211
+ nativeCost: (0, import_viem10.formatEther)(nativeCost),
2212
+ nativeSymbol,
2213
+ usdCost
1991
2214
  };
1992
2215
  }
1993
- function executePaymentPlanDemo(_input) {
1994
- return {
1995
- viable: true,
1996
- recommendedNetwork: "arbitrum",
1997
- availableBalance: "500000000",
1998
- bridgeRequired: false,
1999
- balances: [
2216
+ function formatPaymentFeeEstimate(result) {
2217
+ return [
2218
+ "## Payment Fee Estimate",
2219
+ "",
2220
+ `- **Network:** ${result.network}`,
2221
+ `- **Estimated Gas:** ${result.gasLimit}`,
2222
+ `- **Gas Price:** ${result.gasPriceGwei} gwei`,
2223
+ `- **Native Cost:** ${result.nativeCost} ${result.nativeSymbol}`,
2224
+ `- **USD Cost:** ${result.usdCost}`
2225
+ ].join("\n");
2226
+ }
2227
+
2228
+ // src/tools/compareNetworkFees.ts
2229
+ var import_zod18 = require("zod");
2230
+ var compareNetworkFeesInputSchema = import_zod18.z.object({
2231
+ amount: import_zod18.z.string().regex(/^\d+(\.\d+)?$/).describe("Payment amount (e.g., '100')"),
2232
+ token: import_zod18.z.enum(["USDC", "USDT", "USDT0"]).describe("Token to use for payment"),
2233
+ networks: import_zod18.z.array(import_zod18.z.string()).optional().describe(
2234
+ "Networks to compare. If not provided, compares all networks that support the token."
2235
+ )
2236
+ });
2237
+ var ALL_NETWORKS2 = [
2238
+ "ethereum",
2239
+ "base",
2240
+ "arbitrum",
2241
+ "optimism",
2242
+ "polygon",
2243
+ "avalanche",
2244
+ "ink",
2245
+ "berachain",
2246
+ "unichain"
2247
+ ];
2248
+ async function executeCompareNetworkFees(input, options) {
2249
+ const { amount, token } = input;
2250
+ const requestedNetworks = input.networks ? input.networks : ALL_NETWORKS2;
2251
+ const networks = requestedNetworks.filter((n) => supportsToken(n, token));
2252
+ if (networks.length === 0) {
2253
+ throw new Error(`No supported networks found for token ${token}`);
2254
+ }
2255
+ const results = await Promise.allSettled(
2256
+ networks.map(
2257
+ (network) => executeEstimatePaymentFee(
2258
+ { network, amount, token },
2259
+ {
2260
+ rpcUrl: options.rpcUrls?.[network],
2261
+ demoMode: options.demoMode
2262
+ }
2263
+ )
2264
+ )
2265
+ );
2266
+ const fees = [];
2267
+ for (const result of results) {
2268
+ if (result.status === "fulfilled") {
2269
+ fees.push(result.value);
2270
+ }
2271
+ }
2272
+ if (fees.length === 0) {
2273
+ throw new Error("Failed to estimate fees on any network");
2274
+ }
2275
+ fees.sort((a, b) => {
2276
+ const costA = parseFloat(a.nativeCost) || Infinity;
2277
+ const costB = parseFloat(b.nativeCost) || Infinity;
2278
+ const usdA = parseFloat(a.usdCost.replace("$", "")) || Infinity;
2279
+ const usdB = parseFloat(b.usdCost.replace("$", "")) || Infinity;
2280
+ return usdA - usdB || costA - costB;
2281
+ });
2282
+ return {
2283
+ token,
2284
+ amount,
2285
+ fees,
2286
+ cheapest: fees[0].network
2287
+ };
2288
+ }
2289
+ function formatNetworkFeeComparison(result) {
2290
+ const lines = [
2291
+ "## Network Fee Comparison",
2292
+ "",
2293
+ `**Token:** ${result.token} | **Amount:** ${result.amount}`,
2294
+ `**Cheapest:** ${result.cheapest}`,
2295
+ "",
2296
+ "| Network | Gas Price | Native Cost | USD Cost |",
2297
+ "|---------|----------|-------------|----------|"
2298
+ ];
2299
+ for (const fee of result.fees) {
2300
+ const marker = fee.network === result.cheapest ? " *" : "";
2301
+ lines.push(
2302
+ `| ${fee.network}${marker} | ${fee.gasPriceGwei} gwei | ${fee.nativeCost} ${fee.nativeSymbol} | ${fee.usdCost} |`
2303
+ );
2304
+ }
2305
+ return lines.join("\n");
2306
+ }
2307
+
2308
+ // src/tools/signMessage.ts
2309
+ var import_zod19 = require("zod");
2310
+ var signMessageInputSchema = import_zod19.z.object({
2311
+ chain: import_zod19.z.enum([
2312
+ "ethereum",
2313
+ "base",
2314
+ "arbitrum",
2315
+ "optimism",
2316
+ "polygon",
2317
+ "avalanche",
2318
+ "ink",
2319
+ "berachain",
2320
+ "unichain"
2321
+ ]).describe("Blockchain network context for signing"),
2322
+ message: import_zod19.z.string().min(1).describe("Message to sign")
2323
+ });
2324
+
2325
+ // src/tools/verifySignature.ts
2326
+ var import_zod20 = require("zod");
2327
+ var import_viem11 = require("viem");
2328
+ var verifySignatureInputSchema = import_zod20.z.object({
2329
+ chain: import_zod20.z.enum([
2330
+ "ethereum",
2331
+ "base",
2332
+ "arbitrum",
2333
+ "optimism",
2334
+ "polygon",
2335
+ "avalanche",
2336
+ "ink",
2337
+ "berachain",
2338
+ "unichain"
2339
+ ]).describe("Blockchain network context for verification"),
2340
+ message: import_zod20.z.string().min(1).describe("The original message that was signed"),
2341
+ signature: import_zod20.z.string().regex(/^0x[a-fA-F0-9]+$/).describe("The signature to verify (hex string)"),
2342
+ address: import_zod20.z.string().regex(/^0x[a-fA-F0-9]{40}$/).describe("The expected signer address")
2343
+ });
2344
+
2345
+ // src/tools/getTransferHistory.ts
2346
+ var import_zod21 = require("zod");
2347
+ var import_viem12 = require("viem");
2348
+ var chains9 = __toESM(require("viem/chains"));
2349
+ var getTransferHistoryInputSchema = import_zod21.z.object({
2350
+ network: import_zod21.z.enum([
2351
+ "ethereum",
2352
+ "base",
2353
+ "arbitrum",
2354
+ "optimism",
2355
+ "polygon",
2356
+ "avalanche",
2357
+ "ink",
2358
+ "berachain",
2359
+ "unichain"
2360
+ ]).describe("Blockchain network to query"),
2361
+ address: import_zod21.z.string().regex(/^0x[a-fA-F0-9]{40}$/).describe("Wallet address to get transfer history for"),
2362
+ token: import_zod21.z.enum(["USDC", "USDT", "USDT0"]).optional().describe("Filter by specific token. If not provided, queries all supported stablecoins."),
2363
+ limit: import_zod21.z.number().int().min(1).max(100).optional().describe("Maximum number of transfers to return (default: 10, max: 100)")
2364
+ });
2365
+
2366
+ // src/tools/getHistoricalPrice.ts
2367
+ var import_zod22 = require("zod");
2368
+ var getHistoricalPriceInputSchema = import_zod22.z.object({
2369
+ token: import_zod22.z.string().min(1).describe('Token symbol (e.g., "ETH", "USDC", "USDT", "MATIC", "AVAX")'),
2370
+ days: import_zod22.z.number().int().min(1).max(365).optional().describe("Number of days of history to retrieve (default: 7, max: 365)")
2371
+ });
2372
+
2373
+ // src/tools/quoteStore.ts
2374
+ var import_crypto = require("crypto");
2375
+ var DEFAULT_TTL_MS = 5 * 60 * 1e3;
2376
+ var quotes = /* @__PURE__ */ new Map();
2377
+ var cleanupInterval = null;
2378
+ function ensureCleanup() {
2379
+ if (cleanupInterval) return;
2380
+ cleanupInterval = setInterval(() => {
2381
+ const now = Date.now();
2382
+ for (const [id, quote] of quotes) {
2383
+ if (now > quote.expiresAt) {
2384
+ quotes.delete(id);
2385
+ }
2386
+ }
2387
+ }, 6e4);
2388
+ if (cleanupInterval.unref) {
2389
+ cleanupInterval.unref();
2390
+ }
2391
+ }
2392
+ function createQuote(type, data, ttlMs = DEFAULT_TTL_MS) {
2393
+ ensureCleanup();
2394
+ const id = (0, import_crypto.randomUUID)();
2395
+ const now = Date.now();
2396
+ quotes.set(id, {
2397
+ id,
2398
+ type,
2399
+ createdAt: now,
2400
+ expiresAt: now + ttlMs,
2401
+ data
2402
+ });
2403
+ return id;
2404
+ }
2405
+ function getQuote(quoteId) {
2406
+ const quote = quotes.get(quoteId);
2407
+ if (!quote) return null;
2408
+ if (Date.now() > quote.expiresAt) {
2409
+ quotes.delete(quoteId);
2410
+ return null;
2411
+ }
2412
+ return quote;
2413
+ }
2414
+ function deleteQuote(quoteId) {
2415
+ quotes.delete(quoteId);
2416
+ }
2417
+
2418
+ // src/tools/wdkQuoteSwap.ts
2419
+ var import_zod23 = require("zod");
2420
+ var import_viem13 = require("viem");
2421
+ var wdkQuoteSwapInputSchema = import_zod23.z.object({
2422
+ fromToken: import_zod23.z.string().describe('Token to swap from (e.g., "ETH", "USDC")'),
2423
+ toToken: import_zod23.z.string().describe('Token to swap to (e.g., "USDT0", "USDC")'),
2424
+ amount: import_zod23.z.string().regex(/^\d+(\.\d+)?$/).describe("Amount to swap (e.g., '1.0')"),
2425
+ chain: import_zod23.z.string().describe('Chain to execute swap on (e.g., "ethereum", "arbitrum")')
2426
+ });
2427
+ async function executeWdkQuoteSwap(input, wdk) {
2428
+ const decimals = ["USDC", "USDT", "USDT0"].includes(input.fromToken.toUpperCase()) ? 6 : 18;
2429
+ const amountBigInt = (0, import_viem13.parseUnits)(input.amount, decimals);
2430
+ const quote = await wdk.getSwapQuote(input.chain, input.fromToken, amountBigInt);
2431
+ const outputDecimals = ["USDC", "USDT", "USDT0"].includes(input.toToken.toUpperCase()) ? 6 : 18;
2432
+ const outputDivisor = 10 ** outputDecimals;
2433
+ const toAmount = (Number(quote.outputAmount) / outputDivisor).toFixed(outputDecimals === 6 ? 6 : 8);
2434
+ const inputAmount = parseFloat(input.amount);
2435
+ const outputAmount = parseFloat(toAmount);
2436
+ const exchangeRate = inputAmount > 0 ? (outputAmount / inputAmount).toFixed(6) : "0";
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 executeWdkQuoteSwapDemo(input) {
2460
+ const inputAmount = parseFloat(input.amount);
2461
+ const toAmount = (inputAmount * 0.997).toFixed(6);
2462
+ const exchangeRate = 0.997.toFixed(6);
2463
+ const expiresAt = new Date(Date.now() + 5 * 60 * 1e3).toISOString();
2464
+ const quoteId = createQuote("swap", {
2465
+ fromToken: input.fromToken,
2466
+ toToken: input.toToken,
2467
+ fromAmount: input.amount,
2468
+ toAmount,
2469
+ chain: input.chain,
2470
+ exchangeRate
2471
+ });
2472
+ return {
2473
+ quoteId,
2474
+ fromToken: input.fromToken,
2475
+ toToken: input.toToken,
2476
+ fromAmount: input.amount,
2477
+ toAmount,
2478
+ exchangeRate,
2479
+ fee: "0.3%",
2480
+ priceImpact: "< 0.1%",
2481
+ expiresAt,
2482
+ chain: input.chain
2483
+ };
2484
+ }
2485
+ function formatSwapQuoteResult(result) {
2486
+ return [
2487
+ "## Swap Quote",
2488
+ "",
2489
+ `- **Quote ID:** \`${result.quoteId}\``,
2490
+ `- **From:** ${result.fromAmount} ${result.fromToken}`,
2491
+ `- **To:** ${result.toAmount} ${result.toToken}`,
2492
+ `- **Exchange Rate:** ${result.exchangeRate}`,
2493
+ `- **Fee:** ${result.fee}`,
2494
+ `- **Price Impact:** ${result.priceImpact}`,
2495
+ `- **Chain:** ${result.chain}`,
2496
+ `- **Expires:** ${result.expiresAt}`,
2497
+ "",
2498
+ "_Call `wdk/executeSwap` with the quoteId to execute this swap._"
2499
+ ].join("\n");
2500
+ }
2501
+
2502
+ // src/tools/wdkExecuteSwap.ts
2503
+ var import_zod24 = require("zod");
2504
+ var import_viem14 = require("viem");
2505
+ var wdkExecuteSwapInputSchema = import_zod24.z.object({
2506
+ quoteId: import_zod24.z.string().uuid().describe("Quote ID from wdk/quoteSwap"),
2507
+ confirmed: import_zod24.z.boolean().optional().describe("Set to true to confirm and execute this swap")
2508
+ });
2509
+ async function executeWdkExecuteSwap(input, wdk) {
2510
+ const quote = getQuote(input.quoteId);
2511
+ if (!quote) {
2512
+ throw new Error("Quote not found or expired. Please request a new quote.");
2513
+ }
2514
+ if (quote.type !== "swap") {
2515
+ throw new Error("Invalid quote type. Expected a swap quote.");
2516
+ }
2517
+ const { fromToken, toToken, fromAmount, toAmount, chain } = quote.data;
2518
+ if (!input.confirmed) {
2519
+ return {
2520
+ needsConfirmation: true,
2521
+ summary: `Swap ${fromAmount} ${fromToken} to ${toAmount} ${toToken} on ${chain}`,
2522
+ details: { fromToken, toToken, fromAmount, toAmount, chain, quoteId: input.quoteId }
2523
+ };
2524
+ }
2525
+ const decimals = ["USDC", "USDT", "USDT0"].includes(fromToken.toUpperCase()) ? 6 : 18;
2526
+ const amountBigInt = (0, import_viem14.parseUnits)(fromAmount, decimals);
2527
+ const result = await wdk.swapAndPay({
2528
+ chain,
2529
+ fromToken,
2530
+ amount: amountBigInt
2531
+ });
2532
+ deleteQuote(input.quoteId);
2533
+ return {
2534
+ fromAmount,
2535
+ fromToken,
2536
+ toAmount,
2537
+ toToken,
2538
+ chain,
2539
+ txHash: result?.txHash ?? "0x"
2540
+ };
2541
+ }
2542
+ function executeWdkExecuteSwapDemo(input) {
2543
+ const quote = getQuote(input.quoteId);
2544
+ if (!quote) {
2545
+ throw new Error("Quote not found or expired. Please request a new quote.");
2546
+ }
2547
+ if (quote.type !== "swap") {
2548
+ throw new Error("Invalid quote type. Expected a swap quote.");
2549
+ }
2550
+ const { fromToken, toToken, fromAmount, toAmount, chain } = quote.data;
2551
+ if (!input.confirmed) {
2552
+ return {
2553
+ needsConfirmation: true,
2554
+ summary: `Swap ${fromAmount} ${fromToken} to ${toAmount} ${toToken} on ${chain}`,
2555
+ details: { fromToken, toToken, fromAmount, toAmount, chain, quoteId: input.quoteId }
2556
+ };
2557
+ }
2558
+ deleteQuote(input.quoteId);
2559
+ return {
2560
+ fromAmount,
2561
+ fromToken,
2562
+ toAmount,
2563
+ toToken,
2564
+ chain,
2565
+ txHash: "0xdemo" + Math.random().toString(16).slice(2, 10)
2566
+ };
2567
+ }
2568
+ function formatExecuteSwapResult(result) {
2569
+ return [
2570
+ "## Swap Executed",
2571
+ "",
2572
+ `- **From:** ${result.fromAmount} ${result.fromToken}`,
2573
+ `- **To:** ${result.toAmount} ${result.toToken}`,
2574
+ `- **Chain:** ${result.chain}`,
2575
+ `- **Tx Hash:** \`${result.txHash}\``
2576
+ ].join("\n");
2577
+ }
2578
+
2579
+ // src/tools/quoteBridge.ts
2580
+ var import_zod25 = require("zod");
2581
+ var quoteBridgeInputSchema = import_zod25.z.object({
2582
+ fromChain: import_zod25.z.enum(["ethereum", "arbitrum", "ink", "berachain", "unichain"]).describe("Source chain to bridge from"),
2583
+ toChain: import_zod25.z.enum(["ethereum", "arbitrum", "ink", "berachain", "unichain"]).describe("Destination chain to bridge to"),
2584
+ amount: import_zod25.z.string().regex(/^\d+(\.\d+)?$/).describe("Amount of USDT0 to bridge (e.g., '100' for 100 USDT0)"),
2585
+ recipient: import_zod25.z.string().regex(/^0x[a-fA-F0-9]{40}$/).describe("Recipient address on destination chain")
2586
+ });
2587
+ async function executeQuoteBridge(input, rpcUrls) {
2588
+ const feeResult = await executeGetBridgeFee(input, rpcUrls);
2589
+ const expiresAt = new Date(Date.now() + 5 * 60 * 1e3).toISOString();
2590
+ const quoteId = createQuote("bridge", {
2591
+ fromChain: input.fromChain,
2592
+ toChain: input.toChain,
2593
+ amount: input.amount,
2594
+ recipient: input.recipient,
2595
+ nativeFee: feeResult.nativeFee,
2596
+ nativeFeeFormatted: feeResult.nativeFeeFormatted,
2597
+ estimatedTime: feeResult.estimatedTime
2598
+ });
2599
+ return {
2600
+ quoteId,
2601
+ fromChain: input.fromChain,
2602
+ toChain: input.toChain,
2603
+ amount: input.amount,
2604
+ recipient: input.recipient,
2605
+ nativeFee: feeResult.nativeFee,
2606
+ nativeFeeFormatted: feeResult.nativeFeeFormatted,
2607
+ estimatedTime: feeResult.estimatedTime,
2608
+ expiresAt
2609
+ };
2610
+ }
2611
+ function executeQuoteBridgeDemo(input) {
2612
+ const expiresAt = new Date(Date.now() + 5 * 60 * 1e3).toISOString();
2613
+ const estimatedTime = input.toChain === "ethereum" ? 900 : 300;
2614
+ const quoteId = createQuote("bridge", {
2615
+ fromChain: input.fromChain,
2616
+ toChain: input.toChain,
2617
+ amount: input.amount,
2618
+ recipient: input.recipient,
2619
+ nativeFee: "1000000000000000",
2620
+ nativeFeeFormatted: "0.001 ETH",
2621
+ estimatedTime
2622
+ });
2623
+ return {
2624
+ quoteId,
2625
+ fromChain: input.fromChain,
2626
+ toChain: input.toChain,
2627
+ amount: input.amount,
2628
+ recipient: input.recipient,
2629
+ nativeFee: "1000000000000000",
2630
+ nativeFeeFormatted: "0.001 ETH",
2631
+ estimatedTime,
2632
+ expiresAt
2633
+ };
2634
+ }
2635
+ function formatBridgeQuoteResult(result) {
2636
+ const minutes = Math.ceil(result.estimatedTime / 60);
2637
+ return [
2638
+ "## Bridge Quote",
2639
+ "",
2640
+ `- **Quote ID:** \`${result.quoteId}\``,
2641
+ `- **Route:** ${result.fromChain} -> ${result.toChain}`,
2642
+ `- **Amount:** ${result.amount} USDT0`,
2643
+ `- **Recipient:** \`${result.recipient}\``,
2644
+ `- **Fee:** ${result.nativeFeeFormatted}`,
2645
+ `- **Estimated Time:** ~${minutes} minutes`,
2646
+ `- **Expires:** ${result.expiresAt}`,
2647
+ "",
2648
+ "_Call `t402/executeBridge` with the quoteId to execute this bridge._"
2649
+ ].join("\n");
2650
+ }
2651
+
2652
+ // src/tools/executeBridgeFromQuote.ts
2653
+ var import_zod26 = require("zod");
2654
+ var executeBridgeFromQuoteInputSchema = import_zod26.z.object({
2655
+ quoteId: import_zod26.z.string().uuid().describe("Quote ID from t402/quoteBridge"),
2656
+ confirmed: import_zod26.z.boolean().optional().describe("Set to true to confirm and execute this bridge")
2657
+ });
2658
+ async function executeExecuteBridgeFromQuote(input, options) {
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
+ const result = await executeBridge(
2675
+ { fromChain, toChain, amount, recipient, confirmed: true },
2676
+ options
2677
+ );
2678
+ if ("needsConfirmation" in result) {
2679
+ return result;
2680
+ }
2681
+ deleteQuote(input.quoteId);
2682
+ return result;
2683
+ }
2684
+ function executeExecuteBridgeFromQuoteDemo(input) {
2685
+ const quote = getQuote(input.quoteId);
2686
+ if (!quote) {
2687
+ throw new Error("Quote not found or expired. Please request a new quote.");
2688
+ }
2689
+ if (quote.type !== "bridge") {
2690
+ throw new Error("Invalid quote type. Expected a bridge quote.");
2691
+ }
2692
+ const { fromChain, toChain, amount, recipient } = quote.data;
2693
+ if (!input.confirmed) {
2694
+ return {
2695
+ needsConfirmation: true,
2696
+ summary: `Bridge ${amount} USDT0 from ${fromChain} to ${toChain}`,
2697
+ details: { fromChain, toChain, amount, recipient, quoteId: input.quoteId }
2698
+ };
2699
+ }
2700
+ deleteQuote(input.quoteId);
2701
+ const fakeTxHash = `0x${"a".repeat(64)}`;
2702
+ const fakeGuid = `0x${"b".repeat(64)}`;
2703
+ return {
2704
+ txHash: fakeTxHash,
2705
+ messageGuid: fakeGuid,
2706
+ amount,
2707
+ fromChain,
2708
+ toChain,
2709
+ estimatedTime: quote.data.estimatedTime ?? 300,
2710
+ trackingUrl: `https://layerzeroscan.com/tx/${fakeGuid}`
2711
+ };
2712
+ }
2713
+
2714
+ // src/tools/unified.ts
2715
+ var import_zod27 = require("zod");
2716
+ var smartPayInputSchema = import_zod27.z.object({
2717
+ url: import_zod27.z.string().url().describe("URL of the 402-protected resource"),
2718
+ maxBridgeFee: import_zod27.z.string().regex(/^\d+(\.\d+)?$/).optional().describe("Maximum acceptable bridge fee in native token (optional)"),
2719
+ preferredNetwork: import_zod27.z.string().optional().describe("Preferred network for payment (optional)"),
2720
+ confirmed: import_zod27.z.boolean().optional().describe("Set to true to confirm and execute this payment")
2721
+ });
2722
+ var paymentPlanInputSchema = import_zod27.z.object({
2723
+ paymentRequired: import_zod27.z.object({
2724
+ scheme: import_zod27.z.string().optional(),
2725
+ network: import_zod27.z.string().optional(),
2726
+ maxAmountRequired: import_zod27.z.string().optional(),
2727
+ resource: import_zod27.z.string().optional(),
2728
+ description: import_zod27.z.string().optional(),
2729
+ payTo: import_zod27.z.string().optional(),
2730
+ maxDeadline: import_zod27.z.number().optional()
2731
+ }).passthrough().describe("The 402 PaymentRequired response")
2732
+ });
2733
+ var UNIFIED_TOOL_DEFINITIONS = {
2734
+ "t402/smartPay": {
2735
+ name: "t402/smartPay",
2736
+ description: "Intelligent payment that automatically checks balance, bridges if needed, and pays. Handles the entire payment flow for 402-protected resources.",
2737
+ inputSchema: {
2738
+ type: "object",
2739
+ properties: {
2740
+ url: { type: "string", description: "URL of the 402-protected resource" },
2741
+ maxBridgeFee: {
2742
+ type: "string",
2743
+ description: "Maximum acceptable bridge fee in native token (optional)"
2744
+ },
2745
+ preferredNetwork: {
2746
+ type: "string",
2747
+ description: "Preferred network for payment (optional)"
2748
+ },
2749
+ confirmed: {
2750
+ type: "boolean",
2751
+ description: "Set to true to confirm and execute. Omit for a preview/confirmation prompt."
2752
+ }
2753
+ },
2754
+ required: ["url"]
2755
+ }
2756
+ },
2757
+ "t402/paymentPlan": {
2758
+ name: "t402/paymentPlan",
2759
+ description: "Analyze a 402 response and create an optimal payment plan considering balances across all chains. Returns recommended network, bridge requirements, and balance overview.",
2760
+ inputSchema: {
2761
+ type: "object",
2762
+ properties: {
2763
+ paymentRequired: {
2764
+ type: "object",
2765
+ description: "The 402 PaymentRequired response"
2766
+ }
2767
+ },
2768
+ required: ["paymentRequired"]
2769
+ }
2770
+ }
2771
+ };
2772
+ async function executeSmartPay(input, wdk) {
2773
+ if (!input.confirmed) {
2774
+ return {
2775
+ needsConfirmation: true,
2776
+ summary: `Smart-pay for ${input.url}${input.preferredNetwork ? ` on ${input.preferredNetwork}` : ""}`,
2777
+ details: {
2778
+ url: input.url,
2779
+ ...input.maxBridgeFee ? { maxBridgeFee: input.maxBridgeFee } : {},
2780
+ ...input.preferredNetwork ? { preferredNetwork: input.preferredNetwork } : {}
2781
+ }
2782
+ };
2783
+ }
2784
+ const steps = [];
2785
+ const chains10 = input.preferredNetwork ? [input.preferredNetwork] : ["ethereum", "arbitrum", "base"];
2786
+ steps.push({
2787
+ action: "check_balance",
2788
+ status: "success",
2789
+ detail: `Checking balances on ${chains10.join(", ")}`
2790
+ });
2791
+ const { T402Protocol } = await import("@t402/wdk-protocol");
2792
+ const protocol = await T402Protocol.create(wdk, { chains: chains10 });
2793
+ steps.push({
2794
+ action: "fetch",
2795
+ status: "success",
2796
+ detail: `Fetching ${input.url}`
2797
+ });
2798
+ const { response, receipt } = await protocol.fetch(input.url);
2799
+ if (receipt) {
2800
+ steps.push({
2801
+ action: "pay",
2802
+ status: "success",
2803
+ detail: `Payment made: ${receipt.amount} on ${receipt.network}`
2804
+ });
2805
+ }
2806
+ const contentType = response.headers.get("content-type") ?? void 0;
2807
+ let body = "";
2808
+ try {
2809
+ body = await response.text();
2810
+ if (body.length > 1e4) {
2811
+ body = body.slice(0, 1e4) + "\n... (truncated)";
2812
+ }
2813
+ } catch {
2814
+ body = "[Could not read response body]";
2815
+ }
2816
+ return {
2817
+ success: response.ok,
2818
+ statusCode: response.status,
2819
+ body,
2820
+ contentType,
2821
+ steps,
2822
+ payment: receipt ? {
2823
+ network: receipt.network,
2824
+ scheme: receipt.scheme,
2825
+ amount: receipt.amount,
2826
+ payTo: receipt.payTo
2827
+ } : void 0
2828
+ };
2829
+ }
2830
+ function executeSmartPayDemo(input) {
2831
+ if (!input.confirmed) {
2832
+ return {
2833
+ needsConfirmation: true,
2834
+ summary: `Smart-pay for ${input.url}${input.preferredNetwork ? ` on ${input.preferredNetwork}` : ""}`,
2835
+ details: {
2836
+ url: input.url,
2837
+ ...input.maxBridgeFee ? { maxBridgeFee: input.maxBridgeFee } : {},
2838
+ ...input.preferredNetwork ? { preferredNetwork: input.preferredNetwork } : {}
2839
+ }
2840
+ };
2841
+ }
2842
+ const network = input.preferredNetwork ?? "arbitrum";
2843
+ return {
2844
+ success: true,
2845
+ statusCode: 200,
2846
+ body: `[Demo] Premium content from ${input.url}
2847
+
2848
+ This is simulated content returned after smart payment.`,
2849
+ contentType: "text/plain",
2850
+ steps: [
2851
+ { action: "check_balance", status: "success", detail: `Checked balances on ${network}` },
2852
+ { action: "check_price", status: "success", detail: "Resource costs 1.00 USDT0" },
2853
+ { action: "pay", status: "success", detail: `Paid 1000000 USDT0 on eip155:42161` },
2854
+ { action: "fetch", status: "success", detail: `Fetched ${input.url}` }
2855
+ ],
2856
+ payment: {
2857
+ network: "eip155:42161",
2858
+ scheme: "exact",
2859
+ amount: "1000000",
2860
+ payTo: "0xC88f67e776f16DcFBf42e6bDda1B82604448899B"
2861
+ }
2862
+ };
2863
+ }
2864
+ async function executePaymentPlan(input, wdk) {
2865
+ const targetNetwork = input.paymentRequired.network;
2866
+ const requiredAmount = input.paymentRequired.maxAmountRequired;
2867
+ const aggregated = await wdk.getAggregatedBalances();
2868
+ const balances = aggregated.chains.map((chain) => {
2869
+ const usdt0 = chain.tokens.find((t) => t.symbol === "USDT0");
2870
+ const usdc = chain.tokens.find((t) => t.symbol === "USDC");
2871
+ return {
2872
+ chain: chain.chain,
2873
+ usdt0: usdt0?.formatted ?? "0",
2874
+ usdc: usdc?.formatted ?? "0"
2875
+ };
2876
+ });
2877
+ const requiredBigint = requiredAmount ? BigInt(requiredAmount) : 0n;
2878
+ const bestChain = await wdk.findBestChainForPayment(requiredBigint);
2879
+ if (bestChain) {
2880
+ const needsBridge = targetNetwork ? !bestChain.chain.includes(targetNetwork) : false;
2881
+ return {
2882
+ viable: true,
2883
+ recommendedNetwork: bestChain.chain,
2884
+ availableBalance: bestChain.balance.toString(),
2885
+ bridgeRequired: needsBridge,
2886
+ bridgeDetails: needsBridge ? {
2887
+ fromChain: bestChain.chain,
2888
+ toChain: targetNetwork ?? bestChain.chain,
2889
+ amount: requiredAmount ?? "0",
2890
+ estimatedFee: "0.001"
2891
+ } : void 0,
2892
+ balances
2893
+ };
2894
+ }
2895
+ return {
2896
+ viable: false,
2897
+ bridgeRequired: false,
2898
+ balances,
2899
+ reason: "Insufficient balance across all chains"
2900
+ };
2901
+ }
2902
+ function executePaymentPlanDemo(_input) {
2903
+ return {
2904
+ viable: true,
2905
+ recommendedNetwork: "arbitrum",
2906
+ availableBalance: "500000000",
2907
+ bridgeRequired: false,
2908
+ balances: [
2000
2909
  { chain: "ethereum", usdt0: "100.00", usdc: "250.00" },
2001
2910
  { chain: "arbitrum", usdt0: "500.00", usdc: "0" },
2002
2911
  { chain: "base", usdt0: "50.00", usdc: "100.00" }
@@ -2178,49 +3087,225 @@ var TOOL_DEFINITIONS = {
2178
3087
  "berachain",
2179
3088
  "unichain"
2180
3089
  ],
2181
- description: "Network to execute payment on"
3090
+ description: "Network to execute payment on"
3091
+ },
3092
+ memo: {
3093
+ type: "string",
3094
+ description: "Optional memo/reference for the payment"
3095
+ },
3096
+ confirmed: {
3097
+ type: "boolean",
3098
+ description: "Set to true to confirm and execute. Omit for a preview/confirmation prompt."
3099
+ }
3100
+ },
3101
+ required: ["to", "amount", "token", "network"]
3102
+ }
3103
+ },
3104
+ "t402/payGasless": {
3105
+ name: "t402/payGasless",
3106
+ description: "Execute a gasless stablecoin payment using ERC-4337 account abstraction. Gas fees are sponsored by a paymaster, so no ETH is needed for the transaction. Supported on select networks.",
3107
+ inputSchema: {
3108
+ type: "object",
3109
+ properties: {
3110
+ to: {
3111
+ type: "string",
3112
+ pattern: "^0x[a-fA-F0-9]{40}$",
3113
+ description: "Recipient address"
3114
+ },
3115
+ amount: {
3116
+ type: "string",
3117
+ pattern: "^\\d+(\\.\\d+)?$",
3118
+ description: "Amount to pay (e.g., '10.50' for 10.50 USDC)"
3119
+ },
3120
+ token: {
3121
+ type: "string",
3122
+ enum: ["USDC", "USDT", "USDT0"],
3123
+ description: "Token to use for payment"
3124
+ },
3125
+ network: {
3126
+ type: "string",
3127
+ enum: ["ethereum", "base", "arbitrum", "optimism", "polygon", "avalanche"],
3128
+ description: "Network to execute gasless payment on (must support ERC-4337)"
3129
+ },
3130
+ confirmed: {
3131
+ type: "boolean",
3132
+ description: "Set to true to confirm and execute. Omit for a preview/confirmation prompt."
3133
+ }
3134
+ },
3135
+ required: ["to", "amount", "token", "network"]
3136
+ }
3137
+ },
3138
+ "t402/getBridgeFee": {
3139
+ name: "t402/getBridgeFee",
3140
+ description: "Get the fee quote for bridging USDT0 between chains using LayerZero OFT. Returns the native token fee required and estimated delivery time. Supported chains: ethereum, arbitrum, ink, berachain, unichain.",
3141
+ inputSchema: {
3142
+ type: "object",
3143
+ properties: {
3144
+ fromChain: {
3145
+ type: "string",
3146
+ enum: ["ethereum", "arbitrum", "ink", "berachain", "unichain"],
3147
+ description: "Source chain to bridge from"
3148
+ },
3149
+ toChain: {
3150
+ type: "string",
3151
+ enum: ["ethereum", "arbitrum", "ink", "berachain", "unichain"],
3152
+ description: "Destination chain to bridge to"
3153
+ },
3154
+ amount: {
3155
+ type: "string",
3156
+ pattern: "^\\d+(\\.\\d+)?$",
3157
+ description: "Amount of USDT0 to bridge (e.g., '100' for 100 USDT0)"
3158
+ },
3159
+ recipient: {
3160
+ type: "string",
3161
+ pattern: "^0x[a-fA-F0-9]{40}$",
3162
+ description: "Recipient address on destination chain"
3163
+ }
3164
+ },
3165
+ required: ["fromChain", "toChain", "amount", "recipient"]
3166
+ }
3167
+ },
3168
+ "t402/bridge": {
3169
+ name: "t402/bridge",
3170
+ 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.",
3171
+ inputSchema: {
3172
+ type: "object",
3173
+ properties: {
3174
+ fromChain: {
3175
+ type: "string",
3176
+ enum: ["ethereum", "arbitrum", "ink", "berachain", "unichain"],
3177
+ description: "Source chain to bridge from"
3178
+ },
3179
+ toChain: {
3180
+ type: "string",
3181
+ enum: ["ethereum", "arbitrum", "ink", "berachain", "unichain"],
3182
+ description: "Destination chain to bridge to"
3183
+ },
3184
+ amount: {
3185
+ type: "string",
3186
+ pattern: "^\\d+(\\.\\d+)?$",
3187
+ description: "Amount of USDT0 to bridge (e.g., '100' for 100 USDT0)"
3188
+ },
3189
+ recipient: {
3190
+ type: "string",
3191
+ pattern: "^0x[a-fA-F0-9]{40}$",
3192
+ description: "Recipient address on destination chain"
3193
+ },
3194
+ confirmed: {
3195
+ type: "boolean",
3196
+ description: "Set to true to confirm and execute. Omit for a preview/confirmation prompt."
3197
+ }
3198
+ },
3199
+ required: ["fromChain", "toChain", "amount", "recipient"]
3200
+ }
3201
+ },
3202
+ "t402/getTokenPrice": {
3203
+ name: "t402/getTokenPrice",
3204
+ description: "Get current market prices for tokens (ETH, MATIC, AVAX, USDC, etc.) via CoinGecko. Cached for 5 minutes.",
3205
+ inputSchema: {
3206
+ type: "object",
3207
+ properties: {
3208
+ tokens: {
3209
+ type: "array",
3210
+ items: { type: "string" },
3211
+ description: 'Token symbols to get prices for (e.g., ["ETH", "MATIC", "USDC"])'
3212
+ },
3213
+ currency: {
3214
+ type: "string",
3215
+ description: 'Target currency (default: "usd")'
3216
+ }
3217
+ },
3218
+ required: ["tokens"]
3219
+ }
3220
+ },
3221
+ "t402/getGasPrice": {
3222
+ name: "t402/getGasPrice",
3223
+ description: "Get the current gas price on a specific blockchain network. Returns the price in gwei.",
3224
+ inputSchema: {
3225
+ type: "object",
3226
+ properties: {
3227
+ network: {
3228
+ type: "string",
3229
+ enum: [
3230
+ "ethereum",
3231
+ "base",
3232
+ "arbitrum",
3233
+ "optimism",
3234
+ "polygon",
3235
+ "avalanche",
3236
+ "ink",
3237
+ "berachain",
3238
+ "unichain"
3239
+ ],
3240
+ description: "Blockchain network to check gas price on"
3241
+ }
3242
+ },
3243
+ required: ["network"]
3244
+ }
3245
+ },
3246
+ "t402/estimatePaymentFee": {
3247
+ name: "t402/estimatePaymentFee",
3248
+ description: "Estimate the gas cost (in native token and USD) for a stablecoin payment on a specific network.",
3249
+ inputSchema: {
3250
+ type: "object",
3251
+ properties: {
3252
+ network: {
3253
+ type: "string",
3254
+ enum: [
3255
+ "ethereum",
3256
+ "base",
3257
+ "arbitrum",
3258
+ "optimism",
3259
+ "polygon",
3260
+ "avalanche",
3261
+ "ink",
3262
+ "berachain",
3263
+ "unichain"
3264
+ ],
3265
+ description: "Network to estimate fee on"
2182
3266
  },
2183
- memo: {
3267
+ amount: {
2184
3268
  type: "string",
2185
- description: "Optional memo/reference for the payment"
3269
+ pattern: "^\\d+(\\.\\d+)?$",
3270
+ description: "Payment amount (e.g., '100')"
3271
+ },
3272
+ token: {
3273
+ type: "string",
3274
+ enum: ["USDC", "USDT", "USDT0"],
3275
+ description: "Token to use for payment"
2186
3276
  }
2187
3277
  },
2188
- required: ["to", "amount", "token", "network"]
3278
+ required: ["network", "amount", "token"]
2189
3279
  }
2190
3280
  },
2191
- "t402/payGasless": {
2192
- name: "t402/payGasless",
2193
- description: "Execute a gasless stablecoin payment using ERC-4337 account abstraction. Gas fees are sponsored by a paymaster, so no ETH is needed for the transaction. Supported on select networks.",
3281
+ "t402/compareNetworkFees": {
3282
+ name: "t402/compareNetworkFees",
3283
+ description: "Compare payment fees across multiple networks for the same token. Returns a sorted table from cheapest to most expensive.",
2194
3284
  inputSchema: {
2195
3285
  type: "object",
2196
3286
  properties: {
2197
- to: {
2198
- type: "string",
2199
- pattern: "^0x[a-fA-F0-9]{40}$",
2200
- description: "Recipient address"
2201
- },
2202
3287
  amount: {
2203
3288
  type: "string",
2204
3289
  pattern: "^\\d+(\\.\\d+)?$",
2205
- description: "Amount to pay (e.g., '10.50' for 10.50 USDC)"
3290
+ description: "Payment amount (e.g., '100')"
2206
3291
  },
2207
3292
  token: {
2208
3293
  type: "string",
2209
3294
  enum: ["USDC", "USDT", "USDT0"],
2210
3295
  description: "Token to use for payment"
2211
3296
  },
2212
- network: {
2213
- type: "string",
2214
- enum: ["ethereum", "base", "arbitrum", "optimism", "polygon", "avalanche"],
2215
- description: "Network to execute gasless payment on (must support ERC-4337)"
3297
+ networks: {
3298
+ type: "array",
3299
+ items: { type: "string" },
3300
+ description: "Networks to compare. If not provided, compares all networks that support the token."
2216
3301
  }
2217
3302
  },
2218
- required: ["to", "amount", "token", "network"]
3303
+ required: ["amount", "token"]
2219
3304
  }
2220
3305
  },
2221
- "t402/getBridgeFee": {
2222
- name: "t402/getBridgeFee",
2223
- description: "Get the fee quote for bridging USDT0 between chains using LayerZero OFT. Returns the native token fee required and estimated delivery time. Supported chains: ethereum, arbitrum, ink, berachain, unichain.",
3306
+ "t402/quoteBridge": {
3307
+ name: "t402/quoteBridge",
3308
+ 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.",
2224
3309
  inputSchema: {
2225
3310
  type: "object",
2226
3311
  properties: {
@@ -2248,34 +3333,147 @@ var TOOL_DEFINITIONS = {
2248
3333
  required: ["fromChain", "toChain", "amount", "recipient"]
2249
3334
  }
2250
3335
  },
2251
- "t402/bridge": {
2252
- name: "t402/bridge",
2253
- 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.",
3336
+ "t402/executeBridgeQuote": {
3337
+ name: "t402/executeBridgeQuote",
3338
+ description: "Execute a bridge using a quoteId from t402/quoteBridge. Requires confirmation.",
2254
3339
  inputSchema: {
2255
3340
  type: "object",
2256
3341
  properties: {
2257
- fromChain: {
3342
+ quoteId: {
2258
3343
  type: "string",
2259
- enum: ["ethereum", "arbitrum", "ink", "berachain", "unichain"],
2260
- description: "Source chain to bridge from"
3344
+ description: "Quote ID from t402/quoteBridge"
2261
3345
  },
2262
- toChain: {
3346
+ confirmed: {
3347
+ type: "boolean",
3348
+ description: "Set to true to confirm and execute. Omit for a preview/confirmation prompt."
3349
+ }
3350
+ },
3351
+ required: ["quoteId"]
3352
+ }
3353
+ },
3354
+ "t402/signMessage": {
3355
+ name: "t402/signMessage",
3356
+ description: "Sign a message using the configured wallet. Returns an EIP-191 personal signature. Requires a configured private key.",
3357
+ inputSchema: {
3358
+ type: "object",
3359
+ properties: {
3360
+ chain: {
2263
3361
  type: "string",
2264
- enum: ["ethereum", "arbitrum", "ink", "berachain", "unichain"],
2265
- description: "Destination chain to bridge to"
3362
+ enum: [
3363
+ "ethereum",
3364
+ "base",
3365
+ "arbitrum",
3366
+ "optimism",
3367
+ "polygon",
3368
+ "avalanche",
3369
+ "ink",
3370
+ "berachain",
3371
+ "unichain"
3372
+ ],
3373
+ description: "Blockchain network context for signing"
2266
3374
  },
2267
- amount: {
3375
+ message: {
2268
3376
  type: "string",
2269
- pattern: "^\\d+(\\.\\d+)?$",
2270
- description: "Amount of USDT0 to bridge (e.g., '100' for 100 USDT0)"
3377
+ description: "Message to sign"
3378
+ }
3379
+ },
3380
+ required: ["chain", "message"]
3381
+ }
3382
+ },
3383
+ "t402/verifySignature": {
3384
+ name: "t402/verifySignature",
3385
+ description: "Verify an EIP-191 signed message. Checks whether a signature was produced by the claimed address. No wallet configuration needed \u2014 this is a read-only verification.",
3386
+ inputSchema: {
3387
+ type: "object",
3388
+ properties: {
3389
+ chain: {
3390
+ type: "string",
3391
+ enum: [
3392
+ "ethereum",
3393
+ "base",
3394
+ "arbitrum",
3395
+ "optimism",
3396
+ "polygon",
3397
+ "avalanche",
3398
+ "ink",
3399
+ "berachain",
3400
+ "unichain"
3401
+ ],
3402
+ description: "Blockchain network context for verification"
2271
3403
  },
2272
- recipient: {
3404
+ message: {
3405
+ type: "string",
3406
+ description: "The original message that was signed"
3407
+ },
3408
+ signature: {
3409
+ type: "string",
3410
+ pattern: "^0x[a-fA-F0-9]+$",
3411
+ description: "The signature to verify (hex string)"
3412
+ },
3413
+ address: {
2273
3414
  type: "string",
2274
3415
  pattern: "^0x[a-fA-F0-9]{40}$",
2275
- description: "Recipient address on destination chain"
3416
+ description: "The expected signer address"
2276
3417
  }
2277
3418
  },
2278
- required: ["fromChain", "toChain", "amount", "recipient"]
3419
+ required: ["chain", "message", "signature", "address"]
3420
+ }
3421
+ },
3422
+ "t402/getTransferHistory": {
3423
+ name: "t402/getTransferHistory",
3424
+ description: "Get recent ERC-20 stablecoin transfer history for a wallet address. Queries on-chain Transfer events for USDC, USDT, and USDT0. Returns sent and received transfers sorted by most recent.",
3425
+ inputSchema: {
3426
+ type: "object",
3427
+ properties: {
3428
+ network: {
3429
+ type: "string",
3430
+ enum: [
3431
+ "ethereum",
3432
+ "base",
3433
+ "arbitrum",
3434
+ "optimism",
3435
+ "polygon",
3436
+ "avalanche",
3437
+ "ink",
3438
+ "berachain",
3439
+ "unichain"
3440
+ ],
3441
+ description: "Blockchain network to query"
3442
+ },
3443
+ address: {
3444
+ type: "string",
3445
+ pattern: "^0x[a-fA-F0-9]{40}$",
3446
+ description: "Wallet address to get transfer history for"
3447
+ },
3448
+ token: {
3449
+ type: "string",
3450
+ enum: ["USDC", "USDT", "USDT0"],
3451
+ description: "Filter by specific token. If not provided, queries all supported stablecoins."
3452
+ },
3453
+ limit: {
3454
+ type: "number",
3455
+ description: "Maximum number of transfers to return (default: 10, max: 100)"
3456
+ }
3457
+ },
3458
+ required: ["network", "address"]
3459
+ }
3460
+ },
3461
+ "t402/getHistoricalPrice": {
3462
+ name: "t402/getHistoricalPrice",
3463
+ description: "Get historical price data for a token over a specified period via CoinGecko. Returns price data points, high/low, and percentage change. Useful for trend analysis.",
3464
+ inputSchema: {
3465
+ type: "object",
3466
+ properties: {
3467
+ token: {
3468
+ type: "string",
3469
+ description: 'Token symbol (e.g., "ETH", "USDC", "USDT", "MATIC", "AVAX", "BTC", "SOL")'
3470
+ },
3471
+ days: {
3472
+ type: "number",
3473
+ description: "Number of days of history to retrieve (default: 7, max: 365)"
3474
+ }
3475
+ },
3476
+ required: ["token"]
2279
3477
  }
2280
3478
  }
2281
3479
  };
@@ -2327,6 +3525,10 @@ var WDK_TOOL_DEFINITIONS = {
2327
3525
  chain: {
2328
3526
  type: "string",
2329
3527
  description: 'Chain to execute transfer on (e.g., "ethereum", "arbitrum")'
3528
+ },
3529
+ confirmed: {
3530
+ type: "boolean",
3531
+ description: "Set to true to confirm and execute. Omit for a preview/confirmation prompt."
2330
3532
  }
2331
3533
  },
2332
3534
  required: ["to", "amount", "token", "chain"]
@@ -2354,6 +3556,10 @@ var WDK_TOOL_DEFINITIONS = {
2354
3556
  chain: {
2355
3557
  type: "string",
2356
3558
  description: 'Chain to execute swap on (e.g., "ethereum", "arbitrum")'
3559
+ },
3560
+ confirmed: {
3561
+ type: "boolean",
3562
+ description: "Set to true to confirm and execute. Omit for a preview/confirmation prompt."
2357
3563
  }
2358
3564
  },
2359
3565
  required: ["fromToken", "toToken", "amount", "chain"]
@@ -2377,10 +3583,59 @@ var WDK_TOOL_DEFINITIONS = {
2377
3583
  preferredChain: {
2378
3584
  type: "string",
2379
3585
  description: 'Preferred chain for payment (e.g., "arbitrum"). If not specified, uses first available.'
3586
+ },
3587
+ confirmed: {
3588
+ type: "boolean",
3589
+ description: "Set to true to confirm and execute. Omit for a preview/confirmation prompt."
2380
3590
  }
2381
3591
  },
2382
3592
  required: ["url"]
2383
3593
  }
3594
+ },
3595
+ "wdk/quoteSwap": {
3596
+ name: "wdk/quoteSwap",
3597
+ 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.",
3598
+ inputSchema: {
3599
+ type: "object",
3600
+ properties: {
3601
+ fromToken: {
3602
+ type: "string",
3603
+ description: 'Token to swap from (e.g., "ETH", "USDC")'
3604
+ },
3605
+ toToken: {
3606
+ type: "string",
3607
+ description: 'Token to swap to (e.g., "USDT0", "USDC")'
3608
+ },
3609
+ amount: {
3610
+ type: "string",
3611
+ pattern: "^\\d+(\\.\\d+)?$",
3612
+ description: "Amount to swap (e.g., '1.0')"
3613
+ },
3614
+ chain: {
3615
+ type: "string",
3616
+ description: 'Chain to execute swap on (e.g., "ethereum", "arbitrum")'
3617
+ }
3618
+ },
3619
+ required: ["fromToken", "toToken", "amount", "chain"]
3620
+ }
3621
+ },
3622
+ "wdk/executeSwap": {
3623
+ name: "wdk/executeSwap",
3624
+ description: "Execute a swap using a quoteId from wdk/quoteSwap. Requires confirmation.",
3625
+ inputSchema: {
3626
+ type: "object",
3627
+ properties: {
3628
+ quoteId: {
3629
+ type: "string",
3630
+ description: "Quote ID from wdk/quoteSwap"
3631
+ },
3632
+ confirmed: {
3633
+ type: "boolean",
3634
+ description: "Set to true to confirm and execute. Omit for a preview/confirmation prompt."
3635
+ }
3636
+ },
3637
+ required: ["quoteId"]
3638
+ }
2384
3639
  }
2385
3640
  };
2386
3641
  var ERC8004_TOOL_DEFINITIONS = {
@@ -2499,6 +3754,19 @@ var T402McpServer = class {
2499
3754
  console.error("Warning: Failed to initialize WDK. WDK tools will not be available.");
2500
3755
  }
2501
3756
  }
3757
+ /**
3758
+ * Clear sensitive data from memory.
3759
+ * Should be called on server shutdown to minimize key exposure window.
3760
+ */
3761
+ cleanup() {
3762
+ if (this.config.privateKey) {
3763
+ this.config.privateKey = "";
3764
+ }
3765
+ if (this.config.seedPhrase) {
3766
+ this.config.seedPhrase = "";
3767
+ }
3768
+ this.wdk = null;
3769
+ }
2502
3770
  /**
2503
3771
  * Register TON bridge tools
2504
3772
  *
@@ -2564,6 +3832,24 @@ var T402McpServer = class {
2564
3832
  return await this.handleSmartPay(args);
2565
3833
  case "t402/paymentPlan":
2566
3834
  return await this.handlePaymentPlan(args);
3835
+ // Price and fee tools
3836
+ case "t402/getTokenPrice":
3837
+ return await this.handleGetTokenPrice(args);
3838
+ case "t402/getGasPrice":
3839
+ return await this.handleGetGasPrice(args);
3840
+ case "t402/estimatePaymentFee":
3841
+ return await this.handleEstimatePaymentFee(args);
3842
+ case "t402/compareNetworkFees":
3843
+ return await this.handleCompareNetworkFees(args);
3844
+ // Quote-based tools
3845
+ case "t402/quoteBridge":
3846
+ return await this.handleQuoteBridge(args);
3847
+ case "t402/executeBridgeQuote":
3848
+ return await this.handleExecuteBridgeQuote(args);
3849
+ case "wdk/quoteSwap":
3850
+ return await this.handleWdkQuoteSwap(args);
3851
+ case "wdk/executeSwap":
3852
+ return await this.handleWdkExecuteSwap(args);
2567
3853
  // ERC-8004 tools
2568
3854
  case "erc8004/resolveAgent":
2569
3855
  return await this.handleErc8004ResolveAgent(args);
@@ -2625,6 +3911,28 @@ var T402McpServer = class {
2625
3911
  ]
2626
3912
  };
2627
3913
  }
3914
+ /**
3915
+ * Format a confirmation prompt for elicitation
3916
+ */
3917
+ formatConfirmation(result) {
3918
+ const detailLines = Object.entries(result.details).map(([key, value]) => `- **${key}:** ${value}`).join("\n");
3919
+ return {
3920
+ content: [
3921
+ {
3922
+ type: "text",
3923
+ text: [
3924
+ "## Confirmation Required",
3925
+ "",
3926
+ result.summary,
3927
+ "",
3928
+ detailLines,
3929
+ "",
3930
+ "_Call this tool again with `confirmed: true` to execute._"
3931
+ ].join("\n")
3932
+ }
3933
+ ]
3934
+ };
3935
+ }
2628
3936
  /**
2629
3937
  * Handle t402/pay
2630
3938
  */
@@ -2640,6 +3948,9 @@ var T402McpServer = class {
2640
3948
  rpcUrl: this.config.rpcUrls?.[input.network],
2641
3949
  demoMode: this.config.demoMode
2642
3950
  });
3951
+ if ("needsConfirmation" in result) {
3952
+ return this.formatConfirmation(result);
3953
+ }
2643
3954
  return {
2644
3955
  content: [
2645
3956
  {
@@ -2676,6 +3987,9 @@ var T402McpServer = class {
2676
3987
  rpcUrl: this.config.rpcUrls?.[input.network],
2677
3988
  demoMode: this.config.demoMode
2678
3989
  });
3990
+ if ("needsConfirmation" in result) {
3991
+ return this.formatConfirmation(result);
3992
+ }
2679
3993
  return {
2680
3994
  content: [
2681
3995
  {
@@ -2715,6 +4029,9 @@ var T402McpServer = class {
2715
4029
  rpcUrl: this.config.rpcUrls?.[input.fromChain],
2716
4030
  demoMode: this.config.demoMode
2717
4031
  });
4032
+ if ("needsConfirmation" in result) {
4033
+ return this.formatConfirmation(result);
4034
+ }
2718
4035
  return {
2719
4036
  content: [
2720
4037
  {
@@ -2751,6 +4068,9 @@ var T402McpServer = class {
2751
4068
  async handleWdkTransfer(args) {
2752
4069
  const input = wdkTransferInputSchema.parse(args);
2753
4070
  const result = this.config.demoMode || !this.wdk ? executeWdkTransferDemo(input) : await executeWdkTransfer(input, this.wdk);
4071
+ if ("needsConfirmation" in result) {
4072
+ return this.formatConfirmation(result);
4073
+ }
2754
4074
  return {
2755
4075
  content: [{ type: "text", text: formatWdkTransferResult(result) }]
2756
4076
  };
@@ -2761,6 +4081,9 @@ var T402McpServer = class {
2761
4081
  async handleWdkSwap(args) {
2762
4082
  const input = wdkSwapInputSchema.parse(args);
2763
4083
  const result = this.config.demoMode || !this.wdk ? executeWdkSwapDemo(input) : await executeWdkSwap(input, this.wdk);
4084
+ if ("needsConfirmation" in result) {
4085
+ return this.formatConfirmation(result);
4086
+ }
2764
4087
  return {
2765
4088
  content: [{ type: "text", text: formatWdkSwapResult(result) }]
2766
4089
  };
@@ -2771,6 +4094,9 @@ var T402McpServer = class {
2771
4094
  async handleAutoPay(args) {
2772
4095
  const input = autoPayInputSchema.parse(args);
2773
4096
  const result = this.config.demoMode || !this.wdk ? executeAutoPayDemo(input) : await executeAutoPay(input, this.wdk);
4097
+ if ("needsConfirmation" in result) {
4098
+ return this.formatConfirmation(result);
4099
+ }
2774
4100
  return {
2775
4101
  content: [{ type: "text", text: formatAutoPayResult(result) }]
2776
4102
  };
@@ -2782,6 +4108,9 @@ var T402McpServer = class {
2782
4108
  async handleSmartPay(args) {
2783
4109
  const input = smartPayInputSchema.parse(args);
2784
4110
  const result = this.config.demoMode || !this.wdk ? executeSmartPayDemo(input) : await executeSmartPay(input, this.wdk);
4111
+ if ("needsConfirmation" in result) {
4112
+ return this.formatConfirmation(result);
4113
+ }
2785
4114
  return {
2786
4115
  content: [{ type: "text", text: formatSmartPayResult(result) }]
2787
4116
  };
@@ -2796,6 +4125,111 @@ var T402McpServer = class {
2796
4125
  content: [{ type: "text", text: formatPaymentPlanResult(result) }]
2797
4126
  };
2798
4127
  }
4128
+ // ---- Price and Fee Tool Handlers ----
4129
+ /**
4130
+ * Handle t402/getTokenPrice
4131
+ */
4132
+ async handleGetTokenPrice(args) {
4133
+ const input = getTokenPriceInputSchema.parse(args);
4134
+ const result = await executeGetTokenPrice(input, { demoMode: this.config.demoMode });
4135
+ return {
4136
+ content: [{ type: "text", text: formatTokenPriceResult(result) }]
4137
+ };
4138
+ }
4139
+ /**
4140
+ * Handle t402/getGasPrice
4141
+ */
4142
+ async handleGetGasPrice(args) {
4143
+ const input = getGasPriceInputSchema.parse(args);
4144
+ const result = await executeGetGasPrice(input, {
4145
+ rpcUrl: this.config.rpcUrls?.[input.network],
4146
+ demoMode: this.config.demoMode
4147
+ });
4148
+ return {
4149
+ content: [{ type: "text", text: formatGasPriceResult(result) }]
4150
+ };
4151
+ }
4152
+ /**
4153
+ * Handle t402/estimatePaymentFee
4154
+ */
4155
+ async handleEstimatePaymentFee(args) {
4156
+ const input = estimatePaymentFeeInputSchema.parse(args);
4157
+ const result = await executeEstimatePaymentFee(input, {
4158
+ rpcUrl: this.config.rpcUrls?.[input.network],
4159
+ demoMode: this.config.demoMode
4160
+ });
4161
+ return {
4162
+ content: [{ type: "text", text: formatPaymentFeeEstimate(result) }]
4163
+ };
4164
+ }
4165
+ /**
4166
+ * Handle t402/compareNetworkFees
4167
+ */
4168
+ async handleCompareNetworkFees(args) {
4169
+ const input = compareNetworkFeesInputSchema.parse(args);
4170
+ const result = await executeCompareNetworkFees(input, {
4171
+ rpcUrls: this.config.rpcUrls,
4172
+ demoMode: this.config.demoMode
4173
+ });
4174
+ return {
4175
+ content: [{ type: "text", text: formatNetworkFeeComparison(result) }]
4176
+ };
4177
+ }
4178
+ // ---- Quote-based Tool Handlers ----
4179
+ /**
4180
+ * Handle t402/quoteBridge
4181
+ */
4182
+ async handleQuoteBridge(args) {
4183
+ const input = quoteBridgeInputSchema.parse(args);
4184
+ const result = this.config.demoMode ? executeQuoteBridgeDemo(input) : await executeQuoteBridge(input, this.config.rpcUrls);
4185
+ return {
4186
+ content: [{ type: "text", text: formatBridgeQuoteResult(result) }]
4187
+ };
4188
+ }
4189
+ /**
4190
+ * Handle t402/executeBridgeQuote
4191
+ */
4192
+ async handleExecuteBridgeQuote(args) {
4193
+ if (!this.config.privateKey && !this.config.demoMode) {
4194
+ throw new Error(
4195
+ "Private key not configured. Set T402_PRIVATE_KEY environment variable or enable demo mode."
4196
+ );
4197
+ }
4198
+ const input = executeBridgeFromQuoteInputSchema.parse(args);
4199
+ const result = this.config.demoMode ? executeExecuteBridgeFromQuoteDemo(input) : await executeExecuteBridgeFromQuote(input, {
4200
+ privateKey: this.config.privateKey || "0x",
4201
+ demoMode: this.config.demoMode
4202
+ });
4203
+ if ("needsConfirmation" in result) {
4204
+ return this.formatConfirmation(result);
4205
+ }
4206
+ return {
4207
+ content: [{ type: "text", text: formatBridgeResult(result) }]
4208
+ };
4209
+ }
4210
+ /**
4211
+ * Handle wdk/quoteSwap
4212
+ */
4213
+ async handleWdkQuoteSwap(args) {
4214
+ const input = wdkQuoteSwapInputSchema.parse(args);
4215
+ const result = this.config.demoMode || !this.wdk ? executeWdkQuoteSwapDemo(input) : await executeWdkQuoteSwap(input, this.wdk);
4216
+ return {
4217
+ content: [{ type: "text", text: formatSwapQuoteResult(result) }]
4218
+ };
4219
+ }
4220
+ /**
4221
+ * Handle wdk/executeSwap
4222
+ */
4223
+ async handleWdkExecuteSwap(args) {
4224
+ const input = wdkExecuteSwapInputSchema.parse(args);
4225
+ const result = this.config.demoMode || !this.wdk ? executeWdkExecuteSwapDemo(input) : await executeWdkExecuteSwap(input, this.wdk);
4226
+ if ("needsConfirmation" in result) {
4227
+ return this.formatConfirmation(result);
4228
+ }
4229
+ return {
4230
+ content: [{ type: "text", text: formatExecuteSwapResult(result) }]
4231
+ };
4232
+ }
2799
4233
  // ---- ERC-8004 Tool Handlers ----
2800
4234
  /**
2801
4235
  * Handle erc8004/resolveAgent
@@ -2842,6 +4276,16 @@ var T402McpServer = class {
2842
4276
  */
2843
4277
  async run() {
2844
4278
  await this.initWdk();
4279
+ const onExit = () => this.cleanup();
4280
+ process.on("exit", onExit);
4281
+ process.on("SIGINT", () => {
4282
+ onExit();
4283
+ process.exit(0);
4284
+ });
4285
+ process.on("SIGTERM", () => {
4286
+ onExit();
4287
+ process.exit(0);
4288
+ });
2845
4289
  const transport = new import_stdio.StdioServerTransport();
2846
4290
  await this.server.connect(transport);
2847
4291
  console.error("t402 MCP Server running on stdio");