getpara

para-migration

0
0
# Install this skill:
npx skills add getpara/ai-tooling --skill "para-migration"

Install specific skill from multi-skill repository

# Description

Migrate from other wallet providers (Privy, Dynamic, Reown, etc.) to Para

# SKILL.md


name: para-migration
description: Migrate from other wallet providers (Privy, Dynamic, Reown, etc.) to Para


Para Migration Skill

Migrate from other embedded wallet or auth providers to Para. This skill covers provider detection, step-by-step migration guides, hook/component mapping tables, and common post-migration issues.

Provider Detection

Identify what the project currently uses by checking package.json dependencies:

Dependency Pattern Current Provider
@privy-io/react-auth, @privy-io/expo Privy
@dynamic-labs/sdk-react-core, @dynamic-labs/ethereum Dynamic
@web3modal/wagmi, @reown/appkit Reown (formerly WalletConnect Web3Modal)
@web3auth/modal, @web3auth/no-modal Web3Auth
magic-sdk, @magic-sdk/react-native Magic
thirdweb, @thirdweb-dev/react Thirdweb
@turnkey/sdk-react, @turnkey/http Turnkey
@usecapsule/* Capsule (legacy Para branding)

Additional Detection Signals

  • Privy: Look for <PrivyProvider>, usePrivy(), useWallets() in source
  • Dynamic: Look for <DynamicContextProvider>, useDynamicContext() in source
  • Reown: Look for createWeb3Modal(), <Web3Modal>, useWeb3Modal() in source
  • Web3Auth: Look for <Web3AuthProvider>, web3auth.connect() in source
  • Magic: Look for new Magic(), magic.auth in source

Migration from Privy

Step 1: Replace Packages

Remove:

npm uninstall @privy-io/react-auth @privy-io/wagmi @privy-io/expo

Install:

npm install @getpara/react-sdk @tanstack/react-query

Step 2: Replace Provider

Before (Privy):

import { PrivyProvider } from "@privy-io/react-auth";

<PrivyProvider
  appId="your-privy-app-id"
  config={{
    loginMethods: ["email", "google", "apple"],
    appearance: { theme: "light" },
  }}>
  {children}
</PrivyProvider>

After (Para):

"use client";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { Environment, ParaProvider as ParaSDKProvider } from "@getpara/react-sdk";
import "@getpara/react-sdk/styles.css";

const queryClient = new QueryClient();

<QueryClientProvider client={queryClient}>
  <ParaSDKProvider
    paraClientConfig={{
      apiKey: process.env.NEXT_PUBLIC_PARA_API_KEY!,
      env: Environment.BETA,
    }}
    config={{ appName: "My App" }}
    paraModalConfig={{
      disableEmailLogin: false,
      oAuthMethods: ["GOOGLE", "APPLE"],
      authLayout: ["AUTH:FULL", "EXTERNAL:FULL"],
    }}>
    {children}
  </ParaSDKProvider>
</QueryClientProvider>

Step 3: Replace Hooks

Privy Para Notes
usePrivy() useAccount() from @getpara/react-sdk isConnected, address
usePrivy().login() useModal().openModal() Opens Para auth modal
usePrivy().logout() useLogout().logout()
usePrivy().authenticated useAccount().isConnected
usePrivy().user useAccount() + useLinkedAccounts()
useWallets() useAccount().embedded.wallets Wallet array
usePrivy().sendTransaction() Use viem/ethers signer See signing integration

Migration from Dynamic

Step 1: Replace Packages

Remove:

npm uninstall @dynamic-labs/sdk-react-core @dynamic-labs/ethereum @dynamic-labs/wagmi-connector

Install:

npm install @getpara/react-sdk @tanstack/react-query

Step 2: Replace Provider

Before (Dynamic):

import { DynamicContextProvider } from "@dynamic-labs/sdk-react-core";
import { EthereumWalletConnectors } from "@dynamic-labs/ethereum";

<DynamicContextProvider
  settings={{
    environmentId: "your-dynamic-env-id",
    walletConnectors: [EthereumWalletConnectors],
  }}>
  {children}
</DynamicContextProvider>

After (Para):

"use client";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { Environment, ParaProvider as ParaSDKProvider } from "@getpara/react-sdk";
import "@getpara/react-sdk/styles.css";

const queryClient = new QueryClient();

<QueryClientProvider client={queryClient}>
  <ParaSDKProvider
    paraClientConfig={{
      apiKey: process.env.NEXT_PUBLIC_PARA_API_KEY!,
      env: Environment.BETA,
    }}
    config={{ appName: "My App" }}
    paraModalConfig={{
      authLayout: ["AUTH:FULL", "EXTERNAL:FULL"],
      oAuthMethods: ["GOOGLE", "APPLE"],
    }}>
    {children}
  </ParaSDKProvider>
</QueryClientProvider>

Step 3: Replace Hooks

Dynamic Para Notes
useDynamicContext() useAccount()
useDynamicContext().setShowAuthFlow(true) useModal().openModal()
useDynamicContext().handleLogOut() useLogout().logout()
useDynamicContext().primaryWallet useWallet() Active wallet
useDynamicContext().isAuthenticated useAccount().isConnected

Migration from Reown (WalletConnect Web3Modal)

Step 1: Replace Packages

Remove:

npm uninstall @web3modal/wagmi @web3modal/ethereum @reown/appkit @reown/appkit-wagmi

Install (option A -- full Para modal):

npm install @getpara/react-sdk @tanstack/react-query

Install (option B -- keep wagmi, add Para as connector):

npm install @getpara/react-sdk-lite @getpara/wagmi-v2-integration wagmi viem @tanstack/react-query

Step 2: Replace Config (Option B -- Wagmi Connector)

Before (Reown):

import { createWeb3Modal } from "@web3modal/wagmi/react";
import { createConfig, http } from "wagmi";
import { sepolia } from "wagmi/chains";

const config = createConfig({
  chains: [sepolia],
  transports: { [sepolia.id]: http() },
});

createWeb3Modal({ wagmiConfig: config, projectId: "your-wc-project-id" });

After (Para wagmi connector):

import { paraConnector } from "@getpara/wagmi-v2-integration";
import { ParaWeb, Environment } from "@getpara/react-sdk-lite";
import { createConfig, http } from "wagmi";
import { sepolia } from "wagmi/chains";

const para = new ParaWeb(Environment.BETA, process.env.NEXT_PUBLIC_PARA_API_KEY!);

const connector = paraConnector({
  para,
  appName: "My App",
  chains: [sepolia],
  oAuthMethods: ["GOOGLE", "APPLE"],
});

export const config = createConfig({
  chains: [sepolia],
  connectors: [connector],
  transports: { [sepolia.id]: http() },
});

Step 3: Replace Hooks

Reown Para (wagmi connector) Notes
useWeb3Modal().open() useConnect() with para connector Standard wagmi hook
useDisconnect() useDisconnect() Same wagmi hook
useAccount() useAccount() Same wagmi hook

Migration from Web3Auth

Step 1: Replace Packages

Remove:

npm uninstall @web3auth/modal @web3auth/no-modal @web3auth/ethereum-provider @web3auth/base

Install:

npm install @getpara/react-sdk @tanstack/react-query

Step 2: Replace Setup

Before (Web3Auth):

import { Web3Auth } from "@web3auth/modal";

const web3auth = new Web3Auth({
  clientId: "your-web3auth-client-id",
  chainConfig: { chainNamespace: "eip155", chainId: "0xaa36a7" },
});

await web3auth.initModal();
const provider = await web3auth.connect();

After (Para):

"use client";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { Environment, ParaProvider as ParaSDKProvider } from "@getpara/react-sdk";
import "@getpara/react-sdk/styles.css";

const queryClient = new QueryClient();

<QueryClientProvider client={queryClient}>
  <ParaSDKProvider
    paraClientConfig={{
      apiKey: process.env.NEXT_PUBLIC_PARA_API_KEY!,
      env: Environment.BETA,
    }}
    config={{ appName: "My App" }}
    paraModalConfig={{
      oAuthMethods: ["GOOGLE", "APPLE", "DISCORD"],
      authLayout: ["AUTH:FULL", "EXTERNAL:FULL"],
    }}>
    {children}
  </ParaSDKProvider>
</QueryClientProvider>

Step 3: Replace Hooks

Web3Auth Para Notes
web3auth.connect() useModal().openModal()
web3auth.logout() useLogout().logout()
web3auth.connected useAccount().isConnected
web3auth.provider useClient() + signer integration Use viem/ethers

Migration from Magic

Step 1: Replace Packages

Remove:

npm uninstall magic-sdk @magic-sdk/react-native @magic-ext/oauth

Install:

npm install @getpara/react-sdk @tanstack/react-query

Step 2: Replace Setup

Before (Magic):

import { Magic } from "magic-sdk";
import { OAuthExtension } from "@magic-ext/oauth";

const magic = new Magic("your-magic-publishable-key", {
  extensions: [new OAuthExtension()],
});

After (Para):

"use client";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { Environment, ParaProvider as ParaSDKProvider } from "@getpara/react-sdk";
import "@getpara/react-sdk/styles.css";

const queryClient = new QueryClient();

<QueryClientProvider client={queryClient}>
  <ParaSDKProvider
    paraClientConfig={{
      apiKey: process.env.NEXT_PUBLIC_PARA_API_KEY!,
      env: Environment.BETA,
    }}
    config={{ appName: "My App" }}
    paraModalConfig={{
      disableEmailLogin: false,
      oAuthMethods: ["GOOGLE", "APPLE"],
    }}>
    {children}
  </ParaSDKProvider>
</QueryClientProvider>

Step 3: Replace Calls

Magic Para Notes
magic.auth.loginWithEmailOTP() useModal().openModal() or useSignUpOrLogIn()
magic.oauth.loginWithRedirect() useVerifyOAuth()
magic.user.logout() useLogout().logout()
magic.user.isLoggedIn() useAccount().isConnected
magic.rpcProvider useClient() + signer integration Use viem/ethers

Migration from Capsule (Legacy Branding)

If migrating from @usecapsule/* to @getpara/*, see the dedicated guide. The API surface is identical -- only the package names changed:

Old Package New Package
@usecapsule/react-sdk @getpara/react-sdk
@usecapsule/web-sdk @getpara/web-sdk
@usecapsule/server-sdk @getpara/server-sdk
@usecapsule/viem-v2-integration @getpara/viem-v2-integration
@usecapsule/ethers-v6-integration @getpara/ethers-v6-integration

Find-and-replace @usecapsule/ with @getpara/ in all imports and package.json.

Common Post-Migration Issues

Users lose their wallets

Para creates new wallets for users. If your previous provider had user wallets, those wallets remain with the old provider. Para does not import private keys from other providers -- MPC key shares are generated fresh. Communicate this to users and handle any asset migration separately.

OAuth redirect URLs change

Para OAuth uses its own redirect flow. Update your OAuth provider settings (Google Console, Apple Developer, etc.) to include Para's redirect URLs, or use Para's built-in OAuth which handles this automatically.

Session management differences

Para sessions are managed via passkeys and the Para portal. If you previously managed sessions with JWTs from another provider, switch to Para's session model:

const isActive = await para.isSessionActive();
const { token } = await para.issueJWT(); // For your own backend verification

Missing "use client" directive

If migrating a Next.js app, ensure the ParaProvider wrapper file has "use client" at the top. Previous providers may not have required this.

Missing CSS import

Para's modal requires its stylesheet. Add to your root layout:

import "@getpara/react-sdk/styles.css";

@tanstack/react-query not installed

Para's React SDK depends on React Query. If your previous provider did not use it:

npm install @tanstack/react-query

Wrap your app with QueryClientProvider (see setup examples above).

Environment variable prefix changes

Update environment variable names to match Para's conventions:

Previous Variable Para Variable
PRIVY_APP_ID NEXT_PUBLIC_PARA_API_KEY
DYNAMIC_ENVIRONMENT_ID NEXT_PUBLIC_PARA_API_KEY
WEB3AUTH_CLIENT_ID NEXT_PUBLIC_PARA_API_KEY
MAGIC_PUBLISHABLE_KEY NEXT_PUBLIC_PARA_API_KEY

Signing library compatibility

Para works with the same signing libraries (viem, ethers, cosmjs, solana web3.js). You likely do not need to change your signing code beyond swapping the signer constructor:

// Before (generic provider)
const signer = new ethers.BrowserProvider(window.ethereum).getSigner();

// After (Para)
import { ParaEthersSigner } from "@getpara/ethers-v6-integration";
const signer = new ParaEthersSigner(para, provider);

# Supported AI Coding Agents

This skill is compatible with the SKILL.md standard and works with all major AI coding agents:

Learn more about the SKILL.md standard and how to use these skills with your preferred AI coding agent.