<VersionWarning version="0.1" />

# How to use a Magic signer with permissionless.js

[Magic](https://magic.link/) is a popular embedded wallet provider that supports social logins. While social logins are great, your users still need to onramp in order to pay for gas, which introduces significant friction.

By combining permissionless.js with Magic, you can use Magic to enable a smooth social login experience, while using permissionless.js accounts as the smart wallets to sponsor gas for users, batch transactions, and more.

## Setup

To use Magic with permissionless.js, first create an application that integrates with Magic.

* Refer to the [Magic documentation site](https://magic.link/docs/home/welcome) for instructions on setting up an application with the Magic SDK.
* For a quick start, Magic provides a CLI to create a starter project, available [here](https://magic.link/docs/home/quickstart/cli#run-make-magic).

## Integration

Integrating permissionless.js with Magic is straightforward after setting up the Magic SDK. Magic provides an Externally Owned Account (EOA) wallet to use as a signer with permissionless.js accounts.

### Create the Magic object

After following the Magic documentation, you will have access to a `MagicBase` object as shown below that you can use to create the `SmartAccountSigner` object:

```typescript
import { OAuthExtension } from "@magic-ext/oauth"
import { Magic as MagicBase } from "magic-sdk"
import { providerToSmartAccountSigner } from "permissionless"

const magic = new MagicBase(process.env.MAGIC_API_KEY as string, {
	network: {
		rpcUrl: "https://sepolia.rpc.thirdweb.com",
		chainId: 11155111,
	},
	extensions: [new OAuthExtension()],
})

// Get the Provider from Magic and convert it to a SmartAccountSigner
const magicProvider = await magic.wallet.getProvider()
const smartAccountSigner = await providerToSmartAccountSigner(magicProvider)
```

### Use with permissionless.js

:::code-group
```ts [SimpleAccount]
import { signerToSimpleSmartAccount } from "permissionless/accounts"
import {
	createPimlicoBundlerClient,
	createPimlicoPaymasterClient,
} from "permissionless/clients/pimlico"
import { createPublicClient, http } from "viem"
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"
import { sepolia } from "viem/chains"

const pimlicoRpcUrl = `https://api.pimlico.io/v2/sepolia/rpc?apikey=<api-key>`

const pimlicoPaymaster = createPimlicoPaymasterClient({
	transport: http(pimlicoRpcUrl),
	entryPoint: ENTRYPOINT_ADDRESS_V06,
})

const bundlerClient = createPimlicoBundlerClient({
	transport: http(pimlicoRpcUrl),
	entryPoint: ENTRYPOINT_ADDRESS_V06,
})

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

const smartAccount = await signerToSimpleSmartAccount(publicClient, {
	signer: smartAccountSigner,
	entryPoint: ENTRYPOINT_ADDRESS_V06,
})

const smartAccountClient = createSmartAccountClient({
	account: smartAccount,
	entryPoint: ENTRYPOINT_ADDRESS_V06,
	chain: sepolia, // or whatever chain you are using
	bundlerTransport: http(pimlicoRpcUrl, {
		timeout: 30_000, // optional
	}),
	middleware: {
		gasPrice: async () => (await bundlerClient.getUserOperationGasPrice()).fast,
		sponsorUserOperation: pimlicoPaymaster.sponsorUserOperation,
	},
})
```

```ts [Safe Account]
import { signerToSafeSmartAccount } from "permissionless/accounts"
import {
	createPimlicoBundlerClient,
	createPimlicoPaymasterClient,
} from "permissionless/clients/pimlico"
import { createPublicClient, http } from "viem"
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"
import { sepolia } from "viem/chains"

const pimlicoRpcUrl = `https://api.pimlico.io/v2/sepolia/rpc?apikey=<api-key>`

const pimlicoPaymaster = createPimlicoPaymasterClient({
	transport: http(pimlicoRpcUrl),
	entryPoint: ENTRYPOINT_ADDRESS_V06,
})

const bundlerClient = createPimlicoBundlerClient({
	transport: http(pimlicoRpcUrl),
	entryPoint: ENTRYPOINT_ADDRESS_V06,
})

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

const smartAccount = await signerToSafeSmartAccount(publicClient, {
	signer: smartAccountSigner,
	safeVersion: "1.4.1",
	entryPoint: ENTRYPOINT_ADDRESS_V06,
})

const smartAccountClient = createSmartAccountClient({
	account: smartAccount,
	entryPoint: ENTRYPOINT_ADDRESS_V06,
	chain: sepolia, // or whatever chain you are using
	bundlerTransport: http(pimlicoRpcUrl, {
		timeout: 30_000, // optional
	}),
	middleware: {
		gasPrice: async () => (await bundlerClient.getUserOperationGasPrice()).fast,
		sponsorUserOperation: pimlicoPaymaster.sponsorUserOperation,
	},
})
```

```ts [Kernel Account]
import { signerToEcdsaKernelSmartAccount } from "permissionless/accounts"
import {
	createPimlicoBundlerClient,
	createPimlicoPaymasterClient,
} from "permissionless/clients/pimlico"
import { createPublicClient, http } from "viem"
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"
import { sepolia } from "viem/chains"

const pimlicoRpcUrl = `https://api.pimlico.io/v2/sepolia/rpc?apikey=<api-key>`

const pimlicoPaymaster = createPimlicoPaymasterClient({
	transport: http(pimlicoRpcUrl),
	entryPoint: ENTRYPOINT_ADDRESS_V06,
})

const bundlerClient = createPimlicoBundlerClient({
	transport: http(pimlicoRpcUrl),
	entryPoint: ENTRYPOINT_ADDRESS_V06,
})

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

const smartAccount = await signerToEcdsaKernelSmartAccount(publicClient, {
	signer: smartAccountSigner,
	entryPoint: ENTRYPOINT_ADDRESS_V06,
})

const smartAccountClient = createSmartAccountClient({
	account: smartAccount,
	entryPoint: ENTRYPOINT_ADDRESS_V06,
	chain: sepolia, // or whatever chain you are using
	bundlerTransport: http(pimlicoRpcUrl, {
		timeout: 30_000, // optional
	}),
	middleware: {
		gasPrice: async () => (await bundlerClient.getUserOperationGasPrice()).fast,
		sponsorUserOperation: pimlicoPaymaster.sponsorUserOperation,
	},
})
```

```ts [Biconomy Account]
import { signerToBiconomySmartAccount } from "permissionless/accounts"
import {
	createPimlicoBundlerClient,
	createPimlicoPaymasterClient,
} from "permissionless/clients/pimlico"
import { createPublicClient, http } from "viem"
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"
import { sepolia } from "viem/chains"

const pimlicoRpcUrl = `https://api.pimlico.io/v2/sepolia/rpc?apikey=<api-key>`

const pimlicoPaymaster = createPimlicoPaymasterClient({
	transport: http(pimlicoRpcUrl),
	entryPoint: ENTRYPOINT_ADDRESS_V06,
})

const bundlerClient = createPimlicoBundlerClient({
	transport: http(pimlicoRpcUrl),
	entryPoint: ENTRYPOINT_ADDRESS_V06,
})

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

const smartAccount = await signerToBiconomySmartAccount(publicClient, {
	signer: smartAccountSigner,
	entryPoint: ENTRYPOINT_ADDRESS_V06,
})

const smartAccountClient = createSmartAccountClient({
	account: smartAccount,
	entryPoint: ENTRYPOINT_ADDRESS_V06,
	chain: sepolia, // or whatever chain you are using
	bundlerTransport: http(pimlicoRpcUrl, {
		timeout: 30_000, // optional
	}),
	middleware: {
		gasPrice: async () => (await bundlerClient.getUserOperationGasPrice()).fast,
		sponsorUserOperation: pimlicoPaymaster.sponsorUserOperation,
	},
})
```

```ts [TrustWallet Account]
import { signerToTrustSmartAccount } from "permissionless/accounts"
import {
	createPimlicoBundlerClient,
	createPimlicoPaymasterClient,
} from "permissionless/clients/pimlico"
import { createPublicClient, http } from "viem"
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"
import { sepolia } from "viem/chains"

const pimlicoRpcUrl = `https://api.pimlico.io/v2/sepolia/rpc?apikey=<api-key>`

const pimlicoPaymaster = createPimlicoPaymasterClient({
	transport: http(pimlicoRpcUrl),
	entryPoint: ENTRYPOINT_ADDRESS_V06,
})

const bundlerClient = createPimlicoBundlerClient({
	transport: http(pimlicoRpcUrl),
	entryPoint: ENTRYPOINT_ADDRESS_V06,
})

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

const smartAccount = await signerToTrustSmartAccount(publicClient, {
	signer: smartAccountSigner,
	entryPoint: ENTRYPOINT_ADDRESS_V06,
})

const smartAccountClient = createSmartAccountClient({
	account: smartAccount,
	entryPoint: ENTRYPOINT_ADDRESS_V06,
	chain: sepolia, // or whatever chain you are using
	bundlerTransport: http(pimlicoRpcUrl, {
		timeout: 30_000, // optional
	}),
	middleware: {
		gasPrice: async () => (await bundlerClient.getUserOperationGasPrice()).fast,
		sponsorUserOperation: pimlicoPaymaster.sponsorUserOperation,
	},
})
```
:::
