Quantum-resistant wallet library for The QRL using ML-DSA-87 (FIPS 204).
- ML-DSA-87 digital signatures (NIST post-quantum standard)
- Deterministic key derivation from seeds
- Mnemonic phrase backup (34 words)
- Address generation and validation
- Works in Node.js and browsers
- Dual ESM/CommonJS support
npm install @theqrl/wallet.jsimport { MLDSA87, Seed, isValidAddress } from '@theqrl/wallet.js';
// Create a new random wallet
const wallet = MLDSA87.newWallet();
console.log('Address:', wallet.getAddressStr());
console.log('Mnemonic:', wallet.getMnemonic());
// Sign a message
const message = new TextEncoder().encode('Hello QRL!');
const signature = wallet.sign(message);
// Verify signature
const isValid = MLDSA87.verify(signature, message, wallet.getPK());
console.log('Valid:', isValid); // true
// Clean up sensitive data
wallet.zeroize();const { MLDSA87, Seed, isValidAddress } = require('@theqrl/wallet.js');
const wallet = MLDSA87.newWallet();
console.log('Address:', wallet.getAddressStr());Creates a new wallet with a random seed.
const wallet = MLDSA87.newWallet();
const walletWithMeta = MLDSA87.newWallet([0x01, 0x02]); // Custom 2-byte metadataCreates a wallet from an existing seed (deterministic).
const seed = Seed.from('0x' + '00'.repeat(48)); // 48-byte hex string
const wallet = MLDSA87.newWalletFromSeed(seed);Restores a wallet from a mnemonic phrase.
const mnemonic = 'absorb aback veto waiter rail aroma...'; // 34 words
const wallet = MLDSA87.newWalletFromMnemonic(mnemonic);Factory function that auto-detects wallet type from extended seed.
import { newWalletFromExtendedSeed } from '@theqrl/wallet.js';
const wallet = newWalletFromExtendedSeed('0x01000000...'); // 51-byte hex| Method | Returns | Description |
|---|---|---|
getAddressStr() |
string |
Address with Q prefix (e.g., Qabc123...) |
getAddress() |
Uint8Array |
Raw 20-byte address |
getMnemonic() |
string |
34-word mnemonic phrase |
getPK() |
Uint8Array |
Public key (2,592 bytes) |
getSK() |
Uint8Array |
Secret key (4,896 bytes) |
getHexExtendedSeed() |
string |
Extended seed as hex with 0x prefix |
sign(message) |
Uint8Array |
Sign a message (4,627-byte signature) |
zeroize() |
void |
Overwrite sensitive data with zeros |
| Method | Description |
|---|---|
MLDSA87.verify(signature, message, pk) |
Verify a signature, returns boolean |
Address Format: Q prefix + 40 lowercase hex characters (41 chars total).
- Output is always lowercase; input parsing is case-insensitive
- No checksum encoding (unlike EIP-55)
import {
addressToString,
stringToAddress,
isValidAddress
} from '@theqrl/wallet.js';
// Convert bytes to string
const addrStr = addressToString(addressBytes); // 'Qabc...'
// Convert string to bytes (case-insensitive)
const addrBytes = stringToAddress('Qabc123...');
const same = stringToAddress('QABC123...'); // Also valid
// Validate address format
if (isValidAddress(userInput)) {
// Safe to use
}import {
Seed,
ExtendedSeed,
Descriptor,
newMLDSA87Descriptor,
SEED_SIZE, // 48
EXTENDED_SEED_SIZE, // 51
DESCRIPTOR_SIZE // 3
} from '@theqrl/wallet.js';
// Create seed from hex
const seed = Seed.from('0x' + 'ab'.repeat(48));
// Create descriptor
const descriptor = newMLDSA87Descriptor([0x00, 0x00]);
// Create extended seed
const extSeed = ExtendedSeed.newExtendedSeed(descriptor, seed);See SECURITY.md for the security model and best practices.
Important:
- Always call
wallet.zeroize()when done - Never log or transmit mnemonics/seeds
- Validate addresses with
isValidAddress()before use
The library works in browsers via bundlers (webpack, vite, etc.):
import { MLDSA87 } from '@theqrl/wallet.js';
const wallet = MLDSA87.newWallet();Uses Web Crypto API for secure random number generation.
This library currently supports ML-DSA-87 (FIPS 204), the NIST standardized version of Dilithium.
| Property | Value |
|---|---|
| Security Level | NIST Level 5 |
| Public Key | 2,592 bytes |
| Secret Key | 4,896 bytes |
| Signature | 4,627 bytes |
@theqrl/mldsa87- ML-DSA-87 implementation@noble/hashes- SHA-256, SHAKE-256randombytes- Secure random generation
MIT MIT