
Trading Evm
- 17 installs
- 610 repo stars
- Updated June 26, 2026
- alsk1992/cloddsbot
trading-evm is a skill that swaps tokens on EVM chains using Uniswap V3 and the 1inch aggregator.
About
This skill swaps tokens on EVM chains (Ethereum, Arbitrum, Optimism, Base, Polygon) through Uniswap V3 and the 1inch aggregator. It fetches quotes, compares routes between the two DEXes, checks balances, and executes swaps with slippage control and Flashbots MEV protection on Ethereum. A developer uses it to programmatically trade tokens across EVM chains from the clodds bot.
- Swaps tokens on Ethereum, Arbitrum, Optimism, Base, and Polygon
- Uses Uniswap V3 and the 1inch aggregator with route comparison
- MEV protection via Flashbots on Ethereum
Trading Evm by the numbers
- 17 all-time installs (skills.sh)
- Ranked #731 of 1,106 Finance & Trading skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
trading-evm capabilities & compatibility
Requires EVM_PRIVATE_KEY; ALCHEMY_API_KEY and ONEINCH_API_KEY optional. On-chain gas applies.
- Capabilities
- dex swap · quote fetching · route comparison · balance check
- Use cases
- trading
- Runs
- Runs locally
- Pricing
- Bring your own API key
What trading-evm says it does
Trade any token on Ethereum, Arbitrum, Optimism, Base, and Polygon using Uniswap V3 and 1inch aggregator.
Swap ETH → USDC on Ethereum with MEV protection
npx skills add https://github.com/alsk1992/cloddsbot --skill trading-evmAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 17 |
|---|---|
| repo stars | ★ 610 |
| Last updated | June 26, 2026 |
| Repository | alsk1992/cloddsbot ↗ |
What it does
Swap tokens across EVM chains via Uniswap V3 and 1inch with route comparison.
Who is it for?
Programmatic token swaps across Ethereum, Arbitrum, Optimism, Base, and Polygon.
Skip if: Trading on Solana, centralized exchanges, or prediction markets.
When should I use this skill?
You need to quote or execute an EVM DEX swap with route comparison.
What you get
Quoted and executed EVM DEX swaps with best-route selection and MEV protection.
- DEX swap quotes
- Executed swap transactions with hashes
By the numbers
- 5 EVM chains supported
- 2 DEX/aggregator integrations (Uniswap V3, 1inch)
Files
EVM DEX Trading - Complete API Reference
Trade any token on Ethereum, Arbitrum, Optimism, Base, and Polygon using Uniswap V3 and 1inch aggregator.
Required Environment Variables
EVM_PRIVATE_KEY=0x... # Your EVM wallet private key
ALCHEMY_API_KEY=... # Optional: for better RPC
ONEINCH_API_KEY=... # Optional: for 1inch API---
Supported Chains
| Chain | Chain ID | DEXes | MEV Protection |
|---|---|---|---|
| Ethereum | 1 | Uniswap V3, 1inch | Flashbots Protect |
| Arbitrum | 42161 | Uniswap V3, 1inch | Sequencer |
| Optimism | 10 | Uniswap V3, 1inch | Sequencer |
| Base | 8453 | Uniswap V3, 1inch | Sequencer |
| Polygon | 137 | Uniswap V3, 1inch | Standard |
---
Chat Commands
Swaps
/swap eth <amount> <from> to <to> # Swap on Ethereum
/swap arb <amount> <from> to <to> # Swap on Arbitrum
/swap op <amount> <from> to <to> # Swap on Optimism
/swap base <amount> <from> to <to> # Swap on Base
/swap matic <amount> <from> to <to> # Swap on Polygon
# Examples:
/swap eth 1 ETH to USDC # Swap 1 ETH to USDC on Ethereum
/swap arb 100 USDC to ARB # Swap 100 USDC to ARB on Arbitrum
/swap base 0.5 ETH to DEGEN # Swap 0.5 ETH to DEGEN on BaseQuotes
/quote eth <amount> <from> to <to> # Get quote without executing
/quote arb 1 ETH to USDC # Quote on ArbitrumCompare Routes
/compare <chain> <amount> <from> to <to> # Compare Uniswap vs 1inch
/compare eth 1 ETH to USDC # Compare routes on EthereumBalances
/balance eth # Check ETH and token balances
/balance arb # Check Arbitrum balances
/balance base <token> # Check specific token on Base---
TypeScript API Reference
Uniswap V3
import {
executeUniswapSwap,
getUniswapQuote,
resolveToken,
getTokenInfo,
getEvmBalance
} from 'clodds/evm/uniswap';
// Get quote
const quote = await getUniswapQuote({
chain: 'ethereum',
tokenIn: 'ETH',
tokenOut: 'USDC',
amountIn: '1000000000000000000', // 1 ETH in wei
slippageTolerance: 0.5,
});
console.log(`Expected output: ${quote.amountOut}`);
console.log(`Price impact: ${quote.priceImpact}%`);
console.log(`Route: ${quote.route.join(' → ')}`);
// Execute swap
const result = await executeUniswapSwap({
chain: 'ethereum',
tokenIn: 'ETH',
tokenOut: 'USDC',
amountIn: '1000000000000000000',
slippageTolerance: 0.5,
deadline: 300, // 5 minutes
});
console.log(`TX: ${result.transactionHash}`);
console.log(`Amount out: ${result.amountOut}`);
// Resolve token symbol to address
const usdcAddress = resolveToken('USDC', 'ethereum');
// Get token info
const tokenInfo = await getTokenInfo('ethereum', usdcAddress);
console.log(`${tokenInfo.symbol}: ${tokenInfo.decimals} decimals`);
// Check balance
const balance = await getEvmBalance('ethereum', walletAddress, 'USDC');1inch Aggregator
import {
executeOneInchSwap,
getOneInchQuote,
getOneInchProtocols,
compareDexRoutes
} from 'clodds/evm/oneinch';
// Get quote from 1inch
const quote = await getOneInchQuote({
chain: 'ethereum',
fromToken: 'ETH',
toToken: 'USDC',
amount: '1000000000000000000',
});
console.log(`Expected output: ${quote.toAmount}`);
console.log(`Estimated gas: ${quote.estimatedGas}`);
console.log(`Protocols used: ${quote.protocols.join(', ')}`);
// Execute swap via 1inch
const result = await executeOneInchSwap({
chain: 'ethereum',
fromToken: 'ETH',
toToken: 'USDC',
amount: '1000000000000000000',
slippage: 0.5,
});
// Get available protocols
const protocols = await getOneInchProtocols('ethereum');
// ['UNISWAP_V3', 'SUSHISWAP', 'CURVE', ...]
// Compare routes between Uniswap and 1inch
const comparison = await compareDexRoutes({
chain: 'ethereum',
tokenIn: 'ETH',
tokenOut: 'USDC',
amountIn: '1000000000000000000',
});
console.log(`Uniswap: ${comparison.uniswap.amountOut}`);
console.log(`1inch: ${comparison.oneinch.amountOut}`);
console.log(`Best: ${comparison.best}`);---
Chain-Specific Examples
Ethereum
// Swap ETH → USDC on Ethereum with MEV protection
const result = await executeUniswapSwap({
chain: 'ethereum',
tokenIn: 'ETH',
tokenOut: 'USDC',
amountIn: '1000000000000000000',
useMevProtection: true, // Uses Flashbots
});Arbitrum
// Swap on Arbitrum (lower gas)
const result = await executeOneInchSwap({
chain: 'arbitrum',
fromToken: 'ETH',
toToken: 'ARB',
amount: '500000000000000000', // 0.5 ETH
slippage: 1,
});Base
// Swap on Base
const result = await executeUniswapSwap({
chain: 'base',
tokenIn: 'ETH',
tokenOut: 'DEGEN',
amountIn: '100000000000000000', // 0.1 ETH
slippageTolerance: 2, // Higher slippage for meme coins
});Optimism
// Swap on Optimism
const result = await executeOneInchSwap({
chain: 'optimism',
fromToken: 'USDC',
toToken: 'OP',
amount: '100000000', // 100 USDC (6 decimals)
slippage: 0.5,
});Polygon
// Swap on Polygon
const result = await executeUniswapSwap({
chain: 'polygon',
tokenIn: 'MATIC',
tokenOut: 'USDC',
amountIn: '10000000000000000000', // 10 MATIC
slippageTolerance: 0.5,
});---
Common Tokens
Ethereum
| Symbol | Address |
|---|---|
| ETH | Native |
| USDC | 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 |
| USDT | 0xdAC17F958D2ee523a2206206994597C13D831ec7 |
| WETH | 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 |
| DAI | 0x6B175474E89094C44Da98b954EescdeCB5BE3830 |
Arbitrum
| Symbol | Address |
|---|---|
| ETH | Native |
| ARB | 0x912CE59144191C1204E64559FE8253a0e49E6548 |
| USDC | 0xaf88d065e77c8cC2239327C5EDb3A432268e5831 |
Base
| Symbol | Address |
|---|---|
| ETH | Native |
| USDC | 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 |
| DEGEN | 0x4ed4E862860beD51a9570b96d89aF5E1B0Efefed |
Optimism
| Symbol | Address |
|---|---|
| ETH | Native |
| OP | 0x4200000000000000000000000000000000000042 |
| USDC | 0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85 |
---
MEV Protection
Ethereum (Flashbots)
// Automatically uses Flashbots Protect RPC
const result = await executeUniswapSwap({
chain: 'ethereum',
useMevProtection: true, // Sends via Flashbots
...
});L2 Chains
L2s (Arbitrum, Optimism, Base) have sequencer-level MEV protection by default.
---
Gas Estimation
// Get gas estimate before swapping
const quote = await getUniswapQuote({ ... });
console.log(`Estimated gas: ${quote.gasEstimate}`);
console.log(`Gas price: ${quote.gasPrice} gwei`);
console.log(`Total gas cost: ${quote.gasCostUsd} USD`);---
Error Handling
import { EvmSwapError, InsufficientBalanceError, SlippageExceededError } from 'clodds/evm';
try {
await executeUniswapSwap({ ... });
} catch (error) {
if (error instanceof InsufficientBalanceError) {
console.log('Not enough balance');
} else if (error instanceof SlippageExceededError) {
console.log('Price moved, increase slippage');
}
}/**
* Trading EVM CLI Skill
*
* Commands:
* /trading-evm swap <token> <amount> - Swap via DEX aggregator
* /trading-evm balance [chain] - Check balances
* /trading-evm transfer <to> <amount> <token> - Transfer tokens
* /trading-evm wallet - Wallet info
* /trading-evm chains - Supported chains
* /trading-evm approve <token> <spender> - Token approval
*/
import { formatHelp } from '../../help.js';
import { wrapSkillError } from '../../errors.js';
function helpText(): string {
return formatHelp({
name: 'EVM Trading',
description: 'DEX swaps, transfers, and multi-chain balances on EVM chains.',
sections: [
{
title: 'Trading',
commands: [
{ cmd: '/trading-evm swap <token> <amount> [--chain <chain>]', description: 'DEX swap (Odos/1inch/Uniswap)' },
{ cmd: '/trading-evm approve <token> <spender>', description: 'Token approval' },
],
},
{
title: 'Account',
commands: [
{ cmd: '/trading-evm balance [chain]', description: 'Check balances (single chain or all)' },
{ cmd: '/trading-evm transfer <to> <amount> [token]', description: 'Transfer tokens' },
{ cmd: '/trading-evm wallet', description: 'Wallet info' },
{ cmd: '/trading-evm chains', description: 'Supported chains' },
],
},
],
examples: [
'/trading-evm swap 0xA0b8...3E8 1.5 --chain polygon',
'/trading-evm balance all',
'/trading-evm transfer 0xDEAD...BEEF 0.1 ETH',
],
envVars: [
{ name: 'EVM_PRIVATE_KEY', description: 'Private key for signing transactions', required: true },
],
seeAlso: [
{ cmd: '/cake', description: 'PancakeSwap trading' },
{ cmd: '/bridge', description: 'Cross-chain bridging' },
{ cmd: '/bags', description: 'Portfolio overview' },
],
notes: [
'Shortcuts: /evm-trade',
'Supported chains: ethereum, polygon, arbitrum, optimism, base, avalanche, bsc',
],
});
}
async function execute(args: string): Promise<string> {
const parts = args.trim().split(/\s+/);
const cmd = parts[0]?.toLowerCase() || 'help';
try {
const evmMod = await import('../../../evm/index');
switch (cmd) {
case 'swap': {
const token = parts[1];
const amount = parts[2];
if (!token || !amount) return 'Usage: /trading-evm swap <token> <amount> [--chain <chain>]';
// Parse --chain flag
const chainIdx = parts.indexOf('--chain');
const chainInput = chainIdx !== -1 ? parts[chainIdx + 1] : 'ethereum';
const chain = evmMod.resolveChain(chainInput);
if (!chain) return `Unknown chain: ${chainInput}. Use /trading-evm chains to see supported chains.`;
const wallet = evmMod.getCurrentWallet();
if (!wallet) return 'No wallet configured. Set EVM_PRIVATE_KEY env var or use wallet management.';
// Try Odos first (best aggregator), fall back to Uniswap
try {
const quote = await evmMod.getOdosQuote({
chain: chain as any,
inputToken: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE', // native
outputToken: token,
amount: amount,
userAddress: wallet.address,
});
const result = await evmMod.executeOdosSwap({
chain: chain as any,
inputToken: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE',
outputToken: token,
amount: amount,
userAddress: wallet.address,
privateKey: process.env.EVM_PRIVATE_KEY || '',
maxSlippageBps: 100,
});
return `**Swap Executed via Odos**
Input: ${amount} (native)
Output: ${result.outputAmount}
Tx: ${result.txHash || 'N/A'}`;
} catch {
// Fallback to Uniswap
try {
const resolved = evmMod.resolveToken(token, chain as any);
const uniQuote = await evmMod.getUniswapQuote({
chain: chain as any,
inputToken: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE',
outputToken: resolved || token,
amount: amount,
});
return `**Uniswap Quote**
Input: ${amount} (native)
Output: ~${uniQuote.outputAmount}
Price Impact: ${uniQuote.priceImpact}%
Route: ${uniQuote.route?.join(' -> ') || 'direct'}
To execute, confirm swap parameters.`;
} catch (uniErr: any) {
return `Swap routing failed. Odos and Uniswap both errored.\n\nError: ${uniErr?.message || 'Unknown error'}`;
}
}
}
case 'balance':
case 'balances': {
const chainInput = parts[1] || 'all';
const wallet = evmMod.getCurrentWallet();
if (!wallet) return 'No wallet configured. Set EVM_PRIVATE_KEY env var.';
if (chainInput === 'all') {
const multiBalance = await evmMod.getMultiChainBalances(wallet.address);
const lines: string[] = ['**Multi-Chain Balances**', `Wallet: ${wallet.address}`, ''];
for (const cb of multiBalance.balances) {
if (cb.native && parseFloat(cb.native.balance) > 0) {
lines.push(`**${cb.chainName}**: ${cb.native.balance} ${cb.native.symbol}`);
}
for (const tok of cb.tokens) {
if (parseFloat(tok.balance) > 0) {
lines.push(` ${tok.symbol}: ${tok.balance}`);
}
}
}
if (lines.length <= 3) lines.push('No balances found across any chain.');
return lines.join('\n');
}
const chain = evmMod.resolveChain(chainInput);
if (!chain) return `Unknown chain: ${chainInput}. Use /trading-evm chains to see supported chains.`;
const chainBal = await evmMod.getChainBalances(chain, wallet.address);
const lines: string[] = [
`**${chain} Balances**`,
`Wallet: ${wallet.address}`,
'',
`Native: ${chainBal.native.balance} ${chainBal.native.symbol}`,
];
if (chainBal.tokens.length > 0) {
lines.push('', '**Tokens:**');
for (const tok of chainBal.tokens) {
if (parseFloat(tok.balance) > 0) {
lines.push(` ${tok.symbol}: ${tok.balance}`);
}
}
}
return lines.join('\n');
}
case 'transfer':
case 'send': {
const to = parts[1];
const amount = parts[2];
const token = parts[3];
if (!to || !amount) return 'Usage: /trading-evm transfer <to-address> <amount> [token]';
if (!evmMod.validateAddress(to)) return `Invalid address: ${to}`;
if (!evmMod.validateAmount(amount)) return `Invalid amount: ${amount}`;
const wallet = evmMod.getCurrentWallet();
if (!wallet) return 'No wallet configured. Set EVM_PRIVATE_KEY env var.';
// Parse --chain flag
const chainIdx = parts.indexOf('--chain');
const chainInput = chainIdx !== -1 ? parts[chainIdx + 1] : 'ethereum';
const chain = evmMod.resolveChain(chainInput);
if (!chain) return `Unknown chain: ${chainInput}`;
if (!token || token.toLowerCase() === 'eth' || token.toLowerCase() === 'native') {
// Native transfer
const result = await evmMod.sendNative({
chain: chain as any,
to,
amount,
privateKey: process.env.EVM_PRIVATE_KEY || '',
});
return `**Transfer ${result.success ? 'Sent' : 'Failed'}**
From: ${result.from}
To: ${result.to}
Amount: ${result.amount} (native)
Tx: ${result.txHash || 'N/A'}${result.error ? `\nError: ${result.error}` : ''}`;
} else {
// Token transfer
const result = await evmMod.sendToken({
chain: chain as any,
to,
amount,
privateKey: process.env.EVM_PRIVATE_KEY || '',
tokenAddress: token,
});
return `**Token Transfer ${result.success ? 'Sent' : 'Failed'}**
From: ${result.from}
To: ${result.to}
Token: ${result.token || token}
Amount: ${result.amount}
Tx: ${result.txHash || 'N/A'}${result.error ? `\nError: ${result.error}` : ''}`;
}
}
case 'wallet': {
const wallet = evmMod.getCurrentWallet();
if (!wallet) return 'No wallet configured. Set EVM_PRIVATE_KEY env var or generate one.';
const savedWallets = evmMod.listWallets();
const lines = [
'**EVM Wallet Info**',
'',
`Address: ${wallet.address}`,
'',
];
if (savedWallets.length > 0) {
lines.push('**Saved Wallets:**');
for (const w of savedWallets) {
const marker = w.address.toLowerCase() === wallet.address.toLowerCase() ? ' (active)' : '';
lines.push(` ${w.name}: ${w.address}${marker}`);
}
}
return lines.join('\n');
}
case 'chains': {
const supported = evmMod.getSupportedChains();
const lines = ['**Supported Chains**', ''];
for (const chain of supported) {
const config = evmMod.getChainConfig(chain);
lines.push(` ${chain} (chainId: ${config.chainId}) - ${config.name}`);
lines.push(` Explorer: ${config.explorer}`);
}
return lines.join('\n');
}
case 'approve': {
const tokenAddress = parts[1];
const spender = parts[2];
if (!tokenAddress || !spender) return 'Usage: /trading-evm approve <token-address> <spender-address>';
if (!evmMod.validateAddress(tokenAddress)) return `Invalid token address: ${tokenAddress}`;
if (!evmMod.validateAddress(spender)) return `Invalid spender address: ${spender}`;
const wallet = evmMod.getCurrentWallet();
if (!wallet) return 'No wallet configured. Set EVM_PRIVATE_KEY env var.';
const chainIdx = parts.indexOf('--chain');
const chainInput = chainIdx !== -1 ? parts[chainIdx + 1] : 'ethereum';
const chain = evmMod.resolveChain(chainInput);
if (!chain) return `Unknown chain: ${chainInput}`;
const maxUint256 = '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff';
const result = await evmMod.writeContract({
chain: chain as any,
contractAddress: tokenAddress,
abi: evmMod.COMMON_ABIS.erc20,
method: 'approve',
args: [spender, maxUint256],
privateKey: process.env.EVM_PRIVATE_KEY || '',
});
return `**Approval ${result.success ? 'Sent' : 'Failed'}**
Token: ${tokenAddress}
Spender: ${spender}
Amount: MAX (unlimited)
Tx: ${result.txHash || 'N/A'}${result.error ? `\nError: ${result.error}` : ''}`;
}
default:
return helpText();
}
} catch (err: any) {
if (cmd === 'help' || cmd === '') return helpText();
return wrapSkillError('EVM Trading', cmd || 'command', err);
}
}
export default {
name: 'trading-evm',
description: 'EVM trading - DEX swaps, transfers, multi-chain balances',
commands: ['/trading-evm', '/evm-trade'],
handle: execute,
};
Related skills
FAQ
Which chains are supported?
Ethereum, Arbitrum, Optimism, Base, and Polygon, each with Uniswap V3 and 1inch.
Does it protect against MEV?
Yes, Ethereum swaps can use Flashbots Protect via useMevProtection.