How to Add Embedded Wallets to a React App

A step-by-step guide to adding embedded wallets to a React or Next.js app with Para: install, provider setup, auth, wallet creation, and signing.

By Para Team · Published July 5, 2026

Adding a crypto wallet to a React app used to mean building or wiring together authentication, key management, and chain-specific signing logic from scratch. With a modern SDK, it looks a lot more like adding any other authentication provider. This guide walks through adding embedded wallets to a React or Next.js app with Para: installing the SDK, setting up the provider, opening the auth modal, checking wallet state, and signing.

The steps below follow Para's current React SDK. Code is accurate as of writing; always check the Para docs for the latest package versions before shipping.

What you need before starting

You need a Para account and API key, which you get from the Para developer portal. Sign up, create a project, and copy the API key from the dashboard. Keys carry an environment prefix, BETA_ for development or PROD_ for production, so you can build against a beta key and switch over when you launch. You also need a React or Next.js app already scaffolded; the steps below assume the Next.js App Router, but the SDK works the same way in plain React and Vite.

Step 1: Install the SDK

Install the Para React SDK along with its peer dependencies for chain support:

npm install @getpara/react-sdk @tanstack/react-query wagmi@^2 viem @solana/web3.js @stellar/stellar-sdk --save-exact

Para's SDK is built to sit alongside the EVM and Solana libraries teams already use, so wagmi and viem here are the same libraries you would use in any React app talking to EVM chains, not Para-specific replacements. If your app needs Cosmos support, the docs list the additional Cosmos-specific packages to add.

Step 2: Set up the provider

Wrap your app in ParaProvider, which needs your API key and an app name. This example uses a client component, providers.tsx, that the root layout renders:

// app/providers.tsx
"use client";

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

const queryClient = new QueryClient();

export function Providers({ children }: Readonly<{ children: React.ReactNode }>) {
  return (
    <QueryClientProvider client={queryClient}>
      <ParaProvider
        paraClientConfig={{
          apiKey: process.env.NEXT_PUBLIC_PARA_API_KEY!,
        }}
        config={{ appName: "Your App Name" }}
      >
        {children}
      </ParaProvider>
    </QueryClientProvider>
  );
}

The @getpara/react-sdk/styles.css import is required for Para's prebuilt modal to render correctly. Then render Providers from your root layout:

// app/layout.tsx
import { Providers } from "./providers";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <Providers>{children}</Providers>
      </body>
    </html>
  );
}

Keep your API key in an environment variable rather than hardcoding it, and use a beta key locally.

Step 3: Add the authentication modal

Para ships a prebuilt authentication modal that handles email, social login, and passkeys out of the box, so you do not need to build auth screens yourself. Use the useModal hook to open it, and useAccount to check whether a user is already connected:

// app/components/ConnectButton.tsx
"use client";

import { useModal, useAccount, useWallet } from "@getpara/react-sdk";

export function ConnectButton() {
  const { openModal } = useModal();
  const { isConnected } = useAccount();
  const { data: wallet } = useWallet();

  if (!isConnected) {
    return <button onClick={() => openModal()}>Sign in</button>;
  }

  return <p>Connected: {wallet?.address}</p>;
}

That is the entire authentication flow: no custom forms, no OTP handling, no OAuth redirect logic to wire up yourself. The modal handles email one-time codes, social login, and passkeys, and Para creates the wallet automatically as part of that flow.

Step 4: Read wallet state

Once a user authenticates through the modal, useWallet gives you the wallet data your app needs, most commonly the address to display or use in other calls:

"use client";

import { useWallet, useAccount } from "@getpara/react-sdk";

export function WalletBadge() {
  const { isConnected } = useAccount();
  const { data: wallet } = useWallet();

  if (!isConnected || !wallet) return null;

  return (
    <div>
      <p>Wallet address: {wallet.address}</p>
    </div>
  );
}

There is no separate "create wallet" call to make. Wallet creation happens as part of authentication, so by the time isConnected is true, a wallet already exists for that user.

Step 5: Sign a message

To sign a message, use the useSignMessage hook with the connected wallet's ID:

"use client";

import { useSignMessage, useWallet } from "@getpara/react-sdk";

export function SignMessageButton() {
  const { mutateAsync: signMessageAsync } = useSignMessage();
  const { data: wallet } = useWallet();

  const handleSign = async () => {
    if (!wallet) return;

    const message = "Hello from Para";
    const messageBase64 = btoa(message);

    const result = await signMessageAsync({
      walletId: wallet.id,
      messageBase64,
    });

    console.log("Signature:", result);
  };

  return <button onClick={handleSign}>Sign message</button>;
}

signMessage signs raw bytes directly, which is useful for authentication challenges or off-chain signatures. For onchain transactions, Para's SDK is designed to work with the Web3 libraries you already use, viem, ethers, or wagmi on EVM, rather than reinventing transaction construction. That means once your wallet is connected, you build and send transactions the same way you would with any other viem or wagmi setup, with Para providing the signer underneath.

Step 6: Get API keys and go further

Everything above runs on a single API key from the Para developer portal. From here, the natural next steps are wiring in your production API key, customizing the modal's branding, and adding chain-specific transaction logic with viem or wagmi for EVM, or the Solana or Cosmos equivalents if your app needs them. The Para docs cover framework-specific setup for Vite and Next.js, plus guides for signing transactions with each major chain library.

Why this is worth doing without a backend

For most apps, none of the steps above require a server. Authentication, wallet creation, and signing all run from the client through Para's SDK and infrastructure, which keeps a basic integration genuinely simple. A backend becomes useful later if you want server-side signing for automated flows, pregenerated wallets created before a user signs up, or custom session handling, but it is optional for shipping a working embedded wallet.

Under the hood, Para creates wallets using Distributed MPC, so a key share lives in the user's device secure enclave, protected by a passkey, and another lives in Para's infrastructure. Neither Para nor your app can sign alone, which makes the wallet non-custodial by design. Our MPC wallet explainer and embedded wallets guide cover this architecture in depth if you want to understand what is happening behind the hooks above.

Para's approach

Para's React SDK gives you a working, non-custodial embedded wallet with a handful of hooks and a prebuilt modal, backed by Distributed MPC and passkey authentication. It supports EVM chains, Solana, and Cosmos through the same integration, works alongside viem, ethers, and wagmi, and runs at scale across 15M+ wallets with SOC 2 Type II compliance. Start from the Para docs, or see plans on the pricing page once you are ready to move past the free tier.

Frequently asked questions

How do I add an embedded wallet to a React app?

Install the Para React SDK, wrap your app in ParaProvider with an API key, then use the useModal hook to open Para's prebuilt authentication modal. Once a user authenticates, useAccount and useWallet give you connection status and wallet data, and useSignMessage lets you sign. A basic integration takes minutes.

Do I need a backend to add embedded wallets to React?

No. Para's React SDK handles authentication, wallet creation, and signing entirely from the client for most use cases. A backend becomes useful later if you want server-side signing, pregenerated wallets, or custom session handling, but it is not required to get a working embedded wallet in your app.

Does Para work with viem and wagmi?

Yes. Para's React SDK is designed to work alongside the EVM libraries teams already use, including viem and wagmi, so you are not rewriting your app's transaction logic around a new wallet provider. The wallet integration adds authentication and key management without replacing your existing chain tooling.

Where do I get a Para API key?

Sign up or log in at the Para developer portal, create a project, and copy the API key from the dashboard. Keys are prefixed with an environment tag for beta or production use, so you can develop against a beta key and switch to a production key when you ship.

How long does a basic React integration take?

A prototype with Para's prebuilt modal and a working wallet can be running in well under an hour. A production integration with custom branding, error handling, and edge cases typically takes longer, but the core wallet functionality itself is not the bottleneck.