@openfort/react-native 0.0.3 → 0.1.1
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 +0 -85
- package/dist/components/AuthBoundary.js +83 -0
- package/dist/components/index.js +10 -0
- package/dist/constants/config.js +9 -0
- package/dist/constants/index.js +1 -0
- package/dist/core/client.js +78 -0
- package/dist/core/context.js +37 -0
- package/dist/core/index.js +10 -0
- package/dist/core/provider.js +224 -0
- package/dist/core/storage.js +141 -0
- package/dist/hooks/auth/index.js +14 -0
- package/dist/hooks/auth/useAuthCallback.js +1 -0
- package/dist/hooks/auth/useCreateWalletPostAuth.js +22 -0
- package/dist/hooks/auth/useEmailAuth.js +176 -0
- package/dist/hooks/auth/useGuestAuth.js +52 -0
- package/dist/hooks/auth/useOAuth.js +292 -0
- package/dist/hooks/auth/useSignOut.js +48 -0
- package/dist/hooks/auth/useWalletAuth.js +133 -0
- package/dist/hooks/core/index.js +9 -0
- package/dist/hooks/core/useOpenfort.js +50 -0
- package/dist/hooks/core/useOpenfortClient.js +29 -0
- package/dist/hooks/core/useUser.js +10 -0
- package/dist/hooks/index.js +15 -0
- package/dist/hooks/wallet/index.js +7 -0
- package/dist/hooks/wallet/useWallets.js +389 -0
- package/dist/index.js +24 -1
- package/dist/lib/hookConsistency.js +16 -0
- package/dist/native/index.js +6 -0
- package/dist/native/oauth.js +183 -0
- package/dist/native/storage.js +178 -0
- package/dist/native/webview.js +157 -0
- package/dist/types/auth.js +1 -0
- package/dist/types/baseFlowState.js +8 -0
- package/dist/types/components/AuthBoundary.d.ts +85 -0
- package/dist/types/components/index.d.ts +10 -0
- package/dist/types/config.js +1 -0
- package/dist/types/constants/config.d.ts +9 -0
- package/dist/types/constants/index.d.ts +1 -0
- package/dist/types/core/client.d.ts +24 -0
- package/dist/types/core/context.d.ts +61 -0
- package/dist/types/core/index.d.ts +8 -0
- package/dist/types/core/provider.d.ts +126 -0
- package/dist/types/core/storage.d.ts +34 -0
- package/dist/types/hex.js +1 -0
- package/dist/types/hookOption.js +1 -0
- package/dist/types/hooks/auth/index.d.ts +10 -0
- package/dist/types/hooks/auth/useAuthCallback.d.ts +0 -0
- package/dist/types/hooks/auth/useCreateWalletPostAuth.d.ts +6 -0
- package/dist/types/hooks/auth/useEmailAuth.d.ts +59 -0
- package/dist/types/hooks/auth/useGuestAuth.d.ts +39 -0
- package/dist/types/hooks/auth/useOAuth.d.ts +62 -0
- package/dist/types/hooks/auth/useSignOut.d.ts +9 -0
- package/dist/types/hooks/auth/useWalletAuth.d.ts +48 -0
- package/dist/types/hooks/core/index.d.ts +8 -0
- package/dist/types/hooks/core/useOpenfort.d.ts +38 -0
- package/dist/types/hooks/core/useOpenfortClient.d.ts +29 -0
- package/dist/types/hooks/core/useUser.d.ts +5 -0
- package/dist/types/hooks/index.d.ts +12 -0
- package/dist/types/hooks/wallet/index.d.ts +6 -0
- package/dist/types/hooks/wallet/useWallets.d.ts +74 -0
- package/dist/types/index.d.ts +18 -1
- package/dist/types/index.js +2 -0
- package/dist/types/lib/hookConsistency.d.ts +14 -0
- package/dist/types/native/index.d.ts +5 -0
- package/dist/types/native/oauth.d.ts +91 -0
- package/dist/types/native/storage.d.ts +50 -0
- package/dist/types/native/webview.d.ts +50 -0
- package/dist/types/oauth.js +8 -0
- package/dist/types/openfortError.js +27 -0
- package/dist/types/predicates.js +101 -0
- package/dist/types/state.js +1 -0
- package/dist/types/types/auth.d.ts +168 -0
- package/dist/types/types/baseFlowState.d.ts +14 -0
- package/dist/types/types/config.d.ts +71 -0
- package/dist/types/types/hex.d.ts +1 -0
- package/dist/types/types/hookOption.d.ts +9 -0
- package/dist/types/types/index.d.ts +38 -0
- package/dist/types/types/oauth.d.ts +74 -0
- package/dist/types/types/openfortError.d.ts +13 -0
- package/dist/types/types/predicates.d.ts +64 -0
- package/dist/types/types/state.d.ts +0 -0
- package/dist/types/types/wallet.d.ts +262 -0
- package/dist/types/wallet.js +1 -0
- package/package.json +33 -19
- package/dist/Iframe.js +0 -84
- package/dist/types/Iframe.d.ts +0 -6
- package/polyfills/index.ts +0 -89
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { useCallback } from 'react';
|
|
2
|
+
import { useOpenfortContext } from '../../core/context';
|
|
3
|
+
import { onError, onSuccess } from '../../lib/hookConsistency';
|
|
4
|
+
import { OpenfortError, OpenfortErrorType } from '../../types/openfortError';
|
|
5
|
+
const mapStatus = (status) => {
|
|
6
|
+
return {
|
|
7
|
+
isLoading: status.status === 'generating-message' || status.status === 'awaiting-signature' || status.status === 'submitting-signature',
|
|
8
|
+
isError: status.status === 'error',
|
|
9
|
+
isSuccess: status.status === 'done',
|
|
10
|
+
error: "error" in status ? status.error : null,
|
|
11
|
+
isAwaitingSignature: status.status === 'awaiting-signature',
|
|
12
|
+
isGeneratingMessage: status.status === 'generating-message',
|
|
13
|
+
isSubmittingSignature: status.status === 'submitting-signature',
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
export function useWalletAuth(hookOptions) {
|
|
17
|
+
const { client, siweState, setSiweState, _internal } = useOpenfortContext();
|
|
18
|
+
const generateSiweMessage = useCallback(async (args) => {
|
|
19
|
+
try {
|
|
20
|
+
setSiweState({ status: 'generating-message' });
|
|
21
|
+
// Get wallet address from the external wallet
|
|
22
|
+
const walletAddress = typeof args.wallet === 'string' ? args.wallet : args.wallet.address;
|
|
23
|
+
const result = await client.auth.initSIWE({
|
|
24
|
+
address: walletAddress,
|
|
25
|
+
});
|
|
26
|
+
// Build the SIWE message
|
|
27
|
+
const siweMessage = `${args.from.domain} wants you to sign in with your Ethereum account:\n${walletAddress}\n\nSign in to ${args.from.domain}\n\nURI: ${args.from.uri}\nVersion: 1\nChain ID: 1\nNonce: ${result.nonce}\nIssued At: ${new Date().toISOString()}`;
|
|
28
|
+
setSiweState({
|
|
29
|
+
status: 'awaiting-signature',
|
|
30
|
+
});
|
|
31
|
+
return onSuccess({
|
|
32
|
+
hookOptions,
|
|
33
|
+
options: args,
|
|
34
|
+
data: { message: siweMessage },
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
const errorObj = error instanceof Error ? error : new Error('Failed to generate SIWE message');
|
|
39
|
+
setSiweState({
|
|
40
|
+
status: 'error',
|
|
41
|
+
error: errorObj
|
|
42
|
+
});
|
|
43
|
+
return onError({
|
|
44
|
+
hookOptions,
|
|
45
|
+
options: args,
|
|
46
|
+
error: new OpenfortError('Failed to generate SIWE message', OpenfortErrorType.AUTHENTICATION_ERROR, { error: errorObj }),
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}, [client, setSiweState]);
|
|
50
|
+
const linkSiwe = useCallback(async (opts) => {
|
|
51
|
+
try {
|
|
52
|
+
setSiweState({ status: 'submitting-signature' });
|
|
53
|
+
const message = opts.messageOverride || '';
|
|
54
|
+
if (!message) {
|
|
55
|
+
throw new Error('SIWE message is required. Call generateSiweMessage first.');
|
|
56
|
+
}
|
|
57
|
+
// Get current user access token for linking
|
|
58
|
+
const accessToken = await client.getAccessToken();
|
|
59
|
+
if (!accessToken) {
|
|
60
|
+
throw new Error('User must be authenticated to link wallet');
|
|
61
|
+
}
|
|
62
|
+
const result = await client.auth.authenticateWithSIWE({
|
|
63
|
+
signature: opts.signature,
|
|
64
|
+
message: message,
|
|
65
|
+
walletClientType: 'unknown',
|
|
66
|
+
connectorType: 'unknown',
|
|
67
|
+
});
|
|
68
|
+
setSiweState({ status: 'done' });
|
|
69
|
+
const user = result.player;
|
|
70
|
+
// Refresh user state to reflect SIWE linking
|
|
71
|
+
await _internal.refreshUserState();
|
|
72
|
+
return onSuccess({
|
|
73
|
+
hookOptions,
|
|
74
|
+
options: opts,
|
|
75
|
+
data: { user },
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
catch (e) {
|
|
79
|
+
const error = new OpenfortError('Failed to link in with Ethereum', OpenfortErrorType.AUTHENTICATION_ERROR, { error: e });
|
|
80
|
+
setSiweState({
|
|
81
|
+
status: 'error',
|
|
82
|
+
error
|
|
83
|
+
});
|
|
84
|
+
return onError({
|
|
85
|
+
hookOptions,
|
|
86
|
+
options: opts,
|
|
87
|
+
error
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}, [client, siweState, setSiweState, _internal]);
|
|
91
|
+
const signInWithSiwe = useCallback(async (opts) => {
|
|
92
|
+
try {
|
|
93
|
+
setSiweState({ status: 'submitting-signature' });
|
|
94
|
+
const message = opts.messageOverride || '';
|
|
95
|
+
if (!message) {
|
|
96
|
+
throw new Error('SIWE message is required. Call generateSiweMessage first.');
|
|
97
|
+
}
|
|
98
|
+
const result = await client.auth.authenticateWithSIWE({
|
|
99
|
+
signature: opts.signature,
|
|
100
|
+
message: message,
|
|
101
|
+
walletClientType: 'unknown',
|
|
102
|
+
connectorType: 'unknown'
|
|
103
|
+
});
|
|
104
|
+
setSiweState({ status: 'done' });
|
|
105
|
+
const user = result.player;
|
|
106
|
+
// Refresh user state in provider
|
|
107
|
+
await _internal.refreshUserState(user);
|
|
108
|
+
return onSuccess({
|
|
109
|
+
hookOptions,
|
|
110
|
+
options: opts,
|
|
111
|
+
data: { user },
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
catch (e) {
|
|
115
|
+
const error = new OpenfortError('Failed to sign in with Ethereum', OpenfortErrorType.AUTHENTICATION_ERROR, { error: e });
|
|
116
|
+
setSiweState({
|
|
117
|
+
status: 'error',
|
|
118
|
+
error
|
|
119
|
+
});
|
|
120
|
+
return onError({
|
|
121
|
+
hookOptions,
|
|
122
|
+
options: opts,
|
|
123
|
+
error
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}, [client, siweState, setSiweState, _internal]);
|
|
127
|
+
return {
|
|
128
|
+
generateSiweMessage,
|
|
129
|
+
signInWithSiwe,
|
|
130
|
+
linkSiwe,
|
|
131
|
+
...mapStatus(siweState),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core hooks index
|
|
3
|
+
*
|
|
4
|
+
* This module re-exports all core SDK hooks for convenient importing.
|
|
5
|
+
*/
|
|
6
|
+
// Core SDK hooks
|
|
7
|
+
export { useOpenfort } from './useOpenfort';
|
|
8
|
+
export { useOpenfortClient } from './useOpenfortClient';
|
|
9
|
+
export { useUser } from './useUser';
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core Openfort hook for accessing SDK state and methods
|
|
3
|
+
*/
|
|
4
|
+
import { useOpenfortContext } from '../../core/context';
|
|
5
|
+
/**
|
|
6
|
+
* Hook that exposes the core state of the Openfort SDK
|
|
7
|
+
*
|
|
8
|
+
* This hook provides access to the current authenticated user object,
|
|
9
|
+
* SDK initialization status, and core authentication methods.
|
|
10
|
+
*
|
|
11
|
+
* @returns The Openfort SDK's core state and methods
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* const { user, isReady, error, logout, getAccessToken } = useOpenfort();
|
|
16
|
+
*
|
|
17
|
+
* // Check if SDK is ready
|
|
18
|
+
* if (!isReady) {
|
|
19
|
+
* return <LoadingSpinner />;
|
|
20
|
+
* }
|
|
21
|
+
*
|
|
22
|
+
* // Handle initialization errors
|
|
23
|
+
* if (error) {
|
|
24
|
+
* return <ErrorDisplay error={error} />;
|
|
25
|
+
* }
|
|
26
|
+
*
|
|
27
|
+
* // Check authentication status
|
|
28
|
+
* if (!user) {
|
|
29
|
+
* return <LoginScreen />;
|
|
30
|
+
* }
|
|
31
|
+
*
|
|
32
|
+
* // User is authenticated
|
|
33
|
+
* return (
|
|
34
|
+
* <div>
|
|
35
|
+
* <h1>Welcome, {user.id}!</h1>
|
|
36
|
+
* <button onClick={logout}>Logout</button>
|
|
37
|
+
* </div>
|
|
38
|
+
* );
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export function useOpenfort() {
|
|
42
|
+
const { user, isReady, error, logout, getAccessToken } = useOpenfortContext();
|
|
43
|
+
return {
|
|
44
|
+
user,
|
|
45
|
+
isReady,
|
|
46
|
+
error,
|
|
47
|
+
logout,
|
|
48
|
+
getAccessToken,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { useOpenfortContext } from '../../core/context';
|
|
2
|
+
/**
|
|
3
|
+
* Hook for accessing the Openfort client instance directly
|
|
4
|
+
*
|
|
5
|
+
* This hook provides access to the underlying Openfort client for advanced use cases
|
|
6
|
+
* where you need direct access to the client methods.
|
|
7
|
+
*
|
|
8
|
+
* @returns The Openfort client instance
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* const client = useOpenfortClient();
|
|
13
|
+
*
|
|
14
|
+
* // Use client methods directly
|
|
15
|
+
* const customResult = await client.auth.customMethod();
|
|
16
|
+
*
|
|
17
|
+
* // Access client configuration
|
|
18
|
+
* console.log('App ID:', client.config.appId);
|
|
19
|
+
*
|
|
20
|
+
* // Check client status
|
|
21
|
+
* if (client.isInitialized) {
|
|
22
|
+
* // Perform operations that require initialization
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export function useOpenfortClient() {
|
|
27
|
+
const { client } = useOpenfortContext();
|
|
28
|
+
return client;
|
|
29
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { EmbeddedState } from "@openfort/openfort-js";
|
|
2
|
+
import { useOpenfortContext } from "../../core";
|
|
3
|
+
export function useUser() {
|
|
4
|
+
const { user, embeddedState, getAccessToken } = useOpenfortContext();
|
|
5
|
+
return {
|
|
6
|
+
user,
|
|
7
|
+
isAuthenticated: embeddedState !== EmbeddedState.NONE && embeddedState !== EmbeddedState.UNAUTHENTICATED,
|
|
8
|
+
getAccessToken,
|
|
9
|
+
};
|
|
10
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Openfort React Native SDK Hooks
|
|
3
|
+
*
|
|
4
|
+
* This module provides a comprehensive set of React hooks for integrating
|
|
5
|
+
* with the Openfort platform in React Native applications.
|
|
6
|
+
*
|
|
7
|
+
* The hooks are organized into the following categories:
|
|
8
|
+
* - Core: Core SDK functionality hooks
|
|
9
|
+
*/
|
|
10
|
+
// Re-export all core hooks
|
|
11
|
+
export * from './core';
|
|
12
|
+
// Re-export all authentication hooks
|
|
13
|
+
export * from './auth';
|
|
14
|
+
// Re-export all wallet hooks
|
|
15
|
+
export * from './wallet';
|
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook for embedded Ethereum wallet functionality
|
|
3
|
+
*/
|
|
4
|
+
import { AccountTypeEnum, ChainTypeEnum, EmbeddedState, RecoveryMethod, ShieldAuthType } from '@openfort/openfort-js';
|
|
5
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
6
|
+
import { useOpenfortContext } from '../../core/context';
|
|
7
|
+
import { onError, onSuccess } from '../../lib/hookConsistency';
|
|
8
|
+
import { OpenfortError, OpenfortErrorType } from '../../types/openfortError';
|
|
9
|
+
const mapWalletStatus = (status) => {
|
|
10
|
+
return {
|
|
11
|
+
error: status.error,
|
|
12
|
+
isError: status.status === 'error',
|
|
13
|
+
isSuccess: status.status === 'success',
|
|
14
|
+
isCreating: status.status === 'creating',
|
|
15
|
+
isConnecting: status.status === 'connecting',
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Hook for interacting with embedded Ethereum wallets
|
|
20
|
+
*
|
|
21
|
+
* This hook manages embedded Ethereum wallets based on the user's state from the provider.
|
|
22
|
+
* Wallet state is determined by polling in the provider, not by local state management.
|
|
23
|
+
*
|
|
24
|
+
* @param props - Optional configuration with callback functions
|
|
25
|
+
* @returns Current embedded Ethereum wallet state with actions
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```tsx
|
|
29
|
+
* const ethereumWallet = useEmbeddedEthereumWallet({
|
|
30
|
+
* onCreateWalletSuccess: (provider) => console.log('Ethereum wallet created:', provider),
|
|
31
|
+
* onCreateWalletError: (error) => console.error('Ethereum wallet creation failed:', error),
|
|
32
|
+
* });
|
|
33
|
+
*
|
|
34
|
+
* // Check wallet status and create if needed
|
|
35
|
+
* if (ethereumWallet.status === 'disconnected') {
|
|
36
|
+
* await ethereumWallet.create(); // Uses default chain
|
|
37
|
+
* // Or with specific chain: await ethereumWallet.create({ chainId: 1 });
|
|
38
|
+
* }
|
|
39
|
+
*
|
|
40
|
+
* // Use connected wallets
|
|
41
|
+
* if (ethereumWallet.status === 'connected' && ethereumWallet.wallets.length > 0) {
|
|
42
|
+
* const provider = await ethereumWallet.wallets[0].getProvider();
|
|
43
|
+
* // Use provider for Ethereum transactions
|
|
44
|
+
* }
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export function useWallets(hookOptions = {}) {
|
|
48
|
+
const { client, user, supportedChains, walletConfig, embeddedState, _internal } = useOpenfortContext();
|
|
49
|
+
const [embeddedAccounts, setEmbeddedAccounts] = useState([]);
|
|
50
|
+
const recoverPromiseRef = useRef(null);
|
|
51
|
+
const [activeWalletId, setActiveWalletId] = useState(null); // OPENFORT-JS Should provide this
|
|
52
|
+
const [status, setStatus] = useState({
|
|
53
|
+
status: "idle",
|
|
54
|
+
});
|
|
55
|
+
const activeWallet = useMemo(() => {
|
|
56
|
+
if (!activeWalletId || !embeddedAccounts)
|
|
57
|
+
return null;
|
|
58
|
+
const account = embeddedAccounts.find(acc => acc.id === activeWalletId);
|
|
59
|
+
if (!account)
|
|
60
|
+
return null;
|
|
61
|
+
return {
|
|
62
|
+
address: account.address,
|
|
63
|
+
implementationType: account.implementationType,
|
|
64
|
+
ownerAddress: account.ownerAddress,
|
|
65
|
+
chainType: account.chainType,
|
|
66
|
+
isActive: true,
|
|
67
|
+
isConnecting: false,
|
|
68
|
+
getProvider: async () => {
|
|
69
|
+
return await client.embeddedWallet.getEthereumProvider({ announceProvider: false });
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}, [activeWalletId, embeddedAccounts, client.embeddedWallet]);
|
|
73
|
+
const setActiveWallet = useCallback(async (options) => {
|
|
74
|
+
// If there's already a recovery in progress, return the existing promise
|
|
75
|
+
if (recoverPromiseRef.current) {
|
|
76
|
+
return recoverPromiseRef.current;
|
|
77
|
+
}
|
|
78
|
+
if (wallets.length === 0) {
|
|
79
|
+
return onError({
|
|
80
|
+
hookOptions,
|
|
81
|
+
options,
|
|
82
|
+
error: new OpenfortError('No embedded wallets available to set as active', OpenfortErrorType.WALLET_ERROR),
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
setStatus({
|
|
86
|
+
status: 'connecting',
|
|
87
|
+
address: options?.address,
|
|
88
|
+
});
|
|
89
|
+
// Create and store the recovery promise
|
|
90
|
+
recoverPromiseRef.current = (async () => {
|
|
91
|
+
try {
|
|
92
|
+
// Validate chainId if provided
|
|
93
|
+
let chainId;
|
|
94
|
+
if (options?.chainId) {
|
|
95
|
+
if (!supportedChains || !supportedChains.some(chain => chain.id === options.chainId)) {
|
|
96
|
+
throw new OpenfortError(`Chain ID ${options.chainId} is not supported. Supported chains: ${supportedChains?.map(c => c.id).join(', ') || 'none'}`, OpenfortErrorType.WALLET_ERROR);
|
|
97
|
+
}
|
|
98
|
+
chainId = options.chainId;
|
|
99
|
+
}
|
|
100
|
+
else if (supportedChains && supportedChains.length > 0) {
|
|
101
|
+
// Use the first supported chain as default
|
|
102
|
+
chainId = supportedChains[0].id;
|
|
103
|
+
}
|
|
104
|
+
// Create shield authentication object
|
|
105
|
+
let shieldAuthentication = null;
|
|
106
|
+
console.log('Using walletConfig:', walletConfig);
|
|
107
|
+
if (walletConfig) {
|
|
108
|
+
const accessToken = await client.getAccessToken();
|
|
109
|
+
if (!accessToken) {
|
|
110
|
+
throw new OpenfortError('Access token is required for shield authentication', OpenfortErrorType.WALLET_ERROR);
|
|
111
|
+
}
|
|
112
|
+
// Get encryption session from embedded wallet configuration
|
|
113
|
+
let encryptionSession;
|
|
114
|
+
if ('getEncryptionSession' in walletConfig && walletConfig.getEncryptionSession) {
|
|
115
|
+
encryptionSession = await walletConfig.getEncryptionSession();
|
|
116
|
+
}
|
|
117
|
+
shieldAuthentication = {
|
|
118
|
+
auth: ShieldAuthType.OPENFORT,
|
|
119
|
+
token: accessToken,
|
|
120
|
+
...(encryptionSession && { encryptionSession }),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
const address = options?.address || wallets[0]?.address;
|
|
124
|
+
const embeddedAccountToRecover = embeddedAccounts.find(account => account.chainId === chainId && account.address === address);
|
|
125
|
+
let embeddedAccount;
|
|
126
|
+
if (!embeddedAccountToRecover) {
|
|
127
|
+
// Different chain maybe?
|
|
128
|
+
// if (embeddedAccounts.some(account => account.address === address)) {
|
|
129
|
+
// create wallet with new chain
|
|
130
|
+
// embeddedAccount = await client.embeddedWallet.create({
|
|
131
|
+
// chainId: chainId!,
|
|
132
|
+
// accountType: AccountTypeEnum.SMART_ACCOUNT,
|
|
133
|
+
// chainType: ChainTypeEnum.EVM,
|
|
134
|
+
// shieldAuthentication: shieldAuthentication ?? undefined,
|
|
135
|
+
// recoveryParams: options?.recoveryPassword ? { password: options.recoveryPassword, recoveryMethod: RecoveryMethod.PASSWORD } : undefined
|
|
136
|
+
// });
|
|
137
|
+
// } else {
|
|
138
|
+
throw new OpenfortError(`No embedded account found for address ${address} on chain ID ${chainId}`, OpenfortErrorType.WALLET_ERROR);
|
|
139
|
+
// }
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
// Recover the embedded wallet with shield authentication
|
|
143
|
+
embeddedAccount = await client.embeddedWallet.recover({
|
|
144
|
+
account: embeddedAccountToRecover.id,
|
|
145
|
+
shieldAuthentication: shieldAuthentication ?? undefined,
|
|
146
|
+
recoveryParams: options?.recoveryPassword ? { password: options.recoveryPassword, recoveryMethod: RecoveryMethod.PASSWORD } : undefined
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
const wallet = {
|
|
150
|
+
address: embeddedAccount.address,
|
|
151
|
+
implementationType: embeddedAccount.implementationType,
|
|
152
|
+
ownerAddress: embeddedAccount.ownerAddress,
|
|
153
|
+
chainType: embeddedAccount.chainType,
|
|
154
|
+
isActive: true,
|
|
155
|
+
isConnecting: false,
|
|
156
|
+
getProvider: async () => {
|
|
157
|
+
return await client.embeddedWallet.getEthereumProvider({ announceProvider: false });
|
|
158
|
+
},
|
|
159
|
+
};
|
|
160
|
+
recoverPromiseRef.current = null;
|
|
161
|
+
setStatus({
|
|
162
|
+
status: 'success',
|
|
163
|
+
});
|
|
164
|
+
setActiveWalletId(embeddedAccount.id);
|
|
165
|
+
return onSuccess({
|
|
166
|
+
options,
|
|
167
|
+
hookOptions,
|
|
168
|
+
data: {
|
|
169
|
+
wallet,
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
catch (e) {
|
|
174
|
+
recoverPromiseRef.current = null;
|
|
175
|
+
const error = e instanceof OpenfortError ? e : new OpenfortError('Failed to recover embedded wallet', OpenfortErrorType.WALLET_ERROR);
|
|
176
|
+
setStatus({
|
|
177
|
+
status: 'error',
|
|
178
|
+
error,
|
|
179
|
+
});
|
|
180
|
+
return onError({
|
|
181
|
+
options,
|
|
182
|
+
hookOptions,
|
|
183
|
+
error,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
})();
|
|
187
|
+
return recoverPromiseRef.current;
|
|
188
|
+
}, [client, supportedChains, walletConfig, _internal, embeddedAccounts, hookOptions]);
|
|
189
|
+
// Fetch embedded wallets using embeddedWallet.list()
|
|
190
|
+
const fetchEmbeddedWallets = useCallback(async () => {
|
|
191
|
+
if (!client || embeddedState === EmbeddedState.NONE || embeddedState === EmbeddedState.UNAUTHENTICATED) {
|
|
192
|
+
setEmbeddedAccounts([]);
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
try {
|
|
196
|
+
const accounts = await client.embeddedWallet.list();
|
|
197
|
+
setEmbeddedAccounts(accounts);
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
setEmbeddedAccounts([]);
|
|
201
|
+
}
|
|
202
|
+
}, [client, embeddedState, user]);
|
|
203
|
+
useEffect(() => {
|
|
204
|
+
fetchEmbeddedWallets();
|
|
205
|
+
}, [fetchEmbeddedWallets]);
|
|
206
|
+
useEffect(() => {
|
|
207
|
+
(async () => {
|
|
208
|
+
try {
|
|
209
|
+
const embeddedAccount = await client.embeddedWallet.get();
|
|
210
|
+
setActiveWalletId(embeddedAccount.id);
|
|
211
|
+
}
|
|
212
|
+
catch {
|
|
213
|
+
setActiveWalletId(null);
|
|
214
|
+
}
|
|
215
|
+
})();
|
|
216
|
+
}, [setActiveWalletId, client]);
|
|
217
|
+
// Extract Ethereum wallets from embedded accounts
|
|
218
|
+
const wallets = useMemo(() => (embeddedAccounts
|
|
219
|
+
.reduce((acc, account) => {
|
|
220
|
+
if (!acc.some(a => a.address === account.address)) {
|
|
221
|
+
acc.push(account);
|
|
222
|
+
}
|
|
223
|
+
return acc;
|
|
224
|
+
}, [])
|
|
225
|
+
.map((account) => ({
|
|
226
|
+
address: account.address,
|
|
227
|
+
implementationType: account.implementationType,
|
|
228
|
+
ownerAddress: account.ownerAddress,
|
|
229
|
+
chainType: account.chainType,
|
|
230
|
+
isActive: activeWalletId === account.id,
|
|
231
|
+
isConnecting: status.status === "connecting" && status.address === account.address,
|
|
232
|
+
getProvider: async () => {
|
|
233
|
+
return await client.embeddedWallet.getEthereumProvider({ announceProvider: false });
|
|
234
|
+
},
|
|
235
|
+
}))), [embeddedAccounts, activeWalletId, status.status === "connecting", client.embeddedWallet]);
|
|
236
|
+
const create = useCallback(async (options) => {
|
|
237
|
+
console.log('Creating Ethereum wallet with options:', options);
|
|
238
|
+
try {
|
|
239
|
+
setStatus({
|
|
240
|
+
status: 'creating',
|
|
241
|
+
});
|
|
242
|
+
// Validate chainId if provided
|
|
243
|
+
let chainId;
|
|
244
|
+
if (options?.chainId) {
|
|
245
|
+
if (!supportedChains || !supportedChains.some(chain => chain.id === options.chainId)) {
|
|
246
|
+
throw new OpenfortError(`Chain ID ${options.chainId} is not supported. Supported chains: ${supportedChains?.map(c => c.id).join(', ') || 'none'}`, OpenfortErrorType.WALLET_ERROR);
|
|
247
|
+
}
|
|
248
|
+
chainId = options.chainId;
|
|
249
|
+
}
|
|
250
|
+
else if (supportedChains && supportedChains.length > 0) {
|
|
251
|
+
// Use the first supported chain as default
|
|
252
|
+
chainId = supportedChains[0].id;
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
throw new OpenfortError('No supported chains available for wallet creation', OpenfortErrorType.WALLET_ERROR);
|
|
256
|
+
}
|
|
257
|
+
console.log('Using chain ID for wallet creation:', chainId);
|
|
258
|
+
// Create shield authentication object
|
|
259
|
+
let shieldAuthentication = null;
|
|
260
|
+
if (walletConfig) {
|
|
261
|
+
const accessToken = await client.getAccessToken();
|
|
262
|
+
if (!accessToken) {
|
|
263
|
+
throw new Error('Access token is required for shield authentication');
|
|
264
|
+
}
|
|
265
|
+
console.log('Access token for shield authentication:', accessToken);
|
|
266
|
+
// Get encryption session from embedded wallet configuration
|
|
267
|
+
let encryptionSession;
|
|
268
|
+
if ('getEncryptionSession' in walletConfig && walletConfig.getEncryptionSession) {
|
|
269
|
+
encryptionSession = await walletConfig.getEncryptionSession();
|
|
270
|
+
console.log('Encryption session for shield authentication:', encryptionSession);
|
|
271
|
+
}
|
|
272
|
+
shieldAuthentication = {
|
|
273
|
+
auth: ShieldAuthType.OPENFORT,
|
|
274
|
+
token: accessToken,
|
|
275
|
+
...(encryptionSession && { encryptionSession }),
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
console.log('Shield authentication object:', shieldAuthentication);
|
|
279
|
+
// Configure embedded wallet with shield authentication
|
|
280
|
+
const embeddedAccount = await client.embeddedWallet.create({
|
|
281
|
+
chainId,
|
|
282
|
+
accountType: AccountTypeEnum.SMART_ACCOUNT,
|
|
283
|
+
chainType: options?.chainType || ChainTypeEnum.EVM,
|
|
284
|
+
shieldAuthentication: shieldAuthentication ?? undefined,
|
|
285
|
+
recoveryParams: options?.recoveryPassword ? { password: options.recoveryPassword, recoveryMethod: RecoveryMethod.PASSWORD } : undefined
|
|
286
|
+
});
|
|
287
|
+
console.log('Embedded wallet configured with shield authentication');
|
|
288
|
+
// Get the Ethereum provider
|
|
289
|
+
const provider = await client.embeddedWallet.getEthereumProvider({
|
|
290
|
+
announceProvider: false,
|
|
291
|
+
...(options?.policyId && { policy: options.policyId }),
|
|
292
|
+
});
|
|
293
|
+
// Refetch the list of wallets to ensure the state is up to date
|
|
294
|
+
await fetchEmbeddedWallets();
|
|
295
|
+
setActiveWalletId(embeddedAccount.id);
|
|
296
|
+
setStatus({
|
|
297
|
+
status: 'success',
|
|
298
|
+
});
|
|
299
|
+
return onSuccess({
|
|
300
|
+
hookOptions,
|
|
301
|
+
options,
|
|
302
|
+
data: {
|
|
303
|
+
provider,
|
|
304
|
+
wallet: {
|
|
305
|
+
address: embeddedAccount.address,
|
|
306
|
+
implementationType: embeddedAccount.implementationType,
|
|
307
|
+
ownerAddress: embeddedAccount.ownerAddress,
|
|
308
|
+
chainType: embeddedAccount.chainType,
|
|
309
|
+
isActive: true,
|
|
310
|
+
isConnecting: false,
|
|
311
|
+
getProvider: async () => {
|
|
312
|
+
return await client.embeddedWallet.getEthereumProvider();
|
|
313
|
+
},
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
catch (e) {
|
|
319
|
+
const error = e instanceof OpenfortError ? e : new OpenfortError('Failed to create Ethereum wallet', OpenfortErrorType.WALLET_ERROR, { error: e });
|
|
320
|
+
setStatus({
|
|
321
|
+
status: 'error',
|
|
322
|
+
error,
|
|
323
|
+
});
|
|
324
|
+
return onError({
|
|
325
|
+
hookOptions,
|
|
326
|
+
options,
|
|
327
|
+
error
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
}, [client, supportedChains, walletConfig, _internal, user]);
|
|
331
|
+
const setRecovery = useCallback(async (params) => {
|
|
332
|
+
try {
|
|
333
|
+
setStatus({
|
|
334
|
+
status: 'loading',
|
|
335
|
+
});
|
|
336
|
+
// Set embedded wallet recovery method
|
|
337
|
+
if (params.recoveryMethod === 'password') {
|
|
338
|
+
await client.embeddedWallet.setEmbeddedRecovery({
|
|
339
|
+
recoveryMethod: RecoveryMethod.PASSWORD,
|
|
340
|
+
recoveryPassword: params.recoveryPassword
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
else {
|
|
344
|
+
await client.embeddedWallet.setEmbeddedRecovery({
|
|
345
|
+
recoveryMethod: RecoveryMethod.AUTOMATIC
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
// Get the updated embedded account
|
|
349
|
+
const embeddedAccount = await client.embeddedWallet.get();
|
|
350
|
+
// Refresh user state to reflect recovery changes
|
|
351
|
+
await _internal.refreshUserState();
|
|
352
|
+
setStatus({ status: 'success' });
|
|
353
|
+
return onSuccess({
|
|
354
|
+
hookOptions,
|
|
355
|
+
options: params,
|
|
356
|
+
data: {
|
|
357
|
+
wallet: {
|
|
358
|
+
address: embeddedAccount.address,
|
|
359
|
+
implementationType: embeddedAccount.implementationType,
|
|
360
|
+
ownerAddress: embeddedAccount.ownerAddress,
|
|
361
|
+
chainType: embeddedAccount.chainType,
|
|
362
|
+
isActive: true,
|
|
363
|
+
isConnecting: false,
|
|
364
|
+
getProvider: async () => {
|
|
365
|
+
return await client.embeddedWallet.getEthereumProvider({ announceProvider: false });
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
catch (error) {
|
|
372
|
+
const errorObj = error instanceof Error ? error : new Error('Failed to set wallet recovery');
|
|
373
|
+
return onError({
|
|
374
|
+
hookOptions,
|
|
375
|
+
options: params,
|
|
376
|
+
error: new OpenfortError('Failed to set wallet recovery', OpenfortErrorType.WALLET_ERROR, { error: errorObj }),
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
}, [client, _internal]);
|
|
380
|
+
return {
|
|
381
|
+
wallets,
|
|
382
|
+
activeWallet,
|
|
383
|
+
setRecovery,
|
|
384
|
+
setActiveWallet,
|
|
385
|
+
createWallet: create,
|
|
386
|
+
...mapWalletStatus(status),
|
|
387
|
+
exportPrivateKey: client.embeddedWallet.exportPrivateKey,
|
|
388
|
+
};
|
|
389
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -1 +1,24 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Openfort React Native SDK
|
|
3
|
+
*
|
|
4
|
+
* A comprehensive React Native SDK for integrating with the Openfort platform.
|
|
5
|
+
* This SDK provides authentication, embedded wallets, session management, and UI components
|
|
6
|
+
* for building decentralized applications on React Native.
|
|
7
|
+
*
|
|
8
|
+
* @author Openfort
|
|
9
|
+
* @version 0.1.0
|
|
10
|
+
*/
|
|
11
|
+
// Re-export enums and values from @openfort/openfort-js
|
|
12
|
+
export { OAuthProvider, } from '@openfort/openfort-js';
|
|
13
|
+
// Re-export all types from the main types module
|
|
14
|
+
export * from './types';
|
|
15
|
+
// Re-export all hooks
|
|
16
|
+
export * from './hooks';
|
|
17
|
+
// Re-export all components and UI elements
|
|
18
|
+
export * from './components';
|
|
19
|
+
// Re-export core functionality
|
|
20
|
+
export * from './core';
|
|
21
|
+
// Re-export native functionality
|
|
22
|
+
export * from './native';
|
|
23
|
+
// Re-export constants
|
|
24
|
+
export * from './constants';
|