Installation
To add Calm to your project, install the required packages.- Wagmi is the wallet stack the SDK reads from for the connected account, chain, and signers.
- Viem is the TypeScript interface for Ethereum that wagmi uses for blockchain operations.
- TanStack Query is an async state manager that handles requests, caching, and more.
Import the stylesheet
Import the Calm stylesheet once at your app root (Next.jslayout.tsx, React main.tsx):
@import it from your own CSS file:
Wrap App in <WagmiCalmProvider>
Place <WagmiCalmProvider> inside your wagmi tree — the
<WagmiProvider> + <QueryClientProvider> pair wagmi requires.
app/layout.tsx
Open the onramp
The provider always renders its children. Wrap any trigger element in<CalmOnramp> to open the deposit modal, and use
useReady() to gate the trigger on whether the Calm
context is live (i.e. wagmi has a connected account).
Props
Your publishable key —
calm_public_(live|dev)_<32 hex>. Embedded
in the SIWE message’s Resources field as calm:credential:<calmKey>
so the wallet attests the tenant key as part of the same signature
that proves wallet ownership.Source fiat currency for the bank-deposit onramp.
Initial destination chain for auto-converted USDC. Optional —
defaults to
999 (HyperEVM). Once mounted the SDK owns the chain;
switch it at runtime via
useCalm().setChain(...).The destination chain defaults to HyperEVM (
999) with mode set
to hypercore. It’s independent of the wallet’s wagmi chain — to
deliver USDC elsewhere, override initialChain, or call
useCalm().setChain(...) at runtime (and
setMode(...) when staying on chain 999).Initial Hyperliquid execution layer. Optional — defaults to
"hypercore" when initialChain is 999. Silently ignored on
every other chain because mode only carries meaning on Hyperliquid
(the SDK exposes mode: null off 999). Switch at runtime via
useCalm().setMode(...), which throws when
called with chain !== 999.Override the Calm API root. Use
https://api.sandbox.calmtreasury.xyz for the sandbox environment.useReady
boolean. false until wagmi reports a connected account
and <WagmiCalmProvider> has a configured Calm context; true once
it does. Safe to call before any provider mounts — defaults to
false.
Use it to render your own loading UI in place of the silent null
the provider used to return.
Errors
The provider’s session creation throws on any non-2xx response from the API. TheuseSession hook surfaces the error
in result.error. Common codes:
error.code | Meaning |
|---|---|
binding_expired | The nonce expired (5-minute TTL) before the user signed. Re-mount or retry. |
siwe_invalid | The signed message failed verification (wrong nonce, wrong address recovered, time bounds, unparseable input). |
invalid_publishable_key | calmKey is malformed, unknown, or revoked. Check your Calm dashboard. |
publishable_key_missing | No calm:credential:<key> entry in the SIWE message’s Resources field. Usually a bundler stripping process.env.NEXT_PUBLIC_CALM_KEY — verify the env var is present at build time. |
origin_not_allowed | Your page’s Origin isn’t on the publishable key’s allowlist. Live keys require HTTPS; add the origin in the dashboard. |
refresh_wallet_mismatch | The calm_refresh cookie is bound to a different wallet than the one signing in now. Call useCalm().logout() before re-signing as the new wallet. |