Skip to main content
Integrate Para’s embedded wallets with Porto to combine Para’s authentication and key management with Porto’s smart account features. The usePortoSmartAccount hook handles the entire upgrade flow — wrapping the Para signer, registering admin keys, and submitting the upgrade to Porto’s relay — so you can focus on your application logic.

What You Get

FeaturePara EOAPorto Smart Account
AddressSingle addressSame address (preserved)
Signing Keys1 (MPC-secured)Multiple authorized keys
Session KeysNot supportedSupported
Batched TransactionsNot supportedSupported
Gas SponsorshipNot supportedSupported
Programmable PermissionsNot supportedSupported

Integration Pattern

Para handles:
  • Authentication (social login, email, SMS)
  • Key custody (MPC security)
  • Cross-app identity
  • Raw message signing
Porto handles:
  • Smart account operations (EIP-7702)
  • Transaction batching
  • Gas sponsorship
  • Session key management

Prerequisites

Installation

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

Setup Para Provider

Configure the Para provider:
"use client";

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

const queryClient = new QueryClient();

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

Gas Sponsorship

On testnets, Porto’s relay sponsors gas by default — no configuration needed. For mainnet, you must set up a Porto merchant account to cover gas fees for your users:
  1. Run pnpx porto onboard --admin-key to create a merchant account
  2. Deploy a server-side merchant route using porto/server
  3. Pass your endpoint URL as merchantUrl in the hook config

Usage

Use the usePortoSmartAccount hook to create and manage a Porto smart account. The hook handles Para signer creation, admin key registration, EOA upgrade, and Porto relay configuration internally.
"use client";

import { usePortoSmartAccount } from "@getpara/react-sdk";
import { useMutation } from "@tanstack/react-query";
import { parseEther } from "viem";
import { baseSepolia } from "viem/chains";

export function PortoDemo() {
  const { smartAccount, isLoading, error } = usePortoSmartAccount({
    chain: baseSepolia,
    // merchantUrl: '/porto/merchant', // required for mainnet
  });

  const {
    mutate: sendTransaction,
    isPending: isSending,
    error: sendError,
  } = useMutation({
    mutationFn: async () => {
      if (!smartAccount) throw new Error("Smart account not ready");
      return smartAccount.sendTransaction({
        to: "0xRecipient",
        value: parseEther("0.01"),
      });
    },
    onSuccess: (receipt) => {
      console.log("Transaction hash:", receipt.transactionHash);
    },
  });

  const {
    mutate: sendBatch,
    isPending: isBatching,
    error: batchError,
  } = useMutation({
    mutationFn: async () => {
      if (!smartAccount) throw new Error("Smart account not ready");
      return smartAccount.sendBatchTransaction([
        { to: "0xRecipientA", value: parseEther("0.01") },
        { to: "0xRecipientB", data: "0xencodedCallData" },
      ]);
    },
    onSuccess: (receipt) => {
      console.log("Batch tx hash:", receipt.transactionHash);
    },
  });

  if (isLoading) return <p>Setting up smart account...</p>;
  if (error) return <p>Error: {error.message}</p>;
  if (!smartAccount) return null;

  return (
    <div>
      <h2>Porto Smart Account</h2>
      <p>Address: {smartAccount.smartAccountAddress}</p>
      <p>Mode: {smartAccount.mode}</p>

      <button onClick={() => sendTransaction()} disabled={isSending}>
        {isSending ? "Sending..." : "Send Transaction"}
      </button>
      {sendError && <p style={{ color: "red" }}>{sendError.message}</p>}

      <button onClick={() => sendBatch()} disabled={isBatching}>
        {isBatching ? "Batching..." : "Send Batch"}
      </button>
      {batchError && <p style={{ color: "red" }}>{batchError.message}</p>}
    </div>
  );
}

Accessing the Porto Client Directly

For advanced use cases like session key management, access the underlying Porto client:
const { smartAccount } = usePortoSmartAccount({ chain: baseSepolia });

if (smartAccount) {
  const { portoAccount, portoClient } = smartAccount.client;
  // Use Porto's RelayActions directly for advanced operations
}

How It Works

The usePortoSmartAccount hook performs these steps internally:
  1. Resolves the Para wallet — finds the user’s EVM wallet address
  2. Creates a viem account — wraps the Para signer for raw ECDSA signing
  3. Connects to Porto’s relay — creates a client pointed at https://rpc.porto.sh
  4. Registers an admin key — creates a secp256k1 admin key from the Para signer
  5. Upgrades the EOA — submits a 7702 delegation via prepareUpgradeAccount + upgradeAccount
  6. Returns a unified SmartAccount — with sendTransaction, sendBatchTransaction, and access to the underlying Porto client

Next Steps

Porto Documentation

Explore Porto’s smart account features and SDK documentation

Account Abstraction Guide

See all supported AA providers and the unified SmartAccount interface

Example Repository

View the complete working example

Para React SDK

Learn more about Para’s React SDK features and configuration