> ## 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.

# Para + AbstractJS SDK

> Build server-side flows with Para session-based authentication and Biconomy using the AbstractJS SDK

Para provides session-based authentication that's perfect for server-side transaction execution. This guide shows you how to combine Para with Biconomy's MEE using the AbstractJS SDK for gasless, cross-chain transactions.

## What We're Building

By the end of this tutorial, you'll have a backend service that can:

1. Use Para sessions for secure authentication
2. Execute batched transactions without holding ETH
3. Handle operations across multiple chains

<Info>
  **How it works**: Users authenticate with Para on the frontend and receive a session token. Your backend uses this token to sign transactions on the user's behalf, routing them through Biconomy's MEE for gas abstraction.
</Info>

***

## Step 1: Install Dependencies

```bash theme={null}
npm install @biconomy/abstractjs @getpara/server-sdk @getpara/viem-v2-integration viem express
```

**What these packages do:**

* `@getpara/server-sdk` — Para's server SDK for session management
* `@getpara/viem-v2-integration` — Adapter to use Para with viem
* `@biconomy/abstractjs` — Biconomy's SDK for smart accounts and MEE
* `viem` — Ethereum library for building transactions

## Step 2: Set Up Environment Variables

Create a `.env` file:

```bash theme={null}
# Para credentials
PARA_API_KEY=your_para_api_key
PARA_ENVIRONMENT=BETA

# RPC endpoint
RPC_URL=https://sepolia.arbitrum.io/rpc
```

<Warning>
  Keep your API keys secure. Never commit them to version control.
</Warning>

## Step 3: Create the Request Handler

Set up an Express handler that receives the user's session:

```typescript theme={null}
import type { Request, Response } from "express";
import { Para as ParaServer, Environment } from "@getpara/server-sdk";

export async function handleTransaction(req: Request, res: Response) {
  // Get session from request body
  const session = req.body.session as string;
  
  if (!session) {
    return res.status(400).json({ 
      error: "Missing session token" 
    });
  }

  // Initialize Para with the session
  const para = new ParaServer(
    process.env.PARA_ENVIRONMENT as Environment,
    process.env.PARA_API_KEY
  );
  
  await para.importSession(session);
  
  // Continue with transaction...
}
```

## Step 4: Create Para Account

Create a viem-compatible account from the Para session:

```typescript theme={null}
import { createParaAccount } from "@getpara/viem-v2-integration";
import type { LocalAccount } from "viem";

// Create the Para account adapter
const paraAccount: LocalAccount = createParaAccount(para);
```

<Info>
  **What's happening here?** Para already has the user's key material from their session. The adapter lets viem use Para for signing operations.
</Info>

## Step 5: Set Up Custom Signing

Para requires custom signing methods for EIP-7702:

```typescript theme={null}
import { customSignMessage, customSignAuthorization } from "./signature-utils";

// Override the default signing methods
paraAccount.signMessage = async ({ message }) => 
  customSignMessage(para, message);

paraAccount.signAuthorization = async (authorization) => 
  customSignAuthorization(para, authorization);
```

Here's a basic implementation of the signing utilities:

```typescript theme={null}
// signature-utils.ts
import { Para as ParaServer } from "@getpara/server-sdk";

export async function customSignMessage(
  para: ParaServer, 
  message: string | Uint8Array
): Promise<`0x${string}`> {
  const messageHex = typeof message === "string" 
    ? message 
    : Buffer.from(message).toString("hex");
    
  return await para.signMessage(messageHex);
}

export async function customSignAuthorization(
  para: ParaServer,
  authorization: any
): Promise<any> {
  return await para.signAuthorization(authorization);
}
```

## Step 6: Create Wallet Client

Create a wallet client for signing transactions:

```typescript theme={null}
import { createWalletClient, http } from "viem";
import { arbitrumSepolia } from "viem/chains";

const walletClient = createWalletClient({
  account: paraAccount,
  chain: arbitrumSepolia,
  transport: http(process.env.RPC_URL),
});
```

## Step 7: Sign EIP-7702 Authorization

Sign the authorization that upgrades the EOA to a smart account:

```typescript theme={null}
// Biconomy Nexus smart account implementation
const NEXUS_IMPLEMENTATION = "0x000000004F43C49e93C970E84001853a70923B03";

const authorization = await walletClient.signAuthorization({
  contractAddress: NEXUS_IMPLEMENTATION,
  chainId: 0, // 0 = works on any chain
});
```

<Info>
  **What is chainId: 0?** Setting chainId to 0 means the authorization works on any chain. This is useful for cross-chain applications where you want one authorization to enable transactions everywhere.
</Info>

## Step 8: Create the Smart Account

Create a Nexus account using the EOA address for EIP-7702 mode:

```typescript theme={null}
import { 
  toMultichainNexusAccount, 
  getMEEVersion, 
  MEEVersion 
} from "@biconomy/abstractjs";

const nexusAccount = await toMultichainNexusAccount({
  chainConfigurations: [
    {
      chain: arbitrumSepolia,
      transport: http(process.env.RPC_URL),
      version: getMEEVersion(MEEVersion.V2_1_0),
      // Use the EOA address for EIP-7702 mode
      accountAddress: paraAccount.address,
    },
  ],
  signer: walletClient,
});
```

<Warning>
  **Important**: Setting `accountAddress` to the EOA address is required for EIP-7702 mode. Without this, the SDK will try to compute a different smart account address.
</Warning>

## Step 9: Create MEE Client and Execute

Create the MEE client and execute your transaction:

```typescript theme={null}
import { createMeeClient } from "@biconomy/abstractjs";
import { encodeFunctionData } from "viem";

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

// Build your transaction calls
const calls = [
  {
    to: "0xYourContractAddress" as `0x${string}`,
    value: 0n,
    data: encodeFunctionData({
      abi: yourContractAbi,
      functionName: "yourFunction",
      args: [arg1, arg2],
    }),
  },
];

// Execute with EIP-7702 delegation
const { hash } = await meeClient.execute({
  authorization,
  delegate: true,
  
  // Optional: pay gas with ERC-20
  // feeToken: {
  //   address: "0xUSDC...",
  //   chainId: arbitrumSepolia.id,
  // },
  
  instructions: [
    {
      chainId: arbitrumSepolia.id,
      calls,
    },
  ],
});
```

## Step 10: Wait for Confirmation

```typescript theme={null}
const receipt = await meeClient.waitForSupertransactionReceipt({
  hash,
  timeout: 30000, // 30 seconds
});

res.status(200).json({
  success: true,
  transactionHash: hash,
  receipt: {
    hash: receipt.hash,
    status: receipt.status,
  },
});
```

***

## Complete Example

Here's a full Express.js handler:

```typescript theme={null}
import type { Request, Response } from "express";
import { 
  createMeeClient, 
  toMultichainNexusAccount,
  getMEEVersion,
  MEEVersion
} from "@biconomy/abstractjs";
import { Para as ParaServer, Environment } from "@getpara/server-sdk";
import { createParaAccount } from "@getpara/viem-v2-integration";
import { createWalletClient, http, encodeFunctionData } from "viem";
import { arbitrumSepolia } from "viem/chains";

const NEXUS_IMPLEMENTATION = "0x000000004F43C49e93C970E84001853a70923B03";

export async function executeTransaction(
  req: Request, 
  res: Response
): Promise<void> {
  try {
    const { session, calls } = req.body;

    if (!session) {
      res.status(400).json({ error: "Missing session" });
      return;
    }

    // 1. Initialize Para
    const para = new ParaServer(
      Environment.BETA,
      process.env.PARA_API_KEY!
    );
    await para.importSession(session);

    // 2. Create Para account
    const paraAccount = createParaAccount(para);

    // 3. Create wallet client
    const walletClient = createWalletClient({
      account: paraAccount,
      chain: arbitrumSepolia,
      transport: http(process.env.RPC_URL),
    });

    // 4. Sign authorization
    const authorization = await walletClient.signAuthorization({
      contractAddress: NEXUS_IMPLEMENTATION,
      chainId: 0,
    });

    // 5. Create Nexus account
    const nexusAccount = await toMultichainNexusAccount({
      chainConfigurations: [
        {
          chain: arbitrumSepolia,
          transport: http(process.env.RPC_URL),
          version: getMEEVersion(MEEVersion.V2_1_0),
          accountAddress: paraAccount.address,
        },
      ],
      signer: walletClient,
    });

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

    // 7. Execute transaction
    const { hash } = await meeClient.execute({
      authorization,
      delegate: true,
      instructions: [
        {
          chainId: arbitrumSepolia.id,
          calls,
        },
      ],
    });

    // 8. Wait for confirmation
    const receipt = await meeClient.waitForSupertransactionReceipt({
      hash,
      timeout: 30000,
    });

    res.status(200).json({
      success: true,
      address: paraAccount.address,
      transactionHash: hash,
      receipt: {
        hash: receipt.hash,
        status: receipt.status,
      },
    });

  } catch (error) {
    res.status(500).json({
      error: error instanceof Error ? error.message : "Unknown error",
    });
  }
}
```

***

## Gas Abstraction Options

### Pay with ERC-20 Token

```typescript theme={null}
const { hash } = await meeClient.execute({
  authorization,
  delegate: true,
  feeToken: {
    address: "0xUSDC_ADDRESS",
    chainId: arbitrumSepolia.id,
  },
  instructions: [/* ... */],
});
```

### Sponsor Gas Entirely

Configure sponsorship in your Biconomy dashboard to cover all gas costs for users.

***

## Cross-Chain Execution

Add multiple chains and execute across them:

```typescript theme={null}
import { optimism, base } from "viem/chains";

const nexusAccount = await toMultichainNexusAccount({
  chainConfigurations: [
    {
      chain: arbitrumSepolia,
      transport: http(),
      version: getMEEVersion(MEEVersion.V2_1_0),
      accountAddress: paraAccount.address,
    },
    {
      chain: optimism,
      transport: http(),
      version: getMEEVersion(MEEVersion.V2_1_0),
      accountAddress: paraAccount.address,
    },
  ],
  signer: walletClient,
});

const { hash } = await meeClient.execute({
  authorization,
  delegate: true,
  instructions: [
    { chainId: arbitrumSepolia.id, calls: [/* Arbitrum calls */] },
    { chainId: optimism.id, calls: [/* Optimism calls */] },
  ],
});
```

***

## Key Takeaways

1. **Para provides sessions** — Users authenticate once, then your backend can sign on their behalf
2. **EIP-7702 adds smart features** — The user's address gains smart account capabilities
3. **MEE handles execution** — Gas abstraction and cross-chain routing are automatic
4. **Server-side control** — Your backend manages transaction flow securely

## 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/para/api)
