Migrate PIN to Passkey
Step-by-step guide to migrate a PIN-encrypted wallet to passkey (biometric) authentication.
Overview
PIN-encrypted wallets can be upgraded to passkey (biometric) authentication. After migration, only the passkey works — the old PIN is disabled.
The flow:
- User enters their current PIN (proves ownership)
- Browser registers a new passkey (fingerprint/face)
- Private key is re-encrypted with the passkey-derived key
- Clerk metadata updated with new encrypted key + auth method
If any step fails, the old PIN still works — migration is atomic.
Using the MCP Component
The migrate-to-passkey-dialog handles the full flow:
bashnpx shadcn@latest add dialog input-otp button --yThe component shows a 5-step progress indicator:
- Verify PIN
- Register Passkey
- Authenticate
- Re-encrypt
- Success
Import and use:
tsximport { MigrateToPasskeyDialog } from "@/components/migrate-to-passkey-dialog";
<MigrateToPasskeyDialog
open={showMigrate}
onOpenChange={setShowMigrate}
encryptedPrivateKey={wallet.encryptedPrivateKey}
onSuccess={() => {
toast.success("Migrated to passkey!");
refetchWallet();
}}
/>Using the SDK Hook
For custom UI, use the SDK hook directly:
typescriptimport { useMigrateWalletToPasskey } from "@chipi-stack/chipi-react";
const { migrateWalletToPasskey, isLoading } = useMigrateWalletToPasskey();
await migrateWalletToPasskey({
wallet: walletData,
oldEncryptKey: pin,
externalUserId: userId,
});The hook handles passkey creation, re-encryption, and metadata update.
Edge Cases
- - Wrong PIN: Decryption fails before passkey registration. User can retry.
- - PRF not supported: Migration aborted. User keeps PIN.
- - Biometric cancelled: Migration aborted at registration step. PIN still works.
- - Network failure during metadata update: Rare — Clerk's update is atomic. If it fails, old PIN still works.
- - Multiple devices: After migration, register passkeys on other devices via Passkey Manager.