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.

Terminal
# Install the browser runtime and the React bindings.
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.

Terminal
# Install the native transport and the React bindings.
npm install @lightninglabs/wavelength-react-native @lightninglabs/wavelength-react

See Installation for staging the native runtime binaries before your first build.

Add the provider

Build a WalletEngine outside your component tree and wrap your app in 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'). Move to a hand-built mainnet config (with allowMainnet: true) only once you have key backup and recovery in place.

createWebWalletEngine() builds the engine for the browser transport:

App.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() builds the engine for the native transport:

App.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(); see Handle phases & errors.

Create the wallet

Call useWalletCreate() inside the provider to create a wallet. When phase from 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.

Onboard.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>
)}
</>
);
}