# MetaMask Embedded Wallets SDKs

> Complete documentation for Embedded Wallets SDKs (React, Vue, JS, Node, Android, iOS, React Native, Flutter, Unity, Unreal)

This file contains all documentation content in a single document following the llmstxt.org standard.

## MetaMask Embedded Wallets

<EWSDKCards />

:::tip

Consider which sigining scheme your dapp requires before beginning your integration:

| SDK Family                                         | Key Model                                                                                                                 | Available from                                                    |
| -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- |
| [**Embedded Wallet SDKs**](/embedded-wallets/sdk/) | [SSS](/embedded-wallets/infrastructure/sss-architecture) (key reconstruction)                                        | [Base, Growth, and Scale plans](https://web3auth.io/pricing.html) |
| **MPC Core Kit SDK**                               | [TSS/MPC](/embedded-wallets/infrastructure/mpc-architecture#threshold-signature-scheme-key)  (no key reconstruction) | [Enterprise plan](https://web3auth.io/pricing.html)               |

:::

---

## Embedded Wallets SDK for Android

## Overview

MetaMask Embedded Wallets SDK (formerly Web3Auth Plug and Play) provides authentication for Android applications with social sign-in, external wallets, and more. Our Android SDK, written in Kotlin, simplifies how you connect users to their preferred wallets and manage authentication state natively.

## Requirements

- Android API version `26` or newer
- Android Compile and Target SDK: `34`
- Basic knowledge of Java or Kotlin development

## Prerequisites

- Set up your project on the [Embedded Wallets dashboard](https://developer.metamask.io/).

:::tip

See the [dashboard setup](../../dashboard/README.mdx) guide to learn more.

:::

## Installation

Install the Web3Auth Android SDK by adding it to your project dependencies:

### 1. Add JitPack repository

In your project-level Gradle file add JitPack repository:

```groovy
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
        // focus-next-line
        maven { url "https://jitpack.io" } // <-- Add this line
    }
}
```

### 2. Add Web3Auth dependency

Then, in your app-level `build.gradle` dependencies section, add the following:

```groovy
dependencies {
    // ...
    // focus-next-line
    implementation 'com.github.web3auth:web3auth-android-sdk:10.0.1'
}
```

2.1. Update permissions

Open your app's `AndroidManifest.xml` file and add the following permission. Ensure the `<uses-permission>` element is a direct child of the `<manifest>` root element.

```xml
<uses-permission android:name="android.permission.INTERNET" />
```

2.2 Configure `AndroidManifest.xml` File

Ensure your main activity `launchMode` is set to `singleTop` in your `AndroidManifest.xml`:

```xml
<activity
  android:launchMode="singleTop"
  android:name=".YourActivity">
  // ...
</activity>
```

From version **7.1.2**, set `android:allowBackup` to `false` and add `tools:replace="android:fullBackupContent"` in your `AndroidManifest.xml` file:

```xml
<application
        android:allowBackup="false"
        tools:replace="android:fullBackupContent"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher">
</application>
```

### 3. Handle redirects

Once the Gradle files and permissions have been updated, you need to configure your Embedded Wallets project by allowlisting your scheme and package name.

#### Configure a Plug n Play project

- From the [Embedded Wallets dashboard](https://developer.metamask.io), create or open an existing Web3Auth project.
- Allowlist `{SCHEME}://{YOUR_APP_PACKAGE_NAME}` in the dashboard. This step is mandatory for the redirect to work.

#### Configure deep link

Open your app's `AndroidManifest.xml` file and add the following deep link intent filter to your main activity:

```xml
<intent-filter>
  <action android:name="android.intent.action.VIEW" />

  <category android:name="android.intent.category.DEFAULT" />
  <category android:name="android.intent.category.BROWSABLE" />

  <data android:scheme="{scheme}" android:host="{YOUR_APP_PACKAGE_NAME}"/>
  <!-- Accept URIs: w3a://com.example.w3aflutter -->
</intent-filter>
```

### 4. Triggering sign-in exceptions

:::note

The Android SDK uses the custom tabs and from current implementation of Chrome custom tab, it's not possible to add a listener directly to Chrome custom tab close button and trigger sign-in exceptions.

:::

Apply the `setCustomTabsClosed` method in your sign-in screen to trigger sign-in exceptions for Android.

```kotlin
class MainActivity : AppCompatActivity() {
    // Additional code

    override fun onResume() {
        super.onResume()
        // focus-start
        if (Web3Auth.getCustomTabsClosed()) {
            Toast.makeText(this, "User closed the browser.", Toast.LENGTH_SHORT).show()
            web3Auth.setResultUrl(null)
            Web3Auth.setCustomTabsClosed(false)
        }
        // focus-end
    }

    // Additional code
}
```

## Initialize Embedded Wallets

### 1. Create an Embedded Wallets instance

Create an Embedded Wallets instance and configure it with your project settings:

```kotlin

// focus-start
var web3Auth = Web3Auth(
  Web3AuthOptions(
    clientId = "YOUR_WEB3AUTH_CLIENT_ID", // Pass over your Web3Auth Client ID from Developer Dashboard
    web3AuthNetwork = Web3AuthNetwork.SAPPHIRE_MAINNET, // or Web3AuthNetwork.SAPPHIRE_DEVNET
    redirectUrl = "{YOUR_APP_PACKAGE_NAME}://auth",
  ),
  this
)
// focus-end

// Handle user signing in when app is in background
web3Auth.setResultUrl(intent?.data)
```

### 2. Set result URL

Whenever user initiates a sign-in flow, a new intent of CustomTabs is launched. It's necessary step to use `setResultUrl` in `onNewIntent` method to successful track the sign-in process.

```kotlin
override fun onNewIntent(intent: Intent?) {
  super.onNewIntent(intent)

  // Handle user signing in when app is active
  web3Auth.setResultUrl(intent.data)
}
```

### 3. Initialize the Embedded Wallets instance

After instantiating Embedded Wallets, the next step is to initialize it using the `initialize` method. This method is essential for setting up the SDK, checking for any active sessions, and fetching the whitelabel configuration from your dashboard.

Once the `initialize` method executes successfully, you can use the `getPrivateKey` or `getEd25519PrivateKey` methods to verify if an active session exists. If there is no active session, these methods will return an empty string; otherwise, they will return the respective private key.

:::note

The `initialize` method may throw an error in the following situations:

- No active session exists for the user.
- A network error occurs while fetching the project configuration from the dashboard.
- Session validation fails (for example, the stored session token is invalid or expired).

Wrap the call in a `whenComplete` handler and treat any non-null error as a failed initialization rather than an absent session.

:::

```kotlin
val initializeCF: CompletableFuture<Void> = web3Auth.initialize()
initializeCF.whenComplete { _, error ->
  if (error == null) {
    // Check for the active session
    if(web3Auth.getPrivateKey().isNotEmpty()) {
      // Active session found
    }
    // No active session is not present

  } else {
    // Handle the error
  }
}
```

## Advanced configuration

The Web3Auth Android SDK offers a rich set of advanced configuration options:

- **[Custom authentication](./advanced/custom-authentication.mdx):** Define authentication methods.
- **[Whitelabeling and UI customization](./advanced/whitelabel.mdx):** Personalize the modal's appearance.
- **[Multi-Factor Authentication (MFA)](./advanced/mfa.mdx):** Set up and manage MFA.
- **[Dapp Share](./advanced/dapp-share.mdx):** Share dapp sessions across devices.

:::tip

See the [advanced configuration sections](./advanced/) to learn more about each configuration option.

:::

<Tabs
  defaultValue="basic-config"
  values={[
    { label: "Basic Configuration", value: "basic-config" },
    { label: "Advanced Configuration", value: "advanced-config" },
  ]}
>

<TabItem value="basic-config">

```kotlin
val web3Auth = Web3Auth(
    Web3AuthOptions(
        clientId = "YOUR_CLIENT_ID",
        web3AuthNetwork = Web3AuthNetwork.SAPPHIRE_MAINNET, // or Web3AuthNetwork.SAPPHIRE_DEVNET
        redirectUrl = "YOUR_APP_SCHEME://auth"
    ),
    this
)
```

</TabItem>

<TabItem value="advanced-config">

```kotlin
val web3Auth = Web3Auth(
    Web3AuthOptions(
        clientId = "YOUR_CLIENT_ID",
        web3AuthNetwork = Web3AuthNetwork.SAPPHIRE_MAINNET, // or Web3AuthNetwork.SAPPHIRE_DEVNET
        redirectUrl = "YOUR_APP_SCHEME://auth",
        authConnectionConfig = listOf(AuthConnectionConfig(
          authConnectionId = "auth-connection-id", // Get it from MetaMask Developer Dashboard
          authConnection = AuthConnection.GOOGLE,
          clientId = getString(R.string.google_client_id) // Google's client id
        )),
        mfaSettings = MfaSettings(
          deviceShareFactor = MfaSetting(true, 1, true),
          socialBackupFactor = MfaSetting(true, 2, true),
          passwordFactor = MfaSetting(true, 3, false),
          backUpShareFactor = MfaSetting(true, 4, false),
          passkeysFactor = MfaSetting(true, 5, true),
          authenticatorFactor = MfaSetting(true, 6, true),
        )
    ),
    this
)
```

</TabItem>

</Tabs>

## Single Factor Auth (SFA) Support

Web3Auth Android SDK includes built-in support for Single Factor Auth (SFA), allowing for seamless authentication when you already have a JWT token from your authentication system. When MFA is disabled, users won't even notice Web3Auth's presence; they'll be automatically authenticated using just your JWT token, making the sign-in experience frictionless.

```kotlin
// SFA sign-in with custom JWT
val loginCompletableFuture = web3Auth.connectTo(
    LoginParams(
        AuthConnection.CUSTOM,
        authConnectionId = "your_verifier_id",
        idToken = "your_jwt_token"
    )
)
```

SFA mode is automatically activated when you provide an `idToken` parameter. This enables direct authentication without additional social sign-in steps, perfect for applications that already have their own authentication system.

## Blockchain Integration

Embedded Wallets is blockchain agnostic, enabling integration with any blockchain network. Out of the box, Embedded Wallets offers robust support for both **Solana** and **Ethereum**.

### Ethereum integration

For Ethereum integration, you can get the private key using the `getPrivateKey` method and use it with web3j or other Ethereum libraries:

```kotlin

// Use your Web3Auth instance to get the private key
val privateKey = web3Auth.getPrivateKey()

// Generate the Credentials
val credentials = Credentials.create(privateKey)

// Get the address
val address = credentials.address

// Create the Web3j instance using your RPC URL
val web3 = Web3j.build(HttpService("YOUR_RPC_URL"))

// Get the balance
val balanceResponse = web3.ethGetBalance(address, DefaultBlockParameterName.LATEST).send()

// Convert the balance from Wei to Ether format
val ethBalance = BigDecimal.valueOf(balanceResponse.balance.toDouble()).divide(BigDecimal.TEN.pow(18))
```

### Solana integration

For Solana integration, you can get the Ed25519 private key using the `getEd25519PrivateKey` method and use it with sol4k or any other Solana libraries:

```kotlin

val connection = Connection(RpcUrl.DEVNET)

// Use your Web3Auth instance to get the private key
val ed25519PrivateKey = web3Auth.getEd25519PrivateKey()

// Generate the Solana KeyPair
val solanaKeyPair = Keypair.fromSecretKey(ed25519PrivateKey.hexToByteArray())

// Get the user's public key
val publicKey = solanaKeyPair.publicKey.toBase58()

// Get the user balance
val userBalance = connection.getBalance(publicKey).toBigDecimal()
```

---

## Advanced configuration

The Embedded Wallets SDK provides extensive configuration options that allow you to customize authentication flows, UI appearance, blockchain integrations, and security features to meet your application's specific requirements.

## Configuration structure

When setting up Embedded Wallets, you'll pass in the options to the constructor. This consists of:

```kotlin

// focus-start
var web3Auth = Web3Auth(
  Web3AuthOptions(
    clientId = "YOUR_WEB3AUTH_CLIENT_ID", // Pass over your Web3Auth Client ID from Developer Dashboard
    web3AuthNetwork = Web3AuthNetwork.SAPPHIRE_MAINNET,
    redirectUrl = "{YOUR_APP_PACKAGE_NAME}://auth",
  ),
  this
)
// focus-end

// Handle user signing in when app is in background
web3Auth.setResultUrl(intent?.data)
```

### `Web3AuthOptions`

The Web3Auth Constructor takes an object with `Web3AuthOptions` as input.

<Tabs
  values={[
    { label: "Basic Parameters", value: "basic" },
    { label: "Advanced Parameters", value: "advanced" },
    { label: "Interface", value: "interface" },
  ]}
>

<TabItem value="basic">

| Parameter         | Description                                                                                                                                                                                    |
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `context`         | Android context to launch web-based authentication, usually is the current activity. It's a mandatory field, and accepts `android.content.Context` as a value.                                 |
| `clientId`        | Your Embedded Wallets Client ID. You can get it from Embedded Wallets [dashboard](https://developer.metamask.io/) under project details. It's a mandatory field of type `String`               |
| `web3AuthNetwork` | Defines the Embedded Wallets Network. It's a mandatory field of type `Web3AuthNetwork`.                                                                                                        |
| `redirectUrl`     | URL that Embedded Wallets will redirect API responses upon successful authentication from browser. It's a mandatory field of type `String`.                                                    |
| `sessionTime?`    | Allows developers to configure the session management time. Session time is in seconds, default is `86400 * 30` (30 days). `sessionTime` can be max 30 days.                                   |
| `useSFAKey?`      | Use SFA key to get single factor auth key. It's an optional field with default value as `false`. Useful for pre-generated wallets and SFA mode.                                                |
| `chains?`         | Custom chain configuration for blockchain networks. It takes `Chains` as a value. See [Chains configuration](#chains-configuration) below.                                                     |
| `defaultChainId?` | Default chain ID to use. It's an optional field with a default value of `"0x1"` (Ethereum mainnet). The first chain from the project config will be used if the project has chains configured. |
| `enableLogging?`  | Setting to true will enable logs. It's an optional field with default value as `false`.                                                                                                        |

</TabItem>

<TabItem value="advanced">

| Parameter               | Description                                                                                                                                                  |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `whiteLabel?`           | Whitelabel options for Embedded Wallets. It helps you define custom UI, branding, and translations for your brand app. It takes `WhiteLabelData` as a value. |
| `authConnectionConfig?` | Auth connection config for the custom auth connections. It takes `List<AuthConnectionConfig>` as a value.                                                    |
| `mfaSettings?`          | Allows developers to configure the MFA settings for authentication. It takes `MfaSettings` as a value.                                                       |
| `walletServicesConfig?` | Configuration for Wallet Services including whitelabel options. It takes `WalletServicesConfig` as a value.                                                  |

</TabItem>

<TabItem value="interface">

```kotlin
data class Web3AuthOptions(
    val clientId: String,
    var redirectUrl: String,
    @SerializedName("network") val web3AuthNetwork: Web3AuthNetwork,
    @SerializedName("buildEnv") var authBuildEnv: BuildEnv = BuildEnv.PRODUCTION,
    var whiteLabel: WhiteLabelData? = null,
    var authConnectionConfig: List<AuthConnectionConfig>? = emptyList(),
    val useSFAKey: Boolean? = false,
    var chains: Chains? = null,
    var mfaSettings: MfaSettings? = null,
    val sessionTime: Int = 30 * 86400,
    val walletServicesConfig: WalletServicesConfig? = null,
    var defaultChainId: String? = "0x1",
    var enableLogging: Boolean = false
)
```

</TabItem>
</Tabs>

## Session management

Control how long users stay authenticated and how sessions persist. The session key is stored in the device's encrypted Keystore.

**Key Configuration Options:**

- `sessionTime` - Session duration in seconds. Controls how long users remain authenticated before needing to sign in again.
  - Minimum: 1 second (`1`).
  - Maximum: 30 days (`86400 * 30`).
  - Default: 30 days (`86400 * 30`).

```kotlin
var web3Auth = Web3Auth(
  Web3AuthOptions(
    clientId = "YOUR_WEB3AUTH_CLIENT_ID", // Pass over your Web3Auth Client ID from Developer Dashboard
    web3AuthNetwork = Web3AuthNetwork.SAPPHIRE_MAINNET,
    sessionTime = 86400 * 7, // 7 days (in seconds)
    redirectUrl = "{YOUR_APP_PACKAGE_NAME}://auth",
  ),
  this
)
```

## Chains Configuration

The `chains` parameter lets you specify a custom blockchain network for the SDK. When set, this chain is used by Wallet Services (`showWalletUI`, `request`) in addition to any chains configured in the project dashboard.

### `Chains` Fields

| Field              | Type             | Required | Description                                                                                         |
| ------------------ | ---------------- | -------- | --------------------------------------------------------------------------------------------------- |
| `chainId`          | `String`         | Yes      | Chain ID in hex format (for example, `"0x1"` for Ethereum mainnet, `"0x89"` for Polygon).           |
| `rpcTarget`        | `String`         | Yes      | RPC endpoint URL for the chain.                                                                     |
| `chainNamespace`   | `ChainNamespace` | No       | Namespace of the chain. Accepts `ChainNamespace.EIP155`, `SOLANA`, or `OTHER`. Default is `EIP155`. |
| `decimals`         | `Int?`           | No       | Number of decimals for the native token. Default is `18`.                                           |
| `blockExplorerUrl` | `String?`        | No       | URL of the block explorer for this chain.                                                           |
| `displayName`      | `String?`        | No       | Human-readable name for the chain.                                                                  |
| `logo`             | `String?`        | No       | URL of the chain's logo image.                                                                      |
| `ticker`           | `String?`        | No       | Ticker symbol for the native token (for example, `"ETH"`).                                          |
| `tickerName`       | `String?`        | No       | Full name of the native token (for example, `"Ethereum"`).                                          |

### Interface

```kotlin
data class Chains(
    val chainNamespace: ChainNamespace = ChainNamespace.EIP155,
    val decimals: Int? = 18,
    val blockExplorerUrl: String? = null,
    val chainId: String,
    val displayName: String? = null,
    val logo: String? = null,
    val rpcTarget: String,
    val ticker: String? = null,
    val tickerName: String? = null,
)
```

### Example

```kotlin
val web3Auth = Web3Auth(
  Web3AuthOptions(
    clientId = "YOUR_WEB3AUTH_CLIENT_ID",
    web3AuthNetwork = Web3AuthNetwork.SAPPHIRE_MAINNET,
    redirectUrl = "YOUR_APP_SCHEME://auth",
    chains = Chains(
      chainId = "0x89",
      rpcTarget = "https://rpc.ankr.com/polygon",
      displayName = "Polygon Mainnet",
      ticker = "MATIC",
      tickerName = "Matic",
      blockExplorerUrl = "https://polygonscan.com"
    )
  ),
  this
)
```

## Custom authentication methods

Control the sign-in options presented to your users. For detailed configuration options and implementation examples, see the [custom authentication](./custom-authentication.mdx) section.

## UI customization

Customize the brand experience by customizing the Embedded Wallets sign-in screens to match your application's design. For complete customization options, refer to the [Whitelabeling & UI Customization](./whitelabel.mdx) section.

## Multi-Factor Authentication

Add additional security layers to protect user accounts with two-factor authentication. For detailed configuration options and implementation examples, see the [Multi-Factor Authentication](./mfa.mdx) section.

**Key Configuration Options:**

- `mfaSettings` - Configure MFA settings for different authentication flows
- `mfaLevel` - Control when users are prompted to set up MFA

## Wallet Services Configuration

The `walletServicesConfig` parameter in `Web3AuthOptions` allows you to customize the behavior of the wallet UI (`showWalletUI`) and request signing (`request`). For full configuration options, see the [Smart Accounts](./smart-accounts) section.

| Parameter               | Description                                                                                                                                           |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `confirmationStrategy?` | Controls how transaction confirmations are displayed. Accepts `ConfirmationStrategy` enum. Default is `ConfirmationStrategy.DEFAULT`.                 |
| `whiteLabel?`           | Whitelabel settings specific to the Wallet Services UI. When set, merged with the project-level whitelabel config. Accepts `WhiteLabelData` as value. |

```kotlin
val web3Auth = Web3Auth(
  Web3AuthOptions(
    clientId = "YOUR_WEB3AUTH_CLIENT_ID",
    web3AuthNetwork = Web3AuthNetwork.SAPPHIRE_MAINNET,
    redirectUrl = "YOUR_APP_SCHEME://auth",
    walletServicesConfig = WalletServicesConfig(
      confirmationStrategy = ConfirmationStrategy.MODAL
    )
  ),
  this
)
```

---

## Custom authentication

Custom authentication is a way to authenticate users with your custom authentication service. For example, while authenticating with Google, you can use your own Google Client ID to authenticate users directly.

This feature, with Multi-Factor Authentication (MFA) turned off, can even make Embedded Wallets invisible to the end user.

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this
SDK in a production environment is the **Growth Plan**. You can use this feature in Web3Auth
Sapphire Devnet network for free.

:::

## Getting an Auth Connection ID

:::info prerequisite

To enable this, you need to [create a connection](/embedded-wallets/dashboard/authentication) from the **Authentication** tab of your project from the [Embedded Wallets dashboard](https://developer.metamask.io) with your desired configuration.

:::

To configure a connection, you need to provide the particular details of the connection in the Embedded Wallets dashboard. This enables us to map a `authConnectionId` with your connection details. This `authConnectionId` helps us to identify the connection details while initializing the SDK. You can configure multiple connections for the same project, and you can also update the connection details anytime.

:::tip

Learn more about the [auth provider setup](/embedded-wallets/authentication) and the different configurations available for each connection.

:::

## Configuration

To use custom authentication (using social providers or sign-in providers like Auth0, AWS identity services, Firebase, and so on, or even your own custom JWT sign-in) you can add the configuration using `authConnectionConfig` parameter during the initialization.

**"Auth Connection"** is called **"Verifier"** in the Android SDK. It is the older terminology which we will be updating in the upcoming releases.

Consequentially, you will see the terms **"Verifier ID"** and **"Aggregate Verifier"** used in the codebase and documentation referring to **"Auth Connection ID"** and **"Grouped Auth Connection"** respectively.

The `authConnectionConfig` parameter is a list of `AuthConnectionConfig` instances, each defining a specific authentication connection.

After creating the auth connection from the [Web3Auth Dashboard](https://dashboard.web3auth.io), you can use the following parameters in the `AuthConnectionConfig`.

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Interface", value: "interface" },
  ]}
>

<TabItem value="table">

| Parameter                  | Description                                                                                                                                                                                                                                                                                                                                                        |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `authConnectionId`         | The name of the auth connection that you have registered on the Web3Auth Dashboard. It's a mandatory field, and accepts `String` as a value.                                                                                                                                                                                                                       |
| `authConnection`           | Type of sign-in for this auth connection; this value affects the sign-in flow that is used. For example, if you choose the Google auth connection, a Google sign-in flow will be used. If you choose `custom`, you should be providing your own JWT token, and no sign-in flow will be presented. It's a mandatory field, and accepts `AuthConnection` as a value. |
| `clientId`                 | Client id provided by your sign-in provider used for custom auth connection. For example, Google's Client ID or Web3Auth's client Id if using `custom` as AuthConnection. It's a mandatory field, and accepts `String` as a value.                                                                                                                                 |
| `name?`                    | Display name for the auth connection. If null, the default name is used. It accepts `String` as a value.                                                                                                                                                                                                                                                           |
| `description?`             | Description for the button. If provided, it renders as a full length button. else, icon button. It accepts `String` as a value.                                                                                                                                                                                                                                    |
| `groupedAuthConnectionId?` | The field in JWT token which maps to the grouped Auth Connection ID. Please make sure you selected the correct JWT Auth Connection ID in the developer dashboard. It accepts `String` as a value.                                                                                                                                                                  |
| `logoHover?`               | Logo to be shown on mouse hover. It accepts `String` as a value.                                                                                                                                                                                                                                                                                                   |
| `logoLight?`               | Light logo for dark background. It accepts `String` as a value.                                                                                                                                                                                                                                                                                                    |
| `logoDark?`                | Dark logo for light background. It accepts `String` as a value.                                                                                                                                                                                                                                                                                                    |
| `mainOption?`              | Show sign-in button on the main list. It accepts `Boolean` as a value. Default value is false.                                                                                                                                                                                                                                                                     |
| `showOnModal?`             | Whether to show the sign-in button on modal or not. Default value is true.                                                                                                                                                                                                                                                                                         |
| `showOnDesktop?`           | Whether to show the sign-in button on desktop. Default value is true.                                                                                                                                                                                                                                                                                              |
| `showOnMobile?`            | Whether to show the sign-in button on mobile. Default value is true.                                                                                                                                                                                                                                                                                               |

</TabItem>

<TabItem value="interface">

```kotlin
data class AuthConnectionConfig(
    var authConnectionId: String,
    private var authConnection: AuthConnection,
    private var name: String? = null,
    private var description: String? = null,
    private var clientId: String,
    private var groupedAuthConnectionId: String? = null,
    private var logoHover: String? = null,
    private var logoLight: String? = null,
    private var logoDark: String? = null,
    private var mainOption: Boolean? = false,
    private var showOnModal: Boolean? = true,
    private var showOnDesktop: Boolean? = true,
    private var showOnMobile: Boolean? = true,
)

enum class AuthConnection {
    @SerializedName("google")
    GOOGLE,
    @SerializedName("facebook")
    FACEBOOK,
    @SerializedName("reddit")
    REDDIT,
    @SerializedName("discord")
    DISCORD,
    @SerializedName("twitch")
    TWITCH,
    @SerializedName("apple")
    APPLE,
    @SerializedName("line")
    LINE,
    @SerializedName("github")
    GITHUB,
    @SerializedName("kakao")
    KAKAO,
    @SerializedName("linkedin")
    LINKEDIN,
    @SerializedName("twitter")
    TWITTER,
    @SerializedName("weibo")
    WEIBO,
    @SerializedName("wechat")
    WECHAT,
    @SerializedName("email_passwordless")
    EMAIL_PASSWORDLESS,
    @SerializedName("custom")
    CUSTOM, // for jwt
    @SerializedName("sms_passwordless")
    SMS_PASSWORDLESS,
    @SerializedName("farcaster")
    FARCASTER
}
```

</TabItem>
</Tabs>

### Usage

<!-- vale off -->

<Tabs
  defaultValue="google"
  values={[
    { label: "Google", value: "google" },
    { label: "Facebook", value: "facebook" },
    { label: "Auth0", value: "auth0" },
    { label: "JWT", value: "jwt" },
  ]}
>

<TabItem value="google">

```kotlin

val web3Auth = Web3Auth(
  Web3AuthOptions(
    clientId = "YOUR_WEB3AUTH_CLIENT_ID", // Pass over your Web3Auth Client ID from Developer Dashboard
    web3AuthNetwork = Web3AuthNetwork.SAPPHIRE_MAINNET,
    redirectUrl = "{YOUR_APP_PACKAGE_NAME}://auth",
    // focus-start
    authConnectionConfig = listOf(AuthConnectionConfig(
      authConnectionId = "auth-connection-id", // Get it from MetaMask Developer Dashboard
      authConnection = AuthConnection.GOOGLE,
      clientId = getString(R.string.google_client_id) // Google's client id
    ))
    // focus-end
  ),
  this
)

// focus-start
val loginCompletableFuture: CompletableFuture<Web3AuthResponse> = web3Auth.connectTo(
    LoginParams(AuthConnection.GOOGLE)
)
// focus-end
```

</TabItem>

<TabItem value="facebook">

```kotlin

val web3Auth = Web3Auth(
  Web3AuthOptions(
    clientId = "YOUR_WEB3AUTH_CLIENT_ID", // Pass over your Web3Auth Client ID from Developer Dashboard
    web3AuthNetwork = Web3AuthNetwork.SAPPHIRE_MAINNET,
    redirectUrl = "{YOUR_APP_PACKAGE_NAME}://auth",
    // focus-start
    authConnectionConfig = listOf(
      AuthConnectionConfig(
        authConnectionId = "auth-connection-id", // Get it from MetaMask Developer Dashboard
        authConnection = AuthConnection.FACEBOOK,
        clientId = getString(R.string.facebook_client_id) // Facebook's client id
      )
    )
    // focus-end
  ),
  this
)

// focus-start
val loginCompletableFuture: CompletableFuture<Web3AuthResponse> = web3Auth.connectTo(
  LoginParams(AuthConnection.FACEBOOK)
)
// focus-end

```

</TabItem>

<TabItem value="auth0">

```kotlin

val web3Auth = Web3Auth(
  Web3AuthOptions(
    clientId = "YOUR_WEB3AUTH_CLIENT_ID", // Pass over your Web3Auth Client ID from Developer Dashboard
    web3AuthNetwork = Web3AuthNetwork.SAPPHIRE_MAINNET,
    redirectUrl = "{YOUR_APP_PACKAGE_NAME}://auth",
    // focus-start
    authConnectionConfig = listOf(AuthConnectionConfig(
      authConnectionId = "auth-connection-id", // Get it from MetaMask Developer Dashboard
      authConnection = AuthConnection.CUSTOM,
      clientId = getString(R.string.auth0_project_id) // Auth0's client id
    ))
    // focus-end
  ),
  this
)

// focus-start
val loginCompletableFuture: CompletableFuture<Web3AuthResponse> = web3Auth.connectTo(
    LoginParams(AuthConnection.CUSTOM)
)
// focus-end
```

</TabItem>

<TabItem value="jwt">

```kotlin

val web3Auth = Web3Auth(
  Web3AuthOptions(
    clientId = "YOUR_WEB3AUTH_CLIENT_ID", // Pass over your Web3Auth Client ID from Developer Dashboard
    web3AuthNetwork = Web3AuthNetwork.SAPPHIRE_MAINNET,
    redirectUrl = "{YOUR_APP_PACKAGE_NAME}://auth",
    // focus-start
    authConnectionConfig = listOf(
      AuthConnectionConfig(
        authConnectionId = "auth-connection-id", // Get it from MetaMask Developer Dashboard
        authConnection = AuthConnection.CUSTOM,
      )
    )
    // focus-end
  ),
  this
)

// focus-start
val loginCompletableFuture: CompletableFuture<Web3AuthResponse> = web3Auth.connectTo(
  LoginParams(AuthConnection.CUSTOM)
)
// focus-end

```

</TabItem>
</Tabs>

<!-- vale on -->

## Configure extra sign-in options

Additional to the `LoginConfig` you can pass extra options to the `connectTo` method to configure the sign-in flow for cases requiring additional info for enabling sign-in. The `ExtraLoginOptions` accepts the following parameters.

### Parameters

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Interface", value: "interface" },
  ]}
>

<TabItem value="table">

| Parameter                | Description                                                                                                                                                                                                                    |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `additionalParams?`      | Additional params in `HashMap` format for OAuth sign-in, use id_token(JWT) to authenticate with web3auth.                                                                                                                      |
| `domain?`                | Your custom authentication domain in `String` format. For example, if you are using Auth0, it can be example.au.auth0.com.                                                                                                     |
| `client_id?`             | Client id in `String` format, provided by your sign-in provider used for custom verifier.                                                                                                                                      |
| `leeway?`                | The value used to account for clock skew in JWT expiration times. The value is in seconds, and ideally should be no more than 60 seconds or 120 seconds at max. It takes `String` as a value.                                  |
| `userIdField?`           | The field in JWT token which maps to user id. Please make sure you selected correct JWT user id in the developer dashboard. It takes `String` as a value.                                                                      |
| `isUserIdCaseSensitive?` | Boolean to confirm Whether the user id field is case sensitive or not.                                                                                                                                                         |
| `display?`               | Allows developers the configure the display of UI. It takes `Display` as a value.                                                                                                                                              |
| `prompt?`                | Prompt shown to the user during authentication process. It takes `Prompt` as a value.                                                                                                                                          |
| `max_age?`               | Max time allowed without re-authentication. If the last time the user authenticated is greater than this value, then the user must re-authenticate. It takes `String` as a value.                                              |
| `ui_locales?`            | The space separated list of language tags, ordered by preference. For instance `fr-CA fr en`.                                                                                                                                  |
| `id_token_hint?`         | It denotes the previously issued ID token. It takes `String` as a value.                                                                                                                                                       |
| `id_token?`              | JWT (ID Token) to be passed for sign-in.                                                                                                                                                                                       |
| `access_token?`          | Access token for OAuth flows. It takes `String` as a value.                                                                                                                                                                    |
| `flow_type?`             | Specifies the email passwordless flow type. It takes `EmailFlowType` as a value (`CODE` or `LINK`).                                                                                                                            |
| `acr_values?`            | Authentication Context Class Reference values for the authorization request.                                                                                                                                                   |
| `scope?`                 | The default scope to be used on authentication requests. The default scope defined in the Auth0 client is included along with this scope. It takes `String` as a value.                                                        |
| `audience?`              | The audience, presented as the aud claim in the access token, defines the intended consumer of the token. It takes `String` as a value.                                                                                        |
| `connection?`            | The name of the connection configured for your application. If null, it will redirect to the Auth0 sign-in page and show the Auth0 sign-in widget. It takes `String` as a value.                                               |
| `state?`                 | state                                                                                                                                                                                                                          |
| `response_type?`         | Defines which grant to execute for the authorization server. It takes `String` as a value.                                                                                                                                     |
| `nonce?`                 | nonce                                                                                                                                                                                                                          |
| `redirect_uri?`          | It can be used to specify the default URL, where your custom jwt verifier can redirect your browser to with the result. If you are using Auth0, it must be allowlisted in the Allowed Callback URLs in your Auth0 application. |

</TabItem>

<TabItem value="interface">

```kotlin
data class ExtraLoginOptions(
  private var additionalParams : HashMap<String, String>? = null,
  private var domain : String? = null,
  private var client_id : String? = null,
  private var leeway : String? = null,
  private var userIdField : String? = null,
  private var isUserIdCaseSensitive : Boolean? = null,
  private var display : Display? = null,
  private var prompt : Prompt? = null,
  private var max_age : String? = null,
  private var ui_locales : String? = null,
  private var id_token : String? = null,
  private var id_token_hint : String? = null,
  private var access_token : String? = null,
  private var flow_type : EmailFlowType? = null,
  private var acr_values : String? = null,
  private var scope : String? = null,
  private var audience : String? = null,
  private var connection : String? = null,
  private var state : String? = null,
  private var response_type : String? = null,
  private var nonce : String? = null,
  private var redirect_uri : String? = null
)

enum class EmailFlowType {
    @SerializedName("code")
    CODE,
    @SerializedName("link")
    LINK
}
```

</TabItem>
</Tabs>

### Single verifier Usage

<!-- vale off -->

<Tabs
  defaultValue="auth0"
  values={[
    { label: "Auth0", value: "auth0" },
    { label: "Custom JWT", value: "custom-jwt" },
    { label: "Email Passwordless", value: "email-passwordless" },
    { label: "SMS Passwordless", value: "sms-passwordless" },
  ]}
>

<TabItem value="auth0">

Auth0 has a special sign-in flow, called the SPA flow. This flow requires a `client_id` and `domain` to be passed, and Web3Auth will get the JWT `id_token` from Auth0 directly. You can pass these configurations in the `ExtraLoginOptions` object in the `connectTo` method.

```kotlin

val web3Auth = Web3Auth(
  Web3AuthOptions(
    clientId = "YOUR_WEB3AUTH_CLIENT_ID", // Pass over your Web3Auth Client ID from Developer Dashboard
    web3AuthNetwork = Web3AuthNetwork.SAPPHIRE_MAINNET,
    redirectUrl = "{YOUR_APP_PACKAGE_NAME}://auth",
    // focus-start
    authConnectionConfig = listOf(AuthConnectionConfig(
      authConnectionId = "auth-connection-id", // Get it from MetaMask Developer Dashboard
      authConnection = AuthConnection.CUSTOM,
      clientId = getString(R.string.auth0_project_id) // Auth0's client id
    ))
    // focus-end
  ),
  this
)

val loginCompletableFuture: CompletableFuture<Web3AuthResponse> = web3Auth.connectTo(
  LoginParams(
    AuthConnection.CUSTOM,
    // focus-start
    extraLoginOptions = ExtraLoginOptions(
      domain = "https://username.us.auth0.com", // Domain of your Auth0 app
      userIdField = "sub", // The field in jwt token which maps to user id.
    )
    // focus-end
  )
)
```

</TabItem>

<TabItem value="custom-jwt">
If you're using any other provider like Firebase, AWS identity services, or deploying your own custom JWT
server, you need to put the jwt token into the `idToken` field of the `LoginParams`. For SFA (Single Factor Auth) mode, this enables direct authentication without additional sign-in flows.

```kotlin

val web3Auth = Web3Auth(
  Web3AuthOptions(
    clientId = "YOUR_WEB3AUTH_CLIENT_ID", // Pass over your Web3Auth Client ID from Developer Dashboard
    web3AuthNetwork = Web3AuthNetwork.SAPPHIRE_MAINNET,
    redirectUrl = "{YOUR_APP_PACKAGE_NAME}://auth",
    // focus-start
    authConnectionConfig = listOf(AuthConnectionConfig(
      authConnectionId = "auth-connection-id", // Get it from MetaMask Developer Dashboard
      authConnection = AuthConnection.CUSTOM,
    ))
    // focus-end
  ),
  this
)

val loginCompletableFuture: CompletableFuture<Web3AuthResponse> = web3Auth.connectTo(
  LoginParams(
    AuthConnection.CUSTOM,
    // focus-start
    idToken = "Your JWT id token",
    // focus-end
  )
)
```

</TabItem>

<TabItem value="email-passwordless">

To use the Email Passwordless sign-in, you need to put the email into the `loginHint` parameter of
the `LoginParams`. By default, the sign-in flow will be `code` flow, if you want to use the
`link` flow, you need to put `flow_type` into the `extraLoginOptions` parameter.

```kotlin

val web3Auth = Web3Auth(
  Web3AuthOptions(
    clientId = "YOUR_WEB3AUTH_CLIENT_ID", // Pass over your Web3Auth Client ID from Developer Dashboard
    web3AuthNetwork = Web3AuthNetwork.SAPPHIRE_MAINNET,
    redirectUrl = "{YOUR_APP_PACKAGE_NAME}://auth",
  ),
  this
)

val loginCompletableFuture: CompletableFuture<Web3AuthResponse> = web3Auth.connectTo(
  LoginParams(
    AuthConnection.EMAIL_PASSWORDLESS,
    // focus-start
    loginHint = "hello@web3auth.io",
    extraLoginOptions = ExtraLoginOptions(
      flow_type = EmailFlowType.CODE // Use CODE for OTP flow or LINK for magic link flow
    )
    // focus-end
  )
)
```

</TabItem>

<TabItem value="sms-passwordless">

To use the SMS Passwordless sign-in, send the phone number as the `loginHint` parameter of the
`LoginParams`. Please make sure the phone number is in the format of
+\{country_code}-\{phone_number}, that is, (+91-09xx901xx1).

```kotlin

val web3Auth = Web3Auth(
  Web3AuthOptions(
    clientId = "YOUR_WEB3AUTH_CLIENT_ID", // Pass over your Web3Auth Client ID from Developer Dashboard
    web3AuthNetwork = Web3AuthNetwork.SAPPHIRE_MAINNET,
    redirectUrl = "{YOUR_APP_PACKAGE_NAME}://auth",
  ),
  this
)

// focus-start
val loginCompletableFuture: CompletableFuture<Web3AuthResponse> = web3Auth.connectTo(
  LoginParams(
    AuthConnection.SMS_PASSWORDLESS,
    loginHint = "+91-9911223344"
  )
)
// focus-end

```

</TabItem>
</Tabs>

<!-- vale on -->

### Grouped Auth Connection Usage

You can use grouped auth connections to combine multiple sign-in methods to get the same address for the users regardless of their sign-in providers. For example, combining a Google and Email Passwordless sign-in, or Google and GitHub via Auth0 to access the same address for your user.

```kotlin

val web3Auth = Web3Auth(
  Web3AuthOptions(
    clientId = "YOUR_WEB3AUTH_CLIENT_ID", // Pass over your Web3Auth Client ID from Developer Dashboard
    web3AuthNetwork = Web3AuthNetwork.SAPPHIRE_MAINNET,
    redirectUrl = "{YOUR_APP_PACKAGE_NAME}://auth",
    // focus-start
    authConnectionConfig = listOf(
      AuthConnectionConfig(
        authConnectionId = "aggregate-sapphire",
        groupedAuthConnectionId = "w3a-google",
        authConnection = AuthConnection.GOOGLE,
        name = "Aggregate Login",
        clientId = getString(R.string.web3auth_google_client_id)
      ),
      AuthConnectionConfig(
        authConnectionId = "aggregate-sapphire",
        groupedAuthConnectionId = "w3a-a0-email-passwordless",
        authConnection = AuthConnection.CUSTOM,
        name = "Aggregate Login",
        clientId = getString(R.string.web3auth_auth0_client_id)
      )
    )
    // focus-end
  ),
  this
)

// focus-start
// Google Login
web3Auth.connectTo(LoginParams(AuthConnection.GOOGLE))
// focus-end

// focus-start
// Auth0 Login
web3Auth.connectTo(LoginParams(
  AuthConnection.CUSTOM,
  extraLoginOptions = ExtraLoginOptions(
    domain = "https://web3auth.au.auth0.com",
    userIdField = "email",
    isUserIdCaseSensitive = false
  )
))
// focus-end
```

---

## Dapp share

## Embedded Wallets infrastructure at a glance

As described in the [Embedded Wallets infrastructure](/embedded-wallets/infrastructure/), to enable non-custodial key management in Embedded Wallets, we split the private key into multiple parts, that is, into `shares`. These shares are a part of the offchain multisig, where multiple shares are stored in different places and can be used to reconstruct the private key dynamically in the user's frontend application. Typically, there are 3 shares:

1. **`ShareA` is managed by a sign-in service via node operators:** This share is further split amongst a network of nodes and retrieved via conventional authentication flows.
2. **`ShareB` is stored on the user's device:** Implementation is device and system specific. For example, on mobile devices, the share could be stored in device storage secured via biometrics.
3. **`ShareC` is a recovery share:** An extra share to be kept by the user, possibly kept on a separate device, downloaded or based on user input with enough entropy (such as, password, security questions, hardware device).

Similar to existing 2FA systems, a user needs to prove ownership of at least 2 out of 3 (2/3) shares, in order to retrieve their private key. This initial setup provides several benefits.

## The user experience in mobile platforms

The user experience on mobile platforms differs significantly from the web platforms. This is because the user has to be redirected to a browser where they can sign in using their social accounts and then return to the app once they have been successfully authenticated. This user experience shifts the context between two applications, whereas, in the web platforms, the context remains within the browser only.

For the dapp share sign-in flow, we need to reconstruct the Shares `A` and `B`. `Share B` is managed by the sign-in service and is provided on successful authentication. Whereas in web platforms, `Share A` is stored in the browser context. We can still store it in the browser context for mobile devices, but this has a few risks like users deleting browser data by mistake. This is a bigger problem in mobile devices since the user doesn't realize that the browser is being used to sign in within the app and clearing the browser data can cause sign-in to fail. Hence, to tackle this issue, Web3Auth issues a dapp share, that is, a backup share that can be stored by the app developer directly within their application and used to reconstruct the private key after the user signs in successfully.

## Dapp share in Android

Web3Auth issues a dapp share, that is, a backup share that can be stored by the app developer directly within their application and used to reconstruct the private key after the user signs in successfully.

After a successful sign-in from a user, the user details are returned as a response to the application in mobile devices.

#### Sample response in Android

```json
{
  "userInfo": {
    "email": "w3a-heroes@web3auth.com",
    "name": "Web3Auth Heroes",
    "profileImage": "https://lh3.googleusercontent.com/a/Ajjjsdsmdjmnm...",
    "authConnectionId": "torus",
    "userId": "w3a-heroes@web3auth.com",
    "authConnection": "google",
    "groupedAuthConnectionId": "w3a-google-sapphire",
    "dappShare": "", // 24 words of seed phrase will be sent only in case of custom auth connections
    "idToken": "<jwtToken issued by Web3Auth>",
    "oAuthIdToken": "<jwtToken issued by OAuth Provider>", // will be sent only in case of custom auth connections
    "oAuthAccessToken": "<accessToken issued by OAuth Provider>", // will be sent only in case of custom auth connections
    "isMfaEnabled": false // Returns whether the user has enabled MFA or not
  }
}
```

If you notice, the responses have a field called `dappShare` which is a 24 words seed phrase that can be used to reconstruct the private key. This dapp share is a supplement to the `Share A` and represents half of the private key. The application can store the dapp share in their own application local storage.

Now, while signing in, the user can use their social accounts to obtain one share, and the application provides the dapp share, removing the need to store the share in the browser context and enabling user to sign in without repeating the full flow. This can be done by passing over the stored dapp share value in the `connectTo` method.

:::note

One major thing to note here is that the `dappShare` is only available for custom auth connections and not the standard Web3Auth auth connections. This is done to make sure that an application only has access to the corresponding share to the private key of their application's user. Hence, to use dapp share, one has to use the custom authentication feature of Web3Auth. Also, the dapp share is only returned to users who have enabled 2FA to their account.

:::

```kotlin
web3Auth.connectTo(LoginParams(selectedLoginProvider, dappShare = "<24 words seed phrase>"))
```

## Example

```kotlin

class MainActivity : AppCompatActivity() {

	private lateinit var web3Auth: Web3Auth

	private fun signIn() {
		val selectedLoginProvider = AuthConnection.GOOGLE
		// Can be GOOGLE, FACEBOOK, TWITCH etc.
		val loginCompletableFuture: CompletableFuture<Web3AuthResponse> =
				web3Auth.connectTo(LoginParams(selectedLoginProvider,
						// focus-next-line
						dappShare = "<24 words seed phrase>"))
		loginCompletableFuture.whenComplete { loginResponse, error ->
			if (error == null) {
				// render logged in UI
			} else {
				// render error UI
			}

		}
	}

	override fun onCreate(savedInstanceState: Bundle?) {
		// ...
		// Setup UI and event handlers
		val signInButton = findViewById<Button>(R.id.signInButton)
		signInButton.setOnClickListener { signIn() }
		// ...
	}
	// ...
}
```

---

## Multi-factor authentication

Embedded Wallets prioritizes security by offering Multi-Factor Authentication (MFA). MFA is an extra layer of protection that verifies a user's identity when accessing their account.

To ensure ownership, the user must provide two or more different backup factors. They have the option to choose from the device, social, backup factor (seed phrase), and password factors to guarantee access to their web3 account. Once a user creates a recovery factor, MFA is enabled, and their keys are divided into three shares for offchain multi-sig, making the key self-custodial.

These backup factors simplify the user experience when recovering their account if they lose access to the original device, or they can sign in on a new device.

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this SDK in a production environment is the **Scale Plan**. You can use this feature in Web3Auth Sapphire Devnet network for free.

:::

## Enable using the multi-factor authentication level

For a dapp, we provide various options to set up MFA. You can customize the MFA screen by passing the `mfaLevel` parameter in the `connectTo` method. You can enable or disable a backup factor and change their order. Currently, there are four values for MFA level.

:::caution Note

If you are using default verifiers, your users may have set up MFA on other dapps that also use default Web3Auth verifiers. In this case, the MFA screen will continue to appear if the user has enabled MFA on other dapps. This is because MFA cannot be turned off once it is enabled.

:::

### Multi-factor authentication level options

| MFA Level | Description                                                  |
| --------- | ------------------------------------------------------------ |
| DEFAULT   | Shows the MFA screen every third sign-in.                    |
| OPTIONAL  | Shows the MFA screen on every sign-in, but user can skip it. |
| MANDATORY | Makes it mandatory to set up MFA after first sign-in.        |
| NONE      | Skips the MFA setup screen.                                  |

### Usage

```kotlin
val loginResponse = web3Auth.connectTo(
  LoginParams(
    AuthConnection.GOOGLE,
    // focus-next-line
    mfaLevel = MFALevel.MANDATORY
  )
)
```

## Explicitly enable multi-factor authentication

The `enableMFA` method is used to trigger MFA setup flow for users. The method takes `LoginParams` which will used during custom verifiers. If you are using default sign-in providers, you don't need to pass `LoginParams`. If you are using custom JWT verifiers, you need to pass the JWT token in `loginParams` as well.

<Tabs
  defaultValue="default-verifier"
  values={[
    { label: "Default Verifier", value: "default-verifier" },
    { label: "Custom JWT Verifier", value: "custom-jwt-verifier" },
  ]}
>

<TabItem value = "default-verifier">

```kotlin title="Usage"

class MainActivity : AppCompatActivity() {
    private lateinit var web3Auth: Web3Auth

     private fun enableMFA() {
       // focus-next-line
       val completableFuture = web3Auth.enableMFA()

        completableFuture.whenComplete{_, error ->
            if (error == null) {
                Log.d("MainActivity_Web3Auth", "Launched successfully")
                // Add your logic
            } else {
                // Add your logic on error
                Log.d("MainActivity_Web3Auth", error.message ?: "Something went wrong")
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        // Setup UI and event handlers
        val enableMFAButton = findViewById<Button>(R.id.enableMFAButton)
        enableMFAButton.setOnClickListener { enableMFA() }
        ...
    }
    ...
}
```

</TabItem>

<TabItem value="custom-jwt-verifier">

```kotlin title="Usage"

class MainActivity : AppCompatActivity() { private lateinit var web3Auth: Web3Auth

     private fun enableMFA() {
        val loginParams = LoginParams(
            AuthConnection.CUSTOM,
            idToken = "your_jwt_token"
        )

        // focus-next-line
        val completableFuture = web3Auth.enableMFA(loginParams)

        completableFuture.whenComplete{_, error ->
            if (error == null) {
                Log.d("MainActivity_Web3Auth", "Launched successfully")
                // Add your logic
            } else {
                // Add your logic on error
                Log.d("MainActivity_Web3Auth", error.message ?: "Something went wrong")
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        // Setup UI and event handlers
        val enableMFAButton = findViewById<Button>(R.id.enableMFAButton)
        enableMFAButton.setOnClickListener { enableMFA() }
        ...
    }
    ...

}

```

</TabItem>
</Tabs>

## Configure multi-factor authentication settings

You can configure the order of MFA or enable/disable MFA type by passing the `mfaSettings` parameter in `Web3AuthOptions`.

:::note Note

- At least two factors are mandatory when setting up the `MfaSettings`.
- If you set `mandatory: true` for all factors, the user must set up all four factors.
- If you set `mandatory: false` for all factors, the user can skip setting up MFA. But at least two factors are mandatory.
- If you set `mandatory: true` for some factors and `mandatory: false` for others, the user must set up the mandatory factors and can skip the optional factors. But, the user must set up at least two factors.
- The `priority` field is used to set the order of the factors. The factor with the lowest priority will be the first factor to be set up. The factor with the highest priority will be the last factor to be set up.

:::

### Parameters - `MfaSettings`

`MfaSettings` allows you to set the type of the MFA.

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Class", value: "class" },
  ]}
>

<TabItem value="table">

| Parameter              | Description                                                                   |
| ---------------------- | ----------------------------------------------------------------------------- |
| `deviceShareFactor?`   | MFA setting for deviceShareFactor. It accepts `MfaSetting` as a value.        |
| `backUpShareFactor?`   | MFA setting for backUpShareFactor. It accepts `MfaSetting` as a value.        |
| `socialBackupFactor?`  | MFA setting for socialBackupFactor. It accepts `MfaSetting` as a value.       |
| `passwordFactor?`      | MFA setting for the password factor. It accepts `MfaSetting` as a value.      |
| `passkeysFactor?`      | MFA setting for the passkeys factor. It accepts `MfaSetting` as a value.      |
| `authenticatorFactor?` | MFA setting for the authenticator factor. It accepts `MfaSetting` as a value. |

</TabItem>

<TabItem value="class">

```kotlin
	data class MfaSettings(
		private var deviceShareFactor: MfaSetting? = null,
		private var backUpShareFactor: MfaSetting? = null,
		private var socialBackupFactor: MfaSetting? = null,
		private var passwordFactor: MfaSetting? = null,
		private var passkeysFactor: MfaSetting? = null,
		private var authenticatorFactor: MfaSetting? = null,
	)
```

</TabItem>
</Tabs>

### Parameters - `MfaSetting` by factor

`MfaSetting` allows you to configure MFA behavior for a particular MFA type.

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Class", value: "class" },
  ]}
>

<TabItem value="table">

| Parameter    | Description                                                                     |
| ------------ | ------------------------------------------------------------------------------- |
| `enable`     | Enable/Disable MFA. It accepts `Boolean` as a value.                            |
| `priority?`  | Priority of MFA. It accepts `Int` as a value, where valid range is from 1 to 4. |
| `mandatory?` | Mandatory/Optional MFA. It accepts `Boolean` as a value.                        |

</TabItem>

<TabItem value="class">

```kotlin
data class MfaSetting(
	var enable: Boolean,
	var priority: Int?,
	var mandatory: Boolean?
)
```

</TabItem>
</Tabs>

### Usage

```kotlin

val web3Auth = Web3Auth(
  Web3AuthOptions(
    clientId = "YOUR_WEB3AUTH_CLIENT_ID", // Pass over your Web3Auth Client ID from Developer Dashboard
    web3AuthNetwork = Web3AuthNetwork.SAPPHIRE_MAINNET,
    redirectUrl = "{YOUR_APP_PACKAGE_NAME}://auth",
    // focus-start
    mfaSettings = MfaSettings(
      deviceShareFactor = MfaSetting(true, 1, true),
      socialBackupFactor = MfaSetting(true, 2, true),
      passwordFactor = MfaSetting(true, 3, false),
      backUpShareFactor = MfaSetting(true, 4, false),
      passkeysFactor = MfaSetting(true, 5, true),
      authenticatorFactor = MfaSetting(true, 6, true),
    )
    // focus-end
  ),
  this
)

val loginResponse = web3Auth.connectTo(
  LoginParams(
    AuthConnection.GOOGLE,
    // focus-next-line
    mfaLevel = MFALevel.MANDATORY
  )
)
```

---

## Smart Accounts

Smart Accounts enable Account Abstraction (ERC-4337) for your users, allowing features like gas sponsorship (paymasters), batched transactions, and session keys. Smart account support is configured in your Web3Auth Dashboard and is automatically applied when you use `showWalletUI` or `request`.

:::info

Smart Account configuration is managed at the project level in the [Web3Auth Dashboard](https://dashboard.web3auth.io). The SDK automatically retrieves the configuration during `initialize()`.

:::

## Wallet Services Configuration

You can customize the wallet UI behavior for smart account flows using `walletServicesConfig` in `Web3AuthOptions`.

### `WalletServicesConfig`

| Parameter               | Description                                                                                                                                                                              |
| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `confirmationStrategy?` | Controls how transaction confirmations are presented. Accepts `ConfirmationStrategy` as a value. Default is `ConfirmationStrategy.DEFAULT`.                                              |
| `whiteLabel?`           | Optional whitelabel configuration to apply specifically to the Wallet Services UI. Accepts `WhiteLabelData` as a value. When set, it is merged with the project-level whitelabel config. |

### `ConfirmationStrategy`

| Value          | Description                                                         |
| -------------- | ------------------------------------------------------------------- |
| `POPUP`        | Shows transaction confirmations in a popup window.                  |
| `MODAL`        | Shows transaction confirmations in a modal overlay.                 |
| `AUTO_APPROVE` | Automatically approves transactions without showing a confirmation. |
| `DEFAULT`      | Uses the platform default confirmation behavior.                    |

### Interface

```kotlin
data class WalletServicesConfig(
    val confirmationStrategy: ConfirmationStrategy? = ConfirmationStrategy.DEFAULT,
    var whiteLabel: WhiteLabelData? = null
)

enum class ConfirmationStrategy {
    @SerializedName("popup")
    POPUP,
    @SerializedName("modal")
    MODAL,
    @SerializedName("auto-approve")
    AUTO_APPROVE,
    @SerializedName("default")
    DEFAULT
}
```

### Usage

```kotlin
val web3Auth = Web3Auth(
  Web3AuthOptions(
    clientId = "YOUR_WEB3AUTH_CLIENT_ID",
    web3AuthNetwork = Web3AuthNetwork.SAPPHIRE_MAINNET,
    redirectUrl = "YOUR_APP_SCHEME://auth",
    walletServicesConfig = WalletServicesConfig(
      confirmationStrategy = ConfirmationStrategy.MODAL
    )
  ),
  this
)
```

## Using Smart Account Operations

Once smart accounts are enabled in your dashboard, you can use the `request` method to send user operations. See the [request](../../usage/request) page for full details and examples.

### Supported Smart Account Methods

| Method                         | Description                                      |
| ------------------------------ | ------------------------------------------------ |
| `eth_sendUserOperation`        | Send a user operation for account abstraction.   |
| `eth_estimateUserOperationGas` | Estimate gas for a user operation.               |
| `wallet_showUserOperation`     | Display user operation details in the wallet UI. |

### Example

```kotlin
val userOp = JsonObject().apply {
    addProperty("sender", smartAccountAddress)
    addProperty("nonce", "0x0")
    addProperty("initCode", "0x")
    addProperty("callData", encodedCallData)
    addProperty("callGasLimit", "0x5208")
    addProperty("verificationGasLimit", "0x5208")
    addProperty("preVerificationGas", "0x5208")
    addProperty("maxFeePerGas", "0x3b9aca00")
    addProperty("maxPriorityFeePerGas", "0x3b9aca00")
    addProperty("paymasterAndData", "0x")
    addProperty("signature", "0x")
}

val params = JsonArray().apply {
    add(userOp)
}

val userOpCompletableFuture = web3Auth.request(
    "eth_sendUserOperation",
    requestParams = params
)

userOpCompletableFuture.whenComplete { result, error ->
    if (error == null) {
        Log.d("UserOp Hash", result.toString())
    } else {
        Log.d("UserOp Error", error.message ?: "Failed to send user operation")
    }
}
```

:::tip

The bundler and paymaster configuration is automatically handled by the Web3Auth Dashboard. You do not need to provide these URLs manually in your Android code.

:::

---

## Whitelabel

Embedded Wallets supports whitelabeling with application branding for a consistent user experience. You can customize three different aspects:

- **UI elements:** Customize the appearance of modals and components
- **Branding:** Apply your brand colors, logos, and themes
- **Translations:** Localize the interface for your users

:::info

All of these settings can be easily managed directly from the Embedded Wallets dashboard. Once you update your branding, or UI preferences there, the changes will automatically apply to your integration.

:::

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this
SDK in a production environment is the **Growth Plan**. You can use this feature in Web3Auth
Sapphire Devnet network for free.

:::

## Customizing the Web3Auth sign-in screens

For defining custom UI, branding, and translations for your brand during Embedded Wallets instantiation, you just need to specify an additional parameter within the `Web3AuthOptions` object called `whiteLabel`. This parameter takes object called `WhiteLabelData`.

### `WhiteLabelData`

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Interface", value: "interface" },
  ]}
>

<TabItem value="table">

| Parameter          | Description                                                                                                                                                              |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `appName?`         | Display name for the app in the UI.                                                                                                                                      |
| `logoLight?`       | App logo to be used in dark mode. It accepts a URL in `String` as a value.                                                                                               |
| `logoDark?`        | App logo to be used in light mode. It accepts a URL in `String` as a value.                                                                                              |
| `defaultLanguage?` | Language which will be used by Web3Auth, app will use browser language if not specified. Default language is `Language.EN`. Checkout `Language` for supported languages. |
| `mode?`            | Theme mode for the sign-in modal. Choose between `ThemeModes.AUTO`, `ThemeModes.LIGHT` or `ThemeModes.DARK` background modes. Default value is `ThemeModes.AUTO`.        |
| `theme?`           | Used to customize the theme of the sign-in modal. It accepts `HashMap` as a value.                                                                                       |
| `appUrl?`          | URL to be used in the Modal. It accepts a URL in `String` as a value.                                                                                                    |
| `useLogoLoader?`   | Use logo loader. If `logoDark` and `logoLight` are null, the default Web3Auth logo will be used for the loader. Default value is false.                                  |

</TabItem>

<TabItem value="interface">

```kotlin
data class WhiteLabelData(
    var appName: String? = null,
    var appUrl: String? = null,
    var logoLight: String? = null,
    var logoDark: String? = null,
    var defaultLanguage: Language? = Language.EN,
    var mode: ThemeModes? = null,
    var useLogoLoader: Boolean? = false,
    var theme: HashMap<String, String?>? = null
)
```

</TabItem>
</Tabs>

### `name`

The name of the application. This will be displayed in the key reconstruction page.

  
    
      Standard screen without any change
    
    
  
  
    
      Name changed to <code>Formidable Duo</code>
    
    
  

### `logoLight` & `logoDark`

The logo of the application. Displayed in dark and light mode respectively. This will be displayed
in the key reconstruction page.

  
    
      <code>logoLight</code> on dark mode
    
    
  
  
    
      <code>logoDark</code> on light mode
    
    
  

### `defaultLanguage`

Default language will set the language used on all OpenLogin screens. The supported languages are:

  
    
      
        <code>en</code> - English (default)
      
      
        <code>de</code> - German
      
      
        <code>ja</code> - Japanese
      
      
        <code>ko</code> - Korean
      
      
        <code>zh</code> - Mandarin
      
      
        <code>es</code> - Spanish
      
      
        <code>fr</code> - French
      
      
        <code>pt</code> - Portuguese
      
      
        <code>nl</code> - Dutch
      
      
        <code>tr</code> - Turkish
      
    
  
  
    
  

### `dark`

Can be set to `true` or `false` with default set to `false`.

  
    
      For Light: <code>dark: false</code>
    
    
  
  
    
      For Dark: <code>dark: true</code>
    
    
  

### `theme`

Theme is a record of colors that can be configured. As of, now only `primary` color can be set and
has effect on OpenLogin screens (default primary color is `#0364FF`). Theme affects icons and links.
Examples below.

  
    
      Standard color <code>#0364FF</code>
    
    
  
  
    
      Color changed to <code>#D72F7A</code>
    
    
  

### Example

```kotlin title="Usage"
web3Auth = Web3Auth(
  Web3AuthOptions(
    clientId = getString(R.string.web3auth_project_id),
    web3AuthNetwork = Web3AuthNetwork.SAPPHIRE_MAINNET,
    redirectUrl = "{YOUR_APP_PACKAGE_NAME}://auth",
    // Optional whitelabel object
    // focus-start
    whiteLabel = WhiteLabelData(
      appName = "Web3Auth Sample App",
      appUrl = null,
      logoLight = null,
      logoDark = null,
      defaultLanguage = Language.EN, // EN, DE, JA, KO, ZH, ES, FR, PT, NL, TR
      mode = ThemeModes.DARK, // LIGHT, DARK, AUTO
      useLogoLoader = true,
      theme = hashMapOf(
        "primary" to "#229954"
      )
    )
    // focus-end
  ),
  this
)
```

---

## Examples

<ExampleCards exampleMap={pnpAndroidExamples} />

---

## Using Android SDK

Embedded Wallets provides a comprehensive set of functions to handle authentication, user management, and blockchain interactions in your Android applications. These functions allow you to implement features like user sign-in, Multi-Factor Authentication (MFA), private key retrieval, and Wallet Services with minimal effort. Each function is designed to handle a specific aspect of Embedded Wallets' functionality, making it easy to integrate into your Android projects.

## List of functions

:::tip

For detailed usage, configuration options, and code examples, refer to the dedicated documentation page for each function.

:::

### Authentication functions

| Function Name                     | Description                                                                                          |
| --------------------------------- | ---------------------------------------------------------------------------------------------------- |
| [`connectTo()`](./connect-to.mdx) | Signs in the user with the selected auth connection. Supports both PnP and SFA authentication modes. |
| [`logout()`](./logout.mdx)        | Signs out the user from the current session.                                                         |

### User management functions

| Function Name                          | Description                                                                                   |
| -------------------------------------- | --------------------------------------------------------------------------------------------- |
| [`getUserInfo()`](./get-user-info.mdx) | Retrieves the authenticated user's information as a `UserInfo` object.                        |
| `getWeb3AuthResponse()`                | Retrieves the full `Web3AuthResponse` from the current session, including keys and user info. |

### Private key functions

| Function Name                                             | Description                                                                     |
| --------------------------------------------------------- | ------------------------------------------------------------------------------- |
| [`getPrivateKey()`](./get-private-key.mdx)                | Retrieve the user's secp256k1 private key for EVM-compatible chains.            |
| [`getEd25519PrivateKey()`](./get-ed25519-private-key.mdx) | Retrieve the user's ed25519 private key for chains like Solana, Near, Algorand. |

### Security functions

| Function Name                     | Description                                |
| --------------------------------- | ------------------------------------------ |
| [`enableMFA()`](./enable-mfa.mdx) | Enables MFA for the user.                  |
| [`manageMFA()`](./manage-mfa.mdx) | Allows users to manage their MFA settings. |

### Wallet Services functions

| Function Name                                    | Description                                                                                            |
| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------ |
| [`showWalletUI()`](./launch-wallet-services.mdx) | Launches the prebuilt Wallet Services UI in WebView with automatic chain configuration from dashboard. |
| [`request()`](./request.mdx)                     | Opens prebuilt transaction screens for signing EVM transactions with simplified parameters.            |

## `getWeb3AuthResponse()`

The `getWeb3AuthResponse()` method returns the full `Web3AuthResponse` from the current session. This gives you direct access to all session data including keys, user info, signatures, and factor keys.

```kotlin
val response = web3Auth.getWeb3AuthResponse()
```

:::warning

`getWeb3AuthResponse()` throws an `Error` with code `NOUSERFOUND` when no active session exists. Check for an active session using `getPrivateKey().isNotEmpty()` before calling this method.

:::

For most use cases, prefer the typed methods (`getPrivateKey()`, `getEd25519PrivateKey()`, `getUserInfo()`) which provide a more ergonomic API with clear error messages.

---

## Sign in a user

To sign in a user, use the `connectTo` method.
It triggers the sign-in flow and opens a browser modal where the user can authenticate.
Pass supported auth connections to `connectTo` for specific social sign-in providers such as GOOGLE, APPLE, and FACEBOOK, or use whitelabel sign-in.

## Parameters

The `connectTo` method takes `LoginParams` as a required input.

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Class", value: "class" },
  ]}
>

<TabItem value="table">

| Parameter                  | Description                                                                                                                                                                                                                                                                                                                                                                           |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `authConnection`           | It sets the OAuth sign-in method to be used. You can use any of the supported values are `GOOGLE`, `FACEBOOK`, `REDDIT`, `DISCORD`, `TWITCH`, `APPLE`, `LINE`, `GITHUB`, `KAKAO`, `LINKEDIN`, `TWITTER`, `WEIBO`, `WECHAT`, `EMAIL_PASSWORDLESS`, `CUSTOM`, `SMS_PASSWORDLESS`, and `FARCASTER`.                                                                                      |
| `authConnectionId?`        | The connection ID for custom authentication. This is optional for social sign-in providers but required for custom JWT-based authentication.                                                                                                                                                                                                                                          |
| `groupedAuthConnectionId?` | Used for aggregate verifiers. When multiple auth connections are grouped under a single verifier, this specifies the aggregate verifier ID.                                                                                                                                                                                                                                           |
| `loginHint?`               | Provides a hint for the sign-in process. For email passwordless, this should be the email address. For SMS passwordless, this should be the phone number.                                                                                                                                                                                                                             |
| `idToken?`                 | JWT token for SFA (Single Factor Auth) sign-in. When provided, sign-in uses SFA mode.                                                                                                                                                                                                                                                                                                 |
| `extraLoginOptions?`       | It can be used to set the OAuth sign-in options for corresponding `authConnection`. Default value for the field is `null`, and it accepts `ExtraLoginOptions` as a value.                                                                                                                                                                                                             |
| `appState?`                | It can be used to keep track of the app state when user will be redirected to app after sign-in. Default is `null`, and accepts `String` as a value.                                                                                                                                                                                                                                  |
| `mfaLevel?`                | Customize the MFA screen shown to the user during OAuth authentication. Default value for field is `MFALevel.DEFAULT`, which shows MFA screen every third sign-in. It accepts `MFALevel` as a value.                                                                                                                                                                                  |
| `dappShare?`               | Custom verifier sign-in can return a dapp share after successful authentication. This is useful if the dapps want to use this share to allow users to sign in seamlessly. It accepts `String` as a value.                                                                                                                                                                             |
| `curve?`                   | It will be used to determine the public key encoded in the jwt token which returned in `getUserInfo` function after the user signs in. This parameter won't change format of private key returned by Web3Auth. Private key returned by `getPrivateKey` is always secp256k1. To get the ed25519 key you can use `getEd25519PrivateKey` method. The default value is `Curve.SECP256K1`. |
| `dappUrl?`                 | URL of the dapp. This is used for analytics and debugging purposes.                                                                                                                                                                                                                                                                                                                   |

</TabItem>

<TabItem value="class">

```kotlin
data class LoginParams(
    val authConnection: AuthConnection,
    val authConnectionId: String? = null,
    val groupedAuthConnectionId: String? = null,
    val appState: String? = null,
    val mfaLevel: MFALevel? = null,
    val extraLoginOptions: ExtraLoginOptions? = null,
    var dappShare: String? = null,
    val curve: Curve? = Curve.SECP256K1,
    var dappUrl: String? = null,
    var loginHint: String? = null,
    val idToken: String? = null,
)

enum class AuthConnection {
    @SerializedName("google")
    GOOGLE,
    @SerializedName("facebook")
    FACEBOOK,
    @SerializedName("reddit")
    REDDIT,
    @SerializedName("discord")
    DISCORD,
    @SerializedName("twitch")
    TWITCH,
    @SerializedName("apple")
    APPLE,
    @SerializedName("line")
    LINE,
    @SerializedName("github")
    GITHUB,
    @SerializedName("kakao")
    KAKAO,
    @SerializedName("linkedin")
    LINKEDIN,
    @SerializedName("twitter")
    TWITTER,
    @SerializedName("weibo")
    WEIBO,
    @SerializedName("wechat")
    WECHAT,
    @SerializedName("email_passwordless")
    EMAIL_PASSWORDLESS,
    @SerializedName("custom")
    CUSTOM, //for jwt
    @SerializedName("sms_passwordless")
    SMS_PASSWORDLESS,
    @SerializedName("farcaster")
    FARCASTER
}
```

</TabItem>
</Tabs>

## Return Value: `Web3AuthResponse`

`connectTo` returns a `CompletableFuture<Web3AuthResponse>`. The response contains:

| Field                   | Type            | Description                                                                                |
| ----------------------- | --------------- | ------------------------------------------------------------------------------------------ |
| `privateKey`            | `String?`       | secp256k1 private key (EVM). Use `getPrivateKey()` for safe retrieval.                     |
| `ed25519PrivKey`        | `String?`       | Ed25519 private key (Solana, Near, etc.). Use `getEd25519PrivateKey()` for safe retrieval. |
| `userInfo`              | `UserInfo?`     | User profile information. See [getUserInfo](../get-user-info) for field details.           |
| `coreKitKey`            | `String?`       | SFA key returned when `useSFAKey = true`.                                                  |
| `coreKitEd25519PrivKey` | `String?`       | SFA Ed25519 key returned when `useSFAKey = true`.                                          |
| `factorKey`             | `String?`       | Factor key for MFA flows.                                                                  |
| `sessionId`             | `String?`       | Current session identifier.                                                                |
| `signatures`            | `List<String>?` | Session token signatures for advanced use cases.                                           |
| `error`                 | `String?`       | Non-null when the session returned an error.                                               |

Prefer the typed methods `getPrivateKey()` and `getEd25519PrivateKey()` over reading `privateKey` directly; they correctly handle the `useSFAKey` flag and throw `IllegalStateException` instead of returning null when no key is available.

## Usage

```kotlin

val web3Auth = Web3Auth(
  Web3AuthOptions(
    clientId = "YOUR_WEB3AUTH_CLIENT_ID", // Pass over your Web3Auth Client ID from Developer Dashboard
    web3AuthNetwork = Web3AuthNetwork.SAPPHIRE_MAINNET,
    redirectUrl = "{YOUR_APP_PACKAGE_NAME}://auth",
  ),
  this
)

// focus-start
val loginCompletableFuture: CompletableFuture<Web3AuthResponse> = web3Auth.connectTo(
    LoginParams(AuthConnection.GOOGLE)
)
// focus-end
```

## Examples

<!-- vale off -->

<Tabs
  defaultValue="google"
  values={[
    { label: "Google", value: "google" },
    { label: "Facebook", value: "facebook" },
    { label: "Discord", value: "discord" },
    { label: "Twitch", value: "twitch" },
    { label: "Email Passwordless", value: "email_passwordless" },
    { label: "SMS Passwordless", value: "sms_passwordless" },
    { label: "Farcaster", value: "farcaster" },
    { label: "JWT", value: "jwt" },
  ]}
>

<TabItem value="google">

```kotlin

val web3Auth = Web3Auth(
  Web3AuthOptions(
    clientId = "YOUR_WEB3AUTH_CLIENT_ID", // Pass over your Web3Auth Client ID from Developer Dashboard
    web3AuthNetwork = Web3AuthNetwork.SAPPHIRE_MAINNET,
    redirectUrl = "{YOUR_APP_PACKAGE_NAME}://auth",
  ),
  this
)

// focus-start
val loginCompletableFuture: CompletableFuture<Web3AuthResponse> = web3Auth.connectTo(
    LoginParams(AuthConnection.GOOGLE)
)
// focus-end
```

</TabItem>

<TabItem value="facebook">

```kotlin

val web3Auth = Web3Auth(
  Web3AuthOptions(
    clientId = "YOUR_WEB3AUTH_CLIENT_ID", // Pass over your Web3Auth Client ID from Developer Dashboard
    web3AuthNetwork = Web3AuthNetwork.SAPPHIRE_MAINNET,
    redirectUrl = "{YOUR_APP_PACKAGE_NAME}://auth",
  ),
  this
)

// focus-start
val loginCompletableFuture: CompletableFuture<Web3AuthResponse> = web3Auth.connectTo(
    LoginParams(AuthConnection.FACEBOOK)
)
// focus-end
```

</TabItem>

<TabItem value="discord">

```kotlin

val web3Auth = Web3Auth(
  Web3AuthOptions(
    clientId = "YOUR_WEB3AUTH_CLIENT_ID", // Pass over your Web3Auth Client ID from Developer Dashboard
    web3AuthNetwork = Web3AuthNetwork.SAPPHIRE_MAINNET,
    redirectUrl = "{YOUR_APP_PACKAGE_NAME}://auth",
  ),
  this
)

// focus-start
val loginCompletableFuture: CompletableFuture<Web3AuthResponse> = web3Auth.connectTo(
    LoginParams(AuthConnection.DISCORD)
)
// focus-end
```

</TabItem>

<TabItem value="twitch">

```kotlin

val web3Auth = Web3Auth(
  Web3AuthOptions(
    clientId = "YOUR_WEB3AUTH_CLIENT_ID", // Pass over your Web3Auth Client ID from Developer Dashboard
    web3AuthNetwork = Web3AuthNetwork.SAPPHIRE_MAINNET,
    redirectUrl = "{YOUR_APP_PACKAGE_NAME}://auth",
  ),
  this
)

// focus-start
val loginCompletableFuture: CompletableFuture<Web3AuthResponse> = web3Auth.connectTo(
    LoginParams(AuthConnection.TWITCH)
)
// focus-end
```

</TabItem>

<TabItem value="email_passwordless">

```kotlin

val web3Auth = Web3Auth(
  Web3AuthOptions(
    clientId = "YOUR_WEB3AUTH_CLIENT_ID", // Pass over your Web3Auth Client ID from Developer Dashboard
    web3AuthNetwork = Web3AuthNetwork.SAPPHIRE_MAINNET,
    redirectUrl = "{YOUR_APP_PACKAGE_NAME}://auth",
  ),
  this
)

// focus-start
val loginCompletableFuture: CompletableFuture<Web3AuthResponse> = web3Auth.connectTo(
    LoginParams(
        AuthConnection.EMAIL_PASSWORDLESS,
        loginHint = "hello@web3auth.io"
    )
)
// focus-end
```

</TabItem>

<TabItem value="sms_passwordless">

```kotlin

val web3Auth = Web3Auth(
  Web3AuthOptions(
    clientId = "YOUR_WEB3AUTH_CLIENT_ID", // Pass over your Web3Auth Client ID from Developer Dashboard
    web3AuthNetwork = Web3AuthNetwork.SAPPHIRE_MAINNET,
    redirectUrl = "{YOUR_APP_PACKAGE_NAME}://auth",
  ),
  this
)

// focus-start
val loginCompletableFuture: CompletableFuture<Web3AuthResponse> = web3Auth.connectTo(
    LoginParams(
        AuthConnection.SMS_PASSWORDLESS,
        loginHint = "+91-9911223344"
    )
)
// focus-end
```

</TabItem>

<TabItem value="farcaster">

```kotlin

val web3Auth = Web3Auth(
  Web3AuthOptions(
    clientId = "YOUR_WEB3AUTH_CLIENT_ID", // Pass over your Web3Auth Client ID from Developer Dashboard
    web3AuthNetwork = Web3AuthNetwork.SAPPHIRE_MAINNET,
    redirectUrl = "{YOUR_APP_PACKAGE_NAME}://auth",
  ),
  this
)

// focus-start
val loginCompletableFuture: CompletableFuture<Web3AuthResponse> = web3Auth.connectTo(
  LoginParams(AuthConnection.FARCASTER)
)
// focus-end
```

</TabItem>

<TabItem value="jwt">

```kotlin title="Usage"

val web3Auth = Web3Auth(
  Web3AuthOptions(
    clientId = "YOUR_WEB3AUTH_CLIENT_ID", // Pass over your Web3Auth Client ID from Developer Dashboard
    web3AuthNetwork = Web3AuthNetwork.SAPPHIRE_MAINNET,
    redirectUrl = "{YOUR_APP_PACKAGE_NAME}://auth",
  ),
  this
)

// focus-start
val loginCompletableFuture: CompletableFuture<Web3AuthResponse> = web3Auth.connectTo(
    LoginParams(
        AuthConnection.CUSTOM,
        authConnectionId = "your_auth_connection_id",
        idToken = "your_jwt_token"
    )
)
// focus-end
```

</TabItem>
</Tabs>

<!-- vale on -->

---

## Enable MFA for a user

The `enableMFA` method is used to trigger MFA setup flow for users. The method takes `LoginParams` which will used during custom verifiers. If you are using default sign-in providers, you don't need to pass `LoginParams`. If you are using custom JWT verifiers, you need to pass the JWT token in `loginParams` as well.

## Usage

<Tabs
  defaultValue="default-verifier"
  values={[
    { label: "Default Verifier", value: "default-verifier" },
    { label: "Custom JWT Verifier", value: "custom-jwt-verifier" },
  ]}
>

<TabItem value = "default-verifier">

```kotlin title="Usage"

class MainActivity : AppCompatActivity() {
    private lateinit var web3Auth: Web3Auth

     private fun enableMFA() {
       // focus-next-line
       val completableFuture = web3Auth.enableMFA()

        completableFuture.whenComplete{_, error ->
            if (error == null) {
                Log.d("MainActivity_Web3Auth", "Launched successfully")
                // Add your logic
            } else {
                // Add your logic on error
                Log.d("MainActivity_Web3Auth", error.message ?: "Something went wrong")
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        // Setup UI and event handlers
        val enableMFAButton = findViewById<Button>(R.id.enableMFAButton)
        enableMFAButton.setOnClickListener { enableMFA() }
        ...
    }
    ...
}
```

</TabItem>

<TabItem value="custom-jwt-verifier">

:::warning

`enableMFA` does **not** accept an `idToken` in `LoginParams`. Passing `idToken` will cause the SDK to throw an `ENABLE_MFA_NOT_ALLOWED` error. For custom JWT verifiers, pass an empty `LoginParams` with the `authConnection` only; the SDK automatically uses the session's auth connection to re-authenticate.

:::

```kotlin title="Usage"

class MainActivity : AppCompatActivity() {
    private lateinit var web3Auth: Web3Auth

    private fun enableMFA() {
        val loginParams = LoginParams(
            AuthConnection.CUSTOM,
            authConnectionId = "your_auth_connection_id"
        )

        // focus-next-line
        val completableFuture = web3Auth.enableMFA(loginParams)

        completableFuture.whenComplete { _, error ->
            if (error == null) {
                Log.d("MainActivity_Web3Auth", "Launched successfully")
                // Add your logic
            } else {
                // Add your logic on error
                Log.d("MainActivity_Web3Auth", error.message ?: "Something went wrong")
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        // Setup UI and event handlers
        val enableMFAButton = findViewById<Button>(R.id.enableMFAButton)
        enableMFAButton.setOnClickListener { enableMFA() }
        ...
    }
    ...
}
```

</TabItem>
</Tabs>

---

## Ed25519 private key

To retrieve the Ed25519 private key of the user, use `getEd25519PrivateKey` method. This private key can be used to sign transactions on Solana, Near, Algorand, and other chains that use the ed25519 curve.

:::note

Web3Auth supports two widely used cryptographic curves, Secp256k1 and Ed25519, making it chain-agnostic and compatible with multiple blockchain networks. [Learn more about how to connect different blockchains](/embedded-wallets/connect-blockchain).

:::

:::info Session behavior

- When no active session exists, `getEd25519PrivateKey()` throws `IllegalStateException`. Check for an active session first using `getPrivateKey().isNotEmpty()`.
- If `useSFAKey = true` in `Web3AuthOptions`, this method returns the SFA Ed25519 core kit key instead of the standard Ed25519 key.

:::

## Usage

```kotlin
val ed25519PrivateKey = web3Auth.getEd25519PrivateKey()
```

---

## Secp256k1 private key

To retrieve the secp256k1 private key of the user, use `getPrivateKey` method. The method returns an EVM compatible private key which can be used to sign transactions on EVM compatible chains.

:::note

Web3Auth supports two widely used cryptographic curves, Secp256k1 and Ed25519, making it chain-agnostic and compatible with multiple blockchain networks. [Learn more about how to connect different blockchains](/embedded-wallets/connect-blockchain).

:::

:::info Session behavior

- When `initialize()` completes and no active session exists, `getPrivateKey()` returns an **empty string** (`""`). Use this to check for an active session.
- After a successful `connectTo()`, `getPrivateKey()` returns the private key.
- If `useSFAKey = true` in `Web3AuthOptions`, this method returns the SFA core kit key instead of the standard secp256k1 key.
- `getPrivateKey()` throws `IllegalStateException` if the internal response is in an unexpected null state.

:::

## Usage

```kotlin
val initializeCF = web3Auth.initialize()
initializeCF.whenComplete { _, error ->
    if (error == null) {
        val privateKey = web3Auth.getPrivateKey()
        if (privateKey.isNotEmpty()) {
            // Active session found, user is already logged in
        } else {
            // No active session, prompt user to log in
        }
    }
}
```

---

## Retrieve user information

You can use the `getUserInfo` method to retrieve various details about the user, such as their sign-in method, whether multi-factor authentication (MFA) is enabled, profile image, name, and other relevant information.

:::note

`getUserInfo()` throws an `Error` with code `NOUSERFOUND` when no active session exists. Always call it after `initialize()` completes and only when `getPrivateKey()` returns a non-empty string.

:::

## Usage

```kotlin
val userInfo = web3Auth.getUserInfo()
```

## `UserInfo` Fields

| Field                     | Type       | Description                                                                                          |
| ------------------------- | ---------- | ---------------------------------------------------------------------------------------------------- |
| `email`                   | `String`   | Email address of the user. Empty string if not available.                                            |
| `name`                    | `String`   | Display name of the user. Empty string if not available.                                             |
| `profileImage`            | `String`   | URL of the user's profile image. Empty string if not available.                                      |
| `authConnectionId`        | `String`   | The auth connection ID (verifier name) used to sign in.                                              |
| `groupedAuthConnectionId` | `String`   | The grouped auth connection ID if aggregate verifiers are used. Empty string if not applicable.      |
| `userId`                  | `String`   | The user's unique ID within the auth connection (for example, email for email-based, sub for OAuth). |
| `authConnection`          | `String`   | The auth connection type used (for example, `"google"`, `"custom"`).                                 |
| `dappShare`               | `String`   | dapp share for custom verifiers. Empty string for default verifiers.                                 |
| `idToken`                 | `String`   | JWT issued by Web3Auth after authentication.                                                         |
| `oAuthIdToken`            | `String`   | JWT issued by the OAuth provider. Only present for custom verifiers.                                 |
| `oAuthAccessToken`        | `String`   | Access token issued by the OAuth provider. Only present for custom verifiers.                        |
| `isMfaEnabled`            | `Boolean?` | Whether the user has MFA enabled. `null` if the information is not available in the session.         |

### Interface

```kotlin
data class UserInfo(
    var email: String = "",
    var name: String = "",
    var profileImage: String = "",
    var groupedAuthConnectionId: String = "",
    var authConnectionId: String = "",
    var userId: String = "",
    var authConnection: String = "",
    var dappShare: String = "",
    var idToken: String = "",
    var oAuthIdToken: String = "",
    var oAuthAccessToken: String = "",
    var isMfaEnabled: Boolean? = null
)
```

---

## Show wallet UI

The `showWalletUI` method launches a WebView which allows you to use the prebuilt Wallet Services UI.
The method automatically uses the chain configuration from your project settings and no longer requires a manual `ChainConfig` parameter.

### Supported features

- **EVM chains**: Full support for all EVM-compatible chains
- **Account abstraction**: Built-in support for smart accounts (ERC-4337)
- **Gas sponsorship**: Cover transaction fees for your users
- **Batch transactions**: Execute multiple transactions in one go
- **Custom spending limits**: Set transaction limits for enhanced security

:::note

Access to Wallet Services is gated.
You can use this feature on `sapphire_devnet` without a paid plan.
The minimum [pricing plan](https://web3auth.io/pricing.html) to use this feature in a production environment is the **Scale Plan**.

:::

:::warning

The chain configuration is now automatically retrieved from your project settings in the Embedded Wallets dashboard.
Make sure your project has the appropriate chains configured in the dashboard.

:::

## Usage

```kotlin
// focus-start
val completableFuture = web3Auth.showWalletUI()
// focus-end
```

You can also specify a custom path:

```kotlin
// focus-start
val completableFuture = web3Auth.showWalletUI("custom-wallet-path")
// focus-end
```

## Smart accounts configuration

When smart accounts are enabled in your Embedded Wallets dashboard, the wallet UI automatically provides account abstraction features.

### Dashboard configuration

1. Navigate to your project in the [Embedded Wallets dashboard](https://developer.metamask.io)
2. Enable Smart Accounts in your project settings
3. Configure your preferred bundler and paymaster providers

### Features available

Once configured, users can:

- **Send gasless transactions**: Transactions can be sponsored by your paymaster
- **Batch operations**: Multiple transactions can be bundled and executed as one
- **ERC-20 token payments**: Users can pay gas fees using ERC-20 tokens instead of native tokens
- **Automated transaction policies**: Set up rules for automatic transaction execution

### User experience

When smart accounts are enabled:

1. Users will see a smart account address instead of an EOA address
2. Transaction confirmation screens will show sponsorship details
3. Batch transaction options will be available in the wallet UI
4. Gas payment options will include ERC-20 tokens if configured

---

## Logging out a user

Logging out your user is as simple as calling the `logout` method. This method will clear the session data and the user will be logged out from Web3Auth.

## Usage

```kotlin
val logoutCompletableFuture = web3Auth.logout()
```

---

## Manage MFA for a user

The `manageMFA` method is used to trigger manage MFA flow for users, allowing users to update their MFA settings. The method takes `LoginParams` which will used during custom verifiers. If you are using default sign-in providers, you don't need to pass `LoginParams`. If you are using custom JWT verifiers, you need to pass the JWT token in `loginParams` as well.

## Usage

<Tabs
  defaultValue="default-verifier"
  values={[
    { label: "Default Verifier", value: "default-verifier" },
    { label: "Custom JWT Verifier", value: "custom-jwt-verifier" },
  ]}
>

<TabItem value = "default-verifier">

```kotlin
val manageMFACF = web3Auth.manageMFA()

manageMFACF.whenComplete{_, error ->
  if (error == null) {
     // Handle success
  } else {
     // Handle error
  }
}
```

</TabItem>

<TabItem value="custom-jwt-verifier">

```kotlin title="Usage"
val loginParams = LoginParams(
  AuthConnection.CUSTOM,
  authConnectionId = "your_auth_connection_id"
)

val manageMFACF = web3Auth.manageMFA(loginParams)

manageMFACF.whenComplete { _, error ->
  if (error == null) {
    // Handle success
  } else {
    // Handle error
  }
}
```

</TabItem>
</Tabs>

---

## Request signature

The `request` method facilitates the use of prebuilt transaction screens for signing transactions. The method will return [SignResponse](#signresponse). It can be used to sign transactions for any EVM chain and screens can be customized to your branding.

Please check the list of [JSON RPC methods](https://docs.metamask.io/wallet/reference/json-rpc-api/), noting that the request method currently supports only the signing methods.

## Parameters

| Parameter       | Description                                                                                                                                                                                             |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `method`        | JSON RPC method name in `String`. Supports signing methods and smart account operations (see supported methods below).                                                                                  |
| `requestParams` | Parameters for the corresponding method. The parameters should be in the list and correct sequence. Take a look at [RPC methods](https://docs.metamask.io/wallet/reference/json-rpc-api/) to know more. |
| `path?`         | The path where the signing service is located. Default value is `"wallet/request"`. This is an internal routing path for the Wallet Services infrastructure.                                            |
| `appState?`     | It can be used to keep track of the app state. Default is `null`, and accepts `String` as a value.                                                                                                      |

:::warning

The chain configuration is now automatically retrieved from your project settings in the Web3Auth Dashboard. The request will use the appropriate chain based on your project configuration.

:::

## Supported Methods

### Standard Signing Methods

- `personal_sign` - Sign a message
- `eth_sign` - Sign data
- `eth_signTypedData` - Sign typed structured data
- `eth_signTypedData_v4` - Sign typed structured data (v4)
- `eth_sendTransaction` - Send a transaction

### Smart Account Operations

When smart accounts are enabled in your dashboard, additional methods are available:

- `eth_sendUserOperation` - Send a user operation for account abstraction
- `eth_estimateUserOperationGas` - Estimate gas for a user operation
- `wallet_showUserOperation` - Display user operation details in wallet UI

## Usage

### Standard Transaction Signing

```kotlin
val params = JsonArray().apply {
    // Message to be signed
    add("Hello, World!")
    // User's EOA address
    add(address)
}

// focus-start
val signMsgCompletableFuture = web3Auth.request(
    "personal_sign",
    requestParams = params
)
// focus-end

signMsgCompletableFuture.whenComplete { signResult, error ->
    if (error == null) {
        // focus-next-line
        Log.d("Sign Result", signResult.toString())

    } else {
        Log.d("Sign Error", error.message ?: "Something went wrong")
    }
}
```

### Smart Account User Operation

When smart accounts are enabled, you can send user operations:

```kotlin
// Build user operation parameters
val userOp = JsonObject().apply {
    addProperty("sender", smartAccountAddress)
    addProperty("nonce", "0x0")
    addProperty("initCode", "0x")
    addProperty("callData", encodedCallData)
    addProperty("callGasLimit", "0x5208")
    addProperty("verificationGasLimit", "0x5208")
    addProperty("preVerificationGas", "0x5208")
    addProperty("maxFeePerGas", "0x3b9aca00")
    addProperty("maxPriorityFeePerGas", "0x3b9aca00")
    addProperty("paymasterAndData", "0x")
    addProperty("signature", "0x")
}

val params = JsonArray().apply {
    add(userOp)
}

// focus-start
val userOpCompletableFuture = web3Auth.request(
    "eth_sendUserOperation",
    requestParams = params
)
// focus-end

userOpCompletableFuture.whenComplete { result, error ->
    if (error == null) {
        // focus-next-line
        Log.d("UserOp Hash", result.toString())
    } else {
        Log.d("UserOp Error", error.message ?: "Failed to send user operation")
    }
}
```

:::tip

For smart account operations, the Web3Auth dashboard will automatically handle:

- Bundler URL configuration
- Paymaster integration for sponsored transactions
- User operation validation

:::

## SignResponse

| Name      | Description                                                   |
| --------- | ------------------------------------------------------------- |
| `success` | Determines whether the request was successful or not.         |
| `result?` | Holds the signature for the request when `success` is `true`. |
| `error?`  | Holds the error for the request when `success` is `false`.    |

---

## Embedded Wallets SDK for Flutter

## Overview

MetaMask Embedded Wallets SDK (formerly Web3Auth Plug and Play) provides social login authentication for Flutter applications. The Flutter SDK, written in Dart, helps you manage authentication state across both iOS and Android platforms. After sign-in, export the private key and use platform-native blockchain libraries such as web3dart or solana.

## Requirements

- **Android** API version 26 or newer
- **iOS** 14, Xcode 12+ and Swift 5.x
- Basic knowledge of Dart and Flutter Development

## Prerequisites

- Set up your project on the [Embedded Wallets dashboard](https://developer.metamask.io/)

:::tip

See the [dashboard setup](../../dashboard/README.mdx) guide to learn more.

:::

## Installation

To install the Web3Auth Flutter package, you have two options. You can either manually add the package in the `pubspec.yaml` file, or you can use the `flutter pub add` command.

### Add via pubspec.yaml

Add `web3auth_flutter` as a dependency to your `pubspec.yaml`:

```yaml
dependencies:
  web3auth_flutter: ^7.0.0
```

### Add via Flutter pub add

Add `web3auth_flutter` using `flutter pub add` command:

```sh
flutter pub add web3auth_flutter
```

### 1. Android configuration

Once we have installed Web3Auth Flutter SDK, we also need to add the configuration for Android.

#### Update `compileSdkVersion`

For Android build `compileSdkVersion` needs to be `34`. Check your app module Gradle file in your project to change it:

```groovy
android {
    namespace "com.example.app_name"
    // focus-next-line
    compileSdkVersion 34
   // ..
}
```

#### Add Embedded Wallets to Gradle

In your project-level Gradle file add JitPack repository:

```groovy
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
        // focus-next-line
        maven { url "https://jitpack.io" } // <-- Add this line
    }
}
```

#### Update permissions

Open your app's `AndroidManifest.xml` file and add the following permission. Please make sure the `<uses-permission>` element should be a direct child of the `<manifest>` root element:

```xml
<uses-permission android:name="android.permission.INTERNET" />
```

#### Configure deep link

Open your app's `AndroidManifest.xml` file and add the following deep link intent filter to your Main activity:

```xml
<intent-filter>
  <action android:name="android.intent.action.VIEW" />

  <category android:name="android.intent.category.DEFAULT" />
  <category android:name="android.intent.category.BROWSABLE" />

  <data android:scheme="{scheme}" android:host="{YOUR_APP_PACKAGE_NAME}"/>
  <!-- Accept URIs: w3a://com.example.w3aflutter -->
</intent-filter>
```

#### Handle custom tabs

For Android, you need to handle custom tabs lifecycle to trigger login exceptions. The Android SDK uses chrome custom tabs, and it's not possible to add a listener directly to the chrome custom tab close button to trigger login exceptions.

```dart
class LoginScreen extends StatefulWidget {
  @override
  _LoginScreenState createState() => _LoginScreenState();
}

class _LoginScreenState extends State<LoginScreen> with WidgetsBindingObserver {
  @override
  void initState() {
    super.initState();
    // focus-next-line
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void dispose() {
    super.dispose();
    // focus-next-line
    WidgetsBinding.instance.removeObserver(this);
  }

  // focus-start
  @override
  void didChangeAppLifecycleState(final AppLifecycleState state) {
    // This is important to trigger the user cancellation on Android.
    if (state == AppLifecycleState.resumed) {
      Web3AuthFlutter.setCustomTabsClosed();
    }
  }
  // focus-end
}
```

### 2. iOS configuration

#### Update global iOS platform

For iOS build global platform needs to be 14.0. Check `Podfile` in your project to change the global platform:

```
platform :ios, '14.0'
```

### 3. Configure redirects

- From the [Embedded Wallets dashboard](https://developer.metamask.io/), create or open an existing Web3Auth project.
- For iOS, allowlist `{bundleId}://auth` in the dashboard. This step is mandatory for the redirect to work.

## Initialize Web3Auth

### 1. Configure Web3Auth instance

Import and configure Web3Auth in your Flutter application:

```dart title="main.dart"

Future<void> initWeb3Auth() async {
  late final String redirectUrl;

  if (Platform.isAndroid) {
    redirectUrl = 'w3a://com.example.w3aflutter';
    // w3a://com.example.w3aflutter
  } else {
    redirectUrl = 'com.example.w3aflutter://auth';
    // com.example.w3aflutter://auth
  }

  // focus-start
  await Web3AuthFlutter.init(Web3AuthOptions(
    clientId: "YOUR_WEB3AUTH_CLIENT_ID", // Pass your Web3Auth Client ID, ideally using an environment variable // Get your Client ID from Embedded Wallets dashboard
    web3AuthNetwork: Web3AuthNetwork.sapphire_mainnet, // or Web3AuthNetwork.sapphire_devnet
    redirectUrl: redirectUrl,
    authBuildEnv: BuildEnv.production,
  ));
  // focus-end
}
```

### 2. Initialize an Embedded Wallets instance

Initialize the Embedded Wallets instance and check for existing sessions:

```dart
class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
  String _result = '';
  bool logoutVisible = false;

  @override
  void initState() {
    super.initState();
    initPlatformState();
  }

  Future<void> initPlatformState() async {
    await initWeb3Auth();

    try {
      // Initialize and check for existing session
      // focus-start
      await Web3AuthFlutter.initialize();
      // focus-end
      final privateKey = await Web3AuthFlutter.getPrivateKey();

      if (privateKey.isNotEmpty) {
        setState(() {
          logoutVisible = true;
          _result = 'Existing session found';
        });
      }
    } catch (e) {
      print('Error: $e');
    }
  }
}
```

:::note

After configuring Embedded Wallets, the next step is to initialize it using the `initialize` method. This method is essential for setting up the SDK, checking for any active sessions, and fetching the whitelabel configuration from your dashboard.

If the API call to fetch the project configuration fails, the method will throw an error.

:::

## Advanced configuration

The Embedded Wallets Flutter SDK offers a rich set of advanced configuration options:

- **[Custom authentication](./advanced/custom-authentication.mdx):** Define authentication methods.
- **[Whitelabeling and UI customization](./advanced/whitelabel.mdx):** Personalize the modal's appearance.
- **[Multi-Factor Authentication (MFA)](./advanced/mfa.mdx):** Set up and manage MFA.
- **[Dapp Share](./advanced/dapp-share.mdx):** Share dapp sessions across devices.

:::tip

See the [advanced configuration sections](./advanced/) to learn more about each configuration option.

:::

<Tabs
  defaultValue="basic-config"
  values={[
    { label: "Basic Configuration", value: "basic-config" },
    { label: "Advanced Configuration", value: "advanced-config" },
  ]}
>

<TabItem value="basic-config">

```dart
await Web3AuthFlutter.init(Web3AuthOptions(
  clientId: "YOUR_WEB3AUTH_CLIENT_ID", // Pass your Web3Auth Client ID, ideally using an environment variable
  web3AuthNetwork: Web3AuthNetwork.sapphire_mainnet, // or Web3AuthNetwork.sapphire_devnet
  redirectUrl: redirectUrl,
));
```

</TabItem>

<TabItem value="advanced-config">

```dart
await Web3AuthFlutter.init(Web3AuthOptions(
  clientId: "YOUR_WEB3AUTH_CLIENT_ID", // Pass your Web3Auth Client ID, ideally using an environment variable
  web3AuthNetwork: Web3AuthNetwork.sapphire_mainnet,
  redirectUrl: redirectUrl,
  defaultChainId: "0x1",
  chains: [
    Chains(
      chainId: "0x1",
      rpcTarget: "https://rpc.ankr.com/eth",
      displayName: "Ethereum Mainnet",
      blockExplorerUrl: "https://etherscan.io",
      ticker: "ETH",
      tickerName: "Ethereum",
    ),
  ],
  mfaSettings: MfaSettings(
    deviceShareFactor: MfaSetting(
      enable: true,
      priority: 1,
    ),
    backUpShareFactor: MfaSetting(
      enable: true,
      priority: 2,
    ),
    socialBackupFactor: MfaSetting(
      enable: true,
      priority: 3,
    ),
    passwordFactor: MfaSetting(
      enable: true,
      priority: 4,
    ),
  ),
));
```

</TabItem>

</Tabs>

## Blockchain integration

Web3Auth is blockchain agnostic, enabling integration with any blockchain network. Out of the box, Web3Auth offers robust support for both **Solana** and **Ethereum**.

### Ethereum integration

For Ethereum integration, you can get the private key and use it with web3dart or other Ethereum libraries:

```dart

// Use your Web3Auth instance to get the private key
final privateKey = await Web3AuthFlutter.getPrivateKey();

// Generate the Credentials
final credentials = EthPrivateKey.fromHex(privateKey);

// Get the address
final address = credentials.address;

// Create the Web3Client instance using your RPC URL
final client = Web3Client("YOUR_RPC_URL", Client());

// Get the balance
final balanceResponse = await client.getBalance(address);

// Convert the balance to ether format, and round off to 4 decimal places.
final balance = balanceResponse.getValueInUnit(EtherUnit.ether).toStringAsFixed(4);
```

### Solana integration

For Solana integration, you can get the Ed25519 private key:

```dart

// Use your Web3Auth instance to get the ED25519 private key
final privateKey = await Web3AuthFlutter.getEd25519PrivateKey();

// Generate the KeyPair
final keyPair = await Ed25519HDKeyPair.fromPrivateKeyBytes(
  privateKey: privateKey,
);

// Get the address
final address = keyPair.address;

// Create the SolanaClient instance using Solana RPC URL
final client = SolanaClient(
  rpcUrl: Uri.parse('https://api.devnet.solana.com'),
  websocketUrl: Uri.parse('ws://api.devnet.solana.com'),
);

// Get the balance
final balanceResponse = await client.rpcClient.getBalance(address);

// Convert the balance from lamports to SOL, and round off to 4 decimal places
final balance = (balanceResponse.value / pow(10, 9)).toStringAsFixed(4);

```

---

## Advanced configuration(Advanced)

The Embedded Wallets SDK provides extensive configuration options that allow you to customize authentication flows, UI appearance, blockchain integrations, and security features to meet your application's specific requirements.

## Configuration structure

When setting up Embedded Wallets, you'll pass in the options to the constructor. This consists of:

```dart

Future<void> initWeb3Auth() async {

  late final String redirectUrl;

  if (Platform.isAndroid) {
    redirectUrl = 'w3a://com.example.w3aflutter';
  } else {
    redirectUrl = 'com.example.w3aflutter://auth';
  }

  // focus-start

  await Web3AuthFlutter.init(Web3AuthOptions(
    clientId: "YOUR_WEB3AUTH_CLIENT_ID", // Pass your Web3Auth Client ID, ideally using an environment variable // Get your Client ID from MetaMask Developer Dashboard dashboard
    web3AuthNetwork: Web3AuthNetwork.sapphire_mainnet, // or Web3AuthNetwork.sapphire_devnet
    redirectUrl: redirectUrl,
  ));

  // focus-end
}
```

### `Web3AuthOptions`

The Web3Auth Constructor takes an object with `Web3AuthOptions` as input.

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Class", value: "class" },
  ]}
>

<TabItem value="table">

| Parameter               | Description                                                                                                                    |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `clientId`              | Your Web3Auth Client ID from the [Dashboard](https://developer.metamask.io/). Mandatory `String`.                              |
| `web3AuthNetwork`       | Web3Auth Network: `sapphire_mainnet`, `sapphire_devnet`, `mainnet`, `cyan`, `aqua`, or `testnet`. Mandatory `Web3AuthNetwork`. |
| `redirectUrl`           | URL that Web3Auth redirects to after successful authentication. Mandatory `String`.                                            |
| `whiteLabel?`           | Whitelabel options for custom UI, branding, and translations. Takes `WhiteLabelData` as a value.                               |
| `authConnectionConfig?` | Auth connection config for custom connections. Takes `List<AuthConnectionConfig>` as a value.                                  |
| `chains?`               | Chain configuration for Wallet Services and signing. Takes `List<Chains>` as a value.                                          |
| `defaultChainId?`       | Default chain ID from the `chains` list.                                                                                       |
| `mfaSettings?`          | Configure MFA settings for authentication. Takes `MfaSettings` as a value.                                                     |
| `sessionTime?`          | Configure session management time in seconds. Default is 30 days. Max 30 days.                                                 |

</TabItem>

<TabItem value="class">

```dart
class Web3AuthOptions {
  final String clientId;
  final Web3AuthNetwork web3AuthNetwork;
  final BuildEnv? authBuildEnv;
  final String redirectUrl;
  final WhiteLabelData? whiteLabel;
  final List<AuthConnectionConfig>? authConnectionConfig;
  final List<Chains>? chains;
  final String? defaultChainId;
  final bool? useSFAKey;
  final MfaSettings? mfaSettings;
  final int sessionTime;

  Web3AuthOptions({
    required this.clientId,
    required this.web3AuthNetwork,
    this.authBuildEnv = BuildEnv.production,
    required this.redirectUrl,
    this.whiteLabel,
    this.authConnectionConfig = const [],
    this.chains,
    this.defaultChainId,
    this.useSFAKey = false,
    this.sessionTime = 30 * 86400,
    this.mfaSettings,
  });
}
```

</TabItem>
</Tabs>

## Session management

Control how long users stay authenticated and how sessions persist. The session key is stored in the device's encrypted Keystore.

**Key Configuration Options:**

- `sessionTime` - Session duration in seconds. Controls how long users remain authenticated before needing to log in again.
  - Minimum: 1 second (`1`).
  - Maximum: 30 days (`86400 * 30`).
  - Default: 30 days (`30 * 86400`).

```dart
await Web3AuthFlutter.init(Web3AuthOptions(
    clientId: "YOUR_WEB3AUTH_CLIENT_ID", // Pass your Web3Auth Client ID, ideally using an environment variable // Get your Client ID from MetaMask Developer Dashboard dashboard
    web3AuthNetwork: Web3AuthNetwork.sapphire_mainnet, // or Web3AuthNetwork.sapphire_devnet
    sessionTime: 30 * 86400, // 30 days (in seconds)
    redirectUrl: redirectUrl,
));
```

## Custom authentication methods

Control the login options presented to your users. For detailed configuration options and implementation examples, see the [custom authentication](./custom-authentication.mdx) section.

## UI customization

Customize the brand experience by customizing the Web3Auth Login Screens to match your application's design. For complete customization options, refer to the [whitelabeling and UI customization](./whitelabel.mdx) section.

## Multi-Factor Authentication (MFA)

Add additional security layers to protect user accounts with two-factor authentication. See the [detailed configuration options and implementation examples](./mfa.mdx).

**Key Configuration Options:**

- `mfaSettings` - Configure MFA settings for different authentication flows
- `mfaLevel` - Control when users are prompted to set up MFA

---

## Using custom authentication

Custom authentication lets users sign in with your own OAuth provider or JWT issuer. For example, you can use your own Google Client ID, Firebase ID token, or Auth0 application.

This feature, with MFA turned off, can make Embedded Wallets invisible to the end user.

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this
SDK in a production environment is the **Growth Plan**. You can use this feature in Web3Auth
Sapphire Devnet network for free.

:::

## Getting an auth connection ID

:::info prerequisite

To enable this, [create a connection](/embedded-wallets/dashboard/authentication) from the **Authentication** tab of your project in the [Embedded Wallets developer dashboard](https://developer.metamask.io) with your desired configuration.

:::

To configure a connection, provide the connection details in the Embedded Wallets dashboard. This maps an `authConnectionId` to your connection configuration. You can configure multiple connections for the same project and update connection details at any time.

:::tip

Learn more about the [auth provider setup](/embedded-wallets/authentication) and the different configurations available for each connection.

:::

## Configuration

To use custom authentication (social providers, Auth0, AWS Cognito, Firebase, or your own JWT login), add `authConnectionConfig` during initialization.

`authConnectionConfig` is a list of `AuthConnectionConfig` objects.

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this
SDK in a production environment is the **Growth Plan**. You can use this feature in Web3Auth
Sapphire Devnet network for free.

:::

### Parameters

After creating the connection, use the following parameters in `AuthConnectionConfig`.

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Class", value: "class" },
  ]}
>

<TabItem value="table">

| Parameter                  | Description                                                                                                      |
| -------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `authConnection`           | Type of sign-in for the connection. For example, `google` for Google OAuth or `custom` for JWT. Mandatory.       |
| `authConnectionId`         | Auth connection ID registered in the Embedded Wallets dashboard. Mandatory.                                      |
| `clientId`                 | Client ID from your login provider. Mandatory.                                                                   |
| `name?`                    | Display name for the connection. If null, the default name is used.                                              |
| `description?`             | Description for the button. If provided, renders as a full-length button; otherwise, an icon button.             |
| `groupedAuthConnectionId?` | Grouped auth connection ID. If provided, `authConnectionId` becomes a sub-identifier for the grouped connection. |
| `logoHover?`               | Logo shown on mouse hover.                                                                                       |
| `logoLight?`               | Light logo for dark backgrounds.                                                                                 |
| `logoDark?`                | Dark logo for light backgrounds.                                                                                 |
| `mainOption?`              | Show the sign-in button on the main list.                                                                        |
| `showOnModal?`             | Whether to show the sign-in button on the modal.                                                                 |
| `showOnDesktop?`           | Whether to show the sign-in button on desktop.                                                                   |
| `showOnMobile?`            | Whether to show the sign-in button on mobile.                                                                    |
| `jwtParameters?`           | Extra JWT options for custom connections.                                                                        |

</TabItem>

<TabItem value="class">

```dart
class AuthConnectionConfig {
  final AuthConnection authConnection;
  final String authConnectionId;
  final String clientId;
  final String? name;
  final String? description;
  final String? groupedAuthConnectionId;
  final String? logoHover;
  final String? logoLight;
  final String? logoDark;
  final bool? mainOption;
  final bool? showOnModal;
  final bool? showOnDesktop;
  final bool? showOnMobile;
  final ExtraLoginOptions? jwtParameters;

  AuthConnectionConfig({
    required this.authConnection,
    required this.authConnectionId,
    required this.clientId,
    this.name,
    this.description,
    this.groupedAuthConnectionId,
    this.logoHover,
    this.logoLight,
    this.logoDark,
    this.mainOption,
    this.showOnModal,
    this.showOnDesktop,
    this.showOnMobile,
    this.jwtParameters,
  });
}
```

</TabItem>
</Tabs>

### Usage

<Tabs
  defaultValue="google"
  values={[
    { label: "Google", value: "google" },
    { label: "Firebase JWT", value: "firebase" },
    { label: "Auth0", value: "auth0" },
  ]}
>

<TabItem value="google">

```dart title="Usage"
Future<void> initWeb3Auth() async {
  final authConnectionConfig = [
    AuthConnectionConfig(
      authConnection: AuthConnection.google,
      authConnectionId: "YOUR_AUTH_CONNECTION_ID",
      clientId: "YOUR_GOOGLE_CLIENT_ID",
    ),
  ];

  late final String redirectUrl;
  if (Platform.isAndroid) {
    redirectUrl = 'w3a://com.example.w3aflutter';
  } else {
    redirectUrl = 'com.example.w3aflutter://auth';
  }

  await Web3AuthFlutter.init(
    Web3AuthOptions(
      clientId: "WEB3AUTH_CLIENT_ID",
      web3AuthNetwork: Web3AuthNetwork.sapphire_mainnet,
      redirectUrl: redirectUrl,
      authConnectionConfig: authConnectionConfig,
    ),
  );
}

final Web3AuthResponse response = await Web3AuthFlutter.connectTo(
  LoginParams(authConnection: AuthConnection.google),
);
```

</TabItem>

<TabItem value="firebase">

```dart title="Usage"
Future<void> initWeb3Auth() async {
  final authConnectionConfig = [
    AuthConnectionConfig(
      authConnection: AuthConnection.custom,
      authConnectionId: "w3a-firebase-demo",
      clientId: "WEB3AUTH_CLIENT_ID",
    ),
  ];

  late final String redirectUrl;
  if (Platform.isAndroid) {
    redirectUrl = 'w3a://com.example.w3aflutter';
  } else {
    redirectUrl = 'com.example.w3aflutter://auth';
  }

  await Web3AuthFlutter.init(
    Web3AuthOptions(
      clientId: "WEB3AUTH_CLIENT_ID",
      web3AuthNetwork: Web3AuthNetwork.sapphire_mainnet,
      redirectUrl: redirectUrl,
      authConnectionConfig: authConnectionConfig,
    ),
  );
}

// Obtain a Firebase ID token from your auth provider, then:
final Web3AuthResponse response = await Web3AuthFlutter.connectTo(
  LoginParams(
    authConnection: AuthConnection.custom,
    authConnectionId: "w3a-firebase-demo",
    idToken: firebaseIdToken,
  ),
);
```

</TabItem>

<TabItem value="auth0">

```dart title="Usage"
Future<void> initWeb3Auth() async {
  final authConnectionConfig = [
    AuthConnectionConfig(
      authConnection: AuthConnection.custom,
      authConnectionId: "w3a-auth0-demo",
      clientId: "YOUR_AUTH0_CLIENT_ID",
    ),
  ];

  late final String redirectUrl;
  if (Platform.isAndroid) {
    redirectUrl = 'w3a://com.example.w3aflutter';
  } else {
    redirectUrl = 'com.example.w3aflutter://auth';
  }

  await Web3AuthFlutter.init(
    Web3AuthOptions(
      clientId: "WEB3AUTH_CLIENT_ID",
      web3AuthNetwork: Web3AuthNetwork.sapphire_mainnet,
      redirectUrl: redirectUrl,
      authConnectionConfig: authConnectionConfig,
    ),
  );
}

final Web3AuthResponse response = await Web3AuthFlutter.connectTo(
  LoginParams(
    authConnection: AuthConnection.custom,
    authConnectionId: "w3a-auth0-demo",
    extraLoginOptions: ExtraLoginOptions(
      domain: "https://tenant-name.us.auth0.com",
      userIdField: "sub",
    ),
  ),
);
```

</TabItem>
</Tabs>

## Configure extra login options

In addition to `authConnectionConfig` during initialization, you can pass extra options to `connectTo` for authorization flows that need additional parameters. `ExtraLoginOptions` accepts the following parameters.

### Parameters

| Parameter                | Description                                                                                                         |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------- |
| `additionalParams?`      | Additional params in `Map` format for OAuth sign-in.                                                                |
| `domain?`                | Your custom authentication domain. For example, `example.au.auth0.com` for Auth0.                                   |
| `client_id?`             | Client ID provided by your login provider for custom connections.                                                   |
| `leeway?`                | Clock skew allowance for JWT expiration, in seconds. Ideally no more than 60–120 seconds.                           |
| `userIdField?`           | JWT field that maps to the user ID. Ensure you selected the correct JWT user identifier in the developer dashboard. |
| `isUserIdCaseSensitive?` | Whether the user ID field is case sensitive.                                                                        |
| `display?`               | Configures the display of the UI. Takes `Display` as a value.                                                       |
| `prompt?`                | Prompt shown during authentication. Takes `Prompt` as a value.                                                      |
| `max_age?`               | Max time allowed without reauthentication.                                                                          |
| `ui_locales?`            | Space-separated list of language tags, ordered by preference. For instance `fr-CA fr en`.                           |
| `id_token_hint?`         | Previously issued ID token.                                                                                         |
| `id_token?`              | JWT (ID token) for legacy custom flows. Prefer `LoginParams.idToken` for Firebase and other JWT providers.          |
| `login_hint?`            | User's email address for email passwordless sign-in.                                                                |
| `flow_type?`             | Email passwordless flow type. Defaults to `EmailFlowType.code`. Use `EmailFlowType.link` for magic-link flow.       |
| `redirect_uri?`          | Default redirect URL for custom JWT verifiers. If you use Auth0, allowlist it in Allowed Callback URLs.             |

### Email and SMS passwordless

```dart
final Web3AuthResponse response = await Web3AuthFlutter.connectTo(
  LoginParams(
    authConnection: AuthConnection.email_passwordless,
    extraLoginOptions: ExtraLoginOptions(
      login_hint: "hello@web3auth.io",
    ),
  ),
);
```

For SMS passwordless, use the format `+{country_code}-{phone_number}` (for example, `+91-9911223311`).

### Grouped connections

Use grouped connections so the same user gets the same wallet address across multiple sign-in methods:

```dart
final authConnectionConfig = [
  AuthConnectionConfig(
    authConnection: AuthConnection.google,
    authConnectionId: "w3a-google",
    groupedAuthConnectionId: "aggregate-sapphire",
    clientId: "YOUR_GOOGLE_CLIENT_ID",
  ),
  AuthConnectionConfig(
    authConnection: AuthConnection.custom,
    authConnectionId: "w3a-a0-github",
    groupedAuthConnectionId: "aggregate-sapphire",
    clientId: "YOUR_AUTH0_CLIENT_ID",
  ),
];

await Web3AuthFlutter.init(
  Web3AuthOptions(
    clientId: "WEB3AUTH_CLIENT_ID",
    web3AuthNetwork: Web3AuthNetwork.sapphire_mainnet,
    redirectUrl: redirectUrl,
    authConnectionConfig: authConnectionConfig,
  ),
);

// Sign in with Google
await Web3AuthFlutter.connectTo(
  LoginParams(
    authConnection: AuthConnection.google,
    authConnectionId: "w3a-google",
    groupedAuthConnectionId: "aggregate-sapphire",
  ),
);

// Sign in with GitHub via Auth0
await Web3AuthFlutter.connectTo(
  LoginParams(
    authConnection: AuthConnection.custom,
    authConnectionId: "w3a-a0-github",
    groupedAuthConnectionId: "aggregate-sapphire",
    extraLoginOptions: ExtraLoginOptions(
      domain: "https://web3auth.au.auth0.com",
      userIdField: "email",
      connection: "github",
      isUserIdCaseSensitive: false,
    ),
  ),
);
```

See [grouped connections](/embedded-wallets/authentication/group-connections) for dashboard setup.

---

## Dapp share(Advanced)

## Embedded Wallets infrastructure at a glance

As described in the [Embedded Wallets infrastructure](/embedded-wallets/infrastructure/), to enable the non custodiality of Embedded Wallets, we split the private key into multiple parts, known as `shares`. These shares are a part of the offchain multisig, where multiple shares are stored in different places and can be used to reconstruct the private key dynamically in the user's frontend application. Typically, there are 3 shares:

1. **`ShareA` is managed by a login service via node operators:** This share is further split amongst a network of nodes and retrieved via conventional authentication flows.
2. **`ShareB` is stored on the user's device:** Implementation is device and system specific. For example, on mobile devices, the share could be stored in device storage secured via biometrics.
3. **`ShareC` is a recovery share:** An extra share to be kept by the user, possibly kept on a separate device, downloaded or based on user input with enough entropy (such as, password, security questions, hardware device).

Similar to existing 2FA systems, a user needs to prove ownership of at least 2 out of 3 (2/3) shares, in order to retrieve their private key. This initial setup provides several benefits.

## The user experience in mobile platforms

The user experience on mobile platforms is very different from the web platforms. This is because the user has to be redirected to a browser where they can login using their socials and then back to the app once they have been successfully authenticated. This user experience shifts the context between two applications, whereas, in the web platforms, the context remains within the browser only.

For the dapp share login flow, we need to reconstruct the Shares `A` and `B`. `Share B` is managed by the login service and is provided on successful authentication. Whereas in web platforms, `Share A` is stored in the browser context. We can still store it in the browser context for mobile devices, but this has a few risks like users accidentally deleting browser data. This is a bigger problem in mobile devices since the user doesn't realize that the browser is being used to login within the app and clearing the browser data can cause their logins to fail. Hence, to tackle this issue, Web3Auth issues a dapp share, that is, a backup share that can be stored by the app developer directly within their application and used to reconstruct the private key after successful login by the user.

## Dapp share in Flutter

Web3Auth issues a dapp share, that is, a backup share that can be stored by the app developer directly within their application and used to reconstruct the private key after successful login by the user.

After a successful login from a user, the user details are returned as a response to the application on mobile devices.

#### Sample response in Flutter

```json
{
  "userInfo": {
    "email": "w3a-heroes@web3auth.com",
    "name": "Web3Auth Heroes",
    "profileImage": "https://lh3.googleusercontent.com/a/Ajjjsdsmdjmnm...",
    "authConnectionId": "torus",
    "userId": "w3a-heroes@web3auth.com",
    "authConnection": "google",
    "groupedAuthConnectionId": "w3a-google-sapphire",
    "dappShare": "", // 24 words of seed phrase will be sent only incase of custom verifiers
    "idToken": "<jwtToken issued by Web3Auth>",
    "oAuthIdToken": "<jwtToken issued by OAuth Provider>", // will be sent only incase of custom verifiers
    "oAuthAccessToken": "<accessToken issued by OAuth Provider>", // will be sent only incase of custom verifiers
    "isMfaEnabled": false // Returns whether the user has enabled MFA or not
  }
}
```

Notice, the reponses has a field called `dappShare` which is a 24 words seed phrase that can be used to reconstruct the private key. This dappShare is a supplement to the `Share A` and represents half of the private key. The application can store the dapp share in its own application's local storage safely.

While logging in, the user can use their social accounts to obtain one share, and the application provides the dapp share, removing the need to store the share in the browser context and enabling the user to sign in without repeating the full flow. This can be done by passing over the stored dapp share value in the login function.

:::note

It's important to note that the `dappShare` is only available for custom auth connections and not the standard Embedded Wallets connections. This is done to make sure that an application only has access to the corresponding share to the private key of their application's user. Hence, to use dapp share, one has to use the custom authentication feature of Web3Auth. Also, the dapp share is only returned to users who have enabled 2FA to their account.

:::

```dart
final Web3AuthResponse response = await Web3AuthFlutter.connectTo(LoginParams(
  authConnection: AuthConnection.google,
  // focus-next-line
  dappShare: "<24 words seed phrase>",
));
```

## Example

```dart
Future<void> initWeb3Auth() async {
  HashMap themeMap = HashMap<String, String>();
  themeMap['primary'] = "#229954";

  late final String redirectUrl;
  if (Platform.isAndroid) {
    redirectUrl = 'w3a://com.example.w3aflutter';
  } else if (Platform.isIOS) {
    redirectUrl = 'com.example.w3aflutter://auth';
  } else {
    throw UnKnownException('Unknown platform');
  }

  await Web3AuthFlutter.init(
    Web3AuthOptions(
      clientId: "WEB3AUTH_CLIENT_ID",
      web3AuthNetwork: Web3AuthNetwork.sapphire_devnet,
      redirectUrl: redirectUrl,
    ),
  );
}

final Web3AuthResponse response = await Web3AuthFlutter.connectTo(LoginParams(
  authConnection: AuthConnection.google,
  // focus-next-line
  dappShare: "<24 words seed phrase>",
));
```

---

## Multi-factor authentication(Advanced)

At Web3Auth, we prioritize your security by offering Multi-Factor Authentication (MFA). MFA is an extra layer of protection that verifies your identity when accessing your account. To ensure ownership, you must provide two or more different backup factors. You have the option to choose from the device, social, backup factor (seed phrase), and password factors to guarantee access to your web3 account. Once you create a recovery factor, MFA is enabled, and your keys are divided into three shares for offchain multi-sig, making the key self-custodial. With backup factors, you can easily recover your account if you lose access to your original device or helps login into a new device.

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this SDK in a production environment is the **Scale Plan**. You can use this feature in Web3Auth Sapphire Devnet network for free.

:::

## Enable using the Multi-Factor Authentication level

For a dapp, we provide various options to set up MFA. You can customize the MFA screen by passing the `mfaLevel` parameter in the `connectTo` method. You can enable or disable a backup factor and change their order. Currently, there are four values for MFA level.

:::caution Note

If you are using default auth connections, your users may have set up MFA on other dapps that also use default Embedded Wallets connections. In this case, the MFA screen will continue to appear if the user has enabled MFA on other dapps. This is because MFA cannot be turned off once it is enabled.

:::

### Multi-Factor Authentication level options

| MFA Level | Description                                                |
| --------- | ---------------------------------------------------------- |
| DEFAULT   | Shows the MFA screen every third login.                    |
| OPTIONAL  | Shows the MFA screen on every login, but user can skip it. |
| MANDATORY | Makes it mandatory to set up MFA after first login.        |
| NONE      | Skips the MFA setup screen.                                |

### Usage

```dart
Web3AuthFlutter.connectTo(
  LoginParams(
    authConnection: AuthConnection.google,
    // focus-next-line
    mfaLevel: MFALevel.MANDATORY,
  ),
);
```

## Explicitly enable Multi-Factor Authentication

The `enableMFA` method is used to trigger MFA setup flow for users. The method takes optional `LoginParams` for custom connections. If you are using default social login providers, you don't need to pass `LoginParams`. If you are using custom JWT connections, pass the JWT token in `loginParams` using `LoginParams.idToken`.

<Tabs
  defaultValue="default-verifier"
  values={[
    { label: "Default connection", value: "default-verifier" },
    { label: "Custom JWT connection", value: "custom-jwt-verifier" },
  ]}
>

<TabItem value="default-verifier">

```dart title="Usage"
try {
  // focus-next-line
  await Web3AuthFlutter.enableMFA();
} on UserCancelledException {
  log("User cancelled.");
} catch(e) {
  log("Unknown exception occurred");
}
```

</ TabItem>

<TabItem value="custom-jwt-verifier">

```dart title="Usage"
try {
    final loginParams = LoginParams(
      authConnection: AuthConnection.custom,
      authConnectionId: "YOUR_AUTH_CONNECTION_ID",
      idToken: "YOUR_JWT_TOKEN",
    );

    // focus-next-line
    await Web3AuthFlutter.enableMFA(loginParams: loginParams);

} on UserCancelledException { log("User cancelled."); } catch(e) { log("Unknown exception occurred"); }

```

</ TabItem>
</ Tabs>

## Configure Multi-Factor Authentication settings

You can configure the order of MFA, and enable or disable MFA type by passing the `mfaSettings` parameter in `Web3AuthOptions` during initialization.

:::note Note

- At least two factors are mandatory when setting up the mfaSettings.
- If you set `mandatory: true` for all factors, the user must set up all four factors.
- If you set `mandatory: false` for all factors, the user can skip setting up MFA. But at least two factors are mandatory.
- If you set `mandatory: true` for some factors and `mandatory: false` for others, the user must set up the mandatory factors and can skip the optional factors. But, the user must set up at least two factors.
- The `priority` field is used to set the order of the factors. The factor with the lowest priority will be the first factor to be set up. The factor with the highest priority will be the last factor to be set up.

:::

### Parameters - `MfaSettings`

`MfaSettings` allows you to set the type of the MFA.

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Class", value: "class" },
  ]}
>

<TabItem value="table">

| Parameter              | Description                                                              |
| ---------------------- | ------------------------------------------------------------------------ |
| `deviceShareFactor?`   | MFA setting for deviceShareFactor. It accepts `MfaSetting` as a value.   |
| `backUpShareFactor?`   | MFA setting for backUpShareFactor. It accepts `MfaSetting` as a value.   |
| `socialBackupFactor?`  | MFA setting for socialBackupFactor. It accepts `MfaSetting` as a value.  |
| `passwordFactor?`      | MFA setting for passwordFactor. It accepts `MfaSetting` as a value.      |
| `passkeysFactor?`      | MFA setting for passkeysFactor. It accepts `MfaSetting` as a value.      |
| `authenticatorFactor?` | MFA setting for authenticatorFactor. It accepts `MfaSetting` as a value. |

</TabItem>

<TabItem value="class">

```dart
class MfaSettings {
  final MfaSetting? deviceShareFactor;
  final MfaSetting? backUpShareFactor;
  final MfaSetting? socialBackupFactor;
  final MfaSetting? passwordFactor;
  final MfaSetting? passkeysFactor;
  final MfaSetting? authenticatorFactor;

  MfaSettings({
    this.deviceShareFactor,
    this.backUpShareFactor,
    this.socialBackupFactor,
    this.passwordFactor,
    this.passkeysFactor,
    this.authenticatorFactor,
  });

  Map<String, dynamic> toJson() {
    return {
      'deviceShareFactor': deviceShareFactor,
      'backUpShareFactor': backUpShareFactor,
      'socialBackupFactor': socialBackupFactor,
      'passwordFactor': passwordFactor,
      'passkeysFactor': passkeysFactor,
      'authenticatorFactor': authenticatorFactor,
    };
  }
}
```

</TabItem>
</Tabs>

### Parameters - `MfaSetting`

`MfaSetting` allows you to configure the behavior of an individual MFA factor.

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Class", value: "class" },
  ]}
>

<TabItem value="table">

| Parameter    | Description                                                                     |
| ------------ | ------------------------------------------------------------------------------- |
| `enable`     | Enable/Disable MFA. It accepts `bool` as a value.                               |
| `priority?`  | Priority of MFA. It accepts `int` as a value, where valid range is from 1 to 4. |
| `mandatory?` | Mandatory/Optional MFA. It acccepts `bool` as a value.                          |

</TabItem>
<TabItem value="class">

```dart
class MfaSetting {
  final bool enable;
  final int? priority;
  final bool? mandatory;

  MfaSetting({required this.enable, this.priority, this.mandatory});

  Map<String, dynamic> toJson() {
    return {'enable': enable, 'priority': priority, 'mandatory': mandatory};
  }
}
```

</TabItem>
</Tabs>

### Usage

```dart
Future<void> initWeb3Auth() async {

  late final String redirectUrl;
  if (Platform.isAndroid) {
    redirectUrl = 'w3a://com.example.w3aflutter';
  } else {
    redirectUrl = 'com.example.w3aflutter://auth';
  }

  await Web3AuthFlutter.init(
    Web3AuthOptions(
    clientId: "WEB3AUTH_CLIENT_ID",
    web3AuthNetwork: Web3AuthNetwork.sapphire_mainnet,
    redirectUrl: redirectUrl,
    // focus-start
    mfaSettings: MfaSettings(
      deviceShareFactor: MfaSetting(
        enable: true,
        priority: 4,
        mandatory: true,
      ),
      backUpShareFactor: MfaSetting(
        enable: true,
        priority: 2,
        mandatory: true,
      ),
      socialBackupFactor: MfaSetting(
        enable: true,
        priority: 3,
        mandatory: false,
      ),
      passwordFactor: MfaSetting(
        enable: true,
        priority: 1,
        mandatory: true,
      ),
      passkeysFactor: MfaSetting(
        enable: true,
        priority: 5,
        mandatory: true,
      ),
      authenticatorFactor: MfaSetting(
        enable: true,
        priority: 6,
        mandatory: true,
      ),
    ),
    // focus-end
  );

  await Web3AuthFlutter.initialize();
}
```

---

## Whitelabel(Advanced)

Embedded Wallets allows complete whitelabeling with application branding for a consistent user experience. You can customize three different aspects:

- **UI elements:** Customize the appearance of modals and components
- **Branding:** Apply your brand colors, logos, and themes
- **Translations:** Localize the interface for your users

:::info

All of these settings can be easily managed directly from the Embedded Wallets dashboard. Once you update your branding, or UI preferences there, the changes will automatically apply to your integration.

:::

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this
SDK in a production environment is the **Growth Plan**. You can use this feature in Web3Auth
Sapphire Devnet network for free.

:::

## Customizing the Web3Auth login screens

For defining custom UI, branding, and translations for your brand app, you just need to define an optional object called `WhiteLabelData`. `WhiteLabelData` can be definied during initialization of the SDK in `Web3AuthOptions` object.

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this
SDK in a production environment is the **Growth Plan**. You can use this feature in Web3Auth
Sapphire Devnet network for free.

:::

### Arguments

`WhiteLabelData`

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Class", value: "class" },
  ]}
>

<TabItem value="table">

| Parameter          | Description                                                                                                                                                              |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `appName?`         | Display name for the app in the UI.                                                                                                                                      |
| `logoLight?`       | App logo to be used in dark mode. It accepts URL as a string.                                                                                                            |
| `logoDark?`        | App logo to be used in light mode. It accepts URL as a string.                                                                                                           |
| `defaultLanguage?` | Language which will be used by Web3Auth, app will use browser language if not specified. Default language is `Language.en`. Checkout `Language` for supported languages. |
| `mode?`            | Theme mode for the login modal. Choose between `ThemeModes.auto`, `ThemeModes.light` or `ThemeModes.dark` background modes. Default value is `ThemeModes.auto`.          |
| `theme?`           | Used to customize the theme of the login modal. It accepts `HashMap` as a value.                                                                                         |
| `appUrl?`          | URL to be used in the Modal. It accepts URL as a string.                                                                                                                 |
| `useLogoLoader?`   | Use logo loader. If `logoDark` and `logoLight` are null, the default Web3Auth logo will be used for the loader. Default value is false.                                  |

</TabItem>
<TabItem value="class">

```dart
class WhiteLabelData {
  final String? appName;
  final String? logoLight;
  final String? logoDark;
  final Language? defaultLanguage;
  final ThemeModes? mode;
  final HashMap? theme;
  final String? appUrl;
  final bool? useLogoLoader;

  WhiteLabelData({
    this.appName,
    this.logoLight,
    this.logoDark,
    this.defaultLanguage = Language.en,
    this.mode = ThemeModes.auto,
    this.theme,
    this.appUrl,
    this.useLogoLoader,
  });

  Map<String, dynamic> toJson() {
    return {
      'appName': appName,
      'logoLight': logoLight,
      'logoDark': logoDark,
      'defaultLanguage': defaultLanguage.toString().split('.').last,
      'mode': mode.toString().split('.').last,
      'theme': theme,
      'appUrl': appUrl,
      'useLogoLoader': useLogoLoader
    };
  }
}
```

</TabItem>
</Tabs>

### `name`

The name of the application. This will be displayed in the key reconstruction page.

  
    
      Standard screen without any change
    
    
  
  
    
      Name changed to <code>Formidable Duo</code>
    
    
  

### `logoLight` & `logoDark`

The logo of the application. Displayed in dark and light mode respectively. This will be displayed
in the key reconstruction page.

  
    
      <code>logoLight</code> on dark mode
    
    
  
  
    
      <code>logoDark</code> on light mode
    
    
  

### `defaultLanguage`

Default language will set the language used on all OpenLogin screens. The supported languages are:

  
    
      
        <code>en</code> - English (default)
      
      
        <code>de</code> - German
      
      
        <code>ja</code> - Japanese
      
      
        <code>ko</code> - Korean
      
      
        <code>zh</code> - Mandarin
      
      
        <code>es</code> - Spanish
      
      
        <code>fr</code> - French
      
      
        <code>pt</code> - Portuguese
      
      
        <code>nl</code> - Dutch
      
      
        <code>tr</code> - Turkish
      
    
  
  
    
  

### `dark`

Can be set to `true` or `false` with default set to `false`.

  
    
      For Light: <code>dark: false</code>
    
    
  
  
    
      For Dark: <code>dark: true</code>
    
    
  

### `theme`

Theme is a record of colors that can be configured. As of, now only `primary` color can be set and
has effect on OpenLogin screens (default primary color is `#0364FF`). Theme affects icons and links.
Examples below.

  
    
      Standard color <code>#0364FF</code>
    
    
  
  
    
      Color changed to <code>#D72F7A</code>
    
    
  

### Example

```dart title="Usage"
Future<void> initWeb3Auth() async {

  // focus-start
  final themeMap = HashMap<String, String>();
  themeMap['primary'] = "#229954";
  // focus-end

  late final String redirectUrl;
  if (Platform.isAndroid) {
    redirectUrl = 'w3a://com.example.w3aflutter';
  } else if (Platform.isIOS) {
    redirectUrl = 'com.example.w3aflutter://auth';
  } else {
    throw UnKnownException('Unknown platform');
  }

  await Web3AuthFlutter.init(
    Web3AuthOptions(
      clientId: "WEB3AUTH_CLIENT_ID",
      web3AuthNetwork: Web3AuthNetwork.sapphire_mainnet,
      redirectUrl: redirectUrl,
      // focus-start
      whiteLabel: WhiteLabelData(
        appName: "Web3Auth Flutter App",
        logoLight:
          "https://www.vectorlogo.zone/logos/flutterio/flutterio-icon.svg",
        logoDark:
          "https://cdn.icon-icons.com/icons2/2389/PNG/512/flutter_logo_icon_145273.png",
        defaultLanguage: Language.en,
        mode: ThemeModes.auto,
        appUrl: "https://web3auth.io",
        useLogoLoader: true,
        theme: themeMap,
      ),
    // focus-end
    ),
  );
}
```

---

## Examples(Flutter)

<ExampleCards exampleMap={pnpFlutterExamples} />

---

## Using Flutter SDK

Embedded Wallets provides a comprehensive set of functions to handle authentication, user management, and blockchain interactions in your Flutter applications. These functions allow you to implement features like user sign-in, Multi-Factor Authentication (MFA), private key retrieval, and Wallet Services with minimal effort. Each function is designed to handle a specific aspect of Embedded Wallets' functionality, making it easy to integrate into your Flutter projects.

## List of functions

:::tip

For detailed usage, configuration options, and code examples, refer to the dedicated documentation page for each function.

:::

### Authentication functions

| Function Name                     | Description                                          |
| --------------------------------- | ---------------------------------------------------- |
| [`connectTo()`](./connect-to.mdx) | Signs the user in with the selected auth connection. |
| [`logout()`](./logout.mdx)        | Signs the user out from the current session.         |

### User management functions

| Function Name                          | Description                                     |
| -------------------------------------- | ----------------------------------------------- |
| [`getUserInfo()`](./get-user-info.mdx) | Retrieves the authenticated user's information. |

### Private key functions

| Function Name                                             | Description                                                                     |
| --------------------------------------------------------- | ------------------------------------------------------------------------------- |
| [`getPrivateKey()`](./get-private-key.mdx)                | Retrieve the user's secp256k1 private key for EVM-compatible chains.            |
| [`getEd25519PrivateKey()`](./get-ed25519-private-key.mdx) | Retrieve the user's ed25519 private key for chains like Solana, Near, Algorand. |

### Security functions

| Function Name                     | Description                                |
| --------------------------------- | ------------------------------------------ |
| [`enableMFA()`](./enable-mfa.mdx) | Enables MFA for the user.                  |
| [`manageMFA()`](./manage-mfa.mdx) | Allows users to manage their MFA settings. |

### Wallet Services functions

| Function Name                            | Description                                                       |
| ---------------------------------------- | ----------------------------------------------------------------- |
| [`showWalletUI()`](./show-wallet-ui.mdx) | Launches the templated wallet UI in WebView.                      |
| [`request()`](./request.mdx)             | Opens templated transaction screens for signing EVM transactions. |

---

## Sign in a user(Usage)

To sign in a user, use the `connectTo` method. It triggers the sign-in flow and opens an in-app browser so the user can authenticate with the selected provider. Pass supported `AuthConnection` values for social logins (such as Google, Apple, Facebook) or custom JWT connections.

## Parameters

The `connectTo` method takes `LoginParams` as a required input.

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Class", value: "class" },
  ]}
>

<TabItem value="table">

| Parameter                  | Description                                                                                                                                                                                                                                                                              |
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `authConnection`           | Sets the OAuth sign-in method to use. Supported values include `google`, `facebook`, `reddit`, `discord`, `twitch`, `github`, `apple`, `kakao`, `linkedin`, `twitter`, `weibo`, `wechat`, `line`, `email_passwordless`, `email_password`, `custom`, `sms_passwordless`, and `farcaster`. |
| `authConnectionId?`        | Auth connection ID from the Embedded Wallets dashboard. Required for `custom` connections.                                                                                                                                                                                               |
| `groupedAuthConnectionId?` | Grouped auth connection ID for aggregate connections.                                                                                                                                                                                                                                    |
| `extraLoginOptions?`       | OAuth options for the corresponding `authConnection`. For example, pass the user's email address as `login_hint` for `email_passwordless`. Defaults to `null`.                                                                                                                           |
| `appState?`                | Tracks app state when the user returns after sign-in. Defaults to `null`.                                                                                                                                                                                                                |
| `mfaLevel?`                | Customizes the MFA screen during OAuth authentication. Defaults to `MFALevel.DEFAULT`, which shows MFA every third sign-in.                                                                                                                                                              |
| `dappShare?`               | Custom connection logins can return a dapp share after successful sign-in. Useful if your dapp uses this share to let users sign in without repeating the full flow.                                                                                                                     |
| `curve?`                   | Determines the public key encoded in the JWT returned by `getUserInfo`. Does not change the private key format from Web3Auth. `getPrivateKey` always returns secp256k1. Use `getEd25519PrivateKey` for ed25519. Defaults to `Curve.secp256k1`.                                           |
| `idToken?`                 | JWT (ID token) for `custom` connections. Pass Firebase, Auth0, or other provider tokens here instead of `extraLoginOptions.id_token`.                                                                                                                                                    |
| `loginHint?`               | Optional login hint (for example, email or phone number) passed directly on `LoginParams`.                                                                                                                                                                                               |

</TabItem>

<TabItem value="class">

```dart
class LoginParams {
  final AuthConnection authConnection;
  final String? authConnectionId;
  final String? groupedAuthConnectionId;
  final String? appState;
  final MFALevel? mfaLevel;
  final ExtraLoginOptions? extraLoginOptions;
  final String? dappShare;
  final Curve? curve;
  final String? dappUrl;
  final String? loginHint;
  final String? idToken;

  LoginParams({
    required this.authConnection,
    this.authConnectionId,
    this.groupedAuthConnectionId,
    this.appState,
    this.mfaLevel,
    this.extraLoginOptions,
    this.dappShare,
    this.curve = Curve.secp256k1,
    this.dappUrl,
    this.loginHint,
    this.idToken,
  });
}

enum AuthConnection {
  google,
  facebook,
  reddit,
  discord,
  twitch,
  github,
  apple,
  kakao,
  linkedin,
  twitter,
  weibo,
  wechat,
  line,
  email_passwordless,
  email_password,
  custom,
  sms_passwordless,
  farcaster,
}
```

</TabItem>
</Tabs>

## Usage

```dart
final Web3AuthResponse response = await Web3AuthFlutter.connectTo(
  LoginParams(authConnection: AuthConnection.google),
);
```

## Examples

<Tabs
  defaultValue="google"
  values={[
    { label: "Google", value: "google" },
    { label: "Facebook", value: "facebook" },
    { label: "Discord", value: "discord" },
    { label: "Twitch", value: "twitch" },
    { label: "Email Passwordless", value: "email_passwordless" },
    { label: "SMS Passwordless", value: "sms_passwordless" },
    { label: "Farcaster", value: "farcaster" },
    { label: "Custom JWT", value: "custom" },
  ]}
>

<TabItem value="google">

```dart title="Usage"
Future<void> initWeb3Auth() async {
  late final String redirectUrl;

  if (Platform.isAndroid) {
    redirectUrl = 'w3a://com.example.w3aflutter';
  } else if (Platform.isIOS) {
    redirectUrl = 'com.example.w3aflutter://auth';
  } else {
    throw UnKnownException('Unknown platform');
  }

  await Web3AuthFlutter.init(Web3AuthOptions(
    clientId: "WEB3AUTH_CLIENT_ID",
    web3AuthNetwork: Web3AuthNetwork.sapphire_mainnet,
    redirectUrl: redirectUrl,
  ));

  await Web3AuthFlutter.initialize();
}

// Sign in
final Web3AuthResponse response = await Web3AuthFlutter.connectTo(
  // focus-next-line
  LoginParams(authConnection: AuthConnection.google),
);
```

</TabItem>

<TabItem value="facebook">

```dart title="Usage"
final Web3AuthResponse response = await Web3AuthFlutter.connectTo(
  // focus-next-line
  LoginParams(authConnection: AuthConnection.facebook),
);
```

</TabItem>

<TabItem value="discord">

```dart title="Usage"
final Web3AuthResponse response = await Web3AuthFlutter.connectTo(
  // focus-next-line
  LoginParams(authConnection: AuthConnection.discord),
);
```

</TabItem>

<TabItem value="twitch">

```dart title="Usage"
final Web3AuthResponse response = await Web3AuthFlutter.connectTo(
  // focus-next-line
  LoginParams(authConnection: AuthConnection.twitch),
);
```

</TabItem>

<TabItem value="email_passwordless">

```dart title="Usage"
final Web3AuthResponse response = await Web3AuthFlutter.connectTo(
  LoginParams(
    authConnection: AuthConnection.email_passwordless,
    // focus-next-line
    extraLoginOptions: ExtraLoginOptions(login_hint: "hello@web3auth.io"),
  ),
);
```

</TabItem>

<TabItem value="sms_passwordless">

```dart title="Usage"
final Web3AuthResponse response = await Web3AuthFlutter.connectTo(
  LoginParams(
    authConnection: AuthConnection.sms_passwordless,
    // focus-next-line
    extraLoginOptions: ExtraLoginOptions(login_hint: "+91-9911223344"),
  ),
);
```

</TabItem>

<TabItem value="farcaster">

```dart title="Usage"
final Web3AuthResponse response = await Web3AuthFlutter.connectTo(
  // focus-next-line
  LoginParams(authConnection: AuthConnection.farcaster),
);
```

</TabItem>

<TabItem value="custom">

```dart title="Usage"
final Web3AuthResponse response = await Web3AuthFlutter.connectTo(
  LoginParams(
    authConnection: AuthConnection.custom,
    authConnectionId: "YOUR_AUTH_CONNECTION_ID",
    // focus-next-line
    idToken: "YOUR_JWT_TOKEN",
  ),
);
```

</TabItem>
</Tabs>

---

## Enable MFA for a user(Usage)

The `enableMFA` method is used to trigger MFA setup flow for users. The method takes optional `LoginParams` for custom connections. If you are using default social login providers, you don't need to pass `LoginParams`. If you are using custom JWT connections, pass the JWT token in `loginParams` using `LoginParams.idToken`.

## Usage

<Tabs
  defaultValue="default-verifier"
  values={[
    { label: "Default connection", value: "default-verifier" },
    { label: "Custom JWT connection", value: "custom-jwt-verifier" },
  ]}
>

<TabItem value="default-verifier">

```dart title="Usage"
try {
  // focus-next-line
  await Web3AuthFlutter.enableMFA();
} on UserCancelledException {
  log("User cancelled.");
} catch (e) {
  log("Unknown exception occurred");
}
```

</TabItem>

<TabItem value="custom-jwt-verifier">

```dart title="Usage"
try {
  final loginParams = LoginParams(
    authConnection: AuthConnection.custom,
    authConnectionId: "YOUR_AUTH_CONNECTION_ID",
    idToken: "YOUR_JWT_TOKEN",
  );

  // focus-next-line
  await Web3AuthFlutter.enableMFA(loginParams: loginParams);
} on UserCancelledException {
  log("User cancelled.");
} catch (e) {
  log("Unknown exception occurred");
}
```

</TabItem>
</Tabs>

---

## Ed25519 private key(Usage)

To retrieve the ed25519 private key of the user, use the `getEd25519PrivateKey` method. This private key can be used to sign transactions on Solana, Near, Algorand, and other chains that use the ed25519 curve.

## Usage

```dart
final privateKey = await Web3AuthFlutter.getEd25519PrivateKey();
```

:::note

Web3Auth supports two widely used cryptographic curves, Secp256k1 and Ed25519, making it chain-agnostic and compatible with multiple blockchain networks. [Learn more about how to connect different blockchains](/embedded-wallets/connect-blockchain).

:::

---

## Secp256k1 private key(Usage)

To retrieve the secp256k1 private key of the user, use the `getPrivateKey` method. The method returns an EVM compatible private key which can be used to sign transactions on EVM compatible chains.

## Usage

```dart
final privateKey = await Web3AuthFlutter.getPrivateKey();
```

:::note

Web3Auth supports two widely used cryptographic curves, Secp256k1 and Ed25519, making it chain-agnostic and compatible with multiple blockchain networks. [Learn more about how to connect different blockchains](/embedded-wallets/connect-blockchain).

:::

---

## Retrieve user information(Usage)

You can use the `getUserInfo` method to retrieve various details about the user, such as their auth connection, whether multi-factor authentication (MFA) is enabled, profile image, name, and other relevant information.

## Usage

```dart
final userInfo = await Web3AuthFlutter.getUserInfo();
```

## UserInfo response

```json
{
  "userInfo": {
    "email": "w3a-heroes@web3auth.com",
    "name": "Web3Auth Heroes",
    "profileImage": "https://lh3.googleusercontent.com/a/Ajjjsdsmdjmnm...",
    "authConnectionId": "torus",
    "userId": "w3a-heroes@web3auth.com",
    "authConnection": "google",
    "groupedAuthConnectionId": "",
    "dappShare": "",
    "idToken": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjFjZjQ4Y...",
    "oAuthIdToken": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjFjZjQ4Y...",
    "oAuthAccessToken": "ya29.a0Aa4xrXMmY_0S6s...",
    "isMfaEnabled": false
  }
}
```

---

## Logging out a user(Usage)

To logout the user and remove the session ID from the device you can use the `logout` method. The user will need to login again to use the dapp next time the dapp is opened.

## Usage

```dart
await Web3AuthFlutter.logout();
```

---

## Manage MFA settings

The `manageMFA` method is used to trigger a login flow that will open a browser to manage the MFA factors for the user. The user will be able to add, remove, and configure MFA factors from the templated user interface.

## Usage

```dart
try {
  await Web3AuthFlutter.manageMFA();
} on UserCancelledException {
  log("User cancelled.");
} catch(e) {
  log("Unknown exception occurred");
}
```

---

## Request signature(Usage)

The `request` method facilitates the use of prebuilt transaction screens for signing transactions. The method returns [SignResponse](#signresponse). It can be used to sign transactions for any EVM chain and screens can be customized to match your branding.

Configure chains during initialization with `Web3AuthOptions(chains: [...])`. The `request` method uses those chains; you no longer pass a separate chain configuration argument.

Please check the list of [JSON RPC methods](https://docs.metamask.io/wallet/reference/json-rpc-api/), noting that the request method currently supports only the signing methods.

## Arguments

| Arguments       | Description                                                                                                                                                                                            |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `method`        | JSON RPC method name in `String`. Currently, the request method only supports the signing methods.                                                                                                     |
| `requestParams` | Parameters for the corresponding method. The parameters should be in the list and correct sequence. Take a look at [RPC methods](https://docs.metamask.io/wallet/reference/json-rpc-api) to know more. |
| `path?`         | Wallet request path. Defaults to `"wallet/request"`.                                                                                                                                                   |
| `appState?`     | Optional app state string passed to the wallet UI.                                                                                                                                                     |

## Usage

```dart title="Usage"

try {
  List<dynamic> params = [];
  // Message to be signed
  params.add("Hello, Web3Auth from Flutter!");
  // User's EOA address
  params.add("<User Address in Hex>");

  // focus-start
  final response = await Web3AuthFlutter.request(
    "personal_sign",
    params,
  );

  log(response.toString());
  // focus-end
} on UserCancelledException {
  log("User cancelled.");
} catch (e) {
  log("Unknown exception occurred");
}
```

## SignResponse

| Name      | Description                                                   |
| --------- | ------------------------------------------------------------- |
| `success` | Determines whether the request was successful or not.         |
| `result?` | Holds the signature for the request when `success` is `true`. |
| `error?`  | Holds the error for the request when `success` is `false`.    |

---

## Show wallet UI(Usage)

The `showWalletUI` method launches the templated wallet UI in a WebView. The wallet UI lets users view account details, tokens, and other features for the chains configured in `Web3AuthOptions`.

Configure chains during initialization with the `chains` and `defaultChainId` parameters on `Web3AuthOptions`. See [Get started](/embedded-wallets/sdk/flutter/) for chain configuration examples.

## Parameters

| Parameter | Description                             |
| --------- | --------------------------------------- |
| `path?`   | Wallet UI path. Defaults to `"wallet"`. |

## Usage

```dart title="Usage"
try {
  // focus-start
  await Web3AuthFlutter.showWalletUI();
  // focus-end
} on UserCancelledException {
  log("User cancelled.");
} catch (e) {
  log("Unknown exception occurred");
}
```

## Chain configuration

Pass chain details when you initialize the SDK:

```dart
await Web3AuthFlutter.init(
  Web3AuthOptions(
    clientId: "WEB3AUTH_CLIENT_ID",
    web3AuthNetwork: Web3AuthNetwork.sapphire_mainnet,
    redirectUrl: redirectUrl,
    chains: [
      Chains(
        chainId: "0x1",
        rpcTarget: "https://mainnet.infura.io/v3/<YOUR_KEY>",
        displayName: "Ethereum Mainnet",
        ticker: "ETH",
        tickerName: "Ethereum",
      ),
    ],
    defaultChainId: "0x1",
  ),
);
```

---

## Embedded Wallets SDK for iOS

## Overview

The MetaMask Embedded Wallets SDK for iOS (formerly Web3Auth Plug and Play) supports social
sign-ins, external wallets, and native authentication state management.
The SDK is written in Swift.

## Prerequisites

- iOS 14+
- Xcode 12+
- Swift 5.x
- A project configured on the
  [Embedded Wallets dashboard](https://developer.metamask.io/).
  See the [dashboard setup](../../dashboard/README.mdx) guide for details.

## Installation

Install the Web3Auth iOS SDK using one of the following methods:

### Swift package manager

1. In Xcode, with your app project open, navigate to **File > Add Package Dependencies**.

2. When prompted, add the Web3Auth iOS SDK repository:

   ```sh
   https://github.com/Web3Auth/web3auth-swift-sdk
   ```

   From the **Dependency Rule** dropdown, select **Exact Version** and enter **12.0.1** as the
   version.

3. Xcode automatically resolves and downloads your dependencies in the background.

### CocoaPods

To install the Embedded Wallets SDK using CocoaPods, follow the steps:

1. Open the Podfile, and add the Embedded Wallets pod:

```sh
pod 'Web3Auth', '~> 12.0.1'
```

2. Once added, use `pod install` command to download the Embedded Wallets dependency.

### Configure redirection

To use Embedded Wallets for iOS, allowlist your `bundleId` in your Embedded Wallets project.

- Go to the [Embedded Wallets developer dashboard](https://developer.metamask.io) and create or
  open an existing project.
- Allowlist `{bundleId}://auth` in the dashboard.
  This step is mandatory for the redirect to work.

## Initialize Embedded Wallets

The iOS SDK uses an async initialization pattern.
The constructor fetches project configuration and restores any active session automatically.
The SDK does not require a separate `initialize()` call.

### Create and initialize an Embedded Wallets instance

Import and configure Web3Auth in your application:

```swift

class ViewModel: ObservableObject {
    var web3Auth: Web3Auth?

    func setup() async {
        do {
            // focus-start
            web3Auth = try await Web3Auth(
                options: Web3AuthOptions(
                    clientId: "<YOUR_CLIENT_ID>", // From the Embedded Wallets dashboard
                    web3AuthNetwork: .SAPPHIRE_MAINNET, // or .SAPPHIRE_DEVNET
                    redirectUrl: "<YOUR_BUNDLE_ID>://auth"
                )
            )
            // focus-end

            // Check for an active session
            if web3Auth?.web3AuthResponse != nil {
                // User is already signed in
            }
        } catch {
            print("Error initializing Web3Auth: \(error)")
        }
    }
}
```

:::note

The async constructor throws if the project configuration fetch fails or if a stored session token
is invalid.
Wrap it in `do/catch` and treat any error as a failed initialization rather than an absent session.

:::

## Advanced configuration

The Embedded Wallets iOS SDK supports several advanced configuration options:

- **[Custom authentication](./advanced/custom-authentication.mdx):** Define authentication methods.
- **[Whitelabeling and UI customization](./advanced/whitelabel.mdx):** Personalize the modal's appearance.
- **[Multi-Factor Authentication (MFA)](./advanced/mfa.mdx):** Set up and manage MFA.
- **[Dapp share](./advanced/dapp-share.mdx):** Share dapp sessions across devices.

:::tip

See the [advanced configuration sections](./advanced/) to learn more about each configuration option.

:::

<Tabs
  defaultValue="basic-config"
  values={[
    { label: "Basic Configuration", value: "basic-config" },
    { label: "Advanced Configuration", value: "advanced-config" },
  ]}
>

<TabItem value="basic-config">

```swift
web3Auth = try await Web3Auth(
    options: Web3AuthOptions(
        clientId: "<YOUR_CLIENT_ID>",
        web3AuthNetwork: .SAPPHIRE_MAINNET, // or .SAPPHIRE_DEVNET
        redirectUrl: "<YOUR_BUNDLE_ID>://auth"
    )
)
```

</TabItem>

<TabItem value="advanced-config">

```swift
web3Auth = try await Web3Auth(
    options: Web3AuthOptions(
        clientId: "<YOUR_CLIENT_ID>",
        web3AuthNetwork: .SAPPHIRE_MAINNET, // or .SAPPHIRE_DEVNET
        redirectUrl: "<YOUR_BUNDLE_ID>://auth",
        authConnectionConfig: [
            AuthConnectionConfig(
                authConnectionId: "<YOUR_AUTH_CONNECTION_ID>", // From the Embedded Wallets dashboard
                authConnection: .GOOGLE,
                clientId: "YOUR_GOOGLE_CLIENT_ID"
            )
        ],
        mfaSettings: MfaSettings(
            deviceShareFactor: MfaSetting(enable: true, priority: 1),
            backUpShareFactor: MfaSetting(enable: true, priority: 2),
            socialBackupFactor: MfaSetting(enable: true, priority: 3),
            passwordFactor: MfaSetting(enable: true, priority: 4)
        )
    )
)
```

</TabItem>

</Tabs>

## Single-factor authentication (SFA) support

The iOS SDK supports single-factor authentication (SFA), which authenticates users directly with a
JWT token from your own authentication system.
When MFA is disabled, users sign in using only the JWT token.

```swift
// SFA sign-in with custom JWT
let result = try await web3Auth.connectTo(
    loginParams: LoginParams(
        authConnection: .CUSTOM,
        authConnectionId: "<YOUR_AUTH_CONNECTION_ID>",
        idToken: "<YOUR_JWT_TOKEN>"
    )
)
```

SFA mode is activated automatically when you provide an `idToken` parameter.

## Blockchain integration

Embedded Wallets supports any blockchain network, with built-in support for **Ethereum** and
**Solana**.

### Ethereum integration

Get the private key using the `getPrivateKey` method and use it with web3.swift or other Ethereum
libraries:

```swift

// Use your Web3Auth instance to get the private key
let privateKey = web3Auth.getPrivateKey()

// Generate the Ethereum Account
let account = try EthereumAccount(privateKey)

// Get the address
let address = account.address

// Create a client
let client = EthereumHttpClient(
    // Please avoid using public RPC URL in production, use services like Infura.
    url: URL(string: rpcUrl)!,
    // Replace with the chain id of the network you want to connect to
    network: .custom(chainId)
)

// Get the balance
let balanceResponse = try await client.eth_getBalance(
    address: address,
    block: .Latest
)

// Convert the balance from Wei to Ether format
let balance = toEther(wei: balanceResponse)
```

### Solana integration

Get the Ed25519 private key using the `getEd25519PrivateKey` method and use it with SolanaSwift or
other Solana libraries:

```swift

// Use your Web3Auth instance to get the private key
let ed25519PrivateKey = try web3Auth.getEd25519PrivateKey()

// Generate the KeyPair
let keyPair = try KeyPair(secretKey: Data(hex: ed25519PrivateKey))

// Get the user account
let userAccount = keyPair.publicKey.base58EncodedString

// Create the JSONRPCAPIClient instance
let endpoint = APIEndPoint(
    address: "https://api.devnet.solana.com",
    network: .devnet
)
let solanaJSONRPCClient = JSONRPCAPIClient(endpoint: endpoint)

// Get the balance
let balanceResponse = try await solanaJSONRPCClient.getBalance(
    account: userAccount
)

// Solana's token decimals is set to be 9
let userBalance = balanceResponse.convertToBalance(decimals: 9)
```

---

## Advanced configuration(3)

The Embedded Wallets SDK offers configuration options to customize authentication flows, UI
appearance, blockchain integrations, and security features for your dapp.

## Configuration structure

Pass options to the `Web3Auth` constructor during setup:

```swift

// focus-start
web3Auth = try await Web3Auth(
    options: Web3AuthOptions(
        clientId: "YOUR_WEB3AUTH_CLIENT_ID", // Get your Client ID from Embedded Wallets dashboard
        web3AuthNetwork: .SAPPHIRE_MAINNET, // or .SAPPHIRE_DEVNET
        redirectUrl: "com.yourapp.bundleid://auth"
    )
)
// focus-end
```

### `Web3AuthOptions`

The constructor takes a `Web3AuthOptions` struct as input.

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Struct", value: "struct" },
  ]}
>

<TabItem value="table">

**Basic parameters:**

| Parameter         | Description                                                                                                                                        |
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `clientId`        | Your Web3Auth Client ID from the [Dashboard](https://developer.metamask.io/). It's a mandatory field of type `String`.                             |
| `web3AuthNetwork` | Web3Auth Network: `.SAPPHIRE_MAINNET`, `.SAPPHIRE_DEVNET`, `.MAINNET`, `.CYAN`, `.AQUA`, or `.TESTNET`. Mandatory field of type `Web3AuthNetwork`. |
| `redirectUrl`     | URL that Web3Auth will redirect API responses upon successful authentication. It's a mandatory field of type `String`.                             |
| `sessionTime?`    | Session duration in seconds. Default is `86400 * 30` (30 days). Maximum is 30 days.                                                                |
| `useSFAKey?`      | Use SFA key to get single factor auth key. Default is `false`. Useful for wallet pre-generation and SFA mode.                                      |
| `defaultChainId?` | Default chain ID to use. Default is `"0x1"` (Ethereum mainnet).                                                                                    |
| `enableLogging?`  | Enable SDK logging. Default is `false`.                                                                                                            |

**Advanced parameters:**

| Parameter               | Description                                                                                                                               |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `whiteLabel?`           | Whitelabel options for custom UI, branding, and translations. Takes `WhiteLabelData` as a value.                                          |
| `authConnectionConfig?` | Auth connection config for custom auth connections. Takes `[AuthConnectionConfig]` as a value.                                            |
| `mfaSettings?`          | Configure MFA settings for authentication. Takes `MfaSettings` as a value.                                                                |
| `chains?`               | Custom chain configuration for blockchain networks. Takes `[Chains]` as a value. See [Chains configuration](#chains-configuration) below. |
| `walletServicesConfig?` | Configuration for Wallet Services including whitelabel options. Takes `WalletServicesConfig` as a value.                                  |

</TabItem>

<TabItem value="struct">

```swift
public struct Web3AuthOptions: Codable {
    let clientId: String
    var redirectUrl: String
    let authBuildEnv: BuildEnv?
    var authConnectionConfig: [AuthConnectionConfig]?
    var whiteLabel: WhiteLabelData?
    var chains: [Chains]?
    var defaultChainId: String?
    let enableLogging: Bool?
    let sessionTime: Int
    var web3AuthNetwork: Web3AuthNetwork
    var useSFAKey: Bool?
    var walletServicesConfig: WalletServicesConfig?
    var mfaSettings: MfaSettings?
}
```

</TabItem>
</Tabs>

## Session management

Control how long users stay authenticated and how sessions persist. The session key is stored in the device's encrypted Keychain.

**Key configuration options:**

- `sessionTime` - Session duration in seconds. Controls how long users remain authenticated
  before needing to sign in again.
  - Minimum: 1 second (`1`).
  - Maximum: 30 days (`86400 * 30`).
  - Default: 30 days (`86400 * 30`).

```swift
web3Auth = try await Web3Auth(
    options: Web3AuthOptions(
        clientId: "YOUR_WEB3AUTH_CLIENT_ID", // Get your Client ID from Embedded Wallets dashboard
        web3AuthNetwork: .SAPPHIRE_MAINNET,
        redirectUrl: "com.yourapp.bundleid://auth",
        sessionTime: 86400 * 7 // 7 days (in seconds)
    )
)
```

## Chains configuration

The `chains` parameter lets you specify custom blockchain networks for the SDK.
When set, these chains are used by Wallet Services (`showWalletUI`, `request`) in addition to
any chains configured in the project dashboard.

### `Chains` fields

| Field               | Type             | Required | Description                                                                               |
| ------------------- | ---------------- | -------- | ----------------------------------------------------------------------------------------- |
| `chainId`           | `String`         | Yes      | Chain ID in hex format (for example, `"0x1"` for Ethereum mainnet, `"0x89"` for Polygon). |
| `rpcTarget`         | `String`         | Yes      | RPC endpoint URL for the chain.                                                           |
| `chainNamespace`    | `ChainNamespace` | No       | Namespace of the chain. Accepts `.eip155`, `.solana`, or `.other`. Default is `.eip155`.  |
| `decimals?`         | `Int?`           | No       | Number of decimals for the native token. Default is `18`.                                 |
| `blockExplorerUrl?` | `String?`        | No       | URL of the block explorer for this chain.                                                 |
| `displayName?`      | `String?`        | No       | Human-readable name for the chain.                                                        |
| `logo?`             | `String?`        | No       | URL of the chain's logo image.                                                            |
| `ticker?`           | `String?`        | No       | Ticker symbol for the native token (for example, `"ETH"`).                                |
| `tickerName?`       | `String?`        | No       | Full name of the native token (for example, `"Ethereum"`).                                |

### Interface

```swift
public struct Chains: Codable {
    public let chainNamespace: ChainNamespace
    public let decimals: Int?
    public let blockExplorerUrl: String?
    public let chainId: String?
    public let displayName: String?
    public let logo: String?
    public let rpcTarget: String
    public let ticker: String?
    public let tickerName: String?
}
```

### Example

```swift
web3Auth = try await Web3Auth(
    options: Web3AuthOptions(
        clientId: "YOUR_WEB3AUTH_CLIENT_ID",
        web3AuthNetwork: .SAPPHIRE_MAINNET,
        redirectUrl: "com.yourapp.bundleid://auth",
        chains: [
            Chains(
                chainId: "0x89",
                rpcTarget: "https://rpc.ankr.com/polygon",
                displayName: "Polygon Mainnet",
                ticker: "MATIC",
                tickerName: "Matic",
                blockExplorerUrl: "https://polygonscan.com"
            )
        ]
    )
)
```

## Wallet Services configuration

The `walletServicesConfig` parameter in `Web3AuthOptions` customizes the behavior of the wallet
UI (`showWalletUI`) and request signing (`request`).
For full configuration options, see the [Wallet Services](./wallet-services.mdx) section.

| Parameter               | Description                                                                                                                                  |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `confirmationStrategy?` | Controls how transaction confirmations are displayed. Accepts `ConfirmationStrategy`. Default is `.defaultStrategy`.                         |
| `whiteLabel?`           | Whitelabel settings specific to the Wallet Services UI. When set, merged with the project-level whitelabel config. Accepts `WhiteLabelData`. |

```swift
web3Auth = try await Web3Auth(
    options: Web3AuthOptions(
        clientId: "YOUR_WEB3AUTH_CLIENT_ID",
        web3AuthNetwork: .SAPPHIRE_MAINNET,
        redirectUrl: "com.yourapp.bundleid://auth",
        walletServicesConfig: WalletServicesConfig(
            confirmationStrategy: .modal
        )
    )
)
```

## Custom authentication methods

Control the sign-in options presented to your users.
For detailed configuration options and implementation examples, see the
[custom authentication](./custom-authentication.mdx) section.

## UI customization

Customize the Embedded Wallets sign-in screens to match your dapp's design.
For complete customization options, see
[Whitelabeling and UI customization](./whitelabel.mdx).

## Multi-Factor Authentication

Add security layers to protect user accounts with two-factor authentication.
For detailed configuration options and implementation examples, see
[Multi-Factor Authentication](./mfa.mdx).

**Key configuration options:**

- `mfaSettings` - Configure MFA settings for different authentication flows
- `mfaLevel` - Control when users are prompted to set up MFA

---

## Using custom authentication in iOS SDK

Custom authentication lets you use your own identity provider to sign users in directly. For example,
you can use your own Google Client ID when authenticating with Google.

With MFA disabled, custom authentication makes the wallet infrastructure invisible to your users, so
they don't see any authentication modal or branding.

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this
SDK in a production environment is the **Growth Plan**. You can use this feature in Web3Auth
Sapphire Devnet network for free.

:::

## Create a connection

:::info prerequisite

[Create a connection](../../../dashboard/authentication.mdx) from the **Authentication** tab of
your project in the [Embedded Wallets developer dashboard](https://developer.metamask.io).

:::

Provide your connection details in the Embedded Wallets dashboard to generate an `authConnectionId`.
The SDK uses this ID to identify the connection during initialization. You can configure multiple
connections for the same project and update them anytime.

:::tip

See [authentication provider setup](../../../authentication/README.mdx) for available connection configurations.

:::

## Configuration

To use custom authentication with supported social providers or sign-in providers like Auth0, `AWS Cognito`, Firebase, or your own custom JWT, add the configuration using the `authConnectionConfig`
parameter during initialization.

The `authConnectionConfig` parameter is an array of `AuthConnectionConfig` instances, each defining
a specific authentication connection.

### Parameters

After creating the auth connection from the [Embedded Wallets developer dashboard](https://developer.metamask.io), you can use the following parameters in the `AuthConnectionConfig`.

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Struct", value: "struct" },
  ]}
>

<TabItem value="table">

| Parameter                  | Description                                                                                                                                                                                                                                                                                                                          |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `authConnectionId`         | Name of the auth connection registered in the Embedded Wallets dashboard. Required. `String`.                                                                                                                                                                                                                                        |
| `authConnection`           | Sign-in type for this connection. Social values such as `.GOOGLE` trigger the provider sign-in flow. `.CUSTOM` marks a JWT-based auth connection: Auth0 and similar providers retrieve the token via `ExtraLoginOptions`, while Firebase, AWS Cognito, or your own JWT server use `LoginParams.idToken`. Required. `AuthConnection`. |
| `clientId`                 | Client ID from your sign-in provider (for example, Google Client ID), or your Embedded Wallets client ID when using `.CUSTOM`. Required. `String`.                                                                                                                                                                                   |
| `name?`                    | Display name for the auth connection. If `nil`, the default name is used. `String`.                                                                                                                                                                                                                                                  |
| `description?`             | Description for the sign-in button. If provided, the button renders at full width; otherwise it renders as an icon button. `String`.                                                                                                                                                                                                 |
| `groupedAuthConnectionId?` | JWT token field that maps to a grouped auth connection ID. Must match the JWT auth connection ID configured in the dashboard. `String`.                                                                                                                                                                                              |
| `logoHover?`               | Logo shown on mouse hover. `String`.                                                                                                                                                                                                                                                                                                 |
| `logoLight?`               | Light logo for dark backgrounds. `String`.                                                                                                                                                                                                                                                                                           |
| `logoDark?`                | Dark logo for light backgrounds. `String`.                                                                                                                                                                                                                                                                                           |
| `mainOption?`              | Show the sign-in button on the main list. Default is `false`. `Bool`.                                                                                                                                                                                                                                                                |
| `showOnModal?`             | Show the sign-in button on the modal. Default is `true`. `Bool`.                                                                                                                                                                                                                                                                     |
| `showOnDesktop?`           | Show the sign-in button on desktop. Default is `true`. `Bool`.                                                                                                                                                                                                                                                                       |
| `showOnMobile?`            | Show the sign-in button on mobile. Default is `true`. `Bool`.                                                                                                                                                                                                                                                                        |
| `jwtParameters?`           | Default JWT sign-in options for this auth connection. Useful for Auth0 configuration. `ExtraLoginOptions`.                                                                                                                                                                                                                           |
| `isDefault?`               | Whether this auth connection is the default connector. Used internally by the SDK. `Bool`.                                                                                                                                                                                                                                           |

</TabItem>

<TabItem value="struct">

```swift
public struct AuthConnectionConfig: Codable {
    let authConnectionId: String
    let authConnection: AuthConnection
    let name: String?
    let description: String?
    let clientId: String
    let groupedAuthConnectionId: String?
    let logoHover: String?
    let logoLight: String?
    let logoDark: String?
    let mainOption: Bool?
    let showOnModal: Bool?
    let showOnDesktop: Bool?
    let showOnMobile: Bool?
    let jwtParameters: ExtraLoginOptions?
    let isDefault: Bool?
}

public enum AuthConnection: String, Codable {
    case GOOGLE = "google"
    case FACEBOOK = "facebook"
    case REDDIT = "reddit"
    case DISCORD = "discord"
    case TWITCH = "twitch"
    case APPLE = "apple"
    case LINE = "line"
    case GITHUB = "github"
    case KAKAO = "kakao"
    case LINKEDIN = "linkedin"
    case TWITTER = "twitter"
    case WEIBO = "weibo"
    case WECHAT = "wechat"
    case EMAIL_PASSWORDLESS = "email_passwordless"
    case CUSTOM = "custom"
    case SMS_PASSWORDLESS = "sms_passwordless"
    case FARCASTER = "farcaster"
}
```

</TabItem>
</Tabs>

### Usage

<Tabs
  defaultValue="Google"
  values={[
    { label: "Google", value: "Google" },
    { label: "Facebook", value: "Facebook" },
    { label: "JWT", value: "jwt" },
  ]}
>

<TabItem value="Google">

```swift

let web3Auth = try await Web3Auth(
    options: Web3AuthOptions(
        clientId: "YOUR_WEB3AUTH_CLIENT_ID",
        web3AuthNetwork: .SAPPHIRE_MAINNET,
        redirectUrl: "com.yourapp.bundleid://auth",
        // focus-start
        authConnectionConfig: [
            AuthConnectionConfig(
                authConnectionId: "your-auth-connection-id", // Get it from Embedded Wallets dashboard
                authConnection: .GOOGLE,
                clientId: "YOUR_GOOGLE_CLIENT_ID"
            )
        ]
        // focus-end
    )
)

// focus-next-line
let result = try await web3Auth.connectTo(loginParams: LoginParams(authConnection: .GOOGLE))
```

</TabItem>

<TabItem value="Facebook">

```swift

let web3Auth = try await Web3Auth(
    options: Web3AuthOptions(
        clientId: "YOUR_WEB3AUTH_CLIENT_ID",
        web3AuthNetwork: .SAPPHIRE_MAINNET,
        redirectUrl: "com.yourapp.bundleid://auth",
        // focus-start
        authConnectionConfig: [
            AuthConnectionConfig(
                authConnectionId: "your-auth-connection-id", // Get it from Embedded Wallets dashboard
                authConnection: .FACEBOOK,
                clientId: "YOUR_FACEBOOK_CLIENT_ID"
            )
        ]
        // focus-end
    )
)

// focus-next-line
let result = try await web3Auth.connectTo(loginParams: LoginParams(authConnection: .FACEBOOK))
```

</TabItem>

<TabItem value="jwt">

```swift

let web3Auth = try await Web3Auth(
    options: Web3AuthOptions(
        clientId: "YOUR_WEB3AUTH_CLIENT_ID",
        web3AuthNetwork: .SAPPHIRE_MAINNET,
        redirectUrl: "com.yourapp.bundleid://auth",
        // focus-start
        authConnectionConfig: [
            AuthConnectionConfig(
                authConnectionId: "your-auth-connection-id", // Get it from Embedded Wallets dashboard
                authConnection: .CUSTOM,
                clientId: "YOUR_WEB3AUTH_CLIENT_ID"
            )
        ]
        // focus-end
    )
)

// focus-next-line
let result = try await web3Auth.connectTo(loginParams: LoginParams(authConnection: .CUSTOM))
```

</TabItem>

</Tabs>

## Configure extra sign-in options

In addition to the auth connection config during initialization, you can pass extra options to the
`connectTo` function to configure the sign-in flow. `ExtraLoginOptions` accepts the following parameters.

### Parameters

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Struct", value: "struct" },
  ]}
>

<TabItem value="table">

| Parameter                | Description                                                                                                                                                      |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `additionalParams?`      | Additional parameters in `[String: String]` format for OAuth sign-in. Use `id_token` (JWT) to authenticate with the SDK. `[String: String]`.                     |
| `domain?`                | Custom authentication domain (for example, `example.au.auth0.com` for Auth0). `String`.                                                                          |
| `client_id?`             | Client ID from your sign-in provider for custom auth connections. `String`.                                                                                      |
| `leeway?`                | Clock-skew tolerance for JWT expiration, in seconds. Recommended maximum is 120 seconds. `Int`.                                                                  |
| `userIdField?`           | JWT token field that maps to the user ID. Must match the JWT user ID configured in the dashboard. `String`.                                                      |
| `isUserIdCaseSensitive?` | Whether the user ID field is case-sensitive. `Bool`.                                                                                                             |
| `display?`               | OIDC `display` parameter controlling how the authentication UI renders (for example, `page`, `popup`, `touch`). `String`.                                        |
| `prompt?`                | OIDC `prompt` parameter shown during authentication (for example, `login`, `consent`, `none`). `String`.                                                         |
| `max_age?`               | Maximum time (in seconds) since the last authentication before the user must re-authenticate. `String`.                                                          |
| `ui_locales?`            | Space-separated list of language tags, ordered by preference (for example, `fr-CA fr en`). `String`.                                                             |
| `id_token_hint?`         | Previously issued ID token, used as a hint for re-authentication. `String`.                                                                                      |
| `id_token?`              | JWT (ID token) to pass for sign-in. `String`.                                                                                                                    |
| `login_hint?`            | Hint for the sign-in provider (for example, an email address). For passwordless flows, prefer `LoginParams.loginHint`. `String`.                                 |
| `access_token?`          | Access token for OAuth flows. `String`.                                                                                                                          |
| `flow_type?`             | Email passwordless flow type. `EmailFlowType` (`.code` or `.link`).                                                                                              |
| `acr_values?`            | Authentication context class reference values requested from the provider. `String`.                                                                             |
| `scope?`                 | Default scope for authentication requests. `String`.                                                                                                             |
| `audience?`              | Audience for the access token, presented as the `aud` claim. `String`.                                                                                           |
| `connection?`            | Name of the connection configured for your dapp. If `nil`, redirects to the Auth0 sign-in page. `String`.                                                        |
| `state?`                 | Opaque value used to maintain state between the request and callback, preventing CSRF attacks. `String`.                                                         |
| `response_type?`         | Grant type to execute for the authorization server. `String`.                                                                                                    |
| `nonce?`                 | Random value used to prevent replay attacks in OIDC flows. `String`.                                                                                             |
| `redirect_uri?`          | URL where your custom JWT verifier redirects the browser with the result. For Auth0, must be allowlisted in **Allowed Callback URLs** in your Auth0 application. |

</TabItem>

<TabItem value="struct">

```swift
public struct ExtraLoginOptions: Codable {
    let display: String?
    let prompt: String?
    let max_age: String?
    let ui_locales: String?
    let id_token_hint: String?
    let id_token: String?
    var login_hint: String?
    let acr_values: String?
    let scope: String?
    let audience: String?
    let connection: String?
    let domain: String?
    let client_id: String?
    let redirect_uri: String?
    let leeway: Int?
    let userIdField: String?
    let isUserIdCaseSensitive: Bool?
    let additionalParams: [String: String]?
    let access_token: String?
    let flow_type: EmailFlowType?
}

public enum EmailFlowType: String, Codable {
    case code = "code"
    case link = "link"
}
```

</TabItem>

</Tabs>

### Single auth connection example

<Tabs defaultValue="auth0"
  values={[
    { label: "Auth0", value: "auth0" },
    { label: "Custom JWT", value: "custom-jwt" },
    { label: "Email Passwordless", value: "email-passwordless" },
    { label: "SMS Passwordless", value: "sms-passwordless" },
  ]}
>

<TabItem value="auth0">

Auth0 uses the `.CUSTOM` auth connection type with Auth0's SPA flow. Unlike Firebase or custom JWT
servers where you pass a pre-obtained token in `LoginParams.idToken`, the SDK retrieves the JWT
`id_token` from Auth0 directly. Pass your Auth0 `client_id` and `domain` in `ExtraLoginOptions` in
the `connectTo` call.

```swift

let web3Auth = try await Web3Auth(
    options: Web3AuthOptions(
        clientId: "YOUR_WEB3AUTH_CLIENT_ID",
        web3AuthNetwork: .SAPPHIRE_MAINNET,
        redirectUrl: "com.yourapp.bundleid://auth",
        // focus-start
        authConnectionConfig: [
            AuthConnectionConfig(
                authConnectionId: "your-auth-connection-id", // Get it from Embedded Wallets dashboard
                authConnection: .CUSTOM,
                clientId: "YOUR_AUTH0_CLIENT_ID"
            )
        ]
        // focus-end
    )
)

// focus-start
let result = try await web3Auth.connectTo(
    loginParams: LoginParams(
        authConnection: .CUSTOM,
        extraLoginOptions: ExtraLoginOptions(
            domain: "https://username.us.auth0.com", // Domain of your Auth0 app
            userIdField: "sub" // The field in JWT token which maps to user ID
        )
    )
)
// focus-end
```

</TabItem>

<TabItem value="custom-jwt">

If you're using another provider like Firebase, `AWS Cognito`, or your own custom JWT server, pass the
JWT token in the `idToken` parameter of `LoginParams`. In Single Factor Auth (SFA) mode, this
enables direct authentication without additional sign-in flows.

```swift

let web3Auth = try await Web3Auth(
    options: Web3AuthOptions(
        clientId: "YOUR_WEB3AUTH_CLIENT_ID",
        web3AuthNetwork: .SAPPHIRE_MAINNET,
        redirectUrl: "com.yourapp.bundleid://auth",
        // focus-start
        authConnectionConfig: [
            AuthConnectionConfig(
                authConnectionId: "your-auth-connection-id", // Get it from Embedded Wallets dashboard
                authConnection: .CUSTOM,
                clientId: "YOUR_WEB3AUTH_CLIENT_ID"
            )
        ]
        // focus-end
    )
)

// focus-start
let result = try await web3Auth.connectTo(
    loginParams: LoginParams(
        authConnection: .CUSTOM,
        authConnectionId: "your-auth-connection-id",
        idToken: "your_jwt_token" // Direct SFA authentication
    )
)
// focus-end
```

</TabItem>

<TabItem value="email-passwordless">

For Email Passwordless sign-in, pass the email address as the `loginHint` parameter of `LoginParams`.
The default flow is `code` (OTP). To use a magic link flow instead, set `flow_type` to `.link` in
`extraLoginOptions`.

```swift

let web3Auth = try await Web3Auth(
    options: Web3AuthOptions(
        clientId: "YOUR_WEB3AUTH_CLIENT_ID",
        web3AuthNetwork: .SAPPHIRE_MAINNET,
        redirectUrl: "com.yourapp.bundleid://auth"
    )
)

// focus-start
let result = try await web3Auth.connectTo(
    loginParams: LoginParams(
        authConnection: .EMAIL_PASSWORDLESS,
        loginHint: "hello@web3auth.io",
        extraLoginOptions: ExtraLoginOptions(
            flow_type: .code // Use .code for OTP flow or .link for magic link flow
        )
    )
)
// focus-end
```

</TabItem>

<TabItem value="sms-passwordless">

For SMS Passwordless sign-in, pass the phone number as the `loginHint` parameter of `LoginParams`.
The phone number must use the format `+{country_code}-{phone_number}`, for example `+91-9911223344`.

```swift

let web3Auth = try await Web3Auth(
    options: Web3AuthOptions(
        clientId: "YOUR_WEB3AUTH_CLIENT_ID",
        web3AuthNetwork: .SAPPHIRE_MAINNET,
        redirectUrl: "com.yourapp.bundleid://auth"
    )
)

// focus-start
let result = try await web3Auth.connectTo(
    loginParams: LoginParams(
        authConnection: .SMS_PASSWORDLESS,
        loginHint: "+91-9911223344"
    )
)
// focus-end
```

</TabItem>
</Tabs>

### Grouped auth connection example

Grouped auth connections combine multiple sign-in methods so your users get the same address regardless
of how they sign in. For example, combine Google and Email Passwordless, or Google and GitHub via
Auth0, to resolve to the same address.

```swift

let web3Auth = try await Web3Auth(
    options: Web3AuthOptions(
        clientId: "YOUR_WEB3AUTH_CLIENT_ID",
        web3AuthNetwork: .SAPPHIRE_MAINNET,
        redirectUrl: "com.yourapp.bundleid://auth",
        // focus-start
        authConnectionConfig: [
            AuthConnectionConfig(
                authConnectionId: "aggregate-sapphire",
                groupedAuthConnectionId: "w3a-google",
                authConnection: .GOOGLE,
                name: "Aggregate Login",
                clientId: "YOUR_GOOGLE_CLIENT_ID"
            ),
            AuthConnectionConfig(
                authConnectionId: "aggregate-sapphire",
                groupedAuthConnectionId: "w3a-a0-email-passwordless",
                authConnection: .CUSTOM,
                name: "Aggregate Login",
                clientId: "YOUR_AUTH0_CLIENT_ID"
            )
        ]
        // focus-end
    )
)

func loginWithGoogle() async throws {
    // focus-next-line
    let result = try await web3Auth.connectTo(loginParams: LoginParams(authConnection: .GOOGLE))
}

func loginWithGitHub() async throws {
    // focus-start
    let result = try await web3Auth.connectTo(
        loginParams: LoginParams(
            authConnection: .CUSTOM,
            extraLoginOptions: ExtraLoginOptions(
                connection: "github",
                domain: "https://web3auth.au.auth0.com",
                userIdField: "email",
                isUserIdCaseSensitive: false
            )
        )
    )
    // focus-end
}
```

---

## Dapp share(3)

## Embedded Wallets infrastructure at a glance

As described in the [Embedded Wallets infrastructure](/embedded-wallets/infrastructure/), to keep
Embedded Wallets non-custodial, the private key is split into multiple parts called `shares`.
These shares are a part of the offchain multisig, where multiple shares are stored in different
places and can be used to reconstruct the private key dynamically in the user's frontend
application.
Typically, there are 3 shares:

1. **`ShareA` is managed by a sign-in service via node operators:** This share is further split
   amongst a network of nodes and retrieved via conventional authentication flows.
2. **`ShareB` is stored on the user's device:** Implementation is device and system specific.
   For example, on mobile devices, the share could be stored in device storage secured via
   biometrics.
3. **`ShareC` is a recovery share:** An extra share to be kept by the user, possibly kept on a
   separate device, downloaded or based on user input with enough entropy (such as, password,
   security questions, hardware device).

Similar to existing 2FA systems, a user needs to prove ownership of at least 2 out of 3 (2/3)
shares to retrieve their private key.

## Mobile platform user experience

The user experience on mobile platforms differs from web platforms.
On mobile, the user is redirected to a browser to sign in with their social accounts and then
back to the app after authentication.
This shifts context between two applications, whereas on web platforms the context remains
within the browser only.

For a seamless sign-in flow, Shares `A` and `B` must be reconstructed.
`Share B` is managed by the sign-in service and is provided on successful authentication.
On web platforms, `Share A` is stored in the browser context.
You can still store it in the browser context on mobile devices, but this carries risks; users
may delete browser data by mistake.
This is a bigger problem on mobile because users don't realize the browser is used to sign in
within the app, and clearing browser data can cause sign-in to fail.
To address this, Embedded Wallets issues a dapp share, a backup share that you can store
directly in your app and use to reconstruct the private key after a successful sign-in.

## Dapp share in iOS

After a successful sign-in, the SDK returns user details to your app.

#### Sample response in iOS

```json
{
  "userInfo": {
    "email": "w3a-heroes@web3auth.com",
    "name": "Web3Auth Heroes",
    "profileImage": "https://lh3.googleusercontent.com/a/Ajjjsdsmdjmnm...",
    "authConnectionId": "torus",
    "userId": "w3a-heroes@web3auth.com",
    "authConnection": "google",
    "groupedAuthConnectionId": "w3a-google-sapphire",
    "dappShare": "", // 24 words of seed phrase will be sent only incase of custom auth connections
    "idToken": "<jwtToken issued by Web3Auth>",
    "oAuthIdToken": "<jwtToken issued by OAuth Provider>", // will be sent only incase of custom auth connections
    "oAuthAccessToken": "<accessToken issued by OAuth Provider>", // will be sent only incase of custom auth connections
    "isMfaEnabled": false // Returns whether the user has enabled MFA or not
  }
}
```

The response includes a `dappShare` field, a 24-word seed phrase that can reconstruct the
private key.
`dappShare` supplements `Share A` and represents half of the private key.
You can store the dapp share in your app's local storage.

During sign-in, the user's social account provides one share, and your app provides the dapp
share, removing the need to store a share in the browser context.
Pass the stored dapp share value in the `connectTo` call.

:::note

`dappShare` is only available for custom auth connections, not standard Embedded Wallets auth
connections.
This ensures your app only has access to the share corresponding to your users' private keys.
To use dapp share, you must use the
[custom authentication](./custom-authentication.mdx) feature.
Dapp share is only returned to users who have enabled 2FA on their account.

:::

```swift
try await web3Auth.connectTo(
    loginParams: LoginParams(
        authConnection: selectedAuthConnection,
        dappShare: "<24 words seed phrase>"
    )
)
```

## Example

```swift

class ViewModel: ObservableObject {
    var web3Auth: Web3Auth?
    @Published var loggedIn: Bool = false
    @Published var userInfo: Web3AuthUserInfo?
    @Published var isLoading = false
    @Published var navigationTitle: String = ""

    func setup() async {
        guard web3Auth == nil else { return }
        await MainActor.run {
            isLoading = true
            navigationTitle = "Loading"
        }
        web3Auth = try? await Web3Auth(
            options: Web3AuthOptions(
                clientId: "YOUR_WEB3AUTH_CLIENT_ID",
                web3AuthNetwork: .SAPPHIRE_MAINNET,
                redirectUrl: "com.yourapp.bundleid://auth"
            )
        )

        await MainActor.run {
            if self.web3Auth?.web3AuthResponse != nil {
                userInfo = web3Auth?.web3AuthResponse?.userInfo
                loggedIn = true
            }
            isLoading = false
            navigationTitle = loggedIn ? "UserInfo" : "SignIn"
        }
    }

    func login(authConnection: AuthConnection) {
        Task {
            do {
                let result = try await web3Auth?.connectTo(
                    loginParams: LoginParams(
                        // authConnection can be .GOOGLE, .FACEBOOK, .APPLE etc
                        authConnection: authConnection,
                        // focus-next-line
                        dappShare: "<24 words seed phrase>"
                    )
                )

                await MainActor.run {
                    userInfo = result?.userInfo
                    loggedIn = true
                }
            } catch {
                print("Error: \(error)")
            }
        }
    }
}
```

---

## Multi-factor authentication in iOS SDK

Multi-Factor Authentication (MFA) adds an extra layer of protection that verifies your identity
when accessing your account.
To ensure ownership, you must provide two or more different backup factors.
Choose from device, social, backup factor (seed phrase), and password factors to secure access
to your web3 account.
Once you create a recovery factor, MFA is enabled, and your keys are divided into three shares
for offchain multi-sig, making the key self-custodial.
With backup factors, you can recover your account if you lose access to your original device or
need to sign in on a new device.

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this SDK in a production environment is the **Scale Plan**. You can use this feature in Web3Auth Sapphire Devnet network for free.

:::

## Enable using the MFA level

Customize the MFA screen by passing the `mfaLevel` parameter in the `connectTo` method.
You can enable or disable a backup factor and change their order.
Four MFA level values are available.

:::caution Note

If you're using default auth connections, your users may have set up MFA on other dapps that
also use default Embedded Wallets auth connections.
In this case, the MFA screen continues to appear if the user has enabled MFA on other dapps.
MFA can't be turned off once enabled.

:::

### MFA level options

| MFA Level | Description                                                  |
| --------- | ------------------------------------------------------------ |
| DEFAULT   | Shows the MFA screen every third sign-in.                    |
| OPTIONAL  | Shows the MFA screen on every sign-in, but user can skip it. |
| MANDATORY | Makes it mandatory to set up MFA after first sign-in.        |
| NONE      | Skips the MFA setup screen.                                  |

### Usage

```swift

let web3Auth = try await Web3Auth(
    options: Web3AuthOptions(
        clientId: "YOUR_WEB3AUTH_CLIENT_ID",
        web3AuthNetwork: .SAPPHIRE_MAINNET,
        redirectUrl: "com.yourapp.bundleid://auth"
    )
)

let result = try await web3Auth.connectTo(
    loginParams: LoginParams(
        authConnection: .GOOGLE,
        // focus-next-line
        mfaLevel: .MANDATORY
    )
)
```

## Explicitly enable MFA

The `enableMFA` method triggers the MFA setup flow for users.
It takes `LoginParams`, which is used during custom auth connections.
If you're using default sign-in providers, you don't need to pass `LoginParams`.
For custom JWT auth connections, pass the valid JWT token in `LoginParams`.

<Tabs
  defaultValue="default-verifier"
  values={[
    { label: "Default Auth Connection", value: "default-verifier" },
    { label: "Custom JWT Auth Connection", value: "custom-jwt-verifier" },
  ]}
>

<TabItem value = "default-verifier">

```swift
do {
  // focus-next-line
  let isMFAEnabled = try await web3Auth.enableMFA()
} catch {
  print(error.localizedDescription)
  // Handle Error
}
```

</TabItem>

<TabItem value = "custom-jwt-verifier">

```swift
do {
    let loginParams = LoginParams(
        authConnection: .CUSTOM,
        authConnectionId: "your-auth-connection-id",
        idToken: "your_jwt_token"
    )

    // focus-next-line
    let isMFAEnabled = try await web3Auth.enableMFA(loginParams)
} catch {
    print(error.localizedDescription)
    // Handle Error
}
```

</TabItem>
</Tabs>

## Configure Multi-Factor Authentication settings

Configure the order of MFA or enable/disable MFA types by passing the `mfaSettings` object in
`Web3AuthOptions`.

:::note Note

- At least two factors are mandatory when setting up `mfaSettings`.
- If you set `mandatory: true` for all factors, the user must set up all factors.
- If you set `mandatory: false` for all factors, the user can skip MFA setup, but at least
  two factors are still mandatory.
- If you set `mandatory: true` for some factors and `mandatory: false` for others, the user
  must set up the mandatory factors and can skip the optional ones, but must set up at least
  two factors total.
- The `priority` field sets the order of the factors. The lowest priority value is set up
  first; the highest is set up last.

:::

### `MfaSettings` parameters

`MfaSettings` configures which MFA factor types are available.

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Class", value: "class" },
  ]}
>

<TabItem value="table">

| Parameter              | Description                                                                |
| ---------------------- | -------------------------------------------------------------------------- |
| `deviceShareFactor?`   | MFA setting for deviceShareFactor. It accepts `MfaSetting` as a value.     |
| `backUpShareFactor?`   | MFA setting for backUpShareFactor. It accepts `MfaSetting` as a value.     |
| `socialBackupFactor?`  | MFA setting for socialBackupFactor. It accepts `MfaSetting` as a value.    |
| `passwordFactor?`      | MFA setting for `passwordFactor`. It accepts `MfaSetting` as a value.      |
| `passkeysFactor?`      | MFA setting for `passkeysFactor`. It accepts `MfaSetting` as a value.      |
| `authenticatorFactor?` | MFA setting for `authenticatorFactor`. It accepts `MfaSetting` as a value. |

</TabItem>

<TabItem value="class">

```swift
public struct MfaSettings: Codable {
    public init(deviceShareFactor: MfaSetting?, backUpShareFactor: MfaSetting?, socialBackupFactor: MfaSetting?, passwordFactor: MfaSetting?, passkeysFactor: MfaSetting?, authenticatorFactor: MfaSetting?) {
        self.deviceShareFactor = deviceShareFactor
        self.backUpShareFactor = backUpShareFactor
        self.socialBackupFactor = socialBackupFactor
        self.passwordFactor = passwordFactor
        self.passkeysFactor = passkeysFactor
        self.authenticatorFactor = authenticatorFactor
    }

    let deviceShareFactor: MfaSetting?
    let backUpShareFactor: MfaSetting?
    let socialBackupFactor: MfaSetting?
    let passwordFactor: MfaSetting?
    let passkeysFactor: MfaSetting?
    let authenticatorFactor: MfaSetting?
}
```

</TabItem>
</Tabs>

### `MfaSetting` parameters

`MfaSetting` configures the behavior of an individual MFA factor.

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Class", value: "class" },
  ]}
>

<TabItem value="table">

| Parameter    | Description                                                                     |
| ------------ | ------------------------------------------------------------------------------- |
| `enable`     | Enable/Disable MFA. It accepts `Bool` as a value.                               |
| `priority?`  | Priority of MFA. It accepts `Int` as a value, where valid range is from 1 to 4. |
| `mandatory?` | Mandatory/Optional MFA. It accepts `Bool` as a value.                           |

</TabItem>

<TabItem value="class">

```swift
public struct MfaSetting: Codable {
    public init(enable: Bool, priority: Int?, mandatory: Bool? = nil) {
        self.enable = enable
        self.priority = priority
        self.mandatory = mandatory
    }

    let enable: Bool
    let priority: Int?
    let mandatory: Bool?
}
```

</TabItem>
</Tabs>

### Usage

```swift

let web3Auth = try await Web3Auth(
    options: Web3AuthOptions(
        clientId: "YOUR_WEB3AUTH_CLIENT_ID",
        web3AuthNetwork: .SAPPHIRE_MAINNET,
        redirectUrl: "com.yourapp.bundleid://auth",
        // focus-start
        mfaSettings: MfaSettings(
            deviceShareFactor: MfaSetting(enable: true, priority: 1),
            backUpShareFactor: MfaSetting(enable: true, priority: 2),
            socialBackupFactor: MfaSetting(enable: true, priority: 3),
            passwordFactor: MfaSetting(enable: true, priority: 4),
            passkeysFactor: MfaSetting(enable: true, priority: 5),
            authenticatorFactor: MfaSetting(enable: true, priority: 6)
        )
        // focus-end
    )
)

let result = try await web3Auth.connectTo(
    loginParams: LoginParams(
        authConnection: .GOOGLE,
        // focus-next-line
        mfaLevel: .MANDATORY
    )
)
```

---

## Wallet Services configuration

The iOS SDK provides fine-grained control over the `showWalletUI` and `request` flows through
the `walletServicesConfig` parameter in `Web3AuthOptions`.
Customize how transaction confirmations display and tailor the wallet UI branding.

:::note

Wallet Services requires a paid plan.
You can use this feature in `sapphire_devnet` at no cost.
The minimum [pricing plan](https://web3auth.io/pricing.html) to use this feature in a
production environment is the **Scale Plan**.

:::

## `WalletServicesConfig`

Pass `walletServicesConfig` in `Web3AuthOptions` to configure how Wallet Services behave across
your dapp.

### Parameters

| Parameter               | Description                                                                                                                                               |
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `confirmationStrategy?` | Controls how transaction confirmations are displayed. Accepts `ConfirmationStrategy`. Default is `.defaultStrategy`.                                      |
| `whiteLabel?`           | Whitelabel configuration for the Wallet Services UI. When provided, merged with the project-level whitelabel config. Accepts `WhiteLabelData` as a value. |

### `ConfirmationStrategy`

`ConfirmationStrategy` controls the UI shown when a user needs to confirm a transaction or signature request.

| Value              | Description                                                                                                                             |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------- |
| `.defaultStrategy` | Shows the default Web3Auth confirmation screen inside the wallet WebView. This is the default value.                                    |
| `.modal`           | Shows the confirmation request in a bottom sheet modal on top of your application, rather than navigating to a new full-screen WebView. |
| `.popup`           | Shows the confirmation in a small popup window. Useful for minimal UI disruption.                                                       |

### Interface

```swift
public struct WalletServicesConfig: Codable {
    public let confirmationStrategy: ConfirmationStrategy?
    public let whiteLabel: WhiteLabelData?

    public init(
        confirmationStrategy: ConfirmationStrategy? = nil,
        whiteLabel: WhiteLabelData? = nil
    )
}

public enum ConfirmationStrategy: String, Codable {
    case defaultStrategy = "default"
    case modal = "modal"
    case popup = "popup"
}
```

## Setup

Configure `walletServicesConfig` during SDK initialization:

```swift

web3Auth = try await Web3Auth(
    options: Web3AuthOptions(
        clientId: "YOUR_WEB3AUTH_CLIENT_ID",
        web3AuthNetwork: .SAPPHIRE_MAINNET,
        redirectUrl: "com.yourapp.bundleid://auth",
        // focus-start
        walletServicesConfig: WalletServicesConfig(
            confirmationStrategy: .modal,
            whiteLabel: WhiteLabelData(
                appName: "My App",
                theme: ["primary": "#0364FF"]
            )
        )
        // focus-end
    )
)
```

## Usage examples

<Tabs
  defaultValue="show-wallet"
  values={[
    { label: "Show Wallet UI", value: "show-wallet" },
    { label: "Sign Personal Message", value: "personal-sign" },
    { label: "Sign Typed Data", value: "typed-data" },
  ]}
>

<TabItem value="show-wallet">

```swift
do {
    // focus-next-line
    try await web3Auth.showWalletUI()
} catch {
    print(error.localizedDescription)
    // Handle error
}
```

</TabItem>

<TabItem value="personal-sign">

```swift
do {
    var params = [Any]()
    params.append("Hello, Web3Auth from iOS!")
    params.append(address) // User's EOA address

    // focus-start
    let response = try await web3Auth.request(
        method: "personal_sign",
        requestParams: params
    )
    // focus-end

    if let response = response, response.success {
        print("Signature: \(response.result!)")
    }
} catch {
    print(error.localizedDescription)
    // Handle error
}
```

</TabItem>

<TabItem value="typed-data">

```swift
do {
    let typedData = """
    {
        "types": {
            "EIP712Domain": [
                { "name": "name", "type": "string" }
            ],
            "Mail": [
                { "name": "contents", "type": "string" }
            ]
        },
        "primaryType": "Mail",
        "domain": { "name": "Ether Mail" },
        "message": { "contents": "Hello, Bob!" }
    }
    """

    var params = [Any]()
    params.append(address) // User's EOA address
    params.append(typedData)

    // focus-start
    let response = try await web3Auth.request(
        method: "eth_signTypedData_v4",
        requestParams: params
    )
    // focus-end

    if let response = response, response.success {
        print("Signature: \(response.result!)")
    }
} catch {
    print(error.localizedDescription)
    // Handle error
}
```

</TabItem>
</Tabs>

---

## Whitelabel iOS SDK

Embedded Wallets supports whitelabeling with your dapp's branding for a consistent user
experience.
You can customize three aspects:

- **UI elements:** Customize the appearance of modals and components
- **Branding:** Apply your brand colors, logos, and themes
- **Translations:** Localize the interface for your users

:::info

All of these settings can be easily managed directly from the Embedded Wallets dashboard. Once you update your branding, or UI preferences there, the changes will automatically apply to your integration.

:::

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this
SDK in a production environment is the **Growth Plan**. You can use this feature in Web3Auth
Sapphire Devnet network for free.

:::

## Customizing the Embedded Wallets sign-in screens

Define a `WhiteLabelData` object to customize UI, branding, and translations.
Pass it during initialization of the SDK in `Web3AuthOptions`.

### Parameters

The following parameters customize the sign-in screens:

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Interface", value: "interface" },
  ]}
>

<TabItem value="table">

| Parameter          | Description                                                                                                                                                       |
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `appName?`         | Display name for the app in the UI.                                                                                                                               |
| `logoLight?`       | App logo to be used in dark mode. It accepts URL as a string.                                                                                                     |
| `logoDark?`        | App logo to be used in light mode. It accepts URL as a string.                                                                                                    |
| `defaultLanguage?` | Language used by Embedded Wallets. Falls back to browser language if not specified. Default is `Language.en`. See `Language` for supported languages.             |
| `mode?`            | Theme mode for the sign-in modal. Choose between `ThemeModes.auto`, `ThemeModes.light` or `ThemeModes.dark` background modes. Default value is `ThemeModes.auto`. |
| `theme?`           | Used to customize the theme of the sign-in modal. It accepts a dictionary of `[String: String]` as a value.                                                       |
| `appUrl?`          | URL to be used in the modal. It accepts URL as a string.                                                                                                          |
| `useLogoLoader?`   | Use logo loader. If `logoDark` and `logoLight` are nil, the default Embedded Wallets logo is used for the loader. Default is false.                               |

</TabItem>

<TabItem value="interface">

```swift
public struct WhiteLabelData: Codable {
    let appName: String?
    let logoLight: String?
    let logoDark: String?
    let defaultLanguage: Language?
    let mode: ThemeModes?
    let theme: [String: String]?
    let appUrl: String?
    let useLogoLoader: Bool?
}
```

</TabItem>
</Tabs>

### `name`

The name of the application. This will be displayed in the key reconstruction page.

  
    
      Standard screen without any change
    
    
  
  
    
      Name changed to <code>Formidable Duo</code>
    
    
  

### `logoLight` & `logoDark`

The logo of the application. Displayed in dark and light mode respectively. This will be displayed
in the key reconstruction page.

  
    
      <code>logoLight</code> on dark mode
    
    
  
  
    
      <code>logoDark</code> on light mode
    
    
  

### `defaultLanguage`

Default language will set the language used on all OpenLogin screens. The supported languages are:

  
    
      
        <code>en</code> - English (default)
      
      
        <code>de</code> - German
      
      
        <code>ja</code> - Japanese
      
      
        <code>ko</code> - Korean
      
      
        <code>zh</code> - Mandarin
      
      
        <code>es</code> - Spanish
      
      
        <code>fr</code> - French
      
      
        <code>pt</code> - Portuguese
      
      
        <code>nl</code> - Dutch
      
      
        <code>tr</code> - Turkish
      
    
  
  
    
  

### `dark`

Can be set to `true` or `false` with default set to `false`.

  
    
      For Light: <code>dark: false</code>
    
    
  
  
    
      For Dark: <code>dark: true</code>
    
    
  

### `theme`

Theme is a record of colors that can be configured. As of, now only `primary` color can be set and
has effect on OpenLogin screens (default primary color is `#0364FF`). Theme affects icons and links.
Examples below.

  
    
      Standard color <code>#0364FF</code>
    
    
  
  
    
      Color changed to <code>#D72F7A</code>
    
    
  

### Example

```swift title="Usage"
web3Auth = try await Web3Auth(
    options: Web3AuthOptions(
        clientId: "YOUR_WEB3AUTH_CLIENT_ID",
        web3AuthNetwork: .SAPPHIRE_MAINNET,
        redirectUrl: "com.yourapp.bundleid://auth",
        // focus-start
        whiteLabel: WhiteLabelData(
            appName: "Web3Auth Stub",
            logoLight: "https://images.web3auth.io/web3auth-logo-w.svg",
            logoDark: "https://images.web3auth.io/web3auth-logo-w.svg",
            defaultLanguage: .en, // en, de, ja, ko, zh, es, fr, pt, nl
            mode: .dark,
            theme: ["primary": "#d53f8c"]
        )
        // focus-end
    )
)
```

---

## Examples - PnP iOS SDK

<ExampleCards exampleMap={pnpiOSExamples} />

---

## Using iOS SDK

Embedded Wallets provides methods for authentication, user management, and blockchain interactions
in your iOS applications.
Use these methods to implement sign-in, multi-factor authentication (MFA), private key retrieval,
and Wallet Services.

## Available methods

### Authentication methods

| Method                           | Description                                          |
| -------------------------------- | ---------------------------------------------------- |
| [`connectTo()`](./connectTo.mdx) | Signs in the user with the selected auth connection. |
| [`logout()`](./logout.mdx)       | Signs out the user from the current session.         |

### User management methods

| Method                                 | Description                                     |
| -------------------------------------- | ----------------------------------------------- |
| [`getUserInfo()`](./get-user-info.mdx) | Retrieves the authenticated user's information. |

### Private key methods

| Method                                                 | Description                                                                      |
| ------------------------------------------------------ | -------------------------------------------------------------------------------- |
| [`getPrivateKey()`](./getPrivateKey.mdx)               | Retrieves the user's secp256k1 private key for EVM-compatible chains.            |
| [`getEd25519PrivateKey()`](./getEd25519PrivateKey.mdx) | Retrieves the user's Ed25519 private key for chains like Solana, Near, Algorand. |

### Security methods

| Method                            | Description                        |
| --------------------------------- | ---------------------------------- |
| [`enableMFA()`](./enable-mfa.mdx) | Enables MFA for the user.          |
| [`manageMFA()`](./manage-mfa.mdx) | Manages MFA settings for the user. |

### Wallet Services methods

| Method                                 | Description                                                      |
| -------------------------------------- | ---------------------------------------------------------------- |
| [`showWalletUI()`](./showWalletUI.mdx) | Launches the built-in wallet UI in WebView.                      |
| [`request()`](./request.mdx)           | Opens built-in transaction screens for signing EVM transactions. |

---

## Sign in a user(3)

To sign in a user, use the `connectTo` method.
It triggers the sign-in flow and navigates the user to a browser modal for authentication.
Pass supported auth connections for specific social sign-ins (such as `.GOOGLE`, `.APPLE`,
`.FACEBOOK`) or use whitelabel sign-in.

For SFA (Single Factor Auth) sign-in with a JWT token, pass the `idToken` parameter to
authenticate directly without the browser modal.

## Parameters

The `connectTo` method accepts `LoginParams` as a required parameter.

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Struct", value: "struct" },
  ]}
>

<TabItem value="table">

| Parameter                  | Description                                                                                                                                                                                                                                                                                         |
| -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `authConnection`           | It sets the OAuth sign-in method to be used. You can use any of the supported values: `.GOOGLE`, `.FACEBOOK`, `.REDDIT`, `.DISCORD`, `.TWITCH`, `.APPLE`, `.LINE`, `.GITHUB`, `.KAKAO`, `.LINKEDIN`, `.TWITTER`, `.WEIBO`, `.WECHAT`, `.EMAIL_PASSWORDLESS`, `.SMS_PASSWORDLESS`, and `.FARCASTER`. |
| `authConnectionId?`        | The auth connection ID for the connection. Required for SFA mode when `idToken` is passed. Default value is `nil`.                                                                                                                                                                                  |
| `groupedAuthConnectionId?` | The grouped auth connection ID for grouped auth connections. It accepts `String` as a value.                                                                                                                                                                                                        |
| `extraLoginOptions?`       | It can be used to set the OAuth sign-in options for the corresponding `authConnection`. Default value is `nil`, and it accepts `ExtraLoginOptions` as a value.                                                                                                                                      |
| `appState?`                | It can be used to keep track of the app state when user will be redirected to app after sign-in. Default is `nil`, and it accepts a string value.                                                                                                                                                   |
| `mfaLevel?`                | Customize the MFA screen shown to the user during authentication. Default value is `.DEFAULT`, which shows MFA screen every 3rd sign-in. It accepts `MFALevel` as a value.                                                                                                                          |
| `dappShare?`               | Custom auth connection sign-ins can get a dapp share returned to them post successful sign-in. This is useful if the dapps want to use this share to allow users to sign in seamlessly. It accepts a string value.                                                                                  |
| `curve?`                   | It will be used to determine the public key encoded in the JWT token which is returned in `getUserInfo` after user sign-in. Private key returned by `getPrivateKey` is always secp256k1. To get the ed25519 key you can use `getEd25519PrivateKey`. The default value is `.SECP256K1`.              |
| `loginHint?`               | Used to specify the user's email address or phone number for email/SMS passwordless sign-in flows. For SMS, the format should be: `+{country_code}-{phone_number}` (for example `+1-1234567890`). It accepts a string value.                                                                        |
| `idToken?`                 | JWT token for SFA (Single Factor Auth) mode. When provided, enables direct authentication without the social sign-in browser flow. It accepts a string value.                                                                                                                                       |

</TabItem>

<TabItem value="struct">

```swift
public struct LoginParams: Codable, Sendable {
    public init(
        authConnection: AuthConnection,
        authConnectionId: String? = nil,
        groupedAuthConnectionId: String? = nil,
        appState: String? = nil,
        mfaLevel: MFALevel? = nil,
        extraLoginOptions: ExtraLoginOptions? = nil,
        dappShare: String? = nil,
        curve: SUPPORTED_KEY_CURVES = .SECP256K1,
        dappUrl: String? = nil,
        loginHint: String? = nil,
        idToken: String? = nil
    )
}

public enum AuthConnection: String, Codable {
    case GOOGLE = "google"
    case FACEBOOK = "facebook"
    case REDDIT = "reddit"
    case DISCORD = "discord"
    case TWITCH = "twitch"
    case APPLE = "apple"
    case LINE = "line"
    case GITHUB = "github"
    case KAKAO = "kakao"
    case LINKEDIN = "linkedin"
    case TWITTER = "twitter"
    case WEIBO = "weibo"
    case WECHAT = "wechat"
    case EMAIL_PASSWORDLESS = "email_passwordless"
    case CUSTOM = "custom"
    case SMS_PASSWORDLESS = "sms_passwordless"
    case FARCASTER = "farcaster"
}
```

</TabItem>
</Tabs>

## Usage

```swift

let web3Auth = try await Web3Auth(
    options: Web3AuthOptions(
        clientId: "YOUR_WEB3AUTH_CLIENT_ID",
        web3AuthNetwork: .SAPPHIRE_MAINNET,
        redirectUrl: "com.yourapp.bundleid://auth"
    )
)

// focus-next-line
let result = try await web3Auth.connectTo(loginParams: LoginParams(authConnection: .GOOGLE))
```

## Examples

<Tabs
  defaultValue="Google"
  values={[
    { label: "Google", value: "Google" },
    { label: "Facebook", value: "Facebook" },
    { label: "Discord", value: "Discord" },
    { label: "Twitch", value: "Twitch" },
    { label: "Email Passwordless", value: "EmailPasswordless" },
    { label: "SMS Passwordless", value: "SmsPasswordless" },
    { label: "Farcaster", value: "Farcaster" },
    { label: "SFA JWT", value: "SfaJwt" },
  ]}
>

<TabItem value="Google">

```swift

let web3Auth = try await Web3Auth(
    options: Web3AuthOptions(
        clientId: "YOUR_WEB3AUTH_CLIENT_ID",
        web3AuthNetwork: .SAPPHIRE_MAINNET,
        redirectUrl: "com.yourapp.bundleid://auth"
    )
)

// focus-next-line
let result = try await web3Auth.connectTo(loginParams: LoginParams(authConnection: .GOOGLE))
```

</TabItem>

<TabItem value="Facebook">

```swift

let web3Auth = try await Web3Auth(
    options: Web3AuthOptions(
        clientId: "YOUR_WEB3AUTH_CLIENT_ID",
        web3AuthNetwork: .SAPPHIRE_MAINNET,
        redirectUrl: "com.yourapp.bundleid://auth"
    )
)

// focus-next-line
let result = try await web3Auth.connectTo(loginParams: LoginParams(authConnection: .FACEBOOK))
```

</TabItem>

<TabItem value="Discord">

```swift

let web3Auth = try await Web3Auth(
    options: Web3AuthOptions(
        clientId: "YOUR_WEB3AUTH_CLIENT_ID",
        web3AuthNetwork: .SAPPHIRE_MAINNET,
        redirectUrl: "com.yourapp.bundleid://auth"
    )
)

// focus-next-line
let result = try await web3Auth.connectTo(loginParams: LoginParams(authConnection: .DISCORD))
```

</TabItem>

<TabItem value="Twitch">

```swift

let web3Auth = try await Web3Auth(
    options: Web3AuthOptions(
        clientId: "YOUR_WEB3AUTH_CLIENT_ID",
        web3AuthNetwork: .SAPPHIRE_MAINNET,
        redirectUrl: "com.yourapp.bundleid://auth"
    )
)

// focus-next-line
let result = try await web3Auth.connectTo(loginParams: LoginParams(authConnection: .TWITCH))
```

</TabItem>

<TabItem value="EmailPasswordless">

```swift

let web3Auth = try await Web3Auth(
    options: Web3AuthOptions(
        clientId: "YOUR_WEB3AUTH_CLIENT_ID",
        web3AuthNetwork: .SAPPHIRE_MAINNET,
        redirectUrl: "com.yourapp.bundleid://auth"
    )
)

// focus-start
let result = try await web3Auth.connectTo(
    loginParams: LoginParams(
        authConnection: .EMAIL_PASSWORDLESS,
        loginHint: "hello@web3auth.io",
        extraLoginOptions: ExtraLoginOptions(
            flow_type: .code // Use .code for OTP flow or .link for magic link flow
        )
    )
)
// focus-end
```

</TabItem>

<TabItem value="SmsPasswordless">

```swift

let web3Auth = try await Web3Auth(
    options: Web3AuthOptions(
        clientId: "YOUR_WEB3AUTH_CLIENT_ID",
        web3AuthNetwork: .SAPPHIRE_MAINNET,
        redirectUrl: "com.yourapp.bundleid://auth"
    )
)

// focus-start
let result = try await web3Auth.connectTo(
    loginParams: LoginParams(
        authConnection: .SMS_PASSWORDLESS,
        // The phone number should be in format of +{country_code}-{phone_number}
        loginHint: "+91-9911223344"
    )
)
// focus-end
```

</TabItem>

<TabItem value="Farcaster">

```swift

let web3Auth = try await Web3Auth(
    options: Web3AuthOptions(
        clientId: "YOUR_WEB3AUTH_CLIENT_ID",
        web3AuthNetwork: .SAPPHIRE_MAINNET,
        redirectUrl: "com.yourapp.bundleid://auth"
    )
)

// focus-next-line
let result = try await web3Auth.connectTo(loginParams: LoginParams(authConnection: .FARCASTER))
```

</TabItem>

<TabItem value="SfaJwt">

For SFA (Single Factor Auth) mode, pass the JWT token via `idToken` to authenticate directly
without any browser-based sign-in flow.
This is useful when you already have a JWT from your own authentication system.

```swift

let web3Auth = try await Web3Auth(
    options: Web3AuthOptions(
        clientId: "YOUR_WEB3AUTH_CLIENT_ID",
        web3AuthNetwork: .SAPPHIRE_MAINNET,
        redirectUrl: "com.yourapp.bundleid://auth"
    )
)

// focus-start
let result = try await web3Auth.connectTo(
    loginParams: LoginParams(
        authConnection: .CUSTOM,
        authConnectionId: "your-auth-connection-id", // Get it from the Embedded Wallets dashboard
        idToken: "your_jwt_token"
    )
)
// focus-end
```

</TabItem>
</Tabs>

---

## Enable MFA

The `enableMFA` method triggers multi-factor authentication (MFA) setup for users, adding an
additional recovery factor to protect wallet access.
It accepts an optional `LoginParams` parameter.

- If you use a default sign-in provider, call `enableMFA()` without arguments.
- If you use a custom JWT auth connection, pass a `LoginParams` object that includes the valid JWT
  token.

## Usage

<Tabs
  defaultValue="default-verifier"
  values={[
    { label: "Default Auth Connection", value: "default-verifier" },
    { label: "Custom JWT Auth Connection", value: "custom-jwt-verifier" },
  ]}
>

<TabItem value = "default-verifier">

```swift
do {
  // focus-next-line
  let isMFAEnabled = try await web3Auth.enableMFA()
} catch {
  print(error.localizedDescription)
  // Handle Error
}
```

</TabItem>

<TabItem value = "custom-jwt-verifier">

:::warning

Single-factor authentication (SFA) mode users (authenticated directly via `idToken`) cannot enable
MFA.
The `enableMFA` call throws an error if the user signed in using a JWT token directly.

:::

```swift
do {
    let loginParams = LoginParams(
        authConnection: .CUSTOM,
        authConnectionId: "your-auth-connection-id",
        idToken: "your_jwt_token"
    )

    // focus-next-line
    let isMFAEnabled = try await web3Auth.enableMFA(loginParams)
} catch {
    print(error.localizedDescription)
    // Handle Error
}
```

</TabItem>
</Tabs>

---

## Get user info

The `getUserInfo` method returns details about the user, including sign-in type, whether
multi-factor authentication (MFA) is enabled, profile image, and name.

This method throws an error if no user session exists.

## Usage

```swift
let web3AuthUserInfo = try web3Auth.getUserInfo()
```

## Example response

```json
{
  "userInfo": {
    "email": "w3a-heroes@web3auth.com",
    "name": "Web3Auth Heroes",
    "profileImage": "https://lh3.googleusercontent.com/a/Ajjjsdsmdjmnm...",
    "authConnectionId": "torus",
    "userId": "w3a-heroes@web3auth.com",
    "authConnection": "google",
    "groupedAuthConnectionId": "w3a-google-sapphire",
    "dappShare": "", // 24 words of seed phrase will be sent only incase of custom auth connections
    "idToken": "<jwtToken issued by Web3Auth>",
    "oAuthIdToken": "<jwtToken issued by OAuth Provider>", // will be sent only incase of custom auth connections
    "oAuthAccessToken": "<accessToken issued by OAuth Provider>", // will be sent only incase of custom auth connections
    "isMfaEnabled": false // Returns whether the user has enabled MFA or not
  }
}
```

---

## Ed25519 Private Key(3)

The `getEd25519PrivateKey` method returns the user's Ed25519 private key.
Use this key to sign transactions on Solana, Near, Algorand, and other chains that use the Ed25519
curve.

This method throws an error if no user session exists or if the key is unavailable.

## Usage

```swift
let ed25519PrivateKey = try web3Auth.getEd25519PrivateKey()
```

---

## Secp256k1 Private Key(3)

The `getPrivateKey` method returns the user's secp256k1 private key (the elliptic curve used by
Ethereum and EVM-compatible chains).
Use this key to sign transactions on EVM-compatible chains.

When you set `useSFAKey` to `true` in `Web3AuthOptions`, this method returns the single-factor
authentication (SFA) key instead of the standard private key.

## Usage

```swift
let privateKey = web3Auth.getPrivateKey()
```

---

## Logout user

To sign out the user and remove the session ID from the device, use the `logout` method. The user must sign in again to use the dapp the next time the dapp is opened.

## Usage

```swift
try await web3Auth.logout()
```

---

## Manage MFA

The `manageMFA` method triggers the multi-factor authentication (MFA) management flow, allowing
users to update their MFA settings.
It accepts an optional `LoginParams` parameter.

- If you use a default sign-in provider, call `manageMFA()` without arguments.
- If you use a custom JWT auth connection, pass a `LoginParams` object that includes the JWT
  token.

## Usage

<Tabs
  defaultValue="default-verifier"
  values={[
    { label: "Default Auth Connection", value: "default-verifier" },
    { label: "Custom JWT Auth Connection", value: "custom-jwt-verifier" },
  ]}
>

<TabItem value = "default-verifier">

```swift
do {
  let response = try await web3Auth.manageMFA()
  if response {
    // Handle success
  } else {
    // Something went wrong
  }
} catch {
  // Handle error
}
```

</TabItem>

<TabItem value="custom-jwt-verifier">

```swift
let loginParams = LoginParams(
    authConnection: .CUSTOM,
    authConnectionId: "<YOUR_AUTH_CONNECTION_ID>",
    idToken: "<YOUR_JWT_TOKEN>"
)

do {
    let response = try await web3Auth.manageMFA(loginParams)
    if response {
        // Handle success
    } else {
        // Something went wrong
    }
} catch {
    // Handle error
}
```

</TabItem>
</Tabs>

---

## Request signature(3)

The `request` method opens built-in transaction screens for signing transactions.
The method returns a `SignResponse?`.
Use it to sign transactions on any EVM chain.
You can white-label the screens to match your branding.

See the list of [JSON-RPC methods](https://docs.metamask.io/wallet/reference/json-rpc-api/).
The `request` method currently supports only signing methods.

The SDK retrieves chain configuration automatically from your project settings in the Embedded
Wallets dashboard.

## Parameters

| Parameter       | Description                                                                                                                                                    |
| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `method`        | JSON RPC method name in `String`. Currently, the request method only supports the signing methods.                                                             |
| `requestParams` | Parameters for the corresponding method, in the correct sequence. See [JSON-RPC methods](https://docs.metamask.io/wallet/reference/json-rpc-api/) for details. |
| `path?`         | Path in the wallet WebView. The default is `"wallet/request"`.                                                                                                 |
| `appState?`     | Optional app state string to be passed through the request flow.                                                                                               |

## Usage

```swift
do {
    var params = [Any]()
    // Message to be signed
    params.append("Hello, Web3Auth from iOS!")
    // User's EOA address
    params.append(address)

    // focus-start
    let response = try await web3Auth.request(
        method: "personal_sign",
        requestParams: params
    )
    // focus-end

    if let response = response {
        if response.success {
            print(response.result!)
        } else {
            // Handle Error
            print(response.error!)
        }
    }
} catch {
    print(error.localizedDescription)
    // Handle error
}
```

## SignResponse

| Name      | Description                                                   |
| --------- | ------------------------------------------------------------- |
| `success` | Whether the request succeeded.                                |
| `result?` | Holds the signature for the request when `success` is `true`. |
| `error?`  | Holds the error for the request when `success` is `false`.    |

---

## Show Wallet UI(3)

The `showWalletUI` method launches a WebView with the built-in wallet UI.
The SDK retrieves chain configuration automatically from your project settings in the Embedded
Wallets dashboard.

:::info

Wallet Services is currently only available for EVM chains.

:::

:::note

Access to Wallet Services is gated.
This feature is free in `sapphire_devnet`.
The minimum [pricing plan](https://web3auth.io/pricing.html) to use this feature in production is
the **Scale Plan**.

:::

![Wallet Services](/img/embedded-wallets/wallet-services/mobile-wallet-services.png)

## Parameters

| Parameter | Description                                                                                                                                              |
| --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `path?`   | Path to navigate to in the wallet UI. The default is `"wallet"`. You can use `"wallet/transactions"`, `"wallet/nfts"`, etc. for specific wallet screens. |

## Usage

```swift
do {
    // focus-next-line
    try await web3Auth.showWalletUI()
} catch {
    print(error.localizedDescription)
    // Handle error
}
```

## Navigate to a specific screen

```swift
do {
    // focus-next-line
    try await web3Auth.showWalletUI(path: "wallet/transactions")
} catch {
    print(error.localizedDescription)
    // Handle error
}
```

---

## Getting started with the Web SDK

:::note[Naming]

Embedded Wallets SDKs were previously known as Web3Auth Plug and Play SDKs. Package names and APIs remain Web3Auth (for example, `@web3auth/modal`).

:::

## Overview

Embedded Wallets provide authentication for web applications with social logins, external wallets, and more. Our JavaScript SDK simplifies how you connect users to their preferred wallets and manage authentication state.

:::info Migration from v9 or v10

Use the [Web SDK v11 migration guide](/embedded-wallets/migration-guides/web). It includes an LLM agent prompt, a full v9/v10-to-v11 API map, and step-by-step changes for `@web3auth/modal` (JavaScript).

:::

## Requirements

- This is a frontend SDK and must be used in a browser environment
- Node.js 22+ and npm 10+
- Basic knowledge of JavaScript

## Prerequisites

- Set up your project on the [Embedded Wallets dashboard](https://developer.metamask.io/)

:::tip

See the [dashboard setup](../../dashboard/README.mdx) guide to learn more.

:::

## Installation

Install the Web3Auth Modal SDK using npm or yarn:

```bash npm2yarn
npm install --save @web3auth/modal
```

### 1. Configuration

Create an instance of Embedded Wallets containing the basic required configuration. This configuration will contain your Embedded Wallets Client ID and network details from the [Embedded Wallets dashboard](https://developer.metamask.io/).

```javascript

const web3auth = new Web3Auth({
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable // Get your Client ID from MetaMask Developer Dashboard
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET, // or WEB3AUTH_NETWORK.SAPPHIRE_DEVNET
})
```

### 2. Initialize Embedded Wallets

Initialize the Web3Auth instance before using any authentication methods:

```javascript
await web3auth.init()
```

## Advanced configuration

The Web3Auth Modal SDK offers a rich set of advanced configuration options:

- **[Smart accounts](./advanced/smart-accounts.mdx):** Configure account abstraction parameters.
- **[Custom authentication](./advanced/custom-authentication.mdx):** Define authentication methods.
- **[Whitelabeling and UI customization](./advanced/whitelabel.mdx):** Personalize the modal's appearance.
- **[Multi-Factor Authentication (MFA)](./advanced/mfa.mdx):** Set up and manage MFA.
- **[Wallet Services](./advanced/wallet-services.mdx):** Integrate additional Wallet Services.

:::tip

See the [advanced configuration](./advanced/README.mdx) section to learn more about each configuration option.

:::

<Tabs
  defaultValue="basic-config"
  values={[
    { label: "Basic Configuration", value: "basic-config" },
    { label: "Advanced Configuration", value: "advanced-config" },
  ]}
>

<TabItem value="basic-config">

```javascript

const web3auth = new Web3Auth({
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET, // or WEB3AUTH_NETWORK.SAPPHIRE_DEVNET
})
```

</TabItem>

<TabItem value="advanced-config">

```javascript

const web3auth = new Web3Auth({
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
  modalConfig: {
    connectors: {
      [WALLET_CONNECTORS.AUTH]: {
        label: 'auth',
        loginMethods: {
          google: {
            name: 'google login',
            // logoDark: "url to your custom logo which will shown in dark mode",
          },
          facebook: {
            name: 'facebook login',
            showOnModal: false, // hides the facebook option
          },
          email_passwordless: {
            name: 'email passwordless login',
            showOnModal: true,
            authConnectionId: 'w3a-email_passwordless-demo',
          },
          sms_passwordless: {
            name: 'sms passwordless login',
            showOnModal: true,
            authConnectionId: 'w3a-sms_passwordless-demo',
          },
        },
        showOnModal: true, // set to false to hide all social login methods
      },
    },
    hideWalletDiscovery: true, // set to true to hide external wallets discovery
  },
  mfaLevel: MFA_LEVELS.MANDATORY,
})
```

</TabItem>

</Tabs>

## Blockchain integration

Web3Auth is blockchain agnostic, enabling integration with any blockchain network. Out of the box, Web3Auth offers robust support for both **Solana** and **Ethereum**, each with dedicated provider methods.

### Solana integration

To interact with Solana networks, use the Solana wallet from the `connection` object after sign-in:

```javascript
await web3auth.connect()
const solanaWallet = web3auth.connection?.solanaWallet ?? null
```

For building and signing transactions, use [`@solana/kit`](https://www.npmjs.com/package/@solana/kit) with the hooks or composables in the React and Vue SDKs, or see [Solana on JavaScript](/embedded-wallets/connect-blockchain/solana/javascript).

### Ethereum integration

For Ethereum integration, use the EIP-1193 provider from `connection` with ethers or viem:

```javascript
await web3auth.connect()
const provider = web3auth.connection?.ethereumProvider ?? null
if (!provider) return

// Use with ethers.js
const ethProvider = new ethers.BrowserProvider(provider)
// OR
// Use with viem
const walletClient = createWalletClient({
  chain: getViewChain(provider),
  transport: custom(provider),
})
```

## Troubleshooting

### JWT errors

When using custom authentication, you may encounter JWT errors:

- [**Invalid JWT verifiers ID field**](/embedded-wallets/troubleshooting/jwt-errors#invalid-jwt-verifiers-id-field)
- [**Failed to verify JWS signature**](/embedded-wallets/troubleshooting/jwt-errors#failed-to-verify-jws-signature)
- [**Duplicate token**](/embedded-wallets/troubleshooting/jwt-errors#duplicate-token)
- [**Expired token**](/embedded-wallets/troubleshooting/jwt-errors#expired-token)
- [**Mismatch JWT validation field**](/embedded-wallets/troubleshooting/jwt-errors#mismatch-jwt-validation-field)

---

## Advanced configuration(4)

The Embedded Wallets SDK provides extensive configuration options that allow you to customize authentication flows, UI appearance, blockchain integrations, and security features to meet your application's specific requirements.

## Configuration structure

When setting up Embedded Wallets, you'll pass in the options to the constructor. This consists of:

```tsx

const web3auth = new Web3Auth({
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID',
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
})

await web3auth.init()
```

### `Web3AuthOptions`

<Tabs
  defaultValue="basic"
  values={[
    { label: "Basic parameters", value: "basic" },
    { label: "Advanced parameters", value: "advanced" },
    { label: "Interface", value: "interface" },
  ]}
>

<TabItem value="basic">

| Parameter                         | Description                                                                                                                                                                              |
| --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `clientId`                        | (Mandatory) Client ID, available from the [Embedded Wallets dashboard](https://developer.metamask.io).                                                                                   |
| `web3AuthNetwork`                 | (Mandatory) Web3Auth network to use for the session and the issued `idToken`. Default is `sapphire_mainnet`.                                                                             |
| `enableLogging?`                  | Setting to true enables logs. Default is false.                                                                                                                                          |
| `sessionTime?`                    | Session Time (in seconds) for `idToken` issued by Web3Auth for server side verification. Default is 7 days (7 \* 86400). Max value can be 30 days (86400 \* 30) and min can be 1 sec (1) |
| `useSFAKey?`                      | Uses Single Factor Auth SDK key with Web3Auth provider. Default is false.                                                                                                                |
| `storageType?`                    | Setting to `local` persists social login session across browser tabs. Default is `local`.                                                                                                |
| `defaultChainId?`                 | Default chain ID to use. Your first chain will be used as default.                                                                                                                       |
| `multiInjectedProviderDiscovery?` | Whether to enable discovery of injected wallets in the browser. Default is true.                                                                                                         |

</TabItem>

<TabItem value="advanced">

| Parameter                   | Description                                                                                                                                                                                 |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `chains?`                   | Optional in-code chain list. By default, chains are fetched from the [dashboard](/embedded-wallets/dashboard/chains-and-networks/). Pass `chains` only for custom RPC, demos, or overrides. |
| `uiConfig?`                 | (Fetched automatically from dashboard) Config for configuring UI display properties.                                                                                                        |
| `modalConfig?`              | Helps you customize the modal UI elements and authentication methods.                                                                                                                       |
| `accountAbstractionConfig?` | (Fetched automatically from Dashboard) Account abstraction config for your chain namespace.                                                                                                 |
| `useAAWithExternalWallet?`  | (Fetched automatically from Dashboard) Whether to use AA with external wallet.                                                                                                              |
| `walletServicesConfig?`     | (Fetched automatically from Dashboard) Configure any parameter related to Wallet Services plugin                                                                                            |
| `ssr?`                      | Whether to enable SSR mode.                                                                                                                                                                 |
| `mfaSettings?`              | MFA settings for the auth connector.                                                                                                                                                        |
| `mfaLevel?`                 | MFA level for the auth connector.                                                                                                                                                           |
| `privateKeyProvider?`       | Private key provider for your chain namespace.                                                                                                                                              |

</TabItem>

<TabItem value="interface">

```tsx
export interface Web3AuthOptions extends IWeb3AuthCoreOptions {
  /**
   * Config for configuring modal ui display properties
   */
  uiConfig?: Omit<UIConfig, 'connectorListener'>
  /**
   * Config for configuring modal ui display properties
   */
  modalConfig?: ConnectorsModalConfig
}

export interface IWeb3AuthCoreOptions {
  /**
   * Client id for web3auth.
   * You can obtain your client id from the web3auth developer dashboard.
   * You can set any random string for this on localhost.
   */
  clientId: string
  /**
   * multiple chain configurations,
   * only provided chains will be used
   */
  chains?: CustomChainConfig[]
  /**
   * default chain Id to use
   */
  defaultChainId?: string
  /**
   * setting to true will enable logs
   *
   * @defaultValue false
   */
  enableLogging?: boolean
  /**
   * setting to "local" will persist social login session across browser tabs.
   *
   * @defaultValue "local"
   */
  storageType?: 'session' | 'local' | 'cookies'
  /**
   * sessionTime (in seconds) for idToken issued by Web3Auth for server side verification.
   * @defaultValue 7 * 86400
   *
   * Note: max value can be 30 days (86400 * 30) and min can be  1 sec (1)
   */
  sessionTime?: number
  /**
   * Web3Auth Network to use for the session.
   */
  web3AuthNetwork: WEB3AUTH_NETWORK_TYPE
  /**
   * Uses core-kit key with web3auth provider
   * @defaultValue false
   */
  useSFAKey?: boolean
  /**
   * Whitelabel options for web3auth
   */
  uiConfig?: UIConfig
  /**
   * Account abstraction config for your chain namespace
   */
  accountAbstractionConfig?: AccountAbstractionMultiChainConfig
  /**
   * Whether to use AA with external wallet
   */
  useAAWithExternalWallet?: boolean
  /**
   * Connectors to use
   */
  connectors?: ConnectorFn[]
  /**
   * Plugins to use
   */
  plugins?: PluginFn[]
  /**
   * Whether to enable multi injected provider discovery
   * @defaultValue true
   */
  multiInjectedProviderDiscovery?: boolean
  /**
   * Wallet services config
   */
  walletServicesConfig?: WalletServicesConfig
  /**
   * Private key provider for xrpl, mpc cases
   */
  privateKeyProvider?: IBaseProvider<string>
  /**
   * Whether to enable SSR mode
   *
   * @defaultValue false
   */
  ssr?: boolean
  /**
   * Build environment for Auth connector
   * @internal
   * @defaultValue BUILD_ENV.PRODUCTION
   */
  authBuildEnv?: BUILD_ENV_TYPE
  /**
   * MFA settings for the auth connector
   */
  mfaSettings?: MfaSettings
  /**
   * MFA level for the auth connector
   */
  mfaLevel?: MfaLevelType
}
```

</TabItem>

</Tabs>

## Session management

Control how long users stay authenticated and how sessions persist.

**Key Configuration Options:**

- `sessionTime` - Session duration in seconds. Controls how long users remain authenticated before
  needing to sign in again.
  - Minimum: 1 second (`1`).
  - Maximum: 30 days (`86400 * 30`).
  - Default: 7 days (`86400 * 7`).
- `storageType` - Storage location for authentication state. Options:
  - `"local"`: Persists across browser tabs and browser restarts (`localStorage`)
  - `"session"`: Persists only in current tab, cleared when tab closes (`sessionStorage`)

```tsx
const web3AuthOptions = {
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,

  // Session configuration
  sessionTime: 86400 * 7, // 7 days (in seconds)
  storageType: 'local', // 'local' (persistent across tabs) or 'session' (single tab only)
}
```

## Multi-Factor Authentication

Add additional security layers to protect user accounts with two-factor authentication. For detailed
configuration options and implementation examples, see the [Multi-Factor Authentication](./mfa.mdx)
section.

**Key Configuration Options:**

- `mfaSettings` - Configure MFA settings for different authentication flows
- `mfaLevel` - Control when users are prompted to set up MFA

## Custom authentication methods

Control the sign-in options presented to your users and how they're displayed in the modal. For
detailed configuration options and implementation examples, see the
[custom authentication](./custom-authentication.mdx) section.

**Key Configuration Options:**

- `modalConfig` - Define which authentication methods are available and customize their appearance

## UI customization

Customize the brand experience by customizing the Web3Auth Modal to match your application's
design. For complete customization options, refer to the
[Whitelabeling and UI Customization](./whitelabel.mdx) section.

**Key Configuration Options:**

- `uiConfig` - Personalize the modal's look and feel with custom colors, logos, themes, and more
- `modalConfig` - Control the visibility and arrangement of authentication options

## Smart accounts (account abstraction)

Improve user experience with gasless transactions and advanced account features. Learn more in the
[smart accounts](./smart-accounts.mdx) documentation.

**Key Configuration Options:**

- `accountAbstractionConfig` - Fine-tune parameters for smart account implementation
- `useAAWithExternalWallet` - Enable account abstraction functionality even when users connect with
  external wallets

## Wallet Services

Extend your application with enhanced wallet functionality. See the
[Wallet Services](./wallet-services.mdx) documentation for complete configuration options.

**Key Configuration Options:**

- `walletServicesConfig` - Integrate additional Wallet Services and features

---

## Custom Authentication(Advanced)

Custom authentication is a way to authenticate users with your custom authentication service. For example, while authenticating with Google, you can use your own Google Client ID to authenticate users directly.

This feature, with MFA turned off, can even make Embedded Wallets invisible to the end user.

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this
SDK in a production environment is the **Growth Plan**. You can use this feature in Web3Auth
Sapphire Devnet network for free.

:::

## Get an Auth Connection ID

:::info prerequisite

To enable this, you need to [create a connection](/embedded-wallets/dashboard/authentication) from the **Authentication** tab of your project from the [Embedded Wallets developer dashboard](https://developer.metamask.io) with your desired configuration.

:::

To configure a connection, you need to provide the particular details of the connection into our Embedded Wallets dashboard. This enables us to map a `authConnectionId` with your connection details. This `authConnectionId` helps us to identify the connection details while initializing the SDK. You can configure multiple connections for the same project, and you can also update the connection details anytime.

:::tip

Learn more about the [auth provider setup](/embedded-wallets/authentication) and the different configurations available for each connection.

:::

## Modal custom authentication

The basic custom authentication is available directly in the modal. You can configure each of the auth providers in the modal to direct to your `authConnectionId`.

:::note

You can only configure implicit sign-in via modal, for JWT-based logins, you need to create your own UI and use the `connectTo` function.

:::

For the modal custom authentication, you need to pass the `modalConfig` object to the `Web3AuthOptions` object within the constructor.

:::tip

Learn more about the `modalConfig` object in the [Whitelabel](whitelabel.mdx) section.

:::

### Usage

<Tabs>
  <TabItem value="Single connections">

```ts

const web3auth = new Web3Auth({
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
  // focus-start
  modalConfig: {
    connectors: {
      [WALLET_CONNECTORS.AUTH]: {
        label: 'auth',
        loginMethods: {
          google: {
            name: 'google login',
            authConnectionId: 'w3a-google-demo',
          },
          facebook: {
            name: 'facebook login',
            authConnectionId: 'w3a-facebook-demo',
          },
          discord: {
            name: 'discord login',
            authConnectionId: 'w3a-discord-demo',
          },
          twitch: {
            name: 'twitch login',
            authConnectionId: 'w3a-twitch-demo',
          },
          twitter: {
            name: 'twitter login',
            // it will hide the twitter option from the Web3Auth modal.
            showOnModal: false,
          },
          email_passwordless: {
            name: 'email passwordless login',
            authConnectionId: 'w3a-email_passwordless-demo',
          },
          sms_passwordless: {
            name: 'sms passwordless login',
            authConnectionId: 'w3a-sms_passwordless-demo',
          },
        },
        // setting it to false will hide all social login methods from modal.
        showOnModal: true,
      },
    },
  },
  // focus-end
})

// Initialize web3auth
await web3auth.init()
```

  </TabItem>
  <TabItem value="Grouped connections">

```ts

const web3auth = new Web3Auth({
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
  // focus-start
  modalConfig: {
    connectors: {
      [WALLET_CONNECTORS.AUTH]: {
        label: 'auth',
        loginMethods: {
          google: {
            name: 'google login',
            authConnectionId: 'w3a-google',
            groupedAuthConnectionId: 'aggregate-sapphire',
          },
          facebook: {
            name: 'facebook login',
            authConnectionId: 'w3a-facebook',
            groupedAuthConnectionId: 'aggregate-sapphire',
          },
          email_passwordless: {
            name: 'email passwordless login',
            authConnectionId: 'w3a-email-passwordless',
            groupedAuthConnectionId: 'aggregate-sapphire',
          },
        },
      },
    },
  },
  // focus-end
})

// Initialize web3auth
await web3auth.init()
```

  </TabItem>
</Tabs>

## Advanced custom authentication

The more advanced custom authentication is available via the `connectTo` function. This allows you to any service you want and tie it to your Web3Auth Integration. **This method allows you to make Web3Auth totally invisible to your end users and have a fully customized experience all across.**

You can utilise this function to enable multiple types of connections like:

- Implicit Sign-in connections
- JWT sign-in connections
- Grouped auth connections

<details>
  <summary>`connectTo` Function Reference</summary>

```ts
connectTo<T extends WALLET_CONNECTOR_TYPE>(
  connector: T,
  params?: LoginParamMap[T]
): Promise<Connection | null>;

export type LoginParamMap = {
    [WALLET_CONNECTORS.AUTH]: Partial<AuthLoginParams>;
    ...
};
```

#### `AuthLoginParams`

<Tabs>
  <TabItem value="Table">

| Parameter                  | Description                                                                                                                          |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `loginHint?`               | Helps pass over the login hint to the auth provider. This is used especially for `email_passwordless` and `sms_passwordless` logins. |
| `idToken?`                 | Pass over the JWT ID token directly to Web3Auth for JWT authentication.                                                              |
| `authConnection?`          | The auth provider to use for login (for example, "google", "facebook").                                                              |
| `authConnectionId?`        | The ID configured in your Embedded Wallets dashboard for the connection.                                                             |
| `groupedAuthConnectionId?` | The grouped Auth Connection ID to be used for login.                                                                                 |
| `extraLoginOptions?`       | Custom OAuth options (for example, login_hint, domain).                                                                              |

  </TabItem>

  <TabItem value="Interface">
    ```tsx
    export type AuthLoginParams = LoginParams & {
      loginHint?: string;
      idToken?: string;
  };
    export type LoginParams = {
  /**
   * Any custom state you wish to pass along. This will be returned to you post redirect.
   * Use this to store data that you want to be available to the dapp after login.
   */
  appState?: string;
  /**
   * The auth connection to be used for login.
   */
  authConnection: AUTH_CONNECTION_TYPE | CUSTOM_AUTH_CONNECTION_TYPE;
  /**
   * The auth connection id to be used for login.
   */
  authConnectionId?: string;
  /**
   * The grouped auth connection id to be used for login.
   */
  groupedAuthConnectionId?: string;
  /**
   * You can set the `mfaLevel` to customize when mfa screen should be shown to user.
   * It currently accepts 4 values:-
   * - `'default'`: Setting mfa level to `default` will present mfa screen to user on every third login.
   * - `'optional'`: Setting mfa level to `default` will present mfa screen to user on every login but user can skip it.
   * - `'mandatory'`: Setting mfa level to `mandatory` will make it mandatory for user to setup mfa after login.
   * - `'none'`: Setting mfa level to `none` will make the user skip the mfa setup screen
   *
   * Defaults to `none`
   * @defaultValue `none`
   */
  mfaLevel?: MfaLevelType;
  /**
   * This option is for internal use only in torus wallet and has no effect
   * on user's login on other dapps.
   *
   * Defaults to false
   * @defaultValue false
   * @internal
   */
  getWalletKey?: boolean;
  /**
   * extraLoginOptions can be used to pass standard OAuth login options to
   * loginProvider.
   *
   * For ex: you will have to pass `login_hint` as user's email and `domain`
   * as your app domain in `extraLoginOptions` while using `email_passwordless`
   * loginProvider
   */
  extraLoginOptions?: ExtraLoginOptions;
  /**
   * Custom Logins can get a dapp share returned to them post successful login.
   * This is useful if the dapps want to use this share to allow users to sign in without repeating the full flow
   * dappShare is a 24 word seed phrase
   */
  dappShare?: string;
  /**
   * This curve will be used to determine the public key encoded in the jwt token which returned in
   * `getUserInfo` function after user login.
   * You can use that public key from jwt token as a unique user identifier in your backend.
   *
   * - `'secp256k1'`: secp256k1 based pub key is added as a wallet public key in jwt token to use.
   * - `'ed25519'`: ed25519 based pub key is added as a wallet public key in jwt token to use.
   *
   * Note: This parameter won't change format of private key returned by auth. Private key returned
   * by auth is always `secp256k1`.
   *
   *
   * @defaultValue secp256k1
   */
  curve?: SUPPORTED_KEY_CURVES_TYPE;
  /**
   * Allows the dapp to set a custom redirect url for the manage mfa flow.
   *
   */
  dappUrl?: string;
};
    ```
  </TabItem>
</Tabs>

#### Auth connection types

```ts
export const AUTH_CONNECTION = {
  GOOGLE: 'google',
  TWITTER: 'twitter',
  FACEBOOK: 'facebook',
  DISCORD: 'discord',
  FARCASTER: 'farcaster',
  APPLE: 'apple',
  GITHUB: 'github',
  REDDIT: 'reddit',
  LINE: 'line',
  KAKAO: 'kakao',
  LINKEDIN: 'linkedin',
  TWITCH: 'twitch',
  TELEGRAM: 'telegram',
  WECHAT: 'wechat',
  EMAIL_PASSWORDLESS: 'email_passwordless',
  SMS_PASSWORDLESS: 'sms_passwordless',
  CUSTOM: 'custom',
}
```

#### Advanced options (`extraLoginOptions`)

For custom integrations (like Auth0, AWS Cognito), you can provide additional options:

<Tabs>
  <TabItem value="Table">

| Parameter               | Description                                                 |
| ----------------------- | ----------------------------------------------------------- |
| `isUserIdCaseSensitive` | Whether the user ID field is case sensitive [Default: true] |
| `domain`                | Auth provider domain (for example, "example.auth0.com")     |
| `client_id`             | Client ID from your auth provider                           |
| `scope`                 | OAuth scopes (for example, "email profile openid")          |
| `response_type`         | Response type for OAuth flow                                |
| `login_hint`            | Pre-fill user identifier                                    |

  </TabItem>
  <TabItem value="Interface">
    ```ts
    export type ExtraLoginOptions = Auth0ClientOptions;

    export interface Auth0ClientOptions extends BaseLoginOptions {
    /**
     * Your Auth0 account domain such as `'example.auth0.com'`,
     * `'example.eu.auth0.com'` or , `'example.mycompany.com'`
     * (when using [custom domains](https://auth0.com/docs/custom-domains))
     */
    domain?: string;
    /**
     * The Client ID found on your Application settings page
     */
    client_id?: string;
    /**
     * The field in jwt token which maps to user id
     */
    userIdField?: string;
    /**
     * Whether the user id field is case sensitive
     * @defaultValue true
     */
    isUserIdCaseSensitive?: boolean;
    id_token?: string;
    access_token?: string;
    /**
     * The route for user info endpoint. This will be padded to domain
     * @defaultValue userinfo
     * */
    user_info_route?: string;
    /**
     * The flow type for email_passwordless login
     */
    flow_type?: EMAIL_FLOW_TYPE;
    }
    ```

  </TabItem>
</Tabs>

</details>

### Implicit logins

Implicit logins are the easiest way to authenticate users with your custom authentication services. Web3Auth currently supports implicit logins for the following providers directly:

- Google
- Facebook
- Discord
- Twitch
- Auth0 (Custom)

In addition to these you can also use any other provider (like Auth0, AWS Cognito, Azure AD) by providing the particular details of their login within the `extraLoginOptions` object within the `connectTo` function.

#### Usage

<Tabs>
  <TabItem value="Google">
```ts
// web3auth instance already initialized
await web3auth.connectTo(WALLET_CONNECTORS.AUTH, {
  authConnection: AUTH_CONNECTION.GOOGLE,
  authConnectionId: "w3a-google-demo",
});
```
  </TabItem>
  <TabItem value="Facebook">
```ts
// web3auth instance already initialized
await web3auth.connectTo(WALLET_CONNECTORS.AUTH, {
  authConnection: AUTH_CONNECTION.FACEBOOK,
  authConnectionId: "w3a-facebook-demo",
});
```
  </TabItem>
  <TabItem value="Discord">
```ts
// web3auth instance already initialized
await web3auth.connectTo(WALLET_CONNECTORS.AUTH, {
  authConnection: AUTH_CONNECTION.DISCORD,
  authConnectionId: "w3a-discord-demo",
});
```
  </TabItem>
  <TabItem value="Twitch">
```ts
// web3auth instance already initialized
await web3auth.connectTo(WALLET_CONNECTORS.AUTH, {
  authConnection: AUTH_CONNECTION.TWITCH,
  authConnectionId: "w3a-twitch-demo",
});
```
  </TabItem>
  <TabItem value="Auth0 Google">
```ts
// web3auth instance already initialized
await web3auth.connectTo(WALLET_CONNECTORS.AUTH, {
  authConnection: AUTH_CONNECTION.CUSTOM,
  authConnectionId: "w3a-auth0-demo",
  extraLoginOptions: {
    connection: "google-oauth2",
  },
});
```
  </TabItem>
  <TabItem value="Auth0 SPA">
```ts
// web3auth instance already initialized
await web3auth.connectTo(WALLET_CONNECTORS.AUTH, {
  authConnection: AUTH_CONNECTION.CUSTOM,
  authConnectionId: "w3a-auth0-demo",
});
```
  </TabItem>
  <TabItem value="AWS Cognito">
```ts
// web3auth instance already initialized
await web3auth.connectTo(WALLET_CONNECTORS.AUTH, {
  authConnection: AUTH_CONNECTION.CUSTOM,
  authConnectionId: "w3a-cognito-demo",
  extraLoginOptions: {
    clientId: import.meta.env['VITE_COGNITO_CLIENT_ID'],
    domain: "https://shahbaz-web3auth.auth.ap-south-1.amazoncognito.com",
    verifierIdField: "email",
    response_type: "token",
    scope: "email profile openid",
  },
});
```
  </TabItem>
</Tabs>

### JWT login

JWT login is a way to authenticate users with your custom authentication services. With this method, Web3Auth just takes into account the `idToken` passed over to the `connectTo` function and uses it to authenticate the user. You can utilise this method with any authentication service that is OAuth 2.0 Compatible.

:::warning

If you have not configured on the dashboard, whether you user ID is case sensitive or not, then you need to pass the `isUserIdCaseSensitive` option to the `extraLoginOptions`.

:::

#### Usage

<Tabs>
  <TabItem value="Google One Tap">

```ts
const loginWithGoogle = async (response: CredentialResponse) => {
  const idToken = response.credential;

  // focus-start
  await web3auth.connectTo(WALLET_CONNECTORS.AUTH, {
    authConnectionId: "w3a-google-demo",
    authConnection: AUTH_CONNECTION.GOOGLE,
    idToken,
    extraLoginOptions: {
      isUserIdCaseSensitive: false,
    },
  });
  // focus-end
};

...

<GoogleLogin
  onSuccess={loginWithGoogle}
  onError={() => {
    console.log("Login Failed");
  }}
  useOneTap
/>
```

  </TabItem>
  <TabItem value="Auth0 JWT login">

```ts
const { getIdTokenClaims, loginWithPopup } = useAuth0()

const loginWithAuth0 = async () => {
  try {
    await loginWithPopup()

    const idToken = (await getIdTokenClaims())?.__raw.toString()
    if (!idToken) {
      throw new Error('No id token found')
    }

    // focus-start
    await web3auth.connectTo(WALLET_CONNECTORS.AUTH, {
      authConnectionId: 'w3a-auth0-demo',
      authConnection: AUTH_CONNECTION.CUSTOM,
      idToken,
      extraLoginOptions: {
        isUserIdCaseSensitive: false,
      },
    })
    // focus-end
  } catch (err) {
    console.error(err)
  }
}
```

</TabItem>
<TabItem value="Firebase JWT login">

```ts
const loginWithFirebaseGithub = async () => {
  try {
    const app = initializeApp(firebaseConfig)
    const auth = getAuth(app)
    const githubProvider = new GithubAuthProvider()

    const result = await signInWithPopup(auth, githubProvider)

    const idToken = await result.user.getIdToken(true)

    // focus-start
    await web3auth.connectTo(WALLET_CONNECTORS.AUTH, {
      authConnectionId: 'w3a-firebase-demo',
      authConnection: AUTH_CONNECTION.CUSTOM,
      idToken,
      extraLoginOptions: {
        isUserIdCaseSensitive: false,
      },
    })
    // focus-end
  } catch (error) {
    console.error('Firebase authentication error:', error)
  }
}
```

</TabItem>
<TabItem value="Custom JWT login">

```ts
const getIdToken = async () => {
  // Get ID Token from server
  const res = await fetch('http://localhost:8080/api/token', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
  })
  const data = await res.json()
  return data?.token
}

const loginWithJWT = async () => {
  try {
    const idToken = await getIdToken()

    // focus-start
    await web3auth.connectTo(WALLET_CONNECTORS.AUTH, {
      authConnection: AUTH_CONNECTION.CUSTOM,
      authConnectionId: 'w3a-node-demo',
      idToken,
      extraLoginOptions: {
        isUserIdCaseSensitive: false,
      },
    })
    // focus-end
  } catch (err) {
    console.error(err)
  }
}
```

  </TabItem>
</Tabs>

### Grouped auth connections

Grouped auth connections allows you to group multiple auth connections together and use them as a single connection. This is useful when you want to authenticate the user with multiple providers and require the same user wallet address to be generated.

For example, you can group Google and email passwordless providers together and use them as a single connection. Now, if your user logs in with Google Auth or even with email passwordless using the same email, they will get the same wallet address.

:::info Prerequisites

You need to configure a grouped connection, by combining your single connections in the Embedded Wallets dashboard before using this feature.

:::

<Tabs>
  <TabItem value="Google [Implicit] + Auth0 [Implicit]">

```ts
const loginWithGoogle = async () => {
  // focus-start
  await web3auth.connectTo(WALLET_CONNECTORS.AUTH, {
    groupedAuthConnectionId: 'aggregate-sapphire',
    authConnectionId: 'w3a-google',
    authConnection: AUTH_CONNECTION.GOOGLE,
  })
  // focus-end
}

const loginWithAuth0Google = async () => {
  // focus-start
  await web3auth.connectTo(WALLET_CONNECTORS.AUTH, {
    groupedAuthConnectionId: 'aggregate-sapphire',
    authConnectionId: 'w3a-a0-google',
    authConnection: AUTH_CONNECTION.CUSTOM,
    extraLoginOptions: {
      connection: 'google-oauth2',
    },
  })
  // focus-end
}

const loginWithAuth0GitHub = async () => {
  // focus-start
  await web3auth.connectTo(WALLET_CONNECTORS.AUTH, {
    groupedAuthConnectionId: 'aggregate-sapphire',
    authConnectionId: 'w3a-a0-github',
    authConnection: AUTH_CONNECTION.CUSTOM,
    extraLoginOptions: {
      connection: 'github',
    },
  })
  // focus-end
}
```

  </TabItem>
  <TabItem value="Google One Tap [JWT] + Auth0 [JWT]">

```ts
const loginWithGoogle = async (response: CredentialResponse) => {
  const idToken = response.credential

  // focus-start
  await web3auth.connectTo(WALLET_CONNECTORS.AUTH, {
    groupedAuthConnectionId: 'aggregate-sapphire',
    authConnectionId: 'w3a-google',
    authConnection: AUTH_CONNECTION.GOOGLE,
    idToken,
    extraLoginOptions: {
      isUserIdCaseSensitive: false,
      verifierIdField: 'email',
    },
  })
  // focus-end
}

const loginWithAuth0 = async () => {
  try {
    await loginWithPopup()
    const idToken = (await getIdTokenClaims())?.__raw.toString()
    if (!idToken) {
      throw new Error('No id token found')
    }

    // focus-start
    await web3auth.connectTo(WALLET_CONNECTORS.AUTH, {
      groupedAuthConnectionId: 'aggregate-sapphire',
      authConnectionId: 'w3a-a0-github',
      authConnection: AUTH_CONNECTION.CUSTOM,
      idToken,
      extraLoginOptions: {
        isUserIdCaseSensitive: false,
        verifierIdField: 'email',
      },
    })
    // focus-end
  } catch (err) {
    console.error(err)
  }
}
```

</TabItem>
<TabItem value="Google [Implicit] + Firebase [JWT]">

```ts
const loginWithGoogle = async () => {
  // focus-start
  await web3auth.connectTo(WALLET_CONNECTORS.AUTH, {
    groupedAuthConnectionId: 'aggregate-sapphire',
    authConnectionId: 'w3a-google',
    authConnection: AUTH_CONNECTION.GOOGLE,
  })
  // focus-end
}

const loginWithFirebaseGithub = async () => {
  const app = initializeApp(firebaseConfig)
  const auth = getAuth(app)
  const githubProvider = new GithubAuthProvider()

  const result = await signInWithPopup(auth, githubProvider)

  const idToken = await result.user.getIdToken(true)

  // focus-start
  await web3auth.connectTo(WALLET_CONNECTORS.AUTH, {
    groupedAuthConnectionId: 'aggregate-sapphire',
    authConnectionId: 'w3a-firebase',
    authConnection: AUTH_CONNECTION.CUSTOM,
    idToken,
    extraLoginOptions: {
      isUserIdCaseSensitive: false,
    },
  })
  // focus-end
}
```

</TabItem>
</Tabs>

---

## Multi-factor authentication(3)

Web3Auth supports Multi-Factor Authentication (MFA) for enhanced security. MFA requires two or more factors, such as device, social, seed phrase, or password, to access your account and recover it if needed. When a recovery factor is set up, MFA is enabled and your key is split into three shares, using Web3Auth MPC for secure, self-custodial storage.

:::caution

If you are using default verifiers, your users may have set up MFA on other dapps that also use default Web3Auth verifiers. In this case, the MFA screen will continue to appear if the user has enabled MFA on other dapps. This is because MFA cannot be turned off once it is enabled.

:::

## Multi-Factor Authentication configuration options

There are two ways to configure MFA in your application:

1. **Using the `mfaLevel` setting:** Controls the frequency of the MFA setup request screen.
2. **Using the `mfaSettings` setting:** Provides granular control over each factor, with their priority level, enable/disable status, and mandatory/optional settings.

## `mfaLevel`

The `mfaLevel` setting allows you to control when and how the MFA setup screen appears to users.

```tsx
mfaLevel?: MfaLevelType;
```

### Multi-Factor Authentication level types

| Level       | Value       | Description                                        |
| ----------- | ----------- | -------------------------------------------------- |
| `DEFAULT`   | "default"   | MFA screen appears every 10th login                |
| `OPTIONAL`  | "optional"  | MFA screen appears every login, but can be skipped |
| `MANDATORY` | "mandatory" | MFA setup is required after login                  |
| `NONE`      | "none"      | MFA setup is skipped entirely                      |

### Type definition

```tsx
export type MfaLevelType = (typeof MFA_LEVELS)[keyof typeof MFA_LEVELS]
export declare const MFA_LEVELS: {
  readonly DEFAULT: 'default'
  readonly OPTIONAL: 'optional'
  readonly MANDATORY: 'mandatory'
  readonly NONE: 'none'
}
```

### Usage

```ts

await web3auth.connectTo(WALLET_CONNECTORS.AUTH, {
  authConnection: AUTH_CONNECTION.GOOGLE,
  authConnectionId: 'w3a-google-demo',
  // focus-next-line
  mfaLevel: MFA_LEVELS.MANDATORY,
})
```

## `mfaSettings`

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this SDK in a production environment is the **Scale Plan**. You can use this feature in Web3Auth Sapphire Devnet network for free.

:::

The `mfaSettings` option provides granular control over each individual MFA factor.

```tsx
mfaSettings?: MfaSettings;
```

### Multi-Factor Authentication factors

| Factor          | Key                   | Description                           |
| --------------- | --------------------- | ------------------------------------- |
| `DEVICE`        | "deviceShareFactor"   | Device-based authentication.          |
| `BACKUP_SHARE`  | "backUpShareFactor"   | Backup share (typically seed phrase). |
| `SOCIAL_BACKUP` | "socialBackupFactor"  | Social account backup.                |
| `PASSWORD`      | "passwordFactor"      | Password-based authentication.        |
| `AUTHENTICATOR` | "authenticatorFactor" | Authenticator app (TOTP).             |

### Multi-Factor Authentication settings properties

| Property    | Type    | Description                                             |
| ----------- | ------- | ------------------------------------------------------- |
| `enable`    | boolean | Whether this factor is enabled.                         |
| `priority`  | number  | Order in which factors are presented (lower = earlier). |
| `mandatory` | boolean | Whether this factor is required.                        |

### Type definitions

```tsx
export type MfaSettings = Partial<Record<MFA_FACTOR_TYPE, MFA_SETTINGS>>
export type MFA_FACTOR_TYPE = (typeof MFA_FACTOR)[keyof typeof MFA_FACTOR]
export declare const MFA_FACTOR: {
  readonly DEVICE: 'deviceShareFactor'
  readonly BACKUP_SHARE: 'backUpShareFactor'
  readonly SOCIAL_BACKUP: 'socialBackupFactor'
  readonly PASSWORD: 'passwordFactor'
  readonly PASSKEYS: 'passkeysFactor'
  readonly AUTHENTICATOR: 'authenticatorFactor'
}
export type MFA_SETTINGS = {
  enable: boolean
  priority?: number
  mandatory?: boolean
}
```

### Important rules

- At least two factors must be enabled when setting up MFA.
- If you set `mandatory: true` for all factors, the user must set up all enabled factors.
- If you set `mandatory: false` for all factors, the user can skip setting up MFA, but at least two factors are still required.
- If you set `mandatory: true` for some factors and `mandatory: false` for others, the user must set up the mandatory factors and can optionally set up the others.
- The `priority` field determines the order of setup - lower priority values appear first.

### Usage

```ts

const web3auth = new Web3Auth({
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
  // focus-start
  mfaSettings: {
    [MFA_FACTOR.DEVICE]: {
      enable: true,
      priority: 1,
      mandatory: true, // at least two factors are mandatory
    },
    [MFA_FACTOR.BACKUP_SHARE]: {
      enable: true,
      priority: 2,
      mandatory: true, // at least two factors are mandatory
    },
    [MFA_FACTOR.SOCIAL_BACKUP]: {
      enable: true,
      priority: 3,
      mandatory: false,
    },
    [MFA_FACTOR.PASSWORD]: {
      enable: true,
      priority: 4,
      mandatory: false,
    },
    [MFA_FACTOR.PASSKEYS]: {
      enable: true,
      priority: 5,
      mandatory: false,
    },
    [MFA_FACTOR.AUTHENTICATOR]: {
      enable: true,
      priority: 6,
      mandatory: false,
    },
  },
  // focus-end
})

// Initialize web3auth
await web3auth.init()
```

---

## Smart accounts(Advanced)

Create and manage smart accounts for your users with just a few lines of code, using our Smart Account feature. Smart accounts offer enhanced control and programmability, enabling features that traditional wallets can't provide.

**Key features of smart accounts include:**

- **Gas abstraction:** Cover transaction fees for users, or allow users to pay for their own transactions using ERC-20 tokens.
- **Batch transactions:** Perform multiple transactions in a single call.
- **Automated transactions:** Allow users to automate actions, like swapping ETH to USDT when ETH hits a specific price.
- **Custom spending limits:** Allow users to set tailored spending limits.

:::tip

For more about ERC-4337 and its components, [check out our detailed blog post](https://blog.web3auth.io/an-ultimate-guide-to-web3-wallets-externally-owned-account-and-smart-contract-wallet/#introduction-to-eip-4337).

:::

Our smart account integration streamlines your setup, allowing you to create and manage smart accounts using your favorite libraries like Viem and Ethers. You don't need to rely on third-party packages to effortlessly create ERC-4337 compatible Smart Contract Wallets (SCWs), giving users the ability to perform batch transactions and efficiently manage gas sponsorship.

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this
SDK in a production environment is the **Growth Plan**. You can use this feature in Web3Auth
Sapphire Devnet network for free.

:::

## Enabling smart accounts

:::info prerequisite

To enable this feature, you need to configure smart accounts from your project in the [Embedded Wallets dashboard](https://developer.metamask.io/).

:::

### Dashboard configuration

To enable smart accounts, navigate to the smart accounts section in the [Embedded Wallets dashboard](https://developer.metamask.io/), and enable the **Set up Smart accounts** toggle. Embedded Wallets currently supports [MetaMaskSmartAccount](https://docs.gator.metamask.io/how-to/create-delegator-account#create-a-metamasksmartaccount) as a Smart Account provider.

#### Wallet configuration

Once smart accounts are enabled, you can customize the wallet configurations:

- **All supported wallets (default):** Allows users to create smart accounts using both embedded and external wallets.
- **Embedded wallets only:** Restricts Smart Account creation to embedded wallets.

#### Configure bundler and paymaster

A bundler aggregates UserOperations and submits them onchain via the global EntryPoint contract. To configure the bundler:

1. Navigate to the **Bundler & Paymaster** tab within the **Smart accounts** section.
2. Add the bundler URL for each supported chain.
3. Add the paymaster URL for each supported chain.

:::info

Currently, the sponsored paymaster can only be configured via the dashboard. For ERC-20 paymaster, refer to the SDK Configuration section below.

:::

### Optional: SDK configuration

While the dashboard provides a convenient way to configure smart accounts, the SDK offers greater flexibility by allowing you to override these settings.

### Basic configuration

To enable smart accounts in your application, add the `accountAbstractionConfig` to your Web3Auth options:

```ts

const web3AuthOptions: Web3AuthOptions = {
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_DEVNET,
  // focus-start
  accountAbstractionConfig: {
    smartAccountType: 'metamask',
    chains: [
      {
        chainId: '0x1',
        bundlerConfig: {
          url: 'YOUR_BUNDLER_URL',
        },
      },
    ],
  },
  // focus-end
}
```

### Advanced configuration: Override paymaster context

You can override the paymaster context defined in the dashboard for specific chains. This is particularly useful when your paymaster requires custom settings or parameters.

```ts

const web3AuthOptions: Web3AuthOptions = {
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_DEVNET,
  // focus-start
  accountAbstractionConfig: {
    smartAccountType: 'metamask',
    chains: [
      {
        chainId: '0x1',
        bundlerConfig: {
          url: 'YOUR_BUNDLER_URL',
          // This is just an example of how you can configure the paymaster context.
          // Please refer to the documentation of the paymaster you are using
          // to understand the required parameters.
          paymasterContext: {
            token: 'SUPPORTED_TOKEN_CONTRACT_ADDRESS',
            sponsorshipPolicyId: 'sp_my_policy_id',
          },
        },
      },
    ],
  },
  // focus-end
}
```

:::info

The paymaster context must be manually configured for each chain that needs to be supported.

:::

## Using smart accounts

### Configure signer

The Web3Auth Smart Account feature is compatible with popular signer SDKs, including Wagmi, ethers,
and viem. You can choose your preferred package to configure the signer.

<!-- vale off -->

<Tabs
  defaultValue="wagmi"
  values={[
    { label: "Wagmi (recommended)", value: "wagmi" },
    { label: "Viem", value: "viem" },
    { label: "Ethers", value: "ethers" },
  ]}
>

<TabItem value="wagmi">

Use Wagmi with `@web3auth/modal/react/wagmi` or `@web3auth/modal/vue/wagmi`. After sign-in, Wagmi
hooks (`useConnection`, `useSendTransaction`, and similar) use the smart account signer automatically.
No manual `connection.ethereumProvider` wiring is required.

```tsx

const { address } = useConnection()
// useSendTransaction, useWriteContract, etc. work with the smart account
```

</TabItem>

<TabItem value="viem">

For vanilla JavaScript or apps without Wagmi, read the EIP-1193 provider from `connection`:

```tsx

const connection = web3auth.connection
const provider = connection?.ethereumProvider ?? null

const walletClient = createWalletClient({
  transport: custom(provider),
})
```

</TabItem>

<TabItem value="ethers">

```tsx

const connection = web3auth.connection
const provider = connection?.ethereumProvider ?? null

const ethersProvider = new ethers.BrowserProvider(provider)
const signer = await ethersProvider.getSigner()
```

</TabItem>
</Tabs>
<!-- vale on -->

### Get smart account address

Once the signers or Wagmi configuration is set up, it can be used to retrieve the user's Smart
Account address.

<Tabs
  defaultValue="viem"
  values={[
    { label: "Viem", value: "viem" },
    { label: "Ethers", value: "ethers" },
    { label: "Wagmi", value: "Wagmi" },
  ]}
>

<TabItem value="viem">

```tsx
// Use walletClient instance from previous step
const addresses = await walletClient.getAddresses()

const smartAccountAddress = addresses[0]
const eoaAddress = addresses[1]
```

</TabItem>

<TabItem value="ethers">

```tsx
// User signer from previous step
const smartAccountAddress = signer.getAddress()
```

</TabItem>

<TabItem value="Wagmi">
```tsx

const { address } = useConnection()
const smartAccountAddress = address

```

</TabItem>
</Tabs>
```

### Send transaction

Developers can use their preferred signer or Wagmi hooks to initiate onchain transactions, while
Web3Auth manages the creation and submission of the UserOperation. Only the `to`, `data`, and
`value` fields need to be provided. Any additional parameters will be ignored and automatically
overridden.

To ensure reliable execution, the bundler client sets maxFeePerGas and maxPriorityFeePerGas values.
If custom values are required, developers can use the
[Viem's BundlerClient](https://viem.sh/account-abstraction/clients/bundler#bundler-client) to
manually construct and send the user operation.

Since Smart Accounts are deployed smart contracts, the user's first transaction also triggers the
onchain deployment of their wallet.

<Tabs
  defaultValue="viem"
  values={[
    { label: "Viem", value: "viem" },
    { label: "Ethers", value: "ethers" },
    { label: "Wagmi", value: "wagmi" },
  ]}
>

<TabItem value="wagmi">

```tsx

const { data: hash, sendTransaction } = useSendTransaction()

// Convert 1 ether to WEI format
const value = web3.utils.toWei(1)

sendTransaction({ to: 'DESTINATION_ADDRESS', value, data: '0x' })

const {
  data: receipt,
  isLoading: isConfirming,
  isSuccess: isConfirmed,
} = useWaitForTransactionReceipt({
  hash,
})
```

</TabItem>
<TabItem value="ethers">

```tsx
// Convert 1 ether to WEI format
const amount = ethers.parseEther('1.0')

// Submits a user operation to the blockchain
const transaction = await signer.sendTransaction({
  to: 'DESTINATION_ADDRESS',
  value: amount,
  // This will perform the transfer of ETH
  data: '0x',
})

// Wait for the transaction to be mined
const receipt = await transaction.wait()
```

</TabItem>
<TabItem value="viem">

```tsx
// Convert 1 ether to WEI format
const amount = parseEther('1')

// Submits a user operation to the blockchain
const hash = await walletClient.sendTransaction({
  to: 'DESTINATION_ADDRESS',
  value: amount,
  // This will perform the transfer of ETH
  data: '0x',
})

// Wait for the transaction to be mined
const receipt = await publicClient.waitForTransactionReceipt({ hash })
```

</TabItem>
</Tabs>

### Sign transaction

You can sign a transaction without immediately sending it. For the user's first transaction, the `UserOperation` calldata will automatically include the deployment data needed to create the Smart Account onchain.

<Tabs
  defaultValue="viem"
  values={[
    { label: "Viem", value: "viem" },
    { label: "Ethers", value: "ethers" },
  ]}
>

<TabItem value="ethers">

```ts
// Convert 1 ether to WEI format
const amount = parseEther('1')

const signature = await signer.signTransaction({
  to: 'DESTINATION_ADDRESS',
  value: amount,
})
```

</TabItem>
<TabItem value="viem">

```ts
// Convert 1 ether to WEI format
const amount = parseEther('1')
const addresses = await walletClient.getAddresses()

const request = await walletClient.prepareTransactionRequest({
  account: addresses[0],
  to: 'DESTINATION_ADDRESS',
  value: amount,
})

const signature = await walletClient.signTransaction(request as any)
```

</TabItem>
</Tabs>

### Sign message

Smart accounts support message signing following the EIP-1271 standard for signature verification, using the `isValidSignature` method defined in the smart contract wallet instead of the `ecrecover` function used by EOAs.

<Tabs
  defaultValue="viem"
  values={[
    { label: "Viem", value: "viem" },
    { label: "Ethers", value: "ethers" },
  ]}
>

<TabItem value="ethers">

```ts
const originalMessage = 'YOUR_MESSAGE'

// Sign the message
const signedMessage = await signer.signMessage(originalMessage)
```

</TabItem>
<TabItem value="viem">

```ts
const originalMessage = 'YOUR_MESSAGE'

const addresses = await walletClient.getAddresses()

const signedMessage = await walletClient.signMessage({
  account: addresses[0],
  message: originalMessage,
})
```

</TabItem>
</Tabs>

### Send batch transaction

One of the key advantages of smart accounts is the ability to execute multiple operations in a single transaction. For example, instead of requiring separate transactions for token approval and then swapping, both operations can be combined into a single UserOperation.

To perform batch transactions, you must use the `BundlerClient` provided by Web3Auth:

```ts
// Use your Web3Auth instance
const accountAbstractionProvider = web3auth.accountAbstractionProvider
// Use the same accountAbstractionProvider we created earlier.
const bundlerClient = accountAbstractionProvider.bundlerClient!
const smartAccount = accountAbstractionProvider.smartAccount!

// 0.00001 ETH in WEI format
const amount = 10000000000000n

const userOpHash = await bundlerClient.sendUserOperation({
  account: smartAccount,
  calls: [
    {
      to: 'DESTINATION_ADDRESS',
      value: amount,
      data: '0x',
    },
    {
      to: 'DESTINATION_ADDRESS',
      value: amount,
      data: '0x',
    },
  ],
})

// Retrieve user operation receipt
const receipt = await bundlerClient.waitForUserOperationReceipt({
  hash: userOpHash,
})

const transactionHash = receipt.receipt.transactionHash
```

:::info

When calling `sendUserOperation`, it returns a UserOperation hash, not the transaction hash. To get the final transaction details, use `waitForUserOperationReceipt`.

:::

### Send transaction using ERC-20 paymaster

You can use ERC-20 tokens to pay for transaction fees instead of the native token (for example, ETH). This requires approving the token for use by the paymaster:

```ts
// Use your Web3Auth instance
const accountAbstractionProvider = web3auth.accountAbstractionProvider

// Use the same accountAbstractionProvider we created earlier.
const bundlerClient = accountAbstractionProvider.bundlerClient!
const smartAccount = accountAbstractionProvider.smartAccount!

// Pimlico's ERC-20 paymaster address
const pimlicoPaymasterAddress = '0x0000000000000039cd5e8aE05257CE51C473ddd1'

// USDC address on Ethereum Sepolia
const usdcAddress = '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238'

// 0.00001 ETH in WEI format
const amount = 10000000000000n

// 10 USDC in WEI format. Since USDC has 6 decimals, 10 * 10^6
const approvalAmount = 10000000n

const userOpHash = await bundlerClient.sendUserOperation({
  account: smartAccount,
  calls: [
    // Approve USDC on Sepolia chain for Pimlico's ERC 20 Paymaster
    {
      to: usdcAddress,
      abi: parseAbi(['function approve(address,uint)']),
      functionName: 'approve',
      args: [pimlicoPaymasterAddress, approvalAmount],
    },
    {
      to: 'DESTINATION_ADDRESS',
      value: amount,
      data: '0x',
    },
    {
      to: 'DESTINATION_ADDRESS',
      value: amount,
      data: '0x',
    },
  ],
})

// Retrieve user operation receipt
const receipt = await bundlerClient.waitForUserOperationReceipt({
  hash: userOpHash,
})

const transactionHash = receipt.receipt.transactionHash
```

## EIP-7702 smart accounts {#eip-7702-smart-accounts}

:::note Web SDK only

EIP-7702 support ships in **Web SDK v11** (`@web3auth/modal` for JavaScript, React, and Vue).

:::

EIP-7702 (Set Code for EOAs) lets users keep their existing EOA address while temporarily delegating execution to a smart account implementation for a single transaction.
This bridges EOA simplicity and account-abstraction capability without forcing users onto a separate smart account address.

### When to use EIP-7702 vs ERC-4337

| Approach                | Address                                 | Best for                                                        |
| ----------------------- | --------------------------------------- | --------------------------------------------------------------- |
| ERC-4337 smart accounts | New smart account address (`aaAddress`) | Full account-abstraction lifecycle with bundlers and paymasters |
| EIP-7702                | Same EOA address                        | One-off or session-scoped AA features without address migration |

### Dashboard configuration

Enable smart accounts in the [Embedded Wallets dashboard](https://developer.metamask.io/) and select an EIP-7702-compatible provider.
The SDK currently lists MetaMask as an EIP-7702-supported smart account provider.

:::caution review

Confirm the exact dashboard toggle and `eipStandard` values for EIP-7702 in your project settings before publishing.

:::

### SDK configuration

When overriding smart account settings in code, set `eipStandard` on `accountAbstractionConfig`:

```ts

const web3AuthOptions: Web3AuthOptions = {
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID',
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_DEVNET,
  accountAbstractionConfig: {
    smartAccountType: 'metamask',
    eipStandard: '7702',
    chains: [
      {
        chainId: '0x1',
        bundlerConfig: {
          url: 'YOUR_BUNDLER_URL',
        },
      },
    ],
  },
}
```

:::caution review

Verify the accepted `eipStandard` enum values against your installed `@web3auth/modal` version.
Use the SDK release notes if the value above fails at build time.

:::

### Capabilities unlocked by EIP-7702

- **Gas sponsorship:** Cover transaction fees through a paymaster without changing the user's address.
- **Batch transactions:** Combine multiple calls in one authorization.
- **Session keys:** Approve scoped permissions for multi-step flows with a single signature.

For ERC-4337-specific flows (UserOperations, bundler clients), use the sections above.
For a conceptual overview, see [Native smart accounts](/embedded-wallets/features/smart-accounts/).

---

## Wallet Services

Embedded Wallets' Wallet Services provides a comprehensive suite of wallet functionality including fiat-on-ramp, swaps, and wallet UI Interoperability with WalletConnect. These services enhance your application by offering a complete wallet experience without building these features from scratch.

:::tip

All these configurations can be directly accessed and managed through the [Embedded Wallets dashboard](https://developer.metamask.io). Manual configuration in the SDK is optional and provided here for reference purposes.

:::

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this
SDK in a production environment is the **Growth Plan**. You can use this feature in Web3Auth
Sapphire Devnet network for free.

:::

## `walletServicesConfig`

The `walletServicesConfig` option allows you to customize the Wallet Services experience for your users.

```tsx
walletServicesConfig?: WalletServicesConfig;
```

### Configuration options

<Tabs>
  <TabItem value="Table">

| Property               | Type                       | Description                                      |
| ---------------------- | -------------------------- | ------------------------------------------------ |
| `confirmationStrategy` | CONFIRMATION_STRATEGY_TYPE | How to display confirmation screens.             |
| `modalZIndex`          | number                     | Z-index for modal windows.                       |
| `enableKeyExport`      | boolean                    | Enable private key export functionality.         |
| `whiteLabel`           | Object                     | Customization options for the widget appearance. |

#### Confirmation strategy options

| Strategy       | Description                                                     |
| -------------- | --------------------------------------------------------------- |
| `default`      | Uses auto-approve by default, modal for WalletConnect requests. |
| `modal`        | Always uses modal for confirmations.                            |
| `auto-approve` | Automatically approves transactions without confirmation.       |

#### Whitelabel options

| Property            | Type                 | Description                                |
| ------------------- | -------------------- | ------------------------------------------ |
| `showWidgetButton`  | boolean              | Whether to show the widget button.         |
| `buttonPosition`    | BUTTON_POSITION_TYPE | Position of the widget button on the page. |
| `hideNftDisplay`    | boolean              | Hide NFT display in the wallet.            |
| `hideTokenDisplay`  | boolean              | Hide token display in the wallet.          |
| `hideTransfers`     | boolean              | Hide transfer functionality.               |
| `hideTopup`         | boolean              | Hide top-up (fiat on-ramp) functionality.  |
| `hideReceive`       | boolean              | Hide receive address functionality.        |
| `hideSwap`          | boolean              | Hide token swap functionality.             |
| `hideShowAllTokens` | boolean              | Hide the "show all tokens" option.         |
| `hideWalletConnect` | boolean              | Hide WalletConnect integration.            |
| `defaultPortfolio`  | "token" \| "nft"     | Default portfolio view.                    |

#### Button position options

| Position       | Description                      |
| -------------- | -------------------------------- |
| `bottom-left`  | Bottom left corner of the page.  |
| `top-left`     | Top left corner of the page.     |
| `bottom-right` | Bottom right corner of the page. |
| `top-right`    | Top right corner of the page.    |

  </TabItem>

  <TabItem value="Interface">

```tsx
export type WalletServicesConfig = Omit<
  WsEmbedParams,
  | 'buildEnv'
  | 'enableLogging'
  | 'chainId'
  | 'chains'
  | 'confirmationStrategy'
  | 'accountAbstractionConfig'
> & {
  /**
   * Determines how to show confirmation screens
   * @defaultValue default
   *
   * default & auto-approve
   * - use auto-approve as default
   * - if wallet connect request use modal
   *
   * modal
   * - use modal always
   */
  confirmationStrategy?: Exclude<WsEmbedParams['confirmationStrategy'], 'popup'>
  modalZIndex?: number
}

export interface WsEmbedParams {
  /**
   * Supported chains
   */
  chains: ProviderConfig[]
  /**
   * Chain to connect with
   */
  chainId: string
  /**
   * Build Environment of WsEmbed.
   *
   * production uses https://wallet.web3auth.io,
   *
   * staging uses https://staging-wallet.web3auth.io,
   *
   * testing uses https://develop-wallet.web3auth.io (latest internal build)
   *
   * development uses http://localhost:4050 (expects wallet-services-frontend to be run locally),
   *
   * @defaultValue production
   */
  buildEnv?: WS_EMBED_BUILD_ENV_TYPE
  /**
   * Enables or disables logging.
   *
   * Defaults to false in prod and true in other environments
   */
  enableLogging?: boolean
  /**
   * url of widget to load
   *
   * Defaults to true
   * @defaultValue true
   */
  walletUrls?: Partial<Record<WS_EMBED_BUILD_ENV_TYPE, WalletUrlConfig>>
  /**
   * Determines how to show confirmation screens
   * @defaultValue default
   *
   * default & popup
   * - use popop as default
   * - if wallet connect request use modal
   *
   * modal
   * - use modal always
   *
   * auto-approve
   * - does not work on embed. will use default
   */
  confirmationStrategy?: CONFIRMATION_STRATEGY_TYPE
  /**
   * Enable and configure account abstraction
   */
  accountAbstractionConfig?: AccountAbstractionMultiChainConfig
  /**
   * Enable private key export
   *
   * Defaults to false
   * @defaultValue false
   */
  enableKeyExport?: boolean
  /**
   * Allows you to customize the look & feel of the widget
   */
  whiteLabel?: {
    /**
     * whether to show/hide ws-embed widget.
     *
     * Defaults to true
     * @defaultValue true
     */
    showWidgetButton?: boolean
    /**
     * Determines where the wsEmbed widget is visible on the page.
     * @defaultValue bottom-left
     */
    buttonPosition?: BUTTON_POSITION_TYPE
    hideNftDisplay?: boolean
    hideTokenDisplay?: boolean
    hideTransfers?: boolean
    hideTopup?: boolean
    hideReceive?: boolean
    hideSwap?: boolean
    hideShowAllTokens?: boolean
    hideWalletConnect?: boolean
    defaultPortfolio?: 'token' | 'nft'
  } & WhiteLabelData
}

export declare const CONFIRMATION_STRATEGY: {
  readonly POPUP: 'popup'
  readonly MODAL: 'modal'
  readonly AUTO_APPROVE: 'auto-approve'
  readonly DEFAULT: 'default'
}
export type CONFIRMATION_STRATEGY_TYPE =
  (typeof CONFIRMATION_STRATEGY)[keyof typeof CONFIRMATION_STRATEGY]

export type AccountAbstractionMultiChainConfig = {
  smartAccountType?: SmartAccountType
  chains?: {
    chainId: string
    bundlerConfig: BundlerConfig
    paymasterConfig?: PaymasterConfig
    smartAccountConfig?: SmartAccountConfig
  }[]
}

export declare const BUTTON_POSITION: {
  readonly BOTTOM_LEFT: 'bottom-left'
  readonly TOP_LEFT: 'top-left'
  readonly BOTTOM_RIGHT: 'bottom-right'
  readonly TOP_RIGHT: 'top-right'
}
export type BUTTON_POSITION_TYPE = (typeof BUTTON_POSITION)[keyof typeof BUTTON_POSITION]
```

  </TabItem>
</Tabs>

## Usage

```ts

const web3auth = new Web3Auth({
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
  // focus-start
  walletServicesConfig: {
    confirmationStrategy: CONFIRMATION_STRATEGY.MODAL,
    modalZIndex: 99999,
    enableKeyExport: false,
    whiteLabel: {
      showWidgetButton: true,
      buttonPosition: BUTTON_POSITION.BOTTOM_RIGHT,
      hideNftDisplay: false,
      hideTokenDisplay: false,
      hideTransfers: false,
      hideTopup: false,
      hideReceive: false,
      hideSwap: false,
      hideShowAllTokens: false,
      hideWalletConnect: false,
      defaultPortfolio: 'token',
    },
  },
  // focus-end
})

// Initialize web3auth
await web3auth.init()
```

---

## Whitelabel(3)

Web3Auth allows complete whitelabeling with application branding for a consistent user experience. You can customize three different aspects:

- **UI elements:** Customize the appearance of modals and components
- **Branding:** Apply your brand colors, logos, and themes
- **Translations:** Localize the interface for your users

:::info

All of these settings can be easily managed directly from the Embedded Wallets dashboard. Once you update your branding, or UI preferences there, the changes will automatically apply to your integration.

:::

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this
SDK in a production environment is the **Growth Plan**. You can use this feature in Web3Auth
Sapphire Devnet network for free.

:::

## Customizing the Web3Auth Modal

While basic modal appearance can be configured directly on the dashboard, the following advanced options provide even greater control through the `modalConfig` property.

### `modalConfig`

The `modalConfig` option in the constructor lets you configure the modal UI and customize authentication:

```ts
modalConfig?: ConnectorsModalConfig;

export interface ConnectorsModalConfig {
    connectors?: Partial<Record<WALLET_CONNECTOR_TYPE, ModalConfig>>;
    hideWalletDiscovery?: boolean;
}

export type WALLET_CONNECTOR_TYPE = (typeof WALLET_CONNECTORS)[keyof typeof WALLET_CONNECTORS];

export interface ModalConfig extends Omit<BaseConnectorConfig, "isInjected" | "chainNamespaces"> {
    loginMethods?: LoginMethodConfig;
}
```

### `LoginMethodConfig`

The `LoginMethodConfig` interface provides extensive customization options for each authentication method:

<Tabs>
  <TabItem value="Table">

| Property                  | Type                   | Description                                                                          |
| ------------------------- | ---------------------- | ------------------------------------------------------------------------------------ |
| `name`                    | `string`               | Custom display name (defaults to auth app's default if not provided)                 |
| `description`             | `string`               | Button description (renders as full-length button if provided; otherwise as an icon) |
| `logoHover`               | `string`               | Logo shown on mouse hover (defaults to auth app's default)                           |
| `logoLight`               | `string`               | Logo for dark theme/background (defaults to auth app's default)                      |
| `logoDark`                | `string`               | Logo for light theme/background (defaults to auth app's default)                     |
| `mainOption`              | `boolean`              | Whether to show login button on the main list                                        |
| `showOnModal`             | `boolean`              | Controls visibility of the login button on modal                                     |
| `authConnectionId`        | `string`               | Auth connection ID of the provider                                                   |
| `groupedAuthConnectionId` | `string`               | Grouped Auth Connection ID of the provider                                           |
| `extraLoginOptions`       | `ExtraLoginOptions`    | Additional parameters for social login                                               |
| `authConnection`          | `AUTH_CONNECTION_TYPE` | Auth connection type (useful for customizing login buttons with custom connectors)   |
| `isDefault`               | `boolean`              | Whether it's the default connector _(internal)_                                      |

  </TabItem>

  <TabItem value="Interface">

```ts
export type LoginMethodConfig = Partial<
  Record<
    AUTH_CONNECTION_TYPE,
    {
      /**
       * Display Name. If not provided, we use the default for auth app
       */
      name?: string
      /**
       * Description for button. If provided, it renders as a full length button. else, icon button
       */
      description?: string
      /**
       * Logo to be shown on mouse hover. If not provided, we use the default for auth app
       */
      logoHover?: string
      /**
       * Logo to be shown on dark background (dark theme). If not provided, we use the default for auth app
       */
      logoLight?: string
      /**
       * Logo to be shown on light background (light theme). If not provided, we use the default for auth app
       */
      logoDark?: string
      /**
       * Show login button on the main list
       */
      mainOption?: boolean
      /**
       * Whether to show the login button on modal or not
       */
      showOnModal?: boolean
      /**
       * Auth connection id of the provider.
       */
      authConnectionId?: string
      /**
       * Grouped Auth connection id of the provider.
       */
      groupedAuthConnectionId?: string
      /**
       * ExtraLoginOption params to be used for social login.
       */
      extraLoginOptions?: ExtraLoginOptions
      /**
       * Auth connection type of the auth connector.
       * Can be different from the original key.
       *
       * Example: This helps in customizing the google login button with auth0 custom connector.
       */
      authConnection?: AUTH_CONNECTION_TYPE
      /**
       * Whether is it default connector.
       *
       * @internal
       */
      isDefault?: boolean
    }
  >
>
```

  </TabItem>
</Tabs>

## Common customization examples

### Disabling specific social login methods

Web3Auth provides the following social login methods:

```tsx
export declare const AUTH_CONNECTION: {
  readonly GOOGLE: 'google'
  readonly TWITTER: 'twitter'
  readonly FACEBOOK: 'facebook'
  readonly DISCORD: 'discord'
  readonly FARCASTER: 'farcaster'
  readonly APPLE: 'apple'
  readonly GITHUB: 'github'
  readonly REDDIT: 'reddit'
  readonly LINE: 'line'
  readonly KAKAO: 'kakao'
  readonly LINKEDIN: 'linkedin'
  readonly TWITCH: 'twitch'
  readonly TELEGRAM: 'telegram'
  readonly WECHAT: 'wechat'
  readonly EMAIL_PASSWORDLESS: 'email_passwordless'
  readonly SMS_PASSWORDLESS: 'sms_passwordless'
  readonly CUSTOM: 'custom'
  readonly AUTHENTICATOR: 'authenticator'
}
```

To disable specific login methods, set `showOnModal` to `false` for the corresponding auth connection:

```ts

const web3auth = new Web3Auth({
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
  // focus-start
  modalConfig: {
    connectors: {
      [WALLET_CONNECTORS.AUTH]: {
        label: 'auth',
        loginMethods: {
          // Disable Facebook and Reddit
          facebook: {
            name: 'facebook',
            showOnModal: false,
          },
          reddit: {
            name: 'reddit',
            showOnModal: false,
          },
        },
        // Setting to false will hide all social login methods from modal
        showOnModal: true,
      },
    },
  },
  // focus-end
})

// Initialize web3auth
await web3auth.init()
```

### Enhancing email and SMS login experience

By specifying a custom `authConnectionId` for email or SMS login methods, you can ensure the entire authentication flow takes place within the modal, eliminating the need for external popups.

:::info

In the default setup, users are redirected to a separate popup to enter their email or phone number for security purposes. However, with a custom `authConnectionId`, this input step is securely embedded directly inside the modal, keeping the input step inside the modal.

:::

```ts

const web3auth = new Web3Auth({
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
  // focus-start
  modalConfig: {
    connectors: {
      [WALLET_CONNECTORS.AUTH]: {
        label: 'auth',
        loginMethods: {
          email_passwordless: {
            name: 'email passwordless login',
            authConnectionId: 'w3a-email_passwordless-demo',
          },
          sms_passwordless: {
            name: 'sms passwordless login',
            authConnectionId: 'w3a-sms_passwordless-demo',
          },
        },
      },
    },
  },
  // focus-end
})

// Initialize web3auth
await web3auth.init()
```

## Creating a fully custom UI

For complete control over the authentication interface, you can bypass the Web3Auth modal entirely and use the `connectTo` function. This allows you to create custom buttons that connect directly to specific auth providers.

See the [custom authentication](custom-authentication.mdx) section for detailed implementation instructions.

---

## Ethereum integration with Web3Auth JS SDK

While using the Embedded Wallets Web SDK, you get a [`EIP1193`](https://eips.ethereum.org/EIPS/eip-1193) provider, similar to the [MetaMask provider](/metamask-connect/evm/reference/provider-api/). This provider can be used with libraries (like [`ethers.js`](https://docs.ethers.io/v5/getting-started/), [`viem`](https://viem.sh/)) to make [Ethereum](https://ethereum.org) calls like getting the user's `account`, fetching `balance`, `sign transaction`, `send transaction`, `read` from and `write` to the smart contract. We have highlighted a few examples to get you started.

## Integration

## Installation

To interact with the blockchain, you can use either the [`viem`](https://viem.sh/) or
[`ethers`](https://docs.ethers.org/v6/) library with Web3Auth.

<Tabs
  defaultValue="viem"
  values={[
    { label: "viem", value: "viem" },
    { label: "ethers.js", value: "ethers" },
  ]}
>
<TabItem value="viem">

```bash npm2yarn
npm install --save viem
```

</TabItem>
<TabItem value="ethers">

```bash npm2yarn
npm install --save ethers
```

</TabItem>
</Tabs>

## Initializing provider

After you connect with `@web3auth/modal`, the SDK exposes an
[`EIP-1193`](https://eips.ethereum.org/EIPS/eip-1193) provider at
`web3auth.connection?.ethereumProvider`. Configure EVM chains on the
[Embedded Wallets dashboard](/embedded-wallets/dashboard/chains-and-networks/).

### Initializing and instantiating the Embedded Wallets SDK

```tsx

const web3auth = new Web3Auth({
  clientId,
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
} satisfies Web3AuthOptions)
```

## Getting the Embedded Wallets provider

After initializing Embedded Wallets, the next step is to initialize the provider and use it for your
operations.

```tsx
// Initialize for PnP Web SDK
await web3auth.init()

// Trigger the login
await web3auth.connect()
// await web3auth.connectTo(); // For custom flow

// Get the provider
const provider = web3auth.connection?.ethereumProvider ?? null

// Continue using the `provider`
```

### Get account and balance

<Tabs
defaultValue="viem"
values={[
  { label: "viem", value: "viem" },
  { label: "ethers.js", value: "ethers.js" },
]}
>
<TabItem value="ethers.js">

```tsx
/*
  Use code from the above Initializing Provider here
*/

const ethersProvider = new ethers.BrowserProvider(provider)
const signer = await ethersProvider.getSigner()

// Get user's Ethereum public address
const address = await signer.getAddress()

// Get user's balance in ether
const balance = ethers.formatEther(await ethersProvider.getBalance(address))
```

</TabItem>
<TabItem value="viem">

```tsx
const publicClient = createPublicClient({
  chain: mainnet, // for mainnet
  transport: custom(provider),
})

const walletClient = createWalletClient({
  chain: mainnet,
  transport: custom(provider),
})

// Get user's Ethereum public address
const address = await walletClient.getAddresses()

// Get user's balance in ether
const balance = await publicClient.getBalance({ address: address[0] })
```

</TabItem>

</Tabs>

### Send transaction

<Tabs
  defaultValue="viem"
  values={[
    { label: "viem", value: "viem" },
    { label: "ethers.js", value: "ethers" },
  ]}
>
<TabItem value="ethers">

```tsx
/*
  Use code from the above Initializing Provider here
*/

const ethersProvider = new ethers.BrowserProvider(provider)
const signer = await ethersProvider.getSigner()

const destination = '0x7aFac68875d2841dc16F1730Fba43974060b907A'
const amount = ethers.parseEther('1.0') // Convert 1 ether to wei

// Submit transaction to the blockchain
const tx = await signer.sendTransaction({
  to: destination,
  value: amount,
})

// Wait for the transaction to be mined
const receipt = await tx.wait()
```

</TabItem>
<TabItem value="viem">

```tsx
/*
  Use code from the above Initializing Provider here
*/

const publicClient = createPublicClient({
  chain: mainnet, // for mainnet
  transport: custom(provider),
})

const walletClient = createWalletClient({
  chain: mainnet, // for mainnet
  transport: custom(provider),
})

// data for the transaction
const destination = '<ADDRESS>'
const amount = parseEther('0.0001')
const [address] = await walletClient.getAddresses()

// Submit transaction to the blockchain
const hash = await walletClient.sendTransaction({
  account: address,
  to: destination,
  value: amount,
})

const receipt = await publicClient.waitForTransactionReceipt({ hash })
```

</TabItem>
</Tabs>

### Sign message

#### Personal sign

<Tabs
  defaultValue="viem"
  values={[
    { label: "viem", value: "viem" },
    { label: "ethers.js", value: "ethers" },
  ]}
>
<TabItem value="ethers">

```tsx
/*
  Use code from the above Initializing Provider here
*/

const ethersProvider = new ethers.BrowserProvider(provider)
const signer = await ethersProvider.getSigner()

const originalMessage = 'YOUR_MESSAGE'

const signedMessage = await signer.signMessage(originalMessage)
```

</TabItem>
<TabItem value="viem">

```tsx
/*
  Use code from the above Initializing Provider here
*/

const publicClient = createPublicClient({
  chain: mainnet, // for mainnet
  transport: custom(provider),
})

const walletClient = createWalletClient({
  chain: mainnet, // for mainnet
  transport: custom(provider),
})

// data for signing
const address = await walletClient.getAddresses()
const originalMessage = 'YOUR_MESSAGE'

// Sign the message
const hash = await walletClient.signMessage({
  account: address[0],
  message: originalMessage,
})
```

</TabItem>
</Tabs>

### Sign typed data v4

<Tabs
  defaultValue="viem"
  values={[
    { label: "viem", value: "viem" },
    { label: "ethers.js", value: "ethers" },
  ]}
>
<TabItem value="viem">

```tsx
// SignTypedData in viem
// https://viem.sh/docs/actions/wallet/signTypedData

/*
  Use code from the above Initializing Provider here
*/

const walletClient = createWalletClient({
  chain: mainnet,
  transport: custom(provider),
})

const address = await walletClient.getAddresses()

const signature = await walletClient.signTypedData({
  account: address[0],
  domain: {
    name: 'Ether Mail',
    version: '1',
    chainId: 1,
    verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
  },
  types: {
    Person: [
      { name: 'name', type: 'string' },
      { name: 'wallet', type: 'address' },
    ],
    Mail: [
      { name: 'from', type: 'Person' },
      { name: 'to', type: 'Person' },
      { name: 'contents', type: 'string' },
    ],
  },
  primaryType: 'Mail',
  message: {
    from: {
      name: 'Cow',
      wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826',
    },
    to: {
      name: 'Bob',
      wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
    },
    contents: 'Hello, Bob!',
  },
})
```

</TabItem>
<TabItem value="ethers">

```tsx
/*
  Use code from the above initializing provider here
*/

const ethersProvider = new ethers.BrowserProvider(provider)
const signer = await ethersProvider.getSigner()

// Get user's Ethereum public address
const fromAddress = await signer.getAddress()

const originalMessage = JSON.stringify({
  domain: {
    // Defining the chain aka Sepolia testnet or Ethereum Main Net
    chainId: 11155111,
    // Give a user friendly name to the specific contract you are signing for.
    name: 'Ether Mail',
    // If name isn't enough add verifying contract to make sure you are establishing contracts with the proper entity
    verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
    // Just let's you know the latest version. Definitely make sure the field name is correct.
    version: '1',
  },

  // Defining the message signing data content.
  message: {
    /*
           - Anything you want. Just a JSON Blob that encodes the data you want to send
           - No required fields
           - This is dapp Specific
           - Be as explicit as possible when building out the message schema.
          */
    contents: 'Hello, Bob!',
    attachedMoneyInEth: 4.2,
    from: {
      name: 'Cow',
      wallets: [
        '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826',
        '0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF',
      ],
    },
    to: [
      {
        name: 'Bob',
        wallets: [
          '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
          '0xB0BdaBea57B0BDABeA57b0bdABEA57b0BDabEa57',
          '0xB0B0b0b0b0b0B000000000000000000000000000',
        ],
      },
    ],
  },
  // Refers to the keys of the *types* object below.
  primaryType: 'Mail',
  types: {
    // TODO: Clarify if EIP712Domain refers to the domain the contract is hosted on
    EIP712Domain: [
      { name: 'name', type: 'string' },
      { name: 'version', type: 'string' },
      { name: 'chainId', type: 'uint256' },
      { name: 'verifyingContract', type: 'address' },
    ],
    // Not an EIP712Domain definition
    Group: [
      { name: 'name', type: 'string' },
      { name: 'members', type: 'Person[]' },
    ],
    // Refer to PrimaryType
    Mail: [
      { name: 'from', type: 'Person' },
      { name: 'to', type: 'Person[]' },
      { name: 'contents', type: 'string' },
    ],
    // Not an EIP712Domain definition
    Person: [
      { name: 'name', type: 'string' },
      { name: 'wallets', type: 'address[]' },
    ],
  },
})
const params = [fromAddress, originalMessage]
const method = 'eth_signTypedData_v4'

const signedMessage = await signer.provider.send(method, params)
```

</TabItem>
</Tabs>

### Smart contract

#### Solidity contract

In this example, we'll be demonstrating how to use Web3Auth with web3.js or ethers.js to interact
with Solidity smart contracts. The simple _Hello World_ contract allows anyone to read and write a
message to it.

```tsx
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;

contract HelloWorld {

  string public message;

  constructor(string memory initMessage) {
    message = initMessage;
  }

  function update(string memory newMessage) public {
    message = newMessage;
  }
}
```

### Deploy contract

<Tabs
  defaultValue="viem"
  values={[
    { label: "viem", value: "viem" },
    { label: "ethers.js", value: "ethers" },
  ]}
>

<TabItem value="ethers">

```tsx
/*
  Use code from the above initializing provider here
*/

const ethersProvider = new ethers.BrowserProvider(provider)
const signer = await ethersProvider.getSigner()

const contractABI = [
  { inputs: [{ internalType: "string", name: "initMessage", type: "string" }], stateMutability: "nonpayable", type: "constructor" },
  { inputs: [], name: "message", outputs: [{ internalType: "string", name: "", type: "string" }], stateMutability: "view", type: "function" },
  {
    inputs: [{ internalType: "string", name: "newMessage", type: "string" }],
    name: "update",
    outputs: [],
    stateMutability: "nonpayable",
    type: "function",
  },
];
const contractByteCode =
  "60806040523480156200001157600080fd5b5060405162000bee38038062000bee8339818101604052810190620000379190620001e3565b80600090816200004891906200047f565b505062000566565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b620000b9826200006e565b810181811067ffffffffffffffff82111715620000db57620000da6200007f565b5b80604052505050565b6000620000f062000050565b9050620000fe8282620000ae565b919050565b600067ffffffffffffffff8211156200012157620001206200007f565b5b6200012c826200006e565b9050602081019050919050565b60005b83811015620001595780820151818401526020810190506200013c565b60008484015250505050565b60006200017c620001768462000103565b620000e4565b9050828152602081018484840111156200019b576200019a62000069565b5b620001a884828562000139565b509392505050565b600082601f830112620001c857620001c762000064565b5b8151620001da84826020860162000165565b91505092915050565b600060208284031215620001fc57620001fb6200005a565b5b600082015167ffffffffffffffff8111156200021d576200021c6200005f565b5b6200022b84828501620001b0565b91505092915050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200028757607f821691505b6020821081036200029d576200029c6200023f565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302620003077fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82620002c8565b620003138683620002c8565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b6000620003606200035a62000354846200032b565b62000335565b6200032b565b9050919050565b6000819050919050565b6200037c836200033f565b620003946200038b8262000367565b848454620002d5565b825550505050565b600090565b620003ab6200039c565b620003b881848462000371565b505050565b5b81811015620003e057620003d4600082620003a1565b600181019050620003be565b5050565b601f8211156200042f57620003f981620002a3565b6200040484620002b8565b8101602085101562000414578190505b6200042c6200042385620002b8565b830182620003bd565b50505b505050565b600082821c905092915050565b6000620004546000198460080262000434565b1980831691505092915050565b60006200046f838362000441565b9150826002028217905092915050565b6200048a8262000234565b67ffffffffffffffff811115620004a657620004a56200007f565b5b620004b282546200026e565b620004bf828285620003e4565b600060209050601f831160018114620004f75760008415620004e2578287015190505b620004ee858262000461565b8655506200055e565b601f1984166200050786620002a3565b60005b8281101562000531578489015182556001820191506020850194506020810190506200050a565b868310156200055157848901516200054d601f89168262000441565b8355505b6001600288020188555050505b505050505050565b61067880620005766000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80633d7403a31461003b578063e21f37ce14610057575b600080fd5b61005560048036038101906100509190610270565b610075565b005b61005f610088565b60405161006c9190610338565b60405180910390f35b80600090816100849190610570565b5050565b6000805461009590610389565b80601f01602080910402602001604051908101604052809291908181526020018280546100c190610389565b801561010e5780601f106100e35761010080835404028352916020019161010e565b820191906000526020600020905b8154815290600101906020018083116100f157829003601f168201915b505050505081565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61017d82610134565b810181811067ffffffffffffffff8211171561019c5761019b610145565b5b80604052505050565b60006101af610116565b90506101bb8282610174565b919050565b600067ffffffffffffffff8211156101db576101da610145565b5b6101e482610134565b9050602081019050919050565b82818337600083830152505050565b600061021361020e846101c0565b6101a5565b90508281526020810184848401111561022f5761022e61012f565b5b61023a8482856101f1565b509392505050565b600082601f8301126102575761025661012a565b5b8135610267848260208601610200565b91505092915050565b60006020828403121561028657610285610120565b5b600082013567ffffffffffffffff8111156102a4576102a3610125565b5b6102b084828501610242565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156102f35780820151818401526020810190506102d8565b60008484015250505050565b600061030a826102b9565b61031481856102c4565b93506103248185602086016102d5565b61032d81610134565b840191505092915050565b6000602082019050818103600083015261035281846102ff565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806103a157607f821691505b6020821081036103b4576103b361035a565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b60006008830261041c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826103df565b61042686836103df565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b600061046d6104686104638461043e565b610448565b61043e565b9050919050565b6000819050919050565b61048783610452565b61049b61049382610474565b8484546103ec565b825550505050565b600090565b6104b06104a3565b6104bb81848461047e565b505050565b5b818110156104df576104d46000826104a8565b6001810190506104c1565b5050565b601f821115610524576104f5816103ba565b6104fe846103cf565b8101602085101561050d578190505b610521610519856103cf565b8301826104c0565b50505b505050565b600082821c905092915050565b600061054760001984600802610529565b1980831691505092915050565b60006105608383610536565b9150826002028217905092915050565b610579826102b9565b67ffffffffffffffff81111561059257610591610145565b5b61059c8254610389565b6105a78282856104e3565b600060209050601f8311600181146105da57600084156105c8578287015190505b6105d28582610554565b86555061063a565b601f1984166105e8866103ba565b60005b82811015610610578489015182556001820191506020850194506020810190506105eb565b8683101561062d5784890151610629601f891682610536565b8355505b6001600288020188555050505b50505050505056fea2646970667358221220eecabaeaef849ff90aa73071525a5fa1972cd301476f7718a27010569d13051264736f6c63430008120033";

const address = signer.getAddress();

const contractFactory = new ContractFactory(JSON.parse(JSON.stringify(contractABI), contractByteCode, address);
// Deploy contract with "Hello World!" in the constructor
const contract = await contractFactory.deploy("Hello World!");

// Wait for deployment to finish
const receipt = await contract.deployed();

const deployedContractAddress = receipt.contractAddress;
```

</TabItem>
<TabItem value="viem">

```tsx
/*
  Use code from the above Initializing Provider here
*/
const publicClient = createPublicClient({
  chain: this.getViewChain(),
  transport: custom(provider),
})

const walletClient = createWalletClient({
  chain: mainnet,
  transport: custom(provider),
})

const contractABI = [
  {
    inputs: [{ internalType: 'string', name: 'initMessage', type: 'string' }],
    stateMutability: 'nonpayable',
    type: 'constructor',
  },
  {
    inputs: [],
    name: 'message',
    outputs: [{ internalType: 'string', name: '', type: 'string' }],
    stateMutability: 'view',
    type: 'function',
  },
  {
    inputs: [{ internalType: 'string', name: 'newMessage', type: 'string' }],
    name: 'update',
    outputs: [],
    stateMutability: 'nonpayable',
    type: 'function',
  },
]
const contractByteCode =
  '60806040523480156200001157600080fd5b5060405162000bee38038062000bee8339818101604052810190620000379190620001e3565b80600090816200004891906200047f565b505062000566565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b620000b9826200006e565b810181811067ffffffffffffffff82111715620000db57620000da6200007f565b5b80604052505050565b6000620000f062000050565b9050620000fe8282620000ae565b919050565b600067ffffffffffffffff8211156200012157620001206200007f565b5b6200012c826200006e565b9050602081019050919050565b60005b83811015620001595780820151818401526020810190506200013c565b60008484015250505050565b60006200017c620001768462000103565b620000e4565b9050828152602081018484840111156200019b576200019a62000069565b5b620001a884828562000139565b509392505050565b600082601f830112620001c857620001c762000064565b5b8151620001da84826020860162000165565b91505092915050565b600060208284031215620001fc57620001fb6200005a565b5b600082015167ffffffffffffffff8111156200021d576200021c6200005f565b5b6200022b84828501620001b0565b91505092915050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200028757607f821691505b6020821081036200029d576200029c6200023f565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302620003077fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82620002c8565b620003138683620002c8565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b6000620003606200035a62000354846200032b565b62000335565b6200032b565b9050919050565b6000819050919050565b6200037c836200033f565b620003946200038b8262000367565b848454620002d5565b825550505050565b600090565b620003ab6200039c565b620003b881848462000371565b505050565b5b81811015620003e057620003d4600082620003a1565b600181019050620003be565b5050565b601f8211156200042f57620003f981620002a3565b6200040484620002b8565b8101602085101562000414578190505b6200042c6200042385620002b8565b830182620003bd565b50505b505050565b600082821c905092915050565b6000620004546000198460080262000434565b1980831691505092915050565b60006200046f838362000441565b9150826002028217905092915050565b6200048a8262000234565b67ffffffffffffffff811115620004a657620004a56200007f565b5b620004b282546200026e565b620004bf828285620003e4565b600060209050601f831160018114620004f75760008415620004e2578287015190505b620004ee858262000461565b8655506200055e565b601f1984166200050786620002a3565b60005b8281101562000531578489015182556001820191506020850194506020810190506200050a565b868310156200055157848901516200054d601f89168262000441565b8355505b6001600288020188555050505b505050505050565b61067880620005766000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80633d7403a31461003b578063e21f37ce14610057575b600080fd5b61005560048036038101906100509190610270565b610075565b005b61005f610088565b60405161006c9190610338565b60405180910390f35b80600090816100849190610570565b5050565b6000805461009590610389565b80601f01602080910402602001604051908101604052809291908181526020018280546100c190610389565b801561010e5780601f106100e35761010080835404028352916020019161010e565b820191906000526020600020905b8154815290600101906020018083116100f157829003601f168201915b505050505081565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61017d82610134565b810181811067ffffffffffffffff8211171561019c5761019b610145565b5b80604052505050565b60006101af610116565b90506101bb8282610174565b919050565b600067ffffffffffffffff8211156101db576101da610145565b5b6101e482610134565b9050602081019050919050565b82818337600083830152505050565b600061021361020e846101c0565b6101a5565b90508281526020810184848401111561022f5761022e61012f565b5b61023a8482856101f1565b509392505050565b600082601f8301126102575761025661012a565b5b8135610267848260208601610200565b91505092915050565b60006020828403121561028657610285610120565b5b600082013567ffffffffffffffff8111156102a4576102a3610125565b5b6102b084828501610242565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156102f35780820151818401526020810190506102d8565b60008484015250505050565b600061030a826102b9565b61031481856102c4565b93506103248185602086016102d5565b61032d81610134565b840191505092915050565b6000602082019050818103600083015261035281846102ff565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806103a157607f821691505b6020821081036103b4576103b361035a565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b60006008830261041c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826103df565b61042686836103df565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b600061046d6104686104638461043e565b610448565b61043e565b9050919050565b6000819050919050565b61048783610452565b61049b61049382610474565b8484546103ec565b825550505050565b600090565b6104b06104a3565b6104bb81848461047e565b505050565b5b818110156104df576104d46000826104a8565b6001810190506104c1565b5050565b601f821115610524576104f5816103ba565b6104fe846103cf565b8101602085101561050d578190505b610521610519856103cf565b8301826104c0565b50505b505050565b600082821c905092915050565b600061054760001984600802610529565b1980831691505092915050565b60006105608383610536565b9150826002028217905092915050565b610579826102b9565b67ffffffffffffffff81111561059257610591610145565b5b61059c8254610389565b6105a78282856104e3565b600060209050601f8311600181146105da57600084156105c8578287015190505b6105d28582610554565b86555061063a565b601f1984166105e8866103ba565b60005b82811015610610578489015182556001820191506020850194506020810190506105eb565b8683101561062d5784890151610629601f891682610536565b8355505b6001600288020188555050505b50505050505056fea2646970667358221220eecabaeaef849ff90aa73071525a5fa1972cd301476f7718a27010569d13051264736f6c63430008120033'

const [account] = await walletClient.getAddresses()
const hash = await walletClient.deployContract({
  abi: this.contractABI,
  account,
  bytecode: this.contractByteCode,
  args: ['Hello World!'],
})

const receipt = await publicClient.waitForTransactionReceipt({ hash })

const deployedContractAddress = receipt.contractAddress
```

</TabItem>
</Tabs>

### Read from contract

<Tabs
  defaultValue="viem"
  values={[
    { label: "viem", value: "viem" },
    { label: "ethers.js", value: "ethers" },
  ]}
>

<TabItem value="ethers">

```tsx
/*
  Use code from the above Initializing Provider here
*/

const ethersProvider = new ethers.BrowserProvider(provider)
const signer = await ethersProvider.getSigner()

const contractABI = [
  {
    inputs: [{ internalType: 'string', name: 'initMessage', type: 'string' }],
    stateMutability: 'nonpayable',
    type: 'constructor',
  },
  {
    inputs: [],
    name: 'message',
    outputs: [{ internalType: 'string', name: '', type: 'string' }],
    stateMutability: 'view',
    type: 'function',
  },
  {
    inputs: [{ internalType: 'string', name: 'newMessage', type: 'string' }],
    name: 'update',
    outputs: [],
    stateMutability: 'nonpayable',
    type: 'function',
  },
]
const contractAddress = '0x04cA407965D60C2B39d892a1DFB1d1d9C30d0334'
const contract = new ethers.Contract(
  contractAddress,
  JSON.parse(JSON.stringify(contractABI)),
  signer
)

// Read message from smart contract
const message = await contract.message()
```

</TabItem>
<TabItem value="viem">

```tsx
/*
  Use code from the above Initializing Provider here
*/

const contractABI = [
  {
    inputs: [{ internalType: 'string', name: 'initMessage', type: 'string' }],
    stateMutability: 'nonpayable',
    type: 'constructor',
  },
  {
    inputs: [],
    name: 'message',
    outputs: [{ internalType: 'string', name: '', type: 'string' }],
    stateMutability: 'view',
    type: 'function',
  },
  {
    inputs: [{ internalType: 'string', name: 'newMessage', type: 'string' }],
    name: 'update',
    outputs: [],
    stateMutability: 'nonpayable',
    type: 'function',
  },
]

const publicClient = createPublicClient({
  chain: mainnet, // for mainnet
  transport: custom(provider),
})

const contractAddress = '0x8AA6820B3F197384874fAdb355361758258cb981' // On Sepolia, replace with your contract address

// Read message from smart contract
const message = await publicClient.readContract({
  address: contractAddress,
  abi: contractABI,
  functionName: 'message',
})
```

</TabItem>
</Tabs>

### Write to contract

<Tabs
  defaultValue="viem"
  values={[
    { label: "viem", value: "viem" },
    { label: "ethers.js", value: "ethers" },
  ]}
>

<TabItem value="ethers">

```tsx
/*
  Use code from the above Initializing Provider here
*/

const ethersProvider = new ethers.BrowserProvider(provider)
const signer = await ethersProvider.getSigner()

const contractABI = [
  {
    inputs: [{ internalType: 'string', name: 'initMessage', type: 'string' }],
    stateMutability: 'nonpayable',
    type: 'constructor',
  },
  {
    inputs: [],
    name: 'message',
    outputs: [{ internalType: 'string', name: '', type: 'string' }],
    stateMutability: 'view',
    type: 'function',
  },
  {
    inputs: [{ internalType: 'string', name: 'newMessage', type: 'string' }],
    name: 'update',
    outputs: [],
    stateMutability: 'nonpayable',
    type: 'function',
  },
]
const contractAddress = '0x04cA407965D60C2B39d892a1DFB1d1d9C30d0334'
const contract = new ethers.Contract(
  contractAddress,
  JSON.parse(JSON.stringify(contractABI)),
  signer
)

// Send transaction to smart contract to update message
const tx = await contract.update('NEW_MESSAGE')

// Wait for transaction to finish
const receipt = await tx.wait()
```

</TabItem>
<TabItem value="viem">

```tsx
/*
  Use code from the above Initializing Provider here
*/

const contractABI = [
  {
    inputs: [{ internalType: 'string', name: 'initMessage', type: 'string' }],
    stateMutability: 'nonpayable',
    type: 'constructor',
  },
  {
    inputs: [],
    name: 'message',
    outputs: [{ internalType: 'string', name: '', type: 'string' }],
    stateMutability: 'view',
    type: 'function',
  },
  {
    inputs: [{ internalType: 'string', name: 'newMessage', type: 'string' }],
    name: 'update',
    outputs: [],
    stateMutability: 'nonpayable',
    type: 'function',
  },
]
const publicClient = createPublicClient({
  chain: mainnet,
  transport: custom(provider),
})

const walletClient = createWalletClient({
  chain: mainnet,
  transport: custom(provider),
})

const contractAddress = '0x8AA6820B3F197384874fAdb355361758258cb981' // On Sepolia, replace with your contract address
address = await walletClient.getAddresses()

// Submit transaction to the blockchain
const hash = await walletClient.writeContract({
  account: address[0],
  address: contractAddress,
  abi: JSON.parse(JSON.stringify(contractABI)),
  functionName: 'update',
  args: ['NEW_MESSAGE'],
})

// Send transaction to smart contract to update message
const receipt = await publicClient.waitForTransactionReceipt({ hash })
```

</TabItem>
</Tabs>

### Fetch user's private key

`private_key` is used to fetch the private key of the logged in user. It is only available for
`in-app` adapters like `auth`.

```tsx
//Assuming user is already logged in.
async getPrivateKey() {
  const privateKey = await provider.request({
    method: 'private_key',
  })
  //Do something with privateKey
}
```

---

## Embedded Wallets events and status

This page documents the key properties and lifecycle events available from an Embedded Wallets instance. These allow you to track the connection status, react to changes, and build responsive user experiences.

## `connected`

Returns `true` if a wallet is connected, otherwise `false`.

#### Interface

```ts
get connected(): boolean;
```

#### Usage

```js
const isConnected = web3auth.connected
```

## `connection`

Returns the active wallet connection, including the Ethereum provider and Solana wallet when connected.

#### Usage

```js
const provider = web3auth.connection?.ethereumProvider ?? null
const solanaWallet = web3auth.connection?.solanaWallet ?? null
```

:::note

In Web SDK v11, reading `web3auth.provider` returns `undefined`. Use `connection` instead.
:::

## `connectedConnectorName`

Name of the currently connected wallet connector, or `null` if not connected.

#### Interface

```ts
connectedConnectorName: WALLET_CONNECTOR_TYPE | null
```

##### `WALLET_CONNECTOR_TYPE`

<Tabs>
  <TabItem value="table" label="Table">

| Event               | Description                 |
| ------------------- | --------------------------- |
| `AUTH`              | Web3Auth connector.         |
| `WALLET_CONNECT_V2` | WalletConnect V2 connector. |
| `COINBASE`          | Coinbase connector.         |
| `METAMASK`          | MetaMask connector.         |

  </TabItem>
  <TabItem value="interface" label="Interface">

```ts
export type WALLET_CONNECTOR_TYPE = (typeof WALLET_CONNECTORS)[keyof typeof WALLET_CONNECTORS]
export declare const WALLET_CONNECTORS: {
  readonly AUTH: 'auth'
  readonly WALLET_CONNECT_V2: 'wallet-connect-v2'
  readonly COINBASE: 'coinbase'
  readonly METAMASK: 'metamask'
}
```

  </TabItem>
</Tabs>

#### Usage

```js
const connectorName = web3auth.connectedConnectorName
```

## `status`

Current status of the Web3Auth instance. Emits status change events.

#### Interface

```ts
status: CONNECTOR_STATUS_TYPE
```

##### `CONNECTOR_STATUS_TYPE`

<Tabs>
  <TabItem value="table" label="Table">

| Event           | Description                                                     |
| --------------- | --------------------------------------------------------------- |
| `NOT_READY`     | Triggered when the connector is not ready.                      |
| `READY`         | Triggered when the connector is ready.                          |
| `CONNECTING`    | Triggered when a connection is being established.               |
| `CONNECTED`     | Triggered when a wallet is successfully connected.              |
| `DISCONNECTING` | Triggered when the wallet is in the process of Disconnecting.   |
| `DISCONNECTED`  | Triggered when the wallet is Disconnected.                      |
| `ERRORED`       | Triggered when an error occurs during the connection lifecycle. |

  </TabItem>
  <TabItem value="interface" label="Interface">

```ts
export type CONNECTOR_STATUS_TYPE = (typeof CONNECTOR_STATUS)[keyof typeof CONNECTOR_STATUS]
export declare const CONNECTOR_STATUS: {
  readonly NOT_READY: 'not_ready'
  readonly READY: 'ready'
  readonly CONNECTING: 'connecting'
  readonly CONNECTED: 'connected'
  readonly DISCONNECTING: 'disconnecting'
  readonly DISCONNECTED: 'disconnected'
  readonly ERRORED: 'errored'
}
```

  </TabItem>
</Tabs>

#### Usage

```js
const status = web3auth.status
```

## `currentChain`

Returns the current chain configuration if connected.

#### Interface

```ts
get currentChain(): CustomChainConfig | undefined;
```

#### `chainConfig`

In Web SDK v11, configure chains on the
[Embedded Wallets dashboard](/embedded-wallets/dashboard/chains-and-networks/). The shape of each
chain matches `CustomChainConfig`:

```javascript
const chainConfig = {
  chainId: '0x1', // Please use 0x1 for Mainnet
  rpcTarget: 'https://rpc.ethereum.org',
  displayName: 'Ethereum Mainnet',
  blockExplorerUrl: 'https://etherscan.io/',
  ticker: 'ETH',
  tickerName: 'Ethereum',
  logo: 'https://images.toruswallet.io/eth.svg',
}
```

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Type Declarations", value: "type" },
  ]}
>

<TabItem value="table">

| Parameter           | Description                            |
| ------------------- | -------------------------------------- |
| `chainNamespace`    | Namespace of the chain                 |
| `chainId`           | Chain ID of the chain                  |
| `rpcTarget`         | RPC target URL for the chain           |
| `wsTarget?`         | Web socket target URL for the chain    |
| `displayName?`      | Display name for the chain             |
| `blockExplorerUrl?` | URL of the block explorer              |
| `ticker?`           | Default currency ticker of the network |
| `tickerName?`       | Name for currency ticker               |
| `decimals?`         | Number of decimals for the currency    |
| `logo?`             | Logo for the token                     |
| `isTestnet?`        | Whether the network is testnet or not  |

</TabItem>

<TabItem value="type">

```tsx
export declare const CHAIN_NAMESPACES: {
  readonly EIP155: 'eip155'
  readonly SOLANA: 'solana'
  readonly CASPER: 'casper'
  readonly XRPL: 'xrpl'
  readonly OTHER: 'other'
}

export type ChainNamespaceType = (typeof CHAIN_NAMESPACES)[keyof typeof CHAIN_NAMESPACES]
export type CustomChainConfig = {
  chainNamespace: ChainNamespaceType
  /**
   * The chain id of the chain
   */
  chainId: string
  /**
   * RPC target Url for the chain
   */
  rpcTarget: string
  /**
   * web socket target url for the chain
   */
  wsTarget?: string
  /**
   * Display Name for the chain
   */
  displayName?: string
  /**
   * Url of the block explorer
   */
  blockExplorerUrl?: string
  /**
   * Default currency ticker of the network (e.g: ETH)
   */
  ticker?: string
  /**
   * Name for currency ticker (e.g: `Ethereum`)
   */
  tickerName?: string
  /**
   * Number of decimals for the currency ticker (e.g: 18)
   */
  decimals?: number
  /**
   * Logo for the token
   */
  logo?: string
  /**
   * Whether the network is testnet or not
   */
  isTestnet?: boolean
}
```

</TabItem>

</Tabs>

#### Usage

```js
const chain = web3auth.currentChain
```

## `connectedConnector`

Returns the connector instance for the connected wallet, or `null`.

#### Interface

```ts
get connectedConnector(): IConnector<unknown> | null;
```

#### Usage

```js
const connector = web3auth.connectedConnector
```

## `accountAbstractionProvider`

Returns the account abstraction provider if available.

#### Interface

```ts
get accountAbstractionProvider(): AccountAbstractionProvider | null;
```

#### Usage

```js
const aaProvider = web3auth.accountAbstractionProvider
```

## `getConnector`

Returns a connector instance for a given connector name and chain namespace.

#### Interface

```ts
getConnector(connectorName: WALLET_CONNECTOR_TYPE, chainNamespace?: ChainNamespaceType): IConnector<unknown> | null;

export type WALLET_CONNECTOR_TYPE = (typeof WALLET_CONNECTORS)[keyof typeof WALLET_CONNECTORS];
export declare const WALLET_CONNECTORS: {
  readonly AUTH: "auth";
  readonly WALLET_CONNECT_V2: "wallet-connect-v2";
  readonly COINBASE: "coinbase";
  readonly METAMASK: "metamask";
};
export type ChainNamespaceType = (typeof CHAIN_NAMESPACES)[keyof typeof CHAIN_NAMESPACES];
```

#### Usage

```js

const connector = web3auth.getConnector(WALLET_CONNECTORS.WALLET_CONNECT_V2, 'eip155')
```

## `getPlugin`

Returns a plugin instance by name, or `null` if not found.

#### Interface

```ts
getPlugin(name: string): IPlugin | null;

export interface IPlugin extends SafeEventEmitter {
  name: string;
  status: PLUGIN_STATUS_TYPE;
  SUPPORTED_CONNECTORS: WALLET_CONNECTOR_TYPE[];
  pluginNamespace: PluginNamespace;
  initWithWeb3Auth(web3auth: IWeb3AuthCore, whiteLabel?: WhiteLabelData): Promise<void>;
  connect(): Promise<void>;
  disconnect(): Promise<void>;
  cleanup(): Promise<void>;
}
```

#### Usage

```js
const plugin = web3auth.getPlugin('walletServices')
```

---

## Examples - PnP Web JS SDK

<ExampleCards
  exampleMap={[...webExamples].filter(
    obj =>
      !obj.tags?.includes('react') && !obj.tags?.includes('vue') && !obj.tags?.includes('nextjs')
  )}
/>

---

## Using PnP Web Modal SDK

Embedded Wallets provides a comprehensive set of functions to handle authentication, user management, and blockchain interactions in your applications. These functions allow you to implement features like user login, multi-factor authentication, chain switching, and Wallet Services with minimal effort. Each function is designed to handle a specific aspect of Embedded Wallets' functionality, making it easy to integrate into your projects.

## List of functions

:::tip

For detailed usage, configuration options, and code examples, refer to the dedicated documentation page for each function.

:::

### Authentication functions

| Function Name                | Description                                 |
| ---------------------------- | ------------------------------------------- |
| [`connect()`](./connect.mdx) | Displays the Modal and logs in the user.    |
| [`logout()`](./logout.mdx)   | Logs out the user from the current session. |

### User management functions

| Function Name                                     | Description                                                   |
| ------------------------------------------------- | ------------------------------------------------------------- |
| [`getUserInfo()`](./get-user-info.mdx)            | Retrieves the authenticated user's information.               |
| [`getAuthTokenInfo()`](./get-auth-token-info.mdx) | Gets the `idToken` from Web3Auth for authentication purposes. |

### Security functions

| Function Name                     | Description                                                                        |
| --------------------------------- | ---------------------------------------------------------------------------------- |
| [`enableMFA()`](./enable-mfa.mdx) | Enables Multi-Factor Authentication for the user.                                  |
| [`manageMFA()`](./manage-mfa.mdx) | Redirects the user to manage their MFA settings in the Web3Auth Account Dashboard. |

### Blockchain functions

| Function Name                         | Description                                                                              |
| ------------------------------------- | ---------------------------------------------------------------------------------------- |
| `addChain()`                          | Adds chain configuration details to the connected adapter.                               |
| [`switchChain()`](./switch-chain.mdx) | Switches to a different blockchain network as per chainId already added to chain config. |

### Wallet Services plugin functions

| Function Name                                                     | Description                                   |
| ----------------------------------------------------------------- | --------------------------------------------- |
| [`showCheckout()`](./show-checkout.mdx)                           | Initiates cryptocurrency top-up for the user. |
| [`showWalletConnectScanner()`](./show-wallet-connect-scanner.mdx) | Displays the WalletConnect QR Code Scanner.   |
| [`showWalletUI()`](./show-wallet-ui.mdx)                          | Shows the Embedded Wallet UI.                 |
| [`showSwap()`](./show-swap.mdx)                                   | Displays the swap UI for token exchanges.     |
| `showTransactionConfirmation()`                                   | Shows the transaction confirmation UI.        |

---

## connect & connectTo

Functions to connect users to Embedded Wallets in the browser.

### Import

```javascript

```

### Choosing the right connection method

You can connect users to Embedded Wallets in two main ways, depending on your application's needs:

- **Use `connect()`** when you want to display the default Embedded Wallets/Web3Auth modal. This is ideal if you want to provide users with a pre-built, user-friendly interface where they can choose from all available login options (for example, social logins, wallets) with minimal setup.

- **Use `connectTo(connector, params)`** when you want to build a fully custom login experience. This method lets you bypass the Web3Auth modal and connect directly to a specific wallet connector (such as Google, Facebook, or a particular wallet). Choose this if you want to design your own UI for login options, or if you want to restrict users to a specific authentication method. This method also allows you to use JWT-based login configurations.

**Summary:**

- Use `connect()` for the standard modal experience.
- Use `connectTo()` for custom UIs or direct connection to a specific login method.

### Usage

<Tabs
  defaultValue="basic"
  values={[
    { label: "Basic Modal", value: "basic" },
    { label: "Custom UI", value: "custom-ui" },
  ]}
>

<TabItem value="basic">

:::info

This is the most common way to connect to Embedded Wallets. It opens the Embedded Wallets/Web3Auth modal UI, allowing users to select from available login options.

:::

```javascript
// Initialize Web3Auth first
const web3auth = new Web3Auth({
  // Your configuration options
})

await web3auth.init()

// Show the modal and connect
await web3auth.connect()

const provider = web3auth.connection?.ethereumProvider ?? null
```

</TabItem>

<TabItem value="custom-ui">

:::info

This method allows you to build your own custom connection UI. It bypasses the Embedded Wallets/Web3Auth modal UI, allowing you to create your own custom UI for login options. This can be useful if you want to hide Embedded Wallets from your end users.

:::

```javascript

// Initialize Web3Auth first
const web3auth = new Web3Auth({
  // Your configuration options
})

await web3auth.init()

// Connect directly to Google
await web3auth.connectTo(WALLET_CONNECTORS.AUTH, {
  authConnection: AUTH_CONNECTION.GOOGLE,
})

const provider = web3auth.connection?.ethereumProvider ?? null
```

</TabItem>

</Tabs>

### Return types

```tsx
connect(): Promise<Connection | null>
connectTo<T extends WALLET_CONNECTOR_TYPE>(connector: T, params?: LoginParamMap[T]): Promise<Connection | null>
```

#### Return values

- **`Connection | null`**: On successful sign-in, returns a `Connection` object with
  `ethereumProvider`, `solanaWallet`, and `connectorName`. On unsuccessful sign-in, returns `null`.
- For the EIP-1193 provider, use `web3auth.connection?.ethereumProvider` after `connect()` or
  `connectTo()`.

:::tip

Read more about connecting your users with the selected blockchain in the
[JavaScript Ethereum integration](/embedded-wallets/sdk/js/ethereum-integration) guide.

:::

---

## enableMFA

Function to enable Multi-Factor Authentication (MFA) for users with Web3Auth.

:::info

Please note that this function doesn't work for external wallet logins. It only works for social login embedded wallets.

:::

```javascript
try {
  await web3auth.enableMFA()
  console.log('MFA setup process initiated')
} catch (error) {
  console.error('Error enabling MFA:', error)
}
```

### Interface

```ts
enableMFA<T>(loginParams?: T): Promise<void>;
```

#### `loginParams`

Optional parameters for the login process when setting up MFA.

#### Return value

`Promise<void>`

A promise that resolves when the MFA setup process has been initiated. This function will trigger a redirect to the MFA setup page, where the user will be asked to login again and set up the MFA methods according to the configuration set in the Web3Auth instance.

---

## getAuthTokenInfo

Function to retrieve the identity token from Web3Auth.

:::note

This function will only return information based on the connected adapter. These details are not stored anywhere and are fetched from the adapter during the connection and remain in the session.

:::

### Usage

```ts
// Later in your code:
try {
  const { idToken } = await web3auth.getAuthTokenInfo()
  console.log(idToken)
} catch (error) {
  console.error('Error authenticating user:', error)
}
```

### Return type

```typescript
getAuthTokenInfo(): Promise<AuthTokenInfo>

type AuthTokenInfo = { idToken: string };
```

### Response format

The `idToken` is a JWT that can be decoded to get user information.

<Tabs
  defaultValue="social-login"
  values={[
    { label: "Social Login", value: "social-login" },
    { label: "External Wallet", value: "external-wallet" },
  ]}
>

<TabItem value="social-login">

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Type Declarations", value: "type" },
  ]}
>

<TabItem value="table">

| Parameter           | Type     | Description                                                                                                                                                                                                                                                                                                                                                                                     |
| ------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `iat`               | `number` | The `iat` (issued at) claim identifies the time at which the JWT was issued.                                                                                                                                                                                                                                                                                                                    |
| `aud`               | `string` | The `aud` (audience) claim identifies the recipients the JWT is intended for (for example, the dapp `client_id`).                                                                                                                                                                                                                                                                               |
| `iss`               | `string` | The `iss` (issuer) claim identifies who issued the JWT (for example, Web3Auth `https://api.openlogin.com/`).                                                                                                                                                                                                                                                                                    |
| `email`             | `string` | (Optional) The email address of the user.                                                                                                                                                                                                                                                                                                                                                       |
| `name`              | `string` | (Optional) The name of the user.                                                                                                                                                                                                                                                                                                                                                                |
| `profileImage`      | `string` | (Optional) The profile image of the user .                                                                                                                                                                                                                                                                                                                                                      |
| `verifier`          | `string` | The Web3Auth verifier used during user login.                                                                                                                                                                                                                                                                                                                                                   |
| `verifierId`        | `string` | The unique user ID provided by the OAuth login provider.                                                                                                                                                                                                                                                                                                                                        |
| `aggregateVerifier` | `string` | (Optional) The name of the verifier if you are using a single ID (aggregate) verifier.                                                                                                                                                                                                                                                                                                          |
| `exp`               | `number` | The `exp` (expiration time) claim identifies the time on, or after which, the _JWT MUST NOT be accepted for processing_.                                                                                                                                                                                                                                                                        |
| `wallets`           | `array`  | List of wallets for which this token is issued:`curve`: Cryptographic curve used for the public key. Possible values are `secp256k1` (default) and `ed25519`. You can specify the curve in the login parameters.`type`: Wallet type. For social logins, this value is `web3auth_key`.`public_key`: Compressed public key derived using the specified curve. |

</TabItem>

<TabItem value="type">

`getAuthTokenInfo(): Promise<AuthTokenInfo>`

```tsx
export type AuthTokenInfo = { idToken: string }
```

</TabItem>

</Tabs>

#### Sample response

```json
{
  "iat": 1655835494,
  "aud": "BCtbnOamqh0cJFEUYA0NB5YkvBECZ3HLZsKfvSRBvew2EiiKW3UxpyQASSR0artjQkiUOCHeZ_ZeygXpYpxZjOs",
  "iss": "https://api.openlogin.com/",
  "email": "xyz@xyz.com",
  "name": "John Doe",
  "profileImage": "https://lh3.googleusercontent.com/a/AATXAJx3lnGmHiM4K97uLo9Rb0AxOceH-dQCBSRqGbck=s96-c",
  "verifier": "torus",
  "verifierId": "xyz@xyz.com",
  "aggregateVerifier": "tkey-google-lrc",
  "exp": 1655921894,
  "wallets": [
    {
      "public_key": "035143318b83eb5d31611f8c03582ab1200494f66f5e11a67c34f5581f48c1b70b",
      "type": "web3auth_key",
      "curve": "secp256k1"
    }
  ]
}
```

</TabItem>

<TabItem value="external-wallet">

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Type Declarations", value: "type" },
  ]}
>

<TabItem value="table">

| Parameter | Type     | Description                                                                                                                                                                             |
| --------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `iat`     | `number` | The `iat` (issued at) claim identifies the time at which the JWT was issued.                                                                                                            |
| `aud`     | `string` | The audience claim identifies the recipients the JWT is intended for (for example, the website URL).                                                                                    |
| `iss`     | `string` | The issuer claim identifies who issued the JWT.Possible values: `torus-evm`, `torus-solana`, `metamask`, `phantom`, `walletconnect-v1`, `coinbase`, `solflare`.                   |
| `wallets` | `array`  | List of wallets for which this token is issued.- `address`: wallet public address.- `type`: network type such as `ethereum`, `solana`, or `starkware` for external wallets. |

</TabItem>

<TabItem value="type">

`getAuthTokenInfo(): Promise<AuthTokenInfo>`

```tsx
export type AuthTokenInfo = { idToken: string }
```

</TabItem>

</Tabs>

#### Sample response

```json
{
  "iat": 1661158877,
  "issuer": "<issuer-name>",
  "audience": "https://requesting.website",
  "wallets": [
    {
      "address": "0x809d4310d578649d8539e718030ee11e603ee8f3",
      "type": "ethereum"
    }
  ],
  "exp": 1661245277
}
```

</TabItem>

</Tabs>

### Error handling

```javascript
try {
  const { idToken } = await web3auth.getAuthTokenInfo()
  // Use the token
} catch (error) {
  // Handle errors (e.g., user not connected, network issues)
  console.error('Authentication failed:', error)
}
```

---

## getUserInfo

Function to retrieve information about the connected user.

:::note

This function will only return information based on the connected adapter. These details are not stored anywhere and are fetched from the adapter during the connection and remain in the session.

:::

:::info

Please note that this function doesn't work for external wallet logins. It only works for social login embedded wallets.

:::

### Usage

```javascript
// After successful login
const userInfo = await web3auth.getUserInfo()
console.log(userInfo)
```

### Return type

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Type Declarations", value: "type" },
  ]}
>

<TabItem value="table">

| Property            | Type    | Description                                                                                        |
| ------------------- | ------- | -------------------------------------------------------------------------------------------------- |
| `email`             | string  | Email of the user.                                                                                 |
| `name`              | string  | Name of the user.                                                                                  |
| `profileImage`      | string  | Profile image of the user.                                                                         |
| `aggregateVerifier` | string  | Aggregate verifier of the user.                                                                    |
| `verifier`          | string  | Verifier of the user.                                                                              |
| `verifierId`        | string  | Verifier ID of the user.                                                                           |
| `typeOfLogin`       | string  | Type of login provider.                                                                            |
| `dappShare`         | string  | Dapp share of the user.                                                                            |
| `idToken`           | string  | token issued by Web3Auth.                                                                          |
| `oAuthIdToken`      | string  | token issued by OAuth provider. Will be available only if you are using custom connections.        |
| `oAuthAccessToken`  | string  | Access token issued by OAuth provider. Will be available only if you are using custom connections. |
| `appState`          | string  | App state of the user.                                                                             |
| `touchIDPreference` | string  | Touch ID preference of the user.                                                                   |
| `isMfaEnabled`      | boolean | Whether Multi Factor Authentication is enabled for the user.                                       |

</TabItem>

<TabItem value="type">

```typescript
getUserInfo(): Promise<Partial<AuthUserInfo>>;

type AuthUserInfo = {
  email?: string;
  name?: string;
  profileImage?: string;
  aggregateVerifier?: string;
  verifier: string;
  verifierId: string;
  typeOfLogin: LOGIN_PROVIDER_TYPE | CUSTOM_LOGIN_PROVIDER_TYPE;
  dappShare?: string;
  /**
   * Token issued by Web3Auth.
   */
  idToken?: string;
  /**
   * Token issued by OAuth provider. Will be available only if you are using
   * custom verifiers.
   */
  oAuthIdToken?: string;
  /**
   * Access tTken issued by OAuth provider. Will be available only if you are using
   * custom verifiers.
   */
  oAuthAccessToken?: string;
  appState?: string;
  touchIDPreference?: string;
  isMfaEnabled?: boolean;
};
```

</TabItem>
</Tabs>

### Sample response

```json
{
  "email": "john@gmail.com",
  "name": "John Dash",
  "profileImage": "https://lh3.googleusercontent.com/a/Ajjjsdsmdjmnm...",
  "aggregateVerifier": "tkey-google-lrc",
  "verifier": "torus",
  "verifierId": "john@gmail.com",
  "typeOfLogin": "google",
  "dappShare": "<24 words seed phrase>", // will be sent only incase of custom verifiers
  "idToken": "<jwtToken issued by Web3Auth>",
  "oAuthIdToken": "<jwtToken issued by OAuth Provider>", // will be sent only incase of custom verifiers
  "oAuthAccessToken": "<accessToken issued by OAuth Provider>" // will be sent only incase of custom verifiers
}
```

---

## logout

Function to disconnect from Web3Auth.

### Usage

```tsx
function LogoutButton() {
  const handleLogout = async () => {
    try {
      await web3auth.logout()
      console.log('Logged out successfully')
    } catch (error) {
      console.error('Error logging out:', error)
    }
  }

  return <button onClick={handleLogout}>Logout</button>
}
```

### Function signature

```tsx
logout(options?: { cleanup: boolean }): Promise<void>;
```

#### Parameters

- **options** (optional)
- **cleanup** (`boolean`): Whether to remove all user data during logout.

#### Return value

Promise that resolves when the user is successfully logged out.

---

## Using PnP Web Modal SDK(Usage)

#### `manageMFA()`

You can redirect users to the Embedded Wallets account dashboard to manage their MFA settings by calling the `manageMFA()` function. This method ensures that identity details are injected into the dashboard internally for custom connection-based dapps. In order to see what's present on the account dashboard, please refer to the [Account Dashboard](/embedded-wallets/features/user-account-dashboard).

:::info

Please note that this function doesn't work for external wallet logins. It only works for social login embedded wallets.

:::

```javascript
await web3auth.manageMFA()
```

#### Interface

```typescript
manageMFA<T>(loginParams?: T): Promise<void>;
```

- **`loginParams` (optional):** Optional parameters to include during the MFA management process.
- **Returns:** A `Promise<void>` indicating successful redirection to the Account Dashboard.

:::tip

If MFA is not already enabled, the `manageMFA()` method will throw an error. Ensure you use `enableMFA()` before calling `manageMFA()`.

If your dapp uses default dashboard connections, users can directly log in to the account dashboard to manage MFA. For custom connection-based dapps, the `manageMFA()` method must be used.

:::

---

## showCheckout

Function to show the cryptocurrency checkout modal, allowing users to select their local currency and specify the token to top up their wallet.

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this SDK in a production environment is the **Scale Plan**. You can use this feature in Web3Auth Sapphire Devnet network for free.

:::

:::info

Please note that this function doesn't work for external wallet logins. It only works for social login embedded wallets.

:::

### Usage

```ts
await web3auth.showCheckout({
  show: true,
}) // Opens the TopUp modal
```

### Parameters

| Name                    | Description                                                                                                                                                                                                                                                                                                              |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `receiveWalletAddress?` | Specifies the recipient's address. By default, it is set to the currently connected address.                                                                                                                                                                                                                             |
| `tokenList?`            | Specifies the tokens to display in the list. By default, all tokens are shown. Use the ticker name to specify which tokens to display, such as `[USDC, USDT, ETH]`. Please checkout the coverage details for [full list of supported networks and tokens](/embedded-wallets/features/funding#network-coverage).          |
| `fiatList?`             | Specifies the available fiat currencies enabled for purchase. Use the currency acronym to define which fiat currencies to display, such as `[USD, SGD, INR, JPY]`. Please checkout the coverage details for [full list of supported currencies](/embedded-wallets/features/funding#country-and-payment-method-coverage). |
| `show`                  | Determines whether the checkout UI is displayed. This can be used to programmatically control its visibility.                                                                                                                                                                                                            |

### Supported cryptocurrencies

To checkout the supported cryptocurrencies and networks, [checkout the coverage documentation](/embedded-wallets/features/funding#fiat-on-ramp-coverage).

---

## showSwap

Function to open the swap interface using the Wallet Services plugin.

:::info

Please note that this function doesn't work for external wallet logins. It only works for social login embedded wallets.

:::

### Usage

```ts
await web3auth.showSwap({
  show: true,
}) // Opens the Swap Modal
```

### Parameters

| Name         | Type      | Description                                                                                                  |
| ------------ | --------- | ------------------------------------------------------------------------------------------------------------ |
| `show`       | `boolean` | Controls whether the swap UI is visible. Set to `true` to display the swap interface, or `false` to hide it. |
| `fromToken?` | `string`  | Specifies the token being swapped from. Optional field.                                                      |
| `toToken?`   | `string`  | Specifies the token being swapped to. Optional field.                                                        |
| `fromValue?` | `string`  | The amount of the `fromToken` to be swapped. Optional field.                                                 |
| `toAddress?` | `string`  | The recipient's address for the `toToken`. Optional field.                                                   |

### Return type

```ts
Promise<void>
```

The function returns a Promise that resolves when the swap modal is successfully displayed.

---

## showWalletConnectScanner

Function to show the WalletConnect QR scanner using the Wallet Services plugin.

:::info

Please note that this function doesn't work for external wallet logins. It only works for social login embedded wallets.

:::

### Usage

```ts

// After initializing and logging in with Web3Auth
async function openWalletConnectScanner() {
  try {
    await web3auth.showWalletConnectScanner({
      show: true,
    })
  } catch (error) {
    console.error('Error opening WalletConnect scanner:', error)
  }
}
```

### Parameters

```ts
interface ShowWalletConnectScannerParams {
  show: boolean
}
```

#### `show`

`boolean`

Determines whether the Wallet Connect UI is displayed. This can be used to programmatically control its visibility.

### Return type

`Promise<void>`

The function returns a promise that resolves when the WalletConnect scanner has been displayed or hidden.

---

## showWalletUI

Function to show the templated wallet UI services modal using the Wallet Services plugin.

:::info

Please note that this function doesn't work for external wallet logins. It only works for social login embedded wallets.

:::

### Usage

```javascript
// Open the Wallet UI modal
await web3auth.showWalletUi({
  show: true,
})
```

### Parameters

```javascript
interface ShowWalletUIParams {
  show: boolean;
  path?: string;
}
```

#### `show`

`boolean`

Determines whether the wallet UI is displayed. This can be used to programmatically control its visibility.

#### `path`

`string?` (optional)

Specifies the path for the Wallet Services.

---

## switchChain

Function to switch blockchain networks with Web3Auth.

## Usage

```javascript
await web3auth.switchChain({ chainId: '0xaa36a7' })
```

## Parameters

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Function Definition", value: "definition" },
  ]}
>

<TabItem value="table">

| Parameter             | Description                                                                | Type   | Required |
| --------------------- | -------------------------------------------------------------------------- | ------ | -------- |
| `{ chainId: string }` | Chain ID of the chain to switch to, for example, `{ chainId: "0xaa36a7" }` | Object | Yes      |

</TabItem>

<TabItem value="definition">

```tsx
async switchChain(params: { chainId: string }): Promise<void> {
    if (this.status !== ADAPTER_STATUS.CONNECTED || !this.connectedAdapterName) throw WalletLoginError.notConnectedError(`No wallet is connected`);
    return this.walletAdapters[this.connectedAdapterName].switchChain(params);
}
```

</TabItem>

</Tabs>

## Example

```javascript title="switchChain.js"
async function onConnected() {
  const chains = web3auth.coreOptions.chains ?? []
  const chainId = web3auth.currentChainId
  // Update UI with chainId and available chains
}

// Initialize Web3Auth first
await web3auth.init()

// Switch to Sepolia Testnet
try {
  await web3auth.switchChain({ chainId: '0xaa36a7' })
  await onConnected()
  console.log('Successfully switched to Sepolia Testnet')
} catch (error) {
  console.error('Error switching chain:', error)
}
```

---

## Embedded Wallets SDK for Node.js

## Overview

The MetaMask Embedded Wallets Node.js SDK (formerly Web3Auth Plug and Play) is a backend solution designed for server-side authentication and key management. This SDK integrates web3 authentication into backend applications, AI agents, and programmatic use cases.

Unlike frontend SDKs, the Node.js SDK is **stateless and sessionless**, making it ideal for:

- Backend AI agents
- Server-side wallet operations
- Programmatic blockchain interactions
- Custodial wallet services, without key management and recovery worries.

## Key features

- **Stateless architecture:** No session management required
- **Multi-chain support:** Support for EVM chains, Solana, and other blockchains
- **Custom authentication:** Mandatory custom auth with single key share
- **Private key access:** Direct access to private keys for any blockchain
- **Backend-optimized:** Designed specifically for server environments

## Requirements

- Node.js 22+
- npm 10+
- Custom authentication setup (mandatory)
- Embedded Wallets dashboard project configuration

## Prerequisites

- Registered on the [Embedded Wallets dashboard](https://developer.metamask.io/)
- Set up a custom **Auth connection** (mandatory for Node.js SDK)

:::tip

See the [dashboard setup](../../dashboard/README.mdx) guide to learn more.

:::

## Installation

Install the Web3Auth Node SDK

```bash npm2yarn
npm install --save @web3auth/node-sdk
```

### 1. Custom authentication setup (required)

The Node.js SDK **only supports custom authentication**. You must create a custom auth connection:

1. Go to the [Embedded Wallets dashboard](https://developer.metamask.io/).
2. Select your project.
3. Navigate to **Authentication** → **Custom connections**.
4. Click **Create connections**.
5. Configure your auth connection with your custom JWT details.

:::info

You can refer to the [Custom JWT Setup](/embedded-wallets/authentication/custom-connections/custom-jwt/) guide to learn more.

:::

### 2. SDK configuration

Create a Web3Auth instance with your client ID, web3auth network name, and chain information:

```javascript
const { Web3Auth } = require('@web3auth/node-sdk')

const web3auth = new Web3Auth({
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable // Get your Client ID from MetaMask Developer Dashboard
  web3AuthNetwork: 'sapphire_mainnet', // or 'sapphire_devnet'
})
```

:::note

Chain configuration comes from your [Embedded Wallets dashboard](https://developer.metamask.io/) project.
You can optionally pass a `chains` array in the constructor to add or override dashboard chains.
Use `defaultChainId` to select which chain is active after `connect()`.
If no chains are configured in the dashboard or constructor, `init()` throws an error.

:::

### 3. Initialize Embedded Wallets

Initialize the Web3Auth instance during your application startup:

```javascript
await web3auth.init()
```

### 4. Authenticate users

Use the connect method with your custom authentication parameters:

```javascript
const result = await web3auth.connect({
  authConnectionId: 'YOUR_AUTH_CONNECTION_ID', // Your custom authentication connection name
  idToken: 'USER_ID_TOKEN', // JWT token from your auth system
})
```

## Configuration options

<Tabs
  defaultValue="basic-config"
  values={[
    { label: "Basic Configuration", value: "basic-config" },
    { label: "Advanced Configuration", value: "advanced-config" },
  ]}
>

<TabItem value="basic-config">

```javascript
const { Web3Auth } = require('@web3auth/node-sdk')

const web3auth = new Web3Auth({
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable
  web3AuthNetwork: 'sapphire_mainnet', // or 'sapphire_devnet'
})

await web3auth.init()
```

</TabItem>

<TabItem value="advanced-config">

```javascript
const { Web3Auth } = require('@web3auth/node-sdk')

const web3auth = new Web3Auth({
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable
  web3AuthNetwork: 'sapphire_mainnet', // or 'sapphire_devnet'
  defaultChainId: '0x1', // or '0x89' for Polygon
  enableLogging: true,
})

await web3auth.init()
```

</TabItem>

</Tabs>

## Configuration parameters

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Interface", value: "interface" },
  ]}
>

<TabItem value="table">

| Parameter         | Type      | Default             | Description                                                                                                                               |
| ----------------- | --------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `clientId`        | `string`  | Required            | Your Web3Auth client ID                                                                                                                   |
| `web3AuthNetwork` | `string`  | `sapphire_mainnet`  | Network: `sapphire_mainnet` or `sapphire_devnet`                                                                                          |
| `authBuildEnv`    | `string`  | `production`        | Build environment for fetching project configuration                                                                                      |
| `defaultChainId`  | `string`  | Optional            | Chain ID to use for the default chain (for example, `0x1` for Ethereum). If not provided, the first chain in the list is used.            |
| `chains`          | `object`  | Optional            | Chain configurations to add or override dashboard chains. Merged with dashboard config; constructor values take precedence per `chainId`. |
| `enableLogging`   | `boolean` | `false`             | Setting to true will enable logs                                                                                                          |
| `usePnPKey`       | `boolean` | `false`             | Setting to true returns the same key as the web SDK (Plug and Play key). Default returns an SFA key.                                      |
| `useDKG`          | `boolean` | `false` on Sapphire | Setting to true generates keys/shares via a DKG network. Always true on legacy networks.                                                  |
| `checkCommitment` | `boolean` | `true`              | Setting to true checks the commitment of the shares                                                                                       |

</TabItem>

<TabItem value="interface">

```typescript

export interface Web3AuthOptions {
  /**
   * Client id for web3auth.
   * You can obtain your client id from the web3auth developer dashboard.
   * You can set any random string for this on localhost.
   */
  clientId: string

  /**
   * Web3Auth Network to use for login
   * @defaultValue sapphire_mainnet
   */
  web3AuthNetwork?: WEB3AUTH_NETWORK_TYPE

  /**
   * Build environment for fetching project configuration
   * @defaultValue production
   */
  authBuildEnv?: BUILD_ENV_TYPE

  /**
   * multiple chain configurations,
   * only provided chains will be used
   */
  chains?: CustomChainConfig[]

  /**
   * default chain Id to use
   */
  defaultChainId?: string

  /**
   * setting to true will enable logs
   *
   * @defaultValue false
   */
  enableLogging?: boolean

  /**
   * setting this to true returns the same key as web sdk (i.e., plug n play key)
   * By default, this sdk returns SFAKey
   */
  usePnPKey?: boolean

  /**
   * set this to true when you wants keys/shares to be generated by a dkg network
   *
   * Default:- false for sapphire network and always true for legacy networks.
   * Legacy networks doesnt support non dkg flow. So this is always true for legacy networks.
   */
  useDKG?: boolean

  /**
   * setting this to true will check the commitment of the shares
   *
   * @defaultValue true
   */
  checkCommitment?: boolean
}
```

</TabItem>

</Tabs>

## Usage

```javascript
// focus-start
const { Web3Auth } = require('@web3auth/node-sdk')
// focus-end

// Dashboard Registration
const clientId =
  'BPi5PB_UiIZ-cPz1GtV5i1I2iOSOHuimiXBI0e-Oe_u6X3oVAbCiAZOTEBtTXw4tsluTITPqA8zMsfxIKMjiqNQ'

// Auth connection
const authConnectionId = 'w3a-node-demo'

// focus-start
const web3auth = new Web3Auth({
  clientId,
  web3AuthNetwork: 'sapphire_mainnet',
})

await web3auth.init()
// focus-end

const privateKey = await fs.readFile('privateKey.pem', 'utf8')

var idToken = jwt.sign(
  {
    sub: '9fcd68c4-af50-4dd7-adf6-abd12a13cb32',
    name: 'Web3Auth DevRel Team',
    email: 'devrel@web3auth.io',
    aud: 'urn:api-web3auth-io', // -> to be used in Custom Authentication as JWT Field
    iss: 'https://web3auth.io', // -> to be used in Custom Authentication as JWT Field
    iat: Math.floor(Date.now() / 1000),
    exp: Math.floor(Date.now() / 1000) + 60 * 60,
  },
  privateKey,
  { algorithm: 'RS256', keyid: '2ma4enu1kdvw5bo9xsfpi3gcjzrt6q78yl0h' }
)

console.log('\x1b[33m%s\x1b[0m', 'JWT Token:', idToken)

// focus-start
const result = await web3auth.connect({
  authConnectionId,
  idToken,
})
// focus-end
```

---

## Blockchain connection

The Embedded Wallets Node SDK supports multiple blockchain networks through different integration methods. On a successful connection, it returns a `result` object containing the provider/ signer for blockchain operations.

By default you get the standard Web3Auth provider, with the ability to get the private key, if enabled from the dashboard. You additionally get the signer for EVM and Solana chains, to be able to do transactions without the need to use the private key provider directly.

### Object structure

```typescript

export type PrivateKeyProvider = IBaseProvider<string>

export type WalletResult =
  | {
      chainNamespace: typeof CHAIN_NAMESPACES.SOLANA
      provider: PrivateKeyProvider
      signer: TransactionSigner
    }
  | {
      chainNamespace: typeof CHAIN_NAMESPACES.EIP155
      provider: PrivateKeyProvider
      signer: WalletClient
    }
  | {
      chainNamespace: typeof CHAIN_NAMESPACES.OTHER
      provider: PrivateKeyProvider
      signer: null
    }
```

### EVM chains

For EVM-compatible chains such as Ethereum, Polygon, BSC.

`connect()` returns a viem `WalletClient` as `result.signer`:

```javascript
const { createPublicClient, formatEther, http } = require('viem')

// Get Ethereum account
const getAccounts = async signer => {
  try {
    // focus-next-line
    const address = signer.account.address
    console.log('\x1b[33m%s\x1b[0m', 'Accounts:', address)
  } catch (error) {
    console.error('\x1b[33m%s\x1b[0m', 'Error fetching accounts:', error)
  }
}

// Get Ethereum balance
const getBalance = async signer => {
  try {
    // focus-start
    const address = signer.account.address
    const publicClient = createPublicClient({
      chain: signer.chain,
      transport: http(),
    })
    const balance = formatEther(await publicClient.getBalance({ address }))
    // focus-end
    console.log('\x1b[33m%s\x1b[0m', 'Balance:', balance, 'ETH')
  } catch (error) {
    console.error('\x1b[33m%s\x1b[0m', 'Error fetching balance:', error)
  }
}

// Sign Ethereum message
const signMessage = async (signer, message) => {
  try {
    // focus-next-line
    const signature = await signer.signMessage({ message })
    console.log('\x1b[33m%s\x1b[0m', 'Signed Message:', signature)
  } catch (error) {
    console.error('\x1b[33m%s\x1b[0m', 'Error signing message:', error)
  }
}

await getAccounts(result.signer) // Get Ethereum accounts
await getBalance(result.signer) // Get Ethereum balance
await signMessage(result.signer, 'Hello Web3Auth!') // Sign a message
```

### Solana integration

Access Solana wallet functionality:

```javascript
const { LAMPORTS_PER_SOL, Connection, PublicKey } = require('@solana/web3.js')
const { createSignableMessage } = require('@solana/signers')

// Get Solana Accounts
const getAccounts = async signer => {
  try {
    // focus-next-line
    const publicKey = signer.address
    console.log('\x1b[33m%s\x1b[0m', 'Public Key:', publicKey)
  } catch (error) {
    console.error('\x1b[33m%s\x1b[0m', 'Error fetching accounts:', error)
  }
}

// Get Solana Balance
const getBalance = async signer => {
  try {
    // focus-start
    const publicKey = new PublicKey(signer.address)
    const connection = new Connection('https://api.devnet.solana.com')
    const balance = (await connection.getBalance(publicKey)) / LAMPORTS_PER_SOL
    // focus-end
    console.log('\x1b[33m%s\x1b[0m', 'Balance:', balance, 'SOL')
  } catch (error) {
    console.error('\x1b[33m%s\x1b[0m', 'Error fetching balance:', error)
  }
}

// Sign Solana Message
const signMessage = async (signer, message) => {
  try {
    // focus-start
    const messageBytes = new TextEncoder().encode(message)

    // Create a SignableMessage object from Uint8Array
    const signableMessage = createSignableMessage(messageBytes)

    const [signature] = await signer.signMessages([signableMessage])
    // focus-end
    console.log('\x1b[33m%s\x1b[0m', 'Signed Message:', signature)
  } catch (error) {
    console.error('\x1b[33m%s\x1b[0m', 'Error signing message:', error)
  }
}

await getAccounts(result.signer) // Get Solana Accounts
await getBalance(result.signer) // Get Solana Balance
await signMessage(result.signer, 'Hello Web3Auth!') // Sign a Message
```

---

## Connect

## Overview

The `connect` method is the primary authentication method for the Node.js SDK. It authenticates users using custom authentication and returns a result object containing the provider/ signer for blockchain operations.

:::warning Prerequisites

- Custom authentication set up on the dashboard.
- Freshly generated JWT token from your authentication system in your backend.

Read more about [custom authentication](/embedded-wallets/authentication/custom-connections/custom-jwt/).

:::

## Usage

```javascript
const result = await web3auth.connect(loginParams)
```

## Parameters

### LoginParams

```typescript
export type LoginParams = {
  idToken: string
  authConnectionId: string
  userId?: string
  userIdField?: string
  isUserIdCaseSensitive?: boolean
  groupedAuthConnectionId?: string
}
```

| Parameter                  | Type      | Description                                                                               |
| -------------------------- | --------- | ----------------------------------------------------------------------------------------- |
| `authConnectionId`         | `string`  | Custom verifier name from Embedded Wallets dashboard.                                     |
| `userId`                   | `string`  | Unique identifier for the user (for example, email, user ID).                             |
| `idToken?`                 | `string`  | Valid JWT token from your authentication system.                                          |
| `groupedAuthConnectionId?` | `string`  | Grouped Auth Connection ID.                                                               |
| `userIdField?`             | `string`  | User's unique identifier field name. Add here if not set on the dashboard.                |
| `isUserIdCaseSensitive?`   | `boolean` | Whether the user ID field is case sensitive or not. Add here if not set on the dashboard. |

## Return value

Returns a `result` object containing the provider/ signer for blockchain operations. By default you get the standard Web3Auth provider, with the ability to get the private key, if enabled from the dashboard. You additionally get the signer for EVM and Solana chains, to be able to do transactions without the need to use the private key provider directly.

### Object structure

```typescript

export type PrivateKeyProvider = IBaseProvider<string>

export type WalletResult =
  | {
      chainNamespace: typeof CHAIN_NAMESPACES.SOLANA
      provider: PrivateKeyProvider
      signer: TransactionSigner
    }
  | {
      chainNamespace: typeof CHAIN_NAMESPACES.EIP155
      provider: PrivateKeyProvider
      signer: WalletClient
    }
  | {
      chainNamespace: typeof CHAIN_NAMESPACES.OTHER
      provider: PrivateKeyProvider
      signer: null
    }
```

## Examples

### Custom JWT token authentication

```javascript
const { Web3Auth } = require('@web3auth/node-sdk')

// Dashboard Registration
const clientId =
  'BPi5PB_UiIZ-cPz1GtV5i1I2iOSOHuimiXBI0e-Oe_u6X3oVAbCiAZOTEBtTXw4tsluTITPqA8zMsfxIKMjiqNQ'

// focus-start
// Auth Connection
const authConnectionId = 'w3a-node-demo'
// focus-end

const web3auth = new Web3Auth({
  clientId,
  web3AuthNetwork: 'sapphire_mainnet',
})

await web3auth.init()

// focus-start
const privateKey = await fs.readFile('privateKey.pem', 'utf8')

var idToken = jwt.sign(
  {
    sub: '9fcd68c4-af50-4dd7-adf6-abd12a13cb32',
    name: 'Web3Auth DevRel Team',
    email: 'devrel@web3auth.io',
    aud: 'urn:api-web3auth-io', // -> to be used in Custom Authentication as JWT Field
    iss: 'https://web3auth.io', // -> to be used in Custom Authentication as JWT Field
    iat: Math.floor(Date.now() / 1000),
    exp: Math.floor(Date.now() / 1000) + 60 * 60,
  },
  privateKey,
  { algorithm: 'RS256', keyid: '2ma4enu1kdvw5bo9xsfpi3gcjzrt6q78yl0h' }
)

console.log('\x1b[33m%s\x1b[0m', 'JWT Token:', idToken)

const result = await web3auth.connect({
  authConnectionId,
  idToken,
})
// focus-end
```

### Firebase authentication

```javascript
const { Web3Auth } = require('@web3auth/node-sdk')

// Dashboard Registration
const clientId =
  'BPi5PB_UiIZ-cPz1GtV5i1I2iOSOHuimiXBI0e-Oe_u6X3oVAbCiAZOTEBtTXw4tsluTITPqA8zMsfxIKMjiqNQ'

// focus-start
// Auth Connection
const authConnectionId = 'w3a-firebase-demo'
// focus-end

const web3auth = new Web3Auth({
  clientId,
  web3AuthNetwork: 'sapphire_mainnet',
})

await web3auth.init()

// focus-start
const app = initializeApp({
  apiKey: 'AIzaSyB0nd9YsPLu-tpdCrsXn8wgsWVAiYEpQ_E',
  authDomain: 'web3auth-oauth-logins.firebaseapp.com',
  projectId: 'web3auth-oauth-logins',
  storageBucket: 'web3auth-oauth-logins.appspot.com',
  messagingSenderId: '461819774167',
  appId: '1:461819774167:web:e74addfb6cc88f3b5b9c92',
})

const auth = getAuth(app)
const res = await signInWithEmailAndPassword(auth, 'custom+jwt@firebase.login', 'Testing@123')
console.log(res)
const idToken = await res.user.getIdToken(true)

console.log('\x1b[33m%s\x1b[0m', 'JWT Token:', idToken)

const result = await web3auth.connect({
  authConnectionId,
  idToken,
})
// focus-end
```

---

## Examples(Node)

<ExampleCards exampleMap={pnpNodeExamples} />

---

## Private key access

## Overview

The Node.js SDK provides direct access to user private keys, enabling integration with any blockchain network. This is a key feature that makes the SDK suitable for backend and programmatic use cases. Note that if the private key export is disabled in the dashboard, the methods will throw an error.

:::warning Security Notice

Private keys provide full control over user assets. Handle them securely:

- Never log private keys
- Store them encrypted if persistence is needed
- Use secure memory handling
- Implement proper access controls

:::

## Available methods

The provider offers different methods to access private keys depending on your blockchain needs:

| Method              | Description                    | Use Case                                         |
| ------------------- | ------------------------------ | ------------------------------------------------ |
| `private_key`       | Ethereum-formatted private key | EVM chains (for example, Ethereum, Polygon, BSC) |
| `solana_privateKey` | Solana private key             | Solana blockchain                                |

## EVM chains

For EVM-compatible chains such as Ethereum, Polygon, BSC.

### Get Ethereum private key

```javascript
const privateKey = await provider.request({ method: 'private_key' })
console.log('Private Key:', privateKey) // 0x1234567890abcdef...
```

### Use with Ethers.js

```javascript
const { ethers } = require('ethers')

// Get private key
const privateKey = await provider.request({ method: 'private_key' })

// Create wallet instance
const wallet = new ethers.Wallet(privateKey)

// Connect to a provider
const rpcProvider = new ethers.JsonRpcProvider('https://rpc.ankr.com/eth')
const connectedWallet = wallet.connect(rpcProvider)

// Get address
const address = await connectedWallet.getAddress()
console.log('Wallet Address:', address)

// Sign a transaction
const tx = {
  to: '0x742d35Cc6635C0532925a3b8138341B0F7E8a4e8',
  value: ethers.parseEther('0.1'),
}

const signedTx = await connectedWallet.signTransaction(tx)
const receipt = await connectedWallet.sendTransaction(tx)
```

### Use with Viem

```javascript
const { createWalletClient, createPublicClient, http, parseEther } = require('viem')
const { privateKeyToAccount } = require('viem/accounts')
const { mainnet } = require('viem/chains')

// Get private key
const privateKey = await provider.request({ method: 'private_key' })

// Create account from private key
const account = privateKeyToAccount(privateKey)

// Create wallet client
const walletClient = createWalletClient({
  account,
  chain: mainnet,
  transport: http('https://rpc.ankr.com/eth'),
})

// Create public client for reading
const publicClient = createPublicClient({
  chain: mainnet,
  transport: http('https://rpc.ankr.com/eth'),
})

// Send transaction
const hash = await walletClient.sendTransaction({
  to: '0x742d35Cc6635C0532925a3b8138341B0F7E8a4e8',
  value: parseEther('0.1'),
})
```

## Solana integration

### Get Solana private key

```javascript
const solana_privateKey = await provider.request({ method: 'solana_privateKey' })
console.log('Solana Private Key:', solana_privateKey) // Base58 encoded
```

### Use with Solana web3.js

```javascript
const {
  Connection,
  Keypair,
  PublicKey,
  Transaction,
  SystemProgram,
  LAMPORTS_PER_SOL,
} = require('@solana/web3.js')
const bs58 = require('bs58')

// Get private key
const solana_privateKey = await provider.request({ method: 'solana_privateKey' })

// Create keypair from private key
const secretKey = bs58.decode(solana_privateKey)
const keypair = Keypair.fromSecretKey(secretKey)

// Connect to Solana
const connection = new Connection('https://api.mainnet-beta.solana.com')

// Get balance
const balance = await connection.getBalance(keypair.publicKey)
console.log('Balance:', balance / LAMPORTS_PER_SOL, 'SOL')

// Send transaction
const transaction = new Transaction().add(
  SystemProgram.transfer({
    fromPubkey: keypair.publicKey,
    toPubkey: new PublicKey('11111111111111111111111111111112'),
    lamports: 0.1 * LAMPORTS_PER_SOL,
  })
)

const signature = await connection.sendTransaction(transaction, [keypair])
```

## Other blockchains

### Get raw private key

```javascript
const rawPrivateKey = await provider.request({ method: 'private_key' })
console.log('Raw Private Key:', rawPrivateKey) // Hex string
```

### Example: Bitcoin integration

```javascript
const bitcoin = require('bitcoinjs-lib')

// Get raw private key
const rawPrivateKey = await provider.request({ method: 'private_key' })

// Create Bitcoin keypair
const keyPair = bitcoin.ECPair.fromPrivateKey(Buffer.from(rawPrivateKey.slice(2), 'hex'))

// Get Bitcoin address
const { address } = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey })
console.log('Bitcoin Address:', address)
```

## Disabling private key export

Private key export can be disabled in the [Embedded Wallets dashboard](https://developer.metamask.io):

1. Go to your project settings.
2. Navigate to **Advanced Settings**.
3. Toggle **Disable Private Key Export**.
4. Save changes.

When disabled, private key methods will throw an error:

```javascript
try {
  const privateKey = await provider.request({ method: 'private_key' })
} catch (error) {
  console.error('Private key export disabled:', error.message)
}
```

---

## Embedded Wallets SDK for React

## Overview

MetaMask Embedded Wallets SDK (formerly Web3Auth Plug and Play) provides authentication
for React applications with social logins, external wallets, and more. React hooks
simplify how you connect users to their preferred wallets and manage authentication state.

For a complete working project, see the
[React quick start example](https://github.com/Web3Auth/web3auth-examples/tree/main/quick-starts/react-quick-start)
on GitHub.

:::info Migration from v9 or v10

Use the [Web SDK v11 migration guide](/embedded-wallets/migration-guides/web). It includes an LLM agent prompt, a full v9/v10-to-v11 API map, and step-by-step changes for `@web3auth/modal/react`.

:::

## Requirements

- This is a frontend SDK and must be used in a browser environment
- Node.js 22+ and npm 10+
- Basic knowledge of JavaScript and React

## Prerequisites

- Set up your project on the [Embedded Wallets dashboard](https://developer.metamask.io/)

:::tip

See the [dashboard setup](../../dashboard/README.mdx) guide to learn more.

:::

## Installation

Install the Web3Auth Modal SDK and Wagmi dependencies:

```bash npm2yarn
npm install --save @web3auth/modal wagmi@3 @tanstack/react-query
```

### 1. Configuration

Create a configuration file with your Client ID and Sapphire network from the
[Embedded Wallets dashboard](https://developer.metamask.io/).

Use **Sapphire Devnet** for local development (`http://localhost`). Sapphire Mainnet does not allow
localhost origins.

```tsx title="web3authContext.tsx"

const clientId = import.meta.env.VITE_WEB3AUTH_CLIENT_ID // or your env prefix

const web3AuthContextConfig: Web3AuthContextConfig = {
  web3AuthOptions: {
    clientId,
    web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_DEVNET, // use SAPPHIRE_MAINNET in production
  },
}

export default web3AuthContextConfig
```

### 2. Set up providers

In your main entry file (`main.tsx` or `index.tsx`), wrap your app with `Web3AuthProvider`,
`QueryClientProvider`, and the Embedded Wallets `WagmiProvider`:

```tsx title="main.tsx"

const queryClient = new QueryClient()

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
  <Web3AuthProvider config={web3AuthContextConfig}>
    <QueryClientProvider client={queryClient}>
      <WagmiProvider>
        <App />
      </WagmiProvider>
    </QueryClientProvider>
  </Web3AuthProvider>
)
```

### 3. Connect users

Use [`useWeb3AuthConnect`](./hooks/useWeb3AuthConnect.mdx) to open the pre-built modal or connect to a
specific login method:

```tsx title="App.tsx"

function App() {
  const { connect, loading, isConnected, error } = useWeb3AuthConnect()
  const { disconnect } = useWeb3AuthDisconnect()
  const { address } = useConnection()

  if (!isConnected) {
    return (
      <button onClick={() => connect()} disabled={loading}>
        {loading ? 'Connecting...' : 'Login'}
      </button>
    )
  }

  return (
    
      {address}
      <button onClick={() => disconnect()}>Log out</button>
    
  )
}
```

## Advanced configuration

The Web3Auth Modal SDK offers a rich set of advanced configuration options:

- **[Smart accounts](./advanced/smart-accounts.mdx):** Configure account abstraction parameters.
- **[Custom authentication](./advanced/custom-authentication.mdx):** Define authentication methods.
- **[Whitelabeling and UI customization](./advanced/whitelabel.mdx):** Personalize the modal's appearance.
- **[Multi-Factor Authentication (MFA)](./advanced/mfa.mdx):** Set up and manage MFA.
- **[Wallet Services](./advanced/wallet-services.mdx):** Integrate additional Wallet Services.

:::tip

See the [advanced configuration](./advanced/README.mdx) section to learn more about each configuration option.

:::

<Tabs
  defaultValue="basic-config"
  values={[
    { label: "Basic Configuration", value: "basic-config" },
    { label: "Advanced Configuration", value: "advanced-config" },
  ]}
>

<TabItem value="basic-config">

```ts

const web3AuthContextConfig: Web3AuthContextConfig = {
  web3AuthOptions: {
    clientId: import.meta.env.VITE_WEB3AUTH_CLIENT_ID,
    web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_DEVNET,
  },
}
```

</TabItem>

<TabItem value="advanced-config">

```ts

  WALLET_CONNECTORS,
  WEB3AUTH_NETWORK,
  MFA_LEVELS,
  type Web3AuthOptions,
} from '@web3auth/modal'

const web3AuthOptions: Web3AuthOptions = {
  clientId: import.meta.env.VITE_WEB3AUTH_CLIENT_ID,
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
  modalConfig: {
    connectors: {
      [WALLET_CONNECTORS.AUTH]: {
        label: 'auth',
        loginMethods: {
          google: {
            name: 'google login',
            // logoDark: "url to your custom logo which will shown in dark mode",
          },
          facebook: {
            name: 'facebook login',
            showOnModal: false, // hides the facebook option
          },
          email_passwordless: {
            name: 'email passwordless login',
            showOnModal: true,
            authConnectionId: 'w3a-email_passwordless-demo',
          },
          sms_passwordless: {
            name: 'sms passwordless login',
            showOnModal: true,
            authConnectionId: 'w3a-sms_passwordless-demo',
          },
        },
        showOnModal: true, // set to false to hide all social login methods
      },
    },
    hideWalletDiscovery: true, // set to true to hide external wallets discovery
  },
  mfaLevel: MFA_LEVELS.MANDATORY,
}

const web3AuthContextConfig: Web3AuthContextConfig = {
  web3AuthOptions,
}
```

</TabItem>

</Tabs>

## Blockchain integration

Web3Auth is blockchain agnostic, enabling integration with any blockchain network. Out of the box,
Web3Auth offers robust support for both **Solana** and **Ethereum**, each with dedicated React hooks.

### Solana integration

Solana hooks are included natively within the `@web3auth/modal` package. Install
[`@solana/kit`](https://www.npmjs.com/package/@solana/kit), [`@solana-program/system`](https://www.npmjs.com/package/@solana-program/system), and
[`@solana/react-hooks`](https://www.npmjs.com/package/@solana/react-hooks), then wrap your app with `SolanaProvider`:

```tsx title="main.tsx"

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
  <Web3AuthProvider config={web3AuthContextConfig}>
    <SolanaProvider>
      <App />
    </SolanaProvider>
  </Web3AuthProvider>
)
```

Use hooks from `@web3auth/modal/react/solana`.

For detailed usage and examples, see the [**Solana hooks**](./solana-hooks/README.mdx) section.

### Ethereum integration

Ethereum wallet operations use [Wagmi](https://wagmi.sh/) hooks after the provider setup above.
Configure EVM chains in the [Embedded Wallets dashboard](../../dashboard/chains-and-networks/); no
in-app chain list is required for standard integrations.

For implementation details and examples, refer to the [**Ethereum hooks**](./ethereum-hooks.mdx) section.

## Troubleshooting

### JWT errors

When using custom authentication, you may encounter JWT errors:

- [**Invalid JWT verifiers ID field**](/embedded-wallets/troubleshooting/jwt-errors#invalid-jwt-verifiers-id-field)
- [**Failed to verify JWS signature**](/embedded-wallets/troubleshooting/jwt-errors#failed-to-verify-jws-signature)
- [**Duplicate token**](/embedded-wallets/troubleshooting/jwt-errors#duplicate-token)
- [**Expired token**](/embedded-wallets/troubleshooting/jwt-errors#expired-token)
- [**Mismatch JWT validation field**](/embedded-wallets/troubleshooting/jwt-errors#mismatch-jwt-validation-field)

---

## Advanced configuration(5)

The Embedded Wallets SDK provides extensive configuration options that allow you to customize authentication flows, UI appearance, blockchain integrations, and security features to meet your application's specific requirements.

## Configuration structure

When setting up Web3Auth, you'll create a configuration object that is passed to the `Web3AuthProvider`. This consists of:

```tsx title="web3authContext.tsx"

// focus-start
const web3AuthOptions: Web3AuthOptions = {
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable // Get your Client ID from MetaMask Developer Dashboard
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET, // or WEB3AUTH_NETWORK.SAPPHIRE_DEVNET
  // Core and advanced options go here
}
// focus-end

const web3AuthContextConfig: Web3AuthContextConfig = {
  web3AuthOptions,
}
```

### `Web3AuthOptions`

<Tabs
  defaultValue="basic"
  values={[
    { label: "Basic parameters", value: "basic" },
    { label: "Advanced parameters", value: "advanced" },
    { label: "Interface", value: "interface" },
  ]}
>

<TabItem value="basic">

| Parameter                         | Description                                                                                                                                                                              |
| --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `clientId`                        | (Mandatory) Client ID, available from the [Embedded Wallets dashboard](https://developer.metamask.io).                                                                                   |
| `web3AuthNetwork`                 | (Mandatory) Web3Auth network to use for the session and the issued `idToken`. Default is `sapphire_mainnet`.                                                                             |
| `enableLogging?`                  | Setting to true enables logs. Default is false.                                                                                                                                          |
| `sessionTime?`                    | Session Time (in seconds) for `idToken` issued by Web3Auth for server side verification. Default is 7 days (7 \* 86400). Max value can be 30 days (86400 \* 30) and min can be 1 sec (1) |
| `useSFAKey?`                      | Uses Single Factor Auth SDK key with Web3Auth provider. Default is false.                                                                                                                |
| `storageType?`                    | Setting to `local` persists social login session across browser tabs. Default is `local`.                                                                                                |
| `defaultChainId?`                 | Default chain ID to use. Your first chain will be used as default.                                                                                                                       |
| `multiInjectedProviderDiscovery?` | Whether to enable discovery of injected wallets in the browser. Default is true.                                                                                                         |

</TabItem>

<TabItem value="advanced">

| Parameter                   | Description                                                                                                                                                                                 |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `chains?`                   | Optional in-code chain list. By default, chains are fetched from the [dashboard](/embedded-wallets/dashboard/chains-and-networks/). Pass `chains` only for custom RPC, demos, or overrides. |
| `uiConfig?`                 | (Fetched automatically from dashboard) Config for configuring UI display properties.                                                                                                        |
| `modalConfig?`              | Helps you customize the modal UI elements and authentication methods.                                                                                                                       |
| `accountAbstractionConfig?` | (Fetched automatically from Dashboard) Account abstraction config for your chain namespace.                                                                                                 |
| `useAAWithExternalWallet?`  | (Fetched automatically from Dashboard) Whether to use AA with external wallet.                                                                                                              |
| `walletServicesConfig?`     | (Fetched automatically from Dashboard) Configure any parameter related to Wallet Services plugin                                                                                            |
| `ssr?`                      | Whether to enable SSR mode.                                                                                                                                                                 |
| `mfaSettings?`              | MFA settings for the auth connector.                                                                                                                                                        |
| `mfaLevel?`                 | MFA level for the auth connector.                                                                                                                                                           |
| `privateKeyProvider?`       | Private key provider for your chain namespace.                                                                                                                                              |

</TabItem>

<TabItem value="interface">

```tsx
export interface Web3AuthOptions extends IWeb3AuthCoreOptions {
  /**
   * Config for configuring modal ui display properties
   */
  uiConfig?: Omit<UIConfig, 'connectorListener'>
  /**
   * Config for configuring modal ui display properties
   */
  modalConfig?: ConnectorsModalConfig
}

export interface IWeb3AuthCoreOptions {
  /**
   * Client id for web3auth.
   * You can obtain your client id from the web3auth developer dashboard.
   * You can set any random string for this on localhost.
   */
  clientId: string
  /**
   * multiple chain configurations,
   * only provided chains will be used
   */
  chains?: CustomChainConfig[]
  /**
   * default chain Id to use
   */
  defaultChainId?: string
  /**
   * setting to true will enable logs
   *
   * @defaultValue false
   */
  enableLogging?: boolean
  /**
   * setting to "local" will persist social login session across browser tabs.
   *
   * @defaultValue "local"
   */
  storageType?: 'session' | 'local' | 'cookies'
  /**
   * sessionTime (in seconds) for idToken issued by Web3Auth for server side verification.
   * @defaultValue 7 * 86400
   *
   * Note: max value can be 30 days (86400 * 30) and min can be  1 sec (1)
   */
  sessionTime?: number
  /**
   * Web3Auth Network to use for the session.
   */
  web3AuthNetwork: WEB3AUTH_NETWORK_TYPE
  /**
   * Uses core-kit key with web3auth provider
   * @defaultValue false
   */
  useSFAKey?: boolean
  /**
   * Whitelabel options for web3auth
   */
  uiConfig?: UIConfig
  /**
   * Account abstraction config for your chain namespace
   */
  accountAbstractionConfig?: AccountAbstractionMultiChainConfig
  /**
   * Whether to use AA with external wallet
   */
  useAAWithExternalWallet?: boolean
  /**
   * Connectors to use
   */
  connectors?: ConnectorFn[]
  /**
   * Plugins to use
   */
  plugins?: PluginFn[]
  /**
   * Whether to enable multi injected provider discovery
   * @defaultValue true
   */
  multiInjectedProviderDiscovery?: boolean
  /**
   * Wallet services config
   */
  walletServicesConfig?: WalletServicesConfig
  /**
   * Private key provider for xrpl, mpc cases
   */
  privateKeyProvider?: IBaseProvider<string>
  /**
   * Whether to enable SSR mode
   *
   * @defaultValue false
   */
  ssr?: boolean
  /**
   * Build environment for Auth connector
   * @internal
   * @defaultValue BUILD_ENV.PRODUCTION
   */
  authBuildEnv?: BUILD_ENV_TYPE
  /**
   * MFA settings for the auth connector
   */
  mfaSettings?: MfaSettings
  /**
   * MFA level for the auth connector
   */
  mfaLevel?: MfaLevelType
}
```

</TabItem>

</Tabs>

## Session management

Control how long users stay authenticated and how sessions persist.

**Key Configuration Options:**

- `sessionTime` - Session duration in seconds. Controls how long users remain authenticated before
  needing to log in again.
  - Minimum: 1 second (`1`).
  - Maximum: 30 days (`86400 * 30`).
  - Default: 7 days (`86400 * 7`).
- `storageType` - Storage location for authentication state. Options:
  - `"local"`: Persists across browser tabs and browser restarts (localStorage)
  - `"session"`: Persists only in current tab, cleared when tab closes (sessionStorage)

```tsx
const web3AuthOptions = {
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,

  // Session configuration
  sessionTime: 86400 * 7, // 7 days (in seconds)
  storageType: 'local', // 'local' (persistent across tabs) or 'session' (single tab only)
}
```

## Multi-Factor Authentication (MFA)

Add additional security layers to protect user accounts with two-factor authentication. For detailed
configuration options and implementation examples, see the [Multi-Factor Authentication](./mfa.mdx)
section.

**Key Configuration Options:**

- `mfaSettings` - Configure MFA settings for different authentication flows
- `mfaLevel` - Control when users are prompted to set up MFA

## Custom authentication methods

Control the login options presented to your users and how they're displayed in the modal. For
detailed configuration options and implementation examples, see the
[custom authentication](./custom-authentication.mdx) section.

**Key Configuration Options:**

- `modalConfig` - Define which authentication methods are available and customize their appearance

## UI customization

Customize the brand experience by customizing the Web3Auth Modal to match your application's
design. For complete customization options, refer to the
[whitelabeling and UI customization](./whitelabel.mdx) section.

**Key Configuration Options:**

- `uiConfig` - Personalize the modal's look and feel with custom colors, logos, themes, and more
- `modalConfig` - Control the visibility and arrangement of authentication options

## Smart accounts (account abstraction)

Improve user experience with gasless transactions and advanced account features. Learn more in the
[smart accounts](./smart-accounts.mdx) documentation.

**Key Configuration Options:**

- `accountAbstractionConfig` - Fine-tune parameters for smart account implementation
- `useAAWithExternalWallet` - Enable account abstraction functionality even when users connect with
  external wallets

## Wallet Services

Extend your application with enhanced wallet functionality. See the
[Wallet Services](./wallet-services.mdx) documentation for complete configuration options.

**Key Configuration Options:**

- `walletServicesConfig` - Integrate additional Wallet Services and features

---

## Custom authentication(3)

Custom authentication is a way to authenticate users with your custom authentication service. For example, while authenticating with Google, you can use your own Google Client ID to authenticate users directly.

This feature, with Multi-Factor Authentication (MFA) turned off, can make Embedded Wallets invisible to the end user.

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this
SDK in a production environment is the **Growth Plan**. You can use this feature in Web3Auth
Sapphire Devnet network for free.

:::

## Getting an Auth Connection ID

:::info prerequisite

To enable this, you need to [create a connection](../../../dashboard/authentication.mdx) from the **Authentication** tab of your project from the [Embedded Wallets developer dashboard](https://developer.metamask.io) with your desired configuration.

:::

To configure a connection, you need to provide the particular details of the connection into our Embedded Wallets dashboard. This enables us to map a `authConnectionId` with your connection details. This `authConnectionId` helps us to identify the connection details while initializing the SDK. You can configure multiple connections for the same project, and you can also update the connection details anytime.

:::tip

Learn more about the [auth provider setup](../../../authentication/README.mdx) and the different configurations available for each connection.

:::

## Modal custom authentication

The basic custom authentication is available directly in the modal. You can configure each of the auth providers in the modal to direct to your `authConnectionId`.

:::note

You can only configure implicit login via modal, for JWT-based logins, you need to create your own UI and use the `connectTo` function.

:::

For the modal custom authentication, you need to pass the `modalConfig` object to the `Web3AuthOptions` object within the constructor.

:::tip

Read more about the `modalConfig` object in the [Whitelabel](./whitelabel.mdx) section.

:::

### Usage

<Tabs>
  <TabItem value="Single connections">
    ```tsx title="web3authContext.tsx"

const web3AuthContextConfig: Web3AuthContextConfig = {
  web3AuthOptions: {
    clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable
    web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
    // focus-start
    modalConfig: {
      connectors: {
        [WALLET_CONNECTORS.AUTH]: {
          label: 'auth',
          loginMethods: {
            google: {
              name: 'google login',
              authConnectionId: 'w3a-google-demo',
            },
            facebook: {
              name: 'facebook login',
              authConnectionId: 'w3a-facebook-demo',
            },
            discord: {
              name: 'discord login',
              authConnectionId: 'w3a-discord-demo',
            },
            twitch: {
              name: 'twitch login',
              authConnectionId: 'w3a-twitch-demo',
            },
            twitter: {
              name: 'twitter login',
              // it will hide the twitter option from the Web3Auth modal.
              showOnModal: false,
            },
            email_passwordless: {
              name: 'email passwordless login',
              authConnectionId: 'w3a-email_passwordless-demo',
            },
            sms_passwordless: {
              name: 'sms passwordless login',
              authConnectionId: 'w3a-sms_passwordless-demo',
            },
          },
          // setting it to false will hide all social login methods from modal.
          showOnModal: true,
        },
      },
    },
    // focus-end
  },
}

export default web3AuthContextConfig
```
  </TabItem>
  <TabItem value="Grouped connections">
    ```tsx title="web3authContext.tsx"

const web3AuthContextConfig: Web3AuthContextConfig = {
  web3AuthOptions: {
    clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable
    web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
    // focus-start
    modalConfig: {
      connectors: {
        [WALLET_CONNECTORS.AUTH]: {
          label: 'auth',
          loginMethods: {
            google: {
              name: 'google login',
              authConnectionId: 'w3a-google',
              groupedAuthConnectionId: 'aggregate-sapphire',
            },
            facebook: {
              name: 'facebook login',
              authConnectionId: 'w3a-facebook',
              groupedAuthConnectionId: 'aggregate-sapphire',
            },
            email_passwordless: {
              name: 'email passwordless login',
              authConnectionId: 'w3a-email-passwordless',
              groupedAuthConnectionId: 'aggregate-sapphire',
            },
          },
        },
      },
    },
    // focus-end
  },
}

export default web3AuthContextConfig
```
  </TabItem>
</Tabs>

## Advanced custom authentication

The more advanced custom authentication is available via the `connectTo` function. This allows you to any service you want and tie it to your Web3Auth Integration. **This method allows you to make Web3Auth totally invisible to your end users and have a fully whitelabeled experience all across.**

You can utilise this function to enable multiple types of connections like:

- Implicit login connections
- JWT login connections
- Grouped auth connections

<details>
  <summary>`connectTo` Function Reference</summary>

```ts
connectTo<T extends WALLET_CONNECTOR_TYPE>(
  connector: T,
  params?: LoginParamMap[T]
): Promise<Connection | null>;

export type LoginParamMap = {
    [WALLET_CONNECTORS.AUTH]: Partial<AuthLoginParams>;
    ...
};
```

#### `AuthLoginParams`

<Tabs>
  <TabItem value="Table">

| Parameter                  | Description                                                                                                                          |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `loginHint?`               | Helps pass over the login hint to the auth provider. This is used especially for `email_passwordless` and `sms_passwordless` logins. |
| `idToken?`                 | Pass over the JWT ID token directly to Web3Auth for JWT authentication.                                                              |
| `authConnection?`          | The auth provider to use for login (for example, "google", "facebook").                                                              |
| `authConnectionId?`        | The ID configured in your Embedded Wallets dashboard for the connection.                                                             |
| `groupedAuthConnectionId?` | The grouped Auth Connection ID to be used for login.                                                                                 |
| `extraLoginOptions?`       | Custom OAuth options (for example, login_hint, domain).                                                                              |

  </TabItem>

  <TabItem value="Interface">
    ```tsx
    export type AuthLoginParams = LoginParams & {
      loginHint?: string;
      idToken?: string;
  };
    export type LoginParams = {
  /**
   * Any custom state you wish to pass along. This will be returned to you post redirect.
   * Use this to store data that you want to be available to the dapp after login.
   */
  appState?: string;
  /**
   * The auth connection to be used for login.
   */
  authConnection: AUTH_CONNECTION_TYPE | CUSTOM_AUTH_CONNECTION_TYPE;
  /**
   * The auth connection ID to be used for login.
   */
  authConnectionId?: string;
  /**
   * The grouped auth connection ID to be used for login.
   */
  groupedAuthConnectionId?: string;
  /**
   * You can set the `mfaLevel` to customize when mfa screen should be shown to user.
   * It currently accepts 4 values:-
   * - `'default'`: Setting mfa level to `default` will present mfa screen to user on every third login.
   * - `'optional'`: Setting mfa level to `default` will present mfa screen to user on every login but user can skip it.
   * - `'mandatory'`: Setting mfa level to `mandatory` will make it mandatory for user to setup mfa after login.
   * - `'none'`: Setting mfa level to `none` will make the user skip the mfa setup screen
   *
   * Defaults to `none`
   * @defaultValue `none`
   */
  mfaLevel?: MfaLevelType;
  /**
   * This option is for internal use only in torus wallet and has no effect
   * on user's login on other dapps.
   *
   * Defaults to false
   * @defaultValue false
   * @internal
   */
  getWalletKey?: boolean;
  /**
   * extraLoginOptions can be used to pass standard OAuth login options to
   * loginProvider.
   *
   * For ex: you will have to pass `login_hint` as user's email and `domain`
   * as your app domain in `extraLoginOptions` while using `email_passwordless`
   * loginProvider
   */
  extraLoginOptions?: ExtraLoginOptions;
  /**
   * Custom Logins can get a dapp share returned to them post successful login.
   * This is useful if the dapps want to use this share to allow users to sign in without repeating the full flow
   * dappShare is a 24 word seed phrase
   */
  dappShare?: string;
  /**
   * This curve will be used to determine the public key encoded in the jwt token which returned in
   * `getUserInfo` function after user login.
   * You can use that public key from jwt token as a unique user identifier in your backend.
   *
   * - `'secp256k1'`: secp256k1 based pub key is added as a wallet public key in jwt token to use.
   * - `'ed25519'`: ed25519 based pub key is added as a wallet public key in jwt token to use.
   *
   * Note: This parameter won't change format of private key returned by auth. Private key returned
   * by auth is always `secp256k1`.
   *
   *
   * @defaultValue secp256k1
   */
  curve?: SUPPORTED_KEY_CURVES_TYPE;
  /**
   * Allows the dapp to set a custom redirect url for the manage mfa flow.
   *
   */
  dappUrl?: string;
};
    ```
  </TabItem>
</Tabs>

#### Auth connection types

```ts
export const AUTH_CONNECTION = {
  GOOGLE: 'google',
  TWITTER: 'twitter',
  FACEBOOK: 'facebook',
  DISCORD: 'discord',
  FARCASTER: 'farcaster',
  APPLE: 'apple',
  GITHUB: 'github',
  REDDIT: 'reddit',
  LINE: 'line',
  KAKAO: 'kakao',
  LINKEDIN: 'linkedin',
  TWITCH: 'twitch',
  TELEGRAM: 'telegram',
  WECHAT: 'wechat',
  EMAIL_PASSWORDLESS: 'email_passwordless',
  SMS_PASSWORDLESS: 'sms_passwordless',
  CUSTOM: 'custom',
}
```

#### Advanced options (`extraLoginOptions`)

For custom integrations (like Auth0, AWS Cognito), you can provide additional options:

<Tabs>
  <TabItem value="Table">

| Parameter               | Description                                                 |
| ----------------------- | ----------------------------------------------------------- |
| `isUserIdCaseSensitive` | Whether the user ID field is case sensitive [Default: true] |
| `domain`                | Auth provider domain (for example, "example.auth0.com")     |
| `client_id`             | Client ID from your auth provider                           |
| `scope`                 | OAuth scopes (for example, "email profile openid")          |
| `response_type`         | Response type for OAuth flow                                |
| `login_hint`            | Pre-fill user identifier                                    |

  </TabItem>
  <TabItem value="Interface">
    ```ts
    export type ExtraLoginOptions = Auth0ClientOptions;

    export interface Auth0ClientOptions extends BaseLoginOptions {
    /**
     * Your Auth0 account domain such as `'example.auth0.com'`,
     * `'example.eu.auth0.com'` or , `'example.mycompany.com'`
     * (when using [custom domains](https://auth0.com/docs/custom-domains))
     */
    domain?: string;
    /**
     * The Client ID found on your Application settings page
     */
    client_id?: string;
    /**
     * The field in jwt token which maps to user id
     */
    userIdField?: string;
    /**
     * Whether the user ID field is case sensitive
     * @defaultValue true
     */
    isUserIdCaseSensitive?: boolean;
    id_token?: string;
    access_token?: string;
    /**
     * The route for user info endpoint. This will be padded to domain
     * @defaultValue userinfo
     * */
    user_info_route?: string;
    /**
     * The flow type for email_passwordless login
     */
    flow_type?: EMAIL_FLOW_TYPE;
    }
    ```

  </TabItem>
</Tabs>

</details>

### Implicit logins

Implicit logins are the easiest way to authenticate users with your custom authentication services. Web3Auth currently supports implicit logins for the following providers directly:

- Google
- Facebook
- Discord
- Twitch
- Auth0 (custom)

In addition to these you can also use any other provider (for example, Auth0, AWS Cognito, Azure AD) by providing the particular details of their login within the `extraLoginOptions` object within the `connectTo` function.

#### Usage

<Tabs>
  <TabItem value="Google">
    ```tsx title="web3authContext.tsx"
await connectTo(WALLET_CONNECTORS.AUTH, {
  authConnection: AUTH_CONNECTION.GOOGLE,
  authConnectionId: 'w3a-google-demo',
})
```
  </TabItem>
  <TabItem value="Facebook">
    ```tsx title="web3authContext.tsx"
await connectTo(WALLET_CONNECTORS.AUTH, {
  authConnection: AUTH_CONNECTION.FACEBOOK,
  authConnectionId: 'w3a-facebook-demo',
})
```
  </TabItem>
  <TabItem value="Discord">
    ```tsx title="web3authContext.tsx"
await connectTo(WALLET_CONNECTORS.AUTH, {
  authConnection: AUTH_CONNECTION.DISCORD,
  authConnectionId: 'w3a-discord-demo',
})
```
  </TabItem>
  <TabItem value="Twitch">
    ```tsx title="web3authContext.tsx"
await connectTo(WALLET_CONNECTORS.AUTH, {
  authConnection: AUTH_CONNECTION.TWITCH,
  authConnectionId: 'w3a-twitch-demo',
})
```
  </TabItem>
  <TabItem value="Auth0 Google">
    ```tsx title="web3authContext.tsx"
await connectTo(WALLET_CONNECTORS.AUTH, {
  authConnection: AUTH_CONNECTION.CUSTOM,
  authConnectionId: 'w3a-auth0-demo',
  extraLoginOptions: {
    connection: 'google-oauth2',
  },
})
```
  </TabItem>
  <TabItem value="Auth0 SPA">
    ```tsx title="web3authContext.tsx"
await connectTo(WALLET_CONNECTORS.AUTH, {
  authConnection: AUTH_CONNECTION.CUSTOM,
  authConnectionId: 'w3a-auth0-demo',
})
```
  </TabItem>
  <TabItem value="AWS Cognito">
    ```tsx title="web3authContext.tsx"
await connectTo(WALLET_CONNECTORS.AUTH, {
  authConnection: AUTH_CONNECTION.CUSTOM,
  authConnectionId: 'w3a-cognito-demo',
  extraLoginOptions: {
    clientId: import.meta.env.VITE_COGNITO_CLIENT_ID,
    domain: 'https://shahbaz-web3auth.auth.ap-south-1.amazoncognito.com',
    verifierIdField: 'email',
    response_type: 'token',
    scope: 'email profile openid',
  },
})
```
  </TabItem>
</Tabs>

### JWT login

JWT login is a way to authenticate users with your custom authentication services. With this method, Web3Auth just takes into account the `idToken` passed over to the `connectTo` function and uses it to authenticate the user. You can utilise this method with any authentication service that is OAuth 2.0 Compatible.

:::warning

If you have not configured on the dashboard, whether you user ID is case sensitive or not, then you need to pass the `isUserIdCaseSensitive` option to the `extraLoginOptions`.

:::

#### Usage

<Tabs>
  <TabItem value="Google One Tap">
    ```tsx title="App.tsx"
const loginWithGoogle = async (response: CredentialResponse) => {
  const idToken = response.credential;

  // focus-start
  await connectTo(WALLET_CONNECTORS.AUTH, {
    authConnectionId: "w3a-google-demo",
    authConnection: AUTH_CONNECTION.GOOGLE,
    idToken,
    extraLoginOptions: {
      isUserIdCaseSensitive: false,
    },
  });
  // focus-end
};

...

<GoogleLogin
  onSuccess={loginWithGoogle}
  onError={() => {
    console.log("Login Failed");
  }}
  useOneTap
/>
```
  </TabItem>
  <TabItem value="Auth0 JWT login">
    ```tsx title="App.tsx"
const { getIdTokenClaims, loginWithPopup } = useAuth0()

const loginWithAuth0 = async () => {
  try {
    await loginWithPopup()

    const idToken = (await getIdTokenClaims())?.__raw.toString()
    if (!idToken) {
      throw new Error('No id token found')
    }

    // focus-start
    await connectTo(WALLET_CONNECTORS.AUTH, {
      authConnectionId: 'w3a-auth0-demo',
      authConnection: AUTH_CONNECTION.CUSTOM,
      idToken,
      extraLoginOptions: {
        isUserIdCaseSensitive: false,
      },
    })
    // focus-end
  } catch (err) {
    console.error(err)
  }
}
```
  </TabItem>
  <TabItem value="Firebase JWT login">
    ```tsx title="App.tsx"
const loginWithFirebaseGithub = async () => {
  try {
    const app = initializeApp(firebaseConfig)
    const auth = getAuth(app)
    const githubProvider = new GithubAuthProvider()

    const result = await signInWithPopup(auth, githubProvider)

    const idToken = await result.user.getIdToken(true)

    // focus-start
    connectTo(WALLET_CONNECTORS.AUTH, {
      authConnectionId: 'w3a-firebase-demo',
      authConnection: AUTH_CONNECTION.CUSTOM,
      idToken,
      extraLoginOptions: {
        isUserIdCaseSensitive: false,
      },
    })
    // focus-end
  } catch (error) {
    console.error('Firebase authentication error:', error)
  }
}
```
  </TabItem>
  <TabItem value="Custom JWT login">
    ```tsx title="App.tsx"
const getIdToken = async () => {
  // Get id token from server
  const res = await fetch('http://localhost:8080/api/token', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
  })
  const data = await res.json()
  return data?.token
}

const loginWithJWT = async () => {
  try {
    const idToken = await getIdToken()

    // focus-start
    await connectTo(WALLET_CONNECTORS.AUTH, {
      authConnection: AUTH_CONNECTION.CUSTOM,
      authConnectionId: 'w3a-node-demo',
      idToken,
      extraLoginOptions: {
        isUserIdCaseSensitive: false,
      },
    })
    // focus-end
  } catch (err) {
    console.error(err)
  }
}
```
  </TabItem>
</Tabs>

### Grouped auth connections

Grouped auth connections allows you to group multiple auth connections together and use them as a single connection. This is useful when you want to authenticate the user with multiple providers and require the same user wallet address to be generated.

For example, you can group Google and email passwordless providers together and use them as a single connection. Now, if your user logs in with Google Auth or even with email passwordless using the same email, they will get the same wallet address.

:::info Prerequisites

You need to configure a grouped connection, by combining your single connections in the Embedded Wallets dashboard before using this feature.

:::

<Tabs>
  <TabItem value="Google [Implicit] + Auth0 [Implicit]">
    ```tsx title="App.tsx"
const loginWithGoogle = async () => {
  // focus-start
  await connectTo(WALLET_CONNECTORS.AUTH, {
    groupedAuthConnectionId: 'aggregate-sapphire',
    authConnectionId: 'w3a-google',
    authConnection: AUTH_CONNECTION.GOOGLE,
  })
  // focus-end
}

const loginWithAuth0Google = async () => {
  // focus-start
  await connectTo(WALLET_CONNECTORS.AUTH, {
    groupedAuthConnectionId: 'aggregate-sapphire',
    authConnectionId: 'w3a-a0-google',
    authConnection: AUTH_CONNECTION.CUSTOM,
    extraLoginOptions: {
      connection: 'google-oauth2',
    },
  })
  // focus-end
}

const loginWithAuth0GitHub = async () => {
  // focus-start
  await connectTo(WALLET_CONNECTORS.AUTH, {
    groupedAuthConnectionId: 'aggregate-sapphire',
    authConnectionId: 'w3a-a0-github',
    authConnection: AUTH_CONNECTION.CUSTOM,
    extraLoginOptions: {
      connection: 'github',
    },
  })
  // focus-end
}
```
  </TabItem>
  <TabItem value="Google One Tap [JWT] + Auth0 [JWT]">
    ```tsx title="App.tsx"
const loginWithGoogle = async (response: CredentialResponse) => {
  const idToken = response.credential

  // focus-start
  await connectTo(WALLET_CONNECTORS.AUTH, {
    groupedAuthConnectionId: 'aggregate-sapphire',
    authConnectionId: 'w3a-google',
    authConnection: AUTH_CONNECTION.GOOGLE,
    idToken,
    extraLoginOptions: {
      isUserIdCaseSensitive: false,
      verifierIdField: 'email',
    },
  })
  // focus-end
}

const loginWithAuth0 = async () => {
  try {
    await loginWithPopup()
    const idToken = (await getIdTokenClaims())?.__raw.toString()
    if (!idToken) {
      throw new Error('No id token found')
    }

    // focus-start
    await connectTo(WALLET_CONNECTORS.AUTH, {
      groupedAuthConnectionId: 'aggregate-sapphire',
      authConnectionId: 'w3a-a0-github',
      authConnection: AUTH_CONNECTION.CUSTOM,
      idToken,
      extraLoginOptions: {
        isUserIdCaseSensitive: false,
        verifierIdField: 'email',
      },
    })
    // focus-end
  } catch (err) {
    console.error(err)
  }
}
```
  </TabItem>
  <TabItem value="Google [Implicit] + Firebase [JWT]">
    ```tsx title="App.tsx"
const loginWithGoogle = async () => {
  // focus-start
  await connectTo(WALLET_CONNECTORS.AUTH, {
    groupedAuthConnectionId: 'aggregate-sapphire',
    authConnectionId: 'w3a-google',
    authConnection: AUTH_CONNECTION.GOOGLE,
  })
  // focus-end
}

const loginWithFirebaseGithub = async () => {
  const app = initializeApp(firebaseConfig)
  const auth = getAuth(app)
  const githubProvider = new GithubAuthProvider()

  const result = await signInWithPopup(auth, githubProvider)

  const idToken = await result.user.getIdToken(true)

  // focus-start
  connectTo(WALLET_CONNECTORS.AUTH, {
    groupedAuthConnectionId: 'aggregate-sapphire',
    authConnectionId: 'w3a-firebase',
    authConnection: AUTH_CONNECTION.CUSTOM,
    idToken,
    extraLoginOptions: {
      isUserIdCaseSensitive: false,
    },
  })
  // focus-end
}
```
  </TabItem>
</Tabs>

---

## Multi-factor authentication(4)

Web3Auth supports Multi-Factor Authentication (MFA) for enhanced security. MFA requires two or more factors, such as device, social, seed phrase, or password, to access your account and recover it if needed. When a recovery factor is set up, MFA is enabled and your key is split into three shares, using Web3Auth MPC for secure, self-custodial storage.

:::caution

If you are using default dashboard connections, your users may have set up MFA on other dapps that also use default Web3Auth connections. In this case, the MFA screen will continue to appear if the user has enabled MFA on other dapps. This is because MFA cannot be turned off once it is enabled.

:::

## Multi-Factor Authentication configuration options

There are two ways to configure MFA in your application:

1. **Using the `mfaLevel` setting:** Controls the frequency of the MFA setup request screen.
2. **Using the `mfaSettings` setting:** Provides granular control over each factor, with their priority level, enable/disable status, and mandatory/optional settings.

## `mfaLevel`

The `mfaLevel` setting allows you to control when and how the MFA setup screen appears to users.

```tsx
mfaLevel?: MfaLevelType;
```

### Multi-Factor Authentication level types

| Level       | Value       | Description                                        |
| ----------- | ----------- | -------------------------------------------------- |
| `DEFAULT`   | "default"   | MFA screen appears every 10th login                |
| `OPTIONAL`  | "optional"  | MFA screen appears every login, but can be skipped |
| `MANDATORY` | "mandatory" | MFA setup is required after login                  |
| `NONE`      | "none"      | MFA setup is skipped entirely                      |

### Type definition

```tsx
export type MfaLevelType = (typeof MFA_LEVELS)[keyof typeof MFA_LEVELS]
export declare const MFA_LEVELS: {
  readonly DEFAULT: 'default'
  readonly OPTIONAL: 'optional'
  readonly MANDATORY: 'mandatory'
  readonly NONE: 'none'
}
```

### Usage examples

### Usage

```tsx

await connectTo(WALLET_CONNECTORS.AUTH, {
  authConnection: AUTH_CONNECTION.GOOGLE,
  authConnectionId: 'w3a-google-demo',
  // focus-next-line
  mfaLevel: MFA_LEVELS.MANDATORY,
})
```

## `mfaSettings`

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this SDK in a production environment is the **Scale Plan**. You can use this feature in Web3Auth Sapphire Devnet network for free.

:::

The `mfaSettings` option provides granular control over each individual MFA factor.

```tsx
mfaSettings?: MfaSettings;
```

### Multi-Factor Authentication factors

| Factor          | Key                   | Description                           |
| --------------- | --------------------- | ------------------------------------- |
| `DEVICE`        | "deviceShareFactor"   | Device-based authentication.          |
| `BACKUP_SHARE`  | "backUpShareFactor"   | Backup share (typically seed phrase). |
| `SOCIAL_BACKUP` | "socialBackupFactor"  | Social account backup.                |
| `PASSWORD`      | "passwordFactor"      | Password-based authentication.        |
| `AUTHENTICATOR` | "authenticatorFactor" | Authenticator app (TOTP).             |

### Multi-Factor Authentication settings properties

| Property    | Type    | Description                                             |
| ----------- | ------- | ------------------------------------------------------- |
| `enable`    | boolean | Whether this factor is enabled.                         |
| `priority`  | number  | Order in which factors are presented (lower = earlier). |
| `mandatory` | boolean | Whether this factor is required.                        |

### Type definitions

```tsx
export type MfaSettings = Partial<Record<MFA_FACTOR_TYPE, MFA_SETTINGS>>
export type MFA_FACTOR_TYPE = (typeof MFA_FACTOR)[keyof typeof MFA_FACTOR]
export declare const MFA_FACTOR: {
  readonly DEVICE: 'deviceShareFactor'
  readonly BACKUP_SHARE: 'backUpShareFactor'
  readonly SOCIAL_BACKUP: 'socialBackupFactor'
  readonly PASSWORD: 'passwordFactor'
  readonly PASSKEYS: 'passkeysFactor'
  readonly AUTHENTICATOR: 'authenticatorFactor'
}
export type MFA_SETTINGS = {
  enable: boolean
  priority?: number
  mandatory?: boolean
}
```

### Important rules

- At least two factors must be enabled when setting up MFA.
- If you set `mandatory: true` for all factors, the user must set up all enabled factors.
- If you set `mandatory: false` for all factors, the user can skip setting up MFA, but at least two factors are still required.
- If you set `mandatory: true` for some factors and `mandatory: false` for others, the user must set up the mandatory factors and can optionally set up the others.
- The `priority` field determines the order of setup - lower priority values appear first.

### Usage

```tsx title="web3AuthContext.tsx"

const web3AuthOptions: Web3AuthOptions = {
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
  // focus-start
  mfaSettings: {
    [MFA_FACTOR.DEVICE]: {
      enable: true,
      priority: 1,
      mandatory: true, // at least two factors are mandatory
    },
    [MFA_FACTOR.BACKUP_SHARE]: {
      enable: true,
      priority: 2,
      mandatory: true, // at least two factors are mandatory
    },
    [MFA_FACTOR.SOCIAL_BACKUP]: {
      enable: true,
      priority: 3,
      mandatory: false,
    },
    [MFA_FACTOR.PASSWORD]: {
      enable: true,
      priority: 4,
      mandatory: false,
    },
    [MFA_FACTOR.PASSKEYS]: {
      enable: true,
      priority: 5,
      mandatory: false,
    },
    [MFA_FACTOR.AUTHENTICATOR]: {
      enable: true,
      priority: 6,
      mandatory: false,
    },
  },
  // focus-end
}

const web3AuthContextConfig = {
  web3AuthOptions,
}
```

---

## Smart accounts(3)

Create and manage smart accounts for your users with just a few lines of code, using our Smart Account feature. Smart accounts offer enhanced control and programmability, enabling features that traditional wallets can't provide.

**Key features of smart accounts include:**

- **Gas abstraction:** Cover transaction fees for users, or allow users to pay for their own transactions using ERC-20 tokens.
- **Batch transactions:** Perform multiple transactions in a single call.
- **Automated transactions:** Allow users to automate actions, like swapping ETH to USDT when ETH hits a specific price.
- **Custom spending limits:** Allow users to set tailored spending limits.

:::tip

For more about ERC-4337 and its components, [check out our detailed blog post](https://blog.web3auth.io/an-ultimate-guide-to-web3-wallets-externally-owned-account-and-smart-contract-wallet/#introduction-to-eip-4337).

:::

Our smart account integration streamlines your setup, allowing you to create and manage smart accounts using your favorite libraries like Viem, Ethers, and Wagmi. You don't need to rely on third-party packages to effortlessly create ERC-4337 compatible Smart Contract Wallets (SCWs), giving users the ability to perform batch transactions and efficiently manage gas sponsorship.

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this
SDK in a production environment is the **Growth Plan**. You can use this feature in Web3Auth
Sapphire Devnet network for free.

:::

## Enabling smart accounts

:::info prerequisite

To enable this feature, you need to configure smart accounts from your project in the [Embedded Wallets dashboard](https://developer.metamask.io/).

:::

### Dashboard configuration

To enable smart accounts, navigate to the smart accounts section in the [Embedded Wallets dashboard](https://developer.metamask.io/), and enable the **Set up Smart accounts** toggle. Embedded Wallets currently supports [MetaMaskSmartAccount](https://docs.gator.metamask.io/how-to/create-delegator-account#create-a-metamasksmartaccount) as a Smart Account provider.

#### Wallet configuration

Once smart accounts are enabled, you can customize the wallet configurations:

- **All supported wallets (default):** Allows users to create smart accounts using both embedded and external wallets.
- **Embedded wallets only:** Restricts Smart Account creation to embedded wallets.

#### Configure bundler and paymaster

A bundler aggregates UserOperations and submits them onchain via the global EntryPoint contract. To configure the bundler:

1. Navigate to the **Bundler & Paymaster** tab within the **Smart accounts** section
2. Add the bundler URL for each supported chain
3. Add the paymaster URL for each supported chain

:::info

Currently, the sponsored paymaster can only be configured via the dashboard. For ERC-20 paymaster, refer to the SDK Configuration section below.

:::

### Optional: SDK configuration

While the dashboard provides a convenient way to configure smart accounts, the SDK offers greater flexibility by allowing you to override these settings.

### Basic configuration

To enable smart accounts in your application, add the `accountAbstractionConfig` to your Web3Auth options:

```ts

const web3AuthOptions: Web3AuthOptions = {
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_DEVNET,
  // focus-start
  accountAbstractionConfig: {
    smartAccountType: 'metamask',
    chains: [
      {
        chainId: '0x1',
        bundlerConfig: {
          url: 'YOUR_BUNDLER_URL',
        },
      },
    ],
  },
  // focus-end
}
```

### Advanced configuration: Override paymaster context

You can override the paymaster context defined in the dashboard for specific chains. This is particularly useful when your paymaster requires custom settings or parameters.

```ts

const web3AuthOptions: Web3AuthOptions = {
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_DEVNET,
  // focus-start
  accountAbstractionConfig: {
    smartAccountType: 'metamask',
    chains: [
      {
        chainId: '0x1',
        bundlerConfig: {
          url: 'YOUR_BUNDLER_URL',
          // This is just an example of how you can configure the paymaster context.
          // Please refer to the documentation of the paymaster you are using
          // to understand the required parameters.
          paymasterContext: {
            token: 'SUPPORTED_TOKEN_CONTRACT_ADDRESS',
            sponsorshipPolicyId: 'sp_my_policy_id',
          },
        },
      },
    ],
  },
  // focus-end
}
```

:::info

The paymaster context must be manually configured for each chain that needs to be supported.

:::

## Using smart accounts

### Configure signer

The Web3Auth Smart Account feature is compatible with popular signer SDKs, including Wagmi, ethers,
and viem. You can choose your preferred package to configure the signer.

<!-- vale off -->

<Tabs
  defaultValue="wagmi"
  values={[
    { label: "Wagmi (recommended)", value: "wagmi" },
    { label: "Viem", value: "viem" },
    { label: "Ethers", value: "ethers" },
  ]}
>

<TabItem value="wagmi">

Use Wagmi with `@web3auth/modal/react/wagmi` or `@web3auth/modal/vue/wagmi`. After sign-in, Wagmi
hooks (`useConnection`, `useSendTransaction`, and similar) use the smart account signer automatically.
No manual `connection.ethereumProvider` wiring is required.

```tsx

const { address } = useConnection()
// useSendTransaction, useWriteContract, etc. work with the smart account
```

</TabItem>

<TabItem value="viem">

For vanilla JavaScript or apps without Wagmi, read the EIP-1193 provider from `connection`:

```tsx

const connection = web3auth.connection
const provider = connection?.ethereumProvider ?? null

const walletClient = createWalletClient({
  transport: custom(provider),
})
```

</TabItem>

<TabItem value="ethers">

```tsx

const connection = web3auth.connection
const provider = connection?.ethereumProvider ?? null

const ethersProvider = new ethers.BrowserProvider(provider)
const signer = await ethersProvider.getSigner()
```

</TabItem>
</Tabs>
<!-- vale on -->

### Get smart account address

Once the signers or Wagmi configuration is set up, it can be used to retrieve the user's Smart
Account address.

<Tabs
  defaultValue="viem"
  values={[
    { label: "Viem", value: "viem" },
    { label: "Ethers", value: "ethers" },
    { label: "Wagmi", value: "Wagmi" },
  ]}
>

<TabItem value="viem">

```tsx
// Use walletClient instance from previous step
const addresses = await walletClient.getAddresses()

const smartAccountAddress = addresses[0]
const eoaAddress = addresses[1]
```

</TabItem>

<TabItem value="ethers">

```tsx
// User signer from previous step
const smartAccountAddress = signer.getAddress()
```

</TabItem>

<TabItem value="Wagmi">
```tsx

const { address } = useConnection()
const smartAccountAddress = address

```

</TabItem>
</Tabs>
```

### Send transaction

Developers can use their preferred signer or Wagmi hooks to initiate onchain transactions, while
Web3Auth manages the creation and submission of the UserOperation. Only the `to`, `data`, and
`value` fields need to be provided. Any additional parameters will be ignored and automatically
overridden.

To ensure reliable execution, the bundler client sets maxFeePerGas and maxPriorityFeePerGas values.
If custom values are required, developers can use the
[Viem's BundlerClient](https://viem.sh/account-abstraction/clients/bundler#bundler-client) to
manually construct and send the user operation.

Since Smart Accounts are deployed smart contracts, the user's first transaction also triggers the
onchain deployment of their wallet.

<Tabs
  defaultValue="viem"
  values={[
    { label: "Viem", value: "viem" },
    { label: "Ethers", value: "ethers" },
    { label: "Wagmi", value: "wagmi" },
  ]}
>

<TabItem value="wagmi">

```tsx

const { data: hash, sendTransaction } = useSendTransaction()

// Convert 1 ether to WEI format
const value = web3.utils.toWei(1)

sendTransaction({ to: 'DESTINATION_ADDRESS', value, data: '0x' })

const {
  data: receipt,
  isLoading: isConfirming,
  isSuccess: isConfirmed,
} = useWaitForTransactionReceipt({
  hash,
})
```

</TabItem>
<TabItem value="ethers">

```tsx
// Convert 1 ether to WEI format
const amount = ethers.parseEther('1.0')

// Submits a user operation to the blockchain
const transaction = await signer.sendTransaction({
  to: 'DESTINATION_ADDRESS',
  value: amount,
  // This will perform the transfer of ETH
  data: '0x',
})

// Wait for the transaction to be mined
const receipt = await transaction.wait()
```

</TabItem>
<TabItem value="viem">

```tsx
// Convert 1 ether to WEI format
const amount = parseEther('1')

// Submits a user operation to the blockchain
const hash = await walletClient.sendTransaction({
  to: 'DESTINATION_ADDRESS',
  value: amount,
  // This will perform the transfer of ETH
  data: '0x',
})

// Wait for the transaction to be mined
const receipt = await publicClient.waitForTransactionReceipt({ hash })
```

</TabItem>
</Tabs>

### Sign transaction

You can sign a transaction without immediately sending it. For the user's first transaction, the `UserOperation` calldata will automatically include the deployment data needed to create the Smart Account onchain.

:::info

Wagmi doesn't have hooks for signing transactions yet.

:::

<Tabs
  defaultValue="viem"
  values={[
    { label: "Viem", value: "viem" },
    { label: "Ethers", value: "ethers" },
  ]}
>

<TabItem value="ethers">

```tsx
// Convert 1 ether to WEI format
const amount = parseEther('1')

const signature = await signer.signTransaction({
  to: 'DESTINATION_ADDRESS',
  value: amount,
})
```

</TabItem>
<TabItem value="viem">

```tsx
// Convert 1 ether to WEI format
const amount = parseEther('1')
const addresses = await walletClient.getAddresses()

const request = await walletClient.prepareTransactionRequest({
  account: addresses[0],
  to: 'DESTINATION_ADDRESS',
  value: amount,
})

const signature = await walletClient.signTransaction(request as any)
```

</TabItem>
</Tabs>

### Sign message

Smart accounts support message signing following the EIP-1271 standard for signature verification, using the `isValidSignature` method defined in the smart contract wallet instead of the `ecrecover` function used by EOAs.

<!-- vale off -->

<Tabs
  defaultValue="viem"
  values={[
    { label: "Viem", value: "viem" },
    { label: "Ethers", value: "ethers" },
    { label: "Wagmi", value: "wagmi" },
  ]}
>

<TabItem value="wagmi">

```tsx

const { data: signature, signMessage } = useSignMessage()

const message = 'YOUR_MESSAGE'

signMessage({ message })

// Use signature as needed
```

</TabItem>
<TabItem value="ethers">

```tsx
const originalMessage = 'YOUR_MESSAGE'

// Sign the message
const signedMessage = await signer.signMessage(originalMessage)
```

</TabItem>
<TabItem value="viem">

```tsx
const originalMessage = 'YOUR_MESSAGE'

const addresses = await walletClient.getAddresses()

const signedMessage = await walletClient.signMessage({
  account: addresses[0],
  message: originalMessage,
})
```

</TabItem>
</Tabs>
<!-- vale on -->

### Send batch transaction

One of the key advantages of Smart accounts is the ability to execute multiple operations in a single transaction. For example, instead of requiring separate transactions for token approval and then swapping, both operations can be combined into a single UserOperation.

To perform batch transactions, you must use the `BundlerClient` provided by Web3Auth:

```ts
// Use your Web3Auth instance
const accountAbstractionProvider = web3auth.accountAbstractionProvider
// Use the same accountAbstractionProvider we created earlier.
const bundlerClient = accountAbstractionProvider.bundlerClient!
const smartAccount = accountAbstractionProvider.smartAccount!

// 0.00001 ETH in WEI format
const amount = 10000000000000n

const userOpHash = await bundlerClient.sendUserOperation({
  account: smartAccount,
  calls: [
    {
      to: 'DESTINATION_ADDRESS',
      value: amount,
      data: '0x',
    },
    {
      to: 'DESTINATION_ADDRESS',
      value: amount,
      data: '0x',
    },
  ],
})

// Retrieve user operation receipt
const receipt = await bundlerClient.waitForUserOperationReceipt({
  hash: userOpHash,
})

const transactionHash = receipt.receipt.transactionHash
```

:::info

When calling `sendUserOperation`, it returns a UserOperation hash, not the transaction hash. To get the final transaction details, use `waitForUserOperationReceipt`.

:::

### Send transaction using ERC-20 paymaster

You can use ERC-20 tokens to pay for transaction fees instead of the native token (for example, ETH). This requires approving the token for use by the paymaster:

```ts
// Use your Web3Auth instance
const accountAbstractionProvider = web3auth.accountAbstractionProvider

// Use the same accountAbstractionProvider we created earlier.
const bundlerClient = accountAbstractionProvider.bundlerClient!
const smartAccount = accountAbstractionProvider.smartAccount!

// Pimlico's ERC-20 paymaster address
const pimlicoPaymasterAddress = '0x0000000000000039cd5e8aE05257CE51C473ddd1'

// USDC address on Ethereum Sepolia
const usdcAddress = '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238'

// 0.00001 ETH in WEI format
const amount = 10000000000000n

// 10 USDC in WEI format. Since USDC has 6 decimals, 10 * 10^6
const approvalAmount = 10000000n

const userOpHash = await bundlerClient.sendUserOperation({
  account: smartAccount,
  calls: [
    // Approve USDC on Sepolia chain for Pimlico's ERC 20 Paymaster
    {
      to: usdcAddress,
      abi: parseAbi(['function approve(address,uint)']),
      functionName: 'approve',
      args: [pimlicoPaymasterAddress, approvalAmount],
    },
    {
      to: 'DESTINATION_ADDRESS',
      value: amount,
      data: '0x',
    },
    {
      to: 'DESTINATION_ADDRESS',
      value: amount,
      data: '0x',
    },
  ],
})

// Retrieve user operation receipt
const receipt = await bundlerClient.waitForUserOperationReceipt({
  hash: userOpHash,
})

const transactionHash = receipt.receipt.transactionHash
```

## EIP-7702 smart accounts {#eip-7702-smart-accounts}

:::note Web SDK only

EIP-7702 support ships in **Web SDK v11** (`@web3auth/modal` for JavaScript, React, and Vue).

:::

EIP-7702 (Set Code for EOAs) lets users keep their existing EOA address while temporarily delegating execution to a smart account implementation for a single transaction.
This bridges EOA simplicity and account-abstraction capability without forcing users onto a separate smart account address.

### When to use EIP-7702 vs ERC-4337

| Approach                | Address                                 | Best for                                                        |
| ----------------------- | --------------------------------------- | --------------------------------------------------------------- |
| ERC-4337 smart accounts | New smart account address (`aaAddress`) | Full account-abstraction lifecycle with bundlers and paymasters |
| EIP-7702                | Same EOA address                        | One-off or session-scoped AA features without address migration |

### Dashboard configuration

Enable smart accounts in the [Embedded Wallets dashboard](https://developer.metamask.io/) and select an EIP-7702-compatible provider.
The SDK currently lists MetaMask as an EIP-7702-supported smart account provider.

:::caution review

Confirm the exact dashboard toggle and `eipStandard` values for EIP-7702 in your project settings before publishing.

:::

### SDK configuration

When overriding smart account settings in code, set `eipStandard` on `accountAbstractionConfig`:

```ts

const web3AuthOptions: Web3AuthOptions = {
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID',
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_DEVNET,
  accountAbstractionConfig: {
    smartAccountType: 'metamask',
    eipStandard: '7702',
    chains: [
      {
        chainId: '0x1',
        bundlerConfig: {
          url: 'YOUR_BUNDLER_URL',
        },
      },
    ],
  },
}
```

:::caution review

Verify the accepted `eipStandard` enum values against your installed `@web3auth/modal` version.
Use the SDK release notes if the value above fails at build time.

:::

### Capabilities unlocked by EIP-7702

- **Gas sponsorship:** Cover transaction fees through a paymaster without changing the user's address.
- **Batch transactions:** Combine multiple calls in one authorization.
- **Session keys:** Approve scoped permissions for multi-step flows with a single signature.

For ERC-4337-specific flows (UserOperations, bundler clients), use the sections above.
For a conceptual overview, see [Native smart accounts](/embedded-wallets/features/smart-accounts/).

---

## Wallet Services(Advanced)

Web3Auth Wallet Services provides a comprehensive suite of wallet functionality including fiat-on-ramp, swaps, and interoperability with WalletConnect. These services enhance your application by offering a complete wallet experience without building these features from scratch.

:::tip

All these configurations can be directly accessed and managed through the [Embedded Wallets dashboard](https://developer.metamask.io). Manual configuration in the SDK is optional and provided here for reference purposes.

:::

:::note

Access to Wallet Services is gated. You can use this feature in `sapphire_devnet` at no cost. The minimum [pricing plan](https://web3auth.io/pricing.html) to use this feature in a production environment is the **Scale Plan**.

:::

## `walletServicesConfig`

The `walletServicesConfig` option allows you to customize the Wallet Services experience for your users.

```tsx
walletServicesConfig?: WalletServicesConfig;
```

### Configuration options

<Tabs>
  <TabItem value="Table">

| Property               | Type                       | Description                                      |
| ---------------------- | -------------------------- | ------------------------------------------------ |
| `confirmationStrategy` | CONFIRMATION_STRATEGY_TYPE | How to display confirmation screens.             |
| `modalZIndex`          | number                     | Z-index for modal windows.                       |
| `enableKeyExport`      | boolean                    | Enable private key export functionality.         |
| `whiteLabel`           | Object                     | Customization options for the widget appearance. |

#### Confirmation strategy options

| Strategy       | Description                                                     |
| -------------- | --------------------------------------------------------------- |
| `default`      | Uses auto-approve by default, modal for WalletConnect requests. |
| `modal`        | Always uses modal for confirmations.                            |
| `auto-approve` | Automatically approves transactions without confirmation.       |

#### Whitelabel options

| Property            | Type                 | Description                                |
| ------------------- | -------------------- | ------------------------------------------ |
| `showWidgetButton`  | boolean              | Whether to show the widget button.         |
| `buttonPosition`    | BUTTON_POSITION_TYPE | Position of the widget button on the page. |
| `hideNftDisplay`    | boolean              | Hide NFT display in the wallet.            |
| `hideTokenDisplay`  | boolean              | Hide token display in the wallet.          |
| `hideTransfers`     | boolean              | Hide transfer functionality.               |
| `hideTopup`         | boolean              | Hide top-up (fiat on-ramp) functionality.  |
| `hideReceive`       | boolean              | Hide receive address functionality.        |
| `hideSwap`          | boolean              | Hide token swap functionality.             |
| `hideShowAllTokens` | boolean              | Hide the "show all tokens" option.         |
| `hideWalletConnect` | boolean              | Hide WalletConnect integration.            |
| `defaultPortfolio`  | "token" \| "nft"     | Default portfolio view.                    |

#### Button position options

| Position       | Description                      |
| -------------- | -------------------------------- |
| `bottom-left`  | Bottom left corner of the page.  |
| `top-left`     | Top left corner of the page.     |
| `bottom-right` | Bottom right corner of the page. |
| `top-right`    | Top right corner of the page.    |

  </TabItem>

  <TabItem value="Interface">

```tsx
export type WalletServicesConfig = Omit<
  WsEmbedParams,
  | 'buildEnv'
  | 'enableLogging'
  | 'chainId'
  | 'chains'
  | 'confirmationStrategy'
  | 'accountAbstractionConfig'
> & {
  /**
   * Determines how to show confirmation screens
   * @defaultValue default
   *
   * default & auto-approve
   * - use auto-approve as default
   * - if wallet connect request use modal
   *
   * modal
   * - use modal always
   */
  confirmationStrategy?: Exclude<WsEmbedParams['confirmationStrategy'], 'popup'>
  modalZIndex?: number
}

export interface WsEmbedParams {
  /**
   * Supported chains
   */
  chains: ProviderConfig[]
  /**
   * Chain to connect with
   */
  chainId: string
  /**
   * Build Environment of WsEmbed.
   *
   * production uses https://wallet.web3auth.io,
   *
   * staging uses https://staging-wallet.web3auth.io,
   *
   * testing uses https://develop-wallet.web3auth.io (latest internal build)
   *
   * development uses http://localhost:4050 (expects wallet-services-frontend to be run locally),
   *
   * @defaultValue production
   */
  buildEnv?: WS_EMBED_BUILD_ENV_TYPE
  /**
   * Enables or disables logging.
   *
   * Defaults to false in prod and true in other environments
   */
  enableLogging?: boolean
  /**
   * URL of widget to load
   *
   * Defaults to true
   * @defaultValue true
   */
  walletUrls?: Partial<Record<WS_EMBED_BUILD_ENV_TYPE, WalletUrlConfig>>
  /**
   * Determines how to show confirmation screens
   * @defaultValue default
   *
   * default & popup
   * - use popop as default
   * - if WalletConnect request use modal
   *
   * modal
   * - use modal always
   *
   * auto-approve
   * - does not work on embed. will use default
   */
  confirmationStrategy?: CONFIRMATION_STRATEGY_TYPE
  /**
   * Enable and configure account abstraction
   */
  accountAbstractionConfig?: AccountAbstractionMultiChainConfig
  /**
   * Enable private key export
   *
   * Defaults to false
   * @defaultValue false
   */
  enableKeyExport?: boolean
  /**
   * Allows you to customize the look & feel of the widget
   */
  whiteLabel?: {
    /**
     * whether to show/hide ws-embed widget.
     *
     * Defaults to true
     * @defaultValue true
     */
    showWidgetButton?: boolean
    /**
     * Determines where the wsEmbed widget is visible on the page.
     * @defaultValue bottom-left
     */
    buttonPosition?: BUTTON_POSITION_TYPE
    hideNftDisplay?: boolean
    hideTokenDisplay?: boolean
    hideTransfers?: boolean
    hideTopup?: boolean
    hideReceive?: boolean
    hideSwap?: boolean
    hideShowAllTokens?: boolean
    hideWalletConnect?: boolean
    defaultPortfolio?: 'token' | 'nft'
  } & WhiteLabelData
}

export declare const CONFIRMATION_STRATEGY: {
  readonly POPUP: 'popup'
  readonly MODAL: 'modal'
  readonly AUTO_APPROVE: 'auto-approve'
  readonly DEFAULT: 'default'
}
export type CONFIRMATION_STRATEGY_TYPE =
  (typeof CONFIRMATION_STRATEGY)[keyof typeof CONFIRMATION_STRATEGY]

export type AccountAbstractionMultiChainConfig = {
  smartAccountType?: SmartAccountType
  chains?: {
    chainId: string
    bundlerConfig: BundlerConfig
    paymasterConfig?: PaymasterConfig
    smartAccountConfig?: SmartAccountConfig
  }[]
}

export declare const BUTTON_POSITION: {
  readonly BOTTOM_LEFT: 'bottom-left'
  readonly TOP_LEFT: 'top-left'
  readonly BOTTOM_RIGHT: 'bottom-right'
  readonly TOP_RIGHT: 'top-right'
}
export type BUTTON_POSITION_TYPE = (typeof BUTTON_POSITION)[keyof typeof BUTTON_POSITION]
```

  </TabItem>
</Tabs>

## Usage

```tsx title="web3AuthContext.tsx"

  BUTTON_POSITION,
  CONFIRMATION_STRATEGY,
  WEB3AUTH_NETWORK,
  type Web3AuthOptions,
} from '@web3auth/modal'

const web3AuthOptions: Web3AuthOptions = {
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
  // focus-start
  walletServicesConfig: {
    confirmationStrategy: CONFIRMATION_STRATEGY.MODAL,
    modalZIndex: 99999,
    enableKeyExport: false,
    whiteLabel: {
      showWidgetButton: true,
      buttonPosition: BUTTON_POSITION.BOTTOM_RIGHT,
      hideNftDisplay: false,
      hideTokenDisplay: false,
      hideTransfers: false,
      hideTopup: false,
      hideReceive: false,
      hideSwap: false,
      hideShowAllTokens: false,
      hideWalletConnect: false,
      defaultPortfolio: 'token',
    },
  },
  // focus-end
}

const web3AuthContextConfig = {
  web3AuthOptions,
}
```

---

## Whitelabel(4)

Web3Auth allows complete whitelabeling with application branding for a consistent user experience. You can customize three different aspects:

- **UI elements:** Customize the appearance of modals and components
- **Branding:** Apply your brand colors, logos, and themes
- **Translations:** Localize the interface for your users

:::info

All of these settings can be easily managed directly from the Embedded Wallets dashboard. Once you update your branding, or UI preferences there, the changes will automatically apply to your integration.

:::

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this
SDK in a production environment is the **Growth Plan**. You can use this feature in Web3Auth
Sapphire Devnet network for free.

:::

## Customizing the Web3Auth Modal

While basic modal appearance can be configured directly on the dashboard, the following advanced options provide even greater control through the `modalConfig` property.

### `modalConfig`

The `modalConfig` option in the constructor lets you configure the modal UI and customize authentication:

```ts
modalConfig?: ConnectorsModalConfig;

export interface ConnectorsModalConfig {
    connectors?: Partial<Record<WALLET_CONNECTOR_TYPE, ModalConfig>>;
    hideWalletDiscovery?: boolean;
}

export type WALLET_CONNECTOR_TYPE = (typeof WALLET_CONNECTORS)[keyof typeof WALLET_CONNECTORS];

export interface ModalConfig extends Omit<BaseConnectorConfig, "isInjected" | "chainNamespaces"> {
    loginMethods?: LoginMethodConfig;
}
```

### `LoginMethodConfig`

The `LoginMethodConfig` interface provides extensive customization options for each authentication method:

<Tabs>
  <TabItem value="Table">

| Property                  | Type                   | Description                                                                          |
| ------------------------- | ---------------------- | ------------------------------------------------------------------------------------ |
| `name`                    | `string`               | Custom display name (defaults to auth app's default if not provided)                 |
| `description`             | `string`               | Button description (renders as full-length button if provided; otherwise as an icon) |
| `logoHover`               | `string`               | Logo shown on mouse hover (defaults to auth app's default)                           |
| `logoLight`               | `string`               | Logo for dark theme/background (defaults to auth app's default)                      |
| `logoDark`                | `string`               | Logo for light theme/background (defaults to auth app's default)                     |
| `mainOption`              | `boolean`              | Whether to show login button on the main list                                        |
| `showOnModal`             | `boolean`              | Controls visibility of the login button on modal                                     |
| `authConnectionId`        | `string`               | Auth connection ID of the provider                                                   |
| `groupedAuthConnectionId` | `string`               | Grouped Auth Connection ID of the provider                                           |
| `extraLoginOptions`       | `ExtraLoginOptions`    | Additional parameters for social login                                               |
| `authConnection`          | `AUTH_CONNECTION_TYPE` | Auth connection type (useful for customizing login buttons with custom connectors)   |
| `isDefault`               | `boolean`              | Whether it's the default connector _(internal)_                                      |

  </TabItem>

  <TabItem value="Interface">

```ts
export type LoginMethodConfig = Partial<
  Record<
    AUTH_CONNECTION_TYPE,
    {
      /**
       * Display Name. If not provided, we use the default for auth app
       */
      name?: string
      /**
       * Description for button. If provided, it renders as a full length button. else, icon button
       */
      description?: string
      /**
       * Logo to be shown on mouse hover. If not provided, we use the default for auth app
       */
      logoHover?: string
      /**
       * Logo to be shown on dark background (dark theme). If not provided, we use the default for auth app
       */
      logoLight?: string
      /**
       * Logo to be shown on light background (light theme). If not provided, we use the default for auth app
       */
      logoDark?: string
      /**
       * Show login button on the main list
       */
      mainOption?: boolean
      /**
       * Whether to show the login button on modal or not
       */
      showOnModal?: boolean
      /**
       * Auth connection id of the provider.
       */
      authConnectionId?: string
      /**
       * Grouped auth connection id of the provider.
       */
      groupedAuthConnectionId?: string
      /**
       * ExtraLoginOption params to be used for social login.
       */
      extraLoginOptions?: ExtraLoginOptions
      /**
       * Auth connection type of the auth connector.
       * Can be different from the original key.
       *
       * Example: This helps in customizing the google login button with auth0 custom connector.
       */
      authConnection?: AUTH_CONNECTION_TYPE
      /**
       * Whether is it default connector.
       *
       * @internal
       */
      isDefault?: boolean
    }
  >
>
```

  </TabItem>
</Tabs>

## Common customization examples

### Disabling specific social login methods

Web3Auth provides the following social login methods:

```tsx
export declare const AUTH_CONNECTION: {
  readonly GOOGLE: 'google'
  readonly TWITTER: 'twitter'
  readonly FACEBOOK: 'facebook'
  readonly DISCORD: 'discord'
  readonly FARCASTER: 'farcaster'
  readonly APPLE: 'apple'
  readonly GITHUB: 'github'
  readonly REDDIT: 'reddit'
  readonly LINE: 'line'
  readonly KAKAO: 'kakao'
  readonly LINKEDIN: 'linkedin'
  readonly TWITCH: 'twitch'
  readonly TELEGRAM: 'telegram'
  readonly WECHAT: 'wechat'
  readonly EMAIL_PASSWORDLESS: 'email_passwordless'
  readonly SMS_PASSWORDLESS: 'sms_passwordless'
  readonly CUSTOM: 'custom'
  readonly AUTHENTICATOR: 'authenticator'
}
```

To disable specific login methods, set `showOnModal` to `false` for the corresponding auth connection:

```tsx title="web3AuthContextConfig.ts"

const web3AuthContextConfig: Web3AuthContextConfig = {
  web3AuthOptions: {
    clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable
    web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
    // focus-start
    modalConfig: {
      connectors: {
        [WALLET_CONNECTORS.AUTH]: {
          label: 'auth',
          loginMethods: {
            // Disable Facebook and Reddit
            facebook: {
              name: 'facebook',
              showOnModal: false,
            },
            reddit: {
              name: 'reddit',
              showOnModal: false,
            },
          },
          // Setting to false will hide all social login methods from modal
          showOnModal: true,
        },
      },
    },
    // focus-end
  },
}

export default web3AuthContextConfig
```

### Enhancing email and SMS login experience

By specifying a custom `authConnectionId` for email or SMS login methods, you can ensure the entire authentication flow takes place within the modal, eliminating the need for external popups.

:::info

In the default setup, users are redirected to a separate popup to enter their email or phone number for security purposes. However, with a custom `authConnectionId`, this input step is securely embedded directly inside the modal, keeping the input step inside the modal.

:::

```tsx title="web3AuthContextConfig.ts"

const web3AuthContextConfig: Web3AuthContextConfig = {
  web3AuthOptions: {
    clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable
    web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
    // focus-start
    modalConfig: {
      connectors: {
        [WALLET_CONNECTORS.AUTH]: {
          label: 'auth',
          loginMethods: {
            email_passwordless: {
              name: 'email passwordless login',
              authConnectionId: 'w3a-email_passwordless-demo',
            },
            sms_passwordless: {
              name: 'sms passwordless login',
              authConnectionId: 'w3a-sms_passwordless-demo',
            },
          },
        },
      },
    },
    // focus-end
  },
}

export default web3AuthContextConfig
```

## Creating a fully custom UI

For complete control over the authentication interface, you can bypass the Web3Auth modal entirely and use the `connectTo` function. This allows you to create custom buttons that connect directly to specific auth providers.

See the [custom authentication](./custom-authentication.mdx) section for detailed implementation instructions.

---

## React hooks for Ethereum (via Wagmi)

Web3Auth supports hooks based Ethereum wallet operations in React via [Wagmi](https://wagmi.sh/). Once you have set up Wagmi using the Web3Auth Modal SDK, you can use all Wagmi hooks directly in your application, no additional wrappers or configuration are needed beyond the initial setup.

## Wagmi integration

You need to install the `wagmi` and `@tanstack/react-query` packages and use the Embedded Wallets
implementation of `WagmiProvider` for configuration.

:::info

The Embedded Wallets implementation of `WagmiProvider` is a custom implementation that is used to integrate
with the Embedded Wallets/Web3Auth Modal SDK. It is a wrapper around the `WagmiProvider` that makes it compatible.

With this implementation, you can use the Wagmi hooks, however **no external connectors are
supported**. Embedded Wallets provides a whole suite of connectors which you can use directly for a better
experience with external wallets.

:::

```bash npm2yarn
npm install wagmi@3 @tanstack/react-query
```

```tsx title="main.tsx"

// focus-start

// focus-end

// focus-next-line
const queryClient = new QueryClient()

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
  <Web3AuthProvider config={web3AuthContextConfig}>
    {/* focus-start */}
    <QueryClientProvider client={queryClient}>
      <WagmiProvider>
        <App />
      </WagmiProvider>
    </QueryClientProvider>
    {/* focus-end */}
  </Web3AuthProvider>
)
```

:::info

Wagmi provides a comprehensive set of React hooks for Ethereum and EVM-compatible chains. Embedded Wallets
integrates with Wagmi, so you can use hooks like `useConnection`, `useBalance`,
`useSendTransaction`, and more, out of the box.

:::

Below are some examples of using Wagmi hooks in your dapp after Embedded Wallets and Wagmi are set up. You
can note these functions work directly with Wagmi. Once you have set up Wagmi with Embedded Wallets, you can
use any Wagmi hook as you would in a standard Wagmi application.

### Get account balance

```tsx

export function Balance() {
  const { address } = useConnection()
  const { data, isLoading, error } = useBalance({ address })

  return (
    
      Balance
      
        {data?.value !== undefined && `${formatUnits(data.value, data.decimals)} ${data.symbol}`}{' '}
        {isLoading && 'Loading...'} {error && 'Error: ' + error.message}
      
    
  )
}
```

### Send transaction

```tsx

export function SendTransaction() {
  const { data: hash, error, isPending, sendTransaction } = useSendTransaction()

  async function submit(e: FormEvent<HTMLFormElement>) {
    e.preventDefault()
    const formData = new FormData(e.target as HTMLFormElement)
    const to = formData.get('address') as Hex
    const value = formData.get('value') as string
    sendTransaction({ to, value: parseEther(value) })
  }

  const { isLoading: isConfirming, isSuccess: isConfirmed } = useWaitForTransactionReceipt({
    hash,
  })

  return (
    
      Send Transaction
      <form onSubmit={submit}>
        <input name="address" placeholder="Address" required />
        <input name="value" placeholder="Amount (ETH)" type="number" step="0.000000001" required />
        <button disabled={isPending} type="submit">
          {isPending ? 'Confirming...' : 'Send'}
        </button>
      </form>
      {hash && Transaction Hash: {hash}}
      {isConfirming && 'Waiting for confirmation...'}
      {isConfirmed && 'Transaction confirmed.'}
      {error && Error: {(error as BaseError).shortMessage || error.message}}
    
  )
}
```

### Switch chain

```tsx

export function SwitchChain() {
  const chainId = useChainId()
  const chains = useChains()
  const { switchChain, error } = useSwitchChain()

  return (
    
      Switch Chain
      Connected to {chainId}
      {chains.map(chain => (
        <button
          disabled={chainId === chain.id}
          key={chain.id}
          onClick={() => switchChain({ chainId: chain.id })}
          type="button"
          className="card">
          {chain.name}
        </button>
      ))}
      {error?.message}
    
  )
}
```

---

## Examples - PnP Web React SDK

<ExampleCards
  exampleMap={[...webExamples].filter(
    obj => obj.tags?.includes('react') || obj.tags?.includes('nextjs')
  )}
/>

---

## React hooks for Web3Auth Modal

Embedded Wallets offers a comprehensive suite of React hooks to streamline integration and state management within your React applications. These hooks abstract away common authentication and wallet operations, enabling you to implement Embedded Wallets' features with minimal boilerplate. Each hook is focused on a specific aspect of Embedded Wallets' functionality, making it easy to implement authentication, wallet operations, and blockchain interactions in your React projects.

## List of React hooks

:::tip

For detailed usage, configuration options, and code examples, refer to the dedicated documentation page for each hook.

:::

### Web3Auth hooks

| Hook Name                          | Description                                                         |
| ---------------------------------- | ------------------------------------------------------------------- |
| [`useWeb3Auth`](./useWeb3Auth.mdx) | Core hook for Embedded Wallets initialization and state management. |

### Authentication hooks

| Hook Name                                              | Description                                    |
| ------------------------------------------------------ | ---------------------------------------------- |
| [`useWeb3AuthConnect`](./useWeb3AuthConnect.mdx)       | Handles Embedded Wallets connection processes. |
| [`useWeb3AuthDisconnect`](./useWeb3AuthDisconnect.mdx) | Manages disconnection from Embedded Wallets.   |

### Identity hooks

| Hook Name                                    | Description                                              |
| -------------------------------------------- | -------------------------------------------------------- |
| [`useAuthTokenInfo`](./useAuthTokenInfo.mdx) | Retrieves and manages identity tokens.                   |
| [`useWeb3AuthUser`](./useWeb3AuthUser.mdx)   | Provides access to the authenticated user's information. |

### Blockchain hooks

| Hook Name                                | Description                                             |
| ---------------------------------------- | ------------------------------------------------------- |
| [`useSwitchChain`](./useSwitchChain.mdx) | Allows switching between different blockchain networks. |

### Multi-Factor Authentication hooks

| Hook Name                            | Description                                                      |
| ------------------------------------ | ---------------------------------------------------------------- |
| [`useEnableMFA`](./useEnableMFA.mdx) | Enables Multi-Factor Authentication (MFA) for enhanced security. |
| [`useManageMFA`](./useManageMFA.mdx) | Provides functionality to manage MFA settings.                   |

### Wallet Services plugin hooks

| Hook Name                                                  | Description                                         |
| ---------------------------------------------------------- | --------------------------------------------------- |
| [`useWalletConnectScanner`](./useWalletConnectScanner.mdx) | Integrates WalletConnect scanner functionality.     |
| [`useWalletUI`](./useWalletUI.mdx)                         | Manages wallet UI components and user interactions. |
| [`useCheckout`](./useCheckout.mdx)                         | Facilitates cryptocurrency checkout processes.      |
| [`useSwap`](./useSwap.mdx)                                 | Enables token swapping capabilities.                |
| [`useWalletServicesPlugin`](./useWalletServicesPlugin.mdx) | Provides access to Wallet Services plugins.         |

---

## useAuthTokenInfo

Hook to retrieve and manage the identity token from Embedded Wallets.

### Import

```tsx

```

### Usage

```tsx

function AuthTokenInfoButton() {
  const { getAuthTokenInfo, loading, error, token } = useAuthTokenInfo()

  return (
    
      <button onClick={() => getAuthTokenInfo()} disabled={loading}>
        {loading ? 'Authenticating...' : 'Get Identity Token'}
      </button>
      {token && Token: {token}}
      {error && Error: {error.message}}
    
  )
}
```

### Return type

```tsx

```

#### `loading`

`boolean`

Whether the authentication process is in progress.

#### `error`

`Web3AuthError | null`

Error that occurred during the authentication process.

#### `token`

`string | null`

The identity token returned after successful authentication.

#### `getAuthTokenInfo`

`() => Promise<string | null>`

Function to initiate the authentication process and retrieve the identity token.

---

## useCheckout

Hook to show the cryptocurrency checkout modal using Wallet Services plugin.

:::info

Please note that this hook doesn't work for external wallet logins. It only works for social login embedded wallets.

:::

### Import

```tsx

```

### Usage

```tsx

function CheckoutButton() {
  const { showCheckout, loading, error } = useCheckout()

  return (
    
      <button onClick={() => showCheckout()} disabled={loading}>
        {loading ? 'Opening Checkout...' : 'Show Checkout'}
      </button>
      {error && {error.message}}
    
  )
}
```

### Return type

```tsx

```

#### `loading`

`boolean`

Whether the checkout process is in progress.

#### `error`

`Web3AuthError | null`

error that occurred during the checkout process.

#### `showCheckout`

`(showCheckoutParams?: BaseEmbedControllerState["showCheckout"]) => Promise<void>`

Function to initiate the checkout modal. Optional `showCheckoutParams` can be passed to customize the modal.

---

## useEnableMFA

Hook to enable Multi-Factor Authentication (MFA) using Web3Auth.

:::info

Please note that this hook doesn't work for external wallet logins. It only works for social login embedded wallets.

:::

### Import

```tsx

```

### Usage

```tsx

function EnableMFAButton() {
  const { enableMFA, loading, error } = useEnableMFA()

  return (
    
      <button onClick={() => enableMFA()} disabled={loading}>
        {loading ? 'Enabling MFA...' : 'Enable MFA'}
      </button>
      {error && {error.message}}
    
  )
}
```

### Return type

```tsx

```

#### `loading`

`boolean`

Whether the MFA enabling process is in progress.

#### `error`

`Web3AuthError | null`

Error that occurred during the MFA enabling process.

#### `enableMFA`

`<T>(params?: T) => Promise<void>`

Function to initiate the MFA enabling process. Accepts optional parameters depending on the MFA method or configuration required by your implementation.

---

## useManageMFA

Hook to manage Multi-Factor Authentication (MFA) using Embedded Wallets. This hook provides a convenient way to trigger MFA management actions, such as updating or configuring MFA settings for the user.

:::info

Please note that this hook doesn't work for external wallet logins. It only works for social login embedded wallets.

:::

### Import

```tsx

```

### Usage

```tsx

function ManageMFAButton() {
  const { manageMFA, loading, error } = useManageMFA()

  return (
    
      <button onClick={() => manageMFA()} disabled={loading}>
        {loading ? 'Managing MFA...' : 'Manage MFA'}
      </button>
      {error && {error.message}}
    
  )
}
```

### Return type

```tsx

```

#### `loading`

`boolean`

Whether the MFA management process is in progress.

#### `error`

`Web3AuthError | null`

Error that occurred during the MFA management process.

#### `manageMFA`

`<T>(params?: T) => Promise<void>`

Function to initiate the MFA management process. Accepts optional parameters depending on the MFA action or configuration required by your implementation.

---

## useSwap

Hook to open the Swap interface using the Wallet Services plugin.

:::info

Please note that this hook doesn't work for external wallet logins. It only works for social login embedded wallets.

:::

### Import

```tsx

```

### Usage

```tsx

function SwapButton() {
  const { showSwap, loading, error } = useSwap()

  return (
    
      <button onClick={() => showSwap()} disabled={loading}>
        {loading ? 'Opening Swap...' : 'Open Swap'}
      </button>
      {error && Error: {error.message}}
    
  )
}
```

### Return type

```tsx

```

#### `loading`

`boolean`

Whether the swap interface is being opened.

#### `error`

`Web3AuthError | null`

Error that occurred while opening the swap interface.

#### `showSwap`

`(showSwapParams?: BaseEmbedControllerState["showSwap"]) => Promise<void>`

Function to open the swap interface. Accepts optional parameters for customizing the swap view.

---

## useSwitchChain

Hook to switch blockchain networks with Embedded Wallets.

### Import

```tsx

```

### Usage

```tsx

function SwitchChainButton() {
  const { switchChain, loading, error } = useSwitchChain()

  return (
    
      <button onClick={() => switchChain('0x1')} disabled={loading}>
        {loading ? 'Switching...' : 'Switch to Ethereum Mainnet'}
      </button>
      {error && Error: {error.message}}
    
  )
}
```

### Return type

```tsx

```

#### `loading`

`boolean`

Whether the chain switching process is in progress.

#### `error`

`Web3AuthError | null`

Error that occurred during the chain switching process.

#### `switchChain`

`(chainId: string) => Promise<void>`

Function to initiate the chain switch. Pass the target `chainId` as a string (for example, "0x1" for Ethereum Mainnet).

## Example

```tsx title="switchChain.tsx"

export function SwitchChain() {
  const { web3Auth } = useWeb3Auth()

  const { switchChain, error } = useSwitchChain()

  return (
    
      Switch chain
      Connected to {web3Auth?.currentChain?.displayName}
      {web3Auth?.coreOptions.chains?.map(chain => {
        return (
          <button
            disabled={web3Auth?.currentChain?.chainId === chain.chainId}
            key={chain.chainId}
            onClick={() => switchChain(chain.chainId)}
            type="button"
            className="card">
            {chain.displayName}
          </button>
        )
      })}

      {error?.message}
    
  )
}
```

---

## useWalletConnectScanner

Hook to show the WalletConnect QR scanner using the Wallet Services plugin.

:::info

Please note that this hook doesn't work for external wallet logins. It only works for social login embedded wallets.

:::

### Import

```tsx

```

### Usage

```tsx

function WalletConnectScannerButton() {
  const { showWalletConnectScanner, loading, error } = useWalletConnectScanner()

  return (
    
      <button onClick={() => showWalletConnectScanner()} disabled={loading}>
        {loading ? 'Opening Scanner...' : 'Show WalletConnect Scanner'}
      </button>
      {error && {error.message}}
    
  )
}
```

### Return type

```tsx

```

#### `loading`

`boolean`

Whether the scanner opening process is in progress.

#### `error`

`Web3AuthError | null`

Error that occurred during the scanner opening process.

#### `showWalletConnectScanner`

`(showWalletConnectScannerParams?: BaseEmbedControllerState["showWalletConnect"]) => Promise<void>`

Function to show the WalletConnect QR scanner. Accepts optional parameters for customizing the scanner behavior.

---

## useWalletServicesPlugin

Hook to access the Wallet Services plugin context, enabling wallet-related features such as WalletConnect, checkout, swap, and wallet UI.

:::info

Please note that this hook doesn't work for external wallet logins. It only works for social login embedded wallets.

:::

### Import

```tsx

```

### Usage

```tsx

function WalletServicesExample() {
  const { isPluginConnected, showWalletConnectScanner, showCheckout, showWalletUI } =
    useWalletServicesPlugin()

  return (
    
      <button onClick={() => showWalletConnectScanner()} disabled={!isPluginConnected}>
        Show WalletConnect Scanner
      </button>
      <button onClick={() => showCheckout()} disabled={!isPluginConnected}>
        Show Checkout
      </button>
      <button onClick={() => showWalletUI()} disabled={!isPluginConnected}>
        Show Wallet UI
      </button>
    
  )
}
```

### Return type

```tsx

```

#### `isPluginConnected`

`boolean`

Whether the Wallet Services plugin is connected and ready to use.

#### `showWalletConnectScanner`

`(showWalletConnectParams?: BaseEmbedControllerState["showWalletConnect"]) => Promise<void>`

Shows the WalletConnect QR scanner. Accepts optional parameters for customizing the scanner behavior.

#### `showCheckout`

`(showCheckoutParams?: BaseEmbedControllerState["showCheckout"]) => Promise<void>`

Shows the topup modal for fiat-to-crypto checkout. Accepts optional parameters for customizing the checkout experience.

#### `showWalletUI`

`(showWalletUiParams?: BaseEmbedControllerState["showWalletUi"]) => Promise<void>`

Shows the Wallet Services modal UI. Accepts optional parameters for customizing the wallet UI experience.

---

## useWalletUI

Hook to show the Wallet Services UI modal using the Wallet Services plugin.

:::info

Please note that this hook doesn't work for external wallet logins. It only works for social login embedded wallets.

:::

### Import

```tsx

```

### Usage

```tsx

function WalletUIButton() {
  const { showWalletUI, loading, error } = useWalletUI()

  return (
    
      <button onClick={() => showWalletUI()} disabled={loading}>
        {loading ? 'Opening Wallet UI...' : 'Show Wallet UI'}
      </button>
      {error && {error.message}}
    
  )
}
```

### Return type

```tsx

```

#### `loading`

`boolean`

Whether the Wallet UI opening process is in progress.

#### `error`

`Web3AuthError | null`

Error that occurred during the Wallet UI opening process.

#### `showWalletUI`

`(showWalletUiParams?: BaseEmbedControllerState["showWalletUi"]) => Promise<void>`

Function to show the Wallet Services modal UI. Accepts optional parameters for customizing the wallet UI experience.

---

## useWeb3Auth

Hook to access the Web3Auth context.

### Import

```tsx

```

### Usage

```tsx

function App() {
  const { web3Auth, isConnected, isInitializing, connection, status, initError } = useWeb3Auth()

  if (isConnected) {
    console.log('Connected via:', connection?.connectorName)
  }
  if (isInitializing) {
    console.log('Web3Auth is initializing')
  }
  if (connection?.ethereumProvider) {
    // Use for JSON-RPC edge cases; prefer Wagmi hooks for standard EVM flows
    console.log('Ethereum provider available')
  }
  if (status) {
    console.log('Web3Auth status:', status)
  }
  if (initError) {
    console.log('Web3Auth initialization error:', initError)
  }
}
```

:::info

For EVM wallet operations, use [Wagmi hooks](../ethereum-hooks.mdx) (`useConnection`, `useBalance`,
`useSendTransaction`) after setting up `WagmiProvider`.
Use `connection.ethereumProvider` only for JSON-RPC methods Wagmi does not cover.
See the [Web SDK v11 migration guide](/embedded-wallets/migration-guides/web#provider-api-changes-all-frameworks).

:::

### Return type

```tsx

```

#### `connection`

`{ ethereumProvider, solanaWallet, connectorName } | null`

Active wallet connection after sign-in. `ethereumProvider` is an EIP-1193 provider for EVM;
`solanaWallet` exposes Solana wallet utilities.

#### `initError`

`Error | null`

Error that occurred during Web3Auth initialization.

#### `isConnected`

`boolean`

Whether the user is connected to Web3Auth.

#### `isInitialized`

`boolean`

Whether Web3Auth has completed initialization.

#### `isInitializing`

`boolean`

Whether Web3Auth is currently initializing.

#### `status`

`string`

Current status of the Web3Auth connection.

#### `web3Auth`

`Web3Auth`

The Web3Auth instance.

#### `getPlugin`

`(pluginName: PLUGIN_NAME) => IPlugin | null`

Helper function to get a plugin by name.

---

## useWeb3AuthConnect

Hook to connect to Web3Auth.

### Import

```tsx

```

### Choosing the right connection method

You can connect users to Web3Auth in two main ways, depending on your application's needs:

- **Use `connect()`** when you want to display the default Web3Auth modal. This is ideal if you want to provide users with a pre-built, user-friendly interface where they can choose from all available login options (for example, social logins, wallets) with minimal setup.

- **Use `connectTo(connector, params)`** when you want to build a fully custom login experience. This method lets you bypass the Web3Auth modal and connect directly to a specific wallet connector (such as Google, Facebook, or a particular wallet). Choose this if you want to design your own UI for login options, or if you want to restrict users to a specific authentication method. This method also allows you to use JWT-based login configurations.

**Summary:**

- Use `connect()` for the standard modal experience.
- Use `connectTo()` for custom UIs or direct connection to a specific login method.

### Usage

<Tabs
  defaultValue="basic"
  values={[
    { label: "Basic Modal", value: "basic" },
    { label: "Custom UI", value: "custom-ui" },
  ]}
>

<TabItem value="basic">

:::info

This is the most common way to connect to Web3Auth. It opens the Web3Auth modal UI, allowing users to select from available login options.

:::

```tsx

function ConnectButton() {
  const { connect, loading, isConnected, error } = useWeb3AuthConnect()

  return (
    
      <button onClick={() => connect()} disabled={loading || isConnected}>
        {loading ? 'Connecting...' : isConnected ? 'Connected' : 'Connect'}
      </button>
      {error && {error.message}}
    
  )
}
```

</TabItem>

<TabItem value="custom-ui">

:::info

This method allows you to build your own custom connection UI. It bypasses the Web3Auth modal UI, allowing you to create your own custom UI for login options. This can be useful if you want to hide Web3Auth from your end users.

:::

```tsx

function CustomConnectors() {
  const { connectTo, loading, isConnected, error } = useWeb3AuthConnect()

  const loginWithGoogle = () => {
    connectTo(WALLET_CONNECTORS.AUTH, { authConnection: AUTH_CONNECTION.GOOGLE })
  }

  return (
    
      <button onClick={loginWithGoogle} disabled={loading || isConnected}>
        Login with Google
      </button>
      {error && {error.message}}
    
  )
}
```

</TabItem>

</Tabs>

### Return type

```tsx

```

#### `isConnected`

`boolean`

Whether the user is connected to Web3Auth.

#### `loading`

`boolean`

Whether the connection process is in progress.

#### `error`

`Web3AuthError | null`

error that occurred during the connection process.

#### `connectorName`

`WALLET_CONNECTOR_TYPE | null`

Name of the connected connector.

#### `connect`

`() => Promise<Connection | null>`

Function to initiate the connection process. Opens the Web3Auth modal UI.

#### `connectTo`

`<T extends WALLET_CONNECTOR_TYPE>(connector: T, params?: LoginParamMap[T]) => Promise<Connection | null>`

Function to connect directly to a specific wallet connector. This bypasses the Web3Auth modal UI, allowing you to build custom interfaces. This method also allows you to use JWT-based login configurations.

---

## useWeb3AuthDisconnect

Hook to disconnect from Embedded Wallets.

### Import

```tsx

```

### Usage

```tsx

function DisconnectButton() {
  const { disconnect, loading, error } = useWeb3AuthDisconnect()

  return (
    
      <button onClick={() => disconnect()} disabled={loading}>
        {loading ? 'Disconnecting...' : 'Disconnect'}
      </button>
      {error && {error.message}}
    
  )
}
```

### Return type

```tsx

```

#### `loading`

`boolean`

Whether the disconnection process is in progress.

#### `error`

`Web3AuthError | null`

Error that occurred during the disconnection process.

#### `disconnect`

`(options?: { cleanup: boolean }) => Promise<void>`

Function to initiate the disconnection process. Optional `cleanup` parameter controls whether to remove all user data.

---

## useWeb3AuthUser

Hook to fetch and manage the current Embedded Wallets user information.

In Web SDK v11, `userInfo` can include a `linkedAccounts` array when the user has linked external wallets.
See [User details](/embedded-wallets/dashboard/advanced/user-details/#richer-user-object-web-sdk-v11) and [Multi-wallet linking](/embedded-wallets/features/multi-wallet-linking/).

:::info

For external-wallet-only logins, profile fields may be limited compared to social or passwordless logins.
Use `linkedAccounts` to see every wallet linked to the same user.

:::

### Import

```tsx

```

### Usage

```tsx

function UserInfo() {
  const { userInfo, loading, error, isMFAEnabled, getUserInfo } = useWeb3AuthUser()

  if (loading) return Loading user info...
  if (error) return Error: {error.message}
  if (!userInfo) return No user info available.

  return (
    <>
      
        <pre>{JSON.stringify(userInfo, null, 2)}</pre>
        MFA Enabled: {isMFAEnabled ? 'Yes' : 'No'}
        <button onClick={() => getUserInfo()}>Refresh User Info</button>
      
      {error && {error.message}}
    </>
  )
}
```

### Return type

```tsx

```

#### `loading`

`boolean`

Whether the user info fetching process is in progress.

#### `error`

`Web3AuthError | null`

Error that occurred during the user info fetching process.

#### `userInfo`

`Partial<UserInfo> | null`

The current user's information, or null if not available.
May include `linkedAccounts` (array of linked wallet addresses and connectors) in Web SDK v11.

#### `isMFAEnabled`

`boolean`

Whether Multi-Factor Authentication (MFA) is enabled for the user.

#### `getUserInfo`

`() => Promise<Partial<UserInfo> | null>`

Function to fetch the latest user information from Web3Auth.

---

## React hooks for Solana

Embedded Wallets provides a set of React hooks for basic Solana wallet operations. These hooks are designed to simplify common Solana interactions in your React app.

:::info

For building transactions, use [`@solana/kit`](https://www.npmjs.com/package/@solana/kit) and [`@solana-program/system`](https://www.npmjs.com/package/@solana-program/system) with the hooks provided.

:::

## Solana hooks

| Hook Name                                                      | Description                                  |
| -------------------------------------------------------------- | -------------------------------------------- |
| [`useSignAndSendTransaction`](./useSignAndSendTransaction.mdx) | Sign and send a Solana transaction.          |
| [`useSignMessage`](./useSignMessage.mdx)                       | Sign a message with the Solana wallet.       |
| [`useSignTransaction`](./useSignTransaction.mdx)               | Sign a Solana transaction (without sending). |
| [`useSolanaWallet`](./useSolanaWallet.mdx)                     | Access Solana wallet state and utilities.    |

Install dependencies:

```bash npm2yarn
npm install @solana/kit @solana-program/system @solana/react-hooks
```

---

## useSignAndSendTransaction

Hook to sign and send a Solana transaction using the connected Solana wallet from Embedded Wallets.

### Import

```tsx

```

### Usage

```tsx

function SignAndSendTransactionButton({
  transaction,
}: {
  transaction: TransactionOrVersionedTransaction
}) {
  const { signAndSendTransaction, loading, error, data } = useSignAndSendTransaction()

  const handleSignAndSend = async () => {
    try {
      const signature = await signAndSendTransaction(transaction)
      // Do something with signature
    } catch (e) {
      // Handle error
    }
  }

  return (
    
      <button onClick={handleSignAndSend} disabled={loading}>
        {loading ? 'Signing & Sending...' : 'Sign & Send Transaction'}
      </button>
      {error && Error: {error.message}}
      {data && Signature: {data}}
    
  )
}
```

### Return type

```ts
export type IUseSignAndSendTransaction = {
  loading: boolean
  error: Web3AuthError | null
  data: string | null
  signAndSendTransaction: (transaction: TransactionOrVersionedTransaction) => Promise<string>
}
```

#### `loading`

`boolean`

Indicates if the transaction signing and sending is in progress.

#### `error`

`Web3AuthError | null`

Error object if signing or sending fails, otherwise null.

#### `data`

`string | null`

The transaction signature as a string, or null if not signed yet.

#### `signAndSendTransaction`

`(transaction: TransactionOrVersionedTransaction) => Promise<string>`

Function to sign and send a transaction. Returns the transaction signature as a string.

## Example

```tsx title="sendVersionedTransaction.tsx"

export function SendVersionedTransaction() {
  const { web3Auth } = useWeb3Auth()
  const { accounts } = useSolanaWallet()
  const {
    data: signature,
    error,
    loading: isPending,
    signAndSendTransaction,
  } = useSignAndSendTransaction()
  const [formError, setFormError] = useState<string | null>(null)

  async function submit(e: FormEvent<HTMLFormElement>) {
    e.preventDefault()
    setFormError(null)

    const rpcTarget = web3Auth?.currentChain?.rpcTarget
    if (!rpcTarget || !accounts?.length) return

    const form = new FormData(e.currentTarget)
    const to = form.get('address')?.toString().trim() ?? ''
    const amountSol = Number(form.get('value'))
    if (!to || !Number.isFinite(amountSol) || amountSol <= 0) {
      setFormError('Enter a valid recipient address and a positive amount.')
      return
    }

    try {
      const transaction = await buildSolTransferTransaction(rpcTarget, accounts[0], to, amountSol)
      await signAndSendTransaction(transaction)
    } catch (err) {
      setFormError(err instanceof Error ? err.message : 'Failed to send transaction.')
    }
  }

  return (
    
      Send Transaction
      <form onSubmit={submit}>
        <input name="address" placeholder="Recipient address" required />
        <input name="value" placeholder="Amount (SOL)" type="number" step="0.01" min="0" required />
        <button disabled={isPending} type="submit">
          {isPending ? 'Sending...' : 'Send'}
        </button>
      </form>
      {signature && Transaction signature: {signature}}
      {(formError ?? error?.message) && (
        Error: {formError ?? error?.message}
      )}
    
  )
}
```

---

## useSignMessage

Hook to sign a message using the connected Solana wallet from Embedded Wallets.

### Import

```tsx

```

### Usage

```tsx

function SignMessageButton({ message }: { message: string }) {
  const { signMessage, loading, error, data } = useSignMessage()

  const handleSign = async () => {
    try {
      const signature = await signMessage(message)
      // Do something with signature
    } catch (e) {
      // Handle error
    }
  }

  return (
    
      <button onClick={handleSign} disabled={loading}>
        {loading ? 'Signing...' : 'Sign Message'}
      </button>
      {error && Error: {error.message}}
      {data && Signature: {data}}
    
  )
}
```

### Return type

```ts
export type IUseSignMessage = {
  loading: boolean
  error: Web3AuthError | null
  data: string | null
  signMessage: (message: string) => Promise<string>
}
```

#### `loading`

`boolean`

Indicates if the message signing is in progress.

#### `error`

`Web3AuthError | null`

Error object if signing fails, otherwise null.

#### `data`

`string | null`

The signature as a string, or null if not signed yet.

#### `signMessage`

`(message: string) => Promise<string>`

Function to sign a message. Returns the signature as a string.

## Example

```tsx title="signMessage.tsx"

export function SignMessage() {
  const { signMessage, loading, error, data } = useSignMessage()

  async function submit(e: FormEvent<HTMLFormElement>) {
    e.preventDefault()
    const formData = new FormData(e.target as HTMLFormElement)
    const message = formData.get('message')?.toString().trim()
    if (!message) return
    void signMessage(message)
  }

  return (
    <form onSubmit={submit}>
      <input name="message" placeholder="Message" required />
      <button disabled={loading} type="submit">
        {loading ? 'Signing...' : 'Sign message'}
      </button>
      {data && Message hash: {data}}
      {error && Error: {error.message}}
    </form>
  )
}
```

---

## useSignTransaction

Hook to sign a Solana transaction using the connected wallet from Embedded Wallets.

### Import

```tsx

```

### Usage

```tsx

function SignTransactionButton({ transaction }: { transaction: Transaction }) {
  const { signTransaction, loading, error, data } = useSignTransaction()

  const handleSign = async () => {
    try {
      const signedTx = await signTransaction(transaction)
      // Do something with signedTx
    } catch (e) {
      // Handle error
    }
  }

  return (
    
      <button onClick={handleSign} disabled={loading}>
        {loading ? 'Signing...' : 'Sign Transaction'}
      </button>
      {error && Error: {error.message}}
      {data && Signed Transaction: {data}}
    
  )
}
```

### Return type

```ts
export type IUseSignTransaction = {
  loading: boolean
  error: Web3AuthError | null
  data: string | null
  signTransaction: (transaction: TransactionOrVersionedTransaction) => Promise<string>
}
```

#### `loading`

`boolean`

Indicates if the transaction signing is in progress.

#### `error`

`Web3AuthError | null`

Error object if signing fails, otherwise null.

#### `data`

`string | null`

The signed transaction as a string, or null if not signed yet.

#### `signTransaction`

`(transaction: TransactionOrVersionedTransaction) => Promise<string>`

Function to sign a Solana transaction. Returns the signed transaction as a string.

## Example

```tsx title="signTransaction.tsx"

export function SignTransaction() {
  const { web3Auth } = useWeb3Auth()
  const { accounts } = useSolanaWallet()
  const {
    data: signedTransaction,
    error,
    loading: isPending,
    signTransaction,
  } = useSignTransaction()
  const [formError, setFormError] = useState<string | null>(null)

  async function submit(e: FormEvent<HTMLFormElement>) {
    e.preventDefault()
    setFormError(null)

    const rpcTarget = web3Auth?.currentChain?.rpcTarget
    if (!rpcTarget || !accounts?.length) return

    const form = new FormData(e.currentTarget)
    const to = form.get('address')?.toString().trim() ?? ''
    const amountSol = Number(form.get('value'))
    if (!to || !Number.isFinite(amountSol) || amountSol <= 0) {
      setFormError('Enter a valid recipient address and a positive amount.')
      return
    }

    try {
      const transaction = await buildSolTransferTransaction(rpcTarget, accounts[0], to, amountSol)
      await signTransaction(transaction)
    } catch (err) {
      setFormError(err instanceof Error ? err.message : 'Failed to sign transaction.')
    }
  }

  return (
    
      Sign Transaction
      <form onSubmit={submit}>
        <input name="address" placeholder="Recipient address" required />
        <input name="value" placeholder="Amount (SOL)" type="number" step="0.01" min="0" required />
        <button disabled={isPending} type="submit">
          {isPending ? 'Signing...' : 'Sign'}
        </button>
      </form>
      {signedTransaction && Signed transaction: {signedTransaction}}
      {(formError ?? error?.message) && (
        Error: {formError ?? error?.message}
      )}
    
  )
}
```

```tsx title="solana/transfer.ts"

  address,
  appendTransactionMessageInstruction,
  compileTransaction,
  createNoopSigner,
  createSolanaRpc,
  createTransactionMessage,
  lamports,
  pipe,
  setTransactionMessageFeePayerSigner,
  setTransactionMessageLifetimeUsingBlockhash,
} from '@solana/kit'

export async function buildSolTransferTransaction(
  rpcTarget: string,
  from: string,
  to: string,
  amountSol: number
): Promise<Transaction> {
  const rpc = createSolanaRpc(rpcTarget)
  const { value: latestBlockhash } = await rpc.getLatestBlockhash().send()
  const feePayer = createNoopSigner(address(from))

  const message = pipe(
    createTransactionMessage({ version: 0 }),
    m => setTransactionMessageFeePayerSigner(feePayer, m),
    m => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, m),
    m =>
      appendTransactionMessageInstruction(
        getTransferSolInstruction({
          source: feePayer,
          destination: address(to),
          amount: lamports(BigInt(Math.round(amountSol * 1e9))),
        }),
        m
      )
  )

  return compileTransaction(message)
}
```

---

## useSolanaWallet

Hook to retrieve Solana accounts, RPC client, and wallet from Web3Auth.

### Import

```tsx

```

### Usage

```tsx

function SolanaWalletInfo() {
  const { accounts, rpc, solanaWallet, getPrivateKey } = useSolanaWallet()

  return (
    
      Accounts: {accounts ? accounts.join(', ') : 'No accounts'}
      Solana wallet: {solanaWallet ? 'Available' : 'Not available'}
      RPC: {rpc ? 'Available' : 'Not available'}
    
  )
}
```

### Return type

```tsx

```

#### `accounts`

`string[] | null`

Base58 Solana account addresses, or `null` if not available.

#### `solanaWallet`

`Wallet | null`

The wallet-standard Solana wallet instance, or `null` if not available.

#### `rpc`

`Rpc<SolanaRpcApi> | null`

The `@solana/kit` RPC client for making Solana RPC calls, or `null` if not available.

#### `getPrivateKey`

`() => Promise<string>`

Returns the user's private key when available (in-app adapters only).

### Example: Fetching SOL balance

```tsx title="getBalance.tsx"

export function Balance() {
  const { web3Auth } = useWeb3Auth()
  const { accounts } = useSolanaWallet()
  const [balance, setBalance] = useState<string | null>(null)
  const [isLoading, setIsLoading] = useState(false)
  const [error, setError] = useState<string | null>(null)

  async function fetchBalance() {
    const rpcTarget = web3Auth?.currentChain?.rpcTarget
    if (!rpcTarget || !accounts?.length) return

    setIsLoading(true)
    setError(null)
    try {
      const rpc = createSolanaRpc(rpcTarget)
      const { value } = await rpc.getBalance(address(accounts[0])).send()
      setBalance(`${Number(value) / 1e9} SOL`)
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to fetch balance.')
    } finally {
      setIsLoading(false)
    }
  }

  return (
    
      Balance
      {balance && {balance}}
      <button
        onClick={() => void fetchBalance()}
        type="button"
        className="card"
        disabled={isLoading}>
        {isLoading ? 'Fetching...' : 'Fetch Balance'}
      </button>
      {error && Error: {error}}
    
  )
}
```

---

## Embedded Wallets SDK for React Native

## Overview

The MetaMask Embedded Wallets SDK for React Native lets you add social login and embedded wallet functionality to your iOS and Android apps. Version 9 is a hooks-first API: you wrap your app in a `Web3AuthProvider` and access all functionality through React hooks, no class instance, no `useEffect`-based initialisation.

:::info Migration from v8 or earlier

Use the [React Native migration guide](/embedded-wallets/migration-guides/react-native). It includes an LLM agent prompt, a full legacy-to-v9 API map, and step-by-step file targets for any prior `@web3auth/react-native-sdk` version.

:::

## Requirements

- React Native 0.71 or later (bare workflow)
- Expo SDK 48 or later (managed workflow)
- iOS 14 or later
- Android API level 31 or later (target SDK)

## Prerequisites

Set up your project on the [Embedded Wallets dashboard](https://developer.metamask.io/):

1. Create a new project and copy the **Client ID**.
2. Go to **Allowed Origins** and add your app's deep link scheme (for example, `web3authrnexample://auth`).

See the [dashboard setup guide](../../dashboard/README.mdx) for more detail.

## Installation

### 1. Install the SDK

```bash npm2yarn
npm install @web3auth/react-native-sdk
```

### 2. Install helper modules

The SDK requires a `WebBrowser` and a persistent `Storage` implementation. The correct packages differ between bare React Native and Expo:

<Tabs
  defaultValue="bare"
  values={[
    { label: 'Bare React Native', value: 'bare' },
    { label: 'Expo', value: 'expo' },
  ]}
>

<TabItem value="bare">

```bash npm2yarn
npm install @toruslabs/react-native-web-browser react-native-encrypted-storage
npm install --save-dev @babel/plugin-transform-export-namespace-from
```

</TabItem>

<TabItem value="expo">

```bash npm2yarn
npm install expo-web-browser expo-secure-store
npm install --save-dev @babel/plugin-transform-export-namespace-from
```

</TabItem>

</Tabs>

### 3. Android setup

In your `android/app/build.gradle`, ensure the compile SDK version is 31 or higher:

```gradle title="android/app/build.gradle"
compileSdkVersion = 31
targetSdkVersion = 31
```

Add the intent filter with your custom scheme to `AndroidManifest.xml`:

```xml title="AndroidManifest.xml"
<intent-filter>
  <action android:name="android.intent.action.VIEW" />
  <category android:name="android.intent.category.DEFAULT" />
  <category android:name="android.intent.category.BROWSABLE" />
  <!-- replace with your own scheme -->
  <data android:scheme="web3authrnexample" />
</intent-filter>
```

Also set `android:exported="true"` on your main activity:

```xml title="AndroidManifest.xml"
<activity
  android:name=".MainActivity"
  android:exported="true"
  ...>
```

### 4. iOS setup

In your `Podfile`, set the minimum platform to iOS 14:

```ruby title="Podfile"
platform :ios, '14'
```

Then install Pods:

```sh
cd ios && pod install
```

Register your redirect URL (for example, `web3authrnexample://auth`) in the **Allowed Origins** section of the dashboard. No additional Info.plist entry is required.

### 5. Expo setup

Add your scheme to `app.json`:

```json title="app.json"
{
  "expo": {
    "scheme": "web3authexpoexample"
  }
}
```

:::note

The SDK does not work with the Expo Go app. Use a custom dev client or an EAS build. Run `npx expo prebuild` before building.

:::

## Configure polyfills and bundler

### Entry point

Add `import "@web3auth/react-native-sdk/setup"` as the **first line** of your app's entry file. This single import replaces the `globals.js` / `react-native-get-random-values` pattern used in v8.

<Tabs
  defaultValue="bare"
  values={[
    { label: 'Bare React Native', value: 'bare' },
    { label: 'Expo', value: 'expo' },
  ]}
>

<TabItem value="bare">

```js title="index.js"
// highlight-next-line

AppRegistry.registerComponent(appName, () => App)
```

</TabItem>

<TabItem value="expo">

Create `index.ts` and change `"main"` to `"index.ts"` in `package.json`:

```ts title="index.ts"
// highlight-next-line

registerRootComponent(App)
```

</TabItem>

</Tabs>

### Metro bundler

<Tabs
  defaultValue="bare"
  values={[
    { label: 'Bare React Native', value: 'bare' },
    { label: 'Expo', value: 'expo' },
  ]}
>

<TabItem value="bare">

```js title="metro.config.js"
const { getDefaultConfig } = require('@react-native/metro-config')
// highlight-next-line
const { withWeb3Auth } = require('@web3auth/react-native-sdk/metro-config')

const config = getDefaultConfig(__dirname)
// highlight-next-line
module.exports = withWeb3Auth(config)
```

</TabItem>

<TabItem value="expo">

```js title="metro.config.js"
const { getDefaultConfig } = require('expo/metro-config')
// highlight-next-line
const { withWeb3Auth } = require('@web3auth/react-native-sdk/metro-config')

const config = getDefaultConfig(__dirname)
// highlight-next-line
module.exports = withWeb3Auth(config)
```

</TabItem>

</Tabs>

### Babel config

<Tabs
  defaultValue="bare"
  values={[
    { label: 'Bare React Native', value: 'bare' },
    { label: 'Expo', value: 'expo' },
  ]}
>

<TabItem value="bare">

```js title="babel.config.js"
module.exports = {
  presets: ['module:@react-native/babel-preset'],
  // highlight-next-line
  plugins: ['@babel/plugin-transform-export-namespace-from'],
}
```

</TabItem>

<TabItem value="expo">

```js title="babel.config.js"
module.exports = function (api) {
  api.cache(true)
  return {
    presets: ['babel-preset-expo'],
    // highlight-next-line
    plugins: ['@babel/plugin-transform-export-namespace-from'],
  }
}
```

</TabItem>

</Tabs>

## SDK configuration

Create a dedicated `web3authConfig.ts` file. This is the only file you need to edit to change SDK settings, chains, or optional features.

<Tabs
  defaultValue="basic"
  values={[
    { label: 'Basic (EVM)', value: 'basic' },
    { label: 'Solana', value: 'solana' },
    { label: 'With Account Abstraction', value: 'aa' },
  ]}
>

<TabItem value="basic">

```typescript title="web3authConfig.ts"

  CHAIN_NAMESPACES,
  WEB3AUTH_NETWORK,
  type Web3AuthContextConfig,
} from '@web3auth/react-native-sdk'

const web3AuthConfig: Web3AuthContextConfig = {
  web3AuthOptions: {
    clientId: 'YOUR_CLIENT_ID', // from developer.metamask.io
    redirectUrl: 'web3authrnexample://auth',
    network: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
    chains: [
      {
        chainNamespace: CHAIN_NAMESPACES.EIP155,
        chainId: '0xaa36a7',
        rpcTarget: 'https://rpc.ankr.com/eth_sepolia',
        displayName: 'Ethereum Sepolia Testnet',
        blockExplorerUrl: 'https://sepolia.etherscan.io',
        ticker: 'ETH',
        tickerName: 'Ethereum',
      },
    ],
    defaultChainId: '0xaa36a7',
  },
}

export default web3AuthConfig
```

</TabItem>

<TabItem value="solana">

```typescript title="web3authConfig.ts"

  CHAIN_NAMESPACES,
  WEB3AUTH_NETWORK,
  type Web3AuthContextConfig,
} from '@web3auth/react-native-sdk'

const web3AuthConfig: Web3AuthContextConfig = {
  web3AuthOptions: {
    clientId: 'YOUR_CLIENT_ID',
    redirectUrl: 'web3authrnexample://auth',
    network: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
    chains: [
      {
        chainNamespace: CHAIN_NAMESPACES.SOLANA,
        chainId: '0x2', // Solana Testnet
        rpcTarget: 'https://api.testnet.solana.com',
        displayName: 'Solana Testnet',
        blockExplorerUrl: 'https://explorer.solana.com',
        ticker: 'SOL',
        tickerName: 'Solana',
      },
    ],
    defaultChainId: '0x2',
  },
}

export default web3AuthConfig
```

</TabItem>

<TabItem value="aa">

```typescript title="web3authConfig.ts"

  CHAIN_NAMESPACES,
  WEB3AUTH_NETWORK,
  type AccountAbstractionConfig,
  type Web3AuthContextConfig,
} from '@web3auth/react-native-sdk'

const aaConfig: AccountAbstractionConfig = {
  smartAccountType: 'safe',
}

const web3AuthConfig: Web3AuthContextConfig = {
  web3AuthOptions: {
    clientId: 'YOUR_CLIENT_ID',
    redirectUrl: 'web3authrnexample://auth',
    network: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
    chains: [
      {
        chainNamespace: CHAIN_NAMESPACES.EIP155,
        chainId: '0xaa36a7',
        rpcTarget: 'https://rpc.ankr.com/eth_sepolia',
        displayName: 'Ethereum Sepolia Testnet',
        blockExplorerUrl: 'https://sepolia.etherscan.io',
        ticker: 'ETH',
        tickerName: 'Ethereum',
      },
    ],
    defaultChainId: '0xaa36a7',
    accountAbstractionConfig: aaConfig,
  },
}

export default web3AuthConfig
```

</TabItem>

</Tabs>

## Set up `Web3AuthProvider`

`Web3AuthProvider` is the React context provider that initialises the SDK and makes all hooks available to the component tree.

<Tabs
  defaultValue="bare"
  values={[
    { label: 'Bare React Native', value: 'bare' },
    { label: 'Expo', value: 'expo' },
  ]}
>

<TabItem value="bare">

```tsx

export default function App() {
  return (
    <Web3AuthProvider webBrowser={WebBrowser} storage={EncryptedStorage} config={web3AuthConfig}>
      <Screen />
    </Web3AuthProvider>
  )
}
```

</TabItem>

<TabItem value="expo">

```tsx

export default function App() {
  return (
    <Web3AuthProvider webBrowser={WebBrowser} storage={SecureStore} config={web3AuthConfig}>
      <Screen />
    </Web3AuthProvider>
  )
}
```

</TabItem>

</Tabs>

### Props

| Prop         | Type                    | Required | Description                                                                                                                                                   |
| ------------ | ----------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `webBrowser` | `IWebBrowser`           | Yes      | In-app browser implementation. Use `@toruslabs/react-native-web-browser` for bare React Native and `expo-web-browser` for Expo.                               |
| `storage`    | `IStorage`              | Yes      | Persistent key-value storage for session data. Use `react-native-encrypted-storage` for bare React Native and `expo-secure-store` for Expo.                   |
| `config`     | `Web3AuthContextConfig` | Yes      | SDK configuration object containing `web3AuthOptions`. Typically imported from a dedicated `web3authConfig.ts` file.                                          |
| `key?`       | `string`                | No       | React reconciler key. Change this value to force the provider to remount with a new configuration (for example, when toggling account abstraction on or off). |
| `children`   | `React.ReactNode`       | Yes      | Child components that consume the Web3Auth hooks.                                                                                                             |

## Sign users in

Call `connectTo` from the `useWeb3AuthConnect` hook. The SDK opens the authentication provider in an in-app browser and returns control to your app after the redirect.

```tsx

function LoginView() {
  const { connectTo, loading } = useWeb3AuthConnect()

  return (
    <View>
      <Button
        title={loading ? 'Signing in…' : 'Sign in with Google'}
        disabled={loading}
        onPress={() => connectTo({ authConnection: AUTH_CONNECTION.GOOGLE })}
      />
      <Button
        title="Sign in with Email"
        onPress={() =>
          connectTo({
            authConnection: AUTH_CONNECTION.EMAIL_PASSWORDLESS,
            extraLoginOptions: { login_hint: 'user@example.com' },
          })
        }
      />
    </View>
  )
}
```

See the [hooks reference](./hooks/) and the [login usage page](./usage/login.mdx) for the full `connectTo` parameter reference.

## Use the provider for EVM calls

After the user connects, use `useWeb3Auth().provider` with `ethers` or `viem`. No additional provider setup is needed.

```tsx

function HomeView() {
  const { provider } = useWeb3Auth()

  const getAddress = async () => {
    const ep = new ethers.BrowserProvider(provider!)
    const signer = await ep.getSigner()
    return await signer.getAddress()
  }

  const signMessage = async (message: string) => {
    const ep = new ethers.BrowserProvider(provider!)
    const signer = await ep.getSigner()
    return await signer.signMessage(message)
  }
}
```

## Use the signer for Solana

```tsx

function SolanaView() {
  const { web3Auth } = useWeb3Auth()
  const signer = web3Auth?.signer as TransactionSigner | null

  const getAddress = () => String(signer?.address)

  const getBalance = async () => {
    const connection = new Connection('https://api.testnet.solana.com', 'confirmed')
    return connection.getBalance(new PublicKey(getAddress()))
  }
}
```

## Advanced configuration

- [Account Abstraction (smart accounts)](./advanced/smart-accounts.mdx)
- [Custom authentication](./advanced/custom-authentication.mdx)
- [Whitelabeling and UI customization](./advanced/whitelabel.mdx)
- [Multi-Factor Authentication (MFA)](./advanced/mfa.mdx)
- [Dapp share](./advanced/dapp-share.mdx)

## Hooks reference

See the [hooks reference](./hooks/) for full documentation on all available hooks:
`useWeb3Auth`, `useWeb3AuthConnect`, `useWeb3AuthDisconnect`, `useWeb3AuthUser`, `useWalletUI`, `useSignatureRequest`, `useIdentityToken`, `useEnableMFA`, `useManageMFA`.

## Troubleshooting

If you run into Metro bundler errors, see the [Metro polyfill troubleshooting guide](../../troubleshooting/metro-issues.mdx).

---

## Advanced configuration(6)

All advanced SDK settings are configured in a `web3authConfig.ts` file and passed to `Web3AuthProvider` via the `config` prop. There is no constructor to call, the provider initialises the SDK automatically using the options you supply.

## Configuration file

```typescript title="web3authConfig.ts"

  CHAIN_NAMESPACES,
  WEB3AUTH_NETWORK,
  MFA_LEVELS,
  type Web3AuthContextConfig,
} from '@web3auth/react-native-sdk'

const web3AuthConfig: Web3AuthContextConfig = {
  web3AuthOptions: {
    clientId: 'YOUR_CLIENT_ID', // from developer.metamask.io
    redirectUrl: 'yourapp://auth',
    network: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
    chains: [
      {
        chainNamespace: CHAIN_NAMESPACES.EIP155,
        chainId: '0xaa36a7',
        rpcTarget: 'https://rpc.ankr.com/eth_sepolia',
        displayName: 'Ethereum Sepolia Testnet',
        blockExplorerUrl: 'https://sepolia.etherscan.io',
        ticker: 'ETH',
        tickerName: 'Ethereum',
      },
    ],
    defaultChainId: '0xaa36a7',
    // Optional advanced settings:
    mfaLevel: MFA_LEVELS.DEFAULT,
    sessionTime: 86400 * 7, // 7 days
    enableLogging: false,
  },
}

export default web3AuthConfig
```

## `web3AuthOptions` parameter reference

<Tabs
  defaultValue="table"
  values={[
    { label: 'Parameters', value: 'table' },
    { label: 'Interface', value: 'interface' },
  ]}
>

<TabItem value="table">

| Parameter                   | Required | Description                                                                                                                                                                                                               |
| --------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `clientId`                  | Yes      | Your project's Client ID from the [Embedded Wallets dashboard](https://developer.metamask.io).                                                                                                                            |
| `network`                   | Yes      | Sapphire network to use. Use `WEB3AUTH_NETWORK.SAPPHIRE_DEVNET` for development (allows `localhost`) and `WEB3AUTH_NETWORK.SAPPHIRE_MAINNET` for production.                                                              |
| `redirectUrl`               | Yes      | Deep link URL that Web3Auth redirects to after authentication. Must be allowlisted in the dashboard under **Allowed Origins**.                                                                                            |
| `chains?`                   | No       | Array of `CustomChainConfig` objects defining the EVM or Solana chains your app supports. Replaces the v8 `privateKeyProvider` pattern. The SDK creates the appropriate provider automatically based on `chainNamespace`. |
| `defaultChainId?`           | No       | Hex chain ID string for the default active chain (for example, `"0xaa36a7"`). Defaults to the first entry in `chains`.                                                                                                    |
| `accountAbstractionConfig?` | No       | Smart account configuration (`AccountAbstractionMultiChainConfig`). Set `smartAccountType` to `"safe"` or another supported provider to enable account abstraction. Set to `null` to disable.                             |
| `walletServicesConfig?`     | No       | Configuration for the Wallet Services in-app browser overlay. Controls `confirmationStrategy` and other embed parameters.                                                                                                 |
| `whiteLabel?`               | No       | Custom branding and UI options (`WhiteLabelData`). Applies to the authentication screens launched in the in-app browser.                                                                                                  |
| `mfaLevel?`                 | No       | Default MFA prompt behavior. Accepts `MFA_LEVELS.DEFAULT`, `MFA_LEVELS.OPTIONAL`, `MFA_LEVELS.MANDATORY`, or `MFA_LEVELS.NONE`.                                                                                           |
| `sessionTime?`              | No       | Session duration in seconds. Minimum is `1`; maximum is `86400 * 30` (30 days). Defaults to `86400` (1 day).                                                                                                              |
| `enableLogging?`            | No       | Set to `true` to print SDK debug logs to the console. Defaults to `false`.                                                                                                                                                |
| `walletSdkURL?`             | No       | Optional URL override for the Wallet Services embed. Leave unset to use the default production URL.                                                                                                                       |

</TabItem>

<TabItem value="interface">

```typescript
export interface SdkInitParams {
  /** Your project Client ID from the Embedded Wallets dashboard */
  clientId: string
  /** Sapphire network: SAPPHIRE_DEVNET or SAPPHIRE_MAINNET */
  network: WEB3AUTH_NETWORK_TYPE
  /** Deep link URL registered in the dashboard under Allowed Origins */
  redirectUrl: string
  /** EVM / Solana chain configurations; replaces privateKeyProvider */
  chains?: CustomChainConfig[]
  /** Default active chain ID (hex string) */
  defaultChainId?: string
  /** Smart account configuration; set to null to disable */
  accountAbstractionConfig?: AccountAbstractionMultiChainConfig | null
  /** Wallet Services overlay configuration */
  walletServicesConfig?: WalletServicesConfig
  /** Whitelabel and branding options */
  whiteLabel?: WhiteLabelData
  /** Default MFA level */
  mfaLevel?: MfaLevelType
  /** Session duration in seconds (default: 86400) */
  sessionTime?: number
  /** Enable SDK debug logging */
  enableLogging?: boolean
  /** Override URL for the Wallet Services embed */
  walletSdkURL?: string
}
```

</TabItem>

</Tabs>

## Chain configuration

Pass an array of `CustomChainConfig` objects to the `chains` field in `web3AuthOptions`. The SDK selects the appropriate EVM or Solana provider automatically based on `chainNamespace`.

<!-- vale off -->

<Tabs
  defaultValue="evm"
  values={[
    { label: 'EVM chain', value: 'evm' },
    { label: 'Solana chain', value: 'solana' },
    { label: 'Interface', value: 'interface' },
  ]}
>

<TabItem value="evm">

```typescript

const web3AuthConfig = {
  web3AuthOptions: {
    clientId: 'YOUR_CLIENT_ID',
    redirectUrl: 'yourapp://auth',
    network: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
    chains: [
      {
        chainNamespace: CHAIN_NAMESPACES.EIP155,
        chainId: '0xaa36a7', // Ethereum Sepolia
        rpcTarget: 'https://rpc.ankr.com/eth_sepolia',
        displayName: 'Ethereum Sepolia',
        blockExplorerUrl: 'https://sepolia.etherscan.io',
        ticker: 'ETH',
        tickerName: 'Ethereum',
      },
    ],
    defaultChainId: '0xaa36a7',
  },
}
```

</TabItem>

<TabItem value="solana">

```typescript

const web3AuthConfig = {
  web3AuthOptions: {
    clientId: 'YOUR_CLIENT_ID',
    redirectUrl: 'yourapp://auth',
    network: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
    chains: [
      {
        chainNamespace: CHAIN_NAMESPACES.SOLANA,
        chainId: '0x2', // Solana Testnet
        rpcTarget: 'https://api.testnet.solana.com',
        displayName: 'Solana Testnet',
        blockExplorerUrl: 'https://explorer.solana.com',
        ticker: 'SOL',
        tickerName: 'Solana',
        logo: 'https://images.toruswallet.io/solana.svg',
      },
    ],
    defaultChainId: '0x2',
  },
}
```

</TabItem>

<TabItem value="interface">

```typescript
export interface CustomChainConfig {
  /** Chain namespace: CHAIN_NAMESPACES.EIP155 for EVM, CHAIN_NAMESPACES.SOLANA for Solana */
  chainNamespace: ChainNamespaceType
  /** Chain ID as a hex string (for example, "0x1" for Ethereum mainnet) */
  chainId: string
  /** JSON-RPC endpoint URL for this chain */
  rpcTarget: string
  /** Human-readable chain name shown in the UI */
  displayName?: string
  /** Block explorer base URL */
  blockExplorerUrl?: string
  /** Native token ticker symbol (for example, "ETH") */
  ticker?: string
  /** Native token full name (for example, "Ethereum") */
  tickerName?: string
  /** Token logo URL */
  logo?: string
  /** WebSocket endpoint URL (optional) */
  wsTarget?: string
}
```

</TabItem>

</Tabs>
<!-- vale on -->

### `CHAIN_NAMESPACES`

| Constant                  | Use for                         |
| ------------------------- | ------------------------------- |
| `CHAIN_NAMESPACES.EIP155` | All EVM-compatible chains       |
| `CHAIN_NAMESPACES.SOLANA` | Solana mainnet, devnet, testnet |

## Session management

Control how long users stay authenticated by setting `sessionTime` in `web3AuthOptions`:

- Minimum: `1` second
- Maximum: `86400 * 30` (30 days)
- Default: `86400` (1 day)

```typescript
web3AuthOptions: {
  // ...
  sessionTime: 86400 * 7, // 7 days
}
```

## Advanced topics

- [Custom authentication](./custom-authentication.mdx), configure social login connections and custom JWT flows
- [Smart accounts](./smart-accounts.mdx), enable ERC-4337 account abstraction
- [Whitelabeling](./whitelabel.mdx), customize authentication UI branding
- [Multi-Factor Authentication](./mfa.mdx), control MFA prompts and factor configuration
- [Dapp share](./dapp-share.mdx), pass a custom device share for MFA-enabled wallets

---

## Custom authentication in React Native SDK

Custom authentication lets you integrate your own identity provider, Google with your own Client ID, Firebase, Auth0, AWS Cognito, or any custom JWT issuer, so that the resulting wallet is tied to your user identity rather than to Web3Auth's default verifiers.

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this
SDK in a production environment is the **Growth Plan**. You can use this feature in Web3Auth
Sapphire Devnet network for free.

:::

## Prerequisites

Create a **Connection** in the [Authentication tab](https://developer.metamask.io) of your project on the Embedded Wallets dashboard. The dashboard will give you an **Auth Connection ID** which you pass to `connectTo` at sign-in time.

No changes to `web3AuthOptions` are required for custom authentication in v9. The `loginConfig` parameter from v8 has been removed.

## Single connection

Use `AUTH_CONNECTION.CUSTOM` with `authConnectionId` to target a specific connection registered on the dashboard.

<Tabs
  defaultValue="firebase"
  values={[
    { label: 'Firebase (JWT)', value: 'firebase' },
    { label: 'Auth0 (SDK-native)', value: 'auth0' },
    { label: 'Custom Google Client ID', value: 'google' },
  ]}
>

<TabItem value="firebase">

The SDK handles the Firebase redirect natively. Obtain the Firebase `idToken` first (using the Firebase JS SDK), then pass it directly to `connectTo`:

```tsx

function FirebaseLoginButton() {
  const { connectTo, loading } = useWeb3AuthConnect()

  const login = async () => {
    const auth = getAuth()
    const result = await signInWithPopup(auth, new GoogleAuthProvider())
    const idToken = await result.user.getIdToken(true)

    await connectTo({
      authConnection: AUTH_CONNECTION.CUSTOM,
      authConnectionId: 'w3a-firebase-demo', // Dashboard Connection ID
      idToken,
      extraLoginOptions: { verifierIdField: 'sub' },
    })
  }

  return <Button title="Sign in with Firebase" disabled={loading} onPress={login} />
}
```

</TabItem>

<TabItem value="auth0">

For Auth0, the SDK opens Auth0's login page natively, you no longer need `react-native-auth0`:

```tsx

function Auth0LoginButton() {
  const { connectTo, loading } = useWeb3AuthConnect()

  return (
    <Button
      title="Sign in with Auth0"
      disabled={loading}
      onPress={() =>
        connectTo({
          authConnection: AUTH_CONNECTION.CUSTOM,
          authConnectionId: 'w3a-auth0-demo', // Dashboard Connection ID
          extraLoginOptions: {
            domain: 'https://web3auth.au.auth0.com', // Your Auth0 domain
            verifierIdField: 'sub',
          },
        })
      }
    />
  )
}
```

</TabItem>

<TabItem value="google">

To use your own Google Client ID instead of Web3Auth's default, create a Google connection on the dashboard:

```tsx

function GoogleLoginButton() {
  const { connectTo, loading } = useWeb3AuthConnect()

  return (
    <Button
      title="Sign in with Google"
      disabled={loading}
      onPress={() =>
        connectTo({
          authConnection: AUTH_CONNECTION.GOOGLE,
          authConnectionId: 'my-google-connection', // Your dashboard Connection ID
        })
      }
    />
  )
}
```

</TabItem>

</Tabs>

## Grouped connections (aggregate verifiers)

Grouped connections allow users to sign in through different providers and always receive the same wallet address, as long as the underlying email or user identifier matches. This is useful for "Sign in with Google" and "Sign in with email" mapping to the same wallet.

Configure a **Grouped Connection** on the dashboard, then pass the group ID as `groupedAuthConnectionId` alongside each individual connection's `authConnectionId`:

```tsx

function GroupedLoginView() {
  const { connectTo, loading } = useWeb3AuthConnect()

  const loginWithGoogle = () =>
    connectTo({
      authConnection: AUTH_CONNECTION.GOOGLE,
      authConnectionId: 'w3a-google', // individual connection
      groupedAuthConnectionId: 'aggregate-sapphire', // grouped connection
    })

  const loginWithEmail = () =>
    connectTo({
      authConnection: AUTH_CONNECTION.CUSTOM,
      authConnectionId: 'w3a-a0-email-passwordless',
      groupedAuthConnectionId: 'aggregate-sapphire', // same group → same wallet
    })

  return (
    <View>
      <Button title="Sign in with Google" disabled={loading} onPress={loginWithGoogle} />
      <Button title="Sign in with Email" disabled={loading} onPress={loginWithEmail} />
    </View>
  )
}
```

Both buttons produce the same wallet address for users whose email matches across providers.

## `connectTo` parameter reference

<Tabs
  defaultValue="table"
  values={[
    { label: 'Parameters', value: 'table' },
    { label: 'Interface', value: 'interface' },
    { label: 'AUTH_CONNECTION enum', value: 'enum' },
  ]}
>

<TabItem value="table">

| Parameter                  | Required | Description                                                                                                                                                                                                                            |
| -------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `authConnection`           | Yes      | Authentication method. Pass an `AUTH_CONNECTION.*` constant. Replaces the v8 `loginProvider` field.                                                                                                                                    |
| `authConnectionId?`        | No       | Dashboard Connection ID for the auth connection. Required when using `AUTH_CONNECTION.CUSTOM` or when you have multiple connections of the same type and need to target one specifically. Replaces the v8 `loginConfig[key].verifier`. |
| `groupedAuthConnectionId?` | No       | Dashboard Grouped Connection ID when using grouped (aggregate) connections. Connections sharing the same `groupedAuthConnectionId` produce the same wallet address. Replaces the v8 `loginConfig[key].verifierSubIdentifier`.          |
| `idToken?`                 | No       | A JWT issued by your authentication provider (Firebase, Auth0, Cognito, and so on). Pass this when using `AUTH_CONNECTION.CUSTOM`. The token is sent directly to the SDK instead of opening a browser redirect.                        |
| `extraLoginOptions?`       | No       | Additional OAuth hints passed to the authentication provider. Common fields: `login_hint` (email), `domain` (Auth0 domain), `verifierIdField` (JWT claim to use as the wallet identifier).                                             |
| `redirectUrl?`             | No       | Override the global `redirectUrl` from `web3AuthOptions` for this login call only.                                                                                                                                                     |
| `mfaLevel?`                | No       | Override the global `mfaLevel` for this login call only.                                                                                                                                                                               |
| `curve?`                   | No       | Elliptic curve to use for key generation. Accepts `SUPPORTED_KEY_CURVES.SECP256K1` (EVM) or `SUPPORTED_KEY_CURVES.ED25519` (Solana). Defaults to the chain namespace.                                                                  |
| `sessionTime?`             | No       | Override the global session duration (in seconds) for this login session only.                                                                                                                                                         |
| `dappShare?`               | No       | Custom device share key for MFA-enabled wallets. Required when reconstructing a key with a custom share.                                                                                                                               |
| `appState?`                | No       | Arbitrary state string that is returned in the redirect callback. Useful for restoring application state after the OAuth redirect.                                                                                                     |

</TabItem>

<TabItem value="interface">

```typescript
export interface SdkLoginParams {
  /** Authentication method: use AUTH_CONNECTION.* constants */
  authConnection: AUTH_CONNECTION_TYPE
  /** Dashboard Connection ID; required for AUTH_CONNECTION.CUSTOM */
  authConnectionId?: string
  /** Grouped Connection ID for aggregate verifier flows */
  groupedAuthConnectionId?: string
  /** JWT from your auth provider for custom authentication */
  idToken?: string
  /** Additional OAuth parameters (login_hint, domain, verifierIdField, etc.) */
  extraLoginOptions?: ExtraLoginOptions
  /** Override redirectUrl for this login call */
  redirectUrl?: string
  /** Override MFA level for this login call */
  mfaLevel?: MfaLevelType
  /** Elliptic curve for key generation */
  curve?: SUPPORTED_KEY_CURVES_TYPE
  /** Override session duration for this session */
  sessionTime?: number
  /** Custom device share for MFA-enabled wallets */
  dappShare?: string
  /** Arbitrary app state to restore after redirect */
  appState?: string
}
```

</TabItem>

<TabItem value="enum">

`AUTH_CONNECTION` replaces the v8 `LOGIN_PROVIDER` enum. Import it from `@web3auth/react-native-sdk`.

| `AUTH_CONNECTION` constant           | Description                                               | v8 `LOGIN_PROVIDER` equivalent      |
| ------------------------------------ | --------------------------------------------------------- | ----------------------------------- |
| `AUTH_CONNECTION.GOOGLE`             | Google OAuth 2.0                                          | `LOGIN_PROVIDER.GOOGLE`             |
| `AUTH_CONNECTION.FACEBOOK`           | Facebook OAuth                                            | `LOGIN_PROVIDER.FACEBOOK`           |
| `AUTH_CONNECTION.APPLE`              | Sign in with Apple                                        | `LOGIN_PROVIDER.APPLE`              |
| `AUTH_CONNECTION.DISCORD`            | Discord OAuth                                             | `LOGIN_PROVIDER.DISCORD`            |
| `AUTH_CONNECTION.TWITTER`            | Twitter / X OAuth                                         | `LOGIN_PROVIDER.TWITTER`            |
| `AUTH_CONNECTION.GITHUB`             | GitHub OAuth                                              | `LOGIN_PROVIDER.GITHUB`             |
| `AUTH_CONNECTION.TWITCH`             | Twitch OAuth                                              | `LOGIN_PROVIDER.TWITCH`             |
| `AUTH_CONNECTION.LINE`               | LINE OAuth                                                | `LOGIN_PROVIDER.LINE`               |
| `AUTH_CONNECTION.KAKAO`              | Kakao OAuth                                               | `LOGIN_PROVIDER.KAKAO`              |
| `AUTH_CONNECTION.LINKEDIN`           | LinkedIn OAuth                                            | `LOGIN_PROVIDER.LINKEDIN`           |
| `AUTH_CONNECTION.WEIBO`              | Weibo OAuth                                               | `LOGIN_PROVIDER.WEIBO`              |
| `AUTH_CONNECTION.WECHAT`             | WeChat OAuth                                              | `LOGIN_PROVIDER.WECHAT`             |
| `AUTH_CONNECTION.EMAIL_PASSWORDLESS` | Magic link / OTP sent to an email address                 | `LOGIN_PROVIDER.EMAIL_PASSWORDLESS` |
| `AUTH_CONNECTION.SMS_PASSWORDLESS`   | OTP sent to a phone number                                | `LOGIN_PROVIDER.SMS_PASSWORDLESS`   |
| `AUTH_CONNECTION.FARCASTER`          | Farcaster protocol sign-in                                | ,                                   |
| `AUTH_CONNECTION.CUSTOM`             | Any custom JWT flow (Firebase, Auth0, Cognito, and so on) | `LOGIN_PROVIDER.JWT`                |

</TabItem>

</Tabs>

## `extraLoginOptions` field reference

| Field                        | Type      | Description                                                                                                                   |
| ---------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `domain?`                    | `string`  | Your identity provider domain (for example, `https://example.auth0.com`).                                                     |
| `login_hint?`                | `string`  | Pre-filled email address for email passwordless flows.                                                                        |
| `verifierIdField?`           | `string`  | The JWT claim to use as the user identifier (typically `sub` or `email`). Must match the setting in the dashboard connection. |
| `isVerifierIdCaseSensitive?` | `boolean` | Whether the verifier ID field comparison is case-sensitive. Default is `true`.                                                |
| `client_id?`                 | `string`  | Client ID of the OAuth application (if different from `clientId` in `web3AuthOptions`).                                       |
| `leeway?`                    | `string`  | Clock skew tolerance in seconds for JWT expiry checks. Maximum `120`.                                                         |
| `scope?`                     | `string`  | Space-separated list of OAuth scopes to request.                                                                              |
| `id_token_hint?`             | `string`  | A previously issued ID token to pass as a hint.                                                                               |
| `redirect_uri?`              | `string`  | Override the redirect URI for the OAuth flow.                                                                                 |

---

## Dapp share in React Native SDK

## Background

As described in the [Embedded Wallets infrastructure](/embedded-wallets/infrastructure/), the user's private key is split into multiple shares to achieve non-custody:

1. **Share A**, Managed by the login service across node operators and returned after authentication.
2. **Share B**, Stored on the user's device.
3. **Share C**, A recovery share held by the user (for MFA-enabled accounts).

On mobile devices, Share B is typically stored in an in-app browser context. Because users can accidentally clear browser data without realizing the browser was used for authentication, this can break future logins. The dapp share solves this by letting your app store its own backup of a key share directly in app storage.

## What is a dapp share?

After a successful login on an MFA-enabled account, Web3Auth returns a `dappShare`, a 24-word seed phrase that represents half the private key. Your app can store this in its own secure storage (for example, `react-native-encrypted-storage`) and pass it back to the SDK on subsequent logins, eliminating reliance on the browser context.

:::note

Dapp share is only returned for **custom verifiers** (not default Web3Auth verifiers) and only when MFA is enabled for the user's account.

:::

## Passing dapp share at login

Pass the stored dapp share as the `dappShare` parameter to `connectTo`:

```tsx

function DappShareLoginView() {
  const { connectTo, loading } = useWeb3AuthConnect()

  const loginWithDappShare = async () => {
    const storedDappShare = await EncryptedStorage.getItem('dapp_share')

    await connectTo({
      authConnection: AUTH_CONNECTION.GOOGLE,
      authConnectionId: 'my-google-connection',
      mfaLevel: 'mandatory',
      dappShare: storedDappShare ?? undefined,
    })
  }

  return <Button title="Sign in" disabled={loading} onPress={loginWithDappShare} />
}
```

## Storing the dapp share after login

After a successful login, the user info returned by `useWeb3AuthUser()` contains the `dappShare` field for MFA-enabled accounts. Store it securely after the first successful login:

```typescript

function usePersistDappShare() {
  const { userInfo } = useWeb3AuthUser()

  useEffect(() => {
    if (userInfo?.dappShare) {
      EncryptedStorage.setItem('dapp_share', userInfo.dappShare)
    }
  }, [userInfo?.dappShare])
}
```

---

## Multi-factor authentication in React Native SDK

The Multi-Factor Authentication feature lets users create a backup share (recovery phrase), which they use to log in from a new device or recover their account if they lose their device.

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this SDK in a production environment is the **Scale Plan**. You can use this feature in Web3Auth Sapphire Devnet network for free.

:::

## Default MFA level

Set `mfaLevel` in `web3AuthOptions` to control when the MFA setup prompt is shown globally:

```typescript title="web3authConfig.ts"

const web3AuthConfig: Web3AuthContextConfig = {
  web3AuthOptions: {
    clientId: 'YOUR_CLIENT_ID',
    redirectUrl: 'yourapp://auth',
    network: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
    chains: [...],
    // highlight-next-line
    mfaLevel: MFA_LEVELS.DEFAULT,
  },
}
```

| `MFA_LEVELS` value     | Behavior                                                       |
| ---------------------- | -------------------------------------------------------------- |
| `MFA_LEVELS.DEFAULT`   | Shows the MFA screen on every third login.                     |
| `MFA_LEVELS.OPTIONAL`  | Shows the MFA screen on every login, but the user can skip it. |
| `MFA_LEVELS.MANDATORY` | MFA setup is required immediately after the first login.       |
| `MFA_LEVELS.NONE`      | MFA setup screen is never shown.                               |

You can also override `mfaLevel` on a per-login basis by passing it to `connectTo`:

```tsx

function MfaLoginView() {
  const { connectTo, loading } = useWeb3AuthConnect()

  const handleLogin = async () => {
    await connectTo({
      authConnection: AUTH_CONNECTION.GOOGLE,
      mfaLevel: MFA_LEVELS.MANDATORY,
    })
  }

  return <Button title="Sign in" disabled={loading} onPress={handleLogin} />
}
```

:::caution

If a user has already enabled MFA through another app that uses the same Web3Auth verifier, the MFA screen will continue to appear regardless of the `mfaLevel` setting. MFA cannot be disabled once it has been enabled by the user.

:::

## Runtime MFA management

Use the `useEnableMFA` and `useManageMFA` hooks to let users set up or update their MFA factors from within your app:

```tsx

function MFAControls() {
  const { enableMFA, loading: enabling } = useEnableMFA()
  const { manageMFA, loading: managing } = useManageMFA()

  return (
    <View>
      <Button title="Enable MFA" disabled={enabling} onPress={() => enableMFA()} />
      <Button title="Manage MFA" disabled={managing} onPress={() => manageMFA()} />
    </View>
  )
}
```

## MFA factor order (Scale plan and above)

:::note

Configuring `mfaSettings` is a paid feature. See [pricing](https://web3auth.io/pricing.html). You can test it on `sapphire_devnet` at no cost.

:::

Pass a `mfaSettings` object to configure which MFA factors are available and in what order they are shown:

```typescript

const mfaSettings: MfaSettings = {
  deviceShareFactor: { enable: true, priority: 1, mandatory: true },
  backUpShareFactor: { enable: true, priority: 2, mandatory: true },
  socialBackupFactor: { enable: true, priority: 3, mandatory: false },
  passwordFactor: { enable: true, priority: 4, mandatory: false },
  passkeysFactor: { enable: true, priority: 5, mandatory: false },
  authenticatorFactor: { enable: true, priority: 6, mandatory: false },
}

const web3AuthConfig: Web3AuthContextConfig = {
  web3AuthOptions: {
    ...
    mfaLevel: MFA_LEVELS.MANDATORY,
    // highlight-next-line
    mfaSettings,
  },
}
```

### `mfaSettings` rules

- At least two factors must be marked `mandatory: true`.
- The `priority` field determines the display order (lower = shown first).
- If all factors have `mandatory: false`, the user can still skip the screen. At least two must be set up overall.

### Available MFA factors

| Factor key            | Description                         |
| --------------------- | ----------------------------------- |
| `deviceShareFactor`   | Device-bound share (default factor) |
| `backUpShareFactor`   | Downloadable recovery phrase        |
| `socialBackupFactor`  | OAuth-based recovery                |
| `passwordFactor`      | Password-protected recovery share   |
| `passkeysFactor`      | Passkey-based recovery              |
| `authenticatorFactor` | TOTP authenticator app              |

### Related

- [`useEnableMFA` hook reference](../hooks/useEnableMFA.mdx)
- [`useManageMFA` hook reference](../hooks/useManageMFA.mdx)

---

## Smart accounts(4)

Create and manage smart accounts for your users with just a few lines of code, using
our smart account feature. Additionally, smart accounts offer enhanced control and programmability,
enabling features like those listed below.

- Gas Abstraction: Cover transaction fees for users, or allow users to pay for their own
  transactions using ERC-20 tokens.
- Batch Transactions: Perform multiple transactions in a single call.
- Automated Transactions: Allow users to automate actions, like swapping ETH to USDT when ETH hits
  $4,000.
- Set Spending Limits: Allow users to set tailored spending limits.

Our smart account integration streamlines your setup, allowing you to create and manage smart
accounts using your favorite libraries like Viem, Ethers, and Wagmi. With this, you don't need to
rely on third party packages to effortlessly create ERC-4337 compatible Smart Contract Wallets
(SCWs), and give users the ability to perform batch transactions and efficiently manage gas
sponsorship.

Embedded Wallet's smart account feature gives you the flexibility to configure your bundler client, and
integrate with your paymaster. For more insights into how ERC-4337 works and its components,
[check out our detailed blog post](https://blog.web3auth.io/an-ultimate-guide-to-web3-wallets-externally-owned-account-and-smart-contract-wallet/#introduction-to-eip-4337).

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this
SDK in a production environment is the **Growth Plan**. You can use this feature in Web3Auth
Sapphire Devnet network for free.

:::

## Enabling smart accounts

:::info prerequisite

Enable smart accounts in the [Embedded Wallets dashboard](https://developer.metamask.io/) under your project's smart accounts settings before configuring the SDK.

:::

## SDK configuration

In v9, account abstraction is enabled by adding `accountAbstractionConfig` to `web3AuthOptions` in your `web3authConfig.ts` file. No separate `AccountAbstractionProvider` or `privateKeyProvider` construction is needed.

<Tabs
  defaultValue="bare"
  values={[
    { label: 'Bare React Native', value: 'bare' },
    { label: 'Expo', value: 'expo' },
  ]}
>

<TabItem value="bare">

```typescript title="web3authConfig.ts"

  CHAIN_NAMESPACES,
  WEB3AUTH_NETWORK,
  type AccountAbstractionConfig,
  type Web3AuthContextConfig,
} from '@web3auth/react-native-sdk'

const aaConfig: AccountAbstractionConfig = {
  smartAccountType: 'safe',
}

const web3AuthConfig: Web3AuthContextConfig = {
  web3AuthOptions: {
    clientId: 'YOUR_CLIENT_ID',
    redirectUrl: 'yourapp://auth',
    network: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
    chains: [
      {
        chainNamespace: CHAIN_NAMESPACES.EIP155,
        chainId: '0xaa36a7',
        rpcTarget: 'https://rpc.ankr.com/eth_sepolia',
        displayName: 'Ethereum Sepolia Testnet',
        blockExplorerUrl: 'https://sepolia.etherscan.io',
        ticker: 'ETH',
        tickerName: 'Ethereum',
      },
    ],
    defaultChainId: '0xaa36a7',
    // highlight-next-line
    accountAbstractionConfig: aaConfig,
  },
}

export default web3AuthConfig
```

</TabItem>

<TabItem value="expo">

The configuration is identical for Expo. Only the `Web3AuthProvider` props change (use `expo-web-browser` and `expo-secure-store` instead of the bare equivalents):

```typescript title="web3authConfig.ts"

  CHAIN_NAMESPACES,
  WEB3AUTH_NETWORK,
  type AccountAbstractionConfig,
  type Web3AuthContextConfig,
} from '@web3auth/react-native-sdk'

const aaConfig: AccountAbstractionConfig = {
  smartAccountType: 'safe',
}

const web3AuthConfig: Web3AuthContextConfig = {
  web3AuthOptions: {
    clientId: 'YOUR_CLIENT_ID',
    redirectUrl: 'yourapp://auth',
    network: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
    chains: [
      {
        chainNamespace: CHAIN_NAMESPACES.EIP155,
        chainId: '0xaa36a7',
        rpcTarget: 'https://rpc.ankr.com/eth_sepolia',
        displayName: 'Ethereum Sepolia Testnet',
        blockExplorerUrl: 'https://sepolia.etherscan.io',
        ticker: 'ETH',
        tickerName: 'Ethereum',
      },
    ],
    defaultChainId: '0xaa36a7',
    // highlight-next-line
    accountAbstractionConfig: aaConfig,
  },
}

export default web3AuthConfig
```

</TabItem>

</Tabs>

:::tip Dynamic AA toggle

To let users toggle account abstraction on or off at runtime, maintain the config as state and pass a new `key` to `Web3AuthProvider` when it changes. This forces the provider to remount with the updated configuration:

```tsx
const [useAA, setUseAA] = useState(false)
const config = useMemo(() => getWeb3AuthConfig(useAA), [useAA])

return (
  <Web3AuthProvider key={useAA ? 'aa' : 'eoa'} ... config={config}>
    ...
  </Web3AuthProvider>
)
```

:::

## Configure signers

The Web3Auth Smart Account feature is compatible with popular signer SDKs, including Wagmi, ethers,
and viem. You can choose your preferred package to configure the signer.

<!-- vale off -->

<Tabs
  defaultValue="wagmi"
  values={[
    { label: "Wagmi (recommended)", value: "wagmi" },
    { label: "Viem", value: "viem" },
    { label: "Ethers", value: "ethers" },
  ]}
>

<TabItem value="wagmi">

Use Wagmi with `@web3auth/modal/react/wagmi` or `@web3auth/modal/vue/wagmi`. After sign-in, Wagmi
hooks (`useConnection`, `useSendTransaction`, and similar) use the smart account signer automatically.
No manual `connection.ethereumProvider` wiring is required.

```tsx

const { address } = useConnection()
// useSendTransaction, useWriteContract, etc. work with the smart account
```

</TabItem>

<TabItem value="viem">

For vanilla JavaScript or apps without Wagmi, read the EIP-1193 provider from `connection`:

```tsx

const connection = web3auth.connection
const provider = connection?.ethereumProvider ?? null

const walletClient = createWalletClient({
  transport: custom(provider),
})
```

</TabItem>

<TabItem value="ethers">

```tsx

const connection = web3auth.connection
const provider = connection?.ethereumProvider ?? null

const ethersProvider = new ethers.BrowserProvider(provider)
const signer = await ethersProvider.getSigner()
```

</TabItem>
</Tabs>
<!-- vale on -->

## Smart account address

Once the signers or Wagmi configuration is set up, it can be used to retrieve the user's Smart
Account address.

<Tabs
  defaultValue="viem"
  values={[
    { label: "Viem", value: "viem" },
    { label: "Ethers", value: "ethers" },
    { label: "Wagmi", value: "Wagmi" },
  ]}
>

<TabItem value="viem">

```tsx
// Use walletClient instance from previous step
const addresses = await walletClient.getAddresses()

const smartAccountAddress = addresses[0]
const eoaAddress = addresses[1]
```

</TabItem>

<TabItem value="ethers">

```tsx
// User signer from previous step
const smartAccountAddress = signer.getAddress()
```

</TabItem>

<TabItem value="Wagmi">
```tsx

const { address } = useConnection()
const smartAccountAddress = address

```

</TabItem>
</Tabs>
```

## Send transaction

Developers can use their preferred signer or Wagmi hooks to initiate onchain transactions, while
Web3Auth manages the creation and submission of the UserOperation. Only the `to`, `data`, and
`value` fields need to be provided. Any additional parameters will be ignored and automatically
overridden.

To ensure reliable execution, the bundler client sets maxFeePerGas and maxPriorityFeePerGas values.
If custom values are required, developers can use the
[Viem's BundlerClient](https://viem.sh/account-abstraction/clients/bundler#bundler-client) to
manually construct and send the user operation.

Since Smart Accounts are deployed smart contracts, the user's first transaction also triggers the
onchain deployment of their wallet.

<Tabs
  defaultValue="viem"
  values={[
    { label: "Viem", value: "viem" },
    { label: "Ethers", value: "ethers" },
    { label: "Wagmi", value: "wagmi" },
  ]}
>

<TabItem value="wagmi">

```tsx

const { data: hash, sendTransaction } = useSendTransaction()

// Convert 1 ether to WEI format
const value = web3.utils.toWei(1)

sendTransaction({ to: 'DESTINATION_ADDRESS', value, data: '0x' })

const {
  data: receipt,
  isLoading: isConfirming,
  isSuccess: isConfirmed,
} = useWaitForTransactionReceipt({
  hash,
})
```

</TabItem>
<TabItem value="ethers">

```tsx
// Convert 1 ether to WEI format
const amount = ethers.parseEther('1.0')

// Submits a user operation to the blockchain
const transaction = await signer.sendTransaction({
  to: 'DESTINATION_ADDRESS',
  value: amount,
  // This will perform the transfer of ETH
  data: '0x',
})

// Wait for the transaction to be mined
const receipt = await transaction.wait()
```

</TabItem>
<TabItem value="viem">

```tsx
// Convert 1 ether to WEI format
const amount = parseEther('1')

// Submits a user operation to the blockchain
const hash = await walletClient.sendTransaction({
  to: 'DESTINATION_ADDRESS',
  value: amount,
  // This will perform the transfer of ETH
  data: '0x',
})

// Wait for the transaction to be mined
const receipt = await publicClient.waitForTransactionReceipt({ hash })
```

</TabItem>
</Tabs>

---

## Whitelabeling the React Native SDK

Embedded Wallets allows complete whitelabeling with application branding for a consistent user experience. You can customize the appearance, branding, and language of the authentication screens opened in the in-app browser.

:::info

All of these settings can be easily managed directly from the Embedded Wallets dashboard. Once you update your branding, or UI preferences there, the changes will automatically apply to your integration.

:::

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this
SDK in a production environment is the **Growth Plan**. You can use this feature in Web3Auth
Sapphire Devnet network for free.

:::

## Configuration

Set `whiteLabel` inside `web3AuthOptions` in your `web3authConfig.ts`:

```typescript title="web3authConfig.ts"

  CHAIN_NAMESPACES,
  WEB3AUTH_NETWORK,
  type Web3AuthContextConfig,
} from '@web3auth/react-native-sdk'

const web3AuthConfig: Web3AuthContextConfig = {
  web3AuthOptions: {
    clientId: 'YOUR_CLIENT_ID',
    redirectUrl: 'yourapp://auth',
    network: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
    chains: [
      {
        chainNamespace: CHAIN_NAMESPACES.EIP155,
        chainId: '0xaa36a7',
        rpcTarget: 'https://rpc.ankr.com/eth_sepolia',
        displayName: 'Ethereum Sepolia Testnet',
        blockExplorerUrl: 'https://sepolia.etherscan.io',
        ticker: 'ETH',
        tickerName: 'Ethereum',
      },
    ],
    defaultChainId: '0xaa36a7',
    // highlight-start
    whiteLabel: {
      appName: 'My App',
      logoLight: 'https://example.com/logo-light.png',
      logoDark: 'https://example.com/logo-dark.png',
      defaultLanguage: 'en',
      mode: 'auto',
      theme: {
        primary: '#cddc39',
      },
    },
    // highlight-end
  },
}

export default web3AuthConfig
```

## `WhiteLabelData` parameters

| Parameter          | Type                                     | Description                                                                                                              |
| ------------------ | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `appName?`         | `string`                                 | Display name for your app shown on the authentication screens.                                                           |
| `appUrl?`          | `string`                                 | Your app's URL shown on the authentication screens.                                                                      |
| `logoLight?`       | `string`                                 | Logo URL used in dark mode (light-colored logo).                                                                         |
| `logoDark?`        | `string`                                 | Logo URL used in light mode (dark-colored logo).                                                                         |
| `defaultLanguage?` | `LANGUAGE_TYPE`                          | Language for the authentication UI. Supported: `en`, `de`, `ja`, `ko`, `zh`, `es`, `fr`, `pt`, `nl`. Defaults to `en`.   |
| `mode?`            | `THEME_MODE_TYPE`                        | Color scheme: `"auto"`, `"light"`, or `"dark"`. Defaults to `"auto"`.                                                    |
| `theme?`           | `Record<string, string>`                 | Custom color overrides. `primary` sets the accent color (hex string).                                                    |
| `useLogoLoader?`   | `boolean`                                | Use your app logo on the loading screen. If no logo is provided, the default Web3Auth logo is used. Defaults to `false`. |
| `tncLink?`         | `Partial<Record<LANGUAGE_TYPE, string>>` | Language-keyed Terms and Conditions URL (for example, `{ en: "https://example.com/tnc" }`).                              |
| `privacyPolicy?`   | `Partial<Record<LANGUAGE_TYPE, string>>` | Language-keyed Privacy Policy URL.                                                                                       |

### `name`

The name of the application. This will be displayed in the key reconstruction page.

  
    
      Standard screen without any change
    
    
  
  
    
      Name changed to <code>Formidable Duo</code>
    
    
  

### `logoLight` & `logoDark`

The logo of the application. Displayed in dark and light mode respectively. This will be displayed
in the key reconstruction page.

  
    
      <code>logoLight</code> on dark mode
    
    
  
  
    
      <code>logoDark</code> on light mode
    
    
  

### `defaultLanguage`

Default language will set the language used on all OpenLogin screens. The supported languages are:

  
    
      
        <code>en</code> - English (default)
      
      
        <code>de</code> - German
      
      
        <code>ja</code> - Japanese
      
      
        <code>ko</code> - Korean
      
      
        <code>zh</code> - Mandarin
      
      
        <code>es</code> - Spanish
      
      
        <code>fr</code> - French
      
      
        <code>pt</code> - Portuguese
      
      
        <code>nl</code> - Dutch
      
      
        <code>tr</code> - Turkish
      
    
  
  
    
  

### `dark`

Can be set to `true` or `false` with default set to `false`.

  
    
      For Light: <code>dark: false</code>
    
    
  
  
    
      For Dark: <code>dark: true</code>
    
    
  

### `theme`

Theme is a record of colors that can be configured. As of, now only `primary` color can be set and
has effect on OpenLogin screens (default primary color is `#0364FF`). Theme affects icons and links.
Examples below.

  
    
      Standard color <code>#0364FF</code>
    
    
  
  
    
      Color changed to <code>#D72F7A</code>

---

## Examples - PnP React Native SDK

<ExampleCards exampleMap={pnpReactNativeExamples} />

---

## React Native hooks for Embedded Wallets

The Embedded Wallets React Native SDK provides a set of React hooks that cover every aspect of authentication and wallet operations. All hooks must be used inside the `Web3AuthProvider` component tree.

## Core hooks

| Hook                               | Description                                                                              |
| ---------------------------------- | ---------------------------------------------------------------------------------------- |
| [`useWeb3Auth`](./useWeb3Auth.mdx) | Access SDK state: `isConnected`, `isInitializing`, `provider`, `web3Auth`, and `signer`. |

## Authentication hooks

| Hook                                                   | Description                                           |
| ------------------------------------------------------ | ----------------------------------------------------- |
| [`useWeb3AuthConnect`](./useWeb3AuthConnect.mdx)       | Connect a user via any auth method using `connectTo`. |
| [`useWeb3AuthDisconnect`](./useWeb3AuthDisconnect.mdx) | Disconnect the current user session.                  |

## Identity hooks

| Hook                                         | Description                                         |
| -------------------------------------------- | --------------------------------------------------- |
| [`useWeb3AuthUser`](./useWeb3AuthUser.mdx)   | Read the authenticated user's profile information.  |
| [`useIdentityToken`](./useIdentityToken.mdx) | Retrieve a signed JWT for server-side verification. |

## Multi-Factor Authentication hooks

| Hook                                 | Description                                        |
| ------------------------------------ | -------------------------------------------------- |
| [`useEnableMFA`](./useEnableMFA.mdx) | Enable MFA for the current user's embedded wallet. |
| [`useManageMFA`](./useManageMFA.mdx) | Manage existing MFA settings and factors.          |

## Wallet Services hooks

| Hook                                               | Description                                                                  |
| -------------------------------------------------- | ---------------------------------------------------------------------------- |
| [`useWalletUI`](./useWalletUI.mdx)                 | Show the Wallet Services in-app browser overlay.                             |
| [`useSignatureRequest`](./useSignatureRequest.mdx) | Request a signature or transaction approval via the Wallet Services overlay. |

---

## useEnableMFA(Hooks)

Hook to enable Multi-Factor Authentication (MFA) for the current user's embedded wallet.

:::info

This hook only works for social login embedded wallets. It is not available for external wallet connections.

:::

### Import

```tsx

```

### Usage

```tsx

function EnableMFAButton() {
  const { enableMFA, loading, error } = useEnableMFA()

  return (
    <View>
      <Button
        title={loading ? 'Setting up MFA…' : 'Enable MFA'}
        disabled={loading}
        onPress={() => enableMFA()}
      />
      {error && <Text>{error.message}</Text>}
    </View>
  )
}
```

### Return type

#### `enableMFA`

`() => Promise<void>`

Opens the MFA setup flow in the Wallet Services overlay. The user is guided through registering a second factor (device, recovery key, or authenticator app). Once set up, the user's wallet key is split across multiple shares.

#### `loading`

`boolean`

`true` while the MFA setup process is in progress.

#### `error`

`Web3AuthError | null`

Error from the most recent `enableMFA` call, or `null` if successful.

### Related

- [MFA advanced guide](../advanced/mfa.mdx)
- [`useManageMFA`](./useManageMFA.mdx)

---

## useIdentityToken

Hook to retrieve a signed identity JWT issued by Web3Auth. Use this token for server-side verification that proves the user owns their embedded wallet.

### Import

```tsx

```

### Usage

```tsx

function VerifyButton() {
  const { getIdentityToken, loading, error } = useIdentityToken()

  const verifyOnServer = async () => {
    const token = await getIdentityToken()
    // Send token to your backend for verification
    await fetch('/api/verify', {
      method: 'POST',
      headers: { Authorization: `Bearer ${token}` },
    })
  }

  return (
    <View>
      <Button
        title={loading ? 'Fetching token…' : 'Verify identity'}
        disabled={loading}
        onPress={verifyOnServer}
      />
      {error && <Text>{error.message}</Text>}
    </View>
  )
}
```

### Return type

#### `getIdentityToken`

`() => Promise<string>`

Returns a signed JWT from the Web3Auth network. The token payload contains the user's wallet address and verifier information. Verify the token on your backend using the Web3Auth JWKS endpoint.

#### `loading`

`boolean`

`true` while the token is being fetched.

#### `error`

`Web3AuthError | null`

Error from the most recent `getIdentityToken` call, or `null` if successful.

:::info

This hook requires an active authenticated session. Call it only when `useWeb3Auth().isConnected` is `true`.

:::

---

## useManageMFA(Hooks)

Hook to manage Multi-Factor Authentication settings for the current user's embedded wallet.

:::info

This hook only works for social login embedded wallets. It is not available for external wallet connections.

:::

### Import

```tsx

```

### Usage

```tsx

function ManageMFAButton() {
  const { manageMFA, loading, error } = useManageMFA()

  return (
    <View>
      <Button
        title={loading ? 'Opening MFA settings…' : 'Manage MFA'}
        disabled={loading}
        onPress={() => manageMFA()}
      />
      {error && <Text>{error.message}</Text>}
    </View>
  )
}
```

### Return type

#### `manageMFA`

`() => Promise<void>`

Opens the MFA management screen in the Wallet Services overlay. The user can view, update, or remove existing second factors.

#### `loading`

`boolean`

`true` while the MFA management interface is loading.

#### `error`

`Web3AuthError | null`

Error from the most recent `manageMFA` call, or `null` if successful.

### Related

- [MFA advanced guide](../advanced/mfa.mdx)
- [`useEnableMFA`](./useEnableMFA.mdx)

---

## useSignatureRequest

Hook to send JSON-RPC signing requests through the Wallet Services overlay. Unlike signing directly with `provider`, this presents a human-readable confirmation screen to the user before executing the operation.

### Import

```tsx

```

### Usage

```tsx

function SigningView() {
  const { request, loading, error } = useSignatureRequest()
  const { provider } = useWeb3Auth()

  const getAddress = async () => {
    const ep = new ethers.BrowserProvider(provider!)
    const signer = await ep.getSigner()
    return await signer.getAddress()
  }

  const signPersonalMessage = async () => {
    const address = await getAddress()
    const message = 'Hello from Web3Auth!'
    // Presents a signing confirmation in the Wallet Services overlay
    const signature = await request('personal_sign', [
      ethers.hexlify(ethers.toUtf8Bytes(message)),
      address,
    ])
    console.log('Signature:', signature)
  }

  const sendTransaction = async () => {
    const address = await getAddress()
    const txHash = await request('eth_sendTransaction', [
      {
        from: address,
        to: '0x0000000000000000000000000000000000000001',
        value: ethers.toBeHex(ethers.parseEther('0.001')),
        gasLimit: ethers.toBeHex(21000),
      },
    ])
    console.log('Transaction hash:', txHash)
  }

  return (
    <View>
      <Button title="Sign message" disabled={loading} onPress={signPersonalMessage} />
      <Button title="Send ETH" disabled={loading} onPress={sendTransaction} />
      {error && <Text>{error.message}</Text>}
    </View>
  )
}
```

### Return type

#### `request`

`(method: string, params: unknown[]) => Promise<unknown>`

Sends a JSON-RPC call through the Wallet Services overlay. The user sees a confirmation screen before the operation is executed. Returns the JSON-RPC result value on success.

Common `method` values:

| Method                 | Description                              |
| ---------------------- | ---------------------------------------- |
| `personal_sign`        | Sign a personal message (EIP-191).       |
| `eth_signTypedData_v4` | Sign typed structured data (EIP-712).    |
| `eth_sendTransaction`  | Send a transaction.                      |
| `eth_signTransaction`  | Sign a transaction without broadcasting. |

#### `loading`

`boolean`

`true` while the request is pending user confirmation or execution.

#### `error`

`Web3AuthError | null`

Error from the most recent `request` call, or `null` if successful.

---

## useWalletUI(Hooks)

Hook to open the Wallet Services in-app browser overlay. This provides users with a pre-built wallet interface for viewing balances, sending tokens, and managing their wallet, without leaving your app.

### Import

```tsx

```

### Usage

```tsx

function WalletButton() {
  const { showWalletUI, loading, error } = useWalletUI()

  return (
    <View>
      <Button
        title={loading ? 'Opening wallet…' : 'Open Wallet'}
        disabled={loading}
        onPress={() => showWalletUI()}
      />
      {error && <Text>{error.message}</Text>}
    </View>
  )
}
```

### Return type

#### `showWalletUI`

`() => Promise<void>`

Opens the Wallet Services overlay in an in-app browser. The user can view their balance, send/receive tokens, swap, and interact with dapps, all within the overlay. Replaces the v8 `web3auth.launchWalletServices(chainConfig)` method.

#### `loading`

`boolean`

`true` while the overlay is loading.

#### `error`

`Web3AuthError | null`

Error from the most recent `showWalletUI` call, or `null` if successful.

:::info

`walletServicesConfig` can be added to `web3AuthOptions` to customise the overlay behaviour. See the [advanced configuration](../advanced/README.mdx) for details.

:::

---

## useWeb3Auth(Hooks)

Core hook that exposes the SDK state and the underlying `Web3Auth` instance. Use this hook to check whether the user is connected, access the EIP-1193 provider for EVM calls, or access the Solana signer.

### Import

```tsx

```

### Usage

```tsx

function HomeView() {
  const { isConnected, isInitializing, provider, web3Auth } = useWeb3Auth()

  if (isInitializing) return <Text>Initializing…</Text>
  if (!isConnected) return <Text>Please sign in</Text>

  const getEvmAddress = async () => {
    const ep = new ethers.BrowserProvider(provider!)
    const signer = await ep.getSigner()
    return await signer.getAddress()
  }

  const getSolanaAddress = () => {
    const signer = web3Auth?.signer as TransactionSigner | null
    return signer ? String(signer.address) : null
  }

  return <View>...</View>
}
```

### Return type

#### `isConnected`

`boolean`

`true` when the user has an active authenticated session. Gates all other hook usage that requires a connected wallet.

#### `isInitializing`

`boolean`

`true` while the provider is restoring a previous session on mount. Render a loading indicator while this is `true` to avoid a flash of the logged-out state.

#### `provider`

`IProvider | null`

The EIP-1193 compatible provider for the connected EVM chain. Pass this directly to `new ethers.BrowserProvider(provider)` or `createWalletClient({ transport: custom(provider) })` (viem). `null` when not connected or when the active chain is Solana.

#### `web3Auth`

`Web3Auth | null`

The underlying SDK instance. Primarily useful for accessing `web3Auth.signer` on Solana chains and for advanced use cases. Prefer the dedicated hooks for common operations.

#### `signer`

`unknown`

Alias for `web3Auth?.signer`. On Solana chains this is a `TransactionSigner` from `@solana/signers`. On EVM chains this is `null`, use `provider` instead.

---

## useWeb3AuthConnect(Hooks)

Hook to connect a user to Web3Auth. Call `connectTo` with an `AUTH_CONNECTION` constant to open the chosen authentication method in an in-app browser.

### Import

```tsx

```

### Usage

<Tabs
  defaultValue="google"
  values={[
    { label: 'Google', value: 'google' },
    { label: 'Email passwordless', value: 'email' },
    { label: 'Custom JWT', value: 'jwt' },
    { label: 'Grouped connection', value: 'grouped' },
  ]}
>

<TabItem value="google">

```tsx

function LoginView() {
  const { connectTo, loading, error } = useWeb3AuthConnect()

  return (
    <View>
      <Button
        title={loading ? 'Signing in…' : 'Sign in with Google'}
        disabled={loading}
        onPress={() => connectTo({ authConnection: AUTH_CONNECTION.GOOGLE })}
      />
      {error && <Text>{error.message}</Text>}
    </View>
  )
}
```

</TabItem>

<TabItem value="email">

```tsx

function EmailLogin() {
  const { connectTo, loading } = useWeb3AuthConnect()
  const [email, setEmail] = useState('')

  return (
    <View>
      <TextInput value={email} onChangeText={setEmail} placeholder="your@email.com" />
      <Button
        title="Continue with email"
        disabled={loading}
        onPress={() =>
          connectTo({
            authConnection: AUTH_CONNECTION.EMAIL_PASSWORDLESS,
            extraLoginOptions: { login_hint: email },
          })
        }
      />
    </View>
  )
}
```

</TabItem>

<TabItem value="jwt">

```tsx

function FirebaseJwtLoginView() {
  const { connectTo, loading } = useWeb3AuthConnect()

  const loginWithFirebase = async () => {
    // Obtain the idToken from your own authentication flow (Firebase, Auth0, etc.)
    const idToken = await getFirebaseIdToken()

    await connectTo({
      authConnection: AUTH_CONNECTION.CUSTOM,
      authConnectionId: 'w3a-firebase-demo', // Dashboard Connection ID
      idToken,
      extraLoginOptions: { verifierIdField: 'sub' },
    })
  }

  return <Button title="Sign in with Firebase" disabled={loading} onPress={loginWithFirebase} />
}
```

</TabItem>

<TabItem value="grouped">

```tsx

function GroupedLoginView() {
  const { connectTo, loading } = useWeb3AuthConnect()

  const loginWithGoogle = () =>
    connectTo({
      authConnection: AUTH_CONNECTION.GOOGLE,
      authConnectionId: 'w3a-google',
      groupedAuthConnectionId: 'aggregate-sapphire',
    })

  const loginWithEmail = () =>
    connectTo({
      authConnection: AUTH_CONNECTION.EMAIL_PASSWORDLESS,
      authConnectionId: 'w3a-a0-email-passwordless',
      groupedAuthConnectionId: 'aggregate-sapphire', // same group → same wallet
    })

  return (
    <View>
      <Button title="Google" disabled={loading} onPress={loginWithGoogle} />
      <Button title="Email" disabled={loading} onPress={loginWithEmail} />
    </View>
  )
}
```

</TabItem>

</Tabs>

### Return type

#### `connectTo`

`(params: SdkLoginParams) => Promise<IProvider | null>`

Initiates authentication using the specified method. Opens an in-app browser for the OAuth or magic-link flow and resolves with the EIP-1193 provider on success.

#### `loading`

`boolean`

`true` while the authentication flow is in progress.

#### `error`

`Web3AuthError | null`

Error from the most recent `connectTo` call, or `null` if no error occurred.

#### `isConnected`

`boolean`

`true` if the user is currently authenticated. Mirrors `useWeb3Auth().isConnected`.

### `connectTo` parameters

<Tabs
  defaultValue="table"
  values={[
    { label: 'Parameters', value: 'table' },
    { label: 'Interface', value: 'interface' },
    { label: 'AUTH_CONNECTION enum', value: 'enum' },
  ]}
>

<TabItem value="table">

| Parameter                  | Required | Description                                                                                                                                                                                                                            |
| -------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `authConnection`           | Yes      | Authentication method. Pass an `AUTH_CONNECTION.*` constant. Replaces the v8 `loginProvider` field.                                                                                                                                    |
| `authConnectionId?`        | No       | Dashboard Connection ID for the auth connection. Required when using `AUTH_CONNECTION.CUSTOM` or when you have multiple connections of the same type and need to target one specifically. Replaces the v8 `loginConfig[key].verifier`. |
| `groupedAuthConnectionId?` | No       | Dashboard Grouped Connection ID when using grouped (aggregate) connections. Connections sharing the same `groupedAuthConnectionId` produce the same wallet address. Replaces the v8 `loginConfig[key].verifierSubIdentifier`.          |
| `idToken?`                 | No       | A JWT issued by your authentication provider (Firebase, Auth0, Cognito, and so on). Pass this when using `AUTH_CONNECTION.CUSTOM`. The token is sent directly to the SDK instead of opening a browser redirect.                        |
| `extraLoginOptions?`       | No       | Additional OAuth hints passed to the authentication provider. Common fields: `login_hint` (email), `domain` (Auth0 domain), `verifierIdField` (JWT claim to use as the wallet identifier).                                             |
| `redirectUrl?`             | No       | Override the global `redirectUrl` from `web3AuthOptions` for this login call only.                                                                                                                                                     |
| `mfaLevel?`                | No       | Override the global `mfaLevel` for this login call only.                                                                                                                                                                               |
| `curve?`                   | No       | Elliptic curve to use for key generation. Accepts `SUPPORTED_KEY_CURVES.SECP256K1` (EVM) or `SUPPORTED_KEY_CURVES.ED25519` (Solana). Defaults to the chain namespace.                                                                  |
| `sessionTime?`             | No       | Override the global session duration (in seconds) for this login session only.                                                                                                                                                         |
| `dappShare?`               | No       | Custom device share key for MFA-enabled wallets. Required when reconstructing a key with a custom share.                                                                                                                               |
| `appState?`                | No       | Arbitrary state string that is returned in the redirect callback. Useful for restoring application state after the OAuth redirect.                                                                                                     |

</TabItem>

<TabItem value="interface">

```typescript
export interface SdkLoginParams {
  /** Authentication method: use AUTH_CONNECTION.* constants */
  authConnection: AUTH_CONNECTION_TYPE
  /** Dashboard Connection ID; required for AUTH_CONNECTION.CUSTOM */
  authConnectionId?: string
  /** Grouped Connection ID for aggregate verifier flows */
  groupedAuthConnectionId?: string
  /** JWT from your auth provider for custom authentication */
  idToken?: string
  /** Additional OAuth parameters (login_hint, domain, verifierIdField, etc.) */
  extraLoginOptions?: ExtraLoginOptions
  /** Override redirectUrl for this login call */
  redirectUrl?: string
  /** Override MFA level for this login call */
  mfaLevel?: MfaLevelType
  /** Elliptic curve for key generation */
  curve?: SUPPORTED_KEY_CURVES_TYPE
  /** Override session duration for this session */
  sessionTime?: number
  /** Custom device share for MFA-enabled wallets */
  dappShare?: string
  /** Arbitrary app state to restore after redirect */
  appState?: string
}
```

</TabItem>

<TabItem value="enum">

`AUTH_CONNECTION` replaces the v8 `LOGIN_PROVIDER` enum. Import it from `@web3auth/react-native-sdk`.

| `AUTH_CONNECTION` constant           | Description                                               | v8 `LOGIN_PROVIDER` equivalent      |
| ------------------------------------ | --------------------------------------------------------- | ----------------------------------- |
| `AUTH_CONNECTION.GOOGLE`             | Google OAuth 2.0                                          | `LOGIN_PROVIDER.GOOGLE`             |
| `AUTH_CONNECTION.FACEBOOK`           | Facebook OAuth                                            | `LOGIN_PROVIDER.FACEBOOK`           |
| `AUTH_CONNECTION.APPLE`              | Sign in with Apple                                        | `LOGIN_PROVIDER.APPLE`              |
| `AUTH_CONNECTION.DISCORD`            | Discord OAuth                                             | `LOGIN_PROVIDER.DISCORD`            |
| `AUTH_CONNECTION.TWITTER`            | Twitter / X OAuth                                         | `LOGIN_PROVIDER.TWITTER`            |
| `AUTH_CONNECTION.GITHUB`             | GitHub OAuth                                              | `LOGIN_PROVIDER.GITHUB`             |
| `AUTH_CONNECTION.TWITCH`             | Twitch OAuth                                              | `LOGIN_PROVIDER.TWITCH`             |
| `AUTH_CONNECTION.LINE`               | LINE OAuth                                                | `LOGIN_PROVIDER.LINE`               |
| `AUTH_CONNECTION.KAKAO`              | Kakao OAuth                                               | `LOGIN_PROVIDER.KAKAO`              |
| `AUTH_CONNECTION.LINKEDIN`           | LinkedIn OAuth                                            | `LOGIN_PROVIDER.LINKEDIN`           |
| `AUTH_CONNECTION.WEIBO`              | Weibo OAuth                                               | `LOGIN_PROVIDER.WEIBO`              |
| `AUTH_CONNECTION.WECHAT`             | WeChat OAuth                                              | `LOGIN_PROVIDER.WECHAT`             |
| `AUTH_CONNECTION.EMAIL_PASSWORDLESS` | Magic link / OTP sent to an email address                 | `LOGIN_PROVIDER.EMAIL_PASSWORDLESS` |
| `AUTH_CONNECTION.SMS_PASSWORDLESS`   | OTP sent to a phone number                                | `LOGIN_PROVIDER.SMS_PASSWORDLESS`   |
| `AUTH_CONNECTION.FARCASTER`          | Farcaster protocol sign-in                                | ,                                   |
| `AUTH_CONNECTION.CUSTOM`             | Any custom JWT flow (Firebase, Auth0, Cognito, and so on) | `LOGIN_PROVIDER.JWT`                |

</TabItem>

</Tabs>

### Related

- [Sign in usage guide](../usage/login.mdx)
- [Custom authentication](../advanced/custom-authentication.mdx)

---

## useWeb3AuthDisconnect(Hooks)

Hook to disconnect the current user session.

### Import

```tsx

```

### Usage

```tsx

function LogoutButton() {
  const { disconnect, loading, error } = useWeb3AuthDisconnect()

  return (
    <View>
      <Button
        title={loading ? 'Signing out…' : 'Sign out'}
        disabled={loading}
        onPress={() => disconnect()}
      />
      {error && <Text>{error.message}</Text>}
    </View>
  )
}
```

### Return type

#### `disconnect`

`() => Promise<void>`

Terminates the current authenticated session and clears the stored session data from the device. After this resolves, `useWeb3Auth().isConnected` becomes `false`.

#### `loading`

`boolean`

`true` while the disconnect operation is in progress.

#### `error`

`Web3AuthError | null`

Error from the most recent `disconnect` call, or `null` if no error occurred.

---

## useWeb3AuthUser(Hooks)

Hook to access the authenticated user's profile information. The returned `userInfo` object is reactive, it updates automatically when the session changes.

### Import

```tsx

```

### Usage

```tsx

function UserProfile() {
  const { userInfo } = useWeb3AuthUser()

  if (!userInfo) return null

  return (
    <View>
      <Text>Name: {userInfo.name}</Text>
      <Text>Email: {userInfo.email}</Text>
      {userInfo.profileImage && (
        <Image source={{ uri: userInfo.profileImage }} style={{ width: 48, height: 48 }} />
      )}
    </View>
  )
}
```

### Return type

#### `userInfo`

`UserInfo | null`

The authenticated user's profile object. `null` when no user is connected.

| Field               | Type      | Description                                                         |
| ------------------- | --------- | ------------------------------------------------------------------- |
| `email`             | `string`  | User's email address, if provided by the authentication provider.   |
| `name`              | `string`  | User's display name.                                                |
| `profileImage`      | `string`  | URL of the user's profile picture.                                  |
| `aggregateVerifier` | `string`  | Aggregate verifier identifier (grouped connection flows).           |
| `verifier`          | `string`  | Verifier identifier used for this authentication.                   |
| `verifierId`        | `string`  | The claim value used as the user's identifier within the verifier.  |
| `typeOfLogin`       | `string`  | Authentication method that was used (for example, `google`, `jwt`). |
| `dappShare`         | `string`  | Device share for MFA-enabled wallets.                               |
| `oAuthIdToken`      | `string`  | Raw OAuth `id_token` from the authentication provider.              |
| `oAuthAccessToken`  | `string`  | Raw OAuth `access_token` from the authentication provider.          |
| `isMfaEnabled`      | `boolean` | Whether MFA is currently enabled for this user.                     |

---

## Usage overview

The following pages document each operation exposed by the v9 SDK hooks API. All hooks require the component to be inside a `Web3AuthProvider`.

## Hook to operation mapping

If you are migrating from v8, this table maps the old class methods to their v9 hook equivalents:

| v8 method                            | v9 hook and function                                     | Page                                      |
| ------------------------------------ | -------------------------------------------------------- | ----------------------------------------- |
| `web3auth.login({ loginProvider })`  | `useWeb3AuthConnect()` → `connectTo({ authConnection })` | [Login](./login.mdx)                      |
| `web3auth.logout()`                  | `useWeb3AuthDisconnect()` → `disconnect()`               | [Logout](./logout.mdx)                    |
| `web3auth.userInfo()`                | `useWeb3AuthUser()` → `userInfo`                         | [User info](./user-info.mdx)              |
| `web3auth.privKey` / `getPrivKey()`  | `useWeb3Auth()` → `provider` (for signing)               | [Private key](./private-key.mdx)          |
| Ed25519 key (`getEd25519PrivKey()`)  | `useWeb3Auth()` → `web3Auth.signer`                      | [Ed25519 / Solana](./ed25519-key.mdx)     |
| `web3auth.launchWalletServices()`    | `useWalletUI()` → `showWalletUI()`                       | [Wallet UI](./launch-wallet-services.mdx) |
| `web3auth.request(chainConfig, ...)` | `useSignatureRequest()` → `request(method, params)`      | [Signature request](./request.mdx)        |
| `enableMFA()` on instance            | `useEnableMFA()` → `enableMFA()`                         | [Enable MFA](./enable-mfa.mdx)            |

## All usage pages

- [Login](./login.mdx)
- [Logout](./logout.mdx)
- [User info](./user-info.mdx)
- [Private key](./private-key.mdx)
- [Ed25519 / Solana signer](./ed25519-key.mdx)
- [Enable MFA](./enable-mfa.mdx)
- [Wallet UI](./launch-wallet-services.mdx)
- [Signature request](./request.mdx)

---

## Solana signer (Ed25519)

For Solana chains, the SDK exposes a `TransactionSigner` from `@solana/signers` via `useWeb3Auth().web3Auth.signer`. This replaces the v8 `SolanaWallet` from `@web3auth/solana-provider`.

## Configuration

Ensure your `web3authConfig.ts` uses `CHAIN_NAMESPACES.SOLANA`:

```typescript title="web3authConfig.ts"

  CHAIN_NAMESPACES,
  WEB3AUTH_NETWORK,
  type Web3AuthContextConfig,
} from '@web3auth/react-native-sdk'

const web3AuthConfig: Web3AuthContextConfig = {
  web3AuthOptions: {
    clientId: 'YOUR_CLIENT_ID',
    redirectUrl: 'yourapp://auth',
    network: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
    chains: [
      {
        chainNamespace: CHAIN_NAMESPACES.SOLANA,
        chainId: '0x2', // Solana Testnet
        rpcTarget: 'https://api.testnet.solana.com',
        displayName: 'Solana Testnet',
        blockExplorerUrl: 'https://explorer.solana.com',
        ticker: 'SOL',
        tickerName: 'Solana',
      },
    ],
    defaultChainId: '0x2',
  },
}
```

## Get the signer

```tsx

function SolanaView() {
  const { web3Auth } = useWeb3Auth()
  const solanaSigner = web3Auth?.signer as TransactionSigner | null

  const getAddress = () => (solanaSigner ? String(solanaSigner.address) : null)
}
```

## Get balance

```tsx

function SolanaBalance() {
  const { web3Auth } = useWeb3Auth()
  const solanaSigner = web3Auth?.signer as TransactionSigner | null

  const getBalance = async () => {
    if (!solanaSigner) return null
    const connection = new Connection('https://api.testnet.solana.com', 'confirmed')
    const lamports = await connection.getBalance(new PublicKey(String(solanaSigner.address)))
    return lamports / 1e9 // Convert lamports to SOL
  }
}
```

## Sign a message

```tsx

function SignMessageView() {
  const { web3Auth } = useWeb3Auth()

  const signSolanaMessage = async (message: string) => {
    const solanaSigner = web3Auth?.signer as TransactionSigner | null
    if (!solanaSigner) throw new Error('Not connected')

    const encoded = new TextEncoder().encode(message)
    const signature = await signBytes(solanaSigner, encoded)
    return Buffer.from(signature).toString('base64')
  }

  return <Button title="Sign message" onPress={() => signSolanaMessage('Hello')} />
}
```

## Related

- [useWeb3Auth hook reference](../hooks/useWeb3Auth.mdx)
- [Solana chain configuration](../advanced/README.mdx#chain-configuration)

---

## Enable MFA(Usage)

Use the `useEnableMFA` hook to let users enable Multi-Factor Authentication for their embedded wallet.

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this SDK in a production environment is the **Scale Plan**. You can use this feature in Web3Auth Sapphire Devnet network for free.

:::

:::info

MFA is only available for social login embedded wallets. It is not supported for external wallet connections.

:::

## Import

```tsx

```

## Usage

```tsx

function EnableMFAView() {
  const { enableMFA, loading, error } = useEnableMFA()

  return (
    <View>
      <Text>Secure your wallet with Multi-Factor Authentication.</Text>
      <Button
        title={loading ? 'Setting up MFA…' : 'Enable MFA'}
        disabled={loading}
        onPress={() => enableMFA()}
      />
      {error && <Text style={{ color: 'red' }}>{error.message}</Text>}
    </View>
  )
}
```

## Related

- [useEnableMFA hook reference](../hooks/useEnableMFA.mdx)
- [useManageMFA hook reference](../hooks/useManageMFA.mdx)
- [MFA advanced guide](../advanced/mfa.mdx)

---

## Show Wallet UI(4)

Use the `useWalletUI` hook to open the Wallet Services in-app browser overlay, which provides a pre-built wallet interface for viewing balances, sending tokens, and managing the wallet.

## Import

```tsx

```

## Usage

```tsx

function WalletButton() {
  const { showWalletUI, loading, error } = useWalletUI()

  return (
    <View>
      <Button
        title={loading ? 'Opening wallet…' : 'Open Wallet'}
        disabled={loading}
        onPress={() => showWalletUI()}
      />
      {error && <Text style={{ color: 'red' }}>{error.message}</Text>}
    </View>
  )
}
```

## Related

- [useWalletUI hook reference](../hooks/useWalletUI.mdx)
- [Signature request](./request.mdx)

---

## Sign in a user(4)

Use the `useWeb3AuthConnect` hook to authenticate a user. Call `connectTo` with an `AUTH_CONNECTION` constant and any additional parameters required by the chosen provider.

## Import

```tsx

```

## Usage

<Tabs
  defaultValue="social"
  values={[
    { label: 'Social login', value: 'social' },
    { label: 'Email passwordless', value: 'email' },
    { label: 'Custom JWT', value: 'jwt' },
  ]}
>

<TabItem value="social">

```tsx

function LoginView() {
  const { connectTo, loading, error } = useWeb3AuthConnect()

  return (
    <View>
      <Button
        title={loading ? 'Signing in…' : 'Sign in with Google'}
        disabled={loading}
        onPress={() => connectTo({ authConnection: AUTH_CONNECTION.GOOGLE })}
      />
      <Button
        title="Sign in with Apple"
        disabled={loading}
        onPress={() => connectTo({ authConnection: AUTH_CONNECTION.APPLE })}
      />
      {error && <Text style={{ color: 'red' }}>{error.message}</Text>}
    </View>
  )
}
```

</TabItem>

<TabItem value="email">

```tsx

function EmailLoginView() {
  const { connectTo, loading } = useWeb3AuthConnect()
  const [email, setEmail] = useState('')

  return (
    <View>
      <TextInput
        value={email}
        onChangeText={setEmail}
        placeholder="Enter your email"
        keyboardType="email-address"
        autoCapitalize="none"
      />
      <Button
        title={loading ? 'Sending link…' : 'Continue with email'}
        disabled={loading || !email}
        onPress={() =>
          connectTo({
            authConnection: AUTH_CONNECTION.EMAIL_PASSWORDLESS,
            extraLoginOptions: { login_hint: email },
          })
        }
      />
    </View>
  )
}
```

</TabItem>

<TabItem value="jwt">

```tsx

function JwtLoginView() {
  const { connectTo, loading } = useWeb3AuthConnect()

  const loginWithFirebase = async () => {
    // Obtain the idToken from your own authentication flow (Firebase, Auth0, etc.)
    const idToken = await getFirebaseIdToken()

    await connectTo({
      authConnection: AUTH_CONNECTION.CUSTOM,
      authConnectionId: 'w3a-firebase-demo', // Dashboard Connection ID
      idToken,
      extraLoginOptions: { verifierIdField: 'sub' },
    })
  }

  return <Button title="Sign in with Firebase" disabled={loading} onPress={loginWithFirebase} />
}
```

</TabItem>

</Tabs>

## Parameters

<Tabs
  defaultValue="table"
  values={[
    { label: 'Parameters', value: 'table' },
    { label: 'Interface', value: 'interface' },
    { label: 'AUTH_CONNECTION enum', value: 'enum' },
  ]}
>

<TabItem value="table">

| Parameter                  | Required | Description                                                                                                                                                                                                                            |
| -------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `authConnection`           | Yes      | Authentication method. Pass an `AUTH_CONNECTION.*` constant. Replaces the v8 `loginProvider` field.                                                                                                                                    |
| `authConnectionId?`        | No       | Dashboard Connection ID for the auth connection. Required when using `AUTH_CONNECTION.CUSTOM` or when you have multiple connections of the same type and need to target one specifically. Replaces the v8 `loginConfig[key].verifier`. |
| `groupedAuthConnectionId?` | No       | Dashboard Grouped Connection ID when using grouped (aggregate) connections. Connections sharing the same `groupedAuthConnectionId` produce the same wallet address. Replaces the v8 `loginConfig[key].verifierSubIdentifier`.          |
| `idToken?`                 | No       | A JWT issued by your authentication provider (Firebase, Auth0, Cognito, and so on). Pass this when using `AUTH_CONNECTION.CUSTOM`. The token is sent directly to the SDK instead of opening a browser redirect.                        |
| `extraLoginOptions?`       | No       | Additional OAuth hints passed to the authentication provider. Common fields: `login_hint` (email), `domain` (Auth0 domain), `verifierIdField` (JWT claim to use as the wallet identifier).                                             |
| `redirectUrl?`             | No       | Override the global `redirectUrl` from `web3AuthOptions` for this login call only.                                                                                                                                                     |
| `mfaLevel?`                | No       | Override the global `mfaLevel` for this login call only.                                                                                                                                                                               |
| `curve?`                   | No       | Elliptic curve to use for key generation. Accepts `SUPPORTED_KEY_CURVES.SECP256K1` (EVM) or `SUPPORTED_KEY_CURVES.ED25519` (Solana). Defaults to the chain namespace.                                                                  |
| `sessionTime?`             | No       | Override the global session duration (in seconds) for this login session only.                                                                                                                                                         |
| `dappShare?`               | No       | Custom device share key for MFA-enabled wallets. Required when reconstructing a key with a custom share.                                                                                                                               |
| `appState?`                | No       | Arbitrary state string that is returned in the redirect callback. Useful for restoring application state after the OAuth redirect.                                                                                                     |

</TabItem>

<TabItem value="interface">

```typescript
export interface SdkLoginParams {
  /** Authentication method: use AUTH_CONNECTION.* constants */
  authConnection: AUTH_CONNECTION_TYPE
  /** Dashboard Connection ID; required for AUTH_CONNECTION.CUSTOM */
  authConnectionId?: string
  /** Grouped Connection ID for aggregate verifier flows */
  groupedAuthConnectionId?: string
  /** JWT from your auth provider for custom authentication */
  idToken?: string
  /** Additional OAuth parameters (login_hint, domain, verifierIdField, etc.) */
  extraLoginOptions?: ExtraLoginOptions
  /** Override redirectUrl for this login call */
  redirectUrl?: string
  /** Override MFA level for this login call */
  mfaLevel?: MfaLevelType
  /** Elliptic curve for key generation */
  curve?: SUPPORTED_KEY_CURVES_TYPE
  /** Override session duration for this session */
  sessionTime?: number
  /** Custom device share for MFA-enabled wallets */
  dappShare?: string
  /** Arbitrary app state to restore after redirect */
  appState?: string
}
```

</TabItem>

<TabItem value="enum">

`AUTH_CONNECTION` replaces the v8 `LOGIN_PROVIDER` enum. Import it from `@web3auth/react-native-sdk`.

| `AUTH_CONNECTION` constant           | Description                                               | v8 `LOGIN_PROVIDER` equivalent      |
| ------------------------------------ | --------------------------------------------------------- | ----------------------------------- |
| `AUTH_CONNECTION.GOOGLE`             | Google OAuth 2.0                                          | `LOGIN_PROVIDER.GOOGLE`             |
| `AUTH_CONNECTION.FACEBOOK`           | Facebook OAuth                                            | `LOGIN_PROVIDER.FACEBOOK`           |
| `AUTH_CONNECTION.APPLE`              | Sign in with Apple                                        | `LOGIN_PROVIDER.APPLE`              |
| `AUTH_CONNECTION.DISCORD`            | Discord OAuth                                             | `LOGIN_PROVIDER.DISCORD`            |
| `AUTH_CONNECTION.TWITTER`            | Twitter / X OAuth                                         | `LOGIN_PROVIDER.TWITTER`            |
| `AUTH_CONNECTION.GITHUB`             | GitHub OAuth                                              | `LOGIN_PROVIDER.GITHUB`             |
| `AUTH_CONNECTION.TWITCH`             | Twitch OAuth                                              | `LOGIN_PROVIDER.TWITCH`             |
| `AUTH_CONNECTION.LINE`               | LINE OAuth                                                | `LOGIN_PROVIDER.LINE`               |
| `AUTH_CONNECTION.KAKAO`              | Kakao OAuth                                               | `LOGIN_PROVIDER.KAKAO`              |
| `AUTH_CONNECTION.LINKEDIN`           | LinkedIn OAuth                                            | `LOGIN_PROVIDER.LINKEDIN`           |
| `AUTH_CONNECTION.WEIBO`              | Weibo OAuth                                               | `LOGIN_PROVIDER.WEIBO`              |
| `AUTH_CONNECTION.WECHAT`             | WeChat OAuth                                              | `LOGIN_PROVIDER.WECHAT`             |
| `AUTH_CONNECTION.EMAIL_PASSWORDLESS` | Magic link / OTP sent to an email address                 | `LOGIN_PROVIDER.EMAIL_PASSWORDLESS` |
| `AUTH_CONNECTION.SMS_PASSWORDLESS`   | OTP sent to a phone number                                | `LOGIN_PROVIDER.SMS_PASSWORDLESS`   |
| `AUTH_CONNECTION.FARCASTER`          | Farcaster protocol sign-in                                | ,                                   |
| `AUTH_CONNECTION.CUSTOM`             | Any custom JWT flow (Firebase, Auth0, Cognito, and so on) | `LOGIN_PROVIDER.JWT`                |

</TabItem>

</Tabs>

## Related

- [useWeb3AuthConnect hook reference](../hooks/useWeb3AuthConnect.mdx)
- [Custom authentication guide](../advanced/custom-authentication.mdx)

---

## Sign out a user

Use the `useWeb3AuthDisconnect` hook to end the current authenticated session.

## Import

```tsx

```

## Usage

```tsx

function LogoutButton() {
  const { disconnect, loading, error } = useWeb3AuthDisconnect()

  return (
    <View>
      <Button
        title={loading ? 'Signing out…' : 'Sign out'}
        disabled={loading}
        onPress={() => disconnect()}
      />
      {error && <Text style={{ color: 'red' }}>{error.message}</Text>}
    </View>
  )
}
```

Calling `disconnect()` clears the persisted session from device storage. After it resolves, `useWeb3Auth().isConnected` becomes `false` and the `provider` becomes `null`.

## Related

- [useWeb3AuthDisconnect hook reference](../hooks/useWeb3AuthDisconnect.mdx)

---

## Blockchain provider and private key

In v9, the preferred way to perform EVM blockchain operations is through the `provider` returned by `useWeb3Auth()`. This is an EIP-1193 compatible provider that you pass directly to ethers or viem, no `EthereumPrivateKeyProvider` or `getPrivKey()` is needed.

## Using the provider with ethers

```tsx

function EvmActions() {
  const { provider } = useWeb3Auth()

  const getAddress = async () => {
    const ep = new ethers.BrowserProvider(provider!)
    const signer = await ep.getSigner()
    return await signer.getAddress()
  }

  const getBalance = async () => {
    const ep = new ethers.BrowserProvider(provider!)
    const signer = await ep.getSigner()
    const balance = await ep.getBalance(await signer.getAddress())
    return ethers.formatEther(balance)
  }

  const signMessage = async (message: string) => {
    const ep = new ethers.BrowserProvider(provider!)
    const signer = await ep.getSigner()
    return await signer.signMessage(message)
  }

  const sendTransaction = async (to: string, valueEth: string) => {
    const ep = new ethers.BrowserProvider(provider!)
    const signer = await ep.getSigner()
    const tx = await signer.sendTransaction({
      to,
      value: ethers.parseEther(valueEth),
    })
    return tx.hash
  }
}
```

## Using the provider with viem

```tsx

function ViemActions() {
  const { provider } = useWeb3Auth()

  const getAddress = async () => {
    const client = createWalletClient({
      chain: sepolia,
      transport: custom(provider!),
    })
    const [address] = await client.getAddresses()
    return address
  }
}
```

## Raw private key export

:::caution

Exporting raw private keys is strongly discouraged. Use the `provider` for signing instead. Raw key export must be explicitly enabled in the [Embedded Wallets dashboard](https://developer.metamask.io/) under **Key Export** settings.

:::

If key export is enabled in your project, you can request the private key using `personal_sign` through the provider:

```tsx

function ExportPrivateKeyView() {
  const { provider } = useWeb3Auth()

  const exportPrivateKey = async () => {
    // Requires key export to be enabled in the dashboard
    const privateKey = await provider?.request({
      method: 'eth_private_key',
    })
    return privateKey
  }

  // Call exportPrivateKey() from a button handler or effect when needed
}
```

## Related

- [useWeb3Auth hook reference](../hooks/useWeb3Auth.mdx)

---

## Signature request

Use the `useSignatureRequest` hook to send JSON-RPC signing requests through the Wallet Services overlay. Unlike signing directly through the provider, this presents a human-readable confirmation screen to the user before the operation is executed.

## Import

```tsx

```

## Usage

```tsx

function SigningView() {
  const { provider } = useWeb3Auth()
  const { request, loading, error } = useSignatureRequest()

  const getAddress = async () => {
    const ep = new ethers.BrowserProvider(provider!)
    const signer = await ep.getSigner()
    return await signer.getAddress()
  }

  const signPersonalMessage = async () => {
    const address = await getAddress()
    const message = 'Hello from Web3Auth!'
    const signature = await request('personal_sign', [
      ethers.hexlify(ethers.toUtf8Bytes(message)),
      address,
    ])
    console.log('Signature:', signature)
  }

  const signTypedData = async () => {
    const address = await getAddress()
    const typedData = {
      types: {
        Message: [{ name: 'content', type: 'string' }],
      },
      primaryType: 'Message',
      domain: { name: 'MyApp', version: '1' },
      message: { content: 'Hello!' },
    }
    const signature = await request('eth_signTypedData_v4', [address, JSON.stringify(typedData)])
    console.log('Typed data signature:', signature)
  }

  const sendTransaction = async () => {
    const address = await getAddress()
    const txHash = await request('eth_sendTransaction', [
      {
        from: address,
        to: '0x0000000000000000000000000000000000000001',
        value: ethers.toBeHex(ethers.parseEther('0.001')),
        gasLimit: ethers.toBeHex(21000),
      },
    ])
    console.log('Transaction hash:', txHash)
  }

  return (
    <View>
      <Button title="Sign message" disabled={loading} onPress={signPersonalMessage} />
      <Button title="Sign typed data" disabled={loading} onPress={signTypedData} />
      <Button title="Send ETH" disabled={loading} onPress={sendTransaction} />
      {error && <Text style={{ color: 'red' }}>{error.message}</Text>}
    </View>
  )
}
```

## Supported methods

| Method                 | Description                                 |
| ---------------------- | ------------------------------------------- |
| `personal_sign`        | Sign a personal message (EIP-191).          |
| `eth_signTypedData_v4` | Sign structured typed data (EIP-712).       |
| `eth_sendTransaction`  | Send an Ethereum transaction.               |
| `eth_signTransaction`  | Sign a transaction without broadcasting it. |

## Related

- [useSignatureRequest hook reference](../hooks/useSignatureRequest.mdx)
- [Show Wallet UI](./launch-wallet-services.mdx)

---

## Get user info(Usage)

Use the `useWeb3AuthUser` hook to access the authenticated user's profile. The `userInfo` object is reactive, it updates automatically when the session changes.

## Import

```tsx

```

## Usage

```tsx

function UserProfile() {
  const { userInfo } = useWeb3AuthUser()

  if (!userInfo) return null

  return (
    <View>
      {userInfo.profileImage && (
        <Image
          source={{ uri: userInfo.profileImage }}
          style={{ width: 64, height: 64, borderRadius: 32 }}
        />
      )}
      <Text>Name: {userInfo.name}</Text>
      <Text>Email: {userInfo.email}</Text>
      <Text>Login method: {userInfo.typeOfLogin}</Text>
      <Text>MFA enabled: {userInfo.isMfaEnabled ? 'Yes' : 'No'}</Text>
    </View>
  )
}
```

## Return value fields

| Field               | Type      | Description                                                                           |
| ------------------- | --------- | ------------------------------------------------------------------------------------- |
| `name`              | `string`  | User's display name from the identity provider.                                       |
| `email`             | `string`  | User's email address (if provided by the identity provider).                          |
| `profileImage`      | `string`  | URL of the user's profile image.                                                      |
| `verifier`          | `string`  | The verifier (connection) used for authentication.                                    |
| `verifierId`        | `string`  | The value of the claim used as the user identifier.                                   |
| `aggregateVerifier` | `string`  | The grouped connection ID if a grouped connection was used.                           |
| `typeOfLogin`       | `string`  | Authentication method (for example, `google`, `jwt`).                                 |
| `dappShare`         | `string`  | Device share for MFA-enabled wallets. Store this in secure storage for future logins. |
| `oAuthIdToken`      | `string`  | Raw `id_token` from the OAuth provider.                                               |
| `oAuthAccessToken`  | `string`  | Raw `access_token` from the OAuth provider.                                           |
| `isMfaEnabled`      | `boolean` | Whether MFA is currently enabled for this account.                                    |

## Related

- [useWeb3AuthUser hook reference](../hooks/useWeb3AuthUser.mdx)

---

## Embedded Wallets SDK for Unity

## Overview

MetaMask Embedded Wallets SDK (formerly Web3Auth Plug and Play) provides authentication for Unity game applications with social logins, external wallets, and more. Our Unity SDK, written in C#, simplifies how you connect users to their preferred wallets and manage authentication state across all mobile platforms.

## Requirements

- Unity Editor 2019.4.9f1 or greater
- .Net Framework 4.x
- iOS Platform Target Version 14 and above
- Android Target SDK Version 24 and above
- Basic knowledge of C# and Unity Development

## Prerequisites

- Set up your project on the [Embedded Wallets dashboard](https://developer.metamask.io/)

:::tip

See the [dashboard setup](../../dashboard/README.mdx) guide to learn more.

:::

## Installation

Install the Web3Auth Unity SDK using one of the following methods:

### Download Unity package

Download the [.unitypackage](https://github.com/Web3Auth/web3auth-unity-sdk/releases/latest) from our latest release and import the package file into your existing Unity3D project.

:::warning

You may encounter errors when importing this package into your existing project.

`The type or namespace name 'Newtonsoft' could not be found (are you missing a using directive or an assembly reference?)`

To fix this problem you need to add the following line into the dependencies object which is inside the `Packages/manifest.json` file.

```json title="/Packages/manifest.json"
"com.unity.nuget.newtonsoft-json": "3.2.1"
```

:::

### Configure Web3Auth project

- From the [Embedded Wallets dashboard](https://developer.metamask.io/), create or select an Web3Auth project:
- Add `{{SCHEMA}}://{YOUR_APP_PACKAGE_NAME}/auth` to **Allowlist URLs**.
- Copy the `Client ID` for usage later.

## Initialize Web3Auth

### 1. Create Web3Auth instance

Attach a `Web3Auth.cs` script to your game object where you want to write your authentication code:

```cs title="/Assets/Web3Auth.cs"
using System;
using System.Linq;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Newtonsoft.Json;

public class Web3Auth : MonoBehaviour
{
  // Start is called before the first frame update
  void Start() {}
  public void login() {}
  private void onLogin(Web3AuthResponse response) {}
  public void logout() {}
  private void onLogout() {}
}
```

Within your script, import the `Web3Auth` component in your class:

```cs
Web3Auth web3Auth;
```

Create an instance within your `Start()` function by creating an instance of the component you just imported:

```cs
web3Auth = GetComponent<Web3Auth>();
```

### 2. Configure Web3Auth options

After instantiation, within your `Start()` function, set up the Web3Auth Options:

```cs
web3Auth.setOptions(new Web3AuthOptions(){
    clientId = "YOUR_WEB3AUTH_CLIENT_ID", // Pass your Web3Auth Client ID, ideally using an environment variable // Get your Client ID from MetaMask Developer Dashboard
    network = Web3Auth.Network.SAPPHIRE_MAINNET, // or Web3Auth.Network.SAPPHIRE_DEVNET
    redirectUrl = new Uri("torusapp://com.torus.Web3AuthUnity/auth"),
});
```

### 3. Set up event handlers

Set up event handlers for login and logout events:

```cs
void Start()
{
    web3Auth = GetComponent<Web3Auth>();
    web3Auth.setOptions(new Web3AuthOptions()
    {
        clientId = "YOUR_WEB3AUTH_CLIENT_ID", // Pass your Web3Auth Client ID, ideally using an environment variable
        network = Web3Auth.Network.SAPPHIRE_MAINNET,
        redirectUrl = new Uri("torusapp://com.torus.Web3AuthUnity/auth"),
    });

    // Set up event handlers
    web3Auth.onLogin += onLogin;
    web3Auth.onLogout += onLogout;
}

private void onLogin(Web3AuthResponse response)
{
    Debug.Log("Login successful!");
    Debug.Log("Private Key: " + response.privKey);
}

private void onLogout()
{
    Debug.Log("Logout successful!");
}
```

## Advanced configuration

The Web3Auth Unity SDK offers a rich set of advanced configuration options:

- **[Custom authentication](./advanced/custom-authentication.mdx):** Define authentication methods.
- **[Whitelabeling and UI customization](./advanced/whitelabel.mdx):** Personalize the modal's appearance.
- **[Multi-Factor Authentication (MFA)](./advanced/mfa.mdx):** Set up and manage MFA.
- **[Dapp share](./advanced/dapp-share.mdx):** Share dapp sessions across devices.

:::tip

See the [advanced configuration sections](./advanced/) to learn more about each configuration option.

:::

<Tabs
  defaultValue="basic-config"
  values={[
    { label: "Basic Configuration", value: "basic-config" },
    { label: "Advanced Configuration", value: "advanced-config" },
  ]}
>

<TabItem value="basic-config">

```cs
web3Auth = GetComponent<Web3Auth>();

//focus-start
web3Auth.setOptions(new Web3AuthOptions(){
    clientId = "YOUR_WEB3AUTH_CLIENT_ID", // Pass your Web3Auth Client ID, ideally using an environment variable
    network = Web3Auth.Network.SAPPHIRE_MAINNET, // or Web3Auth.Network.SAPPHIRE_DEVNET
    redirectUrl = new Uri("torusapp://com.torus.Web3AuthUnity/auth"),
});
//focus-end
```

</TabItem>

<TabItem value="advanced-config">

```cs
web3Auth = GetComponent<Web3Auth>();

var loginConfigItem = new LoginConfigItem()
    {
        verifier = "google-verifier", // Get this from the MetaMask Developer Dashboard
        typeOfLogin = TypeOfLogin.GOOGLE,
        clientId = "YOUR_GOOGLE_CLIENT_ID" // Google's client ID
    };

//focus-start
web3Auth.setOptions(new Web3AuthOptions(){
    clientId = "YOUR_WEB3AUTH_CLIENT_ID", // Pass your Web3Auth Client ID, ideally using an environment variable
    network = Web3Auth.Network.SAPPHIRE_MAINNET, // or Web3Auth.Network.SAPPHIRE_DEVNET
    redirectUrl = new Uri("torusapp://com.torus.Web3AuthUnity/auth"),
    loginConfig = new Dictionary<string, LoginConfigItem>
    {
        {"google", loginConfigItem}
    }
    mfaSettings = new MfaSettings() {
        deviceShareFactor = new MfaSetting() {
            enable = true,
            priority = 1
        },
        backUpShareFactor = new MfaSetting() {
            enable = true,
            priority = 2
        },
        socialBackupFactor = new MfaSetting() {
            enable = true,
            priority = 3
        },
        passwordFactor = new MfaSetting() {
            enable = true,
            priority = 4
        }
    }
});
//focus-end
```

</TabItem>

</Tabs>

## Blockchain integration

Web3Auth is blockchain agnostic, enabling integration with any blockchain network. We recommend using the **Nethereum Library** for Ethereum integration.

### Ethereum integration

:::tip

We recommend you use the [Nethereum Library](https://docs.nethereum.com/) for making the blockchain calls. See [how to integrate Nethereum with Web3Auth](../../connect-blockchain/evm/ethereum/unity.mdx).

:::

For Ethereum integration, you can get the private key and use it with Nethereum:

```cs
using Nethereum.Web3;
using Nethereum.Util;
using Nethereum.Signer;
using Nethereum.Hex.HexConvertors.Extensions;
using Nethereum.ABI.Encoders;
using Nethereum.Hex.HexTypes;
using Nethereum.Web3.Accounts;
using Nethereum.Web3.Accounts.Managed;

public class Web3AuthScript : MonoBehaviour
{
    Web3 web3;
    Web3Auth web3Auth;
    private string privateKey;
    private Account account;

    const string rpcURL = "" // EVM chain RPC URL

    void Start()
    {

      web3Auth = GetComponent<Web3Auth>();

      // Add Web3Auth Unity SDK Initialisation Code here

      web3Auth.onLogin += onLogin;
      web3Auth.onLogout += onLogout;
      web3 = new Web3(rpcURL);
    }

    private void onLogin(Web3AuthResponse response)
    {
        //focus-start
        // get the private key from web3auth response
        privateKey = response.privKey;
        // generate the user account
        var account = new Account(privateKey);
        // get the user address
        address = account.Address;

        // create the web3 instance
        web3 = new Web3("rpcURL");

        // get the user balance
        var balance = web3.Eth.GetBalance.SendRequestAsync(address).Result.Value;
        //focus-end
    }
// ...
}
```

### Solana integration

For Solana integration, you can get the Ed25519 private key:

```cs
private void onLogin(Web3AuthResponse response)
{
    var ed25519PrivKey = response.ed25519PrivKey;
    // Use Ed25519 private key with Solana libraries
    Debug.Log("Solana Ed25519 Private Key: " + ed25519PrivKey);
}
```

---

## Advanced configuration(7)

The Embedded Wallets SDK provides extensive configuration options that allow you to customize authentication flows, UI appearance, blockchain integrations, and security features to meet your Unity application's specific requirements.

## Configuration structure

When setting up Web3Auth, you'll pass in the options to the constructor. This consists of:

```cs
web3Auth = GetComponent<Web3Auth>();

// focus-start
web3Auth.setOptions(new Web3AuthOptions(){
    clientId = "YOUR_WEB3AUTH_CLIENT_ID", // Pass your Web3Auth Client ID, ideally using an environment variable // Get your Client ID from MetaMask Developer Dashboard
    network = Web3Auth.Network.SAPPHIRE_MAINNET, // or Web3Auth.Network.SAPPHIRE_DEVNET
    redirectUrl = new Uri("torusapp://com.torus.Web3AuthUnity/auth"),
});
// focus-end
```

### `Web3AuthOptions`

The Web3Auth Constructor takes an object with `Web3AuthOptions` as input.

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Class", value: "class" },
  ]}
>

<TabItem value="table">

| Parameter      | Description                                                                                                                                  |
| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `clientId`     | Your Web3Auth Client ID from the [Dashboard](https://developer.metamask.io/). It's a mandatory field of type `string`.                       |
| `network`      | Web3Auth Network: `SAPPHIRE_MAINNET`, `SAPPHIRE_DEVNET`, `MAINNET`, `CYAN`, `AQUA` or `TESTNET`. Mandatory field of type `Web3Auth.Network`. |
| `redirectUrl`  | URL that Web3Auth will redirect API responses upon successful authentication. It's a mandatory field of type `Uri`.                          |
| `whiteLabel?`  | Whitelabel options for custom UI, branding, and translations. Takes `WhiteLabelData` as a value.                                             |
| `loginConfig?` | Login config for custom verifiers. Takes `LoginConfigItem` as a value.                                                                       |
| `mfaSettings?` | Configure MFA settings for authentication. Takes `MfaSettings` as a value.                                                                   |
| `sessionTime?` | Configure session management time in seconds. Default is 86400 seconds (1 day). Max 30 days.                                                 |

</TabItem>

<TabItem value="class">

```cs
public class Web3AuthOptions
{
    public string clientId { get; set; }
    public Web3Auth.Network network { get; set; }
    public Uri redirectUrl { get; set; }
    public WhiteLabelData whiteLabel { get; set; }
    public LoginConfigItem loginConfig { get; set; }
    public MfaSettings mfaSettings { get; set; }
    public int sessionTime { get; set; } = 86400;
}
```

</TabItem>
</Tabs>

## Session management

Control how long users stay authenticated and how sessions persist in Unity.

**Key Configuration Options:**

- `sessionTime` - Session duration in seconds. Controls how long users remain authenticated before needing to log in again.
  - Minimum: 1 second (`1`).
  - Maximum: 30 days (`86400 * 30`).
  - Default: 1 day (`86400`).

```cs
web3Auth.setOptions(new Web3AuthOptions(){
    clientId = "YOUR_WEB3AUTH_CLIENT_ID", // Pass your Web3Auth Client ID, ideally using an environment variable
    network = Web3Auth.Network.SAPPHIRE_MAINNET,
    sessionTime = 86400 * 7, // 7 days (in seconds)
    redirectUrl = new Uri("torusapp://com.torus.Web3AuthUnity/auth"),
});
```

## Custom authentication methods

Control the login options presented to your users. For detailed configuration options and implementation examples, see the [custom authentication](./custom-authentication.mdx) section.

## UI customization

Customize the brand experience by customizing the Embedded Wallets login screens to match your Unity application's design. For complete customization options, refer to the [whitelabeling and UI customization](./whitelabel.mdx) section.

## Multi-Factor Authentication (MFA)

Add additional security layers to protect user accounts with two-factor authentication. For detailed configuration options and implementation examples, see the [Multi-Factor Authentication](./mfa.mdx) section.

**Key Configuration Options:**

- `mfaSettings` - Configure MFA settings for different authentication flows
- `mfaLevel` - Control when users are prompted to set up MFA

## Dapp share

Share authentication sessions across different applications. For detailed configuration options and implementation examples, see the [dapp share](./dapp-share.mdx) section.

---

## Using custom authentication in PnP Unity SDK

Custom authentication is a way to authenticate users with your custom authentication service. For example, while authenticating with Google, you can use your own Google Client ID to authenticate users directly.

This feature, with MFA turned off, can make Embedded Wallets invisible to the end user.

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this
SDK in a production environment is the **Growth Plan**. You can use this feature in Web3Auth
Sapphire Devnet network for free.

:::

## Get an Auth Connection ID

:::info prerequisite

To enable this, you need to [create a connection](/embedded-wallets/dashboard/authentication) from the **Authentication** tab of your project from the [Embedded Wallets dashboard](https://developer.metamask.io) with your desired configuration.

:::

To configure a connection, you need to provide the particular details of the connection into our Embedded Wallets dashboard. This enables us to map a `authConnectionId with your connection details. This `authConnectionId helps us to identify the connection details while initializing the SDK. You can configure multiple connections for the same project, and you can also update the connection details anytime.

:::tip

Learn more about the [auth provider setup](/embedded-wallets/authentication) and the different configurations available for each connection.

:::

## Configuration

:::warning

**"Auth Connection"** is called **"Verifier"** in the Android SDK. It is the older terminology which we will be updating in the upcoming releases.

Consequentially, you will see the terms **"Verifier ID"** and **"Aggregate Verifier"** used in the codebase and documentation referring to **"Auth Connection ID"** and **"Grouped Auth Connection"** respectively.

:::

To use custom authentication (using supported Social providers or Login providers like Auth0, AWS Cognito, Firebase. or your own custom JWT login) you can add the configuration using `loginConfig` parameter during the initialization.

The `loginConfig` parameter is a key value map. The key should be one of the `Web3AuthProvider` in its string form, and the value should be a `LoginConfigItem` instance.

### Parameters

#### `LoginConfigItem`

The `LoginConfigItem` struct contains various parameters that define the behavior of the custom authentication process. Below are the details of the `LoginConfigItem` struct:

| Parameter                | Description                                                                                                                                                                                                                                                                                                       |
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `verifier`               | The name of the verifier that you have registered on the Embedded Wallets dashboard. It's a mandatory field, and accepts `string` as a value.                                                                                                                                                                     |
| `typeOfLogin`            | Type of login for this verifier. This value will affect the login flow. For example, if you choose `google`, a Google sign-in flow will be used. If you choose `jwt`, you should provide your own JWT token, and no sign-in flow will be presented. It's a mandatory field, and accepts `TypeOfLogin` as a value. |
| `clientId`               | Client ID provided by your login provider, such as Google's Client ID or Web3Auth's client ID if using `jwt` as `TypeOfLogin`. It's a mandatory field, and accepts `string` as a value.                                                                                                                           |
| `name?`                  | Display name for the verifier. If null, the default name is used. It accepts `string` as a value.                                                                                                                                                                                                                 |
| `description?`           | Description for the button. If provided, it renders as a full-length button; otherwise, an icon button is shown. It accepts `string` as a value.                                                                                                                                                                  |
| `verifierSubIdentifier?` | The field in the JWT token that maps to the verifier ID. Ensure you selected the correct JWT verifier ID in the developer dashboard. It accepts `string` as a value.                                                                                                                                              |
| `logoHover?`             | Logo to be shown on mouse hover. It accepts `string` as a value.                                                                                                                                                                                                                                                  |
| `logoLight?`             | Light logo for dark backgrounds. It accepts `string` as a value.                                                                                                                                                                                                                                                  |
| `logoDark?`              | Dark logo for light backgrounds. It accepts `string` as a value.                                                                                                                                                                                                                                                  |
| `mainOption?`            | shows the login button on the main list. It accepts `bool` as a value. The default value is `false`.                                                                                                                                                                                                              |
| `showOnModal?`           | Whether to show the login button on the modal. The default value is `true`.                                                                                                                                                                                                                                       |
| `showOnDesktop?`         | Whether to show the login button on the desktop. The default value is `true`.                                                                                                                                                                                                                                     |
| `showOnMobile?`          | Whether to show the login button on mobile. The default value is `true`.                                                                                                                                                                                                                                          |

#### `TypeOfLogin`

```csharp
public enum TypeOfLogin
{
    [EnumMember(Value = "google")]
    GOOGLE,
    [EnumMember(Value = "facebook")]
    FACEBOOK,
    [EnumMember(Value = "reddit")]
    REDDIT,
    [EnumMember(Value = "discord")]
    DISCORD,
    [EnumMember(Value = "twitch")]
    TWITCH,
    [EnumMember(Value = "apple")]
    APPLE,
    [EnumMember(Value = "line")]
    LINE,
    [EnumMember(Value = "github")]
    GITHUB,
    [EnumMember(Value = "kakao")]
    KAKAO,
    [EnumMember(Value = "linkedin")]
    LINKEDIN,
    [EnumMember(Value = "twitter")]
    TWITTER,
    [EnumMember(Value = "weibo")]
    WEIBO,
    [EnumMember(Value = "wechat")]
    WECHAT,
    [EnumMember(Value = "email_passwordless")]
    EMAIL_PASSWORDLESS,
    [EnumMember(Value = "email_password")]
    EMAIL_PASSWORD,
    [EnumMember(Value = "jwt")]
    JWT
}
```

#### `extraLoginOptions`

The `extraLoginOptions` parameter can be used to pass additional options required by specific login providers.

| Parameter                    | Description                                                                                                                                                 |
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `domain?`                    | Your custom authentication domain in `string` format. For example, if you are using Auth0, it can be `example.auth0.com`.                                   |
| `client_id?`                 | Client ID in `string` format, provided by your login provider and used for the custom verifier.                                                             |
| `verifierIdField?`           | The field in JWT token which maps to verifier ID. Ensure you select the correct JWT verifier ID in the developer dashboard. It takes a `string` as a value. |
| `isVerifierIdCaseSensitive?` | Boolean to confirm whether the verifier ID field is case-sensitive or not.                                                                                  |
| `prompt?`                    | Prompt shown to the user during the authentication process. Accepts a string value.                                                                         |
| `id_token?`                  | JWT (ID token) to be passed for login.                                                                                                                      |
| `login_hint?`                | It is used to send the user's email address during email passwordless login. Accepts a string value.                                                        |

## Single verifier

To use custom authentication with a single verifier, configure the `loginConfig` parameter of the `Web3AuthOptions` class. The `loginConfig` parameter is a key-value map where the key should be one of the `Web3AuthProvider` in its string form, and the value should be a `LoginConfigItem` struct instance.

```csharp
void Start()
{
    web3Auth = GetComponent<Web3Auth>();

    var loginConfigItem = new LoginConfigItem()
    {
        verifier = "google-verifier", // Get this from the MetaMask Developer Dashboard
        typeOfLogin = TypeOfLogin.GOOGLE,
        clientId = "YOUR_GOOGLE_CLIENT_ID" // Google's client ID
    };

    web3Auth.setOptions(new Web3AuthOptions()
    {
        redirectUrl = new Uri("torusapp://com.torus.Web3AuthUnity/auth"),
        clientId = "YOUR_WEB3AUTH_CLIENT_ID", // Pass your Web3Auth Client ID, ideally using an environment variable // Web3Auth's client ID
        network = Web3Auth.Network.TESTNET, // or other networks
        loginConfig = new Dictionary<string, LoginConfigItem>
        {
            {"google", loginConfigItem}
        }
    });
}
```

### Example implementations

#### Using Google login

```csharp
public void loginGoogle()
{
    var selectedProvider = Provider.GOOGLE;

    var options = new LoginParams()
    {
        loginProvider = selectedProvider,
    };

    web3Auth.login(options);
}
```

#### Using JWT login

To use JWT login (for example, Auth0):

```csharp
public void loginJWT()
{
    var selectedProvider = Provider.JWT;

    var options = new LoginParams()
    {
        loginProvider = selectedProvider,
        extraLoginOptions = new ExtraLoginOptions()
        {
            domain = "https://example.auth0.com", // Auth0 domain
            verifierIdField = "sub", // The field in JWT token mapping to verifier ID
            id_token = "YOUR_JWT_ID_TOKEN" // JWT ID token
        }
    };

    web3Auth.login(options);
}
```

## Aggregate verifier

You can use an aggregate verifier to combine multiple login methods, allowing users to log in using different providers but receive the same address.

To use aggregate verifiers, set up the `loginConfig` object with multiple providers under a single verifier.

```csharp
void Start()
{
    web3Auth = GetComponent<Web3Auth>();

    var googleConfig = new LoginConfigItem()
    {
        verifier = "aggregate-sapphire",
        verifierSubIdentifier = "google-sub-id",
        clientId = "YOUR_GOOGLE_CLIENT_ID",
        typeOfLogin = TypeOfLogin.GOOGLE,
    };

    var auth0GitHubConfig = new LoginConfigItem()
    {
        verifier = "aggregate-sapphire",
        verifierSubIdentifier = "github-sub-id",
        clientId = "YOUR_GITHUB_CLIENT_ID",
        typeOfLogin = TypeOfLogin.JWT,
    };

    web3Auth.setOptions(new Web3AuthOptions()
    {
        clientId = "YOUR_WEB3AUTH_CLIENT_ID", // Pass your Web3Auth Client ID, ideally using an environment variable
        redirectUrl = new System.Uri("w3aexample://com.web3auth.unityaggregateexample"),
        network = Web3Auth.Network.SAPPHIRE_MAINNET,
        loginConfig = new Dictionary<string, LoginConfigItem>
        {
            {"google", googleConfig},
            {"github", auth0GitHubConfig}
        }
    });
}
```

### Example implementations

#### Using Google and GitHub combined login

```csharp
public void loginGoogle()
{
    var selectedProvider = Provider.GOOGLE;

    var options = new LoginParams()
    {
        loginProvider = selectedProvider,
    };

    web3Auth.login(options);
}

public void loginGitHub()
{
    var selectedProvider = Provider.GITHUB;

    var options = new LoginParams()
    {
        loginProvider = selectedProvider,
        extraLoginOptions = new ExtraLoginOptions()
        {
            domain = "https://example.auth0.com",
            verifierIdField = "email",
            isVerifierIdCaseSensitive = false,
            prompt = Prompt.LOGIN,
        }
    };

    web3Auth.login(options);
}
```

---

## Using dapp share in PnP Unity SDK

## Embedded Wallets infrastructure at a glance

If you go through the [Web3Auth infrastructure](/embedded-wallets/infrastructure/), you'll notice that to enable the non custodiality of Web3Auth, we split the private key into multiple parts, called `shares`. These shares are a part of the offchain multisig, where multiple shares are stored in different places and can be used to reconstruct the private key dynamically in the user's frontend application. Typically, there are 3 shares:

1. **`ShareA` is stored on the user's device:** The Implementation is device and system specific. For example, on mobile devices, the share could be stored in device storage secured via biometrics.
2. **`ShareB` is managed by a login service via node operators:** This share is further split amongst a network of nodes and retrieved via conventional authentication flows.
3. **`ShareC` is a recovery share:** An extra share to be kept by the user, possibly stored on a separate device, downloaded or based on user input with enough entropy (such as, password, security questions, hardware device).

Similar to existing 2FA systems, a user needs to prove ownership of at least 2 out of 3 (2/3) shares, in order to retrieve their private key. This initial setup provides several benefits.

## The user experience in mobile/native OS platforms

The user experience in gaming and native OS platforms is very different from the web platforms. This is because the user has to be redirected to a browser where they can login using their socials and then back to the app once they have been successfully authenticated. This user experience shifts the context between two applications, whereas in the web platforms, the context remains within the browser only.

For the dapp share login flow, we need to reconstruct the Shares `A` and `B`. `Share A` is managed by the login service and is provided on successful authentication. Whereas in web platforms, `Share B` is stored in the browser context. We can still store it in the browser context for other devices, but this has a few risks, like user accidently deleting browser data. This is a bigger problem while using native platform application, since the user doesn't realise that the browser is being used to login within the app and clearing the browser data can cause their logins to fail. Hence, to tackle this issue, Web3Auth issues a dapp share, that is, a backup share that can be stored by the app developer directly within their application and used to reconstruct the private key after successful login by the user.

## Dapp share in Unity

Web3Auth issues a dapp share, that is, a backup share that can be stored by the app developer directly within their application and used to reconstruct the private key after successful login by the user.

After a successful login from a user, the user details are returned as a response to the application on mobile devices.

### Sample response in Unity

```json
{
  "ed25519PrivKey": "666523652352635....",
  "privKey": "0ajjsdsd....",
  "coreKitKey": "0ajjsdsd....",
  "coreKitEd25519PrivKey": "666523652352635....",
  "sessionId": "....",
  "error": "....",
  "userInfo": {
    "aggregateVerifier": "w3a-google",
    "email": "john@gmail.com",
    "name": "John Dash",
    "profileImage": "https://lh3.googleusercontent.com/a/Ajjjsdsmdjmnm...",
    "typeOfLogin": "google",
    "verifier": "torus",
    "verifierId": "john@gmail.com",
    "dappShare": "<24 words seed phrase>", // will be sent only incase of custom verifiers
    "idToken": "<jwtToken issued by Web3Auth>",
    "oAuthIdToken": "<jwtToken issued by OAuth Provider>", // will be sent only incase of custom verifiers
    "oAuthAccessToken": "<accessToken issued by OAuth Provider>", // will be sent only incase of custom verifiers
    "isMfaEnabled": true // returns true if user has enabled mfa
  }
}
```

If you notice, the response has a field called `dappShare` which is a 24 words seed phrase that can be used to reconstruct the private key. This `dappShare` is a suplement to the `Share A` and represents half of the private key. The application can store the dapp share in their own application local storage safely.

Now, while logging in, the user can use their social accounts to obtain one share, and the application provides the dapp share, removing the need to store the share in the browser context and enabling user to sign in without repeating the full flow. This can be done by passing over the stored dapp share value in the login function.

:::note

One major thing to note here is that the `dappShare` is only available for custom verifiers and not in the standard Web3Auth verifiers. This is done to make sure that an application only has access to the corresponding share to the private key of their application's user. Hence, to use dapp share, one has to use the custom authentication feature of Web3Auth. Also, the dapp share is only returned to users who have enabled 2FA to their account.

:::

## Example

```cs
public void login()
{
    var selectedProvider = Provider.GOOGLE;
    var options = new LoginParams()
    {
      loginProvider = selectedProvider,
		dappShare = "enter your dapp share"
    };
    web3Auth.login(options);
}
```

---

## Multi-factor authentication in PnP Unity SDK

MFA is an extra layer of protection that verifies your identity when accessing your account. To ensure ownership, you must provide two or more different backup factors. You have the option to choose from the device, social, backup factor (seed phrase), and password factors to guarantee access to your web3 account. Once you create a recovery factor, MFA is enabled, and your keys are divided into three shares for offchain multi-sig, making the key self-custodial. With backup factors, you can easily recover your account if you lose access to your original device or help login into a new device.

For a dapp, we provide several options to set up Multi-Factor Authentication. You can customize the MFA screen by setting the `mfaLevel` argument. You can enable or disable a backup factor and change their order. Currently, there are four values for `mfaLevel`:

- `default`: presents the MFA screen every third login
- `optional`: presents the MFA screen on every login, but you can skip it
- `mandatory`: make it mandatory to set up MFA after login
- `none`: skips the MFA setup screen

:::caution Note

If you are using default verifiers, your users may have set up MFA on other dapps that also use default Web3Auth verifiers. In this case, the MFA screen will continue to appear if the user has enabled MFA on other dapps. This is because MFA cannot be turned off once it is enabled.

:::

We offer the following backup factors under `mfaSettings`:

- `deviceShareFactor`,
- `backUpShareFactor`,
- `socialBackupFactor`,
- `passwordFactor`,
- `passkeysFactor`, and
- `authenticatorFactor`.

Choose the best options that suit your needs to ensure a safe and secure web3 experience.

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this SDK in a production environment is the **Scale Plan**. You can use this feature in Web3Auth Sapphire Devnet network for free.

:::

## Arguments

### `MFALevel`

```cs
public enum MFALevel
{
    [EnumMember(Value = "default")]
    DEFAULT,
    [EnumMember(Value = "optional")]
    OPTIONAL,
    [EnumMember(Value = "mandatory")]
    MANDATORY,
    [EnumMember(Value = "none")]
    NONE
}
```

```cs title="Usage"
public void login()
{
    var selectedProvider = Provider.GOOGLE;
    var options = new LoginParams()
    {
        loginProvider = selectedProvider,
		mfaLevel = MFALevel.MANDATORY
    };
    web3Auth.login(options);
}
```

### `MFASettings`

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this SDK in a production environment is the **SCALE Plan**. You can use this feature at no cost on `sapphire_devnet`.

:::

`MfaSetting`

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Class", value: "class" },
  ]}
>

<TabItem value="table">

| Parameter    | Description                                                                     |
| ------------ | ------------------------------------------------------------------------------- |
| `enable`     | Enable/Disable MFA. It accepts `bool` as a value.                               |
| `priority?`  | Priority of MFA. It accepts `int` as a value, where valid range is from 1 to 4. |
| `mandatory?` | Mandatory/Optional MFA. It acccepts `bool` as a value.                          |

</TabItem>
<TabItem value="class">

```cs
public class MfaSetting
{
    public bool enable { get; set; }
    public int? priority { get; set; }
    public bool? mandatory { get; set; }

    // Constructor
    public MfaSetting(bool enable, int? priority, bool? mandatory)
    {
        this.enable = enable;
        this.priority = priority;
        this.mandatory = mandatory;
    }
}
```

</TabItem>
</Tabs>

```cs title="Usage"
using System;
using System.Linq;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Newtonsoft.Json;

public class Web3custom : MonoBehaviour
{
  Web3Auth web3Auth;

  // Start is called before the first frame update
  void Start()
  {
    web3Auth = GetComponent<Web3Auth>();
    web3Auth.setOptions(new Web3AuthOptions()
    {
      redirectUrl = new Uri("torusapp://com.torus.Web3AuthUnity/auth"),
      clientId = "BAwFgL-r7wzQKmtcdiz2uHJKNZdK7gzEf2q-m55xfzSZOw8jLOyIi4AVvvzaEQO5nv2dFLEmf9LBkF8kaq3aErg",
      network = Web3Auth.Network.TESTNET,
      mfaSettings = new MfaSettings(
        new MfaSetting(true, 1, true),
        new MfaSetting(true, 1, true),
        new MfaSetting(true, 1, false),
        new MfaSetting(true, 1, true),
        new MfaSetting(true, 1, true),
        new MfaSetting(true, 1, true)
      )
    });
    web3Auth.onLogin += onLogin;
    web3Auth.onLogout += onLogout;
  }
  public void login() {}
  private void onLogin(Web3AuthResponse response) {}
  public void logout() {}
  private void onLogout() {}
}

```

:::note Note

- At least two factors are mandatory when setting up the mfaSettings.
- If you set `mandatory: true` for all factors, the user must set up all four factors.
- If you set `mandatory: false` for all factors, the user can skip setting up MFA. But at least two factors are mandatory.
- If you set `mandatory: true` for some factors and `mandatory: false` for others, the user must set up the mandatory factors and can skip the optional factors. But, the user must set up at least two factors.
- The `priority` field is used to set the order of the factors. The factor with the lowest priority will be the first factor to be set up. The factor with the highest priority will be the last factor to be set up.

:::

---

## Whitelabel PnP Unity SDK

Embedded Wallets supports whitelabeling with application branding for a consistent user experience. You can customize three different aspects:

- **UI elements:** Customize the appearance of modals and components
- **Branding:** Apply your brand colors, logos, and themes
- **Translations:** Localize the interface for your users

:::info

All of these settings can be easily managed directly from the Embedded Wallets dashboard. Once you update your branding, or UI preferences there, the changes will automatically apply to your integration.

:::

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this
SDK in a production environment is the **Growth Plan**. You can use this feature in Web3Auth
Sapphire Devnet network for free.

:::

## Customizing the Embedded Wallets login screens

For defining custom UI, branding, and translations for your branded app, you just need to add an additional parameter within the `Web3AuthOptions` class called `whiteLabel`. This parameter takes another object called `WhiteLabelData`.

### `WhiteLabelData`

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Interface", value: "interface" },
  ]}
>

<TabItem value="table">

| Parameter          | Description                                                                                                                                                                                          |
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `appName?`         | Display name for the app in the UI.                                                                                                                                                                  |
| `logoLight?`       | App logo to be used in dark mode. It accepts URL as string.                                                                                                                                          |
| `logoDark?`        | App logo to be used in light mode. It accepts URL as string.                                                                                                                                         |
| `defaultLanguage?` | Language which will be used by Web3Auth, app will use browser language if not specified. Default language is `Web3Auth.Language.en`. Checkout `Web3Auth.Language` for supported languages.           |
| `mode?`            | Theme mode for the login modal. Choose between `Web3Auth.ThemeModes.auto`, `Web3Auth.ThemeModes.light` or `Web3Auth.ThemeModes.dark` background modes. Default value is `Web3Auth.ThemeModes.light`. |
| `theme?`           | Used to customize the theme of the login modal. It accepts ` Dictionary<string, string>` as a value.                                                                                                 |
| `appUrl?`          | URL to be used in the modal. It accepts URL as string.                                                                                                                                               |
| `useLogoLoader?`   | Use logo loader. If `logoDark` and `logoLight` are null, the default Web3Auth logo will be used for the loader. Default value is false.                                                              |

</TabItem>

<TabItem value="interface">

```cs
public class WhiteLabelData {
  public string? appName { get; set; }
  public string? logoLight { get; set; }
  public string? logoDark { get; set; }
  public Web3Auth.Language? defaultLanguage { get; set; } = Web3Auth.Language.en;
  public Web3Auth.ThemeModes? mode { get; set; } = Web3Auth.ThemeModes.light;
  public Dictionary<string, string>? theme { get; set; }
  public string? appUrl { get; set; }
  public bool? useLogoLoader { get; set; } = false;
}
```

</TabItem>
</Tabs>

### `name`

The name of the application. This will be displayed in the key reconstruction page.

  
    
      Standard screen without any change
    
    
  
  
    
      Name changed to <code>Formidable Duo</code>
    
    
  

### `logoLight` & `logoDark`

The logo of the application. Displayed in dark and light mode respectively. This will be displayed
in the key reconstruction page.

  
    
      <code>logoLight</code> on dark mode
    
    
  
  
    
      <code>logoDark</code> on light mode
    
    
  

### `defaultLanguage`

Default language will set the language used on all OpenLogin screens. The supported languages are:

  
    
      
        <code>en</code> - English (default)
      
      
        <code>de</code> - German
      
      
        <code>ja</code> - Japanese
      
      
        <code>ko</code> - Korean
      
      
        <code>zh</code> - Mandarin
      
      
        <code>es</code> - Spanish
      
      
        <code>fr</code> - French
      
      
        <code>pt</code> - Portuguese
      
      
        <code>nl</code> - Dutch
      
      
        <code>tr</code> - Turkish
      
    
  
  
    
  

### `dark`

Can be set to `true` or `false` with default set to `false`.

  
    
      For Light: <code>dark: false</code>
    
    
  
  
    
      For Dark: <code>dark: true</code>
    
    
  

### `theme`

Theme is a record of colors that can be configured. As of, now only `primary` color can be set and
has effect on OpenLogin screens (default primary color is `#0364FF`). Theme affects icons and links.
Examples below.

  
    
      Standard color <code>#0364FF</code>
    
    
  
  
    
      Color changed to <code>#D72F7A</code>
    
    
  

### Example

```cs
void Start()
{
  web3Auth = GetComponent<Web3Auth>();
  web3Auth.setOptions(new Web3AuthOptions()
  {
    redirectUrl = new Uri("torusapp://com.torus.Web3AuthUnity/auth"),
    clientId = "BAwFgL-r7wzQKmtcdiz2uHJKNZdK7gzEf2q-m55xfzSZOw8jLOyIi4AVvvzaEQO5nv2dFLEmf9LBkF8kaq3aErg",
    network = Web3Auth.Network.TESTNET,
    // focus-start
    whiteLabel = new WhiteLabelData() {
      appName = "Web3Auth Sample App",
      logoLight = null,
      logoDark = null,
      defaultLanguage = "en",
      mode = "dark",
      theme = new Dictionary < string, string > {
        {
          "primary",
          "#d53f8c"
        }
      }
    }
    // focus-end

  });
}
```

---

## Examples - PnP Unity SDK

<ExampleCards exampleMap={pnpUnityExamples} />

---

## Using Unity SDK

Embedded Wallets provides a comprehensive set of functions to handle authentication, user management, and blockchain interactions in your Unity applications. These functions allow you to implement features like user login, multi-factor authentication, private key retrieval, and Wallet Services with minimal effort. Each function is designed to handle a specific aspect of Embedded Wallets' functionality, making it easy to integrate into your Unity projects.

## List of functions

:::tip

For detailed usage, configuration options, and code examples, refer to the dedicated documentation page for each function.

:::

### Authentication functions

| Function Name              | Description                                        |
| -------------------------- | -------------------------------------------------- |
| [`login()`](./login.mdx)   | Logs the user in with the selected login provider. |
| [`logout()`](./logout.mdx) | Logs the user out from the current session.        |

### User management functions

| Function Name                          | Description                                     |
| -------------------------------------- | ----------------------------------------------- |
| [`getUserInfo()`](./get-user-info.mdx) | Retrieves the authenticated user's information. |

### Private key functions

| Function Name                                          | Description                                                                     |
| ------------------------------------------------------ | ------------------------------------------------------------------------------- |
| [`getPrivKey()`](./get-private-key.mdx)                | Retrieve the user's secp256k1 private key for EVM-compatible chains.            |
| [`getEd25519PrivKey()`](./get-ed25519-private-key.mdx) | Retrieve the user's ed25519 private key for chains like Solana, Near, Algorand. |

### Security functions

| Function Name                     | Description                                       |
| --------------------------------- | ------------------------------------------------- |
| [`enableMFA()`](./enable-mfa.mdx) | Enables Multi-Factor Authentication for the user. |

### Wallet Services functions

| Function Name                                            | Description                                                   |
| -------------------------------------------------------- | ------------------------------------------------------------- |
| [`launchWalletServices()`](./launch-wallet-services.mdx) | Launches the templated wallet UI in WebView.                  |
| [`request()`](./request.mdx)                             | Opens templated transaction screens for signing transactions. |

---

## Enable MFA(3)

The `enableMFA` method is used to trigger MFA setup flow for users. The method takes `LoginParams` which will used during custom verifiers. If you are using default login providers, you don't need to pass `LoginParams`. If you are using custom JWT verifiers, you need to pass the JWT token in `loginParams` as well.

:::tip

Additionally you can associate a function to be triggered on successful MFA Enabled.

```cs
void Start()
{
    web3Auth = GetComponent<Web3Auth>();
    web3Auth.setOptions(new Web3AuthOptions()
    {

    });
    // focus-next-line
    web3Auth.onMFASetup += onMFASetup;
}
//focus-start
private void onMFASetup(bool response)
{
    // Functions to be called after MFA setup
}
//focus-end
```

:::

## Usage

<Tabs
  defaultValue="default-verifier"
  values={[
    { label: "Default Verifier", value: "default-verifier" },
    { label: "Custom JWT Verifier", value: "custom-jwt-verifier" },
  ]}
>

<TabItem value="default-verifier">

```cs
{
    var selectedProvider = Provider.GOOGLE;

    var options = new LoginParams()
    {
        loginProvider = selectedProvider,
    };

    web3Auth.enableMFA(options);
}
```

</TabItem>

<TabItem value="custom-jwt-verifier">

```cs
{
    var selectedProvider = Provider.JWT;

    var options = new LoginParams()
    {
        loginProvider = selectedProvider,
        extraLoginOptions = new ExtraLoginOptions()
        {
            domain = "https://web3auth.au.auth0.com",
            verifierIdField = "sub",
            prompt = Prompt.LOGIN,
        }
    };

    web3Auth.enableMFA(options);
}

```

</TabItem>
</Tabs>

---

## Get Ed25519 private key

To retrieve the Ed25519 private key of the user, you can access it from the login response. This private key can be used to sign transactions on Solana, Near, Algorand, and other chains that use the ed25519 curve.

## Usage

```cs
private void onLogin(Web3AuthResponse response)
{
    var ed25519PrivKey = response.ed25519PrivKey;
    Debug.Log("Ed25519 Private Key: " + ed25519PrivKey);

    // Use Ed25519 private key for Solana, Near, Algorand transactions
}
```

---

## Get Secp256k1 private key

To retrieve the secp256k1 private key of the user, you can access it from the login response. The method returns an EVM compatible private key which can be used to sign transactions on EVM compatible chains.

## Usage

```cs
private void onLogin(Web3AuthResponse response)
{
    var privateKey = response.privKey;
    Debug.Log("Secp256k1 Private Key: " + privateKey);

    // Use private key for EVM transactions
}
```

---

## Get user info(3)

You can use the `getUserInfo` method to retrieve various details about the user, such as their login type, whether multi-factor authentication (MFA) is enabled, profile image, name, and other relevant information.

## Usage

```cs
private void onLogin(Web3AuthResponse response)
{
    var userInfo = response.userInfo;
    Debug.Log("User Info: " + JsonUtility.ToJson(userInfo));
}
```

## UserInfo response

```json
{
  "aggregateVerifier": "w3a-google",
  "email": "john@gmail.com",
  "name": "John Dash",
  "profileImage": "https://lh3.googleusercontent.com/a/Ajjjsdsmdjmnm...",
  "typeOfLogin": "google",
  "verifier": "torus",
  "verifierId": "john@gmail.com",
  "dappShare": "<24 words seed phrase>", // will be sent only incase of custom verifiers
  "idToken": "<jwtToken issued by Web3Auth>",
  "oAuthIdToken": "<jwtToken issued by OAuth Provider>", // will be sent only incase of custom verifiers
  "oAuthAccessToken": "<accessToken issued by OAuth Provider>", // will be sent only incase of custom verifiers
  "isMfaEnabled": true // returns true if user has enabled mfa
}
```

---

## Launch Wallet Services

The `launchWalletServices` method launches a WebView which allows you to use the templated wallet UI services. The method takes `ChainConfig` as the required input. Wallet Services is currently only available for EVM chains.

:::note

Access to Wallet Services is gated. You can use this feature in `sapphire_devnet` for free. The minimum [pricing plan](https://web3auth.io/pricing.html) to use this feature in a production environment is the **Scale Plan**.

:::

## Parameters

`ChainConfig`

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Class", value: "class" },
  ]}
>

<TabItem value="table">

| Parameter           | Description                                                                                                                 |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `chainNamespace`    | Custom configuration for your preferred blockchain. As of now only EVM supported. Default value is `ChainNamespace.eip155`. |
| `decimals?`         | Number of decimals for the currency ticker. Default value is 18, and accepts `int` as value.                                |
| `blockExplorerUrl?` | Blockchain's explorer URL. (for example, `https://etherscan.io`)                                                            |
| `chainId`           | The chain ID of the selected blockchain in hex `String`.                                                                    |
| `displayName?`      | Display Name for the chain.                                                                                                 |
| `logo?`             | Logo for the selected `chainNamespace` and `chainId`.                                                                       |
| `rpcTarget`         | RPC Target URL for the selected `chainNamespace` & `chainId`.                                                               |
| `ticker?`           | Default currency ticker of the network (for example, `ETH`)                                                                 |
| `tickerName?`       | Name for currency ticker (for example, `Ethereum`)                                                                          |

</TabItem>

<TabItem value="class">

```cs
using System.Collections.Generic;
#nullable enable
public class ChainConfig {
    public Web3Auth.ChainNamespace? chainNamespace { get; set; } = Web3Auth.ChainNamespace.EIP155;
    public int decimals { get; set; } = 18;
    public string blockExplorerUrl { get; set; } = null;
    public string chainId { get; set; }
    public string displayName { get; set; } = null;
    public string logo { get; set; } = null;
    public string rpcTarget { get; set; }
    public string ticker { get; set; } = null;
    public string tickerName { get; set; } = null;
}
```

</TabItem>
</Tabs>

## Usage

```cs
{
    var chainConfig = new ChainConfig()
    {
        chainId = "0x1",
        rpcTarget = rpcURL,
        ticker = "ETH",
        chainNamespace = Web3Auth.ChainNamespace.EIP155
    };
    web3Auth.launchWalletServices(chainConfig);
}
```

---

## Login user

This function helps your users to trigger the login process. The login flow is triggered based on the selected Provider.

:::tip

Additionally, you can associate a function to be triggered on successful login. This function receives the user's profile as a parameter.

```cs
void Start()
{
    web3Auth = GetComponent<Web3Auth>();
    web3Auth.setOptions(new Web3AuthOptions()
    {

    });
    // focus-next-line
    web3Auth.onLogin += onLogin;
}
//focus-start
private void onLogin(Web3AuthResponse response)
{
    // Functions to be called after logging in your user
}
//focus-end
```

:::

## Arguments

`web3Auth.login()` requires `LoginParams` as a required input.

### `LoginParams`

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Interface", value: "interface" },
  ]}
>

<TabItem value="table">

| Parameter            | Description                                                                                                                                                                                                                                                                                              |
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `loginProvider`      | Sets the OAuth login method to be used. You can use any of the supported values are `GOOGLE`, `FACEBOOK`, `REDDIT`, `DISCORD`, `TWITCH`, `APPLE`, `LINE`, `GITHUB`, `KAKAO`, `LINKEDIN`, `TWITTER`, `WEIBO`, `WECHAT`, `EMAIL_PASSWORDLESS`.                                                             |
| `extraLoginOptions?` | It can be used to set the OAuth login options for corresponding `loginProvider`. For instance, you'll need to pass the user's email address as. The Default value for the field is `null`, and it accepts `ExtraLoginOptions` as a value.                                                                |
| `redirectUrl?`       | URL where user will be redirected after successful login. By default user will be redirected to same page where login will be initiated. Default value for the field is `null`, and accepts `URI` as a value.                                                                                            |
| `appState?`          | It can be used to keep track of the app state when user will be redirected to app after login. Default is `null`, and accepts `string` as a value.                                                                                                                                                       |
| `mfaLevel?`          | Customize the MFA screen shown to the user during OAuth authentication. Default value for field is `MFALevel.DEFAULT`, which shows MFA screen every 3rd login. It accepts `MFALevel` as a value.                                                                                                         |
| `dappShare?`         | Custom verifier logins can get a dapp share returned to them after a successful login. This is useful if the dapps want to use this share to allow users to sign in without repeating the full flow. It accepts `string` as a value.                                                                     |
| `curve?`             | It is used to determine the public key encoded in the JWT token which returned in `getUserInfo` function after user login. This parameter won't change the format of private key returned by Web3Auth. Private key returned by `getPrivKey` is always secp256k1. The default value is `Curve.SECP256K1`. |
| `sessionTime?`       | Allows developers to configure the session management time. Session Time is in seconds, and takes an `int` as a value.                                                                                                                                                                                   |

</TabItem>

<TabItem value="interface">

```cs
public class LoginParams
{
    public Provider loginProvider { get; set; }
    public string dappShare { get; set; }
    public ExtraLoginOptions extraLoginOptions { get; set; }
    public Uri redirectUrl { get; set; }
    public string appState { get; set; }
    public MFALevel mfaLevel { get; set; }
    public int sessionTime { get; set; }
    public Curve curve { get; set; }
}
```

</TabItem>

</Tabs>

### `Provider`

```cs
public enum Provider
{
    [EnumMember(Value = "google")]
    GOOGLE,
    [EnumMember(Value = "facebook")]
    FACEBOOK,
    [EnumMember(Value = "reddit")]
    REDDIT,
    [EnumMember(Value = "discord")]
    DISCORD,
    [EnumMember(Value = "twitch")]
    TWITCH,
    [EnumMember(Value = "apple")]
    APPLE,
    [EnumMember(Value = "line")]
    LINE,
    [EnumMember(Value = "github")]
    GITHUB,
    [EnumMember(Value = "kakao")]
    KAKAO,
    [EnumMember(Value = "linkedin")]
    LINKEDIN,
    [EnumMember(Value = "twitter")]
    TWITTER,
    [EnumMember(Value = "weibo")]
    WEIBO,
    [EnumMember(Value = "wechat")]
    WECHAT,
    [EnumMember(Value = "email_passwordless")]
    EMAIL_PASSWORDLESS,
    [EnumMember(Value = "email_password")]
    EMAIL_PASSWORD,
    [EnumMember(Value = "jwt")]
    JWT,
    [EnumMember(Value = "CUSTOM_VERIFIER")]
    CUSTOM_VERIFIER
}
```

### `ExtraLoginOptions`

The `LoginParams` class accepts the `ExtraLoginOptions` as an optional input, containing advanced options for custom authentication, email passwordless login, among others. This parameter can be considered as advanced login options needed for specific cases.

```cs
LoginParams() { selectedLoginProvider, extraLoginOptions = ExtraLoginOptions() }
```

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Interface", value: "interface" },
  ]}
>

<TabItem value="table">

| Parameter                    | Description                                                                                                                                                                                                                      |
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `additionalParams?`          | Additional params in `Dictionary<string, string>` format for OAuth login, use id_token (JWT) to authenticate with Embedded Wallets.                                                                                              |
| `domain?`                    | Your custom authentication domain in `string` format. For example, if you are using Auth0, this could be example.au.auth0.com.                                                                                                   |
| `client_id?`                 | Client ID in `string` format, provided by your login provider used for custom verifier.                                                                                                                                          |
| `leeway?`                    | The value used to account for clock skew in JWT expirations. The value is in the seconds, and ideally should be no more than 60 seconds, with a maximum of 120 seconds. String value.                                            |
| `verifierIdField?`           | The field in the JWT token that maps to verifier ID. Please make sure you have selected the correct JWT verifier ID in the Developer Dashboard. String value.                                                                    |
| `isVerifierIdCaseSensitive?` | Boolean to confirm whether the verifier ID field is case sensitive or not.                                                                                                                                                       |
| `display?`                   | Allows developers to configure the display of UI. It takes `Display` as a value.                                                                                                                                                 |
| `prompt?`                    | Prompt shown to the user during the authentication process. It takes `Prompt` as a value.                                                                                                                                        |
| `max_age?`                   | Maximum time allowed without reauthentication. If the last time the user authenticated is greater than this value, then the user must reauthenticate. String value.                                                              |
| `ui_locales?`                | The space separated list of language tags, ordered by preference. For example `fr-CA fr en`.                                                                                                                                     |
| `id_token_hint?`             | It specify the previously issued ID token. String value.                                                                                                                                                                         |
| `id_token?`                  | JWT (ID token) to be passed for login.                                                                                                                                                                                           |
| `login_hint?`                | It is used to send the user's email address during email passwordless login. String value.                                                                                                                                       |
| `acr_values?`                | acr_values                                                                                                                                                                                                                       |
| `scope?`                     | The default scope to be used on authentication requests. The default scope defined in the Auth0Client is included along with this scope. String value.                                                                           |
| `audience?`                  | The audience, presented as the aud claim in the access token, defines the intended consumer of the token. String value.                                                                                                          |
| `connection?`                | The name of the connection configured for your application. If null, it will redirect to the Auth0 Login Page and show the Login Widget. String value.                                                                           |
| `state?`                     | State                                                                                                                                                                                                                            |
| `response_type?`             | Defines which grant to be execute for the authorization server. String value.                                                                                                                                                    |
| `nonce?`                     | Nonce value                                                                                                                                                                                                                      |
| `redirect_uri?`              | It can be used to specify the default URL, where your custom JWT verifier can redirect your browser to with the result. If you are using Auth0, it must be allowlisted in the Allowed Callback URLs in your Auth0's application. |

</TabItem>

<TabItem value="interface">

```cs
public class ExtraLoginOptions {
    public Dictionary<string, string> additionalParams { get; set; }
    public string domain { get; set; }
    public string client_id { get; set; }
    public string leeway { get; set; }
    public string verifierIdField { get; set; }
    public bool isVerifierIdCaseSensitive { get; set; }
    public Display display { get; set; }
    public Prompt prompt { get; set; }
    public string max_age { get; set; }
    public string ui_locales { get; set; }
    public string id_token_hint { get; set; }
    public string login_hint { get; set; }
    public string id_token { get; set; }
    public string acr_values { get; set; }
    public string scope { get; set; }
    public string audience { get; set; }
    public string connection { get; set; }
    public string state { get; set; }
    public string response_type { get; set; }
    public string nonce { get; set; }
    public string redirect_uri { get; set; }
}
```

</TabItem>

</Tabs>

### `Curve`

The `LoginParams` class accepts a `curve` parameter. This parameter can be used to select the elliptic curve to use for the signature.

```cs
LoginParams() { selectedLoginProvider, curve = Curve.SECP256K1 }
```

<Tabs
  defaultValue="secp256k1"
  values={[
    { label: "SECP256K1", value: "secp256k1" },
    { label: "ED25519", value: "ed25519" },
  ]}
>

<TabItem value="secp256k1">

```cs
public void login()
{
    var selectedProvider = Provider.GOOGLE;
    var options = new LoginParams()
    {
        loginProvider = selectedProvider,
        //focus-next-line
        curve = Curve.SECP256K1
    };
    web3Auth.login(options);
}
```

</TabItem>

<TabItem value="ed25519">

```cs
public void login()
{
    var selectedProvider = Provider.GOOGLE;
    var options = new LoginParams()
    {
        loginProvider = selectedProvider,
        //focus-next-line
        curve = Curve.ED25519
    };
    web3Auth.login(options);
}
```

</TabItem>

</Tabs>

## Sample response

```json
{
  "ed25519PrivKey": "666523652352635....",
  "privKey": "0ajjsdsd....",
  "coreKitKey": "0ajjsdsd....",
  "coreKitEd25519PrivKey": "666523652352635....",
  "sessionId": "....",
  "error": "....",
  "userInfo": {
    "aggregateVerifier": "w3a-google",
    "email": "john@gmail.com",
    "name": "John Dash",
    "profileImage": "https://lh3.googleusercontent.com/a/Ajjjsdsmdjmnm...",
    "typeOfLogin": "google",
    "verifier": "torus",
    "verifierId": "john@gmail.com",
    "dappShare": "<24 words seed phrase>", // will be sent only incase of custom verifiers
    "idToken": "<jwtToken issued by Web3Auth>",
    "oAuthIdToken": "<jwtToken issued by OAuth Provider>", // will be sent only incase of custom verifiers
    "oAuthAccessToken": "<accessToken issued by OAuth Provider>", // will be sent only incase of custom verifiers
    "isMfaEnabled": true // returns true if user has enabled mfa
  }
}
```

## Examples

<Tabs
  defaultValue="google"
  values={[
    { label: "Google", value: "google" },
    { label: "Facebook", value: "facebook" },
    { label: "Discord", value: "discord" },
    { label: "Twitch", value: "twitch" },
    { label: "Email Passwordless", value: "email_passwordless" },
    { label: "JWT", value: "jwt" },
  ]}
>

<TabItem value="google">

```cs
public void login()
{
    var selectedProvider = Provider.GOOGLE;
    var options = new LoginParams()
    {
        loginProvider = selectedProvider
    };
    web3Auth.login(options);
}
```

</TabItem>

<TabItem value="facebook">

```cs
public void login()
{
    var selectedProvider = Provider.FACEBOOK;
    var options = new LoginParams()
    {
        loginProvider = selectedProvider
    };
    web3Auth.login(options);
}
```

</TabItem>

<TabItem value="discord">

```cs
public void login()
{
    var selectedProvider = Provider.DISCORD;
    var options = new LoginParams()
    {
        loginProvider = selectedProvider
    };
    web3Auth.login(options);
}
```

</TabItem>

<TabItem value="twitch">

```cs
public void login()
{
    var selectedProvider = Provider.TWITCH;
    var options = new LoginParams()
    {
        loginProvider = selectedProvider
    };
    web3Auth.login(options);
}
```

</TabItem>

<TabItem value="email_passwordless">

```cs
public void login()
{
    var selectedProvider = Provider.EMAIL_PASSWORDLESS;
    var options = new LoginParams()
    {
        loginProvider = selectedProvider,
        extraLoginOptions = new ExtraLoginOptions()
        {
            login_hint = "hello@web3auth.io"
        }
    };
    web3Auth.login(options);
}
```

</TabItem>

<TabItem value="jwt">

```cs
public void login()
{
    var selectedProvider = Provider.JWT;
    var options = new LoginParams()
    {
        loginProvider = selectedProvider,
        extraLoginOptions = new ExtraLoginOptions()
        {
            id_token = "your_jwt_token"
        }
    };
    web3Auth.login(options);
}
```

</TabItem>

</Tabs>

---

## Logout user(Usage)

Trigger logout flow. This function doesn't take parameters. A completable future containing a void object will be returned on successfull logout otherwise an error response is returned.

:::tip

Additionally you can associate a function to be triggered on successful logout.

```cs
void Start()
{
    web3Auth = GetComponent<Web3Auth>();
    web3Auth.setOptions(new Web3AuthOptions()
    {

    });
    // focus-next-line
    web3Auth.onLogout += onLogout;
}
//focus-start
private void onLogout()
{
    // Functions to be called after user logs out
}
//focus-end
```

:::

## Usage

```cs
public void logout()
{
    web3Auth.logout();
    Debug.Log("Logged out!");
}
```

---

## Request signature(4)

The `request` method facilitates the use of templated transaction screens for signing transactions.

Please check the list of [JSON RPC methods](https://docs.metamask.io/wallet/reference/json-rpc-api/), noting that the request method currently supports only the signing methods.

## Parameters

| Arguments       | Description                                                                                                                                                                                            |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `chainConfig`   | Defines the chain to be used for signature.                                                                                                                                                            |
| `method`        | JSON RPC method name in `String`. Currently, the request method only supports the singing methods.                                                                                                     |
| `requestParams` | Parameters for the corresponding method. The parameters should be in the list and correct sequence. Take a look at [RPC methods](https://docs.metamask.io/wallet/reference/json-rpc-api) to know more. |

:::tip

Additionally you can associate a `getSignResponse` function to retrieve the signature for the request.

```cs
void Start()
{
    web3Auth = GetComponent<Web3Auth>();
    web3Auth.setOptions(new Web3AuthOptions()
    {

    });
    // focus-next-line
    web3Auth.onSignResponse += onSignResponse;
}
//focus-start
private void onSignResponse(SignResponse signResponse)
{
    // Functions to be called after receiving sign response
}
//focus-end
```

:::

## Usage

```cs
 public void PopupSignMessageUI() {
    var chainConfig = new ChainConfig()
    {
        chainId = "0xaa36a7",
        rpcTarget = "https://ethereum-sepolia.publicnode.com",
        ticker = "ETH",
        chainNamespace = Web3Auth.ChainNamespace.EIP155
    };

    JArray paramsArray = new JArray
    {
            "Hello World",
            account.Address,
            "Android"
    };

    web3Auth.request(chainConfig, "personal_sign", paramsArray);
}

private void onSignResponse(SignResponse signResponse)

{
    Debug.Log("Retrieved SignResponse: " + signResponse);
    updateConsole("Retrieved SignResponse: " + signResponse);
}

```

---

## Embedded Wallets SDK for Unreal Engine

## Overview

MetaMask Embedded Wallets SDK (formerly Web3Auth Plug and Play) provides authentication for Unreal Engine game applications with social logins, external wallets, and more. Our Unreal SDK, written in C++, simplifies how you connect users to their preferred wallets and manage authentication state across all mobile platforms.

## Requirements

- Unreal Engine `v5.3.1` with Xcode 15
- [Epic Game Launcher](https://www.unrealengine.com/en-US/download) to download Unreal library
- Basic knowledge of C++ and Unreal Engine Development

## Prerequisites

- Set up your project on the [Embedded Wallets dashboard](https://developer.metamask.io/)

:::tip

See the [dashboard setup](../../dashboard/README.mdx) guide to learn more.

:::

## Installation

Install the Web3Auth Unreal Engine SDK using one of the following methods:

### Git clone installation

Follow these instructions to install the `web3auth-unreal-sdk` plugin:

1. Close your existing Unreal Engine app.
2. Create a directory in your app root called Plugins.
3. Clone with:

```bash
git clone https://github.com/Web3Auth/web3auth-unreal-sdk/tree/main/Plugins/Web3AuthSDK ./Plugins/Web3AuthSDK
```

4. Open UE5 Editor, navigator to `Menu` → `Edit` → `Plugins`, check the option to enable Web3AuthSDK.
5. Start your app and it will ask to compile the plugin. Proceed with that.

### Manual installation

Download the [Unreal Package](https://github.com/Web3Auth/web3auth-unreal-sdk/releases) from our latest release and import the package file into your existing Unreal Engine project.

### 1. Configure Embedded Wallets project

1.1 Go to the [Embedded Wallets dashboard](https://developer.metamask.io/), create or select an Web3Auth project:
1.2 Add `{{SCHEMA}}://{YOUR_APP_PACKAGE_NAME}` to **Allowlist URLs**.
1.3 Copy the `Client ID` for usage later.

### 2. Configure deep link for Android

To setup the Android SDK and NDK for Unreal's editor, [see the Unreal documentation](https://docs.unrealengine.com/5.0/en-US/how-to-set-up-android-sdk-and-ndk-for-your-unreal-engine-development-environment).

- To add redirect URI into your Android app, open the `<Project-path>/Plugins/Web3AuthSDK/Source/Web3AuthSDK_Android.xml` file.
- Find the `<androidManifestUpdates>` tag and inside that, will be a `<data>` tag element. Replace the existing redirect URI with one that you have registered on your Embedded Wallets dashboard.

### 3. Configure deep link for iOS

Configure your iOS deep link settings in the appropriate configuration files. Make sure the redirect URI matches what you have registered in your Embedded Wallets dashboard.

## Initialize Web3Auth

### 1. Initialize Embedded Wallets instance

Initialize the Web3Auth SDK in your Unreal project:

```cpp
#include "Web3AuthSDK.h"

void AYourGameMode::BeginPlay()
{
    Super::BeginPlay();

    // Initialize Web3Auth
    FWeb3AuthOptions Options;
    Options.ClientId = TEXT("YOUR_CLIENT_ID"); // Get your Client ID from MetaMask Developer Dashboard
    Options.Network = TEXT("sapphire_mainnet"); // or "sapphire_devnet"
    Options.RedirectUrl = TEXT("YOUR_SCHEMA://YOUR_APP_PACKAGE_NAME");

    UWeb3AuthSDK::GetInstance()->Initialize(Options);
}
```

### 2. Setup authentication callbacks

Set up callbacks to handle authentication responses:

```cpp
void AYourGameMode::SetupWeb3AuthCallbacks()
{
    // Bind login success callback
    UWeb3AuthSDK::GetInstance()->OnLoginSuccess.AddDynamic(this, &AYourGameMode::OnWeb3AuthLoginSuccess);

    // Bind login error callback
    UWeb3AuthSDK::GetInstance()->OnLoginError.AddDynamic(this, &AYourGameMode::OnWeb3AuthLoginError);

    // Bind logout callback
    UWeb3AuthSDK::GetInstance()->OnLogout.AddDynamic(this, &AYourGameMode::OnWeb3AuthLogout);
}

UFUNCTION()
void AYourGameMode::OnWeb3AuthLoginSuccess(const FString& PrivateKey, const FString& PublicAddress)
{
    UE_LOG(LogTemp, Warning, TEXT("Web3Auth Login Success - Private Key: %s"), *PrivateKey);
}

UFUNCTION()
void AYourGameMode::OnWeb3AuthLoginError(const FString& Error)
{
    UE_LOG(LogTemp, Error, TEXT("Web3Auth Login Error: %s"), *Error);
}

UFUNCTION()
void AYourGameMode::OnWeb3AuthLogout()
{
    UE_LOG(LogTemp, Warning, TEXT("Web3Auth Logout Success"));
}
```

## Advanced configuration

The Embedded Wallets Unreal SDK offers a rich set of advanced configuration options:

- **[Custom authentication](./advanced/custom-authentication.mdx):** Define authentication methods.
- **[Whitelabeling and UI customization](./advanced/whitelabel.mdx):** Personalize the modal's appearance.
- **[Multi-Factor Authentication (MFA)](./advanced/mfa.mdx):** Set up and manage MFA.

:::tip

See the [advanced configuration sections](./advanced/) to learn more about each configuration option.

:::

<Tabs
  defaultValue="basic-config"
  values={[
    { label: "Basic Configuration", value: "basic-config" },
    { label: "Advanced Configuration", value: "advanced-config" },
  ]}
>

<TabItem value="basic-config">

```cpp
FWeb3AuthOptions Options;
Options.ClientId = TEXT("YOUR_CLIENT_ID");
Options.Network = TEXT("sapphire_mainnet"); // or "sapphire_devnet"
Options.RedirectUrl = TEXT("YOUR_SCHEMA://YOUR_APP_PACKAGE_NAME");

UWeb3AuthSDK::GetInstance()->Initialize(Options);
```

</TabItem>

<TabItem value="advanced-config">

```cpp
FWeb3AuthOptions Options;
Options.ClientId = TEXT("YOUR_CLIENT_ID");
Options.Network = TEXT("sapphire_mainnet");
Options.RedirectUrl = TEXT("YOUR_SCHEMA://YOUR_APP_PACKAGE_NAME");

// Set up whitelabel options
FWeb3AuthWhiteLabelOptions WhiteLabelOptions;
WhiteLabelOptions.AppName = TEXT("Your App Name");
WhiteLabelOptions.LogoLight = TEXT("https://your-logo-light.png");
WhiteLabelOptions.LogoDark = TEXT("https://your-logo-dark.png");
WhiteLabelOptions.DefaultLanguage = TEXT("en");
WhiteLabelOptions.Mode = TEXT("auto");

Options.WhiteLabelOptions = WhiteLabelOptions;

UWeb3AuthSDK::GetInstance()->Initialize(Options);
```

</TabItem>

</Tabs>

## Blockchain integration

Web3Auth is blockchain agnostic, enabling integration with any blockchain network. Out of the box, Web3Auth offers robust support for both **Solana** and **Ethereum**.

### Ethereum integration

For Ethereum integration, you can get the private key and use it with Ethereum libraries:

```cpp
UFUNCTION()
void AYourGameMode::OnWeb3AuthLoginSuccess(const FString& PrivateKey, const FString& PublicAddress)
{
    // Use private key for Ethereum transactions
    UE_LOG(LogTemp, Warning, TEXT("Ethereum Private Key: %s"), *PrivateKey);
    UE_LOG(LogTemp, Warning, TEXT("Ethereum Address: %s"), *PublicAddress);
}
```

### Solana integration

For Solana integration, you can get the Ed25519 private key:

```cpp
UFUNCTION()
void AYourGameMode::OnWeb3AuthLoginSuccess(const FString& PrivateKey, const FString& PublicAddress)
{
    // Get Ed25519 private key for Solana
    FString Ed25519PrivKey = UWeb3AuthSDK::GetInstance()->GetEd25519PrivKey();
    UE_LOG(LogTemp, Warning, TEXT("Solana Ed25519 Private Key: %s"), *Ed25519PrivKey);
}
```

---

## Advanced configuration(8)

The Embedded Wallets SDK provides extensive configuration options that allow you to customize authentication flows, UI appearance, blockchain integrations, and security features to meet your Unreal application's specific requirements.

## Configuration structure

When setting up Web3Auth, you'll pass in the options to the constructor. This consists of:

```cpp
#include "Web3AuthSDK.h"

// focus-start
FWeb3AuthOptions Options;
Options.ClientId = TEXT("YOUR_CLIENT_ID"); // Get your Client ID from the MetaMask Developer Dashboard
Options.Network = TEXT("sapphire_mainnet"); // or "sapphire_devnet"
Options.RedirectUrl = TEXT("YOUR_SCHEMA://YOUR_APP_PACKAGE_NAME");

UWeb3AuthSDK::GetInstance()->Initialize(Options);
// focus-end
```

### `FWeb3AuthOptions`

The Web3Auth Constructor takes an object with `FWeb3AuthOptions` as input.

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Struct", value: "struct" },
  ]}
>

<TabItem value="table">

| Parameter            | Description                                                                                                                                     |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `ClientId`           | Your Web3Auth Client ID from the [Dashboard](https://developer.metamask.io/). It's a mandatory field of type `FString`.                         |
| `Network`            | Web3Auth Network: `"sapphire_mainnet"`, `"sapphire_devnet"`, `"mainnet"`, `"cyan"`, `"aqua"` or `"testnet"`. Mandatory field of type `FString`. |
| `RedirectUrl`        | URL that Web3Auth will redirect API responses upon successful authentication. It's a mandatory field of type `FString`.                         |
| `WhiteLabelOptions?` | Whitelabel options for custom UI, branding, and translations. Takes `FWeb3AuthWhiteLabelOptions` as a value.                                    |
| `SessionTime?`       | Configure session management time in seconds. Default is 86400 seconds (1 day). Max 30 days.                                                    |

</TabItem>

<TabItem value="struct">

```cpp
USTRUCT(BlueprintType)
struct FWeb3AuthOptions
{
    GENERATED_BODY()

    UPROPERTY(EditAnywhere, BlueprintReadWrite)
    FString ClientId;

    UPROPERTY(EditAnywhere, BlueprintReadWrite)
    FString Network;

    UPROPERTY(EditAnywhere, BlueprintReadWrite)
    FString RedirectUrl;

    UPROPERTY(EditAnywhere, BlueprintReadWrite)
    FWeb3AuthWhiteLabelOptions WhiteLabelOptions;

    UPROPERTY(EditAnywhere, BlueprintReadWrite)
    int32 SessionTime = 86400;
};
```

</TabItem>
</Tabs>

## Session management

Control how long users stay authenticated and how sessions persist in Unreal Engine.

**Key Configuration Options:**

- `SessionTime` - Session duration in seconds. Controls how long users remain authenticated before needing to log in again.
  - Minimum: 1 second (`1`).
  - Maximum: 30 days (`86400 * 30`).
  - Default: 1 day (`86400`).

```cpp
FWeb3AuthOptions Options;
Options.ClientId = TEXT("YOUR_CLIENT_ID");
Options.Network = TEXT("sapphire_mainnet");
Options.SessionTime = 86400 * 7; // 7 days (in seconds)
Options.RedirectUrl = TEXT("YOUR_SCHEMA://YOUR_APP_PACKAGE_NAME");

UWeb3AuthSDK::GetInstance()->Initialize(Options);
```

## Custom authentication methods

Control the login options presented to your users. For detailed configuration options and implementation examples, see the [custom authentication](./custom-authentication.mdx) section.

## UI customization

Customize the brand experience by customizing the Web3Auth Login Screens to match your Unreal application's design. For complete customization options, refer to the [whitelabeling and UI customization](./whitelabel.mdx) section.

## Multi-Factor Authentication (MFA)

Add additional security layers to protect user accounts with two-factor authentication. For detailed configuration options and implementation examples, see the [Multi-Factor Authentication](./mfa.mdx) section.

**Key Configuration Options:**

- `MfaSettings` - Configure MFA settings for different authentication flows
- `MfaLevel` - Control when users are prompted to set up MFA

---

## Using custom authentication in PnP Unreal Engine SDK

Custom authentication is a way to authenticate users with your custom authentication service. For example, while authenticating with Google, you can use your own Google Client ID to authenticate users directly.

This feature, with MFA turned off, can make Embedded Wallets invisible to the end user.

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this
SDK in a production environment is the **Growth Plan**. You can use this feature in Web3Auth
Sapphire Devnet network for free.

:::

## Getting an Auth Connection ID

:::info prerequisite

To enable this, you need to [create a connection](/embedded-wallets/dashboard/authentication) from the **Authentication** tab of your project from the [Embedded Wallets developer dashboard](https://developer.metamask.io) with your desired configuration.

:::

To configure a connection, you need to provide the particular details of the connection into our Embedded Wallets dashboard. This enables us to map a `authConnectionId with your connection details. This `authConnectionId helps us to identify the connection details while initializing the SDK. You can configure multiple connections for the same project, and you can also update the connection details anytime.

:::tip

Learn more about the [auth provider setup](/embedded-wallets/authentication) and the different configurations available for each connection.

:::

## Configuration

:::warning

**"Auth Connection"** is called **"Verifier"** in the Android SDK. It is the older terminology which we will be updating in the upcoming releases.

Consequentially, you will see the terms **"Verifier ID"** and **"Aggregate Verifier"** used in the codebase and documentation referring to **"Auth Connection ID"** and **"Grouped Auth Connection"** respectively.

:::

To use custom authentication (using supported Social providers or Login providers like Auth0, AWS Cognito, Firebase, or your own custom JWT login), you can add the configuration using `loginConfig` parameter during the initialization.

The `loginConfig` field is a key value map. The key should be one of the `Web3AuthProvider` in its string form, and the value should be a `LoginConfigItem` struct instance.

## Arguments

### `LoginConfigItem`

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Interface", value: "interface" },
  ]}
>

<TabItem value="table">

| Parameter                | Description                                                                                                                                                                                                                                                                                                                        |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `verifier`               | The name of the verifier that you have registered on the Embedded Wallets dashboard. It's a mandatory field, and accepts `FString` as a value.                                                                                                                                                                                     |
| `typeOfLogin`            | Type of login of this verifier, this value will affect the login flow that is adapted. For example, if you choose `google`, a Google sign-in flow will be used. If you choose `jwt`, you should be providing your own JWT token, no sign-in flow will be presented. It's a mandatory field, and accepts `FTypeOfLogin` as a value. |
| `clientId`               | Client ID provided by your login provider used for custom verifier. for example, Google's Client ID or Web3Auth's client ID if using JWT as `TypeOfLogin`. It's a mandatory field, and accepts `FString` as a value.                                                                                                               |
| `name?`                  | Display name for the verifier. If null, the default name is used. It accepts `FString` as a value.                                                                                                                                                                                                                                 |
| `description?`           | Description for the button. If provided, it renders as a full length button. else, icon button. It accepts `FString` as a value.                                                                                                                                                                                                   |
| `verifierSubIdentifier?` | The field in JWT token which maps to verifier ID. Please make sure you selected correct JWT verifier ID in the developer dashboard. It accepts `FString` as a value.                                                                                                                                                               |
| `logoHover?`             | Logo to be shown on mouse hover. It accepts `FString` as a value.                                                                                                                                                                                                                                                                  |
| `logoLight?`             | Light logo for dark background. It accepts `FString` as a value.                                                                                                                                                                                                                                                                   |
| `logoDark?`              | Dark logo for light background. It accepts `FString` as a value.                                                                                                                                                                                                                                                                   |
| `mainOption?`            | Show login button on the main list. Boolean value; default is `false`.                                                                                                                                                                                                                                                             |
| `showOnModal?`           | Whether to show the login button on modal or not. Default value is `true`.                                                                                                                                                                                                                                                         |
| `showOnDesktop?`         | Whether to show the login button on desktop. Default value is `true`.                                                                                                                                                                                                                                                              |
| `showOnMobile?`          | Whether to show the login button on mobile. Default value is `true`.                                                                                                                                                                                                                                                               |

</TabItem>

<TabItem value="interface">

```cs
USTRUCT(BlueprintType)
struct FLoginConfigItem
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		FString verifier;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		FString typeOfLogin;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		FString name;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		FString description;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		FString clientId;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		FString verifierSubIdentifier;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		FString logoHover;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		FString logoLight;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		FString logoDark;
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		bool mainOption;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		bool showOnModal;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		bool showOnDesktop;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		bool showOnMobile;

	FLoginConfigItem() {};

	bool operator== (const FLoginConfigItem& other) {
		return other.clientId == clientId;
	}

};
```

</TabItem>

</Tabs>

### `TypeOfLogin`

```c
UENUM(BlueprintType)
enum class FTypeOfLogin : uint8
{
	GOOGLE,
	FACEBOOK,
	REDDIT,
	DISCORD,
	TWITCH,
	APPLE,
	LINE,
	GITHUB,
	KAKAO,
	LINKEDIN,
	TWITTER,
	WEIBO,
	WECHAT,
	EMAIL_PASSWORDLESS,
	EMAIL_PASSWORD,
	JWT
};
```

## Usage

<Tabs
  defaultValue="google"
  values={[
    { label: "Google", value: "google" },
    { label: "Facebook", value: "facebook" },
    { label: "Email Passwordless", value: "email_passwordless" },
    { label: "Auth0", value: "auth0" },
  ]}
>

<TabItem value="google">

</TabItem>

<TabItem value="facebook">

</TabItem>

<TabItem value="email_passwordless">

</TabItem>

<TabItem value="auth0">

</TabItem>

</Tabs>

:::note

- dapp share is only returned for the custom authentication verifiers.
- 2FA should be enabled for the account using it.

  Use `mfaLevel = MFALevel.MANDATORY` in the `LoginParams` during login. See **[MFA](../mfa)** for more details.

:::

---

## Multi-factor authentication in PnP Unreal Engine SDK

The Multi Factor Authentication feature refers to the ability of the user to create a backup share (recovery phrase). This helps them login into a new device and also to recover their account if they lose their original device.

You can set the mfaLevel within the `loginParams` to customize when mfa screen should be shown to user. It currently accepts 4 values:

- **`default`** - Setting the mfaLevel to default will present the MFA screen to user on every third login. `mfaLevel = MFALevel.DEFAULT`
- **`optional`** - Setting mfaLevel to optional will present the MFA screen to user on every login but user will have the option to skip it. `mfaLevel = MFALevel.OPTIONAL`
- **`mandatory`** - Setting mfaLevel to mandatory will make it mandatory for user to setup MFA after login. `mfaLevel = MFALevel.MANDATORY`
- **`none`** - Setting mfaLevel to none will skip the mfa setup screen totally. `mfaLevel = MFALevel.NONE`

:::caution Note

If you are using default verifiers, your users may have set up MFA on other dapps that also use default Web3Auth verifiers. In this case, the MFA screen will continue to appear if the user has enabled MFA on other dapps. This is because MFA cannot be turned off once it is enabled.

:::

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this SDK in a production environment is the **Scale Plan**. You can use this feature in Web3Auth Sapphire Devnet network for free.

:::

## `MFALevel`

```c
UENUM(BlueprintType)
enum class FMFALevel : uint8
{
	DEFAULT,
	OPTIONAL,
	MANDATORY,
	NONE
};
```

### Usage

## `MFASettings`

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this SDK in a production environment is the **SCALE Plan**. You can use this feature in `sapphire_devnet` for free.

:::

```c
USTRUCT(BlueprintType)
struct FMfaSettings
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
    	FMfaSetting deviceShareFactor;

    UPROPERTY(EditAnywhere, BlueprintReadWrite)
    	FMfaSetting backUpShareFactor;

    UPROPERTY(EditAnywhere, BlueprintReadWrite)
        FMfaSetting socialBackupFactor;

    UPROPERTY(EditAnywhere, BlueprintReadWrite)
        FMfaSetting passwordFactor;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		FMfaSetting passkeysFactor;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		FMfaSetting authenticatorFactor;

	FMfaSettings() {};

	void operator= (const FMfaSettings& other) {
		deviceShareFactor = other.deviceShareFactor;
		backUpShareFactor = other.backUpShareFactor;
		socialBackupFactor = other.socialBackupFactor;
		passwordFactor = other.passwordFactor;
		passkeysFactor = other.passkeysFactor;
		authenticatorFactor = other.authenticatorFactor;
	}

	bool operator==(const FMfaSettings& other) const
    {
    if (deviceShareFactor == other.deviceShareFactor &&
	    backUpShareFactor == other.backUpShareFactor  &&
	    socialBackupFactor == other.socialBackupFactor &&
	    passwordFactor == other.passwordFactor &&
	    passkeysFactor == other.passkeysFactor &&
	    authenticatorFactor == other.authenticatorFactor)
		{
			return true;
		}
	return false;
    }

};
```

:::note Note

- At least two factors are mandatory when setting up the mfaSettings.
- If you set `mandatory: true` for all factors, the user must set up all four factors.
- If you set `mandatory: false` for all factors, the user can skip setting up MFA. But at least two factors are mandatory.
- If you set `mandatory: true` for some factors and `mandatory: false` for others, the user must set up the mandatory factors and can skip the optional factors. But, the user must set up at least two factors.
- The `priority` field is used to set the order of the factors. The factor with the lowest priority will be the first factor to be set up. The factor with the highest priority will be the last factor to be set up.

:::

### Usage

---

## Whitelabel PnP Unreal Engine SDK

Embedded Wallets supports whitelabeling with application branding for a consistent user experience. You can customize three different aspects:

- **UI elements:** Customize the appearance of modals and components
- **Branding:** Apply your brand colors, logos, and themes
- **Translations:** Localize the interface for your users

:::info

All of these settings can be easily managed directly from the Embedded Wallets dashboard. Once you update your branding, or UI preferences there, the changes will automatically apply to your integration.

:::

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this
SDK in a production environment is the **Growth Plan**. You can use this feature in Web3Auth
Sapphire Devnet network for free.

:::

## Customizing the Embedded Wallets login screens

For defining custom UI, branding, and translations for your brand during Embedded Wallets instantiation, you just need to specify an additional parameter within the `Web3AuthOptions` object called `whiteLabel`. This parameter takes object called `WhiteLabelData`.

### `WhiteLabelData`

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Interface", value: "interface" },
  ]}
>

<TabItem value="table">

| Parameter          | Description                                                                                                                                                                 |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `appName?`         | Display name for the app in the UI.                                                                                                                                         |
| `logoLight?`       | App logo to be used in dark mode. It accepts URL in `FString` as a value.                                                                                                   |
| `logoDark?`        | App logo to be used in light mode. It accepts URL in `FString` as a value.                                                                                                  |
| `defaultLanguage?` | Language which will be used by Web3Auth, app will use browser language if not specified. Default language is `FLanguage::en`. Checkout `FLanguage` for supported languages. |
| `mode?`            | Theme mode for the login modal. Choose between `FThemeModes::auto`, `FThemeModes::light` or `FThemeModes::dark` background modes.                                           |
| `theme?`           | Used to customize the theme of the login modal. It accepts `TMap<FString, FString>` as a value.                                                                             |
| `appUrl?`          | URL to be used in the Modal. It accepts URL in `FString` as a value.                                                                                                        |
| `useLogoLoader?`   | Use logo loader. If `logoDark` and `logoLight` are null, the default Web3Auth logo will be used for the loader. Default value is false.                                     |

</TabItem>
<TabItem value="interface">

```cs
USTRUCT(BlueprintType)
struct FWhiteLabelData
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		FString appName;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		FString logoLight;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		FString logoDark;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
    	FLanguage defaultLanguage = FLanguage::en;

    UPROPERTY(EditAnywhere, BlueprintReadWrite)
    	FThemeModes mode;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		TMap<FString, FString> theme;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
    	FString appUrl;

    UPROPERTY(EditAnywhere, BlueprintReadWrite)
    	bool useLogoLoader;

	FWhiteLabelData() {};

	void operator= (const FWhiteLabelData& other) {
		appName = other.appName;
		logoLight = other.logoLight;
		logoDark = other.logoDark;
		defaultLanguage = other.defaultLanguage;
		mode = other.mode;
		theme = other.theme;
		appUrl = other.appUrl;
		useLogoLoader = other.useLogoLoader;
	}

};
```

</TabItem>
</Tabs>

### `name`

The name of the application. This will be displayed in the key reconstruction page.

  
    
      Standard screen without any change
    
    
  
  
    
      Name changed to <code>Formidable Duo</code>
    
    
  

### `logoLight` & `logoDark`

The logo of the application. Displayed in dark and light mode respectively. This will be displayed
in the key reconstruction page.

  
    
      <code>logoLight</code> on dark mode
    
    
  
  
    
      <code>logoDark</code> on light mode
    
    
  

### `defaultLanguage`

Default language will set the language used on all OpenLogin screens. The supported languages are:

  
    
      
        <code>en</code> - English (default)
      
      
        <code>de</code> - German
      
      
        <code>ja</code> - Japanese
      
      
        <code>ko</code> - Korean
      
      
        <code>zh</code> - Mandarin
      
      
        <code>es</code> - Spanish
      
      
        <code>fr</code> - French
      
      
        <code>pt</code> - Portuguese
      
      
        <code>nl</code> - Dutch
      
      
        <code>tr</code> - Turkish
      
    
  
  
    
  

### `dark`

Can be set to `true` or `false` with default set to `false`.

  
    
      For Light: <code>dark: false</code>
    
    
  
  
    
      For Dark: <code>dark: true</code>
    
    
  

### `theme`

Theme is a record of colors that can be configured. As of, now only `primary` color can be set and
has effect on OpenLogin screens (default primary color is `#0364FF`). Theme affects icons and links.
Examples below.

  
    
      Standard color <code>#0364FF</code>
    
    
  
  
    
      Color changed to <code>#D72F7A</code>
    
    
  

## Example

---

## Examples - PnP Unreal SDK

<ExampleCards exampleMap={pnpUnrealExamples} />

---

## Using Unreal SDK

Embedded Wallets provides a comprehensive set of functions to handle authentication, user management, and blockchain interactions in your Unreal Engine applications. These functions allow you to implement features like user login, multi-factor authentication, private key retrieval, and Wallet Services with minimal effort. Each function is designed to handle a specific aspect of Embedded Wallets' functionality, making it easy to integrate into your Unreal projects.

## List of functions

:::tip

For detailed usage, configuration options, and code examples, refer to the dedicated documentation page for each function.

:::

### Authentication functions

| Function Name              | Description                                        |
| -------------------------- | -------------------------------------------------- |
| [`login()`](./login.mdx)   | Logs in the user with the selected login provider. |
| [`logout()`](./logout.mdx) | Logs out the user from the current session.        |

### User management functions

| Function Name                          | Description                                     |
| -------------------------------------- | ----------------------------------------------- |
| [`getUserInfo()`](./get-user-info.mdx) | Retrieves the authenticated user's information. |

### Private key functions

| Function Name                                          | Description                                                                     |
| ------------------------------------------------------ | ------------------------------------------------------------------------------- |
| [`getPrivKey()`](./get-private-key.mdx)                | Retrieve the user's secp256k1 private key for EVM-compatible chains.            |
| [`getEd25519PrivKey()`](./get-ed25519-private-key.mdx) | Retrieve the user's ed25519 private key for chains like Solana, Near, Algorand. |

---

## Get Ed25519 private key(Usage)

To retrieve the Ed25519 private key of the user, you can get it using the `GetEd25519PrivKey` method. This private key can be used to sign transactions on Solana, Near, Algorand, and other chains that use the ed25519 curve.

## Usage

```cpp
UFUNCTION()
void AYourGameMode::OnWeb3AuthLoginSuccess(const FString& PrivateKey, const FString& PublicAddress)
{
    // Get Ed25519 private key for Solana
    FString Ed25519PrivKey = UWeb3AuthSDK::GetInstance()->GetEd25519PrivKey();
    UE_LOG(LogTemp, Warning, TEXT("Solana Ed25519 Private Key: %s"), *Ed25519PrivKey);
}
```

---

## Get Secp256k1 private key(Usage)

To retrieve the secp256k1 private key of the user, you can access it from the login success callback. The method returns an EVM compatible private key which can be used to sign transactions on EVM compatible chains.

## Usage

```cpp
UFUNCTION()
void AYourGameMode::OnWeb3AuthLoginSuccess(const FString& PrivateKey, const FString& PublicAddress)
{
    // Use private key for EVM transactions
    UE_LOG(LogTemp, Warning, TEXT("Ethereum Private Key: %s"), *PrivateKey);
    UE_LOG(LogTemp, Warning, TEXT("Ethereum Address: %s"), *PublicAddress);
}
```

---

## Get user info(4)

You can use the `getUserInfo` method to retrieve various details about the user, such as their login type, whether Multi-Factor Authentication (MFA) is enabled, profile image, name, and other relevant information.

## Usage

```cpp
UFUNCTION()
void AYourGameMode::OnWeb3AuthLoginSuccess(const FString& PrivateKey, const FString& PublicAddress)
{
    // Get user info from the login success callback
    FString UserInfo = UWeb3AuthSDK::GetInstance()->GetUserInfo();
    UE_LOG(LogTemp, Warning, TEXT("User Info: %s"), *UserInfo);
}
```

## UserInfo response

```json
{
  "aggregateVerifier": "w3a-google",
  "email": "john@gmail.com",
  "name": "John Dash",
  "profileImage": "https://lh3.googleusercontent.com/a/Ajjjsdsmdjmnm...",
  "typeOfLogin": "google",
  "verifier": "torus",
  "verifierId": "john@gmail.com",
  "dappShare": "<24 words seed phrase>", // will be sent only incase of custom verifiers
  "idToken": "<jwtToken issued by Web3Auth>",
  "oAuthIdToken": "<jwtToken issued by OAuth Provider>", // will be sent only incase of custom verifiers
  "oAuthAccessToken": "<accessToken issued by OAuth Provider>", // will be sent only incase of custom verifiers
  "isMfaEnabled": true // returns true if user has enabled mfa
}
```

---

## Login user(Usage)

This function helps your user to trigger the login process. The login flow will be triggered based on the selected provider.

## Parameters

`UWeb3AuthSDK::GetInstance()->Login()` requires `FWeb3AuthLoginParams` as a required input.

### `FWeb3AuthLoginParams`

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Interface", value: "interface" },
  ]}
>

<TabItem value="table">

| Parameter            | Description                                                                                                                                                                                                                                     |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `loginProvider`      | It sets the OAuth login method to be used. You can use any of the supported values are `GOOGLE`, `FACEBOOK`, `REDDIT`, `DISCORD`, `TWITCH`, `APPLE`, `LINE`, `GITHUB`, `KAKAO`, `LINKEDIN`, `TWITTER`, `WEIBO`, `WECHAT`, `EMAIL_PASSWORDLESS`. |
| `extraLoginOptions?` | It can be used to set the OAuth login options for corresponding `loginProvider`. For instance, you'll need to pass user's email address as. Default value for the field is `null`, and it accepts `FExtraLoginOptions` as a value.              |
| `redirectUrl?`       | URL where user will be redirected after successfull login. By default user will be redirected to same page where login will be initiated. Default value for the field is `null`, and accepts `FString` as a value.                              |
| `appState?`          | It can be used to keep track of the app state when user will be redirected to app after login. Default is `null`, and accepts `FString` as a value.                                                                                             |
| `mfaLevel?`          | Customize the MFA screen shown to the user during OAuth authentication. Default value for field is `MFALevel.DEFAULT`, which shows MFA screen every 3rd login. It accepts `FMFALevel` as a value.                                               |
| `dappShare?`         | Custom verifier logins can get a dapp share returned to them post successful login. This is useful if the dapps want to use this share to allow users to sign in without repeating the full flow. It accepts `FString` as a value.              |
| `curve?`             | It will be used to determine the public key encoded in the JWT token which returned in `getUserInfo` function after user login. The default value is `FCurve::speck256k1`.                                                                      |

</TabItem>

<TabItem value="interface">

```cpp
USTRUCT(BlueprintType)
struct FLoginParams
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		FString loginProvider;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		FString dappShare;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		FExtraLoginOptions extraLoginOptions;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		FString appState;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		FString redirectUrl;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		FMFALevel mfaLevel;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		FCurve curve;

	FLoginParams() {};
};
```

</TabItem>

</Tabs>

## Provider

```cpp
UENUM(BlueprintType)
enum class EWeb3AuthProvider : uint8
{
    GOOGLE UMETA(DisplayName = "Google"),
    FACEBOOK UMETA(DisplayName = "Facebook"),
    REDDIT UMETA(DisplayName = "Reddit"),
    DISCORD UMETA(DisplayName = "Discord"),
    TWITCH UMETA(DisplayName = "Twitch"),
    APPLE UMETA(DisplayName = "Apple"),
    LINE UMETA(DisplayName = "Line"),
    GITHUB UMETA(DisplayName = "GitHub"),
    KAKAO UMETA(DisplayName = "Kakao"),
    LINKEDIN UMETA(DisplayName = "LinkedIn"),
    TWITTER UMETA(DisplayName = "Twitter"),
    WEIBO UMETA(DisplayName = "Weibo"),
    WECHAT UMETA(DisplayName = "WeChat"),
    EMAIL_PASSWORDLESS UMETA(DisplayName = "Email Passwordless"),
    JWT UMETA(DisplayName = "JWT")
};
```

## Usage

```cpp
void AYourGameMode::LoginWithGoogle()
{
    FWeb3AuthLoginParams LoginParams;
    LoginParams.LoginProvider = TEXT("google");

    UWeb3AuthSDK::GetInstance()->Login(LoginParams);
}

UFUNCTION()
void AYourGameMode::OnWeb3AuthLoginSuccess(const FString& PrivateKey, const FString& PublicAddress)
{
    UE_LOG(LogTemp, Warning, TEXT("Web3Auth Login Success - Private Key: %s"), *PrivateKey);
    UE_LOG(LogTemp, Warning, TEXT("Web3Auth Login Success - Address: %s"), *PublicAddress);
}
```

---

## Logout user(3)

Trigger logout flow. This function doesn't take any parameters. A completable future containing void object is returned on successfull logout otherwise an error response is returned.

## Usage

```cpp
void AYourGameMode::LogoutUser()
{
    UWeb3AuthSDK::GetInstance()->Logout();
}

UFUNCTION()
void AYourGameMode::OnWeb3AuthLogout()
{
    UE_LOG(LogTemp, Warning, TEXT("Web3Auth Logout Success"));
}
```

---

## Getting started with the Vue SDK

:::note[Naming]

Embedded Wallets SDKs were previously known as Web3Auth Plug and Play SDKs. Package names and APIs remain Web3Auth (for example, `@web3auth/modal`).

:::

## Overview

MetaMask Embedded Wallets SDK provides authentication for Vue applications with social logins, external wallets, and more. Our Vue Composables simplifies how you connect users to their preferred wallets and manage authentication state.

:::info Migration from v9 or v10

Use the [Web SDK v11 migration guide](/embedded-wallets/migration-guides/web). It includes an LLM agent prompt, a full v9/v10-to-v11 API map, and step-by-step changes for `@web3auth/modal/vue`.

:::

## Requirements

- This is a frontend SDK and must be used in a browser environment
- Node.js 22+ and npm 10+
- Basic knowledge of JavaScript and Vue

## Prerequisites

- Set up your project on the [Embedded Wallets dashboard](https://developer.metamask.io/)

:::tip

See the [dashboard setup](../../dashboard/README.mdx) guide to learn more.

:::

## Installation

Install the Web3Auth Modal SDK using npm or yarn:

```bash npm2yarn
npm install --save @web3auth/modal @wagmi/vue @tanstack/vue-query
```

### 1. Configuration

Create a configuration file for Web3Auth. This file will contain your Web3Auth Client ID and Network details from the [Embedded Wallets dashboard](https://developer.metamask.io/).

```ts title="web3authContext.ts"

const web3AuthOptions: Web3AuthOptions = {
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable // Get your Client ID from MetaMask Developer Dashboard
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET, // or WEB3AUTH_NETWORK.SAPPHIRE_DEVNET
}

const web3AuthContextConfig: Web3AuthContextConfig = {
  web3AuthOptions,
}

export default web3AuthContextConfig
```

### 2. Set up providers

Register Vue Query in `main.ts` when you use Wagmi:

```ts title="main.ts"

createApp(App).use(VueQueryPlugin).mount('#app')
```

In `App.vue`, wrap your app with `Web3AuthProvider` and the Embedded Wallets `WagmiProvider`:

```html title="App.vue"
<script setup lang="ts">

</script>

<template>
  <Web3AuthProvider :config="web3AuthContextConfig">
    <WagmiProvider>
      <Home />
    </WagmiProvider>
  </Web3AuthProvider>
</template>
```

## Advanced configuration

The Embedded Wallets Modal SDK offers a rich set of advanced configuration options:

- **[Smart accounts](./advanced/smart-accounts.mdx):** Configure account abstraction parameters.
- **[Custom authentication](./advanced/custom-authentication.mdx):** Define authentication methods.
- **[Whitelabeling and UI customization](./advanced/whitelabel.mdx):** Personalize the modal's appearance.
- **[Multi-Factor Authentication (MFA)](./advanced/mfa.mdx):** Set up and manage MFA.
- **[Wallet Services](./advanced/wallet-services.mdx):** Integrate additional Wallet Services.

:::tip

See the [advanced configuration](./advanced/README.mdx) section to learn more about each configuration option.

:::

<Tabs
  defaultValue="basic-config"
  values={[
    { label: "Basic Configuration", value: "basic-config" },
    { label: "Advanced Configuration", value: "advanced-config" },
  ]}
>

<TabItem value="basic-config">

```ts

const web3AuthOptions: Web3AuthOptions = {
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET, // or WEB3AUTH_NETWORK.SAPPHIRE_DEVNET
}

const web3AuthContextConfig: Web3AuthContextConfig = {
  web3AuthOptions,
}
```

</TabItem>

<TabItem value="advanced-config">

```ts

  WALLET_CONNECTORS,
  WEB3AUTH_NETWORK,
  MFA_LEVELS,
  type Web3AuthOptions,
} from '@web3auth/modal'

const web3AuthOptions: Web3AuthOptions = {
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
  modalConfig: {
    connectors: {
      [WALLET_CONNECTORS.AUTH]: {
        label: 'auth',
        loginMethods: {
          google: {
            name: 'google login',
            // logoDark: "url to your custom logo which will shown in dark mode",
          },
          facebook: {
            name: 'facebook login',
            showOnModal: false, // hides the facebook option
          },
          email_passwordless: {
            name: 'email passwordless login',
            showOnModal: true,
            authConnectionId: 'w3a-email_passwordless-demo',
          },
          sms_passwordless: {
            name: 'sms passwordless login',
            showOnModal: true,
            authConnectionId: 'w3a-sms_passwordless-demo',
          },
        },
        showOnModal: true, // set to false to hide all social login methods
      },
    },
    hideWalletDiscovery: true, // set to true to hide external wallets discovery
  },
  mfaLevel: MFA_LEVELS.MANDATORY,
}

const web3AuthContextConfig: Web3AuthContextConfig = {
  web3AuthOptions,
}
```

</TabItem>

</Tabs>

## Blockchain integration

Web3Auth is blockchain agnostic, enabling integration with any blockchain network. Out of the box, Web3Auth offers robust support for both **Solana** and **Ethereum**, each with dedicated Vue composables.

### Solana integration

Solana composables are included natively within the `@web3auth/modal` package. Install
[`@solana/kit`](https://www.npmjs.com/package/@solana/kit), [`@solana-program/system`](https://www.npmjs.com/package/@solana-program/system), and
then wrap your app with `SolanaProvider`:

```html title="App.vue"
<script setup lang="ts">

</script>

<template>
  <Web3AuthProvider :config="web3AuthContextConfig">
    <SolanaProvider>
      <Home />
    </SolanaProvider>
  </Web3AuthProvider>
</template>
```

Use composables from `@web3auth/modal/vue/solana`.

### Ethereum integration

Ethereum composables are provided through [`@wagmi/vue`](https://wagmi.sh/vue/getting-started), which works with Embedded Wallets. This allows you to leverage a wide range of Ethereum composables for account management, transactions, and more.

For implementation details and examples, refer to the [Ethereum Composables](./ethereum-composables.mdx) section.

## Troubleshooting

### JWT errors

When using custom authentication, you may encounter JWT errors:

- [**Invalid JWT verifiers ID field**](/embedded-wallets/troubleshooting/jwt-errors#invalid-jwt-verifiers-id-field)
- [**Failed to verify JWS signature**](/embedded-wallets/troubleshooting/jwt-errors#failed-to-verify-jws-signature)
- [**Duplicate token**](/embedded-wallets/troubleshooting/jwt-errors#duplicate-token)
- [**Expired token**](/embedded-wallets/troubleshooting/jwt-errors#expired-token)
- [**Mismatch JWT validation field**](/embedded-wallets/troubleshooting/jwt-errors#mismatch-jwt-validation-field)

---

## Advanced configuration(9)

The Embedded Wallets SDK provides extensive configuration options that allow you to customize authentication flows, UI appearance, blockchain integrations, and security features to meet your application's specific requirements.

## Configuration structure

When setting up Embedded Wallets, you'll create a configuration object that is passed to the `Web3AuthProvider`. This consists of:

```tsx title="web3authContext.tsx"

// focus-start
const web3AuthOptions: Web3AuthOptions = {
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable // Get your Client ID from MetaMask Developer Dashboard
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET, // or WEB3AUTH_NETWORK.SAPPHIRE_DEVNET
  // Core and advanced options go here
}
// focus-end

const web3AuthContextConfig: Web3AuthContextConfig = {
  web3AuthOptions,
}
```

### `Web3AuthOptions`

<Tabs
  defaultValue="basic"
  values={[
    { label: "Basic parameters", value: "basic" },
    { label: "Advanced parameters", value: "advanced" },
    { label: "Interface", value: "interface" },
  ]}
>

<TabItem value="basic">

| Parameter                         | Description                                                                                                                                                                              |
| --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `clientId`                        | (Mandatory) Client ID, available from the [Embedded Wallets dashboard](https://developer.metamask.io).                                                                                   |
| `web3AuthNetwork`                 | (Mandatory) Web3Auth network to use for the session and the issued `idToken`. Default is `sapphire_mainnet`.                                                                             |
| `enableLogging?`                  | Setting to true enables logs. Default is false.                                                                                                                                          |
| `sessionTime?`                    | Session Time (in seconds) for `idToken` issued by Web3Auth for server side verification. Default is 7 days (7 \* 86400). Max value can be 30 days (86400 \* 30) and min can be 1 sec (1) |
| `useSFAKey?`                      | Uses Single Factor Auth SDK key with Web3Auth provider. Default is false.                                                                                                                |
| `storageType?`                    | Setting to `local` persists social login session across browser tabs. Default is `local`.                                                                                                |
| `defaultChainId?`                 | Default chain ID to use. Your first chain will be used as default.                                                                                                                       |
| `multiInjectedProviderDiscovery?` | Whether to enable discovery of injected wallets in the browser. Default is true.                                                                                                         |

</TabItem>

<TabItem value="advanced">

| Parameter                   | Description                                                                                                                                                                                 |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `chains?`                   | Optional in-code chain list. By default, chains are fetched from the [dashboard](/embedded-wallets/dashboard/chains-and-networks/). Pass `chains` only for custom RPC, demos, or overrides. |
| `uiConfig?`                 | (Fetched automatically from dashboard) Config for configuring UI display properties.                                                                                                        |
| `modalConfig?`              | Helps you customize the modal UI elements and authentication methods.                                                                                                                       |
| `accountAbstractionConfig?` | (Fetched automatically from Dashboard) Account abstraction config for your chain namespace.                                                                                                 |
| `useAAWithExternalWallet?`  | (Fetched automatically from Dashboard) Whether to use AA with external wallet.                                                                                                              |
| `walletServicesConfig?`     | (Fetched automatically from Dashboard) Configure any parameter related to Wallet Services plugin                                                                                            |
| `ssr?`                      | Whether to enable SSR mode.                                                                                                                                                                 |
| `mfaSettings?`              | MFA settings for the auth connector.                                                                                                                                                        |
| `mfaLevel?`                 | MFA level for the auth connector.                                                                                                                                                           |
| `privateKeyProvider?`       | Private key provider for your chain namespace.                                                                                                                                              |

</TabItem>

<TabItem value="interface">

```tsx
export interface Web3AuthOptions extends IWeb3AuthCoreOptions {
  /**
   * Config for configuring modal ui display properties
   */
  uiConfig?: Omit<UIConfig, 'connectorListener'>
  /**
   * Config for configuring modal ui display properties
   */
  modalConfig?: ConnectorsModalConfig
}

export interface IWeb3AuthCoreOptions {
  /**
   * Client id for web3auth.
   * You can obtain your client id from the web3auth developer dashboard.
   * You can set any random string for this on localhost.
   */
  clientId: string
  /**
   * multiple chain configurations,
   * only provided chains will be used
   */
  chains?: CustomChainConfig[]
  /**
   * default chain Id to use
   */
  defaultChainId?: string
  /**
   * setting to true will enable logs
   *
   * @defaultValue false
   */
  enableLogging?: boolean
  /**
   * setting to "local" will persist social login session across browser tabs.
   *
   * @defaultValue "local"
   */
  storageType?: 'session' | 'local' | 'cookies'
  /**
   * sessionTime (in seconds) for idToken issued by Web3Auth for server side verification.
   * @defaultValue 7 * 86400
   *
   * Note: max value can be 30 days (86400 * 30) and min can be  1 sec (1)
   */
  sessionTime?: number
  /**
   * Web3Auth Network to use for the session.
   */
  web3AuthNetwork: WEB3AUTH_NETWORK_TYPE
  /**
   * Uses core-kit key with web3auth provider
   * @defaultValue false
   */
  useSFAKey?: boolean
  /**
   * Whitelabel options for web3auth
   */
  uiConfig?: UIConfig
  /**
   * Account abstraction config for your chain namespace
   */
  accountAbstractionConfig?: AccountAbstractionMultiChainConfig
  /**
   * Whether to use AA with external wallet
   */
  useAAWithExternalWallet?: boolean
  /**
   * Connectors to use
   */
  connectors?: ConnectorFn[]
  /**
   * Plugins to use
   */
  plugins?: PluginFn[]
  /**
   * Whether to enable multi injected provider discovery
   * @defaultValue true
   */
  multiInjectedProviderDiscovery?: boolean
  /**
   * Wallet services config
   */
  walletServicesConfig?: WalletServicesConfig
  /**
   * Private key provider for xrpl, mpc cases
   */
  privateKeyProvider?: IBaseProvider<string>
  /**
   * Whether to enable SSR mode
   *
   * @defaultValue false
   */
  ssr?: boolean
  /**
   * Build environment for Auth connector
   * @internal
   * @defaultValue BUILD_ENV.PRODUCTION
   */
  authBuildEnv?: BUILD_ENV_TYPE
  /**
   * MFA settings for the auth connector
   */
  mfaSettings?: MfaSettings
  /**
   * MFA level for the auth connector
   */
  mfaLevel?: MfaLevelType
}
```

</TabItem>

</Tabs>

## Session management

Control how long users stay authenticated and how sessions persist.

**Key Configuration Options:**

- `sessionTime` - Session duration in seconds. Controls how long users remain authenticated before
  needing to log in again.
  - Minimum: 1 second (`1`).
  - Maximum: 30 days (`86400 * 30`).
  - Default: 7 days (`86400 * 7`).
- `storageType` - Storage location for authentication state. Options:
  - `"local"`: Persists across browser tabs and browser restarts (localStorage)
  - `"session"`: Persists only in current tab, cleared when tab closes (sessionStorage)

```tsx
const web3AuthOptions = {
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,

  // Session configuration
  sessionTime: 86400 * 7, // 7 days (in seconds)
  storageType: 'local', // 'local' (persistent across tabs) or 'session' (single tab only)
}
```

## Multi-Factor Authentication

Add additional security layers to protect user accounts with two-factor authentication. For detailed
configuration options and implementation examples, see [Multi-Factor Authentication (MFA)](./mfa.mdx).

**Key Configuration Options:**

- `mfaSettings` - Configure MFA settings for different authentication flows
- `mfaLevel` - Control when users are prompted to set up MFA

## Custom authentication methods

Control the login options presented to your users and how they're displayed in the modal. For
detailed configuration options and implementation examples, see the
[custom authentication](./custom-authentication.mdx) section.

**Key Configuration Options:**

- `modalConfig` - Define which authentication methods are available and customize their appearance

## UI customization

Customize the brand experience by customizing the Web3Auth Modal to match your application's
design. For complete customization options, refer to the
[Whitelabeling & UI Customization](./whitelabel.mdx) section.

**Key Configuration Options:**

- `uiConfig` - Personalize the modal's look and feel with custom colors, logos, themes, and more
- `modalConfig` - Control the visibility and arrangement of authentication options

## Smart accounts (account abstraction)

Improve user experience with gasless transactions and advanced account features. Learn more in the
[smart accounts](./smart-accounts.mdx) documentation.

**Key Configuration Options:**

- `accountAbstractionConfig` - Fine-tune parameters for smart account implementation
- `useAAWithExternalWallet` - Enable account abstraction functionality even when users connect with
  external wallets

## Wallet Services

Extend your application with enhanced wallet functionality. See the
[Wallet Services](./wallet-services.mdx) documentation for complete configuration options.

**Key Configuration Options:**

- `walletServicesConfig` - Integrate additional Wallet Services and features

---

## Custom authentication(4)

Custom authentication is a way to authenticate users with your custom authentication service. For example, while authenticating with Google, you can use your own Google Client ID to authenticate users directly.

This feature, with MFA turned off, can make Embedded Wallets invisible to the end user.

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this
SDK in a production environment is the **Growth Plan**. You can use this feature in Web3Auth
Sapphire Devnet network for free.

:::

## Getting an Auth Connection ID

:::info prerequisite

To enable this, you need to [create a connection](../../../dashboard/authentication.mdx) from the **Authentication** tab of your project from the [Embedded Wallets developer dashboard](https://developer.metamask.io) with your desired configuration.

:::

To configure a connection, you need to provide the particular details of the connection into our Embedded Wallets dashboard. This enables us to map a `authConnectionId with your connection details. This `authConnectionId helps us to identify the connection details while initializing the SDK. You can configure multiple connections for the same project, and you can also update the connection details anytime.

:::tip

Learn more about the [auth provider setup](../../../authentication/README.mdx) and the different configurations available for each connection.

:::

## Modal custom authentication

The basic custom authentication is available directly in the modal. You can configure each of the auth providers in the modal to direct to your `authConnectionId`.

:::note

You can only configure implicit login via modal, for JWT-based logins, you need to create your own UI and use the `connectTo` function.

:::

For the modal custom authentication, you need to pass the `modalConfig` object to the `Web3AuthOptions` object within the constructor.

:::tip

Learn more about the `modalConfig` object in the [Whitelabel](./whitelabel.mdx) section.

:::

### Usage

<Tabs>
  <TabItem value="Single connections">

```ts title="web3authContext.ts"

const web3AuthContextConfig: Web3AuthContextConfig = {
  web3AuthOptions: {
    clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable
    web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
    // focus-start
    modalConfig: {
      connectors: {
        [WALLET_CONNECTORS.AUTH]: {
          label: 'auth',
          loginMethods: {
            google: {
              name: 'google login',
              authConnectionId: 'w3a-google-demo',
            },
            facebook: {
              name: 'facebook login',
              authConnectionId: 'w3a-facebook-demo',
            },
            discord: {
              name: 'discord login',
              authConnectionId: 'w3a-discord-demo',
            },
            twitch: {
              name: 'twitch login',
              authConnectionId: 'w3a-twitch-demo',
            },
            twitter: {
              name: 'twitter login',
              // it will hide the twitter option from the Web3Auth modal.
              showOnModal: false,
            },
            email_passwordless: {
              name: 'email passwordless login',
              authConnectionId: 'w3a-email_passwordless-demo',
            },
            sms_passwordless: {
              name: 'sms passwordless login',
              authConnectionId: 'w3a-sms_passwordless-demo',
            },
          },
          // setting it to false will hide all social login methods from modal.
          showOnModal: true,
        },
      },
    },
    // focus-end
  },
}

export default web3AuthContextConfig
```

  </TabItem>
  <TabItem value="Grouped connections">

```ts title="web3authContext.ts"

const web3AuthContextConfig: Web3AuthContextConfig = {
  web3AuthOptions: {
    clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable
    web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
    // focus-start
    modalConfig: {
      connectors: {
        [WALLET_CONNECTORS.AUTH]: {
          label: 'auth',
          loginMethods: {
            google: {
              name: 'google login',
              authConnectionId: 'w3a-google',
              groupedAuthConnectionId: 'aggregate-sapphire',
            },
            facebook: {
              name: 'facebook login',
              authConnectionId: 'w3a-facebook',
              groupedAuthConnectionId: 'aggregate-sapphire',
            },
            email_passwordless: {
              name: 'email passwordless login',
              authConnectionId: 'w3a-email-passwordless',
              groupedAuthConnectionId: 'aggregate-sapphire',
            },
          },
        },
      },
    },
    // focus-end
  },
}

export default web3AuthContextConfig
```

  </TabItem>
</Tabs>

## Advanced custom authentication

The more advanced custom authentication is available via the `connectTo` function. This allows you to any service you want and tie it to your Web3Auth Integration. **This method allows you to make Web3Auth totally invisible to your end users and have a fully whitelabeled experience all across.**

You can utilise this function to enable multiple types of connections like:

- Implicit Login connections
- JWT login connections
- Grouped auth connections

<details>
  <summary>`connectTo` Function Reference</summary>

```ts
connectTo<T extends WALLET_CONNECTOR_TYPE>(
  connector: T,
  params?: LoginParamMap[T]
): Promise<Connection | null>;

export type LoginParamMap = {
    [WALLET_CONNECTORS.AUTH]: Partial<AuthLoginParams>;
    ...
};
```

#### `AuthLoginParams`

<Tabs>
  <TabItem value="Table">

| Parameter                  | Description                                                                                                                          |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `loginHint?`               | Helps pass over the login hint to the auth provider. This is used especially for `email_passwordless` and `sms_passwordless` logins. |
| `idToken?`                 | Pass over the JWT ID token directly to Web3Auth for JWT authentication.                                                              |
| `authConnection?`          | The auth provider to use for login (for example, "google", "facebook").                                                              |
| `authConnectionId?`        | The ID configured in your Embedded Wallets dashboard for the connection.                                                             |
| `groupedAuthConnectionId?` | The grouped Auth Connection ID to be used for login.                                                                                 |
| `extraLoginOptions?`       | Custom OAuth options (for example, login_hint, domain).                                                                              |

  </TabItem>

  <TabItem value="Interface">
    ```ts
    export type AuthLoginParams = LoginParams & {
      loginHint?: string;
      idToken?: string;
  };
    export type LoginParams = {
  /**
   * Any custom state you wish to pass along. This will be returned to you post redirect.
   * Use this to store data that you want to be available to the dapp after login.
   */
  appState?: string;
  /**
   * The auth connection to be used for login.
   */
  authConnection: AUTH_CONNECTION_TYPE | CUSTOM_AUTH_CONNECTION_TYPE;
  /**
   * The auth connection id to be used for login.
   */
  authConnectionId?: string;
  /**
   * The grouped auth connection id to be used for login.
   */
  groupedAuthConnectionId?: string;
  /**
   * You can set the `mfaLevel` to customize when mfa screen should be shown to user.
   * It currently accepts 4 values:-
   * - `'default'`: Setting mfa level to `default` will present mfa screen to user on every third login.
   * - `'optional'`: Setting mfa level to `default` will present mfa screen to user on every login but user can skip it.
   * - `'mandatory'`: Setting mfa level to `mandatory` will make it mandatory for user to setup mfa after login.
   * - `'none'`: Setting mfa level to `none` will make the user skip the mfa setup screen
   *
   * Defaults to `none`
   * @defaultValue `none`
   */
  mfaLevel?: MfaLevelType;
  /**
   * This option is for internal use only in torus wallet and has no effect
   * on user's login on other dapps.
   *
   * Defaults to false
   * @defaultValue false
   * @internal
   */
  getWalletKey?: boolean;
  /**
   * extraLoginOptions can be used to pass standard OAuth login options to
   * loginProvider.
   *
   * For ex: you will have to pass `login_hint` as user's email and `domain`
   * as your app domain in `extraLoginOptions` while using `email_passwordless`
   * loginProvider
   */
  extraLoginOptions?: ExtraLoginOptions;
  /**
   * Custom Logins can get a dapp share returned to them post successful login.
   * This is useful if the dapps want to use this share to allow users to sign in without repeating the full flow
   * dappShare is a 24 word seed phrase
   */
  dappShare?: string;
  /**
   * This curve will be used to determine the public key encoded in the jwt token which returned in
   * `getUserInfo` function after user login.
   * You can use that public key from jwt token as a unique user identifier in your backend.
   *
   * - `'secp256k1'`: secp256k1 based pub key is added as a wallet public key in jwt token to use.
   * - `'ed25519'`: ed25519 based pub key is added as a wallet public key in jwt token to use.
   *
   * Note: This parameter won't change format of private key returned by auth. Private key returned
   * by auth is always `secp256k1`.
   *
   *
   * @defaultValue secp256k1
   */
  curve?: SUPPORTED_KEY_CURVES_TYPE;
  /**
   * Allows the dapp to set a custom redirect url for the manage MFA flow.
   *
   */
  dappUrl?: string;
};
    ```
  </TabItem>
</Tabs>

#### Auth connection types

```ts
export const AUTH_CONNECTION = {
  GOOGLE: 'google',
  TWITTER: 'twitter',
  FACEBOOK: 'facebook',
  DISCORD: 'discord',
  FARCASTER: 'farcaster',
  APPLE: 'apple',
  GITHUB: 'github',
  REDDIT: 'reddit',
  LINE: 'line',
  KAKAO: 'kakao',
  LINKEDIN: 'linkedin',
  TWITCH: 'twitch',
  TELEGRAM: 'telegram',
  WECHAT: 'wechat',
  EMAIL_PASSWORDLESS: 'email_passwordless',
  SMS_PASSWORDLESS: 'sms_passwordless',
  CUSTOM: 'custom',
}
```

#### Advanced options (`extraLoginOptions`)

For custom integrations (like Auth0, AWS Cognito), you can provide additional options:

<Tabs>
  <TabItem value="Table">

| Parameter               | Description                                                  |
| ----------------------- | ------------------------------------------------------------ |
| `isUserIdCaseSensitive` | Whether the user ID field is case sensitive (Default: true). |
| `domain`                | Auth provider domain (for example, "example.auth0.com") .    |
| `client_id`             | Client ID from your auth provider.                           |
| `scope`                 | OAuth scopes (for example, "email profile openid").          |
| `response_type`         | Response type for OAuth flow.                                |
| `login_hint`            | Pre-fill user identifier.                                    |

  </TabItem>
  <TabItem value="Interface">
    ```ts
    export type ExtraLoginOptions = Auth0ClientOptions;

    export interface Auth0ClientOptions extends BaseLoginOptions {
    /**
     * Your Auth0 account domain such as `'example.auth0.com'`,
     * `'example.eu.auth0.com'` or , `'example.mycompany.com'`
     * (when using [custom domains](https://auth0.com/docs/custom-domains))
     */
    domain?: string;
    /**
     * The Client ID found on your Application settings page
     */
    client_id?: string;
    /**
     * The field in jwt token which maps to user id
     */
    userIdField?: string;
    /**
     * Whether the user id field is case sensitive
     * @defaultValue true
     */
    isUserIdCaseSensitive?: boolean;
    id_token?: string;
    access_token?: string;
    /**
     * The route for user info endpoint. This will be padded to domain
     * @defaultValue userinfo
     * */
    user_info_route?: string;
    /**
     * The flow type for email_passwordless login
     */
    flow_type?: EMAIL_FLOW_TYPE;
    }
    ```

  </TabItem>
</Tabs>

</details>

### Implicit logins

Implicit logins are the easiest way to authenticate users with your custom authentication services. Web3Auth currently supports implicit logins for the following providers directly:

- Google
- Facebook
- Discord
- Twitch
- Auth0 (custom)

In addition to these you can also use any other provider, for example Auth0, AWS Cognito, Azure AD. by providing the particular details of their login within the `extraLoginOptions` object within the `connectTo` function.

#### Usage

<Tabs>
  <TabItem value="Google">
```ts
await connectTo(WALLET_CONNECTORS.AUTH, {
  authConnection: AUTH_CONNECTION.GOOGLE,
  authConnectionId: "w3a-google-demo",
});
```

  </TabItem>
  <TabItem value="Facebook">
```ts
await connectTo(WALLET_CONNECTORS.AUTH, {
  authConnection: AUTH_CONNECTION.FACEBOOK,
  authConnectionId: "w3a-facebook-demo",
});
```

  </TabItem>
  <TabItem value="Discord">
```ts
await connectTo(WALLET_CONNECTORS.AUTH, {
  authConnection: AUTH_CONNECTION.DISCORD,
  authConnectionId: "w3a-discord-demo",
});
```

  </TabItem>
  <TabItem value="Twitch">
```ts
await connectTo(WALLET_CONNECTORS.AUTH, {
  authConnection: AUTH_CONNECTION.TWITCH,
  authConnectionId: "w3a-twitch-demo",
});
```

  </TabItem>
  <TabItem value="Auth0 Google">
```ts
await connectTo(WALLET_CONNECTORS.AUTH, {
  authConnection: AUTH_CONNECTION.CUSTOM,
  authConnectionId: "w3a-auth0-demo",
  extraLoginOptions: {
    connection: "google-oauth2",
  },
});
```

  </TabItem>
  <TabItem value="Auth0 SPA">
```ts
await connectTo(WALLET_CONNECTORS.AUTH, {
  authConnection: AUTH_CONNECTION.CUSTOM,
  authConnectionId: "w3a-auth0-demo",
});
```

  </TabItem>
  <TabItem value="AWS Cognito">
```ts
await connectTo(WALLET_CONNECTORS.AUTH, {
  authConnection: AUTH_CONNECTION.CUSTOM,
  authConnectionId: "w3a-cognito-demo",
  extraLoginOptions: {
    clientId: import.meta.env['VITE_COGNITO_CLIENT_ID'],
    domain: "https://shahbaz-web3auth.auth.ap-south-1.amazoncognito.com",
    verifierIdField: "email",
    response_type: "token",
    scope: "email profile openid",
  },
});
```

  </TabItem>
</Tabs>

### JWT login

JWT login is a way to authenticate users with your custom authentication services. With this method, Web3Auth just takes into account the `idToken` passed over to the `connectTo` function and uses it to authenticate the user. You can utilise this method with any authentication service that is OAuth 2.0 Compatible.

:::warning

If you have not configured on the dashboard, whether you user ID is case sensitive or not, then you need to pass the `isUserIdCaseSensitive` option to the `extraLoginOptions`.

:::

#### Usage

<Tabs>
  <TabItem value="Google One Tap">

```ts
const loginWithGoogle = async (idToken: string) => {
  // focus-start
  await connectTo(WALLET_CONNECTORS.AUTH, {
    authConnectionId: 'w3a-google-demo',
    authConnection: AUTH_CONNECTION.GOOGLE,
    idToken,
    extraLoginOptions: {
      isUserIdCaseSensitive: false,
    },
  })
  // focus-end
}
```

  </TabItem>
  <TabItem value="Auth0 JWT login">

```html
<script setup lang="ts">

  const { connectTo } = useWeb3AuthConnect()
  const auth0Client = new Auth0Client({
    domain: 'YOUR_AUTH0_DOMAIN',
    clientId: 'YOUR_AUTH0_CLIENT_ID',
    authorizationParams: {
      redirect_uri: window.location.origin,
    },
  })

  const loginWithAuth0 = async () => {
    await auth0Client.loginWithPopup()
    const idToken = await auth0Client.getIdTokenClaims()

    // focus-start
    await connectTo(WALLET_CONNECTORS.AUTH, {
      authConnectionId: 'w3a-auth0-demo',
      authConnection: AUTH_CONNECTION.CUSTOM,
      idToken: idToken.__raw,
      extraLoginOptions: {
        isUserIdCaseSensitive: false,
      },
    })
    // focus-end
  }
</script>

<template>
  <button @click="loginWithAuth0">Login with Auth0</button>
</template>
```

</TabItem>
<TabItem value="Firebase JWT login">

```ts
const loginWithFirebaseGithub = async () => {
  try {
    const app = initializeApp(firebaseConfig)
    const auth = getAuth(app)
    const githubProvider = new GithubAuthProvider()

    const result = await signInWithPopup(auth, githubProvider)

    const idToken = await result.user.getIdToken(true)

    // focus-start
    connectTo(WALLET_CONNECTORS.AUTH, {
      authConnectionId: 'w3a-firebase-demo',
      authConnection: AUTH_CONNECTION.CUSTOM,
      idToken,
      extraLoginOptions: {
        isUserIdCaseSensitive: false,
      },
    })
    // focus-end
  } catch (error) {
    console.error('Firebase authentication error:', error)
  }
}
```

</TabItem>
<TabItem value="Custom JWT login">

```ts
const getIdToken = async () => {
  // Get ID Token from server
  const res = await fetch('http://localhost:8080/api/token', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
  })
  const data = await res.json()
  return data?.token
}

const loginWithJWT = async () => {
  try {
    const idToken = await getIdToken()

    // focus-start
    await connectTo(WALLET_CONNECTORS.AUTH, {
      authConnection: AUTH_CONNECTION.CUSTOM,
      authConnectionId: 'w3a-node-demo',
      idToken,
      extraLoginOptions: {
        isUserIdCaseSensitive: false,
      },
    })
    // focus-end
  } catch (err) {
    console.error(err)
  }
}
```

</TabItem>
</Tabs>

### Grouped auth connections

Grouped auth connections allows you to group multiple auth connections together and use them as a single connection. This is useful when you want to authenticate the user with multiple providers and require the same user wallet address to be generated.

For example, you can group Google and email passwordless providers together and use them as a single connection. Now, if your user logs in with Google Auth or even with email passwordless using the same email, they will get the same wallet address.

:::info Prerequisites

You need to configure a grouped connection, by combining your single connections in the Embedded Wallets dashboard before using this feature.

:::

<Tabs>
  <TabItem value="Google [Implicit] + Auth0 [Implicit]">

```ts
const loginWithGoogle = async () => {
  // focus-start
  await connectTo(WALLET_CONNECTORS.AUTH, {
    groupedAuthConnectionId: 'aggregate-sapphire',
    authConnectionId: 'w3a-google',
    authConnection: AUTH_CONNECTION.GOOGLE,
  })
  // focus-end
}

const loginWithAuth0Google = async () => {
  // focus-start
  await connectTo(WALLET_CONNECTORS.AUTH, {
    groupedAuthConnectionId: 'aggregate-sapphire',
    authConnectionId: 'w3a-a0-google',
    authConnection: AUTH_CONNECTION.CUSTOM,
    extraLoginOptions: {
      connection: 'google-oauth2',
    },
  })
  // focus-end
}

const loginWithAuth0GitHub = async () => {
  // focus-start
  await connectTo(WALLET_CONNECTORS.AUTH, {
    groupedAuthConnectionId: 'aggregate-sapphire',
    authConnectionId: 'w3a-a0-github',
    authConnection: AUTH_CONNECTION.CUSTOM,
    extraLoginOptions: {
      connection: 'github',
    },
  })
  // focus-end
}
```

  </TabItem>
  <TabItem value="Google One Tap [JWT] + Auth0 [JWT]">

```ts

const { connectTo } = useWeb3AuthConnect()

const loginWithGoogle = async (idToken: string) => {
  // focus-start
  await connectTo(WALLET_CONNECTORS.AUTH, {
    groupedAuthConnectionId: 'aggregate-sapphire',
    authConnectionId: 'w3a-google',
    authConnection: AUTH_CONNECTION.GOOGLE,
    idToken,
    extraLoginOptions: {
      isUserIdCaseSensitive: false,
      verifierIdField: 'email',
    },
  })
  // focus-end
}

const auth0Client = new Auth0Client({
  domain: 'YOUR_AUTH0_DOMAIN',
  clientId: 'YOUR_AUTH0_CLIENT_ID',
  authorizationParams: {
    redirect_uri: window.location.origin,
  },
})

const loginWithAuth0 = async () => {
  try {
    await auth0Client.loginWithPopup()
    const idToken = (await getIdTokenClaims())?.__raw.toString()
    if (!idToken) {
      throw new Error('No id token found')
    }

    // focus-start
    await connectTo(WALLET_CONNECTORS.AUTH, {
      groupedAuthConnectionId: 'aggregate-sapphire',
      authConnectionId: 'w3a-a0-github',
      authConnection: AUTH_CONNECTION.CUSTOM,
      idToken,
      extraLoginOptions: {
        isUserIdCaseSensitive: false,
        verifierIdField: 'email',
      },
    })
    // focus-end
  } catch (err) {
    console.error(err)
  }
}
```

</TabItem>
<TabItem value="Google [Implicit] + Firebase [JWT]">

```ts
const loginWithGoogle = async () => {
  // focus-start
  await connectTo(WALLET_CONNECTORS.AUTH, {
    groupedAuthConnectionId: 'aggregate-sapphire',
    authConnectionId: 'w3a-google',
    authConnection: AUTH_CONNECTION.GOOGLE,
  })
  // focus-end
}

const loginWithFirebaseGithub = async () => {
  const app = initializeApp(firebaseConfig)
  const auth = getAuth(app)
  const githubProvider = new GithubAuthProvider()

  const result = await signInWithPopup(auth, githubProvider)

  const idToken = await result.user.getIdToken(true)

  // focus-start
  connectTo(WALLET_CONNECTORS.AUTH, {
    groupedAuthConnectionId: 'aggregate-sapphire',
    authConnectionId: 'w3a-firebase',
    authConnection: AUTH_CONNECTION.CUSTOM,
    idToken,
    extraLoginOptions: {
      isUserIdCaseSensitive: false,
    },
  })
  // focus-end
}
```

</TabItem>
</Tabs>

---

## Multi-factor authentication(5)

Web3Auth supports Multi-Factor Authentication (MFA) for enhanced security. MFA requires two or more factors, such as device, social, seed phrase, or password, to access your account and recover it if needed. When a recovery factor is set up, MFA is enabled and your key is split into three shares, using Web3Auth MPC for secure, self-custodial storage.

:::caution

If you are using default dashboard connections, your users may have set up MFA on other dapps that also use default Web3Auth connections. In this case, the MFA screen will continue to appear if the user has enabled MFA on other dapps. This is because MFA cannot be turned off once it is enabled.

:::

## Multi-Factor Authentication configuration options

There are two ways to configure MFA in your application:

1. **Using the `mfaLevel` setting:** Controls the frequency of the MFA setup request screen.
2. **Using the `mfaSettings` setting:** Provides granular control over each factor, with their priority level, enable/disable status, and mandatory/optional settings.

## `mfaLevel`

The `mfaLevel` setting allows you to control when and how the MFA setup screen appears to users.

```tsx
mfaLevel?: MfaLevelType;
```

### Multi-Factor Authentication level types

| Level       | Value       | Description                                         |
| ----------- | ----------- | --------------------------------------------------- |
| `DEFAULT`   | "default"   | MFA screen appears every 10th login.                |
| `OPTIONAL`  | "optional"  | MFA screen appears every login, but can be skipped. |
| `MANDATORY` | "mandatory" | MFA setup is required after login.                  |
| `NONE`      | "none"      | MFA setup is skipped entirely.                      |

### Type definition

```tsx
export type MfaLevelType = (typeof MFA_LEVELS)[keyof typeof MFA_LEVELS]
export declare const MFA_LEVELS: {
  readonly DEFAULT: 'default'
  readonly OPTIONAL: 'optional'
  readonly MANDATORY: 'mandatory'
  readonly NONE: 'none'
}
```

### Usage examples

### Usage

```tsx

await connectTo(WALLET_CONNECTORS.AUTH, {
  authConnection: AUTH_CONNECTION.GOOGLE,
  authConnectionId: 'w3a-google-demo',
  // focus-next-line
  mfaLevel: MFA_LEVELS.MANDATORY,
})
```

## `mfaSettings`

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this SDK in a production environment is the **Scale Plan**. You can use this feature in Web3Auth Sapphire Devnet network for free.

:::

The `mfaSettings` option provides granular control over each individual MFA factor.

```tsx
mfaSettings?: MfaSettings;
```

### Multi-Factor Authentication factors

| Factor          | Key                   | Description                           |
| --------------- | --------------------- | ------------------------------------- |
| `DEVICE`        | "deviceShareFactor"   | Device-based authentication.          |
| `BACKUP_SHARE`  | "backUpShareFactor"   | Backup share (typically seed phrase). |
| `SOCIAL_BACKUP` | "socialBackupFactor"  | Social account backup.                |
| `PASSWORD`      | "passwordFactor"      | Password-based authentication.        |
| `AUTHENTICATOR` | "authenticatorFactor" | Authenticator app (TOTP).             |

### Multi-Factor Authentication settings properties

| Property    | Type    | Description                                             |
| ----------- | ------- | ------------------------------------------------------- |
| `enable`    | boolean | Whether this factor is enabled.                         |
| `priority`  | number  | Order in which factors are presented (lower = earlier). |
| `mandatory` | boolean | Whether this factor is required.                        |

### Type definitions

```tsx
export type MfaSettings = Partial<Record<MFA_FACTOR_TYPE, MFA_SETTINGS>>
export type MFA_FACTOR_TYPE = (typeof MFA_FACTOR)[keyof typeof MFA_FACTOR]
export declare const MFA_FACTOR: {
  readonly DEVICE: 'deviceShareFactor'
  readonly BACKUP_SHARE: 'backUpShareFactor'
  readonly SOCIAL_BACKUP: 'socialBackupFactor'
  readonly PASSWORD: 'passwordFactor'
  readonly PASSKEYS: 'passkeysFactor'
  readonly AUTHENTICATOR: 'authenticatorFactor'
}
export type MFA_SETTINGS = {
  enable: boolean
  priority?: number
  mandatory?: boolean
}
```

### Important rules

- At least two factors must be enabled when setting up MFA.
- If you set `mandatory: true` for all factors, the user must set up all enabled factors.
- If you set `mandatory: false` for all factors, the user can skip setting up MFA, but at least two factors are still required.
- If you set `mandatory: true` for some factors and `mandatory: false` for others, the user must set up the mandatory factors and can optionally set up the others.
- The `priority` field determines the order of setup - lower priority values appear first.

### Usage

```ts title="web3authContext.ts"

const web3AuthOptions: Web3AuthOptions = {
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
  // focus-start
  mfaSettings: {
    [MFA_FACTOR.DEVICE]: {
      enable: true,
      priority: 1,
      mandatory: true, // at least two factors are mandatory
    },
    [MFA_FACTOR.BACKUP_SHARE]: {
      enable: true,
      priority: 2,
      mandatory: true, // at least two factors are mandatory
    },
    [MFA_FACTOR.SOCIAL_BACKUP]: {
      enable: true,
      priority: 3,
      mandatory: false,
    },
    [MFA_FACTOR.PASSWORD]: {
      enable: true,
      priority: 4,
      mandatory: false,
    },
    [MFA_FACTOR.PASSKEYS]: {
      enable: true,
      priority: 5,
      mandatory: false,
    },
    [MFA_FACTOR.AUTHENTICATOR]: {
      enable: true,
      priority: 6,
      mandatory: false,
    },
  },
  // focus-end
}

const web3AuthContextConfig: Web3AuthContextConfig = {
  web3AuthOptions,
}

export default web3AuthContextConfig
```

---

## Smart accounts(5)


Create and manage smart accounts for your users with just a few lines of code, using our Smart Account feature. Smart accounts offer enhanced control and programmability, enabling features that traditional wallets can't provide.

**Key features of smart accounts include:**

- **Gas abstraction:** Cover transaction fees for users, or allow users to pay for their own transactions using ERC-20 tokens.
- **Batch transactions:** Perform multiple transactions in a single call.
- **Automated transactions:** Allow users to automate actions, like swapping ETH to USDT when ETH hits a specific price.
- **Custom spending limits:** Allow users to set tailored spending limits.

:::tip

For more about ERC-4337 and its components, [check out our detailed blog post](https://blog.web3auth.io/an-ultimate-guide-to-web3-wallets-externally-owned-account-and-smart-contract-wallet/#introduction-to-eip-4337).

:::

Our smart account integration streamlines your setup, allowing you to create and manage smart accounts using your favorite libraries like Viem, Ethers, and Wagmi. You don't need to rely on third-party packages to effortlessly create ERC-4337 compatible Smart Contract Wallets (SCWs), giving users the ability to perform batch transactions and efficiently manage gas sponsorship.

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this
SDK in a production environment is the **Growth Plan**. You can use this feature in Web3Auth
Sapphire Devnet network for free.

:::

## Enabling smart accounts

:::info prerequisite

To enable this feature, you need to configure smart accounts from your project in the [Embedded Wallets dashboard](https://developer.metamask.io/).

:::

### Dashboard configuration

To enable smart accounts, navigate to the smart accounts section in the MetaMask Developer Dashboard, and enable the "Set up Smart accounts" toggle. Web3Auth currently supports [MetaMaskSmartAccount](https://docs.gator.metamask.io/how-to/create-delegator-account#create-a-metamasksmartaccount) as a Smart Account provider.

#### Wallet configuration

Once smart accounts are enabled, you can customize the wallet configurations:

- **All supported wallets (default):** Allows users to create smart accounts using both embedded and external wallets.
- **Embedded wallets only:** Restricts Smart Account creation to only embedded wallets.

#### Configure bundler and paymaster

A bundler aggregates UserOperations and submits them onchain via the global EntryPoint contract. To configure the bundler:

1. Navigate to the **Bundler & Paymaster** tab within the **Smart accounts** section.
2. Add the bundler URL for each supported chain.
3. Add the paymaster URL for each supported chain.

:::info

Currently, the sponsored paymaster can only be configured via the dashboard. For ERC-20 paymaster, refer to the SDK Configuration section below.

:::

### Optional: SDK configuration

While the dashboard provides a convenient way to configure smart accounts, the SDK offers greater flexibility by allowing you to override these settings.

### Basic configuration

To enable smart accounts in your application, add the `accountAbstractionConfig` to your Web3Auth options:

```ts

const web3AuthOptions: Web3AuthOptions = {
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_DEVNET,
  // focus-start
  accountAbstractionConfig: {
    smartAccountType: 'metamask',
    chains: [
      {
        chainId: '0x1',
        bundlerConfig: {
          url: 'YOUR_BUNDLER_URL',
        },
      },
    ],
  },
  // focus-end
}

const web3AuthContextConfig: Web3AuthContextConfig = {
  web3AuthOptions,
}

export default web3AuthContextConfig
```

### Advanced configuration: Override paymaster context

You can override the paymaster context defined in the dashboard for specific chains. This is particularly useful when your paymaster requires custom settings or parameters.

```ts

const web3AuthOptions: Web3AuthOptions = {
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_DEVNET,
  // focus-start
  accountAbstractionConfig: {
    smartAccountType: 'metamask',
    chains: [
      {
        chainId: '0x1',
        bundlerConfig: {
          url: 'YOUR_BUNDLER_URL',
          // This is just an example of how you can configure the paymaster context.
          // Please refer to the documentation of the paymaster you are using
          // to understand the required parameters.
          paymasterContext: {
            token: 'SUPPORTED_TOKEN_CONTRACT_ADDRESS',
            sponsorshipPolicyId: 'sp_my_policy_id',
          },
        },
      },
    ],
  },
  // focus-end
}

const web3AuthContextConfig: Web3AuthContextConfig = {
  web3AuthOptions,
}

export default web3AuthContextConfig
```

:::info

The paymaster context must be manually configured for each chain that needs to be supported.

:::

## Using smart accounts

### Configure signer

The Web3Auth Smart Account feature is compatible with popular signer SDKs, including Wagmi, ethers,
and viem. You can choose your preferred package to configure the signer.

<!-- vale off -->

<Tabs
  defaultValue="wagmi"
  values={[
    { label: "Wagmi (recommended)", value: "wagmi" },
    { label: "Viem", value: "viem" },
    { label: "Ethers", value: "ethers" },
  ]}
>

<TabItem value="wagmi">

Use Wagmi with `@web3auth/modal/react/wagmi` or `@web3auth/modal/vue/wagmi`. After sign-in, Wagmi
hooks (`useConnection`, `useSendTransaction`, and similar) use the smart account signer automatically.
No manual `connection.ethereumProvider` wiring is required.

```tsx

const { address } = useConnection()
// useSendTransaction, useWriteContract, etc. work with the smart account
```

</TabItem>

<TabItem value="viem">

For vanilla JavaScript or apps without Wagmi, read the EIP-1193 provider from `connection`:

```tsx

const connection = web3auth.connection
const provider = connection?.ethereumProvider ?? null

const walletClient = createWalletClient({
  transport: custom(provider),
})
```

</TabItem>

<TabItem value="ethers">

```tsx

const connection = web3auth.connection
const provider = connection?.ethereumProvider ?? null

const ethersProvider = new ethers.BrowserProvider(provider)
const signer = await ethersProvider.getSigner()
```

</TabItem>
</Tabs>
<!-- vale on -->

### Get Smart account address

Once the signers or Wagmi configuration is set up, it can be used to retrieve the user's Smart
Account address.

<Tabs
  defaultValue="viem"
  values={[
    { label: "Viem", value: "viem" },
    { label: "Ethers", value: "ethers" },
    { label: "Wagmi", value: "Wagmi" },
  ]}
>

<TabItem value="viem">

```tsx
// Use walletClient instance from previous step
const addresses = await walletClient.getAddresses()

const smartAccountAddress = addresses[0]
const eoaAddress = addresses[1]
```

</TabItem>

<TabItem value="ethers">

```tsx
// User signer from previous step
const smartAccountAddress = signer.getAddress()
```

</TabItem>

<TabItem value="Wagmi">
```tsx

const { address } = useConnection()
const smartAccountAddress = address

```

</TabItem>
</Tabs>
```

### Send transaction

Developers can use their preferred signer or Wagmi hooks to initiate onchain transactions, while
Web3Auth manages the creation and submission of the UserOperation. Only the `to`, `data`, and
`value` fields need to be provided. Any additional parameters will be ignored and automatically
overridden.

To ensure reliable execution, the bundler client sets maxFeePerGas and maxPriorityFeePerGas values.
If custom values are required, developers can use the
[Viem's BundlerClient](https://viem.sh/account-abstraction/clients/bundler#bundler-client) to
manually construct and send the user operation.

Since Smart Accounts are deployed smart contracts, the user's first transaction also triggers the
onchain deployment of their wallet.

<Tabs
  defaultValue="viem"
  values={[
    { label: "Viem", value: "viem" },
    { label: "Ethers", value: "ethers" },
    { label: "Wagmi", value: "wagmi" },
  ]}
>

<TabItem value="wagmi">

```tsx

const { data: hash, sendTransaction } = useSendTransaction()

// Convert 1 ether to WEI format
const value = web3.utils.toWei(1)

sendTransaction({ to: 'DESTINATION_ADDRESS', value, data: '0x' })

const {
  data: receipt,
  isLoading: isConfirming,
  isSuccess: isConfirmed,
} = useWaitForTransactionReceipt({
  hash,
})
```

</TabItem>
<TabItem value="ethers">

```tsx
// Convert 1 ether to WEI format
const amount = ethers.parseEther('1.0')

// Submits a user operation to the blockchain
const transaction = await signer.sendTransaction({
  to: 'DESTINATION_ADDRESS',
  value: amount,
  // This will perform the transfer of ETH
  data: '0x',
})

// Wait for the transaction to be mined
const receipt = await transaction.wait()
```

</TabItem>
<TabItem value="viem">

```tsx
// Convert 1 ether to WEI format
const amount = parseEther('1')

// Submits a user operation to the blockchain
const hash = await walletClient.sendTransaction({
  to: 'DESTINATION_ADDRESS',
  value: amount,
  // This will perform the transfer of ETH
  data: '0x',
})

// Wait for the transaction to be mined
const receipt = await publicClient.waitForTransactionReceipt({ hash })
```

</TabItem>
</Tabs>

### Sign transaction

You can sign a transaction without immediately sending it. For the user's first transaction, the `UserOperation` calldata will automatically include the deployment data needed to create the Smart Account onchain.

:::info

Wagmi doesn't have hooks for signing transactions yet.

:::

<Tabs
  defaultValue="viem"
  values={[
    { label: "Viem", value: "viem" },
    { label: "Ethers", value: "ethers" },
  ]}
>

<TabItem value="ethers">

```tsx
// Convert 1 ether to WEI format
const amount = parseEther('1')

const signature = await signer.signTransaction({
  to: 'DESTINATION_ADDRESS',
  value: amount,
})
```

</TabItem>
<TabItem value="viem">

```tsx
// Convert 1 ether to WEI format
const amount = parseEther('1')
const addresses = await walletClient.getAddresses()

const request = await walletClient.prepareTransactionRequest({
  account: addresses[0],
  to: 'DESTINATION_ADDRESS',
  value: amount,
})

const signature = await walletClient.signTransaction(request as any)
```

</TabItem>
</Tabs>

### Sign message

Smart accounts support message signing following the EIP-1271 standard for signature verification, using the `isValidSignature` method defined in the smart contract wallet instead of the `ecrecover` function used by EOAs.

<!-- vale off -->

<Tabs
  defaultValue="viem"
  values={[
    { label: "Viem", value: "viem" },
    { label: "Ethers", value: "ethers" },
    { label: "Wagmi", value: "wagmi" },
  ]}
>

<TabItem value="wagmi">

```html
<script setup lang="ts">

  const message = ref('YOUR_MESSAGE')
  const { data, isPending, error, signMessage } = useSignMessage()

  const handleSignMessage = () => {
    signMessage({ message: message.value })
  }
</script>

<template>
  
    <input v-model="message" placeholder="Enter message to sign" />
    <button @click="handleSignMessage" :disabled="isPending">
      {{ isPending ? 'Signing...' : 'Sign Message' }}
    </button>

    
      Signature:
      <pre>{{ data }}</pre>
    

    
      Error:
      <pre>{{ error.message }}</pre>
    
  
</template>
```

</TabItem>
<TabItem value="ethers">

```tsx
const originalMessage = 'YOUR_MESSAGE'

// Sign the message
const signedMessage = await signer.signMessage(originalMessage)
```

</TabItem>
<TabItem value="viem">

```tsx
const originalMessage = 'YOUR_MESSAGE'

const addresses = await walletClient.getAddresses()

const signedMessage = await walletClient.signMessage({
  account: address[0],
  message: originalMessage,
})
```

</TabItem>
</Tabs>
<!-- vale on -->

### Send batch transaction

One of the key advantages of smart accounts is the ability to execute multiple operations in a single transaction. For example, instead of requiring separate transactions for token approval and then swapping, both operations can be combined into a single UserOperation.

To perform batch transactions, you must use the `BundlerClient` provided by Web3Auth:

```ts
// Use your Web3Auth instance
const accountAbstractionProvider = web3auth.accountAbstractionProvider
// Use the same accountAbstractionProvider we created earlier.
const bundlerClient = accountAbstractionProvider.bundlerClient!
const smartAccount = accountAbstractionProvider.smartAccount!

// 0.00001 ETH in WEI format
const amount = 10000000000000n

const userOpHash = await bundlerClient.sendUserOperation({
  account: smartAccount,
  calls: [
    {
      to: 'DESTINATION_ADDRESS',
      value: amount,
      data: '0x',
    },
    {
      to: 'DESTINATION_ADDRESS',
      value: amount,
      data: '0x',
    },
  ],
})

// Retrieve user operation receipt
const receipt = await bundlerClient.waitForUserOperationReceipt({
  hash: userOpHash,
})

const transactionHash = receipt.receipt.transactionHash
```

:::info

When calling `sendUserOperation`, it returns a UserOperation hash, not the transaction hash. To get the final transaction details, use `waitForUserOperationReceipt`.

:::

### Send Transaction Using ERC-20 paymaster

You can use ERC-20 tokens to pay for transaction fees instead of the native token (for example, ETH). This requires approving the token for use by the paymaster:

```ts
// Use your Web3Auth instance
const accountAbstractionProvider = web3auth.accountAbstractionProvider

// Use the same accountAbstractionProvider we created earlier.
const bundlerClient = accountAbstractionProvider.bundlerClient!
const smartAccount = accountAbstractionProvider.smartAccount!

// Pimlico's ERC-20 Paymaster address
const pimlicoPaymasterAddress = '0x0000000000000039cd5e8aE05257CE51C473ddd1'

// USDC address on Ethereum Sepolia
const usdcAddress = '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238'

// 0.00001 ETH in WEI format
const amount = 10000000000000n

// 10 USDC in WEI format. Since USDC has 6 decimals, 10 * 10^6
const approvalAmount = 10000000n

const userOpHash = await bundlerClient.sendUserOperation({
  account: smartAccount,
  calls: [
    // Approve USDC on Sepolia chain for Pimlico's ERC 20 Paymaster
    {
      to: usdcAddress,
      abi: parseAbi(['function approve(address,uint)']),
      functionName: 'approve',
      args: [pimlicoPaymasterAddress, approvalAmount],
    },
    {
      to: 'DESTINATION_ADDRESS',
      value: amount,
      data: '0x',
    },
    {
      to: 'DESTINATION_ADDRESS',
      value: amount,
      data: '0x',
    },
  ],
})

// Retrieve user operation receipt
const receipt = await bundlerClient.waitForUserOperationReceipt({
  hash: userOpHash,
})

const transactionHash = receipt.receipt.transactionHash
```

## EIP-7702 smart accounts {#eip-7702-smart-accounts}

:::note Web SDK only

EIP-7702 support ships in **Web SDK v11** (`@web3auth/modal` for JavaScript, React, and Vue).

:::

EIP-7702 (Set Code for EOAs) lets users keep their existing EOA address while temporarily delegating execution to a smart account implementation for a single transaction.
This bridges EOA simplicity and account-abstraction capability without forcing users onto a separate smart account address.

### When to use EIP-7702 vs ERC-4337

| Approach                | Address                                 | Best for                                                        |
| ----------------------- | --------------------------------------- | --------------------------------------------------------------- |
| ERC-4337 smart accounts | New smart account address (`aaAddress`) | Full account-abstraction lifecycle with bundlers and paymasters |
| EIP-7702                | Same EOA address                        | One-off or session-scoped AA features without address migration |

### Dashboard configuration

Enable smart accounts in the [Embedded Wallets dashboard](https://developer.metamask.io/) and select an EIP-7702-compatible provider.
The SDK currently lists MetaMask as an EIP-7702-supported smart account provider.

:::caution review

Confirm the exact dashboard toggle and `eipStandard` values for EIP-7702 in your project settings before publishing.

:::

### SDK configuration

When overriding smart account settings in code, set `eipStandard` on `accountAbstractionConfig`:

```ts

const web3AuthOptions: Web3AuthOptions = {
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID',
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_DEVNET,
  accountAbstractionConfig: {
    smartAccountType: 'metamask',
    eipStandard: '7702',
    chains: [
      {
        chainId: '0x1',
        bundlerConfig: {
          url: 'YOUR_BUNDLER_URL',
        },
      },
    ],
  },
}
```

:::caution review

Verify the accepted `eipStandard` enum values against your installed `@web3auth/modal` version.
Use the SDK release notes if the value above fails at build time.

:::

### Capabilities unlocked by EIP-7702

- **Gas sponsorship:** Cover transaction fees through a paymaster without changing the user's address.
- **Batch transactions:** Combine multiple calls in one authorization.
- **Session keys:** Approve scoped permissions for multi-step flows with a single signature.

For ERC-4337-specific flows (UserOperations, bundler clients), use the sections above.
For a conceptual overview, see [Native smart accounts](/embedded-wallets/features/smart-accounts/).

---

## Wallet Services(3)

Embedded Wallets' Wallet Services provides a comprehensive suite of wallet functionality including fiat-on-ramp, swaps, and wallet UI Interoperability with WalletConnect. These services enhance your application by offering a complete wallet experience without building these features from scratch.

:::tip

All these configurations can be directly accessed and managed through the [Embedded Wallets dashboard](https://developer.metamask.io). Manual configuration in the SDK is optional and provided here for reference purposes.

:::

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this
SDK in a production environment is the **Growth Plan**. You can use this feature in Web3Auth
Sapphire Devnet network for free.

:::

## `walletServicesConfig`

The `walletServicesConfig` option allows you to customize the Wallet Services experience for your users.

```tsx
walletServicesConfig?: WalletServicesConfig;
```

### Configuration options

<Tabs>
  <TabItem value="Table">

| Property               | Type                       | Description                                      |
| ---------------------- | -------------------------- | ------------------------------------------------ |
| `confirmationStrategy` | CONFIRMATION_STRATEGY_TYPE | How to display confirmation screens.             |
| `modalZIndex`          | number                     | Z-index for modal windows.                       |
| `enableKeyExport`      | boolean                    | Enable private key export functionality.         |
| `whiteLabel`           | Object                     | Customization options for the widget appearance. |

#### Confirmation strategy options

| Strategy       | Description                                                     |
| -------------- | --------------------------------------------------------------- |
| `default`      | Uses auto-approve by default, modal for WalletConnect requests. |
| `modal`        | Always uses modal for confirmations.                            |
| `auto-approve` | Automatically approves transactions without confirmation.       |

#### Whitelabel options

| Property            | Type                 | Description                                |
| ------------------- | -------------------- | ------------------------------------------ |
| `showWidgetButton`  | boolean              | Whether to show the widget button.         |
| `buttonPosition`    | BUTTON_POSITION_TYPE | Position of the widget button on the page. |
| `hideNftDisplay`    | boolean              | Hide NFT display in the wallet.            |
| `hideTokenDisplay`  | boolean              | Hide token display in the wallet.          |
| `hideTransfers`     | boolean              | Hide transfer functionality.               |
| `hideTopup`         | boolean              | Hide top-up (fiat on-ramp) functionality.  |
| `hideReceive`       | boolean              | Hide receive address functionality.        |
| `hideSwap`          | boolean              | Hide token swap functionality.             |
| `hideShowAllTokens` | boolean              | Hide the "show all tokens" option.         |
| `hideWalletConnect` | boolean              | Hide WalletConnect integration.            |
| `defaultPortfolio`  | "token" \| "nft"     | Default portfolio view.                    |

#### Button position options

| Position       | Description                      |
| -------------- | -------------------------------- |
| `bottom-left`  | Bottom left corner of the page.  |
| `top-left`     | Top left corner of the page.     |
| `bottom-right` | Bottom right corner of the page. |
| `top-right`    | Top right corner of the page.    |

  </TabItem>

  <TabItem value="Interface">

```tsx
export type WalletServicesConfig = Omit<
  WsEmbedParams,
  | 'buildEnv'
  | 'enableLogging'
  | 'chainId'
  | 'chains'
  | 'confirmationStrategy'
  | 'accountAbstractionConfig'
> & {
  /**
   * Determines how to show confirmation screens
   * @defaultValue default
   *
   * default & auto-approve
   * - use auto-approve as default
   * - if wallet connect request use modal
   *
   * modal
   * - use modal always
   */
  confirmationStrategy?: Exclude<WsEmbedParams['confirmationStrategy'], 'popup'>
  modalZIndex?: number
}

export interface WsEmbedParams {
  /**
   * Supported chains
   */
  chains: ProviderConfig[]
  /**
   * Chain to connect with
   */
  chainId: string
  /**
   * Build Environment of WsEmbed.
   *
   * production uses https://wallet.web3auth.io,
   *
   * staging uses https://staging-wallet.web3auth.io,
   *
   * testing uses https://develop-wallet.web3auth.io (latest internal build)
   *
   * development uses http://localhost:4050 (expects wallet-services-frontend to be run locally),
   *
   * @defaultValue production
   */
  buildEnv?: WS_EMBED_BUILD_ENV_TYPE
  /**
   * Enables or disables logging.
   *
   * Defaults to false in prod and true in other environments
   */
  enableLogging?: boolean
  /**
   * url of widget to load
   *
   * Defaults to true
   * @defaultValue true
   */
  walletUrls?: Partial<Record<WS_EMBED_BUILD_ENV_TYPE, WalletUrlConfig>>
  /**
   * Determines how to show confirmation screens
   * @defaultValue default
   *
   * default & popup
   * - use popop as default
   * - if WalletConnect request use modal
   *
   * modal
   * - use modal always
   *
   * auto-approve
   * - does not work on embed. will use default
   */
  confirmationStrategy?: CONFIRMATION_STRATEGY_TYPE
  /**
   * Enable and configure account abstraction
   */
  accountAbstractionConfig?: AccountAbstractionMultiChainConfig
  /**
   * Enable private key export
   *
   * Defaults to false
   * @defaultValue false
   */
  enableKeyExport?: boolean
  /**
   * Allows you to customize the look & feel of the widget
   */
  whiteLabel?: {
    /**
     * whether to show/hide ws-embed widget.
     *
     * Defaults to true
     * @defaultValue true
     */
    showWidgetButton?: boolean
    /**
     * Determines where the wsEmbed widget is visible on the page.
     * @defaultValue bottom-left
     */
    buttonPosition?: BUTTON_POSITION_TYPE
    hideNftDisplay?: boolean
    hideTokenDisplay?: boolean
    hideTransfers?: boolean
    hideTopup?: boolean
    hideReceive?: boolean
    hideSwap?: boolean
    hideShowAllTokens?: boolean
    hideWalletConnect?: boolean
    defaultPortfolio?: 'token' | 'nft'
  } & WhiteLabelData
}

export declare const CONFIRMATION_STRATEGY: {
  readonly POPUP: 'popup'
  readonly MODAL: 'modal'
  readonly AUTO_APPROVE: 'auto-approve'
  readonly DEFAULT: 'default'
}
export type CONFIRMATION_STRATEGY_TYPE =
  (typeof CONFIRMATION_STRATEGY)[keyof typeof CONFIRMATION_STRATEGY]

export type AccountAbstractionMultiChainConfig = {
  smartAccountType?: SmartAccountType
  chains?: {
    chainId: string
    bundlerConfig: BundlerConfig
    paymasterConfig?: PaymasterConfig
    smartAccountConfig?: SmartAccountConfig
  }[]
}

export declare const BUTTON_POSITION: {
  readonly BOTTOM_LEFT: 'bottom-left'
  readonly TOP_LEFT: 'top-left'
  readonly BOTTOM_RIGHT: 'bottom-right'
  readonly TOP_RIGHT: 'top-right'
}
export type BUTTON_POSITION_TYPE = (typeof BUTTON_POSITION)[keyof typeof BUTTON_POSITION]
```

  </TabItem>
</Tabs>

## Usage

```ts title="web3authContext.ts"

  BUTTON_POSITION,
  CONFIRMATION_STRATEGY,
  WEB3AUTH_NETWORK,
  type Web3AuthOptions,
} from '@web3auth/modal'

const web3AuthOptions: Web3AuthOptions = {
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
  // focus-start
  walletServicesConfig: {
    confirmationStrategy: CONFIRMATION_STRATEGY.MODAL,
    modalZIndex: 99999,
    enableKeyExport: false,
    whiteLabel: {
      showWidgetButton: true,
      buttonPosition: BUTTON_POSITION.BOTTOM_RIGHT,
      hideNftDisplay: false,
      hideTokenDisplay: false,
      hideTransfers: false,
      hideTopup: false,
      hideReceive: false,
      hideSwap: false,
      hideShowAllTokens: false,
      hideWalletConnect: false,
      defaultPortfolio: 'token',
    },
  },
  // focus-end
}

const web3AuthContextConfig: Web3AuthContextConfig = {
  web3AuthOptions,
}

export default web3AuthContextConfig
```

---

## Whitelabel(5)

Embedded Wallets allows complete whitelabeling with application branding for a consistent user experience. You can customize three different aspects:

- **UI elements:** Customize the appearance of modals and components
- **Branding:** Apply your brand colors, logos, and themes
- **Translations:** Localize the interface for your users

:::info

All of these settings can be easily managed directly from the Embedded Wallets dashboard. Once you update your branding, or UI preferences there, the changes will automatically apply to your integration.

:::

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this
SDK in a production environment is the **Growth Plan**. You can use this feature in Web3Auth
Sapphire Devnet network for free.

:::

## Customizing the Web3Auth Modal

While basic modal appearance can be configured directly on the dashboard, the following advanced options provide even greater control through the `modalConfig` property.

### `modalConfig`

The `modalConfig` option in the constructor lets you configure the modal UI and customize authentication:

```ts
modalConfig?: ConnectorsModalConfig;

export interface ConnectorsModalConfig {
    connectors?: Partial<Record<WALLET_CONNECTOR_TYPE, ModalConfig>>;
    hideWalletDiscovery?: boolean;
}

export type WALLET_CONNECTOR_TYPE = (typeof WALLET_CONNECTORS)[keyof typeof WALLET_CONNECTORS];

export interface ModalConfig extends Omit<BaseConnectorConfig, "isInjected" | "chainNamespaces"> {
    loginMethods?: LoginMethodConfig;
}
```

### `LoginMethodConfig`

The `LoginMethodConfig` interface provides extensive customization options for each authentication method:

<Tabs>
  <TabItem value="Table">

| Property                  | Type                   | Description                                                                          |
| ------------------------- | ---------------------- | ------------------------------------------------------------------------------------ |
| `name`                    | `string`               | Custom display name (defaults to auth app's default if not provided)                 |
| `description`             | `string`               | Button description (renders as full-length button if provided; otherwise as an icon) |
| `logoHover`               | `string`               | Logo shown on mouse hover (defaults to auth app's default)                           |
| `logoLight`               | `string`               | Logo for dark theme/background (defaults to auth app's default)                      |
| `logoDark`                | `string`               | Logo for light theme/background (defaults to auth app's default)                     |
| `mainOption`              | `boolean`              | Whether to show login button on the main list                                        |
| `showOnModal`             | `boolean`              | Controls visibility of the login button on modal                                     |
| `authConnectionId`        | `string`               | Auth Connection ID of the provider                                                   |
| `groupedAuthConnectionId` | `string`               | Grouped auth connection ID of the provider                                           |
| `extraLoginOptions`       | `ExtraLoginOptions`    | Additional parameters for social login                                               |
| `authConnection`          | `AUTH_CONNECTION_TYPE` | Auth connection type (useful for customizing login buttons with custom connectors)   |
| `isDefault`               | `boolean`              | Whether it's the default connector _(internal)_                                      |

  </TabItem>

  <TabItem value="Interface">

```ts
export type LoginMethodConfig = Partial<
  Record<
    AUTH_CONNECTION_TYPE,
    {
      /**
       * Display Name. If not provided, we use the default for auth app
       */
      name?: string
      /**
       * Description for button. If provided, it renders as a full length button. else, icon button
       */
      description?: string
      /**
       * Logo to be shown on mouse hover. If not provided, we use the default for auth app
       */
      logoHover?: string
      /**
       * Logo to be shown on dark background (dark theme). If not provided, we use the default for auth app
       */
      logoLight?: string
      /**
       * Logo to be shown on light background (light theme). If not provided, we use the default for auth app
       */
      logoDark?: string
      /**
       * Show login button on the main list
       */
      mainOption?: boolean
      /**
       * Whether to show the login button on modal or not
       */
      showOnModal?: boolean
      /**
       * Auth Connection ID of the provider.
       */
      authConnectionId?: string
      /**
       * Grouped Auth Connection ID of the provider.
       */
      groupedAuthConnectionId?: string
      /**
       * ExtraLoginOption params to be used for social login.
       */
      extraLoginOptions?: ExtraLoginOptions
      /**
       * Auth connection type of the auth connector.
       * Can be different from the original key.
       *
       * Example: This helps in customizing the Google login button with auth0 custom connector.
       */
      authConnection?: AUTH_CONNECTION_TYPE
      /**
       * Whether is it default connector.
       *
       * @internal
       */
      isDefault?: boolean
    }
  >
>
```

  </TabItem>
</Tabs>

## Common customization examples

### Disabling specific social login methods

Embedded Wallets provides the following social login methods:

```tsx
export declare const AUTH_CONNECTION: {
  readonly GOOGLE: 'google'
  readonly TWITTER: 'twitter'
  readonly FACEBOOK: 'facebook'
  readonly DISCORD: 'discord'
  readonly FARCASTER: 'farcaster'
  readonly APPLE: 'apple'
  readonly GITHUB: 'github'
  readonly REDDIT: 'reddit'
  readonly LINE: 'line'
  readonly KAKAO: 'kakao'
  readonly LINKEDIN: 'linkedin'
  readonly TWITCH: 'twitch'
  readonly TELEGRAM: 'telegram'
  readonly WECHAT: 'wechat'
  readonly EMAIL_PASSWORDLESS: 'email_passwordless'
  readonly SMS_PASSWORDLESS: 'sms_passwordless'
  readonly CUSTOM: 'custom'
  readonly AUTHENTICATOR: 'authenticator'
}
```

To disable specific login methods, set `showOnModal` to `false` for the corresponding auth connection:

```ts title="web3AuthContextConfig.ts"

const web3AuthContextConfig: Web3AuthContextConfig = {
  web3AuthOptions: {
    clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable
    web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
    // focus-start
    modalConfig: {
      connectors: {
        [WALLET_CONNECTORS.AUTH]: {
          label: 'auth',
          loginMethods: {
            // Disable Facebook and Reddit
            facebook: {
              name: 'facebook',
              showOnModal: false,
            },
            reddit: {
              name: 'reddit',
              showOnModal: false,
            },
          },
          // Setting to false will hide all social login methods from modal
          showOnModal: true,
        },
      },
    },
    // focus-end
  },
}

export default web3AuthContextConfig
```

### Enhancing email and SMS login experience

By specifying a custom `authConnectionId` for email or SMS login methods, you can ensure the entire authentication flow takes place within the modal, eliminating the need for external popups.

:::info

In the default setup, users are redirected to a separate popup to enter their email or phone number for security purposes. However, with a custom `authConnectionId`, this input step is securely embedded directly inside the modal, keeping the input step inside the modal.

:::

```ts title="web3AuthContextConfig.ts"

const web3AuthContextConfig: Web3AuthContextConfig = {
  web3AuthOptions: {
    clientId: 'YOUR_WEB3AUTH_CLIENT_ID', // Pass your Web3Auth Client ID, ideally using an environment variable
    web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
    // focus-start
    modalConfig: {
      connectors: {
        [WALLET_CONNECTORS.AUTH]: {
          label: 'auth',
          loginMethods: {
            email_passwordless: {
              name: 'email passwordless login',
              authConnectionId: 'w3a-email_passwordless-demo',
            },
            sms_passwordless: {
              name: 'sms passwordless login',
              authConnectionId: 'w3a-sms_passwordless-demo',
            },
          },
        },
      },
    },
    // focus-end
  },
}

export default web3AuthContextConfig
```

## Creating a fully custom UI

For complete control over the authentication interface, you can bypass the Web3Auth modal entirely and use the `connectTo` function. This allows you to create custom buttons that connect directly to specific auth providers.

See the [custom authentication](./custom-authentication.mdx) section for detailed implementation instructions.

---

## Vue composables for Web3Auth Modal

Embedded Wallets offers a comprehensive suite of Vue composables to streamline integration and state management within your Vue applications. These composables abstract away common authentication and wallet operations, enabling you to implement Embedded Wallets features with minimal boilerplate. Each composable is focused on a specific aspect of Embedded Wallets functionality, making it easy to implement authentication, wallet operations, and blockchain interactions in your Vue projects.

## List of Vue composables

:::tip

For detailed usage, configuration options, and code examples, refer to the dedicated documentation page for each composable.

:::

### Embedded Wallets composables

| Composable Name                     | Description                                                                        |
| ----------------------------------- | ---------------------------------------------------------------------------------- |
| [`useWeb3Auth` ](./useWeb3Auth.mdx) | Core composable for Embedded Wallets/Web3Auth initialization and state management. |

### Authentication composables

| Composable Name                                        | Description                                             |
| ------------------------------------------------------ | ------------------------------------------------------- |
| [`useWeb3AuthConnect`](./useWeb3AuthConnect.mdx)       | Handles Embedded Wallets/Web3Auth connection processes. |
| [`useWeb3AuthDisconnect`](./useWeb3AuthDisconnect.mdx) | Manages disconnection from Embedded Wallets/Web3Auth.   |

### Identity composables

| Composable Name                              | Description                                              |
| -------------------------------------------- | -------------------------------------------------------- |
| [`useAuthTokenInfo`](./useAuthTokenInfo.mdx) | Retrieves and manages identity tokens.                   |
| [`useWeb3AuthUser`](./useWeb3AuthUser.mdx)   | Provides access to the authenticated user's information. |

### Blockchain composables

| Composable Name                          | Description                                             |
| ---------------------------------------- | ------------------------------------------------------- |
| [`useSwitchChain`](./useSwitchChain.mdx) | Allows switching between different blockchain networks. |

### MFA composables

| Composable Name                      | Description                                                      |
| ------------------------------------ | ---------------------------------------------------------------- |
| [`useEnableMFA`](./useEnableMFA.mdx) | Enables Multi-Factor Authentication (MFA) for enhanced security. |
| [`useManageMFA`](./useManageMFA.mdx) | Provides functionality to manage MFA settings.                   |

### Wallet Services plugin composables

| Composable Name                                            | Description                                         |
| ---------------------------------------------------------- | --------------------------------------------------- |
| [`useWalletConnectScanner`](./useWalletConnectScanner.mdx) | Integrates WalletConnect scanner functionality.     |
| [`useWalletUI`](./useWalletUI.mdx)                         | Manages wallet UI components and user interactions. |
| [`useCheckout` ](./useCheckout.mdx)                        | Facilitates cryptocurrency checkout processes.      |
| [`useSwap` ](./useSwap.mdx)                                | Enables token swapping capabilities.                |
| [`useWalletServicesPlugin`](./useWalletServicesPlugin.mdx) | Provides access to wallet service plugins.          |

---

## useAuthTokenInfo(Composables)

Composable to retrieve and manage the identity token from Embedded Wallets in Vue.

### Import

```ts

```

### Usage

```html
<script setup lang="ts">

  const { getAuthTokenInfo, loading, error, token } = useAuthTokenInfo()
</script>

<template>
  
    <button @click="getAuthTokenInfo" :disabled="loading">
      {{ loading ? "Authenticating..." : "Get Identity Token" }}
    </button>
    Token: {{ token }}
    Error: {{ error.message }}
  
</template>
```

### Return type

```ts

```

#### `loading`

`Ref<boolean>`

Whether the authentication process is in progress.

#### `error`

`Ref<Web3AuthError | null>`

Error that occurred during the authentication process.

#### `token`

`Ref<string | null>`

The identity token returned after successful authentication.

#### `getAuthTokenInfo`

`() => Promise<string | null>`

Function to initiate the authentication process and retrieve the identity token.

---

## useCheckout(Composables)

Composable to show the cryptocurrency checkout modal using Wallet Services plugin.

:::info

Please note that this composable doesn't work for external wallet logins. It only works for social login embedded wallets.

:::

### Import

```ts

```

### Usage

```html
<script setup lang="ts">

  const { showCheckout, loading, error } = useCheckout()
</script>

<template>
  <button @click="showCheckout" :disabled="loading">
    {{ loading ? "Opening Checkout..." : "Show Checkout" }}
  </button>
  Error: {{ error.message }}
</template>
```

### Return type

```ts

```

#### `loading`

`boolean`

Whether the checkout process is in progress.

#### `error`

`Web3AuthError | null`

Error that occurred during the checkout process.

#### `showCheckout`

`(showCheckoutParams?: BaseEmbedControllerState["showCheckout"]) => Promise<void>`

Function to initiate the checkout modal. Optional `showCheckoutParams` can be passed to customize the modal.

---

## useEnableMFA(Composables)

Composable to enable Multi-Factor Authentication (MFA) using Embedded Wallets in Vue.

:::info

Please note that this composable doesn't work for external wallet logins. It only works for social login embedded wallets.

:::

### Import

```ts

```

### Usage

```html
<script setup lang="ts">

  const { enableMFA, loading, error } = useEnableMFA()
</script>

<template>
  <button @click="enableMFA" :disabled="loading">
    {{ loading ? "Enabling MFA..." : "Enable MFA" }}
  </button>
  {{ error.message }}
</template>
```

### Return type

```ts

```

#### `loading`

`Ref<boolean>`

Whether the MFA enabling process is in progress.

#### `error`

`Ref<Web3AuthError | null>`

Error that occurred during the MFA enabling process.

#### `enableMFA`

`<T>(params?: T) => Promise<void>`

Function to initiate the MFA enabling process. Accepts optional parameters depending on the MFA method or configuration required by your implementation.

---

## useManageMFA(Composables)

Hook to manage Multi-Factor Authentication (MFA) using Embedded Wallets. This composable provides a convenient way to trigger MFA management actions, such as updating or configuring MFA settings for the user.

:::info

Please note that this composable doesn't work for external wallet logins. It only works for social login embedded wallets.

:::

### Import

```ts

```

### Usage

```html
<script setup lang="ts">

  const { manageMFA, loading, error } = useManageMFA()
</script>

<template>
  <button @click="manageMFA" :disabled="loading">
    {{ loading ? "Managing MFA..." : "Manage MFA" }}
  </button>
  {{ error.message }}
</template>
```

### Return type

```ts

```

#### `loading`

`boolean`

Whether the MFA management process is in progress.

#### `error`

`Web3AuthError | null`

Error that occurred during the MFA management process.

#### `manageMFA`

`<T>(params?: T) => Promise<void>`

Function to initiate the MFA management process. Accepts optional parameters depending on the MFA action or configuration required by your implementation.

---

## useSwap(Composables)

Hook to open the swap interface using the Wallet Services plugin.

:::info

Please note that this composable doesn't work for external wallet logins. It only works for social login embedded wallets.

:::

### Import

```ts

```

### Usage

```html
<script setup lang="ts">

  const { showSwap, loading, error } = useSwap()
</script>

<template>
  <button @click="showSwap()" :disabled="loading">
    {{ loading ? "Opening Swap..." : "Open Swap" }}
  </button>
  Error: {{ error.message }}
</template>
```

### Return type

```ts

```

#### `loading`

`boolean`

Whether the swap interface is being opened.

#### `error`

`Web3AuthError | null`

Error that occurred while opening the swap interface.

#### `showSwap`

`(showSwapParams?: BaseEmbedControllerState["showSwap"]) => Promise<void>`

Function to open the swap interface. Accepts optional parameters for customizing the swap view.

---

## useSwitchChain(Composables)

Composable to switch blockchain networks with Embedded Wallets in Vue.

### Import

```ts

```

### Usage

```html
<script setup lang="ts">

  const { switchChain, loading, error } = useSwitchChain()
</script>

<template>
  <button @click="switchChain('0x1')" :disabled="loading">
    {{ loading ? "Switching..." : "Switch to Ethereum Mainnet" }}
  </button>
  Error: {{ error.message }}
</template>
```

### Return type

```ts

```

#### `loading`

`boolean`

Whether the chain switching process is in progress.

#### `error`

`Web3AuthError | null`

Error that occurred during the chain switching process.

#### `switchChain`

`(chainId: string) => Promise<void>`

Function to initiate the chain switch. Pass the target `chainId` as a string (for example, "0x1" for Ethereum Mainnet).

## Example

```html title="switchChain.vue"
<script setup lang="ts">

  const { web3Auth } = useWeb3Auth()
  const { switchChain, error } = useSwitchChain()

  const currentChainName = computed(() => web3Auth.value?.currentChain?.displayName || '')
</script>

<template>
  
    Switch Chain
    Connected to {{ currentChainName }}
    <button
      v-for="chain in web3Auth.value?.coreOptions?.chains"
      :key="chain.chainId"
      :disabled="web3Auth?.currentChain?.chainId === chain.chainId"
      @click="switchChain({ chainId: chain.chainId })"
      type="button"
      class="card">
      {{ chain.displayName }}
    </button>
    {{ error.message }}
  
</template>
```

---

## useWalletConnectScanner(Composables)

Composable to show the WalletConnect QR scanner using the Wallet Services plugin in Vue.

:::info

Please note that this composable doesn't work for external wallet logins. It only works for social login embedded wallets.

:::

### Import

```ts

```

### Usage

```html
<script setup>

  const { showWalletConnectScanner, loading, error } = useWalletConnectScanner()
</script>

<template>
  <button @click="showWalletConnectScanner()" :disabled="loading">
    {{ loading ? "Opening Scanner..." : "Show WalletConnect Scanner" }}
  </button>
  {{ error.message }}
</template>
```

### Return type

```ts

```

#### `loading`

`boolean`

Whether the scanner opening process is in progress.

#### `error`

`Web3AuthError | null`

Error that occurred during the scanner opening process.

#### showWalletConnectScanner

`(showWalletConnectScannerParams?: BaseEmbedControllerState["showWalletConnect"]) => Promise<void>`

Function to show the WalletConnect QR scanner. Accepts optional parameters for customizing the scanner behavior.

---

## useWalletServicesPlugin(Composables)

Hook to access the Wallet Services Ppugin context, enabling wallet-related features such as WalletConnect, checkout, swap, and wallet UI.

:::info

Please note that this composable doesn't work for external wallet logins. It only works for social login embedded wallets.

:::

### Import

```ts

```

### Usage

```html
<script setup lang="ts">

  const { isPluginConnected, showWalletConnectScanner, showCheckout, showWalletUI } =
    useWalletServicesPlugin()
</script>

<template>
  <button @click="showWalletConnectScanner()" :disabled="!isPluginConnected">
    Show WalletConnect Scanner
  </button>
  <button @click="showCheckout()" :disabled="!isPluginConnected">Show Checkout</button>
  <button @click="showWalletUI()" :disabled="!isPluginConnected">Show Wallet UI</button>
</template>
```

### Return type

```ts

```

#### `isPluginConnected`

`boolean`

Whether the Wallet Services plugin is connected and ready to use.

#### `showWalletConnectScanner`

`(showWalletConnectParams?: BaseEmbedControllerState["showWalletConnect"]) => Promise<void>`

Shows the WalletConnect QR scanner. Accepts optional parameters for customizing the scanner behavior.

#### `showCheckout`

`(showCheckoutParams?: BaseEmbedControllerState["showCheckout"]) => Promise<void>`

Shows the topup modal for fiat-to-crypto checkout. Accepts optional parameters for customizing the checkout experience.

#### `showWalletUI`

`(showWalletUiParams?: BaseEmbedControllerState["showWalletUi"]) => Promise<void>`

Shows the Wallet Services modal UI. Accepts optional parameters for customizing the wallet UI experience.

---

## useWalletUI(Composables)

Hook to show the Wallet Services UI modal using the Wallet Services plugin.

:::info

Please note that this composable doesn't work for external wallet logins. It only works for social login embedded wallets.

:::

### Import

```ts

```

### Usage

```html
<script setup>

  const { showWalletUI, loading, error } = useWalletUI()
</script>

<template>
  <button @click="showWalletUI" :disabled="loading">
    {{ loading ? "Opening Wallet UI..." : "Show Wallet UI" }}
  </button>
  {{ error.message }}
</template>
```

### Return type

```ts

```

#### `loading`

`boolean`

Whether the Wallet UI opening process is in progress.

#### `error`

`Web3AuthError | null`

Error that occurred during the Wallet UI opening process.

#### `showWalletUI`

`(showWalletUiParams?: BaseEmbedControllerState["showWalletUi"]) => Promise<void>`

Function to show the Wallet Services modal UI. Accepts optional parameters for customizing the wallet UI experience.

---

## useWeb3Auth(Composables)

Composable to access the Embedded Wallets/Web3Auth context in Vue.

### Import

```ts

```

### Usage

```html
<script setup lang="ts">

  const { web3Auth, isConnected, isInitializing, connection, status, initError } = useWeb3Auth()

  watchEffect(() => {
    if (isConnected.value) {
      console.log('Connected via:', connection.value?.connectorName)
    }
    if (isInitializing.value) {
      console.log('Web3Auth is initializing')
    }
    if (connection.value?.ethereumProvider) {
      console.log('Ethereum provider available')
    }
    if (status.value) {
      console.log('Web3Auth status:', status.value)
    }
    if (initError.value) {
      console.log('Web3Auth initialization error:', initError.value)
    }
  })
</script>
```

:::info

For EVM wallet operations, use [Wagmi composables](../ethereum-composables.mdx) after setting up
`WagmiProvider`.
Use `connection.ethereumProvider` only for JSON-RPC methods Wagmi does not cover.
See the [Web SDK v11 migration guide](/embedded-wallets/migration-guides/web#provider-api-changes-all-frameworks).

:::

### Return type

```ts

```

#### `connection`

`Ref<{ ethereumProvider, solanaWallet, connectorName } | null>`

Active wallet connection after sign-in.

#### `initError`

`Ref<Error | null>`

Error that occurred during Web3Auth initialization.

#### `isConnected`

`Ref<boolean>`

Whether the user is connected to Web3Auth.

#### `isInitialized`

`Ref<boolean>`

Whether Web3Auth has completed initialization.

#### `isInitializing`

`Ref<boolean>`

Whether Web3Auth is currently initializing.

#### `status`

`Ref<string>`

Current status of the Web3Auth connection.

#### `web3Auth`

`Ref<Web3Auth>`

The Web3Auth instance.

#### `getPlugin`

`(pluginName: PLUGIN_NAME) => IPlugin | null`

Helper function to get a plugin by name.

---

## useWeb3AuthConnect(Composables)

Composable to connect to Embedded Wallets in Vue.

### Import

```ts

```

### Choosing the right connection method

You can connect users to Embedded Wallets in two main ways, depending on your application's needs:

- **Use `connect()`** when you want to display the default Embedded Wallets/Web3Auth modal. This is ideal if you want to provide users with a pre-built, user-friendly interface where they can choose from all available login options (such as social logins, wallets) with minimal setup.

- **Use `connectTo(connector, params)`** when you want to build a fully custom login experience. This method lets you bypass the Embedded Wallets/Web3Auth modal and connect directly to a specific wallet connector (such as Google, Facebook, or a particular wallet). Choose this if you want to design your own UI for login options, or if you want to restrict users to a specific authentication method. This method also allows you to use JWT-based login configurations.

**Summary:**

- Use `connect()` for the standard modal experience.
- Use `connectTo()` for custom UIs or direct connection to a specific login method.

### Usage

<Tabs
  defaultValue="basic"
  values={[
    { label: "Basic Modal", value: "basic" },
    { label: "Custom UI", value: "custom-ui" },
  ]}
>

<TabItem value="basic">

:::info

This is the most common way to connect to Embedded Wallets/Web3Auth. It opens the Web3Auth modal UI, allowing users to select from available login options.

:::

```html
<script setup lang="ts">

  const { connect, loading, isConnected, error } = useWeb3AuthConnect()
</script>

<template>
  <button @click="connect" :disabled="loading || isConnected">
    Connecting...
    Connected
    Connect
  </button>
  {{ error.message }}
</template>
```

</TabItem>

<TabItem value="custom-ui">

:::info

This method allows you to build your own custom connection UI. It bypasses the Web3Auth modal UI, allowing you to create your own custom UI for login options. This can be useful if you want to hide Embedded Wallets from your end users.

:::

```html
<script setup lang="ts">

  const { connectTo, loading, isConnected, error } = useWeb3AuthConnect()

  const loginWithGoogle = () => {
    connectTo(WALLET_CONNECTORS.AUTH, { authConnection: AUTH_CONNECTION.GOOGLE })
  }
</script>

<template>
  <button @click="loginWithGoogle" :disabled="loading || isConnected">Login with Google</button>
  {{ error.message }}
</template>
```

</TabItem>

</Tabs>

### Return type

```ts

```

#### `isConnected`

`boolean`

Whether the user is connected to Web3Auth.

#### `loading`

`boolean`

Whether the connection process is in progress.

#### `error`

`Web3AuthError | null`

Error that occurred during the connection process.

#### `connectorName`

`WALLET_CONNECTOR_TYPE | null`

Name of the connected connector.

#### `connect`

`() => Promise<Connection | null>`

Function to initiate the connection process. Opens the Web3Auth modal UI.

#### `connectTo`

`<T extends WALLET_CONNECTOR_TYPE>(connector: T, params?: LoginParamMap[T]) => Promise<Connection | null>`

Function to connect directly to a specific wallet connector. This bypasses the Web3Auth modal UI, allowing you to build custom interfaces. This method also allows you to use JWT-based login configurations.

---

## useWeb3AuthDisconnect(Composables)

Hook to disconnect from Web3Auth.

### Import

```ts

```

### Usage

```html
<script setup lang="ts">

  const { disconnect, loading, error } = useWeb3AuthDisconnect()
</script>

<template>
  <button @click="disconnect()" :disabled="loading">
    {{ loading ? "Disconnecting..." : "Disconnect" }}
  </button>
  {{ error.message }}
</template>
```

### Return type

```ts

```

#### `loading`

`Ref<boolean>`

Whether the disconnection process is in progress.

#### `error`

`Ref<Web3AuthError | null>`

Error that occurred during the disconnection process.

#### `disconnect`

`(options?: { cleanup: boolean }) => Promise<void>`

Function to initiate the disconnection process. Optional `cleanup` parameter controls whether to remove all user data.

---

## useWeb3AuthUser(Composables)

Composable to fetch and manage the current Web3Auth user information in Vue.

In Web SDK v11, `userInfo` can include a `linkedAccounts` array when the user has linked external wallets.
See [User details](/embedded-wallets/dashboard/advanced/user-details/#richer-user-object-web-sdk-v11) and [Multi-wallet linking](/embedded-wallets/features/multi-wallet-linking/).

:::info

For external-wallet-only logins, profile fields may be limited compared to social or passwordless logins.
Use `linkedAccounts` to see every wallet linked to the same user.

:::

### Import

```ts

```

### Usage

```html
<script setup lang="ts">

  const { userInfo, loading, error, isMFAEnabled, getUserInfo } = useWeb3AuthUser()
</script>

<template>
  Loading user info...
  Error: {{ error.message }}
  No user info available.
  
    <pre>{{ JSON.stringify(userInfo, null, 2) }}</pre>
    MFA Enabled: {{ isMFAEnabled ? "Yes" : "No" }}
    <button @click="getUserInfo">Refresh User Info</button>
  
</template>
```

### Return type

```ts

```

#### `loading`

`boolean`

Whether the user info fetching process is in progress.

#### `error`

`Web3AuthError | null`

Error that occurred during the user info fetching process.

#### `userInfo`

`Partial<UserInfo> | null`

The current user's information, or null if not available.
May include `linkedAccounts` (array of linked wallet addresses and connectors) in Web SDK v11.

#### `isMFAEnabled`

`boolean`

Whether Multi-Factor Authentication (MFA) is enabled for the user.

#### `getUserInfo`

`() => Promise<Partial<UserInfo> | null>`

Function to fetch the latest user information from Web3Auth.

---

## Vue composables for Ethereum (via Wagmi)

Web3Auth supports composable-based Ethereum wallet operations in Vue via [Wagmi](https://wagmi.sh/). Once you have set up Wagmi using the Web3Auth Modal SDK (see the [setup guide](#wagmi-integration)), you can use all Wagmi composables directly in your application, no additional wrappers or configuration are needed beyond the initial setup.

## Wagmi integration

You need to install the `@wagmi/vue` and `@tanstack/vue-query` packages and use the **Web3Auth
implementation of `WagmiProvider`** for configuration.

:::info

The Web3Auth implementation of `WagmiProvider` is a custom implementation that is used to integrate
with the Web3Auth Modal SDK. It is a wrapper around the `WagmiProvider` that makes it compatible.

With this implementation, you can use the Wagmi composables, however **no external connectors are
supported**. Web3Auth provides a whole suite of connectors which you can use directly for a better
experience with external wallets.

:::

```bash npm2yarn
npm install @wagmi/vue @tanstack/vue-query
```

Update your `main.ts` to use the Vue Query plugin **only if you are using Wagmi**:

```ts title="main.ts"
// focus-next-line

// focus-next-line
createApp(App).use(VueQueryPlugin).mount('#app')
```

Then, in your `App.vue`, wrap your app with both providers:

```html title="App.vue"
<script setup lang="ts">

  // focus-next-line

</script>

<template>
  
    <Web3AuthProvider :config="web3AuthContextConfig">
      <!-- focus-start -->
      <WagmiProvider>
        <Home />
      </WagmiProvider>
      <!-- focus-end -->
    </Web3AuthProvider>
  
</template>
```

:::info

Wagmi provides a comprehensive set of composables for Ethereum and EVM-compatible chains in Vue.
Web3Auth integrates with Wagmi, so you can use composables like `useConnection`,
`useBalance`, `useSendTransaction`, and more, out of the box.

:::

Below are some examples of using Wagmi composables in your dapp after Web3Auth and Wagmi are set up.
You can note these functions work directly with Wagmi. Once you have set up Wagmi with Web3Auth, you
can use any Wagmi composable as you would in a standard Wagmi application.

### Get account balance

```html
<script setup lang="ts">

  const { address } = useConnection()
  const { data, isLoading, error } = useBalance({ address })
</script>

<template>
  
    Balance
    
      
        {{ formatUnits(data.value, data.decimals) }} {{ data.symbol }}
      
      Loading...
      Error: {{ error.message }}
    
  
</template>
```

### Send transaction

```html
<script setup lang="ts">

  const address = ref('')
  const value = ref('')
  const { data: hash, error, isPending, sendTransaction } = useSendTransaction()

  function submit() {
    sendTransaction({
      to: address.value,
      value: parseEther(value.value),
    })
  }

  const { isLoading: isConfirming, isSuccess: isConfirmed } = useWaitForTransactionReceipt({
    hash,
  })
</script>

<template>
  
    Send Transaction
    <form @submit.prevent="submit">
      <input v-model="address.value" name="address" placeholder="Address" required />
      <input
        v-model="value.value"
        name="value"
        placeholder="Amount (ETH)"
        type="number"
        step="0.000000001"
        required />
      <button :disabled="isPending" type="submit">
        {{ isPending ? "Confirming..." : "Send" }}
      </button>
    </form>
    Transaction Hash: {{ hash }}
    Waiting for confirmation...
    Transaction confirmed.
    Error: {{ error.shortMessage || error.message }}
  
</template>
```

### Switch chain

```html
<script setup lang="ts">

  const chainId = useChainId()
  const { chains, switchChain, error } = useSwitchChain()
</script>

<template>
  
    Switch Chain
    Connected to {{ chainId }}
    
      <button
        v-for="chain in chains"
        :key="chain.id"
        :disabled="chainId === chain.id"
        @click="switchChain({ chainId: chain.id })"
        type="button"
        class="card">
        {{ chain.name }}
      </button>
    
    {{ error.message }}
  
</template>
```

---

## Examples - PnP Vue SDK

<ExampleCards exampleMap={[...webExamples].filter(obj => obj.tags?.includes('vue'))} />

---

## Vue composables for Solana

Embedded Wallets provides a set of Vue composables for basic Solana wallet operations. These composables are designed to simplify common Solana interactions in your Vue app.

:::info

For building transactions, use [`@solana/kit`](https://www.npmjs.com/package/@solana/kit) and [`@solana-program/system`](https://www.npmjs.com/package/@solana-program/system) with the composables provided.

:::

Install `@solana/kit` and `@solana-program/system` to build and sign Solana transactions with the Embedded Wallets Vue SDK.

:::info

Web3Auth provides Vue composables for common Solana wallet operations. Import them from `@web3auth/modal/vue/solana`.

:::

```bash npm2yarn
npm install @solana/kit @solana-program/system
```

## Solana composables

| Composable Name             | Description                                     |
| --------------------------- | ----------------------------------------------- |
| `useSignAndSendTransaction` | Sign and send a Solana transaction.             |
| `useSignMessage`            | Sign a message with the Solana wallet.          |
| `useSignTransaction`        | Sign a Solana transaction (without sending).    |
| `useSolanaWallet`           | Access Solana accounts, RPC client, and wallet. |

## Composable usage examples

### Get Solana wallet

<GetSolanaWallet />

### Fetch balance

<FetchBalance />

### Sign message

<SignMessage />

### Sign transaction

<SignTransaction />

### Sign and send transaction

<SignAndSendTransaction />

---

## useSignAndSendTransaction(Solana-composables)

Composable to sign and send a Solana transaction using the connected Solana wallet from Web3Auth in Vue.

### Import

```ts

```

### Usage

```html
<script setup lang="ts">

  const transaction = ref<TransactionOrVersionedTransaction | null>(null) // Provide your transaction here
  const { signAndSendTransaction, loading, error, data } = useSignAndSendTransaction()

  const handleSignAndSend = async () => {
    if (!transaction.value) return
    try {
      await signAndSendTransaction(transaction.value)
      // Do something with data.value (signature)
    } catch (e) {
      // Handle error
    }
  }
</script>

<template>
  
    <button @click="handleSignAndSend" :disabled="loading">
      {{ loading ? "Signing & Sending..." : "Sign & Send Transaction" }}
    </button>
    Error: {{ error.message }}
    Signature: {{ data }}
  
</template>
```

### Return type

```ts
export type IUseSignAndSendTransaction = {
  loading: boolean
  error: Web3AuthError | null
  data: string | null
  signAndSendTransaction: (transaction: TransactionOrVersionedTransaction) => Promise<string>
}
```

#### `loading`

`boolean`

Indicates if the transaction signing and sending is in progress.

#### `error`

`Web3AuthError | null`

Error object if signing or sending fails, otherwise null.

#### `data`

`string | null`

The transaction signature as a string, or null if not signed yet.

#### `signAndSendTransaction`

`(transaction: TransactionOrVersionedTransaction) => Promise<string>`

Function to sign and send a transaction. Returns the transaction signature as a string.

## Example

```vue title="SendVersionedTransaction.vue"
<script setup lang="ts">

  const { web3Auth } = useWeb3Auth()
  const { accounts } = useSolanaWallet()
  const {
    data: signature,
    error,
    loading: isPending,
    signAndSendTransaction,
  } = useSignAndSendTransaction()
  const formError = ref<string | null>(null)

  async function submit(event: Event) {
    event.preventDefault()
    formError.value = null

    const rpcTarget = web3Auth.value?.currentChain?.rpcTarget
    if (!rpcTarget || !accounts.value?.length) return

    const form = new FormData(event.target as HTMLFormElement)
    const to = form.get('address')?.toString().trim() ?? ''
    const amountSol = Number(form.get('value'))
    if (!to || !Number.isFinite(amountSol) || amountSol <= 0) {
      formError.value = 'Enter a valid recipient address and a positive amount.'
      return
    }

    try {
      const transaction = await buildSolTransferTransaction(
        rpcTarget,
        accounts.value[0],
        to,
        amountSol
      )
      await signAndSendTransaction(transaction)
    } catch (err) {
      formError.value = err instanceof Error ? err.message : 'Failed to send transaction.'
    }
  }
</script>

<template>
  
    Send Transaction
    <form @submit.prevent="submit">
      <input name="address" placeholder="Recipient address" required />
      <input name="value" placeholder="Amount (SOL)" type="number" step="0.01" min="0" required />
      <button type="submit" :disabled="isPending">
        {{ isPending ? 'Sending...' : 'Send' }}
      </button>
    </form>
    Transaction signature: {{ signature }}
    
      Error: {{ formError ?? error?.message }}
    
  
</template>
```

---

## useSignMessage(Solana-composables)

Composable to sign a message using the connected Solana wallet from Web3Auth in Vue.

### Import

```ts

```

### Usage

```html
<script setup lang="ts">

  const message = ref('')
  const { signMessage, loading, error, data } = useSignMessage()

  const handleSign = async () => {
    try {
      await signMessage(message.value)
      // Do something with data.value
    } catch (e) {
      // Handle error
    }
  }
</script>

<template>
  
    <input v-model="message" placeholder="Message" />
    <button @click="handleSign" :disabled="loading">
      {{ loading ? "Signing..." : "Sign Message" }}
    </button>
    Error: {{ error.message }}
    Signature: {{ data }}
  
</template>
```

### Return Type

```ts
export type IUseSignMessage = {
  loading: boolean
  error: Web3AuthError | null
  data: string | null
  signMessage: (message: string) => Promise<string>
}
```

#### loading

`boolean`

Indicates if the message signing is in progress.

#### error

`Web3AuthError | null`

Error object if signing fails, otherwise null.

#### data

`string | null`

The signature as a string, or null if not signed yet.

#### signMessage

`(message: string) => Promise<string>`

Function to sign a message. Returns the signature as a string.

## Example

```vue title="SignMessage.vue"
<script setup lang="ts">

  const { signMessage, loading, error, data } = useSignMessage()

  function submit(event: Event) {
    event.preventDefault()
    const formData = new FormData(event.target as HTMLFormElement)
    const message = formData.get('message')?.toString().trim()
    if (!message) return
    void signMessage(message)
  }
</script>

<template>
  <form @submit.prevent="submit">
    <input name="message" placeholder="Message" required />
    <button :disabled="loading" type="submit">
      {{ loading ? 'Signing...' : 'Sign message' }}
    </button>
    Message hash: {{ data }}
    Error: {{ error.message }}
  </form>
</template>
```

---

## useSignTransaction(Solana-composables)

Composable to sign a Solana transaction using the connected wallet from Web3Auth.

### Import

```ts

```

### Usage

```html
<script setup lang="ts">

  const transaction = ref<Transaction | null>(null) // Your transaction object
  const { signTransaction, loading, error, data } = useSignTransaction()

  const handleSign = async () => {
    if (!transaction.value) return
    try {
      await signTransaction(transaction.value)
      // Do something with data.value (signed transaction)
    } catch (e) {
      // Handle error
    }
  }
</script>

<template>
  
    <button @click="handleSign" :disabled="loading">
      {{ loading ? "Signing..." : "Sign Transaction" }}
    </button>
    Error: {{ error.message }}
    Signed Transaction: {{ data }}
  
</template>
```

### Return type

```ts
export type IUseSignTransaction = {
  loading: Ref<boolean>
  error: Ref<Web3AuthError | null>
  data: Ref<string | null>
  signTransaction: (transaction: TransactionOrVersionedTransaction) => Promise<string>
}
```

#### `loading`

`Ref<boolean>`

Indicates if the transaction signing is in progress.

#### `error`

`Ref<Web3AuthError | null>`

Error object if signing fails, otherwise null.

#### `data`

`Ref<string | null>`

The signed transaction as a string, or null if not signed yet.

#### `signTransaction`

`(transaction: TransactionOrVersionedTransaction) => Promise<string>`

Function to sign a Solana transaction. Returns the signed transaction as a string.

## Example

```vue title="SignTransaction.vue"
<script setup lang="ts">

  const { web3Auth } = useWeb3Auth()
  const { accounts } = useSolanaWallet()
  const {
    data: signedTransaction,
    error,
    loading: isPending,
    signTransaction,
  } = useSignTransaction()
  const formError = ref<string | null>(null)

  async function submit(event: Event) {
    event.preventDefault()
    formError.value = null

    const rpcTarget = web3Auth.value?.currentChain?.rpcTarget
    if (!rpcTarget || !accounts.value?.length) return

    const form = new FormData(event.target as HTMLFormElement)
    const to = form.get('address')?.toString().trim() ?? ''
    const amountSol = Number(form.get('value'))
    if (!to || !Number.isFinite(amountSol) || amountSol <= 0) {
      formError.value = 'Enter a valid recipient address and a positive amount.'
      return
    }

    try {
      const transaction = await buildSolTransferTransaction(
        rpcTarget,
        accounts.value[0],
        to,
        amountSol
      )
      await signTransaction(transaction)
    } catch (err) {
      formError.value = err instanceof Error ? err.message : 'Failed to sign transaction.'
    }
  }
</script>

<template>
  
    Sign Transaction
    <form @submit.prevent="submit">
      <input name="address" placeholder="Recipient address" required />
      <input name="value" placeholder="Amount (SOL)" type="number" step="0.01" min="0" required />
      <button type="submit" :disabled="isPending">
        {{ isPending ? 'Signing...' : 'Sign' }}
      </button>
    </form>
    Signed transaction: {{ signedTransaction }}
    
      Error: {{ formError ?? error?.message }}
    
  
</template>
```

```ts title="solana/transfer.ts"

  address,
  appendTransactionMessageInstruction,
  compileTransaction,
  createNoopSigner,
  createSolanaRpc,
  createTransactionMessage,
  lamports,
  pipe,
  setTransactionMessageFeePayerSigner,
  setTransactionMessageLifetimeUsingBlockhash,
} from '@solana/kit'

export async function buildSolTransferTransaction(
  rpcTarget: string,
  from: string,
  to: string,
  amountSol: number
): Promise<Transaction> {
  const rpc = createSolanaRpc(rpcTarget)
  const { value: latestBlockhash } = await rpc.getLatestBlockhash().send()
  const feePayer = createNoopSigner(address(from))

  const message = pipe(
    createTransactionMessage({ version: 0 }),
    m => setTransactionMessageFeePayerSigner(feePayer, m),
    m => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, m),
    m =>
      appendTransactionMessageInstruction(
        getTransferSolInstruction({
          source: feePayer,
          destination: address(to),
          amount: lamports(BigInt(Math.round(amountSol * 1e9))),
        }),
        m
      )
  )

  return compileTransaction(message)
}
```

---

## useSolanaWallet(Solana-composables)

Composable to retrieve Solana accounts, RPC client, and wallet from Embedded Wallets in Vue.

### Import

```ts

```

### Usage

```vue
<script setup lang="ts">

  const { accounts, rpc, solanaWallet } = useSolanaWallet()
</script>

<template>
  
    Accounts: {{ accounts?.length ? accounts.join(', ') : 'No accounts' }}
    Solana wallet: {{ solanaWallet ? 'Available' : 'Not available' }}
    RPC: {{ rpc ? 'Available' : 'Not available' }}
  
</template>
```

### Return type

```ts

```

#### `accounts`

`Ref<string[] | null>`

Base58 Solana account addresses, or `null` if not available.

#### `solanaWallet`

`Ref<Wallet | null>`

The wallet-standard Solana wallet instance, or `null` if not available.

#### `rpc`

`Ref<Rpc<SolanaRpcApi> | null>`

The `@solana/kit` RPC client for making Solana RPC calls, or `null` if not available.

### Example: Fetching SOL balance

```vue title="getBalance.vue"
<script setup lang="ts">

  const { web3Auth } = useWeb3Auth()
  const { accounts } = useSolanaWallet()

  const balance = ref<string | null>(null)
  const loading = ref(false)
  const error = ref<string | null>(null)

  async function fetchBalance() {
    const rpcTarget = web3Auth.value?.currentChain?.rpcTarget
    if (!rpcTarget || !accounts.value?.length) return

    loading.value = true
    error.value = null
    try {
      const rpc = createSolanaRpc(rpcTarget)
      const { value } = await rpc.getBalance(address(accounts.value[0])).send()
      balance.value = `${Number(value) / 1e9} SOL`
    } catch (e) {
      error.value = e instanceof Error ? e.message : 'Failed to fetch balance.'
    } finally {
      loading.value = false
    }
  }
</script>

<template>
  
    Balance
    {{ balance }}
    <button type="button" class="card" :disabled="loading" @click="fetchBalance">
      {{ loading ? 'Fetching...' : 'Fetch Balance' }}
    </button>
    Error: {{ error }}
  
</template>
```
