Implement session keys

It is strongly advised to only implement session keys in a project using starknetkit.

1. Installation

npm install @argent/x-sessions

2. Import packages

import {
  SignSessionError,
  CreateSessionParams,
  createSession,
  buildSessionAccount,
  bytesToHexString
} from "@argent/x-sessions"
import { ec } from "starknet"

3. Session Configuration

The dapp will need to create a sessionKey . This is simply a private/public key pair.

const privateKey = ec.starkCurve.utils.randomPrivateKey();
const sessionKey: SessionKey = {
  privateKey, //string
  publicKey: ec.starkCurve.getStarkKey(privateKey), //string
};

Define your session parameters:

const sessionParams: CreateSessionParams = {
  allowedMethods: [{
    "Contract Address": "0x00000...000",
    selector: "do_something"
  }],
  expiry: Math.floor((Date.now() + 1000 * 60 * 60 * 24) / 1000) as any, // 1 day
  sessionKey: sessionKey,
  metaData: {
    projectID: "your-dapp",
    txFees: [{
      tokenAddress: ETHTokenAddress,
      maxAmount: parseUnits("0.1", 18).value.toString()
    }]
  }
}

The allowedMethods params represents which contracts calls the user will authorize the dapp to send on his behalf.

Expiry is a security measure. After the expiry date, the session becomes invalid.

3. Creating a Session

// Compute the typed data to be signed
const sessionRequest = createSessionRequest({
  sessionParams,
  chainId
})

// wallet is a StarknetWindowObject. There are others ways to sign typed data.
// You could use the starknet-react hook useSignTypedData
const authorisationSignature = await wallet.request({
  type: "wallet_signTypedData",
  params: sessionRequest.sessionTypedData
})

// Build session request
const session = await createSession({
  sessionRequest, // SessionRequest
  address, // Account address
  chainId, // StarknetChainId
  authorisationSignature // Signature
})

// Create session account. This is the account that will be used to execute transactions. 
const sessionAccount = await buildSessionAccount({
  useCacheAuthorisation: false, // optional and defaulted to false, will be added in future developments
  session,
  sessionKey,
  provider: new RpcProvider({
    nodeUrl: "<https://starknet-sepolia.public.blastapi.io/rpc/v0_7>",
    chainId: constants.StarknetChainId.SN_SEPOLIA
  }),
  argentSessionServiceBaseUrl: ARGENT_SESSION_SERVICE_BASE_URL // Optional: defaulted to mainnet url. This is basically the backend api. 
})

4. Executing Transactions

try {
  const tx = await sessionAccount.execute({
    contractAddress: "0x...",
    selector: "transfer",
    calldata: ["0x..."]
  })
} catch (e) {
  console.error((e as SignSessionError).cause, e.message)
}

Best Practices

  1. Set appropriate expiry times based on your use case

  2. Limit allowed methods to only necessary functions

  3. Set reasonable token spending limits

  4. Implement proper error handling for session operations

  5. Consider implementing session refresh mechanisms for long-running applications

Last updated