js连接web3,连接小狐狸metamask钱包,实现链不对后切换网络和创建网络
前言:在今天之前,用metamask检测链不对,并且自动切换网络和创建网络的功能,从来没有真正自己实践一次。
核心代码:
import { useWeb3React } from "@web3-react/core";
// 从这句看出用的库web3-react,既不是web3js,也不是etherjs
export default function WalletModal({ isOpen, onClose }: UseModalProps) { const { activate } = useWeb3React(); function getOptions() { const option = SUPPORTED_WALLETS["METAMASK"]; return ( <VStack> <Button variant="outline" onClick={async () => { activate(option.connector); onClose(); if (window.ethereum) { try { await (window.ethereum as any).request({ method: 'wallet_switchEthereumChain', params: [{ chainId: "0x41" // 目标链ID }] }) console.log('wallet_switchEthereumChain'); } catch (e) { console.log('(e as any).code', (e as any).code); if ((e as any).code === 4902) { try { console.log('wallet_addEthereumChain'); await (window.ethereum as any).request({ method: 'wallet_addEthereumChain', params: [ { chainId: "0x41", // 目标链ID chainName: 'OKC Testnet', nativeCurrency: { name: 'OKT', symbol: 'OKT', decimals: 18 }, rpcUrls: ['https://exchaintestrpc.okex.org'], // 节点 blockExplorerUrls: ['https://www.oklink.com/zh-cn/okc-test'] } ] }) } catch (ee) { // } } else if ((e as any).code === 4001) return } } }} w="100%" > <HStack w="100%" justifyContent="center"> <Image src={option.iconURL} alt="Metamask Logo" width={25} height={25} borderRadius="3px" /> <Text>Metamask</Text> </HStack> </Button> </VStack> ); } return ( <Modal isOpen={isOpen} onClose={onClose} isCentered> <ModalOverlay /> <ModalContent w="300px"> <ModalHeader>Select Wallet</ModalHeader> <ModalCloseButton _focus={{ boxShadow: "none", }} /> <ModalBody paddingBottom="1.5rem">{getOptions()}</ModalBody> </ModalContent> </Modal> ); }
注意:
配置中的chainId,rpcUrls和blockExplorerUrls三个值,特别注意。
chainId是16进制。
rpcUrls和blockExplorerUrls必须是https。
此时会报错:
`Property 'ethereum' does not exist on type 'Window & typeof globalThis'` error in React
分析:window.ethereum不存在。
解决办法:
src/react-app-env.d.ts 添加如下内容
/// <reference types="react-scripts" /> import { ExternalProvider } from "@ethersproject/providers"; declare global { interface Window { ethereum?: ExternalProvider; } }
代码的含义是:
先切换网络到指定chainId,如果chainId存在,则切换成功;如果不存在,则添加新网络。
另一种写法:把window.ethereum换为currentProvider。
await (window.ethereum as any).request({}) 改为
currentProvider.send({})
如下所示:
currentProvider.send({ "method": "wallet_addEthereumChain", "params": [ { "chainId": "0x42", "chainName": "OKC Main", "rpcUrls": ["https://exchainrpc.okex.org/"], "nativeCurrency": { "name": "OKT", "symbol": "OKT", "decimals": 18 }, "blockExplorerUrls": ["https://www.oklink.com/okc"] } ] })
参考:
https://blog.csdn.net/github_38633141/article/details/124023708
https://codeleading.com/article/10766257519/
https://okc-docs.readthedocs.io/en/latest/developers/blockchainDetail/rpc.html