Session Keys for StarkNet Account Abstraction
Implement session keys on StarkNet so users authenticate once and interact many times without re-prompting. Essential for games, social apps, and trading bots.
Overview
Session keys let users authenticate once and interact with your app many times without re-prompting for passkey confirmation. Think of it like staying logged in to a website instead of entering your password on every page. The user taps their passkey once at the start of a session, and all subsequent transactions go through automatically within defined permissions and time limits.
Why Session Keys Matter
Without session keys, every transaction requires a passkey tap: send USDC, stake, buy a SKU, call a contract. With session keys, one tap covers an entire session. This is essential for:
- - Games. Players approve once, play many turns without interruption
- - Social apps. Like, tip, and interact without re-auth on every action
- - Trading. Execute multiple trades in a session
- - Subscriptions. Recurring payments without manual approval each time
Session keys require walletType: "CHIPI". They do not work with "READY" (Argent X) wallets.
Create a Session Key
Use the useCreateSessionKey hook to create a time-limited, scope-limited session:
tsximport { useCreateSessionKey } from "@chipi-stack/nextjs";
const { mutateAsync: createSession } = useCreateSessionKey();
const session = await createSession({
encryptKey: passkeyCredential,
wallet: userWallet,
allowedMethods: [
{
contractAddress: "0x_TARGET_CONTRACT",
entrypoint: "transfer",
},
],
expiry: Math.floor(Date.now() / 1000) + 3600, // 1 hour
bearerToken: process.env.NEXT_PUBLIC_CHIPI_API_KEY!,
});The allowedMethods array defines the security boundary. A session key for "transfer" cannot call "approve" or any other function. The expiry limits the time window, reducing risk even if a session key is compromised.
Execute Transactions with a Session Key
Once created, use the session key for subsequent transactions without any passkey prompt:
tsximport { useExecuteSessionTransaction } from "@chipi-stack/nextjs";
const { mutateAsync: execute } = useExecuteSessionTransaction();
await execute({
sessionKey: session,
wallet: userWallet,
calls: [
{
contractAddress: "0x_TARGET_CONTRACT",
entrypoint: "transfer",
calldata: [recipientAddress, amountLow, amountHigh],
},
],
bearerToken: process.env.NEXT_PUBLIC_CHIPI_API_KEY!,
});No encryptKey needed here. The session key replaces the passkey for authorized operations.
Manage Session Lifecycle
- - Store the active session in React state or context
- - Check expiry before executing. If expired, prompt the user to create a new session
- - Revoke session keys when the user logs out or when the session is no longer needed
- - Never create unlimited session keys. Always set an expiry
- - Scope allowedMethods to only what's needed
- - Store session keys securely in memory. Avoid persisting to localStorage in production