@t402/mcp 2.7.1 → 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 +1401 -185
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/server/index.d.ts +36 -0
- package/dist/cjs/server/index.js +1401 -185
- package/dist/cjs/server/index.js.map +1 -1
- package/dist/cjs/tools/index.d.ts +689 -12
- package/dist/cjs/tools/index.js +1155 -29
- package/dist/cjs/tools/index.js.map +1 -1
- package/dist/esm/{chunk-B7X7H6NV.mjs → chunk-SUDCVXHQ.mjs} +1120 -30
- package/dist/esm/chunk-SUDCVXHQ.mjs.map +1 -0
- package/dist/esm/{chunk-3PMBXSJ3.mjs → chunk-XOPD7VTU.mjs} +195 -2
- package/dist/esm/chunk-XOPD7VTU.mjs.map +1 -0
- package/dist/esm/index.mjs +2 -2
- package/dist/esm/server/index.d.mts +36 -0
- package/dist/esm/server/index.mjs +2 -2
- package/dist/esm/tools/index.d.mts +689 -12
- package/dist/esm/tools/index.mjs +70 -1
- package/package.json +14 -14
- package/dist/esm/chunk-3PMBXSJ3.mjs.map +0 -1
- package/dist/esm/chunk-B7X7H6NV.mjs.map +0 -1
package/dist/cjs/server/index.js
CHANGED
|
@@ -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
|
|
1183
|
+
const chains9 = wdk.getConfiguredChains();
|
|
1160
1184
|
return {
|
|
1161
1185
|
evmAddress: signer.address,
|
|
1162
|
-
chains:
|
|
1186
|
+
chains: chains9.length > 0 ? chains9 : ["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
|
|
1218
|
+
const chains9 = 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:
|
|
1225
|
+
chains: chains9,
|
|
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,12 +1407,24 @@ 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
|
-
|
|
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 chains9 = input.preferredChain ? [input.preferredChain] : ["ethereum", "arbitrum", "base"];
|
|
1350
1426
|
const { T402Protocol } = await import("@t402/wdk-protocol");
|
|
1351
|
-
const protocol = await T402Protocol.create(wdk, { chains:
|
|
1427
|
+
const protocol = await T402Protocol.create(wdk, { chains: chains9 });
|
|
1352
1428
|
const { response, receipt } = await protocol.fetch(input.url);
|
|
1353
1429
|
if (receipt && input.maxAmount) {
|
|
1354
1430
|
const paidAmount = parseFloat(receipt.amount) / 1e6;
|
|
@@ -1386,6 +1462,17 @@ async function executeAutoPay(input, wdk) {
|
|
|
1386
1462
|
};
|
|
1387
1463
|
}
|
|
1388
1464
|
function executeAutoPayDemo(input) {
|
|
1465
|
+
if (!input.confirmed) {
|
|
1466
|
+
return {
|
|
1467
|
+
needsConfirmation: true,
|
|
1468
|
+
summary: `Auto-pay for ${input.url}${input.maxAmount ? ` (max ${input.maxAmount})` : ""}`,
|
|
1469
|
+
details: {
|
|
1470
|
+
url: input.url,
|
|
1471
|
+
...input.maxAmount ? { maxAmount: input.maxAmount } : {},
|
|
1472
|
+
...input.preferredChain ? { preferredChain: input.preferredChain } : {}
|
|
1473
|
+
}
|
|
1474
|
+
};
|
|
1475
|
+
}
|
|
1389
1476
|
return {
|
|
1390
1477
|
success: true,
|
|
1391
1478
|
statusCode: 200,
|
|
@@ -1829,197 +1916,939 @@ function formatErc8004VerifyWalletResult(result) {
|
|
|
1829
1916
|
return lines.join("\n");
|
|
1830
1917
|
}
|
|
1831
1918
|
|
|
1832
|
-
// src/tools/
|
|
1833
|
-
var
|
|
1834
|
-
var
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
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"]
|
|
1882
|
-
}
|
|
1883
|
-
}
|
|
1919
|
+
// src/tools/priceService.ts
|
|
1920
|
+
var CACHE_TTL_MS = 5 * 60 * 1e3;
|
|
1921
|
+
var COINGECKO_API = "https://api.coingecko.com/api/v3/simple/price";
|
|
1922
|
+
var TOKEN_TO_COINGECKO_ID = {
|
|
1923
|
+
ETH: "ethereum",
|
|
1924
|
+
MATIC: "matic-network",
|
|
1925
|
+
AVAX: "avalanche-2",
|
|
1926
|
+
BERA: "berachain-bera",
|
|
1927
|
+
USDC: "usd-coin",
|
|
1928
|
+
USDT: "tether",
|
|
1929
|
+
USDT0: "tether"
|
|
1884
1930
|
};
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
const
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
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
|
-
});
|
|
1931
|
+
var cache = /* @__PURE__ */ new Map();
|
|
1932
|
+
async function getTokenPrices(tokens, currency = "usd") {
|
|
1933
|
+
const cacheKey = `${currency}:${tokens.sort().join(",")}`;
|
|
1934
|
+
const cached = cache.get(cacheKey);
|
|
1935
|
+
if (cached && Date.now() - cached.timestamp < CACHE_TTL_MS) {
|
|
1936
|
+
return cached.prices;
|
|
1907
1937
|
}
|
|
1908
|
-
const
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
}
|
|
1915
|
-
} catch {
|
|
1916
|
-
body = "[Could not read response body]";
|
|
1938
|
+
const coinIds = /* @__PURE__ */ new Set();
|
|
1939
|
+
const tokenToCoinId = /* @__PURE__ */ new Map();
|
|
1940
|
+
for (const token of tokens) {
|
|
1941
|
+
const coinId = TOKEN_TO_COINGECKO_ID[token.toUpperCase()] ?? token.toLowerCase();
|
|
1942
|
+
coinIds.add(coinId);
|
|
1943
|
+
tokenToCoinId.set(token.toUpperCase(), coinId);
|
|
1917
1944
|
}
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1945
|
+
const url = `${COINGECKO_API}?ids=${[...coinIds].join(",")}&vs_currencies=${currency}`;
|
|
1946
|
+
const response = await fetch(url);
|
|
1947
|
+
if (!response.ok) {
|
|
1948
|
+
throw new Error(`CoinGecko API error: ${response.status} ${response.statusText}`);
|
|
1949
|
+
}
|
|
1950
|
+
const data = await response.json();
|
|
1951
|
+
const prices = {};
|
|
1952
|
+
for (const token of tokens) {
|
|
1953
|
+
const coinId = tokenToCoinId.get(token.toUpperCase()) ?? token.toLowerCase();
|
|
1954
|
+
prices[token.toUpperCase()] = data[coinId]?.[currency] ?? 0;
|
|
1955
|
+
}
|
|
1956
|
+
cache.set(cacheKey, { prices, timestamp: Date.now() });
|
|
1957
|
+
return prices;
|
|
1958
|
+
}
|
|
1959
|
+
function getTokenPricesDemo(tokens) {
|
|
1960
|
+
const demoPrices = {
|
|
1961
|
+
ETH: 3250.42,
|
|
1962
|
+
MATIC: 0.58,
|
|
1963
|
+
AVAX: 24.15,
|
|
1964
|
+
BERA: 3.82,
|
|
1965
|
+
USDC: 1,
|
|
1966
|
+
USDT: 1,
|
|
1967
|
+
USDT0: 1
|
|
1930
1968
|
};
|
|
1969
|
+
const prices = {};
|
|
1970
|
+
for (const token of tokens) {
|
|
1971
|
+
prices[token.toUpperCase()] = demoPrices[token.toUpperCase()] ?? 0;
|
|
1972
|
+
}
|
|
1973
|
+
return prices;
|
|
1931
1974
|
}
|
|
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}
|
|
1938
1975
|
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1976
|
+
// src/tools/getTokenPrice.ts
|
|
1977
|
+
var import_zod15 = require("zod");
|
|
1978
|
+
var getTokenPriceInputSchema = import_zod15.z.object({
|
|
1979
|
+
tokens: import_zod15.z.array(import_zod15.z.string()).min(1).describe('Token symbols to get prices for (e.g., ["ETH", "MATIC", "USDC"])'),
|
|
1980
|
+
currency: import_zod15.z.string().optional().describe('Target currency (default: "usd"). Supports: usd, eur, gbp, etc.')
|
|
1981
|
+
});
|
|
1982
|
+
async function executeGetTokenPrice(input, options) {
|
|
1983
|
+
const currency = input.currency ?? "usd";
|
|
1984
|
+
const prices = options.demoMode ? getTokenPricesDemo(input.tokens) : await getTokenPrices(input.tokens, currency);
|
|
1985
|
+
return { prices, currency };
|
|
1986
|
+
}
|
|
1987
|
+
function formatTokenPriceResult(result) {
|
|
1988
|
+
const lines = ["## Token Prices", ""];
|
|
1989
|
+
const currencyUpper = result.currency.toUpperCase();
|
|
1990
|
+
for (const [token, price] of Object.entries(result.prices)) {
|
|
1991
|
+
if (price > 0) {
|
|
1992
|
+
lines.push(`- **${token}:** ${price.toLocaleString()} ${currencyUpper}`);
|
|
1993
|
+
} else {
|
|
1994
|
+
lines.push(`- **${token}:** Price unavailable`);
|
|
1952
1995
|
}
|
|
1953
|
-
}
|
|
1996
|
+
}
|
|
1997
|
+
return lines.join("\n");
|
|
1954
1998
|
}
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1999
|
+
|
|
2000
|
+
// src/tools/getGasPrice.ts
|
|
2001
|
+
var import_zod16 = require("zod");
|
|
2002
|
+
var import_viem9 = require("viem");
|
|
2003
|
+
var chains7 = __toESM(require("viem/chains"));
|
|
2004
|
+
var getGasPriceInputSchema = import_zod16.z.object({
|
|
2005
|
+
network: import_zod16.z.enum([
|
|
2006
|
+
"ethereum",
|
|
2007
|
+
"base",
|
|
2008
|
+
"arbitrum",
|
|
2009
|
+
"optimism",
|
|
2010
|
+
"polygon",
|
|
2011
|
+
"avalanche",
|
|
2012
|
+
"ink",
|
|
2013
|
+
"berachain",
|
|
2014
|
+
"unichain"
|
|
2015
|
+
]).describe("Blockchain network to check gas price on")
|
|
2016
|
+
});
|
|
2017
|
+
function getViemChain6(network) {
|
|
2018
|
+
switch (network) {
|
|
2019
|
+
case "ethereum":
|
|
2020
|
+
return chains7.mainnet;
|
|
2021
|
+
case "base":
|
|
2022
|
+
return chains7.base;
|
|
2023
|
+
case "arbitrum":
|
|
2024
|
+
return chains7.arbitrum;
|
|
2025
|
+
case "optimism":
|
|
2026
|
+
return chains7.optimism;
|
|
2027
|
+
case "polygon":
|
|
2028
|
+
return chains7.polygon;
|
|
2029
|
+
case "avalanche":
|
|
2030
|
+
return chains7.avalanche;
|
|
2031
|
+
case "ink":
|
|
2032
|
+
return chains7.ink;
|
|
2033
|
+
case "berachain":
|
|
2034
|
+
return chains7.berachain;
|
|
2035
|
+
case "unichain":
|
|
2036
|
+
return chains7.unichain;
|
|
2037
|
+
default:
|
|
2038
|
+
return chains7.mainnet;
|
|
2039
|
+
}
|
|
2040
|
+
}
|
|
2041
|
+
async function executeGetGasPrice(input, options) {
|
|
2042
|
+
const { network } = input;
|
|
2043
|
+
if (options.demoMode) {
|
|
2044
|
+
const demoGasPrices = {
|
|
2045
|
+
ethereum: 25000000000n,
|
|
2046
|
+
// 25 gwei
|
|
2047
|
+
base: 50000000n,
|
|
2048
|
+
// 0.05 gwei
|
|
2049
|
+
arbitrum: 100000000n,
|
|
2050
|
+
// 0.1 gwei
|
|
2051
|
+
optimism: 50000000n,
|
|
2052
|
+
// 0.05 gwei
|
|
2053
|
+
polygon: 30000000000n,
|
|
2054
|
+
// 30 gwei
|
|
2055
|
+
avalanche: 25000000000n,
|
|
2056
|
+
// 25 nAVAX
|
|
2057
|
+
ink: 50000000n,
|
|
2058
|
+
// 0.05 gwei
|
|
2059
|
+
berachain: 1000000000n,
|
|
2060
|
+
// 1 gwei
|
|
2061
|
+
unichain: 50000000n
|
|
2062
|
+
// 0.05 gwei
|
|
1966
2063
|
};
|
|
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;
|
|
2064
|
+
const gasPrice2 = demoGasPrices[network] ?? 1000000000n;
|
|
1972
2065
|
return {
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
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
|
|
2066
|
+
network,
|
|
2067
|
+
gasPriceWei: gasPrice2.toString(),
|
|
2068
|
+
gasPriceGwei: (0, import_viem9.formatGwei)(gasPrice2),
|
|
2069
|
+
nativeSymbol: NATIVE_SYMBOLS[network]
|
|
1984
2070
|
};
|
|
1985
2071
|
}
|
|
2072
|
+
const chain = getViemChain6(network);
|
|
2073
|
+
const transport = (0, import_viem9.http)(options.rpcUrl ?? DEFAULT_RPC_URLS[network]);
|
|
2074
|
+
const client = (0, import_viem9.createPublicClient)({ chain, transport });
|
|
2075
|
+
const gasPrice = await client.getGasPrice();
|
|
1986
2076
|
return {
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
2077
|
+
network,
|
|
2078
|
+
gasPriceWei: gasPrice.toString(),
|
|
2079
|
+
gasPriceGwei: (0, import_viem9.formatGwei)(gasPrice),
|
|
2080
|
+
nativeSymbol: NATIVE_SYMBOLS[network]
|
|
1991
2081
|
};
|
|
1992
2082
|
}
|
|
1993
|
-
function
|
|
1994
|
-
return
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
{ chain: "arbitrum", usdt0: "500.00", usdc: "0" },
|
|
2002
|
-
{ chain: "base", usdt0: "50.00", usdc: "100.00" }
|
|
2003
|
-
]
|
|
2004
|
-
};
|
|
2083
|
+
function formatGasPriceResult(result) {
|
|
2084
|
+
return [
|
|
2085
|
+
"## Gas Price",
|
|
2086
|
+
"",
|
|
2087
|
+
`- **Network:** ${result.network}`,
|
|
2088
|
+
`- **Gas Price:** ${result.gasPriceGwei} gwei`,
|
|
2089
|
+
`- **Native Token:** ${result.nativeSymbol}`
|
|
2090
|
+
].join("\n");
|
|
2005
2091
|
}
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2092
|
+
|
|
2093
|
+
// src/tools/estimatePaymentFee.ts
|
|
2094
|
+
var import_zod17 = require("zod");
|
|
2095
|
+
var import_viem10 = require("viem");
|
|
2096
|
+
var chains8 = __toESM(require("viem/chains"));
|
|
2097
|
+
var estimatePaymentFeeInputSchema = import_zod17.z.object({
|
|
2098
|
+
network: import_zod17.z.enum([
|
|
2099
|
+
"ethereum",
|
|
2100
|
+
"base",
|
|
2101
|
+
"arbitrum",
|
|
2102
|
+
"optimism",
|
|
2103
|
+
"polygon",
|
|
2104
|
+
"avalanche",
|
|
2105
|
+
"ink",
|
|
2106
|
+
"berachain",
|
|
2107
|
+
"unichain"
|
|
2108
|
+
]).describe("Network to estimate fee on"),
|
|
2109
|
+
amount: import_zod17.z.string().regex(/^\d+(\.\d+)?$/).describe("Payment amount (e.g., '100')"),
|
|
2110
|
+
token: import_zod17.z.enum(["USDC", "USDT", "USDT0"]).describe("Token to use for payment")
|
|
2111
|
+
});
|
|
2112
|
+
function getViemChain7(network) {
|
|
2113
|
+
switch (network) {
|
|
2114
|
+
case "ethereum":
|
|
2115
|
+
return chains8.mainnet;
|
|
2116
|
+
case "base":
|
|
2117
|
+
return chains8.base;
|
|
2118
|
+
case "arbitrum":
|
|
2119
|
+
return chains8.arbitrum;
|
|
2120
|
+
case "optimism":
|
|
2121
|
+
return chains8.optimism;
|
|
2122
|
+
case "polygon":
|
|
2123
|
+
return chains8.polygon;
|
|
2124
|
+
case "avalanche":
|
|
2125
|
+
return chains8.avalanche;
|
|
2126
|
+
case "ink":
|
|
2127
|
+
return chains8.ink;
|
|
2128
|
+
case "berachain":
|
|
2129
|
+
return chains8.berachain;
|
|
2130
|
+
case "unichain":
|
|
2131
|
+
return chains8.unichain;
|
|
2132
|
+
default:
|
|
2133
|
+
return chains8.mainnet;
|
|
2012
2134
|
}
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2135
|
+
}
|
|
2136
|
+
async function executeEstimatePaymentFee(input, options) {
|
|
2137
|
+
const { network, amount, token } = input;
|
|
2138
|
+
const nativeSymbol = NATIVE_SYMBOLS[network];
|
|
2139
|
+
if (options.demoMode) {
|
|
2140
|
+
const demoEstimates = {
|
|
2141
|
+
ethereum: { gasLimit: 65000n, gasPrice: 25000000000n, nativePrice: 3250.42 },
|
|
2142
|
+
base: { gasLimit: 65000n, gasPrice: 50000000n, nativePrice: 3250.42 },
|
|
2143
|
+
arbitrum: { gasLimit: 65000n, gasPrice: 100000000n, nativePrice: 3250.42 },
|
|
2144
|
+
optimism: { gasLimit: 65000n, gasPrice: 50000000n, nativePrice: 3250.42 },
|
|
2145
|
+
polygon: { gasLimit: 65000n, gasPrice: 30000000000n, nativePrice: 0.58 },
|
|
2146
|
+
avalanche: { gasLimit: 65000n, gasPrice: 25000000000n, nativePrice: 24.15 },
|
|
2147
|
+
ink: { gasLimit: 65000n, gasPrice: 50000000n, nativePrice: 3250.42 },
|
|
2148
|
+
berachain: { gasLimit: 65000n, gasPrice: 1000000000n, nativePrice: 3.82 },
|
|
2149
|
+
unichain: { gasLimit: 65000n, gasPrice: 50000000n, nativePrice: 3250.42 }
|
|
2150
|
+
};
|
|
2151
|
+
const est = demoEstimates[network] ?? demoEstimates["ethereum"];
|
|
2152
|
+
const nativeCost2 = est.gasLimit * est.gasPrice;
|
|
2153
|
+
const usdCost2 = Number(nativeCost2) / 1e18 * est.nativePrice;
|
|
2154
|
+
return {
|
|
2155
|
+
network,
|
|
2156
|
+
gasLimit: est.gasLimit.toString(),
|
|
2157
|
+
gasPriceGwei: (0, import_viem10.formatGwei)(est.gasPrice),
|
|
2158
|
+
nativeCost: (0, import_viem10.formatEther)(nativeCost2),
|
|
2159
|
+
nativeSymbol,
|
|
2160
|
+
usdCost: `$${usdCost2.toFixed(4)}`
|
|
2161
|
+
};
|
|
2020
2162
|
}
|
|
2021
|
-
|
|
2022
|
-
|
|
2163
|
+
const tokenAddress = getTokenAddress(network, token);
|
|
2164
|
+
if (!tokenAddress) {
|
|
2165
|
+
throw new Error(`Token ${token} is not supported on ${network}`);
|
|
2166
|
+
}
|
|
2167
|
+
const chain = getViemChain7(network);
|
|
2168
|
+
const transport = (0, import_viem10.http)(options.rpcUrl ?? DEFAULT_RPC_URLS[network]);
|
|
2169
|
+
const client = (0, import_viem10.createPublicClient)({ chain, transport });
|
|
2170
|
+
const amountBigInt = (0, import_viem10.parseUnits)(amount, 6);
|
|
2171
|
+
const dummyTo = "0x000000000000000000000000000000000000dEaD";
|
|
2172
|
+
let gasLimit;
|
|
2173
|
+
try {
|
|
2174
|
+
gasLimit = await client.estimateGas({
|
|
2175
|
+
to: tokenAddress,
|
|
2176
|
+
data: `0xa9059cbb${dummyTo.slice(2).padStart(64, "0")}${amountBigInt.toString(16).padStart(64, "0")}`
|
|
2177
|
+
});
|
|
2178
|
+
} catch {
|
|
2179
|
+
gasLimit = 65000n;
|
|
2180
|
+
}
|
|
2181
|
+
const gasPrice = await client.getGasPrice();
|
|
2182
|
+
const nativeCost = gasLimit * gasPrice;
|
|
2183
|
+
let usdCost;
|
|
2184
|
+
try {
|
|
2185
|
+
const prices = await getTokenPrices([nativeSymbol]);
|
|
2186
|
+
const nativePrice = prices[nativeSymbol] ?? 0;
|
|
2187
|
+
const cost = Number(nativeCost) / 1e18 * nativePrice;
|
|
2188
|
+
usdCost = `$${cost.toFixed(4)}`;
|
|
2189
|
+
} catch {
|
|
2190
|
+
usdCost = "N/A";
|
|
2191
|
+
}
|
|
2192
|
+
return {
|
|
2193
|
+
network,
|
|
2194
|
+
gasLimit: gasLimit.toString(),
|
|
2195
|
+
gasPriceGwei: (0, import_viem10.formatGwei)(gasPrice),
|
|
2196
|
+
nativeCost: (0, import_viem10.formatEther)(nativeCost),
|
|
2197
|
+
nativeSymbol,
|
|
2198
|
+
usdCost
|
|
2199
|
+
};
|
|
2200
|
+
}
|
|
2201
|
+
function formatPaymentFeeEstimate(result) {
|
|
2202
|
+
return [
|
|
2203
|
+
"## Payment Fee Estimate",
|
|
2204
|
+
"",
|
|
2205
|
+
`- **Network:** ${result.network}`,
|
|
2206
|
+
`- **Estimated Gas:** ${result.gasLimit}`,
|
|
2207
|
+
`- **Gas Price:** ${result.gasPriceGwei} gwei`,
|
|
2208
|
+
`- **Native Cost:** ${result.nativeCost} ${result.nativeSymbol}`,
|
|
2209
|
+
`- **USD Cost:** ${result.usdCost}`
|
|
2210
|
+
].join("\n");
|
|
2211
|
+
}
|
|
2212
|
+
|
|
2213
|
+
// src/tools/compareNetworkFees.ts
|
|
2214
|
+
var import_zod18 = require("zod");
|
|
2215
|
+
var compareNetworkFeesInputSchema = import_zod18.z.object({
|
|
2216
|
+
amount: import_zod18.z.string().regex(/^\d+(\.\d+)?$/).describe("Payment amount (e.g., '100')"),
|
|
2217
|
+
token: import_zod18.z.enum(["USDC", "USDT", "USDT0"]).describe("Token to use for payment"),
|
|
2218
|
+
networks: import_zod18.z.array(import_zod18.z.string()).optional().describe(
|
|
2219
|
+
"Networks to compare. If not provided, compares all networks that support the token."
|
|
2220
|
+
)
|
|
2221
|
+
});
|
|
2222
|
+
var ALL_NETWORKS2 = [
|
|
2223
|
+
"ethereum",
|
|
2224
|
+
"base",
|
|
2225
|
+
"arbitrum",
|
|
2226
|
+
"optimism",
|
|
2227
|
+
"polygon",
|
|
2228
|
+
"avalanche",
|
|
2229
|
+
"ink",
|
|
2230
|
+
"berachain",
|
|
2231
|
+
"unichain"
|
|
2232
|
+
];
|
|
2233
|
+
async function executeCompareNetworkFees(input, options) {
|
|
2234
|
+
const { amount, token } = input;
|
|
2235
|
+
const requestedNetworks = input.networks ? input.networks : ALL_NETWORKS2;
|
|
2236
|
+
const networks = requestedNetworks.filter((n) => supportsToken(n, token));
|
|
2237
|
+
if (networks.length === 0) {
|
|
2238
|
+
throw new Error(`No supported networks found for token ${token}`);
|
|
2239
|
+
}
|
|
2240
|
+
const results = await Promise.allSettled(
|
|
2241
|
+
networks.map(
|
|
2242
|
+
(network) => executeEstimatePaymentFee(
|
|
2243
|
+
{ network, amount, token },
|
|
2244
|
+
{
|
|
2245
|
+
rpcUrl: options.rpcUrls?.[network],
|
|
2246
|
+
demoMode: options.demoMode
|
|
2247
|
+
}
|
|
2248
|
+
)
|
|
2249
|
+
)
|
|
2250
|
+
);
|
|
2251
|
+
const fees = [];
|
|
2252
|
+
for (const result of results) {
|
|
2253
|
+
if (result.status === "fulfilled") {
|
|
2254
|
+
fees.push(result.value);
|
|
2255
|
+
}
|
|
2256
|
+
}
|
|
2257
|
+
if (fees.length === 0) {
|
|
2258
|
+
throw new Error("Failed to estimate fees on any network");
|
|
2259
|
+
}
|
|
2260
|
+
fees.sort((a, b) => {
|
|
2261
|
+
const costA = parseFloat(a.nativeCost) || Infinity;
|
|
2262
|
+
const costB = parseFloat(b.nativeCost) || Infinity;
|
|
2263
|
+
const usdA = parseFloat(a.usdCost.replace("$", "")) || Infinity;
|
|
2264
|
+
const usdB = parseFloat(b.usdCost.replace("$", "")) || Infinity;
|
|
2265
|
+
return usdA - usdB || costA - costB;
|
|
2266
|
+
});
|
|
2267
|
+
return {
|
|
2268
|
+
token,
|
|
2269
|
+
amount,
|
|
2270
|
+
fees,
|
|
2271
|
+
cheapest: fees[0].network
|
|
2272
|
+
};
|
|
2273
|
+
}
|
|
2274
|
+
function formatNetworkFeeComparison(result) {
|
|
2275
|
+
const lines = [
|
|
2276
|
+
"## Network Fee Comparison",
|
|
2277
|
+
"",
|
|
2278
|
+
`**Token:** ${result.token} | **Amount:** ${result.amount}`,
|
|
2279
|
+
`**Cheapest:** ${result.cheapest}`,
|
|
2280
|
+
"",
|
|
2281
|
+
"| Network | Gas Price | Native Cost | USD Cost |",
|
|
2282
|
+
"|---------|----------|-------------|----------|"
|
|
2283
|
+
];
|
|
2284
|
+
for (const fee of result.fees) {
|
|
2285
|
+
const marker = fee.network === result.cheapest ? " *" : "";
|
|
2286
|
+
lines.push(
|
|
2287
|
+
`| ${fee.network}${marker} | ${fee.gasPriceGwei} gwei | ${fee.nativeCost} ${fee.nativeSymbol} | ${fee.usdCost} |`
|
|
2288
|
+
);
|
|
2289
|
+
}
|
|
2290
|
+
return lines.join("\n");
|
|
2291
|
+
}
|
|
2292
|
+
|
|
2293
|
+
// src/tools/quoteStore.ts
|
|
2294
|
+
var import_crypto = require("crypto");
|
|
2295
|
+
var DEFAULT_TTL_MS = 5 * 60 * 1e3;
|
|
2296
|
+
var quotes = /* @__PURE__ */ new Map();
|
|
2297
|
+
var cleanupInterval = null;
|
|
2298
|
+
function ensureCleanup() {
|
|
2299
|
+
if (cleanupInterval) return;
|
|
2300
|
+
cleanupInterval = setInterval(() => {
|
|
2301
|
+
const now = Date.now();
|
|
2302
|
+
for (const [id, quote] of quotes) {
|
|
2303
|
+
if (now > quote.expiresAt) {
|
|
2304
|
+
quotes.delete(id);
|
|
2305
|
+
}
|
|
2306
|
+
}
|
|
2307
|
+
}, 6e4);
|
|
2308
|
+
if (cleanupInterval.unref) {
|
|
2309
|
+
cleanupInterval.unref();
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
2312
|
+
function createQuote(type, data, ttlMs = DEFAULT_TTL_MS) {
|
|
2313
|
+
ensureCleanup();
|
|
2314
|
+
const id = (0, import_crypto.randomUUID)();
|
|
2315
|
+
const now = Date.now();
|
|
2316
|
+
quotes.set(id, {
|
|
2317
|
+
id,
|
|
2318
|
+
type,
|
|
2319
|
+
createdAt: now,
|
|
2320
|
+
expiresAt: now + ttlMs,
|
|
2321
|
+
data
|
|
2322
|
+
});
|
|
2323
|
+
return id;
|
|
2324
|
+
}
|
|
2325
|
+
function getQuote(quoteId) {
|
|
2326
|
+
const quote = quotes.get(quoteId);
|
|
2327
|
+
if (!quote) return null;
|
|
2328
|
+
if (Date.now() > quote.expiresAt) {
|
|
2329
|
+
quotes.delete(quoteId);
|
|
2330
|
+
return null;
|
|
2331
|
+
}
|
|
2332
|
+
return quote;
|
|
2333
|
+
}
|
|
2334
|
+
function deleteQuote(quoteId) {
|
|
2335
|
+
quotes.delete(quoteId);
|
|
2336
|
+
}
|
|
2337
|
+
|
|
2338
|
+
// src/tools/wdkQuoteSwap.ts
|
|
2339
|
+
var import_zod19 = require("zod");
|
|
2340
|
+
var import_viem11 = require("viem");
|
|
2341
|
+
var wdkQuoteSwapInputSchema = import_zod19.z.object({
|
|
2342
|
+
fromToken: import_zod19.z.string().describe('Token to swap from (e.g., "ETH", "USDC")'),
|
|
2343
|
+
toToken: import_zod19.z.string().describe('Token to swap to (e.g., "USDT0", "USDC")'),
|
|
2344
|
+
amount: import_zod19.z.string().regex(/^\d+(\.\d+)?$/).describe("Amount to swap (e.g., '1.0')"),
|
|
2345
|
+
chain: import_zod19.z.string().describe('Chain to execute swap on (e.g., "ethereum", "arbitrum")')
|
|
2346
|
+
});
|
|
2347
|
+
async function executeWdkQuoteSwap(input, wdk) {
|
|
2348
|
+
const decimals = ["USDC", "USDT", "USDT0"].includes(input.fromToken.toUpperCase()) ? 6 : 18;
|
|
2349
|
+
const amountBigInt = (0, import_viem11.parseUnits)(input.amount, decimals);
|
|
2350
|
+
const quote = await wdk.getSwapQuote(input.chain, input.fromToken, amountBigInt);
|
|
2351
|
+
const outputDecimals = ["USDC", "USDT", "USDT0"].includes(input.toToken.toUpperCase()) ? 6 : 18;
|
|
2352
|
+
const outputDivisor = 10 ** outputDecimals;
|
|
2353
|
+
const toAmount = (Number(quote.outputAmount) / outputDivisor).toFixed(outputDecimals === 6 ? 6 : 8);
|
|
2354
|
+
const inputAmount = parseFloat(input.amount);
|
|
2355
|
+
const outputAmount = parseFloat(toAmount);
|
|
2356
|
+
const exchangeRate = inputAmount > 0 ? (outputAmount / inputAmount).toFixed(6) : "0";
|
|
2357
|
+
const expiresAt = new Date(Date.now() + 5 * 60 * 1e3).toISOString();
|
|
2358
|
+
const quoteId = createQuote("swap", {
|
|
2359
|
+
fromToken: input.fromToken,
|
|
2360
|
+
toToken: input.toToken,
|
|
2361
|
+
fromAmount: input.amount,
|
|
2362
|
+
toAmount,
|
|
2363
|
+
chain: input.chain,
|
|
2364
|
+
exchangeRate
|
|
2365
|
+
});
|
|
2366
|
+
return {
|
|
2367
|
+
quoteId,
|
|
2368
|
+
fromToken: input.fromToken,
|
|
2369
|
+
toToken: input.toToken,
|
|
2370
|
+
fromAmount: input.amount,
|
|
2371
|
+
toAmount,
|
|
2372
|
+
exchangeRate,
|
|
2373
|
+
fee: "0.3%",
|
|
2374
|
+
priceImpact: "< 0.1%",
|
|
2375
|
+
expiresAt,
|
|
2376
|
+
chain: input.chain
|
|
2377
|
+
};
|
|
2378
|
+
}
|
|
2379
|
+
function executeWdkQuoteSwapDemo(input) {
|
|
2380
|
+
const inputAmount = parseFloat(input.amount);
|
|
2381
|
+
const toAmount = (inputAmount * 0.997).toFixed(6);
|
|
2382
|
+
const exchangeRate = 0.997.toFixed(6);
|
|
2383
|
+
const expiresAt = new Date(Date.now() + 5 * 60 * 1e3).toISOString();
|
|
2384
|
+
const quoteId = createQuote("swap", {
|
|
2385
|
+
fromToken: input.fromToken,
|
|
2386
|
+
toToken: input.toToken,
|
|
2387
|
+
fromAmount: input.amount,
|
|
2388
|
+
toAmount,
|
|
2389
|
+
chain: input.chain,
|
|
2390
|
+
exchangeRate
|
|
2391
|
+
});
|
|
2392
|
+
return {
|
|
2393
|
+
quoteId,
|
|
2394
|
+
fromToken: input.fromToken,
|
|
2395
|
+
toToken: input.toToken,
|
|
2396
|
+
fromAmount: input.amount,
|
|
2397
|
+
toAmount,
|
|
2398
|
+
exchangeRate,
|
|
2399
|
+
fee: "0.3%",
|
|
2400
|
+
priceImpact: "< 0.1%",
|
|
2401
|
+
expiresAt,
|
|
2402
|
+
chain: input.chain
|
|
2403
|
+
};
|
|
2404
|
+
}
|
|
2405
|
+
function formatSwapQuoteResult(result) {
|
|
2406
|
+
return [
|
|
2407
|
+
"## Swap Quote",
|
|
2408
|
+
"",
|
|
2409
|
+
`- **Quote ID:** \`${result.quoteId}\``,
|
|
2410
|
+
`- **From:** ${result.fromAmount} ${result.fromToken}`,
|
|
2411
|
+
`- **To:** ${result.toAmount} ${result.toToken}`,
|
|
2412
|
+
`- **Exchange Rate:** ${result.exchangeRate}`,
|
|
2413
|
+
`- **Fee:** ${result.fee}`,
|
|
2414
|
+
`- **Price Impact:** ${result.priceImpact}`,
|
|
2415
|
+
`- **Chain:** ${result.chain}`,
|
|
2416
|
+
`- **Expires:** ${result.expiresAt}`,
|
|
2417
|
+
"",
|
|
2418
|
+
"_Call `wdk/executeSwap` with the quoteId to execute this swap._"
|
|
2419
|
+
].join("\n");
|
|
2420
|
+
}
|
|
2421
|
+
|
|
2422
|
+
// src/tools/wdkExecuteSwap.ts
|
|
2423
|
+
var import_zod20 = require("zod");
|
|
2424
|
+
var import_viem12 = require("viem");
|
|
2425
|
+
var wdkExecuteSwapInputSchema = import_zod20.z.object({
|
|
2426
|
+
quoteId: import_zod20.z.string().uuid().describe("Quote ID from wdk/quoteSwap"),
|
|
2427
|
+
confirmed: import_zod20.z.boolean().optional().describe("Set to true to confirm and execute this swap")
|
|
2428
|
+
});
|
|
2429
|
+
async function executeWdkExecuteSwap(input, wdk) {
|
|
2430
|
+
const quote = getQuote(input.quoteId);
|
|
2431
|
+
if (!quote) {
|
|
2432
|
+
throw new Error("Quote not found or expired. Please request a new quote.");
|
|
2433
|
+
}
|
|
2434
|
+
if (quote.type !== "swap") {
|
|
2435
|
+
throw new Error("Invalid quote type. Expected a swap quote.");
|
|
2436
|
+
}
|
|
2437
|
+
const { fromToken, toToken, fromAmount, toAmount, chain } = quote.data;
|
|
2438
|
+
if (!input.confirmed) {
|
|
2439
|
+
return {
|
|
2440
|
+
needsConfirmation: true,
|
|
2441
|
+
summary: `Swap ${fromAmount} ${fromToken} to ${toAmount} ${toToken} on ${chain}`,
|
|
2442
|
+
details: { fromToken, toToken, fromAmount, toAmount, chain, quoteId: input.quoteId }
|
|
2443
|
+
};
|
|
2444
|
+
}
|
|
2445
|
+
const decimals = ["USDC", "USDT", "USDT0"].includes(fromToken.toUpperCase()) ? 6 : 18;
|
|
2446
|
+
const amountBigInt = (0, import_viem12.parseUnits)(fromAmount, decimals);
|
|
2447
|
+
const result = await wdk.swapAndPay({
|
|
2448
|
+
chain,
|
|
2449
|
+
fromToken,
|
|
2450
|
+
amount: amountBigInt
|
|
2451
|
+
});
|
|
2452
|
+
deleteQuote(input.quoteId);
|
|
2453
|
+
return {
|
|
2454
|
+
fromAmount,
|
|
2455
|
+
fromToken,
|
|
2456
|
+
toAmount,
|
|
2457
|
+
toToken,
|
|
2458
|
+
chain,
|
|
2459
|
+
txHash: result?.txHash ?? "0x"
|
|
2460
|
+
};
|
|
2461
|
+
}
|
|
2462
|
+
function executeWdkExecuteSwapDemo(input) {
|
|
2463
|
+
const quote = getQuote(input.quoteId);
|
|
2464
|
+
if (!quote) {
|
|
2465
|
+
throw new Error("Quote not found or expired. Please request a new quote.");
|
|
2466
|
+
}
|
|
2467
|
+
if (quote.type !== "swap") {
|
|
2468
|
+
throw new Error("Invalid quote type. Expected a swap quote.");
|
|
2469
|
+
}
|
|
2470
|
+
const { fromToken, toToken, fromAmount, toAmount, chain } = quote.data;
|
|
2471
|
+
if (!input.confirmed) {
|
|
2472
|
+
return {
|
|
2473
|
+
needsConfirmation: true,
|
|
2474
|
+
summary: `Swap ${fromAmount} ${fromToken} to ${toAmount} ${toToken} on ${chain}`,
|
|
2475
|
+
details: { fromToken, toToken, fromAmount, toAmount, chain, quoteId: input.quoteId }
|
|
2476
|
+
};
|
|
2477
|
+
}
|
|
2478
|
+
deleteQuote(input.quoteId);
|
|
2479
|
+
return {
|
|
2480
|
+
fromAmount,
|
|
2481
|
+
fromToken,
|
|
2482
|
+
toAmount,
|
|
2483
|
+
toToken,
|
|
2484
|
+
chain,
|
|
2485
|
+
txHash: "0xdemo" + Math.random().toString(16).slice(2, 10)
|
|
2486
|
+
};
|
|
2487
|
+
}
|
|
2488
|
+
function formatExecuteSwapResult(result) {
|
|
2489
|
+
return [
|
|
2490
|
+
"## Swap Executed",
|
|
2491
|
+
"",
|
|
2492
|
+
`- **From:** ${result.fromAmount} ${result.fromToken}`,
|
|
2493
|
+
`- **To:** ${result.toAmount} ${result.toToken}`,
|
|
2494
|
+
`- **Chain:** ${result.chain}`,
|
|
2495
|
+
`- **Tx Hash:** \`${result.txHash}\``
|
|
2496
|
+
].join("\n");
|
|
2497
|
+
}
|
|
2498
|
+
|
|
2499
|
+
// src/tools/quoteBridge.ts
|
|
2500
|
+
var import_zod21 = require("zod");
|
|
2501
|
+
var quoteBridgeInputSchema = import_zod21.z.object({
|
|
2502
|
+
fromChain: import_zod21.z.enum(["ethereum", "arbitrum", "ink", "berachain", "unichain"]).describe("Source chain to bridge from"),
|
|
2503
|
+
toChain: import_zod21.z.enum(["ethereum", "arbitrum", "ink", "berachain", "unichain"]).describe("Destination chain to bridge to"),
|
|
2504
|
+
amount: import_zod21.z.string().regex(/^\d+(\.\d+)?$/).describe("Amount of USDT0 to bridge (e.g., '100' for 100 USDT0)"),
|
|
2505
|
+
recipient: import_zod21.z.string().regex(/^0x[a-fA-F0-9]{40}$/).describe("Recipient address on destination chain")
|
|
2506
|
+
});
|
|
2507
|
+
async function executeQuoteBridge(input, rpcUrls) {
|
|
2508
|
+
const feeResult = await executeGetBridgeFee(input, rpcUrls);
|
|
2509
|
+
const expiresAt = new Date(Date.now() + 5 * 60 * 1e3).toISOString();
|
|
2510
|
+
const quoteId = createQuote("bridge", {
|
|
2511
|
+
fromChain: input.fromChain,
|
|
2512
|
+
toChain: input.toChain,
|
|
2513
|
+
amount: input.amount,
|
|
2514
|
+
recipient: input.recipient,
|
|
2515
|
+
nativeFee: feeResult.nativeFee,
|
|
2516
|
+
nativeFeeFormatted: feeResult.nativeFeeFormatted,
|
|
2517
|
+
estimatedTime: feeResult.estimatedTime
|
|
2518
|
+
});
|
|
2519
|
+
return {
|
|
2520
|
+
quoteId,
|
|
2521
|
+
fromChain: input.fromChain,
|
|
2522
|
+
toChain: input.toChain,
|
|
2523
|
+
amount: input.amount,
|
|
2524
|
+
recipient: input.recipient,
|
|
2525
|
+
nativeFee: feeResult.nativeFee,
|
|
2526
|
+
nativeFeeFormatted: feeResult.nativeFeeFormatted,
|
|
2527
|
+
estimatedTime: feeResult.estimatedTime,
|
|
2528
|
+
expiresAt
|
|
2529
|
+
};
|
|
2530
|
+
}
|
|
2531
|
+
function executeQuoteBridgeDemo(input) {
|
|
2532
|
+
const expiresAt = new Date(Date.now() + 5 * 60 * 1e3).toISOString();
|
|
2533
|
+
const estimatedTime = input.toChain === "ethereum" ? 900 : 300;
|
|
2534
|
+
const quoteId = createQuote("bridge", {
|
|
2535
|
+
fromChain: input.fromChain,
|
|
2536
|
+
toChain: input.toChain,
|
|
2537
|
+
amount: input.amount,
|
|
2538
|
+
recipient: input.recipient,
|
|
2539
|
+
nativeFee: "1000000000000000",
|
|
2540
|
+
nativeFeeFormatted: "0.001 ETH",
|
|
2541
|
+
estimatedTime
|
|
2542
|
+
});
|
|
2543
|
+
return {
|
|
2544
|
+
quoteId,
|
|
2545
|
+
fromChain: input.fromChain,
|
|
2546
|
+
toChain: input.toChain,
|
|
2547
|
+
amount: input.amount,
|
|
2548
|
+
recipient: input.recipient,
|
|
2549
|
+
nativeFee: "1000000000000000",
|
|
2550
|
+
nativeFeeFormatted: "0.001 ETH",
|
|
2551
|
+
estimatedTime,
|
|
2552
|
+
expiresAt
|
|
2553
|
+
};
|
|
2554
|
+
}
|
|
2555
|
+
function formatBridgeQuoteResult(result) {
|
|
2556
|
+
const minutes = Math.ceil(result.estimatedTime / 60);
|
|
2557
|
+
return [
|
|
2558
|
+
"## Bridge Quote",
|
|
2559
|
+
"",
|
|
2560
|
+
`- **Quote ID:** \`${result.quoteId}\``,
|
|
2561
|
+
`- **Route:** ${result.fromChain} -> ${result.toChain}`,
|
|
2562
|
+
`- **Amount:** ${result.amount} USDT0`,
|
|
2563
|
+
`- **Recipient:** \`${result.recipient}\``,
|
|
2564
|
+
`- **Fee:** ${result.nativeFeeFormatted}`,
|
|
2565
|
+
`- **Estimated Time:** ~${minutes} minutes`,
|
|
2566
|
+
`- **Expires:** ${result.expiresAt}`,
|
|
2567
|
+
"",
|
|
2568
|
+
"_Call `t402/executeBridge` with the quoteId to execute this bridge._"
|
|
2569
|
+
].join("\n");
|
|
2570
|
+
}
|
|
2571
|
+
|
|
2572
|
+
// src/tools/executeBridgeFromQuote.ts
|
|
2573
|
+
var import_zod22 = require("zod");
|
|
2574
|
+
var executeBridgeFromQuoteInputSchema = import_zod22.z.object({
|
|
2575
|
+
quoteId: import_zod22.z.string().uuid().describe("Quote ID from t402/quoteBridge"),
|
|
2576
|
+
confirmed: import_zod22.z.boolean().optional().describe("Set to true to confirm and execute this bridge")
|
|
2577
|
+
});
|
|
2578
|
+
async function executeExecuteBridgeFromQuote(input, options) {
|
|
2579
|
+
const quote = getQuote(input.quoteId);
|
|
2580
|
+
if (!quote) {
|
|
2581
|
+
throw new Error("Quote not found or expired. Please request a new quote.");
|
|
2582
|
+
}
|
|
2583
|
+
if (quote.type !== "bridge") {
|
|
2584
|
+
throw new Error("Invalid quote type. Expected a bridge quote.");
|
|
2585
|
+
}
|
|
2586
|
+
const { fromChain, toChain, amount, recipient } = quote.data;
|
|
2587
|
+
if (!input.confirmed) {
|
|
2588
|
+
return {
|
|
2589
|
+
needsConfirmation: true,
|
|
2590
|
+
summary: `Bridge ${amount} USDT0 from ${fromChain} to ${toChain}`,
|
|
2591
|
+
details: { fromChain, toChain, amount, recipient, quoteId: input.quoteId }
|
|
2592
|
+
};
|
|
2593
|
+
}
|
|
2594
|
+
const result = await executeBridge(
|
|
2595
|
+
{ fromChain, toChain, amount, recipient, confirmed: true },
|
|
2596
|
+
options
|
|
2597
|
+
);
|
|
2598
|
+
if ("needsConfirmation" in result) {
|
|
2599
|
+
return result;
|
|
2600
|
+
}
|
|
2601
|
+
deleteQuote(input.quoteId);
|
|
2602
|
+
return result;
|
|
2603
|
+
}
|
|
2604
|
+
function executeExecuteBridgeFromQuoteDemo(input) {
|
|
2605
|
+
const quote = getQuote(input.quoteId);
|
|
2606
|
+
if (!quote) {
|
|
2607
|
+
throw new Error("Quote not found or expired. Please request a new quote.");
|
|
2608
|
+
}
|
|
2609
|
+
if (quote.type !== "bridge") {
|
|
2610
|
+
throw new Error("Invalid quote type. Expected a bridge quote.");
|
|
2611
|
+
}
|
|
2612
|
+
const { fromChain, toChain, amount, recipient } = quote.data;
|
|
2613
|
+
if (!input.confirmed) {
|
|
2614
|
+
return {
|
|
2615
|
+
needsConfirmation: true,
|
|
2616
|
+
summary: `Bridge ${amount} USDT0 from ${fromChain} to ${toChain}`,
|
|
2617
|
+
details: { fromChain, toChain, amount, recipient, quoteId: input.quoteId }
|
|
2618
|
+
};
|
|
2619
|
+
}
|
|
2620
|
+
deleteQuote(input.quoteId);
|
|
2621
|
+
const fakeTxHash = `0x${"a".repeat(64)}`;
|
|
2622
|
+
const fakeGuid = `0x${"b".repeat(64)}`;
|
|
2623
|
+
return {
|
|
2624
|
+
txHash: fakeTxHash,
|
|
2625
|
+
messageGuid: fakeGuid,
|
|
2626
|
+
amount,
|
|
2627
|
+
fromChain,
|
|
2628
|
+
toChain,
|
|
2629
|
+
estimatedTime: quote.data.estimatedTime ?? 300,
|
|
2630
|
+
trackingUrl: `https://layerzeroscan.com/tx/${fakeGuid}`
|
|
2631
|
+
};
|
|
2632
|
+
}
|
|
2633
|
+
|
|
2634
|
+
// src/tools/unified.ts
|
|
2635
|
+
var import_zod23 = require("zod");
|
|
2636
|
+
var smartPayInputSchema = import_zod23.z.object({
|
|
2637
|
+
url: import_zod23.z.string().url().describe("URL of the 402-protected resource"),
|
|
2638
|
+
maxBridgeFee: import_zod23.z.string().regex(/^\d+(\.\d+)?$/).optional().describe("Maximum acceptable bridge fee in native token (optional)"),
|
|
2639
|
+
preferredNetwork: import_zod23.z.string().optional().describe("Preferred network for payment (optional)"),
|
|
2640
|
+
confirmed: import_zod23.z.boolean().optional().describe("Set to true to confirm and execute this payment")
|
|
2641
|
+
});
|
|
2642
|
+
var paymentPlanInputSchema = import_zod23.z.object({
|
|
2643
|
+
paymentRequired: import_zod23.z.object({
|
|
2644
|
+
scheme: import_zod23.z.string().optional(),
|
|
2645
|
+
network: import_zod23.z.string().optional(),
|
|
2646
|
+
maxAmountRequired: import_zod23.z.string().optional(),
|
|
2647
|
+
resource: import_zod23.z.string().optional(),
|
|
2648
|
+
description: import_zod23.z.string().optional(),
|
|
2649
|
+
payTo: import_zod23.z.string().optional(),
|
|
2650
|
+
maxDeadline: import_zod23.z.number().optional()
|
|
2651
|
+
}).passthrough().describe("The 402 PaymentRequired response")
|
|
2652
|
+
});
|
|
2653
|
+
var UNIFIED_TOOL_DEFINITIONS = {
|
|
2654
|
+
"t402/smartPay": {
|
|
2655
|
+
name: "t402/smartPay",
|
|
2656
|
+
description: "Intelligent payment that automatically checks balance, bridges if needed, and pays. Handles the entire payment flow for 402-protected resources.",
|
|
2657
|
+
inputSchema: {
|
|
2658
|
+
type: "object",
|
|
2659
|
+
properties: {
|
|
2660
|
+
url: { type: "string", description: "URL of the 402-protected resource" },
|
|
2661
|
+
maxBridgeFee: {
|
|
2662
|
+
type: "string",
|
|
2663
|
+
description: "Maximum acceptable bridge fee in native token (optional)"
|
|
2664
|
+
},
|
|
2665
|
+
preferredNetwork: {
|
|
2666
|
+
type: "string",
|
|
2667
|
+
description: "Preferred network for payment (optional)"
|
|
2668
|
+
},
|
|
2669
|
+
confirmed: {
|
|
2670
|
+
type: "boolean",
|
|
2671
|
+
description: "Set to true to confirm and execute. Omit for a preview/confirmation prompt."
|
|
2672
|
+
}
|
|
2673
|
+
},
|
|
2674
|
+
required: ["url"]
|
|
2675
|
+
}
|
|
2676
|
+
},
|
|
2677
|
+
"t402/paymentPlan": {
|
|
2678
|
+
name: "t402/paymentPlan",
|
|
2679
|
+
description: "Analyze a 402 response and create an optimal payment plan considering balances across all chains. Returns recommended network, bridge requirements, and balance overview.",
|
|
2680
|
+
inputSchema: {
|
|
2681
|
+
type: "object",
|
|
2682
|
+
properties: {
|
|
2683
|
+
paymentRequired: {
|
|
2684
|
+
type: "object",
|
|
2685
|
+
description: "The 402 PaymentRequired response"
|
|
2686
|
+
}
|
|
2687
|
+
},
|
|
2688
|
+
required: ["paymentRequired"]
|
|
2689
|
+
}
|
|
2690
|
+
}
|
|
2691
|
+
};
|
|
2692
|
+
async function executeSmartPay(input, wdk) {
|
|
2693
|
+
if (!input.confirmed) {
|
|
2694
|
+
return {
|
|
2695
|
+
needsConfirmation: true,
|
|
2696
|
+
summary: `Smart-pay for ${input.url}${input.preferredNetwork ? ` on ${input.preferredNetwork}` : ""}`,
|
|
2697
|
+
details: {
|
|
2698
|
+
url: input.url,
|
|
2699
|
+
...input.maxBridgeFee ? { maxBridgeFee: input.maxBridgeFee } : {},
|
|
2700
|
+
...input.preferredNetwork ? { preferredNetwork: input.preferredNetwork } : {}
|
|
2701
|
+
}
|
|
2702
|
+
};
|
|
2703
|
+
}
|
|
2704
|
+
const steps = [];
|
|
2705
|
+
const chains9 = input.preferredNetwork ? [input.preferredNetwork] : ["ethereum", "arbitrum", "base"];
|
|
2706
|
+
steps.push({
|
|
2707
|
+
action: "check_balance",
|
|
2708
|
+
status: "success",
|
|
2709
|
+
detail: `Checking balances on ${chains9.join(", ")}`
|
|
2710
|
+
});
|
|
2711
|
+
const { T402Protocol } = await import("@t402/wdk-protocol");
|
|
2712
|
+
const protocol = await T402Protocol.create(wdk, { chains: chains9 });
|
|
2713
|
+
steps.push({
|
|
2714
|
+
action: "fetch",
|
|
2715
|
+
status: "success",
|
|
2716
|
+
detail: `Fetching ${input.url}`
|
|
2717
|
+
});
|
|
2718
|
+
const { response, receipt } = await protocol.fetch(input.url);
|
|
2719
|
+
if (receipt) {
|
|
2720
|
+
steps.push({
|
|
2721
|
+
action: "pay",
|
|
2722
|
+
status: "success",
|
|
2723
|
+
detail: `Payment made: ${receipt.amount} on ${receipt.network}`
|
|
2724
|
+
});
|
|
2725
|
+
}
|
|
2726
|
+
const contentType = response.headers.get("content-type") ?? void 0;
|
|
2727
|
+
let body = "";
|
|
2728
|
+
try {
|
|
2729
|
+
body = await response.text();
|
|
2730
|
+
if (body.length > 1e4) {
|
|
2731
|
+
body = body.slice(0, 1e4) + "\n... (truncated)";
|
|
2732
|
+
}
|
|
2733
|
+
} catch {
|
|
2734
|
+
body = "[Could not read response body]";
|
|
2735
|
+
}
|
|
2736
|
+
return {
|
|
2737
|
+
success: response.ok,
|
|
2738
|
+
statusCode: response.status,
|
|
2739
|
+
body,
|
|
2740
|
+
contentType,
|
|
2741
|
+
steps,
|
|
2742
|
+
payment: receipt ? {
|
|
2743
|
+
network: receipt.network,
|
|
2744
|
+
scheme: receipt.scheme,
|
|
2745
|
+
amount: receipt.amount,
|
|
2746
|
+
payTo: receipt.payTo
|
|
2747
|
+
} : void 0
|
|
2748
|
+
};
|
|
2749
|
+
}
|
|
2750
|
+
function executeSmartPayDemo(input) {
|
|
2751
|
+
if (!input.confirmed) {
|
|
2752
|
+
return {
|
|
2753
|
+
needsConfirmation: true,
|
|
2754
|
+
summary: `Smart-pay for ${input.url}${input.preferredNetwork ? ` on ${input.preferredNetwork}` : ""}`,
|
|
2755
|
+
details: {
|
|
2756
|
+
url: input.url,
|
|
2757
|
+
...input.maxBridgeFee ? { maxBridgeFee: input.maxBridgeFee } : {},
|
|
2758
|
+
...input.preferredNetwork ? { preferredNetwork: input.preferredNetwork } : {}
|
|
2759
|
+
}
|
|
2760
|
+
};
|
|
2761
|
+
}
|
|
2762
|
+
const network = input.preferredNetwork ?? "arbitrum";
|
|
2763
|
+
return {
|
|
2764
|
+
success: true,
|
|
2765
|
+
statusCode: 200,
|
|
2766
|
+
body: `[Demo] Premium content from ${input.url}
|
|
2767
|
+
|
|
2768
|
+
This is simulated content returned after smart payment.`,
|
|
2769
|
+
contentType: "text/plain",
|
|
2770
|
+
steps: [
|
|
2771
|
+
{ action: "check_balance", status: "success", detail: `Checked balances on ${network}` },
|
|
2772
|
+
{ action: "check_price", status: "success", detail: "Resource costs 1.00 USDT0" },
|
|
2773
|
+
{ action: "pay", status: "success", detail: `Paid 1000000 USDT0 on eip155:42161` },
|
|
2774
|
+
{ action: "fetch", status: "success", detail: `Fetched ${input.url}` }
|
|
2775
|
+
],
|
|
2776
|
+
payment: {
|
|
2777
|
+
network: "eip155:42161",
|
|
2778
|
+
scheme: "exact",
|
|
2779
|
+
amount: "1000000",
|
|
2780
|
+
payTo: "0xC88f67e776f16DcFBf42e6bDda1B82604448899B"
|
|
2781
|
+
}
|
|
2782
|
+
};
|
|
2783
|
+
}
|
|
2784
|
+
async function executePaymentPlan(input, wdk) {
|
|
2785
|
+
const targetNetwork = input.paymentRequired.network;
|
|
2786
|
+
const requiredAmount = input.paymentRequired.maxAmountRequired;
|
|
2787
|
+
const aggregated = await wdk.getAggregatedBalances();
|
|
2788
|
+
const balances = aggregated.chains.map((chain) => {
|
|
2789
|
+
const usdt0 = chain.tokens.find((t) => t.symbol === "USDT0");
|
|
2790
|
+
const usdc = chain.tokens.find((t) => t.symbol === "USDC");
|
|
2791
|
+
return {
|
|
2792
|
+
chain: chain.chain,
|
|
2793
|
+
usdt0: usdt0?.formatted ?? "0",
|
|
2794
|
+
usdc: usdc?.formatted ?? "0"
|
|
2795
|
+
};
|
|
2796
|
+
});
|
|
2797
|
+
const requiredBigint = requiredAmount ? BigInt(requiredAmount) : 0n;
|
|
2798
|
+
const bestChain = await wdk.findBestChainForPayment(requiredBigint);
|
|
2799
|
+
if (bestChain) {
|
|
2800
|
+
const needsBridge = targetNetwork ? !bestChain.chain.includes(targetNetwork) : false;
|
|
2801
|
+
return {
|
|
2802
|
+
viable: true,
|
|
2803
|
+
recommendedNetwork: bestChain.chain,
|
|
2804
|
+
availableBalance: bestChain.balance.toString(),
|
|
2805
|
+
bridgeRequired: needsBridge,
|
|
2806
|
+
bridgeDetails: needsBridge ? {
|
|
2807
|
+
fromChain: bestChain.chain,
|
|
2808
|
+
toChain: targetNetwork ?? bestChain.chain,
|
|
2809
|
+
amount: requiredAmount ?? "0",
|
|
2810
|
+
estimatedFee: "0.001"
|
|
2811
|
+
} : void 0,
|
|
2812
|
+
balances
|
|
2813
|
+
};
|
|
2814
|
+
}
|
|
2815
|
+
return {
|
|
2816
|
+
viable: false,
|
|
2817
|
+
bridgeRequired: false,
|
|
2818
|
+
balances,
|
|
2819
|
+
reason: "Insufficient balance across all chains"
|
|
2820
|
+
};
|
|
2821
|
+
}
|
|
2822
|
+
function executePaymentPlanDemo(_input) {
|
|
2823
|
+
return {
|
|
2824
|
+
viable: true,
|
|
2825
|
+
recommendedNetwork: "arbitrum",
|
|
2826
|
+
availableBalance: "500000000",
|
|
2827
|
+
bridgeRequired: false,
|
|
2828
|
+
balances: [
|
|
2829
|
+
{ chain: "ethereum", usdt0: "100.00", usdc: "250.00" },
|
|
2830
|
+
{ chain: "arbitrum", usdt0: "500.00", usdc: "0" },
|
|
2831
|
+
{ chain: "base", usdt0: "50.00", usdc: "100.00" }
|
|
2832
|
+
]
|
|
2833
|
+
};
|
|
2834
|
+
}
|
|
2835
|
+
function formatSmartPayResult(result) {
|
|
2836
|
+
const lines = ["## SmartPay Result", ""];
|
|
2837
|
+
if (result.success) {
|
|
2838
|
+
lines.push(`**Status:** Success (${result.statusCode})`);
|
|
2839
|
+
} else {
|
|
2840
|
+
lines.push(`**Status:** Failed (${result.statusCode})`);
|
|
2841
|
+
}
|
|
2842
|
+
if (result.steps.length > 0) {
|
|
2843
|
+
lines.push("");
|
|
2844
|
+
lines.push("### Steps");
|
|
2845
|
+
for (const step of result.steps) {
|
|
2846
|
+
const icon = step.status === "success" ? "[OK]" : step.status === "skipped" ? "[SKIP]" : "[FAIL]";
|
|
2847
|
+
lines.push(`- ${icon} **${step.action}**: ${step.detail}`);
|
|
2848
|
+
}
|
|
2849
|
+
}
|
|
2850
|
+
if (result.payment) {
|
|
2851
|
+
lines.push("");
|
|
2023
2852
|
lines.push("### Payment Details");
|
|
2024
2853
|
lines.push(`- **Network:** ${result.payment.network}`);
|
|
2025
2854
|
lines.push(`- **Scheme:** ${result.payment.scheme}`);
|
|
@@ -2183,6 +3012,10 @@ var TOOL_DEFINITIONS = {
|
|
|
2183
3012
|
memo: {
|
|
2184
3013
|
type: "string",
|
|
2185
3014
|
description: "Optional memo/reference for the payment"
|
|
3015
|
+
},
|
|
3016
|
+
confirmed: {
|
|
3017
|
+
type: "boolean",
|
|
3018
|
+
description: "Set to true to confirm and execute. Omit for a preview/confirmation prompt."
|
|
2186
3019
|
}
|
|
2187
3020
|
},
|
|
2188
3021
|
required: ["to", "amount", "token", "network"]
|
|
@@ -2213,6 +3046,10 @@ var TOOL_DEFINITIONS = {
|
|
|
2213
3046
|
type: "string",
|
|
2214
3047
|
enum: ["ethereum", "base", "arbitrum", "optimism", "polygon", "avalanche"],
|
|
2215
3048
|
description: "Network to execute gasless payment on (must support ERC-4337)"
|
|
3049
|
+
},
|
|
3050
|
+
confirmed: {
|
|
3051
|
+
type: "boolean",
|
|
3052
|
+
description: "Set to true to confirm and execute. Omit for a preview/confirmation prompt."
|
|
2216
3053
|
}
|
|
2217
3054
|
},
|
|
2218
3055
|
required: ["to", "amount", "token", "network"]
|
|
@@ -2251,6 +3088,144 @@ var TOOL_DEFINITIONS = {
|
|
|
2251
3088
|
"t402/bridge": {
|
|
2252
3089
|
name: "t402/bridge",
|
|
2253
3090
|
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.",
|
|
3091
|
+
inputSchema: {
|
|
3092
|
+
type: "object",
|
|
3093
|
+
properties: {
|
|
3094
|
+
fromChain: {
|
|
3095
|
+
type: "string",
|
|
3096
|
+
enum: ["ethereum", "arbitrum", "ink", "berachain", "unichain"],
|
|
3097
|
+
description: "Source chain to bridge from"
|
|
3098
|
+
},
|
|
3099
|
+
toChain: {
|
|
3100
|
+
type: "string",
|
|
3101
|
+
enum: ["ethereum", "arbitrum", "ink", "berachain", "unichain"],
|
|
3102
|
+
description: "Destination chain to bridge to"
|
|
3103
|
+
},
|
|
3104
|
+
amount: {
|
|
3105
|
+
type: "string",
|
|
3106
|
+
pattern: "^\\d+(\\.\\d+)?$",
|
|
3107
|
+
description: "Amount of USDT0 to bridge (e.g., '100' for 100 USDT0)"
|
|
3108
|
+
},
|
|
3109
|
+
recipient: {
|
|
3110
|
+
type: "string",
|
|
3111
|
+
pattern: "^0x[a-fA-F0-9]{40}$",
|
|
3112
|
+
description: "Recipient address on destination chain"
|
|
3113
|
+
},
|
|
3114
|
+
confirmed: {
|
|
3115
|
+
type: "boolean",
|
|
3116
|
+
description: "Set to true to confirm and execute. Omit for a preview/confirmation prompt."
|
|
3117
|
+
}
|
|
3118
|
+
},
|
|
3119
|
+
required: ["fromChain", "toChain", "amount", "recipient"]
|
|
3120
|
+
}
|
|
3121
|
+
},
|
|
3122
|
+
"t402/getTokenPrice": {
|
|
3123
|
+
name: "t402/getTokenPrice",
|
|
3124
|
+
description: "Get current market prices for tokens (ETH, MATIC, AVAX, USDC, etc.) via CoinGecko. Cached for 5 minutes.",
|
|
3125
|
+
inputSchema: {
|
|
3126
|
+
type: "object",
|
|
3127
|
+
properties: {
|
|
3128
|
+
tokens: {
|
|
3129
|
+
type: "array",
|
|
3130
|
+
items: { type: "string" },
|
|
3131
|
+
description: 'Token symbols to get prices for (e.g., ["ETH", "MATIC", "USDC"])'
|
|
3132
|
+
},
|
|
3133
|
+
currency: {
|
|
3134
|
+
type: "string",
|
|
3135
|
+
description: 'Target currency (default: "usd")'
|
|
3136
|
+
}
|
|
3137
|
+
},
|
|
3138
|
+
required: ["tokens"]
|
|
3139
|
+
}
|
|
3140
|
+
},
|
|
3141
|
+
"t402/getGasPrice": {
|
|
3142
|
+
name: "t402/getGasPrice",
|
|
3143
|
+
description: "Get the current gas price on a specific blockchain network. Returns the price in gwei.",
|
|
3144
|
+
inputSchema: {
|
|
3145
|
+
type: "object",
|
|
3146
|
+
properties: {
|
|
3147
|
+
network: {
|
|
3148
|
+
type: "string",
|
|
3149
|
+
enum: [
|
|
3150
|
+
"ethereum",
|
|
3151
|
+
"base",
|
|
3152
|
+
"arbitrum",
|
|
3153
|
+
"optimism",
|
|
3154
|
+
"polygon",
|
|
3155
|
+
"avalanche",
|
|
3156
|
+
"ink",
|
|
3157
|
+
"berachain",
|
|
3158
|
+
"unichain"
|
|
3159
|
+
],
|
|
3160
|
+
description: "Blockchain network to check gas price on"
|
|
3161
|
+
}
|
|
3162
|
+
},
|
|
3163
|
+
required: ["network"]
|
|
3164
|
+
}
|
|
3165
|
+
},
|
|
3166
|
+
"t402/estimatePaymentFee": {
|
|
3167
|
+
name: "t402/estimatePaymentFee",
|
|
3168
|
+
description: "Estimate the gas cost (in native token and USD) for a stablecoin payment on a specific network.",
|
|
3169
|
+
inputSchema: {
|
|
3170
|
+
type: "object",
|
|
3171
|
+
properties: {
|
|
3172
|
+
network: {
|
|
3173
|
+
type: "string",
|
|
3174
|
+
enum: [
|
|
3175
|
+
"ethereum",
|
|
3176
|
+
"base",
|
|
3177
|
+
"arbitrum",
|
|
3178
|
+
"optimism",
|
|
3179
|
+
"polygon",
|
|
3180
|
+
"avalanche",
|
|
3181
|
+
"ink",
|
|
3182
|
+
"berachain",
|
|
3183
|
+
"unichain"
|
|
3184
|
+
],
|
|
3185
|
+
description: "Network to estimate fee on"
|
|
3186
|
+
},
|
|
3187
|
+
amount: {
|
|
3188
|
+
type: "string",
|
|
3189
|
+
pattern: "^\\d+(\\.\\d+)?$",
|
|
3190
|
+
description: "Payment amount (e.g., '100')"
|
|
3191
|
+
},
|
|
3192
|
+
token: {
|
|
3193
|
+
type: "string",
|
|
3194
|
+
enum: ["USDC", "USDT", "USDT0"],
|
|
3195
|
+
description: "Token to use for payment"
|
|
3196
|
+
}
|
|
3197
|
+
},
|
|
3198
|
+
required: ["network", "amount", "token"]
|
|
3199
|
+
}
|
|
3200
|
+
},
|
|
3201
|
+
"t402/compareNetworkFees": {
|
|
3202
|
+
name: "t402/compareNetworkFees",
|
|
3203
|
+
description: "Compare payment fees across multiple networks for the same token. Returns a sorted table from cheapest to most expensive.",
|
|
3204
|
+
inputSchema: {
|
|
3205
|
+
type: "object",
|
|
3206
|
+
properties: {
|
|
3207
|
+
amount: {
|
|
3208
|
+
type: "string",
|
|
3209
|
+
pattern: "^\\d+(\\.\\d+)?$",
|
|
3210
|
+
description: "Payment amount (e.g., '100')"
|
|
3211
|
+
},
|
|
3212
|
+
token: {
|
|
3213
|
+
type: "string",
|
|
3214
|
+
enum: ["USDC", "USDT", "USDT0"],
|
|
3215
|
+
description: "Token to use for payment"
|
|
3216
|
+
},
|
|
3217
|
+
networks: {
|
|
3218
|
+
type: "array",
|
|
3219
|
+
items: { type: "string" },
|
|
3220
|
+
description: "Networks to compare. If not provided, compares all networks that support the token."
|
|
3221
|
+
}
|
|
3222
|
+
},
|
|
3223
|
+
required: ["amount", "token"]
|
|
3224
|
+
}
|
|
3225
|
+
},
|
|
3226
|
+
"t402/quoteBridge": {
|
|
3227
|
+
name: "t402/quoteBridge",
|
|
3228
|
+
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.",
|
|
2254
3229
|
inputSchema: {
|
|
2255
3230
|
type: "object",
|
|
2256
3231
|
properties: {
|
|
@@ -2277,6 +3252,24 @@ var TOOL_DEFINITIONS = {
|
|
|
2277
3252
|
},
|
|
2278
3253
|
required: ["fromChain", "toChain", "amount", "recipient"]
|
|
2279
3254
|
}
|
|
3255
|
+
},
|
|
3256
|
+
"t402/executeBridgeQuote": {
|
|
3257
|
+
name: "t402/executeBridgeQuote",
|
|
3258
|
+
description: "Execute a bridge using a quoteId from t402/quoteBridge. Requires confirmation.",
|
|
3259
|
+
inputSchema: {
|
|
3260
|
+
type: "object",
|
|
3261
|
+
properties: {
|
|
3262
|
+
quoteId: {
|
|
3263
|
+
type: "string",
|
|
3264
|
+
description: "Quote ID from t402/quoteBridge"
|
|
3265
|
+
},
|
|
3266
|
+
confirmed: {
|
|
3267
|
+
type: "boolean",
|
|
3268
|
+
description: "Set to true to confirm and execute. Omit for a preview/confirmation prompt."
|
|
3269
|
+
}
|
|
3270
|
+
},
|
|
3271
|
+
required: ["quoteId"]
|
|
3272
|
+
}
|
|
2280
3273
|
}
|
|
2281
3274
|
};
|
|
2282
3275
|
var WDK_TOOL_DEFINITIONS = {
|
|
@@ -2327,6 +3320,10 @@ var WDK_TOOL_DEFINITIONS = {
|
|
|
2327
3320
|
chain: {
|
|
2328
3321
|
type: "string",
|
|
2329
3322
|
description: 'Chain to execute transfer on (e.g., "ethereum", "arbitrum")'
|
|
3323
|
+
},
|
|
3324
|
+
confirmed: {
|
|
3325
|
+
type: "boolean",
|
|
3326
|
+
description: "Set to true to confirm and execute. Omit for a preview/confirmation prompt."
|
|
2330
3327
|
}
|
|
2331
3328
|
},
|
|
2332
3329
|
required: ["to", "amount", "token", "chain"]
|
|
@@ -2354,6 +3351,10 @@ var WDK_TOOL_DEFINITIONS = {
|
|
|
2354
3351
|
chain: {
|
|
2355
3352
|
type: "string",
|
|
2356
3353
|
description: 'Chain to execute swap on (e.g., "ethereum", "arbitrum")'
|
|
3354
|
+
},
|
|
3355
|
+
confirmed: {
|
|
3356
|
+
type: "boolean",
|
|
3357
|
+
description: "Set to true to confirm and execute. Omit for a preview/confirmation prompt."
|
|
2357
3358
|
}
|
|
2358
3359
|
},
|
|
2359
3360
|
required: ["fromToken", "toToken", "amount", "chain"]
|
|
@@ -2377,10 +3378,59 @@ var WDK_TOOL_DEFINITIONS = {
|
|
|
2377
3378
|
preferredChain: {
|
|
2378
3379
|
type: "string",
|
|
2379
3380
|
description: 'Preferred chain for payment (e.g., "arbitrum"). If not specified, uses first available.'
|
|
3381
|
+
},
|
|
3382
|
+
confirmed: {
|
|
3383
|
+
type: "boolean",
|
|
3384
|
+
description: "Set to true to confirm and execute. Omit for a preview/confirmation prompt."
|
|
2380
3385
|
}
|
|
2381
3386
|
},
|
|
2382
3387
|
required: ["url"]
|
|
2383
3388
|
}
|
|
3389
|
+
},
|
|
3390
|
+
"wdk/quoteSwap": {
|
|
3391
|
+
name: "wdk/quoteSwap",
|
|
3392
|
+
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.",
|
|
3393
|
+
inputSchema: {
|
|
3394
|
+
type: "object",
|
|
3395
|
+
properties: {
|
|
3396
|
+
fromToken: {
|
|
3397
|
+
type: "string",
|
|
3398
|
+
description: 'Token to swap from (e.g., "ETH", "USDC")'
|
|
3399
|
+
},
|
|
3400
|
+
toToken: {
|
|
3401
|
+
type: "string",
|
|
3402
|
+
description: 'Token to swap to (e.g., "USDT0", "USDC")'
|
|
3403
|
+
},
|
|
3404
|
+
amount: {
|
|
3405
|
+
type: "string",
|
|
3406
|
+
pattern: "^\\d+(\\.\\d+)?$",
|
|
3407
|
+
description: "Amount to swap (e.g., '1.0')"
|
|
3408
|
+
},
|
|
3409
|
+
chain: {
|
|
3410
|
+
type: "string",
|
|
3411
|
+
description: 'Chain to execute swap on (e.g., "ethereum", "arbitrum")'
|
|
3412
|
+
}
|
|
3413
|
+
},
|
|
3414
|
+
required: ["fromToken", "toToken", "amount", "chain"]
|
|
3415
|
+
}
|
|
3416
|
+
},
|
|
3417
|
+
"wdk/executeSwap": {
|
|
3418
|
+
name: "wdk/executeSwap",
|
|
3419
|
+
description: "Execute a swap using a quoteId from wdk/quoteSwap. Requires confirmation.",
|
|
3420
|
+
inputSchema: {
|
|
3421
|
+
type: "object",
|
|
3422
|
+
properties: {
|
|
3423
|
+
quoteId: {
|
|
3424
|
+
type: "string",
|
|
3425
|
+
description: "Quote ID from wdk/quoteSwap"
|
|
3426
|
+
},
|
|
3427
|
+
confirmed: {
|
|
3428
|
+
type: "boolean",
|
|
3429
|
+
description: "Set to true to confirm and execute. Omit for a preview/confirmation prompt."
|
|
3430
|
+
}
|
|
3431
|
+
},
|
|
3432
|
+
required: ["quoteId"]
|
|
3433
|
+
}
|
|
2384
3434
|
}
|
|
2385
3435
|
};
|
|
2386
3436
|
var ERC8004_TOOL_DEFINITIONS = {
|
|
@@ -2564,6 +3614,24 @@ var T402McpServer = class {
|
|
|
2564
3614
|
return await this.handleSmartPay(args);
|
|
2565
3615
|
case "t402/paymentPlan":
|
|
2566
3616
|
return await this.handlePaymentPlan(args);
|
|
3617
|
+
// Price and fee tools
|
|
3618
|
+
case "t402/getTokenPrice":
|
|
3619
|
+
return await this.handleGetTokenPrice(args);
|
|
3620
|
+
case "t402/getGasPrice":
|
|
3621
|
+
return await this.handleGetGasPrice(args);
|
|
3622
|
+
case "t402/estimatePaymentFee":
|
|
3623
|
+
return await this.handleEstimatePaymentFee(args);
|
|
3624
|
+
case "t402/compareNetworkFees":
|
|
3625
|
+
return await this.handleCompareNetworkFees(args);
|
|
3626
|
+
// Quote-based tools
|
|
3627
|
+
case "t402/quoteBridge":
|
|
3628
|
+
return await this.handleQuoteBridge(args);
|
|
3629
|
+
case "t402/executeBridgeQuote":
|
|
3630
|
+
return await this.handleExecuteBridgeQuote(args);
|
|
3631
|
+
case "wdk/quoteSwap":
|
|
3632
|
+
return await this.handleWdkQuoteSwap(args);
|
|
3633
|
+
case "wdk/executeSwap":
|
|
3634
|
+
return await this.handleWdkExecuteSwap(args);
|
|
2567
3635
|
// ERC-8004 tools
|
|
2568
3636
|
case "erc8004/resolveAgent":
|
|
2569
3637
|
return await this.handleErc8004ResolveAgent(args);
|
|
@@ -2625,6 +3693,28 @@ var T402McpServer = class {
|
|
|
2625
3693
|
]
|
|
2626
3694
|
};
|
|
2627
3695
|
}
|
|
3696
|
+
/**
|
|
3697
|
+
* Format a confirmation prompt for elicitation
|
|
3698
|
+
*/
|
|
3699
|
+
formatConfirmation(result) {
|
|
3700
|
+
const detailLines = Object.entries(result.details).map(([key, value]) => `- **${key}:** ${value}`).join("\n");
|
|
3701
|
+
return {
|
|
3702
|
+
content: [
|
|
3703
|
+
{
|
|
3704
|
+
type: "text",
|
|
3705
|
+
text: [
|
|
3706
|
+
"## Confirmation Required",
|
|
3707
|
+
"",
|
|
3708
|
+
result.summary,
|
|
3709
|
+
"",
|
|
3710
|
+
detailLines,
|
|
3711
|
+
"",
|
|
3712
|
+
"_Call this tool again with `confirmed: true` to execute._"
|
|
3713
|
+
].join("\n")
|
|
3714
|
+
}
|
|
3715
|
+
]
|
|
3716
|
+
};
|
|
3717
|
+
}
|
|
2628
3718
|
/**
|
|
2629
3719
|
* Handle t402/pay
|
|
2630
3720
|
*/
|
|
@@ -2640,6 +3730,9 @@ var T402McpServer = class {
|
|
|
2640
3730
|
rpcUrl: this.config.rpcUrls?.[input.network],
|
|
2641
3731
|
demoMode: this.config.demoMode
|
|
2642
3732
|
});
|
|
3733
|
+
if ("needsConfirmation" in result) {
|
|
3734
|
+
return this.formatConfirmation(result);
|
|
3735
|
+
}
|
|
2643
3736
|
return {
|
|
2644
3737
|
content: [
|
|
2645
3738
|
{
|
|
@@ -2676,6 +3769,9 @@ var T402McpServer = class {
|
|
|
2676
3769
|
rpcUrl: this.config.rpcUrls?.[input.network],
|
|
2677
3770
|
demoMode: this.config.demoMode
|
|
2678
3771
|
});
|
|
3772
|
+
if ("needsConfirmation" in result) {
|
|
3773
|
+
return this.formatConfirmation(result);
|
|
3774
|
+
}
|
|
2679
3775
|
return {
|
|
2680
3776
|
content: [
|
|
2681
3777
|
{
|
|
@@ -2715,6 +3811,9 @@ var T402McpServer = class {
|
|
|
2715
3811
|
rpcUrl: this.config.rpcUrls?.[input.fromChain],
|
|
2716
3812
|
demoMode: this.config.demoMode
|
|
2717
3813
|
});
|
|
3814
|
+
if ("needsConfirmation" in result) {
|
|
3815
|
+
return this.formatConfirmation(result);
|
|
3816
|
+
}
|
|
2718
3817
|
return {
|
|
2719
3818
|
content: [
|
|
2720
3819
|
{
|
|
@@ -2751,6 +3850,9 @@ var T402McpServer = class {
|
|
|
2751
3850
|
async handleWdkTransfer(args) {
|
|
2752
3851
|
const input = wdkTransferInputSchema.parse(args);
|
|
2753
3852
|
const result = this.config.demoMode || !this.wdk ? executeWdkTransferDemo(input) : await executeWdkTransfer(input, this.wdk);
|
|
3853
|
+
if ("needsConfirmation" in result) {
|
|
3854
|
+
return this.formatConfirmation(result);
|
|
3855
|
+
}
|
|
2754
3856
|
return {
|
|
2755
3857
|
content: [{ type: "text", text: formatWdkTransferResult(result) }]
|
|
2756
3858
|
};
|
|
@@ -2761,6 +3863,9 @@ var T402McpServer = class {
|
|
|
2761
3863
|
async handleWdkSwap(args) {
|
|
2762
3864
|
const input = wdkSwapInputSchema.parse(args);
|
|
2763
3865
|
const result = this.config.demoMode || !this.wdk ? executeWdkSwapDemo(input) : await executeWdkSwap(input, this.wdk);
|
|
3866
|
+
if ("needsConfirmation" in result) {
|
|
3867
|
+
return this.formatConfirmation(result);
|
|
3868
|
+
}
|
|
2764
3869
|
return {
|
|
2765
3870
|
content: [{ type: "text", text: formatWdkSwapResult(result) }]
|
|
2766
3871
|
};
|
|
@@ -2771,6 +3876,9 @@ var T402McpServer = class {
|
|
|
2771
3876
|
async handleAutoPay(args) {
|
|
2772
3877
|
const input = autoPayInputSchema.parse(args);
|
|
2773
3878
|
const result = this.config.demoMode || !this.wdk ? executeAutoPayDemo(input) : await executeAutoPay(input, this.wdk);
|
|
3879
|
+
if ("needsConfirmation" in result) {
|
|
3880
|
+
return this.formatConfirmation(result);
|
|
3881
|
+
}
|
|
2774
3882
|
return {
|
|
2775
3883
|
content: [{ type: "text", text: formatAutoPayResult(result) }]
|
|
2776
3884
|
};
|
|
@@ -2782,6 +3890,9 @@ var T402McpServer = class {
|
|
|
2782
3890
|
async handleSmartPay(args) {
|
|
2783
3891
|
const input = smartPayInputSchema.parse(args);
|
|
2784
3892
|
const result = this.config.demoMode || !this.wdk ? executeSmartPayDemo(input) : await executeSmartPay(input, this.wdk);
|
|
3893
|
+
if ("needsConfirmation" in result) {
|
|
3894
|
+
return this.formatConfirmation(result);
|
|
3895
|
+
}
|
|
2785
3896
|
return {
|
|
2786
3897
|
content: [{ type: "text", text: formatSmartPayResult(result) }]
|
|
2787
3898
|
};
|
|
@@ -2796,6 +3907,111 @@ var T402McpServer = class {
|
|
|
2796
3907
|
content: [{ type: "text", text: formatPaymentPlanResult(result) }]
|
|
2797
3908
|
};
|
|
2798
3909
|
}
|
|
3910
|
+
// ---- Price and Fee Tool Handlers ----
|
|
3911
|
+
/**
|
|
3912
|
+
* Handle t402/getTokenPrice
|
|
3913
|
+
*/
|
|
3914
|
+
async handleGetTokenPrice(args) {
|
|
3915
|
+
const input = getTokenPriceInputSchema.parse(args);
|
|
3916
|
+
const result = await executeGetTokenPrice(input, { demoMode: this.config.demoMode });
|
|
3917
|
+
return {
|
|
3918
|
+
content: [{ type: "text", text: formatTokenPriceResult(result) }]
|
|
3919
|
+
};
|
|
3920
|
+
}
|
|
3921
|
+
/**
|
|
3922
|
+
* Handle t402/getGasPrice
|
|
3923
|
+
*/
|
|
3924
|
+
async handleGetGasPrice(args) {
|
|
3925
|
+
const input = getGasPriceInputSchema.parse(args);
|
|
3926
|
+
const result = await executeGetGasPrice(input, {
|
|
3927
|
+
rpcUrl: this.config.rpcUrls?.[input.network],
|
|
3928
|
+
demoMode: this.config.demoMode
|
|
3929
|
+
});
|
|
3930
|
+
return {
|
|
3931
|
+
content: [{ type: "text", text: formatGasPriceResult(result) }]
|
|
3932
|
+
};
|
|
3933
|
+
}
|
|
3934
|
+
/**
|
|
3935
|
+
* Handle t402/estimatePaymentFee
|
|
3936
|
+
*/
|
|
3937
|
+
async handleEstimatePaymentFee(args) {
|
|
3938
|
+
const input = estimatePaymentFeeInputSchema.parse(args);
|
|
3939
|
+
const result = await executeEstimatePaymentFee(input, {
|
|
3940
|
+
rpcUrl: this.config.rpcUrls?.[input.network],
|
|
3941
|
+
demoMode: this.config.demoMode
|
|
3942
|
+
});
|
|
3943
|
+
return {
|
|
3944
|
+
content: [{ type: "text", text: formatPaymentFeeEstimate(result) }]
|
|
3945
|
+
};
|
|
3946
|
+
}
|
|
3947
|
+
/**
|
|
3948
|
+
* Handle t402/compareNetworkFees
|
|
3949
|
+
*/
|
|
3950
|
+
async handleCompareNetworkFees(args) {
|
|
3951
|
+
const input = compareNetworkFeesInputSchema.parse(args);
|
|
3952
|
+
const result = await executeCompareNetworkFees(input, {
|
|
3953
|
+
rpcUrls: this.config.rpcUrls,
|
|
3954
|
+
demoMode: this.config.demoMode
|
|
3955
|
+
});
|
|
3956
|
+
return {
|
|
3957
|
+
content: [{ type: "text", text: formatNetworkFeeComparison(result) }]
|
|
3958
|
+
};
|
|
3959
|
+
}
|
|
3960
|
+
// ---- Quote-based Tool Handlers ----
|
|
3961
|
+
/**
|
|
3962
|
+
* Handle t402/quoteBridge
|
|
3963
|
+
*/
|
|
3964
|
+
async handleQuoteBridge(args) {
|
|
3965
|
+
const input = quoteBridgeInputSchema.parse(args);
|
|
3966
|
+
const result = this.config.demoMode ? executeQuoteBridgeDemo(input) : await executeQuoteBridge(input, this.config.rpcUrls);
|
|
3967
|
+
return {
|
|
3968
|
+
content: [{ type: "text", text: formatBridgeQuoteResult(result) }]
|
|
3969
|
+
};
|
|
3970
|
+
}
|
|
3971
|
+
/**
|
|
3972
|
+
* Handle t402/executeBridgeQuote
|
|
3973
|
+
*/
|
|
3974
|
+
async handleExecuteBridgeQuote(args) {
|
|
3975
|
+
if (!this.config.privateKey && !this.config.demoMode) {
|
|
3976
|
+
throw new Error(
|
|
3977
|
+
"Private key not configured. Set T402_PRIVATE_KEY environment variable or enable demo mode."
|
|
3978
|
+
);
|
|
3979
|
+
}
|
|
3980
|
+
const input = executeBridgeFromQuoteInputSchema.parse(args);
|
|
3981
|
+
const result = this.config.demoMode ? executeExecuteBridgeFromQuoteDemo(input) : await executeExecuteBridgeFromQuote(input, {
|
|
3982
|
+
privateKey: this.config.privateKey || "0x",
|
|
3983
|
+
demoMode: this.config.demoMode
|
|
3984
|
+
});
|
|
3985
|
+
if ("needsConfirmation" in result) {
|
|
3986
|
+
return this.formatConfirmation(result);
|
|
3987
|
+
}
|
|
3988
|
+
return {
|
|
3989
|
+
content: [{ type: "text", text: formatBridgeResult(result) }]
|
|
3990
|
+
};
|
|
3991
|
+
}
|
|
3992
|
+
/**
|
|
3993
|
+
* Handle wdk/quoteSwap
|
|
3994
|
+
*/
|
|
3995
|
+
async handleWdkQuoteSwap(args) {
|
|
3996
|
+
const input = wdkQuoteSwapInputSchema.parse(args);
|
|
3997
|
+
const result = this.config.demoMode || !this.wdk ? executeWdkQuoteSwapDemo(input) : await executeWdkQuoteSwap(input, this.wdk);
|
|
3998
|
+
return {
|
|
3999
|
+
content: [{ type: "text", text: formatSwapQuoteResult(result) }]
|
|
4000
|
+
};
|
|
4001
|
+
}
|
|
4002
|
+
/**
|
|
4003
|
+
* Handle wdk/executeSwap
|
|
4004
|
+
*/
|
|
4005
|
+
async handleWdkExecuteSwap(args) {
|
|
4006
|
+
const input = wdkExecuteSwapInputSchema.parse(args);
|
|
4007
|
+
const result = this.config.demoMode || !this.wdk ? executeWdkExecuteSwapDemo(input) : await executeWdkExecuteSwap(input, this.wdk);
|
|
4008
|
+
if ("needsConfirmation" in result) {
|
|
4009
|
+
return this.formatConfirmation(result);
|
|
4010
|
+
}
|
|
4011
|
+
return {
|
|
4012
|
+
content: [{ type: "text", text: formatExecuteSwapResult(result) }]
|
|
4013
|
+
};
|
|
4014
|
+
}
|
|
2799
4015
|
// ---- ERC-8004 Tool Handlers ----
|
|
2800
4016
|
/**
|
|
2801
4017
|
* Handle erc8004/resolveAgent
|