LazorKit LogoLazorKit
SDK (web3.js v1)

Session Keys

Create, use, and revoke session keys with the web3.js v1 SDK.

Session Keys

Session keys let an app or agent execute transactions on behalf of a wallet without passkey re-authentication. See Session Keys concept page for the full protocol explanation.


Create a Session

Ed25519 Admin

import { Keypair, SystemProgram } from '@solana/web3.js';
import { ed25519 } from '@lazorkit/sdk-legacy';

const sessionKp = Keypair.generate();
const slot = await connection.getSlot();

const { instructions, sessionPda } = await client.createSession({
  payer: payer.publicKey,
  walletPda,
  adminSigner: ed25519(ownerKp.publicKey),
  sessionKey: sessionKp.publicKey,
  expiresAt: BigInt(slot) + 216_000n,   // ~1 day
  actions: [
    { type: 'SolMaxPerTx', max: 1_000_000_000n },
    { type: 'SolLimit', remaining: 10_000_000_000n },
    { type: 'ProgramWhitelist', programId: SystemProgram.programId },
  ],
});

expiresAt is a slot number, not a Unix timestamp. Max duration ~30 days.

Passkey Admin (Two-Phase)

const prepared = await client.prepareCreateSession({
  payer: payer.publicKey,
  walletPda,
  secp256r1: { credentialIdHash, publicKeyBytes, authorityPda },
  sessionKey: sessionKp.publicKey,
  expiresAt: BigInt(slot) + 432_000n,
  actions: [
    { type: 'TokenLimit', mint: USDC_MINT, remaining: 1_000_000_000n },
    { type: 'TokenMaxPerTx', mint: USDC_MINT, max: 100_000_000n },
  ],
});

const webauthnResponse = await getWebAuthnResponse(prepared.challenge, rpId, credentialId);
const { instructions, sessionPda } = client.finalizeCreateSession(prepared, webauthnResponse);

Unrestricted Session

Omit actions for a fully open session:

const { instructions, sessionPda } = await client.createSession({
  payer: payer.publicKey,
  walletPda,
  adminSigner: ed25519(ownerKp.publicKey),
  sessionKey: sessionKp.publicKey,
  expiresAt: BigInt(slot) + 9_000n,
});

Execute via Session Key

import { session } from '@lazorkit/sdk-legacy';

const { instructions } = await client.transferSol({
  payer: payer.publicKey,
  walletPda,
  signer: session(sessionPda, sessionKp.publicKey),
  recipient,
  lamports: 500_000_000n,
});

No passkey prompt. The session keypair signs the transaction directly.


Deferred Execution

For large payloads exceeding the ~574 bytes available in a single Secp256r1 Execute (e.g. Jupiter swaps).

TX1 — Authorize

const { instructions: authIx } = await client.prepareAuthorize({
  payer: payer.publicKey,
  walletPda,
  secp256r1: { credentialIdHash, publicKeyBytes, authorityPda },
  instructions: innerInstructions,   // the instructions to pre-authorize
});

const webauthnResponse = await getWebAuthnResponse(prepared.challenge, rpId, credentialId);
const { instructions, deferredExecPda } = client.finalizeAuthorize(prepared, webauthnResponse);

TX2 — ExecuteDeferred

const { instructions } = await client.executeDeferred({
  payer: payer.publicKey,
  walletPda,
  deferredExecPda,
  instructions: innerInstructions,   // must match what was authorized in TX1
});

Reclaim Expired Authorization

If TX2 is never submitted, recover the DeferredExec account rent:

const { instructions } = await client.reclaimDeferred({
  payer: payer.publicKey,
  deferredExecPda,
  refundDestination: payer.publicKey,
});

Only the original payer can reclaim, and only after the deferred account expires.


Revoke a Session

const { instructions } = await client.revokeSession({
  payer: payer.publicKey,
  walletPda,
  adminSigner: ed25519(ownerKp.publicKey),
  sessionPda,
  refundDestination: payer.publicKey,
});

Closes the session PDA and refunds rent. Works on active or already-expired sessions. Only Owner or Admin can revoke.


Action Types Reference

TypeFields
SolLimitremaining: bigint
SolRecurringLimitlimit: bigint, window: bigint
SolMaxPerTxmax: bigint
TokenLimitmint: PublicKey, remaining: bigint
TokenRecurringLimitmint: PublicKey, limit: bigint, window: bigint
TokenMaxPerTxmint: PublicKey, max: bigint
ProgramWhitelistprogramId: PublicKey
ProgramBlacklistprogramId: PublicKey

All SOL/token amounts are in lamports (bigint). Max 16 actions per session.