5

Say I have a secretKeyString extracted from a keyPair using keyPair.secretKey.toString();

I know I can restore a keyPair from the string with:

const secretKeyStringToKeypair = (secretKeyString: string) => {
  const secretKeyArray = secretKeyString.split(",").map(Number);
  const secretKey = Uint8Array.from(secretKeyArray);
  const keyPair = Keypair.fromSecretKey(secretKey);
  return keyPair;
};

Which works, I can do:

expect(keyPair2.secretKey.toString()).toEqual(
  keyPair.secretKey.toString()
);

But is there a better way of doing this? Mapping the string into an array using string methods seems a bit suboptimal, and I'm surprised there's not something built in to @solana/web3.js. I had a peek in the Solana Cookbook and couldn't find anything on the topic.

2 Answers 2

2

Updated answer

I have now gotten a job at Solana Foundation and created the Solana Helpers library with the rest of the Developer Relations team and some well known third parties.

Since the Solana CLI uses 'array of numbers' format, let's do the same:

await addKeypairToEnvFile(testKeypair, "SECRET_KEY");

Will save testKeypair to your .env using the variable name SECRET_KEY.

To restore:

const keypair = await getKeypairFromEnvironment("SECRET_KEY");

See the Solana Helpers docs for more information on both functions.

Original Answer

Answering my own question: this works, but it's better to simply avoid keyPair.secretKey.toString(). Instead save the base58 encoded value of the secretKey:

export const secretKeyToHex = (secretKey: Uint8Array) => {
  return base58.encode(secretKey);
};

And then import that:

export const getKeypairFromString = (secretKeyString: string) => {
  let decodedSecretKey: Uint8Array;
  try {
    decodedSecretKey = base58.decode(secretKeyString);
  } catch (throwObject) {
    throw new Error("Invalid secret key! See README.md");
  }
  return Keypair.fromSecretKey(decodedSecretKey);
};
0

Generate and export the key as a normal string - what most people with Ethereum background would expect.

import { Keypair } from '@solana/web3.js';
import bs58 from 'bs58';

const keypairNew = Keypair.generate();
console.log(keypairNew.publicKey.toBase58());
const privateKey = bs58.encode(keypairNew.secretKey);
console.log(privateKey);

Restore the keypair

const keypairRestored = Keypair.fromSecretKey(bs58.decode(privateKey));
console.log(keypairRestored.publicKey.toBase58());

Works on @solana/web3.js v1.91.8

I am as surprised as the OP is that something this simple just doesn't exist. Just 2-3 months ago I was looking at a similar issue with exporting the private key, only in Python. Took me hours for something so simple. Here? It's been around 30-40 minutes so far. Something like keypair.secretKey.toBase58() and Keypair.fromBase58('<private key string>') are clearly too much to ask for. But hey, maybe in another 5-10 years we'll get them!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.