Skip to main content
The hosted wallet — not the dApp — owns approval, and it decodes what’s being signed so the user is never blind-signing:
  • Connect shows the dApp’s origin + the address being shared, and the user must approve (never automatic).
  • Execute decodes calls against known tokens into human intent — “Approve spending 10 USDC to 0x…” with a loud UNLIMITED badge over the threshold, “Send 5 USDC to 0x…”, or an explicit “Unrecognized contract” warning (it never invents intent). Gas reads “Free · covered by Chipi”.
  • signTypedData decodes the SNIP-12 message into labeled fields and highlights spend-authorization keys (spender / amount / deadline). Typed data it can’t read is hard-blocked — the user can’t blind-sign it. (Of 2024’s ~$494M in reported wallet-drainer losses, 56.7% of phishing thefts used blind-signed Permit-style typed data; this discipline closes that vector.)

Where the trust boundary sits

ChipiConnector (running inside the dApp’s page) holds no keys and signs nothing — it only forwards wallet_* RPC calls over postMessage to the hosted wallet at wallet.chipipay.com, a separate origin the dApp never controls. The same is true of the browser extension: it injects the provider so dApps can discover Chipi, but every signature still happens on the hosted wallet’s own origin, behind the user’s passkey. Neither surface can exfiltrate a key that was never present.