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.
Session keys unlock a wide array of Web3 use cases, including:
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
and Execute 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 the Caller
is permitted to invoke.Spending Limits
: Lists the tokens and associated spending limits, preventing overspending beyond user-defined limits.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:
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.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.
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
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.
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);
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.