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
| Parameter | Type | Required | Description |
|---|
signer | Account | Yes | The 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
| Parameter | Type | Required | Description |
|---|
smartSessionsValidator | SessionsModule | Yes | Sessions module |
feeToken | FeeTokenInfo | Yes | Gas payment token |
trigger | Trigger | No | Funding 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
| Parameter | Type | Required | Description |
|---|
redeemer | Address | Yes | Session signer address |
feeToken | FeeTokenInfo | Yes | Gas payment token |
actions | ActionConfig[] | Yes | Allowed actions |
maxPaymentAmount | bigint | No | Max gas payment |
ActionConfig
| Property | Type | Description |
|---|
chainId | number | Chain where permission applies |
actionTarget | Address | Contract address |
actionTargetSelector | Hex | Function selector |
actionPolicies | Policy[] | 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
| Parameter | Type | Required | Description |
|---|
sessionDetails | SessionDetails | Yes | From grantPermission |
mode | "ENABLE_AND_USE" | "USE" | Yes | Execution mode |
feeToken | FeeTokenInfo | Yes | Gas payment token |
instructions | Instruction[] | Yes | Instructions to execute |
sponsorship | boolean | No | Enable sponsorship |
verificationGasLimit | bigint | No | Custom 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
| Value | Description |
|---|
EQUAL | Exact match |
GREATER_THAN | Value > reference |
LESS_THAN | Value < reference |
GREATER_THAN_OR_EQUAL | Value ≥ reference |
LESS_THAN_OR_EQUAL | Value ≤ reference |
NOT_EQUAL | Value ≠ 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: [...]
});