How to get proper public address from mnemonic phrase for Solana?
Asked Answered
S

3

11

I am trying to get proper public address for Solana wallet using solana-web3.js at my react-native test projectScreenshot from Solflare wallet

import { Keypair} from '@solana/web3.js';
import * as bip39 from 'bip39';
import * as bip32 from 'bip32';

const derivePath = "m/44'/501'/0'/0'";
const mnemonic = "...12 word phrase"

const seed: Buffer = yield bip39.mnemonicToSeed(mnemonic);
// also tried to slice seed.slice(0, 32);
const derivedSeed = bip32.fromSeed(seed).derivePath(derivePath).privateKey;
const keypair = Keypair.fromSeed(derivedSeed);
const publicKey = keypair.publicKey.toString();

I took derive path that is supposed to be for Phantom wallet (and could be chosen at Solflare wallet) But the problem is - I do not get the same public key as I get at these browser wallets.

So where am I possibly making mistake at code above?

UPDATE: When I use 'ed25519-hd-key' lib instead of 'bip32' to get derived seed problem disappears.

import * as ed25519 from 'ed25519-hd-key';

const derivedSeed = ed25519.derivePath(derivePath, seed.toString('hex')).key;
Sedentary answered 20/9, 2021 at 2:47 Comment(0)
B
3

work variant for me:

import nacl from 'tweetnacl';
import * as bip39  from 'bip39';
import { derivePath } from 'ed25519-hd-key';

const web3 = require('@solana/web3.js')

const seed = await bip39.mnemonicToSeed(mnemonic);
const seedBuffer = Buffer.from(seed).toString('hex');
const path44Change = `m/44'/501'/0'/0'`;
const derivedSeed = derivePath(path44Change, seedBuffer).key;
keypair = new web3.Account(nacl.sign.keyPair.fromSeed(derivedSeed).secretKey);
Burnette answered 1/6, 2022 at 21:57 Comment(1)
Please add more explanation of your codeBlameless
F
1

You should use "m/501'/0'/0'" path

Fasten answered 13/10, 2021 at 13:7 Comment(0)
T
0

In addition to @dapp-deep 's answer, I would like to add a bit renewed answer, as the Account from @solana/web.js is depreciated now and instead we can use KeyPair.

  1. bip39.mnemonicToSeed(mnemonic): This line uses the bip39 library to convert the mnemonic phrase (a sequence of easy-to-remember words) into a seed buffer (a fixed-length binary value).

2.Buffer.from(seed).toString('hex'): The seed buffer is then converted to a hexadecimal string representation.

  1. const path44Change = \m/44'/501'/0'/0';: This line defines a derivation path using the BIP44 standard. The path m/44'/501'/0'/0'` is specific to the Solana cryptocurrency and represents the following:

    m stands for the master key (root of the derivation path).

    44' is the purpose field, indicating that the derived keys will be used for a coin-type purpose.

    501' is the coin-type field, which specifies the cryptocurrency (501 is the assigned value for Solana).

    0' is the account field, typically used to represent different accounts derived from the same seed.

    0' is the change field, usually used to differentiate between external and internal/change addresses.

  2. const derivedSeed = derivePath(path44Change, seedBuffer).key;: This line uses an unspecified derivePath function to derive a new seed from the provided derivation path and the seed buffer. The key property of the returned object is assigned to derivedSeed.

  3. const kp = Keypair.fromSeed(derivedSeed);: Finally, the Keypair.fromSeed method from the Solana library is used to create a new keypair object (kp) from the derived seed.

  4. return kp;: The function returns the generated keypair object, which contains both the public and private keys.

The derivation path is necessary because it provides a standardized way to derive multiple keypairs from a single seed (the mnemonic phrase) in a deterministic and reproducible manner. This is particularly useful in cryptocurrency wallets, where multiple addresses can be generated from the same mnemonic, allowing for better organization and management of funds.

By following the BIP44 standard, the derivation path ensures that the derived keys are compatible with other wallets and tools that follow the same standard. It also provides a level of isolation between different types of coins or accounts, reducing the risk of accidental fund transfers or key reuse.

Below is the code needed:

import * as bip39 from "bip39";
import {
  Keypair,
  Connection,
} from "@solana/web3.js";
import { derivePath } from 'ed25519-hd-key';


async function getKeyCreatedBySolanaKeygenFromMnemonic(mnemonic: string) {
  const seed = await bip39.mnemonicToSeed(mnemonic);
    const seedBuffer = Buffer.from(seed).toString('hex');
    const path44Change = `m/44'/501'/0'/0'`;
    const derivedSeed = derivePath(path44Change, seedBuffer).key;
    const kp = Keypair.fromSeed(derivedSeed);
    return kp;
}

Tortoni answered 22/3 at 12:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.