@openfort/react-native 0.1.11 → 0.1.13
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/dist/constants/config.js +1 -1
- package/dist/core/client.js +4 -1
- package/dist/core/provider.js +6 -0
- package/dist/hooks/wallet/index.js +0 -1
- package/dist/hooks/wallet/useWallets.js +88 -44
- package/dist/index.js +3 -1
- package/dist/lib/environmentValidation.js +25 -0
- package/dist/types/constants/config.d.ts +1 -1
- package/dist/types/core/provider.d.ts +3 -1
- package/dist/types/hooks/wallet/index.d.ts +0 -1
- package/dist/types/index.d.ts +3 -2
- package/dist/types/lib/environmentValidation.d.ts +7 -0
- package/package.json +2 -2
- package/dist/hooks/wallet/useWallet.js +0 -32
- package/dist/types/hooks/wallet/useWallet.d.ts +0 -28
package/dist/constants/config.js
CHANGED
package/dist/core/client.js
CHANGED
|
@@ -39,7 +39,10 @@ export function createOpenfortClient({ baseConfiguration, overrides, shieldConfi
|
|
|
39
39
|
// baseUrl,
|
|
40
40
|
// logLevel,
|
|
41
41
|
return new OpenfortClient({
|
|
42
|
-
baseConfiguration
|
|
42
|
+
baseConfiguration: {
|
|
43
|
+
nativeAppIdentifier: nativeAppId,
|
|
44
|
+
...baseConfiguration
|
|
45
|
+
},
|
|
43
46
|
overrides: {
|
|
44
47
|
...overrides,
|
|
45
48
|
crypto: {
|
package/dist/core/provider.js
CHANGED
|
@@ -4,6 +4,7 @@ import { OpenfortContext } from './context';
|
|
|
4
4
|
import { createOpenfortClient, setDefaultClient } from './client';
|
|
5
5
|
import { EmbeddedWalletWebView, WebViewUtils } from '../native';
|
|
6
6
|
import { logger, getEmbeddedStateName } from '../lib/logger';
|
|
7
|
+
import { validateEnvironment } from '../lib/environmentValidation';
|
|
7
8
|
/**
|
|
8
9
|
* Starts polling the embedded wallet state and invokes the callback when transitions occur.
|
|
9
10
|
*
|
|
@@ -69,6 +70,11 @@ function startEmbeddedStatePolling(client, onChange, intervalMs = 1000) {
|
|
|
69
70
|
* ```
|
|
70
71
|
*/
|
|
71
72
|
export const OpenfortProvider = ({ children, publishableKey, customAuth, supportedChains, walletConfig, overrides, thirdPartyAuth, verbose = false, }) => {
|
|
73
|
+
// Validate environment variables before anything else
|
|
74
|
+
validateEnvironment({
|
|
75
|
+
publishableKey,
|
|
76
|
+
shieldPublishableKey: walletConfig?.shieldPublishableKey,
|
|
77
|
+
});
|
|
72
78
|
// Prevent multiple OpenfortProvider instances
|
|
73
79
|
const existingContext = React.useContext(OpenfortContext);
|
|
74
80
|
if (existingContext) {
|
|
@@ -73,6 +73,39 @@ export function useWallets(hookOptions = {}) {
|
|
|
73
73
|
},
|
|
74
74
|
};
|
|
75
75
|
}, [activeWalletId, embeddedAccounts, client.embeddedWallet]);
|
|
76
|
+
const resolveEncryptionSession = useCallback(async () => {
|
|
77
|
+
if (!walletConfig) {
|
|
78
|
+
throw new OpenfortError('Encryption session configuration is required', OpenfortErrorType.WALLET_ERROR);
|
|
79
|
+
}
|
|
80
|
+
if (walletConfig.getEncryptionSession) {
|
|
81
|
+
return await walletConfig.getEncryptionSession();
|
|
82
|
+
}
|
|
83
|
+
if (walletConfig.createEncryptedSessionEndpoint) {
|
|
84
|
+
try {
|
|
85
|
+
const response = await fetch(walletConfig.createEncryptedSessionEndpoint, {
|
|
86
|
+
method: 'POST',
|
|
87
|
+
headers: {
|
|
88
|
+
'Content-Type': 'application/json',
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
if (!response.ok) {
|
|
92
|
+
throw new OpenfortError('Failed to create encryption session', OpenfortErrorType.WALLET_ERROR, { status: response.status });
|
|
93
|
+
}
|
|
94
|
+
const body = await response.json();
|
|
95
|
+
if (!body?.session || typeof body.session !== 'string') {
|
|
96
|
+
throw new OpenfortError('Encryption session response is missing the `session` property', OpenfortErrorType.WALLET_ERROR);
|
|
97
|
+
}
|
|
98
|
+
return body.session;
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
if (error instanceof OpenfortError) {
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
104
|
+
throw new OpenfortError('Failed to create encryption session', OpenfortErrorType.WALLET_ERROR, { error });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
throw new OpenfortError('Encryption session configuration is required', OpenfortErrorType.WALLET_ERROR);
|
|
108
|
+
}, [walletConfig]);
|
|
76
109
|
const setActiveWallet = useCallback(async (options) => {
|
|
77
110
|
// If there's already a recovery in progress, return the existing promise
|
|
78
111
|
if (recoverPromiseRef.current) {
|
|
@@ -105,22 +138,22 @@ export function useWallets(hookOptions = {}) {
|
|
|
105
138
|
chainId = supportedChains[0].id;
|
|
106
139
|
}
|
|
107
140
|
const address = options?.address || wallets[0]?.address;
|
|
108
|
-
|
|
141
|
+
// Find account to recover based on whether we're using EOA or Smart Account
|
|
142
|
+
let embeddedAccountToRecover;
|
|
143
|
+
if (walletConfig?.accountType === AccountTypeEnum.EOA) {
|
|
144
|
+
// For EOAs, match only by address (EOAs work across all chains)
|
|
145
|
+
embeddedAccountToRecover = embeddedAccounts.find(account => account.address.toLowerCase() === address?.toLowerCase());
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
// For Smart Accounts, match by both address and chainId (Smart Accounts are chain-specific)
|
|
149
|
+
embeddedAccountToRecover = embeddedAccounts.find(account => account.chainId === chainId && account.address.toLowerCase() === address?.toLowerCase());
|
|
150
|
+
}
|
|
109
151
|
let embeddedAccount;
|
|
110
152
|
if (!embeddedAccountToRecover) {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
// chainId: chainId!,
|
|
116
|
-
// accountType: AccountTypeEnum.SMART_ACCOUNT,
|
|
117
|
-
// chainType: ChainTypeEnum.EVM,
|
|
118
|
-
// shieldAuthentication: shieldAuthentication ?? undefined,
|
|
119
|
-
// recoveryParams: options?.recoveryPassword ? { password: options.recoveryPassword, recoveryMethod: RecoveryMethod.PASSWORD } : undefined
|
|
120
|
-
// });
|
|
121
|
-
// } else {
|
|
122
|
-
throw new OpenfortError(`No embedded account found for address ${address} on chain ID ${chainId}`, OpenfortErrorType.WALLET_ERROR);
|
|
123
|
-
// }
|
|
153
|
+
const errorMsg = walletConfig?.accountType === AccountTypeEnum.EOA
|
|
154
|
+
? `No embedded EOA account found for address ${address}`
|
|
155
|
+
: `No embedded account found for address ${address} on chain ID ${chainId}`;
|
|
156
|
+
throw new OpenfortError(errorMsg, OpenfortErrorType.WALLET_ERROR);
|
|
124
157
|
}
|
|
125
158
|
else {
|
|
126
159
|
let recoveryParams;
|
|
@@ -132,12 +165,9 @@ export function useWallets(hookOptions = {}) {
|
|
|
132
165
|
};
|
|
133
166
|
}
|
|
134
167
|
else {
|
|
135
|
-
if (!walletConfig?.getEncryptionSession) {
|
|
136
|
-
throw new OpenfortError('Encryption session (walletConfig.getEncryptionSession) is required for automatic recovery', OpenfortErrorType.WALLET_ERROR);
|
|
137
|
-
}
|
|
138
168
|
recoveryParams = {
|
|
139
169
|
recoveryMethod: RecoveryMethod.AUTOMATIC,
|
|
140
|
-
encryptionSession: await
|
|
170
|
+
encryptionSession: await resolveEncryptionSession()
|
|
141
171
|
};
|
|
142
172
|
}
|
|
143
173
|
// Recover the embedded wallet with shield authentication
|
|
@@ -185,7 +215,7 @@ export function useWallets(hookOptions = {}) {
|
|
|
185
215
|
}
|
|
186
216
|
})();
|
|
187
217
|
return recoverPromiseRef.current;
|
|
188
|
-
}, [client, supportedChains,
|
|
218
|
+
}, [client, supportedChains, resolveEncryptionSession, _internal, embeddedAccounts, hookOptions]);
|
|
189
219
|
// Fetch embedded wallets using embeddedWallet.list()
|
|
190
220
|
const fetchEmbeddedWallets = useCallback(async () => {
|
|
191
221
|
if (!client || embeddedState === EmbeddedState.NONE || embeddedState === EmbeddedState.UNAUTHENTICATED) {
|
|
@@ -193,13 +223,18 @@ export function useWallets(hookOptions = {}) {
|
|
|
193
223
|
return;
|
|
194
224
|
}
|
|
195
225
|
try {
|
|
196
|
-
const accounts = await client.embeddedWallet.list(
|
|
226
|
+
const accounts = await client.embeddedWallet.list({
|
|
227
|
+
limit: 100,
|
|
228
|
+
// If its EOA we want all accounts, otherwise we want only smart accounts
|
|
229
|
+
accountType: walletConfig?.accountType === AccountTypeEnum.EOA ?
|
|
230
|
+
undefined : AccountTypeEnum.SMART_ACCOUNT
|
|
231
|
+
});
|
|
197
232
|
setEmbeddedAccounts(accounts);
|
|
198
233
|
}
|
|
199
234
|
catch {
|
|
200
235
|
setEmbeddedAccounts([]);
|
|
201
236
|
}
|
|
202
|
-
}, [client, embeddedState, user]);
|
|
237
|
+
}, [client, embeddedState, user, walletConfig]);
|
|
203
238
|
useEffect(() => {
|
|
204
239
|
fetchEmbeddedWallets();
|
|
205
240
|
}, [fetchEmbeddedWallets]);
|
|
@@ -233,24 +268,36 @@ export function useWallets(hookOptions = {}) {
|
|
|
233
268
|
})();
|
|
234
269
|
}, [setActiveWalletId, client]);
|
|
235
270
|
// Extract Ethereum wallets from embedded accounts
|
|
236
|
-
const wallets = useMemo(() =>
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
271
|
+
const wallets = useMemo(() => {
|
|
272
|
+
// Deduplicate accounts based on account type
|
|
273
|
+
const deduplicatedAccounts = embeddedAccounts.reduce((acc, account) => {
|
|
274
|
+
if (walletConfig?.accountType === AccountTypeEnum.EOA) {
|
|
275
|
+
// For EOAs, deduplicate by address only (EOAs work across all chains)
|
|
276
|
+
if (!acc.some(a => a.address.toLowerCase() === account.address.toLowerCase())) {
|
|
277
|
+
acc.push(account);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
// For Smart Accounts, keep separate entries per chain (they're chain-specific)
|
|
282
|
+
// Only deduplicate exact matches (same address AND same chainId)
|
|
283
|
+
if (!acc.some(a => a.address.toLowerCase() === account.address.toLowerCase() && a.chainId === account.chainId)) {
|
|
284
|
+
acc.push(account);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return acc;
|
|
288
|
+
}, []);
|
|
289
|
+
return deduplicatedAccounts.map((account) => ({
|
|
290
|
+
address: account.address,
|
|
291
|
+
implementationType: account.implementationType,
|
|
292
|
+
ownerAddress: account.ownerAddress,
|
|
293
|
+
chainType: account.chainType,
|
|
294
|
+
isActive: activeWalletId === account.id,
|
|
295
|
+
isConnecting: status.status === "connecting" && status.address === account.address,
|
|
296
|
+
getProvider: async () => {
|
|
297
|
+
return await getEthereumProvider();
|
|
298
|
+
},
|
|
299
|
+
}));
|
|
300
|
+
}, [embeddedAccounts, activeWalletId, status.status, walletConfig?.accountType, client.embeddedWallet]);
|
|
254
301
|
const create = useCallback(async (options) => {
|
|
255
302
|
logger.info('Creating Ethereum wallet with options', options);
|
|
256
303
|
try {
|
|
@@ -282,12 +329,9 @@ export function useWallets(hookOptions = {}) {
|
|
|
282
329
|
};
|
|
283
330
|
}
|
|
284
331
|
else {
|
|
285
|
-
if (!walletConfig?.getEncryptionSession) {
|
|
286
|
-
throw new OpenfortError('Encryption session (walletConfig.getEncryptionSession) is required for automatic recovery', OpenfortErrorType.WALLET_ERROR);
|
|
287
|
-
}
|
|
288
332
|
recoveryParams = {
|
|
289
333
|
recoveryMethod: RecoveryMethod.AUTOMATIC,
|
|
290
|
-
encryptionSession: await
|
|
334
|
+
encryptionSession: await resolveEncryptionSession()
|
|
291
335
|
};
|
|
292
336
|
}
|
|
293
337
|
// Configure embedded wallet with shield authentication
|
|
@@ -337,7 +381,7 @@ export function useWallets(hookOptions = {}) {
|
|
|
337
381
|
error
|
|
338
382
|
});
|
|
339
383
|
}
|
|
340
|
-
}, [client, supportedChains, walletConfig, _internal, user]);
|
|
384
|
+
}, [client, supportedChains, walletConfig, resolveEncryptionSession, _internal, user]);
|
|
341
385
|
const setRecovery = useCallback(async (params) => {
|
|
342
386
|
try {
|
|
343
387
|
setStatus({
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
// Re-export commonly used types from @openfort/openfort-js
|
|
11
11
|
export { OpenfortError, RecoveryMethod, Openfort as OpenfortClient, OpenfortConfiguration, ShieldConfiguration, EmbeddedState, } from '@openfort/openfort-js';
|
|
12
12
|
// Re-export enums and values from @openfort/openfort-js
|
|
13
|
-
export { OAuthProvider, } from '@openfort/openfort-js';
|
|
13
|
+
export { OAuthProvider, AccountTypeEnum, } from '@openfort/openfort-js';
|
|
14
|
+
// Re-export event listener functionality from @openfort/openfort-js
|
|
15
|
+
export { openfortEvents, OpenfortEvents, } from '@openfort/openfort-js';
|
|
14
16
|
// Re-export all types from the main types module
|
|
15
17
|
export * from './types';
|
|
16
18
|
// Re-export all hooks
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maps config keys to their corresponding .env variable names
|
|
3
|
+
*/
|
|
4
|
+
const KEY_TO_ENV_VAR = {
|
|
5
|
+
publishableKey: 'OPENFORT_PUBLISHABLE_KEY',
|
|
6
|
+
shieldPublishableKey: 'OPENFORT_SHIELD_PUBLISHABLE_KEY',
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Validates that required environment variables are present.
|
|
10
|
+
*
|
|
11
|
+
* @param config - Dictionary of configuration keys and their values
|
|
12
|
+
* @throws Error if required environment variables are missing
|
|
13
|
+
*/
|
|
14
|
+
export function validateEnvironment(config) {
|
|
15
|
+
const missing = [];
|
|
16
|
+
Object.entries(config).forEach(([key, value]) => {
|
|
17
|
+
if (!value) {
|
|
18
|
+
const envVarName = KEY_TO_ENV_VAR[key] || key;
|
|
19
|
+
missing.push(envVarName);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
if (missing.length > 0) {
|
|
23
|
+
throw new Error(`[Openfort SDK] Missing required .env variables: ${missing.join(', ')}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { SDKOverrides, AccountTypeEnum, ThirdPartyAuthConfiguration } from '@openfort/openfort-js';
|
|
3
3
|
/**
|
|
4
|
-
* Shape for configuring custom authentication
|
|
4
|
+
* Shape for configuring custom authentication synchronization behavior.
|
|
5
5
|
*/
|
|
6
6
|
interface CustomAuthConfig {
|
|
7
7
|
enabled: boolean;
|
|
@@ -16,6 +16,8 @@ export type CommonEmbeddedWalletConfiguration = {
|
|
|
16
16
|
ethereumProviderPolicyId?: PolicyConfig;
|
|
17
17
|
accountType?: AccountTypeEnum;
|
|
18
18
|
debug?: boolean;
|
|
19
|
+
/** Recovery method for the embedded wallet: 'automatic' or 'password' */
|
|
20
|
+
recoveryMethod?: 'automatic' | 'password';
|
|
19
21
|
};
|
|
20
22
|
export type EncryptionSession = {
|
|
21
23
|
/** Function to retrieve an encryption session using a session ID */
|
package/dist/types/index.d.ts
CHANGED
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
* required to integrate Openfort authentication and embedded wallets into React Native and
|
|
8
8
|
* Expo applications.
|
|
9
9
|
*/
|
|
10
|
-
export { AuthPlayerResponse, OpenfortError, RecoveryMethod, Openfort as OpenfortClient, Provider, OpenfortConfiguration, ShieldConfiguration, EmbeddedState, } from '@openfort/openfort-js';
|
|
11
|
-
export { OAuthProvider, } from '@openfort/openfort-js';
|
|
10
|
+
export { AuthPlayerResponse, OpenfortError, RecoveryMethod, RecoveryParams, Openfort as OpenfortClient, Provider, OpenfortConfiguration, ShieldConfiguration, EmbeddedState, AuthResponse, EmbeddedAccount, SignedMessagePayload, AuthInitPayload, } from '@openfort/openfort-js';
|
|
11
|
+
export { OAuthProvider, AccountTypeEnum, } from '@openfort/openfort-js';
|
|
12
|
+
export { openfortEvents, OpenfortEventMap, OpenfortEvents, } from '@openfort/openfort-js';
|
|
12
13
|
export * from './types';
|
|
13
14
|
export * from './hooks';
|
|
14
15
|
export * from './components';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validates that required environment variables are present.
|
|
3
|
+
*
|
|
4
|
+
* @param config - Dictionary of configuration keys and their values
|
|
5
|
+
* @throws Error if required environment variables are missing
|
|
6
|
+
*/
|
|
7
|
+
export declare function validateEnvironment(config: Record<string, string | undefined>): void;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openfort/react-native",
|
|
3
3
|
"main": "dist/index.js",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.13",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "React Native SDK for Openfort platform integration",
|
|
7
7
|
"scripts": {
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
}
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@openfort/openfort-js": "^0.10.
|
|
26
|
+
"@openfort/openfort-js": "^0.10.28"
|
|
27
27
|
},
|
|
28
28
|
"peerDependencies": {
|
|
29
29
|
"expo-apple-authentication": "*",
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { useWallets } from "./useWallets";
|
|
2
|
-
/**
|
|
3
|
-
* Hook for accessing the currently active embedded wallet
|
|
4
|
-
*
|
|
5
|
-
* This hook provides access to the currently active embedded wallet from the wallet collection.
|
|
6
|
-
* It automatically updates when the active wallet changes through other wallet operations.
|
|
7
|
-
*
|
|
8
|
-
* @returns The active embedded wallet when available, otherwise `null`
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* ```tsx
|
|
12
|
-
* const activeWallet = useWallet();
|
|
13
|
-
*
|
|
14
|
-
* // Check if wallet is available
|
|
15
|
-
* if (activeWallet) {
|
|
16
|
-
* console.log('Active wallet address:', activeWallet.address);
|
|
17
|
-
*
|
|
18
|
-
* // Get provider for transactions
|
|
19
|
-
* const provider = await activeWallet.getProvider();
|
|
20
|
-
*
|
|
21
|
-
* // Use wallet for operations
|
|
22
|
-
* console.log('Wallet chain type:', activeWallet.chainType);
|
|
23
|
-
* console.log('Is connecting:', activeWallet.isConnecting);
|
|
24
|
-
* } else {
|
|
25
|
-
* console.log('No active wallet available');
|
|
26
|
-
* }
|
|
27
|
-
* ```
|
|
28
|
-
*/
|
|
29
|
-
export function useWallet() {
|
|
30
|
-
const { activeWallet } = useWallets();
|
|
31
|
-
return activeWallet;
|
|
32
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Hook for accessing the currently active embedded wallet
|
|
3
|
-
*
|
|
4
|
-
* This hook provides access to the currently active embedded wallet from the wallet collection.
|
|
5
|
-
* It automatically updates when the active wallet changes through other wallet operations.
|
|
6
|
-
*
|
|
7
|
-
* @returns The active embedded wallet when available, otherwise `null`
|
|
8
|
-
*
|
|
9
|
-
* @example
|
|
10
|
-
* ```tsx
|
|
11
|
-
* const activeWallet = useWallet();
|
|
12
|
-
*
|
|
13
|
-
* // Check if wallet is available
|
|
14
|
-
* if (activeWallet) {
|
|
15
|
-
* console.log('Active wallet address:', activeWallet.address);
|
|
16
|
-
*
|
|
17
|
-
* // Get provider for transactions
|
|
18
|
-
* const provider = await activeWallet.getProvider();
|
|
19
|
-
*
|
|
20
|
-
* // Use wallet for operations
|
|
21
|
-
* console.log('Wallet chain type:', activeWallet.chainType);
|
|
22
|
-
* console.log('Is connecting:', activeWallet.isConnecting);
|
|
23
|
-
* } else {
|
|
24
|
-
* console.log('No active wallet available');
|
|
25
|
-
* }
|
|
26
|
-
* ```
|
|
27
|
-
*/
|
|
28
|
-
export declare function useWallet(): import("../..").UserWallet | null;
|