requirePin is true.
All signatures are:
0x-prefixed 130-character hex strings- Recoverable ECDSA in
r(32) ‖ s(32) ‖ v(1)format - Low-s normalised (EIP-2 compliant)
v ∈ {27, 28}— verifiable withecrecover
Sign a personal message (EIP-191)
signMessage prepends the \x19Ethereum Signed Message:\n{length} prefix before hashing and signing. This matches the personal_sign RPC method used by SIWE, login challenges, and most WalletConnect flows.
requirePin is false, omit the PIN:
Sign a 32-byte hash
signTransactionHash signs a pre-computed 32-byte digest directly, without adding any prefix. Use it for:
- ERC-4337
userOpHash - EIP-712 structured-data digests
- Raw Ethereum transaction hashes
- Any other 32-byte payload you have already hashed yourself
0x prefix is optional. Anything else throws signInvalidHash.
Server-side verification
Signatures are ECDSA-recoverable. Your backend (or a smart contract) only needs the address frominitWallet():
Gating pattern
A common pattern is to ask for the PIN only whenrequirePin is true, and skip the prompt otherwise:
pin is undefined when the gate is off, the same call site works in both modes.
Prerequisites checklist
Before calling either signing method you need:- A provisioned wallet (
initWallet()succeeded, orhasWallet()istrue) - A PIN set (
hasPin()istrue) — only whenrequirePinistrue
pinNotSet, or pinInvalid if you omit the PIN entirely while the gate is on.
