| name | controller-setup |
| description | Integrate Cartridge Controller wallet into Starknet applications. Use when setting up Controller for the first time, installing packages, configuring chains/RPC endpoints, or troubleshooting basic integration issues. Covers installation, Controller instantiation, ControllerConnector vs SessionConnector choice, chain configuration, and package compatibility. |
Controller Setup
Cartridge Controller is a gaming-focused smart contract wallet for Starknet with session keys, passkeys, and paymaster support.
Installation
pnpm add @cartridge/controller starknet
pnpm add @cartridge/controller @cartridge/connector starknet
Quick Start
import Controller from "@cartridge/controller";
const controller = new Controller();
const account = await controller.connect();
Session Policies
Session policies are required for session-based transaction execution.
Without policies, execute() fails with error code 130 because the Controller's session validation needs a merkle proof per call.
Without policies, Controller falls back to manual approval via the hosted keychain modal.
On local Katana, policies are required because new Controller accounts cannot be properly deployed without them.
Choosing a Connector
| Use Case | Connector | Key Difference |
|---|
| Web apps with starknet-react | ControllerConnector | Keys managed via browser cookies & localStorage |
| Native/mobile apps | SessionConnector | App generates local keypair, authenticates via browser redirect |
ControllerConnector (Web)
import { ControllerConnector } from "@cartridge/connector";
const connector = new ControllerConnector({
policies,
signupOptions,
});
SessionConnector (Native/Mobile)
import { SessionConnector } from "@cartridge/connector";
import { constants } from "starknet";
const connector = new SessionConnector({
policies,
rpc: "https://api.cartridge.gg/x/starknet/mainnet",
chainId: constants.StarknetChainId.SN_MAIN,
redirectUrl: "myapp://auth-callback",
disconnectRedirectUrl: "myapp://logout",
signupOptions: ["webauthn", "google"],
});
Session flow: App generates keypair → User authenticates in browser → Browser redirects back → App signs transactions locally.
Chain Configuration
Default RPC endpoints are provided. Override with custom chains:
import { constants } from "starknet";
const controller = new Controller({
chains: [
{ rpcUrl: "https://api.cartridge.gg/x/starknet/mainnet" },
{ rpcUrl: "https://api.cartridge.gg/x/starknet/sepolia" },
{ rpcUrl: "http://localhost:5050" },
],
defaultChainId: constants.StarknetChainId.SN_MAIN,
});
Local Development with Katana
When using Controller with a local Katana instance, the Katana config must deploy Controller contracts at genesis.
Without this, transactions fail with "Requested contract address ... is not deployed".
Required katana.toml config:
[dev]
dev = true
no_fee = true
[cartridge]
paymaster = true
[server]
http_cors_origins = "*"
Note: paymaster = true implicitly enables controllers = true.
Start Katana with config:
katana --config katana.toml
See the Katana configuration guide for all TOML options.
Performance: Lazy Loading
Defer iframe mounting until connect() is called:
const controller = new Controller({
lazyload: true,
});
ControllerOptions Reference
type ControllerOptions = {
chains?: Chain[];
defaultChainId?: string;
policies?: SessionPolicies;
propagateSessionErrors?: boolean;
errorDisplayMode?: "modal" | "notification" | "silent";
lazyload?: boolean;
preset?: string;
signupOptions?: AuthOptions;
};
Package Compatibility
{
"@cartridge/connector": "0.11.3-alpha.1",
"@cartridge/controller": "0.11.3-alpha.1",
"@starknet-react/core": "^5.0.1",
"@starknet-react/chains": "^5.0.1",
"starknet": "^8.1.2"
}
Common Issues
Cookies required: Controller sets essential cookies for initialization.
HTTPS required in dev: Use vite-plugin-mkcert for local HTTPS.
Connector outside components: Create ControllerConnector outside React components to avoid recreation on re-render.