# Manage wallets

Guide users through wallet management with Openfort's React Native hooks. Options include:

* Embedded wallet creation during onboarding
* Connecting existing wallets using password, automatic, or passkey recovery
* Handling wallet activation and switching

## Creating a new embedded wallet

To create a new embedded wallet, use the appropriate hook for your target blockchain:

* `useEmbeddedEthereumWallet` for Ethereum chains
* `useEmbeddedSolanaWallet` for Solana

Both hooks provide methods to create and manage wallets securely.

:::code-group

```tsx [Ethereum]
import { useEmbeddedEthereumWallet } from "@openfort/react-native"

function SampleComponent() {
  const {// [!code focus]
    status, // [!code focus]
    create, // [!code focus]
  } = useEmbeddedEthereumWallet()// [!code focus]

  const isCreating = status === 'creating';
  // ...
}
```

```tsx [Solana]
import { useEmbeddedSolanaWallet } from "@openfort/react-native"

function SampleComponent() {
  const {// [!code focus]
    status, // [!code focus]
    create, // [!code focus]
  } = useEmbeddedSolanaWallet()// [!code focus]

  const isCreating = status === 'creating';
  // ...
}
```

:::

## Using an embedded wallet

To use an embedded wallet, access it through the appropriate hook. Both hooks provide the current wallets and methods to manage them.

First, list the wallets linked to the user, then use `setActive` to set the active wallet.

:::code-group

```tsx [Ethereum]
import { useEmbeddedEthereumWallet } from "@openfort/react-native"

function SampleComponent() {
  const {// [!code focus]
    wallets, // [!code focus]
    setActive, // [!code focus]
  } = useEmbeddedEthereumWallet()// [!code focus]
  // ...
}
```

```tsx [Solana]
import { useEmbeddedSolanaWallet } from "@openfort/react-native"

function SampleComponent() {
  const {// [!code focus]
    wallets, // [!code focus]
    setActive, // [!code focus]
  } = useEmbeddedSolanaWallet()// [!code focus]
  // ...
}
```

:::

## Onboarding: create or recover in one flow

During onboarding you usually don't know yet whether the signed-in user already
has an embedded wallet. Instead of adding a dedicated helper, branch on
`wallets.length` and call the action that applies — both paths leave the wallet
**connected** (provider ready), so you don't need to chain calls:

* `create()` creates a new wallet **and** activates it (provider is set, status
  becomes `connected`).
* `setActive({ address })` recovers and activates an existing wallet.

:::code-group

```tsx [Ethereum]
import { useEmbeddedEthereumWallet } from "@openfort/react-native"

function useOnboardWallet() {
  const { wallets, create, setActive } = useEmbeddedEthereumWallet()

  // Reach the `connected` state whether or not the user already has a wallet.
  return async (recoveryPassword?: string) => {
    if (wallets.length > 0) {
      // Recover + activate the existing wallet.
      await setActive({ address: wallets[0].address, recoveryPassword })
    } else {
      // Create a new wallet — this already activates it.
      await create({ recoveryMethod: 'password', recoveryPassword })
    }
    // Either branch leaves you connected: read `status === 'connected'`,
    // `activeWallet`, and `provider` from the hook.
  }
}
```

```tsx [Solana]
import { useEmbeddedSolanaWallet } from "@openfort/react-native"

function useOnboardWallet() {
  const { wallets, create, setActive } = useEmbeddedSolanaWallet()

  // Reach the `connected` state whether or not the user already has a wallet.
  return async (recoveryPassword?: string) => {
    if (wallets.length > 0) {
      // Recover + activate the existing wallet.
      await setActive({ address: wallets[0].address, recoveryPassword })
    } else {
      // Create a new wallet — this already activates it.
      await create({ recoveryMethod: 'password', recoveryPassword })
    }
    // Either branch leaves you connected: read `status === 'connected'`,
    // `activeWallet`, and `provider` from the hook.
  }
}
```

:::

:::tip
`create()` accepts the same options as `setActive()` — `recoveryMethod`,
`recoveryPassword`, `passkeyId`, `otpCode` (plus `chainId` on Ethereum) — so
passkey- and automatic-recovery onboarding follow the same shape.
:::

## Status states

Both `useEmbeddedEthereumWallet` and `useEmbeddedSolanaWallet` hooks use a discriminated union pattern with the following states:

| Status | Description |
|--------|-------------|
| `disconnected` | User is authenticated but no wallet is active |
| `fetching-wallets` | Loading the list of user's wallets |
| `connecting` | Wallet is being recovered or provider is initializing |
| `reconnecting` | Reconnecting to a previously active wallet |
| `creating` | A new wallet is being created |
| `needs-recovery` | Wallet requires recovery (password, passkey, or encryption session) |
| `connected` | Wallet is active and provider is ready for use |
| `error` | An error occurred during wallet operations |

Check the `status` property directly for type-safe state handling (for example, `ethereum.status === 'connected'` or `solana.status === 'connected'`).

## Recovery methods

When creating or recovering wallets, you can choose between three recovery methods:

| Method | Description | User Input |
|--------|-------------|------------|
| `automatic` | Uses encrypted sessions from your backend | None (seamless) |
| `password` | User provides a recovery password | Password input |
| `passkey` | Uses device biometrics (Face ID, Touch ID) | Biometric prompt |

### Creating a wallet with passkey recovery

:::warning
The [`usePasskeyPrfSupport`](/docs/products/embedded-wallet/react-native/hooks/usePasskeyPrfSupport) hook checks for **passkey PRF support** (Android 14+, iOS 18+).
:::

:::code-group

```tsx [Ethereum]
import { useEmbeddedEthereumWallet, usePasskeyPrfSupport } from "@openfort/react-native"

function WalletCreation() {
  const { isSupported: passkeySupported } = usePasskeyPrfSupport();
  const { create, status } = useEmbeddedEthereumWallet();

  const handleCreate = async () => {
    await create({
      recoveryMethod: 'passkey',
      onSuccess: ({ account }) => {
        console.log('Wallet created:', account?.address);
      },
    });
  };

  return (
    <Button
      title="Create with Passkey"
      onPress={handleCreate}
      disabled={!passkeySupported || status === 'creating'}
    />
  );
}
```

```tsx [Solana]
import { useEmbeddedSolanaWallet, usePasskeyPrfSupport } from "@openfort/react-native"

function WalletCreation() {
  const { isSupported: passkeySupported } = usePasskeyPrfSupport();
  const { create, status } = useEmbeddedSolanaWallet();

  const handleCreate = async () => {
    await create({
      recoveryMethod: 'passkey',
      onSuccess: ({ account }) => {
        console.log('Wallet created:', account?.address);
      },
    });
  };

  return (
    <Button
      title="Create with Passkey"
      onPress={handleCreate}
      disabled={!passkeySupported || status === 'creating'}
    />
  );
}
```

:::

### Recovering a wallet

The SDK automatically detects the recovery method from the wallet's `recoveryMethod` property:

:::code-group

```tsx [Ethereum]
function WalletRecovery() {
  const { wallets, setActive } = useEmbeddedEthereumWallet();

  const handleRecover = async (wallet) => {
    // For passkey wallets, this triggers a biometric prompt
    // For password wallets, you'd pass the password
    await setActive({
      address: wallet.address,
      chainId: 84532,
      // Only needed for password recovery:
      // recoveryPassword: 'user-provided-password',
    });
  };

  return (
    <View>
      {wallets.map((wallet) => (
        <Button
          key={wallet.address}
          title={`Connect (${wallet.recoveryMethod})`}
          onPress={() => handleRecover(wallet)}
        />
      ))}
    </View>
  );
}
```

```tsx [Solana]
function WalletRecovery() {
  const { wallets, setActive } = useEmbeddedSolanaWallet();

  const handleRecover = async (wallet) => {
    // For passkey wallets, this triggers a biometric prompt
    // For password wallets, you'd pass the password
    await setActive({
      address: wallet.address,
      // Only needed for password recovery:
      // recoveryPassword: 'user-provided-password',
    });
  };

  return (
    <View>
      {wallets.map((wallet) => (
        <Button
          key={wallet.address}
          title={`Connect (${wallet.recoveryMethod})`}
          onPress={() => handleRecover(wallet)}
        />
      ))}
    </View>
  );
}
```

:::

See the [Passkey Quickstart](/docs/products/embedded-wallet/react-native/quickstart/passkey) for complete setup instructions.
