All articles
Solana·December 6, 2025·5 min read

Solana Multi-Wallet Fan-Out: Automating Hundreds of Keypairs Safely

Running coordinated actions across dozens of wallets — for whitelist farming, volume distribution, or sybil resistance testing — requires a fan-out architecture that avoids nonce collisions and keeps private keys isolated from hot execution paths. This post covers hierarchical deterministic key derivation, encrypted keystore patterns, and batched priority-fee funding flows.

Solana multi-wallet fan-out is one of those patterns that sounds straightforward until you're debugging a nonce race at 2 AM because two workers claimed the same recent blockhash slot and one transaction landed while the other silently expired. Running coordinated actions across dozens — or hundreds — of keypairs requires deliberate architecture: deterministic key derivation, isolated signing paths, and a funding flow that doesn't become the bottleneck before your first slot even fires.

Hierarchical Deterministic Derivation: The Only Sane Starting Point

Generating keypairs ad hoc and storing them in a flat file is how projects get compromised. The correct approach is BIP-44 derivation over a single master seed, producing child keys at paths like m/44'/501'/{index}'/0' — the standard Solana derivation path used by Phantom and Backpack. Your master seed lives in one encrypted location; every wallet address in your fleet is reproducible from that single secret.

In practice, use @solana/web3.js alongside bip39 and ed25519-hd-key:

import { derivePath } from "ed25519-hd-key";
import { Keypair } from "@solana/web3.js";
import * as bip39 from "bip39";

const seed = bip39.mnemonicToSeedSync(process.env.MASTER_MNEMONIC!);
const path = `m/44'/501'/${index}'/0'`;
const { key } = derivePath(path, seed.toString("hex"));
const keypair = Keypair.fromSeed(key);

The index is the only variable. You can derive wallet 0 through wallet 999 on demand without ever writing private keys to disk. Audit surface drops to one secret, not N.

Keystore Patterns: Keeping Private Keys Off the Hot Path

The execution worker — the process that constructs and submits transactions — should never hold a raw private key in memory longer than one signing call. The pattern that works in production: a separate signing service (even just a local Unix socket process) that accepts {walletIndex, messageBytes} and returns {signature}. The worker passes serialized transaction bytes; the signer derives the key, signs, and discards it from scope immediately.

This boundary matters for a few reasons:

  • Memory safety: if the execution worker is compromised or dumps a core, private keys aren't in the snapshot.
  • Rate control: the signer becomes a natural choke point, preventing accidental burst-signing that triggers RPC rate limits.
  • Auditability: every sign operation can be logged with a timestamp, wallet index, and transaction fingerprint before it happens.

For larger fleets, replace the local signing service with a hardware-backed KMS (AWS KMS supports ed25519 as of late 2023). Latency is roughly 5–15 ms per call over the API — acceptable for most fan-out workloads where transaction submission latency dominates anyway.

Nonce Collision Avoidance and Blockhash Management

Solana's "recent blockhash" is valid for approximately 151 slots (~60 seconds at current slot times). If you're submitting 200 transactions from 200 wallets concurrently and you fetch one blockhash to stamp all of them, you're fine — they're all valid in the same window. The collision problem is more subtle: wallet-level nonce conflicts when the same keypair is used by two workers simultaneously, or when a retry fires before the original transaction has expired or confirmed.

The safe pattern:

  1. Assign one wallet index to exactly one worker thread. Never share a keypair across workers. If you need more parallelism, derive more keypairs.
  2. Use durable nonces for high-value or time-insensitive operations. A durable nonce account lets you sign offline and submit later without the 60-second expiry pressure. The nonce authority should be a separate, lower-exposure keypair, not your main treasury.
  3. Track pending transactions by wallet index in a shared state store (Redis works well). Before a worker submits, it checks that no unconfirmed transaction exists for that index. On confirmation or expiry, it clears the lock.

Fetching a fresh blockhash per transaction batch is cheap — one getLatestBlockhash call with confirmed commitment is sufficient for most workloads. Don't cache blockhashes across batches; the 30-second buffer is not as generous as it looks once you account for submission retries.

Batched Priority-Fee Funding: The Infrastructure Most Teams Get Wrong

Funding hundreds of wallets with SOL for rent and priority fees is not a one-time setup step — it's an ongoing operational concern. Wallets drain unevenly depending on activity, and an unfunded wallet is a silent failure that looks like a bug in your transaction logic.

A robust funding flow runs as a background job, not a one-off script:

  • Sweep threshold: if a wallet's SOL balance drops below a configurable floor (e.g., 0.005 SOL), queue it for a top-up.
  • Batch funding transactions: Solana supports up to ~15–20 SystemProgram.transfer instructions in a single transaction before hitting compute limits. Group your top-ups into batches to minimize funding transaction fees.
  • Priority fees on funding transactions themselves: during network congestion, unfunded wallets can't afford their own top-up. Fund from the treasury with a fixed 50,000–100,000 microlamport compute unit price to ensure funding lands even when the network is saturated.

The treasury keypair that sends funding should be air-gapped or KMS-backed — it's the highest-value key in the system. See our services overview for how we architect these funding pipelines as part of a full bot deployment.

Monitoring Fleet Health Without Drowning in RPC Calls

With 200+ wallets, naively polling every balance every 30 seconds is 400+ RPC calls per minute. Use getMultipleAccounts to batch up to 100 accounts per call — that reduces your polling load by 100x. Combine it with websocket subscriptions for the wallets currently active in a trading cycle; poll the rest on a slow background schedule.

Key metrics to expose per wallet:

  • SOL balance (funding health)
  • Last confirmed transaction slot (detects stuck workers)
  • Pending transaction count (detects retry storms)
  • Total fees paid in the last 24h (cost accounting)

A simple Prometheus scraper exporting these lets you alert on individual wallet failures rather than discovering them from downstream effects. When wallet 47 stops confirming transactions, you want a page — not a gap in your volume chart an hour later.


If you're building a fan-out system for Solana and want an architecture review or a production-ready implementation, reach out — this is the kind of infrastructure work we do day-to-day.

Need a bot like this built?

We design, build and run trading bots on Solana, Hyperliquid and Polymarket.

Start a project
#Solana#wallet automation#multi-wallet#fan-out#HD derivation#trading bots#keypair management#MEV#priority fees