# `useSolanaEmbeddedWallet`

:::info
If using Next.js App Router, add `"use client"` at the top of the file.
:::

Manage Solana embedded wallets: create, list, set active, set recovery method, and export private key. The hook accepts an optional `options` argument of type `UseEmbeddedSolanaWalletOptions`; when `options.cluster` is set, the returned `cluster` and `rpcUrl` are derived from it (with `rpcUrl` resolved via the SDK’s shared RPC helper when there is no matching context).

## Day-to-day properties

| Property | Type | Description |
|----------|------|-------------|
| `address` | `string \| undefined` | Current wallet address (base58). |
| `cluster` | `SolanaCluster \| undefined` | Current cluster; when `options.cluster` is passed to the hook, this reflects that override. |
| `embeddedWalletId` | `string \| undefined` | Set when connected (this hook is embedded-only). |
| `isConnected` | `boolean` | True when currently connected. |
| `isConnecting` | `boolean` | True when actively connecting or transitioning. |
| `isDisconnected` | `boolean` | True when disconnected. |
| `isReconnecting` | `boolean` | True when reconnecting after loss of connection. |
| `provider` | `OpenfortEmbeddedSolanaWalletProvider \| undefined` | Provider for signing. |
| `rpcUrl` | `string \| undefined` | RPC URL for the current cluster; when `options.cluster` is passed, resolved via the SDK’s default RPC helper (see [Default Solana RPC URLs](#default-solana-rpc-urls)). |

### Connected wallet state properties

The hook exposes this connection-state shape (subset of the full return type). Shared with `useEthereumEmbeddedWallet`:

```ts
export type ConnectedWalletState = {
  /** embeddedWalletId when connected (this hook is embedded-only). */
  embeddedWalletId?: string
  /** True when currently connected. */
  isConnected: boolean
  /** True when actively connecting or transitioning. */
  isConnecting: boolean
  /** True when disconnected. */
  isDisconnected: boolean
  /** True when reconnecting after loss of connection. */
  isReconnecting: boolean
}
```

## Usage

**Read the active wallet after sign-in** — the most common case. Gate on `isConnected` so you don't render against a half-initialized wallet (mirrors `useEthereumEmbeddedWallet`):

```tsx
import { useSolanaEmbeddedWallet } from "@openfort/react/solana"

function ActiveWallet() {
  const { isConnected, address, activeWallet, provider } = useSolanaEmbeddedWallet()

  if (!isConnected) return null
  // safe to use address / activeWallet / provider here
  return <p>Wallet: {address}</p>
}
```

For granular UI states (loading, recovery prompts, errors) read the `status` discriminated union instead — see [Return type](#return-type).

**List and switch wallets** (cluster from provider/context):

```tsx
import { useSolanaEmbeddedWallet } from "@openfort/react/solana"

function WalletList() {
  const { wallets, activeWallet, setActive, create } = useSolanaEmbeddedWallet()

  return (
    <div>
      {wallets.map((w) => (
        <button key={w.id} onClick={() => setActive({ address: w.address })}>
          {w.address}
        </button>
      ))}
    </div>
  )
}
```

**With options** (parity with Ethereum’s `useEthereumEmbeddedWallet({ chainId: 1 })`): pass `cluster` to override the cluster from context, and optionally `recoveryParams` for wallet access:

```tsx
const { cluster, rpcUrl, activeWallet } = useSolanaEmbeddedWallet({ cluster: 'mainnet-beta' })

// Or with recovery params
const { cluster, rpcUrl } = useSolanaEmbeddedWallet({ cluster: 'devnet', recoveryParams: { ... } })
```

## Return type

The hook returns `SolanaWalletState` (`SolanaWalletStateBase & SolanaWalletDerived & ConnectedWalletState`). All status variants include the actions and the derived/connected fields; the status-specific fields below vary by `status`.

```ts
type SolanaCluster = 'mainnet-beta' | 'devnet' | 'testnet'

type SolanaWalletState = {
  // --- Actions (all statuses) ---
  create(options?: CreateEmbeddedWalletOptions): Promise<EmbeddedAccount>
  wallets: ConnectedEmbeddedSolanaWallet[]
  setActive(options: SetActiveSolanaWalletOptions): Promise<void>
  setRecovery(options: SetRecoveryOptions): Promise<void>
  exportPrivateKey(): Promise<string>

  // --- SolanaWalletDerived (WalletDerived + rpcUrl) ---
  isLoading: boolean
  isError: boolean
  isSuccess: boolean
  rpcUrl?: string

  // --- ConnectedWalletState ---
  embeddedWalletId?: string
  isConnected: boolean
  isConnecting: boolean
  isDisconnected: boolean
  isReconnecting: boolean

  // --- Discriminated by status (union) ---
  status: 'disconnected' | 'fetching-wallets' | 'connecting' | 'reconnecting' | 'creating' | 'needs-recovery' | 'connected' | 'error'
  activeWallet: ConnectedEmbeddedSolanaWallet | null
  address?: string
  cluster?: SolanaCluster
  displayAddress?: string
  provider?: OpenfortEmbeddedSolanaWalletProvider
  error?: string
}
```

Status-specific shape:

* **`disconnected`** | **`fetching-wallets`** | **`creating`**: `activeWallet: null`; no `address`, `cluster`, `displayAddress`, `provider`, `error`.
* **`connecting`** | **`reconnecting`**: `activeWallet` set; `address`, `cluster`, `displayAddress` set.
* **`needs-recovery`**: `activeWallet` set; `address`, `cluster`, `displayAddress` optional.
* **`connected`**: `activeWallet` set; `address`, `cluster`, `displayAddress`, `provider` all set.
* **`error`**: `activeWallet` set or null; `error: string`; `address`, `cluster`, `displayAddress` optional.

`ConnectedEmbeddedSolanaWallet` (items in `wallets` / `activeWallet`):

```ts
type ConnectedEmbeddedSolanaWallet = {
  id: string
  address: string
  chainType: typeof ChainTypeEnum.SVM
  walletIndex: number
  recoveryMethod?: RecoveryMethod
  getProvider(): Promise<OpenfortEmbeddedSolanaWalletProvider>
}
```

## Hook options

```ts
type UseEmbeddedSolanaWalletOptions = {
  /** Optional Solana cluster override (mirrors Ethereum’s chainId in useEthereumEmbeddedWallet). When set, overrides the cluster from SolanaContext; returned cluster and rpcUrl are derived from this. */
  cluster?: SolanaCluster
  /** Optional recovery params for wallet access. */
  recoveryParams?: RecoveryParams
}
```

:::info[Parity with Ethereum]
**Ethereum:** `useEthereumEmbeddedWallet(options?)` with `options.chainId` and `options.recoveryParams`.\
**Solana:** `useSolanaEmbeddedWallet(options?)` with `options.cluster` and `options.recoveryParams`.\
`cluster` is the Solana counterpart of `chainId` for choosing the network from the hook.
:::

### Default Solana RPC URLs

Default Solana RPC URLs are not defined in the hook; they live in the SDK as a single source of truth in `utils/rpc`:

* **`getDefaultSolanaRpcUrl(cluster)`** — returns the default URL for a cluster (`'mainnet-beta'`, `'devnet'`, or `'testnet'`), or `undefined` for unknown clusters.

When you pass `options.cluster` to the hook and no matching context supplies an RPC URL, the hook uses this helper to resolve `rpcUrl`.

## Parameters

### create

The hook uses the shared `CreateEmbeddedWalletOptions` type (same as Ethereum). `chainId` and `accountType` are optional and apply to EVM; Solana create typically omits them.

```ts
export type CreateEmbeddedWalletOptions = {
  chainId?: number
  recoveryMethod?: RecoveryMethod
  passkeyId?: string
  password?: string
  otpCode?: string
  accountType?: AccountTypeEnum
  feeSponsorshipId?: string
} & OpenfortHookOptions<CreateEmbeddedWalletResult>
```

`CreateEmbeddedWalletOptions` and `CreateEmbeddedWalletResult` are from `@openfort/react` shared types; `OpenfortHookOptions` adds `onSuccess`, `onError`, `throwOnError`.

### setActive

```ts
export type SetActiveEmbeddedWalletOptionsBase = {
  recoveryParams?: RecoveryParams
  recoveryMethod?: RecoveryMethod
  passkeyId?: string
  password?: string
  otpCode?: string
}

export type SetActiveSolanaWalletOptions = SetActiveEmbeddedWalletOptionsBase & {
  address: string
}
```

### setRecovery

```ts
export type SetRecoveryOptions = {
  previousRecovery: RecoveryParams
  newRecovery: RecoveryParams
}
```

## Solana configuration reference

### Provider chainType

Requires `walletConfig.chainType: ChainTypeEnum.SVM` on `OpenfortProvider`. The default is `EVM`, so without it the hook stays at `isConnected: false` even after a successful OAuth / email / passkey sign-in. See [provider setup](/docs/products/embedded-wallet/react/#providerstsx) and the [headless Solana quickstart](https://github.com/openfort-xyz/openfort-react/tree/main/examples/quickstarts/solana-headless).

### Cluster

One of `'mainnet-beta'`, `'devnet'`, or `'testnet'`. Set in `walletConfig.solana.cluster` or override per-hook via `options.cluster`.

### Commitment levels

Set `walletConfig.solana.commitment` to control how long the SDK waits for transaction confirmation. Default: `'confirmed'`.

| Level | Description |
|-------|-------------|
| `processed` | Processed by the leader node. Fastest but may be reverted. |
| `confirmed` | Confirmed by a supermajority of validators. Good balance of speed and safety. |
| `finalized` | Finalized and cannot be reverted. Slowest but most secure. |

### Custom RPC URLs

Provide custom RPC endpoints per cluster via `walletConfig.solana.rpcUrls`:

```tsx
solana: {
  cluster: "mainnet-beta",
  rpcUrls: {
    "mainnet-beta": "https://your-rpc.example.com",
    "devnet": "https://your-devnet-rpc.example.com",
  },
}
```

When no custom URL is configured, the SDK falls back to `getDefaultSolanaRpcUrl(cluster)` (exported from `@openfort/react`).

## @solana/kit integration

Use the provider from `activeWallet.getProvider()` with a `TransactionSigner` adapter to sign transactions. See [Wallet actions](/docs/products/embedded-wallet/react/wallet/actions#send-sol-or-sign-transactions) for the full `createOpenfortSigner` pattern and SOL transfer example.

## Related

* [Create wallet](/docs/products/embedded-wallet/react/wallet/create)
* [Active wallet](/docs/products/embedded-wallet/react/wallet/active-wallet/solana)
