Securing a Solana Trading Bot That Holds Keys

The key is the whole attack surface. Where it leaks, what bounds the damage when it does, and the dependency risk nobody audits.

BoltTx Team··9 min read
solanasecuritykey-managementtrading-botoperationstransaction-landing

A trading bot is a program that signs transactions automatically. ★That is the entire security model, and it means a compromised process is a compromised wallet.★

The useful question is not how to make compromise impossible. It is what an attacker gets when it happens.

The Assumption Worth Starting From

★Design as though the process will be compromised, because the alternative is a design with no bound on the damage.★

hot wallet balance = ★maximum loss from a compromised bot★

That single line settles most sizing debates. A wallet holding what the strategy needs to operate for a day loses a day of working capital. A wallet holding everything loses everything, and no amount of code hardening changes which of those you chose.

Separate by trust level, not by convenience:

Wallet Holds If compromised
★Hot / trading★ ★Working capital only★ ★Bounded, recoverable★
Fee payer SOL for fees Wasted fees only
Treasury ★Everything else★ ★Never online★

Where Keys Actually Leak

Not usually through cryptography. Through ordinary operational mistakes:

// ★Every one of these has happened.★
console.log("signing with", keypair.secretKey);     // logs
throw new Error(`failed for ${JSON.stringify(cfg)}`); // ★config in the trace★
await axios.post(url, { ...config });                // ★sent to a third party★
git add .env                                          // committed

★The exception trace is the one people miss.★ An error object that captures configuration, sent to an error-reporting service, has just exported your key to a vendor.

Concrete defences that cost nothing:

Keep the key in a dedicated object that has no toJSON and whose toString returns a placeholder.

★Never put the key in the same structure as loggable configuration.★

Load from an environment variable or secret manager, never a file inside the repo.

Add the key path to .gitignore before the key exists, not after.

If your key handling is sound and transactions still miss, a free BoltTx key is one line to test the submission path.

Dependencies Are the Unaudited Surface

Your bot imports dozens of packages. ★Any one of them runs with the same access to your key as your own code.★

npm ci                    # ★lockfile, not npm install★
npm audit --production

What actually reduces this risk:

★Pin exact versions and commit the lockfile.★ A caret range means a compromised patch release enters your build automatically.

Delay upgrades. A supply-chain compromise is usually caught within days. Not being on the newest version for a week is cheap insurance.

Review what a dependency needs. A charting library that requires network access is worth a second look.

★The highest-value habit is minimising the dependency count in the process that holds the key.★ Anything that does not need to run next to a signing key should run somewhere else.

Bound What the Key Can Do

Application-level limits protect against a confused bot. ★They do not protect against a compromised one, because code holding the key can skip its own checks.★

Only on-chain constraints survive that:

Delegated token authority. Approve a specific amount so the key can spend that and nothing more.

A program-enforced limit. A small on-chain program that rejects anything outside its parameters. ★The only option where holding the key is not sufficient to take the funds.★

Time-locked withdrawals. Moving funds out of the treasury requires a delay, giving you a window to notice.

In-process limits are still worth having — they catch bugs and runaway loops, which are far more common than compromise. Just do not mistake them for a security boundary.

Detection Is What Turns a Breach Into an Incident

★You cannot prevent every compromise, but noticing within minutes rather than days changes the outcome entirely.★

// ★On-chain activity your logs do not know about.★
const onChain = await connection.getSignaturesForAddress(wallet, { limit: 100 });
const unlogged = onChain.filter((s) => !logged.has(s.signature));
if (unlogged.length) alert(`${unlogged.length} unexplained transactions`);

★This is the single most valuable alert a trading bot can have.★ A transaction signed by your key that your bot did not initiate has exactly one explanation, and it is worth waking someone up for.

Also worth alerting on:

Balance dropping faster than trading explains.

Transfers to addresses outside your known set.

★Activity while the bot is stopped★ — unambiguous and immediate.

Have a Response Plan Before You Need One

★Working out what to do during an incident is how funds get lost while people discuss.★

1. Stop the bot. Kill the process before anything else.

2. Move what remains. Pre-write and test this script. ★A sweep script you are writing during an incident is a script you are debugging during an incident.★

3. Revoke delegations. Any approved token authority survives the wallet being emptied.

4. Rotate everything. New keys, new API credentials, new server if the host is suspect.

5. Find the entry point before redeploying. ★Restoring from a backup that contains the compromise repeats it.★

The Practices That Matter Most

★Ranked by damage prevented per unit of effort:★

Small hot wallet. Bounds every other failure. One decision, permanent effect.

Separate treasury, offline. Nothing the bot can reach can drain it.

Key never in logs or error traces. Prevents the most common real-world leak.

Unexplained-transaction alert. Turns a silent drain into a five-minute incident.

Locked dependencies. Closes the surface nobody audits.

Everything else is refinement. ★A bot doing these five is in better shape than one with elaborate internal controls and a fully funded hot wallet.★

What Landing Looks Like

Real transactions through our delivery nodes: median confirmation 336ms — under one slot.

★Security and landing are independent problems.★ A well-secured bot still competes for inclusion like any other, and a fast one with a leaked key loses everything regardless of its slot distribution.

Where BoltTx Fits

We handle submission. Key custody stays entirely with you.

★You sign locally and we never see your private key — there is no key material to send us, and no version of our API that accepts one.★ We never hold funds, never sign, and never modify transaction contents.

Submissions route through our own delivery nodes in four regions with stake-weighted routing and no public mempool exposure, so a transaction is not observable in transit before it lands. An API key leaking costs you quota, not funds — the two are separate credentials with separate consequences.

The tip travels inside the transaction, paid on chain from your own wallet, and reverts with the transaction if it fails, because that is how Solana handles atomic transactions. You pay only on transactions that reach the chain.

Get a free API key. No monthly fee:

const connection = new Connection("https://la.bolttx.io/?api-key=YOUR_KEY");

FAQ

How do I secure a Solana trading bot? Assume the process can be compromised and bound the damage. A small hot wallet, an offline treasury, keys absent from logs, and an alert on unexplained transactions cover most of the risk.

How much SOL should a hot wallet hold? What the strategy needs to operate, and no more. That balance is the maximum loss from a compromise, which makes it a security decision rather than a convenience one.

Where do private keys usually leak? Logs, exception traces, error-reporting services, and committed config files. Cryptographic failures are rare; ordinary operational mistakes are not.

Why are error traces dangerous? An error capturing configuration and sent to a reporting service exports whatever that config contains. Keep keys out of any structure that might be serialised.

Do application-level limits protect me? Against bugs and runaway loops, yes. Against compromise, no, since code holding the key can skip its own checks. Only on-chain constraints survive that.

What on-chain protections are available? Delegated token authority for a bounded amount, a program that enforces limits, and time-locked treasury withdrawals. Only these survive an attacker holding the key.

How do I reduce dependency risk? Pin exact versions, commit the lockfile, delay upgrades by a few days, and minimise the number of packages running in the process that holds the key.

Why delay dependency upgrades? Supply-chain compromises are usually discovered within days. Not being on the newest release for a week costs little and avoids being an early victim.

What is the most valuable security alert? On-chain transactions signed by your key that your logs do not know about. There is exactly one explanation for that, and it warrants immediate action.

How do I detect a compromise quickly? Reconcile chain activity against your own logs frequently, and alert on balance movement that trading does not explain or activity while the bot is stopped.

What should my incident response be? Stop the process, sweep remaining funds with a pre-tested script, revoke delegations, rotate every credential, and find the entry point before redeploying.

Why pre-write the sweep script? Because writing it during an incident means debugging it during an incident. It should be tested in advance and ready to run without modification.

Does revoking a delegation matter after a wallet is emptied? Yes. An approved token authority persists independently of the balance, so a delegation left in place can drain funds you add later.

Should the treasury ever be online? No. It should hold everything the bot does not need, with top-ups as the only path between it and the hot wallet.

Does BoltTx see my private key? No. You sign locally, and there is no API that accepts key material. A leaked API key costs quota rather than funds, since the two are separate credentials.

What is the single highest-value security decision? Sizing the hot wallet. It bounds every other failure mode, it is one decision, and no amount of code hardening substitutes for it.

← Back to all posts