RAILGUN Wallets
RAILGUN Wallets are created using an encryption key and mnemonic. They will be encrypted and stored into the LevelDOWN database, which you initialized in Step 1 of the Getting Started section.
Wallets must be generated using a 12- or 24- word mnemonic. In order to add a RAILGUN wallet to the local database, you can either import using a previously generated mnemonic or create a new mnemonic using ethers.js.
Example: Generate mnemonic using ethers.js
import { Mnemonic, randomBytes } from "ethers";
/**
* Creates a new mnemonic phrase using 16 bytes of entropy.
*
* A mnemonic phrase is a human-readable representation of a cryptographic seed,
* typically used to derive private keys in cryptocurrency wallets.
*
* @returns A string containing the mnemonic phrase with trimmed whitespace
* @example
* const mnemonic = createMnemonic();
* // mnemonic = "word1 word2 word3 ... word12"
*/
export const createMnemonic = (): string => {
const mnemonic = Mnemonic.fromEntropy(randomBytes(16)).phrase.trim();
return mnemonic;
};
You may provide an optional creationBlockNumberMap
which contains the block numbers for each chain when the wallet was created. This mapping will optimize private balance scans, especially for newly created wallets.
Example: Create local RAILGUN Wallet from mnemonic
import {
NETWORK_CONFIG,
NetworkName,
type RailgunWalletInfo,
} from "@railgun-community/shared-models";
import { createRailgunWallet, loadWalletByID } from "@railgun-community/wallet";
import { Mnemonic, randomBytes } from "ethers";
import {
getEncryptionKeyFromPassword,
setEncryptionKeyFromPassword,
} from "./encryption";
import { TEST_ENCRYPTION_KEY, TEST_NETWORK } from "../utils/constants";
/**
* Creates a new mnemonic phrase using 16 bytes of entropy.
*
* A mnemonic phrase is a human-readable representation of a cryptographic seed,
* typically used to derive private keys in cryptocurrency wallets.
*
* @returns A string containing the mnemonic phrase with trimmed whitespace
* @example
* const mnemonic = createMnemonic();
* // mnemonic = "word1 word2 word3 ... word12"
*/
export const createMnemonic = (): string => {
const mnemonic = Mnemonic.fromEntropy(randomBytes(16)).phrase.trim();
return mnemonic;
};
export const getEncryptionKey = async (password: string) => {
const encryptionKey =
(await getEncryptionKeyFromPassword(password).catch(async (err) => {
// check for no such file or directory error.
if (err.code === "ENOENT") {
console.log("No such file or directory");
// try to create a new wallet
return await setEncryptionKeyFromPassword(password);
}
})) ?? TEST_ENCRYPTION_KEY;
return encryptionKey;
};
/**
* Creates a private RAILGUN wallet using a password and mnemonic phrase.
*
* This function generates an encryption key from the provided password,
* then creates a new RAILGUN wallet using the mnemonic phrase and the
* appropriate deployment block for the test network. After creation,
* it loads the wallet by its ID to verify and return the wallet information.
*
* @param password - The password to encrypt the wallet
* @param mnemonic - The mnemonic phrase (seed phrase) to generate the wallet
* @returns A Promise resolving to the RAILGUN wallet information
* @throws Will throw an error if wallet creation or loading fails
*/
export const createPrivateWallet = async (
password: string,
mnemonic: string
): Promise<RailgunWalletInfo> => {
const encryptionKey = await getEncryptionKey(password);
const { deploymentBlock } = NETWORK_CONFIG[TEST_NETWORK];
const creationBlockMap = {
[TEST_NETWORK]: deploymentBlock,
};
const railgunWalletInfo = await createRailgunWallet(
encryptionKey,
mnemonic,
creationBlockMap
);
const walletInfo = await loadWalletByID(
encryptionKey,
railgunWalletInfo.id,
false
);
return walletInfo;
};
/**
* Loads a RAILGUN wallet from storage using a password and wallet ID.
*
* @param password - User's password to decrypt the wallet
* @param walletId - Unique identifier of the RAILGUN wallet to load
* @returns A Promise resolving to the wallet information (RailgunWalletInfo)
*
* @remarks
* This function retrieves the encryption key derived from the password,
* then loads the wallet from storage using the encryption key and wallet ID.
* The third parameter to loadWalletByID is set to false to indicate this is not a viewing wallet.
*/
export const loadPrivateWallet = async (
password: string,
walletId: string
): Promise<RailgunWalletInfo> => {
const encryptionKey = await getEncryptionKey(password);
const walletInfo = await loadWalletByID(encryptionKey, walletId, false);
return walletInfo;
};
After Railgun Wallets are loaded into the local DB for the first time using createRailgunWallet
, You will want to store the field railgunWallet.id
and reuse the encryptionKey
in order to load it again. On subsequent launches of your dApp, instead of calling createRailgunWallet
again, you must use the loadWalletByID
function to instantly reload the Railgun Wallet. The railgunWallet.id
field will additionally be used to reference the wallet when scanning balances, requesting transaction history, or creating new transactions.
Example: Load stored RAILGUN Wallet from ID
const password = 'some secret phrase'; // See `Encryption Keys` section
const id = 'known wallet id'; // Previously stored when local RAILGUN wallet was created
const railgunWalletInfo = await loadPrivateWallet(password, id);
Last updated