# How to use an ERC-7579 compatible smart account with permissionless.js

[ERC-7579](https://eips.ethereum.org/EIPS/eip-7579) defines a standard for modular smart account interfaces. It also defines behavior for interoperability with minimal restrictions for accounts and modules.

Currently Safe and Kernel are the only smart accounts that implements ERC-7579.

For this guide, we will use the Safe smart accounts as an example. If you would like to find out more about the Safe smart account, you can check out the [Safe-specific guide](/references/permissionless/how-to/accounts/use-safe-account).

This guide will show you how to create and use a ERC-7579 compatible smart account with permissionless.js.

## Steps

::::steps
### Import the required packages

```ts
import { owner } from "../owner"
import { createSmartAccountClient } from "permissionless"
import { sepolia } from "viem/chains"
import { encodePacked, http } from "viem"
import { erc7579Actions } from "permissionless/actions/erc7579"
import { createPublicClient } from "viem"
import { createPimlicoClient } from "permissionless/clients/pimlico"
import { entryPoint07Address } from "viem/account-abstraction"
import { toSafeSmartAccount } from "permissionless/accounts"
```

### Create the clients

First we must create the public, (optionally) pimlico paymaster clients that will be used to interact with the SafeAccount.

```ts
const apiKey = "YOUR_PIMLICO_API_KEY"
const bundlerUrl = `https://api.pimlico.io/v2/sepolia/rpc?apikey=${apiKey}`

const publicClient = createPublicClient({
	transport: http("https://sepolia.rpc.thirdweb.com"),
})

const pimlicoClient = createPimlicoClient({
	transport: http(bundlerUrl),
	entryPoint: {
		address: entryPoint07Address,
		version: "0.7",
	},
})
```

### Create the SafeAccount

:::info
For a full list of options for creating a SafeAccount, take a look at the reference documentation page for [`toSafeSmartAccount`](/references/permissionless/reference/accounts/toSafeSmartAccount).
:::

You can also pass an `address` to use an already created SafeAccount.

```ts
const safeAccount = await toSafeSmartAccount({
	client: publicClient,
	owners: [owner],
	version: "1.4.1",
	entryPoint: {
		address: entryPoint07Address,
		version: "0.7",
	},
	safe4337ModuleAddress: "0x7579EE8307284F293B1927136486880611F20002",
	erc7579LaunchpadAddress: "0x7579011aB74c46090561ea277Ba79D510c6C00ff",
	attesters: ["0x000000333034E9f539ce08819E12c1b8Cb29084d"], // This address belongs to Rhinestone. By designating them as attesters, you authorize that only modules explicitly approved by Rhinestone can be installed on your safe.
	attestersThreshold: 1,
})
```

:::warning
The Safe account requires a new `safe4337ModuleAddress` & `erc7579LaunchpadAddress` for it to be 7579 compatible.
:::

:::warning
The address `0x000000333034E9f539ce08819E12c1b8Cb29084d` belongs to Rhinestone. By designating them as attesters, you authorize that only modules explicitly approved by Rhinestone can be installed on your safe.
:::

### Create the smart account client and extend it with the ERC7579 actions

The smart account client is a permissionless.js client that is meant to serve as an almost drop-in replacement for viem's [walletClient](https://viem.sh/docs/clients/wallet).

```ts
const smartAccountClient = createSmartAccountClient({
	account: safeAccount,
	chain: sepolia,
	bundlerTransport: http(bundlerUrl),
	paymaster: pimlicoClient,
	userOperation: {
		estimateFeesPerGas: async () => {
			return (await pimlicoClient.getUserOperationGasPrice()).fast
		},
	},
}).extend(erc7579Actions())
```

### Interact with the 7579 actions

You can install a module on the Safe account using the `installModule` action.

```ts
const ownableExecutorModule = "0x4Fd8d57b94966982B62e9588C27B4171B55E8354"
const moduleData = encodePacked(["address"], ["0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"])
const userOpHash = await smartAccountClient.installModule({
	type: "executor",
	address: ownableExecutorModule,
	context: moduleData,
})

const receipt = await pimlicoClient.waitForUserOperationReceipt({ hash: userOpHash })
```

:::warning
InstallModule returns user operation hash, not transaction hash, you must use `waitForUserOperationReceipt` to wait for the user operation to be included on-chain.
:::

You can also call all other ERC7579 actions, example `supportsExecutionMode`.

```ts
const isExecutionModeSupported = await smartAccountClient.supportsExecutionMode({
	type: "delegatecall",
	revertOnError: true,
	selector: "0x",
	context: "0x",
})
```
::::
