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

# Privy + AbstractJS SDK

> Add gasless transactions to your React app with Privy embedded wallets using the AbstractJS SDK

Privy lets users create wallets through email or social login. This guide shows you how to connect Privy wallets to Biconomy using the AbstractJS SDK for gasless, cross-chain transactions.

## What We're Building

By the end of this tutorial, your users will be able to:

1. Log in with email (no seed phrase)
2. Execute transactions without holding ETH for gas
3. Perform cross-chain operations with one signature

<Info>
  **How it works**: When a user logs in with Privy, they get an embedded wallet. We upgrade this wallet to a smart account using EIP-7702, then route transactions through Biconomy's MEE to handle gas payments.
</Info>

***

## Step 1: Install Dependencies

```bash theme={null}
npm install @privy-io/react-auth @biconomy/abstractjs viem
```

**What these packages do:**

* `@privy-io/react-auth` — Privy's React SDK for wallet creation and auth
* `@biconomy/abstractjs` — Biconomy's SDK for smart accounts and MEE
* `viem` — Ethereum library for building transactions

## Step 2: Configure Privy Provider

Wrap your app with Privy's provider. The key settings are:

```tsx theme={null}
import { PrivyProvider } from "@privy-io/react-auth";

function App({ children }) {
  return (
    <PrivyProvider
      appId={process.env.NEXT_PUBLIC_PRIVY_APP_ID}
      config={{
        // Allow email login
        loginMethods: ["email"],
        
        embeddedWallets: {
          // Auto-create wallet on first login
          createOnLogin: true,
          // Don't prompt for every signature (better UX)
          noPromptOnSignature: true,
        },
      }}
    >
      {children}
    </PrivyProvider>
  );
}
```

## Step 3: Access the Embedded Wallet

After a user logs in, get their wallet from Privy:

```tsx theme={null}
import { useWallets, useSignAuthorization } from "@privy-io/react-auth";
import { createWalletClient, custom } from "viem";
import { optimism } from "viem/chains";

function usePrivyWallet() {
  const { wallets } = useWallets();
  const { signAuthorization } = useSignAuthorization();
  
  // The embedded wallet is typically the first one
  const embeddedWallet = wallets?.[0];
  
  return { embeddedWallet, signAuthorization };
}
```

## Step 4: Create a Wallet Client

The wallet client is how you'll sign transactions:

```tsx theme={null}
async function getWalletClient(embeddedWallet) {
  // Switch to your target chain
  await embeddedWallet.switchChain(optimism.id);
  
  // Get the Ethereum provider from Privy
  const provider = await embeddedWallet.getEthereumProvider();
  
  // Create a viem wallet client
  const walletClient = createWalletClient({
    account: embeddedWallet.address,
    chain: optimism,
    transport: custom(provider),
  });
  
  return walletClient;
}
```

## Step 5: Sign EIP-7702 Authorization

This step upgrades the EOA to a smart account:

```tsx theme={null}
// The Nexus smart account implementation address
const NEXUS_IMPLEMENTATION = "0x000000004F43C49e93C970E84001853a70923B03";

// Sign the authorization to upgrade the wallet
const authorization = await signAuthorization({
  contractAddress: NEXUS_IMPLEMENTATION,
  chainId: 0, // 0 = works on any chain
});
```

<Info>
  **What just happened?** The user signed a message that says "I authorize my wallet to behave like this smart contract." Their address stays the same, but now it has smart account capabilities.
</Info>

## Step 6: Create the Smart Account

Now create a Nexus account that can work across multiple chains:

```tsx theme={null}
import { 
  toMultichainNexusAccount, 
  getMEEVersion, 
  MEEVersion 
} from "@biconomy/abstractjs";
import { optimism, base } from "viem/chains";
import { http } from "viem";

const nexusAccount = await toMultichainNexusAccount({
  chainConfigurations: [
    {
      chain: optimism,
      transport: http(),
      version: getMEEVersion(MEEVersion.V2_1_0),
      // Use the original wallet address (EIP-7702 mode)
      accountAddress: embeddedWallet.address,
    },
    {
      chain: base,
      transport: http(),
      version: getMEEVersion(MEEVersion.V2_1_0),
      accountAddress: embeddedWallet.address,
    },
  ],
  signer: walletClient.account,
});
```

## Step 7: Create the MEE Client

The MEE client handles transaction execution:

```tsx theme={null}
import { createMeeClient } from "@biconomy/abstractjs";

const meeClient = await createMeeClient({ 
  account: nexusAccount 
});
```

## Step 8: Execute a Gasless Transaction

Now you can execute transactions where gas is paid in any token:

```tsx theme={null}
import { erc20Abi } from "viem";

const USDC_ADDRESS = "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85"; // USDC on Optimism

const { hash } = await meeClient.execute({
  // Required for EIP-7702 flow
  authorization,
  delegate: true,
  
  // Pay gas fees with USDC instead of ETH
  feeToken: {
    address: USDC_ADDRESS,
    chainId: optimism.id,
  },
  
  // Your transaction instructions
  instructions: [
    {
      chainId: optimism.id,
      calls: [
        {
          to: "0xRecipientAddress",
          value: 0n,
          data: "0x", // or encoded function data
        },
      ],
    },
  ],
});

// Wait for confirmation
const receipt = await meeClient.waitForSupertransactionReceipt({ hash });
console.log("Transaction complete:", receipt.hash);
```

***

## Complete Example

Here's a full React component putting it all together:

```tsx theme={null}
import { useState } from "react";
import { useWallets, useSignAuthorization } from "@privy-io/react-auth";
import { createWalletClient, custom, http, erc20Abi } from "viem";
import { optimism, base } from "viem/chains";
import {
  createMeeClient,
  toMultichainNexusAccount,
  getMEEVersion,
  MEEVersion,
} from "@biconomy/abstractjs";

const NEXUS_IMPLEMENTATION = "0x000000004F43C49e93C970E84001853a70923B03";
const USDC_OPTIMISM = "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85";

export function GaslessTransfer() {
  const { wallets } = useWallets();
  const { signAuthorization } = useSignAuthorization();
  const [status, setStatus] = useState("");

  async function sendGaslessTransaction() {
    try {
      setStatus("Setting up...");
      
      const embeddedWallet = wallets?.[0];
      if (!embeddedWallet) throw new Error("Please log in first");

      // Create wallet client
      await embeddedWallet.switchChain(optimism.id);
      const provider = await embeddedWallet.getEthereumProvider();
      const walletClient = createWalletClient({
        account: embeddedWallet.address,
        chain: optimism,
        transport: custom(provider),
      });

      setStatus("Signing authorization...");
      
      // Sign EIP-7702 authorization
      const authorization = await signAuthorization({
        contractAddress: NEXUS_IMPLEMENTATION,
        chainId: 0,
      });

      setStatus("Creating smart account...");
      
      // Create multichain account
      const nexusAccount = await toMultichainNexusAccount({
        chainConfigurations: [
          {
            chain: optimism,
            transport: http(),
            version: getMEEVersion(MEEVersion.V2_1_0),
            accountAddress: embeddedWallet.address,
          },
        ],
        signer: walletClient.account,
      });

      // Create MEE client
      const meeClient = await createMeeClient({ account: nexusAccount });

      setStatus("Executing transaction...");
      
      // Execute gasless transaction
      const { hash } = await meeClient.execute({
        authorization,
        delegate: true,
        feeToken: {
          address: USDC_OPTIMISM,
          chainId: optimism.id,
        },
        instructions: [
          {
            chainId: optimism.id,
            calls: [
              {
                to: "0x0000000000000000000000000000000000000000",
                value: 0n,
              },
            ],
          },
        ],
      });

      const receipt = await meeClient.waitForSupertransactionReceipt({ hash });
      setStatus(`Success! Hash: ${receipt.hash}`);
      
    } catch (error) {
      setStatus(`Error: ${error.message}`);
    }
  }

  return (
    <div>
      <button onClick={sendGaslessTransaction}>
        Send Gasless Transaction
      </button>
      <p>{status}</p>
    </div>
  );
}
```

***

## Key Takeaways

1. **Privy creates the wallet** — Users log in with email, Privy creates an embedded wallet
2. **EIP-7702 adds smart features** — The wallet gets upgraded without changing address
3. **MEE handles gas** — Transactions are executed with any ERC-20 token for gas
4. **Cross-chain ready** — Add more chains to `chainConfigurations` for multi-chain ops

## Next Steps

* [Pay gas with different tokens](/overview/abstractjs/gas-tokens)
* [Execute cross-chain transactions](/overview/abstractjs/cross-chain)
* [Sponsor gas for your users](/overview/abstractjs/sponsor-gas)
* [Use Supertransaction API instead](/wallet-integrations/privy/api)
