---
title: "Create a wallet (password)"
description: "Create a password-protected Wavelength wallet in a React app, with inline code at each step."
canonical: https://wavelength.lightning.engineering/guides/create-a-wallet/
---

> Docs index: https://wavelength.lightning.engineering/llms.txt

[Wavelength](/)›Guides›Create a wallet (password)

# Create a wallet (password)

2 min read

Guides

Web SDK

## Install the packages

The Wavelength SDK ships as a transport package, one per platform, plus `@lightninglabs/wavelength-react`, the React bindings. All are ES modules with full TypeScript declarations.

The web transport, `@lightninglabs/wavelength-web`, bundles a WASM module for cryptography and uses OPFS for storage. There are no native dependencies and no server-side component, so a modern browser is all you need at runtime.

```bash
npm install @lightninglabs/wavelength-web @lightninglabs/wavelength-react
```

The React Native transport, `@lightninglabs/wavelength-react-native`, wraps a wallet runtime that is compiled into your app binary rather than fetched at runtime.

```bash
npm install @lightninglabs/wavelength-react-native @lightninglabs/wavelength-react
```

See [Installation](/react-native/get-started/installation/) for staging the native runtime binaries before your first build.

## Add the provider

Build a [`WalletEngine`](/reference/wavelength-core/#WalletEngine) outside your component tree and wrap your app in [`WavelengthProvider`](/reference/wavelength-react/#WavelengthProvider) so every component below it can reach the wallet through hooks. Pass `config` and `autoStart: true` so the engine boots the embedded daemon on its own as soon as the runtime is ready; no boot effect needed.

Start with [`defaultConfig('signet')`](/reference/wavelength-web/#defaultConfig). Move to a hand-built mainnet config (with `allowMainnet: true`) only once you have key backup and recovery in place.

[`createWebWalletEngine()`](/reference/wavelength-web/#createWebWalletEngine) builds the engine for the browser transport:

```tsx
import { createWebWalletEngine } from '@lightninglabs/wavelength-web';
import { WavelengthProvider } from '@lightninglabs/wavelength-react';
import { defaultConfig } from '@lightninglabs/wavelength-web';

const engine = createWebWalletEngine({
  runtimeBaseUrl: '/wavewalletdk/',
  config: defaultConfig('signet'),
  autoStart: true,
});

export function App() {
  return (
    <WavelengthProvider engine={engine}>
      {/* your app */}
    </WavelengthProvider>
  );
}
```

[`createNativeWalletEngine()`](/reference/wavelength-react-native/#createNativeWalletEngine) builds the engine for the native transport:

```tsx
import { createNativeWalletEngine } from '@lightninglabs/wavelength-react-native';
import { WavelengthProvider } from '@lightninglabs/wavelength-react';
import { defaultConfig } from '@lightninglabs/wavelength-react-native';

const engine = createNativeWalletEngine({
  config: defaultConfig('signet'),
  autoStart: true,
});

export function App() {
  return (
    <WavelengthProvider engine={engine}>
      {/* your app */}
    </WavelengthProvider>
  );
}
```

The engine itself owns starting the runtime, so `App` needs no start effect. If you would rather call `start()` yourself (for example to prompt the user first), omit `autoStart` and drive it from [`useWallet()`](/reference/wavelength-react/#useWallet); see [Handle phases & errors](/guides/handle-phases-and-errors/).

## Create the wallet

Call [`useWalletCreate()`](/reference/wavelength-react/#useWalletCreate) inside the provider to create a wallet. When `phase` from [`useWallet()`](/reference/wavelength-react/#useWallet) is `'needsWallet'`, no wallet exists yet.

`create({ password })` generates a fresh HD seed, encrypts it with the password, and stores it locally. The password is whatever you pass in; the SDK does not enforce a minimum length or complexity, so validate it yourself before calling `create`. The whole operation runs on-device and the seed never leaves it. After it resolves, `phase` becomes `'ready'`.

The resolved result includes `mnemonic`, the wallet’s recovery phrase. This is the only time the SDK ever returns it, so show it to the user immediately and prompt them to write it down before continuing. To rebuild a wallet from an existing recovery phrase instead of generating a new one, see [Restore a wallet](/guides/restore-a-wallet/).

```tsx
import { useState } from 'react';
import { useWallet, useWalletCreate } from '@lightninglabs/wavelength-react';

function Onboard() {
  const { phase } = useWallet();
  const { create, createPending, createError } = useWalletCreate();
  const [mnemonic, setMnemonic] = useState<string[] | null>(null);

  const handleCreate = async () => {
    // Generate the HD seed on-device, encrypted with the password.
    const result = await create({ password: 'a-strong-password' });
    // Show the mnemonic once, right after creation: it is not retrievable later.
    setMnemonic(result.mnemonic);
  };

  if (phase !== 'needsWallet') {
    return null;
  }

  return (
    <>
      <button onClick={handleCreate} disabled={createPending}>
        Create wallet
      </button>
      {createError && <p role="alert">{createError.message}</p>}
      {mnemonic && (
        <p>Write down your recovery phrase: {mnemonic.join(' ')}</p>
      )}
    </>
  );
}
```
