Skip to content

Mnemonic from Seed

← Back to Mnemonic Utilities

This example demonstrates how to use mnemonicFromSeed() to convert a 32-byte seed into a 25-word Algorand mnemonic. The mnemonic uses BIP39-style word encoding where each word represents 11 bits of data. Key concepts:

  • A 32-byte (256-bit) seed produces 24 data words (256 / 11 = ~23.3, rounded up)
  • A 25th checksum word is computed from the SHA-512/256 hash of the seed
  • The mnemonic is deterministic: same seed always produces same mnemonic
  • No LocalNet required

From the repository root:

Terminal window
cd examples
npm run example algo25/01-mnemonic-from-seed.ts

View source on GitHub

01-mnemonic-from-seed.ts
/**
* Example: Mnemonic from Seed
*
* This example demonstrates how to use mnemonicFromSeed() to convert a 32-byte
* seed into a 25-word Algorand mnemonic. The mnemonic uses BIP39-style word
* encoding where each word represents 11 bits of data.
*
* Key concepts:
* - A 32-byte (256-bit) seed produces 24 data words (256 / 11 = ~23.3, rounded up)
* - A 25th checksum word is computed from the SHA-512/256 hash of the seed
* - The mnemonic is deterministic: same seed always produces same mnemonic
*
* Prerequisites:
* - No LocalNet required
*/
import { mnemonicFromSeed } from '@algorandfoundation/algokit-utils/algo25'
import { formatBytes, formatHex, printHeader, printInfo, printStep, printSuccess } from '../shared/utils.js'
function main() {
printHeader('Mnemonic from Seed Example')
// Step 1: Generate a random 32-byte seed
printStep(1, 'Generate a Random 32-byte Seed')
const seed = new Uint8Array(32)
crypto.getRandomValues(seed)
printInfo(`Seed length: ${seed.length} bytes (256 bits)`)
printInfo(`Seed bytes: ${formatBytes(seed, 16)}`)
printInfo(`Seed hex: ${formatHex(seed)}`)
// Step 2: Convert seed to mnemonic
printStep(2, 'Convert Seed to 25-Word Mnemonic')
const mnemonic = mnemonicFromSeed(seed)
const words = mnemonic.split(' ')
printInfo(`Total words: ${words.length}`)
printInfo(`Data words: 24 (encoding 256 bits of seed data)`)
printInfo(`Checksum word: 1 (derived from SHA-512/256 hash of seed)`)
// Step 3: Display the 25 words
printStep(3, 'Display the Mnemonic Words')
printInfo('Mnemonic words:')
// Display words in rows of 5 for readability
for (let i = 0; i < words.length; i += 5) {
const row = words.slice(i, i + 5)
const numbered = row.map((w, j) => `${(i + j + 1).toString().padStart(2, ' ')}. ${w.padEnd(10)}`).join(' ')
printInfo(` ${numbered}`)
}
// Step 4: Explain the 11-bit encoding scheme
printStep(4, 'Explain the 11-bit Encoding Scheme')
printInfo('How seed bits map to mnemonic words:')
printInfo(' - Seed: 32 bytes = 256 bits')
printInfo(' - Each word encodes 11 bits (2^11 = 2048 possible words)')
printInfo(' - 256 bits / 11 bits per word = 23.27 words')
printInfo(' - This rounds up to 24 words (with 8 padding bits)')
printInfo(' - 24 words × 11 bits = 264 bits total')
printInfo(' - Extra 8 bits are zero-padded')
printInfo('')
printInfo('Checksum word calculation:')
printInfo(' - Compute SHA-512/256 hash of the 32-byte seed')
printInfo(' - Take the first 11 bits of the hash')
printInfo(' - Map those 11 bits to a word from the wordlist')
printInfo(' - This becomes the 25th (checksum) word')
// Step 5: Verify determinism
printStep(5, 'Verify Determinism - Same Seed Produces Same Mnemonic')
const mnemonic1 = mnemonicFromSeed(seed)
const mnemonic2 = mnemonicFromSeed(seed)
printInfo(`First call result:`)
printInfo(` "${mnemonic1.split(' ').slice(0, 5).join(' ')}..."`)
printInfo(`Second call result:`)
printInfo(` "${mnemonic2.split(' ').slice(0, 5).join(' ')}..."`)
const isIdentical = mnemonic1 === mnemonic2
printInfo(`Mnemonics identical: ${isIdentical ? 'Yes' : 'No'}`)
if (isIdentical) {
printSuccess('Determinism verified: same seed always produces same mnemonic')
}
// Step 6: Show a second random seed for comparison
printStep(6, 'Different Seed Produces Different Mnemonic')
const seed2 = new Uint8Array(32)
crypto.getRandomValues(seed2)
const mnemonic3 = mnemonicFromSeed(seed2)
printInfo(`Seed 1 (first 8 bytes): ${formatHex(seed.slice(0, 8))}...`)
printInfo(`Seed 2 (first 8 bytes): ${formatHex(seed2.slice(0, 8))}...`)
printInfo('')
printInfo(`Mnemonic 1 (first 3 words): ${mnemonic1.split(' ').slice(0, 3).join(' ')}...`)
printInfo(`Mnemonic 2 (first 3 words): ${mnemonic3.split(' ').slice(0, 3).join(' ')}...`)
const isDifferent = mnemonic1 !== mnemonic3
printInfo(`Mnemonics different: ${isDifferent ? 'Yes' : 'No'}`)
// Summary
printStep(7, 'Summary')
printInfo('mnemonicFromSeed() converts a 32-byte seed to a 25-word mnemonic:')
printInfo(' - Input: 32-byte Uint8Array (cryptographically random seed)')
printInfo(' - Output: Space-separated string of 25 words')
printInfo(' - Words 1-24: Encode the 256-bit seed (11 bits per word)')
printInfo(' - Word 25: Checksum derived from SHA-512/256 hash')
printInfo(' - Deterministic: reproducible from the same seed')
printInfo(' - BIP39-compatible wordlist: 2048 English words')
printSuccess('Mnemonic from Seed example completed successfully!')
}
main()