> ## Documentation Index
> Fetch the complete documentation index at: https://docs.biconomy.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Smart Sessions

> Delegate permissions to session signers

## Smart Sessions

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

Enabling and using a permission with Smart Sessions is a two-step process involving setup and actual usage:

### 1. Enable Permission

The initial setup phase involves several key operations to prepare your account for session-based permissions:

* **Deploy the SCA** (if it does not exist yet).
* **Fund the SCA** to ensure gas costs or funding for your DeFi needs.
* **Bridge Funds, Unwind Positions or etc** as part of initial setup by passing extra instructions via the `instructions` array.
* **Install the Smart Sessions Module** into the SCA, ensuring the account is capable of session management.
* **Enable one or more permissions**: Define specific actions and their allowed signers.

### 2. Use Permission

Once a permission is enabled, a valid session signer is now authorized to perform the allowed actions.

* The session signer can initiate actions *within the allowed scope* (such as contract calls, swaps, mints, etc.).
* Calls made by the session signer are validated against the permission rules applied in the previous step.

## Prepare and enable permissions

Deploy accounts, fund accounts, install Smart Sessions module, and enable permissions.

```typescript theme={null}
const quote = await meeClient.getSessionQuote({ mode: 'PREPARE', ...options });
```

### Parameters

| Parameter                      | Type                | Required | Description                                      |
| ------------------------------ | ------------------- | -------- | ------------------------------------------------ |
| `mode`                         | `"PREPARE"`         | Yes      | Prepare or use a permission.                     |
| `enableSession`                | `EnableSession`     | No       | Options to enable a session.                     |
| `smartSessionValidatorAddress` | `Address`           | No       | Address of the Smart Session validator to use.   |
| `instructions`                 | `Instruction[]`     | No       | Array of composable instructions to be executed. |
| `feeToken`                     | `FeeTokenInfo`      | Yes\*    | Token used for gas payment.                      |
| `sponsorship`                  | `boolean`           | No       | Enable or disable gas sponsorship.               |
| `delegate`                     | `boolean`           | No       | Enable EIP-7702 delegate mode.                   |
| `authorization`                | `Authorization`     | No       | EIP-7702 authorization configuration.            |
| `lowerBoundTimestamp`          | `number`            | No       | Earliest allowed execution timestamp.            |
| `upperBoundTimestamp`          | `number`            | No       | Latest allowed execution timestamp.              |
| `cleanUps`                     | `CleanUp[]`         | No       | List of cleanup instructions.                    |
| `simulation`                   | `SimulationOptions` | No       | Simulation config.                               |

### EnableSession

| Property           | Type              | Required | Description                                     |
| ------------------ | ----------------- | -------- | ----------------------------------------------- |
| `redeemer`         | `Address`         | Yes      | Address of the session signer.                  |
| `actions`          | `SessionAction[]` | Yes      | Allowed actions within this session.            |
| `batchActions`     | `boolean`         | No       | Whether to allow batching of actions.           |
| `maxPaymentAmount` | `bigint`          | No       | Maximum payment amount allowed for the session. |

<Info>
  **Payment policy and fee token:** When the session token (e.g. the token used in spending limits or transfer actions) is the same as `feeToken`, the SDK merges those policies with the payment policy—the effective spending limit is increased by `maxPaymentAmount` and no duplicate payment action is added.
</Info>

### SessionAction

| **Property** | **Type**       | **Required** | **Description**                                      |
| ------------ | -------------- | ------------ | ---------------------------------------------------- |
| `actions`    | `ActionData[]` | Yes          | Specific action configurations (see **ActionData**). |
| `chainId`    | `number`       | Yes          | Chain ID where the permission is valid.              |

### ActionData

| Property               | Type       | Required | Description                                                      |
| ---------------------- | ---------- | -------- | ---------------------------------------------------------------- |
| `actionTarget`         | `Address`  | Yes      | Target contract address for this action.                         |
| `actionTargetSelector` | `Hex`      | Yes      | Function selector (4-byte signature) for the contract method.    |
| `actionPolicies`       | `Policy[]` | No       | List of policies defining rules and restrictions on this action. |

### Example

```typescript theme={null}
const quote = await meeClient.getSessionQuote({
  mode: "PREPARE",
  enableSession: {
    redeemer: sessionSigner.address,
    actions,
  },
  simulation: { simulate: true },
  feeToken: { address: USDC, chainId: 8453 },
  trigger: {
    tokenAddress: USDC,
    chainId: 8453,
    amount: parseUnits("2", 6),
  },
});

// Store the sessions details for later use.
let sessionDetails: SessionDetail[] = [];

if (quote) {
  const { hash } = await meeClient.executeSessionQuote(quote);

  await meeClient.waitForSupertransactionReceipt({ hash });

  sessionDetails = quote.sessionDetails;
}
```

***

## Use Permission

Execute instructions using granted permissions.

```typescript theme={null}
const quote = await meeClient.getSessionQuote({ mode: 'USE', ...options });
```

### Parameters

| Parameter             | Type                | Required | Description                                 |
| --------------------- | ------------------- | -------- | ------------------------------------------- |
| `mode`                | `"USE"`             | Yes      | Prepare or use a permission.                |
| `sessionDetails`      | `SessionDetails`    | Yes      | Session information for enabled permissions |
| `instructions`        | `Instruction[]`     | No       | Array of instructions to be executed.       |
| `feeToken`            | `FeeTokenInfo`      | Yes\*    | Token used for gas payment.                 |
| `sponsorship`         | `boolean`           | No       | Enable or disable gas sponsorship.          |
| `delegate`            | `boolean`           | No       | Enable EIP-7702 delegate mode.              |
| `authorization`       | `Authorization`     | No       | EIP-7702 authorization configuration.       |
| `lowerBoundTimestamp` | `number`            | No       | Earliest allowed execution timestamp.       |
| `upperBoundTimestamp` | `number`            | No       | Latest allowed execution timestamp.         |
| `simulation`          | `SimulationOptions` | No       | Simulation config.                          |

### Example

```typescript theme={null}
const quote = await meeClient.getSessionQuote({
  mode: "USE",
  sessionDetails,
  simulation: { simulate: true },
  feeToken: { address: USDC, chainId: 8453 },
  instructions: [
    {
      chainId: 8453,
      calls: [{ to: CounterContract, data: "0x..." }]
    }
  ]
});

const { hash } = await meeClient.executeSessionQuote(quote);

await meeClient.waitForSupertransactionReceipt({ hash });
```

***

## Policies

### Sudo Policy

Grants unlimited permissions for specified functions.

```typescript theme={null}
const sudoPolicy = mcNexus.buildActionPolicy({ type: "sudo" })
```

<Warning>
  Use with caution, provides highest level of access.
</Warning>

***

### Universal Policy

Fine-grained parameter-level control.

```typescript theme={null}
const universalPolicy = mcNexus.buildActionPolicy({
  type: "universal",
  rules: [
    {
      condition: "equal",
      calldataOffset: calldataArgument(2),
      comparisonValue: parseUnits("10", 6),
      isLimited: false,
      usage: { limit: 0n, used: 0n }
    }
  ],
  // Configure spending limit for native token
  valueLimitPerUse: 1n
});
```

Use **`calldataArgument(n)`** to specify the calldata offset for the n-th (1-based) function argument—e.g. `calldataArgument(2)` is the second parameter. Import from `@biconomy/abstractjs`.

***

### Timeframe policy

Add fine-grained expirations to the session actions.

```typescript theme={null}
const now = Math.floor(Date.now() / 1000)
const validAfter = now
const validUntil = now + 3600

const timeframePolicy = mcNexus.buildActionPolicy({
  type: "timeframe",
  validAfter, // unix-timestamp when policy becomes active
  validUntil  // unix-timestamp when policy expires
});
```

***

### Spending limit policy

Add spending limits for the token spendings.

```typescript theme={null}
const spendingLimitsPolicy = mcNexus.buildActionPolicy({
  type: "spendingLimits",
  tokenLimits: [{ token: USDC, limit: parseUnits("10", 6) }]
});
```

***

### Usage limit policy

Add usage limits to control the session usage count.

```typescript theme={null}
const usagePolicy = mcNexus.buildActionPolicy({
  type: "usageLimit",
  limit: 5n
});
```

***

## Actions

### Frequently Used Actions

Build approve, transfer, and transferFrom actions for your session

```typescript theme={null}
const actions = mcNexus.buildSessionAction({
  type: "approve" | "transferFrom" | "transfer",
  data: {
    chainIds: [8453, 10],
    contractAddress: USDC,
    recipientAddress: "0x..." // Optional
    amountLimitPerAction: parseUnits("10", 6), // Optional
    maxAmountLimit: parseUnits("10", 6), // Optional
    usageLimit: 10n, // Optional
    validAfter: Math.floor(Date.now() / 1000), // Optional
    validUntil: Math.floor(Date.now() / 1000) + 60 * 60 * 24 // Optional
    // or
    // policies: [] // Define policies on your own. Defaults to sudo policy
  },
});
```

<Info>
  By default, sudo policy will be configured. Configure policies on your own by defining policies
</Info>

***

### Custom Actions

Build custom actions for your session

```typescript theme={null}
const functionSignature = toFunctionSelector(
  getAbiItem({ abi: CounterAbi, name: "incrementCount" })
);

const customActions = mcNexus.buildSessionAction({
  type: "custom",
  data: {
    chainIds: [8453, 10],
    contractAddress: CounterContract,
    functionSignature,
    policies: [{ type: "sudo" }] // Optional
  }
});
```

***

### Custom action batching

By default, all actions are submitted as a single atomic batch when enabling session permissions.
If you encounter issues with block gas limits on certain chains, you can break the actions into multiple smaller batches.

```typescript theme={null}
const actionOne = mcNexus.buildSessionAction({...});
const actionTwo = mcNexus.buildSessionAction({...});

const batchedActions = mcNexus.buildSessionAction({
  type: "batch",
  data: { actions: [...actionOne, ...actionTwo] }
});

const actionThree = mcNexus.buildSessionAction({...});

// Actions can be partially batched
const actions = [...batchedActions, ...actionThree];
```

<Info>
  To enable custom batching, make sure to configure `batchActions: false` in enableSession while preparing the permissions.
</Info>

***

## Check Permission Status

### meeSessionActions

Extend the MEE client with session-related methods.

```typescript theme={null}
import { meeSessionActions } from "@biconomy/abstractjs";

const sessionClient = meeClient.extend(meeSessionActions);
```

The following methods will be extended

* `isPermissionEnabled`
* `checkEnabledPermissions`

***

### isPermissionEnabled

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

### checkEnabledPermissions

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

***

## Complete Flow

```typescript theme={null}
// 1. User account setup
const userSigner = privateKeyToAccount("0x...");
const mcNexus = await toMultichainNexusAccount(options):
const meeClient = await createMeeClient(options);

// 2. Session signer setup
const sessionSigner = privateKeyToAccount("0x...");
const sessionMcNexus = await toMultichainNexusAccount({
  chainConfigurations: [
    {
      // ... other config
      // User McNexus address needs to be overriden here
      accountAddress: mcNexus.addressOn(chainId, true),
    },
    {
      // ... other config
      // User McNexus address needs to be overriden here
      accountAddress: mcNexus.addressOn(chainId, true),
    },
  ],
  signer: sessionSigner,
});
const sessionMeeClient = await createMeeClient(options);

// 3. Build actions for permissions
const functionSignature = toFunctionSelector(
  getAbiItem({ abi: CounterAbi, name: "incrementCount" })
);

const actions = mcNexus.buildSessionAction({
  type: "custom",
  data: {
    chainIds: [8453, 10],
    contractAddress: CounterContract,
    functionSignature
  }
});

// 4. Prepare and enable sessions
const quote = await meeClient.getSessionQuote({
  mode: "PREPARE",
  enableSession: {
    redeemer: sessionSigner.address,
    actions,
  },
  simulation: { simulate: true },
  feeToken: { address: USDC, chainId: 8453 },
  trigger: {
    tokenAddress: USDC,
    chainId: 8453,
    amount: parseUnits("2", 6),
  },
});

// Store the sessions details for later use.
let sessionDetails: SessionDetail[] = [];

if (quote) {
  const { hash } = await meeClient.executeSessionQuote(quote);

  await meeClient.waitForSupertransactionReceipt({ hash });

  if (quote.sessionDetails) sessionDetails = quote.sessionDetails;
}

// 5. Execute transaction on behalf of user via session signer
const quote = await sessionMeeClient.getSessionQuote({
  mode: "USE",
  sessionDetails,
  simulation: { simulate: true },
  feeToken: { address: USDC, chainId: 8453 },
  instructions: [
    {
      chainId: 8453,
      calls: [{ to: CounterContract, data: "0x..." }]
    }
  ]
});

const { hash } = await sessionMeeClient.executeSessionQuote(quote);

await sessionMeeClient.waitForSupertransactionReceipt({ hash });
```
