A practical guide for AI agents operating on-chain. Learn EIP-1559 fee mechanics, optimal chain selection, batch transaction strategies, and use the Purple Flea Wallet API to route every transfer to the cheapest available network in real time.
Before optimizing, understand what you're paying for. Gas is the unit of computational work on EVM chains. Every agent operation has a cost.
Since EIP-1559, Ethereum and most EVM chains have a protocol-determined base fee that adjusts block-by-block based on demand. This base fee is burned, not paid to validators. Agents that monitor the base fee can time transactions for minimum cost.
The priority fee (miner tip) is what you add on top of the base fee to incentivize fast inclusion. For non-urgent agent transactions, setting a minimal tip of 0.1–0.5 gwei can save 30–60% versus default wallet settings.
The maximum gas units your transaction can consume. A standard ETH transfer uses 21,000 units. USDC transfers use ~65,000. Smart contract interactions vary. Always estimate before submitting — setting too low causes out-of-gas reverts.
For a USDC transfer at 30 gwei base fee + 1 gwei tip on Ethereum: 65,000 × 31 gwei = 2,015,000 gwei = ~$5.20 USD. The same transfer on Polygon costs under $0.001. Chain selection is the single biggest gas lever for agents.
// Quick gas price check across chains using public RPCs
const chains = [
{ name: 'ethereum', rpc: 'https://eth.llamarpc.com' },
{ name: 'polygon', rpc: 'https://polygon.llamarpc.com' },
{ name: 'arbitrum', rpc: 'https://arbitrum.llamarpc.com' },
{ name: 'base', rpc: 'https://base.llamarpc.com' },
{ name: 'bnb', rpc: 'https://bsc.llamarpc.com' },
{ name: 'optimism', rpc: 'https://optimism.llamarpc.com' },
];
async function getGasPrice(chain) {
const resp = await fetch(chain.rpc, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0', id: 1,
method: 'eth_gasPrice', params: [],
}),
});
const { result } = await resp.json();
const gwei = parseInt(result, 16) / 1e9;
return { ...chain, gwei };
}
const prices = await Promise.all(chains.map(getGasPrice));
const cheapest = prices.sort((a, b) => a.gwei - b.gwei)[0];
console.log(`Cheapest: ${cheapest.name} @ ${cheapest.gwei.toFixed(2)} gwei`);
Typical costs for a USDC transfer and a smart contract interaction. Based on median network conditions. Ethereum is 100–10,000x more expensive than L2s and alt-L1s for the same operation.
| Chain | Avg Gas Price | USDC Transfer | Contract Call | Finality | Agent Rating | Cost Level |
|---|---|---|---|---|---|---|
| Polygon (MATIC) | 30–80 gwei | ~$0.003 | 2–5 sec | ★★★★★ | Very Cheap | |
| BNB Chain (BNB) | 1–3 gwei | ~$0.004 | 3–5 sec | ★★★★★ | Very Cheap | |
| Tron (TRX) | Energy model | ~$0.002 | 3 sec | ★★★★★ | Very Cheap | |
| Base (L2) | 0.01–0.1 gwei | ~$0.006 | 2 sec | ★★★★★ | Very Cheap | |
| Arbitrum (L2) | 0.01–0.1 gwei | ~$0.008 | 1 sec | ★★★★★ | Very Cheap | |
| Optimism (L2) | 0.01–0.5 gwei | ~$0.010 | 2 sec | ★★★★☆ | Very Cheap | |
| Solana (SOL) | ~5,000 lamports | ~$0.001 | <1 sec | ★★★★★ | Very Cheap | |
| Ethereum (L1) | 15–100+ gwei | $8 – $80 | 12–30 sec | ★★☆☆☆ | Expensive |
Agents that implement all 8 strategies routinely reduce transaction costs by 90% or more compared to naive implementations.
Before every transfer, query live gas prices across all supported chains. Route to the cheapest chain that supports USDC and your recipient. The Purple Flea Wallet API exposes a /gas-estimate endpoint for this.
Ethereum gas prices are 40–70% lower during UTC 02:00–08:00 (Asian night, US pre-dawn). For non-time-critical agent operations, schedule during these windows. L2s are less affected but still benefit.
Save 40–70% on ETHInstead of sending 10 separate USDC transfers, batch them into a single multicall transaction. The overhead gas (21,000 units) is paid once instead of 10 times. Use multicall contracts for EVM chains.
Save 60–80% per batchFor non-urgent transactions, set the EIP-1559 priority fee (tip) to its minimum — typically 0.1 gwei on L2s and 0.5–1 gwei on mainnet. Most wallets default to 2–5 gwei tips which is unnecessary.
Save 10–30% on tipsArbitrum, Optimism, and Base are Ethereum L2s that inherit Ethereum security but batch transactions into compressed calldata. They support the same USDC contract address format and are 100–500x cheaper than mainnet.
Save 99% vs L1Sending native ETH/MATIC/BNB uses 21,000 gas. Sending ERC-20 tokens like USDC uses 65,000+ gas. Where possible, use native token payments or pre-approve token allowances to reduce per-transaction gas.
Save 30–40% with nativeSubscribe to a gas oracle (Etherscan, Blocknative, or the Purple Flea Wallet API gas endpoint) to track real-time and predicted gas prices. Set agent thresholds: only send if base fee < X gwei.
Prevent overpaymentToken approvals are expensive (~45,000 gas). Approve max allowance (type(uint256).max) once and reuse across all future transfers. Store approval state and skip the approve step on subsequent calls.
Save 45k gas per reuseUTC hourly average gas prices (relative). Green = cheapest. Red = most expensive. Agents on Ethereum should schedule non-urgent transactions during the green windows (UTC 01:00–07:00).
UTC hours. Hover cells for details. Times reflect Ethereum mainnet historical averages.
Production-ready code for AI agents using the Purple Flea Wallet API to route every USDC transfer to the cheapest available chain.
/**
* GasOptimizer — Auto-route USDC transfers to cheapest chain
* Uses Purple Flea Wallet API for gas estimates and transfers.
*
* Supported chains: ethereum, polygon, bnb, arbitrum, optimism, base, solana, tron
*/
const WALLET_API = 'https://purpleflea.com/wallet-api';
class GasOptimizer {
constructor(agentId, apiKey) {
this.agentId = agentId;
this.headers = {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json',
};
// Cache gas estimates for 60 seconds to avoid rate limits
this.cache = new Map();
this.cacheTTL = 60_000;
}
/**
* Fetch live gas costs for all supported chains via Wallet API
* Returns array sorted cheapest-first.
*/
async getChainGasCosts(amountUsdc = 10) {
const cacheKey = `gas_${amountUsdc}`;
const cached = this.cache.get(cacheKey);
if (cached && Date.now() - cached.ts < this.cacheTTL) {
return cached.data;
}
const resp = await fetch(
`${WALLET_API}/gas-estimate?amount=${amountUsdc}&token=USDC`,
{ headers: this.headers }
);
const { chains } = await resp.json();
// Sort by total cost ascending (cheapest first)
const sorted = chains.sort((a, b) => a.estimated_cost_usd - b.estimated_cost_usd);
this.cache.set(cacheKey, { ts: Date.now(), data: sorted });
return sorted;
}
/**
* Select the cheapest chain that satisfies the agent's constraints.
*
* @param {object} opts
* @param {string[]} opts.excludeChains - chains to skip (e.g. ['ethereum'])
* @param {number} opts.maxCostUsd - reject chains above this fee threshold
* @param {number} opts.maxFinalitySec - reject slow-finality chains
* @param {number} opts.amountUsdc - amount being transferred (for fee calc)
*/
async selectOptimalChain({
excludeChains = [],
maxCostUsd = 0.10,
maxFinalitySec = 30,
amountUsdc = 10,
} = {}) {
const chains = await this.getChainGasCosts(amountUsdc);
const candidate = chains.find(c =>
!excludeChains.includes(c.chain) &&
c.estimated_cost_usd <= maxCostUsd &&
c.finality_seconds <= maxFinalitySec
);
if (!candidate) {
throw new Error('No chain meets constraints — relax maxCostUsd or maxFinalitySec');
}
console.log(`Selected: ${candidate.chain} | fee: $${candidate.estimated_cost_usd.toFixed(5)} | finality: ${candidate.finality_seconds}s`);
return candidate;
}
/**
* Send USDC on the cheapest available chain automatically.
*/
async sendOptimized(toAddress, amountUsdc, opts = {}) {
const chain = await this.selectOptimalChain({ ...opts, amountUsdc });
const resp = await fetch(`${WALLET_API}/send`, {
method: 'POST',
headers: this.headers,
body: JSON.stringify({
agent_id: this.agentId,
to: toAddress,
amount: amountUsdc,
token: 'USDC',
chain: chain.chain,
}),
});
const result = await resp.json();
return {
...result,
chain_selected: chain.chain,
gas_cost_usd: chain.estimated_cost_usd,
};
}
}
// Usage example
const optimizer = new GasOptimizer(
'agent_abc123',
'your_api_key_here'
);
// Send 25 USDC — auto-routes to cheapest chain, never spending >$0.05 on gas
const tx = await optimizer.sendOptimized(
'0xRecipientAddressHere',
25,
{
excludeChains: ['ethereum'], // never use expensive L1
maxCostUsd: 0.05, // reject if gas > $0.05
maxFinalitySec: 10, // need fast confirmation
}
);
console.log(`Sent on ${tx.chain_selected}, gas: $${tx.gas_cost_usd}`);
console.log(`Tx hash: ${tx.tx_hash}`);
/**
* BatchTransferManager — Collect transfers and execute as a single
* multicall batch to save 60-80% on gas vs individual transactions.
*/
class BatchTransferManager {
constructor(agentId, apiKey) {
this.agentId = agentId;
this.headers = { 'Authorization': `Bearer ${apiKey}` };
this.queue = [];
this.maxBatch = 50; // max transfers per batch
this.flushAfterMs = 5000; // auto-flush every 5 seconds
this.timer = null;
}
/**
* Queue a USDC transfer. Auto-flushes when batch is full or timer fires.
*/
enqueue(toAddress, amountUsdc, memo = '') {
this.queue.push({ to: toAddress, amount: amountUsdc, memo });
console.log(`Queued transfer: ${amountUsdc} USDC → ${toAddress} (queue size: ${this.queue.length})`);
if (this.queue.length >= this.maxBatch) {
this.flush();
return;
}
// Reset debounce timer
if (this.timer) clearTimeout(this.timer);
this.timer = setTimeout(() => this.flush(), this.flushAfterMs);
}
/**
* Execute all queued transfers as one batch transaction.
* Cost: ~21k base gas + ~25k per transfer (vs 65k individually).
*/
async flush(chain = 'polygon') {
if (this.queue.length === 0) return;
if (this.timer) { clearTimeout(this.timer); this.timer = null; }
const transfers = [...this.queue];
this.queue = [];
const totalUsdc = transfers.reduce((sum, t) => sum + t.amount, 0);
console.log(`Flushing batch: ${transfers.length} transfers, ${totalUsdc} USDC total`);
const resp = await fetch(`${WALLET_API}/batch-send`, {
method: 'POST',
headers: { ...this.headers, 'Content-Type': 'application/json' },
body: JSON.stringify({
agent_id: this.agentId,
chain,
transfers,
token: 'USDC',
}),
});
const result = await resp.json();
const saving = (result.individual_gas_usd - result.batch_gas_usd).toFixed(4);
console.log(`Batch tx: ${result.tx_hash}`);
console.log(`Gas saved: $${saving} (${result.batch_gas_usd} vs $${result.individual_gas_usd})`);
return result;
}
}
// Usage: agent collecting payments to distribute to workers
const batcher = new BatchTransferManager('agent_xyz', 'api_key');
batcher.enqueue('0xWorker1...', 5.00, 'task-001 completion');
batcher.enqueue('0xWorker2...', 3.50, 'task-002 completion');
batcher.enqueue('0xWorker3...', 7.25, 'task-003 completion');
// All 3 flush together after 5 seconds as one tx
// Saves ~60% on gas vs 3 individual sends
EIP-1559 changed how gas pricing works. Agents need to set maxFeePerGas and maxPriorityFeePerGas correctly to avoid overpaying while still getting included quickly.
The absolute maximum you will pay per gas unit. Set this to baseFee * 2 + maxPriorityFeePerGas to handle two blocks of base fee increases. The actual payment is always min(maxFeePerGas, baseFee + tip).
For most agent transactions, set 0.1–1 gwei. Validators prioritize higher tips, but during normal congestion a 0.5 gwei tip gets included within 1–3 blocks. Only increase for time-critical operations.
Set the gas limit to 120% of the estimated gas. This prevents out-of-gas failures on edge cases without over-reserving funds. Unused gas is always refunded.
/**
* Build optimal EIP-1559 gas parameters.
* Fetches current base fee and calculates safe limits.
*/
async function getOptimalGasParams(rpcUrl, urgency = 'normal') {
// Fetch latest block to get current base fee
const resp = await fetch(rpcUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0', id: 1,
method: 'eth_getBlockByNumber',
params: ['latest', false],
}),
});
const { result: block } = await resp.json();
const baseFeeGwei = parseInt(block.baseFeePerGas, 16) / 1e9;
// Set priority fee based on urgency
const tipMap = {
slow: 0.1, // included in 10+ blocks, cheapest
normal: 0.5, // included in 1-3 blocks
fast: 2.0, // included next block
urgent: 5.0, // top of mempool
};
const tip = tipMap[urgency] ?? 0.5;
return {
// maxFeePerGas: 2x current base fee buffer + tip
maxFeePerGas: BigInt(Math.ceil((baseFeeGwei * 2 + tip) * 1e9)),
maxPriorityFeePerGas: BigInt(Math.ceil(tip * 1e9)),
currentBaseFeeGwei: baseFeeGwei,
estimatedCostGwei: baseFeeGwei + tip,
};
}
// Example: get params for a non-urgent agent transfer
const params = await getOptimalGasParams(
'https://polygon.llamarpc.com',
'normal'
);
console.log(`Base fee: ${params.currentBaseFeeGwei} gwei`);
console.log(`maxFeePerGas: ${params.maxFeePerGas / BigInt(1e9)} gwei`);
console.log(`Tip: ${params.maxPriorityFeePerGas / BigInt(1e9)} gwei`);
Claim free USDC from the Purple Flea faucet. Your agent starts on the cheapest chain automatically. Explore all 6 services with the wallet API guiding every transaction cost decision.