当前位置: 首页 > news >正文

DAPP自己快速搭建一个去中心化APP

DAPP环境搭建和DEMO使用

1. DAPP

1.1 DAPP是什么

DAPP是在底层区块链平台衍生的各种分布式应用,是区块链世界中的服务提供形式。它被认为是开启区块链3.0时代的标志。

DAPP之于区块链,就像APP之于Android和iOS,都是应用程序和底层环境之间的关系。目前主流的DAPP开发区块链有三家,分别是:ETH(以太坊)、EOS(柚子)、TRON(波场)。这些就跟Android系统分不同的ROM类似,比如华为的EMUI、小米的MIUI、OPPO的ColorOS等等。

总之,DAPP就是区块链系统上的应用程序,我们使用起来和普通APP并不会有太大的差别。

1.1.2 例子

Steemit是一个内容社交DAPP,作为基于Steem公链开发的DAPP,在业内拥有极高的人气。用户可以在上面分享,文章,视频,图片,绘画作品,摄影作品等等。上传完作品之后,通过用户投票,决定上传质量的高低,上传者从而获得相应的代币。

跟Instagram、Twitter其他内容平台相比,Steemit上的用户能通过自己的贡献而获得相应的回报,能够有效地激励用户参与内容建设。

DAPP是什么意思?总的来说,DAPP就是去中心化应用,DAPP在继承传统APP的优势之后,再结合区块链的特点而形成的,DAPP比较像是众创模式、共享模式、去中心化模式。

1.1.3 DAPP与智能合约、区块链的关系

可以认为,DAPP就是基于P2P对等网络而运行在智能合约之上的分布式应用程序,区块链则为其提供可信的数据记录。

1.1.4 智能合约

智能合约是出现在比特币时代之前,由尼克·萨博(Nick Szabo)在1996年首次提出的概念。他对智能合约的定义如下:

“一个智能合约是一套以数字形式定义的约定,包括合约参与方可以在上面执行这些约定的协议。智能合约的基本思想是,各种各样的合约条款可以嵌入到我们使用的硬件和软件中从而使得攻击者需要很大的代价去攻击。”

基于区块链的智能合约构建及执行分为如下几步:1、多方用户共同参与制定一份智能合约;2、合约通过P2P网络扩散并存入区块链;3、区块链构建的智能合约自动执行。

2. DAPP 开发

2.1 DAPP 的基本架构

主要分为三个部分:

  1. 区块链以及本身提供的能力

  2. 三方钱包等提供的能力

  3. 我们要写的 DAPP 部分----分为三个部分:

  • 和 EVM 交互的合约层-- solidity 编写;
  • 和合约层、钱包交互的交互层-web3js, 其和 Ajax 类似,可以用来读取以太坊区块链,主要使用的 JSON RPC 和区块链进行通信,对区块链网络进行数据的读写操作;
  • 前端代码业务层-vue、react 等编写;

2.2 开发 DAPP 的步骤

  1. 开发智能合约:一般使用 solidity 语言进行开发,选用以太坊合约、bsc 合约等;

  2. 部署智能合约:一般使用 remix 工具进行部署,先在测试环境中进行部署智能合约,申请对应的测试币;

  3. 开发 DAPP 前端:使用前端框架进行开发,前端设计到和钱包的连接、调用合约、数据查询等内容;

2.3 环境搭建

主要需要解决的问题是模拟链(毕竟真链上的操作都是要花钱的)、钱包和合约的问题;

  1. 链可以用ganache进行模拟

  2. 钱包用 MetaMask

  3. solidity 既然是一个编程语言,并且要跑再 EVM 上,那就有 编写、编译、测试和调试的地方,这里推荐使用remix

2.4 部署和调用

DAPP 在被调用之前需要先部署到以太坊上,主要分为部署和调用两部分;

  1. 部署

一个 DAPP 可以由多个智能合约组成,因此部署一个 DAPP 也就是同时部署多个智能合约,那么部署一个智能合约的流程图如下:
智能合约流程图

智能合约使用 RPC 调用以太坊的钱包、Web3.js 等工具;
Web3.js 将合约部署到以太坊中的 Solc 编译器中;
编译器将编译后的字节码返回;
将合约字节码以及相关参数发送到以太坊的节点中;
以太坊部署节点后返回合约地址以及二进制接口(ABI)

  1. 调用

部署好的合约可以进行调用,前端调用主要依赖 MetaMask 插件,前端的 Web3 Provider 是与特定的以太坊节点相连,可以直接使用

web3.currentProvider 调用,下图展示了前端调用合约的一般流程。
前端调用流程图

智能合约: 存在于区块链上的代码片段。它们在区块链内操作,且不可更改。

节点/Web3 提供者: 要从区块链获取数据,需要节点或 Web3 提供者;节点运行区块链的副本。节点是 web3 开发人员栈的重要组成部分,因为没有节点,web3 库就无法与智能合约交互。它们充当进入区块链领域的门户。

3. DAPP 初体验

3.1 使用 truffle 创建项目

npm install -g truffle

3.2 使用 truffle version 检查是否安装成功;

truffle version

3.3 使用自带的 pet-shop 项目进行开发

truffle unbox pet-shop
truffle 框架中本身存在几个项目,可以直接使用自带的 pet-shop 项目进行开发,用 truffle unbox 命令解压缩这个框架到我们的文件夹下。

创建后的项目文件夹:
contracts/:智能合约 Solidity 的源文件,包含一个迁移合约 Migrations.sol;

migrations/:Truffle 使用迁移系统来处理智能合约部署。迁移是一种额外的特殊智能合约,可以跟踪变化;

test/:包含智能合约的 JavaScript 和 Solidity 测试;

truffle-config.js:包含 truffle 配置文件;

3.4 Ganache

Ganache 是一个运行在本地的个人区块链,通过Ganache官网可以下载,其前身是 TestRPC 可以用来开发以太坊的个人区块链;

Ganache 可以部署合同,开发应用程序以及进行测试;

Ganache 中可以免费提供 10 个账号,分别记录了各自的地址以及余额,并且需要关注 RPC SERVER 的地址;

3.4.1 安装Ganache并快速创建

3.4.1.1 编写智能合约

主要是在 contracts 中去新建 Adoption.sol 文件,pragma solidity ^0.5.0; //控制智能合约编译器的版本

pragma solidity ^0.5.0; //控制智能合约编译器的版本

contract Adoption {

  address[16] public adopters;  // 保存领养者的地址,是包括以太坊地址的数组

    // 领养宠物
  function adopt(uint petId) public returns (uint) {
    require(petId >= 0 && petId <= 15);  // 确保id在数组长度内

    adopters[petId] = msg.sender;        // 保存调用这地址
    return petId;
  }

  // 返回领养者
  function getAdopters() public view returns (address[16] memory) {
    return adopters;
  }

}
3.4.1.2 编译和迁移智能合约

Solidity 是一种编译语言,需要编译成字节码,才可以执行在以太坊虚拟机(EVM);

truffle compile

编译成功合约之后需要迁移到区块链中,在 migrations 目录中创建新文件;

//创建自己的迁移文件-2_deploy_contracts.js

var Adoption = artifacts.require("Adoption");

module.exports = function(deployer) {
  deployer.deploy(Adoption);
};
3.4.1.3 在端口7454上运行本地区块链

执行命令 truffle migrate

上述操作完成后,会发现在 Ganache 中存在 4 个区块;

在这里插入图片描述

3.4.1.5 测试智能合约

test目录中创建文件

pragma solidity ^0.5.0;

import "truffle/Assert.sol";   // 引入的断言
import "truffle/DeployedAddresses.sol";  // 用来获取被测试合约的地址
import "../contracts/Adoption.sol";      // 被用来测试的合约

contract TestAdoption {
  Adoption adoption = Adoption(DeployedAddresses.Adoption());

  // 领养测试用例
  function testUserCanAdoptPet() public {
    uint returnedId = adoption.adopt(8);

    uint expected = 8;
    Assert.equal(returnedId, expected, "Adoption of pet ID 8 should be recorded.");
  }

  // 宠物所有者测试用例
  function testGetAdopterAddressByPetId() public {
    // 期望领养者的地址就是本合约地址,因为交易是由测试合约发起交易,
    address expected = address(this);
    address adopter = adoption.adopters(8);
    Assert.equal(adopter, expected, "Owner of pet ID 8 should be recorded.");
  }

    // 测试所有领养者
  function testGetAdopterAddressByPetIdInArray() public {
  // 领养者的地址就是本合约地址

    //address expected = this;因为编译器版本是0.5.0,代码之前编写是按照0.4.17的规范来写的

    address expected=address(this);
    address[16] memory adopters = adoption.getAdopters();
    Assert.equal(adopters[8], expected, "Owner of pet ID 8 should be recorded.");
  }
}
3.4.1.6 使用truffle test进行测试可以判断用例是否通过;

truffle test

3.4.1.7 创建用户界面并和智能合约进行交互

在 src 文件夹中进行界面的开发,主要是补充以太坊的功能,web3 是一个实现了与以太坊节点通信的库,我们利用 web3 来和合约进行交互。优先使用 MetaMask 提供的 Web3 实例,truffle-contract 会帮我们保存合约部署的信息;

打开src/js/app.js文件,修改下面函数:

注意,修改的是指定函数,不是全局复制粘贴
initWeb3: async function () {

    // Modern dapp browsers...

    if (window.ethereum) {

      App.web3Provider = window.ethereum;

      try {

        // Request account access

        await window.ethereum.enable();

      } catch (error) {

        // User denied account access...

        console.error("User denied account access");

      }

    }

    // Legacy dapp browsers...

    else if (window.web3) {

      App.web3Provider = window.web3.currentProvider;

    }

    // If no injected web3 instance is detected, fall back to Ganache

    else {

      App.web3Provider = new Web3.providers.HttpProvider(

        "http://localhost:7545"

      );

    }

    web3 = new Web3(App.web3Provider);



    return App.initContract();

  },



initContract: function () {

    $.getJSON("Adoption.json", function (data) {

      var AdoptionArtifact = data;

      App.contracts.Adoption = TruffleContract(AdoptionArtifact);





      App.contracts.Adoption.setProvider(App.web3Provider);



      return App.markAdopted();

    });

    return App.bindEvents();

  },



markAdopted: function (adopters, account) {

    var adoptionInstance;



    App.contracts.Adoption.deployed()

      .then(function (instance) {

        adoptionInstance = instance;





        return adoptionInstance.getAdopters.call();

      })

      .then(function (adopters) {

        for (i = 0; i < adopters.length; i++) {

          if (adopters[i] !== "0x0000000000000000000000000000000000000000") {

            $(".panel-pet")

              .eq(i)

              .find("button")

              .text("Success")

              .attr("disabled", true);

          }

        }

      })

      .catch(function (err) {

        console.log(err.message);

      });

  },



  handleAdopt: function (event) {

    event.preventDefault();



    var petId = parseInt($(event.target).data("id"));



    var adoptionInstance;



    web3.eth.getAccounts(function (error, accounts) {

      if (error) {

        console.log(error);

      }



      var account = accounts[0];



      App.contracts.Adoption.deployed()

        .then(function (instance) {

          adoptionInstance = instance;



          return adoptionInstance.adopt(petId, { from: account });

        })

        .then(function (result) {

          return App.markAdopted();

        })

        .catch(function (err) {

          console.log(err.message);

        });

    });

  },

};

3.4.1.8 浏览器启动项目并进行交互

npm run dev

4. MetaMask

4.1 安装 MetaMask 和配置区块链网络

使用谷歌插件搜索并下载安装MetaMask

为了连接本地的网络,需要添加新网络;
在连接 metaMask 需要新增网络,网络的链 ID 和 RPC URL 是必须填写的项目,RPC URL如果是本地的,一般是127.0.0.1:7545;那么链 ID一般可以使用 1337,如果有占用可以删除后再使用;在连接对应网络的时候,需要保持 Ganache 是打开的状态;

在确保metamask与ganache处于连接状态后,创建新用户,并使用 Ganache 中其中一个地址的私钥导入账户,导入成功就会发现有免费的 100ETH 可以进行交易;

4.2 启动项目

在这里插入图片描述

4.3 点击 Adopt,进行领养,成功将为 Success。

领养

从活动中可以看到对应的交易信息:
交易信息

5. 参考内容

5.1、主要使用流程

浅谈 Web3.0:动手做一个去中心化 APP

5.2、app.js参考

app.js参考

对了,腾讯云主机又又又又活动了,戳这里查看

总结

通过本文,你应该可以自己搭建一套本地区块链环境,并创造出自己的去中心化APP,当然你也可以把他放到以太坊上,但是每次操作都是有手续费的。但如果有这方便的创业需求也值得一试。喜欢本文可以关注我~有问题可以留言或私信我。

相关文章:

  • uni.app小程序的ajax封装详细讲解
  • 手把手教你做K均值聚类分析
  • 【JavaScript】LeetCode 383. 赎金信
  • java智慧农业水果销售系统计算机毕业设计MyBatis+系统+LW文档+源码+调试部署
  • 1.初识jQuery
  • 影响关系分类汇总
  • JNI学习5.jstring的处理
  • android 各种偶现问题记录
  • 红黑树详解+模拟实现
  • 猿创征文 | Redis之 Jedis实例
  • 中秋征文“好文尝鲜奖”榜单公布,快来领取你的定制礼盒!
  • ACL访问控制列表 基础、创建ACL访问控制列表的两种方式、配置ACL访问控制列表规则、修改ACL规则的默认步长。子网掩码、反掩码、通配符掩码的区别和作用。
  • 面试官:我看你简历上写了MySQL,对MySQL InnoDB引擎的索引了解吗?
  • 微信小程序SEO指南
  • steam搬砖项目一直很稳定,部分反馈
  • 【刷算法】求1+2+3+...+n
  • 【跃迁之路】【735天】程序员高效学习方法论探索系列(实验阶段492-2019.2.25)...
  • CentOS 7 防火墙操作
  • passportjs 源码分析
  • Python_网络编程
  • 今年的LC3大会没了?
  • 什么软件可以剪辑音乐?
  • 小而合理的前端理论:rscss和rsjs
  • 走向全栈之MongoDB的使用
  • !!【OpenCV学习】计算两幅图像的重叠区域
  • ## 临床数据 两两比较 加显著性boxplot加显著性
  • $.type 怎么精确判断对象类型的 --(源码学习2)
  • (webRTC、RecordRTC):navigator.mediaDevices undefined
  • (每日持续更新)jdk api之FileReader基础、应用、实战
  • (五)IO流之ByteArrayInput/OutputStream
  • (转)从零实现3D图像引擎:(8)参数化直线与3D平面函数库
  • .NET 6 在已知拓扑路径的情况下使用 Dijkstra,A*算法搜索最短路径
  • .NET MVC之AOP
  • .NET/C# 在 64 位进程中读取 32 位进程重定向后的注册表
  • .Net高阶异常处理第二篇~~ dump进阶之MiniDumpWriter
  • .NET委托:一个关于C#的睡前故事
  • .project文件
  • /bin、/sbin、/usr/bin、/usr/sbin
  • /bin/bash^M: bad interpreter: No such file or directory
  • @RestController注解的使用
  • [ C++ ] template 模板进阶 (特化,分离编译)
  • [].shift.call( arguments ) 和 [].slice.call( arguments )
  • [Android]一个简单使用Handler做Timer的例子
  • [C#7] 1.Tuples(元组)
  • [C#小技巧]如何捕捉上升沿和下降沿
  • [elastic 8.x]java客户端连接elasticsearch与操作索引与文档
  • [HJ56 完全数计算]
  • [IDF]被改错的密码
  • [JavaEE系列] wait(等待) 和 notify(唤醒)
  • [LeetCode 687]最长同值路径
  • [nginx] LEMP 架构随笔
  • [Nginx]反向代理Node将3000端口访问转换成80端口
  • [NOIP2015] 运输计划
  • [Python]list.append字典的时候,修改字典会导致list内容变化的问题
  • [Python基础]Python文件处理小结