Skip to content

How to use a Particle Network signer with permissionless.js

Particle Network is an intent-centric, modular wallet-as-a-service (WaaS). By utilizing MPC-TSS for key management, Particle can streamline onboarding via familiar Web2 methods such as Google, emails, and phone numbers.

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

Setup

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

Integration

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

Create the Particle Network object

After following the Particle Network documentation, you will have access to a ParticleProvider object as shown below that you can use to create a SmartAccountSigner object:

import { ParticleNetwork } from "@particle-network/auth"
import { ParticleProvider } from "@particle-network/provider"
import { providerToSmartAccountSigner } from "permissionless"
 
// Param options here will be specific to your project.  See the Particle docs for more info.
const particle = new ParticleNetwork({
	projectId,
	clientKey,
	appId,
	chainName,
	chainId,
})
const particleProvider = new ParticleProvider(particle.auth)
 
// Convert the particleProvider to a SmartAccountSigner
const smartAccountSigner = await providerToSmartAccountSigner(particleProvider)

Use with permissionless.js

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://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,
	},
})