Skip to content

Creating Accounts from Mnemonics⚓︎

This tutorial shows how to create accounts for the Symbol blockchain using a mnemonic phrase, also known simply as mnemonic.

This approach is commonly used by HD wallets to manage multiple accounts from a single seed.

Prerequisites⚓︎

If you have not done so already, start with Setting Up a Development Environment.

Full Code⚓︎

import os
from symbolchain.Bip32 import Bip32
from symbolchain.facade.SymbolFacade import SymbolFacade

# Initialize the facade for the testnet network
facade = SymbolFacade('testnet')

# Use an existing mnemonic if provided, otherwise generate a random one
bip32 = Bip32()
mnemonic = os.environ.get('MNEMONIC')
if mnemonic:
    print("Loading mnemonic phrase from environment variable...")
else:
    print("Generating random mnemonic phrase...")
    mnemonic = bip32.random()
print(f'Mnemonic phrase: {mnemonic}')

# Load password from environment variable or use default
password = os.environ.get('PASSWORD', 'correcthorsebatterystaple')
print(f'Password: {password}')

# Derive a root Bip32 node from the mnemonic and a password
root_node = bip32.from_mnemonic(mnemonic, password)

# Derive a child Bip32 node for the account at index 0
account_index = 0
child_node = root_node.derive_path(facade.bip32_path(account_index))

# Convert the Bip32 node to a signing key pair
key_pair = facade.bip32_node_to_key_pair(child_node)

# Derive the address from the public key
address = facade.network.public_key_to_address(key_pair.public_key)

# Output the account details
print(f'Address: {address}')
print(f'Public key: {key_pair.public_key}')
print(f'Private key: {key_pair.private_key}')

Download source

import { Bip32 } from 'symbol-sdk';
import { SymbolFacade } from 'symbol-sdk/symbol';
import process from 'process';

// Initialize the facade for the testnet network
const facade = new SymbolFacade('testnet');

// Use an existing mnemonic if provided, otherwise generate a random one
const bip32 = new Bip32(facade.constructor.BIP32_CURVE_NAME);
let mnemonic = process.env.MNEMONIC;
if (mnemonic) {
    console.log('Loading mnemonic phrase from environment variable...');
} else {
    console.log('Generating random mnemonic phrase...');
    mnemonic = bip32.random();
}
console.log('Mnemonic phrase:', mnemonic);

// Load password from environment variable or use default
const password = process.env.PASSWORD || 'correcthorsebatterystaple';
console.log('Password:', password);

// Derive a root Bip32 node from the mnemonic and a password
const rootNode = bip32.fromMnemonic(mnemonic, password);

// Derive a child Bip32 node for the account at index 0
const accountIndex = 0;
const childNode = rootNode.derivePath(facade.bip32Path(accountIndex));

// Convert the Bip32 node to a signing key pair
const keyPair = facade.constructor.bip32NodeToKeyPair(childNode);

// Derive the address from the public key
const address = facade.network.publicKeyToAddress(keyPair.publicKey);

// Output the account details
console.log('Address:', address.toString());
console.log('Public key:', keyPair.publicKey.toString());
console.log('Private key:', keyPair.privateKey.toString());

Download source

Code Explanation⚓︎

Initializing the Facade⚓︎

# Initialize the facade for the testnet network
facade = SymbolFacade('testnet')
// Initialize the facade for the testnet network
const facade = new SymbolFacade('testnet');

The provides access to Symbol's cryptographic operations and network utilities. It is initialized with a network name (testnet or mainnet) to ensure that network-specific values, such as addresses, are generated correctly.

Defining a Mnemonic⚓︎

# Use an existing mnemonic if provided, otherwise generate a random one
bip32 = Bip32()
mnemonic = os.environ.get('MNEMONIC')
if mnemonic:
    print("Loading mnemonic phrase from environment variable...")
else:
    print("Generating random mnemonic phrase...")
    mnemonic = bip32.random()
print(f'Mnemonic phrase: {mnemonic}')
// Use an existing mnemonic if provided, otherwise generate a random one
const bip32 = new Bip32(facade.constructor.BIP32_CURVE_NAME);
let mnemonic = process.env.MNEMONIC;
if (mnemonic) {
    console.log('Loading mnemonic phrase from environment variable...');
} else {
    console.log('Generating random mnemonic phrase...');
    mnemonic = bip32.random();
}
console.log('Mnemonic phrase:', mnemonic);

The example checks for an existing mnemonic in the MNEMONIC environment variable. If the variable is set, the mnemonic is loaded from it. Otherwise, a new random mnemonic is generated using .

Symbol uses the BIP39 standard, which represents mnemonics as 24 English words selected from a standardized word list. These words encode the entropy (randomness) used to create all derived private keys.

Store your mnemonic phrase securely

The mnemonic phrase can be used to regenerate all derived accounts and private keys. Anyone with access to it can control your accounts, and losing it means losing access permanently.

Never share your mnemonic with anyone, and always store it in a secure location.

Deriving the Root Node⚓︎

# Load password from environment variable or use default
password = os.environ.get('PASSWORD', 'correcthorsebatterystaple')
print(f'Password: {password}')

# Derive a root Bip32 node from the mnemonic and a password
root_node = bip32.from_mnemonic(mnemonic, password)
// Load password from environment variable or use default
const password = process.env.PASSWORD || 'correcthorsebatterystaple';
console.log('Password:', password);

// Derive a root Bip32 node from the mnemonic and a password
const rootNode = bip32.fromMnemonic(mnemonic, password);

After defining the mnemonic, converts the mnemonic and a password into a root node, which serves as the starting point for deriving child accounts.

The password (sometimes called a "25th word") is an optional string that extends the mnemonic seed. It can be left empty or set to any value. When used, it adds another layer of security. Different passwords with the same mnemonic produce completely different accounts.

Password security

The password is part of the account derivation. Both the mnemonic and password are required to regenerate the accounts. If you lose either one, you lose access to all derived accounts.

In this example, the password is loaded from the PASSWORD environment variable. If not set, the snippet uses a default one.

Deriving the Child Account⚓︎

# Derive a child Bip32 node for the account at index 0
account_index = 0
child_node = root_node.derive_path(facade.bip32_path(account_index))
// Derive a child Bip32 node for the account at index 0
const accountIndex = 0;
const childNode = rootNode.derivePath(facade.bip32Path(accountIndex));

The root node can generate multiple accounts, each with its own unique keys and address. This allows a single mnemonic to manage many accounts while keeping them cryptographically isolated.

Deriving an account requires specifying an account index. generates the derivation path (a standardized string that specifies which account to derive) for that index, and follows that path to create the account.

In this example, the account at index 0 is derived. Additional accounts can be derived by using different indices (e.g., 1, 2, 3, ...). Each index produces a completely different account.

Creating the Account⚓︎

# Convert the Bip32 node to a signing key pair
key_pair = facade.bip32_node_to_key_pair(child_node)

# Derive the address from the public key
address = facade.network.public_key_to_address(key_pair.public_key)

# Output the account details
print(f'Address: {address}')
print(f'Public key: {key_pair.public_key}')
print(f'Private key: {key_pair.private_key}')
// Convert the Bip32 node to a signing key pair
const keyPair = facade.constructor.bip32NodeToKeyPair(childNode);

// Derive the address from the public key
const address = facade.network.publicKeyToAddress(keyPair.publicKey);

// Output the account details
console.log('Address:', address.toString());
console.log('Public key:', keyPair.publicKey.toString());
console.log('Private key:', keyPair.privateKey.toString());

Once the child node is derived, it is converted into a usable key pair and address.

  1. Key pair creation: extracts the private key and public key from the child node. The private key must remain secret, while the public key can be safely shared.

  2. Address derivation: converts the public key into an address, a shorter, human-readable, network-specific identifier for the account.

Output⚓︎

The output shown below corresponds to a typical run of the program.

Generating random mnemonic phrase...
Mnemonic phrase: east actual egg series spot express addict always human swallow decrease turn surround direct place burst million curious dish divorce net nephew allow *****
Password: correcthorsebatterystaple
Address: TCHBDENCLKEBILBPWP3JPB2XNY64OE7PYHHE32I
Public key: 3B6A27BCCEB6A42D62A3A8D02A6F0D73653215771DE243A63AC048A18B59DA29
Private key: 0000000000000000000000000000000000000000000000000000000000000000

Each time the code runs without environment variables, it generates a different random mnemonic and account. If the same mnemonic and password are provided, the same account is always derived for the given account index.

Conclusion⚓︎

This tutorial showed how to:

Step Related documentation
Create a random mnemonic
Derive an account from a mnemonic , , and
Get the key pair of the account ,