一、背景及基础知识(只需了解即可,也可不看)

1. ES6

2. babel转码器

3. ESLint

二、项目需求及项目结构图

三、源码分析

1. 文件简要解释(弄懂每个文件大概做什么的即可)

2. app.js文件注释(重点)

四、试运行项目

五、测试合约功能


前言

这个示例是《区块链技术进阶与实践》提供的例子,书不错。

前提:在学习这个例子前要安装好ganache、truffle等区块链开发环境,对智能合约基本语法和DAPP如何开发有基本概念。

运行环境ganache-cli v6.1.6    truffle v4.1.13  solidity ^0.4.24

本积分系统最原始的源代码在:https://github.com/Blockchain-book/Ethereum-Score-Hella

建议下载本人注释后的源代码:https://download.csdn.net/download/u011680118/10649989

注意

由于运行环境更新,原始的源代码可能过时,编译会报错,建议根据错误提示修改源代码。

下载之后如果直接truffle migrate会报错

把build文件夹删掉,再在本地重新进行编译部署即可。

或者运行 truffle migrate --reset 命令也可以。

附注:这个项目基于truffle的例子webpack,可以新建一个文件夹,cd到文件夹内,在命令行中输入 truffle unbox webpack,下载并学习这个例子,与本积分例子对比。例子中的前台JavaScript代码很值得学习。

一、背景及基础知识(只需了解即可,也可不看)

1. ES6

ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准。

ECMAScript 和 JavaScript 的关系是,前者是后者的规格,后者是前者的一种实现。

ES6 既是一个历史名词,也是一个泛指,含义是 5.1 版以后的 JavaScript 的下一代标准,涵盖了 ES2015、ES2016、ES2017 等等

来自 <http://es6.ruanyifeng.com/#docs/intro>

2. babel转码器

Babel 是一个广泛使用的 ES6 转码器,可以将 ES6 代码转为 ES5 代码,从而在现有环境执行。这意味着,你可以用 ES6 的方式编写程序,又不用担心现有环境是否支持。

Babel 的配置文件是.babelrc,存放在项目的根目录下。使用 Babel 的第一步,就是配置这个文件。

3. ESLint

二、项目需求及项目结构图

这个系统有客户、银行、商户组成,进行积分的交易,具体需求如下图:

三、源码分析

1. 文件简要解释(弄懂每个文件大概做什么的即可)

用sublime text打开文件夹,可以看到组织目录

app是前端html代码和一些脚本程序

stylesheets里面是app.css,设定网页各个部件的样式

html是前台代码,index.html里面有客户注册、登陆、商户注册、登陆、银行登陆和测试功能。

客户登陆后页面跳转到customer.html,页面链接中有当前登陆账户的地址,可以实现查询信息、购买商品、转让积分等功能

商户登陆后页面跳转到merchant.html,页面链接中有当前登陆账户的地址,可以实现查询信息、添加商品、转让积分、积分清算等功能

银行登陆后页面跳转到bank.html,页面链接中有当前登陆账户的地址,可以实现发行积分、查看信息等功能

JavaScript代码的解释见代码注释,主要用到web3来与节点通信,获取节点的账户列表等信息,用到truffle-constract 来生成合约实例,调用合约的方法。这两个js库都可以在项目目录下 npm install 进行下载,会根据package.json确定版本

build 是在compile之后生成的文件夹

contracts、migrations、test 是truffle自动生成的文件夹

node_modules是前端需要的一些依赖文件,在下载web3.js之后有的

以点号开头的文件都是用于JavaScript的转码,可以暂时不管

package.json 前端开发,测试需要依赖的一些库的配置信息,这个文件是 npm init 时创建的一个文件,会记录当前整个项目中的一些基础信息。package.json里面定义的是版本范围(比如^1.0.0),具体跑npm install的时候安的什么版本,要解析后才能决定,这里面定义的依赖关系树,可以称之为逻辑树(logical tree)。

package-lock.json 这个文件却是 node_modules 文件夹或者 package.json 文件发生变化时自动生成的。这个文件主要功能是确定当前安装的包的依赖,以便后续重新安装的时候生成相同的依赖,而忽略项目开发过程中有些依赖已经发生的更新。

来自 <http://www.cnblogs.com/tianzun-blog/p/9275931.html>

node_modules文件夹下才是npm实际安装的确定版本的东西,这里面的文件夹结构我们可以称之为物理树(physical tree)。

安装过程中有一些去重算法,所以你会发现逻辑树结构和物理树结构不完全一样。

package-lock.json可以理解成对结合了逻辑树和物理树的一个快照(snapshot),里面有明确的各依赖版本号,实际安装的结构,也有逻辑树的结构。

其最大的好处就是能获得可重复的构建(repeatable build),当你在CI(持续集成)上重复build的时候,得到的artifact是一样的,因为依赖的版本都被锁住了。

链接:https://www.zhihu.com/question/62331583/answer/257972185

truffle.js如下:

// Allows us to use ES6 in our migrations and tests.
require('babel-register')module.exports = {networks: {truffle: {host: '127.0.0.1',port: 9545,network_id: '*' // Match any network id},develop: {host: '127.0.0.1',port: 8545,network_id: '*' // Match any network id}}
}
  • require: 用于加载babel模块,实现JavaScript的转码,以兼容。
  • networks: 指定在移植(Migration)时使用哪个网络。当在某个特定的网络上编译或运行移植时,合约会缓存起来方便后续使用。这里开发使用的是本地的ganache-cli客户端。

webpack.config.js

webpack在执行时,除在命令行传入参数,还可以通过指定的配置文件来执行。默认会搜索当前目录下webpack.config.js。这个文件是一个node.js模块,返回一个json格式的配置对象,或者通过--config选项来指定配置文件。

来自 <https://www.cnblogs.com/zuozuo-blog/p/6560485.html>

2. app.js文件注释(重点)

// Import the page's CSS. Webpack will know what to do with it.
import '../stylesheets/app.css'//在node中使用babel支持ES6,也仅仅是将ES6转码为ES5再执行,import语法会被转码为require/*引入customer.js等模块,以使用其中的方法require相当于module.exports的传送门,module.exports后面的内容是什么,require的结果就是什么customer.js等模块中exports的都是方法,可以在这里被调用,如 customer.newCustomer(ScoreInstance, account) */
const customer = require('./customer')
const bank = require('./bank')
const merchant = require('./merchant')// Import libraries we need.
/* import是编译时的(require是运行时的),它必须放在文件开头,而且使用格式也是确定的。它不会将整个模块运行后赋值给某个变量,而是只选择import的接口进行编译,这样在性能上比require好很多。*/
import { default as Web3 } from 'web3'      //等同于 import Web3 from 'web3';
import { default as contract } from 'truffle-contract'    //等同于 import contract from 'truffle-contract';// Import our contract artifacts and turn them into usable abstractions.
//导入智能合约编译之后生成的abi的json文件 Score.json
import ScoreArtifacts from '../../build/contracts/Score'// ScoreContract is our usable abstraction, which we'll use through the code below.
//初始化智能合约,实际上就是为你的智能合约创建一个对应的js对象ScoreContract,方便后续调用
//The input to the contract function is a JSON blob defined by truffle-contract-schema.
let ScoreContract = contract(ScoreArtifacts)
let ScoreInstance
// The following code is simple to show off interacting with your contracts.
// As your needs grow you will likely need to change its form and structure.
// For application bootstrapping, check out window.addEventListener below.
let accounts
let accountwindow.App = {// 进行初始化init: function () {// 设置智能合约的web3连接,使其能与以太坊节点通信,truffle-contract中的方法ScoreContract.setProvider(window.web3.currentProvider)// 类似于geth客户端查询以太坊账户信息,Get the initial account balance so it can be displayed.// web3.eth.getAccounts(callback(error, result){ ... }) window.web3.eth.getAccounts(function (err, accs) {if (err != null) {        //查询有问题window.App.setStatus('There was an error fetching your accounts.')return}if (accs.length === 0) {  //没有以太坊账户window.App.setStatus('Couldn\'t get any accounts! Make sure your Ethereum client is configured correctly.')return}accounts = accs           //把获取的以太坊账户全部存在变量accounts中,连的是ganache-cli的rpc模拟服务,预制了几个有eth的帐号//如果安装了MetaMask插件,应该获得的就是MetaMask里的帐号account = accounts[0]     //第一个以太坊账户存在account中})//Create an instance of ScoreContract that represents the default address managed by ScoreContract.//Creates an instance of the contract abstraction representing the contract at its deployed address. // truffle-contract中的方法ScoreContract.deployed().then(function (instance) {ScoreInstance = instance  //获取合约的实例,不用重复deploy,都用这一个}).catch(function (e) {console.log(e, null)})},//===================================== 客户方法 ==========================================// 新建客户newCustomer: function () {customer.newCustomer(ScoreInstance, account)},// 客户登录customerLogin: function () {customer.customerLogin(ScoreInstance, account)},// 当前客户信息,currentAccount在url中截取,在status框显示当前登陆账户getCurrentCustomer: function (currentAccount) {customer.showCurrentAccount(currentAccount)},// 当前客户余额getScoreWithCustomerAddr: function (currentAccount) {customer.getScoreWithCustomerAddr(currentAccount, ScoreInstance, account)},// 客户购买商品buyGood: function (currentAccount) {customer.buyGood(currentAccount, ScoreInstance, account)},// 查看已经购买的物品getGoodsByCustomer: function (currentAccount) {customer.getGoodsByCustomer(currentAccount, ScoreInstance, account)},// 客户转让积分transferScoreToAnotherFromCustomer: function (currentAccount) {customer.transferScoreToAnotherFromCustomer(currentAccount, ScoreInstance, account)},//===================================== 商家方法 ==========================================// 商家注册newMerchant: function () {merchant.newMerchant(ScoreInstance, account)},// 商家登录merchantLogin: function () {merchant.merchantLogin(ScoreInstance, account)},// 当前商家账户getCurrentMerchant: function (currentAccount) {merchant.getCurrentMerchant(currentAccount)},// 当前商家余额getScoreWithMerchantAddr: function (currentAccount) {merchant.getScoreWithMerchantAddr(currentAccount, ScoreInstance, account)},// 商家积分转让transferScoreToAnotherFromMerchant: function (currentAccount) {merchant.transferScoreToAnotherFromMerchant(currentAccount, ScoreInstance, account)},// 商家添加商品addGood: function (currentAccount) {merchant.addGood(currentAccount, ScoreInstance, account)},// 显示商家的所有商品getGoodsByMerchant: function (currentAccount) {merchant.getGoodsByMerchant(currentAccount, ScoreInstance, account)},// 商家清算积分settleScoreWithBank: function (currentAccount) {merchant.settleScoreWithBank(currentAccount, ScoreInstance, account)},//===================================== 银行方法 ==========================================// 发行积分sendScoreToCustomer: function () {bank.sendScoreToCustomer(ScoreInstance, account)},// 银行登录bankLogin: function () {bank.bankLogin(ScoreInstance, account)},// 查看已经发行的积分getIssuedScoreAmount: function () {bank.getIssuedScoreAmount(ScoreInstance, account)},// 已经清算积分总数目getSettledScoreAmount: function () {bank.getSettledScoreAmount(ScoreInstance, account)},//===================================== 调试方法 ==========================================// 查询所有的区块链账户allAccounts: function () {let allAccount = ''window.web3.eth.accounts.forEach(e => {allAccount += e + '\n'})window.App.setConsole(allAccount)  },// 状态栏显示setStatus: function (message) {const status = document.getElementById('status')status.innerHTML = message},// 显示consolesetConsole: function (message) {const status = document.getElementById('console')status.innerHTML = message}
}//在页面载入后,初始化web3,创建一个基于Http的provider,可以与以太坊节点进行通信
//这里用到的就是用ganache-cli启动所提供的对外的rpc服务,因为ganache-cli启动的时候绑定的是localhost,所以测试所使用的浏览器也要在本机。
window.addEventListener('load', function () {// 设置web3连接 http://127.0.0.1:8545 即以太坊节点window.web3 = new Web3(new Web3.providers.HttpProvider('http://127.0.0.1:8545'))window.App.init()   //调用初始化函数
})

四、试运行项目

在命令行中打开ganache-cli客户端,命令为:ganache-cli  运行端口是 8545

另外开一个命令行,cd到contracts目录下,输入truffle compiletruffle migrate --network develop 命令,把合约部署到区块链上,并使用truffle.js中配置的开发网络

可以看到Score合约地址是0x0e2789开头的。。 查看ganache-cli的命令行,其中打印出调试信息,生成的第三个区块中包含了Score合约地址,也是0x0e2789...

部署成功后,输入 npm run dev 命令,会执行 package.json里面的 dev 后面的脚本,即 "webpack-dev-server" 在本地开启服务器,现在可以访问客户端web页面。如果这里报错,说明要安装 webpack-dev-server ,可自行百度如何安装。

在浏览器中输入网址: http://localhost:8000

五、测试合约功能

注意:不同电脑账户不同,每次重启ganache-cli生成的账户也不同

注册客户和商户:我们就用第二个和第三个分别注册为客户和商户

商户账户 0x14d4409c0e31a983ee831e04d5d72f635076b8b5

密码 123

登录后跳转,页面链接末尾是商户地址

客户账户 0x93cbed31e02568a1ef3a2bc2591f74a8920c14ee

密码 空

注册成功后,登录之后页面跳转,客户账户在链接末尾

银行账户默认是第一个账户

输入银行地址后,密码不用管,后台没有比对密码,点登陆即可跳转到银行界面

0x6abc6d15fbb1f8d83d73912ab33f042d2e4d73a0

《区块链技术进阶与实践》之积分系统示例讲解相关推荐

  1. 全新升级,《区块链技术进阶与实战(第2版)》正式上市

    (第 1 版亮相央视新闻联播) 2018 年下半年,浙江大学计算机学院首次推出"区块链与数字货币"课程.作为课程指定教材,<区块链技术进阶与实战(第1版)>面向广大区块 ...

  2. 区块链技术进阶-深入详解以太坊智能合约语言 solidity(含源码)-熊丽兵-专题视频课程...

    区块链技术进阶-深入详解以太坊智能合约语言 solidity(含源码)-103人已学习 课程介绍         区块链开发技术进阶-深入详解以太坊智能合约语言 solidity视频培训教程:本课程是 ...

  3. 以太坊开发测试(6) 运行《区块链技术进阶与实战》Score 电子积分系统

    原项目地址:https://github.com/Blockchain-book/Ethereum-Score-Hella 配置运行过程: 首先下载一个最新的truffle webpack 框架小样 ...

  4. 以太坊区块链积分系统示例讲解

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 查看全文 http://www.taodudu.cc/news/show-4199767.ht ...

  5. 区块链技术发展趋势与银行业探索实践

    在数字化转型的大背景下,全球主要国家都在加快布局区块链技术,抢占新一轮创新变革的高地. 一.区块链技术概述 技术特征 区块链技术是密码学.共识算法.P2P通信.智能合约等多种技术的集成创新,打造了一种 ...

  6. 清华北大教授联袂推荐的好书:《区块链:金融应用实践》

    终于可以利用我的博客做个硬广了,<区块链:金融应用实践>是我和何广峰老师最近新出的书,面向广大的区块链爱好者,感谢清华和北大的教授无私推荐,京东.亚马逊.当当.淘宝均有售. 一.相关评语 ...

  7. 【区块链】以太坊区块链技术初探

    2019独角兽企业重金招聘Python工程师标准>>> [国内首家]以太坊区块链实战教学:http://edu.csdn.net/course/detail/6455 LinApex ...

  8. 比特币,以太坊......区块链技术真的被认同了吗?

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 作者:Zach展--发表在云+社区区块链专栏 近来比特币价格持续走高,掀起了一股"比特潮".比特币更参与到了实际交易中. ...

  9. 本田及通用公司利用区块链技术探索智能电网与电动汽车的互操作性

    点击上方 "蓝色字" 可关注我们! 暴走时评: 据日本新闻媒体Nikkei 5月20日报道,主要汽车制造商本田和通用汽车正在合作利用区块链技术研究电动汽车和智能电网的互操作性.作为 ...

最新文章

  1. C++中的变量作用域介绍
  2. java8 流操作_java8中的流操作
  3. 华为手机所有图标变黑_华为官博科普手机状态栏小图标含义,总共分为4大类...
  4. 比尔·盖茨:如果你想了解硅谷,就看《硅谷》吧
  5. 操作系统之多线程编程—读者优先/写者优先详解
  6. python中用def实现自动排序_漫画排序算法Python实现
  7. sql中“delete from 表名”表示_SQL查询语句知识点总结
  8. java test circle_java-使用Jacoco和Circle CI生成测试覆盖率失败
  9. 转:【微信小程序】实现锚点定位楼层跳跃的实例
  10. Theano 中文文档 0.9 - 1. 欢迎
  11. Python生成二维码-qrcode
  12. ThingsBoard 提示 New ThingsBoard version xx is availabled!
  13. 宋宝华linux内核驱动代码,宋宝华 《Linux设备驱动开发详解》示例代码之fifo字符设备驱动...
  14. java解压zip和rar并解决乱码问题
  15. Web容器、Servlet容器、Spring容器、SpringMVC容器之间的关系
  16. JS编写华氏度转摄氏度
  17. Racket 学习笔记
  18. 自动合并两个.bib 去除.bib中的重复条目
  19. 十几减9的口算题_十几减9精品口算练习
  20. 语义化你的HTML标签和属性

热门文章

  1. css盒心形的代码过程,如何使用CSS和D3实现用文字组成的心形动画效果(附代码)...
  2. 旧电脑更新win10日记
  3. android测试篇(三)单元测试之UI测试 Espresso学习与实践
  4. GBase 8c 数据库产品简介
  5. hdu 5234-三维背包
  6. Excel函数应用之查询与引用函数
  7. 电阻电路的等效变化(Ⅱ)
  8. 2021年Facebook广告投放的9条建议
  9. Windows安装Gitea
  10. systemd 知:介绍