> ## Documentation Index
> Fetch the complete documentation index at: https://docs.chipipay.com/llms.txt
> Use this file to discover all available pages before exploring further.

# useMigrateWalletToPasskey

> Migrates an existing PIN-encrypted wallet to passkey (biometric) authentication.

## Usage

```typescript theme={null}
const {
  migrateWalletToPasskey,
  migrateWalletToPasskeyAsync,
  data,
  isLoading,
  isError,
  isSuccess,
  error,
  reset,
} = useMigrateWalletToPasskey();
```

### Parameters

The mutation accepts an object with:

| Parameter        | Type         | Required | Description                                                     |
| ---------------- | ------------ | -------- | --------------------------------------------------------------- |
| `wallet`         | `WalletData` | Yes      | The current wallet object (`publicKey` + `encryptedPrivateKey`) |
| `oldEncryptKey`  | `string`     | Yes      | The user's current PIN used to decrypt the wallet               |
| `externalUserId` | `string`     | Yes      | Your app's user ID — used as the passkey username               |
| `bearerToken`    | `string`     | Yes      | Auth token from your provider                                   |

### Return Value

| Property                      | Type                                               | Description                 |
| ----------------------------- | -------------------------------------------------- | --------------------------- |
| `migrateWalletToPasskey`      | `(input) => void`                                  | Fire-and-forget migration   |
| `migrateWalletToPasskeyAsync` | `(input) => Promise<MigrateWalletToPasskeyResult>` | Promise-based migration     |
| `data`                        | `MigrateWalletToPasskeyResult \| undefined`        | Migration result            |
| `isLoading`                   | `boolean`                                          | True while migrating        |
| `isError`                     | `boolean`                                          | True if migration failed    |
| `isSuccess`                   | `boolean`                                          | True if migration succeeded |
| `error`                       | `Error \| null`                                    | Error details               |
| `reset`                       | `() => void`                                       | Reset mutation state        |

### `MigrateWalletToPasskeyResult`

| Property       | Type         | Description                                            |
| -------------- | ------------ | ------------------------------------------------------ |
| `success`      | `boolean`    | Whether migration succeeded                            |
| `wallet`       | `WalletData` | Updated wallet with new passkey-encrypted private key  |
| `credentialId` | `string`     | The passkey credential ID (store this for future auth) |

## How It Works

1. A new passkey is created in the browser/device (triggers biometric prompt)
2. The wallet's private key is decrypted using `oldEncryptKey` (the PIN)
3. The private key is re-encrypted using the passkey-derived key
4. The updated wallet is returned — **persist the new wallet object and `credentialId`**

<Warning>
  After migration, the old PIN (`oldEncryptKey`) will no longer work. Store the
  updated wallet object and `credentialId` securely.
</Warning>

## Example Implementation

```typescript theme={null}
import { useMigrateWalletToPasskey } from "@chipi-stack/chipi-react";
import { useAuth } from "@clerk/nextjs";
import { useState } from "react";

export function MigrateToPasskey({ currentWallet, userId }: {
  currentWallet: WalletData;
  userId: string;
}) {
  const { getToken } = useAuth();
  const [currentPin, setCurrentPin] = useState("");
  const { migrateWalletToPasskeyAsync, isLoading, error } = useMigrateWalletToPasskey();

  const handleMigrate = async () => {
    const bearerToken = await getToken();
    if (!bearerToken) return;

    try {
      const result = await migrateWalletToPasskeyAsync({
        wallet: currentWallet,
        oldEncryptKey: currentPin,
        externalUserId: userId,
        bearerToken,
      });

      // Persist the updated wallet and credentialId
      localStorage.setItem("wallet", JSON.stringify(result.wallet));
      localStorage.setItem("passkeyCredentialId", result.credentialId);

      alert("Successfully migrated to passkey!");
    } catch (err) {
      console.error("Migration failed:", err);
    }
  };

  return (
    <div>
      <input
        type="password"
        placeholder="Current PIN"
        value={currentPin}
        onChange={(e) => setCurrentPin(e.target.value)}
      />
      <button onClick={handleMigrate} disabled={isLoading}>
        {isLoading ? "Migrating..." : "Migrate to Passkey"}
      </button>
      {error && <p>Error: {error.message}</p>}
    </div>
  );
}
```

## Related

* [Use Passkeys Guide](/sdk/react/use-passkeys) — Full passkey setup walkthrough
* **useCreateWallet** — Create a wallet with passkey from the start (set `usePasskey: true`)
