> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dynamic.xyz/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Metamask

<Card title="Recommended: JavaScript SDK with React Hooks" icon="react" color="#4779FE">
  For new React apps, we recommend the JavaScript SDK with React Hooks (`@dynamic-labs-sdk/react-hooks`) instead of the legacy React SDK documented here. The JS SDK comes with many benefits such as a much smaller bundle size and other optimizations. Use the [React quickstart (JavaScript SDK)](/javascript/reference/react-quickstart) to get started.
</Card>

<Tip>
  See full example [here](https://github.com/AyushBherwani1998/mm-smart-accounts-dynamic-demo) which uses Pimlico services for bundling, paymaster, gas estimation, etc.
</Tip>

## Basic Implementation

<Steps>
  <Step title="Create app with the React Quickstart">
    Follow the [React Quickstart](/react/reference/quickstart) **Custom setup** path: **Ethereum (EVM)** with **Wagmi** and **viem**. Use the quickstart’s Vite scaffold, or scaffold React with your own tooling and install the same packages. In the [Dynamic dashboard](https://app.dynamic.xyz/dashboard), enable **Ethereum** under **Chains & Networks** and add your dev origin under **Security** → **Allowed Origins**.
  </Step>

  <Step title="Install Delegation Toolkit">
    After the app is created, install the Delegation Toolkit:

    <CodeGroup>
      ```bash npm theme={"system"}
      npm install @metamask/delegation-toolkit
      ```

      ```bash yarn theme={"system"}
      yarn add @metamask/delegation-toolkit
      ```

      ```bash pnpm theme={"system"}
      pnpm add @metamask/delegation-toolkit
      ```

      ```bash bun theme={"system"}
      bun add @metamask/delegation-toolkit
      ```
    </CodeGroup>
  </Step>

  <Step title="Create Smart Account Hook">
    ```tsx src/hooks/useSmartAccount.ts theme={"system"}
    import {
      Implementation,
      MetaMaskSmartAccount,
      toMetaMaskSmartAccount,
    } from "@metamask/delegation-toolkit";
    import { useEffect, useState } from "react";
    import { useAccount, usePublicClient, useWalletClient } from "wagmi";

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

      useEffect(() => {
        if (!address || !walletClient || !publicClient) return;

        console.log("Creating smart account");

        toMetaMaskSmartAccount({
          client: publicClient,
          implementation: Implementation.Hybrid,
          deployParams: [address, [], [], []],
          deploySalt: "0x",
          signatory: { walletClient },
        }).then((smartAccount) => {
          setSmartAccount(smartAccount);
        });
      }, [address, walletClient, publicClient]);

      return { smartAccount };
    }
    ```
  </Step>

  <Step title="Create Bundler Client Hook">
    ```tsx src/hooks/useBundlerClient.ts theme={"system"}
    import { createBundlerClient } from "viem/account-abstraction";
    import { useState, useEffect } from "react";
    import { usePublicClient } from "wagmi";
    import { http } from "viem";

    export function useBundlerClient() {
        const [bundlerClient, setBundlerClient] = useState();
        const publicClient = usePublicClient();

        useEffect(() => {
            if (!publicClient) return;
            setBundlerClient(createBundlerClient({
                client: publicClient,
                transport: http("https://your-bundler-rpc.com"),
            }));
        }, [publicClient]);

        return { bundlerClient };
    }
    ```
  </Step>

  <Step title="Send User Operation">
    ```tsx src/components/SendUserOperation.tsx theme={"system"}
    import { parseEther } from "viem";
    import useBundlerClient from "/hooks/useBundlerClient";
    import useSmartAccount from "../hooks/useSmartAccount";

    const SendUserOperation = () => {
        const { bundlerClient } = useBundlerClient();
        const { smartAccount } = useSmartAccount();

        // Appropriate fee per gas must be determined for the specific bundler being used.
        const maxFeePerGas = 1n;
        const maxPriorityFeePerGas = 1n;

        const handleSendUserOperation = async () => {
            const userOperationHash = await bundlerClient.sendUserOperation({
                account: smartAccount,
                calls: [
                    {
                        to: "0x1234567890123456789012345678901234567890",
                        value: parseEther("1"),
                    },
                ],
                maxFeePerGas,
                maxPriorityFeePerGas,
            });
            // You may want to handle the result here, e.g., show a notification
            console.log("User Operation Hash:", userOperationHash);
        };

        return (
            <button onClick={handleSendUserOperation}>
                Send User Operation
            </button>
        );
    }
    ```
  </Step>
</Steps>

## References

* [Metamask Smart Account Overview](https://docs.metamask.io/delegation-toolkit/development/concepts/smart-accounts/)
* [Metamask Smart Account Quickstart](https://docs.metamask.io/delegation-toolkit/development/get-started/smart-account-quickstart)
