intent-swap-mcp 0.1.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 ADDED
@@ -0,0 +1,97 @@
1
+ # intent-swap MCP Server
2
+
3
+ An MCP (Model Context Protocol) server that lets AI agents execute DeFi swaps via natural language.
4
+
5
+ ## What it does
6
+
7
+ Connect this to Claude Desktop (or any MCP-compatible agent) and say:
8
+
9
+ > "Swap 1 ETH for USDC"
10
+ > "把0.5个以太换成USDT"
11
+ > "Get me a quote for swapping 100 USDC to DAI"
12
+
13
+ The agent will parse your intent, fetch a real-time Uniswap V3 quote, and build the transaction for your wallet to sign.
14
+
15
+ ## Tools
16
+
17
+ | Tool | Description |
18
+ |------|-------------|
19
+ | `parse_swap_intent` | Natural language → structured swap params |
20
+ | `get_token_price` | Real-time USD price via CoinGecko |
21
+ | `get_swap_quote` | Live Uniswap V3 quote (best fee tier auto-selected) |
22
+ | `build_swap_tx` | Generate calldata for wallet signing |
23
+ | `list_supported_tokens` | All supported tokens with prices |
24
+
25
+ ## Supported Tokens
26
+
27
+ ETH, WETH, WBTC, USDC, USDT, DAI, ARB, UNI, LINK, MATIC, OP, PEPE, SHIB, AAVE, CRV
28
+
29
+ ## Setup
30
+
31
+ ### Install
32
+
33
+ ```bash
34
+ npm install -g intent-swap-mcp
35
+ ```
36
+
37
+ ### Claude Desktop config
38
+
39
+ Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
40
+
41
+ ```json
42
+ {
43
+ "mcpServers": {
44
+ "intent-swap": {
45
+ "command": "intent-swap-mcp",
46
+ "env": {
47
+ "OPENAI_API_KEY": "sk-..."
48
+ }
49
+ }
50
+ }
51
+ }
52
+ ```
53
+
54
+ `OPENAI_API_KEY` is optional — without it, the server uses rule-based parsing (works for most common intents).
55
+
56
+ ### Run locally (dev)
57
+
58
+ ```bash
59
+ git clone https://github.com/Lovelle-Zhang/intent-swap
60
+ cd projects/intent-swap-mcp
61
+ npm install
62
+ npm run dev
63
+ ```
64
+
65
+ ## Architecture
66
+
67
+ ```
68
+ User (natural language)
69
+
70
+ parse_swap_intent → structured { fromToken, toToken, amount, ... }
71
+
72
+ get_swap_quote → real-time Uniswap V3 quote (QuoterV2 on-chain)
73
+
74
+ build_swap_tx → calldata for SwapRouter02
75
+
76
+ User wallet signs & broadcasts
77
+ ```
78
+
79
+ No custody. No API keys for on-chain operations. The server never holds private keys.
80
+
81
+ ## Security
82
+
83
+ - The server **never** requests or stores private keys
84
+ - `build_swap_tx` only generates calldata — the user must sign in their own wallet
85
+ - ERC-20 swaps require a separate `approve` transaction (noted in the response)
86
+
87
+ ## Roadmap
88
+
89
+ - [ ] ERC-4337 (Account Abstraction) support for smart contract wallets
90
+ - [ ] Multi-hop routing
91
+ - [ ] Conditional orders ("buy ETH when it drops below $3000")
92
+ - [ ] Arbitrum / Base / Optimism support
93
+ - [ ] Publish to npm
94
+
95
+ ## License
96
+
97
+ MIT
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * intent-swap MCP Server
4
+ *
5
+ * Exposes DeFi swap capabilities as MCP tools so AI agents (Claude, GPT, etc.)
6
+ * can execute on-chain swaps via natural language.
7
+ *
8
+ * Tools:
9
+ * - parse_swap_intent : NL → structured swap params
10
+ * - get_token_price : real-time price via CoinGecko
11
+ * - get_swap_quote : Uniswap V3 on-chain quote
12
+ * - build_swap_tx : build calldata for wallet signing
13
+ */
14
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,244 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * intent-swap MCP Server
4
+ *
5
+ * Exposes DeFi swap capabilities as MCP tools so AI agents (Claude, GPT, etc.)
6
+ * can execute on-chain swaps via natural language.
7
+ *
8
+ * Tools:
9
+ * - parse_swap_intent : NL → structured swap params
10
+ * - get_token_price : real-time price via CoinGecko
11
+ * - get_swap_quote : Uniswap V3 on-chain quote
12
+ * - build_swap_tx : build calldata for wallet signing
13
+ */
14
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
15
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
16
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
17
+ import { z } from "zod";
18
+ import { parseIntent } from "./intent-parser.js";
19
+ import { getTokenPrice, getSupportedTokens } from "./price-feed.js";
20
+ import { getSwapQuote, buildSwapTx } from "./uniswap.js";
21
+ // ─── Server setup ──────────────────────────────────────────────────────────
22
+ const server = new Server({
23
+ name: "intent-swap",
24
+ version: "0.1.0",
25
+ }, {
26
+ capabilities: {
27
+ tools: {},
28
+ },
29
+ });
30
+ // ─── Tool definitions ──────────────────────────────────────────────────────
31
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
32
+ tools: [
33
+ {
34
+ name: "parse_swap_intent",
35
+ description: "Parse a natural language swap request into structured parameters. " +
36
+ "Supports English and Chinese. Examples: 'swap 1 ETH for USDC', " +
37
+ "'把0.5个以太换成USDT', 'buy WBTC with all my ETH'.",
38
+ inputSchema: {
39
+ type: "object",
40
+ properties: {
41
+ intent: {
42
+ type: "string",
43
+ description: "Natural language swap request from the user",
44
+ },
45
+ },
46
+ required: ["intent"],
47
+ },
48
+ },
49
+ {
50
+ name: "get_token_price",
51
+ description: "Get the current USD price of a token. Supported: ETH, WETH, WBTC, BTC, USDC, USDT, DAI, ARB, UNI, LINK, MATIC, OP.",
52
+ inputSchema: {
53
+ type: "object",
54
+ properties: {
55
+ token: {
56
+ type: "string",
57
+ description: "Token symbol (e.g. ETH, USDC, WBTC)",
58
+ },
59
+ },
60
+ required: ["token"],
61
+ },
62
+ },
63
+ {
64
+ name: "get_swap_quote",
65
+ description: "Get a real-time swap quote from Uniswap V3. Returns expected output amount, price impact, and gas estimate.",
66
+ inputSchema: {
67
+ type: "object",
68
+ properties: {
69
+ fromToken: {
70
+ type: "string",
71
+ description: "Source token symbol (e.g. ETH)",
72
+ },
73
+ toToken: {
74
+ type: "string",
75
+ description: "Destination token symbol (e.g. USDC)",
76
+ },
77
+ amount: {
78
+ type: "number",
79
+ description: "Amount of fromToken to swap",
80
+ },
81
+ slippageBps: {
82
+ type: "number",
83
+ description: "Slippage tolerance in basis points (default: 50 = 0.5%)",
84
+ },
85
+ },
86
+ required: ["fromToken", "toToken", "amount"],
87
+ },
88
+ },
89
+ {
90
+ name: "build_swap_tx",
91
+ description: "Build the transaction calldata for a swap. The user must sign and broadcast this transaction themselves via their wallet. " +
92
+ "Returns: to (contract address), data (calldata), value (ETH to send), and a human-readable summary.",
93
+ inputSchema: {
94
+ type: "object",
95
+ properties: {
96
+ fromToken: {
97
+ type: "string",
98
+ description: "Source token symbol",
99
+ },
100
+ toToken: {
101
+ type: "string",
102
+ description: "Destination token symbol",
103
+ },
104
+ amount: {
105
+ type: "number",
106
+ description: "Amount of fromToken to swap",
107
+ },
108
+ recipientAddress: {
109
+ type: "string",
110
+ description: "Wallet address to receive the output tokens (0x...)",
111
+ },
112
+ slippageBps: {
113
+ type: "number",
114
+ description: "Slippage tolerance in basis points (default: 50)",
115
+ },
116
+ },
117
+ required: ["fromToken", "toToken", "amount", "recipientAddress"],
118
+ },
119
+ },
120
+ {
121
+ name: "list_supported_tokens",
122
+ description: "List all supported tokens with their addresses and current prices.",
123
+ inputSchema: {
124
+ type: "object",
125
+ properties: {},
126
+ },
127
+ },
128
+ ],
129
+ }));
130
+ // ─── Tool handlers ─────────────────────────────────────────────────────────
131
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
132
+ const { name, arguments: args } = request.params;
133
+ try {
134
+ switch (name) {
135
+ case "parse_swap_intent": {
136
+ const { intent } = z.object({ intent: z.string() }).parse(args);
137
+ const result = await parseIntent(intent);
138
+ return {
139
+ content: [
140
+ {
141
+ type: "text",
142
+ text: JSON.stringify(result, null, 2),
143
+ },
144
+ ],
145
+ };
146
+ }
147
+ case "get_token_price": {
148
+ const { token } = z.object({ token: z.string() }).parse(args);
149
+ const price = await getTokenPrice(token.toUpperCase());
150
+ if (price === null) {
151
+ return {
152
+ content: [
153
+ {
154
+ type: "text",
155
+ text: `Token ${token} is not supported or price unavailable.`,
156
+ },
157
+ ],
158
+ isError: true,
159
+ };
160
+ }
161
+ return {
162
+ content: [
163
+ {
164
+ type: "text",
165
+ text: JSON.stringify({ token: token.toUpperCase(), priceUsd: price }, null, 2),
166
+ },
167
+ ],
168
+ };
169
+ }
170
+ case "get_swap_quote": {
171
+ const params = z
172
+ .object({
173
+ fromToken: z.string(),
174
+ toToken: z.string(),
175
+ amount: z.number().positive(),
176
+ slippageBps: z.number().optional().default(50),
177
+ })
178
+ .parse(args);
179
+ const quote = await getSwapQuote(params);
180
+ return {
181
+ content: [
182
+ {
183
+ type: "text",
184
+ text: JSON.stringify(quote, null, 2),
185
+ },
186
+ ],
187
+ };
188
+ }
189
+ case "build_swap_tx": {
190
+ const params = z
191
+ .object({
192
+ fromToken: z.string(),
193
+ toToken: z.string(),
194
+ amount: z.number().positive(),
195
+ recipientAddress: z.string().regex(/^0x[0-9a-fA-F]{40}$/),
196
+ slippageBps: z.number().optional().default(50),
197
+ })
198
+ .parse(args);
199
+ const tx = await buildSwapTx(params);
200
+ return {
201
+ content: [
202
+ {
203
+ type: "text",
204
+ text: JSON.stringify(tx, null, 2),
205
+ },
206
+ ],
207
+ };
208
+ }
209
+ case "list_supported_tokens": {
210
+ const tokens = await getSupportedTokens();
211
+ return {
212
+ content: [
213
+ {
214
+ type: "text",
215
+ text: JSON.stringify(tokens, null, 2),
216
+ },
217
+ ],
218
+ };
219
+ }
220
+ default:
221
+ return {
222
+ content: [{ type: "text", text: `Unknown tool: ${name}` }],
223
+ isError: true,
224
+ };
225
+ }
226
+ }
227
+ catch (err) {
228
+ const message = err instanceof Error ? err.message : String(err);
229
+ return {
230
+ content: [{ type: "text", text: `Error: ${message}` }],
231
+ isError: true,
232
+ };
233
+ }
234
+ });
235
+ // ─── Start ─────────────────────────────────────────────────────────────────
236
+ async function main() {
237
+ const transport = new StdioServerTransport();
238
+ await server.connect(transport);
239
+ console.error("intent-swap MCP server running on stdio");
240
+ }
241
+ main().catch((err) => {
242
+ console.error("Fatal:", err);
243
+ process.exit(1);
244
+ });
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Intent parser — rule-based with optional OpenAI fallback.
3
+ * Kept lightweight so the MCP server works without an API key.
4
+ */
5
+ export interface ParsedIntent {
6
+ intentType: "swap" | "conditional";
7
+ fromToken: string;
8
+ toToken: string;
9
+ amount: number | null;
10
+ amountType: "exact" | "percentage" | "max" | null;
11
+ slippagePref: "low" | "normal" | "high";
12
+ condition: {
13
+ token: string;
14
+ operator: "above" | "below";
15
+ targetPrice: number;
16
+ } | null;
17
+ summary: string;
18
+ parsedBy: "rules" | "llm";
19
+ }
20
+ /**
21
+ * Parse a natural language swap intent.
22
+ * Strategy: rule-based first (fast, no API call), LLM fallback for complex/ambiguous inputs.
23
+ * If OPENAI_API_KEY is not set, always uses rules.
24
+ */
25
+ export declare function parseIntent(intent: string): Promise<ParsedIntent>;
@@ -0,0 +1,157 @@
1
+ /**
2
+ * Intent parser — rule-based with optional OpenAI fallback.
3
+ * Kept lightweight so the MCP server works without an API key.
4
+ */
5
+ // ─── Token registry ────────────────────────────────────────────────────────
6
+ const TOKENS = [
7
+ "ETH", "WETH", "WBTC", "BTC", "USDC", "USDT", "DAI", "ARB",
8
+ "UNI", "LINK", "MATIC", "OP", "PEPE", "SHIB", "AAVE", "CRV",
9
+ ];
10
+ const TOKEN_ALIASES = {
11
+ "以太": "ETH", "以太坊": "ETH",
12
+ "比特": "WBTC", "比特币": "WBTC",
13
+ "稳定币": "USDC", "美元": "USDC",
14
+ "泰达": "USDT",
15
+ "以太坊包装": "WETH",
16
+ "polygon": "MATIC", "optimism": "OP",
17
+ };
18
+ function normalizeText(text) {
19
+ let result = text.toUpperCase();
20
+ for (const [alias, token] of Object.entries(TOKEN_ALIASES)) {
21
+ result = result.replace(new RegExp(alias, "gi"), token);
22
+ }
23
+ return result;
24
+ }
25
+ function extractToken(text, exclude) {
26
+ const normalized = normalizeText(text);
27
+ const exact = TOKENS.find((t) => t !== exclude && new RegExp(`\\b${t}\\b`).test(normalized));
28
+ if (exact)
29
+ return exact;
30
+ return TOKENS.find((t) => t !== exclude && normalized.includes(t)) ?? "USDC";
31
+ }
32
+ function extractAmount(text) {
33
+ if (/half|一半/i.test(text))
34
+ return { amount: 50, amountType: "percentage" };
35
+ if (/all|max|full|全部|所有|最大|everything/i.test(text))
36
+ return { amount: null, amountType: "max" };
37
+ const pct = text.match(/(\d+)\s*[%%]/);
38
+ if (pct)
39
+ return { amount: Number(pct[1]), amountType: "percentage" };
40
+ const num = text.match(/(\d+\.?\d*)/);
41
+ if (num)
42
+ return { amount: Number(num[1]), amountType: "exact" };
43
+ return { amount: null, amountType: null };
44
+ }
45
+ function extractSlippage(text) {
46
+ if (/low\s*slippage|tight|minimal|低滑点|精确/i.test(text))
47
+ return "low";
48
+ if (/high\s*slippage|fast|urgent|高滑点|快速|紧急/i.test(text))
49
+ return "high";
50
+ return "normal";
51
+ }
52
+ function extractCondition(text) {
53
+ // "when ETH drops below 3000" / "if ETH goes above 4000"
54
+ const match = text.match(/(?:when|if|once|当|如果)\s+(\w+)\s+(?:drops?|falls?|goes?|跌|低于|下跌|涨|高于|上涨)\s+(?:below|above|under|over|到|至)?\s*\$?(\d+(?:,\d{3})*(?:\.\d+)?)/i);
55
+ if (!match)
56
+ return null;
57
+ const token = match[1].toUpperCase();
58
+ const price = Number(match[2].replace(/,/g, ""));
59
+ const isBelow = /drops?|falls?|below|under|跌|低于|下跌/i.test(match[0]);
60
+ return {
61
+ token: TOKENS.includes(token) ? token : "ETH",
62
+ operator: isBelow ? "below" : "above",
63
+ targetPrice: price,
64
+ };
65
+ }
66
+ // ─── Rule-based parser ─────────────────────────────────────────────────────
67
+ function ruleParse(intent) {
68
+ const fromToken = extractToken(intent);
69
+ const toToken = extractToken(intent, fromToken);
70
+ const { amount, amountType } = extractAmount(intent);
71
+ const slippagePref = extractSlippage(intent);
72
+ const condition = extractCondition(intent);
73
+ const amountStr = amount === null
74
+ ? amountType === "max"
75
+ ? "all"
76
+ : "some"
77
+ : amountType === "percentage"
78
+ ? `${amount}%`
79
+ : `${amount}`;
80
+ return {
81
+ intentType: condition ? "conditional" : "swap",
82
+ fromToken,
83
+ toToken,
84
+ amount,
85
+ amountType,
86
+ slippagePref,
87
+ condition,
88
+ summary: `Swap ${amountStr} ${fromToken} → ${toToken} with ${slippagePref} slippage`,
89
+ parsedBy: "rules",
90
+ };
91
+ }
92
+ // ─── LLM parser (requires OPENAI_API_KEY env var) ─────────────────────────
93
+ async function llmParse(intent) {
94
+ const apiKey = process.env.OPENAI_API_KEY;
95
+ if (!apiKey)
96
+ throw new Error("OPENAI_API_KEY not set");
97
+ const OpenAI = (await import("openai")).default;
98
+ const client = new OpenAI({ apiKey });
99
+ const completion = await client.chat.completions.create({
100
+ model: "gpt-4o-mini",
101
+ temperature: 0,
102
+ response_format: { type: "json_object" },
103
+ messages: [
104
+ {
105
+ role: "system",
106
+ content: `You are a DeFi swap intent parser. Extract structured swap info from natural language.
107
+ Supported tokens: ${TOKENS.join(", ")}
108
+ Return ONLY valid JSON matching this schema:
109
+ {
110
+ "intentType": "swap" | "conditional",
111
+ "fromToken": string,
112
+ "toToken": string,
113
+ "amount": number | null,
114
+ "amountType": "exact" | "percentage" | "max" | null,
115
+ "slippagePref": "low" | "normal" | "high",
116
+ "condition": null | { "token": string, "operator": "above"|"below", "targetPrice": number },
117
+ "summary": string
118
+ }
119
+ Rules:
120
+ - amountType="max" means all tokens, set amount=null
121
+ - Write summary in the same language as the input
122
+ - If tokens are ambiguous, default fromToken="ETH", toToken="USDC"`,
123
+ },
124
+ { role: "user", content: intent },
125
+ ],
126
+ });
127
+ const raw = completion.choices[0]?.message?.content;
128
+ if (!raw)
129
+ throw new Error("Empty LLM response");
130
+ const parsed = JSON.parse(raw);
131
+ if (!parsed.fromToken || !parsed.toToken || !parsed.intentType) {
132
+ throw new Error("Invalid LLM response structure");
133
+ }
134
+ return { ...parsed, parsedBy: "llm" };
135
+ }
136
+ // ─── Public API ────────────────────────────────────────────────────────────
137
+ /**
138
+ * Parse a natural language swap intent.
139
+ * Strategy: rule-based first (fast, no API call), LLM fallback for complex/ambiguous inputs.
140
+ * If OPENAI_API_KEY is not set, always uses rules.
141
+ */
142
+ export async function parseIntent(intent) {
143
+ // Rule-based handles the common cases instantly
144
+ const ruleResult = ruleParse(intent);
145
+ // If rules found both tokens and an amount, trust it
146
+ if (ruleResult.fromToken !== ruleResult.toToken && ruleResult.amount !== null) {
147
+ return ruleResult;
148
+ }
149
+ // Ambiguous — try LLM for better understanding
150
+ try {
151
+ return await llmParse(intent);
152
+ }
153
+ catch {
154
+ // No API key or LLM failed — fall back to rule result
155
+ return ruleResult;
156
+ }
157
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Price feed — CoinGecko free API, no key required.
3
+ */
4
+ export declare function getTokenPrice(symbol: string): Promise<number | null>;
5
+ export declare function getSupportedTokens(): Promise<{
6
+ symbol: string;
7
+ coingeckoId: string;
8
+ priceUsd: number;
9
+ }[]>;
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Price feed — CoinGecko free API, no key required.
3
+ */
4
+ const COINGECKO_IDS = {
5
+ ETH: "ethereum",
6
+ WETH: "weth",
7
+ WBTC: "wrapped-bitcoin",
8
+ BTC: "bitcoin",
9
+ USDC: "usd-coin",
10
+ USDT: "tether",
11
+ DAI: "dai",
12
+ ARB: "arbitrum",
13
+ UNI: "uniswap",
14
+ LINK: "chainlink",
15
+ MATIC: "matic-network",
16
+ OP: "optimism",
17
+ PEPE: "pepe",
18
+ SHIB: "shiba-inu",
19
+ AAVE: "aave",
20
+ CRV: "curve-dao-token",
21
+ };
22
+ // Simple in-memory cache (60s TTL)
23
+ const priceCache = new Map();
24
+ const CACHE_TTL = 60_000;
25
+ export async function getTokenPrice(symbol) {
26
+ const id = COINGECKO_IDS[symbol.toUpperCase()];
27
+ if (!id)
28
+ return null;
29
+ const cached = priceCache.get(symbol);
30
+ if (cached && Date.now() - cached.ts < CACHE_TTL)
31
+ return cached.price;
32
+ try {
33
+ const res = await fetch(`https://api.coingecko.com/api/v3/simple/price?ids=${id}&vs_currencies=usd`, { signal: AbortSignal.timeout(5000) });
34
+ const data = (await res.json());
35
+ const price = data[id]?.usd ?? null;
36
+ if (price !== null)
37
+ priceCache.set(symbol, { price, ts: Date.now() });
38
+ return price;
39
+ }
40
+ catch {
41
+ return null;
42
+ }
43
+ }
44
+ export async function getSupportedTokens() {
45
+ const symbols = Object.keys(COINGECKO_IDS);
46
+ const ids = Object.values(COINGECKO_IDS).join(",");
47
+ let prices = {};
48
+ try {
49
+ const res = await fetch(`https://api.coingecko.com/api/v3/simple/price?ids=${ids}&vs_currencies=usd`, { signal: AbortSignal.timeout(5000) });
50
+ const data = (await res.json());
51
+ for (const [sym, id] of Object.entries(COINGECKO_IDS)) {
52
+ if (data[id]?.usd)
53
+ prices[sym] = data[id].usd;
54
+ }
55
+ }
56
+ catch {
57
+ // return without prices
58
+ }
59
+ return symbols.map((sym) => ({
60
+ symbol: sym,
61
+ coingeckoId: COINGECKO_IDS[sym],
62
+ priceUsd: prices[sym] ?? null,
63
+ }));
64
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Uniswap V3 quote + tx builder.
3
+ * Uses public RPC — no API key required.
4
+ *
5
+ * Quote: calls QuoterV2 on-chain
6
+ * Build: generates SwapRouter02 calldata via viem
7
+ */
8
+ import { type Address } from "viem";
9
+ export interface SwapQuote {
10
+ fromToken: string;
11
+ toToken: string;
12
+ amountIn: number;
13
+ amountOut: number;
14
+ feeTier: number;
15
+ priceImpactPct: number | null;
16
+ gasEstimate: number;
17
+ rateFormatted: string;
18
+ }
19
+ export declare function getSwapQuote(params: {
20
+ fromToken: string;
21
+ toToken: string;
22
+ amount: number;
23
+ slippageBps?: number;
24
+ }): Promise<SwapQuote>;
25
+ export interface SwapTx {
26
+ to: Address;
27
+ data: string;
28
+ value: string;
29
+ fromToken: string;
30
+ toToken: string;
31
+ amountIn: number;
32
+ estimatedAmountOut: number;
33
+ feeTier: number;
34
+ slippageBps: number;
35
+ summary: string;
36
+ warning: string;
37
+ }
38
+ export declare function buildSwapTx(params: {
39
+ fromToken: string;
40
+ toToken: string;
41
+ amount: number;
42
+ recipientAddress: string;
43
+ slippageBps?: number;
44
+ }): Promise<SwapTx>;