首页 > 其他分享 >以太坊dApp入门开发

以太坊dApp入门开发

时间:2022-11-15 16:11:20浏览次数:87  
标签:const 入门 以太 888 console wave dApp ethereum hardhat

一、环境搭建

1、安装nodejs,附带npm

2、本地搭建hardhat开发环境

mkdir my-wave-portal
cd my-wave-portal
npm config set registry https://registry.npm.taobao.org
npm init -y
npm install --save-dev hardhat

启动hardhat交互命令行:

npx hardhat
888    888                      888 888               888
888    888                      888 888               888
888    888                      888 888               888
8888888888  8888b.  888d888 .d88888 88888b.   8888b.  888888
888    888     "88b 888P"  d88" 888 888 "88b     "88b 888
888    888 .d888888 888    888  888 888  888 .d888888 888
888    888 888  888 888    Y88b 888 888  888 888  888 Y88b.
888    888 "Y888888 888     "Y88888 888  888 "Y888888  "Y888

Welcome to Hardhat v2.12.2

? What do you want to do? ...
> Create a JavaScript project
  Create a TypeScript project
  Create an empty hardhat.config.js
  Quit

Create a JavaScript project,接下来会问你项目根目录、是否添加.gitignore,向hardhat发送崩溃报告之类的,全选yes就完了。

安装其他依赖:

npm install --save-dev chai @nomiclabs/hardhat-ethers ethers @nomicfoundation/hardhat-toolbox @nomicfoundation/hardhat-chai-matchers

生成本地的几个随机账户:

>npx hardhat node
You have both ethereum-waffle and @nomicfoundation/hardhat-chai-matchers installed. They don't work correctly together, so please make sure you only use one.

We recommend you migrate to @nomicfoundation/hardhat-chai-matchers. Learn how to do it here: https://hardhat.org/migrate-from-waffle
Started HTTP and WebSocket JSON-RPC server at http://127.0.0.1:8545/

Accounts
========

WARNING: These accounts, and their private keys, are publicly known.
Any funds sent to them on Mainnet or any other live network WILL BE LOST.

Account #0: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 (10000 ETH)
Private Key: 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80

Account #1: 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 (10000 ETH)
Private Key: 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d

......

Account #19: 0x8626f6940E2eb28930eFb4CeF49B2d1F2C9C1199 (10000 ETH)
Private Key: 0xdf57089febbacf7ba0bc227dafbffa9fc08a93fdc68e1e42411a14efcf23656e

WARNING: These accounts, and their private keys, are publicly known.
Any funds sent to them on Mainnet or any other live network WILL BE LOST.

多贴心,还告诉你不要往这里边的账户转钱:)

测试一下本地环境是否正常:

>npx hardhat compile
You have both ethereum-waffle and @nomicfoundation/hardhat-chai-matchers installed. They don't work correctly together, so please make sure you only use one.

We recommend you migrate to @nomicfoundation/hardhat-chai-matchers. Learn how to do it here: https://hardhat.org/migrate-from-waffle
Downloading compiler 0.8.17
Compiled 1 Solidity file successfully

>npx hardhat test
You have both ethereum-waffle and @nomicfoundation/hardhat-chai-matchers installed. They don't work correctly together, so please make sure you only use one.

We recommend you migrate to @nomicfoundation/hardhat-chai-matchers. Learn how to do it here: https://hardhat.org/migrate-from-waffle


  Lock
    Deployment
      √ Should set the right unlockTime (1651ms)
      √ Should set the right owner
      √ Should receive and store the funds to lock
      √ Should fail if the unlockTime is not in the future (52ms)
    Withdrawals
      Validations
        √ Should revert with the right error if called too soon
        √ Should revert with the right error if called from another account
        √ Shouldn't fail if the unlockTime has arrived and the owner calls it (49ms)
      Events
        √ Should emit an event on withdrawals
      Transfers
        √ Should transfer the funds to the owner

  9 passing (2s)

都没问题,可以把工程导入到vs code了,装好hardhat solidity插件后导入。

脚手架里边的几个文件用不着可以删掉:test/Lock.js, script/deploy.js, contracts/Lock.sol

WavePortal.sol文件放在contracts目录,这是合约的源文件。

scripts目录里边创建run.jsdeploy.js,这两个分别用来本地执行测试以及向链上部署合约,对应的执行命令:

npx hardhat run scripts/run.js
npx hardhat run scripts/deploy.js --network goerli

https://buildspace.so/p/build-solidity-web3-app/lessons/get-local-ethereum-network-running

二、接入以太坊

Alchemy网站、这玩意是个BaaS平台,通过api url和key接入Alchemy、让它来帮我们接入以太坊。

注册好了之后可以得到接入API url和key,分mainnet和goerli testnet,还可以领取goerli的水龙头测试币。

三、dApp架构

整个dApp项目分成一个前端react js页面应用,以及部署在以太坊goerli testnet上的WavePortal合约组成。

  • 前端页面使用ethers.js来完成与MetaMask钱包通信,以及和以太坊通信(准确说是和Alchemy平台通信,由Alchemy来连接以太坊)。
  • 合约里边提供了几个public方法供外部应用调用;有emit event事件供外部应用订阅,外部应用可以跟进事件触发来执行回调函数;合约内部有一些状态变量,比如数组、map等等可以存储数据。智能合约有方法有存储,就像个“有状态的对象实例”。
1、Solidity智能合约
2、前端React应用

https://replit.com/ 在线开发环境,构建react应用。

App.jsx代码如下:

import React, { useEffect ,useState } from "react";
import { ethers } from "ethers";
import './App.css';
import abi from './utils/WaveContract.json';

export default function App() {


  /*
  * Just a state variable we use to store our user's public wallet.
  */
  const [currentAccount, setCurrentAccount] = useState("");
  //状态变量,存储前端发来的数据
  const [allWaves, setAllWaves] = useState([]);
  
  //合约地址
  const contractAddress = "0x662c74BDFAee0d24C75d9626AB770072b881CCc0";
  //ABI文件,相当于合约的接口声明
  const contractABI = abi.abi;

  /*
   * 查询合约里的wave数据
   */
  const getAllWaves = async () => {
    try {
      const { ethereum } = window;	//如果安装了metamask插件,那么会向window注入ethereum对象
        
      if(ethereum){
        /*
          ethers.js用法
          provider是连接链的抽象,signer是钱包账户的抽象
        */
        const provider = new ethers.providers.Web3Provider(ethereum);
        const signer = provider.getSigner();
        //前端合约对象
        const wavePortalContract = new ethers.Contract(contractAddress, contractABI, signer);

        const waves = await wavePortalContract.getAllWaves(); //调用智能合约的getAllWaves()方法

        let wavesCleaned = [];
        waves.forEach(
            wave => {
              wavesCleaned.push({
                address: wave.waver,
                timestamp: new Date(wave.timestamp*1000),
                message: wave.message
              });
            }
        );
        
        /*
         * 把查询回来的数据存储到前端的allWaves对象里
         */
        setAllWaves(wavesCleaned);
        
      }else{
        console.log("没有ethereum对象!");
      }
    } catch (error) {
      console.log(error);
    }
  }
  
  /**
  * 
  */
  const checkIfWalletIsConnected = async () => {

    try{
      /*
      * 是否有接入window.ethereum;是否安装了钱包
      */
      const { ethereum } = window;

      if (!ethereum) {
        console.log("Make sure you have metamask!");
        return;
      } else {
        console.log("We have the ethereum object", ethereum);
      }
        
      /*
      * 用户是否授权
        尝试去获取本地钱包账户列表
      */
      const accounts = await ethereum.request({ method: 'eth_accounts' });
      
      if (accounts.length !== 0) {
        const account = accounts[0]; //取本地钱包第一个账户
        console.log("Found an authorized account:", account);
        setCurrentAccount(account);  //把当前账户存到前端currentAccount对象
        getAllWaves();
      } else {
        console.log("No authorized account found")
      }
    }catch(error){
      console.log(error);
    }
    
  }


  /**
  * 连接钱包
  */
  const connectWallet = async () => {
    try {
      const { ethereum } = window;

      if (!ethereum) {
        alert("Get MetaMask!");
        return;
      }
	  //请求获取本地钱包地址
      const accounts = await ethereum.request({ method: "eth_requestAccounts" });

      console.log("Connected", accounts[0]);
      setCurrentAccount(accounts[0]); //钱包地址存放到前端对象
    } catch (error) {
      console.log(error)
    }
  }

  /**
  * 向智能合约发送wave数据
  */
  const wave = async () => {
    try {
      const { ethereum } = window;

      if (ethereum) {
         
        //ethers.js三连~
        const provider = new ethers.providers.Web3Provider(ethereum);
        const signer = provider.getSigner();
        const wavePortalContract = new ethers.Contract(contractAddress, contractABI, signer);

        /*
        * 调用合约wave(message)方法,发送数据
        */
        let waveMessage = document.getElementById("waveMsg");
        const waveTxn = await wavePortalContract.wave(waveMessage.value, {gasLimit:300000});
        console.log("Mining...", waveTxn.hash);

        await waveTxn.wait();  //等待调用wave()方法这个交易执行完毕
        console.log("Mined -- ", waveTxn.hash);

      } else {
        console.log("Ethereum object doesn't exist!");
      }
    } catch (error) {
      console.log(error)
    }
}
  
  /**
  * 调用合约getTotalWaves()方法,前端计数展示合约里多少个Wave
  */
  const totalWaves = async () => {
    const { ethereum } = window;

    if (ethereum) {
      const provider = new ethers.providers.Web3Provider(ethereum);
      const signer = provider.getSigner();
      const wavePortalContract = new ethers.Contract(contractAddress, contractABI, signer);

      let count = await wavePortalContract.getTotalWaves();
      console.log("Retrieved total wave count...", count.toNumber());
      let total = document.getElementById('totalWaves');
      total.innerHTML = "Total Waves : " + count;
    }
  }
  
  /*
  * 页面载入时执行
  */
  useEffect(() => {
    checkIfWalletIsConnected(); //检查钱包是否连接
    totalWaves(); //展示计数wave数

    /**
      emit NewWave事件处理回调函数
    */
    let wavePortalContract;
    //收到事件以后重新渲染 
    const onNewWave = (from, timestamp, message) => {
      console.log("NewWave", from, timestamp, message);
      setAllWaves(prevState => [
        ...prevState,
        {
          address: from,
          timestamp: new Date(timestamp * 1000),
          message: message,
        },
      ]);  //更新前端allWaves对象后,div自动渲染了

      //totalWaves();
    };

    if(window.ethereum){
      const provider = new ethers.providers.Web3Provider(window.ethereum);
      const signer = provider.getSigner();
      wavePortalContract = new ethers.Contract(contractAddress, contractABI, signer);
      wavePortalContract.on("NewWave", onNewWave); //绑定合约的NewWave事件
    }

    return () => {
      if(wavePortalContract){
        wavePortalContract.off("NewWave", onNewWave); //解除事件绑定
      }
    };
    
  }, [])
  
  //返回渲染的页面
  return (
    <div className="mainContainer">

      <div className="dataContainer">
        <div className="header">
        

标签:const,入门,以太,888,console,wave,dApp,ethereum,hardhat
From: https://www.cnblogs.com/lyhero11/p/16892741.html

相关文章

  • Spring Boot Admin 入门
    SpringBootAdmin入门SpringBootAdmin是一个社区项目,主要用于管理和监控SpringBoot应用程序搭建SpringBootAdmin服务器1、创建springboot项目,引入以下依......
  • (更新中..)【Saas】从入门到精通-基本管理设计:权限管理/角色管理/组织管理/成员管理
    前言第一次接触Saas(Serviceasasoft),用此博客记录本人从0-1摸索企业管理(OA)平台的设计思路及中途所遇见的坑,共勉。背景设计一个OA管理平台,此篇重点讲述通用的基......
  • dubbo入门案例以及常见错误
    写在前面如果你已经看到这里了,说明你可能正在写dubbo入门案例,但是好像一直在出错,我也是如此,我发现,入门案例中如果你已经理顺了dubbo大概逻辑的情况下大多数错误其实是......
  • spark (一) 入门 & 安装
    目录基本概念spark核心模块sparkcore(核心)sparksql(结构化数据操作)sparkstreaming(流式数据操作)部署模式local(本地模式)standalone(集群模式)onyarn(集群模式)......
  • CTFSHOW-web入门-web1-6
    此题直接按F12查看源码即可获得flag ------------------------------------------------------------------------------------------------------------------------......
  • 12大深度学习开源框架(caffe,tf,pytorch,mxnet等)快速入门项目
    77人赞同了该文章 这是一篇总结文,给大家来捋清楚12大深度学习开源框架的快速入门,这是有三AI的GitHub项目,欢迎大家star/fork。https://github.com/longpeng20......
  • Nginx入门一:介绍
    2002年,在仔细研究了已有的Web服务器之后,当时任职于俄罗斯门户网站Rambler的工程师IgorSysoev开始编写一个新的Web服务器,目标是解决高并发的C10K问题。并于2004年开源版本号......
  • mybatis入门写法思路
    废话不说直接上思路: 1.先用maven安装mybatis <!--https://mvnrepository.com/artifact/org.mybatis/mybatis--><dependency><groupId>org.mybatis</gr......
  • 【Python基础】快速入门Python(讲解、习题)
    0.导语Python是一种跨平台的计算机程序设计语言。是一种面向对象的动态类型语言,最初被设计用于编写自动化脚本(shell),随着版本的不断更新和语言新功能的添加,越来越多被用于......
  • SqlServer入门知识-创建临时表
    https://zhuanlan.zhihu.com/p/562721751平时会直接在正常的库里面直接建表,好像和这个不一样,了解下。平时用时会直接在库里备份数据,然后删掉备份的表。属于数据备份,不是真......