Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions templates/nextjs/advanced-permissions-starter/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# MetaMask Advanced Permissions (ERC-7715) Starter

This is a NextJS MetaMask Advanced Permissions (ERC-7715) starter created with [@metamask/create-gator-app](https://www.npmjs.com/package/@metamask/create-gator-app).
This is a NextJS MetaMask Advanced Permissions (ERC-7715) starter created with [`@metamask/create-gator-app`](https://www.npmjs.com/package/@metamask/create-gator-app).

This template is meant to help you bootstrap your own projects with [Advanced Permissions (ERC-7715)](https://docs.metamask.io/smart-accounts-kit/guides/advanced-permissions/execute-on-metamask-users-behalf/). It helps you build
a dApp with ERC-7715 support to request permissions and redeem them.
Expand All @@ -9,13 +9,13 @@ Learn more about [ERC-7715](https://eips.ethereum.org/EIPS/eip-7715).

## Prerequisites

1. **Pimlico API Key**: In this template, you’ll use Pimlico’s
bundler and paymaster services to submit user operations and
sponsor transactions. You can get your API key from [Pimlico’s dashboard](https://dashboard.pimlico.io/apikeys).
1. **Pimlico API Key**: In this template, we use Pimlico's Bundler and Paymaster services to submit user
operations and sponsor transactions, respectively. You can retrieve the required API key
from the [Pimlico Dashboard](https://dashboard.pimlico.io/apikeys).

2. **RPC URL** In this template, you’ll need an RPC URL for the Sepolia chain. You can use a public
RPC or any provider of your choice, but we recommend using a paid RPC for better reliability and to
avoid rate-limiting issues.
RPC or any provider of your choice, but we recommend using a paid RPC for better reliability
and to avoid rate-limiting issues.

## Project structure

Expand Down Expand Up @@ -63,7 +63,7 @@ NEXT_PUBLIC_RPC_URL =

## Getting started

First, start the development server using the package manager you chose during setup.
First, start the development server:

```bash
npm run dev
Expand All @@ -87,5 +87,5 @@ This template demonstrates a complete Advanced Permissions (ERC-7715) flow:

To learn more about Smart Accounts Kit, take a look at the following resources:

- [Advanced Permissions (ERC-7715) guide](https://docs.metamask.io/smart-accounts-kit/guides/advanced-permissions/execute-on-metamask-users-behalf/) - Learn how to use ERC-7715 permissions.
- [Advanced Permissions (ERC-7715) guide](https://docs.metamask.io/smart-accounts-kit/guides/advanced-permissions/execute-on-metamask-users-behalf/) - Learn how to use MetaMask Advanced Permissions.
- [Smart Accounts Kit Documentation](https://docs.metamask.io/smart-accounts-kit/) - Learn more about Smart Accounts Kit features and API.
11 changes: 6 additions & 5 deletions templates/nextjs/advanced-permissions-starter/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,17 @@
"start": "next start"
},
"dependencies": {
"@metamask/smart-accounts-kit": "^0.3.0",
"@metamask/sdk": "~0.33.1",
"@metamask/smart-accounts-kit": "^1.0.0",
"@tailwindcss/postcss": "^4.1.1",
"@tanstack/react-query": "^5.90.7",
"@tanstack/react-query": "^5.90.21",
"lucide-react": "^0.487.0",
"next": "15.4.10",
"permissionless": "^0.2.46",
"permissionless": "^0.3.4",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"viem": "^2.38.6",
"wagmi": "^2.19.2"
"viem": "^2.46.1",
"wagmi": "3.4.4"
},
"devDependencies": {
"@eslint/eslintrc": "^3",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
"use client";

import { useAccount, useChainId, useConnect, useSwitchChain } from "wagmi";
import { useChainId, useConnect, useConnection, useSwitchChain } from "wagmi";
import Button from "@/components/Button";
import { metaMask } from "wagmi/connectors";

export default function ConnectButton() {
const { connect } = useConnect();
const { chainId: connectedChainId, isConnected } = useAccount();
const connect = useConnect();
const { chainId: connectedChainId, isConnected } = useConnection();
const { switchChain } = useSwitchChain();
const currentChainId = useChainId();

Expand All @@ -19,7 +19,7 @@ export default function ConnectButton() {
}

return (
<Button className="w-full space-x-2" onClick={() => connect({ connector: metaMask() })}>
<Button className="w-full space-x-2" onClick={() => connect.mutate({ connector: metaMask() })}>
<span>Connect with MetaMask</span>
</Button>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,10 @@ export default function GrantPermissionsButton() {
const currentTime = Math.floor(Date.now() / 1000);
// 30 days in seconds
const expiry = currentTime + 24 * 60 * 60 * 30;

const permissions = await client.requestExecutionPermissions([{
chainId,
expiry,
signer: {
type: "account",
data: {
address: sessionAccount.address,
},
},
isAdjustmentAllowed,
to: sessionAccount.address,
permission: {
type: "native-token-periodic",
data: {
Expand All @@ -71,6 +64,7 @@ export default function GrantPermissionsButton() {
periodDuration: 86400,
justification: "Permission to transfer 0.001 ETH every day",
},
isAdjustmentAllowed
},
}]);
savePermission(permissions[0]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export default function PermissionInfo() {
</div>
<div className="space-y-4">
<pre className="bg-gray-200 dark:bg-gray-900 p-3 rounded text-xs max-h-80 text-gray-800 dark:text-gray-300 overflow-x-auto border border-gray-300 dark:border-gray-600">
{JSON.stringify(permission, null, 2)}
{JSON.stringify(permission, (_, v) => typeof v === "bigint" ? v.toString() : v, 2)}
</pre>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { useSessionAccount } from "@/providers/SessionAccountProvider";
import { usePermissions } from "@/providers/PermissionProvider";
import { Loader2, CheckCircle, ExternalLink } from "lucide-react";
import Button from "@/components/Button";
import { useAccount, usePublicClient } from "wagmi";
import { useConnection, usePublicClient } from "wagmi";

export default function RedeemPermissionButton() {
const [loading, setLoading] = useState(false);
Expand All @@ -17,7 +17,7 @@ export default function RedeemPermissionButton() {
const { sessionAccount } = useSessionAccount();
const { permission } = usePermissions();
const publicClient = usePublicClient();
const { chain } = useAccount();
const { chain } = useConnection();

/**
* Handles the redemption of delegation permissions.
Expand All @@ -30,18 +30,11 @@ export default function RedeemPermissionButton() {
setLoading(true);

try {
const { context, signerMeta } = permission;

if (!signerMeta) {
console.error("No signer meta found");
setLoading(false);
return;
}
const { delegationManager } = signerMeta;
const { context, delegationManager } = permission;

// Validate required parameters
if (!context || !delegationManager) {
console.error("Missing required parameters for delegation");
console.error("Missing required parameters for redeem permission");
setLoading(false);
return;
}
Expand All @@ -67,7 +60,7 @@ export default function RedeemPermissionButton() {
to: sessionAccount.address,
data: '0x',
value: 1n,
permissionsContext: context,
permissionContext: context,
delegationManager,
},
],
Expand All @@ -79,8 +72,6 @@ export default function RedeemPermissionButton() {
});

setTxHash(receipt.transactionHash);

console.log(receipt);
} catch (error) {
console.error(error);
} finally {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import RedeemPermissionButton from "@/components/RedeemPermissionButton";
import GrantPermissionsButton from "./GrantPermissionsButton";
import { useSessionAccount } from "@/providers/SessionAccountProvider";
import { usePermissions } from "@/providers/PermissionProvider";
import { useAccount, useChainId } from "wagmi";
import { useConnection, useChainId } from "wagmi";

export default function Steps() {
const [step, setStep] = useState<number>(1);
const { sessionAccount } = useSessionAccount();
const { permission } = usePermissions();
const { isConnected, chainId: connectedChainId } = useAccount();
const { isConnected, chainId: connectedChainId } = useConnection();
const currentChainId = useChainId();

useEffect(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { Address, formatEther } from "viem";
import { ExternalLink } from "lucide-react";
import { useAccount, useBalance } from "wagmi";
import { useConnection, useBalance } from "wagmi";

interface WalletInfoProps {
address: Address;
Expand All @@ -11,7 +11,7 @@ interface WalletInfoProps {

export default function WalletInfo({ address, label }: WalletInfoProps) {
const { data: balance, isLoading } = useBalance({ address });
const { chain } = useAccount();
const { chain } = useConnection();

const viewOnEtherscan = () => {
window.open(`${chain?.blockExplorers?.default?.url}/address/${address}`, "_blank");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

import { useSessionAccount } from "@/providers/SessionAccountProvider";
import WalletInfo from "@/components/WalletInfo";
import { useAccount } from "wagmi";
import { useConnection } from "wagmi";

export default function WalletInfoContainer() {
const { sessionAccount } = useSessionAccount();
const { address } = useAccount();
const { address } = useConnection();

return (
<div className="w-full max-w-4xl mx-auto p-3 space-y-2">
Expand Down
21 changes: 10 additions & 11 deletions templates/nextjs/delegation-starter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@

This is a NextJS MetaMask Smart Accounts & Delegation template created with [`@metamask/create-gator-app`](https://npmjs.com/package/@metamask/create-gator-app).

This template is meant to help you bootstrap your own projects with Metamask Smart Acounts. It helps you build smart accounts with account abstraction, and powerful delegation features.
This template is meant to help you bootstrap your own projects with MetaMask Smart Accounts. It helps you build smart accounts with account abstraction, and powerful delegation features.

Learn more about [Metamask Smart Accounts](https://docs.metamask.io/smart-accounts-kit/concepts/smart-accounts/).
Learn more about [MetaMask Smart Accounts](https://docs.metamask.io/smart-accounts-kit/concepts/smart-accounts/).

## Prerequisites

1. **Pimlico API Key**: In this template, you’ll use Pimlico’s
bundler and paymaster services to submit user operations and
sponsor transactions. You can get your API key from [Pimlico’s dashboard](https://dashboard.pimlico.io/apikeys).
1. **Pimlico API Key**: In this template, we use Pimlico's Bundler and Paymaster services to submit
user operations and sponsor transactions, respectively. You can retrieve the required API key from
the [Pimlico Dashboard](https://dashboard.pimlico.io/apikeys).

2. **Web3Auth Client ID**: During setup, if you used the
`-add-web3auth` flag, you’ll need to create a new project on the
Web3Auth Dashboard and get your Client ID. You can follow the [Web3Auth documentation](https://web3auth.io/docs/dashboard-setup#getting-started).
2. **Web3Auth Client ID**: During setup, if you used the `-add-web3auth` flag, you’ll need to create a new
project on the Web3Auth Dashboard and get your Client ID. You can follow
the [Web3Auth documentation](https://web3auth.io/docs/dashboard-setup#getting-started).

## Project structure

Expand All @@ -33,7 +33,7 @@ template/
└── tsconfig.json # TypeScript configuration
```

## Setup environment variables
## Setup Environment Variables

Update the following environment variables in the `.env` file at
the root of your project.
Expand All @@ -52,8 +52,7 @@ NEXT_PUBLIC_WEB3AUTH_NETWORK =

## Getting started

First, start the development server using the package manager
you chose during setup.
First, start the development server using the package manager you chose during setup:

```bash
npm run dev
Expand Down
11 changes: 6 additions & 5 deletions templates/nextjs/delegation-starter/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@
"start": "next start"
},
"dependencies": {
"@metamask/smart-accounts-kit": "^0.3.0",
"@tanstack/react-query": "^5.90.7",
"@metamask/sdk": "~0.33.1",
"@metamask/smart-accounts-kit": "^1.0.0",
"@tanstack/react-query": "^5.90.21",
"next": "15.4.10",
"permissionless": "^0.2.57",
"permissionless": "^0.3.4",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"viem": "^2.38.6",
"wagmi": "^2.19.2"
"viem": "^2.46.1",
"wagmi": "3.4.4"
},
"devDependencies": {
"@eslint/eslintrc": "^3",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
"use client";

import { useConnect } from "wagmi";
import { useConnect, useConnectors } from "wagmi";
import Button from "@/components/Button";

export default function ConnectButton() {
const { connect, connectors } = useConnect();
const connect = useConnect();
const connectors = useConnectors();

return (
<div className="flex gap-2">
{connectors.map((connector) => (
<Button onClick={() => connect({ connector })} key={connector.id}>
<Button onClick={() => connect.mutate({ connector })} key={connector.id}>
Connect with {connector.name}
</Button>
))}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ export default function CreateDelegationButton() {

const handleCreateDelegation = async () => {
if (!smartAccount || !delegateSmartAccount) return;
console.log(smartAccount.address, delegateSmartAccount.address);
const delegation = prepareRootDelegation(
smartAccount,
delegateSmartAccount.address,
Expand All @@ -30,7 +29,6 @@ export default function CreateDelegationButton() {
signature,
};

console.log(signedDelegation);
storeDelegation(signedDelegation);
changeStep(5);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ export default function DeployDelegatorButton() {
hash: userOperationHash,
});

console.log(receipt);
setLoading(false);
changeStep(3);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ export default function RedeemDelegationButton() {
});

setTransactionHash(receipt.transactionHash);

console.log(receipt);
} catch (error) {
const errorMessage = (error as Error)?.message ?? 'Unknown error occurred';
console.error(`Error redeeming delegation: ${errorMessage}`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ import DeployDelegatorButton from "@/components/DeployDelegatorButton";
import LearnMoreButton from "@/components/LearnMoreButton";
import RedeemDelegationButton from "@/components/RedeemDelegationButton";
import RedeemDelegationCodeBlock from "@/components/RedeemDelegationCodeBlock";
import { useAccount } from "wagmi";
import { useConnection } from "wagmi";
import useDelegateSmartAccount from "@/hooks/useDelegateSmartAccount";
import useDelegatorSmartAccount from "@/hooks/useDelegatorSmartAccount";
import { useStepContext } from "@/hooks/useStepContext";
import useStorageClient from "@/hooks/useStorageClient";

export default function Steps() {
const { step, changeStep } = useStepContext();
const { address } = useAccount();
const { address } = useConnection();
const { smartAccount } = useDelegatorSmartAccount();
const { smartAccount: delegateSmartAccount } = useDelegateSmartAccount();
const { getDelegation } = useStorageClient();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ import {
toMetaMaskSmartAccount,
} from '@metamask/smart-accounts-kit';
import { useEffect, useState } from 'react';
import { useAccount, usePublicClient, useWalletClient } from 'wagmi';
import { useConnection, usePublicClient, useWalletClient } from 'wagmi';

export default function useDelegatorSmartAccount(): {
smartAccount: MetaMaskSmartAccount | null;
} {
const { address } = useAccount();
const { address } = useConnection();
const publicClient = usePublicClient();
const { data: walletClient } = useWalletClient();
const [smartAccount, setSmartAccount] = useState<MetaMaskSmartAccount | null>(
Expand Down
Loading
Loading