Skip to content

Cartridge Controller Node.js Integration

This guide demonstrates how to integrate the Cartridge Controller with a Node.js application.

Installation

npm
npm install @cartridge/controller starknet

Basic Setup

Using Presets

import SessionProvider, {
  ControllerError,
} from "@cartridge/controller/session/node";
import { constants } from "starknet";
import path from "path";
 
async function main() {
  const storagePath =
    process.env.CARTRIDGE_STORAGE_PATH ||
    path.join(process.cwd(), ".cartridge");
 
  // Create a session provider using a verified preset
  const provider = new SessionProvider({
    rpc: "https://api.cartridge.gg/x/starknet/sepolia",
    chainId: constants.StarknetChainId.SN_SEPOLIA,
    preset: "my-game", // Load verified policies from preset
    basePath: storagePath,
  });
 
  console.log("Registering a session...");
  console.log("Open the URL printed below to authorize the session.");
 
  try {
    const account = await provider.connect();
    if (!account) {
      console.log("Session not ready yet. Complete the browser flow and rerun.");
      return;
    }
 
    console.log("Session ready!");
    console.log("Account address:", account.address);
  } catch (error: unknown) {
    const controllerError = error as ControllerError;
    if (controllerError?.code) {
      console.error("Error:", {
        code: controllerError.code,
        message: controllerError.message,
        data: controllerError.data,
      });
    } else {
      console.error("Error:", error);
    }
  }
}
 
main().catch(console.error);

Using Manual Policies

import SessionProvider, {
  ControllerError,
} from "@cartridge/controller/session/node";
import { constants } from "starknet";
import path from "path";
 
export const STRK_CONTRACT_ADDRESS =
  "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7";
 
async function main() {
  const storagePath =
    process.env.CARTRIDGE_STORAGE_PATH ||
    path.join(process.cwd(), ".cartridge");
 
  // Create a session provider with manual policies
  const provider = new SessionProvider({
    rpc: "https://api.cartridge.gg/x/starknet/sepolia",
    chainId: constants.StarknetChainId.SN_SEPOLIA,
    policies: {
      contracts: {
        [STRK_CONTRACT_ADDRESS]: {
          methods: [
            {
              name: "transfer",
              entrypoint: "transfer",
              description: "Transfer STRK",
            },
          ],
        },
      },
    },
    basePath: storagePath,
  });
 
  console.log("Registering a session...");
  console.log("Open the URL printed below to authorize the session.");
 
  try {
    const account = await provider.connect();
    if (!account) {
      console.log("Session not ready yet. Complete the browser flow and rerun.");
      return;
    }
 
    console.log("Session ready!");
    console.log("Account address:", account.address);
 
    // Example: Transfer STRK  
    const recipient = account.address; // Self transfer for demo
    const amount = "0x0"; // Keep it minimal for a demo
 
    const result = await account.execute([
      {
        contractAddress: STRK_CONTRACT_ADDRESS,
        entrypoint: "transfer",
        calldata: [recipient, amount, "0x0"],
      },
    ]);
 
    console.log("Transaction hash:", result.transaction_hash);
  } catch (error: unknown) {
    const controllerError = error as ControllerError;
    if (controllerError?.code) {
      console.error("Execute error:", {
        code: controllerError.code,
        message: controllerError.message,
        data: controllerError.data,
      });
    } else {
      console.error("Execute error:", error);
    }
  }
}
 
main().catch(console.error);

Important Notes

  1. The basePath parameter specifies where session data will be stored. Make sure the directory is writable.

  2. When running the application for the first time, you'll need to complete the session creation in your browser. The application will provide instructions.

  3. Session data is persisted between runs, so you don't need to create a new session each time.

  4. The example includes proper error handling for Controller-specific errors, which include additional context through the code and data fields.

  5. Keep your RPC endpoints and contract addresses secure, preferably in environment variables.