How Do Braavos Session Keys Simplify Web3 Transactions?
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:
- Seamless Web3 in-game interactions, uninterrupted by signing requests.
- Streamlined recurring payments and subscription services.
- Automatic liquidity provisioning.
- Yield farming automation.
- Algorithmic investment bots.
- 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:
Execute After
andExecute Before
: Define the session’s active timeframe. Transactions cannot be submitted before or after these boundaries.Caller
: Specifies the address of the dApp account authorized to submit transactions for the session.Allowed Methods
: Lists the contract addresses and entry points theCaller
is permitted to invoke.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:
- 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. - 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
- 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. - Is the solution self-custodial? Yes, the contract’s code validates session transactions.
- How can a user revoke a session after signing? Users may revoke a session directly through their wallet interface.