> ## 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] Recommended: JavaScript SDK for React Native
>
> While this SDK is still supported, we recommend using newer [JavaScript SDK](https://docs.dynamic.xyz/docs/javascript/reference/react-native-quickstart.md), which is optimized for React Native, but also comes with a host of other benefits.

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

## Basic Implementation

**1. Create app with the React Native Quickstart**

Follow the [React Native Quickstart](https://docs.dynamic.xyz/docs/react-native/reference/quickstart.md) **Custom setup** path and enable **Ethereum (EVM)** with the extensions your stack needs (for example Viem). In the [Dynamic Console](https://console.dynamic.xyz/dashboard), enable **Ethereum** under **Chains & Networks** and add your dev origin under **Security** → **Allowed Origins**.

**2. Install Delegation Toolkit**

After the app is created, install the Delegation Toolkit:

```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
```

**3. 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 };
}
```

**4. 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 };
}
```

**5. 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>
    );
}
```

## 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)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.