wallet.chipipay.com, or your own host built on
createChipiWindowObject / useChipiWalletObject) owns every approval and every signature.
What the SDK enforces
These hold for any wallet built on@chipi-stack/nextjs / @chipi-stack/chipi-react
(14.16.0+):
- Deny by default. The wallet object asks
requestApprovalfor three things:connect,executeandsignTypedData. Without arequestApprovalcallback, all three are refused (113) and a singleconsole.warnsays why. Nothing is ever auto-approved. - Connect is explicit.
wallet_requestAccountsasks for aconnectapproval once per wallet object, even when the wallet is unlocked.silent_modeandwallet_getPermissionsreveal nothing until then. - Typed data must be for this chain.
wallet_signTypedDatarefuses a SNIP-12 domain with nochainId, or one that differs from the wallet’s (SN_MAINand its hex form are the same chain), with114and without prompting. Bramble applies the same rule. (A missingchainIdis refused from 14.17.0; 14.16.x let it through.) - No dApp can create a session. No
wallet_*method creates a session or asks for asessionapproval. Sessions come only from the host callingcreateSession(policy)onuseChipiWalletObject. WithspendCaps, the session and its spending policies are registered in the same owner-signed transaction (sdk.sessions.setupSession). A cap that would mean “unlimited” on-chain (maxPerWindow = 0) is refused. The on-chain whitelist is per entrypoint selector, not per contract, so caps are what bound token spend.
@chipi-stack/starknet-connector) ignores any message that doesn’t come
from the wallet window it opened (0.4.0+), times out requests that get no answer, never reopens
a closed wallet window outside a click, and (0.5.0+) answers passive calls such as
wallet_getPermissions itself while no wallet window is open, so a page-load wallet scan never
tries to open Chipi.
Error codes of the Chipi wallet object
createChipiWindowObject rejects with an Error whose numeric code follows the Starknet
wallet API:
Errors thrown by the host’s
executeCalls or signTypedData reach the dApp as thrown. Through
the connector, these codes arrive as err.code (see Errors).
What the hosted wallet adds
The hosted wallet atwallet.chipipay.com puts a review screen in front of each approval: the
dApp’s origin and the address being shared on connect, decoded token intent on execute
(amounts, recipients, an UNLIMITED badge on large approvals, a warning on unrecognized
contracts), and labeled SNIP-12 fields on signTypedData. That screen lives in the hosted wallet,
not in this SDK; if you build your own host, requestApproval is where you render it.
Message origins: a rule for wallet hosts
Every request the connector sends carries anorigin field, but the dApp writes that field
itself. A wallet host must identify the dApp by the browser-provided MessageEvent.origin of
the message it received, and show and enforce that value. Never trust the origin inside the
message: a phishing page can put any origin it likes there.
Where the trust boundary sits
ChipiConnector (running inside the dApp’s page) holds no keys and signs nothing: it only
forwards wallet_* calls over postMessage to the hosted wallet, 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.
Other wallets on the same page, such as Bramble, are separate objects (window.starknet_bramble)
with their own approvals. The Chipi connector never reads or calls them.
✅ Verified against the SDK source on 2026-10-12.
