Skip to main content
Smart Sessions allow accounts to delegate specific permissions to other signers with fine-grained control over what actions they can perform.

toSmartSessionsModule

Create a Smart Sessions validator module.
import { toSmartSessionsModule } from "@biconomy/abstractjs";

const sessionsModule = toSmartSessionsModule(options);

Parameters

ParameterTypeRequiredDescription
signerAccountYesThe session signer

Example

import { toSmartSessionsModule } from "@biconomy/abstractjs";
import { privateKeyToAccount } from "viem/accounts";

const sessionSigner = privateKeyToAccount("0x...");

const sessionsModule = toSmartSessionsModule({
  signer: sessionSigner
});

meeSessionActions

Extend the MEE client with session-related methods.
import { meeSessionActions } from "@biconomy/abstractjs";

const sessionClient = meeClient.extend(meeSessionActions);

Added Methods

  • prepareForPermissions
  • grantPermissionTypedDataSign
  • grantPermissionPersonalSign
  • usePermission
  • isPermissionEnabled
  • checkEnabledPermissions

prepareForPermissions

Deploy accounts and install Smart Sessions module.
const payload = await sessionClient.prepareForPermissions(options);

Parameters

ParameterTypeRequiredDescription
smartSessionsValidatorSessionsModuleYesSessions module
feeTokenFeeTokenInfoYesGas payment token
triggerTriggerNoFunding trigger

Example

const payload = await sessionClient.prepareForPermissions({
  smartSessionsValidator: sessionsModule,
  feeToken: { address: USDC, chainId: 8453 },
  trigger: {
    tokenAddress: USDC,
    chainId: 8453,
    amount: parseUnits("10", 6)
  }
});

if (payload) {
  await meeClient.waitForSupertransactionReceipt({ hash: payload.hash });
}

grantPermissionTypedDataSign

Grant permissions using EIP-712 typed data signature.
const sessionDetails = await sessionClient.grantPermissionTypedDataSign(options);

Parameters

ParameterTypeRequiredDescription
redeemerAddressYesSession signer address
feeTokenFeeTokenInfoYesGas payment token
actionsActionConfig[]YesAllowed actions
maxPaymentAmountbigintNoMax gas payment

ActionConfig

PropertyTypeDescription
chainIdnumberChain where permission applies
actionTargetAddressContract address
actionTargetSelectorHexFunction selector
actionPoliciesPolicy[]Policies to apply

Example

import { toFunctionSelector, getAbiItem } from "viem";

const sessionDetails = await sessionClient.grantPermissionTypedDataSign({
  redeemer: sessionSigner.address,
  feeToken: { address: USDC, chainId: 8453 },
  actions: [
    {
      chainId: 8453,
      actionTarget: CounterContract,
      actionTargetSelector: toFunctionSelector(
        getAbiItem({ abi: CounterAbi, name: "increment" })
      ),
      actionPolicies: [getSudoPolicy()]
    }
  ],
  maxPaymentAmount: parseUnits("2", 6)
});

usePermission

Execute instructions using granted permissions.
const result = await sessionClient.usePermission(options);

Parameters

ParameterTypeRequiredDescription
sessionDetailsSessionDetailsYesFrom grantPermission
mode"ENABLE_AND_USE" | "USE"YesExecution mode
feeTokenFeeTokenInfoYesGas payment token
instructionsInstruction[]YesInstructions to execute
sponsorshipbooleanNoEnable sponsorship
verificationGasLimitbigintNoCustom gas limit

Example

const result = await sessionClient.usePermission({
  sessionDetails,
  mode: "ENABLE_AND_USE",
  feeToken: { address: USDC, chainId: 8453 },
  instructions: [
    {
      chainId: 8453,
      calls: [{ to: CounterContract, data: "0x..." }]
    }
  ]
});

await meeClient.waitForSupertransactionReceipt({ hash: result.hash });

Policies

getSudoPolicy

Grants unlimited permissions for specified functions.
import { getSudoPolicy } from "@biconomy/abstractjs";

actionPolicies: [getSudoPolicy()]
Use with caution—provides highest level of access.

getUniversalActionPolicy

Fine-grained parameter-level control.
import { getUniversalActionPolicy, ParamCondition } from "@biconomy/abstractjs";

const policy = getUniversalActionPolicy({
  valueLimitPerUse: maxUint256,
  paramRules: {
    length: 2n,
    rules: [
      {
        condition: ParamCondition.EQUAL,
        isLimited: false,
        offset: 0n,
        ref: pad(recipientAddress),
        usage: { limit: 0n, used: 0n }
      },
      {
        condition: ParamCondition.LESS_THAN_OR_EQUAL,
        isLimited: true,
        offset: 32n,
        ref: pad(toHex(parseUnits("100", 6))),
        usage: { limit: parseUnits("1000", 6), used: 0n }
      }
    ]
  }
});

ParamCondition

ValueDescription
EQUALExact match
GREATER_THANValue > reference
LESS_THANValue < reference
GREATER_THAN_OR_EQUALValue ≥ reference
LESS_THAN_OR_EQUALValue ≤ reference
NOT_EQUALValue ≠ reference

Time-Based Permissions

const sessionDetails = await sessionClient.grantPermissionTypedDataSign({
  redeemer: sessionSigner.address,
  feeToken,
  sessionValidAfter: Math.floor(Date.now() / 1000),
  sessionValidUntil: Math.floor(Date.now() / 1000) + 7 * 24 * 60 * 60,  // 7 days
  actions: [...]
});

Check Permission Status

isPermissionEnabled

const isEnabled = await sessionClient.isPermissionEnabled({
  permissionId: permission.permissionId,
  chainId: 8453
});

checkEnabledPermissions

const enabledMap = await sessionClient.checkEnabledPermissions(sessionDetails);
// Returns: { [permissionId]: { [chainId]: boolean } }

Complete Flow

// 1. Setup
const sessionSigner = privateKeyToAccount("0x...");
const sessionsModule = toSmartSessionsModule({ signer: sessionSigner });
const sessionClient = meeClient.extend(meeSessionActions);

// 2. Prepare (deploy + install module)
await sessionClient.prepareForPermissions({
  smartSessionsValidator: sessionsModule,
  feeToken,
  trigger
});

// 3. Grant permissions
const sessionDetails = await sessionClient.grantPermissionTypedDataSign({
  redeemer: sessionSigner.address,
  feeToken,
  actions: [{ chainId: 8453, actionTarget: contract, actionTargetSelector, actionPolicies: [getSudoPolicy()] }]
});

// 4. Use permissions (from session signer)
const result = await dappSessionClient.usePermission({
  sessionDetails,
  mode: "ENABLE_AND_USE",
  feeToken,
  instructions: [...]
});