@stacks-passkey/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.
@@ -0,0 +1,28 @@
1
+ import { type ReactNode } from 'react';
2
+ import { PasskeyClient, type PasskeyConfig, type PasskeySession, type FeeConfig } from '@stacks-passkey/core';
3
+ export type PasskeyProviderConfig = PasskeyConfig & {
4
+ relayUrl: string;
5
+ relayApiKey?: string;
6
+ fee?: FeeConfig;
7
+ };
8
+ export declare function PasskeyProvider({ config, children, }: {
9
+ config: PasskeyProviderConfig;
10
+ children: ReactNode;
11
+ }): import("react").JSX.Element;
12
+ export declare function usePasskeyClient(): PasskeyClient;
13
+ export declare function usePasskeyAccount(): {
14
+ session: PasskeySession | null;
15
+ isRegistered: boolean;
16
+ loading: boolean;
17
+ error: string | null;
18
+ gasBalance: string | null;
19
+ gasTankAddress: string | null;
20
+ register: (userId: string, userName: string) => Promise<import("@stacks-passkey/core").PasskeyCredential>;
21
+ signIn: () => Promise<PasskeySession>;
22
+ logout: () => void;
23
+ transfer: (recipient: string, amount: bigint) => Promise<string>;
24
+ invoke: (contract: string, fn: string, args?: Parameters<PasskeyClient["invoke"]>[2]) => Promise<string>;
25
+ feeMode: import("@stacks-passkey/core").FeeMode;
26
+ };
27
+ export { PasskeyClient };
28
+ export type { PasskeyConfig, PasskeySession, FeeConfig };
package/dist/index.js ADDED
@@ -0,0 +1,140 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { createContext, useCallback, useContext, useEffect, useRef, useState } from 'react';
3
+ import { PasskeyClient, normalizeRpId, clearSession } from '@stacks-passkey/core';
4
+ const PasskeyContext = createContext(null);
5
+ export function PasskeyProvider({ config, children, }) {
6
+ const clientRef = useRef(null);
7
+ const configKeyRef = useRef('');
8
+ const configKey = `${normalizeRpId(config.rpId)}:${config.deployerAddress}:${config.network.chainId}`;
9
+ if (!clientRef.current || configKeyRef.current !== configKey) {
10
+ clientRef.current = new PasskeyClient(config);
11
+ configKeyRef.current = configKey;
12
+ }
13
+ useEffect(() => {
14
+ if (config.fee) {
15
+ clientRef.current?.setFeeConfig(config.fee);
16
+ }
17
+ }, [config.fee]);
18
+ return _jsx(PasskeyContext.Provider, { value: clientRef.current, children: children });
19
+ }
20
+ export function usePasskeyClient() {
21
+ const client = useContext(PasskeyContext);
22
+ if (!client)
23
+ throw new Error('usePasskeyClient must be used within PasskeyProvider');
24
+ return client;
25
+ }
26
+ export function usePasskeyAccount() {
27
+ const client = usePasskeyClient();
28
+ const [session, setSession] = useState(() => client.getSession());
29
+ const [loading, setLoading] = useState(false);
30
+ const [error, setError] = useState(null);
31
+ const [gasBalance, setGasBalance] = useState(null);
32
+ const [gasTankAddress, setGasTankAddress] = useState(null);
33
+ useEffect(() => {
34
+ client
35
+ .getRelayClient()
36
+ .getProjectBalance()
37
+ .then((b) => {
38
+ setGasBalance(b?.gasBalanceMicroStx ?? null);
39
+ setGasTankAddress(b?.gasTankAddress ?? null);
40
+ })
41
+ .catch(() => {
42
+ setGasBalance(null);
43
+ setGasTankAddress(null);
44
+ });
45
+ }, [client]);
46
+ const register = useCallback(async (userId, userName) => {
47
+ setLoading(true);
48
+ setError(null);
49
+ try {
50
+ const credential = await client.register(userId, userName);
51
+ setSession(client.getSession());
52
+ const balance = await client.getRelayClient().getProjectBalance();
53
+ setGasBalance(balance?.gasBalanceMicroStx ?? null);
54
+ return credential;
55
+ }
56
+ catch (e) {
57
+ const message = e instanceof Error ? e.message : 'Registration failed';
58
+ setError(message);
59
+ throw e;
60
+ }
61
+ finally {
62
+ setLoading(false);
63
+ }
64
+ }, [client]);
65
+ const signIn = useCallback(async () => {
66
+ setLoading(true);
67
+ setError(null);
68
+ try {
69
+ const nextSession = await client.signIn();
70
+ setSession(nextSession);
71
+ const balance = await client.getRelayClient().getProjectBalance();
72
+ setGasBalance(balance?.gasBalanceMicroStx ?? null);
73
+ return nextSession;
74
+ }
75
+ catch (e) {
76
+ const message = e instanceof Error ? e.message : 'Sign-in failed';
77
+ setError(message);
78
+ throw e;
79
+ }
80
+ finally {
81
+ setLoading(false);
82
+ }
83
+ }, [client]);
84
+ const logout = useCallback(() => {
85
+ client.logout();
86
+ clearSession();
87
+ setSession(null);
88
+ }, [client]);
89
+ const transfer = useCallback(async (recipient, amount) => {
90
+ setLoading(true);
91
+ setError(null);
92
+ try {
93
+ const txid = await client.transfer(recipient, amount);
94
+ const balance = await client.getRelayClient().getProjectBalance();
95
+ setGasBalance(balance?.gasBalanceMicroStx ?? null);
96
+ return txid;
97
+ }
98
+ catch (e) {
99
+ const message = e instanceof Error ? e.message : 'Transfer failed';
100
+ setError(message);
101
+ throw e;
102
+ }
103
+ finally {
104
+ setLoading(false);
105
+ }
106
+ }, [client]);
107
+ const invoke = useCallback(async (contract, fn, args) => {
108
+ setLoading(true);
109
+ setError(null);
110
+ try {
111
+ const txid = await client.invoke(contract, fn, args);
112
+ const balance = await client.getRelayClient().getProjectBalance();
113
+ setGasBalance(balance?.gasBalanceMicroStx ?? null);
114
+ return txid;
115
+ }
116
+ catch (e) {
117
+ const message = e instanceof Error ? e.message : 'Invoke failed';
118
+ setError(message);
119
+ throw e;
120
+ }
121
+ finally {
122
+ setLoading(false);
123
+ }
124
+ }, [client]);
125
+ return {
126
+ session,
127
+ isRegistered: session !== null,
128
+ loading,
129
+ error,
130
+ gasBalance,
131
+ gasTankAddress,
132
+ register,
133
+ signIn,
134
+ logout,
135
+ transfer,
136
+ invoke,
137
+ feeMode: client.getFeeMode(),
138
+ };
139
+ }
140
+ export { PasskeyClient };
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@stacks-passkey/react",
3
+ "version": "0.1.0",
4
+ "description": "React hooks for Stacks Passkey SDK",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "scripts": {
18
+ "build": "tsc",
19
+ "prepublishOnly": "npm run build"
20
+ },
21
+ "peerDependencies": {
22
+ "react": ">=18"
23
+ },
24
+ "dependencies": {
25
+ "@stacks-passkey/core": "^0.1.0"
26
+ },
27
+ "devDependencies": {
28
+ "@types/react": "^19.0.0",
29
+ "react": "^19.0.0",
30
+ "typescript": "^5.7.2"
31
+ },
32
+ "keywords": [
33
+ "stacks",
34
+ "passkey",
35
+ "webauthn",
36
+ "react"
37
+ ],
38
+ "license": "MIT",
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "git+https://github.com/Stacks-utils/stacks-passkey-sdk.git",
42
+ "directory": "packages/react"
43
+ },
44
+ "publishConfig": {
45
+ "access": "public"
46
+ }
47
+ }