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

# 지갑 액션

> Privy 지갑으로 메시지, 트랜잭션, 타입 데이터에 서명하기

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>;
};

Privy를 사용하여 EVM 지갑의 메시지 서명, 타입 데이터 서명, 트랜잭션을 수행하는 방법을 알아보세요.

## 개요

Privy는 EVM(이더리움 호환) 지갑과 원활하게 작동하는 포괄적인 [지갑 액션 훅](https://docs.privy.io/wallets/using-wallets/ethereum/send-a-transaction)을 제공합니다. 메시지, 타입 데이터, 원시 해시에 서명하고 트랜잭션을 직접 전송할 수 있습니다.

### 달성할 내용

이 가이드를 마치면 다음을 할 수 있습니다:

* EVM 지갑으로 메시지 서명
* 구조화된 데이터에 타입 데이터(EIP-712) 서명
* EVM 네트워크에서 트랜잭션 전송

이 가이드의 코드 스니펫은 다음 예제 프로젝트를 기반으로 합니다:

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

## 구현

### 컴포넌트 설정

<CodeGroup>
  ```tsx 지갑 액션 컴포넌트 (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);

    // 선택을 위한 지갑 매핑
    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">
        {/* 지갑 선택 */}
        <div>
          <label className="block text-sm font-medium mb-2">지갑 선택:</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="">지갑 선택</option>
            {allWallets.map((wallet, index) => (
              <option key={index} value={wallet.address}>
                {wallet.address}
              </option>
            ))}
          </select>
        </div>

        {/* 액션 버튼 */}
        <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"
          >
            메시지 서명
          </button>
          <button 
            onClick={handleSignTypedData}
            disabled={!selectedWallet}
            className="px-4 py-2 bg-green-600 text-white rounded disabled:opacity-50"
          >
            타입 데이터 서명
          </button>
          <button 
            onClick={handleSendTransaction}
            disabled={!selectedWallet}
            className="px-4 py-2 bg-red-600 text-white rounded disabled:opacity-50"
          >
            트랜잭션 전송
          </button>
        </div>
      </div>
    );
  };
  ```
</CodeGroup>

### 지갑 액션

#### 메시지 서명

<CodeGroup>
  ```tsx 메시지 서명 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>

#### 타입 데이터 서명 (EIP-712)

<CodeGroup>
  ```tsx 타입 데이터 서명 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>

#### 트랜잭션 전송

<CodeGroup>
  ```tsx 트랜잭션 전송 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>

## 더 알아보기

* [Privy 문서](https://docs.privy.io/)
* [배치 트랜잭션](/base-account/improve-ux/batch-transactions)
* [가스 스폰서](/base-account/improve-ux/sponsor-gas/paymasters)
