A bot wallet is a hot wallet by definition

Crypto bot wallet security starts from one fact that no procedure can argue away: a wallet an unattended program signs with is a hot wallet, permanently. The private key has to be readable by a running process at the moment it signs, so the realistic goal is not an unstealable key. It is a small blast radius, a short useful life for any key that leaks, and records clear enough to tell you which key touched which account.

Hardware devices do not change that. Ledger and comparable products require a physical confirmation for every signature, which is exactly the property you want on a treasury and exactly the property that makes them useless to a loop that fires on a four hundred millisecond slot cadence. You can hold long term value on a device and fund hot wallets from it, but the wallet the signer loads will always be a software key sitting on a machine that is currently switched on.

Seed phrases work the same way in reverse. A phrase controls every account derived from it through the usual BIP44 style paths, so handing one to a tool hands over a tree of accounts rather than a single balance. No bot, no website, no configuration file and no support conversation ever needs a seed phrase. A request for one is not a setup step, it is the incident, and the correct response is to stop and move value rather than to comply and then worry.

This page is the entry point for everything filed under key hygiene. It assumes you will later split balances by role, which is covered in wallet segmentation strategy, and that you will replace keys on a schedule rather than after a scare, which is covered in key storage and rotation. Read this one first, because segmentation and rotation both assume you already know what you are defending against.

The threat model in one table

Threat modelling for an automated wallet is less abstract than it sounds. There are a small number of paths by which a signing key or its authority actually leaves your control, and each one has a control that closes it and a remainder that no control removes. Write the table down for your own setup, because a path you have not named is a path nobody is watching. The rows below are the ones worth naming for a Solana signer.

Attack pathHow it actually happensControl that removes itResidual risk
Leaked keypair file The JSON keypair is committed to a repository, copied into a container image, left in a shared folder, or read by another process running as the same user. Keys stored outside the project tree, excluded from build contexts, readable only by the signer account, and never pasted into a shell that logs history. Anything running as that user can still read the file while the signer is running. The ceiling on the wallet is the real limit.
Malicious dependency in the bot stack A package or a transitive update executes at install time or at import time, reads the key path or the environment, and posts it out over the same network connection the bot already uses. Pinned lockfiles, a pruned dependency list, install scripts reviewed before they run, and a signer process that holds no credentials beyond the ones it needs. A pinned version can still be a compromised version. Review is a sample, not a proof, so assume some code you did not read has run.
RPC or API key theft An endpoint credential ends up in client side code, a public repository, a screenshot of a config, or a log line that is shipped to a third party dashboard. Provider keys issued per project, kept server side, scoped by domain or address where the provider allows it, and rotated on a fixed schedule. A stolen endpoint key cannot sign, but it can exhaust your quota and it can let someone watch what your addresses do.
Phishing signature request An operator connects a funding or treasury wallet to a page that presents a transaction whose real effect is a transfer or a delegate approval rather than the action described on screen. Treasury wallets that never connect to sites, a device that displays the actual instructions, and a rule that no signature is approved under time pressure. Interfaces can misrepresent what a transaction does. Reading the accounts a transaction touches is a skill, and skills fail on a bad day.
Operator machine that is also a personal machine The same login browses, installs extensions, opens attachments and holds the keypair directory, so any browser level compromise reaches the key file directly. A dedicated machine or virtual machine for signing, its own operating system account, disk encryption, and no general browsing on that profile. Dedicated machines still need updates, and the operator still moves files between environments. Discipline decays, so re-check it.
Backup that leaks The key directory sits inside a synced cloud folder, or the key is captured in a screenshot, a support chat, a note taking app, or a terminal recording shared for debugging. Key paths excluded from every sync client, a standing rule that keys are never pasted or photographed, and redaction checks before any log or capture leaves the machine. Sync clients change defaults, and the copy already uploaded stays uploaded. Assume every historical backup is a copy you do not control.
Stale delegate approval A token account keeps a delegate from an earlier strategy or an earlier interface, and that delegate retains the right to move up to the approved amount long after the run ended. A periodic audit of every token account the wallet owns, followed by a revoke on each approval the current strategy does not need. Revoking does not reverse transfers a delegate already made, and a new approval can be granted by any later signature you authorise.

Reading down the residual column is the useful part. Every honest control leaves something behind, and the leftover in almost every row is the same shape: the balance sitting in the wallet at the moment something goes wrong. That is why a ceiling per wallet does more for you than any single technical measure, and why the segmentation work is not optional decoration on top of good storage.

The keypair file is the key

Solana keypairs are ed25519, and the file the command line tools write is a JSON array of sixty four bytes. There is no password, no wrapper and no recovery step in between. That array is the private key, so every rule you would apply to a raw secret applies to the file: it does not belong in a repository, in a container image layer, in a build artifact, in a ticket, or in a directory that any other service can enumerate.

Path discipline matters more than clever storage here. Put keypair files in a directory that exists only for keys, outside the project tree, owned by the account that runs the signer and readable by nobody else. Reference them by absolute path in configuration rather than copying them next to the code. If the deployment tooling packages a directory, confirm what ends up inside the package rather than assuming the ignore file caught it.

Environment variables are not a hiding place

Putting a key in an environment variable moves it from a file to a process table entry that debugging tools, crash reporters and error trackers routinely capture. If you use one, keep it out of any startup command that a shell records, out of any process listing you share, and out of the structured fields that your logger serialises automatically. A key that reaches a log aggregator has left your machine.

Your dependencies sign for you

Every package the signer imports runs with the same permissions as the signer. That is the whole of the supply chain problem: the code you wrote is a minority of the code that can read your key file. A trading stack tends to accumulate helper libraries, and each addition widens the set of maintainers who can reach your wallet through a routine update that nobody reviews.

Practical control here is boring and effective. Pin exact versions with a committed lockfile so an update is a decision rather than an accident. Remove packages that arrived for a feature you abandoned. Check what runs at install time, because install hooks execute before you have run a single line of your own program. Where the runtime allows it, disable install scripts by default and allow them only for the few packages that genuinely need one.

Separation helps as well. A signer that does nothing but build, sign and submit transactions is a small program with a small dependency list. Charting, notifications, dashboards and data processing do not need to share a process with the key, and moving them into a separate service turns a dependency compromise in the reporting layer into an annoyance instead of a loss.

RPC endpoints and API key security

Endpoint credentials sit in a different category from signing keys, and conflating the two leads people to guard the wrong thing. An RPC key cannot move your funds. What it can do is exhaust the quota you depend on, expose which addresses you query, and give whoever holds it a view of your activity that you did not intend to publish. API key security for a bot is therefore about containment and rotation rather than about secrecy alone.

Issue a separate provider key per project so that revoking one does not take down everything you run. Keep the key on the server; anything that reaches a browser is public. Where the provider supports address or domain restrictions, apply them, because a restricted key that leaks is a smaller problem than an unrestricted one. Rotate on a schedule you actually keep rather than on the day you remember it exists.

There is a second, less obvious risk in the endpoint layer. Your signer trusts whatever the endpoint tells it about blockhashes, simulation results and confirmations. An endpoint that is hostile or simply broken can feed a stale blockhash and cause a run of failures, or report a confirmation that later disappears. Keep a second provider configured, compare balances against a public explorer before you act on anything expensive, and treat a sudden change in failure rate as an endpoint question before you treat it as a strategy question.

Signature requests and delegate approvals

Most operators think about theft as key theft, but authority can leak without the key moving anywhere. SPL Token exposes an approve instruction that names a delegate for a token account and an amount that delegate may move, and a matching revoke instruction that clears it. The approval is per token account and per amount, which means an audit has to walk every account the wallet owns rather than checking one global setting. Details of the instruction pair are in the SPL Token documentation.

Phishing on Solana usually arrives as a signature request rather than as a request for your key. A page describes a claim, an airdrop or a routine approval, and the transaction it hands you does something else. The defences are structural: treasury and funding wallets never connect to sites, signing happens on a device that shows you the instructions, and nobody approves a signature while being rushed. If you cannot explain which accounts a transaction writes to, reject it.

Build the revoke pass into your shutdown routine rather than treating it as a special event. At the end of a run, list the token accounts the wallet owns, look at which of them carry a delegate, and clear the ones the next run will not use. Revoking does not reverse anything a delegate already did, so the value of the pass comes from doing it regularly while nothing is wrong.

The machine that runs the loop

An operator machine that doubles as a personal machine collapses your whole model into one login. The browser is where credential theft is delivered, extensions with page access read what the session reads, and a downloaded attachment executes with the same rights as the process that opens your key directory. Solana wallet hygiene at the machine level is mostly about refusing to mix those two lives.

Give the signer its own machine or its own virtual machine. Create a dedicated operating system account for it, enable full disk encryption, and keep the browsing, messaging and document work on a different profile or a different box entirely. Where a hosted server is doing the work, restrict administrative access to keys you control, close every port the bot does not need, and keep a record of who can reach the host at all.

File movement is the part that quietly undoes this. Keys get copied to a laptop for a quick test, or pulled through a shared drive for a colleague, and after that the boundary is decorative. Decide in advance how a key moves between environments, and if the honest answer is that it does not move, generate a separate key for each environment instead.

Backups, screenshots and chat

Backups are where careful setups leak. A synced folder that quietly includes the key directory copies the file to a service you do not control and to every device attached to that account. Screenshots taken while debugging capture a terminal that has the array on screen. Support conversations attract pasted configuration, and terminal recordings shared to explain a bug carry whatever scrolled past. None of this requires an attacker to be sophisticated.

Set the rule at the level of paths rather than intentions. Exclude the key directory from every sync client explicitly, and re-check after each client update, because defaults change. Keep keys out of note taking apps, password manager notes shared with a team, and any chat, including ones you believe are private. If a capture has to be shared, redact before it leaves the machine rather than after, because the copy that already left cannot be recalled.

An exposed key is public forever

A private key that has ever been readable on an untrusted machine, pasted into a service, captured in a screenshot or synced to a cloud account must be treated as public from that moment on, permanently. Copies cannot be recalled and an ed25519 key cannot be invalidated, so the only response is to move every asset the key controls to a wallet generated elsewhere and to retire the old address. Transfers on Solana are irreversible and are not reversed by support, so a race with somebody who holds the same key is a race you may lose. Move value first, investigate second.

When that happens, stop improvising and follow the ordered response in the incident response playbook. The sequence matters because the instinct to investigate first is what costs people the balance that was still recoverable.

The hardening sequence

The following sequence is designed to be finished in one sitting on a wallet that already exists. Work through it in order, because several steps depend on the inventory produced by the ones above them. Nothing here needs new software beyond the standard command line tools and an explorer.

It is worth being clear about where hosted tooling fits before you start. Any tool that trades on your behalf must hold a signing key somewhere, so choosing a hosted Solana volume bot moves the custody question rather than removing it: the transactions still originate from a key that something, somewhere, can use without asking you each time. The questions below are the same whether the loop runs on your own server or behind somebody else's login.

  1. Pause the run. Stop the signer before you touch anything. A loop that is still submitting will fight your changes and will make the balances you are about to reconcile move under you.
  2. Inventory every key. List every keypair file, environment entry and secret store record that can sign for this project, and write down the public key each one controls. An inventory you cannot complete is itself a finding.
  3. Decide what each key may hold. Give every wallet a role and a ceiling. The ceiling is the amount you are willing to lose in full if that one key leaks, and it belongs in the run sheet rather than in your head.
  4. Generate fresh keys on a clean machine. Create replacements on a machine that does not browse the web. Write them to a dedicated key directory outside the project tree and outside anything that syncs.
  5. Restrict permissions and paths. Set ownership and permissions so only the signer account can read the files. Remove keys from build contexts, images and archives, and confirm what a deployment package actually contains.
  6. Pin and prune dependencies. Commit an exact lockfile, delete packages nothing imports any more, and review anything that runs at install time. Move reporting and dashboards out of the signing process.
  7. Scope and rotate endpoint credentials. Issue a project specific RPC key, keep it server side, apply any restriction the provider offers, and configure a second provider so a bad endpoint is a switch rather than an outage.
  8. Audit and revoke delegates. List the token accounts each wallet owns, check for active delegates, and revoke every approval the current strategy does not need.
  9. Move value to the new wallets. Transfer balances from old wallets to new ones, one at a time, confirming each on an explorer. Do not batch this step while you are still learning the tooling.
  10. Confirm the old keys control nothing. Check the balance and token accounts of every retired public key, destroy the old files, and record the rotation with a timestamp in the run log.
  11. Restart with a canary. Bring the run back on a single wallet with a small balance and watch it complete a full cycle before you re-enable the rest of the fleet.

Verification and what a bad run costs

Verification is the step people skip because the hard work feels done. Do it anyway, and do it against an explorer rather than against the bot's own dashboard, because a compromised or simply buggy stack has every reason to tell you what you want to hear. The checklist below is what a second operator should be able to confirm without asking you a question.

  • Every retired public key shows a zero balance and no token accounts with a balance.
  • No keypair file exists inside the repository, the build context or any synced directory.
  • The signer account is the only account with read access to the key directory.
  • The lockfile is committed and the dependency list contains nothing unused.
  • Endpoint credentials are project specific, server side, and noted with their rotation date.
  • Every token account the fleet owns has either no delegate or a delegate you can name.
  • The run log records the rotation, the new public keys and the per wallet ceiling.

Cost is the other half of verification, because a compromised or misconfigured signer does not always steal the balance. Sometimes it burns it. The base transaction fee on Solana is five thousand lamports per signature and it is charged whether the transaction succeeds or fails, so a loop retrying a doomed transaction pays every time. That is worth pricing before it happens rather than after.

Worked example: what a stuck retry loop costs in fees

Illustrative arithmetic with an arbitrary retry rate; substitute your own numbers. Assume a signer that retries a failing transaction ten times per second, with one signature per transaction, and nobody notices for one hour.

Attempts in one hour: 10 per second multiplied by 3,600 seconds equals 36,000 attempts. Fee per attempt: 5,000 lamports for one signature. Total: 36,000 multiplied by 5,000 equals 180,000,000 lamports. Converted at 1,000,000,000 lamports per SOL, that is 0.18 SOL spent on transactions that all failed.

Now add a second signer to each transaction, which some flows require. The fee doubles to 10,000 lamports per attempt and the hour costs 360,000,000 lamports, or 0.36 SOL. Neither figure is a prediction of your setup; the point is that fees are charged on failure, so an alert on failure rate protects the balance as directly as any storage control does.

Balance checks and account listings are quick enough to run by hand. The commands below cover generating a replacement keypair, reading the public key it produced, checking a balance against a chosen endpoint, listing the token accounts an owner controls, and clearing a delegate. Replace everything in angle brackets with your own values.

verification pass, run from the operator machine
solana-keygen new --no-bip39-passphrase -o /srv/keys/run-02.json
solana address -k /srv/keys/run-02.json
solana balance <PUBKEY> --url <RPC_ENDPOINT>
spl-token accounts --owner <PUBKEY> --url <RPC_ENDPOINT>
spl-token revoke <TOKEN_ACCOUNT>
solana balance <RETIRED_PUBKEY> --url <RPC_ENDPOINT>

None of this makes a hot wallet cold. It makes the wallet cheap to lose, quick to replace and easy to reason about at three in the morning, which is the standard worth holding automation to. Re-run the inventory and the delegate audit on a fixed cadence, keep the ceilings small enough that a bad night is an annoyance, and treat every key that leaves a machine you control as gone.

Questions the desk gets asked

Can a hardware wallet secure a trading bot?

Not for the signing wallet. A hardware device requires a physical confirmation for every signature, which is the property that makes it safe and the property that makes it impossible for a loop firing every few hundred milliseconds. Use a device for the treasury that funds the bot, and accept that the wallet the bot signs with is software.

Is an encrypted keypair file safe on the bot server?

Encryption at rest protects the file from someone who takes the disk or the backup. It does not protect the key from code running as the same user, because the signer must decrypt the key to sign. Treat encryption as a control against theft of storage, not as a control against a compromised process.

How much SOL should a bot wallet hold?

Only the amount you are prepared to write off if that specific key leaks, plus the fee and account reserves the run needs. Pick the ceiling yourself, write it into the run sheet, and refill from a wallet the bot cannot sign for rather than raising the ceiling when a run is going well.

What does revoking a token approval actually do?

An SPL token account can name a delegate that is allowed to move up to a set amount. Revoking clears that delegate for that token account. It does not undo transfers the delegate already made, and it does not affect other token accounts, so an audit has to cover every account the wallet owns.

Should the bot and my personal browser share a machine?

No. A browser is the delivery path for most credential theft, and an extension with page access sits in the same user session as your files. Give the signer its own machine or virtual machine, its own operating system account, and no browsing habit at all.

If a key was exposed for a minute, is rotation enough?

Rotation is necessary but the old key is finished. Anyone who copied it keeps it forever, and a copied ed25519 key cannot be invalidated. Move every asset off the old public key, revoke delegates, and treat that address as public permanently rather than reusing it after a quiet period.