@openfort/react 1.0.2 → 1.0.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.
@@ -1,10 +1,9 @@
1
1
  import { jsx, jsxs } from 'react/jsx-runtime';
2
- import { RecoveryMethod, EmbeddedState } from '@openfort/openfort-js';
2
+ import { RecoveryMethod } from '@openfort/openfort-js';
3
3
  import { motion } from 'framer-motion';
4
4
  import { useState, useEffect, useCallback, useMemo } from 'react';
5
5
  import { PhoneIcon, EmailIcon, FingerPrintIcon, KeyIcon, LockIcon } from '../../../assets/icons.js';
6
6
  import { OpenfortError } from '../../../types.js';
7
- import { useOpenfortCore } from '../../../openfort/useOpenfort.js';
8
7
  import { useRecoveryOTP } from '../../../shared/hooks/useRecoveryOTP.js';
9
8
  import { handleOtpRecoveryError } from '../../../shared/utils/otpError.js';
10
9
  import { useSolanaEmbeddedWallet } from '../../../solana/hooks/useSolanaEmbeddedWallet.js';
@@ -55,7 +54,6 @@ const OtherMethod = ({ currentMethod, onChangeMethod, }) => {
55
54
  };
56
55
  const SolanaCreateAutomatic = ({ onBack, logoutOnBack }) => {
57
56
  var _a;
58
- const { embeddedState } = useOpenfortCore();
59
57
  const { setRoute, triggerResize } = useOpenfort();
60
58
  const embeddedWallet = useSolanaEmbeddedWallet();
61
59
  const { isEnabled: isWalletRecoveryOTPEnabled, requestOTP } = useRecoveryOTP();
@@ -115,11 +113,12 @@ const SolanaCreateAutomatic = ({ onBack, logoutOnBack }) => {
115
113
  })();
116
114
  }, [shouldCreate]);
117
115
  const [canSendOtp, setCanSendOtp] = useState(true);
116
+ // Trigger creation on mount. We only land here when no Solana wallet exists.
117
+ // Don't gate on embeddedState — the user may have an EVM wallet (embeddedState=READY)
118
+ // but still need a Solana wallet.
118
119
  useEffect(() => {
119
- if (embeddedState === EmbeddedState.EMBEDDED_SIGNER_NOT_CONFIGURED) {
120
- setShouldCreate(true);
121
- }
122
- }, [embeddedState]);
120
+ setShouldCreate(true);
121
+ }, []);
123
122
  const handleResendClick = useCallback(() => {
124
123
  setOtpStatus('send-otp');
125
124
  setCanSendOtp(false);
@@ -145,7 +144,6 @@ const SolanaCreateAutomatic = ({ onBack, logoutOnBack }) => {
145
144
  const SolanaCreatePasskey = ({ onChangeMethod, onBack, logoutOnBack, }) => {
146
145
  const { triggerResize, setRoute } = useOpenfort();
147
146
  const embeddedWallet = useSolanaEmbeddedWallet();
148
- const { embeddedState } = useOpenfortCore();
149
147
  const [shouldCreate, setShouldCreate] = useState(false);
150
148
  const [recoveryError, setRecoveryError] = useState(null);
151
149
  useEffect(() => {
@@ -164,11 +162,12 @@ const SolanaCreatePasskey = ({ onChangeMethod, onBack, logoutOnBack, }) => {
164
162
  }
165
163
  })();
166
164
  }, [shouldCreate]);
165
+ // Trigger creation on mount. We only land here when no Solana wallet exists.
166
+ // Don't gate on embeddedState — the user may have an EVM wallet (embeddedState=READY)
167
+ // but still need a Solana wallet.
167
168
  useEffect(() => {
168
- if (embeddedState === EmbeddedState.EMBEDDED_SIGNER_NOT_CONFIGURED) {
169
- setShouldCreate(true);
170
- }
171
- }, [embeddedState]);
169
+ setShouldCreate(true);
170
+ }, []);
172
171
  useEffect(() => {
173
172
  if (recoveryError)
174
173
  triggerResize();
@@ -1 +1 @@
1
- {"version":3,"file":"SolanaCreateWallet.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"SolanaCreateWallet.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -29,7 +29,7 @@ const errorForChainRegistry = {
29
29
  }),
30
30
  };
31
31
  const LoadWallets = () => {
32
- const { chainType, user } = useOpenfortCore();
32
+ const { chainType, user, isLoadingAccounts } = useOpenfortCore();
33
33
  const { triggerResize, setRoute, setConnector, walletConfig } = useOpenfort();
34
34
  const ethereumWallet = useEthereumEmbeddedWallet();
35
35
  const solanaWallet = useSolanaEmbeddedWallet();
@@ -38,7 +38,10 @@ const LoadWallets = () => {
38
38
  const wallets = embeddedWallet.wallets;
39
39
  const isLoadingWallets = embeddedWallet.status === 'fetching-wallets' ||
40
40
  embeddedWallet.status === 'connecting' ||
41
- embeddedWallet.status === 'creating';
41
+ embeddedWallet.status === 'creating' ||
42
+ // For Solana, the hook never enters 'fetching-wallets' — accounts are derived from the
43
+ // core embeddedAccounts store. Wait for the core fetch to complete before routing.
44
+ isLoadingAccounts;
42
45
  const errorWallets = embeddedWallet.status === 'error' ? new Error(embeddedWallet.error) : undefined;
43
46
  useEffect(() => {
44
47
  let timeout;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * @remarks Client-only. Use in a Client Component (e.g. add `"use client"` in Next.js App Router).
8
8
  *
9
- * @returns user, linkedAccounts, isAuthenticated, isConnected, getAccessToken, validateAndRefreshToken
9
+ * @returns user, linkedAccounts, isLoading, isAuthenticated, isConnected, getAccessToken, validateAndRefreshToken
10
10
  *
11
11
  * @example
12
12
  * ```tsx
@@ -21,6 +21,7 @@
21
21
  export declare function useUser(): {
22
22
  user: import("@openfort/openfort-js").User | null;
23
23
  linkedAccounts: import("@openfort/openfort-js").UserAccount[];
24
+ isLoading: boolean;
24
25
  isAuthenticated: boolean;
25
26
  isConnected: boolean;
26
27
  getAccessToken: () => Promise<string | null>;
@@ -11,7 +11,7 @@ import { handleOAuthConfigError } from '../../utils/oauthErrorHandler.js';
11
11
  *
12
12
  * @remarks Client-only. Use in a Client Component (e.g. add `"use client"` in Next.js App Router).
13
13
  *
14
- * @returns user, linkedAccounts, isAuthenticated, isConnected, getAccessToken, validateAndRefreshToken
14
+ * @returns user, linkedAccounts, isLoading, isAuthenticated, isConnected, getAccessToken, validateAndRefreshToken
15
15
  *
16
16
  * @example
17
17
  * ```tsx
@@ -24,7 +24,7 @@ import { handleOAuthConfigError } from '../../utils/oauthErrorHandler.js';
24
24
  * ```
25
25
  */
26
26
  function useUser() {
27
- const { user, client, embeddedState, linkedAccounts, activeEmbeddedAddress } = useOpenfortCore();
27
+ const { user, client, embeddedState, linkedAccounts, activeEmbeddedAddress, isLoading } = useOpenfortCore();
28
28
  const isAuthenticated = embeddedState !== EmbeddedState.NONE && embeddedState !== EmbeddedState.UNAUTHENTICATED;
29
29
  const isConnected = embeddedState === EmbeddedState.READY && !!activeEmbeddedAddress;
30
30
  const getAccessTokenAndUpdate = useCallback(async () => {
@@ -50,6 +50,7 @@ function useUser() {
50
50
  return {
51
51
  user,
52
52
  linkedAccounts,
53
+ isLoading,
53
54
  isAuthenticated,
54
55
  isConnected,
55
56
  getAccessToken: getAccessTokenAndUpdate,
@@ -1 +1 @@
1
- {"version":3,"file":"useUser.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"useUser.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,5 +1,5 @@
1
1
  import { ChainTypeEnum, EmbeddedState } from '@openfort/openfort-js';
2
- import { useContext, useMemo, useState, useEffect, useRef, useCallback, useLayoutEffect, createElement, Fragment } from 'react';
2
+ import { useContext, useMemo, useState, useEffect, useRef, useLayoutEffect, useCallback, createElement, Fragment } from 'react';
3
3
  import { useStore } from 'zustand';
4
4
  import { routes } from '../components/Openfort/types.js';
5
5
  import { useOpenfort } from '../components/Openfort/useOpenfort.js';
@@ -99,8 +99,10 @@ const CoreOpenfortProvider = ({ children, onConnect, onDisconnect, openfortConfi
99
99
  });
100
100
  });
101
101
  }, []);
102
- // Sync chainType from UI context into the store
103
- useEffect(() => {
102
+ // Sync chainType from UI context into the store — useLayoutEffect so the store
103
+ // is updated before the next paint, preventing a one-render-cycle race where
104
+ // the strategy context (synchronous) sees SVM but the store still shows EVM.
105
+ useLayoutEffect(() => {
104
106
  store.getState().setChainType(chainType);
105
107
  }, [store, chainType]);
106
108
  // Recompute isLoading when bridge address changes (bridge connects/disconnects)
@@ -1 +1 @@
1
- {"version":3,"file":"CoreOpenfortProvider.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"CoreOpenfortProvider.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1 +1 @@
1
- export declare const OPENFORT_VERSION = "1.0.2";
1
+ export declare const OPENFORT_VERSION = "1.0.3";
package/build/version.js CHANGED
@@ -1,4 +1,4 @@
1
- const OPENFORT_VERSION = '1.0.2';
1
+ const OPENFORT_VERSION = '1.0.3';
2
2
 
3
3
  export { OPENFORT_VERSION };
4
4
  //# sourceMappingURL=version.js.map
@@ -9,7 +9,12 @@ function setEmbeddedWalletProvider(p) {
9
9
  function embeddedWalletConnector() {
10
10
  return createConnector((config) => {
11
11
  const accountsChangedHandler = (accs) => {
12
- config.emitter.emit('change', { accounts: accs });
12
+ // Filter out non-EVM addresses (e.g. Solana base58) that the SDK may emit
13
+ // when recover() is called for a Solana wallet — sdk bug, defensive guard.
14
+ const valid = accs.filter((a) => /^0x[0-9a-fA-F]{40}$/i.test(a));
15
+ if (valid.length === 0)
16
+ return;
17
+ config.emitter.emit('change', { accounts: valid });
13
18
  };
14
19
  const chainChangedHandler = (chain) => {
15
20
  config.emitter.emit('change', { chainId: Number(chain) });
@@ -1 +1 @@
1
- {"version":3,"file":"embeddedConnector.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"embeddedConnector.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openfort/react",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "author": "Openfort (https://www.openfort.io)",
5
5
  "license": "BSD-2-Clause license",
6
6
  "description": "The easiest way to integrate Openfort to your project.",