@fiber-pay/react 0.2.3

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/README.md ADDED
@@ -0,0 +1,41 @@
1
+ # @fiber-pay/react
2
+
3
+ React hooks and components for browser payment flows on Fiber.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pnpm add @fiber-pay/react react
9
+ ```
10
+
11
+ ## One-line import
12
+
13
+ ```tsx
14
+ import { FiberPayQuickCard, useFiberNode, useFiberPayment } from '@fiber-pay/react';
15
+ ```
16
+
17
+ ## Quick start
18
+
19
+ ```tsx
20
+ import { FiberPayQuickCard } from '@fiber-pay/react';
21
+
22
+ export function App() {
23
+ return <FiberPayQuickCard network="testnet" />;
24
+ }
25
+ ```
26
+
27
+ ## Component customization
28
+
29
+ `FiberPayQuickCard` supports lightweight integration hooks:
30
+
31
+ - `className`, `style`, `title`
32
+ - `onInvoiceCreated(invoice)`
33
+ - `onPaymentResult(result)`
34
+ - `onError({ scope, message })`
35
+
36
+ ## Hooks
37
+
38
+ - `useFiberNode(options)`
39
+ - `useFiberPayment(node)`
40
+
41
+ `useFiberNode` exposes passkey/password startup, node lifecycle methods, and passkey diagnostics (`passkeySupportReason`, `passkeyUnavailableReason`).
@@ -0,0 +1,51 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { GetPaymentResult, FiberBrowserNodeConfig, FiberWasmFactory, BrowserNodeState, FiberBrowserNode, NodeInfoResult, PasskeySupportReason } from '@fiber-pay/sdk/browser';
3
+ import { CSSProperties } from 'react';
4
+
5
+ interface FiberPayQuickCardProps {
6
+ network?: 'testnet' | 'mainnet';
7
+ walletId?: string;
8
+ passkeyUsername?: string;
9
+ title?: string;
10
+ className?: string;
11
+ style?: CSSProperties;
12
+ onInvoiceCreated?: (invoice: string) => void;
13
+ onPaymentResult?: (result: GetPaymentResult) => void;
14
+ onError?: (error: {
15
+ scope: 'node' | 'payment' | 'invoice';
16
+ message: string;
17
+ }) => void;
18
+ }
19
+ declare function FiberPayQuickCard(props: FiberPayQuickCardProps): react_jsx_runtime.JSX.Element;
20
+
21
+ interface UseFiberNodeOptions {
22
+ network: 'testnet' | 'mainnet';
23
+ walletId?: string;
24
+ nodeConfig?: FiberBrowserNodeConfig['nodeConfig'];
25
+ wasmFactory?: FiberWasmFactory;
26
+ }
27
+ interface UseFiberNodeResult {
28
+ state: BrowserNodeState;
29
+ node: FiberBrowserNode | null;
30
+ nodeInfo: NodeInfoResult | null;
31
+ error: string | null;
32
+ isPasskeySupported: boolean;
33
+ passkeySupportReason: PasskeySupportReason | null;
34
+ passkeyUnavailableReason: string | null;
35
+ hasPasskeyConfigured: boolean;
36
+ startWithPassword: (password: string) => Promise<void>;
37
+ createPasskeyAndStart: (username?: string) => Promise<void>;
38
+ startWithPasskey: () => Promise<void>;
39
+ stop: () => Promise<void>;
40
+ }
41
+ declare function useFiberNode(options: UseFiberNodeOptions): UseFiberNodeResult;
42
+
43
+ interface UseFiberPaymentResult {
44
+ payInvoice: (invoice: string) => Promise<void>;
45
+ isPaying: boolean;
46
+ paymentResult: GetPaymentResult | null;
47
+ error: string | null;
48
+ }
49
+ declare function useFiberPayment(node: FiberBrowserNode | null): UseFiberPaymentResult;
50
+
51
+ export { FiberPayQuickCard, type FiberPayQuickCardProps, type UseFiberNodeOptions, type UseFiberNodeResult, type UseFiberPaymentResult, useFiberNode, useFiberPayment };
package/dist/index.js ADDED
@@ -0,0 +1,488 @@
1
+ // src/fiber-pay-quick-card.tsx
2
+ import { useEffect as useEffect3, useId, useState as useState3 } from "react";
3
+
4
+ // src/use-fiber-node.ts
5
+ import {
6
+ FiberBrowserNode,
7
+ PasskeyCredentialProvider,
8
+ PasswordCredentialProvider
9
+ } from "@fiber-pay/sdk/browser";
10
+ import { useCallback, useEffect, useRef, useState } from "react";
11
+ var PASSKEY_UNAVAILABLE_REASON_TEXT = {
12
+ "window-unavailable": "Passkey is not available because there is no browser window context.",
13
+ "insecure-context": "Passkey requires a secure context (HTTPS or localhost).",
14
+ "webauthn-unavailable": "This browser does not provide WebAuthn support for passkeys.",
15
+ "prf-unsupported": "This browser or authenticator does not support WebAuthn PRF.",
16
+ unknown: "Passkey support could not be fully detected in this environment."
17
+ };
18
+ function isPasskeyPotentiallySupported(status) {
19
+ return status.supported || status.reason === "unknown";
20
+ }
21
+ function toPasskeyUnavailableReason(reason) {
22
+ if (reason === "supported") {
23
+ return null;
24
+ }
25
+ return PASSKEY_UNAVAILABLE_REASON_TEXT[reason];
26
+ }
27
+ function asErrorMessage(error) {
28
+ if (error instanceof Error) {
29
+ return error.message;
30
+ }
31
+ return String(error);
32
+ }
33
+ function useFiberNode(options) {
34
+ const walletId = options.walletId ?? `wallet-${options.network}`;
35
+ const [state, setState] = useState("idle");
36
+ const [nodeInfo, setNodeInfo] = useState(null);
37
+ const [error, setError] = useState(null);
38
+ const [isPasskeySupported, setIsPasskeySupported] = useState(false);
39
+ const [passkeySupportReason, setPasskeySupportReason] = useState(
40
+ null
41
+ );
42
+ const [passkeyUnavailableReason, setPasskeyUnavailableReason] = useState(null);
43
+ const [hasPasskeyConfigured, setHasPasskeyConfigured] = useState(false);
44
+ const nodeRef = useRef(null);
45
+ const isMountedRef = useRef(true);
46
+ const nodeListenersRef = useRef(null);
47
+ const detachNodeListeners = useCallback((node) => {
48
+ if (!node || !nodeListenersRef.current) {
49
+ return;
50
+ }
51
+ node.off("stateChange", nodeListenersRef.current.stateChange);
52
+ node.off("error", nodeListenersRef.current.error);
53
+ nodeListenersRef.current = null;
54
+ }, []);
55
+ useEffect(
56
+ () => () => {
57
+ isMountedRef.current = false;
58
+ const node = nodeRef.current;
59
+ nodeRef.current = null;
60
+ if (node) {
61
+ detachNodeListeners(node);
62
+ void node.stop().catch(() => {
63
+ });
64
+ }
65
+ },
66
+ [detachNodeListeners]
67
+ );
68
+ useEffect(() => {
69
+ let cancelled = false;
70
+ PasskeyCredentialProvider.getSupportStatus().then((status) => {
71
+ if (!cancelled) {
72
+ const supported = isPasskeyPotentiallySupported(status);
73
+ setIsPasskeySupported(supported);
74
+ setPasskeySupportReason(status.reason);
75
+ setPasskeyUnavailableReason(supported ? null : toPasskeyUnavailableReason(status.reason));
76
+ }
77
+ }).catch((supportError) => {
78
+ if (!cancelled) {
79
+ setIsPasskeySupported(false);
80
+ setPasskeySupportReason("unknown");
81
+ setPasskeyUnavailableReason(toPasskeyUnavailableReason("unknown"));
82
+ }
83
+ if (supportError instanceof Error) {
84
+ console.warn("[fiber-pay/react] Failed to detect passkey support:", supportError.message);
85
+ }
86
+ });
87
+ const provider = new PasskeyCredentialProvider(walletId);
88
+ setHasPasskeyConfigured(provider.isConfigured());
89
+ return () => {
90
+ cancelled = true;
91
+ };
92
+ }, [walletId]);
93
+ const initNode = useCallback(
94
+ (credential) => {
95
+ if (nodeRef.current) {
96
+ const existingState = nodeRef.current.state;
97
+ if (existingState !== "idle" && existingState !== "stopped" && existingState !== "error") {
98
+ throw new Error("Node already running");
99
+ }
100
+ detachNodeListeners(nodeRef.current);
101
+ nodeRef.current = null;
102
+ }
103
+ const nodeConfig = {
104
+ network: options.network,
105
+ credential,
106
+ nodeConfig: {
107
+ databasePrefix: `/${walletId}`,
108
+ ...options.nodeConfig ?? {}
109
+ }
110
+ };
111
+ if (options.wasmFactory) {
112
+ nodeConfig.wasmFactory = options.wasmFactory;
113
+ }
114
+ const node = new FiberBrowserNode(nodeConfig);
115
+ nodeRef.current = node;
116
+ const listeners = {
117
+ stateChange: (nextState) => {
118
+ if (!isMountedRef.current) {
119
+ return;
120
+ }
121
+ setState(nextState);
122
+ if (nextState === "stopped") {
123
+ setNodeInfo(null);
124
+ }
125
+ },
126
+ error: (nextError) => {
127
+ if (!isMountedRef.current) {
128
+ return;
129
+ }
130
+ setError(nextError.message);
131
+ }
132
+ };
133
+ nodeListenersRef.current = listeners;
134
+ node.on("stateChange", listeners.stateChange);
135
+ node.on("error", listeners.error);
136
+ return node;
137
+ },
138
+ [detachNodeListeners, options.network, options.nodeConfig, options.wasmFactory, walletId]
139
+ );
140
+ const cleanupFailedStart = useCallback(
141
+ async (node) => {
142
+ if (!node) {
143
+ return;
144
+ }
145
+ try {
146
+ if (node.state !== "idle" && node.state !== "stopped") {
147
+ await node.stop();
148
+ }
149
+ } catch {
150
+ } finally {
151
+ detachNodeListeners(node);
152
+ if (nodeRef.current === node) {
153
+ nodeRef.current = null;
154
+ }
155
+ }
156
+ },
157
+ [detachNodeListeners]
158
+ );
159
+ const startWithPassword = useCallback(
160
+ async (password) => {
161
+ setError(null);
162
+ let node = null;
163
+ try {
164
+ const credential = new PasswordCredentialProvider(walletId);
165
+ node = initNode(credential);
166
+ const info = await node.start({ unlockParams: { password } });
167
+ if (isMountedRef.current) {
168
+ setNodeInfo(info);
169
+ }
170
+ } catch (startError) {
171
+ if (isMountedRef.current) {
172
+ setError(asErrorMessage(startError));
173
+ }
174
+ await cleanupFailedStart(node);
175
+ }
176
+ },
177
+ [cleanupFailedStart, initNode, walletId]
178
+ );
179
+ const createPasskeyAndStart = useCallback(
180
+ async (username = "User") => {
181
+ setError(null);
182
+ let node = null;
183
+ try {
184
+ const credential = new PasskeyCredentialProvider(walletId);
185
+ await credential.register(username);
186
+ if (isMountedRef.current) {
187
+ setHasPasskeyConfigured(true);
188
+ }
189
+ node = initNode(credential);
190
+ const info = await node.start();
191
+ if (isMountedRef.current) {
192
+ setNodeInfo(info);
193
+ }
194
+ } catch (startError) {
195
+ if (isMountedRef.current) {
196
+ setError(asErrorMessage(startError));
197
+ }
198
+ await cleanupFailedStart(node);
199
+ }
200
+ },
201
+ [cleanupFailedStart, initNode, walletId]
202
+ );
203
+ const startWithPasskey = useCallback(async () => {
204
+ setError(null);
205
+ let node = null;
206
+ try {
207
+ const credential = new PasskeyCredentialProvider(walletId);
208
+ node = initNode(credential);
209
+ const info = await node.start();
210
+ if (isMountedRef.current) {
211
+ setNodeInfo(info);
212
+ }
213
+ } catch (startError) {
214
+ if (isMountedRef.current) {
215
+ setError(asErrorMessage(startError));
216
+ }
217
+ await cleanupFailedStart(node);
218
+ }
219
+ }, [cleanupFailedStart, initNode, walletId]);
220
+ const stop = useCallback(async () => {
221
+ const node = nodeRef.current;
222
+ if (!node) {
223
+ return;
224
+ }
225
+ try {
226
+ await node.stop();
227
+ } catch (stopError) {
228
+ if (isMountedRef.current) {
229
+ setError(asErrorMessage(stopError));
230
+ }
231
+ } finally {
232
+ detachNodeListeners(node);
233
+ if (nodeRef.current === node) {
234
+ nodeRef.current = null;
235
+ }
236
+ if (isMountedRef.current) {
237
+ setNodeInfo(null);
238
+ }
239
+ }
240
+ }, [detachNodeListeners]);
241
+ return {
242
+ state,
243
+ node: nodeRef.current,
244
+ nodeInfo,
245
+ error,
246
+ isPasskeySupported,
247
+ passkeySupportReason,
248
+ passkeyUnavailableReason,
249
+ hasPasskeyConfigured,
250
+ startWithPassword,
251
+ createPasskeyAndStart,
252
+ startWithPasskey,
253
+ stop
254
+ };
255
+ }
256
+
257
+ // src/use-fiber-payment.ts
258
+ import { useCallback as useCallback2, useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
259
+ function asErrorMessage2(error) {
260
+ if (error instanceof Error) {
261
+ return error.message;
262
+ }
263
+ return String(error);
264
+ }
265
+ function useFiberPayment(node) {
266
+ const [isPaying, setIsPaying] = useState2(false);
267
+ const [paymentResult, setPaymentResult] = useState2(null);
268
+ const [error, setError] = useState2(null);
269
+ const isMountedRef = useRef2(true);
270
+ useEffect2(
271
+ () => () => {
272
+ isMountedRef.current = false;
273
+ },
274
+ []
275
+ );
276
+ const payInvoice = useCallback2(
277
+ async (invoice) => {
278
+ if (!node) {
279
+ if (isMountedRef.current) {
280
+ setError("Node is not initialized");
281
+ }
282
+ return;
283
+ }
284
+ if (isMountedRef.current) {
285
+ setIsPaying(true);
286
+ setError(null);
287
+ setPaymentResult(null);
288
+ }
289
+ try {
290
+ const parsed = await node.parseInvoice({ invoice });
291
+ await node.sendPayment({ invoice });
292
+ const paymentHash = parsed.invoice.data.payment_hash;
293
+ const result = await node.waitForPayment(paymentHash);
294
+ if (result.status === "Failed") {
295
+ throw new Error(result.failed_error ?? "Payment failed during routing/execution");
296
+ }
297
+ if (isMountedRef.current) {
298
+ setPaymentResult(result);
299
+ }
300
+ } catch (payError) {
301
+ if (isMountedRef.current) {
302
+ setError(asErrorMessage2(payError));
303
+ }
304
+ } finally {
305
+ if (isMountedRef.current) {
306
+ setIsPaying(false);
307
+ }
308
+ }
309
+ },
310
+ [node]
311
+ );
312
+ return {
313
+ payInvoice,
314
+ isPaying,
315
+ paymentResult,
316
+ error
317
+ };
318
+ }
319
+
320
+ // src/fiber-pay-quick-card.tsx
321
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
322
+ var ONE_CKB_SHANNONS = "0x5f5e100";
323
+ var cardStyle = {
324
+ border: "1px solid #ddd",
325
+ borderRadius: 8,
326
+ padding: 16,
327
+ maxWidth: 520
328
+ };
329
+ var rowStyle = {
330
+ display: "flex",
331
+ gap: 8
332
+ };
333
+ var rowWithMarginStyle = {
334
+ ...rowStyle,
335
+ marginBottom: 8
336
+ };
337
+ function FiberPayQuickCard(props) {
338
+ const network = props.network ?? "testnet";
339
+ const passkeyUsername = props.passkeyUsername ?? "User";
340
+ const title = props.title ?? "FiberPay Quick Card";
341
+ const onError = props.onError;
342
+ const onInvoiceCreated = props.onInvoiceCreated;
343
+ const onPaymentResult = props.onPaymentResult;
344
+ const passwordInputId = useId();
345
+ const invoiceInputId = useId();
346
+ const {
347
+ node,
348
+ nodeInfo,
349
+ state,
350
+ error: nodeError,
351
+ isPasskeySupported,
352
+ hasPasskeyConfigured,
353
+ startWithPassword,
354
+ startWithPasskey,
355
+ createPasskeyAndStart,
356
+ stop
357
+ } = useFiberNode({ network, walletId: props.walletId });
358
+ const { payInvoice, isPaying, error: payError, paymentResult } = useFiberPayment(node);
359
+ const [password, setPassword] = useState3("");
360
+ const [invoiceInput, setInvoiceInput] = useState3("");
361
+ const [createdInvoice, setCreatedInvoice] = useState3("");
362
+ const [isCreatingInvoice, setIsCreatingInvoice] = useState3(false);
363
+ const [invoiceError, setInvoiceError] = useState3(null);
364
+ useEffect3(() => {
365
+ if (nodeError) {
366
+ onError?.({ scope: "node", message: nodeError });
367
+ }
368
+ }, [nodeError, onError]);
369
+ useEffect3(() => {
370
+ if (payError) {
371
+ onError?.({ scope: "payment", message: payError });
372
+ }
373
+ }, [onError, payError]);
374
+ useEffect3(() => {
375
+ if (paymentResult) {
376
+ onPaymentResult?.(paymentResult);
377
+ }
378
+ }, [onPaymentResult, paymentResult]);
379
+ const createInvoice = async () => {
380
+ if (!node) {
381
+ return;
382
+ }
383
+ setIsCreatingInvoice(true);
384
+ setInvoiceError(null);
385
+ try {
386
+ const created = await node.newInvoice({
387
+ amount: ONE_CKB_SHANNONS,
388
+ currency: network === "mainnet" ? "Fibb" : "Fibt",
389
+ description: "FiberPay QuickCard invoice"
390
+ });
391
+ setCreatedInvoice(created.invoice_address);
392
+ onInvoiceCreated?.(created.invoice_address);
393
+ } catch (createInvoiceError) {
394
+ const message = createInvoiceError instanceof Error ? createInvoiceError.message : String(createInvoiceError);
395
+ setInvoiceError(message);
396
+ onError?.({ scope: "invoice", message });
397
+ } finally {
398
+ setIsCreatingInvoice(false);
399
+ }
400
+ };
401
+ return /* @__PURE__ */ jsxs("div", { style: { ...cardStyle, ...props.style }, className: props.className, children: [
402
+ /* @__PURE__ */ jsxs("h3", { children: [
403
+ title,
404
+ " (",
405
+ network,
406
+ ")"
407
+ ] }),
408
+ !nodeInfo ? /* @__PURE__ */ jsxs(Fragment, { children: [
409
+ isPasskeySupported ? /* @__PURE__ */ jsx("div", { style: rowWithMarginStyle, children: hasPasskeyConfigured ? /* @__PURE__ */ jsx("button", { type: "button", onClick: () => void startWithPasskey(), children: "Login with Passkey" }) : /* @__PURE__ */ jsx("button", { type: "button", onClick: () => void createPasskeyAndStart(passkeyUsername), children: "Register Passkey" }) }) : null,
410
+ /* @__PURE__ */ jsx("label", { htmlFor: passwordInputId, children: "Password" }),
411
+ /* @__PURE__ */ jsxs("div", { style: rowStyle, children: [
412
+ /* @__PURE__ */ jsx(
413
+ "input",
414
+ {
415
+ id: passwordInputId,
416
+ type: "password",
417
+ autoComplete: "current-password",
418
+ "aria-label": "Node password",
419
+ value: password,
420
+ onChange: (event) => setPassword(event.target.value),
421
+ placeholder: "Password"
422
+ }
423
+ ),
424
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: () => void startWithPassword(password), children: "Start with Password" })
425
+ ] })
426
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
427
+ /* @__PURE__ */ jsxs("p", { children: [
428
+ /* @__PURE__ */ jsx("strong", { children: "State:" }),
429
+ " ",
430
+ state
431
+ ] }),
432
+ /* @__PURE__ */ jsxs("p", { children: [
433
+ /* @__PURE__ */ jsx("strong", { children: "Pubkey:" }),
434
+ " ",
435
+ nodeInfo.pubkey
436
+ ] }),
437
+ /* @__PURE__ */ jsxs("div", { style: rowWithMarginStyle, children: [
438
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: () => void createInvoice(), disabled: isCreatingInvoice, children: isCreatingInvoice ? "Creating..." : "Create Invoice (1 CKB)" }),
439
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: () => void stop(), children: "Stop Node" })
440
+ ] }),
441
+ createdInvoice ? /* @__PURE__ */ jsxs("p", { children: [
442
+ /* @__PURE__ */ jsx("strong", { children: "Created invoice:" }),
443
+ " ",
444
+ createdInvoice
445
+ ] }) : null,
446
+ /* @__PURE__ */ jsx("label", { htmlFor: invoiceInputId, children: "Invoice" }),
447
+ /* @__PURE__ */ jsxs("div", { style: rowStyle, children: [
448
+ /* @__PURE__ */ jsx(
449
+ "input",
450
+ {
451
+ id: invoiceInputId,
452
+ "aria-label": "Invoice to pay",
453
+ value: invoiceInput,
454
+ onChange: (event) => setInvoiceInput(event.target.value),
455
+ placeholder: "Paste invoice to pay"
456
+ }
457
+ ),
458
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: () => void payInvoice(invoiceInput), disabled: isPaying, children: isPaying ? "Paying..." : "Pay" })
459
+ ] }),
460
+ paymentResult ? /* @__PURE__ */ jsxs("p", { children: [
461
+ /* @__PURE__ */ jsx("strong", { children: "Payment:" }),
462
+ " ",
463
+ paymentResult.status
464
+ ] }) : null
465
+ ] }),
466
+ nodeError ? /* @__PURE__ */ jsxs("p", { style: { color: "#b91c1c" }, children: [
467
+ /* @__PURE__ */ jsx("strong", { children: "Node error:" }),
468
+ " ",
469
+ nodeError
470
+ ] }) : null,
471
+ payError ? /* @__PURE__ */ jsxs("p", { style: { color: "#b91c1c" }, children: [
472
+ /* @__PURE__ */ jsx("strong", { children: "Payment error:" }),
473
+ " ",
474
+ payError
475
+ ] }) : null,
476
+ invoiceError ? /* @__PURE__ */ jsxs("p", { style: { color: "#b91c1c" }, children: [
477
+ /* @__PURE__ */ jsx("strong", { children: "Invoice error:" }),
478
+ " ",
479
+ invoiceError
480
+ ] }) : null
481
+ ] });
482
+ }
483
+ export {
484
+ FiberPayQuickCard,
485
+ useFiberNode,
486
+ useFiberPayment
487
+ };
488
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/fiber-pay-quick-card.tsx","../src/use-fiber-node.ts","../src/use-fiber-payment.ts"],"sourcesContent":["import type { GetPaymentResult } from '@fiber-pay/sdk/browser';\nimport { type CSSProperties, useEffect, useId, useState } from 'react';\nimport { useFiberNode } from './use-fiber-node.js';\nimport { useFiberPayment } from './use-fiber-payment.js';\n\nexport interface FiberPayQuickCardProps {\n network?: 'testnet' | 'mainnet';\n walletId?: string;\n passkeyUsername?: string;\n title?: string;\n className?: string;\n style?: CSSProperties;\n onInvoiceCreated?: (invoice: string) => void;\n onPaymentResult?: (result: GetPaymentResult) => void;\n onError?: (error: { scope: 'node' | 'payment' | 'invoice'; message: string }) => void;\n}\n\nconst ONE_CKB_SHANNONS = '0x5f5e100';\n\nconst cardStyle: CSSProperties = {\n border: '1px solid #ddd',\n borderRadius: 8,\n padding: 16,\n maxWidth: 520,\n};\n\nconst rowStyle: CSSProperties = {\n display: 'flex',\n gap: 8,\n};\n\nconst rowWithMarginStyle: CSSProperties = {\n ...rowStyle,\n marginBottom: 8,\n};\n\nexport function FiberPayQuickCard(props: FiberPayQuickCardProps) {\n const network = props.network ?? 'testnet';\n const passkeyUsername = props.passkeyUsername ?? 'User';\n const title = props.title ?? 'FiberPay Quick Card';\n const onError = props.onError;\n const onInvoiceCreated = props.onInvoiceCreated;\n const onPaymentResult = props.onPaymentResult;\n const passwordInputId = useId();\n const invoiceInputId = useId();\n\n const {\n node,\n nodeInfo,\n state,\n error: nodeError,\n isPasskeySupported,\n hasPasskeyConfigured,\n startWithPassword,\n startWithPasskey,\n createPasskeyAndStart,\n stop,\n } = useFiberNode({ network, walletId: props.walletId });\n\n const { payInvoice, isPaying, error: payError, paymentResult } = useFiberPayment(node);\n\n const [password, setPassword] = useState('');\n const [invoiceInput, setInvoiceInput] = useState('');\n const [createdInvoice, setCreatedInvoice] = useState('');\n const [isCreatingInvoice, setIsCreatingInvoice] = useState(false);\n const [invoiceError, setInvoiceError] = useState<string | null>(null);\n\n useEffect(() => {\n if (nodeError) {\n onError?.({ scope: 'node', message: nodeError });\n }\n }, [nodeError, onError]);\n\n useEffect(() => {\n if (payError) {\n onError?.({ scope: 'payment', message: payError });\n }\n }, [onError, payError]);\n\n useEffect(() => {\n if (paymentResult) {\n onPaymentResult?.(paymentResult);\n }\n }, [onPaymentResult, paymentResult]);\n\n const createInvoice = async () => {\n if (!node) {\n return;\n }\n\n setIsCreatingInvoice(true);\n setInvoiceError(null);\n try {\n const created = await node.newInvoice({\n amount: ONE_CKB_SHANNONS,\n currency: network === 'mainnet' ? 'Fibb' : 'Fibt',\n description: 'FiberPay QuickCard invoice',\n });\n setCreatedInvoice(created.invoice_address);\n onInvoiceCreated?.(created.invoice_address);\n } catch (createInvoiceError) {\n const message =\n createInvoiceError instanceof Error\n ? createInvoiceError.message\n : String(createInvoiceError);\n setInvoiceError(message);\n onError?.({ scope: 'invoice', message });\n } finally {\n setIsCreatingInvoice(false);\n }\n };\n\n return (\n <div style={{ ...cardStyle, ...props.style }} className={props.className}>\n <h3>\n {title} ({network})\n </h3>\n\n {!nodeInfo ? (\n <>\n {isPasskeySupported ? (\n <div style={rowWithMarginStyle}>\n {hasPasskeyConfigured ? (\n <button type=\"button\" onClick={() => void startWithPasskey()}>\n Login with Passkey\n </button>\n ) : (\n <button type=\"button\" onClick={() => void createPasskeyAndStart(passkeyUsername)}>\n Register Passkey\n </button>\n )}\n </div>\n ) : null}\n\n <label htmlFor={passwordInputId}>Password</label>\n <div style={rowStyle}>\n <input\n id={passwordInputId}\n type=\"password\"\n autoComplete=\"current-password\"\n aria-label=\"Node password\"\n value={password}\n onChange={(event) => setPassword(event.target.value)}\n placeholder=\"Password\"\n />\n <button type=\"button\" onClick={() => void startWithPassword(password)}>\n Start with Password\n </button>\n </div>\n </>\n ) : (\n <>\n <p>\n <strong>State:</strong> {state}\n </p>\n <p>\n <strong>Pubkey:</strong> {nodeInfo.pubkey}\n </p>\n\n <div style={rowWithMarginStyle}>\n <button type=\"button\" onClick={() => void createInvoice()} disabled={isCreatingInvoice}>\n {isCreatingInvoice ? 'Creating...' : 'Create Invoice (1 CKB)'}\n </button>\n <button type=\"button\" onClick={() => void stop()}>\n Stop Node\n </button>\n </div>\n\n {createdInvoice ? (\n <p>\n <strong>Created invoice:</strong> {createdInvoice}\n </p>\n ) : null}\n\n <label htmlFor={invoiceInputId}>Invoice</label>\n <div style={rowStyle}>\n <input\n id={invoiceInputId}\n aria-label=\"Invoice to pay\"\n value={invoiceInput}\n onChange={(event) => setInvoiceInput(event.target.value)}\n placeholder=\"Paste invoice to pay\"\n />\n <button type=\"button\" onClick={() => void payInvoice(invoiceInput)} disabled={isPaying}>\n {isPaying ? 'Paying...' : 'Pay'}\n </button>\n </div>\n\n {paymentResult ? (\n <p>\n <strong>Payment:</strong> {paymentResult.status}\n </p>\n ) : null}\n </>\n )}\n\n {nodeError ? (\n <p style={{ color: '#b91c1c' }}>\n <strong>Node error:</strong> {nodeError}\n </p>\n ) : null}\n {payError ? (\n <p style={{ color: '#b91c1c' }}>\n <strong>Payment error:</strong> {payError}\n </p>\n ) : null}\n {invoiceError ? (\n <p style={{ color: '#b91c1c' }}>\n <strong>Invoice error:</strong> {invoiceError}\n </p>\n ) : null}\n </div>\n );\n}\n","import {\n type BrowserNodeState,\n FiberBrowserNode,\n type FiberBrowserNodeConfig,\n type FiberWasmFactory,\n type NodeInfoResult,\n PasskeyCredentialProvider,\n type PasskeySupportReason,\n type PasskeySupportStatus,\n PasswordCredentialProvider,\n} from '@fiber-pay/sdk/browser';\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\nexport interface UseFiberNodeOptions {\n network: 'testnet' | 'mainnet';\n walletId?: string;\n nodeConfig?: FiberBrowserNodeConfig['nodeConfig'];\n wasmFactory?: FiberWasmFactory;\n}\n\nexport interface UseFiberNodeResult {\n state: BrowserNodeState;\n node: FiberBrowserNode | null;\n nodeInfo: NodeInfoResult | null;\n error: string | null;\n isPasskeySupported: boolean;\n passkeySupportReason: PasskeySupportReason | null;\n passkeyUnavailableReason: string | null;\n hasPasskeyConfigured: boolean;\n startWithPassword: (password: string) => Promise<void>;\n createPasskeyAndStart: (username?: string) => Promise<void>;\n startWithPasskey: () => Promise<void>;\n stop: () => Promise<void>;\n}\n\nconst PASSKEY_UNAVAILABLE_REASON_TEXT: Record<\n Exclude<PasskeySupportReason, 'supported'>,\n string\n> = {\n 'window-unavailable': 'Passkey is not available because there is no browser window context.',\n 'insecure-context': 'Passkey requires a secure context (HTTPS or localhost).',\n 'webauthn-unavailable': 'This browser does not provide WebAuthn support for passkeys.',\n 'prf-unsupported': 'This browser or authenticator does not support WebAuthn PRF.',\n unknown: 'Passkey support could not be fully detected in this environment.',\n};\n\nexport function isPasskeyPotentiallySupported(status: PasskeySupportStatus): boolean {\n return status.supported || status.reason === 'unknown';\n}\n\nexport function toPasskeyUnavailableReason(reason: PasskeySupportReason): string | null {\n if (reason === 'supported') {\n return null;\n }\n return PASSKEY_UNAVAILABLE_REASON_TEXT[reason];\n}\n\nfunction asErrorMessage(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n return String(error);\n}\n\ninterface NodeEventListeners {\n stateChange: (nextState: BrowserNodeState) => void;\n error: (nextError: Error) => void;\n}\n\nexport function useFiberNode(options: UseFiberNodeOptions): UseFiberNodeResult {\n const walletId = options.walletId ?? `wallet-${options.network}`;\n const [state, setState] = useState<BrowserNodeState>('idle');\n const [nodeInfo, setNodeInfo] = useState<NodeInfoResult | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [isPasskeySupported, setIsPasskeySupported] = useState(false);\n const [passkeySupportReason, setPasskeySupportReason] = useState<PasskeySupportReason | null>(\n null,\n );\n const [passkeyUnavailableReason, setPasskeyUnavailableReason] = useState<string | null>(null);\n const [hasPasskeyConfigured, setHasPasskeyConfigured] = useState(false);\n\n const nodeRef = useRef<FiberBrowserNode | null>(null);\n const isMountedRef = useRef(true);\n const nodeListenersRef = useRef<NodeEventListeners | null>(null);\n\n const detachNodeListeners = useCallback((node: FiberBrowserNode | null) => {\n if (!node || !nodeListenersRef.current) {\n return;\n }\n\n node.off('stateChange', nodeListenersRef.current.stateChange);\n node.off('error', nodeListenersRef.current.error);\n nodeListenersRef.current = null;\n }, []);\n\n useEffect(\n () => () => {\n isMountedRef.current = false;\n\n const node = nodeRef.current;\n nodeRef.current = null;\n\n if (node) {\n detachNodeListeners(node);\n void node.stop().catch(() => {});\n }\n },\n [detachNodeListeners],\n );\n\n useEffect(() => {\n let cancelled = false;\n\n PasskeyCredentialProvider.getSupportStatus()\n .then((status) => {\n if (!cancelled) {\n const supported = isPasskeyPotentiallySupported(status);\n setIsPasskeySupported(supported);\n setPasskeySupportReason(status.reason);\n setPasskeyUnavailableReason(supported ? null : toPasskeyUnavailableReason(status.reason));\n }\n })\n .catch((supportError) => {\n if (!cancelled) {\n setIsPasskeySupported(false);\n setPasskeySupportReason('unknown');\n setPasskeyUnavailableReason(toPasskeyUnavailableReason('unknown'));\n }\n\n if (supportError instanceof Error) {\n console.warn('[fiber-pay/react] Failed to detect passkey support:', supportError.message);\n }\n });\n\n const provider = new PasskeyCredentialProvider(walletId);\n setHasPasskeyConfigured(provider.isConfigured());\n\n return () => {\n cancelled = true;\n };\n }, [walletId]);\n\n const initNode = useCallback(\n (credential: PasswordCredentialProvider | PasskeyCredentialProvider) => {\n if (nodeRef.current) {\n const existingState = nodeRef.current.state;\n if (existingState !== 'idle' && existingState !== 'stopped' && existingState !== 'error') {\n throw new Error('Node already running');\n }\n\n detachNodeListeners(nodeRef.current);\n nodeRef.current = null;\n }\n\n const nodeConfig: ConstructorParameters<typeof FiberBrowserNode>[0] = {\n network: options.network,\n credential,\n nodeConfig: {\n databasePrefix: `/${walletId}`,\n ...(options.nodeConfig ?? {}),\n },\n };\n\n if (options.wasmFactory) {\n nodeConfig.wasmFactory = options.wasmFactory;\n }\n\n const node = new FiberBrowserNode(nodeConfig);\n\n nodeRef.current = node;\n\n const listeners: NodeEventListeners = {\n stateChange: (nextState) => {\n if (!isMountedRef.current) {\n return;\n }\n\n setState(nextState);\n if (nextState === 'stopped') {\n setNodeInfo(null);\n }\n },\n error: (nextError: Error) => {\n if (!isMountedRef.current) {\n return;\n }\n\n setError(nextError.message);\n },\n };\n\n nodeListenersRef.current = listeners;\n node.on('stateChange', listeners.stateChange);\n node.on('error', listeners.error);\n\n return node;\n },\n [detachNodeListeners, options.network, options.nodeConfig, options.wasmFactory, walletId],\n );\n\n const cleanupFailedStart = useCallback(\n async (node: FiberBrowserNode | null) => {\n if (!node) {\n return;\n }\n\n try {\n if (node.state !== 'idle' && node.state !== 'stopped') {\n await node.stop();\n }\n } catch {\n // Ignore cleanup failures after a start error.\n } finally {\n detachNodeListeners(node);\n if (nodeRef.current === node) {\n nodeRef.current = null;\n }\n }\n },\n [detachNodeListeners],\n );\n\n const startWithPassword = useCallback(\n async (password: string) => {\n setError(null);\n let node: FiberBrowserNode | null = null;\n\n try {\n const credential = new PasswordCredentialProvider(walletId);\n node = initNode(credential);\n const info = await node.start({ unlockParams: { password } });\n if (isMountedRef.current) {\n setNodeInfo(info);\n }\n } catch (startError) {\n if (isMountedRef.current) {\n setError(asErrorMessage(startError));\n }\n\n await cleanupFailedStart(node);\n }\n },\n [cleanupFailedStart, initNode, walletId],\n );\n\n const createPasskeyAndStart = useCallback(\n async (username = 'User') => {\n setError(null);\n let node: FiberBrowserNode | null = null;\n\n try {\n const credential = new PasskeyCredentialProvider(walletId);\n await credential.register(username);\n if (isMountedRef.current) {\n setHasPasskeyConfigured(true);\n }\n\n node = initNode(credential);\n const info = await node.start();\n if (isMountedRef.current) {\n setNodeInfo(info);\n }\n } catch (startError) {\n if (isMountedRef.current) {\n setError(asErrorMessage(startError));\n }\n\n await cleanupFailedStart(node);\n }\n },\n [cleanupFailedStart, initNode, walletId],\n );\n\n const startWithPasskey = useCallback(async () => {\n setError(null);\n let node: FiberBrowserNode | null = null;\n\n try {\n const credential = new PasskeyCredentialProvider(walletId);\n node = initNode(credential);\n const info = await node.start();\n if (isMountedRef.current) {\n setNodeInfo(info);\n }\n } catch (startError) {\n if (isMountedRef.current) {\n setError(asErrorMessage(startError));\n }\n\n await cleanupFailedStart(node);\n }\n }, [cleanupFailedStart, initNode, walletId]);\n\n const stop = useCallback(async () => {\n const node = nodeRef.current;\n if (!node) {\n return;\n }\n\n try {\n await node.stop();\n } catch (stopError) {\n if (isMountedRef.current) {\n setError(asErrorMessage(stopError));\n }\n } finally {\n detachNodeListeners(node);\n if (nodeRef.current === node) {\n nodeRef.current = null;\n }\n\n if (isMountedRef.current) {\n setNodeInfo(null);\n }\n }\n }, [detachNodeListeners]);\n\n return {\n state,\n node: nodeRef.current,\n nodeInfo,\n error,\n isPasskeySupported,\n passkeySupportReason,\n passkeyUnavailableReason,\n hasPasskeyConfigured,\n startWithPassword,\n createPasskeyAndStart,\n startWithPasskey,\n stop,\n };\n}\n","import type { FiberBrowserNode, GetPaymentResult } from '@fiber-pay/sdk/browser';\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\nexport interface UseFiberPaymentResult {\n payInvoice: (invoice: string) => Promise<void>;\n isPaying: boolean;\n paymentResult: GetPaymentResult | null;\n error: string | null;\n}\n\nfunction asErrorMessage(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n return String(error);\n}\n\nexport function useFiberPayment(node: FiberBrowserNode | null): UseFiberPaymentResult {\n const [isPaying, setIsPaying] = useState(false);\n const [paymentResult, setPaymentResult] = useState<GetPaymentResult | null>(null);\n const [error, setError] = useState<string | null>(null);\n const isMountedRef = useRef(true);\n\n useEffect(\n () => () => {\n isMountedRef.current = false;\n },\n [],\n );\n\n const payInvoice = useCallback(\n async (invoice: string) => {\n if (!node) {\n if (isMountedRef.current) {\n setError('Node is not initialized');\n }\n return;\n }\n\n if (isMountedRef.current) {\n setIsPaying(true);\n setError(null);\n setPaymentResult(null);\n }\n\n try {\n const parsed = await node.parseInvoice({ invoice });\n await node.sendPayment({ invoice });\n\n const paymentHash = parsed.invoice.data.payment_hash;\n const result = await node.waitForPayment(paymentHash);\n\n if (result.status === 'Failed') {\n throw new Error(result.failed_error ?? 'Payment failed during routing/execution');\n }\n\n if (isMountedRef.current) {\n setPaymentResult(result);\n }\n } catch (payError) {\n if (isMountedRef.current) {\n setError(asErrorMessage(payError));\n }\n } finally {\n if (isMountedRef.current) {\n setIsPaying(false);\n }\n }\n },\n [node],\n );\n\n return {\n payInvoice,\n isPaying,\n paymentResult,\n error,\n };\n}\n"],"mappings":"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","names":["useEffect","useState","useCallback","useEffect","useRef","useState","asErrorMessage","useState","useEffect"]}
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@fiber-pay/react",
3
+ "version": "0.2.3",
4
+ "description": "React hooks and components for Fiber browser payments",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "README.md"
17
+ ],
18
+ "keywords": [
19
+ "fiber",
20
+ "ckb",
21
+ "react",
22
+ "passkey",
23
+ "wasm",
24
+ "payment"
25
+ ],
26
+ "license": "MIT",
27
+ "publishConfig": {
28
+ "access": "public"
29
+ },
30
+ "engines": {
31
+ "node": ">=20"
32
+ },
33
+ "sideEffects": false,
34
+ "dependencies": {
35
+ "@nervosnetwork/fiber-js": "~0.8.0",
36
+ "@fiber-pay/sdk": "0.2.3"
37
+ },
38
+ "peerDependencies": {
39
+ "react": "^18.0.0 || ^19.0.0"
40
+ },
41
+ "devDependencies": {
42
+ "@types/react": "^18.0.0 || ^19.0.0"
43
+ },
44
+ "scripts": {
45
+ "build": "tsup",
46
+ "dev": "tsup --watch",
47
+ "typecheck": "tsc --noEmit",
48
+ "test": "vitest run --config vitest.config.ts"
49
+ }
50
+ }