ether.js使用-前端如何与智能合约交互

2,272 阅读2分钟

后端

通过Remix IDE来编译智能合约。

它可以从浏览器在线编写、测试、部署Solidity合约,无需配置

  • 编写智能合约

    image-20230211210032065

    这里编写一个最简单的计数器合约

  • 编译

    image-20230211210347430

    这里编译的版本和合约上的版本需要对应

  • 部署

    image-20230211210702634

    image-20230211211242010

    部署到本地服务Ganache,需要注意服务器在本地的端口号,对应编辑器

到这里,我们的后端合约就部署完成了,接下来介绍前端如何与合约进行交互

前端

MetaMask介绍

在Ethereum上进行实验和开始开发的最快速和最简单的方法是使用MetaMask,它是一个浏览器扩展

1.安装ethers库

ehers.js是web3.js的替代品,用来与合约交互。用户通过编写 JavaScript 代码就可以与区块链进行交互,包括读写等操作。

npm i ethers

2.检测是否安装MetaMask

可以通过浏览器控制台全局访问 ethereum,如果有值,则说明已经安装

image-20230211181405136

接下来通过前端的方式,检测全局环境下有没有安装MetaMask

<script setup>
const login = ()=>{
  const {ethereum} = window
  if(ethereum){
    console.log("已安装metamask钱包");
  }else{
    console.log("未安装metamask钱包");
  }
}
</script><template>
  <h1>基于web3的前端交互</h1><h2 @click="login">登录</h2>
</template>

点击登录,此时我的浏览器中已经安装

image-20230211182611341

3.引入

  • 引入ethers

  • 定义函数,操作web与合约交互的环境的提供者

    const Provider = ()=>{
      return new ethers.provider.Web3Provider(window.ethereum)
    }
    

    将本地的metamask注入到 Provider中,后续用过metamask来操作

  • 登录metamask

    await Provider().send("eth_requestAccounts",[])

    拉起metamask登录,登录成功返回钱包地址

4.获取ABI、Address

  • 在Remix中,获取写好的合约ABI,ABI是合约函数的结构

image-20230211185204383

  • 获取链上地址

    image-20230211203138593

image-20230211185547714

5.获取合约

用过 ethers.Contract调用合约,传入三个参数:contractAddress、contractABI、signer

// 获取合约
const Conctract = ()=>{
  const Provider = this.Provider
  // 导入签名
  const signer = Provider.getSigner()
  // 获取合约,参数:contractAddress、contractABI、signer
  const Contract = ethers.Contract(contractAddress,contractABI,signer)
  return Contract;
}
​

6.执行合约方法

// 调用合约
const count = ref(0)
// 获取count
const getCount = async ()=>{
  // 实例化合约
  const Contract = Conctract()
  // 调用合约中的方法
  const res = await Contract.get_count()
  count.value = res.toNumber()
}
getCount()
​
const addCount = async ()=>{
  const Contract = Conctract()
  const res = await Contract.add_count()
  await res.wait()
  await getCount()
} 
setTimeout(() => {
  addCount
}, 2000);