@lightninglabs/wavelength-react 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (C) 2026 Lightning Labs and The Lightning Network Developers
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,68 @@
1
+ # @lightninglabs/wavelength-react
2
+
3
+ React provider and hooks for [Wavelength](https://wavelength.lightning.engineering): embed a
4
+ self-custodial Lightning wallet directly in your app. Your users send and
5
+ receive Lightning payments with no node to run, no channels to open, and no
6
+ inbound liquidity to manage, while their keys stay on their own device.
7
+
8
+ This package is transport-agnostic. It depends only on
9
+ [`@lightninglabs/wavelength-core`](https://www.npmjs.com/package/@lightninglabs/wavelength-core) and takes an injected engine, so the
10
+ same binding runs over both the web and React Native transports. Build the
11
+ engine with the transport you use, and pass it to `WavelengthProvider`.
12
+
13
+ ## Install
14
+
15
+ ```sh
16
+ # Web (React + the browser transport)
17
+ npm install @lightninglabs/wavelength-react @lightninglabs/wavelength-web
18
+ ```
19
+
20
+ On React Native, install
21
+ [`@lightninglabs/wavelength-react-native`](https://www.npmjs.com/package/@lightninglabs/wavelength-react-native) instead of the web
22
+ transport.
23
+
24
+ ## Quick start
25
+
26
+ ```tsx
27
+ import { WavelengthProvider, useWallet, useWalletBalance, useWalletSend } from "@lightninglabs/wavelength-react";
28
+ import { createWebWalletEngine, defaultConfig } from "@lightninglabs/wavelength-web";
29
+
30
+ const engine = createWebWalletEngine({
31
+ runtimeBaseUrl: "https://your-host/wavewalletdk/",
32
+ config: defaultConfig("signet"),
33
+ autoStart: true,
34
+ });
35
+
36
+ function Root() {
37
+ return (
38
+ <WavelengthProvider engine={engine}>
39
+ <Wallet />
40
+ </WavelengthProvider>
41
+ );
42
+ }
43
+
44
+ function Wallet() {
45
+ const { phase } = useWallet();
46
+ const balance = useWalletBalance();
47
+ const { send } = useWalletSend();
48
+
49
+ if (phase !== "ready") return <p>Loading… ({phase})</p>;
50
+
51
+ return (
52
+ <div>
53
+ <p>Spendable: {balance?.confirmedSat ?? 0} sats</p>
54
+ <button onClick={() => send({ invoice: "lnbc…" })}>Pay</button>
55
+ </div>
56
+ );
57
+ }
58
+ ```
59
+
60
+ State-reading hooks like `useWalletBalance()` and `useWalletActivity()` return
61
+ their value directly. Mutation hooks like `useWalletSend()`,
62
+ `useWalletReceive()`, and `useWalletDeposit()` each expose an action plus
63
+ verb-prefixed state, for example `useWalletSend()` returns
64
+ `{ send, sendPending, sendError, sendData, resetSend }`. `useWalletEngine()` is
65
+ the escape hatch for anything the hooks don't cover.
66
+
67
+ See the [documentation](https://wavelength.lightning.engineering) for the full
68
+ hook reference.
@@ -0,0 +1,274 @@
1
+ import type { Balance, CreateWalletRequest, CreateWalletResult, DepositRequest, DepositResult, Entry, ExitBatchEvent, ExitBatchOptions, ExitBatchResult, ExitRequest, ExitResult, ExitStatusResult, ExitSummaryResult, GetExitPlanRequest, GetExitPlanResult, ListRequest, ListResult, PrepareSendResult, ReceiveRequest, ReceiveResult, RecoveryState, RestoreWalletRequest, RuntimeConfig, RuntimePhase, SendRequest, SendResult, SweepWalletRequest, SweepWalletResult, UnlockWalletRequest, UnlockWalletResult, WavelengthLogPayload, WalletInfo } from "@lightninglabs/wavelength-core";
2
+ /**
3
+ * The application-shell hook: the lifecycle phase to route on, the last fatal
4
+ * runtime error, and the runtime actions. There are no pending flags here:
5
+ * phase === 'starting' / 'stopping' already encode them.
6
+ */
7
+ export declare function useWallet(): {
8
+ phase: RuntimePhase;
9
+ error: Error | null;
10
+ start: (config?: RuntimeConfig) => Promise<WalletInfo>;
11
+ stop: () => Promise<void>;
12
+ };
13
+ /** The most recent complete wallet info, or null before the runtime reports it. */
14
+ export declare function useWalletInfo(): WalletInfo | null;
15
+ /** The most recent wallet balance, or null before it is known. */
16
+ export declare function useWalletBalance(): Balance | null;
17
+ /** The most recent activity entries, newest-first as returned by the daemon. */
18
+ export declare function useWalletActivity(): readonly Entry[];
19
+ /** The background recovery status and its acknowledge action. */
20
+ export declare function useWalletRecovery(): {
21
+ recovery: RecoveryState;
22
+ acknowledge: () => void;
23
+ };
24
+ /** The buffered runtime log tail and a clear action. */
25
+ export declare function useWalletLogs(): {
26
+ logs: readonly WavelengthLogPayload[];
27
+ clear: () => void;
28
+ };
29
+ /** The result of {@link useWalletCreate}. */
30
+ export type UseWalletCreateResult = {
31
+ /** Creates a new wallet. */
32
+ create: (req: CreateWalletRequest) => Promise<CreateWalletResult>;
33
+ /** True while a create is in flight. */
34
+ createPending: boolean;
35
+ /** The last create failure, or null. */
36
+ createError: Error | null;
37
+ /** The last successful create result, or null. */
38
+ createData: CreateWalletResult | null;
39
+ /** Clears the create error and data. */
40
+ resetCreate: () => void;
41
+ };
42
+ /**
43
+ * Creates a new wallet, exposing `createPending` / `createError` /
44
+ * `createData`. This hook and {@link useWalletPasskey} both expose a
45
+ * `create` verb, and destructuring both collides on all four of `create`,
46
+ * `createPending`, `createError`, and `resetCreate`; components composing
47
+ * both should keep one as a namespaced object (e.g.
48
+ * `const passkey = useWalletPasskey(...)`) instead of destructuring both.
49
+ */
50
+ export declare function useWalletCreate(): UseWalletCreateResult;
51
+ /** The result of {@link useWalletRestore}. */
52
+ export type UseWalletRestoreResult = {
53
+ /** Restores a wallet from a mnemonic. */
54
+ restore: (req: RestoreWalletRequest) => Promise<WalletInfo>;
55
+ /** True while a restore is in flight. */
56
+ restorePending: boolean;
57
+ /** The last restore failure, or null. */
58
+ restoreError: Error | null;
59
+ /** The last successful restore result, or null. */
60
+ restoreData: WalletInfo | null;
61
+ /** Clears the restore error and data. */
62
+ resetRestore: () => void;
63
+ };
64
+ /**
65
+ * Restores a wallet from a mnemonic, exposing `restorePending` /
66
+ * `restoreError` / `restoreData`. The promise (and `restorePending`)
67
+ * resolve when the wallet is usable, not when the optional recovery scan
68
+ * finishes; observe the scan through useWalletRecovery.
69
+ */
70
+ export declare function useWalletRestore(): UseWalletRestoreResult;
71
+ /** The result of {@link useWalletUnlock}. */
72
+ export type UseWalletUnlockResult = {
73
+ /** Unlocks an existing wallet. */
74
+ unlock: (req: UnlockWalletRequest) => Promise<UnlockWalletResult>;
75
+ /** True while an unlock is in flight. */
76
+ unlockPending: boolean;
77
+ /** The last unlock failure, or null. */
78
+ unlockError: Error | null;
79
+ /** The last successful unlock result, or null. */
80
+ unlockData: UnlockWalletResult | null;
81
+ /** Clears the unlock error and data. */
82
+ resetUnlock: () => void;
83
+ };
84
+ /** Unlocks an existing wallet, exposing `unlockPending` / `unlockError` / `unlockData`. */
85
+ export declare function useWalletUnlock(): UseWalletUnlockResult;
86
+ /** The result of {@link useWalletDeposit}. */
87
+ export type UseWalletDepositResult = {
88
+ /** Requests an on-chain deposit address. */
89
+ deposit: (req?: DepositRequest) => Promise<DepositResult>;
90
+ /** True while a deposit request is in flight. */
91
+ depositPending: boolean;
92
+ /** The last deposit failure, or null. */
93
+ depositError: Error | null;
94
+ /** The last successful deposit result, or null. */
95
+ depositData: DepositResult | null;
96
+ /** Clears the deposit error and data. */
97
+ resetDeposit: () => void;
98
+ };
99
+ /** Requests an on-chain deposit address, exposing `depositPending` / `depositError` / `depositData`. */
100
+ export declare function useWalletDeposit(): UseWalletDepositResult;
101
+ /** The result of {@link useWalletReceive}. */
102
+ export type UseWalletReceiveResult = {
103
+ /** Requests a Lightning receive. */
104
+ receive: (req: ReceiveRequest) => Promise<ReceiveResult>;
105
+ /** True while a receive is in flight. */
106
+ receivePending: boolean;
107
+ /** The last receive failure, or null. */
108
+ receiveError: Error | null;
109
+ /** The last successful receive result, or null. */
110
+ receiveData: ReceiveResult | null;
111
+ /** Clears the receive error and data. */
112
+ resetReceive: () => void;
113
+ };
114
+ /** Requests a Lightning receive, exposing `receivePending` / `receiveError` / `receiveData`. */
115
+ export declare function useWalletReceive(): UseWalletReceiveResult;
116
+ /** The result of {@link useWalletPrepareSend}. */
117
+ export type UseWalletPrepareSendResult = {
118
+ /** Quotes a payment without dispatching it. */
119
+ prepare: (req: SendRequest) => Promise<PrepareSendResult>;
120
+ /** True while a prepare is in flight. */
121
+ preparePending: boolean;
122
+ /** The last prepare failure, or null. */
123
+ prepareError: Error | null;
124
+ /** The last successful prepare result, or null. */
125
+ prepareData: PrepareSendResult | null;
126
+ /** Clears the prepare error and data. */
127
+ resetPrepare: () => void;
128
+ };
129
+ /**
130
+ * Quotes a payment without dispatching it. `prepareData` holds the latest
131
+ * quote for a review screen; pair with useWalletSend's `sendPrepared` to
132
+ * dispatch.
133
+ */
134
+ export declare function useWalletPrepareSend(): UseWalletPrepareSendResult;
135
+ /** The result of {@link useWalletSend}. */
136
+ export type UseWalletSendResult = {
137
+ /** Dispatches a payment in one shot. */
138
+ send: (req: SendRequest) => Promise<SendResult>;
139
+ /** Dispatches a payment from a quote returned by useWalletPrepareSend. */
140
+ sendPrepared: (prepared: PrepareSendResult) => Promise<SendResult>;
141
+ /** True while a send is in flight. */
142
+ sendPending: boolean;
143
+ /** The last send failure, or null. */
144
+ sendError: Error | null;
145
+ /** The last successful send result, or null. */
146
+ sendData: SendResult | null;
147
+ /** Clears the send error and data. */
148
+ resetSend: () => void;
149
+ };
150
+ /**
151
+ * Dispatches a payment: `send` is the one-shot path, `sendPrepared` confirms
152
+ * a quote from useWalletPrepareSend. The two verbs are alternative dispatch
153
+ * paths for the same payment and share one `sendPending` / `sendError` /
154
+ * `sendData` slot.
155
+ */
156
+ export declare function useWalletSend(): UseWalletSendResult;
157
+ /** The result of {@link useWalletRefresh}. */
158
+ export type UseWalletRefreshResult = {
159
+ /** Re-fetches info, balance, and activity. */
160
+ refresh: () => Promise<void>;
161
+ /** True while a refresh triggered by this hook instance is in flight. */
162
+ refreshPending: boolean;
163
+ /** The last refresh failure, or null. */
164
+ refreshError: Error | null;
165
+ /** Clears the refresh error. */
166
+ resetRefresh: () => void;
167
+ };
168
+ /**
169
+ * Re-fetches info, balance, and activity. `refreshPending` tracks this hook
170
+ * instance's own calls only (what a pull-to-refresh spinner should show);
171
+ * engine-initiated background refreshes never flip it.
172
+ */
173
+ export declare function useWalletRefresh(): UseWalletRefreshResult;
174
+ /** The result of {@link useWalletExit}. */
175
+ export type UseWalletExitResult = {
176
+ /** Starts a single exit (cooperative or unilateral). */
177
+ exit: (req: ExitRequest) => Promise<ExitResult>;
178
+ exitPending: boolean;
179
+ exitError: Error | null;
180
+ exitData: ExitResult | null;
181
+ resetExit: () => void;
182
+ };
183
+ /** Starts a single exit for one outpoint. Takes the full request union. */
184
+ export declare function useWalletExit(): UseWalletExitResult;
185
+ /** The result of {@link useWalletExitPlan}. */
186
+ export type UseWalletExitPlanResult = {
187
+ /** Previews unilateral-exit readiness and funding for a set of outpoints. */
188
+ plan: (req: GetExitPlanRequest) => Promise<GetExitPlanResult>;
189
+ planPending: boolean;
190
+ planError: Error | null;
191
+ planData: GetExitPlanResult | null;
192
+ resetPlan: () => void;
193
+ };
194
+ /** Previews unilateral-exit readiness. Pair with useWalletExitBatch to start. */
195
+ export declare function useWalletExitPlan(): UseWalletExitPlanResult;
196
+ /** The result of {@link useWalletList}. */
197
+ export type UseWalletListResult = {
198
+ /** Lists wallet activity, VTXOs, or on-chain outputs. */
199
+ list: (req: ListRequest) => Promise<ListResult>;
200
+ listPending: boolean;
201
+ listError: Error | null;
202
+ listData: ListResult | null;
203
+ resetList: () => void;
204
+ };
205
+ /** Lists wallet data on demand (e.g. VTXOs for an exit picker). */
206
+ export declare function useWalletList(): UseWalletListResult;
207
+ /** The result of {@link useWalletExitBatch}. */
208
+ export type UseWalletExitBatchResult = {
209
+ /**
210
+ * Starts a batch of exits. Resolves once every exit has STARTED, not
211
+ * completed: a unilateral exit runs for hours or days afterward.
212
+ */
213
+ exitBatch: (opts: ExitBatchOptions) => Promise<ExitBatchResult>;
214
+ exitBatchPending: boolean;
215
+ exitBatchError: Error | null;
216
+ exitBatchData: ExitBatchResult | null;
217
+ /** The batch's progress events, in order, for the current or last run. */
218
+ exitBatchEvents: readonly ExitBatchEvent[];
219
+ resetExitBatch: () => void;
220
+ };
221
+ /**
222
+ * Orchestrates a multi-outpoint exit with funding-contention guards. Guards
223
+ * against re-entrancy: calling `exitBatch` again while a run is already in
224
+ * flight returns the same in-flight promise instead of starting a second
225
+ * concurrent run (which would otherwise reset the shared event log out from
226
+ * under the first run).
227
+ */
228
+ export declare function useWalletExitBatch(): UseWalletExitBatchResult;
229
+ /** The result of {@link useWalletExits}. */
230
+ export type UseWalletExitsResult = {
231
+ /** The wallet-wide in-progress exit portfolio, or null before first load. */
232
+ summary: ExitSummaryResult | null;
233
+ summaryPending: boolean;
234
+ summaryError: Error | null;
235
+ /** Refetches the summary on demand. */
236
+ refreshSummary: () => Promise<ExitSummaryResult>;
237
+ };
238
+ /**
239
+ * Reads the in-progress exit portfolio. Fetches on mount and whenever wallet
240
+ * activity changes (so a completed exit clears without manual refresh).
241
+ */
242
+ export declare function useWalletExits(): UseWalletExitsResult;
243
+ /** The result of {@link useWalletExitStatus}. */
244
+ export type UseWalletExitStatusResult = {
245
+ /** The exit's status, or null before first load. */
246
+ status: ExitStatusResult | null;
247
+ statusPending: boolean;
248
+ statusError: Error | null;
249
+ /** Refetches the status on demand. */
250
+ refreshStatus: () => Promise<ExitStatusResult>;
251
+ };
252
+ /**
253
+ * Reads one exit's status. Defaults to the cheap phase-only call; pass
254
+ * `{ detailed: true }` for tree progress, CSV countdown, and fees (a live
255
+ * round-trip). Pass `{ pollMs }` to poll while the hook is mounted (a plain
256
+ * `setInterval` with no visibility/focus gating; polling stops on unmount).
257
+ * Fetches on mount and whenever `outpoint` or the options change.
258
+ */
259
+ export declare function useWalletExitStatus(outpoint: string, opts?: {
260
+ detailed?: boolean;
261
+ pollMs?: number;
262
+ }): UseWalletExitStatusResult;
263
+ /** The result of {@link useWalletSweep}. */
264
+ export type UseWalletSweepResult = {
265
+ /** Previews (broadcast:false) or broadcasts (broadcast:true) a backing-wallet sweep to an address. */
266
+ sweep: (req: SweepWalletRequest) => Promise<SweepWalletResult>;
267
+ sweepPending: boolean;
268
+ sweepError: Error | null;
269
+ sweepData: SweepWalletResult | null;
270
+ resetSweep: () => void;
271
+ };
272
+ /** Previews or broadcasts a sweep of the backing on-chain wallet. */
273
+ export declare function useWalletSweep(): UseWalletSweepResult;
274
+ //# sourceMappingURL=hooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"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"}
package/dist/hooks.js ADDED
@@ -0,0 +1,310 @@
1
+ import { useCallback, useEffect, useRef, useState } from "react";
2
+ import { useWalletEngine } from "./provider.js";
3
+ import { useWalletMutationState } from "./useWalletMutation.js";
4
+ import { useWalletSelector } from "./useWalletSelector.js";
5
+ /**
6
+ * The application-shell hook: the lifecycle phase to route on, the last fatal
7
+ * runtime error, and the runtime actions. There are no pending flags here:
8
+ * phase === 'starting' / 'stopping' already encode them.
9
+ */
10
+ export function useWallet() {
11
+ const engine = useWalletEngine();
12
+ const phase = useWalletSelector((s) => s.phase);
13
+ const error = useWalletSelector((s) => s.error);
14
+ const start = useCallback((config) => engine.start(config), [engine]);
15
+ const stop = useCallback(() => engine.stop(), [engine]);
16
+ return { phase, error, start, stop };
17
+ }
18
+ /** The most recent complete wallet info, or null before the runtime reports it. */
19
+ export function useWalletInfo() {
20
+ return useWalletSelector((s) => s.info);
21
+ }
22
+ /** The most recent wallet balance, or null before it is known. */
23
+ export function useWalletBalance() {
24
+ return useWalletSelector((s) => s.balance);
25
+ }
26
+ /** The most recent activity entries, newest-first as returned by the daemon. */
27
+ export function useWalletActivity() {
28
+ return useWalletSelector((s) => s.activity);
29
+ }
30
+ /** The background recovery status and its acknowledge action. */
31
+ export function useWalletRecovery() {
32
+ const engine = useWalletEngine();
33
+ const recovery = useWalletSelector((s) => s.recovery);
34
+ const acknowledge = useCallback(() => engine.acknowledgeRecovery(), [engine]);
35
+ return { recovery, acknowledge };
36
+ }
37
+ /** The buffered runtime log tail and a clear action. */
38
+ export function useWalletLogs() {
39
+ const engine = useWalletEngine();
40
+ const logs = useWalletSelector((s) => s.logs);
41
+ const clear = useCallback(() => engine.clearLogs(), [engine]);
42
+ return { logs, clear };
43
+ }
44
+ /**
45
+ * Creates a new wallet, exposing `createPending` / `createError` /
46
+ * `createData`. This hook and {@link useWalletPasskey} both expose a
47
+ * `create` verb, and destructuring both collides on all four of `create`,
48
+ * `createPending`, `createError`, and `resetCreate`; components composing
49
+ * both should keep one as a namespaced object (e.g.
50
+ * `const passkey = useWalletPasskey(...)`) instead of destructuring both.
51
+ */
52
+ export function useWalletCreate() {
53
+ const engine = useWalletEngine();
54
+ const m = useWalletMutationState();
55
+ const create = useCallback((req) => m.track(() => engine.createWallet(req)), [engine, m.track]);
56
+ return {
57
+ create,
58
+ createPending: m.pending,
59
+ createError: m.error,
60
+ createData: m.data,
61
+ resetCreate: m.reset,
62
+ };
63
+ }
64
+ /**
65
+ * Restores a wallet from a mnemonic, exposing `restorePending` /
66
+ * `restoreError` / `restoreData`. The promise (and `restorePending`)
67
+ * resolve when the wallet is usable, not when the optional recovery scan
68
+ * finishes; observe the scan through useWalletRecovery.
69
+ */
70
+ export function useWalletRestore() {
71
+ const engine = useWalletEngine();
72
+ const m = useWalletMutationState();
73
+ const restore = useCallback((req) => m.track(() => engine.restoreWallet(req)), [engine, m.track]);
74
+ return {
75
+ restore,
76
+ restorePending: m.pending,
77
+ restoreError: m.error,
78
+ restoreData: m.data,
79
+ resetRestore: m.reset,
80
+ };
81
+ }
82
+ /** Unlocks an existing wallet, exposing `unlockPending` / `unlockError` / `unlockData`. */
83
+ export function useWalletUnlock() {
84
+ const engine = useWalletEngine();
85
+ const m = useWalletMutationState();
86
+ const unlock = useCallback((req) => m.track(() => engine.unlockWallet(req)), [engine, m.track]);
87
+ return {
88
+ unlock,
89
+ unlockPending: m.pending,
90
+ unlockError: m.error,
91
+ unlockData: m.data,
92
+ resetUnlock: m.reset,
93
+ };
94
+ }
95
+ /** Requests an on-chain deposit address, exposing `depositPending` / `depositError` / `depositData`. */
96
+ export function useWalletDeposit() {
97
+ const engine = useWalletEngine();
98
+ const m = useWalletMutationState();
99
+ const deposit = useCallback((req) => m.track(() => engine.deposit(req)), [engine, m.track]);
100
+ return {
101
+ deposit,
102
+ depositPending: m.pending,
103
+ depositError: m.error,
104
+ depositData: m.data,
105
+ resetDeposit: m.reset,
106
+ };
107
+ }
108
+ /** Requests a Lightning receive, exposing `receivePending` / `receiveError` / `receiveData`. */
109
+ export function useWalletReceive() {
110
+ const engine = useWalletEngine();
111
+ const m = useWalletMutationState();
112
+ const receive = useCallback((req) => m.track(() => engine.receive(req)), [engine, m.track]);
113
+ return {
114
+ receive,
115
+ receivePending: m.pending,
116
+ receiveError: m.error,
117
+ receiveData: m.data,
118
+ resetReceive: m.reset,
119
+ };
120
+ }
121
+ /**
122
+ * Quotes a payment without dispatching it. `prepareData` holds the latest
123
+ * quote for a review screen; pair with useWalletSend's `sendPrepared` to
124
+ * dispatch.
125
+ */
126
+ export function useWalletPrepareSend() {
127
+ const engine = useWalletEngine();
128
+ const m = useWalletMutationState();
129
+ const prepare = useCallback((req) => m.track(() => engine.prepareSend(req)), [engine, m.track]);
130
+ return {
131
+ prepare,
132
+ preparePending: m.pending,
133
+ prepareError: m.error,
134
+ prepareData: m.data,
135
+ resetPrepare: m.reset,
136
+ };
137
+ }
138
+ /**
139
+ * Dispatches a payment: `send` is the one-shot path, `sendPrepared` confirms
140
+ * a quote from useWalletPrepareSend. The two verbs are alternative dispatch
141
+ * paths for the same payment and share one `sendPending` / `sendError` /
142
+ * `sendData` slot.
143
+ */
144
+ export function useWalletSend() {
145
+ const engine = useWalletEngine();
146
+ const m = useWalletMutationState();
147
+ const send = useCallback((req) => m.track(() => engine.send(req)), [engine, m.track]);
148
+ const sendPrepared = useCallback((prepared) => m.track(() => engine.sendPrepared(prepared)), [engine, m.track]);
149
+ return {
150
+ send,
151
+ sendPrepared,
152
+ sendPending: m.pending,
153
+ sendError: m.error,
154
+ sendData: m.data,
155
+ resetSend: m.reset,
156
+ };
157
+ }
158
+ /**
159
+ * Re-fetches info, balance, and activity. `refreshPending` tracks this hook
160
+ * instance's own calls only (what a pull-to-refresh spinner should show);
161
+ * engine-initiated background refreshes never flip it.
162
+ */
163
+ export function useWalletRefresh() {
164
+ const engine = useWalletEngine();
165
+ const m = useWalletMutationState();
166
+ const refresh = useCallback(() => m.track(() => engine.refresh()), [engine, m.track]);
167
+ return {
168
+ refresh,
169
+ refreshPending: m.pending,
170
+ refreshError: m.error,
171
+ resetRefresh: m.reset,
172
+ };
173
+ }
174
+ /** Starts a single exit for one outpoint. Takes the full request union. */
175
+ export function useWalletExit() {
176
+ const engine = useWalletEngine();
177
+ const m = useWalletMutationState();
178
+ const exit = useCallback((req) => m.track(() => engine.exit(req)), [engine, m.track]);
179
+ return {
180
+ exit,
181
+ exitPending: m.pending,
182
+ exitError: m.error,
183
+ exitData: m.data,
184
+ resetExit: m.reset,
185
+ };
186
+ }
187
+ /** Previews unilateral-exit readiness. Pair with useWalletExitBatch to start. */
188
+ export function useWalletExitPlan() {
189
+ const engine = useWalletEngine();
190
+ const m = useWalletMutationState();
191
+ const plan = useCallback((req) => m.track(() => engine.getExitPlan(req)), [engine, m.track]);
192
+ return {
193
+ plan,
194
+ planPending: m.pending,
195
+ planError: m.error,
196
+ planData: m.data,
197
+ resetPlan: m.reset,
198
+ };
199
+ }
200
+ /** Lists wallet data on demand (e.g. VTXOs for an exit picker). */
201
+ export function useWalletList() {
202
+ const engine = useWalletEngine();
203
+ const m = useWalletMutationState({ keepPreviousData: true });
204
+ const list = useCallback((req) => m.track(() => engine.list(req)), [engine, m.track]);
205
+ return {
206
+ list,
207
+ listPending: m.pending,
208
+ listError: m.error,
209
+ listData: m.data,
210
+ resetList: m.reset,
211
+ };
212
+ }
213
+ /**
214
+ * Orchestrates a multi-outpoint exit with funding-contention guards. Guards
215
+ * against re-entrancy: calling `exitBatch` again while a run is already in
216
+ * flight returns the same in-flight promise instead of starting a second
217
+ * concurrent run (which would otherwise reset the shared event log out from
218
+ * under the first run).
219
+ */
220
+ export function useWalletExitBatch() {
221
+ const engine = useWalletEngine();
222
+ const m = useWalletMutationState();
223
+ const [events, setEvents] = useState([]);
224
+ const inFlight = useRef(null);
225
+ const exitBatch = useCallback((opts) => {
226
+ if (inFlight.current)
227
+ return inFlight.current;
228
+ setEvents([]);
229
+ const p = m.track(() => engine.exitBatch({
230
+ ...opts,
231
+ onEvent: (event) => setEvents((prev) => [...prev, event]),
232
+ }));
233
+ inFlight.current = p;
234
+ // Clear on settle (both branches) so we never leave a stale in-flight
235
+ // promise, and never surface an unhandled rejection here.
236
+ void p.then(() => { inFlight.current = null; }, () => { inFlight.current = null; });
237
+ return p;
238
+ }, [engine, m.track]);
239
+ const resetExitBatch = useCallback(() => {
240
+ setEvents([]);
241
+ m.reset();
242
+ }, [m.reset]);
243
+ return {
244
+ exitBatch,
245
+ exitBatchPending: m.pending,
246
+ exitBatchError: m.error,
247
+ exitBatchData: m.data,
248
+ exitBatchEvents: events,
249
+ resetExitBatch,
250
+ };
251
+ }
252
+ /**
253
+ * Reads the in-progress exit portfolio. Fetches on mount and whenever wallet
254
+ * activity changes (so a completed exit clears without manual refresh).
255
+ */
256
+ export function useWalletExits() {
257
+ const engine = useWalletEngine();
258
+ const m = useWalletMutationState({ keepPreviousData: true });
259
+ const activity = useWalletSelector((s) => s.activity);
260
+ const refreshSummary = useCallback(() => m.track(() => engine.exitSummary()), [engine, m.track]);
261
+ useEffect(() => {
262
+ void refreshSummary();
263
+ // Refetch when the activity slice changes reference (a stream push).
264
+ }, [refreshSummary, activity]);
265
+ return {
266
+ summary: m.data,
267
+ summaryPending: m.pending,
268
+ summaryError: m.error,
269
+ refreshSummary,
270
+ };
271
+ }
272
+ /**
273
+ * Reads one exit's status. Defaults to the cheap phase-only call; pass
274
+ * `{ detailed: true }` for tree progress, CSV countdown, and fees (a live
275
+ * round-trip). Pass `{ pollMs }` to poll while the hook is mounted (a plain
276
+ * `setInterval` with no visibility/focus gating; polling stops on unmount).
277
+ * Fetches on mount and whenever `outpoint` or the options change.
278
+ */
279
+ export function useWalletExitStatus(outpoint, opts = {}) {
280
+ const engine = useWalletEngine();
281
+ const m = useWalletMutationState({ keepPreviousData: true });
282
+ const { detailed, pollMs } = opts;
283
+ const refreshStatus = useCallback(() => m.track(() => engine.exitStatus({ outpoint, detailed })), [engine, m.track, outpoint, detailed]);
284
+ useEffect(() => {
285
+ void refreshStatus();
286
+ if (!pollMs)
287
+ return;
288
+ const id = setInterval(() => void refreshStatus(), pollMs);
289
+ return () => clearInterval(id);
290
+ }, [refreshStatus, pollMs]);
291
+ return {
292
+ status: m.data,
293
+ statusPending: m.pending,
294
+ statusError: m.error,
295
+ refreshStatus,
296
+ };
297
+ }
298
+ /** Previews or broadcasts a sweep of the backing on-chain wallet. */
299
+ export function useWalletSweep() {
300
+ const engine = useWalletEngine();
301
+ const m = useWalletMutationState();
302
+ const sweep = useCallback((req) => m.track(() => engine.sweepWallet(req)), [engine, m.track]);
303
+ return {
304
+ sweep,
305
+ sweepPending: m.pending,
306
+ sweepError: m.error,
307
+ sweepData: m.data,
308
+ resetSweep: m.reset,
309
+ };
310
+ }
@@ -0,0 +1,6 @@
1
+ export * from "@lightninglabs/wavelength-core";
2
+ export { WavelengthProvider, useWalletEngine } from "./provider.tsx";
3
+ export * from "./hooks.ts";
4
+ export { useWalletPasskey } from "./useWalletPasskey.ts";
5
+ export type { PasskeyWalletOutcome } from "./useWalletPasskey.ts";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAKA,cAAc,gCAAgC,CAAC;AAG/C,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGrE,cAAc,YAAY,CAAC;AAG3B,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,YAAY,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,12 @@
1
+ // Re-export the core contract so a React host can import every type and enum
2
+ // from this one package. Transports are NOT re-exported: create an engine
3
+ // with createWebWalletEngine (wavelength-web) or createNativeWalletEngine
4
+ // (wavelength-react-native) and pass it to WavelengthProvider. Keeping this
5
+ // binding transport-agnostic is what lets it run over web or React Native.
6
+ export * from "@lightninglabs/wavelength-core";
7
+ // The provider and the engine escape hatch.
8
+ export { WavelengthProvider, useWalletEngine } from "./provider.js";
9
+ // The granular state and mutation hooks.
10
+ export * from "./hooks.js";
11
+ // The passkey hook and its outcome type.
12
+ export { useWalletPasskey } from "./useWalletPasskey.js";
@@ -0,0 +1,22 @@
1
+ import type { WalletEngine } from "@lightninglabs/wavelength-core";
2
+ import { ReactNode } from "react";
3
+ /**
4
+ * Provides a WalletEngine to descendants. The provider owns nothing: the
5
+ * consumer creates the engine (typically once, at module scope, via
6
+ * createWebWalletEngine or createNativeWalletEngine) and owns its lifetime.
7
+ */
8
+ export declare function WavelengthProvider({ children, engine, }: {
9
+ /** The subtree that gains access to the wallet engine. */
10
+ children: ReactNode;
11
+ /**
12
+ * A WalletEngine from any transport, e.g. createWebWalletEngine() from
13
+ * \@lightninglabs/wavelength-web.
14
+ */
15
+ engine: WalletEngine;
16
+ }): import("react").JSX.Element;
17
+ /**
18
+ * Returns the engine from the nearest WavelengthProvider: the escape hatch for
19
+ * anything the granular hooks do not cover. Throws outside a provider.
20
+ */
21
+ export declare function useWalletEngine(): WalletEngine;
22
+ //# sourceMappingURL=provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,SAAS,EAA6B,MAAM,OAAO,CAAC;AAI7D;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,QAAQ,EACR,MAAM,GACP,EAAE;IACD,0DAA0D;IAC1D,QAAQ,EAAE,SAAS,CAAC;IACpB;;;OAGG;IACH,MAAM,EAAE,YAAY,CAAC;CACtB,+BAcA;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI,YAAY,CAO9C"}
@@ -0,0 +1,27 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { createContext, useContext } from "react";
3
+ const WalletEngineContext = createContext(null);
4
+ /**
5
+ * Provides a WalletEngine to descendants. The provider owns nothing: the
6
+ * consumer creates the engine (typically once, at module scope, via
7
+ * createWebWalletEngine or createNativeWalletEngine) and owns its lifetime.
8
+ */
9
+ export function WavelengthProvider({ children, engine, }) {
10
+ if (!engine) {
11
+ throw new Error("WavelengthProvider requires an `engine` prop. Create one with " +
12
+ "createWebWalletEngine() from @lightninglabs/wavelength-web (or " +
13
+ "createNativeWalletEngine() from @lightninglabs/wavelength-react-native).");
14
+ }
15
+ return (_jsx(WalletEngineContext.Provider, { value: engine, children: children }));
16
+ }
17
+ /**
18
+ * Returns the engine from the nearest WavelengthProvider: the escape hatch for
19
+ * anything the granular hooks do not cover. Throws outside a provider.
20
+ */
21
+ export function useWalletEngine() {
22
+ const engine = useContext(WalletEngineContext);
23
+ if (!engine) {
24
+ throw new Error("useWalletEngine must be used inside WavelengthProvider");
25
+ }
26
+ return engine;
27
+ }
@@ -0,0 +1,38 @@
1
+ import type { OpenWalletFromPasskeyResult, PasskeyCeremony } from "@lightninglabs/walletdk-core";
2
+ /**
3
+ * Pairs the Go-side open result with the credential id that was used, so the app
4
+ * can persist it and scope future unlocks.
5
+ */
6
+ export type PasskeyWalletOutcome = {
7
+ /** The result returned by opening the wallet from the passkey. */
8
+ result: OpenWalletFromPasskeyResult;
9
+ /** The credential id used in the ceremony, for persistence and scoping. */
10
+ credentialId: string;
11
+ };
12
+ /** The state and actions returned by {@link usePasskeyWallet}. */
13
+ export type UsePasskeyWallet = {
14
+ /** Whether the environment supports passkey PRF. */
15
+ supported: boolean;
16
+ /** True while a ceremony is in flight. */
17
+ busy: boolean;
18
+ /** The last error message, or "" when there is none. */
19
+ error: string;
20
+ /** Registers a passkey and creates the wallet from it. */
21
+ createPasskeyWallet: (appName: string) => Promise<PasskeyWalletOutcome | null>;
22
+ /**
23
+ * Asserts a passkey (scoped when allowCredentialId is set, discoverable
24
+ * otherwise) and imports/unlocks the wallet.
25
+ */
26
+ openPasskeyWallet: (allowCredentialId?: string) => Promise<PasskeyWalletOutcome | null>;
27
+ /** Clears the current error message. */
28
+ clearError: () => void;
29
+ };
30
+ /**
31
+ * Drives a passkey ceremony and opens the wallet through the provider's client,
32
+ * refreshing provider state on success so the phase advances automatically. The
33
+ * ceremony is injected (browser: webPasskeyCeremony from walletdk-web; native
34
+ * transports supply their own), which keeps walletdk-react free of any transport
35
+ * dependency. Must be used inside a {@link WalletDKProvider}.
36
+ */
37
+ export declare function usePasskeyWallet(ceremony: PasskeyCeremony): UsePasskeyWallet;
38
+ //# sourceMappingURL=usePasskeyWallet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usePasskeyWallet.d.ts","sourceRoot":"","sources":["../src/usePasskeyWallet.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,2BAA2B,EAC3B,eAAe,EAChB,MAAM,8BAA8B,CAAC;AAGtC;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,kEAAkE;IAClE,MAAM,EAAE,2BAA2B,CAAC;IACpC,2EAA2E;IAC3E,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,kEAAkE;AAClE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,oDAAoD;IACpD,SAAS,EAAE,OAAO,CAAC;IACnB,0CAA0C;IAC1C,IAAI,EAAE,OAAO,CAAC;IACd,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,mBAAmB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;IAC/E;;;OAGG;IACH,iBAAiB,EAAE,CACjB,iBAAiB,CAAC,EAAE,MAAM,KACvB,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;IAC1C,wCAAwC;IACxC,UAAU,EAAE,MAAM,IAAI,CAAC;CACxB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,eAAe,GAAG,gBAAgB,CAyE5E"}
@@ -0,0 +1,65 @@
1
+ import { useCallback, useEffect, useState } from "react";
2
+ import { useWalletDK } from "./provider";
3
+ /**
4
+ * Drives a passkey ceremony and opens the wallet through the provider's client,
5
+ * refreshing provider state on success so the phase advances automatically. The
6
+ * ceremony is injected (browser: webPasskeyCeremony from walletdk-web; native
7
+ * transports supply their own), which keeps walletdk-react free of any transport
8
+ * dependency. Must be used inside a {@link WalletDKProvider}.
9
+ */
10
+ export function usePasskeyWallet(ceremony) {
11
+ const { client, refresh } = useWalletDK();
12
+ const [supported, setSupported] = useState(false);
13
+ const [busy, setBusy] = useState(false);
14
+ const [error, setError] = useState("");
15
+ useEffect(() => {
16
+ let cancelled = false;
17
+ ceremony.supportsPasskeyPrf().then((v) => {
18
+ if (!cancelled)
19
+ setSupported(v);
20
+ }, () => {
21
+ // An injected ceremony whose probe rejects degrades to unsupported
22
+ // rather than leaving an unhandled rejection.
23
+ if (!cancelled)
24
+ setSupported(false);
25
+ });
26
+ return () => {
27
+ cancelled = true;
28
+ };
29
+ }, [ceremony]);
30
+ const run = useCallback(async (fn) => {
31
+ setError("");
32
+ setBusy(true);
33
+ try {
34
+ return await fn();
35
+ }
36
+ catch (err) {
37
+ setError(err instanceof Error ? err.message : String(err));
38
+ return null;
39
+ }
40
+ finally {
41
+ setBusy(false);
42
+ }
43
+ }, []);
44
+ const createPasskeyWallet = useCallback((appName) => run(async () => {
45
+ const { prfOutput, credentialId } = await ceremony.registerPasskeyWallet(appName);
46
+ const result = await client.openWalletFromPasskey({ prfOutput });
47
+ await refresh().catch(() => undefined);
48
+ return { result, credentialId };
49
+ }), [run, client, refresh, ceremony]);
50
+ const openPasskeyWallet = useCallback((allowCredentialId) => run(async () => {
51
+ const { prfOutput, credentialId } = await ceremony.assertPasskeyPrf(allowCredentialId);
52
+ const result = await client.openWalletFromPasskey({ prfOutput });
53
+ await refresh().catch(() => undefined);
54
+ return { result, credentialId };
55
+ }), [run, client, refresh, ceremony]);
56
+ const clearError = useCallback(() => setError(""), []);
57
+ return {
58
+ supported,
59
+ busy,
60
+ error,
61
+ createPasskeyWallet,
62
+ openPasskeyWallet,
63
+ clearError,
64
+ };
65
+ }
@@ -0,0 +1,41 @@
1
+ type MutationState<R> = {
2
+ pending: boolean;
3
+ error: Error | null;
4
+ data: R | null;
5
+ };
6
+ /**
7
+ * Hook-local mutation state shared by every mutation hook: `track` runs one
8
+ * async operation, clearing the previous error and data up front, capturing a failure
9
+ * into `error`, and rethrowing the same Error instance so imperative callers
10
+ * can await/catch (throw-and-capture). A cancelled passkey ceremony rethrows
11
+ * without being recorded: a dismissed OS prompt is not a failure to display.
12
+ * `isPasskeyCancelled` (rather than a bare `instanceof`) is used because a
13
+ * consumer bundle can end up with a duplicate copy of core (e.g. two resolved
14
+ * package versions), which breaks `instanceof` across the boundary; the
15
+ * predicate falls back to matching `err.name` for that case.
16
+ *
17
+ * Overlapping `track` calls are resolved by call order, not settlement order:
18
+ * each call is stamped with a monotonically increasing generation, and only
19
+ * the latest call is allowed to write state. An older call that settles
20
+ * after a newer one still rethrows to its own caller; it just cannot clobber
21
+ * the newer call's `pending: true` or its result.
22
+ *
23
+ * By default, a new call blanks `data` back to null the moment it starts:
24
+ * right for a mutation, where a fresh submit should not keep showing the
25
+ * previous result while it is in flight. Pass `{ keepPreviousData: true }`
26
+ * for a polling read hook instead, where the same call shape is reused to
27
+ * refetch: blanking `data` on every refetch would flicker a rendered result
28
+ * to null on each poll. With the option set, `track` preserves the existing
29
+ * `data` while `pending` flips true, and keeps preserving it if the call
30
+ * errors: a transient poll failure surfaces through `error` without blanking
31
+ * a still-valid last-good result. `data` is only overwritten once a new
32
+ * result lands.
33
+ */
34
+ export declare function useWalletMutationState<R>(opts?: {
35
+ keepPreviousData?: boolean;
36
+ }): {
37
+ track: (operation: () => Promise<R>) => Promise<R>;
38
+ reset: () => void;
39
+ } & MutationState<R>;
40
+ export {};
41
+ //# sourceMappingURL=useWalletMutation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useWalletMutation.d.ts","sourceRoot":"","sources":["../src/useWalletMutation.ts"],"names":[],"mappings":"AAGA,KAAK,aAAa,CAAC,CAAC,IAAI;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;CAChB,CAAC;AAIF;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE;IAC/C,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,GAAG;IACF,KAAK,EAAE,CAAC,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IACnD,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,GAAG,aAAa,CAAC,CAAC,CAAC,CA4CnB"}
@@ -0,0 +1,75 @@
1
+ import { isPasskeyCancelled, toError } from "@lightninglabs/wavelength-core";
2
+ import { useCallback, useRef, useState } from "react";
3
+ const IDLE = { pending: false, error: null, data: null };
4
+ /**
5
+ * Hook-local mutation state shared by every mutation hook: `track` runs one
6
+ * async operation, clearing the previous error and data up front, capturing a failure
7
+ * into `error`, and rethrowing the same Error instance so imperative callers
8
+ * can await/catch (throw-and-capture). A cancelled passkey ceremony rethrows
9
+ * without being recorded: a dismissed OS prompt is not a failure to display.
10
+ * `isPasskeyCancelled` (rather than a bare `instanceof`) is used because a
11
+ * consumer bundle can end up with a duplicate copy of core (e.g. two resolved
12
+ * package versions), which breaks `instanceof` across the boundary; the
13
+ * predicate falls back to matching `err.name` for that case.
14
+ *
15
+ * Overlapping `track` calls are resolved by call order, not settlement order:
16
+ * each call is stamped with a monotonically increasing generation, and only
17
+ * the latest call is allowed to write state. An older call that settles
18
+ * after a newer one still rethrows to its own caller; it just cannot clobber
19
+ * the newer call's `pending: true` or its result.
20
+ *
21
+ * By default, a new call blanks `data` back to null the moment it starts:
22
+ * right for a mutation, where a fresh submit should not keep showing the
23
+ * previous result while it is in flight. Pass `{ keepPreviousData: true }`
24
+ * for a polling read hook instead, where the same call shape is reused to
25
+ * refetch: blanking `data` on every refetch would flicker a rendered result
26
+ * to null on each poll. With the option set, `track` preserves the existing
27
+ * `data` while `pending` flips true, and keeps preserving it if the call
28
+ * errors: a transient poll failure surfaces through `error` without blanking
29
+ * a still-valid last-good result. `data` is only overwritten once a new
30
+ * result lands.
31
+ */
32
+ export function useWalletMutationState(opts) {
33
+ const [state, setState] = useState(IDLE);
34
+ const generationRef = useRef(0);
35
+ const keepPreviousData = opts?.keepPreviousData ?? false;
36
+ const track = useCallback(async (operation) => {
37
+ const generation = ++generationRef.current;
38
+ if (keepPreviousData) {
39
+ setState((s) => ({ ...s, pending: true, error: null }));
40
+ }
41
+ else {
42
+ setState({ pending: true, error: null, data: null });
43
+ }
44
+ try {
45
+ const data = await operation();
46
+ if (generation === generationRef.current) {
47
+ setState({ pending: false, error: null, data });
48
+ }
49
+ return data;
50
+ }
51
+ catch (err) {
52
+ if (isPasskeyCancelled(err)) {
53
+ if (generation === generationRef.current) {
54
+ setState(IDLE);
55
+ }
56
+ throw err;
57
+ }
58
+ const error = toError(err);
59
+ if (generation === generationRef.current) {
60
+ if (keepPreviousData) {
61
+ setState((s) => ({ ...s, pending: false, error }));
62
+ }
63
+ else {
64
+ setState({ pending: false, error, data: null });
65
+ }
66
+ }
67
+ throw error;
68
+ }
69
+ }, [keepPreviousData]);
70
+ const reset = useCallback(() => {
71
+ generationRef.current += 1;
72
+ setState(IDLE);
73
+ }, []);
74
+ return { track, reset, ...state };
75
+ }
@@ -0,0 +1,43 @@
1
+ import type { OpenWalletFromPasskeyResult, PasskeyCeremony } from "@lightninglabs/wavelength-core";
2
+ /**
3
+ * Pairs the daemon-side open result with the credential id that was used, so
4
+ * the app can persist it and scope future unlocks.
5
+ */
6
+ export type PasskeyWalletOutcome = {
7
+ /** The result returned by opening the wallet from the passkey. */
8
+ result: OpenWalletFromPasskeyResult;
9
+ /** The credential id used in the ceremony, for persistence and scoping. */
10
+ credentialId: string;
11
+ };
12
+ /**
13
+ * Drives a passkey ceremony and opens the wallet through the engine, which
14
+ * refetches info and refreshes in the background so the phase advances
15
+ * automatically. The ceremony is injected (browser: webPasskeyCeremony from
16
+ * wavelength-web; native transports supply their own), which keeps
17
+ * wavelength-react transport-free.
18
+ * Creation and opening track separately because apps render them on different
19
+ * screens. A cancelled ceremony (PasskeyCancelledError) rejects but is never
20
+ * recorded into createError/openError. Must be used inside WavelengthProvider.
21
+ */
22
+ export declare function useWalletPasskey(ceremony: PasskeyCeremony): {
23
+ /**
24
+ * Whether the environment supports passkey PRF. Null while the support
25
+ * probe is in flight; render a brief loading state rather than assuming
26
+ * either answer.
27
+ */
28
+ supported: boolean | null;
29
+ /** Registers a passkey and creates the wallet from it. */
30
+ create: (appName: string) => Promise<PasskeyWalletOutcome>;
31
+ createPending: boolean;
32
+ createError: Error | null;
33
+ resetCreate: () => void;
34
+ /**
35
+ * Asserts a passkey (scoped when credentialId is set, discoverable
36
+ * otherwise) and imports/unlocks the wallet.
37
+ */
38
+ open: (credentialId?: string) => Promise<PasskeyWalletOutcome>;
39
+ openPending: boolean;
40
+ openError: Error | null;
41
+ resetOpen: () => void;
42
+ };
43
+ //# sourceMappingURL=useWalletPasskey.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useWalletPasskey.d.ts","sourceRoot":"","sources":["../src/useWalletPasskey.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,2BAA2B,EAC3B,eAAe,EAChB,MAAM,gCAAgC,CAAC;AAKxC;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,kEAAkE;IAClE,MAAM,EAAE,2BAA2B,CAAC;IACpC,2EAA2E;IAC3E,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,eAAe,GAAG;IAC3D;;;;OAIG;IACH,SAAS,EAAE,OAAO,GAAG,IAAI,CAAC;IAC1B,0DAA0D;IAC1D,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAC3D,aAAa,EAAE,OAAO,CAAC;IACvB,WAAW,EAAE,KAAK,GAAG,IAAI,CAAC;IAC1B,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB;;;OAGG;IACH,IAAI,EAAE,CAAC,YAAY,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAC/D,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,EAAE,KAAK,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,IAAI,CAAC;CACvB,CAiEA"}
@@ -0,0 +1,57 @@
1
+ import { useCallback, useEffect, useState } from "react";
2
+ import { useWalletEngine } from "./provider.js";
3
+ import { useWalletMutationState } from "./useWalletMutation.js";
4
+ /**
5
+ * Drives a passkey ceremony and opens the wallet through the engine, which
6
+ * refetches info and refreshes in the background so the phase advances
7
+ * automatically. The ceremony is injected (browser: webPasskeyCeremony from
8
+ * wavelength-web; native transports supply their own), which keeps
9
+ * wavelength-react transport-free.
10
+ * Creation and opening track separately because apps render them on different
11
+ * screens. A cancelled ceremony (PasskeyCancelledError) rejects but is never
12
+ * recorded into createError/openError. Must be used inside WavelengthProvider.
13
+ */
14
+ export function useWalletPasskey(ceremony) {
15
+ const engine = useWalletEngine();
16
+ const [supported, setSupported] = useState(null);
17
+ const createM = useWalletMutationState();
18
+ const openM = useWalletMutationState();
19
+ useEffect(() => {
20
+ let cancelled = false;
21
+ ceremony.supportsPasskeyPrf().then((v) => {
22
+ if (!cancelled)
23
+ setSupported(v);
24
+ }, () => {
25
+ // An injected ceremony whose probe rejects degrades to unsupported
26
+ // rather than leaving an unhandled rejection.
27
+ if (!cancelled)
28
+ setSupported(false);
29
+ });
30
+ return () => {
31
+ cancelled = true;
32
+ };
33
+ }, [ceremony]);
34
+ const openFromPrf = useCallback(async (prfOutput, credentialId) => {
35
+ const result = await engine.openWalletFromPasskey({ prfOutput });
36
+ return { result, credentialId };
37
+ }, [engine]);
38
+ const create = useCallback((appName) => createM.track(async () => {
39
+ const { prfOutput, credentialId } = await ceremony.registerPasskeyWallet(appName);
40
+ return openFromPrf(prfOutput, credentialId);
41
+ }), [createM.track, ceremony, openFromPrf]);
42
+ const open = useCallback((credentialId) => openM.track(async () => {
43
+ const assertion = await ceremony.assertPasskeyPrf(credentialId);
44
+ return openFromPrf(assertion.prfOutput, assertion.credentialId);
45
+ }), [openM.track, ceremony, openFromPrf]);
46
+ return {
47
+ supported,
48
+ create,
49
+ createPending: createM.pending,
50
+ createError: createM.error,
51
+ resetCreate: createM.reset,
52
+ open,
53
+ openPending: openM.pending,
54
+ openError: openM.error,
55
+ resetOpen: openM.reset,
56
+ };
57
+ }
@@ -0,0 +1,3 @@
1
+ import type { WalletSnapshot } from "@lightninglabs/wavelength-core";
2
+ export declare function useWalletSelector<T>(select: (snap: WalletSnapshot) => T): T;
3
+ //# sourceMappingURL=useWalletSelector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useWalletSelector.d.ts","sourceRoot":"","sources":["../src/useWalletSelector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAUrE,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,CAAC,GAAG,CAAC,CAQ3E"}
@@ -0,0 +1,12 @@
1
+ import { useSyncExternalStore } from "react";
2
+ import { useWalletEngine } from "./provider.js";
3
+ // Subscribes a component to one slice of the engine snapshot. The engine
4
+ // keeps slices referentially stable, so useSyncExternalStore's Object.is
5
+ // check makes unrelated changes free. Selectors must return references
6
+ // stored in the snapshot, never freshly built objects; hooks needing several
7
+ // fields call this once per field. The third argument serves the same
8
+ // snapshot during server rendering.
9
+ export function useWalletSelector(select) {
10
+ const engine = useWalletEngine();
11
+ return useSyncExternalStore(engine.subscribe, () => select(engine.getSnapshot()), () => select(engine.getSnapshot()));
12
+ }
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "@lightninglabs/wavelength-react",
3
+ "version": "0.1.0",
4
+ "private": false,
5
+ "description": "React provider and hooks for the Wavelength self-custodial Lightning wallet SDK.",
6
+ "license": "MIT",
7
+ "homepage": "https://wavelength.lightning.engineering",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/lightninglabs/wavelength-sdk.git",
11
+ "directory": "packages/react"
12
+ },
13
+ "bugs": "https://github.com/lightninglabs/wavelength-sdk/issues",
14
+ "keywords": [
15
+ "lightning",
16
+ "bitcoin",
17
+ "wallet",
18
+ "self-custodial",
19
+ "payments",
20
+ "react",
21
+ "hooks"
22
+ ],
23
+ "publishConfig": {
24
+ "access": "public"
25
+ },
26
+ "type": "module",
27
+ "main": "dist/index.js",
28
+ "types": "dist/index.d.ts",
29
+ "exports": {
30
+ ".": {
31
+ "types": "./dist/index.d.ts",
32
+ "import": "./dist/index.js"
33
+ }
34
+ },
35
+ "sideEffects": false,
36
+ "dependencies": {
37
+ "@lightninglabs/wavelength-core": "0.1.0"
38
+ },
39
+ "peerDependencies": {
40
+ "react": "^18.0.0 || ^19.0.0"
41
+ },
42
+ "devDependencies": {
43
+ "@happy-dom/global-registrator": "^20.10.6",
44
+ "@testing-library/dom": "^10.4.1",
45
+ "@testing-library/react": "^16.3.2",
46
+ "@types/react": "^19.2.17",
47
+ "@types/react-dom": "^19.2.3",
48
+ "react": "^19.2.7",
49
+ "react-dom": "^19.2.7",
50
+ "tsx": "^4.23.0"
51
+ },
52
+ "files": [
53
+ "dist"
54
+ ],
55
+ "scripts": {
56
+ "build": "tsc -p tsconfig.json",
57
+ "typecheck": "tsc -p tsconfig.json --noEmit",
58
+ "test": "node --import tsx --import ./src/testing/setup.ts --test"
59
+ }
60
+ }