23

I need to use a Phantom Wallet through the Solana CLI, but I'm unable to configure it.

For example, to check balance using

solana balance --keypair fileexportedfromphantom

but can't read the info.

How do I convert that private key into a valid form for use in Solana CLI?

TylerH
  • 20,799
  • 66
  • 75
  • 101
user1843376
  • 535
  • 2
  • 7
  • 12
  • my private key was serie of byte numbers like 53,63,65 but problem was i had to put them in phantom extension including the brackets [] then it worked – luky Jul 24 '22 at 22:48

3 Answers3

50

Try:

solana-keygen recover 'prompt://?key=0/0' -o <file.json>

And enter the 24-word recovery phrase from Phantom under "Show Secret Recovery Phrase".

This is because Phantom uses the 0/0 derivation path for wallets and needs the extra provided path to get to the correct account.

You can use the same command with 1/0, 2/0 ... N/0 to get the different Phantom derived accounts.

See here for more info about hierarchical derivation with the Solana tools: https://docs.solana.com/wallet-guide/paper-wallet#hierarchical-derivation

Or use the Solflare wallet to check the derivation paths for your particular 24 word phrase here: https://solflare.com/access


As per the recent comment from @FutForFut, this assumes you have or want to use the Secret Recovery Phrase from Phantom. In certain cases, you might only have the private key from Phantom ("Show Private Key") in menus. This is a base58 encoded key, and you'll need to convert that into a byte-array in a JSON file.

Here's the Javascript snippet, using the bs58 package (https://www.npmjs.com/package/bs58):

const bs58 = require('bs58');
const fs = require('fs');
b = bs58.decode('privatekeyexportedfromphantom');
j = new Uint8Array(b.buffer, b.byteOffset, b.byteLength / Uint8Array.BYTES_PER_ELEMENT);
fs.writeFileSync('key.json', `[${j}]`);

Update fields privatekeyexportedfromphantom and key.json as required.

yamen
  • 15,390
  • 3
  • 42
  • 52
  • One non-obvious thing about Phantom: If you use the secret recovery phrase, as suggested in this answer, anyone who has that recovery phrase will be able to construct the private keys for ALL accounts in that wallet. I suspect the more common use case is to just get ONE special account/wallet imported into the Solana CLI. In that case, Jon C's answer is more appropriate, and more secure since it will only expose one keypair, not the whole sequence of derived (or derivable keypairs). – AllBlooming Jun 20 '22 at 22:43
  • Thanks, I've added the alternative method to this answer also. – yamen Jun 28 '22 at 05:07
  • Made a replit https://replit.com/@therealsuji/Phantom-Private-Key-to-Keypair?v=1 – SujithaW Aug 06 '22 at 16:00
14

It's a bit annoying, but you'll have to decode the base-58 private key returned by Phantom into an array of bytes. Here's a simple Python code snippet to accomplish this, using the base58 package (https://pypi.org/project/base58/):

import base58
byte_array = base58.b58decode(MY_PRIVATE_KEY_IN_BASE58)
json_string = "[" + ",".join(map(lambda b: str(b), byte_array)) + "]"
print(json_string)

You can pipe that output to a file, and then use that as your --keypair with the CLI tools.

Jon C
  • 7,019
  • 10
  • 17
  • Error: could not read keypair file . If i use solana-keygen new, to generate a key it's showed like a combinations of numbers. The output generated using your script is binary – user1843376 Sep 20 '21 at 17:14
  • I get something like this [�,[,:,�,�,>,�,L,=,�,J,�, and this is the expected look: [157,179,177,192,112, – user1843376 Sep 20 '21 at 17:39
  • Strange, I just tested this again myself and it works. For `MY_PRIVATE_KEY_IN_BASE58`, you're supposed to put in a string, e.g. `"4AfmonCVDRutyt3vMfsooagRsoNXTCVURGZ7nzSZPP9CWykXUmgA72Sfgrne7EcqtVJE6Gq6aA8xw21bHtbZMQzL"` which gives `[158,99,132,43,140,119,254,9,6,225,141,208,225,184,48,219,246,115,45,3,0,67,160,190,25,199,130,208,179,210,219,1,41,32,144,228,51,198,235,65,64,71,155,119,235,189,157,49,2,65,230,165,161,159,153,77,213,153,226,174,35,2,212,89]` Can you test that? This is running with python 3.8 on ubuntu 20.04 – Jon C Sep 22 '21 at 09:49
  • Exactly the same fails for me – user1843376 Sep 22 '21 at 12:20
  • works for me, run simple python script in terminal or repl. – kafinsalim Nov 06 '21 at 15:29
  • Thank you so much! I was pulling my hair trying to understand the difference between Phantom wallet private key and a 32-byte private key – SpaceMonkey Dec 28 '21 at 17:57
  • It worked for me, I am just wondering why it converts to base 10 upon using string()? – Alaska Apr 28 '22 at 00:05
  • Don't forget to `pip3 install base58`... – AllBlooming Jun 20 '22 at 22:44
0

here's a little python 3 script to take in your private key, and output it to the solana configuration directory

from pathlib import Path

import base58

SAVE_DIR = Path.home() / '.config' / 'solana'


def convert_key():
    byte_array = base58.b58decode(input('Enter Public Key: '))
    return "[" + ",".join(map(lambda b: str(b), byte_array)) + "]"


def create_file(save_dir: Path, key_name: str) -> Path:
    keypair_path = save_dir / f'{key_name}.json'
    if not SAVE_DIR.exists():
        raise FileNotFoundError('Solana config directory not found')
    if not SAVE_DIR.is_dir():
        raise NotADirectoryError('Solana config directory not found')
    if keypair_path.exists():
        raise FileExistsError('Keypair already exists')
    return keypair_path


def main():
    keypair = input('Enter keypair name: ')
    keypair_path = create_file(SAVE_DIR, keypair)
    keypair_path.write_text(convert_key())
    print(f'Keypair {keypair} created at {keypair_path}')


if __name__ == '__main__':
    main()

Ehutzle
  • 1
  • 2