Privy를 사용하여 EVM 지갑의 메시지 서명, 타입 데이터 서명, 트랜잭션을 수행하는 방법을 알아보세요.Documentation Index
Fetch the complete documentation index at: https://daehan-base.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
개요
Privy는 EVM(이더리움 호환) 지갑과 원활하게 작동하는 포괄적인 지갑 액션 훅을 제공합니다. 메시지, 타입 데이터, 원시 해시에 서명하고 트랜잭션을 직접 전송할 수 있습니다.달성할 내용
이 가이드를 마치면 다음을 할 수 있습니다:- EVM 지갑으로 메시지 서명
- 구조화된 데이터에 타입 데이터(EIP-712) 서명
- EVM 네트워크에서 트랜잭션 전송
구현
컴포넌트 설정
"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>
);
};
지갑 액션
메시지 서명
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);
}
};
타입 데이터 서명 (EIP-712)
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);
}
};
트랜잭션 전송
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);
}
};