Keypairs and Wallets

How to generate a new Keypair

Many of the different actions you can take with the various Solana libraries require a Keypair or Wallet. If you are connecting to a wallet, you do not have to worry. However, if you are in need of a keypair, you will need to generate one.

Press </> button to view full source
let keypair = Keypair.generate();
keypair = Keypair()
let wallet = Keypair::new();
solana-keygen new

How to restore a Keypair from a secret

If you already have your secret, you can get your Keypair from the secret to test out your dApp.

  1. From Bytes
Press </> button to view full source
const keypair = Keypair.fromSecretKey(
  Uint8Array.from([
    174, 47, 154, 16, 202, 193, 206, 113, 199, 190, 53, 133, 169, 175, 31, 56, 222, 53, 138, 189, 224, 216, 117,
    173, 10, 149, 53, 45, 73, 251, 237, 246, 15, 185, 186, 82, 177, 240, 148, 69, 241, 227, 167, 80, 141, 89, 240,
    121, 121, 35, 172, 247, 68, 251, 226, 218, 48, 63, 176, 109, 168, 89, 238, 135,
  ])
);
secret_key= [
        174, 47, 154, 16, 202, 193, 206, 113, 199, 190, 53, 133, 169, 175, 31, 56, 222, 53, 138,
        189, 224, 216, 117, 173, 10, 149, 53, 45, 73, 251, 237, 246, 15, 185, 186, 82, 177, 240,
        148, 69, 241, 227, 167, 80, 141, 89, 240, 121, 121, 35, 172, 247, 68, 251, 226, 218, 48,
        63, 176, 109, 168, 89, 238, 135,
    ]
    
keypair = Keypair.from_secret_key(bytes(secret_key))
let secret_key: [u8; 64] = [
    174, 47, 154, 16, 202, 193, 206, 113, 199, 190, 53, 133, 169, 175, 31, 56, 222, 53, 138,
    189, 224, 216, 117, 173, 10, 149, 53, 45, 73, 251, 237, 246, 15, 185, 186, 82, 177, 240,
    148, 69, 241, 227, 167, 80, 141, 89, 240, 121, 121, 35, 172, 247, 68, 251, 226, 218, 48,
    63, 176, 109, 168, 89, 238, 135,
];

let wallet = Keypair::from_bytes(&secret_key)?;
# input your secret into the Keypath listed under solana config get
  1. From Base58 String
Press </> button to view full source
const keypair = Keypair.fromSecretKey(
  bs58.decode("5MaiiCavjCmn9Hs1o3eznqDEhRwxo7pXiAYez7keQUviUkauRiTMD8DrESdrNjN8zd9mTmVhRvBJeg5vhyvgrAhG")
);
b58_string = "5MaiiCavjCmn9Hs1o3eznqDEhRwxo7pXiAYez7keQUviUkauRiTMD8DrESdrNjN8zd9mTmVhRvBJeg5vhyvgrAhG"
keypair = Keypair.from_secret_key(base58.b58decode(b58_string))
let wallet = Keypair::from_base58_string(
    "5MaiiCavjCmn9Hs1o3eznqDEhRwxo7pXiAYez7keQUviUkauRiTMD8DrESdrNjN8zd9mTmVhRvBJeg5vhyvgrAhG",
);

How to verify a Keypair

If you are given a keypair, you can verify whether or not the secret matches the given public key

Press </> button to view full source
const publicKey = new PublicKey("24PNhTaNtomHhoy3fTRaMhAFCRj4uHqhZEEoWrKDbR5p");
const keypair = Keypair.fromSecretKey(
Uint8Array.from([
    174, 47, 154, 16, 202, 193, 206, 113, 199, 190, 53, 133, 169, 175, 31, 56, 222, 53, 138, 189, 224, 216, 117,
    173, 10, 149, 53, 45, 73, 251, 237, 246, 15, 185, 186, 82, 177, 240, 148, 69, 241, 227, 167, 80, 141, 89, 240,
    121, 121, 35, 172, 247, 68, 251, 226, 218, 48, 63, 176, 109, 168, 89, 238, 135,
  ])
);
console.log(keypair.publicKey.toBase58() === publicKey.toBase58());
// true
public_key = PublicKey("24PNhTaNtomHhoy3fTRaMhAFCRj4uHqhZEEoWrKDbR5p")

keys = [
        174, 47, 154, 16, 202, 193, 206, 113, 199, 190, 53, 133, 169, 175, 31, 56, 222, 53, 138,
        189, 224, 216, 117, 173, 10, 149, 53, 45, 73, 251, 237, 246, 15, 185, 186, 82, 177, 240,
        148, 69, 241, 227, 167, 80, 141, 89, 240, 121, 121, 35, 172, 247, 68, 251, 226, 218, 48,
        63, 176, 109, 168, 89, 238, 135,
    ]
keypair = Keypair.from_secret_key(bytes(keys))

print(keypair.public_key.to_base58() == public_key.to_base58())
# True
solana-keygen verify <PUBKEY> prompt://

How to check if a public key has an associated private key

In certain special cases (e.g. a Program Derived Address), public keys may not have a private key associated with them. You can check this by looking to see if the public key lies on the ed25519 curve. Only public keys that lie on the curve can be controlled by users with wallets.

Press </> button to view full source
const key = new PublicKey("5oNDL3swdJJF1g9DzJiZ4ynHXgszjAEpUkxVYejchzrY");
console.log(PublicKey.isOnCurve(key.toBytes()));
key = PublicKey('5oNDL3swdJJF1g9DzJiZ4ynHXgszjAEpUkxVYejchzrY')
print(is_on_curve(key))
let pubkey = Pubkey::from_str("5oNDL3swdJJF1g9DzJiZ4ynHXgszjAEpUkxVYejchzrY").unwrap();
println!("{:?}", pubkey.is_on_curve())

How to generate a mnemonic phrase

If you're creating a wallet, you will need to generate a mnemonic phrase so that the user can save it as a backup.

Press </> button to view full source
const mnemonic = bip39.generateMnemonic();
mnemo = Mnemonic("english")
words = mnemo.generate(strength=256)
solana-keygen new

How to restore a Keypair from a mnemonic phrase

Many wallet extensions use mnemonics to represent their secret keys. You can convert the mnemonic to Keypairs for local testing.

  1. BIP39
Press </> button to view full source
const mnemonic = "pill tomorrow foster begin walnut borrow virtual kick shift mutual shoe scatter";
const seed = bip39.mnemonicToSeedSync(mnemonic, ""); // (mnemonic, password)
const keypair = Keypair.fromSeed(seed.slice(0, 32));
mnemo = Mnemonic("english")
seed = mnemo.to_seed("pill tomorrow foster begin walnut borrow virtual kick shift mutual shoe scatter")
keypair = Keypair.from_secret_key(seed)
solana-keygen recover
  1. BIP44
Press </> button to view full source
const mnemonic = "neither lonely flavor argue grass remind eye tag avocado spot unusual intact";
const seed = bip39.mnemonicToSeedSync(mnemonic, ""); // (mnemonic, password)
for (let i = 0; i < 10; i++) {
  const path = `m/44'/501'/${i}'/0'`;
  const keypair = Keypair.fromSeed(derivePath(path, seed.toString("hex")).key);
  console.log(`${path} => ${keypair.publicKey.toBase58()}`);
}
solana-keygen recover 'prompt:?key=0/0'

How to generate a vanity address

Vanity publickeys, or custom addresses are keys that have start with specific characters. For example, a person may want a publickey to start with "elv1s", or maybe even "cook". These can help other people remember who the key belongs to, making the key more easily identifiable.

Note: The more characters in your vanity address, the longer it will take.

WARNING

You should just use the CLI for this task. The Python and TypeScript examples are for illustrative purposes and are much slower than the CLI.

Press </> button to view full source
let keypair = Keypair.generate();
while(!keypair.publicKey.toBase58().startsWith("elv1s")) {
  keypair = Keypair.generate();
}
keypair = Keypair()
while(str(keypair.public_key)[:5]!="elv1s") :
    keypair = Keypair()
solana-keygen grind --starts-with e1v1s:1

How to sign and verify messages with wallets

The primary function of a keypair is to sign messages and enable verification of the signature. Verification of a signature allows the recipient to be sure that the data was signed by the owner of a specific private key.

To do so we will import the TweetNaClopen in new window crypto library.

Press </> button to view full source
const message = "The quick brown fox jumps over the lazy dog";
const messageBytes = decodeUTF8(message);

const signature = nacl.sign.detached(messageBytes, keypair.secretKey);
const result = nacl.sign.detached.verify(messageBytes, signature, keypair.publicKey.toBytes());

console.log(result);  
message = "The quick brown fox jumps over the lazy dog"
message_bytes = bytes(message,'utf8')
signed_message = keypair.sign(message_bytes)

verify_sign = VerifyKey(
    pubkey_bytes
).verify(
    smessage=message_bytes,  
    signature=signed_message.signature
)

How to connect to a wallet

Solana's wallet-adapteropen in new window libraries make it easy to manage wallet connections client-side.

React

Run the following command to install the required dependencies:

yarn add @solana/wallet-adapter-react @solana/wallet-adapter-react-ui @solana/wallet-adapter-base @solana/wallet-adapter-wallets

The React wallet-adapter libraries allow us to persist and access wallet connection states through hooks and Context providers, namely, useWallet, WalletProvider, useConnection, and ConnectionProvider. The React App must be wrapped with WalletProvider and ConnectionProvider.

Additionally, we can prompt users to connect by using useWalletModal to toggle visibility of the connection modal and wrapping the App with WalletModalProvider from @solana/wallet-adapter-react-ui, as well. The connection modal will handle that connection flow for us, so we can just listen for when a wallet has connected. We know a wallet is connected when the useWallet response has a non-null wallet property. Vice versa, if that property is null, we know the wallet is disconnected.

Press </> button to view full source
const { wallet } = useWallet();
const { setVisible } = useWalletModal();

const onRequestConnectWallet = () => {
  setVisible(true);
};

// Prompt the user to connect their wallet
if (!wallet) {
  return <button onClick={onRequestConnectWallet}>Connect Wallet</button>;
}

// Displays the connected wallet address
return (
  <main>
    <p>Wallet successfully connected!</p>
    <p>{wallet.publicKey.toBase58()}</p>
  </main>
);

Vue

Run the following command to install the required dependencies:

npm install solana-wallets-vue @solana/wallet-adapter-wallets

The Solana Wallets Vueopen in new window plugin allows us to initialise a wallet store and create a new $wallet global property that can be accessed inside any component. All the properties and methods you can get from useWallet() are displayed hereopen in new window. We also import and render the WalletMultiButton component to allow users to select a wallet et connect to it.

Press </> button to view full source
<script setup>
import { WalletMultiButton } from "solana-wallets-vue";
</script>

<template>
  <wallet-multi-button></wallet-multi-button>
</template>

Svelte

Run the following command to install the required dependencies:

npm install @svelte-on-solana/wallet-adapter-core @svelte-on-solana/wallet-adapter-ui @solana/wallet-adapter-base @solana/wallet-adapter-wallets @solana/web3.js

The Svelte Wallet Adapteropen in new window package allows to add a Svelte Store ($walletStore) accessible among all the JS, TS or/and Svelte files inside a project done with Svelte Template or SvelteKit. Using the repo reference hereopen in new window you can be able to use the adapter for SSR or SPA. The UI package contains a <WalletMultiButton /> component to allow users to select a wallet to connect to it.

Press </> button to view full source
<script>
  import { walletStore } from "@svelte-on-solana/wallet-adapter-core";
  import { WalletMultiButton } from "@svelte-on-solana/wallet-adapter-ui";
</script>

{#if $walletStore?.connected}
  Wallet with public key {$walletStore.publicKey} successfully connected!
{:else}
  <WalletMultiButton />
{/if}
Last Updated: 4/21/2022, 4:41:21 PM