D Web3 시리즈
3D-web3 시리즈의 마지막 포스팅입니다.
1 -
2 -
삼 -
4 - 3D 웹 - react-web3
안정적인 버전은 v6이며 현재 v8은 베타 버전입니다.
Uniswap 엔지니어링 책임자인 Noah Zinsmeister가 개발했습니다.
높은 수준에서 web3-react는 dApp과 관련된 특정 주요 데이터(예: 사용자의 현재 계정)가 최신 상태로 유지되도록 하는 상태 머신입니다. 이를 위해 web3-react는 Context를 사용하여 이 데이터를 효율적으로 저장하고 애플리케이션에서 필요할 때마다 주입합니다.
Web3-react v6은 컨텍스트를 사용하여 이 데이터를 효율적으로 저장하고 애플리케이션에서 필요할 때마다 주입합니다.
유용한 링크:
Uniswap/web3-reactsource code
Uniswap/web3-reactdocuments
How to Use Web3React in Your Next Project
다음과 같이 web3 환경을 만드는 다른 여러 라이브러리가 있습니다.
Rainbowkit || Wagmi || Scaffold-eth || useDApp || web3modal || Web3-UI
우리는 배후에서 Ethers.js를 사용하고 있습니다. DApp에서 컨텍스트를 유지하고 블록체인과 쉽게 연결하기 위해. 또한 다양한 종류의 블록체인 공급자, 지갑 또는 체인을 연결하고 블록체인을 보다 효율적으로 쿼리합니다.
어쨌든 이더를 사용하여 전체 DApp을 직접 구축할 수 있습니다.
우리는 다음을 사용할 것입니다:
사용자 측의 MaskMask 지갑
이더리움 웹 클라이언트 라이브러리 - "@web3-react", "ethersproject"
npm i @web3-react/core @web3-react/injected-connector
npm i @ethersproject/contracts @ethersproject/providers
npm i events
이 데모에서는 동일한 토큰을 BSC 테스트넷과 뭄바이(폴리곤 테스트넷)에 배포하고 있습니다.
먼저 브라우저에 메타마스크, TrustWallet(WalletConnect) 또는 코인베이스 확장 프로그램이 설치되어 있어야 합니다.
@Notice WalletConnect establishes an encrypted connection between your wallet and the DApp. Use it with Ex. with "Trust Wallet"
You can check all css details in . This article focuses on the web3 connection.
1단계_ 모든 구성 요소 자식에 대한 web3 컨텍스트 생성
컨텍스트 제공자 추가
web3-react relies on the existence of a Web3ReactProvider at the root of your application.
저수준 공급자에서 web3 편의 라이브러리 개체를 인스턴스화하는 단일 getLibrary 소품이 필요합니다.
import React, { useEffect } from 'react';
import { Web3ReactProvider } from '@web3-react/core'
import { Web3Provider } from '@ethersproject/providers'
function getLibrary(provider) {
const library = new Web3Provider(provider)
library.pollingInterval = 12000
return library
}
function Web3ContextProvider({ children }) {
return (
<Web3ReactProvider getLibrary={getLibrary}>
{children}
</Web3ReactProvider>
)
}
export default Web3ContextProvider
App.jsx에 추가
import Web3ContextProvider from './web3/Web3ContextProvider';
import ConnectWallet from './web3/ConnectWallet';
return (
...
<Web3ContextProvider style={{ height: '15vh' }} className='header'>
<ConnectWallet />
</Web3ContextProvider>
...
)
2단계_ Web3 개체 인스턴스화 및 메서드 정의
ConnectWallet.jsx 생성
"useWeb3React"를 사용하여 "InjectedConnector"를 사용하여 블록체인에 연결합니다.
MetaMask를 사용하면 "windows.ethereum"을 통해 공급자에게 연락할 수 있습니다.
지갑을 연결하고 연결 해제하는 버튼과 현재 체인을 변경할 수 있는 버튼을 제공합니다.
import { useEffect } from 'react'
import { useWeb3React } from '@web3-react/core'
import { InjectedConnector } from '@web3-react/injected-connector'
import "../App.css"
import "../Button.css"
import "../Select.css"
import { changeChainById } from "./transaction/chains"
import ClaimToken from "./ClaimToken"
const ConnectWallet = () => {
const injectedConnector = new InjectedConnector({
supportedChainIds: [1, 97, 80001],
})
const { chainId, account, activate, active, library, deactivate, connector } = useWeb3React()
const activateWallet = () => {
activate(injectedConnector)
}
const deactivateWallet = () => {
deactivate(injectedConnector)
}
const changeChain = (_chainID) => {
changeChainById(_chainID)
}
useEffect(() => {
if (!chainId) return
document.getElementById('select-form').value = chainId
}, [chainId])
return (
<main className="web3-navbar">
<h2 >Welcome to 3D web3 series</h2>
<div className='connect-box'>
<b>ChainId: {chainId}</b>
<div>Account: {account}</div>
{active ? (
<button type="button" className='button-4' onClick={deactivateWallet}>
Disconnect
</button>
) : (
<button type="button" className='button-3' onClick={activateWallet}>
Connect Wallet
</button>
)}
</div>
<div className='box'>
<select id='select-form' onChange={e => {
let _chainID = e.target.value
changeChain(_chainID)
}}>
<option key={1} value={1}>Ethereum Chain</option>
<option key={97} value={97}>BSC testnet</option>
<option key={80001} value={80001}>Mumbai testnet</option>
</select>
</div>
<div>
<ClaimToken
account={account}
chainId={chainId}
/>
</div>
</main>
)
}
export default ConnectWallet
3단계_ 체인간 추가 및 변경 방법.
우리가 사용하고 있는 다른 블록체인metamask RPC API's 사이를 전환하기 위해 메소드를 구축했습니다.
"wallet_switchEthereumChain"메서드를 호출하여 사용자에게 체인 변경을 요청합니다.
사용자가 특정 체인을 구성하지 않은 경우 "wallet_addEthereumChain"메서드를 잡아서 호출하여 사용자에게 선택한 체인을 추가하도록 요청합니다.
@알아채다. tryCatch를 사용하십시오. 이를 처리하기 위해 일부 반복되는 오류가 있습니다here.
체인을 변경/추가하기 위해서는 체인 정보를 제공해야 합니다. 코드를 체크인하십시오.
export const changeChainById = async (chainID) => {
if (!window.ethereum)
return alert("install metamask extension in your browser");
try {
await ethereum.request({
method: "wallet_switchEthereumChain",
params: [{ chainId: chains[chainID].chainId }],
});
} catch (switchError) {
// This error code indicates that the chain has not been added to MetaMask.
if (switchError.code === 4902) {
try {
await ethereum.request({
method: "wallet_addEthereumChain",
params: [chains[chainID]],
});
} catch (addError) {
console.log("error: ", addError);
if (ex.code === 32002)
return alert("already pending request from user in metamask");
else
return alert(
"Disconnect wallet from metamask configuration and try again!"
);
}
}
// handle other "switch" errors
}
return;
};
const ETH = {
name: "Ether",
symbol: "ETH",
decimals: 18,
};
const MATIC = {
name: "Matic",
symbol: "MATIC",
decimals: 18,
};
const BNB = {
name: "Binance",
symbol: "BNB",
decimals: 18,
};
const chains = {
1: {
chainId: "0x1",
chainName: "Ethereum mainnet",
nativeCurrency: ETH,
rpcUrls: [
import.meta.env.VITE_APP_INFURA_KEY
? `https://mainnet.infura.io/v3/${import.meta.env.VITE_APP_INFURA_KEY}`
: undefined,
import.meta.env.VITE_APP_ALCHEMY_KEY
? `https://eth-mainnet.alchemyapi.io/v2/${
import.meta.env.VITE_APP_ALCHEMY_KEY
}`
: undefined,
"https://cloudflare-eth.com",
].filter((url) => url !== undefined),
blockExplorerUrls: ["https://etherscan.com/"],
},
97: {
chainId: "0x61",
chainName: "Binance Testnet",
nativeCurrency: BNB,
rpcUrls: [
"https://data-seed-prebsc-1-s1.binance.org:8545/",
"https://data-seed-prebsc-2-s1.binance.org:8545/",
"http://data-seed-prebsc-1-s2.binance.org:8545/",
"https://data-seed-prebsc-2-s3.binance.org:8545/",
],
// rpcUrls: 'https://data-seed-prebsc-1-s1.binance.org:8545',
blockExplorerUrls: ["https://testnet.bscscan.com/"],
},
80001: {
chainId: "0x13881",
chainName: "Polygon Mumbai",
nativeCurrency: MATIC,
rpcUrls: [
import.meta.env.VITE_APP_INFURA_KEY
? `https://polygon-mumbai.infura.io/v3/${
import.meta.env.VITE_APP_INFURA_KEY
}`
: undefined,
].filter((url) => url !== undefined),
blockExplorerUrls: ["https://mumbai.polygonscan.com/"],
},
};
4단계_ 트랜잭션 정의
UI를 정의하는 ClaimToken.jsx 구성 요소를 만듭니다.
import { burnToken, claimToken } from './transaction/transaction'
import "../App.css"
export default function TransactionMetaMask(props) {
const claimTokenTx = () => {
if (props.chainId === 97 || props.chainId === 80001) {
claimToken(props.provider, props.account, props.chainId, 1)
} else {
scrollTo(0, 0)
alert('Tokens are only available in BSC and Polygon testnets')
}
}
const burnTokenTx = () => {
if (props.chainId === 97 || props.chainId === 80001) {
burnToken(props.provider, props.account, props.chainId, 1)
} else {
scrollTo(0, 0)
alert('Tokens are only available in BSC and Polygon testnets')
}
}
return (
<div className='token-buttons'>
<button type="button" className='button-3' onClick={claimTokenTx}>
Claim Token
</button>
<button type="button" className='button-3' onClick={burnTokenTx}>
Burn Token
</button>
</div>
)
}
트랜잭션을 보내 블록체인 데이터를 수정하려면 "@ethersproject/providers"에서 직접 공급자를 가져와서 "서명자"개체를 생성할 수 있습니다.
이제 스마트 계약 주소, ABI 및 서명자를 사용하여 "계약"개체를 만듭니다(계약 메서드와 상호 작용할 준비가 됨).
import { Contract } from "@ethersproject/contracts";
import { Web3Provider } from "@ethersproject/providers";
// Same ABI for all SC living in EVM compatible networks
export const contractAbi = [...];
const contractsAddress = {
80001: "0x41e6913ce749018910e45980996dac1f99012c96", // MUMBAI
97: "0x6ec4c5ce6cc67729d89785f715e103e5981c9780", // BSC Test
};
// TODO
export const getContract = (chainId) => {
// using ethersproject to set signer using default provider
const provider = new Web3Provider(window.ethereum);
const signer = provider.getSigner();
const contractAddress = contractsAddress[chainId];
const contract = new Contract(contractAddress, contractAbi, signer);
return contract;
};
마지막으로 비동기 RPC를 보내고 모든 오류를 포착합니다.
import { getContract } from "./contract";
// writeToContractUsingWeb3React
const claimToken = async (account, chainId, amount) => {
try {
const myContract = getContract(chainId);
// Metamask calculates gas, but, for walletConnect and coinbase we need to set gas limit
const overrides = {
gasLimit: 230000,
};
const txResponse = await myContract.mint(account, amount, overrides);
const txReceipt = await txResponse.wait();
console.log(txReceipt);
// alert(txReceipt);
} catch (ex) {
console.log(ex);
if (ex.code === 32002)
return alert("already pending request from user in metamask");
if (ex.code === 4001) return alert("User denied transaction signature");
return alert('"Connect / Disconnect" your wallet and try again.');
}
};
const burnToken = async (chainId, amount) => {
try {
const myContract = getContract(chainId);
// Metamask calculates gas, but, for walletConnect and coinbase we need to set gas limit
const overrides = {
gasLimit: 230000,
};
const txResponse = await myContract.burn(amount, overrides);
const txReceipt = await txResponse.wait();
console.log(txReceipt);
// alert(txReceipt);
} catch (ex) {
console.log(ex);
if (ex.code === 32002)
return alert("already pending request from user in metamask");
if (ex.code === 4001) return alert("User denied transaction signature");
return alert('"Connect / Disconnect" your wallet and try again.');
}
};
export { claimToken, burnToken };
이제 저장소를 포크하고 localy를 시도하십시오.
npm install
// add to .env.local
// VITE_APP_INFURA_KEY
// VITE_APP_ALCHEMY_KEY
npm run dev
또는 Code Sand Box 데모를 확인하십시오.
RPC 공급자는 수시로 비활성화될 수 있습니다.
이 경우 infura 또는 alchemy에서 자체 무료 RPC API를 제공하십시오.
BSC 테스트넷 토큰 주소, bscscan
뭄바이 토큰 주소, polygonscan
도움이 되었기를 바랍니다.
Reference
이 문제에 관하여(D Web3 시리즈), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/uigla/3d-web-react-web3-44e7텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)