Introduction

Motivation

The Braavos session keys feature empowers dApp developers by enabling them to request permissions to execute transactions on behalf of users without requiring repeated signing prompts. This feature also enables backend-based, gas-sponsored transaction execution at a later time, offering significant flexibility and usability enhancements.

All session key transactions submitted by dApps undergo validation by the Braavos account, ensuring compliance with the user-granted permissions.

Use Case

Session keys unlock a wide array of Web3 use cases, including:

  1. Seamless Web3 in-game interactions, uninterrupted by signing requests.
  2. Streamlined recurring payments and subscription services.
  3. Automatic liquidity provisioning.
  4. Yield farming automation.
  5. Algorithmic investment bots.
  6. And many more.

Session Types

Gas Sponsored Sessions

Gas-sponsored sessions enable transactions to be submitted and paid for by a dedicated account controlled by the dApp. This concept is aligned with SNIP-9 Outside Execution but provides additional flexibility.

To initiate a gas-sponsored session, the dApp requests the wallet to sign a gas-sponsored session request. This request outlines the permissions being sought and is comprised by the following elements:

  1. Execute After and Execute Before: Define the session’s active timeframe. Transactions cannot be submitted before or after these boundaries.
  2. Caller: Specifies the address of the dApp account authorized to submit transactions for the session.
  3. Allowed Methods: Lists the contract addresses and entry points the Caller is permitted to invoke.
  4. Spending Limits: Lists the tokens and associated spending limits, preventing overspending beyond user-defined limits.

Account Sessions

Account sessions allow transactions to be submitted by the dApp and paid for directly by the user’s account. The dApp stores the required session parameters in the browser and is able to send transactions without prompting the user for signatures.

When requesting account session permissions, the wallet prompts the user to sign a request, similar to a gas-sponsored session request, with these notable differences:

  1. Since the transactions are submitted by the user’s account, the Caller field is not applicable. Instead, a temporary in-browser key is employed for signing transactions. The associated NPM package simplifies key management, abstracting it away from dApp developers.
  2. A gas limit must be included in the session request, as the account covers transaction costs.

Interacting With Sessions

Installing

To start a session in your dApp, install the NPM package in your environment:

npm install starknet-sessions --add

or

yarn add starknet-sessions

The package repository is here. And a sample dApp can be viewed here with its repo here.

Start a Gas Sponsored Session

To start a gas sponsored session a dApp must request the wallet to sign a gas sponsored session request by calling signGasSponsoredSessionRequest :

signGasSponsoredSessionRequest = async (
    account: AccountInterface,
    request: GasSponsoredSessionSignatureRequest
): Promise<Signature>;

Where account is the connected wallet account and the type GasSponsoredSessionSignatureRequest contains the following properties:

type GasSponsoredSessionSignatureRequest = {
    callerAddress: string;
    executeAfter: Date;
    executeBefore: Date;
    requestedMethods: RequestedMethod[];
    spendingLimits: SpendingLimit[];
};

type RequestedMethod = {
    contractAddress: string;
    entrypoint: string;
};

type SpendingLimit = {
    tokenAddress: string;
    amount: Uint256;
};

Once a Signature is obtained, it should be communicated to the server that will be executing the session transactions. To craft the gas sponsored session transaction the server should use the following function:

getGasSponsoredSessionTx = async (
    request: GasSponsoredSessionTransactionRequest
): Promise<Call>;

Where GasSponsoredSessionTransactionRequest is the following type:

type GasSponsoredSessionTransactionRequest = {
    callerAddress: string;
    executeAfter: Date;
    executeBefore: Date;
    requestedMethods: RequestedMethod[];
    spendingLimits: SpendingLimit[];
    sessionAccountAddress: string;
    calls: Call[];
    gsSessionSignature: Signature;
};

The calls array should contain the calls to execute and gsSessionSignature should be the obtained signature

Start an Account Session

To start a gas sponsored session a dApp must request the wallet to sign a gas sponsored session request by calling requestSessionAccount :

requestSessionAccount = async (
    provider: ProviderInterface,
    account: AccountInterface,
    request: SessionAccountRequest
): Promise<SessionAccount>;

Where SessionAccountRequest contains the following properties:

type SessionAccountRequest = {
    executeAfter: Date;
    executeBefore: Date;
    requestedMethods: RequestedMethod[];
    spendingLimits: SpendingLimit[];
    strkGasLimit: u128;
}

This function returns an account object which can be used to execute transactions on behalf of the user account.

Example: Session Key Based Trading Bot

To implement a backend based algorithmic trading bot, developers must first request a user's permission to execute transactions on their behalf. In this example, the bot needs permission to swap ETH and STRK back and forth on AVNU. The bot's frontend would ask the user to sign an object that allows it to call multi_route_swap on AVNU's contract address and approve for both ETH and STRK. The spending limit array restricts the amount of ETH approved to 0.01 ETH.

import { signGasSponsoredSessionRequest } from "starknet-sessions";
const sessionGSRequest = {
    callerAddress: "0x01bf914fef319eb1cc2769100f817fbbdd99be01b1e20daa45ab031dee3ef14b",
    sessionAccountAddress: userAddress,
    executeAfter: new Date(1732122979),
    executeBefore: new Date(1756299408),
    requestedMethods: [
        {
            contractAddress:
                "0x04270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f",
            entrypoint: "multi_route_swap",
        },
        {
            contractAddress:
                "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7",
            entrypoint: "approve",
        },
        {
            contractAddress:
                "0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d",
            entrypoint: "approve",
        },
    ],
    spendingLimits: [
        {
            tokenAddress:
                "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7",
            amount: { low: 10000000000000000, high: 0 },
        },
    ],
};
const wallet = await getStarknet().getLastConnectedWallet();
if (wallet?.isConnected) {
    signature = await signGasSponsoredSessionRequest(
        wallet.account,
        sessionGSRequest
    );
}

Once signed, the frontend transmits the signature and session request details to the backend.

To execute a swap, the trading bot can use the library's getGasSponsoredSessionTx function to craft a call that its account can execute.

import { getGasSponsoredSessionTx } from "starknet-sessions";
const res = await getGasSponsoredSessionTx({
    calls: [
        {
            contractAddress:
                "0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d",
            entrypoint: "approve",
            calldata: [
                "0x01bf914fef319eb1cc2769100f817fbbdd99be01b1e20daa45ab031dee3ef14b",
                100000000000000,
                0,
            ],
        },
        {
            contractAddress:
                "0x04270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f",
            entrypoint: "multi_route_swap",
            calldata: [...],
        },
    ],
    ...sessionGSRequest,
    gsSessionSignature: signature,
});
const txres = await botAccount.execute(res);

FAQ

  1. What transaction types are allowed when executing account session transactions? Account session transactions must be V3 transactions. This means that a session user account must have a STRK balance to cover fees. This doesn’t affect gas sponsored transaction execution because they are initiated by the server’s account.
  2. Is the solution self-custodial? Yes, the contract's code validates session transactions.
  3. How can a user revoke a session after signing? Users may revoke a session directly through their wallet interface.