Skip to main content

Smart Sessions

Overview

note

💡 The support for smart-session is included in the Appkit SDK in the experimental package.

Smart Sessions allow developers to easily integrate session-based permission handling within their decentralized applications (dApps). Using the grantPermissions method, can send permission requests to wallets.

This guide will walk you through on how to use the grantPermissions method, including the basic setup and an example of how to request permissions from a wallet.

Implementations

The grantPermissions method provides an easy way to interact with the smart wallet to request permissions.

Step 1 | Install the library

npm install @reown/appkit-experimental

Step 2 | Import the method

First, import the grantPermissions method from the @reown/appkit-experimental/smart-session package.

import { grantPermissions, type SmartSessionGrantPermissionsRequest } from '@reown/appkit-experimental/smart-session'

Step 3 | Define the Permission Request

Create an object adhering to the SmartSessionGrantPermissionsRequest type. This object specifies details like the address, chainID, signer, policies, permissions, and expiry time.

Example request object:

const request: SmartSessionGrantPermissionsRequest = {
expiry: Math.floor(Date.now() / 1000) + 24 * 60 * 60, // 24 hours
chainId: toHex(baseSepolia.id),
address: address,
signer: {
type: 'keys',
data: {
keys :[{
type: 'secp256k1',
publicKey: '0x...' //public key of dapp signer
}]
}
},
permissions: [ {
type: 'contract-call',
data: {
address: '0x2E65BAfA07238666c3b239E94F32DaD3cDD6498D', // sample donut contract address
abi: [
{
inputs: [{ internalType: 'uint256', name: 'amount', type: 'uint256' }],
name: 'purchase',
outputs: [],
stateMutability: 'payable',
type: 'function'
}
],
functions: [ {
functionName: 'purchase'
} ]
}
}],
policies: []
}

Step 4 | Invoke the Method

Call the grantPermissions function, passing the request object. This will trigger the permission request via the connected wallet.

 const response = await grantPermissions(request)

Step 5 | Handle the Response

Upon successful execution, the response will include the granted permissions and the session context. So the response can be handled as needed.

Response Format

{
chainId: `0x14a34`
address: `0x...`
expiry: 1727824386
permissions: [
{
type: 'contract-call',
data: {
address: '0x2E65BAfA07238666c3b239E94F32DaD3cDD6498D', // sample donut contract address
abi: [
{
inputs: [{ internalType: 'uint256', name: 'amount', type: 'uint256' }],
name: 'purchase',
outputs: [],
stateMutability: 'payable',
type: 'function'
}
],
functions: [ {
functionName: 'purchase'
} ]
}
}
],
context: '...' // Context identifier for the session
}

How to use the permissions

The dApp must call the following two endpoints from the wallet services API to use these permissions.

  1. https://rpc.walletconnect.org/v1/wallets/prepareCalls - Accepts an EIP-5792 wallet_sendCalls request. Responds with the prepared calls (in the case of Appkit Embedded Wallet, an Entrypoint v0.7 user operation), some context, and a signature request.
  2. https://rpc.walletconnect.org/v1/wallets/sendPreparedCalls - Accepts prepared calls, a signature, and the context returned from prepareCalls if present. Returns an EIP-5792 calls ID.

Steps to follow for executing any async action by the dApp backend.

  1. Dapp makes the wallet_prepareCalls JSON RPC call to the wallet service API. Accepts an EIP-5792 wallet_sendCalls request, and returns the prepared calls according to the account's implementation.

    Parameter

    type PrepareCallsParams = [{
    from: `0x${string}`
    chainId: `0x${string}`
    calls: {
    to: `0x${string}`
    data: `0x${string}`
    value: `0x${string}`
    }[];
    capabilities: Record<string, any>
    }]

    Return value

    type PrepareCallsReturnValue = [{
    preparedCalls: {
    type: string
    data: any
    chainId: `0x${string}`
    }
    signatureRequest: {
    hash: `0x${string}`
    }
    context: `0x${string}`
    }]
  2. App developers are expected to Sign the signatureRequest.hash returned from wallet_prepareCalls call using the dApp key (secp256k1 or secp256r1)

  3. dApps makes the wallet_sendPreparedCalls JSON RPC call to wallet service API. The RPC accepts the prepared response from wallet_prepareCalls request along with a signature, and returns an EIP-5792 call bundle ID.

Reference

Currently supported Permission types

ContractCallPermission

export enum ParamOperator {
EQUAL = 'EQUAL',
GREATER_THAN = 'GREATER_THAN',
LESS_THAN = 'LESS_THAN'
}

export enum Operation {
Call = 'Call',
DelegateCall = 'DelegateCall'
}

export type ArgumentCondition = {
operator: ParamOperator
value: `0x${string}`
}

export type FunctionPermission = {
functionName: string
args?: ArgumentCondition[]
valueLimit?: `0x${string}`
operation?: Operation
}
export type ContractCallPermission = {
type: 'contract-call'
data: {
address: `0x${string}`
abi: Record<string, unknown>[]
functions: FunctionPermission[]
}
}