Skip to main content
Starknet users already hold a key they trust. Sign in with Starknet (SIWS) turns that key into a login: your server issues a one-time nonce, the user’s wallet signs a SNIP-12 message containing it, and your server asks the account contract whether the signature is valid. @chipi-stack/backend (14.16.0+) ships both halves:
  • createStarknetSignInTypedData builds the message.
  • verifyStarknetSignIn checks it: chain, domain, URI, nonce, expiry, and the signature.
It works with deployed accounts (any wallet, through the account’s own is_valid_signature) and with accounts that are not deployed yet, which is how new Bramble and Ready accounts start out. The browser example uses Bramble. Braavos and Ready take the same requests; only discovery differs. SIWS is mainnet only. The domain’s chainId must be SN_MAIN; from 14.17.0 its felt form (0x534e5f4d41494e, hex or decimal) is accepted too, since wallets echo either.

1. Issue the message (server)

Store the nonce with a short expiry, then return the typed data to the browser.
The builder sticks to what every wallet accepts: SNIP-12 revision 1, SN_MAIN in the domain, and single-line printable ASCII strings. It throws on anything else, because some wallets (Bramble among them) refuse to sign it.

2. Sign it (browser)

Bramble injects window.starknet_bramble (id "bramble"). It does not set window.starknet, and it can appear after DOMContentLoaded, so wait for its starknet#initialized event before deciding it is missing. Bramble is strict, and the snippet follows its rules:
  • Prompts need a click. Bramble opens its panel only during a user gesture, so start from a click handler. Each prompt stays pending until the user decides; don’t retry it automatically.
  • Params are parsed strictly. Pass { silent_mode: false } to wallet_requestAccounts, never undefined params or extra keys (114).
  • Mainnet first. Bramble refuses typed data whose domain chainId is not its active network (114, before any prompt). Check wallet_requestChainId before you ask for a signature.
  • Deployment data. wallet_deploymentData answers 115 when the account is already deployed (send nothing) and 116 when Bramble can’t derive it.
A locked wallet, an unconnected site and a refused request all reach the page as 163 with no detail, so show one message with a manual retry button. This snippet connects and signs from one click. Bramble opens its panel only during a user gesture, and the click’s gesture can expire while the user approves the connection. If the signature prompt doesn’t open, split the flow into two clicks: one to connect, one to sign. The signature is [r, s] for Bramble’s OpenZeppelin account and Braavos, and ["1", "0", publicKey, r, s] for Ready (Argent). Send it as returned; the server passes the whole array to the account. With get-starknet v4, getAvailableWallets() finds Bramble by id === "bramble"; run it after injection. starknetkit needs Bramble added as an explicit InjectedConnector.

3. Verify (server)

Consume the nonce (once, atomically), then verify:
What it checks: ADDRESS_MISMATCH has two sources: deployment data for another account than the one in the message, or deployment data whose constructor arguments don’t produce its own address. The typed data is rebuilt from its message before hashing, so a client can’t swap in extra types or a testnet domain. Only 'VALID' counts as valid: accounts answer 0 or revert on a bad signature, and a looser “anything non-zero” check would accept garbage. Undeployed accounts are supported for OpenZeppelin 3.0 (Bramble’s default account, signature [r, s]) and Argent 0.4 without a guardian (Ready, signature ["1", "0", publicKey, r, s]). An undeployed Argent account with a guardian gets UNSUPPORTED_ACCOUNT_CLASS, because its second signature can’t be checked off-chain; so does any other class. Ask the user to make one transaction first: Bramble deploys an OpenZeppelin or Argent account in the same flow as its first transaction.

Lower-level helpers

  • isValidStarknetSignature(provider, address, hash, signature) asks any deployed account about any message hash.
  • verifyUndeployedStarknetSignature(deploymentData, hash, signature) does the off-chain check on its own.
✅ Verified against the SDK source on 2026-10-12.