Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

useGrantPermissions

Hook to grant permissions to a spender address, enabling session keys, subscriptions, and automated transactions.

Type: hook

Import

import { useGrantPermissions } from '@jaw.id/wagmi';

Signature

function useGrantPermissions(parameters?: {
  config?: Config;
  mutation?: UseMutationParameters;
}): UseMutationResult

Parameters

config

Type: Config (optional)

Wagmi config. If not provided, uses the config from WagmiProvider.

mutation

Type: UseMutationParameters (optional)

TanStack React Query mutation options.

Returns

Returns a TanStack React Query mutation result:

PropertyTypeDescription
mutatefunctionFunction to grant permissions
mutateAsyncfunctionAsync version of mutate
dataWalletGrantPermissionsResponseGranted permission details
isPendingbooleanWhether granting is in progress
isSuccessbooleanWhether granting succeeded
isErrorbooleanWhether granting failed
errorErrorError if granting failed

data

When successful, data contains:

interface WalletGrantPermissionsResponse {
  /** Smart account this permission is valid for */
  account: Address;
  /** Entity that can use this permission */
  spender: Address;
  /** Timestamp when permission becomes valid */
  start: number;
  /** Timestamp when permission expires */
  end: number;
  /** Salt for uniqueness */
  salt: Hex;
  /** Array of call permissions */
  calls: CallPermissionDetail[];
  /** Array of spend permissions */
  spends: SpendPermissionDetail[];
  /** Permission identifier (hash) */
  permissionId: Hex;
  /** Chain ID in hex */
  chainId: Hex;
}

Mutation Variables

When calling mutate(), pass an object with the following properties:

expiry (required)

Type: number

Unix timestamp (in seconds) when the permission expires. The permission becomes invalid after this time.

// Permission valid for 1 week
const expiry = Math.floor(Date.now() / 1000) + 86400 * 7;

spender (required)

Type: Address

The address that will be granted permission to execute calls on behalf of the account. This is typically:

  • A session key address
  • A backend service address
  • An automation bot address
const spender = '0x1234...'; // The address that can use this permission

permissions (required)

Type: PermissionsDetail

The permissions to grant. Contains two optional arrays: calls (what functions can be called) and spends (token spending limits).

interface PermissionsDetail {
  /** Call permissions - which contracts and functions can be called */
  calls?: CallPermissionDetail[];
  /** Spend permissions - token spending limits */
  spends?: SpendPermissionDetail[];
}

permissions.calls

Type: CallPermissionDetail[] (optional)

Array of call permissions specifying which contract functions the spender can call.

interface CallPermissionDetail {
  /** Target contract address */
  target: Address;
  /** Function selector (4 bytes hex). Optional if functionSignature is provided. */
  selector?: Hex;
  /** Human-readable function signature. Selector is computed from this if not provided. */
  functionSignature?: string;
}
FieldTypeRequiredDescription
targetAddressYesContract address the spender can call
selectorHexNo*4-byte function selector (e.g., '0xa9059cbb')
functionSignaturestringNo*Human-readable signature (e.g., 'transfer(address,uint256)')

*Either selector or functionSignature must be provided.

permissions.spends

Type: SpendPermissionDetail[] (optional)

Array of spend permissions specifying token spending limits per time period.

interface SpendPermissionDetail {
  /** Token address. Use NATIVE_TOKEN constant for ETH. */
  token: Address;
  /** Maximum amount per period (in wei, as string) */
  allowance: string;
  /** Time period unit for the limit */
  unit: 'minute' | 'hour' | 'day' | 'week' | 'month' | 'year' | 'forever';
  /** Multiplier for the period (1-255). Defaults to 1. */
  multiplier?: number;
}
FieldTypeRequiredDescription
tokenAddressYesToken contract address. Use 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE for native ETH.
allowancestringYesMaximum spend amount per period in wei (as string, supports large numbers)
unitSpendPeriodYesTime period: 'minute', 'hour', 'day', 'week', 'month', 'year', or 'forever'
multipliernumberNoPeriod multiplier (1-255). E.g., unit: 'day', multiplier: 3 = every 3 days. Defaults to 1.

address (optional)

Type: Address

Specific account address to grant permissions for. Defaults to the connected account.

chainId (optional)

Type: number

Target chain ID. Defaults to the connected chain.

connector (optional)

Type: Connector

Specific connector to use. Defaults to the active connector.

Examples

Basic Usage - Allow Token Transfers

import { useGrantPermissions } from '@jaw.id/wagmi';
import { parseUnits } from 'viem';
 
const USDC = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48';
 
function GrantPermissionButton() {
  const { mutate: grant, isPending, data } = useGrantPermissions();
 
  const handleGrant = () => {
    grant({
      expiry: Math.floor(Date.now() / 1000) + 86400 * 7, // 1 week
      spender: '0xYourBackendService...',
      permissions: {
        calls: [
          {
            target: USDC,
            functionSignature: 'transfer(address,uint256)',
          },
        ],
        spends: [
          {
            token: USDC,
            allowance: parseUnits('100', 6).toString(), // 100 USDC
            unit: 'day',
          },
        ],
      },
    });
  };
 
  return (
    <div>
      <button onClick={handleGrant} disabled={isPending}>
        {isPending ? 'Granting...' : 'Grant Permission'}
      </button>
      {data && <p>Permission ID: {data.permissionId}</p>}
    </div>
  );
}

Subscription Service - Monthly Limit

import { useGrantPermissions } from '@jaw.id/wagmi';
import { parseUnits } from 'viem';
 
function SubscriptionButton() {
  const { mutate: grant, isPending } = useGrantPermissions();
 
  const handleSubscribe = () => {
    grant({
      expiry: Math.floor(Date.now() / 1000) + 86400 * 365, // 1 year
      spender: '0xSubscriptionService...',
      permissions: {
        calls: [
          {
            target: USDC_ADDRESS,
            functionSignature: 'transfer(address,uint256)',
          },
        ],
        spends: [
          {
            token: USDC_ADDRESS,
            allowance: parseUnits('9.99', 6).toString(), // $9.99/month
            unit: 'month',
          },
        ],
      },
    });
  };
 
  return (
    <button onClick={handleSubscribe} disabled={isPending}>
      Subscribe for $9.99/month
    </button>
  );
}

DeFi Automation - Swap Permission

import { useGrantPermissions } from '@jaw.id/wagmi';
 
const UNISWAP_ROUTER = '0x...';
 
function AutomatedTradingSetup() {
  const { mutate: grant, isPending } = useGrantPermissions();
 
  const handleSetup = () => {
    grant({
      expiry: Math.floor(Date.now() / 1000) + 86400 * 30, // 30 days
      spender: '0xTradingBot...',
      permissions: {
        calls: [
          {
            target: UNISWAP_ROUTER,
            functionSignature: 'swapExactTokensForTokens(uint256,uint256,address[],address,uint256)',
          },
          {
            target: UNISWAP_ROUTER,
            functionSignature: 'swapTokensForExactTokens(uint256,uint256,address[],address,uint256)',
          },
        ],
        spends: [
          {
            token: USDC_ADDRESS,
            allowance: parseUnits('1000', 6).toString(), // 1000 USDC per week
            unit: 'week',
          },
          {
            token: WETH_ADDRESS,
            allowance: parseUnits('0.5', 18).toString(), // 0.5 WETH per week
            unit: 'week',
          },
        ],
      },
    });
  };
 
  return (
    <button onClick={handleSetup} disabled={isPending}>
      Enable Automated Trading
    </button>
  );
}

Native ETH Spending Limit

import { useGrantPermissions } from '@jaw.id/wagmi';
import { parseEther } from 'viem';
 
const NATIVE_TOKEN = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE';
 
function NativeSpendingLimit() {
  const { mutate: grant, isPending } = useGrantPermissions();
 
  const handleGrant = () => {
    grant({
      expiry: Math.floor(Date.now() / 1000) + 86400 * 7,
      spender: '0xGamingContract...',
      permissions: {
        spends: [
          {
            token: NATIVE_TOKEN,
            allowance: parseEther('0.1').toString(), // 0.1 ETH per day
            unit: 'day',
          },
        ],
      },
    });
  };
 
  return (
    <button onClick={handleGrant} disabled={isPending}>
      Allow 0.1 ETH/day for Gaming
    </button>
  );
}

With Period Multiplier

// Allow 500 USDC every 2 weeks
grant({
  expiry: Math.floor(Date.now() / 1000) + 86400 * 90, // 90 days
  spender: '0xPayrollService...',
  permissions: {
    spends: [
      {
        token: USDC_ADDRESS,
        allowance: parseUnits('500', 6).toString(),
        unit: 'week',
        multiplier: 2, // Every 2 weeks
      },
    ],
  },
});

With Callbacks

import { useGrantPermissions } from '@jaw.id/wagmi';
 
function GrantWithCallbacks() {
  const { mutate: grant } = useGrantPermissions({
    mutation: {
      onSuccess: (data) => {
        console.log('Permission granted:', data.permissionId);
        // Store permission ID for later revocation
        savePermissionId(data.permissionId);
      },
      onError: (error) => {
        console.error('Failed to grant permission:', error);
      },
    },
  });
 
  // ...
}

Use Cases

  • Session Keys - Allow a temporary key to perform specific actions without full wallet access
  • Subscription Services - Grant recurring spending permissions for SaaS, content, or services
  • Automated Trading - Allow a bot to execute specific trades within spending limits
  • Gaming - Let a game contract execute moves without transaction prompts
  • DeFi Automation - Enable auto-compounding, limit orders, or rebalancing
  • Payroll - Allow scheduled payments to employees

Related