Launch Week 3A week of New Features

Learn more

Guide for App Developers: Leveraging EIP-7702 Enabled Wallets in Your dApp

6 min read

Guide for App Developers: Leveraging EIP-7702 Enabled Wallets in Your dApp

EIP-7702 enables Externally Owned Accounts (EOAs) to temporarily delegate authority to smart contracts, unlocking smart account features like transaction batching, gas sponsorship, and session keys without permanent changes to the account.

This guide provides a concise, actionable roadmap for integrating EIP-7702 enabled wallets into your decentralized application (dApp), focusing on detecting support, wallet interactions, transaction batching (with EIP-7821), permissions (with EIP-7715), and transaction history.

Table of Contents

  1. Detecting EIP-7702 Support
  2. Integrating with EIP-5792 for Wallet Interactions
  3. Implementing Transaction Batching with EIP-7821
  4. Managing Permissions with EIP-7715
  5. Enhancing Transaction History

Detecting EIP-7702 Support

Before enabling EIP-7702 features, your dApp must confirm that the connected wallet supports this proposal to ensure compatibility and a seamless user experience.

Methods to Detect Support

  • Wallet Capabilities Check (Recommended): Use the wallet_getCapabilities method from EIP-5792 to query wallet features securely.


    _10
    async function check7702Support(provider) {
    _10
    try {
    _10
    const capabilities = await provider.request({ method: 'wallet_getCapabilities' });
    _10
    return capabilities.includes('eip7702');
    _10
    } catch (error) {
    _10
    console.error('Error checking EIP-7702 support:', error);
    _10
    return false;
    _10
    }
    _10
    }

  • On-Chain Verification (Alternative): Check for temporary smart contract code, though less reliable due to delegation’s transient nature.


    _10
    function is7702Enabled(address eoa) public view returns (bool) {
    _10
    return eoa.code.length > 0 && eoa.code[0] == 0xEF; // EIP-7702 marker
    _10
    }

Implementation Tip

Use the capabilities check to dynamically enable EIP-7702 features in your frontend, falling back to standard flows for unsupported wallets.

Integrating with EIP-5792 for Wallet Interactions

EIP-5792 provides JSON-RPC methods for dApps to interact with wallets, serving as the primary interface for accessing EIP-7702 features like batching and gas sponsorship.

Key Methods

  • wallet_sendCalls: Sends batched transactions.
  • wallet_getCapabilities: Queries supported features.
  • wallet_sponsorTransaction: Requests gas sponsorship.

Steps to Integrate

  1. Study the EIP-5792 specification for method details.
  2. Update wallet connection logic (e.g., ethers.js, Web3.js) to support these methods.
  3. Handle responses and errors gracefully.

Example: Sending a Batch


_13
async function sendBatchedTransactions(provider, transactions) {
_13
try {
_13
const result = await provider.request({
_13
method: 'wallet_sendCalls',
_13
params: [{ calls: transactions }]
_13
});
_13
console.log('Batch sent:', result);
_13
return result;
_13
} catch (error) {
_13
console.error('Error sending batch:', error);
_13
throw error;
_13
}
_13
}

Next Steps

Check wallet provider documentation (e.g., Openfort) for EIP-5792 implementation specifics.

Implementing Transaction Batching with EIP-7821

Transaction batching, enabled by EIP-7702, allows multiple actions (e.g., token approval and swap) to be executed in a single transaction, reducing user signatures and improving UX. EIP-7821 complements this by introducing a standard for Call Operation Events, enabling wallets to emit structured events for batched calls, which simplifies tracking and verification.

How It Works

  • EIP-7702: The wallet delegates execution to a smart contract, which processes multiple calls in one transaction.
  • EIP-7821: Defines a CallOperation event emitted for each call in a batch, allowing dApps to parse and display individual operations (e.g., on block explorers or transaction histories).

EIP-7821 Event


_10
event CallOperation(
_10
address indexed caller,
_10
address indexed target,
_10
bytes4 selector,
_10
uint256 value,
_10
bytes data,
_10
bool success,
_10
bytes returnData
_10
);

Steps to Implement

  1. Prepare Transactions: Create an array of transaction objects with to (target address) and data (encoded function call).
  2. Send the Batch: Use EIP-5792’s wallet_sendCalls to execute the batch.
  3. Parse CallOperation Events: Monitor transaction logs for CallOperation events to verify each call’s outcome and update your UI.

Example Code


_22
const transactions = [
_22
{ to: tokenAddress, data: approveData }, // Approve token
_22
{ to: swapAddress, data: swapData } // Perform swap
_22
];
_22
_22
async function sendAndTrackBatch(provider, transactions) {
_22
const tx = await sendBatchedTransactions(provider, transactions);
_22
const receipt = await provider.getTransactionReceipt(tx.transactionHash);
_22
_22
// Parse CallOperation events
_22
const callEventABI = [
_22
"event CallOperation(address indexed caller, address indexed target, bytes4 selector, uint256 value, bytes data, bool success, bytes returnData)"
_22
];
_22
const iface = new ethers.utils.Interface(callEventABI);
_22
receipt juice.forEach(log => {
_22
try {
_22
const event = iface.parseLog(log);
_22
console.log(`Call to ${event.args.target} ${event.args.success ? 'succeeded' : 'failed'}`);
_22
} catch (e) {}
_22
});
_22
return receipt;
_22
}

Benefits

  • EIP-7702: Fewer signatures, streamlined UX.
  • EIP-7821: Transparent tracking of batched calls, improving auditability and user trust.

UI Tip

Display batched transactions as a single action (e.g., “Approve + Swap”) with expandable details derived from CallOperation events.

Managing Permissions with EIP-7715

EIP-7702 enables temporary delegations, such as session keys, for restricted actions. EIP-7715 (Permission Tree) complements this by providing a standard for wallets to manage and expose granular permissions, allowing dApps to request specific capabilities (e.g., limited token transfers) without full account control.

Understanding EIP-7715

  • Defines a Permission Tree, a structured format for wallets to represent permissions (e.g., allowed functions, contracts, or time limits).
  • Enables dApps to query permissions via a getPermissions method, ensuring compatibility with wallet-managed restrictions.

Key Interface (EIP-7715)


_11
interface IPermissionTree {
_11
function getPermissions(address account) external view returns (Permission[] memory);
_11
_11
struct Permission {
_11
address target; // Contract address
_11
bytes4 selector; // Function selector
_11
uint256 valueLimit; // Max ETH value
_11
uint256 expiration; // Permission expiry
_11
bytes extraData; // Additional constraints
_11
}
_11
}

Requesting Permissions

Use EIP-5792 or wallet-specific methods to request permissions, then query the wallet’s Permission Tree to verify granted capabilities.

Example Code


_25
async function requestAndVerifyPermissions(provider, requestedPermissions) {
_25
try {
_25
// Request permissions (wallet-specific or future EIP-5792 extension)
_25
await provider.request({
_25
method: 'wallet_requestPermissions',
_25
params: [{
_25
target: tokenAddress,
_25
selector: '0xa9059cbb', // transfer(address,uint256)
_25
valueLimit: 0,
_25
expiration: Math.floor(Date.now() / 1000) + 3600
_25
}]
_25
});
_25
_25
// Query Permission Tree
_25
const permissionTreeContract = new ethers.Contract(permissionTreeAddress, [
_25
'function getPermissions(address account) view returns (tuple(address target, bytes4 selector, uint256 valueLimit, uint256 expiration, bytes extraData)[])'
_25
], provider);
_25
const permissions = await permissionTreeContract.getPermissions(await provider.getSigner().getAddress());
_25
console.log('Granted permissions:', permissions);
_25
return permissions;
_25
} catch (error) {
_25
console.error('Error managing permissions:', error);
_25
throw error;
_25
}
_25
}

Note

EIP-7715 adoption may vary; ensure fallback logic for wallets without Permission Tree support.

Enhancing Transaction History

EIP-7702’s batched transactions require tailored handling to display meaningful history, especially with EIP-7821’s event logs.

Fetching On-Chain Data

Fetch ETH transfers directly to avoid third-party APIs:


_10
struct Transfer {
_10
address from;
_10
address to;
_10
uint256 value;
_10
}
_10
_10
function getEthTransfers(address account) public view returns (Transfer[] memory) {
_10
// Parse logs or traces (implementation-specific)
_10
}

Handling Batched Transactions

  • Use EIP-7821’s CallOperation events to extract individual actions from a batch.
  • Display batches as a single entry with expandable details.

Example Code


_21
async function displayTransactionHistory(provider, txHash) {
_21
const receipt = await provider.getTransactionReceipt(txHash);
_21
const callEventABI = [
_21
"event CallOperation(address indexed caller, address indexed target, bytes4 selector, uint256 value, bytes data, bool success, bytes returnData)"
_21
];
_21
const iface = new ethers.utils.Interface(callEventABI);
_21
const actions = receipt.logs.map(log => {
_21
try {
_21
const event = iface.parseLog(log);
_21
return {
_21
target: event.args.target,
_21
success: event.args.success,
_21
action: event.args.selector
_21
};
_21
} catch (e) {
_21
return null;
_21
}
_21
}).filter(action => action);
_21
console.log('Batch actions:', actions);
_21
// Update UI with actions
_21
}

Conclusion

This guide equips you to integrate EIP-7702 enabled wallets by:

  • Detecting support to ensure compatibility.
  • Using EIP-5792 for seamless wallet interactions.
  • Implementing transaction batching with EIP-7821 for auditable, streamlined UX.
  • Managing permissions with EIP-7715 for secure, granular control.
  • Enhancing transaction history with on-chain data and event parsing.
Share this article