> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getpara.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Account Abstraction Integrations

> Set up smart accounts with Para's unified SDK interface across all supported AA providers

export const Link = ({href, label, newTab = false}) => {
  const [isHovered, setIsHovered] = useState(false);
  return <a href={href} target={newTab ? '_blank' : '_self'} rel={newTab ? 'noopener noreferrer' : undefined} className="not-prose inline-block relative text-black font-semibold cursor-pointer border-b-0 no-underline" onMouseEnter={() => setIsHovered(true)} onMouseLeave={() => setIsHovered(false)}>
      {label}
      <span className={`absolute left-0 bottom-0 w-full rounded-sm bg-gradient-to-r from-orange-600 to-purple-600 transition-all duration-300 ${isHovered ? 'h-0.5' : 'h-px'}`} />
    </a>;
};

## Account Abstraction

Account abstraction (AA) replaces traditional externally owned accounts (EOAs) with programmable smart contract accounts. This unlocks capabilities that EOAs alone cannot provide:

* **Gas sponsorship** — let users transact without holding native tokens for gas fees
* **Batched transactions** — bundle multiple operations into a single atomic transaction
* **Session keys** — grant temporary, scoped permissions without exposing the primary key
* **Custom authorization** — implement multi-factor auth, spending limits, or recovery logic at the account level
* **Programmable accounts** — create accounts with built-in rules for corporate or multi-user scenarios

Two standards are currently in use for AA on EVM-based chains:

|                     | EIP-4337                                                        | EIP-7702                                                   |
| ------------------- | --------------------------------------------------------------- | ---------------------------------------------------------- |
| **How it works**    | UserOperations processed by bundlers via an EntryPoint contract | EOA delegates to a smart contract via a type-4 transaction |
| **Account address** | New smart contract address (different from EOA)                 | Same as your EOA                                           |
| **Chain support**   | All EVM chains                                                  | Requires chain-level support                               |
| **Infrastructure**  | Bundler + Paymaster                                             | Provider-dependent                                         |
| **Gas overhead**    | Higher (extra validation steps)                                 | Lower (native execution)                                   |
| **Maturity**        | Production-ready                                                | Emerging                                                   |
| **Best for**        | Maximum compatibility, dedicated smart wallet                   | Keeping EOA address, simpler flows                         |

Both standards support **gas sponsorship** and **batched transactions**.

<Tip>
  Learn more about [EIP-4337](https://eips.ethereum.org/EIPS/eip-4337) and [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) on the Ethereum Improvement Proposals site.
</Tip>

## Para Integrations

Para acts as the **signer** (EOA) that controls smart contract wallets — it is not a smart wallet itself. Para handles secure key management via MPC, while the AA provider deploys and manages the smart contract account on-chain. This means your users' private keys remain secure and under their control regardless of which provider you choose.

Para wraps each provider in a shared `SmartAccount` interface. Whether you use EIP-4337 or EIP-7702 mode, your application code stays the same — you can swap providers or switch between standards without rewriting transaction logic.

Every provider integration is available as an **action function** (`createXxxSmartAccount`) — an imperative async function you can call anywhere, including outside React components, inside custom hooks, or in server-side code. React applications also get a **hook** (`useXxxSmartAccount`) — a declarative wrapper powered by React Query that handles initialization, caching, and automatic re-creation when config changes.

Both return the same `SmartAccount` object:

```typescript theme={null}
import type { Chain, Hex, LocalAccount, TransactionReceipt } from "viem";

interface SmartAccount {
  smartAccountAddress: Hex;              // On-chain account address
  signer: LocalAccount;                 // Para viem signer
  chain: Chain;                          // Configured chain
  mode: "4337" | "7702";                // Account type
  provider: string;                      // Provider name

  // Send a single transaction and wait for receipt
  sendTransaction(params: {
    to: Hex;
    value?: bigint;
    data?: Hex;
  }): Promise<TransactionReceipt>;

  // Send batched transactions atomically
  sendBatchTransaction(calls: Array<{
    to: Hex;
    value?: bigint;
    data?: Hex;
  }>): Promise<TransactionReceipt>;

  client: any;                           // Provider-specific client for advanced usage
}
```

When using `mode: "7702"`, the return type narrows to include an optional `delegationAddress` field — the smart
contract the EOA delegates to. When using `mode: "4337"`, `smartAccountAddress` is the counterfactual smart
contract address (different from `signer.address`).

## Provider Comparison

| Provider                                                      | 4337 | 7702 | External Wallets | Chain Restrictions                        | Key Feature                                       |
| ------------------------------------------------------------- | :--: | :--: | :--------------: | ----------------------------------------- | ------------------------------------------------- |
| [Alchemy](https://accountkit.alchemy.com/react/quickstart)    |   ✓  |   ✓  |         ✓        | Alchemy-supported chains                  | Modular accounts, gas policies                    |
| [ZeroDev](https://docs.zerodev.app/)                          |   ✓  |   ✓  |         ✓        | Any EVM chain                             | Kernel accounts, session keys, plugins            |
| [Pimlico](https://docs.pimlico.io/)                           |   ✓  |   ✓  |         ✓        | Any EVM chain                             | Permissionless SDK, flexible paymaster            |
| [Biconomy](https://docs.biconomy.io/)                         |   ✓  |   ✓  |         ✓        | MEE-supported chains                      | Cross-chain orchestration via MEE                 |
| [Thirdweb](https://portal.thirdweb.com/)                      |   ✓  |   ✓  |         ✓        | Any EVM chain                             | Smart wallets, gas sponsorship                    |
| [Gelato](https://docs.gelato.network/)                        |      |   ✓  |                  | Any EVM chain                             | Native 7702, built-in gas sponsorship             |
| [Porto](https://porto.sh)                                     |      |   ✓  |                  | [Multiple chains](https://porto.sh/relay) | 7702-native relay, merchant-based gas sponsorship |
| [Safe](https://docs.safe.global/)                             |   ✓  |      |         ✓        | Any EVM chain                             | Multi-sig, modular accounts                       |
| [Rhinestone](https://docs.rhinestone.wtf/)                    |   ✓  |      |         ✓        | Any EVM chain                             | Cross-chain orchestration                         |
| [Coinbase Developer Platform](https://docs.cdp.coinbase.com/) |   ✓  |      |                  | Base, Base Sepolia only                   | Coinbase smart accounts                           |

## Using with External Wallets

If your user signs in with a supported browser wallet (MetaMask, Rainbow, etc.) and has no embedded wallets in their session, invoking any of the hooks and not specifying an address (or specifying the external wallet's address) will use that wallet as the smart account signer, with no extra configuration needed.

* External wallets can only use **EIP-4337 mode**. EIP-7702 requires `signAuthorization`, which most browser wallets currently don't support — attempting it throws a `SmartAccountError` with code `INVALID_CONFIG`.
* The external wallet must be on the **same chain** as the smart account before calling `sendTransaction`. A mismatch throws a `SmartAccountError` with code `CHAIN_MISMATCH`. You can use wagmi's `useSwitchChain` to manage your connection state before attempting a transaction.

## Provider Guides

Select a provider below for installation and usage instructions.

<Tabs>
  <Tab title="Alchemy">
    <Link label="Alchemy Account Kit" href="https://www.alchemy.com/account-kit" /> provides modular smart accounts with built-in gas sponsorship via Alchemy's Gas Manager. Create and manage smart accounts, submit gasless transactions, and execute batched UserOperations — all without requiring users to leave your application. Supports both EIP-4337 and EIP-7702 modes.

    ### Setup

    1. Create an <Link label="Alchemy account" href="https://dashboard.alchemy.com/signup" /> and obtain your **API key** and **Gas Policy ID** from the Alchemy dashboard.

    2. Install the required dependencies:

    <CodeGroup>
      ```bash npm theme={null}
      npm install @getpara/react-sdk viem
      ```

      ```bash yarn theme={null}
      yarn add @getpara/react-sdk viem
      ```

      ```bash pnpm theme={null}
      pnpm add @getpara/react-sdk viem
      ```
    </CodeGroup>

    ### Usage

    <Tabs>
      <Tab title="useAlchemySmartAccount">
        The simplest way to integrate Alchemy smart accounts into your Para React application. The hook manages initialization, caching, and re-creation automatically via React Query.

        ```tsx AlchemySmartAccount.tsx theme={null}
        import { useAlchemySmartAccount } from "@getpara/react-sdk";
        import { useMutation } from "@tanstack/react-query";
        import { sepolia } from "viem/chains";
        import { parseEther } from "viem";

        const ALCHEMY_API_KEY = process.env.NEXT_PUBLIC_ALCHEMY_API_KEY!;
        const GAS_POLICY_ID = process.env.NEXT_PUBLIC_ALCHEMY_GAS_POLICY_ID!;

        export function AlchemySmartAccount() {
          // Initialize the smart account. The hook handles Para signer creation,
          // account client setup, and paymaster configuration internally.
          // It re-creates the account automatically if any config value changes.
          const { smartAccount, isLoading, error } = useAlchemySmartAccount({
            apiKey: ALCHEMY_API_KEY,
            chain: sepolia,
            gasPolicyId: GAS_POLICY_ID, // enables gas sponsorship
            mode: "4337", // or "7702" — see EIP comparison above
          });

          // Wrap sendTransaction in a mutation for loading/error state management.
          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);
            },
          });

          // Wrap sendBatchTransaction for executing multiple calls atomically.
          // All calls are bundled into a single on-chain transaction.
          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>
              <p>Smart Account: {smartAccount.smartAccountAddress}</p>
              <p>Mode: {smartAccount.mode}</p>

              {/* Single transaction */}
              <button onClick={() => sendTransaction()} disabled={isSending}>
                {isSending ? "Sending..." : "Send Transaction"}
              </button>
              {sendError && <p>Send failed: {sendError.message}</p>}

              {/* Batched transactions */}
              <button onClick={() => sendBatch()} disabled={isBatching}>
                {isBatching ? "Batching..." : "Send Batch"}
              </button>
              {batchError && <p>Batch failed: {batchError.message}</p>}
            </div>
          );
        }
        ```
      </Tab>

      <Tab title="createAlchemySmartAccount">
        For use outside React components or when you need more control over initialization.

        ```typescript alchemy-action.ts theme={null}
        import { createAlchemySmartAccount } from "@getpara/react-sdk";
        import { sepolia } from "viem/chains";
        import { parseEther } from "viem";

        // `para` is your authenticated Para instance
        const smartAccount = await createAlchemySmartAccount({
          para,
          apiKey: "YOUR_ALCHEMY_API_KEY",
          chain: sepolia,
          gasPolicyId: "YOUR_GAS_POLICY_ID",
          mode: "4337", // or "7702"
        });

        if (smartAccount) {
          // Send a single transaction
          const receipt = await smartAccount.sendTransaction({
            to: "0xRecipient",
            value: parseEther("0.01"),
          });

          // Send batched transactions
          const batchReceipt = await smartAccount.sendBatchTransaction([
            { to: "0xRecipientA", value: parseEther("0.01") },
            { to: "0xRecipientB", data: "0xencodedCallData" },
          ]);
        }
        ```
      </Tab>
    </Tabs>

    <Note>
      Alchemy requires chains from `@account-kit/infra` (e.g. `sepolia`, `baseSepolia`). Plain viem chains are
      automatically mapped if an Alchemy equivalent exists. For gasless transactions, set up a Gas Manager Policy in your <Link label="Alchemy Dashboard" href="https://dashboard.alchemy.com" /> and pass the policy ID as `gasPolicyId`.
    </Note>

    <Info>
      **External wallet support:** Alchemy supports external wallets (e.g. MetaMask, Rainbow) as signers via the `signer` parameter in 4337 mode. Requesting `mode: "7702"` with an external wallet will throw a `SmartAccountError` — external wallets cannot produce the raw `signAuthorization` needed for EIP-7702.
    </Info>
  </Tab>

  <Tab title="ZeroDev">
    <Link label="ZeroDev" href="https://docs.zerodev.app/" /> is an embedded AA wallet powering many smart accounts across EVM chains. Known for its extensive feature set including gas sponsorship, session keys, recovery, multisig, and <Link label="chain abstraction" href="https://docs.zerodev.app/sdk/advanced/chain-abstraction" />. Supports both EIP-4337 and EIP-7702 modes.

    ### Setup

    1. Create a <Link label="ZeroDev account" href="https://dashboard.zerodev.app/" /> and obtain your **Project ID** from the ZeroDev dashboard.

    2. Install the required dependencies:

    <CodeGroup>
      ```bash npm theme={null}
      npm install @getpara/react-sdk viem
      ```

      ```bash yarn theme={null}
      yarn add @getpara/react-sdk viem
      ```

      ```bash pnpm theme={null}
      pnpm add @getpara/react-sdk viem
      ```
    </CodeGroup>

    ### Usage

    <Tabs>
      <Tab title="useZeroDevSmartAccount">
        The simplest way to integrate ZeroDev smart accounts into your Para React application. The hook manages initialization, caching, and re-creation automatically via React Query.

        ```tsx ZeroDevSmartAccount.tsx theme={null}
        import { useZeroDevSmartAccount } from "@getpara/react-sdk";
        import { useMutation } from "@tanstack/react-query";
        import { sepolia } from "viem/chains";
        import { parseEther } from "viem";

        const ZERODEV_PROJECT_ID = process.env.NEXT_PUBLIC_ZERODEV_PROJECT_ID!;

        export function ZeroDevSmartAccount() {
          // Initialize the smart account. The hook handles Para signer creation,
          // Kernel account setup, and ECDSA validator configuration internally.
          const { smartAccount, isLoading, error } = useZeroDevSmartAccount({
            projectId: ZERODEV_PROJECT_ID,
            chain: sepolia,
            mode: "4337", // or "7702"
          });

          // Wrap sendTransaction in a mutation for loading/error state management.
          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);
            },
          });

          // Wrap sendBatchTransaction for executing multiple calls atomically.
          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>
              <p>Smart Account: {smartAccount.smartAccountAddress}</p>
              <p>Mode: {smartAccount.mode}</p>

              {/* Single transaction */}
              <button onClick={() => sendTransaction()} disabled={isSending}>
                {isSending ? "Sending..." : "Send Transaction"}
              </button>
              {sendError && <p>Send failed: {sendError.message}</p>}

              {/* Batched transactions */}
              <button onClick={() => sendBatch()} disabled={isBatching}>
                {isBatching ? "Batching..." : "Send Batch"}
              </button>
              {batchError && <p>Batch failed: {batchError.message}</p>}
            </div>
          );
        }
        ```
      </Tab>

      <Tab title="createZeroDevSmartAccount">
        For use outside React components or when you need more control over initialization.

        ```typescript zerodev-action.ts theme={null}
        import { createZeroDevSmartAccount } from "@getpara/react-sdk";
        import { sepolia } from "viem/chains";
        import { parseEther } from "viem";

        // `para` is your authenticated Para instance
        const smartAccount = await createZeroDevSmartAccount({
          para,
          projectId: "YOUR_ZERODEV_PROJECT_ID",
          chain: sepolia,
          mode: "4337", // or "7702"
        });

        if (smartAccount) {
          // Send a single transaction
          const receipt = await smartAccount.sendTransaction({
            to: "0xRecipient",
            value: parseEther("0.01"),
          });

          // Send batched transactions
          const batchReceipt = await smartAccount.sendBatchTransaction([
            { to: "0xRecipientA", value: parseEther("0.01") },
            { to: "0xRecipientB", data: "0xencodedCallData" },
          ]);
        }
        ```
      </Tab>
    </Tabs>

    <Note>
      You can optionally pass `bundlerUrl` and `paymasterUrl` to use custom infrastructure instead of ZeroDev's defaults. For more on managing your ZeroDev project and RPC endpoints, see the <Link label="ZeroDev RPC documentation" href="https://docs.zerodev.app/meta-infra/rpcs" />.
    </Note>

    <Info>
      **External wallet support:** ZeroDev supports external wallets (e.g. MetaMask, Rainbow) as signers via the `signer` parameter in 4337 mode. Requesting `mode: "7702"` with an external wallet will throw a `SmartAccountError` — external wallets cannot produce the raw `signAuthorization` needed for EIP-7702.
    </Info>
  </Tab>

  <Tab title="Pimlico">
    <Link label="Pimlico" href="https://docs.pimlico.io/" /> provides account abstraction infrastructure via <Link label="permissionless.js" href="https://docs.pimlico.io/permissionless" />, a TypeScript library built on viem with no extra dependencies and a small bundle size. Pimlico supports multiple account implementations including Safe, Kernel, Biconomy, and SimpleAccount. Supports both EIP-4337 and EIP-7702 modes.

    ### Setup

    1. Create a <Link label="Pimlico account" href="https://dashboard.pimlico.io/" /> and obtain your **API key** from the Pimlico dashboard.

    2. Install the required dependencies:

    <CodeGroup>
      ```bash npm theme={null}
      npm install @getpara/react-sdk viem
      ```

      ```bash yarn theme={null}
      yarn add @getpara/react-sdk viem
      ```

      ```bash pnpm theme={null}
      pnpm add @getpara/react-sdk viem
      ```
    </CodeGroup>

    ### Usage

    <Tabs>
      <Tab title="usePimlicoSmartAccount">
        The simplest way to integrate Pimlico smart accounts into your Para React application. The hook manages initialization, caching, and re-creation automatically via React Query.

        ```tsx PimlicoSmartAccount.tsx theme={null}
        import { usePimlicoSmartAccount } from "@getpara/react-sdk";
        import { useMutation } from "@tanstack/react-query";
        import { sepolia } from "viem/chains";
        import { parseEther } from "viem";

        const PIMLICO_API_KEY = process.env.NEXT_PUBLIC_PIMLICO_API_KEY!;

        export function PimlicoSmartAccount() {
          // Initialize the smart account. The hook handles Para signer creation,
          // simple account setup, and Pimlico paymaster configuration internally.
          const { smartAccount, isLoading, error } = usePimlicoSmartAccount({
            apiKey: PIMLICO_API_KEY,
            chain: sepolia,
            mode: "4337", // or "7702"
          });

          // Wrap sendTransaction in a mutation for loading/error state management.
          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);
            },
          });

          // Wrap sendBatchTransaction for executing multiple calls atomically.
          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>
              <p>Smart Account: {smartAccount.smartAccountAddress}</p>
              <p>Mode: {smartAccount.mode}</p>

              {/* Single transaction */}
              <button onClick={() => sendTransaction()} disabled={isSending}>
                {isSending ? "Sending..." : "Send Transaction"}
              </button>
              {sendError && <p>Send failed: {sendError.message}</p>}

              {/* Batched transactions */}
              <button onClick={() => sendBatch()} disabled={isBatching}>
                {isBatching ? "Batching..." : "Send Batch"}
              </button>
              {batchError && <p>Batch failed: {batchError.message}</p>}
            </div>
          );
        }
        ```
      </Tab>

      <Tab title="createPimlicoSmartAccount">
        For use outside React components or when you need more control over initialization.

        ```typescript pimlico-action.ts theme={null}
        import { createPimlicoSmartAccount } from "@getpara/react-sdk";
        import { sepolia } from "viem/chains";
        import { parseEther } from "viem";

        // `para` is your authenticated Para instance
        const smartAccount = await createPimlicoSmartAccount({
          para,
          apiKey: "YOUR_PIMLICO_API_KEY",
          chain: sepolia,
          mode: "4337", // or "7702"
        });

        if (smartAccount) {
          // Send a single transaction
          const receipt = await smartAccount.sendTransaction({
            to: "0xRecipient",
            value: parseEther("0.01"),
          });

          // Send batched transactions
          const batchReceipt = await smartAccount.sendBatchTransaction([
            { to: "0xRecipientA", value: parseEther("0.01") },
            { to: "0xRecipientB", data: "0xencodedCallData" },
          ]);
        }
        ```
      </Tab>
    </Tabs>

    <Note>
      The Pimlico bundler/paymaster URL is automatically constructed from your API key and chain name. You can override it with a custom `rpcUrl`. Pimlico's permissionless.js also supports other account types (Safe, Kernel, Biconomy, SimpleAccount) — see the <Link label="permissionless.js tutorial" href="https://docs.pimlico.io/permissionless/tutorial/tutorial-1" />.
    </Note>

    <Info>
      **External wallet support:** Pimlico supports external wallets (e.g. MetaMask, Rainbow) as signers via the `signer` parameter in 4337 mode. Requesting `mode: "7702"` with an external wallet will throw a `SmartAccountError` — external wallets cannot produce the raw `signAuthorization` needed for EIP-7702.
    </Info>
  </Tab>

  <Tab title="Biconomy">
    <Link label="Biconomy" href="https://docs.biconomy.io/" /> is a full-stack AA toolkit built on ERC-4337 that provides smart accounts, paymasters, and bundlers. Its Multi-chain Execution Environment (MEE) enables cross-chain orchestration of transactions. Supports both EIP-4337 and EIP-7702 modes.

    ### Setup

    1. Create a <Link label="Biconomy account" href="https://dashboard.biconomy.io/" /> and obtain your **API key** from the Biconomy dashboard.

    2. Install the required dependencies:

    <CodeGroup>
      ```bash npm theme={null}
      npm install @getpara/react-sdk viem
      ```

      ```bash yarn theme={null}
      yarn add @getpara/react-sdk viem
      ```

      ```bash pnpm theme={null}
      pnpm add @getpara/react-sdk viem
      ```
    </CodeGroup>

    ### Usage

    <Tabs>
      <Tab title="useBiconomySmartAccount">
        The simplest way to integrate Biconomy smart accounts into your Para React application. The hook manages initialization, caching, and re-creation automatically via React Query.

        ```tsx BiconomySmartAccount.tsx theme={null}
        import { useBiconomySmartAccount } from "@getpara/react-sdk";
        import { useMutation } from "@tanstack/react-query";
        import { sepolia } from "viem/chains";
        import { parseEther } from "viem";

        const BICONOMY_API_KEY = process.env.NEXT_PUBLIC_BICONOMY_API_KEY!;

        export function BiconomySmartAccount() {
          // Initialize the smart account. The hook handles Para signer creation,
          // Nexus account setup, and MEE client configuration internally.
          const { smartAccount, isLoading, error } = useBiconomySmartAccount({
            apiKey: BICONOMY_API_KEY,
            chain: sepolia,
            mode: "4337", // or "7702"
          });

          // Wrap sendTransaction in a mutation for loading/error state management.
          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);
            },
          });

          // Wrap sendBatchTransaction for executing multiple calls atomically.
          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>
              <p>Smart Account: {smartAccount.smartAccountAddress}</p>
              <p>Mode: {smartAccount.mode}</p>

              {/* Single transaction */}
              <button onClick={() => sendTransaction()} disabled={isSending}>
                {isSending ? "Sending..." : "Send Transaction"}
              </button>
              {sendError && <p>Send failed: {sendError.message}</p>}

              {/* Batched transactions */}
              <button onClick={() => sendBatch()} disabled={isBatching}>
                {isBatching ? "Batching..." : "Send Batch"}
              </button>
              {batchError && <p>Batch failed: {batchError.message}</p>}
            </div>
          );
        }
        ```
      </Tab>

      <Tab title="createBiconomySmartAccount">
        For use outside React components or when you need more control over initialization.

        ```typescript biconomy-action.ts theme={null}
        import { createBiconomySmartAccount } from "@getpara/react-sdk";
        import { sepolia } from "viem/chains";
        import { parseEther } from "viem";

        // `para` is your authenticated Para instance
        const smartAccount = await createBiconomySmartAccount({
          para,
          apiKey: "YOUR_BICONOMY_API_KEY",
          chain: sepolia,
          mode: "4337", // or "7702"
        });

        if (smartAccount) {
          // Send a single transaction
          const receipt = await smartAccount.sendTransaction({
            to: "0xRecipient",
            value: parseEther("0.01"),
          });

          // Send batched transactions
          const batchReceipt = await smartAccount.sendBatchTransaction([
            { to: "0xRecipientA", value: parseEther("0.01") },
            { to: "0xRecipientB", data: "0xencodedCallData" },
          ]);
        }
        ```
      </Tab>
    </Tabs>

    <Note>
      Biconomy transactions are executed via the MEE (Multi-chain Execution Environment). You can optionally pass a custom `meeUrl` to use your own MEE node.
    </Note>

    <Info>
      **External wallet support:** Biconomy supports external wallets (e.g. MetaMask, Rainbow) as signers via the `signer` parameter in 4337 mode. Requesting `mode: "7702"` with an external wallet will throw a `SmartAccountError` — external wallets cannot produce the raw `signAuthorization` needed for EIP-7702.
    </Info>
  </Tab>

  <Tab title="Thirdweb">
    <Link label="Thirdweb" href="https://portal.thirdweb.com/" /> provides smart wallets with built-in gas sponsorship.
    Supports both EIP-4337 and EIP-7702 modes.

    ### Setup

    1. Create a <Link label="Thirdweb account" href="https://thirdweb.com/dashboard" /> and obtain your **Client ID** from the Thirdweb dashboard.

    2. Install the required dependencies:

    <CodeGroup>
      ```bash npm theme={null}
      npm install @getpara/react-sdk viem
      ```

      ```bash yarn theme={null}
      yarn add @getpara/react-sdk viem
      ```

      ```bash pnpm theme={null}
      pnpm add @getpara/react-sdk viem
      ```
    </CodeGroup>

    ### Usage

    <Tabs>
      <Tab title="useThirdwebSmartAccount">
        The simplest way to integrate Thirdweb smart accounts into your Para React application. The hook manages initialization, caching, and re-creation automatically via React Query.

        ```tsx ThirdwebSmartAccount.tsx theme={null}
        import { useThirdwebSmartAccount } from "@getpara/react-sdk";
        import { useMutation } from "@tanstack/react-query";
        import { sepolia } from "viem/chains";
        import { parseEther } from "viem";

        const THIRDWEB_CLIENT_ID = process.env.NEXT_PUBLIC_THIRDWEB_CLIENT_ID!;

        export function ThirdwebSmartAccount() {
          // Initialize the smart account. The hook handles Para signer creation,
          // smart wallet setup, and gas sponsorship configuration internally.
          const { smartAccount, isLoading, error } = useThirdwebSmartAccount({
            clientId: THIRDWEB_CLIENT_ID,
            chain: sepolia,
            sponsorGas: true, // enable gas sponsorship (default)
            mode: "4337", // or "7702"
          });

          // Wrap sendTransaction in a mutation for loading/error state management.
          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);
            },
          });

          // Wrap sendBatchTransaction for executing multiple calls atomically.
          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>
              <p>Smart Account: {smartAccount.smartAccountAddress}</p>
              <p>Mode: {smartAccount.mode}</p>

              {/* Single transaction */}
              <button onClick={() => sendTransaction()} disabled={isSending}>
                {isSending ? "Sending..." : "Send Transaction"}
              </button>
              {sendError && <p>Send failed: {sendError.message}</p>}

              {/* Batched transactions */}
              <button onClick={() => sendBatch()} disabled={isBatching}>
                {isBatching ? "Batching..." : "Send Batch"}
              </button>
              {batchError && <p>Batch failed: {batchError.message}</p>}
            </div>
          );
        }
        ```
      </Tab>

      <Tab title="createThirdwebSmartAccount">
        For use outside React components or when you need more control over initialization.

        ```typescript thirdweb-action.ts theme={null}
        import { createThirdwebSmartAccount } from "@getpara/react-sdk";
        import { sepolia } from "viem/chains";
        import { parseEther } from "viem";

        // `para` is your authenticated Para instance
        const smartAccount = await createThirdwebSmartAccount({
          para,
          clientId: "YOUR_THIRDWEB_CLIENT_ID",
          chain: sepolia,
          sponsorGas: true, // enable gas sponsorship (default)
          mode: "4337", // or "7702"
        });

        if (smartAccount) {
          // Send a single transaction
          const receipt = await smartAccount.sendTransaction({
            to: "0xRecipient",
            value: parseEther("0.01"),
          });

          // Send batched transactions
          const batchReceipt = await smartAccount.sendBatchTransaction([
            { to: "0xRecipientA", value: parseEther("0.01") },
            { to: "0xRecipientB", data: "0xencodedCallData" },
          ]);
        }
        ```
      </Tab>
    </Tabs>

    <Note>
      Set `sponsorGas: false` to disable gas sponsorship. In EIP-4337 mode, you can optionally provide `factoryAddress` and `accountAddress` for custom smart wallet deployments.
    </Note>

    <Info>
      **External wallet support:** Thirdweb supports external wallets (e.g. MetaMask, Rainbow) as signers via the `signer` parameter in 4337 mode. Requesting `mode: "7702"` with an external wallet will throw a `SmartAccountError` — external wallets cannot produce the raw `signAuthorization` needed for EIP-7702.
    </Info>
  </Tab>

  <Tab title="Gelato">
    <Link label="Gelato" href="https://docs.gelato.network/" /> provides native EIP-7702 smart accounts with built-in gas sponsorship via relay infrastructure.

    ### Setup

    1. Create a <Link label="Gelato account" href="https://app.gelato.network/" /> and obtain your **API key** from the Gelato dashboard.

    2. Install the required dependencies:

    <CodeGroup>
      ```bash npm theme={null}
      npm install @getpara/react-sdk viem
      ```

      ```bash yarn theme={null}
      yarn add @getpara/react-sdk viem
      ```

      ```bash pnpm theme={null}
      pnpm add @getpara/react-sdk viem
      ```
    </CodeGroup>

    ### Usage

    <Tabs>
      <Tab title="useGelatoSmartAccount">
        The simplest way to integrate Gelato smart accounts into your Para React application. The hook manages initialization, caching, and re-creation automatically via React Query.

        ```tsx GelatoSmartAccount.tsx theme={null}
        import { useGelatoSmartAccount } from "@getpara/react-sdk";
        import { useMutation } from "@tanstack/react-query";
        import { sepolia } from "viem/chains";
        import { parseEther } from "viem";

        const GELATO_API_KEY = process.env.NEXT_PUBLIC_GELATO_API_KEY!;

        export function GelatoSmartAccount() {
          // Initialize the smart account. The hook handles Para signer creation,
          // Gelato account setup, and 7702 delegation internally.
          // Gelato only supports EIP-7702 mode.
          const { smartAccount, isLoading, error } = useGelatoSmartAccount({
            apiKey: GELATO_API_KEY,
            chain: sepolia,
          });

          // Wrap sendTransaction in a mutation for loading/error state management.
          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);
            },
          });

          // Wrap sendBatchTransaction for executing multiple calls atomically.
          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>
              <p>Smart Account: {smartAccount.smartAccountAddress}</p>
              <p>Mode: {smartAccount.mode}</p>

              {/* Single transaction */}
              <button onClick={() => sendTransaction()} disabled={isSending}>
                {isSending ? "Sending..." : "Send Transaction"}
              </button>
              {sendError && <p>Send failed: {sendError.message}</p>}

              {/* Batched transactions */}
              <button onClick={() => sendBatch()} disabled={isBatching}>
                {isBatching ? "Batching..." : "Send Batch"}
              </button>
              {batchError && <p>Batch failed: {batchError.message}</p>}
            </div>
          );
        }
        ```
      </Tab>

      <Tab title="createGelatoSmartAccount">
        For use outside React components or when you need more control over initialization.

        ```typescript gelato-action.ts theme={null}
        import { createGelatoSmartAccount } from "@getpara/react-sdk";
        import { sepolia } from "viem/chains";
        import { parseEther } from "viem";

        // `para` is your authenticated Para instance
        const smartAccount = await createGelatoSmartAccount({
          para,
          apiKey: "YOUR_GELATO_API_KEY",
          chain: sepolia,
        });

        if (smartAccount) {
          // Send a single transaction
          const receipt = await smartAccount.sendTransaction({
            to: "0xRecipient",
            value: parseEther("0.01"),
          });

          // Send batched transactions
          const batchReceipt = await smartAccount.sendBatchTransaction([
            { to: "0xRecipientA", value: parseEther("0.01") },
            { to: "0xRecipientB", data: "0xencodedCallData" },
          ]);
        }
        ```
      </Tab>
    </Tabs>

    <Note>
      Gelato only supports EIP-7702 mode. Gas sponsorship is built into Gelato's relay infrastructure — no separate paymaster configuration is needed.
    </Note>

    <Info>
      **No external wallet support.** Gelato is 7702-only and requires `signAuthorization`, which external wallets (MetaMask, Rainbow, etc.) cannot produce. Passing an external wallet as `signer` will throw a `SmartAccountError`.
    </Info>
  </Tab>

  <Tab title="Porto">
    <Link label="Porto" href="https://porto.sh/docs" /> provides 7702-native smart accounts with a built-in relay — no bundler or paymaster needed.

    ### Setup

    1. No API key or third-party account is needed. Porto uses its own relay RPC.

    2. **Gas sponsorship:** On testnets, Porto's relay sponsors gas by default — no setup needed.
       For **mainnet**, you must set up a <Link label="Porto merchant account" href="https://porto.sh/sdk/guides/sponsoring" /> to cover gas fees for your users. Run `pnpx porto onboard --admin-key` to create a merchant
       account, deploy a server-side merchant route using `porto/server`, and pass your endpoint URL
       as `merchantUrl` in the config below.

    3. Install the required dependencies:

    <CodeGroup>
      ```bash npm theme={null}
      npm install @getpara/react-sdk viem
      ```

      ```bash yarn theme={null}
      yarn add @getpara/react-sdk viem
      ```

      ```bash pnpm theme={null}
      pnpm add @getpara/react-sdk viem
      ```
    </CodeGroup>

    ### Usage

    <Tabs>
      <Tab title="usePortoSmartAccount">
        The simplest way to integrate Porto smart accounts into your Para React application. The hook manages initialization, caching, and re-creation automatically via React Query.

        ```tsx PortoSmartAccount.tsx theme={null}
        import { usePortoSmartAccount } from "@getpara/react-sdk";
        import { useMutation } from "@tanstack/react-query";
        import { parseEther } from "viem";
        import { base } from "viem/chains";

        export function PortoSmartAccount() {
          // Initialize the smart account. The hook handles Para signer creation
          // and Porto relay configuration internally.
          // Testnets: gas is sponsored by default, no merchantUrl needed.
          // Mainnet: merchantUrl is required for gas sponsorship.
          const { smartAccount, isLoading, error } = usePortoSmartAccount({
            chain: base,
            merchantUrl: '/porto/merchant',        // required for mainnet
          });

          // Wrap sendTransaction in a mutation for loading/error state management.
          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);
            },
          });

          // Wrap sendBatchTransaction for executing multiple calls atomically.
          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>
              <p>Smart Account: {smartAccount.smartAccountAddress}</p>
              <p>Mode: {smartAccount.mode}</p>

              {/* Single transaction */}
              <button onClick={() => sendTransaction()} disabled={isSending}>
                {isSending ? "Sending..." : "Send Transaction"}
              </button>
              {sendError && <p>Send failed: {sendError.message}</p>}

              {/* Batched transactions */}
              <button onClick={() => sendBatch()} disabled={isBatching}>
                {isBatching ? "Batching..." : "Send Batch"}
              </button>
              {batchError && <p>Batch failed: {batchError.message}</p>}
            </div>
          );
        }
        ```
      </Tab>

      <Tab title="createPortoSmartAccount">
        For use outside React components or when you need more control over initialization.

        ```typescript porto-action.ts theme={null}
        import { createPortoSmartAccount } from "@getpara/react-sdk";
        import { parseEther } from "viem";
        import { base } from "viem/chains";

        // `para` is your authenticated Para instance
        // Testnets: gas is sponsored by default, no merchantUrl needed.
        // Mainnet: merchantUrl is required for gas sponsorship.
        const smartAccount = await createPortoSmartAccount({
          para,
          chain: base,
          merchantUrl: '/porto/merchant',     // required for mainnet
        });

        if (smartAccount) {
          // Send a single transaction
          const receipt = await smartAccount.sendTransaction({
            to: "0xRecipient",
            value: parseEther("0.01"),
          });

          // Send batched transactions
          const batchReceipt = await smartAccount.sendBatchTransaction([
            { to: "0xRecipientA", value: parseEther("0.01") },
            { to: "0xRecipientB", data: "0xencodedCallData" },
          ]);
        }
        ```
      </Tab>
    </Tabs>

    <Note>
      Porto only supports EIP-7702 mode. The Porto relay supports <Link label="multiple chains" href="https://porto.sh/relay" /> including Base, Optimism, Arbitrum, Ethereum, and several testnets. On testnets, gas fees are sponsored by default. For mainnet, a <Link label="merchant account" href="https://porto.sh/sdk/guides/sponsoring" /> is required — pass `merchantUrl` to enable gas sponsorship.
    </Note>

    <Info>
      **No external wallet support.** Porto is 7702-only and requires `signAuthorization`, which external wallets (MetaMask, Rainbow, etc.) cannot produce. Passing an external wallet as `signer` will throw a `SmartAccountError`.
    </Info>
  </Tab>

  <Tab title="Safe">
    <Link label="Safe" href="https://docs.safe.global/" /> (formerly Gnosis Safe) provides multi-signature smart contract wallets with ERC-4337 compatibility. The user's EOA from Para serves as the signer, while the Safe smart contract wallet holds assets and submits transactions. Powered by Pimlico's bundler and paymaster infrastructure.

    ### Setup

    1. Create a <Link label="Pimlico account" href="https://dashboard.pimlico.io/" /> and obtain your **API key** — Safe uses Pimlico for bundler and paymaster services.

    2. Install the required dependencies:

    <CodeGroup>
      ```bash npm theme={null}
      npm install @getpara/react-sdk viem
      ```

      ```bash yarn theme={null}
      yarn add @getpara/react-sdk viem
      ```

      ```bash pnpm theme={null}
      pnpm add @getpara/react-sdk viem
      ```
    </CodeGroup>

    ### Usage

    <Tabs>
      <Tab title="useSafeSmartAccount">
        The simplest way to integrate Safe smart accounts into your Para React application. The hook manages initialization, caching, and re-creation automatically via React Query.

        ```tsx SafeSmartAccount.tsx theme={null}
        import { useSafeSmartAccount } from "@getpara/react-sdk";
        import { useMutation } from "@tanstack/react-query";
        import { sepolia } from "viem/chains";
        import { parseEther } from "viem";

        const PIMLICO_API_KEY = process.env.NEXT_PUBLIC_PIMLICO_API_KEY!;

        export function SafeSmartAccount() {
          // Initialize the smart account. The hook handles Para signer creation,
          // Safe account setup, and Pimlico paymaster configuration internally.
          // Safe only supports EIP-4337 mode.
          const { smartAccount, isLoading, error } = useSafeSmartAccount({
            pimlicoApiKey: PIMLICO_API_KEY,
            chain: sepolia,
          });

          // Wrap sendTransaction in a mutation for loading/error state management.
          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);
            },
          });

          // Wrap sendBatchTransaction for executing multiple calls atomically.
          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>
              <p>Smart Account: {smartAccount.smartAccountAddress}</p>
              <p>Mode: {smartAccount.mode}</p>

              {/* Single transaction */}
              <button onClick={() => sendTransaction()} disabled={isSending}>
                {isSending ? "Sending..." : "Send Transaction"}
              </button>
              {sendError && <p>Send failed: {sendError.message}</p>}

              {/* Batched transactions */}
              <button onClick={() => sendBatch()} disabled={isBatching}>
                {isBatching ? "Batching..." : "Send Batch"}
              </button>
              {batchError && <p>Batch failed: {batchError.message}</p>}
            </div>
          );
        }
        ```
      </Tab>

      <Tab title="createSafeSmartAccount">
        For use outside React components or when you need more control over initialization.

        ```typescript safe-action.ts theme={null}
        import { createSafeSmartAccount } from "@getpara/react-sdk";
        import { sepolia } from "viem/chains";
        import { parseEther } from "viem";

        // `para` is your authenticated Para instance
        const smartAccount = await createSafeSmartAccount({
          para,
          pimlicoApiKey: "YOUR_PIMLICO_API_KEY",
          chain: sepolia,
        });

        if (smartAccount) {
          // Send a single transaction
          const receipt = await smartAccount.sendTransaction({
            to: "0xRecipient",
            value: parseEther("0.01"),
          });

          // Send batched transactions
          const batchReceipt = await smartAccount.sendBatchTransaction([
            { to: "0xRecipientA", value: parseEther("0.01") },
            { to: "0xRecipientB", data: "0xencodedCallData" },
          ]);
        }
        ```
      </Tab>
    </Tabs>

    <Note>
      Safe only supports EIP-4337 mode. You can optionally pass `safeVersion` (default: `"1.4.1"`) and `saltNonce` for deterministic address generation.
    </Note>

    <Info>
      **External wallet support:** Safe supports external wallets (e.g. MetaMask, Rainbow) as signers via the `signer` parameter.
    </Info>
  </Tab>

  <Tab title="Rhinestone">
    <Link label="Rhinestone" href="https://docs.rhinestone.wtf/" /> provides cross-chain smart accounts with intent-based transactions, automatic bridging, and gas abstraction across multiple EVM chains. Transactions are routed through Rhinestone's orchestrator which handles cross-chain execution automatically.

    ### Setup

    1. Obtain your **Rhinestone API key** and optionally a **Pimlico API key** for bundler/paymaster infrastructure.

    2. Install the required dependencies:

    <CodeGroup>
      ```bash npm theme={null}
      npm install @getpara/react-sdk viem
      ```

      ```bash yarn theme={null}
      yarn add @getpara/react-sdk viem
      ```

      ```bash pnpm theme={null}
      pnpm add @getpara/react-sdk viem
      ```
    </CodeGroup>

    ### Usage

    <Tabs>
      <Tab title="useRhinestoneSmartAccount">
        The simplest way to integrate Rhinestone smart accounts into your Para React application. The hook manages initialization, caching, and re-creation automatically via React Query.

        ```tsx RhinestoneSmartAccount.tsx theme={null}
        import { useRhinestoneSmartAccount } from "@getpara/react-sdk";
        import { useMutation } from "@tanstack/react-query";
        import { sepolia } from "viem/chains";
        import { parseEther } from "viem";

        const RHINESTONE_API_KEY = process.env.NEXT_PUBLIC_RHINESTONE_API_KEY!;
        const PIMLICO_API_KEY = process.env.NEXT_PUBLIC_PIMLICO_API_KEY!;

        export function RhinestoneSmartAccount() {
          // Initialize the smart account. The hook handles Para signer creation,
          // Rhinestone account setup, and orchestrator configuration internally.
          // Rhinestone only supports EIP-4337 mode.
          const { smartAccount, isLoading, error } = useRhinestoneSmartAccount({
            chain: sepolia,
            rhinestoneApiKey: RHINESTONE_API_KEY,
            pimlicoApiKey: PIMLICO_API_KEY,
          });

          // Wrap sendTransaction in a mutation for loading/error state management.
          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);
            },
          });

          // Wrap sendBatchTransaction for executing multiple calls atomically.
          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>
              <p>Smart Account: {smartAccount.smartAccountAddress}</p>
              <p>Mode: {smartAccount.mode}</p>

              {/* Single transaction */}
              <button onClick={() => sendTransaction()} disabled={isSending}>
                {isSending ? "Sending..." : "Send Transaction"}
              </button>
              {sendError && <p>Send failed: {sendError.message}</p>}

              {/* Batched transactions */}
              <button onClick={() => sendBatch()} disabled={isBatching}>
                {isBatching ? "Batching..." : "Send Batch"}
              </button>
              {batchError && <p>Batch failed: {batchError.message}</p>}
            </div>
          );
        }
        ```
      </Tab>

      <Tab title="createRhinestoneSmartAccount">
        For use outside React components or when you need more control over initialization.

        ```typescript rhinestone-action.ts theme={null}
        import { createRhinestoneSmartAccount } from "@getpara/react-sdk";
        import { sepolia } from "viem/chains";
        import { parseEther } from "viem";

        // `para` is your authenticated Para instance
        const smartAccount = await createRhinestoneSmartAccount({
          para,
          chain: sepolia,
          rhinestoneApiKey: "YOUR_RHINESTONE_API_KEY",
          pimlicoApiKey: "YOUR_PIMLICO_API_KEY",
        });

        if (smartAccount) {
          // Send a single transaction
          const receipt = await smartAccount.sendTransaction({
            to: "0xRecipient",
            value: parseEther("0.01"),
          });

          // Send batched transactions
          const batchReceipt = await smartAccount.sendBatchTransaction([
            { to: "0xRecipientA", value: parseEther("0.01") },
            { to: "0xRecipientB", data: "0xencodedCallData" },
          ]);
        }
        ```
      </Tab>
    </Tabs>

    <Note>
      Rhinestone only supports EIP-4337 mode. Both `rhinestoneApiKey` and `pimlicoApiKey` are optional but recommended for production use. For advanced cross-chain use cases with automatic bridging, see the <Link label="Rhinestone documentation" href="https://docs.rhinestone.dev" />.
    </Note>

    <Info>
      **External wallet support:** Rhinestone supports external wallets (e.g. MetaMask, Rainbow) as signers via the `signer` parameter.
    </Info>
  </Tab>

  <Tab title="Coinbase Developer Platform">
    <Link label="Coinbase Developer Platform" href="https://docs.cdp.coinbase.com/" /> provides Coinbase smart accounts on Base. Uses viem's built-in `toCoinbaseSmartAccount` — no additional bundler packages required.

    ### Setup

    1. Create a <Link label="CDP account" href="https://portal.cdp.coinbase.com/" /> and obtain your **RPC token** from the paymaster URL in the CDP dashboard.

    2. Install the required dependencies:

    <CodeGroup>
      ```bash npm theme={null}
      npm install @getpara/react-sdk viem
      ```

      ```bash yarn theme={null}
      yarn add @getpara/react-sdk viem
      ```

      ```bash pnpm theme={null}
      pnpm add @getpara/react-sdk viem
      ```
    </CodeGroup>

    ### Usage

    <Tabs>
      <Tab title="useCDPSmartAccount">
        The simplest way to integrate CDP smart accounts into your Para React application. The hook manages initialization, caching, and re-creation automatically via React Query.

        ```tsx CDPSmartAccount.tsx theme={null}
        import { useCDPSmartAccount } from "@getpara/react-sdk";
        import { useMutation } from "@tanstack/react-query";
        import { baseSepolia } from "viem/chains";
        import { parseEther } from "viem";

        const CDP_RPC_TOKEN = process.env.NEXT_PUBLIC_CDP_RPC_TOKEN!;

        export function CDPSmartAccount() {
          // Initialize the smart account. The hook handles Para signer creation,
          // Coinbase account setup, and CDP paymaster configuration internally.
          // CDP only supports EIP-4337 mode on Base and Base Sepolia.
          const { smartAccount, isLoading, error } = useCDPSmartAccount({
            rpcToken: CDP_RPC_TOKEN,
            chain: baseSepolia,
          });

          // Wrap sendTransaction in a mutation for loading/error state management.
          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);
            },
          });

          // Wrap sendBatchTransaction for executing multiple calls atomically.
          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>
              <p>Smart Account: {smartAccount.smartAccountAddress}</p>
              <p>Mode: {smartAccount.mode}</p>

              {/* Single transaction */}
              <button onClick={() => sendTransaction()} disabled={isSending}>
                {isSending ? "Sending..." : "Send Transaction"}
              </button>
              {sendError && <p>Send failed: {sendError.message}</p>}

              {/* Batched transactions */}
              <button onClick={() => sendBatch()} disabled={isBatching}>
                {isBatching ? "Batching..." : "Send Batch"}
              </button>
              {batchError && <p>Batch failed: {batchError.message}</p>}
            </div>
          );
        }
        ```
      </Tab>

      <Tab title="createCDPSmartAccount">
        For use outside React components or when you need more control over initialization.

        ```typescript cdp-action.ts theme={null}
        import { createCDPSmartAccount } from "@getpara/react-sdk";
        import { baseSepolia } from "viem/chains";
        import { parseEther } from "viem";

        // `para` is your authenticated Para instance
        const smartAccount = await createCDPSmartAccount({
          para,
          rpcToken: "YOUR_CDP_RPC_TOKEN",
          chain: baseSepolia,
        });

        if (smartAccount) {
          // Send a single transaction
          const receipt = await smartAccount.sendTransaction({
            to: "0xRecipient",
            value: parseEther("0.01"),
          });

          // Send batched transactions
          const batchReceipt = await smartAccount.sendBatchTransaction([
            { to: "0xRecipientA", value: parseEther("0.01") },
            { to: "0xRecipientB", data: "0xencodedCallData" },
          ]);
        }
        ```
      </Tab>
    </Tabs>

    <Note>
      CDP only supports EIP-4337 mode and is limited to **Base** and **Base Sepolia** chains. No additional bundler packages are needed — CDP uses viem's built-in `toCoinbaseSmartAccount`.
    </Note>

    <Info>
      **No external wallet support.** CDP's Coinbase smart wallet uses raw `ecrecover` for signature verification, which is incompatible with the EIP-191 prefix that external wallets (MetaMask, Rainbow, etc.) add when signing. Passing an external wallet as `signer` will throw a `SmartAccountError`.
    </Info>
  </Tab>
</Tabs>

## Examples

Explore working examples of Para with AA providers:

<CardGroup cols={2}>
  <Card title="Alchemy Account Kit Example" icon="github" href="https://github.com/getpara/examples-hub/blob/3.0.0/server/with-node/src/routes/signWithAlchemy.ts">
    Node.js example with Alchemy Account Kit
  </Card>

  <Card title="ZeroDev Example" icon="github" href="https://github.com/getpara/examples-hub/blob/3.0.0/server/with-node/src/routes/signWithZerodev.ts">
    Node.js example with ZeroDev Kernel accounts
  </Card>

  <Card title="Rhinestone Example" icon="github" href="https://github.com/getpara/examples-hub/tree/3.0.0/web/with-react-nextjs/aa-rhinestone">
    Next.js example with Rhinestone cross-chain accounts
  </Card>
</CardGroup>
