wavelength-react
React bindings for the Wavelength SDK - the WavelengthProvider component and hooks for balance, activity, and wallet operations.
@lightninglabs/wavelength-react is the React binding for the Wavelength SDK: a context provider that hands a WalletEngine down to a component subtree, plus hooks for reading its state and calling wallet operations.
Provider
WavelengthProvider
classContext provider that hands a WalletEngine down to descendants. Wrap your application root (or any subtree) with this component so child hooks can access wallet state and operations.
function WavelengthProvider(props: WavelengthProviderProps): JSX.Element| Parameter | Type | Description |
|---|---|---|
engine | WalletEngine | A WalletEngine from any transport, e.g. createWebWalletEngine() from wavelength-web or createNativeWalletEngine() from wavelength-react-native. Required; the provider throws synchronously if it is missing. |
children | ReactNode | The component subtree that can call Wavelength SDK hooks. |
WavelengthProviderProps
typeProps for the WavelengthProvider component. WavelengthProviderProps is not itself an exported name; the props type is declared inline on the component’s destructured parameter. It is named and documented separately here only for readability.
type WavelengthProviderProps = { children: ReactNode; engine: WalletEngine;};useWalletEngine
functionReturns the WalletEngine from the nearest WavelengthProvider: the escape hatch for anything the granular hooks below do not cover (for example calling engine.client directly, or a method with no dedicated hook). Throws outside a provider.
function useWalletEngine(): WalletEngineuseWallet
useWallet
functionThe application-shell hook: the lifecycle phase to route your top-level UI on, the last fatal runtime error, and the start/stop actions. There are no pending flags here: phase === 'starting' / 'stopping' already encode them.
function useWallet(): { phase: RuntimePhase; error: Error | null; start(config?: RuntimeConfig): Promise<WalletInfo>; stop(): Promise<void>;};| Parameter | Type | Description |
|---|---|---|
phase | RuntimePhase | Current runtime/wallet lifecycle phase. See RuntimePhase on the wavelength-core reference; note it now includes 'restoring'. |
error | Error | null | The last fatal runtime-level error, or null. Set when the initial runtime load fails, when start()/stop() fails, or after the engine's background processes exhaust their failure budget (e.g. repeated sync-poll or background-refresh failures). |
start(config?) | (config?: RuntimeConfig) => Promise<WalletInfo> | Starts the runtime. Falls back to the engine's configured config (the one passed to createWebWalletEngine/createNativeWalletEngine) when called with no argument; throws if neither exists. Resolves with the WalletInfo from startup. |
stop() | () => Promise<void> | Stops the runtime and clears the in-memory snapshot (info/balance/activity reset to null/null/[]); persisted wallet data is untouched. |
{ phase, error, start, stop }The runtime lifecycle phase, last fatal error, and start/stop actions.
Reading state
The five hooks below each subscribe to one slice of the engine’s snapshot via useSyncExternalStore, so a component re-renders only when the slice it reads actually changes. useWalletInfo, useWalletBalance, and useWalletActivity are plain selectors; useWalletRecovery and useWalletLogs also return an action (acknowledge() and clear() respectively) alongside their slice.
useWalletInfo
functionThe most recent complete wallet info, or null before the runtime reports it.
function useWalletInfo(): WalletInfo | nullWalletInfo | nullThe current WalletInfo, or null before the runtime reports it. Always a complete object: the engine refetches full info whenever the wallet comes up (create, unlock, passkey open, restore).
useWalletBalance
functionThe most recent wallet balance, or null before it is known.
function useWalletBalance(): Balance | nullBalance | nullThe current Balance, or null before known.
useWalletActivity
functionThe most recent activity entries, newest-first as returned by the daemon.
function useWalletActivity(): Entry[]Entry[]Always the result of list({ view: 'activity', pendingOnly: false }); it does not reflect the vtxos or onchain views.
useWalletRecovery
functionThe background recovery status set by useWalletRestore and its acknowledge action.
function useWalletRecovery(): { recovery: RecoveryState; acknowledge(): void;};| Parameter | Type | Description |
|---|---|---|
recovery | RecoveryState | The background recovery status, a discriminated union on status: { status: 'idle' } | { status: 'restoring' } | { status: 'done', result: CreateWalletResult } | { status: 'failed', error: Error }. failed covers both a background scan that errored on an already-usable wallet and a restore that failed before the wallet came up at all, including an untracked restore; read phase from useWallet() alongside it to tell the two apart (ready vs. needsWallet). See RecoveryState on the wavelength-core reference. Drive a "restoring your balance and history" banner off the ready case, or a restore-failed message on the onboarding screen off the needsWallet case. |
acknowledge() | () => void | Resets recovery to { status: 'idle' }, e.g. after the user dismisses the banner. |
useWalletLogs
functionThe buffered runtime log tail and a clear action.
function useWalletLogs(): { logs: WavelengthLogPayload[]; clear(): void;};| Parameter | Type | Description |
|---|---|---|
logs | WavelengthLogPayload[] | Bounded tail (up to 200 entries) of 'log' events from the runtime, newest last. |
clear() | () => void | Clears the buffered log tail. |
Mutations
The eight hooks below drive a wallet operation and carry hook-local, verb-prefixed *Pending/*Error/*Data state, all built on one shared convention:
useWalletCreate
functionCreates a new wallet, with hook-local createPending/createError/createData state.
function useWalletCreate(): { create(req: CreateWalletRequest): Promise<CreateWalletResult>; createPending: boolean; createError: Error | null; createData: CreateWalletResult | null; resetCreate(): void;};| Parameter | Type | Description |
|---|---|---|
create(req) | (req: CreateWalletRequest) => Promise<CreateWalletResult> | Creates a new wallet, refetches info, and kicks a background refresh. See createWallet on the wavelength-core reference. |
{ create, createPending, createError, createData, resetCreate }See the mutation convention above.
useWalletRestore
functionRestores a wallet from a mnemonic, with hook-local restorePending/restoreError/restoreData state.
function useWalletRestore(): { restore(req: RestoreWalletRequest): Promise<WalletInfo>; restorePending: boolean; restoreError: Error | null; restoreData: WalletInfo | null; resetRestore(): void;};| Parameter | Type | Description |
|---|---|---|
restore(req) | (req: RestoreWalletRequest) => Promise<WalletInfo> | Restores a wallet from req.mnemonic. See restoreWallet on the wavelength-core reference. |
{ restore, restorePending, restoreError, restoreData, resetRestore }See the mutation convention above, with one twist: restore’s promise (and therefore restorePending/restoreError) only covers getting the wallet up; it resolves as soon as the restored wallet is usable, not when the optional server-assisted recovery scan finishes, and it never rejects for a scan failure. Observe the scan, and a restore that fails before the wallet came up, separately through useWalletRecovery: even a fire-and-forget restore() call whose promise is not awaited still surfaces a pre-usability failure there once phase falls back to 'needsWallet'.
useWalletUnlock
functionUnlocks an existing wallet, with hook-local unlockPending/unlockError/unlockData state.
function useWalletUnlock(): { unlock(req: UnlockWalletRequest): Promise<UnlockWalletResult>; unlockPending: boolean; unlockError: Error | null; unlockData: UnlockWalletResult | null; resetUnlock(): void;};| Parameter | Type | Description |
|---|---|---|
unlock(req) | (req: UnlockWalletRequest) => Promise<UnlockWalletResult> | Unlocks an existing wallet, refetches info, and kicks a background refresh. See unlockWallet on the wavelength-core reference. |
{ unlock, unlockPending, unlockError, unlockData, resetUnlock }See the mutation convention above.
useWalletDeposit
functionRequests an on-chain deposit address, with hook-local depositPending/depositError/depositData state.
function useWalletDeposit(): { deposit(req?: DepositRequest): Promise<DepositResult>; depositPending: boolean; depositError: Error | null; depositData: DepositResult | null; resetDeposit(): void;};| Parameter | Type | Description |
|---|---|---|
deposit(req?) | (req?: DepositRequest) => Promise<DepositResult> | Requests an on-chain deposit address and kicks a background refresh. req is optional and defaults to {} when omitted. See deposit on the wavelength-core reference. |
{ deposit, depositPending, depositError, depositData, resetDeposit }See the mutation convention above.
useWalletReceive
functionRequests a Lightning receive invoice, with hook-local receivePending/receiveError/receiveData state.
function useWalletReceive(): { receive(req: ReceiveRequest): Promise<ReceiveResult>; receivePending: boolean; receiveError: Error | null; receiveData: ReceiveResult | null; resetReceive(): void;};| Parameter | Type | Description |
|---|---|---|
receive(req) | (req: ReceiveRequest) => Promise<ReceiveResult> | Requests a Lightning receive invoice and kicks a background refresh. See receive on the wavelength-core reference. |
{ receive, receivePending, receiveError, receiveData, resetReceive }See the mutation convention above.
useWalletPrepareSend
functionQuotes a payment without dispatching it, with hook-local preparePending/prepareError/prepareData state.
function useWalletPrepareSend(): { prepare(req: SendRequest): Promise<PrepareSendResult>; preparePending: boolean; prepareError: Error | null; prepareData: PrepareSendResult | null; resetPrepare(): void;};| Parameter | Type | Description |
|---|---|---|
prepare(req) | (req: SendRequest) => Promise<PrepareSendResult> | Quotes a payment without dispatching it; no refresh, since a quote moves no money. See prepareSend on the wavelength-core reference. |
{ prepare, preparePending, prepareError, prepareData, resetPrepare }See the mutation convention above. prepareData holds the latest quote for a review screen; pair it with useWalletSend’s sendPrepared to dispatch it.
useWalletSend
functionDispatches a payment: send is the one-shot path, sendPrepared confirms a quote from useWalletPrepareSend. The two verbs are alternative dispatch paths for the same payment and share one sendPending/sendError/sendData slot.
function useWalletSend(): { send(req: SendRequest): Promise<SendResult>; sendPrepared(prepared: PrepareSendResult): Promise<SendResult>; sendPending: boolean; sendError: Error | null; sendData: SendResult | null; resetSend(): void;};| Parameter | Type | Description |
|---|---|---|
send(req) | (req: SendRequest) => Promise<SendResult> | Quotes and dispatches a payment in one call, then kicks a background refresh. See send on the wavelength-core reference. |
sendPrepared(prepared) | (prepared: PrepareSendResult) => Promise<SendResult> | Dispatches a quote returned by useWalletPrepareSend, then kicks a background refresh. See sendPrepared on the wavelength-core reference. |
{ send, sendPrepared, sendPending, sendError, sendData, resetSend }See the mutation convention above.
useWalletRefresh
functionRe-fetches info, balance, and activity.
function useWalletRefresh(): { refresh(): Promise<void>; refreshPending: boolean; refreshError: Error | null; resetRefresh(): void;};| Parameter | Type | Description |
|---|---|---|
refresh() | () => Promise<void> | Re-fetches info, balance, and activity concurrently. See refresh on the wavelength-core reference. |
{ refresh, refreshPending, refreshError, resetRefresh }The one mutation hook with no data field: refresh() resolves void, so there is nothing to hold. refreshPending tracks only this hook instance’s own calls, not the engine’s own background refreshes (the sync poll, the activity-driven settle reconcile, or the refresh kicked automatically after another mutation): those never flip it. Use it as what a pull-to-refresh spinner should show.
Exiting Ark
Seven hooks cover the exit surface. useWalletExit, useWalletExitPlan,
useWalletSweep, and useWalletList are 1:1 wrappers
around one WalletEngine verb
each, following the same mutation convention as the hooks above.
useWalletExitBatch is the orchestrator: it drives a
full multi-outpoint exit through the funding-contention guards documented on
exitBatch in the wavelength-core
reference, and additionally exposes the batch’s progress events.
useWalletExitStatus and
useWalletExits are read hooks instead of mutations: they
fetch on mount (and on relevant changes) and expose a refresh* action
rather than a reset* one, since there is no pending/error/data trio to
clear back to idle, only a cached read to force fresh.
useWalletExit
functionStarts a single exit for one outpoint, with hook-local exitPending/exitError/exitData state. A 1:1 wrapper around WalletEngine.exit().
function useWalletExit(): { exit(req: ExitRequest): Promise<ExitResult>; exitPending: boolean; exitError: Error | null; exitData: ExitResult | null; resetExit(): void;};| Parameter | Type | Description |
|---|---|---|
exit(req) | (req: ExitRequest) => Promise<ExitResult> | Starts a single exit, cooperative or unilateral depending on req. Takes the full ExitRequest union; see exit on the wavelength-core reference. |
{ exit, exitPending, exitError, exitData, resetExit }See the mutation convention above.
useWalletExitPlan
functionPreviews unilateral-exit readiness and backing-wallet funding for a set of outpoints, with hook-local planPending/planError/planData state. A 1:1 wrapper around WalletEngine.getExitPlan(). Pair it with useWalletExitBatch to act on a plan: exitBatch previews and re-plans internally, so this hook is for a standalone preview screen rather than a required prerequisite step before calling exitBatch.
function useWalletExitPlan(): { plan(req: GetExitPlanRequest): Promise<GetExitPlanResult>; planPending: boolean; planError: Error | null; planData: GetExitPlanResult | null; resetPlan(): void;};| Parameter | Type | Description |
|---|---|---|
plan(req) | (req: GetExitPlanRequest) => Promise<GetExitPlanResult> | Previews funding for the given outpoints without moving funds. See getExitPlan on the wavelength-core reference. |
{ plan, planPending, planError, planData, resetPlan }See the mutation convention above.
useWalletSweep
functionPreviews (broadcast: false) or broadcasts (broadcast: true) a sweep of the backing on-chain wallet, with hook-local sweepPending/sweepError/sweepData state. A 1:1 wrapper around WalletEngine.sweepWallet(). Call it with broadcast: false first to preview the fee and net amount, then again with broadcast: true once the user confirms; only the broadcasting call moves funds and kicks a background refresh.
function useWalletSweep(): { sweep(req: SweepWalletRequest): Promise<SweepWalletResult>; sweepPending: boolean; sweepError: Error | null; sweepData: SweepWalletResult | null; resetSweep(): void;};| Parameter | Type | Description |
|---|---|---|
sweep(req) | (req: SweepWalletRequest) => Promise<SweepWalletResult> | Previews or broadcasts the sweep, depending on req.broadcast. See sweepWallet on the wavelength-core reference. |
{ sweep, sweepPending, sweepError, sweepData, resetSweep }See the mutation convention above.
useWalletExitBatch
functionThe orchestrator: starts a batch of exits across multiple outpoints, handling the funding-contention guards internally. Unlike the other mutation hooks, it also exposes exitBatchEvents, the batch’s progress events in order for the current or last run, so a UI can render a live per-outpoint timeline instead of waiting for the whole batch to settle.
function useWalletExitBatch(): { exitBatch(opts: ExitBatchOptions): Promise<ExitBatchResult>; exitBatchPending: boolean; exitBatchError: Error | null; exitBatchData: ExitBatchResult | null; exitBatchEvents: ExitBatchEvent[]; resetExitBatch(): void;};| Parameter | Type | Description |
|---|---|---|
exitBatch(opts) | (opts: ExitBatchOptions) => Promise<ExitBatchResult> | Starts the batch. See ExitBatchOptions on the wavelength-core reference for the cooperative/unilateral discriminated union. |
{ exitBatch, exitBatchPending, exitBatchError, exitBatchData, exitBatchEvents, resetExitBatch }The mutation convention above, plus exitBatchEvents: the ExitBatchEvent list for the current or last run, reset to empty each time exitBatch() is called or resetExitBatch() runs.
useWalletExitStatus
functionReads one exit’s status. Defaults to the cheap, coarse phase-only call; pass { detailed: true } for recovery-tree progress, the CSV maturity countdown, and a fee breakdown, at the cost of a live round-trip. Fetches on mount and whenever outpoint or the options change.
function useWalletExitStatus( outpoint: string, opts?: { detailed?: boolean; pollMs?: number },): { status: ExitStatusResult | null; statusPending: boolean; statusError: Error | null; refreshStatus(): Promise<ExitStatusResult>;};| Parameter | Type | Description |
|---|---|---|
outpoint | string | The VTXO outpoint whose exit status is read. |
opts.detailed | boolean | Optional. Requests the detailed fields; leave it false for a coarse, cheaper status. |
opts.pollMs | number | Optional. Polls at this interval, in milliseconds, while the component stays mounted. Polling is opt-in (omit it for a one-shot fetch); it keeps running with no visibility/focus gating (including in a backgrounded tab) and stops only on unmount, so there is no timer left running once the user navigates away. |
{ status, statusPending, statusError, refreshStatus }status is null before the first load resolves. Unlike the mutation hooks above, there is no reset action: refetch on demand with refreshStatus(), or change outpoint/opts to refetch automatically.
useWalletExits
functionReads the wallet-wide in-progress exit portfolio. Fetches on mount and whenever wallet activity changes, so a completed exit clears from the summary without a manual refresh.
function useWalletExits(): { summary: ExitSummaryResult | null; summaryPending: boolean; summaryError: Error | null; refreshSummary(): Promise<ExitSummaryResult>;};{ summary, summaryPending, summaryError, refreshSummary }summary is null before the first load resolves. Like useWalletExitStatus, there is no reset action; call refreshSummary() to refetch on demand.
useWalletList
functionLists wallet activity, VTXOs, or on-chain outputs on demand, with hook-local listPending/listError/listData state. A 1:1 wrapper around WalletEngine.list(). Reach for it for an on-demand fetch, such as populating a VTXO picker before an exit; the always-fresh activity feed is already available from useWalletActivity() without a manual fetch.
function useWalletList(): { list(req: ListRequest): Promise<ListResult>; listPending: boolean; listError: Error | null; listData: ListResult | null; resetList(): void;};| Parameter | Type | Description |
|---|---|---|
list(req) | (req: ListRequest) => Promise<ListResult> | Lists the requested view. See list on the wavelength-core reference. |
{ list, listPending, listError, listData, resetList }See the mutation convention above.
Passkeys
useWalletPasskey
functionDrives a passkey ceremony and opens the wallet through the engine, refreshing engine state on success so phase advances automatically. The ceremony is injected, which keeps wavelength-react free of any transport dependency: in the browser, pass webPasskeyCeremony from wavelength-web; the React Native transport supplies createNativePasskeyCeremony (wavelength-react-native). Creation and opening track separately (create*/open* fields below) because apps render them on different screens. Must be called within a WavelengthProvider subtree; throws otherwise.
function useWalletPasskey(ceremony: PasskeyCeremony): { supported: boolean | null; create(appName: string): Promise<PasskeyWalletOutcome>; createPending: boolean; createError: Error | null; resetCreate(): void; open(credentialId?: string): Promise<PasskeyWalletOutcome>; openPending: boolean; openError: Error | null; resetOpen(): void;};| Parameter | Type | Description |
|---|---|---|
ceremony | PasskeyCeremony | Platform ceremony implementation. In the browser, pass webPasskeyCeremony from wavelength-web. |
| Parameter | Type | Description |
|---|---|---|
supported | boolean | null | Whether the environment supports passkey PRF. Starts null while ceremony.supportsPasskeyPrf() is in flight, then settles to true or false once it resolves; if that probe rejects, supported settles to false rather than throwing. Treat null as still-checking and gate passkey UI on it accordingly, not as a falsy unsupported state. The probe is memoized per ceremony instance, so warming it once at app boot means supported is usually already settled by the time a screen reads it. |
create(appName) | (appName: string) => Promise<PasskeyWalletOutcome> | Registers a passkey and creates the wallet from it. Follows the same throw-and-capture convention as the mutation hooks above: it both resolves/rejects and updates createPending/createError/reset via resetCreate. |
createPending | boolean | True while create() is in flight. |
createError | Error | null | The last error from create(), or null. A PasskeyCancelledError is never recorded here. |
resetCreate() | () => void | Clears createPending/createError back to idle. |
open(credentialId?) | (credentialId?: string) => Promise<PasskeyWalletOutcome> | Asserts a passkey (scoped to credentialId when provided, discoverable otherwise) and imports/unlocks the wallet. |
openPending | boolean | True while open() is in flight. |
openError | Error | null | The last error from open(), or null. A PasskeyCancelledError is never recorded here. |
resetOpen() | () => void | Clears openPending/openError back to idle. |
PasskeyWalletOutcome
typePairs the daemon-side open result with the credential id used in the ceremony, so the app can persist it and scope future unlocks to the same passkey. Returned by both create and open.
type PasskeyWalletOutcome = { result: OpenWalletFromPasskeyResult; credentialId: string;};| Parameter | Type | Description |
|---|---|---|
result | OpenWalletFromPasskeyResult | The result returned by opening the wallet from the passkey. See OpenWalletFromPasskeyResult on the wavelength-core reference. |
credentialId | string | The credential id that produced the PRF output, for persistence and scoping future assertions. |
PasskeyCeremony
typeThe per-platform contract useWalletPasskey drives. It is defined in wavelength-core but documented here since this package is its primary consumer; the browser implementation, webPasskeyCeremony, lives in wavelength-web. The React Native transport supplies createNativePasskeyCeremony (wavelength-react-native) as its implementation of the same contract.
type WalletKind = 'passkey' | 'password';
type PasskeyAssertion = { prfOutput: string; credentialId: string;};
type PasskeyCeremony = { supportsPasskeyPrf(): Promise<boolean>; registerPasskeyWallet(appName: string): Promise<PasskeyAssertion>; assertPasskeyPrf(allowCredentialId?: string): Promise<PasskeyAssertion>;};| Parameter | Type | Description |
|---|---|---|
WalletKind | 'passkey' | 'password' | Labels how a local wallet is unlocked. |
supportsPasskeyPrf() | () => Promise<boolean> | Resolves true when the platform supports passkey PRF. |
registerPasskeyWallet(appName) | (appName: string) => Promise<PasskeyAssertion> | Registers a new passkey and returns its assertion. appName becomes the WebAuthn relying-party name in the web implementation. |
assertPasskeyPrf(allowCredentialId?) | (allowCredentialId?: string) => Promise<PasskeyAssertion> | Asserts an existing passkey, optionally scoped to a credential id (discoverable when omitted). |
PasskeyAssertion.prfOutput | string | The PRF output (hex) shared with the Go SDK. |
PasskeyAssertion.credentialId | string | The credential id that produced the PRF output. |
Re-exported from wavelength-core
@lightninglabs/wavelength-react re-exports the complete
@lightninglabs/wavelength-core surface. That includes WavelengthClient,
WalletEngine, createWalletEngine, FacadeMethod, ActivityStreamOptions,
RuntimeConfig, WalletInfo, WalletStatus, Balance, Entry, the complete
activity/exit/send/list type families, all named nested response types, and all
generated string-enum constants. RuntimePhase, WalletState,
RecoveryState, PasskeyCancelledError, and toError are included too.
defaultConfig comes from the transport packages
(@lightninglabs/wavelength-web and
@lightninglabs/wavelength-react-native). The core contract and enum constant
families are listed on the wavelength-core reference.
See also
- wavelength-core reference for
WalletEngine,WavelengthClient,RuntimeConfig,WalletInfo,Balance,Entry,RuntimePhase, andWalletState. - wavelength-web reference for
createWebWalletEngine()andwebPasskeyCeremony, the browser transport and passkey ceremony used with this package. - wavelength-react-native reference for
createNativeWalletEngine()andcreateNativePasskeyCeremony(), the React Native transport and passkey ceremony used with this package.