Sessions and Policies
Cartridge Controller supports session-based authorization and policy-based transaction approvals. When policies are pre-approved by the user, games can execute transactions seamlessly without requesting approval for each interaction, creating a smooth gaming experience.
How Sessions Work
- Policy Definition: Games define which contract methods they need to call
- User Approval: Users approve these policies once during initial connection
- Session Creation: Controller creates a session with approved transaction permissions
- Gasless Execution: Games can execute approved transactions without user prompts
- Paymaster Integration: Transactions can be sponsored through Cartridge Paymaster
Transactions Without Policies
Cartridge Controller can execute transactions without defining policies. When no policies are provided:
- Each transaction requires manual user approval via the Cartridge interface
- Users will see a confirmation screen for every transaction
- No gasless transactions or paymaster integration
- Suitable for simple applications that don't need session-based authorization
// Controller without policies - requires manual approval for each transaction
const controller = new Controller();
const account = await controller.connect();
// This will prompt the user for approval
const tx = await account.execute([
{
contractAddress: "0x123...",
entrypoint: "transfer",
calldata: ["0x456...", "100"],
}
]);
Sessions vs. Manual Approval
Feature | With Policies (Sessions) | Without Policies (Manual) |
---|---|---|
Transaction Approval | Pre-approved via policies | Manual approval each time |
User Experience | Seamless gameplay | Confirmation prompts |
Gasless Transactions | Yes (via Paymaster) | No |
Setup Complexity | Higher (policy definition) | Lower (basic setup) |
Best For | Games, frequent transactions | Simple apps, occasional transactions |
Session Options
export type SessionOptions = {
rpc: string; // RPC endpoint URL
chainId: string; // Chain ID for the session
policies: SessionPolicies; // Approved transaction policies
redirectUrl: string; // URL to redirect after registration
disconnectRedirectUrl?: string; // Optional URL to redirect after disconnect/logout
};
Defining Policies
Policies allow your application to define permissions that can be pre-approved by the user:
type SessionPolicies = {
contracts: {
[address: string]: ContractPolicy; // Contract interaction policies
};
messages?: TypedDataMessage[]; // Optional signed message policies
};
type ContractPolicy = {
name?: string; // Human-readable name of the contract
description?: string; // Description of the contract
methods: Method[]; // Allowed contract methods
};
type ContractMethod = {
name: string; // Method name
entrypoint: string; // Contract method entrypoint
description?: string; // Optional method description
};
type SignMessagePolicy = TypedDataPolicy & {
name?: string; // Human-readable name of the policy
description?: string; // Description of the policy
};
type TypedDataPolicy = {
types: Record<string, StarknetType[]>;
primaryType: string;
domain: StarknetDomain;
};
Disconnect Redirect
The disconnectRedirectUrl
option allows you to redirect users to a specific URL after they disconnect or logout from their session. This is particularly useful for:
- Mobile Apps: Redirect users back to your mobile app using deep links (e.g.,
"myapp://logout-complete"
) - Web Apps: Send users to a logout confirmation page or back to your landing page
- Cross-Platform: Handle logout flows consistently across different platforms
const session = new SessionConnector({
policies,
rpc: "https://starknet-mainnet.public.blastapi.io/rpc/v0.7",
chainId: "SN_MAIN",
redirectUrl: "https://myapp.com/",
disconnectRedirectUrl: "whatsapp://", // Deep link example
});
When disconnect()
is called, users will be redirected to the keychain logout page, and after successful logout, they will be automatically redirected to your specified URL.
Note: If no disconnectRedirectUrl
is provided, users will remain on the keychain logout page after disconnection.
Usage Examples
Contract Interaction Policies Example
const policies: SessionPolicies = {
contracts: {
"0x4ed3a7c5f53c6e96186eaf1b670bd2e2a3699c08e070aedf4e5fc6ac246ddc1": {
name: "Pillage",
description: "Allows you to raid a structure and pillage resources",
methods: [
{
name: "Battle Pillage",
description: "Pillage a structure",
entrypoint: "battle_pillage"
}
]
},
"0x2620f65aa2fd72d705306ada1ee7410023a3df03da9291f1ccb744fabfebc0": {
name: "Battle contract",
description: "Required to engage in battles",
methods: [
{
name: "Battle Start",
description: "Start a battle",
entrypoint: "battle_start"
},
{
name: "Battle Join",
description: "Join a battle",
entrypoint: "battle_join"
},
{
name: "Battle Leave",
description: "Leave a battle",
entrypoint: "battle_leave"
},
]
},
// Include other contracts as needed
}
};
// Using the controller directly
const controller = new Controller({
policies,
// other options
});
// Using starknet-react connector
const connector = new CartridgeConnector({
policies,
// other options
});
// Using SessionConnector with disconnect redirect
const session = new SessionConnector({
policies,
rpc: "https://starknet-mainnet.public.blastapi.io/rpc/v0.7",
chainId: "SN_MAIN",
redirectUrl: "https://myapp.com/",
disconnectRedirectUrl: "https://myapp.com/logout-complete", // Optional: redirect after logout
});
Signed Message Policy Example
Signed Message policies allow the application to sign a typed message without manual approval from the user.
const policies: SessionPolicies = {
messages: [
{
name: "Eternum Message Signing",
description: "Allows signing messages for Eternum",
types: {
StarknetDomain: [
{ name: "name", type: "shortstring" },
{ name: "version", type: "shortstring" },
{ name: "chainId", type: "shortstring" },
{ name: "revision", type: "shortstring" }
],
"s0_eternum-Message": [
{ name: "identity", type: "ContractAddress" },
{ name: "channel", type: "shortstring" },
{ name: "content", type: "string" },
{ name: "timestamp", type: "felt" },
{ name: "salt", type: "felt" }
]
},
primaryType: "s0_eternum-Message",
domain: {
name: "Eternum",
version: "1",
chainId: "SN_MAIN",
revision: "1"
}
}
]
};
Verified Sessions
Verified session policies provide a better user experience by attesting to the validity of a games session policy configuration, providing confidence to it's players.
When using verified session policies, the user experience is significantly improved:
- No Approval Screen: Verified sessions automatically bypass the user approval screen
- Instant Connection: Sessions are created automatically with a default 24-hour duration
- Seamless UX: Users can start playing immediately without manual session approval
- Graceful Fallback: If automatic session creation fails, the system falls back to showing the standard approval UI
This automatic behavior only applies to verified policies. Unverified policies will continue to show the approval screen as before, maintaining security for untrusted applications.
Getting VerifiedVerified configs can be committed to the configs
folder in @cartridge/presets
.
Before they are merged, the team will need to collaborate with Cartridge to verify the policies.