How to use a Capsule signer with permissionless.js
Capsule offers a signing solution enabling the creation of secure, embedded MPC wallets accessible via email or social login. These wallets, compatible across different applications, offer portability, recoverability, and programmability, eliminating the need for users to establish separate signers or contract accounts for each application.
Setup
To use Capsule with permissionless.js, first create an application that integrates with Capsule.
- Refer to the Capsule documentation site for instructions on setting up an application with the Capsule.
- For a quick start, Capsule provides an example hub, available here.
Integration
Integrating permissionless.js with Capsule is straightforward after setting up the project. Capsule provides an Externally Owned Account (EOA) wallet to use as a signer with permissionless.js accounts.
Create the Capsule signer
After following the Capsule documentation, you will have access to a CapsuleWeb3Provider
object that you can use to create a SmartAccountSigner
object:
import Capsule from "@usecapsule/web-sdk"
import { createCapsuleViemClient } from '@usecapsule/viem-v2-integration';
import { walletClientToSmartAccountSigner } from "permissionless"
import { http } from "viem"
import { sepolia } from "viem/chains"
// Param options here will be specific to your project. See the Capsule docs for more info.
const capsule = new Capsule(env, apiKey)
// Convert a Capsule viem client to a SmartAccountSigner
// Follow the Capsule docs for more instructions on creating the Viem client https://docs.usecapsule.com/integration-guide/signing-transactions
const viemClient = createCapsuleViemClient(capsule, {
chain: sepolia,
transport: http("https://rpc.ankr.com/eth_sepolia"),
})
const smartAccountSigner = walletClientToSmartAccountSigner(viemClient)
Use with permissionless.js
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://rpc.ankr.com/eth_sepolia"),
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,
},
})