Skip to content

useGrantPermissions

The useGrantPermissions hook simplifies the creation and authorization of session keys using EIP-7715. Session keys allow you to delegate permissions to specific accounts for a limited time, enabling use cases like gasless transactions and scoped permissions.

Import

import { useGrantPermissions } from '@openfort/openfort-react';

Usage

import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts';
import { useGrantPermissions } from '@openfort/openfort-react';
 
function CreateSessionKey() {
  const { grantPermissions, isLoading, isError, error } = useGrantPermissions({
    onSuccess: (result) => {
      console.log('Session created:', result);
      // Store the session key securely
      localStorage.setItem('sessionKey', result.privateKey);
    },
    onError: (error) => {
      console.error('Failed to create session:', error);
    },
  });
 
  const handleCreateSession = async () => {
    // Generate a new session key
    const sessionKey = generatePrivateKey();
    const accountSession = privateKeyToAccount(sessionKey);
 
    // Grant permissions to the session key
    const result = await grantPermissions({
      sessionKey,
      request: {
        signer: {
          type: 'account',
          data: {
            id: accountSession.address,
          },
        },
        expiry: 60 * 60 * 24, // 24 hours
        permissions: [
          {
            type: 'contract-call',
            data: {
              address: '0x2522f4fc9af2e1954a3d13f7a5b2683a00a4543a',
              calls: [],
            },
            policies: [],
          },
        ],
      },
    });
 
    if (result.address) {
      console.log('Session active for:', result.address);
      console.log('Private key (store securely!):', result.privateKey);
    }
  };
 
  return (
    <div>
      <button onClick={handleCreateSession} disabled={isLoading}>
        {isLoading ? 'Creating Session...' : 'Create Session Key'}
      </button>
      {isError && <p>Error: {error?.message}</p>}
    </div>
  );
}

Parameters

hookOptions

Optional configuration object with callback functions:

PropertyTypeDescription
onSuccess(result: GrantPermissionsResult) => voidCalled when permissions are granted successfully
onError(error: OpenfortError) => voidCalled when the operation fails

grantPermissions Parameters

The grantPermissions function accepts an object with:

PropertyTypeRequiredDescription
sessionKeyHexYesThe private key of the session account
requestGrantPermissionsParametersYesThe permission request configuration (EIP-7715)

Request Object Structure

{
  signer: {
    type: 'account',
    data: {
      id: '0x...', // Session account address
    },
  },
  expiry: number, // Unix timestamp or duration in seconds
  permissions: [
    {
      type: 'contract-call', // or 'native-token-transfer', 'erc20-transfer', etc.
      data: {
        address: '0x...', // Contract address
        calls: [], // Optional: specific function calls to allow
      },
      policies: [], // Optional: additional policies
    },
  ],
}

Return Value

PropertyTypeDescription
grantPermissions(params, options?) => Promise<GrantPermissionsHookResult>Function to grant permissions to a session key
isLoadingbooleanWhether the operation is in progress
isErrorbooleanWhether the last operation failed
isSuccessbooleanWhether the last operation succeeded
errorOpenfortError | undefinedError object if the operation failed

GrantPermissionsResult

The successful result includes:

PropertyTypeDescription
address0x${string}The wallet address that granted permissions
privateKey0x${string}The session key private key
Additional EIP-7715 response fields

Permission Types

The hook supports various permission types defined in EIP-7715:

  • contract-call: Allow calls to specific smart contracts
  • native-token-transfer: Allow native token transfers
  • erc20-transfer: Allow ERC-20 token transfers
  • erc721-transfer: Allow NFT transfers
  • erc1155-transfer: Allow semi-fungible token transfers

Examples

Contract-Specific Permissions

const result = await grantPermissions({
  sessionKey,
  request: {
    signer: {
      type: 'account',
      data: { id: accountSession.address },
    },
    expiry: 60 * 60 * 24, // 24 hours
    permissions: [
      {
        type: 'contract-call',
        data: {
          address: '0x2522f4fc9af2e1954a3d13f7a5b2683a00a4543a',
          calls: [],
        },
        policies: [],
      },
    ],
  },
});

Multiple Permissions

const result = await grantPermissions({
  sessionKey,
  request: {
    signer: {
      type: 'account',
      data: { id: accountSession.address },
    },
    expiry: 60 * 60 * 2, // 2 hours
    permissions: [
      {
        type: 'contract-call',
        data: {
          address: '0x1111111111111111111111111111111111111111',
          calls: [],
        },
        policies: [],
      },
      {
        type: 'erc20-transfer',
        data: {
          address: '0x2222222222222222222222222222222222222222',
          calls: [],
        },
        policies: [],
      },
    ],
  },
});

Using the Session Key

After creating a session key, you can use it to sign transactions:

import { privateKeyToAccount } from 'viem/accounts';
 
// Retrieve the stored session key
const storedSessionKey = localStorage.getItem('sessionKey');
 
if (storedSessionKey) {
  const sessionAccount = privateKeyToAccount(storedSessionKey as `0x${string}`);
  
  // Use the session account to sign transactions
  const signature = await sessionAccount.signMessage({
    message: 'Transaction data',
  });
}

Error Handling

The hook provides comprehensive error handling:

const { grantPermissions, error } = useGrantPermissions({
  onError: (err) => {
    if (err.type === 'WALLET_ERROR') {
      console.error('Wallet connection issue:', err.message);
    } else if (err.type === 'CONFIGURATION_ERROR') {
      console.error('Chain not configured:', err.message);
    }
  },
});

Notes

  • Session keys are stored in-memory on the client. Make sure to persist them securely if needed (e.g., encrypted localStorage).
  • The expiry field can be either a Unix timestamp or a duration in seconds from the current time.
  • Always validate that session keys haven't expired before using them.
  • Session keys can be revoked at any time by the wallet owner.

Related