Web3Auth
Last updated
Was this helpful?
Last updated
Was this helpful?
Was this helpful?
Web3Auth는 dApp이나 지갑에 연결되는 지갑 인프라입니다. 웹3.0 지갑과 애플리케이션에 접속 가능한 인증 인프라 역할을 합니다. Web3Auth의 뛰어난 사용자 편의성을 통해 주류 사용자 및 암호화폐 네이티브 모두를 단 몇 분 만에 온보딩할 수 있습니다.
지갑 인프라로서 Web3Auth는 모든 소셜 로그인, 웹 및 모바일 네이티브 플랫폼, 지갑 및 기타 키 관리 기능을 기본으로 지원합니다. 본 가이드를 통해 여러분은 클레이튼 네트워크에 구축된 탈중앙화 웹 애플리케이션에 Web3Auth를 통합할 수 있게 됩니다. 이 외 다른 플랫폼(Android, iOS, React Native, Flutter, Unity)에 Web3Auth를 통합하려면 이 가이드를 참조하세요.
작동하는 React 프로젝트(npx create-react-app 프로젝트명
실행).
필요한 지갑이 설치됨(Coinbase Wallet, Metamask).
RPC 엔드포인트: 지원되는 엔드포인트 공급자 중 하나에서 가져올 수 있음.
Faucet에서 얻은 테스트 KLAY: 충분한 KLAY를 계정에 충전.
Web3Auth 대시보드에서 클라이언트 ID 획득.
dApp에서 Web3Auth를 사용하려면 먼저 필요한 라이브러리와 SDK를 설치해야 합니다. 따라서 ethers.js와 Web3Auth 웹 SDK를 설정해야 합니다. Web3Auth를 ethers.js 또는 web3.js 라이브러리와 함께 사용하여 Klaytn 블록체인과 통신할 수 있습니다. 본 가이드에서는 ethers.js를 사용하도록 하겠습니다.
npm install --save @web3auth/modal
npm install --save ethers
필요한 라이브러리를 성공적으로 설치한 다음에는 Web3Auth 인스턴스를 초기화하고, Web3Auth 공급자 인스턴스를 useState() 훅에 설정하고, useEffect() 훅에 init() 함수를 설정합니다.
import { Web3Auth } from "@web3auth/modal";
import { ContractFactory, ethers } from "ethers";
import { useState, useEffect } from "react";
function App() {
const [web3auth, setWeb3auth] = useState(null);
const [provider, setProvider] = useState(null);
useEffect(() => {
const init = async () => {
try {
const web3auth = new Web3Auth({
clientId: "YOUR_WEB3AUTH_CLIENT_ID", // get it from Web3Auth Dashboard
web3AuthNetwork: "cyan",
chainConfig: {
chainNamespace: "eip155",
// modify if mainnet => “0x2019”
chainId: "0x3e9", // hex of 1001, Klaytn Baobab testnet.
rpcTarget: "https://public-en-baobab.klaytn.net", // modify if mainnet
displayName: "Klaytn Testnet", // modify if mainnet
blockExplorer: "https://baobab.scope.klaytn.com/", // modify if mainnet
ticker: "KLAY",
tickerName: "KLAY",
},
})
setWeb3auth(web3auth);
await web3auth.initModal();
setProvider(web3auth.provider);
} catch (error) {
console.error(error);
}
};
init();
}, []);
App.js
파일의 앱 함수 내에서 web3Auth 인스턴스의 connect() 메서드를 호출하여 지갑 연결을 초기화합니다.
const connectWallet = async() => {
if (!web3auth) {
console.log("web3auth not initialized yet");
return;
}
const web3authProvider = await web3auth.connect();
console.log(web3authProvider);
}
return (
<div className="App">
<button onClick={connectWallet}>Connect Wallet</button>
</div>
);
이 가이드에서는 유틸리티 함수인 truncateAddress()
를 사용하겠습니다: truncateAddress() 함수는 유효한 주소를 전달 받아 읽기 쉬운 형식으로 반환합니다. 다음은 프로젝트에서 유틸리티 함수를 설정하고 사용하는 방법을 단계별로 보여줍니다.
1단계: src
루트 폴더에 utils.js
파일을 생성합니다.
새로 만든 utils.js 파일에 다음 코드를 붙여넣습니다.
export const truncateAddress = (address) => {
if (!address) return "No Account";
const match = address.match(
/^(0x[a-zA-Z0-9]{2})[a-zA-Z0-9]+([a-zA-Z0-9]{4})$/
);
if (!match) return address;
return `${match[1]}…${match[2]}`;
};
2단계: App.js
파일에서 함수를 불러옵니다.
import { truncateAddress } from "./utils";
Web3Auth 인스턴스에서 connect()
메서드를 호출하여 지갑을 성공적으로 연결했다면 공급자(provider) 및 서명자(signer) 객체를 사용하여 사용자 계정과 잔액을 가져올 수 있습니다.
const [web3auth, setWeb3auth] = useState(null);
const [provider, setProvider] = useState(null);
const [address, setAddress] = useState("");
const [balance, setBalance] = useState("");
const connectWallet = async() => {
if (!web3auth) {
console.log("web3auth not initialized yet");
return;
}
const web3authProvider = await web3auth.connect();
setProvider(web3authProvider);
// this guide uses ethers version 6.3.0.
const ethersProvider = new ethers.BrowserProvider(web3authProvider);
// for ethers version below 6.3.0.
// const provider = new ethers.providers.Web3Provider(web3authProvider);
const ethersProvider = new ethers.BrowserProvider(web3authProvider);
const signer = await ethersProvider.getSigner();
// Get user's Ethereum public address
const address = signer.address;
// Get user's balance in ether
const balance = ethers.formatEther(
await ethersProvider.getBalance(address) // balance is in wei
);
setAddress(address);
setBalance(balance);
return (
<div className="App">
<button onClick={connectWallet}>Connect Wallet</button>
<div>Wallet Address: ${truncateAddress(address)} Balance: ${balance}</div>
</div>
);
}
지갑 연결을 끊으려면 Web3Auth 인스턴스에서 logout() 메서드를 사용하면 됩니다. 또한 상태 새로고침을 하여 이전에 저장된 연결 데이터를 모두 지우는 것도 좋은 방법 중 하나입니다.
function App() {
const disconnect = async () => {
if (!web3auth) {
console.log("web3auth not initialized yet");
return;
}
await web3auth.logout();
refreshState();
}
// refresh state
const refreshState = () => {
setAddress();
setBalance();
// make sure to add every other useState modifier function declared here.
}
return (
<div className="App">
<button onClick={disconnect}>Disconnect</button>
</div>
);
}
Web3Auth를 사용하여 체인을 전환하려면 먼저 addChain() 메서드를 호출하여 연결된 어댑터에 원하는 체인 구성을 추가한 다음 switchChain() 메서드를 호출해야 합니다.
const switchChain = async () => {
if (!web3auth) {
console.log("web3auth not initialized yet");
return;
}
// add chain - Klaytn Mainnet
await web3auth.addChain({
chainId: "0x2019",
displayName: "Klaytn Cypress",
chainNamespace: "eip155",
tickerName: "KLAY",
ticker: "KLAY",
decimals: 18,
rpcTarget: "https://public-en-cypress.klaytn.net",
blockExplorer: "https://scope.klaytn.com",
});
// switch chain
await web3auth.switchChain({chainId: "0x2019"});
}
return (
<div className="App">
<button onClick={switchChain}>Switch Chain</button>
</div>
);
Web3Auth의 고유한 기능 중 하나는 소셜 로그인입니다. 사용자가 소셜 플랫폼을 사용하여 로그인하면 Web3Auth 인스턴스는 로그인한 사용자에 대한 몇 가지 정보를 반환합니다. 로그인한 사용자 정보를 가져오는 방법은 Web3Auth 인스턴스에서 getUserInfo() 메서드를 호출하는 것만큼 간단합니다.
// add to the existing useState hook.
const [userData, setUserData] = useState({});
const getUserInfo = async () => {
if (!web3auth) {
console.log("web3auth not initialized yet");
return;
}
const user = await web3auth.getUserInfo();
setUserData(user);
};
return (
<div className="App">
<button onClick={getUserInfo}>Get User Info</button>
<div> { userData ? `User Email: ${userData.email}, User Name: ${userData.name}` : ""} </div>
</div>
);
공급자(Provider) 및 서명자(Signer) 객체를 초기화하면 사용자는 임의의 문자열에 서명할 수 있습니다.
// add to the existing useState hook.
const [signedMessage, setSignedMessage] = useState("");
const signMessage = async(e) => {
e.preventDefault();
if (!provider) {
console.log("provider not initialized yet");
return;
}
// this guide uses ethers version 6.3.0.
const ethersProvider = new ethers.BrowserProvider(provider);
// for ethers version below 6.3.0.
// const provider = new ethers.providers.Web3Provider(provider);
const signer = await ethersProvider.getSigner();
const originalMessage = e.target.message.value;
const result = await signer.signMessage(originalMessage);
setSignedMessage(result)
}
return (
<div className="App">
<form onSubmit={signMessage}>
<input type="text" name="message" placeholder="Set message" required/>
<input type="submit" value="Sign Message"/>
</form>
<div>SignedMessage: ${signedMessage}</div>
</div>
);
한 사용자에서 다른 사용자로 KLAY를 보내는 것과 같은 네이티브 트랜잭션을 수행할 수 있습니다.
// add to the existing useState hook.
const [txHash, setTxHash] = useState();
const sendKlay = async () => {
if (!provider) {
console.log("provider not initialized yet");
return;
}
const destination = "paste recipient address";
// this guide uses ethers version 6.3.0.
const ethersProvider = new ethers.BrowserProvider(provider);
// for ethers version below 6.3.0.
// const provider = new ethers.providers.Web3Provider(provider);
const signer = await ethersProvider.getSigner();
// Submit transaction to the blockchain and wait for it to be mined
const tx = await signer.sendTransaction({
to: destination,
value: ethers.parseEther("0.1"),
maxPriorityFeePerGas: "5000000000", // Max priority fee per gas
maxFeePerGas: "6000000000000", // Max fee per gas
})
const receipt = await tx.wait();
setTxHash(receipt.hash)
}
return (
<div className="App">
<button onClick={sendKlay}>Send Klay</button>
<div>Send-Klay Tx Hash : {txHash ? <a href={`https://baobab.scope.klaytn.com/tx/${txHash}`} target="_blank">Klaytnscope</a> : ' ' } </div>
</div>
);
컨트랙트 배포하기
애플리케이션 바이너리 인터페이스(ABI)와 컨트랙트 바이트 코드가 주어지면 스마트 컨트랙트를 배포할 수 있습니다.
// add to the existing useState hook.
const [contractAddress, setContractAddress] = useState(null);
const deployContract = async () => {
if (!provider) {
console.log("provider not initialized yet");
return;
}
// this guide uses ethers version 6.3.0.
const ethersProvider = new ethers.BrowserProvider(provider);
// for ethers version below 6.3.0.
// const provider = new ethers.providers.Web3Provider(provider);
const signer = await ethersProvider.getSigner();
// paste your contractABI
const contractABI = [
{
"inputs": [
{
"internalType": "uint256",
"name": "_initNum",
"type": "uint256"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [],
"name": "retrieve",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "num",
"type": "uint256"
}
],
"name": "store",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]
// Paste your contract byte code
const contractBytecode = '608060405234801561001057600080fd5b506040516102063803806102068339818101604052810190610032919061007a565b80600081905550506100a7565b600080fd5b6000819050919050565b61005781610044565b811461006257600080fd5b50565b6000815190506100748161004e565b92915050565b6000602082840312156100905761008f61003f565b5b600061009e84828501610065565b91505092915050565b610150806100b66000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80632e64cec11461003b5780636057361d14610059575b600080fd5b610043610075565b60405161005091906100a1565b60405180910390f35b610073600480360381019061006e91906100ed565b61007e565b005b60008054905090565b8060008190555050565b6000819050919050565b61009b81610088565b82525050565b60006020820190506100b66000830184610092565b92915050565b600080fd5b6100ca81610088565b81146100d557600080fd5b50565b6000813590506100e7816100c1565b92915050565b600060208284031215610103576101026100bc565b5b6000610111848285016100d8565b9150509291505056fea26469706673582212200370e757ac1c15a024febfa9bf6999504ac6616672ad66bd654e87765f74813e64736f6c63430008120033'
const contractFactory = new ContractFactory(contractABI, contractBytecode, signer);
const contract = await contractFactory.deploy(400);
// get contract address
setContractAddress(contract.target)
}
return (
<div className="App">
<button onClick={deployContract}>Deploy Contract</button>
<div>Contract Address: {contractAddress ? contractAddress : ''} </div>
</div>
);
Web3Auth 공급자 및 서명자 객체를 사용하면 블록체인에 배포된 스마트 컨트랙트에 쓰기 및 읽기와 같은 컨트랙트 상호 작용을 할 수 있습니다.
컨트랙트 작성하기
// add to existing useState hook
const [contractTx, setContractTx] = useState();
const writeToContract = async (e) => {
e.preventDefault();
if (!provider) {
console.log("provider not initialized yet");
return;
}
// this guide uses ethers version 6.3.0.
const ethersProvider = new ethers.BrowserProvider(provider);
// for ethers version below 6.3.0.
// const provider = new ethers.providers.Web3Provider(provider);
const signer = await ethersProvider.getSigner();
// Paste your contractABI
const contractABI = [
{
"inputs": [
{
"internalType": "uint256",
"name": "_initNum",
"type": "uint256"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [],
"name": "retrieve",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "num",
"type": "uint256"
}
],
"name": "store",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]
// Paste your contract address
const contractAddress = "0x3b01E4025B428fFad9481a500BAc36396719092C";
const contract = new ethers.Contract(contractAddress, contractABI, signer);
const value = e.target.store_value.value;
// Send a transaction to smart contract to update the value
const tx = await contract.store(value);
// Wait for the transaction to finish
const receipt = await tx.wait();
const result = receipt.hash;
setContractTx(result)
}
return (
<div className="App">
<form onSubmit={writeToContract}>
<input name="store_value" placeholder="Set contract value" required/>
<input type="submit" value="Store"/>
</form>
<div>Write-to-contract Tx Hash: ${contractTx}</div>
</div>
);
컨트랙트 읽기
// add to existing useState hook
const [contractMessage, setContractMessage] = useState();
const readFromContract = async () => {
if (!provider) {
console.log("provider not initialized yet");
return;
}
// this guide uses ethers version 6.3.0.
const ethersProvider = new ethers.BrowserProvider(provider);
// for ethers version below 6.3.0.
// const provider = new ethers.providers.Web3Provider(provider);
// paste your contract ABI
const contractABI = [
{
"inputs": [
{
"internalType": "uint256",
"name": "_initNum",
"type": "uint256"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [],
"name": "retrieve",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "num",
"type": "uint256"
}
],
"name": "store",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]
// paste your contract address
const contractAddress = "0x3b01E4025B428fFad9481a500BAc36396719092C";
const contract = new ethers.Contract(contractAddress, contractABI, ethersProvider)
// Reading a message from the smart contract
const contractMessage = await contract.retrieve();
setContractMessage(contractMessage.toString())
}
return (
<button onClick={readFromContract}>Read From Contract</button>
<div>Read-from-contract Message: ${contractMessage}</div>
)
Polyfill node core module error
BREAKING CHANGES: webpack<5 used to include polyfills for node.js core modules by default.
이 오류는 Webpack 5 버전을 사용할 때 발생합니다. 이 버전에서는 NodeJS 폴리필이 더 이상 기본적으로 지원되지 않습니다. 이 문제를 해결하려면 해당 가이드를 참조하세요.
Web3Auth에 대한 자세한 가이드는 Web3Auth 문서 및 Web3Auth Github 리포지토리에서 확인할 수 있습니다. 또한 이 가이드에 대한 전체 코드 구현은 GitHub에서 확인할 수 있습니다.