Airdrop Farming Wallet Management System Development
Airdrop farming in 2024-2025 is professional activity with hundreds of wallets, systematic on-chain transactions and work with dozens of protocols simultaneously. Manual management doesn't scale: too many repetitive operations, too high error risk, too hard to track progress per wallet. Automation system is mandatory tool for serious farmer.
What is Professional Airdrop Farming
Analysis of major airdrops (Arbitrum, Optimism, ZkSync, LayerZero, EigenLayer) shows patterns that got rewarded: regular activity over many months, protocol diversity, native transactions (not just bridging), token holdings, governance participation. System should automate exactly these patterns while keeping activity organic.
System Architecture
Wallet Hierarchy
Professional farmer works with several key levels:
Master Wallet — cold wallet (Ledger/Trezor or air-gapped machine). Holds main capital. Never used directly in protocols.
Fund Wallets (2-5) — intermediate wallets for distribution. Get ETH/USDC from master, distribute to farming wallets.
Farming Wallets (50-500) — working wallets directly interacting with protocols. Each generated as separate HD-path from one or multiple seed phrases.
Master Wallet
↓ (manual transfers)
Fund Wallets [1-5]
↓ (automated distribution)
Farming Wallets [50-500]
↓ (automated interactions)
DeFi Protocols
Important: farming wallets shouldn't have direct on-chain connections to master wallet. Chain fund wallet → farming wallet with different time intervals reduces correlation.
Key Generation and Storage
All farming wallets generated deterministically from seed phrases via BIP44:
import { HDNodeWallet, Mnemonic } from "ethers";
function generateFarmingWallets(
mnemonic: string,
count: number,
startIndex: number = 0
): WalletInfo[] {
const masterNode = HDNodeWallet.fromMnemonic(
Mnemonic.fromPhrase(mnemonic)
).derivePath("m/44'/60'/0'/0");
return Array.from({ length: count }, (_, i) => {
const wallet = masterNode.deriveChild(startIndex + i);
return {
index: startIndex + i,
address: wallet.address,
privateKey: wallet.privateKey,
derivationPath: `m/44'/60'/0'/0/${startIndex + i}`,
};
});
}
Storage. Never store private keys openly. Options:
- AES-256-GCM encryption with password (KDF: Argon2id)
- Seed phrase only + on-demand derivation
- HashiCorp Vault for team use
Wallet and Activity Database
CREATE TABLE wallets (
id SERIAL PRIMARY KEY,
address VARCHAR(42) UNIQUE NOT NULL,
derivation_path VARCHAR(64),
wallet_group VARCHAR(64), -- for grouping
created_at TIMESTAMPTZ DEFAULT NOW(),
last_active_at TIMESTAMPTZ,
total_gas_spent NUMERIC(30, 18) DEFAULT 0,
notes TEXT,
tags TEXT[]
);
CREATE TABLE protocol_interactions (
id BIGSERIAL PRIMARY KEY,
wallet_id INTEGER REFERENCES wallets(id),
protocol VARCHAR(128) NOT NULL,
chain_id INTEGER NOT NULL,
tx_hash VARCHAR(66),
action_type VARCHAR(64), -- swap, bridge, stake, lp, vote
amount NUMERIC(30, 18),
gas_used NUMERIC(30, 18),
executed_at TIMESTAMPTZ DEFAULT NOW(),
status VARCHAR(16) DEFAULT 'pending',
metadata JSONB
);
CREATE TABLE farming_tasks (
id BIGSERIAL PRIMARY KEY,
wallet_id INTEGER REFERENCES wallets(id),
task_type VARCHAR(128) NOT NULL,
protocol VARCHAR(128) NOT NULL,
chain_id INTEGER NOT NULL,
parameters JSONB NOT NULL,
scheduled_at TIMESTAMPTZ,
executed_at TIMESTAMPTZ,
status VARCHAR(16) DEFAULT 'pending',
retry_count INTEGER DEFAULT 0,
error_message TEXT
);
Automation of Interactions
Task Runner
Transaction execution system should imitate human behavior: random delays between transactions, time-of-day variability, different gas prices.
class FarmingTaskRunner {
async executeTask(task: FarmingTask): Promise<TxReceipt> {
const wallet = await this.walletManager.getWallet(task.walletId);
const provider = this.getProvider(task.chainId);
// Random delay 30s - 5 min before transaction
const delay = randomBetween(30_000, 300_000);
await sleep(delay);
// Random gas price variation ±10%
const gasPrice = await this.getGasWithVariance(provider, 0.1);
const handler = this.handlers.get(task.taskType);
if (!handler) throw new Error(`Unknown task type: ${task.taskType}`);
return handler.execute(wallet, task.parameters, { gasPrice });
}
private async getGasWithVariance(provider: Provider, variance: number) {
const feeData = await provider.getFeeData();
const base = feeData.maxFeePerGas!;
const multiplier = 1 + (Math.random() * 2 - 1) * variance;
return base * BigInt(Math.round(multiplier * 100)) / 100n;
}
}
Protocol Handlers
Each protocol — separate handler:
// Example: Uniswap V3 swap handler
class UniswapV3SwapHandler implements ProtocolHandler {
async execute(
wallet: Wallet,
params: SwapParams,
options: ExecutionOptions
): Promise<TxReceipt> {
const router = new Contract(UNISWAP_V3_ROUTER, ROUTER_ABI, wallet);
const deadline = Math.floor(Date.now() / 1000) + 1800; // 30 min
const tx = await router.exactInputSingle({
tokenIn: params.tokenIn,
tokenOut: params.tokenOut,
fee: params.fee, // 500, 3000, 10000
recipient: wallet.address,
deadline,
amountIn: params.amountIn,
amountOutMinimum: params.minAmountOut,
sqrtPriceLimitX96: 0,
}, {
maxFeePerGas: options.gasPrice,
maxPriorityFeePerGas: options.maxPriorityFeePerGas,
});
return tx.wait();
}
}
Similar handlers created for: Curve, AAVE, GMX, Stargate, Wormhole/LayerZero bridge, Pendle, various lending protocols.
Task Scheduler
Tasks scheduled considering: minimum interval between transactions on one wallet, activity time windows, dependencies (get tokens first, then stake).
class TaskScheduler {
async scheduleForWallet(walletId: number, plan: FarmingPlan) {
const tasks: ScheduledTask[] = [];
let currentTime = plan.startTime;
for (const action of plan.actions) {
// Random shift ±20% of planned interval
const variance = action.interval * 0.2;
const jitter = (Math.random() * 2 - 1) * variance;
currentTime = new Date(currentTime.getTime() + action.interval + jitter);
tasks.push({
walletId,
taskType: action.type,
protocol: action.protocol,
chainId: action.chainId,
parameters: action.params,
scheduledAt: currentTime,
});
}
await this.db.farmingTasks.bulkInsert(tasks);
}
}
Monitoring and Analytics
Dashboard Metrics
For each wallet system shows:
- On-chain activity by protocols (with first/last transaction dates)
- Gas spent (in USD)
- Current positions (LP, staking, lending)
- Score by known metrics (volume, transaction count, unique protocols, active days)
- Current balance per chain
interface WalletStats {
address: string;
totalTxCount: number;
activeDays: number; // unique days with transactions
uniqueProtocols: number;
totalVolumeUSD: number;
totalGasSpentUSD: number;
chainActivity: Record<number, ChainActivity>;
protocolActivity: ProtocolActivity[];
estimatedAirdropScore: Record<string, number>; // project -> estimated score
}
Airdrop Eligibility Assessment
For each tracked project — set of on-chain criteria with weights. System auto-calculates each wallet's current score and recommends what needs doing.
Anti-sybil Protection
Modern airdrop systems (EigenLayer, Wormhole) actively fight sybil attacks. System should consider:
Activity Uniqueness. Don't copy patterns between wallets. Different amounts, different protocols, different time patterns.
IP Rotation. Each wallet or group works via separate proxy/VPN. Common IP = strong sybil signal.
Source of Funds. Funding chain shouldn't trace to one source. CEX withdrawals to different wallets — good. Direct transfer from one wallet to 100 — bad.
Wallet Age. Old wallets valued more. System should create wallets early and give them "history" before target deadline.
Gas and Economics
With 200 wallets, 3-5 transactions/day per wallet — gas optimization important:
- L2 transactions (Arbitrum, Base, Optimism) 10-50x cheaper than mainnet
- Batching: if protocol supports multicall — combine operations
- Gas price monitoring: transactions during low gas periods (night UTC)
- Auto-calculate minimum ETH balance per wallet
Stack
| Component | Technology |
|---|---|
| Backend | Node.js + TypeScript, Fastify |
| Task queue | Bull + Redis |
| Database | PostgreSQL + TimescaleDB |
| Blockchain | ethers.js v6, viem |
| RPC | Alchemy, Infura (with failover) |
| Proxy | SOCKS5 rotation (Bright Data, Oxylabs) |
| Frontend | React + TanStack Query |
| Monitoring | Grafana + Prometheus |
Timeline
- MVP (wallet generation, basic handlers for 3-5 protocols, dashboard): 4-6 weeks
- Production (20+ handlers, scheduler, analytics, anti-sybil): 10-14 weeks
- Support and updates for new protocols: ongoing







