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:
| Property | Type | Description |
|---|---|---|
onSuccess | (result: GrantPermissionsResult) => void | Called when permissions are granted successfully |
onError | (error: OpenfortError) => void | Called when the operation fails |
grantPermissions Parameters
The grantPermissions function accepts an object with:
| Property | Type | Required | Description |
|---|---|---|---|
sessionKey | Hex | Yes | The private key of the session account |
request | GrantPermissionsParameters | Yes | The 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
| Property | Type | Description |
|---|---|---|
grantPermissions | (params, options?) => Promise<GrantPermissionsHookResult> | Function to grant permissions to a session key |
isLoading | boolean | Whether the operation is in progress |
isError | boolean | Whether the last operation failed |
isSuccess | boolean | Whether the last operation succeeded |
error | OpenfortError | undefined | Error object if the operation failed |
GrantPermissionsResult
The successful result includes:
| Property | Type | Description |
|---|---|---|
address | 0x${string} | The wallet address that granted permissions |
privateKey | 0x${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 contractsnative-token-transfer: Allow native token transferserc20-transfer: Allow ERC-20 token transferserc721-transfer: Allow NFT transferserc1155-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
expiryfield 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.