1、创建utils文件夹在这个文件夹下创建web3.ts文件:
import { ethers } from 'ethers'
import { ExternalProvider, JsonRpcFetchFunc } from '@ethersproject/providers';
import { InjectedConnector } from '@web3-react/injected-connector'
// 提供一个provider转成web3provider
export const getLibray = (provider: ExternalProvider | JsonRpcFetchFunc) => {
const web3Provider = new ethers.providers.Web3Provider(provider)
return web3Provider
}
export const InjectConnector = new InjectedConnector({ supportedChainIds: [56] })
2、创建chain文件夹,在这个文件夹下创建一个index.ts文件:
// 支持的链
export const SuportChain = {
eth: {
chanId: 1,
name: 'eth'
},
bsc: {
chainId: 56,
name: 'bsc'
},
polygon: {
chainId: 56,
name: 'polygon'
}
}
// 链id 网络id
export enum NetworkID {
// 主网
Mainnet = 56,
// 测试网
Testnet = 97
}
export enum SUPPORT_CHAIN {
BSC = 56,
BSCTEST = 97
}
// 当前链ID
export const CURRENT_CHAIN = 56
// MetaMask 中 request 请求中的 methods 方法
export enum MetaMaskRequestMethods {
// 添加在metamask中不存在的链
addEthereumChain = "wallet_addEthereumChain",
// 吧Token代币添加到钱包中
watchAsset = 'wallet_watchAsset',
// 获取当前链接的网络Id
chainId = 'eth_chainId',
// eth_requestAccunts 获取账号(可以理解为链接钱包)
requestAccount = 'eth_requestAccounts',
// 获取账户地址
accounts = 'eth_accounts',
// 获取最新区块编号
blockNumber = 'eth_blockNumber'
}
// 添加一条链到metamask上时请求网络参数
export const AddEthereumChainParams: { [key: number]: any } = {
8: {
chainId: '0x8',
chainName: 'Ubiq',
chativeCurrency: {
name: 'Ubiq Ether',
symbol: 'BUQ',
decimals: 18,
},
rpcUrl: ['https://rpc.octano.dev/'],
blockExplorerUrls: ['https://ubiqscan.io/']
},
56: {
chainId: '0x38',
chainName: 'Binance Smart Chain Mainnet',
nativeCurrency: {
name: 'BNB',
symbol: 'bnb',
decimals: 18
},
rpcUrls: ['https://bsc-dataseed1.ninicoin.io', 'https://bsc-dataseed1.defibit.io', 'https://bsc-dataseed.binance.org'],
blockExplorerUrls: ['https://bscscan.com/'],
}
}
3、在react-app-env.d.ts内添加:
/// <reference types="react-scripts" />
interface Window {
ethereum?:{
isMetaMask?:true
request?:(...args:any[])=>Promise<void>
}
BinanceChain?:{
bnbSign?:(address:string,message:string) => Promise<{publicKey:string;signature:string}>
}
web3:any
}
4、创建types文件夹,在这个文件夹中创建ethereum.tsx文件:
type EthereumProviderEip1193 = {
request: (args: {
method: string
params?: unknown[] | object
}) => Promise<unknown>
}
type EthereumProviderSend = {
send: (method: string, params: string[]) => Promise<unknown>
}
type EthereumProviderSendAsync = {
sendAsync: (
params: {
method: string
params: string[]
from: string
jsonrpc: '2.0'
id: number
},
callback: (err: Error, result: unknown) => void
) => void
selectedAddress: string
}
/**
* window.ethereum 类型
* Eip-1193 规范
*/
export type EthereumProvider = EthereumProviderEip1193 &
EthereumProviderSend &
EthereumProviderSendAsync
5、再到utils文件夹中创建ethereum.ts文件:
import { AddEthereumChainParams, MetaMaskRequestMethods } from "chain";
import { EthereumProvider } from "types/ethereum";
function isUnwrappedRpcResult(response: unknown): response is {
error?: string
result?: unknown
} {
return (
typeof response === 'object' && response !== null && 'jsonrpc' in response
)
}
/**
* 防止有的客户端没有包裹response
*/
export function rpcResult(response: unknown): unknown | null {
// Some providers don’t wrap the response
if (isUnwrappedRpcResult(response)) {
if (response.error) {
throw new Error(response.error)
}
return response.result || null
}
return response || null
}
/**
* metamask request 方法封装
* @param ethereum provider, 浏览器中使用window.ethereum
* @param method 请求方法
* @param params 参数
* @returns
*/
export async function ethereumRequest(
ethereum: EthereumProvider,
method: string,
params: string[]
): Promise<any> {
// If ethereum.request() exists, the provider is probably EIP-1193 compliant.
if (ethereum.request) {
return ethereum.request({ method, params }).then(rpcResult)
}
// This is specific to some older versions of MetaMask combined with Web3.js.
if (ethereum.sendAsync && ethereum.selectedAddress) {
return new Promise((resolve, reject) => {
ethereum.sendAsync(
{
method,
params,
from: ethereum.selectedAddress,
jsonrpc: '2.0',
id: 0,
},
(err: Error, result: any) => {
if (err) {
reject(err)
} else {
resolve(result)
}
}
)
}).then(rpcResult)
}
// If none of the previous two exist, we assume the provider is pre EIP-1193,
// using .send() rather than .request().
if (ethereum.send) {
return ethereum.send(method, params).then(rpcResult)
}
throw new Error(
'The Ethereum provider doesn’t seem to provide a request method.'
)
}
/**
* 获取区块编码
* @param ethereum provider, 默认使用window.ethereum
* @returns
*/
export async function getBlockNumber(ethereum?: EthereumProvider) {
ethereum = ethereum ?? window.ethereum as any
return ethereumRequest(ethereum!, MetaMaskRequestMethods.blockNumber, [])
}
/**
* 添加链到metamask 上
*/
export async function addChainToBlock(id: number, ethereum?: EthereumProvider) {
ethereum = ethereum ?? window.ethereum as any
const params = AddEthereumChainParams[id]
// ! 确保ethereum 部位null
return ethereumRequest(ethereum!, MetaMaskRequestMethods.addEthereumChain, [params])
}
6、在创建hooks文件夹,在这个文件夹里创建useAuth.ts:
import { UnsupportedChainIdError, useWeb3React } from '@web3-react/core'
import { InjectConnector } from '../utils/web3'
import { addChainToBlock } from 'utils/ethereum'
export const useAuth = () => {
const { activate } = useWeb3React()
const Login = () => {
if (InjectConnector) {
activate(InjectConnector, async (error: Error) => {
if (error instanceof UnsupportedChainIdError) {
const hasSetup = await addChainToBlock(56)
if (hasSetup) {
activate(InjectConnector)
}
}
})
}
}
return Login
}
然后再src目录下的index.tsx文件下这么写:
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
// 这下边的两个是添加的引入文件
import { getLibray } from "./utils/web3";
import { Web3ReactProvider } from "@web3-react/core";
ReactDOM.render(
<React.StrictMode>
{/* 在这里用 Web3ReactProvider 包裹 app 文件 */}
<Web3ReactProvider getLibrary={getLibray}>
<App />
</Web3ReactProvider>
</React.StrictMode>,
document.getElementById("root")
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
在然后再你需要获取MetaMask小狐狸地址的地方这么写:
import React, { useEffect } from "react";
import "./App.css";
import { useWeb3React } from "@web3-react/core";
import { useAuth } from "hooks/useAuth";
function App() {
const Login = useAuth();
const { account, library, chainId } = useWeb3React();
console.log("地址1", account);
const GetClick = () => {
Login();
console.log("地址2", account);
};
useEffect(() => {
Login();
}, []);
return (
<div className="App">
<button onClick={GetClick}>获取钱包地址</button>
</div>
);
}
export default App;
你只需要按我说的创建文件夹步骤复制代码,就可以链接到你的小狐狸了,记得要在tsconfig.json文件中添加"baseUrl": "src",
希望我能帮到你。我技术有限,有不对的地方请在评论区指教;