Ether.js+Web3modal基础使用

1.说明

  1. 现在网站会提供很多种钱包,web3modal可以提供统一的provider,不需要你操心太多东西

  2. 用ether.js而不是web3.js的原因是简单,爽

2.安装

npm i web3modal
npm i ethers
//另外还需要安装对应wallet的包,自行搜索就行

3.连接钱包

// MM默认就有,无需显式加入
const providerOptions = {
  walletconnect: {
    package: walletconnectProvider,
    options: {
      infuraId: "",
    },
  },
};
//构建Web3Modal对象
const web3Modal = new Web3Modal({
  //缓存provider
  cacheProvider: true,
  providerOptions,
});

//连接wallet
async function connect() {
  try {
    const web3ModalProvider = await web3Modal.connect();
    provider = new ethers.providers.Web3Provider(web3ModalProvider);
    //注册监听,比如disconnect,accountsChanged,chainChanged
    registerEthListener(web3ModalProvider);
    //主要是处理业务上的需求
    updateCurrentStatus(await provider.listAccounts());
  } catch (error) {
    console.log(error);
  }
}

4.上面的registerEthListener

//可以根据自己的需要些具体的内容
function registerEthListener(web3ModalProvider) {
  web3ModalProvider
    .on("disconnect", (error) => {
      
    })
    .on("accountsChanged", (accounts) => {
      
    })
    .on("chainChanged", (chainId) => {
      
    });
}

5.切换网络&添加网络

//你需要的network信息
const networkInfo = {
  localhardhat: {
    //这里一定要16进制,不然报错
    chainId: "0x539",
    chainName: "LOCALHARDHAT",
    nativeCurrency: {
      name: "LOCALHARDHAT",
      symbol: "LH",
      decimals: 18,
    },
    rpcUrls: ["http://192.168.50.36:8545/"],
    blockExplorerUrls: ["http://192.168.50.36:8545/"],
  },
  matic: {
    chainId: "0x89",
    chainName: "Ploygon",
    nativeCurrency: {
      name: "MATIC",
      symbol: "MATIC",
      decimals: 18,
    },
    rpcUrls: ["https://rpc-mainnet.maticvigil.com/"],
    blockExplorerUrls: ["https://polygonscan.com/"],
  },
};
//切换网络
//walletProvider是上面的web3ModalProvider,而不是ethers获取的provider
async function switchNetwork(network, walletProvider) {
  try {
    await walletProvider.request({
      method: "wallet_switchEthereumChain",
      params: [{ chainId: networkInfo[network].chainId }],
    });
  } catch (error) {
    console.log(error);
    if ((error.code = 4902)) {
      return await addNetwork(network, walletProvider);
    }
    throw error;
  }
}
//添加网络
async function addNetwork(network, walletProvider) {
  try {
    return await walletProvider.request({
      method: "wallet_addEthereumChain",
      params: [networkInfo[network]],
    });
  } catch (error) {
    console.log(error);
  }
}

6.预估Gas调用合约写方法

  1. 这里要引入一个number包用于计算

npm i big-number
//引入项目
import BigNumber from "bignumber.js";
//预估gas,并且调用合约
//functionName:你要调用的方法,如safeMint
//args:调用合约的参数,array类型,例如[arg1, arg2, arg3, {}],最后的{}不能少,函数中会将计算出来的gas要放里面,如果要传入eth,则最后的{}为{value:xxx}
async function executeContractMethosWithEstimatedGas(
  functionName,
  args
) {
//合约信息,provider是连接ethers时的
  const contract=new ethers.Contract(contractAddress,contractAbi,provider);

  const estimatedGas = new BigNumber(
    ethersOf(
      await contract.estimateGasfunctionName
        .then((value) => {
          const minimumGas = ethers.BigNumber.from("300000");
          if (value.lt(minimumGas)) {
            return minimumGas;
          }
          return values;
        })
        .catch((error) => {
          //出错时给个固定值
          return ethers.BigNumber.from("700000");
        })
    )
  );
//将计算结果放入参数中
  const argsForOverridden = args.pop();
  args.gasLimit = parseEthers(estimatedGas.times(1.2).toString());
  args.push(argsForOverridden);
  return contract.connect(getSigner())functionName;
}
//以下是周边函数
function getSigner(){
  if(!provider){
    console.log("please connect awallet first");
    return;
  }
  return provider.getSigner();
}

function parseUnits(amount,unit){
  const bnAmount=new BigNumber(amount);
  try {
    return ethers.utils.parseUnits(bnAmount.toFixed(unit),unit);
  } catch (error) {
    return ethers.BigNumber.from(bnAmount.times(Math.pow(10,unit)).toFixed(0));
  }
}
const ETHER_DECIMALS=18;
function parseEthers(amount){
  return parseUnits(amount,ETHER_DECIMALS);
}

function ethersOf(amount){
  return ethers.utils.formatEther(amount);
}

7.网络确认

说明:一个写操作分为两步。1.提交执行,2.网络确认。类似uni页面操作后会有pending

//tx是上面executeContractMethosWithEstimatedGas会返回的结果
async function waitForTransaction(tx){
  //2是网络确认数量,自定义
  return await provider.waitForTransaction(tx.hash,2);
}

以上就是一些基础操作,还有个读合约,那个别的网站都有,就没贴了

签名:

https://mirror.xyz/0xE3a463d743F762D538031BAD3f1E748BB41f96ec/S1CbvnSfUIMKk1CkUr9nQDiT_YN1iHMGsL2IlJE3KGw