controller-sessions

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Controller Sessions & Policies

Controller会话与策略

Sessions enable pre-approved, gasless transactions without user prompts for each interaction.
会话功能支持预批准的无Gas费交易,无需用户在每次交互时都进行确认。

How Sessions Work

会话工作机制

  1. Define policies (which contracts/methods your app needs)
  2. User approves policies once during connection
  3. Controller creates session with approved permissions
  4. Transactions execute seamlessly via Paymaster
  1. 定义策略(你的应用需要交互的合约/方法)
  2. 用户在连接时一次性批准策略
  3. Controller创建带有已批准权限的会话
  4. 通过Paymaster无缝执行交易

With vs Without Policies

启用与未启用策略的对比

FeatureWith PoliciesWithout Policies
Transaction approvalPre-approvedManual each time
Gasless transactionsYes (Paymaster)No
Error handlingConfigurable display modesStandard modal
Best forGames, frequent txsSimple apps
特性启用策略未启用策略
交易审批预批准每次手动确认
无Gas费交易是(通过Paymaster)
错误处理可配置显示模式标准弹窗
适用场景游戏、高频交易简单应用

Defining Policies

定义策略

typescript
import { SessionPolicies } from "@cartridge/controller";

const policies: SessionPolicies = {
  contracts: {
    "0x1234...": {
      name: "My Game",
      description: "Game contract interactions",
      methods: [
        {
          name: "Move Player",
          entrypoint: "move_player",
          description: "Move player on the map",
        },
        {
          name: "Attack",
          entrypoint: "attack",
        },
      ],
    },
  },
};

const controller = new Controller({ policies });
typescript
import { SessionPolicies } from "@cartridge/controller";

const policies: SessionPolicies = {
  contracts: {
    "0x1234...": {
      name: "My Game",
      description: "Game contract interactions",
      methods: [
        {
          name: "Move Player",
          entrypoint: "move_player",
          description: "Move player on the map",
        },
        {
          name: "Attack",
          entrypoint: "attack",
        },
      ],
    },
  },
};

const controller = new Controller({ policies });

Token Spending Limits

代币支出限额

For
approve
methods, specify spending limits in hex format:
typescript
const policies: SessionPolicies = {
  contracts: {
    // ETH contract
    "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7": {
      name: "Ethereum",
      methods: [
        {
          name: "approve",
          entrypoint: "approve",
          spender: "0x1234567890abcdef1234567890abcdef12345678",
          amount: "0x3", // Limit: 3 ETH (hex, accounts for decimals)
        },
      ],
    },
  },
};
  • Use
    0xffffffffffffffffffffffffffffffff
    for unlimited (max uint128)
  • Users see USD values alongside token amounts when price data is available
对于
approve
方法,需以十六进制格式指定支出限额:
typescript
const policies: SessionPolicies = {
  contracts: {
    // ETH contract
    "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7": {
      name: "Ethereum",
      methods: [
        {
          name: "approve",
          entrypoint: "approve",
          spender: "0x1234567890abcdef1234567890abcdef12345678",
          amount: "0x3", // Limit: 3 ETH (hex, accounts for decimals)
        },
      ],
    },
  },
};
  • 使用
    0xffffffffffffffffffffffffffffffff
    表示无限制(最大uint128值)
  • 当有价格数据时,用户会在代币金额旁看到对应的USD价值

Signed Message Policies

签名消息策略

Pre-approve typed message signing:
typescript
const policies: SessionPolicies = {
  messages: [
    {
      name: "Game Message",
      types: {
        StarknetDomain: [
          { name: "name", type: "shortstring" },
          { name: "version", type: "shortstring" },
          { name: "chainId", type: "shortstring" },
          { name: "revision", type: "shortstring" },
        ],
        GameMessage: [
          { name: "content", type: "string" },
          { name: "timestamp", type: "felt" },
        ],
      },
      primaryType: "GameMessage",
      domain: {
        name: "MyGame",
        version: "1",
        chainId: "SN_MAIN",
        revision: "1",
      },
    },
  ],
};
预批准类型化消息签名:
typescript
const policies: SessionPolicies = {
  messages: [
    {
      name: "Game Message",
      types: {
        StarknetDomain: [
          { name: "name", type: "shortstring" },
          { name: "version", type: "shortstring" },
          { name: "chainId", type: "shortstring" },
          { name: "revision", type: "shortstring" },
        ],
        GameMessage: [
          { name: "content", type: "string" },
          { name: "timestamp", type: "felt" },
        ],
      },
      primaryType: "GameMessage",
      domain: {
        name: "MyGame",
        version: "1",
        chainId: "SN_MAIN",
        revision: "1",
      },
    },
  ],
};

Error Handling

错误处理

Error Display Modes

错误显示模式

typescript
const controller = new Controller({
  policies,
  errorDisplayMode: "notification", // "modal" | "notification" | "silent"
});
  • modal (default): Full error modal, blocks interaction
  • notification: Toast notification (clickable to open modal), non-blocking
  • silent: Console only, custom handling required
typescript
const controller = new Controller({
  policies,
  errorDisplayMode: "notification", // "modal" | "notification" | "silent"
});
  • modal(默认):全屏错误弹窗,阻止交互
  • notification:提示消息(可点击打开弹窗),不阻止交互
  • silent:仅在控制台输出,需自定义处理逻辑

Error Handling Interaction

错误处理交互逻辑

propagateSessionErrors
errorDisplayMode
Behavior
true
AnyErrors rejected immediately, no UI shown
false
(default)
modal
Opens controller modal
false
notification
Shows clickable toast
false
silent
No UI, logged to console
propagateSessionErrors
errorDisplayMode
行为
true
任意错误立即抛出,不显示UI
false
(默认)
modal
打开Controller弹窗
false
notification
显示可点击的提示消息
false
silent
无UI提示,仅在控制台记录

Error Propagation

错误抛出

Return errors to your app instead of showing keychain UI:
typescript
import { Controller, ResponseCodes } from "@cartridge/controller";

const controller = new Controller({
  policies,
  propagateSessionErrors: true,
});

const result = await account.execute(calls);
if (result.code === ResponseCodes.SUCCESS) {
  console.log("Tx hash:", result.transaction_hash);
} else if (result.code === ResponseCodes.ERROR) {
  console.error(result.message, result.error);
}
Note:
SessionRefreshRequired
and
ManualExecutionRequired
always show modal regardless of settings.
将错误返回至你的应用,而非显示密钥链UI:
typescript
import { Controller, ResponseCodes } from "@cartridge/controller";

const controller = new Controller({
  policies,
  propagateSessionErrors: true,
});

const result = await account.execute(calls);
if (result.code === ResponseCodes.SUCCESS) {
  console.log("Tx hash:", result.transaction_hash);
} else if (result.code === ResponseCodes.ERROR) {
  console.error(result.message, result.error);
}
注意:无论设置如何,
SessionRefreshRequired
ManualExecutionRequired
始终会显示弹窗。

Disconnect Redirect

断开连接重定向

For mobile apps and cross-platform logout flows:
typescript
const connector = new SessionConnector({
  policies,
  rpc: "https://api.cartridge.gg/x/starknet/mainnet",
  chainId: "SN_MAIN",
  redirectUrl: "myapp://callback",
  disconnectRedirectUrl: "myapp://logout", // Where to go after logout
});
适用于移动应用和跨平台登出流程:
typescript
const connector = new SessionConnector({
  policies,
  rpc: "https://api.cartridge.gg/x/starknet/mainnet",
  chainId: "SN_MAIN",
  redirectUrl: "myapp://callback",
  disconnectRedirectUrl: "myapp://logout", // Where to go after logout
});

Verified Sessions

已验证会话

Verified policies display trust badges and streamlined approval flows. Submit configs to
@cartridge/presets
for verification.
已验证策略会显示信任标识并提供简化的审批流程。请将配置提交至
@cartridge/presets
进行验证。

SessionOptions Type

SessionOptions类型

typescript
type SessionOptions = {
  rpc: string;                        // RPC endpoint URL
  chainId: string;                    // Chain ID
  policies: SessionPolicies;          // Approved transaction policies
  redirectUrl: string;                // URL to redirect after auth
  disconnectRedirectUrl?: string;     // URL to redirect after logout
  signupOptions?: AuthOptions;        // Auth methods to show
};
typescript
type SessionOptions = {
  rpc: string;                        // RPC endpoint URL
  chainId: string;                    // Chain ID
  policies: SessionPolicies;          // Approved transaction policies
  redirectUrl: string;                // URL to redirect after auth
  disconnectRedirectUrl?: string;     // URL to redirect after logout
  signupOptions?: AuthOptions;        // Auth methods to show
};