DApp开发入门

作者: mirrorzyb | 来源:发表于2021-10-01 21:40 被阅读0次

    近一两年随着DeFi的火热,DApp开发也受到越来越多的关注,单纯从概念来说,DApp还是比较容易理解的,也就是App + decentralization(去中心化)。而去中心化我个人认为主要体现在两个方面,一是账户体系,二是服务或数据

    账户体系也就是我们的钱包账户。

    服务或数据,则对应我们的智能合约以及链上数据,获取这些数据非常简单,不需要Token认证,也不需要session,cookie,一切都是可以公开访问的,甚至你可以直接在一些区块链浏览器直接操作合约。

    本文仅介绍以太坊系列的DApp开发,其他链原理差不太多。

    目标

    1. 了解一些基础的区块链概念和操作
    2. 熟悉与MetaMask钱包的交互
    3. 了解ERC20 Token、并与ERC20合约进行交互
    4. 在Mdex的某个矿池中抵押LP Token(流动性证明),赎回LP Token

    环境与工具

    1. 需要安装MetaMask钱包并创建或导入账号
    2. ethers.js (与以太坊区块链及其生态系统进行交互的JavaScript库),也可以用web3.js
    3. create-react-app(demo相关)
    4. Heco区块链浏览器

    钱包操作

    MetaMask安装完成并运行后,可以在Chrome控制台打印MetaMask注入的window.ethereum对象

    截屏2021-06-04 上午10.55.39.png

    关于ethereum对象,我们只需要关心ethereum.request就足够了,MetaMask 使用ethereum.request(args)方法来包装 RPC API。这些 API 基于所有以太坊客户端公开的接口。 简单来说钱包交互的大部分操作都是由request()方法实现,通过传入不同的方法名来区分。

    ⚠️即使ethereum对象中提供了chainId,isMetaMask,selectAddress属性,我们也不能完全相信这些属性,他们是不稳定或不标准,不建议使用。我们可以通过上面说的request方法,拿到可靠的数据

    钱包通过method方法名,进行对应的实现 以获取钱包地址为例

    调用ethereum.request({ method: "eth_requestAccounts" }),钱包实现了该方法,那么就可以拿到钱包的地址了。

    case "eth_requestAccounts":
        return ["0xFD513D86a57BAFeAf46ddcC1bDDf629409A03cCf"]
    

    常见的钱包操作

    1. 连接钱包

      const accounts = await ethereum.request({ method: "eth_requestAccounts" });
      const account = accounts[0];
      
    2. 监听网络和账号切换事件

      //监听账户变化
      ethereum.on("accountsChanged", (accounts) => {
        setAccount(accounts[0]);
      });
      //监听网络变化
      ethereum.on("chainChanged", (chainId) => {
        setChainId(chainId);
      });
      
    3. 添加自定义代币(添加自己的平台币到钱包账户,是个非常方便的功能。基于EIP-747

      const Dog = {
        symbol: "Dog",
        decimals: 18,
        image: "https://hecoinfo.com/token/images/dogtoken_32.png",
        address: "0xb3863e02d6930762933f672ca134c1ccecd0d413",
      };
      
      ethereum.request({
        method: "wallet_watchAsset",
        params: {
          type: "ERC20", // Initially only supports ERC20, but eventually more!
          options: Dog,
        },
      });
      
    1. 添加自定义网络(像Mdex支持同时支持ETH、HECO、BSC,MetaMask只有ETH主网和测试网,可以直接通过此协议增加对应的网络到钱包,如果钱包支持的话,基于EIP-3085仅支持非内置网络),社区目前有个EIP-3326提案,可以直接在以太坊网络进行切换。

      const Dog = {
        symbol: "Dog",
        decimals: 18,
        image: "https://hecoinfo.com/token/images/dogtoken_32.png",
        address: "0xb3863e02d6930762933f672ca134c1ccecd0d413",
      };
      
      ethereum.request({
        method: "wallet_watchAsset",
        params: {
          type: "ERC20", // Initially only supports ERC20, but eventually more!
          options: Dog,
        },
      });
      

    Provider

    Provider 是一个连接以太坊网络的抽象,用与查询以太坊网络状态或者发送更改状态的交易。

    MetaMask注入的window.ethereum就是一个Provider,一个RPC节点也是一个Provider,通过Provider,我们有了访问区块链的能力。 在连接到钱包的情况下,通常使用钱包的Provider就可以了,ethers.providers.Web3Provider(ethereum)

    如果只需要查询一些区块链数据,可以使用EtherscanProvider 和 InfuraProvider 连接公开的第三方节点服务提供商。JsonRpcProvider 和 IpcProvider 允许连接到我们控制或可以访问的以太坊节点。

    获取当前账户余额

    const balance = await provider.getBalance(account);
    

    获取最新区块号

    const blockNumber = await provider.getBlockNumber();
    

    其他RPC操作,可以通过JSON-RPC查看。

    ERC20 Token

    ERC20 通证标准(ERC20 Token Standard)是通过以太坊创建通证时的一种规范。按照ERC20的规范可以编写一个智能合约,创建"可互换通证"。它并非强制要求,但遵循这个标准,所创建的通证可以与众多交易所,钱包等进行交互。目前的平台币基本都遵循ERC20标准。

    contract ERC20 {
          function name() constant returns (string name)
          function symbol() constant returns (string symbol)
          function decimals() constant returns (uint8 decimals)
          function totalSupply() constant returns (uint totalSupply);
          function balanceOf(address _owner) constant returns (uint balance);
          function transfer(address _to, uint _value) returns (bool success);
          function transferFrom(address _from, address _to, uint _value) returns (bool success);
          function approve(address _spender, uint _value) returns (bool success);
          function allowance(address _owner, address _spender) constant returns (uint remaining);
          event Transfer(address indexed _from, address indexed _to, uint _value);
          event Approval(address indexed _owner, address indexed _spender, uint _value);
    }
    

    通过ethers.js可以连接ERC20的合约,合约编译后会生成ABI,合约部署后,会生成合约地址,开发者通过ABI和合约地址,对合约发送消息。

    合约中的方法大致分为两种:视图方法(免费),非视图方法(消耗Gas),可以通过ABI查看方法类型。

    截屏2021-06-08 上午10.10.11.png
    1. 初始化ERC20合约,如果是视图方法,只是进行数据的读取,传入Provider就可以,如果需要更改合约状态,需要用户签名,则需要传入Signer

      需要Token的合约地址和ERC20的合约ABI,可以通过浏览器查询到相关的信息,例如Dog

      new ethers Contract( addressOrName, abi,providerOrSigner)
      
    2. 查询合约的相关信息,这里以Heco的Dog为例,其他的Token都是一样的。

      const totalSupply = await contract.totalSupply();
      const balance = await contract.balanceOf(account);
      
    3. Transfer,转账的单位是Wei,可以通过etherjs提供的工具函数进行转换。

      const contract = new ethers.Contract(
            Dog.address,
            ERC20ABI,
            provider.getSigner()
          );
       const tx = await contract.transfer(
           "0xFD513D86a57BAFeAf46ddcC1bDDf629409A03cCf",
           parseEther("1.0")
        );
      

    ⚠️ERC20需要多加关注的是Approve()方法以及transfer()transferFrom()的区别,授权过的代币,被授权的那一方,可以通过调用transferFrom()方法,转走你授权数量内的代币,所以授权是一个很危险的操作,假设你授权了一个不良的合约,那你会面临授权的token被转走的风险,即使你没有泄露私钥助记词。

    抵押和赎回

    挖矿合约仅需要了解大概过程,挖矿合约并非标准,涉及到具体业务 这里选择Mdex DEP-HUSD矿池进行操作,也就是抵押DEP-HUSD LP Token 获取Mdex 。 此处已经提前添加了LP Token以及进行了Approve操作。

    操作成功与否可以通过Mdex页面进行查看或在浏览器进行查询

    1. 从HecoInfo上获取到Mdex Pool的ABI,通过ABI连接Mdex Pool的合约

      const pool = new ethers.Contract(
            POOL_ADDRESS,
            POOLABI,
            provider.getSigner()
          );
      
    2. 抵押全部的LP

        const pid = await pool.LpOfPid(LP_ADDRESS);
      
        const lpToken = new ethers.Contract(LP_ADDRESS, ERC20ABI, provider.getSigner());
        //抵押
        const lpBanlance = await lpToken.balanceOf(account);
        const tx = await pool.deposit(pid, lpBanlance);
      
    3. 赎回全部的LP

      const pid = await pool.LpOfPid(LP_ADDRESS);
      const userInfo = await pool.userInfo(pid, account);
      const tx = await pool.withdraw(pid, userInfo[0]);
      

    文档与三方库

    便利三方库:web3-react use-wallet

    文档:doc.metamask.io ethers

    相关文章

      网友评论

        本文标题:DApp开发入门

        本文链接:https://www.haomeiwen.com/subject/mununltx.html