Skip to main content

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.

PyPI version npm version License: MIT


The problem

Doing a cross-chain swap today (e.g. ETH on Base โ†’ MYST on Polygon) requires:

  1. Finding the best route across DEXes
  2. Handling native gas on the destination chain (cold start problem)
  3. Protecting against slippage and sandwich attacks
  4. 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 action
  • MEDIUM โ€” logs a warning
  • HIGH โ€” logs a warning, consider reducing amount or increasing slippage
  • CRITICAL โ€” 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_KEY from 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

  1. Query Paraswap โ€” aggregator covering 50+ DEXes, best price in most cases
  2. Query Uniswap V3 โ€” direct on-chain quote as fallback/comparison
  3. Pick the best โ€” highest expectedOutput wins
  4. 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

  1. autoswap.swap โ€” Full swap execution (live or dry-run)
  2. 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

autoswap-0.1.0.tar.gz (128.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

autoswap-0.1.0-py3-none-any.whl (63.1 kB view details)

Uploaded Python 3

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

Hashes for autoswap-0.1.0.tar.gz
Algorithm Hash digest
SHA256 1dd2a8dc90124d05c6358a183a41273ffa683e6d0ec49761418106512fbea6ad
MD5 97ae76b8301bcd717b72fdf8dd89c02f
BLAKE2b-256 599071b0215e9ae67fbb08f26cec51c1bf5fc8087838840209b2f981cb25827a

See more details on using hashes here.

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

Hashes for autoswap-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0b9764da5c66c3a7bfe0b657ee0f44beb8ab95bf323bd82e937525c4ebcd17c1
MD5 7bcf18c62248598864f97f0c7cf53c63
BLAKE2b-256 bab5fb1dbc1b933b2d64c223ede9045f538e7d6f5e7544b9d4c30138157a39ef

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page