# Creating a new embedded wallet

To create a new embedded wallet, use `useEthereumEmbeddedWallet` (Ethereum) or `useSolanaEmbeddedWallet` (Solana).

:::code-group

```tsx [Ethereum]
import { useEthereumEmbeddedWallet } from "@openfort/react/ethereum"
import { RecoveryMethod } from "@openfort/react"

function CreateWallet() {
  const { create, isLoading } = useEthereumEmbeddedWallet()

  const handleCreate = async () => {
    const wallet = await create({
      recoveryMethod: RecoveryMethod.AUTOMATIC,
    })
    console.log("Ethereum wallet created:", wallet.address)
  }

  return (
    <button onClick={handleCreate} disabled={isLoading}>
      Create wallet
    </button>
  )
}
```

```tsx [Solana]
import { useSolanaEmbeddedWallet } from "@openfort/react/solana"
import { RecoveryMethod } from "@openfort/react"

function CreateWallet() {
  const { create, isLoading } = useSolanaEmbeddedWallet()

  const handleCreate = async () => {
    const wallet = await create({
      recoveryMethod: RecoveryMethod.AUTOMATIC,
    })
    console.log("Solana wallet created:", wallet.address)
  }

  return (
    <button onClick={handleCreate} disabled={isLoading}>
      Create wallet
    </button>
  )
}
```

:::

This creates a new embedded wallet with **Automatic recovery** and sets it as the active wallet.

:::tip\[Auto-create behavior]
By default, the SDK automatically creates a wallet after authentication when none exists. To disable this and control creation manually, set `autoCreateWalletAfterAuth: false` in [`walletConfig`](/docs/products/embedded-wallet/react/wallet#auto-create-wallet).
:::

:::info
`accountType` (Smart Account vs EOA) and `chainId` are available via `CreateEmbeddedWalletOptions`. `accountType` is currently supported for Ethereum; Solana uses EOA by default. Gas sponsorship is configured at the provider level via `walletConfig.ethereum.ethereumFeeSponsorshipId`, not per-wallet-creation.
:::

## Recovery method

Recovering the embedded wallet is needed when a user logs into a new device. There are three recovery methods available:

* **Automatic recovery** — Uses an encrypted session from your backend; no user action.
* **Password recovery** — User sets a password; no backend required.
* **Passkey recovery** — WebAuthn (Face ID, Touch ID, fingerprint); no backend required.

Not sure which to use? See the [recovery methods guide](/docs/configuration/recovery-methods).

When creating a wallet, choose one: `RecoveryMethod.AUTOMATIC`, `RecoveryMethod.PASSWORD`, or `RecoveryMethod.PASSKEY`. Configure the same method in `OpenfortProvider` (see examples below).

### Automatic recovery

Automatic recovery requires a backend to create encryption sessions. Set `createEncryptedSessionEndpoint` or `getEncryptionSession` in `walletConfig`. See the [Automatic Recovery session](/docs/products/embedded-wallet/server/automatic-recovery-session) guide.

:::code-group

```tsx [Endpoint]
import { OpenfortProvider } from "@openfort/react"

function App() {
  return (
    <OpenfortProvider
      publishableKey="YOUR_OPENFORT_PUBLISHABLE_KEY"
      walletConfig={{
        shieldPublishableKey: "YOUR_SHIELD_PUBLISHABLE_KEY",
        ethereum: { chainId: 84532 }, {/* Same with solana: { cluster: "devnet" },  */}
        createEncryptedSessionEndpoint: "YOUR_BACKEND_ENDPOINT",
      }}
    >
      {/* Add your wallet components here */}
    </OpenfortProvider>
  )
}
```

```tsx [Callback]
import { OpenfortProvider } from "@openfort/react"

function App() {
  return (
    <OpenfortProvider
      publishableKey="YOUR_OPENFORT_PUBLISHABLE_KEY"
      walletConfig={{
        shieldPublishableKey: "YOUR_SHIELD_PUBLISHABLE_KEY",
        ethereum: { chainId: 84532 }, {/* Same with solana: { cluster: "devnet" },  */}
        getEncryptionSession: async ({ accessToken, userId }) => {
          const res = await fetch("YOUR_BACKEND_ENDPOINT", {
            method: "POST",
            body: JSON.stringify({ user_id: userId }),
            headers: { Authorization: `Bearer ${accessToken}` },
          })
          const { session } = await res.json()
          return session
        },
      }}
    >
      {/* Add your wallet components here */}
    </OpenfortProvider>
  )
}
```

:::

**OTP-protected sessions:** If your backend requires a one-time password, add `requestWalletRecoverOTPEndpoint` or `requestWalletRecoverOTP` to `walletConfig`. The recovery UI will show the OTP input when the backend signals it:

```tsx
walletConfig={{
  shieldPublishableKey: "YOUR_SHIELD_PUBLISHABLE_KEY",
  createEncryptedSessionEndpoint: "/api/encryption-session",
  requestWalletRecoverOTPEndpoint: "/api/send-recovery-otp",
  // OR use a callback:
  // requestWalletRecoverOTP: async ({ accessToken, userId, email }) => {
  //   await sendOtpEmail(email)
  // },
}}
```

Then specify `RecoveryMethod.AUTOMATIC` when creating (or omit it; it defaults to automatic):

:::code-group

```tsx [Ethereum]
import { useEthereumEmbeddedWallet } from "@openfort/react/ethereum"
import { RecoveryMethod } from "@openfort/react"

function CreateWallet() {
  const { create, isLoading } = useEthereumEmbeddedWallet()

  const handleCreate = async () => {
    const wallet = await create({
      recoveryMethod: RecoveryMethod.AUTOMATIC,
    })
    console.log("Wallet created:", wallet.address)
  }

  return <button onClick={handleCreate} disabled={isLoading}>Create wallet</button>
}
```

```tsx [Solana]
import { useSolanaEmbeddedWallet } from "@openfort/react/solana"
import { RecoveryMethod } from "@openfort/react"

function CreateWallet() {
  const { create, isLoading } = useSolanaEmbeddedWallet()

  const handleCreate = async () => {
    const wallet = await create({
      recoveryMethod: RecoveryMethod.AUTOMATIC,
    })
    console.log("Wallet created:", wallet.address)
  }

  return <button onClick={handleCreate} disabled={isLoading}>Create wallet</button>
}
```

:::

### Password recovery

Password recovery lets users set their own password to protect the wallet. No backend is required. Configure the provider, then use `RecoveryMethod.PASSWORD` when calling `create()`:

:::code-group

```tsx [Provider]
import { OpenfortProvider, RecoveryMethod } from "@openfort/react"

function App() {
  return (
    {/* Wrap with providers required for your chain(s), e.g. WagmiProvider for Ethereum */}
    <OpenfortProvider
      publishableKey="YOUR_OPENFORT_PUBLISHABLE_KEY"
      walletConfig={{
        shieldPublishableKey: "YOUR_SHIELD_PUBLISHABLE_KEY",
        {/* Same with solana: { cluster: "devnet" },  */}
        ethereum: { chainId: 84532 }, 
      }}
      uiConfig={{
        walletRecovery: {
          defaultMethod: RecoveryMethod.PASSWORD,
        },
      }}
    >
      {/* Add your wallet components here */}
    </OpenfortProvider>
  )
}
```

```tsx [create()]
import { useEthereumEmbeddedWallet } from "@openfort/react/ethereum"
import { RecoveryMethod } from "@openfort/react"

function CreateWallet() {
  {/* Same with useSolanaEmbeddedWallet from @openfort/react/solana */}
  const { create, isLoading } = useEthereumEmbeddedWallet()

  const handleCreate = async (password: string) => {
    const wallet = await create({
      recoveryMethod: RecoveryMethod.PASSWORD,
      password,
    })
    console.log("Wallet created:", wallet.address)
  }

  return (
    <form onSubmit={(e) => { e.preventDefault(); handleCreate((e.target as HTMLFormElement).password.value) }}>
      <input name="password" type="password" placeholder="Password" />
      <button type="submit" disabled={isLoading}>Create wallet</button>
    </form>
  )
}
```

:::

### Passkey recovery

Passkey recovery uses WebAuthn (Face ID, Touch ID, fingerprint). No backend is required. Configure the provider, then use `RecoveryMethod.PASSKEY` when calling `create()`.

:::warning\[Domain-bound credentials]
WebAuthn credentials are bound to a specific domain. Credentials created for `example.com` only work on that domain — they cannot be used on other applications. If your product spans multiple domains, use automatic recovery instead.
:::

:::code-group

```tsx [Provider]
import { OpenfortProvider, RecoveryMethod } from "@openfort/react"

function App() {
  return (
    {/* Wrap with providers required for your chain(s), e.g. WagmiProvider for Ethereum */}
    <OpenfortProvider
      publishableKey="YOUR_OPENFORT_PUBLISHABLE_KEY"
      walletConfig={{
        shieldPublishableKey: "YOUR_SHIELD_PUBLISHABLE_KEY",
        {/* Same with solana: { cluster: "devnet" },  */}
        ethereum: { chainId: 84532 },   
        // passkeyDisplayName: "My App Wallet", // optional: shown in the WebAuthn dialog
      }}
      uiConfig={{
        walletRecovery: {
          defaultMethod: RecoveryMethod.PASSKEY,
        },
      }}
    >
      {/* Add your wallet components here */}
    </OpenfortProvider>
  )
}
```

```tsx [create()]
import { useEthereumEmbeddedWallet } from "@openfort/react/ethereum"
import { RecoveryMethod } from "@openfort/react"

function CreateWallet() {
  {/* Same with useSolanaEmbeddedWallet from @openfort/react/solana */}
  const { create, isLoading } = useEthereumEmbeddedWallet()

  const handleCreate = async () => {
    const wallet = await create({
      recoveryMethod: RecoveryMethod.PASSKEY,
    })
    console.log("Wallet created:", wallet.address)
  }

  return (
    <button onClick={handleCreate} disabled={isLoading}>
      Create wallet with passkey
    </button>
  )
}
```

:::

### Controlling which methods appear in the UI

Use `uiConfig.walletRecovery` to restrict or pre-select the recovery methods shown:

```tsx
import { OpenfortProvider, RecoveryMethod } from "@openfort/react"

uiConfig={{
  walletRecovery: {
    allowedMethods: [RecoveryMethod.PASSKEY, RecoveryMethod.PASSWORD],
    defaultMethod: RecoveryMethod.PASSKEY,
  },
}}
```

:::info
`RecoveryMethod.AUTOMATIC` is automatically excluded from `allowedMethods` if no encryption session configuration (`createEncryptedSessionEndpoint` or `getEncryptionSession`) is provided in `walletConfig`.
:::
