Skip to main content
A session lets your application execute approved calls without asking for a passkey signature each time. The user grants the authority once; your application keeps the session signer and passes it to the embedded wallet to sign later intents. SmartSessions and the session signing option are EVM-only. They do not grant authority to spend from the managed Solana wallet; see Solana availability. Start with the shared embedded wallet setup, authenticate the user, and keep the returned session.accounts.evm.address as accountAddress. Configure the same sponsorship endpoints before granting or executing a session. The examples below use the SDK’s viem ^2.55.0 peer dependency.
1

Create a session signer

Generate an ECDSA key for the session. Only send its public address to Rhinestone.
The wallet signs with a viem LocalAccount, here built from a locally accessible Hex private key. Keep the key in storage appropriate to its value and environment. A non-exportable KMS or HSM key needs a custom toAccount() signer, which this guide does not cover.
2

Define the authority

Grant one ERC-20 transfer action on Base Sepolia. The recipient is fixed, each transfer is capped at 10 tokens, and that function can execute up to 25 times during the 24-hour window.
definePermissions() derives the selector and calldata constraints from the ABI. The name and ABI make the review readable, but they are app-supplied metadata. The contract address, selector, parameter rules, validity window, and usage limit define the authority.See Session limits before granting broader actions or using assets from another chain.
3

Ask the user to grant the session

Use the initialized wallet client and authenticated account from the embedded wallet setup:
The embedded wallet shows the scope, collects the owner’s passkey authorization, and installs or enables the session-key configuration. No target chain is selected implicitly.
4

Persist the signer and handle

Store both halves before signing with the session. The signer is the capability; the handle describes the approved onchain configuration.
The stable, account-scoped key remains available after the in-memory grant result is gone. If an account has multiple grants, store a grant map and selected grantId under that account namespace instead of overwriting this record.sessionStorage survives a page refresh but not a tab close. Use encrypted application storage or a protected backend secret store when the session must last longer. Never send the private key to Rhinestone.Rhinestone separately stores public grant metadata so the handle can be recovered from the same account namespace. It cannot recover the private signer.
5

Send with the session

Pass the stored handle and its signer as session on sendIntent(). The wallet signs with the session key instead of the passkey, so no dialog or passkey prompt appears. The user must still be signed in to the account that granted the session.
The wallet prepares the intent, rebuilds the per-chain session-key signatures from the handle, and submits them. It returns the same result as a passkey-signed send, and sponsorship works the same way. The onchain validator rejects calls outside the grant.Session signing supports EVM destinations only. It can request destination.token, with or without amount, funded from an explicit EVM source; a cross-chain source needs the grant installed there too. A recipient, Solana source or destination, or module install is refused. The signer must be the granted session key. With sendBatchIntent({ intents, session }), each intent is prepared, signed, and submitted independently, so check every entry of results.

Try a scoped session

This testnet demo grants a narrower action than the transfer example above: mint 0.1 mUSD to your own account on Base Sepolia, up to 25 times within 24 hours. Grant the permission once, then mint without another passkey prompt. Fees are sponsored, and the session key stays in this tab’s sessionStorage.