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.
A new Smart Sessions SDK flow is now available with improved features and recommended best practices. We encourage all developers to migrate to the new smart sessions flow.See the updated documentation here: Smart Sessions Reference

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
Legacy prepareForPermissions is documented with the minimal parameter set above. For extended options (e.g. redeemer, actions, maxPaymentAmount, or payloads that include sessionDetails), use the new flow: getSessionQuote with mode: 'PREPARE'.

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
When sessionDetails were obtained from prepareForPermissions (not from grantPermissionTypedDataSign / grantPermissionPersonalSign), use mode USE only. Using ENABLE_AND_USE in that case will throw.

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

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: [...]
});