Skip to main content
useSession({ address }) calls the active modality’s session-creation callback on mount and on a 50-minute interval, keeping the 1-hour calm_session cookie fresh ahead of expiry. It also refetches when the tab regains focus — backgrounded tabs throttle the timer, so focus revalidation catches the “user came back after 2h idle” case before the next call would 401.

Import

import { useSession } from "@calm-xyz/react";

Usage

app/page.tsx
"use client";
import { useCalm, useSession } from "@calm-xyz/react";
import { useReady } from "@calm-xyz/react/wagmi"; // or @calm-xyz/react/privy

function SignedIn() {
  const { address } = useCalm();
  const { data, isPending, error } = useSession({ address });
  if (isPending) return <div>Loading…</div>;
  if (error) return <div>Auth error: {error.message}</div>;
  return <div>Signed in as {data?.wallet}</div>;
}

export default function Page() {
  const ready = useReady();
  if (!ready) return <div>Loading…</div>;
  return <SignedIn />;
}
<SignedIn> calls useCalm(), which throws outside the Calm context. Gate it on useReady() (from @calm-xyz/react/wagmi or @calm-xyz/react/privy) so the inner component only renders once the provider is live.

Parameters

import { type UseSessionParameters } from "@calm-xyz/react";

address

string The wallet address the session is bound to. Must match the wallet the active provider is configured for.

Return Type

import { type UseSessionReturnType } from "@calm-xyz/react";
UseQueryResult<SessionResponse, ApiError> from @tanstack/react-query — the SDK’s query client is set up by the active modality provider.

data

SessionResponse | undefined The session-creation response: { wallet, expires_at }. wallet is lowercased and 0x-prefixed; expires_at is the ISO timestamp the calm_session cookie expires at (1 hour from creation).

isPending

boolean true until the first session-creation call resolves. Use to gate loading UI.

error

ApiError | null The structured error from the modality’s createSession callback. Branch on error.code to drive recovery UI (e.g. siwe_invalid, binding_expired, refresh_wallet_mismatch).

status

"pending" | "error" | "success" The react-query status — useful when you want one value to switch on in a switch rather than three booleans.

refetch

() => Promise<UseQueryResult<SessionResponse, ApiError>> Manually trigger a session refresh — useful after the partner does something that may have invalidated the cookie (e.g. their own wallet stack’s logout). useCalm().logout() invalidates the same query under the hood, so most callers don’t need this directly. See the @tanstack/react-query useQuery docs for the full set of fields on the return type.