- Additional devices that each act on their own. Add the user’s laptop passkey alongside their phone passkey. Either device can sign a transfer. This is what most consumer apps want.
- Co-signing where multiple signers must approve. Require two signatures (or three of four, etc.) before any transfer goes through. This is what agent treasuries, shared wallets, and high-value accounts want.
Available without advertisement until external audit closes. The on-chain
logic shipped with SHHH V8.4 and has a mainnet smoke — see
scripts/receipts/.
When to use which
| Your use case | Path |
|---|---|
| User wants their phone + their laptop to both work | Independent owners (each device signs on its own) |
| User wants a backup passkey on a second device “in case” | Independent owners; same as above |
| Agent spends from a treasury you co-control | Co-signing — typically 2-of-2 above a spend threshold, 1-of-2 below |
| Shared org wallet across finance + ops | Co-signing — set the threshold to match your governance |
| High-value personal account where any single device shouldn’t be enough | Co-signing — 2-of-3 between phone + laptop + recovery contact |
- Agent treasuries — an automated agent spends up to $X/day on its own, anything bigger requires a co-sign from the user’s passkey. 2-of-2 above the threshold, 1-of-2 below.
- AI-API service accounts — a service account shares custody with a human operator. Routine API spend doesn’t prompt; settlement transfers do.
- Co-signed org treasuries — Chipi credits balance is N-of-M with key roles distributed across finance + ops + the founder.
Compared to single-owner
Single-owner SHHH wallets sign via one V2_SNIP12 envelope:verified_count ≥ threshold. The set of owners and the threshold N live on-chain.
Owner kinds within a threshold
Anything that works as a single-owner signer kind works as a threshold owner. You can mix:- An EOA on MetaMask (
EIP191_SECP256K1) co-signs with a passkey (WEBAUTHN_P256) - A Phantom / Solana wallet (
ED25519) co-signs with a STARK key held server-side - A JWT_ES256 service account co-signs with a STARK key held server-side
- A guardian (
role: "GUARDIAN") does NOT count toward the threshold for normal transactions — guardians only initiate recovery, never co-sign
Configuring N and M
The wallet is created with N initial owners (M=N at start). Add or remove owners post-creation via the recovery flows in recovery:propose_add_owner→execute_add_ownerafter 48hpropose_remove_owner→execute_remove_ownerafter 24hpropose_set_threshold→execute_set_thresholdafter 48h
cancel_pending_op.
SDK status
| Surface | Status | Notes |
|---|---|---|
Backend builders (buildThresholdEnvelope, buildProposeSetThresholdCall, buildExecuteSetThresholdCall) | Shipped | See @chipi-stack/backend exports |
| Python builders | Shipped | Mirrors TS — see chipi_sdk.shhh.threshold |
| React hook | useGuardianRecovery().buildProposeSetThreshold / .buildExecuteSetThreshold cover the governance side | The N-of-M signature assembly hook (useThresholdSign) ships next |
| Mainnet smoke | Shipped (view-shape + parser) | Real-money smoke deferred until external audit closes |
External wallets that don’t expose a key (MetaMask, Phantom)
MetaMask and Phantom never hand you a private key — the user signs in their wallet and you get a signature back. Each has a*FromSignature builder so you
can wrap that signature into an inner envelope:
| Wallet | Kind | Builder | Sync? |
|---|---|---|---|
| MetaMask / any EVM EOA | EIP191_SECP256K1 | buildEip191EnvelopeFromSignature | sync |
| Phantom / any Solana wallet | ED25519 | buildEd25519EnvelopeFromSignature | async (Garaga WASM init) |
ed25519SignedBytes(messageHash) — the 64-byte hex-ASCII encoding of the OE
hash — not the raw 32-byte hash. The on-chain verifier reconstructs those same
bytes, so signing anything else fails verification.
Gas
The paymaster sums the per-kind gas overhead across each inner envelope. A 2-of-2 STARK + EIP-191 OE budgets 2M + 10M = 12M l2_gas for verification on top of the call’s own cost. See the passkey API reference for the kinds available client-side; gas tables live with the backend builders. This composes — you don’t budget gas yourself. The paymaster reserves it automatically based on the envelope shape.Threshold + recovery together
The headline product story for SHHH V8.4 is threshold combined with guardian recovery:- Day-to-day operations require N-of-M signatures
- Lost-key recovery still works because a guardian can initiate
initiate_recoveryeven if N-1 owners have lost their keys
Related
- Passkey reference — what each owner can be on the browser side
- Recovery — add/remove owners + guardian recovery
- Migration — getting from CHIPI v29 to SHHH first
