Cross-chain swaps in one line โ built for AI agents. Auto-routing, bridge, gas, slippage protection.
Project description
AutoSwap ๐
Cross-chain swaps in one line โ built for AI agents.
The problem
Doing a cross-chain swap today (e.g. ETH on Base โ MYST on Polygon) requires:
- Finding the best route across DEXes
- Handling native gas on the destination chain (cold start problem)
- Protecting against slippage and sandwich attacks
- Managing bridge failures, provider rate limits, tx reverts
No existing tool solves this in a single call. AutoSwap does.
Quick Start
Python (1 line)
from autoswap import swap
result = swap(
from_token="ETH",
from_chain="base",
to_token="MYST",
to_chain="polygon",
amount=0.003,
slippage_max=2.0,
dry_run=True, # simulate first โ always
)
print(result.route_taken)
# โ "ETHโUSDC (base) | bridge USDC baseโpolygon | USDCโMYST (polygon)"
print(f"~{result.amount_out:.4f} MYST")
# โ "~47.3281 MYST"
JavaScript (1 line)
const { swap } = require('autoswap');
const result = await swap({
fromToken: 'ETH',
fromChain: 'base',
toToken: 'MYST',
toChain: 'polygon',
amount: 0.003,
slippageMax: 2.0,
dryRun: true,
});
console.log(result.routeTaken);
// โ "ETHโUSDC (base) | bridge USDC baseโpolygon | USDCโMYST (polygon)"
console.log(`~${result.amountOut} MYST`);
CLI
# Simulate a cross-chain swap
autoswap --from ETH --from-chain base --to MYST --to-chain polygon --amount 0.003 --dry-run
# Get a price quote (fastest, no wallet needed)
autoswap quote --from ETH --from-chain base --to USDC --to-chain base --amount 0.001
# Live swap (reads ETH_PRIVATE_KEY from environment)
autoswap --from USDC --from-chain base --to USDC --to-chain polygon --amount 10.0
Installation
Python
pip install autoswap
JavaScript / Node.js
npm install autoswap
MCP Tool (Claude / Cursor / Cline)
Add to your MCP config (.cursor/mcp.json or Claude Desktop config):
{
"mcpServers": {
"autoswap": {
"command": "python3",
"args": ["-m", "autoswap.mcp_handler"],
"env": {
"ETH_PRIVATE_KEY": "your_private_key_here"
}
}
}
}
Then Claude/Cursor can call autoswap.swap(...) directly.
Supported Chains
| Chain | Chain ID | Native Token | Status |
|---|---|---|---|
| Base | 8453 | ETH | โ Supported |
| Polygon | 137 | POL (MATIC) | โ Supported |
| Arbitrum | 42161 | ETH | โ Supported |
| Optimism | 10 | ETH | โ Supported |
| Ethereum | 1 | ETH | ๐ Coming soon |
Supported Bridge Routes
All combinations of: Base โ Polygon โ Arbitrum โ Optimism
Bridgeable tokens: USDC (primary), WETH
Supported Tokens
| Token | Base | Polygon | Arbitrum | Optimism |
|---|---|---|---|---|
| ETH/WETH | โ | โ | โ | โ |
| USDC | โ | โ | โ | โ |
| DAI | โ | โ | โ | โ |
| USDT | โ | โ | โ | โ |
| MYST | โ | โ | โ | โ |
| POL/MATIC | โ | โ | โ | โ |
Full API Reference
Python: swap()
from autoswap import swap, SwapResult
result: SwapResult = swap(
from_token="ETH", # Input token symbol (case-insensitive)
from_chain="base", # Source chain
to_token="MYST", # Output token symbol
to_chain="polygon", # Destination chain
amount=0.003, # Amount in human units (NOT wei)
wallet_key=None, # 0x... private key, or reads ETH_PRIVATE_KEY from env
slippage_max=2.0, # Max slippage % (default: 2.0)
dry_run=False, # True = simulate only (default: False)
)
SwapResult fields:
| Field | Type | Description |
|---|---|---|
success |
bool | Whether the swap succeeded |
dry_run |
bool | Whether this was a simulation |
route_taken |
str | Human-readable route (e.g. "ETHโUSDC (base) | bridge | USDCโMYST (polygon)") |
route_type |
str | "same_chain" | "direct_bridge" | "swap_bridge_swap" |
from_token |
str | Input token symbol |
from_chain |
str | Source chain |
to_token |
str | Output token symbol |
to_chain |
str | Destination chain |
amount_in |
float | Amount sent |
amount_out |
float | Estimated (dry-run) or actual (live) output |
tx_hashes |
list[str] | Transaction hashes (empty in dry-run) |
fees |
dict | Fee breakdown: {bridge_fee, gas_step1, ...} |
steps |
list[StepResult] | Step-by-step breakdown |
error |
str | None | Error message if failed |
JavaScript: swap(options)
const { swap, quote } = require('autoswap');
// Swap
const result = await swap({
fromToken: 'ETH', // Input token
fromChain: 'base', // Source chain
toToken: 'MYST', // Output token
toChain: 'polygon', // Destination chain
amount: 0.003, // Amount in human units
slippageMax: 2.0, // Max slippage % (default: 2.0)
walletKey: '0x...', // Optional; reads ETH_PRIVATE_KEY from env
dryRun: true, // Simulate (default: false)
timeoutMs: 60000, // Timeout in ms (default: 60000)
});
// Quote only (fast, no wallet needed)
const q = await quote({
fromToken: 'ETH', fromChain: 'base',
toToken: 'USDC', toChain: 'base',
amount: 0.001,
});
console.log(`Expected: ${q.expectedOutput} USDC`);
console.log(`Min out: ${q.minOutput} USDC`);
Security
AutoSwap is built with security as a first principle:
Slippage Protection
- Never sets
amountOutMin=0โ the most common source of MEV exploits - Slippage is calculated against real liquidity, not a fixed percentage of gas
- Default slippage: 2% (good for most pairs). Adjust down for stable/stable swaps
- Hard maximum: 50% โ any route with >50% slippage is rejected
Sandwich Attack Detection
AutoSwap detects and blocks suspicious trades:
# This will raise SafetyError if sandwich risk is detected
result = swap("ETH", "base", "MYST", "polygon", 0.003)
# โ SafetyError: "Sandwich risk CRITICAL: amountOutMin โ 0 on ETHโUSDC"
Risk levels:
LOWโ normal, no actionMEDIUMโ logs a warningHIGHโ logs a warning, consider reducing amount or increasing slippageCRITICALโ blocks the swap entirely
Gas Safety (Cold Start Problem)
AutoSwap automatically detects when you have no native gas on the destination chain and resolves it via a gasless relay. This prevents a common failure mode where a bridged token arrives but can't be used because there's no ETH/POL for gas.
Private Key Handling
- Never hardcode private keys โ use environment variables
- AutoSwap reads
ETH_PRIVATE_KEYfrom your environment - Compatible with agent-vault for encrypted key storage
- In dry-run mode, no key is needed โ safe to use in CI/CD
Environment Variable Setup
export ETH_PRIVATE_KEY="0x..." # Python/CLI
// Node.js โ set before importing autoswap
process.env.ETH_PRIVATE_KEY = '0x...';
How AutoSwap Works
Routing Algorithm
- Query Paraswap โ aggregator covering 50+ DEXes, best price in most cases
- Query Uniswap V3 โ direct on-chain quote as fallback/comparison
- Pick the best โ highest
expectedOutputwins - Validate โ safety checks before building transaction
Cross-Chain Bridge (Across Protocol)
- ~2-5 second fills via exclusive relayers
- USDC is the default bridge token (deepest liquidity)
- Automatic fallback if primary bridge route fails
Route Types
| Scenario | Route |
|---|---|
| ETH โ USDC (same chain) | swap via Paraswap |
| USDC Base โ USDC Polygon | direct bridge via Across |
| ETH Base โ MYST Polygon | ETHโUSDC (Base) | bridge | USDCโMYST (Polygon) |
| ETH Base โ USDC Polygon | ETHโUSDC (Base) | bridge USDC |
Comparison with Competitors
| Feature | AutoSwap | Relay.link | Li.Fi | 1inch Fusion |
|---|---|---|---|---|
| Single function call | โ | โ (manual steps) | โ (SDK setup) | โ (API key required) |
| Cold start gas fix | โ automatic | โ manual | โ manual | โ not addressed |
| Sandwich protection | โ built-in | โ ๏ธ partial | โ ๏ธ partial | โ |
| amountOutMin=0 guard | โ always | โ ๏ธ user's responsibility | โ ๏ธ user's responsibility | โ |
| AI agent / MCP ready | โ native | โ | โ | โ |
| Dry-run simulation | โ | โ | โ ๏ธ | โ |
| Open source | โ MIT | โ | โ GPL | โ |
| No API key needed | โ | โ | โ | โ |
| Slippage auto-calc | โ | โ ๏ธ fixed | โ ๏ธ fixed | โ |
| Retry + fallback | โ | โ | โ | โ |
TL;DR: AutoSwap is the only swap SDK designed for AI agents from the ground up. It handles every failure mode automatically โ including the cold start gas problem that derails other tools.
MCP Tool Integration
AutoSwap exposes itself as an MCP (Model Context Protocol) tool, letting Claude, Cursor, and Cline execute cross-chain swaps directly.
Available MCP Tools
autoswap.swapโ Full swap execution (live or dry-run)autoswap.swap_quoteโ Price quote only (fast, no wallet needed)
Example (Claude calling AutoSwap via MCP)
User: "Swap 0.003 ETH on Base to MYST on Polygon, show me the route first"
Claude: [calls autoswap.swap with dry_run=true]
โ Route: ETHโUSDC (base) | bridge USDC baseโpolygon | USDCโMYST (polygon)
โ Expected output: ~47.3 MYST
โ Steps: 3 (swap, bridge, swap)
โ Bridge fee: 0.08 USDC (~$0.08)
โ Estimated time: ~5 seconds
"Looks good. Execute it."
Claude: [calls autoswap.swap with dry_run=false]
โ TX 1: 0xabc... (ETHโUSDC, confirmed)
โ TX 2: 0xdef... (bridge deposit, confirmed)
โ TX 3: 0x123... (USDCโMYST, confirmed)
โ Received: 47.1 MYST
MCP Config (mcp-tool.json)
See mcp-tool.json for the full tool descriptor. This file is designed to be listed in MCP tool directories.
Examples
Dry-run then live (Python)
from autoswap import swap
# Step 1: Always simulate first
result = swap("ETH", "base", "MYST", "polygon", 0.003, dry_run=True)
result.print_summary()
# Check the route makes sense
print(f"Route: {result.route_taken}")
print(f"Expected output: {result.amount_out:.4f} MYST")
print(f"Steps: {len(result.steps)}")
print(f"Bridge fee: {result.fees.get('bridge_fee', 0):.4f} USDC")
# Step 2: Execute live
if result.success and result.amount_out > 40: # safety check
live_result = swap("ETH", "base", "MYST", "polygon", 0.003, dry_run=False)
if live_result.success:
print(f"โ
Received {live_result.amount_out:.4f} MYST")
print(f"TX hashes: {live_result.tx_hashes}")
Same-chain swap
from autoswap import swap
# ETH โ USDC on Base
result = swap("ETH", "base", "USDC", "base", 0.001, dry_run=True)
print(f"~{result.amount_out:.2f} USDC")
Direct bridge
from autoswap import swap
# USDC Base โ USDC Polygon (no swaps, just bridge)
result = swap("USDC", "base", "USDC", "polygon", 10.0, dry_run=True)
print(f"Route type: {result.route_type}") # "direct_bridge"
print(f"Bridge fee: {result.fees.get('bridge_fee', 0):.4f} USDC")
JSON output for AI agents (CLI)
autoswap --from ETH --from-chain base --to MYST --to-chain polygon \
--amount 0.003 --dry-run --json | jq '.routeTaken'
Error handling (Python)
from autoswap import swap, SwapError
from autoswap import SafetyError
try:
result = swap("ETH", "base", "MYST", "polygon", 0.003)
except SafetyError as e:
print(f"Safety blocked: {e}") # sandwich attack detected
except SwapError as e:
print(f"Swap failed: {e}") # route not found, etc.
Development
Setup
git clone https://github.com/fino-oss/autoswap
cd autoswap
pip install -e ".[dev]"
Run tests
pytest tests/ -v
Tests run in dry-run mode โ no real transactions.
Project structure
autoswap/
โโโ autoswap/ โ Python package (pip installable)
โ โโโ __init__.py โ Public API: swap(), SwapResult
โ โโโ cli.py โ CLI entry point
โ โโโ mcp_handler.py โ MCP subprocess handler
โโโ src/ โ Core implementation
โ โโโ swap.py โ Orchestrator
โ โโโ router.py โ DEX routing (Paraswap + Uniswap V3)
โ โโโ bridge.py โ Cross-chain bridge (Across Protocol)
โ โโโ gas.py โ Native gas resolver
โ โโโ safety.py โ Slippage + sandwich protection
โโโ npm/ โ JavaScript wrapper (npm package)
โ โโโ package.json
โ โโโ src/index.js โ JS API: swap(), quote()
โ โโโ bin/autoswap.js โ CLI
โโโ tests/ โ Dry-run tests
โโโ mcp-tool.json โ MCP tool descriptor
โโโ pyproject.toml โ PyPI config
โโโ README.md
Roadmap
- Phase 1: Python SDK (routing + bridge + gas + safety)
- Phase 2: MCP tool + npm package + PyPI publish
- Phase 3: Hosted API (
POST https://api.autoswap.dev/swap) โ - Phase 4: Arbitrum + Optimism full support
- Phase 5: Additional tokens (AAVE, LINK, UNI, ...)
- Phase 6: Solana cross-chain support
Contributing
PRs welcome. Run tests before submitting:
pytest tests/ -v --tb=short
License
MIT โ see LICENSE.
Built from real pain. Swap 0.003 ETH to MYST, 5 bugs, Sam manually sending POL. Now it's one line.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file autoswap-0.1.0.tar.gz.
File metadata
- Download URL: autoswap-0.1.0.tar.gz
- Upload date:
- Size: 128.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1dd2a8dc90124d05c6358a183a41273ffa683e6d0ec49761418106512fbea6ad
|
|
| MD5 |
97ae76b8301bcd717b72fdf8dd89c02f
|
|
| BLAKE2b-256 |
599071b0215e9ae67fbb08f26cec51c1bf5fc8087838840209b2f981cb25827a
|
File details
Details for the file autoswap-0.1.0-py3-none-any.whl.
File metadata
- Download URL: autoswap-0.1.0-py3-none-any.whl
- Upload date:
- Size: 63.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0b9764da5c66c3a7bfe0b657ee0f44beb8ab95bf323bd82e937525c4ebcd17c1
|
|
| MD5 |
7bcf18c62248598864f97f0c7cf53c63
|
|
| BLAKE2b-256 |
bab5fb1dbc1b933b2d64c223ede9045f538e7d6f5e7544b9d4c30138157a39ef
|