# EIP-7702 Quickstart — Send a user operation from an EOA

This guide showcases a simple demo that uses ERC-4337 and EIP-7702 to send a sponsored user operation from a EOA. We will use SimpleSmartAccount as our smart account implementation of choice, other ERC-7702 compatible smart accounts will work as well.

For a high level overview of EIP-7702, checkout our [EIP-7702 conceptual guide](/guides/eip7702) and for a more technical overview, please refer to the [EIP-7702 proposal](https://eips.ethereum.org/EIPS/eip-7702).

## Installation

Make sure you have `viem^2.28.0` and `permissionless^0.2.24` installed.

:::code-group
```bash [npm]
npm install permissionless viem
```

```bash [yarn]
yarn add permissionless
```

```bash [pnpm]
pnpm install permissionless viem
```

```bash [bun]
bun install permissionless viem
```
:::

### Steps

:::steps
### Setup the smart account

The setup process follows the typical flow of sending a userOperation. The only difference is that when creating the Simple smart account instance, we set the sender address as our EOA's address.

```ts
import { createPublicClient, Hex, http } from "viem";
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";
import {
	to7702KernelSmartAccount,
	to7702SimpleSmartAccount,
} from "permissionless/accounts";
import { sepolia } from "viem/chains";

// This is your EOA's private key
const privateKey = generatePrivateKey();

const eoa7702 = privateKeyToAccount(privateKey);

const client = createPublicClient({
	chain: sepolia,
	transport: http("https://sepolia.drpc.org"),
});

// you can use either simple smart account
const simple7702Account = await to7702SimpleSmartAccount({
	client,
	owner: eoa7702,
});

// or use a kernel smart account
const kernel7702Account = await to7702KernelSmartAccount({
	client,
	owner: eoa7702,
});
```

### Setup paymaster (optional)

The paymaster client will be responsible for interacting with Pimlico's verifying paymaster endpoint and requesting sponsorship. Make sure to replace YOUR\_PIMLICO\_API\_KEY in the code below with your actual Pimlico API key.

```ts
import { createPimlicoClient } from "permissionless/clients/pimlico";

const pimlicoAPIKey = "<YOUR_PIMLICO_API_KEY>";

const pimlicoClient = createPimlicoClient({
	chain: sepolia,
	transport: http(
		`https://api.pimlico.io/v2/11155111/rpc?apikey=${pimlicoAPIKey}`,
	),
});
```

### Create Smart Account Client

A Smart Account Client is an almost drop-in replacement for a standard viem walletClient but for managing smart accounts instead of EOA accounts. In addition, a Smart Account Client also contains, depending on the underlying smart account implementation used, a few extra actions that are specific to smart accounts.

To create a Smart Account Client, use the createSmartAccountClient function.

```ts

import { createSmartAccountClient } from "permissionless";
import { zeroAddress } from "viem";

const smartAccountClient = createSmartAccountClient({
	client,
	chain: sepolia,
	account: simple7702Account, // or kernel7702Account
	paymaster: pimlicoClient,
	bundlerTransport: http(
		`https://api.pimlico.io/v2/11155111/rpc?apikey=${pimlicoAPIKey}`,
	),
	userOperation: {
		estimateFeesPerGas: async () => {
			return (await pimlicoClient.getUserOperationGasPrice()).fast;
		},
	},
});
```

### Sending the transaction

Make sure you set the signed authorization for the first time when the EOA does not have the authorization code set.

```ts

const isSmartAccountDeployed = await smartAccountClient.account.isDeployed();

let transactionHash: Hex;

// We only have to add the authorization field if the EOA does not have the authorization code set
if (!isSmartAccountDeployed) {
	transactionHash = await smartAccountClient.sendTransaction({
		to: zeroAddress,
		value: 0n,
		data: "0x",
		authorization: await eoa7702.signAuthorization({
			address: "0xe6Cae83BdE06E4c305530e199D7217f42808555B",
			chainId: sepolia.id,
			nonce: await client.getTransactionCount({
				address: eoa7702.address,
			}),
		}),
	});
} else {
	transactionHash = await smartAccountClient.sendTransaction({
		to: zeroAddress,
		value: 0n,
		data: "0x",
	});
}
```

### Batch multiple transactions

The process is the same as sending a single transaction, the only difference is that we pass an array of calls to the sendTransaction function.

```ts

let transactionHash_2: Hex;

// We only have to add the authorization field if the EOA does not have the authorization code set
if (!isSmartAccountDeployed) {
	transactionHash_2 = await smartAccountClient.sendTransaction({
		calls: [
			{
				to: zeroAddress,
				value: 0n,
				data: "0x",
			},
			{
				to: zeroAddress,
				value: 0n,
				data: "0x",
			},
		],
		authorization: await eoa7702.signAuthorization({
			address: "0xe6Cae83BdE06E4c305530e199D7217f42808555B",
			chainId: sepolia.id,
			nonce: await client.getTransactionCount({
				address: eoa7702.address,
			}),
		}),
	});
} else {
	transactionHash_2 = await smartAccountClient.sendTransaction({
		calls: [
			{
				to: zeroAddress,
				value: 0n,
				data: "0x",
			},
			{
				to: zeroAddress,
				value: 0n,
				data: "0x",
			},
		],
	});
}
```

### Review

Congratulations! You have successfully sent a sponsored userOperation from your EOA, if you review the transaction on the blockchain explorer, you will see that the userOperation's sender address is equal to your EOA's address.
:::
