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. Both flows are
on-chain since 2026-05-26 and have shipped mainnet smokes — see task
#45 (recovery) and
scripts/receipts/.
The problem
Pre-SHHH wallets (CHIPI v29) had no recovery primitive — a lost PIN or a broken passkey meant the wallet’s USDC was unreachable. SHHH V8.4 closes this with two timelocked flows that route through the on-chain account itself; no off-chain custodian, no Chipi-side key extraction.Flow 1 — Add device (user still has wallet access)
Use when the user wants a second device controlling the same wallet (the canonical “switching from laptop to phone” case) or wants to add a guardian after onboarding. Stages:- Propose — the existing owner signs an outside execution containing
propose_add_owner. The on-chain wallet records a pending op tagged withOP_ADD_OWNERand starts a 48-hour timelock. - Wait — the SDK exposes
useGuardianRecovery().isReady(validAfter)andsecondsRemaining(validAfter)to drive a countdown UI. The pending op state is read from chain — the SDK doesn’t poll on your behalf. - Execute — after 48h, ANY OWNER (or anyone if the wallet is configured as such) calls
execute_add_ownerwith the matchingop_id. The wallet re-derives the proposed payload and asserts equality before mutatingowner_set.
Flow 2 — Guardian recovery (user lost their key)
Use when the user can no longer sign with any existing owner. A pre-registered guardian (a second user, a recovery email’s WebAuthn credential, or a paid “Guardian-as-a-Service” provider) initiates recovery on the user’s behalf. Stages:- Initiate — the guardian (NOT the lost owner) signs an outside execution calling
initiate_recovery. The wallet starts a 7-day timelock. - Wait — 7 days. During this window the original owner can
cancel_recoveryif they regain access — this is the safety valve against a malicious guardian. - Finalize — after 7d, anyone can submit
finalize_recovery. The wallet rotatesowner_setto the new owner specified in step 1.
Cancel safety valve
Within either timelock window, any current owner can cancel the pending op. The two flows take different on-chain selectors:- Add-device uses
cancel_pending_op(op_id)(matches any pendingOP_ADD_OWNER/OP_REMOVE_OWNER/OP_ROTATE_OWNER/OP_SET_THRESHOLD). - Guardian recovery uses
cancel_recovery(owner_id)— keyed by which owner is being replaced, not by an op_id, because recovery operates on the owner set directly rather than through the pending-op queue.
<Recover /> shows a Cancel button automatically when you pass an onCancel callback; pick the matching builder for the mode:
Timelock constants
| Op | Timelock | Default expiry | Why |
|---|---|---|---|
OP_ADD_OWNER | 48h | 14d | Time for the owner to notice an unexpected add-device proposal |
OP_REMOVE_OWNER | 24h | 14d | Same audit window but tighter — removal is reversible by adding back |
OP_ROTATE_OWNER | 24h | 14d | |
OP_SET_THRESHOLD | 48h | 14d | Threshold changes are governance-grade |
RECOVERY | 7d | n/a | Longest window in the system — the user must have a meaningful chance to cancel |
useGuardianRecovery().TIMELOCK_SECONDS and .DEFAULT_OP_EXPIRY_SECONDS.
Who acts as guardian?
Three patterns we’ve seen integrators ship:- Second wallet held by the user — a second device or a paper-backup-rooted wallet. Simplest; no third party.
- Email-rooted WebAuthn credential — register a passkey against the user’s email-bound device at onboarding; that credential is the guardian. The user doesn’t need a second wallet day-one.
- Guardian-as-a-Service — a paid third party (could be Chipi, could be a partner) holds a guardian key, with a published policy on when they sign recoveries (e.g., on a 48h email + 2FA confirmation). This is on our roadmap; the productization design is internal-only for now.
role: "GUARDIAN" is set at owner-add time; a guardian cannot initiate or sign transactions like an owner, only call initiate_recovery (and cancel_recovery if they want to withdraw).
What does NOT recover
Recovery rotates the wallet’s owner set. It does NOT:- Reset session keys (those remain valid until their own
valid_until) - Re-create CHIPI v29 STARK key encryption (those wallets don’t have on-chain recovery at all — see migration to move to SHHH first)
- Touch USDC balances or any other on-chain state — recovery is a key rotation, not a state rollback
Related
- Signer kinds — what kinds of owners you can add
- Threshold — recovery composes with N-of-M for stronger governance
- Migration — get a CHIPI v29 wallet onto SHHH first to use these flows
