Overview
Para is an MPC wallet infrastructure that provides secure, non-custodial embedded wallets. This guide shows you how to integrate Para with Rhinestone smart accounts.
Para uses a different signature format (0/1 v-byte) than standard EVM wallets (27/28 v-byte). You must use wrapParaAccount to wrap Para signers before passing them to Rhinestone.
Prerequisites
Installation
Install the required dependencies:
npm install @getpara/react-sdk @getpara/viem @rhinestone/sdk viem @tanstack/react-query
Setup Para Provider
Create a context provider that wraps your application with Para and React Query. This setup enables Para’s authentication modal, wallet management, and proper React state handling.
"use client";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { ParaProvider } from "@getpara/react-sdk";
import "@getpara/react-sdk/styles.css";
import React, { type ReactNode } from "react";
// Set up queryClient
const queryClient = new QueryClient();
function ContextProvider({
children,
}: {
children: ReactNode;
}) {
return (
<QueryClientProvider client={queryClient}>
<ParaProvider
paraClientConfig={{
apiKey: process.env.NEXT_PUBLIC_PARA_API_KEY as string,
env: "BETA" as any,
}}
config={{
appName: "Your App Name",
}}
paraModalConfig={{
disableEmailLogin: false,
disablePhoneLogin: true,
authLayout: ["AUTH:FULL"],
oAuthMethods: [],
onRampTestMode: true, // Set to false in production
theme: {
foregroundColor: "#2D3648",
backgroundColor: "#FFFFFF",
accentColor: "#0066CC",
darkForegroundColor: "#E8EBF2",
darkBackgroundColor: "#1A1F2B",
darkAccentColor: "#4D9FFF",
mode: "light",
borderRadius: "lg",
font: "Inter",
},
recoverySecretStepEnabled: true,
twoFactorAuthEnabled: false,
}}
>
{children}
</ParaProvider>
</QueryClientProvider>
);
}
export default ContextProvider;
Then wrap your application with this provider:
// app/layout.tsx (Next.js App Router)
import ContextProvider from './context-provider'
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<ContextProvider>
{children}
</ContextProvider>
</body>
</html>
)
}
Initialize Rhinestone with Para
The key is to wrap the Para viem account with wrapParaAccount before passing it to Rhinestone:
import { useEffect } from "react"
import { useWallet } from "@getpara/react-sdk"
import { useViemAccount } from "@getpara/react-sdk/evm/hooks"
import { RhinestoneSDK, wrapParaAccount } from "@rhinestone/sdk"
import type { Account } from "viem"
export function useRhinestoneAccount() {
const { data: wallet } = useWallet()
const { viemAccount } = useViemAccount()
useEffect(() => {
async function init() {
if (!viemAccount || !wallet?.id) return
const rhinestone = new RhinestoneSDK({
apiKey: "proxy",
endpointUrl: `${window.location.origin}/api/orchestrator`,
})
// Wrap Para account for signature compatibility
const wrappedAccount = wrapParaAccount(viemAccount, wallet.id)
// Create Rhinestone account
const rhinestoneAccount = await rhinestone.createAccount({
owners: {
type: "ecdsa",
accounts: [wrappedAccount as Account],
},
})
console.log("Smart Account:", rhinestoneAccount.getAddress())
}
init()
}, [viemAccount, wallet?.id])
}
Send Transactions
Once initialized, use the Rhinestone account for cross-chain transactions:
const transaction = await rhinestoneAccount.sendTransaction({
sourceChains: [baseSepolia],
targetChain: arbitrumSepolia,
calls: [{
to: "USDC",
data: encodeFunctionData({
abi: erc20Abi,
functionName: "transfer",
args: ["0xrecipient", parseUnits("10", 6)],
}),
}],
tokenRequests: [{
address: "USDC",
amount: parseUnits("10", 6),
}],
sponsored: true,
})
const result = await rhinestoneAccount.waitForExecution(transaction)
Complete Example
See the full working example with Para + Rhinestone:
Next Steps