Avoiding address reuse with solana CLI wallet

I’ve created a paper wallet with solana-keygen new --no-outfile then I’ve derived the BIP44 wallet address with solana-keygen pubkey prompt://.

  1. How do I generate other receiving addresses for that seed phrase to prevent address reuse? I’ve read about hiearchical derivation but didn’t really understand it. I tried solana-keygen pubkey prompt://?key=0/1 then solana-keygen verify <the generated pubkey> prompt:// but the verification failed. solana-keygen verify <the generated pubkey> prompt://?key=0/1 succeeded, but I don’t understand why.
  2. How can I check the sum of balances at all wallet addresses generated from the same seed phrase?
1 Like

Firstly, thanks for the link to hierarchical derivation! It answered a lot of questions I had about the weirdness of trying to restore wallets from seed phrases:

Fair warning, I’m still figuring this out myself, but here’s how I understand it from the documentation and the BIPs linked to by the documentation.

If you wanted to get different account addresses to avoid re-using the same address you would do so like this:

# First derived key, the default in most wallets
solana-keygen pubkey prompt://?key=0/0
# Second derived key
solana-keygen pubkey prompt://?key=1/0
# Third derived key
solana-keygen pubkey prompt://?key=2/0
# Fourth derived key
solana-keygen pubkey prompt://?key=3/0

Note: According to BIP-0044 I think that when creating separate public accounts keys that you will be using for taking payments, you should increment the first number, not the second number. The second number should always be 0 for public accounts.

The reason the verification failed, as far as I understand, is that each derived key has a different keypair. So the verify command only works if the public key was created with the exact same derivation path. In other words, you have to use the same prompt:// URL used to create the public key that you used to verify it.

I haven’t seen anything built in for that yet. :thinking: You could do it simply with a bash script, though.

:warning: Warning: If you do not understand the code in the script below don’t run it unless you have good reason to trust me or unless you get somebody else you trust to validate the script is save. There are scammers everywhere who will try to steal your wallet, so be careful


# Start with a sum of 0

# Get the first argument on the commandline as how many accounts to check,
# or use 24 if the first argument is not specified   

# Ask the user to put in their seed phrase.
# This will store it in the $seed variable.
read -sp 'Enter your seed phrase: ' seed

# Loop through the number of accounts
for idx in $(seq $count); do 
        # Get the public key for this account
        pubkey=$(echo $seed | solana-keygen pubkey prompt://?key=$idx/0 2> /dev/null)
        balance=$(solana balance $pubkey)

        # If the previous command failed
        if [ "$pubkey" = "" ]; then 
                echo "Could not parse seed phrase"
                exit 1
        # Print out the individual account balance for the user's benefit
        echo $pubkey: $balance
        # Add this account balance to the sum of the account balances
        sum=$(echo "" | awk "{ print $sum + $balance }")

echo "The sum from the first $count derivable accounts is: $sum"

If you save that script in a file, you can run it like this:

$ bash account_sum.sh 
Enter your seed phrase: 
8tRuTE73WZtac1UDHZA88uC321hpK9YdFsU811hSiqHg: 0 SOL
AGbvLj3RY9Vzvz2ygsxLbu8ws8pqDYWWHhzi4EADHJD9: 12.3 SOL
2QNgyVjJ3DuKsMWtnp69t9D7WsXbjrJY4Y1kamwzj8MP: 0 SOL
579tZiSbmyL3wAdvzt7e8THiyCvD3namBWGqXo8oyDY7: 0 SOL
BujYJTz8C8mxz93Dn5ez4u9U4YYPaQWTwHd1zZ4RLoxB: 2.2 SOL
ABEAarby9HFSsuq5snyFWCgfMxEmqoqSJersWtqQxW71: 0 SOL
oQhYyzkBnzCKYoM7kmgQdAJ5dSQ6eeym5isXQ2oDt97: 0 SOL
The sum from the first 8 derivable accounts is: 14.5
1 Like

Thanks for your answer @zicklag. A few questions:

  1. Why has an apparently random user answered my question, rather than a team member? Why wasn’t my question in an FAQ already anyway?

  2. The Bitcoin wiki talks very clearly about the serious privacy dangers of address reuse. Is there no concern whatsoever for address reuse here or on reddit?

  3. Are there any HD wallets for Solana? This has been standard for Bitcoin for years. Yet nethier Solflare nor Sollet.io support generating new deposit addresses, and Phanotm.app says nothing about address reuse.

Also, Solflare says this:

By default, Solflare will use m/44'/501'/0'/0' as the derivation path for the main wallet.

That’s up with that 44? Is is dicey to use sequential keys starting with the first number 0, because eventually you’ll reach 44?

Why is this topic so confusing?

I’m unsure why, but looking around the forum it seems like there isn’t much activity from team members in answering community questions. I’ve recently gotten on the forum as I’ve been learning Solana myself, and started answering questions when I realized that nobody else seemed to be. I figured it’d be a good way to help out while also helping educate myself on common problems and how things work.

I suppose they thought the docs you linked to were enough, or maybe it’s just not frequently asked. I’m not sure, but most people probably use wallets such as Phantom that don’t even make you aware of the ability to create derived keys. ( which was honestly why I was so confused by the whole thing )

I’m not on Reddit so I wouldn’t know. :man_shrugging:

Sollet, while it isn’t very clear, actually does do hierarchical addresses, but the interface isn’t super nice or configurable. By clicking the “Add Account” button Sollet will create a new derived address from the same seed phrase.

So those first two numbers, the 44'/501' should be the same for every Solana wallet by anybody, by convention. According to BIP-0044:


To describe each component:

  • m: Represents the master key
  • 44': This number is always 44 for BIP-0044 wallets. It represents that the rest of the numbers following it follow the BIP-0044 standard.
  • 501': This number represents the coin type that this wallet is for. The official number for Solana is 501 so all Solana wallets should use 501' for the second number
  • 0': This number is the account number. So this is the number that you increment every time you want to get a new address
  • 0': This number should always be either 0 or 1. 0 is meant for public addresses, and 1 is meant for internal addresses that aren’t used for publicly taking payments.

The last address_index spot is I guess kind of like a sub-address, but I don’t know any wallet that uses it yet.

Going back to Sollet, each time you click “New Account”, it actually increments the third number from the left, in the derivation path. So the first 5 wallet derivations would look like this:

  • m/44'/501'/0'/0'
  • m/44'/501'/1'/0'
  • m/44'/501'/2'/0'
  • m/44'/501'/3'/0'
  • m/44'/501'/4'/0'

This would be the typical strategy for creating new addresses that represent separate “accounts”. That incrementing number can get very high ( the highest I tested up to was 99999999 ), but if that isn’t enough accounts, you can also always keep deriving more child accounts to what seems to be an arbitrary depth. Though I don’t think any wallets support that that I know of and it probably shouldn’t be necessary.

I think it’s kind of an implementation detail that just haven’t gotten well enough support in Solana wallets to make it nice to use and easy to understand. Solana is relatively new.

@solarb I just discovered that Phantom also supports sequences of derived wallets from the same seed phrase. If you use Phantom’s “Add / Connect Wallet” button and select “Create a New Wallet” it will actually derive the next account in the sequence. It won’t create a totally new account with a different seed phrase.

1 Like

Thanks for all the help with this issue @zicklag.

Did you test if Phantom (like Sollet) follows the scheme of incrementing only the account (3rd number in the key derivation path)? Do they both use “hardened” (whatever that means, placing the apostrophe after the number) numbers?

1 Like

@solarb Yes, when adding accounts in Phantom, starting with the same seed phrase, I would end up with the same list of addresses as I would get in Sollet.

About the “hardened”, according to the Solana docs, it seems like the Solana CLI always uses the hardened addresses, and I’m pretty sure that Sollet and Phantom do as well. I would have to double-check that to be sure, though.


Ok so I’ve created a paper wallet using the solana-keygen CLI. Got its pubkey with solana-keygen pubkey prompt://.

Then I obtained a derived wallet address (let’s call it PUBKEY1) with solana-keygen pubkey prompt://?key=1/0 and verified it wiht solana-keygen verify <PUBKEY1> prompt://?key=1/0. Note that solana-keygen verify <PUBKEY1> prompt:// failed because I didn’t include the derivation path.

Now if I send funds to each address, do they end up in the same wallet?

How do I transfer the sum of those funds elsewhere with the CLI, because solana transfer --from prompt:// <RECIPIENT> <AMOUNT> --fee-payer prompt:// will only control funds from the first pubkey, not from PUBLKEY1, which would need the derivation path in the prompt, solana transfer --from prompt://?key=1/0 ?

Sounds like I’d need to make a transaction with two inputs?

It depends on what you mean by “wallet”. Any of the accounts derived from your seed phrase can be considered in the same paper wallet, but the addresses are different, so they are different accounts as far as any transactions are concerned.

The CLI doesn’t have any built-in features to transfer the sum of all the accounts in a wallet. You would have to manually transfer the tokens out of each account one-by-one to wherever you wanted to put them.

As far as I’ve seen there aren’t any Solana wallets that really offer any sort of batch handling of derived accounts like that. You would have to write a script of some sort to do it for you.

Maybe “derived accounts” is misleading; what I’m looking for is standard functionality from Bitcoin wallets, where you give every sender a new public address of your wallet, and all received funds belong to the same wallet. Then the wallet software uses a combination of those inputs when you in turn send funds.

This is critical for accepting payments (or donations), when you should expose a new wallet address once an address has been used to receive funds, unless you want the whole world to trace all your sales.

OK, I understand. As far as I know, Solana does no such thing yet.

I think privacy is a valid concern that isn’t fully addressed by Solana, or at least by the Solana wallets yet.

As we can see the core functionality for the derived addresses is present, but no user-friendly way to capitalize on their privacy benefits.

1 Like