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

# Wallet Actions

> Sign messages, transactions, and typed data with Privy wallets

export const GithubRepoCard = ({title, githubUrl}) => {
  return <a href={githubUrl} target="_blank" rel="noopener noreferrer" className="mb-4 flex items-center rounded-lg bg-zinc-900 p-4 text-white transition-all hover:bg-zinc-800">
      <div className="flex w-full items-center gap-3">
        <svg height="24" width="24" className="flex-shrink-0 dark:fill-white" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
          <path fill="currentColor" fillRule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z" />
        </svg>

        <div className="flex min-w-0 flex-grow flex-col">
          <span className="truncate text-base font-medium">{title}</span>
          <span className="truncate text-xs text-zinc-400">{githubUrl}</span>
        </div>

        <svg className="h-5 w-5 flex-shrink-0 text-zinc-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
        </svg>
      </div>
    </a>;
};

Learn how to perform wallet actions including signing messages, typed data, and transactions for EVM wallets using Privy.

## Overview

Privy provides comprehensive [wallet action hooks](https://docs.privy.io/wallets/using-wallets/ethereum/send-a-transaction) that work seamlessly with EVM (Ethereum-compatible) wallets. You can sign messages, typed data, raw hashes, and transactions, as well as send transactions directly.

### What you'll achieve

By the end of this guide, you will:

* Sign messages for EVM wallets
* Sign typed data (EIP-712) for structured data
* Send transactions on EVM networks

The code snippets in this guide are based on the following example project:

<GithubRepoCard title="Base Account Privy Template" githubUrl="https://github.com/base/base-account-privy" />

## Implementation

### Component Setup

<CodeGroup>
  ```tsx Wallet Actions Component (components/sections/wallet-actions.tsx) expandable theme={null}
  "use client";

  import { useState, useMemo, useEffect } from "react";
  import {
    useWallets,
    useSendTransaction,
    useSignMessage,
    useSignTypedData,
  } from "@privy-io/react-auth";

  const WalletActions = () => {
    const { signMessage } = useSignMessage();
    const { sendTransaction } = useSendTransaction();
    const { signTypedData } = useSignTypedData();
    const { wallets } = useWallets();

  const [selectedWallet, setSelectedWallet] = useState<{
      address: string;
      type: string;
      name: string;
    } | null>(null);

    // Map wallets for selection
    const allWallets = useMemo(() => {
      return wallets.map((wallet) => ({
        address: wallet.address,
        type: "ethereum",
        name: wallet.address,
      }));
    }, [wallets]);

    useEffect(() => {
      if (allWallets.length > 0 && !selectedWallet) {
        setSelectedWallet(allWallets[0]);
      }
    }, [allWallets, selectedWallet]);

    const handleSignMessage = async () => {
      if (!selectedWallet) return;
      
      try {
        const message = "Hello, world!";
        const { signature } = await signMessage(
          { message },
          { address: selectedWallet.address }
        );
        console.log("Message signed:", signature);
      } catch (error) {
        console.error("Failed to sign message:", error);
      }
    };


    const handleSendTransaction = async () => {
      if (!selectedWallet) return;
      
      try {
        const transaction = await sendTransaction(
          { 
            to: "0xE3070d3e4309afA3bC9a6b057685743CF42da77C", 
            value: 10000 
          },
          { address: selectedWallet.address }
        );
        console.log("Transaction sent:", transaction);
      } catch (error) {
        console.error("Failed to send transaction:", error);
      }
    };

    const handleSignTypedData = async () => {
      if (!selectedWallet) return;
      
      try {
        const typedData = {
          domain: {
            name: "Example App",
            version: "1",
            chainId: 1,
            verifyingContract: "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC",
          },
          types: {
            Person: [
              { name: "name", type: "string" },
              { name: "wallet", type: "address" },
            ],
            Mail: [
              { name: "from", type: "Person" },
              { name: "to", type: "Person" },
              { name: "contents", type: "string" },
            ],
          },
          primaryType: "Mail",
          message: {
            from: {
              name: "Alice",
              wallet: "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826",
            },
            to: {
              name: "Bob",
              wallet: "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB",
            },
            contents: "Hello, Bob!",
          },
        };

        const { signature } = await signTypedData(typedData, {
          address: selectedWallet.address,
        });
        console.log("Typed data signature:", signature);
      } catch (error) {
        console.error("Failed to sign typed data:", error);
      }
    };

    return (
      <div className="space-y-4">
        {/* Wallet Selection */}
        <div>
          <label className="block text-sm font-medium mb-2">Select wallet:</label>
          <select
            value={selectedWallet?.address || ""}
            onChange={(e) => {
              const wallet = allWallets.find((w) => w.address === e.target.value);
              setSelectedWallet(wallet || null);
            }}
            className="w-full p-2 border rounded-md"
          >
            <option value="">Select a wallet</option>
            {allWallets.map((wallet, index) => (
              <option key={index} value={wallet.address}>
                {wallet.address}
              </option>
            ))}
          </select>
        </div>

        {/* Action Buttons */}
        <div className="grid grid-cols-3 gap-4">
          <button 
            onClick={handleSignMessage}
            disabled={!selectedWallet}
            className="px-4 py-2 bg-blue-600 text-white rounded disabled:opacity-50"
          >
            Sign Message
          </button>
          <button 
            onClick={handleSignTypedData}
            disabled={!selectedWallet}
            className="px-4 py-2 bg-green-600 text-white rounded disabled:opacity-50"
          >
            Sign Typed Data
          </button>
          <button 
            onClick={handleSendTransaction}
            disabled={!selectedWallet}
            className="px-4 py-2 bg-red-600 text-white rounded disabled:opacity-50"
          >
            Send Transaction
          </button>
        </div>
      </div>
    );
  };
  ```
</CodeGroup>

### Wallet Actions

#### Sign Message

<CodeGroup>
  ```tsx Sign Message theme={null}
  const handleSignMessage = async () => {
    if (!selectedWallet) return;
    
    try {
      const message = "Hello, world!";
      const { signature } = await signMessage(
        { message },
        { address: selectedWallet.address }
      );
      console.log("Signature:", signature);
    } catch (error) {
      console.error("Failed to sign message:", error);
    }
  };
  ```
</CodeGroup>

#### Sign Typed Data (EIP-712)

<CodeGroup>
  ```tsx Sign Typed Data expandable theme={null}
  const handleSignTypedData = async () => {
    if (!selectedWallet) return;
    
    try {
      const typedData = {
        domain: {
          name: "Example App",
          version: "1",
          chainId: 1,
          verifyingContract: "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC",
        },
        types: {
          Person: [
            { name: "name", type: "string" },
            { name: "wallet", type: "address" },
          ],
          Mail: [
            { name: "from", type: "Person" },
            { name: "to", type: "Person" },
            { name: "contents", type: "string" },
          ],
        },
        primaryType: "Mail",
        message: {
          from: {
            name: "Alice",
            wallet: "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826",
          },
          to: {
            name: "Bob",
            wallet: "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB",
          },
          contents: "Hello, Bob!",
        },
      };

      const { signature } = await signTypedData(typedData, {
        address: selectedWallet.address,
      });
      console.log("Typed data signature:", signature);
    } catch (error) {
      console.error("Failed to sign typed data:", error);
    }
  };
  ```
</CodeGroup>

#### Send Transaction

<CodeGroup>
  ```tsx Send Transaction expandable theme={null}
  const handleSendTransaction = async () => {
    if (!selectedWallet) return;
    
    try {
      const transaction = await sendTransaction(
        { 
          to: "0xE3070d3e4309afA3bC9a6b057685743CF42da77C", 
          value: 10000 // Wei
        },
        { address: selectedWallet.address }
      );
      console.log("Transaction hash:", transaction);
    } catch (error) {
      console.error("Failed to send transaction:", error);
    }
  };
  ```
</CodeGroup>

## Explore further

* [Privy docs](https://docs.privy.io/)
* [Batch Transactions](/base-account/improve-ux/batch-transactions)
* [Sponsor Gas](/base-account/improve-ux/sponsor-gas/paymasters)
