ERC-7715: Request permissions
This is an experimental feature. It requires MetaMask Flask 12.14.2 or later, and may change in future releases.
ERC-7715 introduces a standard way for dapps to request permissions from a wallet to execute transactions on a user's behalf.
The MetaMask Delegation Toolkit provides the experimental actions for ERC-7715 that lets a caller request permissions from MetaMask's permissions system.
Request permissions
To request permissions, extend your Viem Wallet Client with erc7715ProviderActions
actions.
You'll need a session account to request the permission, which can be either a smart account or an externally owned account (EOA).
This example uses a MetaMask smart account:
- example.ts
- config.ts
import { sepolia as chain } from "viem/chains";
import { sessionAccount, walletClient } from "./config.ts";
const expiry = Math.floor(Date.now() / 1000 + 604_800); // 1 week from now.
const currentTime = Math.floor(Date.now() / 1000); // now
const grantedPermissions = await walletClient.grantPermissions([{
chainId: chain.id,
expiry,
signer: {
type: "account",
data: {
address: sessionAccount.address,
},
},
permission: {
type: "native-token-stream",
data: {
initialAmount: 1n, // 1 wei
amountPerSecond: 1n, // 1 wei per second
maxAmount: 10n, // 10 wei
startTime: currentTime,
justification: "Payment for a week long subscription",
},
},
}]);
import { createWalletClient, custom, createPublicClient, http } from "viem";
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";
import { sepolia as chain } from "viem/chains";
import { erc7715ProviderActions } from "@metamask/delegation-toolkit/experimental";
import { toMetaMaskSmartAccount, Implementation } from "@metamask/delegation-toolkit";
const publicClient = createPublicClient({
chain: chain,
transport: http(),
});
// The private key of the session owner.
const privateKey = "0x...";
const account = privateKeyToAccount(privateKey);
export const sessionAccount = await toMetaMaskSmartAccount({
client: publicClient,
implementation: Implementation.Hybrid,
deployParams: [account.address, [], [], []],
deploySalt: "0x",
signatory: { account },
});
export const walletClient = createWalletClient({
transport: custom(window.ethereum),
}).extend(erc7715ProviderActions());
ERC-7715 request permission sample
Here's what your ERC-7715 native token streaming allowance request looks like:
[{
chainId: "0xaa36a7",
expiry: 1745041429,
permission: {
type: "native-token-stream",
data: {
amountPerSecond: "0x1",
maxAmount: "0x1",
initialAmount: "0xa",
startTime: 1744955029,
justification: "Payment for a week long subscription",
},
},
signer: {
type: "account",
data: {
address: "0x1234...",
},
},
}]
Learn more about the ERC-7715 permission schema.
Additionally, you can allow users to modify the requested permission by setting the isAdjustmentAllowed
parameter to true
in the request.
import { sepolia as chain } from "viem/chains";
// The config.ts is the same as in the previous example.
import { sessionAccount, walletClient } from "./config.ts";
const expiry = Math.floor(Date.now() / 1000 + 604_800); // 1 week from now.
const currentTime = Math.floor(Date.now() / 1000); // now
const grantedPermissions = await walletClient.grantPermissions([{
chainId: chain.id,
expiry,
signer: {
type: "account",
data: {
address: sessionAccount.address,
},
},
permission: {
type: "native-token-stream",
+ isAdjustmentAllowed: true,
data: {
initialAmount: 1n, // 1 wei
amountPerSecond: 1n, // 1 wei per second
maxAmount: 10n, // 10 wei
startTime: currentTime,
justification: "Payment for a week long subscription",
},
},
}]);
Users have full control over the permissions they grant—depending on the permission you request, they may choose to grant more limited permissions than requested. You should always verify the granted permissions and adjust your dapp's behavior accordingly.