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.
Available without advertisement until external audit closes. The migration
primitive shipped with SDK v14.5.0 (PRs #282 + #285 + #286); mainnet smoke
passed with a real on-chain receipt — see
scripts/receipts/cycle-2/.
What this is
CHIPI v29 wallets (the previous default) cannot use SHHH features — no recovery, no threshold, no pluggable signers, no add-device. Migration is a one-timeupgrade call that replaces the wallet’s class hash from CHIPI v29 to SHHH V8.4 without changing the wallet’s address. After migration:
- All on-chain history points at the same address
- USDC balance, NFT ownership, session-keys reference the same address
- External integrators (gift recipients, x402 sellers, paymaster lanes) don’t need to update anything
- Recovery, threshold, multi-device, and signer-kind flexibility all become available
When to migrate
You’d migrate when:- A user asks to add recovery to an existing wallet (only path: migrate first, then add a guardian)
- A user wants to import a hardware passkey as the wallet’s primary owner (only path: migrate first, then
propose_add_ownerwithWEBAUTHN_P256) - You want to defrag your tenancy onto one wallet class to simplify ops + paymaster reservations
- You’re shipping the dashboard “Migrate to SHHH” button to your users
- The wallet is undeployed (counterfactual) — there’s nothing to upgrade; future deploys go straight to SHHH
- The wallet is v28 or v33 (not v29) — those legacy versions need a separate path; see chipi_back_migration_inventory
- The user is happy with the legacy wallet and doesn’t need recovery / threshold / pluggable signers
What gets migrated
| Component | Before (CHIPI v29) | After (SHHH V8.4) |
|---|---|---|
| Wallet address | 0x… | Same 0x… (no change) |
| Account class hash | 0x053f4f87…f459f2a | 0x075dfb39…fa58a |
| Owner set | One STARK key | [{ kind: "STARK", pubkey: <same STARK key>, role: "OWNER", weight: 1 }] |
| Session keys (SNIP-9 / SNIP-163) | Registered | Preserved — V8.4 embeds the same SNIP-163 component |
Account_public_key storage slot | Populated | Read by bootstrap; cleared after |
| Wallet’s STARK private key | Encrypted client-side | Same key, same encryption — Chipi never sees the cleartext |
| On-chain balances + receipts | Intact | Intact (same address) |
The migration call
- The SDK calls
chipi-back’sPOST /chipi-wallets/prepare-migrate-to-shhh, which returns the SNIP-12 typed data for the[upgrade(V8.4), bootstrap_from_sessions]multicall. - The hook unwraps the STARK private key client-side using
encryptKey(cleartext never crosses the wire). - The hook signs the typed data locally with the STARK key, then calls
POST /chipi-wallets/execute-migrate-to-shhhwith the signature. chipi-backrelays the signed multicall through the paymaster. The on-chain wallet runsupgrade(class hash flip) +bootstrap_from_sessions(owner set rebuild) atomically.- If chipi-back’s DB patch fails after the on-chain success, the execute endpoint still returns 200 with
partial: trueso the dashboard can show “wallet upgraded; backend will catch up”. The reconciler cron does the catch-up.
Two terminal outcomes
ALREADY_MIGRATED fires when the user already migrated (e.g., raced with another tab, or the wallet was migrated via the dashboard before the SDK call).
What can go wrong
Errors the hook surfaces viaerror:
STRANDED— the wallet’sAccount_public_keyslot is empty (rare; means the wallet was created in a non-standard way). Recovery path is different — out of scope for this PR.UNDEPLOYED— wallet is counterfactual (never landed on chain). No migration needed; the next deploy goes straight to SHHH.DEFERRED_LEGACY— wallet is v28 or v33. These need their own helper before standard migration runs; tracked separately.DECRYPTION_FAILED— the suppliedencryptKeydoesn’t decrypt the wallet’s STARK key. Wrong PIN / wrong passkey.MIGRATION_DISABLED—chipi-back’sCHIPI_MIGRATION_ENABLEDenv var is off (kill switch).
Post-migration UX
After migration:- The wallet is
walletType: "SHHH",signerKind: "STARK". All single-owner SHHH operations work immediately. - To get the headline UX (passkey, recovery, threshold), the user adds those as additional owners via
propose_add_owner(see recovery). - The original STARK key is still the primary owner; you can rotate it out later via
propose_remove_owneronce a passkey owner is established.
What’s NOT migrated
- CHIPI v29 PRF-passkey wallets keep their PRF-wrapping for the STARK key. Migrating that wallet to SHHH doesn’t switch the auth model — the STARK key is still PRF-wrapped. To move the user to a true
WEBAUTHN_P256primary, add a passkey owner viapropose_add_ownerafter migration. - Session keys with custom
valid_untilpreserve their on-chain entries but you should re-check them against your app’s policy after migration; the SDK doesn’t re-validate them.
Related
- Overview — what SHHH gives you in return
- Signer kinds — what owners you can add after migration
- Recovery — the flows you unlock
