# RAILGUN Wallets

RAILGUN Wallets are created using an [encryption key](https://docs.railgun.org/developer-guide/wallet/private-wallets/encryption-keys) and mnemonic. They will be encrypted and stored into the LevelDOWN database, which you initialized in [Step 1 of the Getting Started](https://docs.railgun.org/developer-guide/wallet/getting-started/5.-start-the-railgun-privacy-engine) section.&#x20;

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](https://docs.ethers.io/v5/)

```typescript
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.&#x20;

#### Example: Create local RAILGUN Wallet from mnemonic

```typescript
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

```typescript


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);
```
