@t402/mcp 1.0.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/README.md +228 -0
- package/bin/t402-mcp.js +53 -0
- package/dist/cjs/index.d.ts +69 -0
- package/dist/cjs/index.js +1692 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/server/index.d.ts +59 -0
- package/dist/cjs/server/index.js +1613 -0
- package/dist/cjs/server/index.js.map +1 -0
- package/dist/cjs/tools/index.d.ts +424 -0
- package/dist/cjs/tools/index.js +1404 -0
- package/dist/cjs/tools/index.js.map +1 -0
- package/dist/cjs/types-BINGE6ja.d.ts +147 -0
- package/dist/esm/chunk-AN6P2M7N.mjs +272 -0
- package/dist/esm/chunk-AN6P2M7N.mjs.map +1 -0
- package/dist/esm/chunk-SB4O25HA.mjs +1399 -0
- package/dist/esm/chunk-SB4O25HA.mjs.map +1 -0
- package/dist/esm/index.d.mts +69 -0
- package/dist/esm/index.mjs +81 -0
- package/dist/esm/index.mjs.map +1 -0
- package/dist/esm/server/index.d.mts +59 -0
- package/dist/esm/server/index.mjs +12 -0
- package/dist/esm/server/index.mjs.map +1 -0
- package/dist/esm/tools/index.d.mts +424 -0
- package/dist/esm/tools/index.mjs +45 -0
- package/dist/esm/tools/index.mjs.map +1 -0
- package/dist/esm/types-BINGE6ja.d.mts +147 -0
- package/package.json +93 -0
|
@@ -0,0 +1,1404 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/tools/index.ts
|
|
31
|
+
var tools_exports = {};
|
|
32
|
+
__export(tools_exports, {
|
|
33
|
+
GASLESS_SUPPORTED_NETWORKS: () => GASLESS_SUPPORTED_NETWORKS,
|
|
34
|
+
TOOL_DEFINITIONS: () => TOOL_DEFINITIONS,
|
|
35
|
+
bridgeInputSchema: () => bridgeInputSchema,
|
|
36
|
+
executeBridge: () => executeBridge,
|
|
37
|
+
executeGetAllBalances: () => executeGetAllBalances,
|
|
38
|
+
executeGetBalance: () => executeGetBalance,
|
|
39
|
+
executeGetBridgeFee: () => executeGetBridgeFee,
|
|
40
|
+
executePay: () => executePay,
|
|
41
|
+
executePayGasless: () => executePayGasless,
|
|
42
|
+
formatAllBalancesResult: () => formatAllBalancesResult,
|
|
43
|
+
formatBalanceResult: () => formatBalanceResult,
|
|
44
|
+
formatBridgeFeeResult: () => formatBridgeFeeResult,
|
|
45
|
+
formatBridgeResult: () => formatBridgeResult,
|
|
46
|
+
formatGaslessPaymentResult: () => formatGaslessPaymentResult,
|
|
47
|
+
formatPaymentResult: () => formatPaymentResult,
|
|
48
|
+
getAllBalancesInputSchema: () => getAllBalancesInputSchema,
|
|
49
|
+
getBalanceInputSchema: () => getBalanceInputSchema,
|
|
50
|
+
getBridgeFeeInputSchema: () => getBridgeFeeInputSchema,
|
|
51
|
+
payGaslessInputSchema: () => payGaslessInputSchema,
|
|
52
|
+
payInputSchema: () => payInputSchema
|
|
53
|
+
});
|
|
54
|
+
module.exports = __toCommonJS(tools_exports);
|
|
55
|
+
|
|
56
|
+
// src/tools/getBalance.ts
|
|
57
|
+
var import_zod = require("zod");
|
|
58
|
+
var import_viem = require("viem");
|
|
59
|
+
var chains = __toESM(require("viem/chains"));
|
|
60
|
+
|
|
61
|
+
// src/constants.ts
|
|
62
|
+
var CHAIN_IDS = {
|
|
63
|
+
ethereum: 1,
|
|
64
|
+
base: 8453,
|
|
65
|
+
arbitrum: 42161,
|
|
66
|
+
optimism: 10,
|
|
67
|
+
polygon: 137,
|
|
68
|
+
avalanche: 43114,
|
|
69
|
+
ink: 57073,
|
|
70
|
+
berachain: 80094,
|
|
71
|
+
unichain: 130
|
|
72
|
+
};
|
|
73
|
+
var NATIVE_SYMBOLS = {
|
|
74
|
+
ethereum: "ETH",
|
|
75
|
+
base: "ETH",
|
|
76
|
+
arbitrum: "ETH",
|
|
77
|
+
optimism: "ETH",
|
|
78
|
+
polygon: "MATIC",
|
|
79
|
+
avalanche: "AVAX",
|
|
80
|
+
ink: "ETH",
|
|
81
|
+
berachain: "BERA",
|
|
82
|
+
unichain: "ETH"
|
|
83
|
+
};
|
|
84
|
+
var EXPLORER_URLS = {
|
|
85
|
+
ethereum: "https://etherscan.io",
|
|
86
|
+
base: "https://basescan.org",
|
|
87
|
+
arbitrum: "https://arbiscan.io",
|
|
88
|
+
optimism: "https://optimistic.etherscan.io",
|
|
89
|
+
polygon: "https://polygonscan.com",
|
|
90
|
+
avalanche: "https://snowtrace.io",
|
|
91
|
+
ink: "https://explorer.inkonchain.com",
|
|
92
|
+
berachain: "https://berascan.com",
|
|
93
|
+
unichain: "https://unichain.blockscout.com"
|
|
94
|
+
};
|
|
95
|
+
var DEFAULT_RPC_URLS = {
|
|
96
|
+
ethereum: "https://eth.llamarpc.com",
|
|
97
|
+
base: "https://mainnet.base.org",
|
|
98
|
+
arbitrum: "https://arb1.arbitrum.io/rpc",
|
|
99
|
+
optimism: "https://mainnet.optimism.io",
|
|
100
|
+
polygon: "https://polygon-rpc.com",
|
|
101
|
+
avalanche: "https://api.avax.network/ext/bc/C/rpc",
|
|
102
|
+
ink: "https://rpc-gel.inkonchain.com",
|
|
103
|
+
berachain: "https://rpc.berachain.com",
|
|
104
|
+
unichain: "https://mainnet.unichain.org"
|
|
105
|
+
};
|
|
106
|
+
var USDC_ADDRESSES = {
|
|
107
|
+
ethereum: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
108
|
+
base: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
109
|
+
arbitrum: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
|
|
110
|
+
optimism: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",
|
|
111
|
+
polygon: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
|
|
112
|
+
avalanche: "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E"
|
|
113
|
+
};
|
|
114
|
+
var USDT_ADDRESSES = {
|
|
115
|
+
ethereum: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
|
116
|
+
arbitrum: "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9",
|
|
117
|
+
polygon: "0xc2132D05D31c914a87C6611C10748AEb04B58e8F",
|
|
118
|
+
avalanche: "0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7",
|
|
119
|
+
optimism: "0x94b008aA00579c1307B0EF2c499aD98a8ce58e58"
|
|
120
|
+
};
|
|
121
|
+
var USDT0_ADDRESSES = {
|
|
122
|
+
ethereum: "0x6C96dE32CEa08842dcc4058c14d3aaAD7Fa41dee",
|
|
123
|
+
arbitrum: "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9",
|
|
124
|
+
ink: "0x0200C29006150606B650577BBE7B6248F58470c1",
|
|
125
|
+
berachain: "0x779Ded0c9e1022225f8E0630b35a9b54bE713736",
|
|
126
|
+
unichain: "0x588ce4F028D8e7B53B687865d6A67b3A54C75518"
|
|
127
|
+
};
|
|
128
|
+
var BRIDGEABLE_CHAINS = [
|
|
129
|
+
"ethereum",
|
|
130
|
+
"arbitrum",
|
|
131
|
+
"ink",
|
|
132
|
+
"berachain",
|
|
133
|
+
"unichain"
|
|
134
|
+
];
|
|
135
|
+
var ERC20_ABI = [
|
|
136
|
+
{
|
|
137
|
+
name: "balanceOf",
|
|
138
|
+
type: "function",
|
|
139
|
+
stateMutability: "view",
|
|
140
|
+
inputs: [{ name: "account", type: "address" }],
|
|
141
|
+
outputs: [{ name: "", type: "uint256" }]
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
name: "decimals",
|
|
145
|
+
type: "function",
|
|
146
|
+
stateMutability: "view",
|
|
147
|
+
inputs: [],
|
|
148
|
+
outputs: [{ name: "", type: "uint8" }]
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
name: "symbol",
|
|
152
|
+
type: "function",
|
|
153
|
+
stateMutability: "view",
|
|
154
|
+
inputs: [],
|
|
155
|
+
outputs: [{ name: "", type: "string" }]
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
name: "transfer",
|
|
159
|
+
type: "function",
|
|
160
|
+
stateMutability: "nonpayable",
|
|
161
|
+
inputs: [
|
|
162
|
+
{ name: "to", type: "address" },
|
|
163
|
+
{ name: "amount", type: "uint256" }
|
|
164
|
+
],
|
|
165
|
+
outputs: [{ name: "", type: "bool" }]
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
name: "approve",
|
|
169
|
+
type: "function",
|
|
170
|
+
stateMutability: "nonpayable",
|
|
171
|
+
inputs: [
|
|
172
|
+
{ name: "spender", type: "address" },
|
|
173
|
+
{ name: "amount", type: "uint256" }
|
|
174
|
+
],
|
|
175
|
+
outputs: [{ name: "", type: "bool" }]
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
name: "allowance",
|
|
179
|
+
type: "function",
|
|
180
|
+
stateMutability: "view",
|
|
181
|
+
inputs: [
|
|
182
|
+
{ name: "owner", type: "address" },
|
|
183
|
+
{ name: "spender", type: "address" }
|
|
184
|
+
],
|
|
185
|
+
outputs: [{ name: "", type: "uint256" }]
|
|
186
|
+
}
|
|
187
|
+
];
|
|
188
|
+
function getExplorerTxUrl(network, txHash) {
|
|
189
|
+
return `${EXPLORER_URLS[network]}/tx/${txHash}`;
|
|
190
|
+
}
|
|
191
|
+
function getLayerZeroScanUrl(messageGuid) {
|
|
192
|
+
return `https://layerzeroscan.com/tx/${messageGuid}`;
|
|
193
|
+
}
|
|
194
|
+
function supportsToken(network, token) {
|
|
195
|
+
switch (token) {
|
|
196
|
+
case "USDC":
|
|
197
|
+
return network in USDC_ADDRESSES;
|
|
198
|
+
case "USDT":
|
|
199
|
+
return network in USDT_ADDRESSES;
|
|
200
|
+
case "USDT0":
|
|
201
|
+
return network in USDT0_ADDRESSES;
|
|
202
|
+
default:
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
function getTokenAddress(network, token) {
|
|
207
|
+
switch (token) {
|
|
208
|
+
case "USDC":
|
|
209
|
+
return USDC_ADDRESSES[network];
|
|
210
|
+
case "USDT":
|
|
211
|
+
return USDT_ADDRESSES[network];
|
|
212
|
+
case "USDT0":
|
|
213
|
+
return USDT0_ADDRESSES[network];
|
|
214
|
+
default:
|
|
215
|
+
return void 0;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
function parseTokenAmount(amount, decimals) {
|
|
219
|
+
const [wholePart, fractionalPart = ""] = amount.split(".");
|
|
220
|
+
const paddedFractional = fractionalPart.padEnd(decimals, "0").slice(0, decimals);
|
|
221
|
+
return BigInt(wholePart + paddedFractional);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// src/tools/getBalance.ts
|
|
225
|
+
var getBalanceInputSchema = import_zod.z.object({
|
|
226
|
+
network: import_zod.z.enum([
|
|
227
|
+
"ethereum",
|
|
228
|
+
"base",
|
|
229
|
+
"arbitrum",
|
|
230
|
+
"optimism",
|
|
231
|
+
"polygon",
|
|
232
|
+
"avalanche",
|
|
233
|
+
"ink",
|
|
234
|
+
"berachain",
|
|
235
|
+
"unichain"
|
|
236
|
+
]).describe("Blockchain network to check balance on"),
|
|
237
|
+
address: import_zod.z.string().regex(/^0x[a-fA-F0-9]{40}$/).describe("Wallet address to check balance for")
|
|
238
|
+
});
|
|
239
|
+
function getViemChain(network) {
|
|
240
|
+
switch (network) {
|
|
241
|
+
case "ethereum":
|
|
242
|
+
return chains.mainnet;
|
|
243
|
+
case "base":
|
|
244
|
+
return chains.base;
|
|
245
|
+
case "arbitrum":
|
|
246
|
+
return chains.arbitrum;
|
|
247
|
+
case "optimism":
|
|
248
|
+
return chains.optimism;
|
|
249
|
+
case "polygon":
|
|
250
|
+
return chains.polygon;
|
|
251
|
+
case "avalanche":
|
|
252
|
+
return chains.avalanche;
|
|
253
|
+
case "ink":
|
|
254
|
+
return chains.ink;
|
|
255
|
+
case "berachain":
|
|
256
|
+
return chains.berachain;
|
|
257
|
+
case "unichain":
|
|
258
|
+
return chains.unichain;
|
|
259
|
+
default:
|
|
260
|
+
return chains.mainnet;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
async function getTokenBalance(client, tokenAddress, walletAddress) {
|
|
264
|
+
try {
|
|
265
|
+
const [balance, decimals, symbol] = await Promise.all([
|
|
266
|
+
client.readContract({
|
|
267
|
+
address: tokenAddress,
|
|
268
|
+
abi: ERC20_ABI,
|
|
269
|
+
functionName: "balanceOf",
|
|
270
|
+
args: [walletAddress]
|
|
271
|
+
}),
|
|
272
|
+
client.readContract({
|
|
273
|
+
address: tokenAddress,
|
|
274
|
+
abi: ERC20_ABI,
|
|
275
|
+
functionName: "decimals"
|
|
276
|
+
}),
|
|
277
|
+
client.readContract({
|
|
278
|
+
address: tokenAddress,
|
|
279
|
+
abi: ERC20_ABI,
|
|
280
|
+
functionName: "symbol"
|
|
281
|
+
})
|
|
282
|
+
]);
|
|
283
|
+
return {
|
|
284
|
+
symbol,
|
|
285
|
+
address: tokenAddress,
|
|
286
|
+
balance: balance.toString(),
|
|
287
|
+
formatted: (0, import_viem.formatUnits)(balance, decimals),
|
|
288
|
+
decimals
|
|
289
|
+
};
|
|
290
|
+
} catch {
|
|
291
|
+
return null;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
async function executeGetBalance(input, rpcUrls) {
|
|
295
|
+
const { network, address } = input;
|
|
296
|
+
const walletAddress = address;
|
|
297
|
+
const rpcUrl = rpcUrls?.[network] || DEFAULT_RPC_URLS[network];
|
|
298
|
+
const chain = getViemChain(network);
|
|
299
|
+
const client = (0, import_viem.createPublicClient)({
|
|
300
|
+
chain,
|
|
301
|
+
transport: (0, import_viem.http)(rpcUrl)
|
|
302
|
+
});
|
|
303
|
+
const nativeBalance = await client.getBalance({ address: walletAddress });
|
|
304
|
+
const tokenAddresses = [];
|
|
305
|
+
if (USDC_ADDRESSES[network]) {
|
|
306
|
+
tokenAddresses.push({ token: USDC_ADDRESSES[network], expected: "USDC" });
|
|
307
|
+
}
|
|
308
|
+
if (USDT_ADDRESSES[network]) {
|
|
309
|
+
tokenAddresses.push({ token: USDT_ADDRESSES[network], expected: "USDT" });
|
|
310
|
+
}
|
|
311
|
+
if (USDT0_ADDRESSES[network]) {
|
|
312
|
+
tokenAddresses.push({ token: USDT0_ADDRESSES[network], expected: "USDT0" });
|
|
313
|
+
}
|
|
314
|
+
const tokenBalances = await Promise.all(
|
|
315
|
+
tokenAddresses.map(
|
|
316
|
+
({ token }) => getTokenBalance(client, token, walletAddress)
|
|
317
|
+
)
|
|
318
|
+
);
|
|
319
|
+
const tokens = tokenBalances.filter(
|
|
320
|
+
(t) => t !== null
|
|
321
|
+
);
|
|
322
|
+
return {
|
|
323
|
+
network,
|
|
324
|
+
chainId: CHAIN_IDS[network],
|
|
325
|
+
native: {
|
|
326
|
+
symbol: NATIVE_SYMBOLS[network],
|
|
327
|
+
balance: nativeBalance.toString(),
|
|
328
|
+
formatted: (0, import_viem.formatEther)(nativeBalance)
|
|
329
|
+
},
|
|
330
|
+
tokens
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
function formatBalanceResult(balance) {
|
|
334
|
+
const lines = [
|
|
335
|
+
`## Balance on ${balance.network} (Chain ID: ${balance.chainId})`,
|
|
336
|
+
"",
|
|
337
|
+
`### Native Token`,
|
|
338
|
+
`- ${balance.native.symbol}: ${balance.native.formatted}`,
|
|
339
|
+
""
|
|
340
|
+
];
|
|
341
|
+
if (balance.tokens.length > 0) {
|
|
342
|
+
lines.push("### Stablecoins");
|
|
343
|
+
for (const token of balance.tokens) {
|
|
344
|
+
lines.push(`- ${token.symbol}: ${token.formatted}`);
|
|
345
|
+
}
|
|
346
|
+
} else {
|
|
347
|
+
lines.push("_No stablecoin balances found_");
|
|
348
|
+
}
|
|
349
|
+
return lines.join("\n");
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// src/tools/getAllBalances.ts
|
|
353
|
+
var import_zod2 = require("zod");
|
|
354
|
+
var getAllBalancesInputSchema = import_zod2.z.object({
|
|
355
|
+
address: import_zod2.z.string().regex(/^0x[a-fA-F0-9]{40}$/).describe("Wallet address to check balances for"),
|
|
356
|
+
networks: import_zod2.z.array(
|
|
357
|
+
import_zod2.z.enum([
|
|
358
|
+
"ethereum",
|
|
359
|
+
"base",
|
|
360
|
+
"arbitrum",
|
|
361
|
+
"optimism",
|
|
362
|
+
"polygon",
|
|
363
|
+
"avalanche",
|
|
364
|
+
"ink",
|
|
365
|
+
"berachain",
|
|
366
|
+
"unichain"
|
|
367
|
+
])
|
|
368
|
+
).optional().describe(
|
|
369
|
+
"Optional list of networks to check. If not provided, checks all supported networks."
|
|
370
|
+
)
|
|
371
|
+
});
|
|
372
|
+
var ALL_NETWORKS = [
|
|
373
|
+
"ethereum",
|
|
374
|
+
"base",
|
|
375
|
+
"arbitrum",
|
|
376
|
+
"optimism",
|
|
377
|
+
"polygon",
|
|
378
|
+
"avalanche",
|
|
379
|
+
"ink",
|
|
380
|
+
"berachain",
|
|
381
|
+
"unichain"
|
|
382
|
+
];
|
|
383
|
+
async function executeGetAllBalances(input, rpcUrls) {
|
|
384
|
+
const { address, networks = ALL_NETWORKS } = input;
|
|
385
|
+
const balancePromises = networks.map(
|
|
386
|
+
(network) => executeGetBalance({ network, address }, rpcUrls).catch((error) => {
|
|
387
|
+
console.error(`Failed to fetch balance for ${network}:`, error);
|
|
388
|
+
return null;
|
|
389
|
+
})
|
|
390
|
+
);
|
|
391
|
+
const results = await Promise.all(balancePromises);
|
|
392
|
+
const balances = results.filter((b) => b !== null);
|
|
393
|
+
let totalUsdc = 0n;
|
|
394
|
+
let totalUsdt = 0n;
|
|
395
|
+
for (const balance of balances) {
|
|
396
|
+
for (const token of balance.tokens) {
|
|
397
|
+
if (token.symbol === "USDC") {
|
|
398
|
+
totalUsdc += BigInt(token.balance);
|
|
399
|
+
} else if (token.symbol === "USDT" || token.symbol === "USDT0") {
|
|
400
|
+
totalUsdt += BigInt(token.balance);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
const formatTotal = (amount) => {
|
|
405
|
+
const divisor = BigInt(10 ** 6);
|
|
406
|
+
const whole = amount / divisor;
|
|
407
|
+
const fraction = amount % divisor;
|
|
408
|
+
const fractionStr = fraction.toString().padStart(6, "0").replace(/0+$/, "");
|
|
409
|
+
return fractionStr ? `${whole}.${fractionStr}` : whole.toString();
|
|
410
|
+
};
|
|
411
|
+
const totalUsdcFormatted = formatTotal(totalUsdc);
|
|
412
|
+
const totalUsdtFormatted = formatTotal(totalUsdt);
|
|
413
|
+
const chainsWithBalance = balances.filter(
|
|
414
|
+
(b) => b.tokens.some((t) => BigInt(t.balance) > 0n) || BigInt(b.native.balance) > 0n
|
|
415
|
+
);
|
|
416
|
+
const summary = [
|
|
417
|
+
`Found balances on ${chainsWithBalance.length} of ${balances.length} networks checked.`,
|
|
418
|
+
`Total USDC: ${totalUsdcFormatted}`,
|
|
419
|
+
`Total USDT: ${totalUsdtFormatted}`
|
|
420
|
+
].join(" ");
|
|
421
|
+
return {
|
|
422
|
+
address,
|
|
423
|
+
balances,
|
|
424
|
+
totalUsdcBalance: totalUsdcFormatted,
|
|
425
|
+
totalUsdtBalance: totalUsdtFormatted,
|
|
426
|
+
summary
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
function formatAllBalancesResult(result) {
|
|
430
|
+
const lines = [
|
|
431
|
+
`## Multi-Chain Balance Summary`,
|
|
432
|
+
`**Address:** \`${result.address}\``,
|
|
433
|
+
"",
|
|
434
|
+
`### Totals`,
|
|
435
|
+
`- **Total USDC:** ${result.totalUsdcBalance}`,
|
|
436
|
+
`- **Total USDT:** ${result.totalUsdtBalance}`,
|
|
437
|
+
"",
|
|
438
|
+
`### By Network`,
|
|
439
|
+
""
|
|
440
|
+
];
|
|
441
|
+
for (const balance of result.balances) {
|
|
442
|
+
const hasBalance = balance.tokens.some((t) => BigInt(t.balance) > 0n) || BigInt(balance.native.balance) > 0n;
|
|
443
|
+
if (!hasBalance) continue;
|
|
444
|
+
lines.push(`#### ${balance.network}`);
|
|
445
|
+
lines.push(`- ${balance.native.symbol}: ${balance.native.formatted}`);
|
|
446
|
+
for (const token of balance.tokens) {
|
|
447
|
+
if (BigInt(token.balance) > 0n) {
|
|
448
|
+
lines.push(`- ${token.symbol}: ${token.formatted}`);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
lines.push("");
|
|
452
|
+
}
|
|
453
|
+
const emptyNetworks = result.balances.filter(
|
|
454
|
+
(b) => !b.tokens.some((t) => BigInt(t.balance) > 0n) && BigInt(b.native.balance) === 0n
|
|
455
|
+
);
|
|
456
|
+
if (emptyNetworks.length > 0) {
|
|
457
|
+
lines.push(`_No balance on: ${emptyNetworks.map((n) => n.network).join(", ")}_`);
|
|
458
|
+
}
|
|
459
|
+
return lines.join("\n");
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
// src/tools/pay.ts
|
|
463
|
+
var import_zod3 = require("zod");
|
|
464
|
+
var import_viem2 = require("viem");
|
|
465
|
+
var import_accounts = require("viem/accounts");
|
|
466
|
+
var chains2 = __toESM(require("viem/chains"));
|
|
467
|
+
var payInputSchema = import_zod3.z.object({
|
|
468
|
+
to: import_zod3.z.string().regex(/^0x[a-fA-F0-9]{40}$/).describe("Recipient address"),
|
|
469
|
+
amount: import_zod3.z.string().regex(/^\d+(\.\d+)?$/).describe("Amount to pay (e.g., '10.50' for 10.50 USDC)"),
|
|
470
|
+
token: import_zod3.z.enum(["USDC", "USDT", "USDT0"]).describe("Token to use for payment"),
|
|
471
|
+
network: import_zod3.z.enum([
|
|
472
|
+
"ethereum",
|
|
473
|
+
"base",
|
|
474
|
+
"arbitrum",
|
|
475
|
+
"optimism",
|
|
476
|
+
"polygon",
|
|
477
|
+
"avalanche",
|
|
478
|
+
"ink",
|
|
479
|
+
"berachain",
|
|
480
|
+
"unichain"
|
|
481
|
+
]).describe("Network to execute payment on"),
|
|
482
|
+
memo: import_zod3.z.string().optional().describe("Optional memo/reference for the payment")
|
|
483
|
+
});
|
|
484
|
+
function getViemChain2(network) {
|
|
485
|
+
switch (network) {
|
|
486
|
+
case "ethereum":
|
|
487
|
+
return chains2.mainnet;
|
|
488
|
+
case "base":
|
|
489
|
+
return chains2.base;
|
|
490
|
+
case "arbitrum":
|
|
491
|
+
return chains2.arbitrum;
|
|
492
|
+
case "optimism":
|
|
493
|
+
return chains2.optimism;
|
|
494
|
+
case "polygon":
|
|
495
|
+
return chains2.polygon;
|
|
496
|
+
case "avalanche":
|
|
497
|
+
return chains2.avalanche;
|
|
498
|
+
case "ink":
|
|
499
|
+
return chains2.ink;
|
|
500
|
+
case "berachain":
|
|
501
|
+
return chains2.berachain;
|
|
502
|
+
case "unichain":
|
|
503
|
+
return chains2.unichain;
|
|
504
|
+
default:
|
|
505
|
+
return chains2.mainnet;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
async function executePay(input, options) {
|
|
509
|
+
const { to, amount, token, network, memo } = input;
|
|
510
|
+
const { privateKey, rpcUrl, demoMode } = options;
|
|
511
|
+
if (!supportsToken(network, token)) {
|
|
512
|
+
throw new Error(`Token ${token} is not supported on ${network}`);
|
|
513
|
+
}
|
|
514
|
+
const tokenAddress = getTokenAddress(network, token);
|
|
515
|
+
if (!tokenAddress) {
|
|
516
|
+
throw new Error(`Could not find ${token} address for ${network}`);
|
|
517
|
+
}
|
|
518
|
+
const decimals = 6;
|
|
519
|
+
const amountBigInt = (0, import_viem2.parseUnits)(amount, decimals);
|
|
520
|
+
if (demoMode) {
|
|
521
|
+
const fakeTxHash = `0x${"0".repeat(64)}`;
|
|
522
|
+
return {
|
|
523
|
+
txHash: fakeTxHash,
|
|
524
|
+
network,
|
|
525
|
+
amount,
|
|
526
|
+
token,
|
|
527
|
+
to,
|
|
528
|
+
explorerUrl: getExplorerTxUrl(network, fakeTxHash)
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
const chain = getViemChain2(network);
|
|
532
|
+
const transport = (0, import_viem2.http)(rpcUrl || DEFAULT_RPC_URLS[network]);
|
|
533
|
+
const account = (0, import_accounts.privateKeyToAccount)(privateKey);
|
|
534
|
+
const publicClient = (0, import_viem2.createPublicClient)({
|
|
535
|
+
chain,
|
|
536
|
+
transport
|
|
537
|
+
});
|
|
538
|
+
const walletClient = (0, import_viem2.createWalletClient)({
|
|
539
|
+
account,
|
|
540
|
+
chain,
|
|
541
|
+
transport
|
|
542
|
+
});
|
|
543
|
+
const balance = await publicClient.readContract({
|
|
544
|
+
address: tokenAddress,
|
|
545
|
+
abi: ERC20_ABI,
|
|
546
|
+
functionName: "balanceOf",
|
|
547
|
+
args: [account.address]
|
|
548
|
+
});
|
|
549
|
+
if (balance < amountBigInt) {
|
|
550
|
+
throw new Error(
|
|
551
|
+
`Insufficient ${token} balance. Have: ${balance.toString()}, Need: ${amountBigInt.toString()}`
|
|
552
|
+
);
|
|
553
|
+
}
|
|
554
|
+
const hash = await walletClient.writeContract({
|
|
555
|
+
address: tokenAddress,
|
|
556
|
+
abi: ERC20_ABI,
|
|
557
|
+
functionName: "transfer",
|
|
558
|
+
args: [to, amountBigInt]
|
|
559
|
+
});
|
|
560
|
+
const receipt = await publicClient.waitForTransactionReceipt({ hash });
|
|
561
|
+
if (receipt.status !== "success") {
|
|
562
|
+
throw new Error(`Transaction failed: ${hash}`);
|
|
563
|
+
}
|
|
564
|
+
return {
|
|
565
|
+
txHash: hash,
|
|
566
|
+
network,
|
|
567
|
+
amount,
|
|
568
|
+
token,
|
|
569
|
+
to,
|
|
570
|
+
explorerUrl: getExplorerTxUrl(network, hash)
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
function formatPaymentResult(result) {
|
|
574
|
+
return [
|
|
575
|
+
`## Payment Successful`,
|
|
576
|
+
"",
|
|
577
|
+
`- **Amount:** ${result.amount} ${result.token}`,
|
|
578
|
+
`- **To:** \`${result.to}\``,
|
|
579
|
+
`- **Network:** ${result.network}`,
|
|
580
|
+
`- **Transaction:** \`${result.txHash}\``,
|
|
581
|
+
"",
|
|
582
|
+
`[View on Explorer](${result.explorerUrl})`
|
|
583
|
+
].join("\n");
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
// src/tools/payGasless.ts
|
|
587
|
+
var import_zod4 = require("zod");
|
|
588
|
+
var import_viem3 = require("viem");
|
|
589
|
+
var import_accounts2 = require("viem/accounts");
|
|
590
|
+
var chains3 = __toESM(require("viem/chains"));
|
|
591
|
+
var payGaslessInputSchema = import_zod4.z.object({
|
|
592
|
+
to: import_zod4.z.string().regex(/^0x[a-fA-F0-9]{40}$/).describe("Recipient address"),
|
|
593
|
+
amount: import_zod4.z.string().regex(/^\d+(\.\d+)?$/).describe("Amount to pay (e.g., '10.50' for 10.50 USDC)"),
|
|
594
|
+
token: import_zod4.z.enum(["USDC", "USDT", "USDT0"]).describe("Token to use for payment"),
|
|
595
|
+
network: import_zod4.z.enum([
|
|
596
|
+
"ethereum",
|
|
597
|
+
"base",
|
|
598
|
+
"arbitrum",
|
|
599
|
+
"optimism",
|
|
600
|
+
"polygon",
|
|
601
|
+
"avalanche"
|
|
602
|
+
]).describe("Network to execute gasless payment on (must support ERC-4337)")
|
|
603
|
+
});
|
|
604
|
+
var GASLESS_SUPPORTED_NETWORKS = [
|
|
605
|
+
"ethereum",
|
|
606
|
+
"base",
|
|
607
|
+
"arbitrum",
|
|
608
|
+
"optimism",
|
|
609
|
+
"polygon",
|
|
610
|
+
"avalanche"
|
|
611
|
+
];
|
|
612
|
+
function getViemChain3(network) {
|
|
613
|
+
switch (network) {
|
|
614
|
+
case "ethereum":
|
|
615
|
+
return chains3.mainnet;
|
|
616
|
+
case "base":
|
|
617
|
+
return chains3.base;
|
|
618
|
+
case "arbitrum":
|
|
619
|
+
return chains3.arbitrum;
|
|
620
|
+
case "optimism":
|
|
621
|
+
return chains3.optimism;
|
|
622
|
+
case "polygon":
|
|
623
|
+
return chains3.polygon;
|
|
624
|
+
case "avalanche":
|
|
625
|
+
return chains3.avalanche;
|
|
626
|
+
case "ink":
|
|
627
|
+
return chains3.ink;
|
|
628
|
+
case "berachain":
|
|
629
|
+
return chains3.berachain;
|
|
630
|
+
case "unichain":
|
|
631
|
+
return chains3.unichain;
|
|
632
|
+
default:
|
|
633
|
+
return chains3.mainnet;
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
async function executePayGasless(input, options) {
|
|
637
|
+
const { to, amount, token, network } = input;
|
|
638
|
+
const { privateKey, bundlerUrl, paymasterUrl, rpcUrl, demoMode } = options;
|
|
639
|
+
if (!GASLESS_SUPPORTED_NETWORKS.includes(network)) {
|
|
640
|
+
throw new Error(
|
|
641
|
+
`Network ${network} does not support ERC-4337 gasless transactions. Supported: ${GASLESS_SUPPORTED_NETWORKS.join(", ")}`
|
|
642
|
+
);
|
|
643
|
+
}
|
|
644
|
+
if (!supportsToken(network, token)) {
|
|
645
|
+
throw new Error(`Token ${token} is not supported on ${network}`);
|
|
646
|
+
}
|
|
647
|
+
const tokenAddress = getTokenAddress(network, token);
|
|
648
|
+
if (!tokenAddress) {
|
|
649
|
+
throw new Error(`Could not find ${token} address for ${network}`);
|
|
650
|
+
}
|
|
651
|
+
const decimals = 6;
|
|
652
|
+
const amountBigInt = (0, import_viem3.parseUnits)(amount, decimals);
|
|
653
|
+
if (demoMode) {
|
|
654
|
+
const fakeTxHash = `0x${"1".repeat(64)}`;
|
|
655
|
+
const fakeUserOpHash = `0x${"2".repeat(64)}`;
|
|
656
|
+
return {
|
|
657
|
+
txHash: fakeTxHash,
|
|
658
|
+
userOpHash: fakeUserOpHash,
|
|
659
|
+
network,
|
|
660
|
+
amount,
|
|
661
|
+
token,
|
|
662
|
+
to,
|
|
663
|
+
explorerUrl: getExplorerTxUrl(network, fakeTxHash),
|
|
664
|
+
paymaster: "demo-paymaster"
|
|
665
|
+
};
|
|
666
|
+
}
|
|
667
|
+
const chain = getViemChain3(network);
|
|
668
|
+
const transport = (0, import_viem3.http)(rpcUrl || DEFAULT_RPC_URLS[network]);
|
|
669
|
+
const account = (0, import_accounts2.privateKeyToAccount)(privateKey);
|
|
670
|
+
const publicClient = (0, import_viem3.createPublicClient)({
|
|
671
|
+
chain,
|
|
672
|
+
transport
|
|
673
|
+
});
|
|
674
|
+
const callData = (0, import_viem3.encodeFunctionData)({
|
|
675
|
+
abi: ERC20_ABI,
|
|
676
|
+
functionName: "transfer",
|
|
677
|
+
args: [to, amountBigInt]
|
|
678
|
+
});
|
|
679
|
+
const nonce = await publicClient.getTransactionCount({
|
|
680
|
+
address: account.address
|
|
681
|
+
});
|
|
682
|
+
const gasPrice = await publicClient.getGasPrice();
|
|
683
|
+
const userOp = {
|
|
684
|
+
sender: account.address,
|
|
685
|
+
nonce: BigInt(nonce),
|
|
686
|
+
initCode: "0x",
|
|
687
|
+
callData,
|
|
688
|
+
callGasLimit: 100000n,
|
|
689
|
+
verificationGasLimit: 100000n,
|
|
690
|
+
preVerificationGas: 50000n,
|
|
691
|
+
maxFeePerGas: gasPrice,
|
|
692
|
+
maxPriorityFeePerGas: gasPrice / 10n,
|
|
693
|
+
paymasterAndData: "0x",
|
|
694
|
+
// Would be filled by paymaster
|
|
695
|
+
signature: "0x"
|
|
696
|
+
};
|
|
697
|
+
const response = await fetch(bundlerUrl, {
|
|
698
|
+
method: "POST",
|
|
699
|
+
headers: { "Content-Type": "application/json" },
|
|
700
|
+
body: JSON.stringify({
|
|
701
|
+
jsonrpc: "2.0",
|
|
702
|
+
id: 1,
|
|
703
|
+
method: "eth_sendUserOperation",
|
|
704
|
+
params: [userOp, chain.id]
|
|
705
|
+
})
|
|
706
|
+
});
|
|
707
|
+
if (!response.ok) {
|
|
708
|
+
throw new Error(`Bundler request failed: ${response.statusText}`);
|
|
709
|
+
}
|
|
710
|
+
const result = await response.json();
|
|
711
|
+
if (result.error) {
|
|
712
|
+
throw new Error(`Bundler error: ${result.error.message}`);
|
|
713
|
+
}
|
|
714
|
+
const userOpHash = result.result;
|
|
715
|
+
let receipt = null;
|
|
716
|
+
for (let i = 0; i < 30; i++) {
|
|
717
|
+
const receiptResponse = await fetch(bundlerUrl, {
|
|
718
|
+
method: "POST",
|
|
719
|
+
headers: { "Content-Type": "application/json" },
|
|
720
|
+
body: JSON.stringify({
|
|
721
|
+
jsonrpc: "2.0",
|
|
722
|
+
id: 1,
|
|
723
|
+
method: "eth_getUserOperationReceipt",
|
|
724
|
+
params: [userOpHash]
|
|
725
|
+
})
|
|
726
|
+
});
|
|
727
|
+
const receiptResult = await receiptResponse.json();
|
|
728
|
+
if (receiptResult.result) {
|
|
729
|
+
receipt = receiptResult.result;
|
|
730
|
+
break;
|
|
731
|
+
}
|
|
732
|
+
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
733
|
+
}
|
|
734
|
+
if (!receipt) {
|
|
735
|
+
throw new Error("Timeout waiting for user operation receipt");
|
|
736
|
+
}
|
|
737
|
+
return {
|
|
738
|
+
txHash: receipt.transactionHash,
|
|
739
|
+
userOpHash,
|
|
740
|
+
network,
|
|
741
|
+
amount,
|
|
742
|
+
token,
|
|
743
|
+
to,
|
|
744
|
+
explorerUrl: getExplorerTxUrl(network, receipt.transactionHash)
|
|
745
|
+
};
|
|
746
|
+
}
|
|
747
|
+
function formatGaslessPaymentResult(result) {
|
|
748
|
+
const lines = [
|
|
749
|
+
`## Gasless Payment Successful`,
|
|
750
|
+
"",
|
|
751
|
+
`- **Amount:** ${result.amount} ${result.token}`,
|
|
752
|
+
`- **To:** \`${result.to}\``,
|
|
753
|
+
`- **Network:** ${result.network}`,
|
|
754
|
+
`- **Transaction:** \`${result.txHash}\``,
|
|
755
|
+
`- **UserOp Hash:** \`${result.userOpHash}\``
|
|
756
|
+
];
|
|
757
|
+
if (result.paymaster) {
|
|
758
|
+
lines.push(`- **Paymaster:** ${result.paymaster}`);
|
|
759
|
+
}
|
|
760
|
+
lines.push("");
|
|
761
|
+
lines.push(`[View on Explorer](${result.explorerUrl})`);
|
|
762
|
+
lines.push("");
|
|
763
|
+
lines.push("_Gas fees were sponsored - no ETH was deducted from your wallet._");
|
|
764
|
+
return lines.join("\n");
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
// src/tools/getBridgeFee.ts
|
|
768
|
+
var import_zod5 = require("zod");
|
|
769
|
+
var import_viem4 = require("viem");
|
|
770
|
+
var chains4 = __toESM(require("viem/chains"));
|
|
771
|
+
var getBridgeFeeInputSchema = import_zod5.z.object({
|
|
772
|
+
fromChain: import_zod5.z.enum(["ethereum", "arbitrum", "ink", "berachain", "unichain"]).describe("Source chain to bridge from"),
|
|
773
|
+
toChain: import_zod5.z.enum(["ethereum", "arbitrum", "ink", "berachain", "unichain"]).describe("Destination chain to bridge to"),
|
|
774
|
+
amount: import_zod5.z.string().regex(/^\d+(\.\d+)?$/).describe("Amount of USDT0 to bridge (e.g., '100' for 100 USDT0)"),
|
|
775
|
+
recipient: import_zod5.z.string().regex(/^0x[a-fA-F0-9]{40}$/).describe("Recipient address on destination chain")
|
|
776
|
+
});
|
|
777
|
+
var LAYERZERO_ENDPOINT_IDS = {
|
|
778
|
+
ethereum: 30101,
|
|
779
|
+
arbitrum: 30110,
|
|
780
|
+
ink: 30291,
|
|
781
|
+
berachain: 30362,
|
|
782
|
+
unichain: 30320
|
|
783
|
+
};
|
|
784
|
+
var ESTIMATED_BRIDGE_TIMES = {
|
|
785
|
+
ethereum: 900,
|
|
786
|
+
// 15 minutes
|
|
787
|
+
arbitrum: 300,
|
|
788
|
+
// 5 minutes
|
|
789
|
+
ink: 300,
|
|
790
|
+
// 5 minutes
|
|
791
|
+
berachain: 300,
|
|
792
|
+
// 5 minutes
|
|
793
|
+
unichain: 300
|
|
794
|
+
// 5 minutes
|
|
795
|
+
};
|
|
796
|
+
var OFT_ABI = [
|
|
797
|
+
{
|
|
798
|
+
name: "quoteSend",
|
|
799
|
+
type: "function",
|
|
800
|
+
stateMutability: "view",
|
|
801
|
+
inputs: [
|
|
802
|
+
{
|
|
803
|
+
name: "_sendParam",
|
|
804
|
+
type: "tuple",
|
|
805
|
+
components: [
|
|
806
|
+
{ name: "dstEid", type: "uint32" },
|
|
807
|
+
{ name: "to", type: "bytes32" },
|
|
808
|
+
{ name: "amountLD", type: "uint256" },
|
|
809
|
+
{ name: "minAmountLD", type: "uint256" },
|
|
810
|
+
{ name: "extraOptions", type: "bytes" },
|
|
811
|
+
{ name: "composeMsg", type: "bytes" },
|
|
812
|
+
{ name: "oftCmd", type: "bytes" }
|
|
813
|
+
]
|
|
814
|
+
},
|
|
815
|
+
{ name: "_payInLzToken", type: "bool" }
|
|
816
|
+
],
|
|
817
|
+
outputs: [
|
|
818
|
+
{
|
|
819
|
+
name: "msgFee",
|
|
820
|
+
type: "tuple",
|
|
821
|
+
components: [
|
|
822
|
+
{ name: "nativeFee", type: "uint256" },
|
|
823
|
+
{ name: "lzTokenFee", type: "uint256" }
|
|
824
|
+
]
|
|
825
|
+
}
|
|
826
|
+
]
|
|
827
|
+
}
|
|
828
|
+
];
|
|
829
|
+
function getViemChain4(network) {
|
|
830
|
+
switch (network) {
|
|
831
|
+
case "ethereum":
|
|
832
|
+
return chains4.mainnet;
|
|
833
|
+
case "arbitrum":
|
|
834
|
+
return chains4.arbitrum;
|
|
835
|
+
case "ink":
|
|
836
|
+
return chains4.ink;
|
|
837
|
+
case "berachain":
|
|
838
|
+
return chains4.berachain;
|
|
839
|
+
case "unichain":
|
|
840
|
+
return chains4.unichain;
|
|
841
|
+
default:
|
|
842
|
+
return void 0;
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
function addressToBytes32(address) {
|
|
846
|
+
return `0x${address.slice(2).padStart(64, "0")}`;
|
|
847
|
+
}
|
|
848
|
+
async function executeGetBridgeFee(input, rpcUrls) {
|
|
849
|
+
const { fromChain, toChain, amount, recipient } = input;
|
|
850
|
+
if (fromChain === toChain) {
|
|
851
|
+
throw new Error("Source and destination chains must be different");
|
|
852
|
+
}
|
|
853
|
+
if (!BRIDGEABLE_CHAINS.includes(fromChain)) {
|
|
854
|
+
throw new Error(`Chain ${fromChain} does not support USDT0 bridging`);
|
|
855
|
+
}
|
|
856
|
+
if (!BRIDGEABLE_CHAINS.includes(toChain)) {
|
|
857
|
+
throw new Error(`Chain ${toChain} does not support USDT0 bridging`);
|
|
858
|
+
}
|
|
859
|
+
const usdt0Address = USDT0_ADDRESSES[fromChain];
|
|
860
|
+
if (!usdt0Address) {
|
|
861
|
+
throw new Error(`USDT0 not found on ${fromChain}`);
|
|
862
|
+
}
|
|
863
|
+
const amountBigInt = parseTokenAmount(amount, 6);
|
|
864
|
+
const chain = getViemChain4(fromChain);
|
|
865
|
+
if (!chain) {
|
|
866
|
+
throw new Error(`Unsupported chain: ${fromChain}`);
|
|
867
|
+
}
|
|
868
|
+
const rpcUrl = rpcUrls?.[fromChain] || DEFAULT_RPC_URLS[fromChain];
|
|
869
|
+
const client = (0, import_viem4.createPublicClient)({
|
|
870
|
+
chain,
|
|
871
|
+
transport: (0, import_viem4.http)(rpcUrl)
|
|
872
|
+
});
|
|
873
|
+
const dstEid = LAYERZERO_ENDPOINT_IDS[toChain];
|
|
874
|
+
const sendParam = {
|
|
875
|
+
dstEid,
|
|
876
|
+
to: addressToBytes32(recipient),
|
|
877
|
+
amountLD: amountBigInt,
|
|
878
|
+
minAmountLD: amountBigInt,
|
|
879
|
+
// No slippage for quote
|
|
880
|
+
extraOptions: "0x",
|
|
881
|
+
composeMsg: "0x",
|
|
882
|
+
oftCmd: "0x"
|
|
883
|
+
};
|
|
884
|
+
const quote = await client.readContract({
|
|
885
|
+
address: usdt0Address,
|
|
886
|
+
abi: OFT_ABI,
|
|
887
|
+
functionName: "quoteSend",
|
|
888
|
+
args: [sendParam, false]
|
|
889
|
+
});
|
|
890
|
+
const nativeSymbol = NATIVE_SYMBOLS[fromChain];
|
|
891
|
+
const estimatedTime = ESTIMATED_BRIDGE_TIMES[toChain] || 300;
|
|
892
|
+
return {
|
|
893
|
+
fromChain,
|
|
894
|
+
toChain,
|
|
895
|
+
amount,
|
|
896
|
+
nativeFee: quote.nativeFee.toString(),
|
|
897
|
+
nativeFeeFormatted: `${(0, import_viem4.formatEther)(quote.nativeFee)} ${nativeSymbol}`,
|
|
898
|
+
estimatedTime
|
|
899
|
+
};
|
|
900
|
+
}
|
|
901
|
+
function formatBridgeFeeResult(result) {
|
|
902
|
+
const minutes = Math.ceil(result.estimatedTime / 60);
|
|
903
|
+
return [
|
|
904
|
+
`## Bridge Fee Quote`,
|
|
905
|
+
"",
|
|
906
|
+
`- **Route:** ${result.fromChain} \u2192 ${result.toChain}`,
|
|
907
|
+
`- **Amount:** ${result.amount} USDT0`,
|
|
908
|
+
`- **Native Fee:** ${result.nativeFeeFormatted}`,
|
|
909
|
+
`- **Estimated Time:** ~${minutes} minutes`,
|
|
910
|
+
"",
|
|
911
|
+
"_Note: Actual fees may vary slightly at execution time._"
|
|
912
|
+
].join("\n");
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
// src/tools/bridge.ts
|
|
916
|
+
var import_zod6 = require("zod");
|
|
917
|
+
var import_viem5 = require("viem");
|
|
918
|
+
var import_accounts3 = require("viem/accounts");
|
|
919
|
+
var chains5 = __toESM(require("viem/chains"));
|
|
920
|
+
var bridgeInputSchema = import_zod6.z.object({
|
|
921
|
+
fromChain: import_zod6.z.enum(["ethereum", "arbitrum", "ink", "berachain", "unichain"]).describe("Source chain to bridge from"),
|
|
922
|
+
toChain: import_zod6.z.enum(["ethereum", "arbitrum", "ink", "berachain", "unichain"]).describe("Destination chain to bridge to"),
|
|
923
|
+
amount: import_zod6.z.string().regex(/^\d+(\.\d+)?$/).describe("Amount of USDT0 to bridge (e.g., '100' for 100 USDT0)"),
|
|
924
|
+
recipient: import_zod6.z.string().regex(/^0x[a-fA-F0-9]{40}$/).describe("Recipient address on destination chain")
|
|
925
|
+
});
|
|
926
|
+
var LAYERZERO_ENDPOINT_IDS2 = {
|
|
927
|
+
ethereum: 30101,
|
|
928
|
+
arbitrum: 30110,
|
|
929
|
+
ink: 30291,
|
|
930
|
+
berachain: 30362,
|
|
931
|
+
unichain: 30320
|
|
932
|
+
};
|
|
933
|
+
var ESTIMATED_BRIDGE_TIMES2 = {
|
|
934
|
+
ethereum: 900,
|
|
935
|
+
arbitrum: 300,
|
|
936
|
+
ink: 300,
|
|
937
|
+
berachain: 300,
|
|
938
|
+
unichain: 300
|
|
939
|
+
};
|
|
940
|
+
var OFT_ABI2 = [
|
|
941
|
+
{
|
|
942
|
+
name: "quoteSend",
|
|
943
|
+
type: "function",
|
|
944
|
+
stateMutability: "view",
|
|
945
|
+
inputs: [
|
|
946
|
+
{
|
|
947
|
+
name: "_sendParam",
|
|
948
|
+
type: "tuple",
|
|
949
|
+
components: [
|
|
950
|
+
{ name: "dstEid", type: "uint32" },
|
|
951
|
+
{ name: "to", type: "bytes32" },
|
|
952
|
+
{ name: "amountLD", type: "uint256" },
|
|
953
|
+
{ name: "minAmountLD", type: "uint256" },
|
|
954
|
+
{ name: "extraOptions", type: "bytes" },
|
|
955
|
+
{ name: "composeMsg", type: "bytes" },
|
|
956
|
+
{ name: "oftCmd", type: "bytes" }
|
|
957
|
+
]
|
|
958
|
+
},
|
|
959
|
+
{ name: "_payInLzToken", type: "bool" }
|
|
960
|
+
],
|
|
961
|
+
outputs: [
|
|
962
|
+
{
|
|
963
|
+
name: "msgFee",
|
|
964
|
+
type: "tuple",
|
|
965
|
+
components: [
|
|
966
|
+
{ name: "nativeFee", type: "uint256" },
|
|
967
|
+
{ name: "lzTokenFee", type: "uint256" }
|
|
968
|
+
]
|
|
969
|
+
}
|
|
970
|
+
]
|
|
971
|
+
},
|
|
972
|
+
{
|
|
973
|
+
name: "send",
|
|
974
|
+
type: "function",
|
|
975
|
+
stateMutability: "payable",
|
|
976
|
+
inputs: [
|
|
977
|
+
{
|
|
978
|
+
name: "_sendParam",
|
|
979
|
+
type: "tuple",
|
|
980
|
+
components: [
|
|
981
|
+
{ name: "dstEid", type: "uint32" },
|
|
982
|
+
{ name: "to", type: "bytes32" },
|
|
983
|
+
{ name: "amountLD", type: "uint256" },
|
|
984
|
+
{ name: "minAmountLD", type: "uint256" },
|
|
985
|
+
{ name: "extraOptions", type: "bytes" },
|
|
986
|
+
{ name: "composeMsg", type: "bytes" },
|
|
987
|
+
{ name: "oftCmd", type: "bytes" }
|
|
988
|
+
]
|
|
989
|
+
},
|
|
990
|
+
{
|
|
991
|
+
name: "_fee",
|
|
992
|
+
type: "tuple",
|
|
993
|
+
components: [
|
|
994
|
+
{ name: "nativeFee", type: "uint256" },
|
|
995
|
+
{ name: "lzTokenFee", type: "uint256" }
|
|
996
|
+
]
|
|
997
|
+
},
|
|
998
|
+
{ name: "_refundAddress", type: "address" }
|
|
999
|
+
],
|
|
1000
|
+
outputs: [
|
|
1001
|
+
{
|
|
1002
|
+
name: "msgReceipt",
|
|
1003
|
+
type: "tuple",
|
|
1004
|
+
components: [
|
|
1005
|
+
{ name: "guid", type: "bytes32" },
|
|
1006
|
+
{ name: "nonce", type: "uint64" },
|
|
1007
|
+
{
|
|
1008
|
+
name: "fee",
|
|
1009
|
+
type: "tuple",
|
|
1010
|
+
components: [
|
|
1011
|
+
{ name: "nativeFee", type: "uint256" },
|
|
1012
|
+
{ name: "lzTokenFee", type: "uint256" }
|
|
1013
|
+
]
|
|
1014
|
+
}
|
|
1015
|
+
]
|
|
1016
|
+
},
|
|
1017
|
+
{
|
|
1018
|
+
name: "oftReceipt",
|
|
1019
|
+
type: "tuple",
|
|
1020
|
+
components: [
|
|
1021
|
+
{ name: "amountSentLD", type: "uint256" },
|
|
1022
|
+
{ name: "amountReceivedLD", type: "uint256" }
|
|
1023
|
+
]
|
|
1024
|
+
}
|
|
1025
|
+
]
|
|
1026
|
+
}
|
|
1027
|
+
];
|
|
1028
|
+
var OFT_SENT_EVENT_TOPIC = (0, import_viem5.keccak256)(
|
|
1029
|
+
(0, import_viem5.toBytes)("OFTSent(bytes32,uint32,address,uint256,uint256)")
|
|
1030
|
+
);
|
|
1031
|
+
function getViemChain5(network) {
|
|
1032
|
+
switch (network) {
|
|
1033
|
+
case "ethereum":
|
|
1034
|
+
return chains5.mainnet;
|
|
1035
|
+
case "arbitrum":
|
|
1036
|
+
return chains5.arbitrum;
|
|
1037
|
+
case "ink":
|
|
1038
|
+
return chains5.ink;
|
|
1039
|
+
case "berachain":
|
|
1040
|
+
return chains5.berachain;
|
|
1041
|
+
case "unichain":
|
|
1042
|
+
return chains5.unichain;
|
|
1043
|
+
default:
|
|
1044
|
+
return void 0;
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
function addressToBytes322(address) {
|
|
1048
|
+
return `0x${address.slice(2).padStart(64, "0")}`;
|
|
1049
|
+
}
|
|
1050
|
+
async function executeBridge(input, options) {
|
|
1051
|
+
const { fromChain, toChain, amount, recipient } = input;
|
|
1052
|
+
const { privateKey, rpcUrl, demoMode, slippageTolerance = 0.5 } = options;
|
|
1053
|
+
if (fromChain === toChain) {
|
|
1054
|
+
throw new Error("Source and destination chains must be different");
|
|
1055
|
+
}
|
|
1056
|
+
if (!BRIDGEABLE_CHAINS.includes(fromChain)) {
|
|
1057
|
+
throw new Error(`Chain ${fromChain} does not support USDT0 bridging`);
|
|
1058
|
+
}
|
|
1059
|
+
if (!BRIDGEABLE_CHAINS.includes(toChain)) {
|
|
1060
|
+
throw new Error(`Chain ${toChain} does not support USDT0 bridging`);
|
|
1061
|
+
}
|
|
1062
|
+
const usdt0Address = USDT0_ADDRESSES[fromChain];
|
|
1063
|
+
if (!usdt0Address) {
|
|
1064
|
+
throw new Error(`USDT0 not found on ${fromChain}`);
|
|
1065
|
+
}
|
|
1066
|
+
const amountBigInt = parseTokenAmount(amount, 6);
|
|
1067
|
+
const slippageMultiplier = BigInt(Math.floor((100 - slippageTolerance) * 100));
|
|
1068
|
+
const minAmountBigInt = amountBigInt * slippageMultiplier / 10000n;
|
|
1069
|
+
if (demoMode) {
|
|
1070
|
+
const fakeTxHash = `0x${"a".repeat(64)}`;
|
|
1071
|
+
const fakeGuid = `0x${"b".repeat(64)}`;
|
|
1072
|
+
const estimatedTime2 = ESTIMATED_BRIDGE_TIMES2[toChain] || 300;
|
|
1073
|
+
return {
|
|
1074
|
+
txHash: fakeTxHash,
|
|
1075
|
+
messageGuid: fakeGuid,
|
|
1076
|
+
amount,
|
|
1077
|
+
fromChain,
|
|
1078
|
+
toChain,
|
|
1079
|
+
estimatedTime: estimatedTime2,
|
|
1080
|
+
trackingUrl: getLayerZeroScanUrl(fakeGuid)
|
|
1081
|
+
};
|
|
1082
|
+
}
|
|
1083
|
+
const chain = getViemChain5(fromChain);
|
|
1084
|
+
if (!chain) {
|
|
1085
|
+
throw new Error(`Unsupported chain: ${fromChain}`);
|
|
1086
|
+
}
|
|
1087
|
+
const transport = (0, import_viem5.http)(rpcUrl || DEFAULT_RPC_URLS[fromChain]);
|
|
1088
|
+
const account = (0, import_accounts3.privateKeyToAccount)(privateKey);
|
|
1089
|
+
const publicClient = (0, import_viem5.createPublicClient)({
|
|
1090
|
+
chain,
|
|
1091
|
+
transport
|
|
1092
|
+
});
|
|
1093
|
+
const walletClient = (0, import_viem5.createWalletClient)({
|
|
1094
|
+
account,
|
|
1095
|
+
chain,
|
|
1096
|
+
transport
|
|
1097
|
+
});
|
|
1098
|
+
const balance = await publicClient.readContract({
|
|
1099
|
+
address: usdt0Address,
|
|
1100
|
+
abi: ERC20_ABI,
|
|
1101
|
+
functionName: "balanceOf",
|
|
1102
|
+
args: [account.address]
|
|
1103
|
+
});
|
|
1104
|
+
if (balance < amountBigInt) {
|
|
1105
|
+
throw new Error(
|
|
1106
|
+
`Insufficient USDT0 balance. Have: ${balance.toString()}, Need: ${amountBigInt.toString()}`
|
|
1107
|
+
);
|
|
1108
|
+
}
|
|
1109
|
+
const dstEid = LAYERZERO_ENDPOINT_IDS2[toChain];
|
|
1110
|
+
const sendParam = {
|
|
1111
|
+
dstEid,
|
|
1112
|
+
to: addressToBytes322(recipient),
|
|
1113
|
+
amountLD: amountBigInt,
|
|
1114
|
+
minAmountLD: minAmountBigInt,
|
|
1115
|
+
extraOptions: "0x",
|
|
1116
|
+
composeMsg: "0x",
|
|
1117
|
+
oftCmd: "0x"
|
|
1118
|
+
};
|
|
1119
|
+
const quote = await publicClient.readContract({
|
|
1120
|
+
address: usdt0Address,
|
|
1121
|
+
abi: OFT_ABI2,
|
|
1122
|
+
functionName: "quoteSend",
|
|
1123
|
+
args: [sendParam, false]
|
|
1124
|
+
});
|
|
1125
|
+
const nativeFeeWithBuffer = quote.nativeFee * 110n / 100n;
|
|
1126
|
+
const hash = await walletClient.writeContract({
|
|
1127
|
+
address: usdt0Address,
|
|
1128
|
+
abi: OFT_ABI2,
|
|
1129
|
+
functionName: "send",
|
|
1130
|
+
args: [
|
|
1131
|
+
sendParam,
|
|
1132
|
+
{ nativeFee: nativeFeeWithBuffer, lzTokenFee: 0n },
|
|
1133
|
+
account.address
|
|
1134
|
+
],
|
|
1135
|
+
value: nativeFeeWithBuffer
|
|
1136
|
+
});
|
|
1137
|
+
const receipt = await publicClient.waitForTransactionReceipt({ hash });
|
|
1138
|
+
if (receipt.status !== "success") {
|
|
1139
|
+
throw new Error(`Bridge transaction failed: ${hash}`);
|
|
1140
|
+
}
|
|
1141
|
+
let messageGuid = "0x";
|
|
1142
|
+
for (const log of receipt.logs) {
|
|
1143
|
+
if (log.topics[0] === OFT_SENT_EVENT_TOPIC && log.topics[1]) {
|
|
1144
|
+
messageGuid = log.topics[1];
|
|
1145
|
+
break;
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
if (messageGuid === "0x") {
|
|
1149
|
+
throw new Error("Failed to extract message GUID from transaction logs");
|
|
1150
|
+
}
|
|
1151
|
+
const estimatedTime = ESTIMATED_BRIDGE_TIMES2[toChain] || 300;
|
|
1152
|
+
return {
|
|
1153
|
+
txHash: hash,
|
|
1154
|
+
messageGuid,
|
|
1155
|
+
amount,
|
|
1156
|
+
fromChain,
|
|
1157
|
+
toChain,
|
|
1158
|
+
estimatedTime,
|
|
1159
|
+
trackingUrl: getLayerZeroScanUrl(messageGuid)
|
|
1160
|
+
};
|
|
1161
|
+
}
|
|
1162
|
+
function formatBridgeResult(result) {
|
|
1163
|
+
const minutes = Math.ceil(result.estimatedTime / 60);
|
|
1164
|
+
return [
|
|
1165
|
+
`## Bridge Transaction Submitted`,
|
|
1166
|
+
"",
|
|
1167
|
+
`- **Route:** ${result.fromChain} \u2192 ${result.toChain}`,
|
|
1168
|
+
`- **Amount:** ${result.amount} USDT0`,
|
|
1169
|
+
`- **Transaction:** \`${result.txHash}\``,
|
|
1170
|
+
`- **Message GUID:** \`${result.messageGuid}\``,
|
|
1171
|
+
`- **Estimated Delivery:** ~${minutes} minutes`,
|
|
1172
|
+
"",
|
|
1173
|
+
`### Tracking`,
|
|
1174
|
+
`- [View on LayerZero Scan](${result.trackingUrl})`,
|
|
1175
|
+
`- [View Source TX](${getExplorerTxUrl(result.fromChain, result.txHash)})`,
|
|
1176
|
+
"",
|
|
1177
|
+
"_Your USDT0 will arrive on ${result.toChain} once the LayerZero message is delivered._"
|
|
1178
|
+
].join("\n");
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
// src/tools/index.ts
|
|
1182
|
+
var TOOL_DEFINITIONS = {
|
|
1183
|
+
"t402/getBalance": {
|
|
1184
|
+
name: "t402/getBalance",
|
|
1185
|
+
description: "Get token balances (native + stablecoins) for a wallet on a specific blockchain network. Returns ETH/native token balance plus USDC, USDT, and USDT0 balances where supported.",
|
|
1186
|
+
inputSchema: {
|
|
1187
|
+
type: "object",
|
|
1188
|
+
properties: {
|
|
1189
|
+
network: {
|
|
1190
|
+
type: "string",
|
|
1191
|
+
enum: [
|
|
1192
|
+
"ethereum",
|
|
1193
|
+
"base",
|
|
1194
|
+
"arbitrum",
|
|
1195
|
+
"optimism",
|
|
1196
|
+
"polygon",
|
|
1197
|
+
"avalanche",
|
|
1198
|
+
"ink",
|
|
1199
|
+
"berachain",
|
|
1200
|
+
"unichain"
|
|
1201
|
+
],
|
|
1202
|
+
description: "Blockchain network to check balance on"
|
|
1203
|
+
},
|
|
1204
|
+
address: {
|
|
1205
|
+
type: "string",
|
|
1206
|
+
pattern: "^0x[a-fA-F0-9]{40}$",
|
|
1207
|
+
description: "Wallet address to check balance for"
|
|
1208
|
+
}
|
|
1209
|
+
},
|
|
1210
|
+
required: ["network", "address"]
|
|
1211
|
+
}
|
|
1212
|
+
},
|
|
1213
|
+
"t402/getAllBalances": {
|
|
1214
|
+
name: "t402/getAllBalances",
|
|
1215
|
+
description: "Get token balances across all supported networks for a wallet. Returns aggregated totals and per-network breakdown of native tokens and stablecoins (USDC, USDT, USDT0).",
|
|
1216
|
+
inputSchema: {
|
|
1217
|
+
type: "object",
|
|
1218
|
+
properties: {
|
|
1219
|
+
address: {
|
|
1220
|
+
type: "string",
|
|
1221
|
+
pattern: "^0x[a-fA-F0-9]{40}$",
|
|
1222
|
+
description: "Wallet address to check balances for"
|
|
1223
|
+
},
|
|
1224
|
+
networks: {
|
|
1225
|
+
type: "array",
|
|
1226
|
+
items: {
|
|
1227
|
+
type: "string",
|
|
1228
|
+
enum: [
|
|
1229
|
+
"ethereum",
|
|
1230
|
+
"base",
|
|
1231
|
+
"arbitrum",
|
|
1232
|
+
"optimism",
|
|
1233
|
+
"polygon",
|
|
1234
|
+
"avalanche",
|
|
1235
|
+
"ink",
|
|
1236
|
+
"berachain",
|
|
1237
|
+
"unichain"
|
|
1238
|
+
]
|
|
1239
|
+
},
|
|
1240
|
+
description: "Optional list of networks to check. If not provided, checks all supported networks."
|
|
1241
|
+
}
|
|
1242
|
+
},
|
|
1243
|
+
required: ["address"]
|
|
1244
|
+
}
|
|
1245
|
+
},
|
|
1246
|
+
"t402/pay": {
|
|
1247
|
+
name: "t402/pay",
|
|
1248
|
+
description: "Execute a stablecoin payment on a specific blockchain network. Supports USDC, USDT, and USDT0 tokens. Requires a configured wallet with sufficient balance and native token for gas.",
|
|
1249
|
+
inputSchema: {
|
|
1250
|
+
type: "object",
|
|
1251
|
+
properties: {
|
|
1252
|
+
to: {
|
|
1253
|
+
type: "string",
|
|
1254
|
+
pattern: "^0x[a-fA-F0-9]{40}$",
|
|
1255
|
+
description: "Recipient address"
|
|
1256
|
+
},
|
|
1257
|
+
amount: {
|
|
1258
|
+
type: "string",
|
|
1259
|
+
pattern: "^\\d+(\\.\\d+)?$",
|
|
1260
|
+
description: "Amount to pay (e.g., '10.50' for 10.50 USDC)"
|
|
1261
|
+
},
|
|
1262
|
+
token: {
|
|
1263
|
+
type: "string",
|
|
1264
|
+
enum: ["USDC", "USDT", "USDT0"],
|
|
1265
|
+
description: "Token to use for payment"
|
|
1266
|
+
},
|
|
1267
|
+
network: {
|
|
1268
|
+
type: "string",
|
|
1269
|
+
enum: [
|
|
1270
|
+
"ethereum",
|
|
1271
|
+
"base",
|
|
1272
|
+
"arbitrum",
|
|
1273
|
+
"optimism",
|
|
1274
|
+
"polygon",
|
|
1275
|
+
"avalanche",
|
|
1276
|
+
"ink",
|
|
1277
|
+
"berachain",
|
|
1278
|
+
"unichain"
|
|
1279
|
+
],
|
|
1280
|
+
description: "Network to execute payment on"
|
|
1281
|
+
},
|
|
1282
|
+
memo: {
|
|
1283
|
+
type: "string",
|
|
1284
|
+
description: "Optional memo/reference for the payment"
|
|
1285
|
+
}
|
|
1286
|
+
},
|
|
1287
|
+
required: ["to", "amount", "token", "network"]
|
|
1288
|
+
}
|
|
1289
|
+
},
|
|
1290
|
+
"t402/payGasless": {
|
|
1291
|
+
name: "t402/payGasless",
|
|
1292
|
+
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.",
|
|
1293
|
+
inputSchema: {
|
|
1294
|
+
type: "object",
|
|
1295
|
+
properties: {
|
|
1296
|
+
to: {
|
|
1297
|
+
type: "string",
|
|
1298
|
+
pattern: "^0x[a-fA-F0-9]{40}$",
|
|
1299
|
+
description: "Recipient address"
|
|
1300
|
+
},
|
|
1301
|
+
amount: {
|
|
1302
|
+
type: "string",
|
|
1303
|
+
pattern: "^\\d+(\\.\\d+)?$",
|
|
1304
|
+
description: "Amount to pay (e.g., '10.50' for 10.50 USDC)"
|
|
1305
|
+
},
|
|
1306
|
+
token: {
|
|
1307
|
+
type: "string",
|
|
1308
|
+
enum: ["USDC", "USDT", "USDT0"],
|
|
1309
|
+
description: "Token to use for payment"
|
|
1310
|
+
},
|
|
1311
|
+
network: {
|
|
1312
|
+
type: "string",
|
|
1313
|
+
enum: ["ethereum", "base", "arbitrum", "optimism", "polygon", "avalanche"],
|
|
1314
|
+
description: "Network to execute gasless payment on (must support ERC-4337)"
|
|
1315
|
+
}
|
|
1316
|
+
},
|
|
1317
|
+
required: ["to", "amount", "token", "network"]
|
|
1318
|
+
}
|
|
1319
|
+
},
|
|
1320
|
+
"t402/getBridgeFee": {
|
|
1321
|
+
name: "t402/getBridgeFee",
|
|
1322
|
+
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.",
|
|
1323
|
+
inputSchema: {
|
|
1324
|
+
type: "object",
|
|
1325
|
+
properties: {
|
|
1326
|
+
fromChain: {
|
|
1327
|
+
type: "string",
|
|
1328
|
+
enum: ["ethereum", "arbitrum", "ink", "berachain", "unichain"],
|
|
1329
|
+
description: "Source chain to bridge from"
|
|
1330
|
+
},
|
|
1331
|
+
toChain: {
|
|
1332
|
+
type: "string",
|
|
1333
|
+
enum: ["ethereum", "arbitrum", "ink", "berachain", "unichain"],
|
|
1334
|
+
description: "Destination chain to bridge to"
|
|
1335
|
+
},
|
|
1336
|
+
amount: {
|
|
1337
|
+
type: "string",
|
|
1338
|
+
pattern: "^\\d+(\\.\\d+)?$",
|
|
1339
|
+
description: "Amount of USDT0 to bridge (e.g., '100' for 100 USDT0)"
|
|
1340
|
+
},
|
|
1341
|
+
recipient: {
|
|
1342
|
+
type: "string",
|
|
1343
|
+
pattern: "^0x[a-fA-F0-9]{40}$",
|
|
1344
|
+
description: "Recipient address on destination chain"
|
|
1345
|
+
}
|
|
1346
|
+
},
|
|
1347
|
+
required: ["fromChain", "toChain", "amount", "recipient"]
|
|
1348
|
+
}
|
|
1349
|
+
},
|
|
1350
|
+
"t402/bridge": {
|
|
1351
|
+
name: "t402/bridge",
|
|
1352
|
+
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.",
|
|
1353
|
+
inputSchema: {
|
|
1354
|
+
type: "object",
|
|
1355
|
+
properties: {
|
|
1356
|
+
fromChain: {
|
|
1357
|
+
type: "string",
|
|
1358
|
+
enum: ["ethereum", "arbitrum", "ink", "berachain", "unichain"],
|
|
1359
|
+
description: "Source chain to bridge from"
|
|
1360
|
+
},
|
|
1361
|
+
toChain: {
|
|
1362
|
+
type: "string",
|
|
1363
|
+
enum: ["ethereum", "arbitrum", "ink", "berachain", "unichain"],
|
|
1364
|
+
description: "Destination chain to bridge to"
|
|
1365
|
+
},
|
|
1366
|
+
amount: {
|
|
1367
|
+
type: "string",
|
|
1368
|
+
pattern: "^\\d+(\\.\\d+)?$",
|
|
1369
|
+
description: "Amount of USDT0 to bridge (e.g., '100' for 100 USDT0)"
|
|
1370
|
+
},
|
|
1371
|
+
recipient: {
|
|
1372
|
+
type: "string",
|
|
1373
|
+
pattern: "^0x[a-fA-F0-9]{40}$",
|
|
1374
|
+
description: "Recipient address on destination chain"
|
|
1375
|
+
}
|
|
1376
|
+
},
|
|
1377
|
+
required: ["fromChain", "toChain", "amount", "recipient"]
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
};
|
|
1381
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1382
|
+
0 && (module.exports = {
|
|
1383
|
+
GASLESS_SUPPORTED_NETWORKS,
|
|
1384
|
+
TOOL_DEFINITIONS,
|
|
1385
|
+
bridgeInputSchema,
|
|
1386
|
+
executeBridge,
|
|
1387
|
+
executeGetAllBalances,
|
|
1388
|
+
executeGetBalance,
|
|
1389
|
+
executeGetBridgeFee,
|
|
1390
|
+
executePay,
|
|
1391
|
+
executePayGasless,
|
|
1392
|
+
formatAllBalancesResult,
|
|
1393
|
+
formatBalanceResult,
|
|
1394
|
+
formatBridgeFeeResult,
|
|
1395
|
+
formatBridgeResult,
|
|
1396
|
+
formatGaslessPaymentResult,
|
|
1397
|
+
formatPaymentResult,
|
|
1398
|
+
getAllBalancesInputSchema,
|
|
1399
|
+
getBalanceInputSchema,
|
|
1400
|
+
getBridgeFeeInputSchema,
|
|
1401
|
+
payGaslessInputSchema,
|
|
1402
|
+
payInputSchema
|
|
1403
|
+
});
|
|
1404
|
+
//# sourceMappingURL=index.js.map
|