Biconomy Passkey SDK Integration Guide
This guide demonstrates how to integrate the Biconomy SDK with passkey authentication in a client-side application.
⚠️ Important: This functionality only works in client-side applications (browsers) as it requires access to the WebAuthn API. It cannot be implemented in backend services.
Setup Environment Variables
Create a .env
file with your Biconomy configuration:
NEXT_PUBLIC_BUNDLER_URL=your_bundler_url
NEXT_PUBLIC_PAYMASTER_URL=your_paymaster_url
Step 1: Create Nexus Client
import { createSmartAccountClient, createBicoPaymasterClient } from '@biconomy/sdk'
import { baseSepolia } from 'wagmi/chains'
import { http, useAccount, useWalletClient } from 'wagmi'
const account = useAccount()
const { data: walletClient } = useWalletClient({ account: account.address })
async function initNexusClient() {
if(walletClient) {
const nexusClient = await createSmartAccountClient({
signer: walletClient,
chain: baseSepolia, // or your preferred chain
paymaster: createBicoPaymasterClient({
paymasterUrl: process.env.NEXT_PUBLIC_PAYMASTER_URL || "",
}),
transport: http(),
bundlerTransport: http(process.env.NEXT_PUBLIC_BUNDLER_URL),
});
return nexusClient;
}
throw new Error('Wallet client not found')
}
Step 2: Register a New Passkey
import { toWebAuthnKey, toPasskeyValidator, WebAuthnMode } from '@biconomy/passkey'
import { NexusClient } from '@biconomy/sdk'
async function registerPasskey(nexusClient: NexusClient, passkeyName: string) {
// Create WebAuthn key
// Ideally "passkeyName" would be set by the user in the UI
const webAuthnKey = await toWebAuthnKey({
passkeyName: passkeyName,
mode: WebAuthnMode.Register,
})
// Create passkey validator
const passkeyValidator = await toPasskeyValidator({
account: nexusClient.account,
webAuthnKey,
})
// Store webAuthnKey for future use
const formattedWebAuthnKey = {
pubX: webAuthnKey.pubX.toString(),
pubY: webAuthnKey.pubY.toString(),
authenticatorId: webAuthnKey.authenticatorId,
authenticatorIdHash: webAuthnKey.authenticatorIdHash,
}
localStorage.setItem('webAuthnKey', JSON.stringify(formattedWebAuthnKey));
return passkeyValidator;
}
Step 3: Login with Existing Passkey
import { NexusClient } from '@biconomy/sdk'
import { toWebAuthnKey, WebAuthnMode, toPasskeyValidator } from '@biconomy/passkey'
async function loginPasskey(nexusClient: NexusClient) {
const webAuthnKey = await toWebAuthnKey({
mode: WebAuthnMode.Login,
})
const passkeyValidator = await toPasskeyValidator({
account: nexusClient.account,
webAuthnKey,
})
return passkeyValidator;
}
Step 4: Install Passkey Validator Module
import type { NexusClient, Module } from '@biconomy/sdk'
async function installPasskeyValidator(nexusClient: NexusClient, passkeyValidator: Module) {
const passkeyValidatorAddress = "0xD990393C670dCcE8b4d8F858FB98c9912dBFAa06"
const userOpHash = await nexusClient?.installModule({
module: {
address: passkeyValidatorAddress,
type: "validator",
initData: passkeyValidator?.initData
},
})
// Wait for transaction to be confirmed
await nexusClient?.waitForUserOperationReceipt({ hash: userOpHash });
}
Step 5: Using Passkey for Transactions
import { createSmartAccountClient, createBicoPaymasterClient, type Module, type NexusClient, moduleActivator } from '@biconomy/sdk'
import { baseSepolia } from 'wagmi/chains'
import { http, useAccount, useWalletClient } from 'wagmi'
import type { Address } from 'viem'
const account = useAccount()
const { data: walletClient } = useWalletClient({ account: account.address })
async function sendTransactionWithPasskey(nexusClient: NexusClient, passkeyValidator: Module, recipientAddress: Address) {
// Extend NexusClient with passkey validator
nexusClient.extend(moduleActivator(passkeyValidator));
// Send transaction
const hash = await nexusClient.sendTransaction({
calls: [
{
to: recipientAddress,
value: BigInt(0) // or your desired value
}
],
});
// Wait for confirmation
const receipt = await nexusClient.waitForTransactionReceipt({ hash });
return receipt;
}
Step 6: Uninstall Passkey Validator (Optional)
import { type NexusClient, type Module, createSmartAccountClient, moduleActivator } from '@biconomy/sdk'
async function uninstallPasskeyValidator(nexusClient: NexusClient, passkeyValidator: Module) {
nexusClient.extend(moduleActivator(passkeyValidator));
const userOpHash = await nexusClient?.uninstallModule({
module: {
address: passkeyValidator.address,
type: "validator",
deInitData: "0x"
}
});
await nexusClient?.waitForUserOperationReceipt({ hash: userOpHash });
// Clear stored passkey data
localStorage.removeItem('webAuthnKey');
}