Migrate your existing Web3Modal application to Para’s unified wallet system. Since both Web3Modal and Para use Wagmi internally, the migration involves replacing the Web3Modal provider with Para’s ParaProvider
while maintaining your existing Wagmi configuration.
Installation
Replace Web3Modal packages with Para SDK while keeping Wagmi:
npm uninstall @web3modal/wagmi
npm install @getpara/react-sdk
npm run postinstall
Configuration Changes
Before: Web3Modal Config
Your existing Web3Modal configuration likely looks like this:
import { cookieStorage , createStorage } from 'wagmi' ;
import { mainnet } from 'wagmi/chains' ;
import { http , createConfig } from 'wagmi' ;
import { walletConnect , injected , coinbaseWallet } from 'wagmi/connectors' ;
export const projectId = process . env . NEXT_PUBLIC_PROJECT_ID ;
if ( ! projectId ) throw new Error ( 'Project ID is not defined' );
const metadata = {
name: 'Web3Modal Example' ,
description: 'Web3Modal Example' ,
url: 'https://web3modal.com' ,
icons: [ 'https://avatars.githubusercontent.com/u/37784886' ],
};
export const config = createConfig ({
chains: [ mainnet ],
transports: {
[mainnet.id]: http (),
},
connectors: [
walletConnect ({ projectId , metadata , showQrModal: false }),
injected ({ shimDisconnect: true }),
coinbaseWallet ({
appName: metadata . name ,
appLogoUrl: metadata . icons [ 0 ],
}),
],
ssr: true ,
storage: createStorage ({
storage: cookieStorage ,
}),
});
After: Para Config
Transform your configuration for Para:
import { Environment } from "@getpara/react-sdk" ;
export const API_KEY = process . env . NEXT_PUBLIC_PARA_API_KEY ?? "" ;
export const ENVIRONMENT =
( process . env . NEXT_PUBLIC_PARA_ENVIRONMENT as Environment ) || Environment . BETA ;
export const PROJECT_ID = process . env . NEXT_PUBLIC_PROJECT_ID ?? "" ;
if ( ! API_KEY ) {
throw new Error ( "Missing NEXT_PUBLIC_PARA_API_KEY environment variable" );
}
Provider Migration
Before: Web3Modal Provider
Your existing Web3Modal provider:
context/Web3ModalProvider.tsx
'use client' ;
import React , { ReactNode } from 'react' ;
import { config , projectId } from '@/config' ;
import { createWeb3Modal } from '@web3modal/wagmi/react' ;
import { QueryClient , QueryClientProvider } from '@tanstack/react-query' ;
import { State , WagmiProvider } from 'wagmi' ;
const queryClient = new QueryClient ();
createWeb3Modal ({
wagmiConfig: config ,
projectId ,
enableAnalytics: true ,
});
export default function Web3ModalProvider ({
children ,
initialState ,
} : {
children : ReactNode ;
initialState ?: State ;
}) {
return (
< WagmiProvider config = { config } initialState = { initialState } >
< QueryClientProvider client = { queryClient } > { children } </ QueryClientProvider >
</ WagmiProvider >
);
}
After: Para Provider
Replace with Para’s provider, passing your Wagmi config:
src/context/ParaProvider.tsx
"use client" ;
import { ParaProvider as Provider } from "@getpara/react-sdk" ;
import { API_KEY , ENVIRONMENT , PROJECT_ID } from "@/config/constants" ;
import { mainnet } from "wagmi/chains" ;
import { cookieStorage , createStorage , http } from "wagmi" ;
export function ParaProvider ({ children } : { children : React . ReactNode }) {
return (
< Provider
paraClientConfig = { {
apiKey: API_KEY ,
env: ENVIRONMENT ,
} }
externalWalletConfig = { {
wallets: [ "METAMASK" , "COINBASE" , "WALLETCONNECT" , "RAINBOW" ],
evmConnector: {
config: {
chains: [ mainnet ],
transports: {
[mainnet.id]: http (),
},
ssr: true ,
storage: createStorage ({
storage: cookieStorage ,
}),
},
},
walletConnect: {
projectId: PROJECT_ID ,
},
} }
config = { {
appName: "Your App Name" ,
description: "Your App Description" ,
} }
paraModalConfig = { {
authLayout: [ "AUTH:FULL" , "EXTERNAL:FULL" ],
theme: { mode: "light" },
} }
>
{ children }
</ Provider >
);
}
Layout Update
Before: Web3Modal Layout
import './globals.css' ;
import type { Metadata } from 'next' ;
import { headers } from 'next/headers' ;
import { cookieToInitialState } from 'wagmi' ;
import { config } from '@/config' ;
import Web3ModalProvider from '@/context/Web3ModalProvider' ;
export const metadata : Metadata = {
title: 'Your App' ,
description: 'Your App Description' ,
};
export default function RootLayout ({ children } : { children : React . ReactNode }) {
const initialState = cookieToInitialState ( config , headers (). get ( 'cookie' ));
return (
< html lang = "en" >
< body >
< Web3ModalProvider initialState = { initialState } >
{ children }
</ Web3ModalProvider >
</ body >
</ html >
);
}
After: Para Layout
import type { Metadata } from "next" ;
import "@getpara/react-sdk/styles.css" ;
import { QueryClient , QueryClientProvider } from "@tanstack/react-query" ;
import { ParaProvider } from "@/context/ParaProvider" ;
const queryClient = new QueryClient ();
export const metadata : Metadata = {
title: "Your App" ,
description: "Your App Description" ,
};
export default function RootLayout ({ children } : { children : React . ReactNode }) {
return (
< html lang = "en" >
< body >
< QueryClientProvider client = { queryClient } >
< ParaProvider >
{ children }
</ ParaProvider >
</ QueryClientProvider >
</ body >
</ html >
);
}
components/ConnectButton.tsx
'use client' ;
import { useWeb3Modal } from '@web3modal/wagmi/react' ;
export default function ConnectButton () {
const { open } = useWeb3Modal ();
return < button onClick = { () => open () } > Connect Wallet </ button > ;
}
src/components/ConnectButton.tsx
"use client" ;
import { useAccount , useModal , useWallet } from "@getpara/react-sdk" ;
export function ConnectButton () {
const { openModal } = useModal ();
const { data : wallet } = useWallet ();
const { isConnected } = useAccount ();
if ( isConnected && wallet ?. address ) {
return (
< button onClick = { () => openModal () } className = "connect-button" >
{ wallet . address . slice ( 0 , 6 ) } ... { wallet . address . slice ( - 4 ) }
</ button >
);
}
return (
< button onClick = { () => openModal () } className = "connect-button" >
Connect Wallet
</ button >
);
}
Configuration Mapping
Para maintains full Wagmi compatibility. Your existing Wagmi hooks and configuration continue to work seamlessly.
Web3Modal Config Para Config Location projectId
walletConnect.projectId
externalWalletConfig
wagmiConfig.chains
evmConnector.config.chains
externalWalletConfig
wagmiConfig.transports
evmConnector.config.transports
externalWalletConfig
wagmiConfig.ssr
evmConnector.config.ssr
externalWalletConfig
wagmiConfig.storage
evmConnector.config.storage
externalWalletConfig
metadata.name
config.appName
Root config metadata.description
config.description
Root config
Advanced Configuration
Multiple Chains
src/context/ParaProvider.tsx
import { mainnet , polygon , arbitrum , optimism } from "wagmi/chains" ;
// In ParaProvider
externalWalletConfig = {{
evmConnector : {
config : {
chains : [ mainnet , polygon , arbitrum , optimism ],
transports : {
[ mainnet . id ]: http (),
[ polygon . id ]: http (),
[ arbitrum . id ]: http (),
[ optimism . id ]: http (),
},
},
},
}}
Custom RPC Endpoints
src/context/ParaProvider.tsx
import { http } from "wagmi" ;
// In ParaProvider
externalWalletConfig = {{
evmConnector : {
config : {
transports : {
[ mainnet . id ]: http ( "https://your-custom-rpc.com" ),
},
},
},
}}
Social Login Support
Para adds embedded wallet support automatically:
src/context/ParaProvider.tsx
paraModalConfig = {{
authLayout : [ "AUTH:FULL" , "EXTERNAL:FULL" ],
oAuthMethods : [ "GOOGLE" , "APPLE" , "DISCORD" , "TWITTER" ],
disableEmailLogin : false ,
disablePhoneLogin : false ,
}}
Using Wagmi Hooks
Your existing Wagmi code continues to work without changes:
src/components/AccountInfo.tsx
import { useAccount , useBalance , useEnsName } from "wagmi" ;
export function AccountInfo () {
const { address } = useAccount ();
const { data : balance } = useBalance ({ address });
const { data : ensName } = useEnsName ({ address });
if ( ! address ) return null ;
return (
< div >
< p > { ensName || address } </ p >
< p > { balance ?. formatted } { balance ?. symbol } </ p >
</ div >
);
}
Migration Checklist
Remove @web3modal/wagmi
and @web3modal/wagmi/react
Install @getpara/react-sdk
Keep wagmi
, viem
, and @tanstack/react-query
Run the Para postinstall script
Move Wagmi config to externalWalletConfig.evmConnector.config
Add Para API key to environment variables
Migrate metadata to Para’s config object
Keep WalletConnect project ID for external wallets
Replace Web3ModalProvider with ParaProvider
Remove cookie state handling (Para manages internally)
Keep QueryClientProvider wrapper
Import Para styles
Replace useWeb3Modal
with useModal
Update connect button component
Keep all Wagmi hook usage unchanged
Test wallet connections
Common Issues
SSR Hydration : Para handles SSR internally. Remove manual cookie state management from your layout.
Connector Configuration : Para manages wallet connectors internally. Remove explicit connector imports from Wagmi.
Next Steps