For AI agents: a documentation index is available at /llms.txt. A markdown version of this page is available at the same URL with .md appended (or via Accept: text/markdown).
Skip to main content

Web SDK v11 Migration Guide

This guide upgrades Embedded Wallets Web SDK integrations from v9 or v10 directly to v11 for JavaScript (@web3auth/modal), React (@web3auth/modal/react), and Vue (@web3auth/modal/vue).

Platform scope

This guide applies to the Web SDK only. Android, iOS, React Native, Flutter, Unity, and Unreal SDKs follow separate version lines and migration guides.

AI-assisted migration​

For the best results, install the Web3Auth by MetaMask, Embedded Wallet SDK skill and MCP server before you migrate. See Build with AI for setup (npx skills add web3auth/skill and MCP at https://mcp.web3auth.io).

Copy the prompt below into your AI coding assistant (Cursor, Claude Code, Codex, Antigravity, or similar):

Migrate my Embedded Wallet SDK (@web3auth/modal) project to v11.

Before changing code:
1. Use the web3auth skill and MCP tools (search_docs, get_doc, get_example, get_sdk_reference).
2. Read the migration guide: https://docs.metamask.io/embedded-wallets/migration-guides/web
3. Detect my framework (JavaScript, React, or Vue) and my current SDK version (v9 or v10).

Then migrate my codebase directly to v11:
- If on v9 modal: apply v9 breaking changes (dashboard chains, initModal() to init(), connectTo, hooks paths, @web3auth/base imports) and v11 changes (connection, Solana kit, polyfills) in one pass.
- If on v9 no-modal: migrate to @web3auth/modal@11, replace Web3AuthNoModal/adapters with connectTo() and dashboard connections, then apply v11 provider/Solana changes.
- If on v10: apply v11 changes only (connection, connect()/connectTo() now return Connection, connectedConnector* renamed to primaryConnector*, CONNECTED event payload, Solana kit, polyfills, wagmi v3, getIdentityToken/useIdentityToken renamed to getAuthTokenInfo/useAuthTokenInfo).
- Update package.json dependencies (including viem >= 2.45) and remove deprecated packages.
- Stop using web3auth.provider / useWeb3Auth().provider. Prefer connection and Wagmi/Solana hooks; use connection.ethereumProvider only when hooks cannot cover the call.
- For Solana apps: migrate from @solana/web3.js to @solana/kit and use the rpc client from useSolanaWallet (hooks stay in @web3auth/modal/react/solana or @web3auth/modal/vue/solana).
- Remove buffer/process/global polyfills added for older SDK versions, but keep any that my chain-specific libraries still need.
- Do not change my Client ID or Sapphire network unless I ask; that would change wallet addresses.

After migrating, list every file you changed and any manual dashboard steps I still need to do.
tip

Use planning mode (where available) for the initial prompt. Review the plan before generating code; config mistakes can change wallet addresses in production.

Install v11​

npm install @web3auth/modal@11

From v9 no-modal: uninstall legacy packages first, then install the unified SDK:

npm uninstall @web3auth/no-modal @web3auth/auth-adapter @web3auth/wallet-services-plugin
npm install @web3auth/modal@11

Remove other v9 packages that @web3auth/modal now replaces, wherever present:

npm uninstall @web3auth/base @web3auth/ethereum-provider @web3auth/solana-provider @web3auth/default-evm-adapter @web3auth/default-solana-adapter @web3auth/wallet-connect-v2-adapter @web3auth/coinbase-adapter @web3auth/account-abstraction-provider @web3auth/modal-react-hooks @web3auth/no-modal-react-hooks @web3auth/wallet-services-plugin-react-hooks @web3auth/modal-vue-composables @web3auth/no-modal-vue-composables @web3auth/wallet-services-plugin-vue-composables

Then update imports such as WEB3AUTH_NETWORK, CHAIN_NAMESPACES, and IProvider from @web3auth/base to @web3auth/modal.

@web3auth/modal@11 declares viem (>=2.45), @solana/kit (>=6.5.0), and @solana/client (^1.7.0) as required peer dependencies, even for EVM-only apps. npm 7 and later installs them automatically; with pnpm or Yarn, or if your app pins an older viem, install or upgrade them explicitly:

npm install viem@^2.45

Do not install @web3auth/ethereum-provider (or other v9 provider packages) with v11. Configure EVM chains on the dashboard, or pass custom chains through the chains option in Web3AuthOptions. The privateKeyProvider option remains only for XRPL (XrplPrivateKeyProvider from @web3auth/modal/providers/xrpl-provider).

For Solana apps, also install:

npm install @solana/kit @solana-program/system @solana/react-hooks

@solana/react-hooks is declared as an optional peer dependency, but React Solana apps must install it because @web3auth/modal/react/solana imports it. Vue Solana apps use @web3auth/modal/vue/solana and do not need @solana/react-hooks.

React and Vue apps using EVM with Wagmi should upgrade to Wagmi v3 (React) or @wagmi/vue (Vue):

npm install wagmi@3 @tanstack/react-query

For Vue:

npm install @wagmi/vue @tanstack/vue-query

For Vue, also register Vue Query in main.ts:

import { VueQueryPlugin } from '@tanstack/vue-query'

createApp(App).use(VueQueryPlugin).mount('#app')

Migrating from v9​

If you're on v9, apply the sections below together with v11 API changes. Version 10 consolidated modal and no-modal flows into @web3auth/modal, moved configuration to the Embedded Wallets dashboard, and integrated Wallet Services and smart accounts into the main SDK; v11 keeps that model and adds the connection API and Solana kit migration described later.

No-modal SDK (v9)​

Recommended: use @web3auth/modal

While @web3auth/no-modal received updates in v9, v11 uses @web3auth/modal for custom UI flows. The modal package supports both the pre-built UI (connect()) and headless custom UI (connectTo()).

Package and class migration​

v9

import { Web3AuthNoModal } from '@web3auth/no-modal'
import { AuthAdapter } from '@web3auth/auth-adapter'

const web3auth = new Web3AuthNoModal({
clientId: 'YOUR_CLIENT_ID',
web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
chainConfig,
privateKeyProvider,
})

v11

import { Web3Auth, WEB3AUTH_NETWORK } from '@web3auth/modal'

const web3auth = new Web3Auth({
clientId: 'YOUR_CLIENT_ID',
web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
})

Custom UI with connectTo​

v9

const authAdapter = new AuthAdapter({
adapterSettings: {
loginConfig: {
google: {
verifier: 'YOUR_GOOGLE_VERIFIER_NAME',
typeOfLogin: 'google',
clientId: 'YOUR_GOOGLE_CLIENT_ID.apps.googleusercontent.com',
},
},
},
})

web3auth.configureAdapter(authAdapter)
await web3auth.init()

await web3auth.connectTo('auth', {
loginProvider: 'google',
})

v11

import { AUTH_CONNECTION, WALLET_CONNECTORS, WEB3AUTH_NETWORK, Web3Auth } from '@web3auth/modal'

await web3auth.init()

await web3auth.connectTo(WALLET_CONNECTORS.AUTH, {
authConnection: AUTH_CONNECTION.GOOGLE,
})

// Or with a dashboard connection ID
await web3auth.connectTo(WALLET_CONNECTORS.AUTH, {
authConnection: AUTH_CONNECTION.GOOGLE,
authConnectionId: 'YOUR_GOOGLE_AUTH_CONNECTION_ID',
})

Verifiers and aggregate verifiers from v9 map to dashboard connections. See Custom authentication.

After sign-in, read the EVM provider from web3auth.connection?.ethereumProvider (see v11 API changes).

Remove packages such as @web3auth/auth-adapter and @web3auth/wallet-services-plugin. Wallet Services is built into @web3auth/modal.

If your no-modal init passed chainConfig and EthereumPrivateKeyProvider, remove them and use dashboard chain configuration instead.

General changes (all frameworks)​

Centralized chain configuration​

Remove EthereumPrivateKeyProvider, chainConfig, and privateKeyProvider from Web3AuthOptions for standard EVM chains. Configure chains on the Embedded Wallets dashboard.

import { Web3Auth, WEB3AUTH_NETWORK } from '@web3auth/modal'

const web3auth = new Web3Auth({
clientId: WEB3AUTH_CLIENT_ID,
web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
})

Multi-Factor Authentication (MFA)​

Move MFA settings from AuthAdapter to Web3AuthOptions:

import { MFA_FACTOR, MFA_LEVELS, WEB3AUTH_NETWORK, type Web3AuthOptions } from '@web3auth/modal'

const web3AuthOptions: Web3AuthOptions = {
clientId: 'YOUR_CLIENT_ID',
web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
mfaLevel: MFA_LEVELS.MANDATORY,
mfaSettings: {
[MFA_FACTOR.DEVICE]: { enable: true, priority: 1, mandatory: true },
[MFA_FACTOR.BACKUP_SHARE]: { enable: true, priority: 2, mandatory: true },
},
}

Method renames​

v9v11
useCoreKitKey: trueuseSFAKey: true
web3auth.authenticateUser()web3auth.getAuthTokenInfo()

Wallet Services, whitelabeling, smart accounts, custom auth​

v9 approachv11 approach
@web3auth/wallet-services-pluginBuilt into @web3auth/modal; see Wallet Services
uiConfig / adapter whitelabelDashboard customization; uiConfig in Web3AuthOptions still works as an override. See Whitelabel
@web3auth/account-abstraction-providerDashboard-managed smart accounts; see Smart accounts
Verifiers / aggregate verifiersDashboard connections; see Custom authentication

Framework-specific changes​

Use @web3auth/modal for both modal and custom UI flows.

Modal UI (v9):

import { CHAIN_NAMESPACES, WEB3AUTH_NETWORK } from '@web3auth/base'
import { EthereumPrivateKeyProvider } from '@web3auth/ethereum-provider'
import { Web3Auth } from '@web3auth/modal'

const chainConfig = {
chainNamespace: CHAIN_NAMESPACES.EIP155,
chainId: '0x1',
rpcTarget: 'YOUR_RPC_URL',
}
const privateKeyProvider = new EthereumPrivateKeyProvider({ config: { chainConfig } })

const web3auth = new Web3Auth({
clientId: WEB3AUTH_CLIENT_ID,
web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
privateKeyProvider,
})

await web3auth.initModal() // or initModal({ modalConfig })
await web3auth.connect()

const provider = web3auth.provider

v11 (modal UI):

import { Web3Auth, WEB3AUTH_NETWORK } from '@web3auth/modal'

const web3auth = new Web3Auth({
clientId: WEB3AUTH_CLIENT_ID,
web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
// modalConfig moves from initModal() to the constructor (optional)
})

await web3auth.init()
await web3auth.connect()

const provider = web3auth.connection?.ethereumProvider ?? null

initModal() is replaced by init(), and modalConfig moves from initModal() into the Web3Auth constructor options. Chains come from the dashboard instead of chainConfig and privateKeyProvider.

Custom UI (v9 no-modal): see No-modal SDK (v9) for connectTo() and connection ID migration. After connectTo(), use web3auth.connection?.ethereumProvider.

v11 API changes​

Web SDK v11 centers on two breaking themes:

  1. Direct provider access removed: see Prefer connection over direct provider access.
  2. Solana SDK replaced: @solana/web3.js is no longer the primary RPC surface. Use @solana/kit, @solana-program/system, and Solana hooks from @web3auth/modal/react/solana or @web3auth/modal/vue/solana.

If you're already on v10, this section is the main code update. If you're on v9, apply it together with Migrating from v9.

Prefer connection over direct provider access​

In earlier versions, many apps stored web3auth.provider or const { provider } = useWeb3Auth() in global state and passed it through the component tree. That made it easy to call JSON-RPC before sign-in finished, or to keep using a provider after the user disconnected.

v11 removes that direct provider surface. Use connection instead: it is set only after a successful sign-in and groups the active wallet APIs in one place:

FieldUse for
connection.ethereumProviderEIP-1193 EVM provider (when hooks are not enough)
connection.solanaWalletSolana wallet surface for kit-based flows
connection.connectorNameWhether the user signed in with Embedded Wallets (auth) or an external wallet
connection.connectorNamespaceNamespace of the active connector, such as eip155, solana, or multichain (v11.2.0+)

How to migrate​

  1. EVM (React/Vue): Use Wagmi hooks from @web3auth/modal/react/wagmi or @web3auth/modal/vue/wagmi for accounts, balances, sends, and message signing.
  2. Solana: Use hooks from @web3auth/modal/react/solana or @web3auth/modal/vue/solana.
  3. Non-EVM chains, custom JSON-RPC, or library bridges: Read connection, then call connection.ethereumProvider (or connection.solanaWallet) only for methods those hooks do not cover, such as private_key, public_key, or chain-specific RPC.

useWeb3Auth() no longer returns provider. On the Web3Auth class, provider is a setter only; reading web3auth.provider returns undefined. Treat any remaining provider variable in your app as connection?.ethereumProvider (or migrate the call site to Wagmi/Solana hooks).

Audit your codebase

Search for .provider, useWeb3Auth().provider, and props named provider passed into helpers. Most EVM call sites can move to Wagmi; the rest should source connection once per sign-in session.

Provider API changes (all frameworks)​

useWeb3Auth() no longer returns provider​

v10

const { provider } = useWeb3Auth()
const accounts = await provider.request({ method: 'eth_accounts' })

v11

const { connection } = useWeb3Auth()
// connection: { ethereumProvider, solanaWallet, connectorName, connectorNamespace }

Start from connection (see Prefer connection over direct provider access). Reach connection.ethereumProvider only when no Wagmi or Solana hook answers your question, for example:

  • Extracting a raw private key for non-EVM chains
  • Custom JSON-RPC methods (for example, xrpl_*)
  • Wrapping in ethers.BrowserProvider for libraries that require an EIP-1193 provider
  • Fetching the app public key for social-login server-side verification

For EVM work in React and Vue, prefer Wagmi hooks (useConnection, useBalance, useSendTransaction, useSignMessage). They receive the provider through the Web3Auth connector and do not need manual wiring.

Web3Auth class: use connection.ethereumProvider instead of provider​

In v11, provider on the Web3Auth class is a setter only. Reading web3auth.provider at runtime returns undefined. Use web3auth.connection?.ethereumProvider instead.

v10

const provider = web3auth.provider

v11

const provider = web3auth.connection?.ethereumProvider ?? null

connect() and connectTo() return Connection​

web3auth.connect(), web3auth.connectTo(), and the connect and connectTo functions from useWeb3AuthConnect() now resolve to a Connection | null instead of an IProvider | null.

v10

const provider = await web3auth.connect()
const accounts = await provider?.request({ method: 'eth_accounts' })

v11

const connection = await web3auth.connect()
const provider = connection?.ethereumProvider ?? null
const accounts = await provider?.request({ method: 'eth_accounts' })

Renamed Web3Auth class getters​

v10v11
web3auth.connectedConnectorNameweb3auth.primaryConnectorName
web3auth.connectedConnectorweb3auth.primaryConnector

web3auth.clearCache() is now async and returns a Promise<void>; await it.

CONNECTED event payload​

The CONNECTOR_EVENTS.CONNECTED payload is now the Connection fields plus reconnected (and an optional pendingUserConsent). identityTokenInfo is removed from the payload, and the IdentityTokenInfo type is renamed to AuthTokenInfo.

v10

web3auth.on(CONNECTOR_EVENTS.CONNECTED, data => {
console.log(data.connector, data.provider, data.reconnected)
})

v11

web3auth.on(CONNECTOR_EVENTS.CONNECTED, data => {
console.log(data.connectorName, data.ethereumProvider, data.reconnected)
})

When you still need connection.ethereumProvider​

Use it only for JSON-RPC edge cases Wagmi does not cover:

  • private_key for non-EVM chain derivation
  • public_key for social-login server verification
  • Custom JSON-RPC methods

For external wallets, use Wagmi useConnection().address instead of eth_accounts.

const pubKey = await connection?.ethereumProvider?.request({ method: 'public_key' })

Migration recipes (v10 → v11)​

Use the recipe that matches your app. See Provider API changes for the underlying API shift.

Recipe A: EVM apps using Wagmi only (Wagmi v3 hook rename)​

If your app already uses Wagmi hooks from @web3auth/modal/react/wagmi or @web3auth/modal/vue/wagmi and never reads useWeb3Auth().provider, update hook names for Wagmi v3: useAccount is deprecated in favor of useConnection. Wagmi v3 has other breaking changes; see the Wagmi v3 migration guide.

import { useConnection, useBalance } from 'wagmi'

const { address } = useConnection()
const { data: balance } = useBalance({ address })

Recipe B: Non-EVM chains that need the private key (React)​

Chains such as Algorand, Aptos, Cosmos, Polkadot, Starknet, Sui, and Tron often need the raw private key. Extract it once in a useEffect, store it in state, and pass the string to helper functions.

v10 RPC helper

export async function getAccounts(provider: IProvider): Promise<string> {
const privateKey = await provider.request({ method: 'private_key' })
// ... use privateKey
}

v11 RPC helper: takes privateKey: string directly; no IProvider import in the helper

export async function getAccounts(privateKey: string): Promise<string> {
// ... use privateKey
}

v10 component

const { provider } = useWeb3Auth()

const onGetAccounts = async () => {
const accounts = await getAccounts(provider)
}

v11 component

import { useEffect, useState } from 'react'
import { useWeb3Auth } from '@web3auth/modal/react'

const { connection } = useWeb3Auth()
const [privateKey, setPrivateKey] = useState<string | null>(null)

useEffect(() => {
if (!connection?.ethereumProvider) return
;(connection.ethereumProvider.request({ method: 'private_key' }) as Promise<string>)
.then(k => setPrivateKey(k ?? null))
.catch(console.error)
}, [connection])

const onGetAccounts = async () => {
if (!privateKey) return
await getAccounts(privateKey)
}

See connect-blockchain for chain-specific helpers.

Recipe C: Libraries that require IProvider (XMTP, XRPL, multi-chain)​

When a library needs an ethers.BrowserProvider wrapper or custom RPC methods, keep IProvider in helper signatures and source it from connection at each call site.

v10

const { provider } = useWeb3Auth()
const accounts = await getAccounts(provider)

v11

const { connection } = useWeb3Auth()

const onGetAccounts = async () => {
const provider = connection?.ethereumProvider ?? null
if (!provider) return
await getAccounts(provider)
}

Do not rely on a global "provider ready" flag. Guard each call with if (!provider) return.

Recipe D: Vanilla JS and Angular (no hooks)​

v10

const provider = web3auth.provider

v11

function getProvider() {
return web3auth.connection?.ethereumProvider ?? null
}

async function getAccounts() {
const provider = getProvider()
if (!provider) return
const address = await RPC.getAccounts(provider)
}

Recipe E: Server-side verification (social vs external wallet)​

v10 (external wallet anti-pattern)

const { web3Auth } = useWeb3Auth()
const { connectorName } = useWeb3AuthConnect()
const { address } = useAccount() // Wagmi v2

if (connectorName === 'auth') {
const pubKey = await web3Auth?.provider?.request({ method: 'public_key' })
} else {
// Redundant: fetches the same address Wagmi already exposes
const address = await web3Auth?.provider?.request({ method: 'eth_accounts' })
}

v11

import { useConnection } from 'wagmi'
import { useWeb3Auth } from '@web3auth/modal/react'

const { connection } = useWeb3Auth()
const { address } = useConnection()

if (connection?.connectorName === 'auth') {
// Social login: no Wagmi hook exposes the app public key
const pubKey = await connection?.ethereumProvider?.request({ method: 'public_key' })
// body: JSON.stringify({ appPubKey: pubKey })
} else {
// External wallet: use Wagmi address
// body: JSON.stringify({ address })
}

Solana migration (all frameworks)​

Remove @solana/web3.js as the primary dependency. Add @solana/kit, @solana-program/system, and @solana/react-hooks (see Install v11).

Hooks import path​

The Solana hook and composable import paths are unchanged from v10. Keep importing them from @web3auth/modal/react/solana (React) or @web3auth/modal/vue/solana (Vue); they are not exported from @web3auth/modal/react or @web3auth/modal/vue.

import {
useSolanaWallet,
useSignTransaction,
useSignAndSendTransaction,
useSignMessage,
} from '@web3auth/modal/react/solana'

SolanaProvider​

v11 adds a SolanaProvider component, exported from @web3auth/modal/react/solana and @web3auth/modal/vue/solana. The official React Solana quick start and Vue Solana quick start wrap the app in it inside Web3AuthProvider:

main.tsx
import { Web3AuthProvider } from '@web3auth/modal/react'
import { SolanaProvider } from '@web3auth/modal/react/solana'
import web3AuthContextConfig from './web3authContext'

ReactDOM.createRoot(document.getElementById('root')!).render(
<Web3AuthProvider config={web3AuthContextConfig}>
<SolanaProvider>
<App />
</SolanaProvider>
</Web3AuthProvider>
)

useSolanaWallet() return shape​

v10 returned { accounts, solanaWallet, connection }, where solanaWallet was a SolanaWallet wrapper and connection was a @solana/web3.js Connection.

v11 replaces connection with a @solana/kit rpc client, returns a wallet-standard Wallet, and adds getPrivateKey() (Embedded Wallets auth connector only):

{
accounts: string[] | null
solanaWallet: Wallet | null
rpc: Rpc<SolanaRpcApi> | null
getPrivateKey: () => Promise<string>
}

Fetch balance​

v10

import { clusterApiUrl, Connection, PublicKey, LAMPORTS_PER_SOL } from '@solana/web3.js'
const connection = new Connection(clusterApiUrl('devnet'))
const balance = await connection.getBalance(new PublicKey(account))
const sol = balance / LAMPORTS_PER_SOL

v11

import { address } from '@solana/kit'
import { useSolanaWallet } from '@web3auth/modal/react/solana'

const { accounts, rpc } = useSolanaWallet()
const { value } = await rpc!.getBalance(address(accounts![0])).send()
const sol = Number(value) / 1e9

In Vue, unwrap refs with .value (rpc.value, accounts.value![0]).

Build and sign a transfer​

v11 uses @solana/kit with the pipe builder and getTransferSolInstruction from @solana-program/system:

import {
address,
appendTransactionMessageInstruction,
compileTransaction,
createNoopSigner,
createTransactionMessage,
lamports,
pipe,
setTransactionMessageFeePayerSigner,
setTransactionMessageLifetimeUsingBlockhash,
} from '@solana/kit'
import { getTransferSolInstruction } from '@solana-program/system'
import { useSolanaWallet, useSignTransaction } from '@web3auth/modal/react/solana'

const { accounts, rpc } = useSolanaWallet()
const { signTransaction } = useSignTransaction()

const { value: latestBlockhash } = await rpc!.getLatestBlockhash().send()
const feePayer = createNoopSigner(address(accounts![0]))

const message = pipe(
createTransactionMessage({ version: 0 }),
m => setTransactionMessageFeePayerSigner(feePayer, m),
m => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, m),
m =>
appendTransactionMessageInstruction(
getTransferSolInstruction({
source: feePayer,
destination: address(toAddress),
amount: lamports(BigInt(Math.floor(amount * 1e9))),
}),
m
)
)

signTransaction(compileTransaction(message))

Key differences from v10:

  • The fee payer must be a TransactionSigner, not a bare PublicKey. Use createNoopSigner(address(pubkey)).
  • Pass the same feePayer signer as source in getTransferSolInstruction.
  • useSignTransaction and useSignAndSendTransaction accept the compiled Transaction from @solana/kit.

See React Solana hooks or Vue Solana composables for full transaction flows.

Sign a message​

v10

const encodedMessage = new TextEncoder().encode('Hello, Web3Auth!')
const signedMessage = await solanaWallet.signMessage(new Uint8Array(encodedMessage))

v11

import { useSignMessage } from '@web3auth/modal/react/solana'

const { signMessage } = useSignMessage()
signMessage('Hello, Web3Auth!')

Optional: Keep @solana/web3.js as a narrow bridge​

Some third-party libraries (@bonfida/spl-name-service, @solana/pay) still depend on @solana/web3.js types. Keep the package installed but limit usage to the component that calls the library. Build transactions with @solana/kit everywhere else.

For Vanilla JS, read connection.solanaWallet from web3auth.connection after sign-in. See the JavaScript SDK Solana integration snippets.

Polyfill removal​

The v11 SDK no longer needs browser polyfills. Remove the polyfills you added for older SDK versions.

Keep polyfills your chain libraries need

Some chain-specific libraries still need Node.js polyfills. For example, the official v11 Algorand, Bitcoin, Cosmos, multi-chain, and XMTP examples still depend on buffer. Keep any polyfill that a library outside the SDK requires.

Vite (vite.config.ts or vite.config.js)​

Delete the define block and any commented browserify resolve.alias entries:

- define: {
- global: 'globalThis',
- },

Removable packages​

Remove these from dependencies or devDependencies unless another library still needs them:

PackagePolyfilled Node.js API
bufferBuffer
processprocess
crypto-browserifycrypto
stream-browserifystream
assertassert
os-browserifyos
stream-httphttp
https-browserifyhttps
empty-moduleUnused module stub
urlurl
zlib-browserifyzlib

Angular (src/polyfills.ts)​

Remove global, Buffer, and process shims. Keep only zone.js:

import 'zone.js'
-
- (window as any).global = window
- global.Buffer = global.Buffer || require('buffer').Buffer
- global.process = global.process || require('process')

Framework-specific v11 changes​

After connect(), read the EVM provider from connection:

await web3auth.connect()
const provider = web3auth.connection?.ethereumProvider ?? null

For Solana, use web3auth.connection?.solanaWallet instead of wrapping web3auth.provider in SolanaWallet.

Breaking changes in v11​

Review these changes when upgrading from v10.

If you hit SDK bugs during upgrade, report them on the MetaMask developer dashboard and check web3auth-web release notes for fixes and known issues.

Node.js minimum version​

@web3auth/modal@11 requires Node.js 22+ and npm 10+. Support for Node.js 18 and 20 is discontinued.

node --version # must be >= 22.x

Identity token API renamed​

v10v11
web3auth.getIdentityToken()web3auth.getAuthTokenInfo() (returns { idToken })
useIdentityToken() (getIdentityToken, token)useAuthTokenInfo() (getAuthTokenInfo, token)

The React hook and Vue composable are both renamed.

Farcaster sign-in deprecated​

Farcaster login is deprecated and no longer supported. The v11 auth connector rejects AUTH_CONNECTION.FARCASTER, and the modal does not show it. Move affected users to another sign-in method.

Removed exports​

  • SolanaWallet (from the v10 Solana provider) is no longer exported. Use connection.solanaWallet or the Solana hooks and composables.
  • The @web3auth/modal/providers/ethereum-mpc-provider subpath is removed.

External wallet authentication mode​

The default initialAuthenticationMode changes from connect-only (v10.10 and later v10 releases, where the option was introduced) to connect and sign ('connect-and-sign'). Sessions persist across page reloads without re-prompting for a signature. See External wallet aggregator.

New Web SDK feature pages​

FeatureDocumentation
Multi-wallet linking and switchingMulti-wallet linking
EIP-7702 smart accountsSmart accounts
Role-based access controlAccess control
Consent screenConsent screen

Changes in v11.1 through v11.4​

These releases are backward compatible with v11.0. Notable additions:

  • v11.2.0: connection.connectorNamespace is added. Users blocked through access control now get WalletLoginError code 5120 ("User is blocked by the application").
  • v11.3.0: Base Account connector. Import baseAccountConnector from @web3auth/modal/connectors and install the optional peer dependency @base-org/account.
  • v11.4.0: The modal opens as a bottom sheet on mobile viewports.
  • v11.4.3: If no auth connections are configured on the dashboard, the modal hides the Embedded Wallets (auth) login options instead of failing during init().

Summary table​

v10 → v11 quick reference​

Areav10v11
Provider from hookconst { provider } = useWeb3Auth()const { connection } = useWeb3Auth(); Wagmi/Solana hooks first, then connection.ethereumProvider
Provider from classweb3auth.providerweb3auth.connection (use .ethereumProvider only when needed)
connect() return valueIProvider | nullConnection | null
Active connector gettersconnectedConnectorName, connectedConnectorprimaryConnectorName, primaryConnector
CONNECTED event dataconnector, provider, identityTokenInfoconnectorName, ethereumProvider, solanaWallet, connectorNamespace
EVM in React/Vueprovider.request(...)Wagmi hooks (useConnection, useBalance, etc.)
Raw private keyprovider.request({ method: 'private_key' })Once via connection.ethereumProvider in useEffect, then pass string to helpers
Solana RPC clientnew Connection(...) from @solana/web3.jsrpc from useSolanaWallet()
Solana transactionnew Transaction(), SystemProgram.transfer(...)pipe(createTransactionMessage(...), ...) + getTransferSolInstruction
Solana fee payernew PublicKey(address)createNoopSigner(address(pubkey))
Solana signing hooks@web3auth/modal/react/solana@web3auth/modal/react/solana (unchanged)
Server pubkey (social)web3Auth?.provider?.request({ method: 'public_key' })connection?.ethereumProvider?.request({ method: 'public_key' })
Server address (external)provider?.request({ method: 'eth_accounts' })useConnection().address from Wagmi

v9, v10, and v11​

Areav9v10v11
Package@web3auth/modal or no-modal + adapters@web3auth/modal@web3auth/modal@11
Custom UI loginconnectTo('auth', { loginProvider }) + adaptersconnectTo(WALLET_CONNECTORS.AUTH, { authConnection })Same as v10
Chain configCode (chainConfig)DashboardDashboard
Provider from hookproviderproviderconnection or Wagmi
Provider from classweb3auth.providerweb3auth.providerweb3auth.connection?.ethereumProvider
Identity tokenauthenticateUser()getIdentityToken()getAuthTokenInfo()
Solana RPC@solana/web3.js Connection@solana/web3.js Connectionrpc from useSolanaWallet()
Solana hooks pathNone (@web3auth/solana-provider)@web3auth/modal/react/solana@web3auth/modal/react/solana
PolyfillsOften requiredOften requiredNot required by the SDK
Node.js18+20+22+ (required)
External wallet authConnect only (manual authenticateUser())Connect only (initialAuthenticationMode from v10.10)Connect and sign (default)
Multi-wallet linkingNot availableNot availablelinkAccount, switchAccount

Next steps​