Batch swap and bridge multiple tokens into a single output token using Relay Protocol, with a single EIP-5792 batch transaction.
- Multi-token batch swaps/bridges in a single wallet call (EIP-5792)
- Same-chain and cross-chain routes with Relay Protocol
- Token holdings discovery with on-chain verification
- Route availability checks before quoting
- Automatic approval skipping when allowance is already sufficient
- Price impact filtering for low-liquidity tokens
- Transfer fee token detection - Blocks fee-on-transfer tokens that may fail
- Status polling using Relay intents
- Relay step execution (transaction + signature steps)
- Wallet detection for explicit deposits (EOA vs smart wallet/EIP-7702)
- Custom token support via Relay
/currencies/v2API - RPC batching via viem multicall for efficient on-chain queries
- Secure API proxy to protect API keys
flowchart TB
subgraph Client["Frontend (Browser)"]
UI[React App]
BS[bridgeService.js]
end
subgraph Vercel["Vercel Platform"]
API["/api/routescan<br/>Serverless Function"]
end
subgraph External["External APIs"]
RS[Routescan API]
RL[Relay Protocol API]
AL[Alchemy RPC]
PR[Public RPC]
DU[Dune Token Logo API]
end
UI --> BS
BS -->|"/api/routescan"| API
API -->|"+ API Key"| RS
BS -->|Direct| RL
BS -->|Direct| AL
BS -->|Direct| DU
UI -->|Wallet add chain| PR
style API fill:#10b981,color:#fff
style RS fill:#6366f1,color:#fff
style RL fill:#8b5cf6,color:#fff
- Ethereum (1)
- Base (8453)
- Arbitrum (42161)
To add more chains, update:
frontend/src/wagmi.js(networks + RPCs)frontend/src/bridgeService.js(RPC selection)frontend/src/wagmi.jsBRIDGE_CHAINSandCOMMON_TOKENS
This app uses EIP-5792 (Wallet Call API) for batching when supported. Wallets that do not support wallet_sendCalls fall back to sequential transactions.
π‘ Recommended Wallets: For the true batch transaction experience, use OKX Wallet or Ambire Wallet - they fully support EIP-5792 batch calls, allowing all swaps and approvals to execute in a single transaction.
Public RPC URLs are used for wallet network addition prompts to avoid origin restrictions.
- React + Vite
- wagmi + viem
- Reown AppKit (WalletConnect)
- Relay Protocol APIs
- Routescan API for holdings (proxied via serverless function)
- Alchemy RPC for on-chain multicall verification
- Public RPC for wallet network add prompts
- Dune token logo API for token icons
Create frontend/.env:
VITE_WALLETCONNECT_PROJECT_ID=your_walletconnect_project_id
VITE_ALCHEMY_API_KEY=your_alchemy_api_key
ROUTESCAN_API_KEY=your_routescan_api_key| Variable | Scope | Description |
|---|---|---|
VITE_WALLETCONNECT_PROJECT_ID |
Client | WalletConnect project ID |
VITE_ALCHEMY_API_KEY |
Client | Alchemy API key for RPC calls |
ROUTESCAN_API_KEY |
Server | Routescan API key (never exposed to client) |
sequenceDiagram
participant User
participant App
participant Proxy as API Proxy
participant Routescan
participant Relay
participant Wallet
User->>App: Connect Wallet
App->>Proxy: Fetch Holdings
Proxy->>Routescan: GET /erc20-holdings (+ API Key)
Routescan-->>Proxy: Token List
Proxy-->>App: Token List
App->>App: On-chain Balance Verification
User->>App: Select Tokens & Destination
App->>Relay: Check Route Availability
Relay-->>App: Routes Available
App->>Relay: Get Quote(s)
Relay-->>App: Quote with Steps
App->>App: Filter Approvals (skip if sufficient)
App->>Wallet: EIP-5792 Batch Transaction
Wallet-->>App: Transaction Hash
App->>Relay: Poll Intent Status
Relay-->>App: Completed
-
Wallet Connection
- Reown AppKit connects the wallet via WalletConnect
-
Fetch Holdings
- Request goes through
/api/routescanproxy - Proxy adds API key server-side and forwards to Routescan
- Response filtered for valid symbols and non-zero USD value
- Request goes through
-
On-chain Verification
- viem
multicallverifies balances using Alchemy RPC
- viem
-
Route Availability
- Relay price API:
POST https://api.relay.link/price - Checks if route exists for token and destination currency
- Relay price API:
-
Quote Creation
- Single token:
POST https://api.relay.link/quote/v2 - Multi-token same-chain: Multiple
quote/v2calls aggregated client-side - Multi-token cross-chain:
POST https://api.relay.link/execute/swap/multi-input - Tokens with price impact >15% are excluded
- Single token:
-
Approval Filtering
- Approve steps decoded and checked against current allowances
- If allowance sufficient, approve steps removed before execution
-
Execution (Batch Transaction)
- All approve + swap/deposit steps sent in single EIP-5792 batch via
useSendCalls
- All approve + swap/deposit steps sent in single EIP-5792 batch via
-
Status Tracking
- Each step includes status endpoint:
GET https://api.relay.link/intents/status/v3?requestId=... - UI polls these endpoints to show progress
- Each step includes status endpoint:
| Service | Endpoints | Purpose |
|---|---|---|
| Relay | /quote/v2, /execute/swap/multi-input, /price, /currencies/v2, /intents/status/v3 |
Quotes, execution, token metadata, status |
| Routescan | /v2/network/mainnet/evm/{chainId}/address/{address}/erc20-holdings |
Token holdings (via proxy) |
| Alchemy | JSON-RPC | Multicall balance verification |
| Public RPC | JSON-RPC | Wallet network add prompts |
| Dune | /beta/token/logo/{chainId}/{tokenAddress} |
Token logos |
βββ api/
β βββ routescan.js # Vercel serverless function (API proxy)
βββ frontend/
β βββ src/
β β βββ App.jsx # Main application
β β βββ bridgeService.js # API calls & business logic
β β βββ wagmi.js # Wallet configuration
β β βββ index.css # Styles
β βββ public/ # Static assets
β βββ .env # Environment variables
β βββ vite.config.js # Vite config with dev proxy
βββ vercel.json # Vercel deployment config
cd frontend
npm install
npm run devThe Vite dev server proxies /api/routescan requests to Routescan API, adding the API key from ROUTESCAN_API_KEY environment variable.
- Push code to GitHub
- Import project in Vercel
- Set environment variables in Vercel Dashboard:
VITE_WALLETCONNECT_PROJECT_IDVITE_ALCHEMY_API_KEYROUTESCAN_API_KEY(server-side, not exposed to client)
- Deploy
The vercel.json is pre-configured to:
- Build from
frontend/directory - Output to
frontend/dist - Route
/api/*to serverless functions inapi/
Yes. BatchBridge is a frontend interface only. All core bridging functionality is handled by Relay Protocol:
| Component | Handled By | Notes |
|---|---|---|
| Token custody | Relay Protocol | We never hold user funds |
| Cross-chain messaging | Relay Protocol | Secure solver network with MEV protection |
| Swap execution | Relay Protocol | Audited smart contracts |
| Price discovery | Relay Protocol | Real-time quotes from multiple sources |
| Transaction signing | User's Wallet | We never access private keys |
BatchBridge is a UI layer that:
- Fetches your token holdings (read-only)
- Helps you select tokens and amounts
- Requests quotes from Relay Protocol
- Batches multiple swap calls into one wallet transaction (EIP-5792)
- Displays transaction status
We implement several safety measures:
- β Transfer fee token detection - Blocks fee-on-transfer tokens that fail on Relay
- β Price impact limits - Warns/blocks swaps with >15% price impact
- β Route availability checks - Only shows tokens with valid routes
- β Approval filtering - Skips unnecessary token approvals
What we DON'T handle:
- Smart contract security β Relay Protocol's audited contracts
- Cross-chain finality β Relay's solver network
- MEV protection β Relay Protocol
- Slippage execution β Relay Protocol
No. This frontend:
- Never requests your private keys
- Never has custody of your tokens
- Only submits transactions YOU approve in your wallet
- Is fully open source for verification
MIT