00:00
那接下来呢,我们就会给大家具体的梳理一下,我们整个的产品架构是什么样的,然后我们怎么样去实现的,大家就也是跟着这个思路,就是去顺一下自己,如果去做一个产品,做一个应用的时候,怎么样去设计,从哪一步开始。呃,首先我们看一下这个DM架构,首先我们是要有区块链啊,这第二步,这个其实就是大家最先应该想到的,这是我们应用的核心,就是我们的核心的业务逻辑代码和那个交易数据都要放到以太坊上面去,呃,然后呢,大家可以想到我们列出来的所有的商品这个信息,它的具体信息,具体图片可能不往上面放,但是基本信息也都应该放在链上,对吧,都应该有据可查,至少得有这个,然后用户去出价,去拍卖的这个记录,记录,还有就是说我们的这个账款打到那个托管账户上,托管合约,这些都是跟以太坊。
01:03
区块链相关的部分啊,这其实就是我们的核心逻辑,那除了这一部分之外呢,大家就会想到还有web前端对吧?因为我们是一个APP,我们是一个应用,所以呃,大家如果要是有同学做过移动端开发的话,那其实也可以把它迁移到就是安卓啊iOS的开发上,我们这里是只讲这个,就是纯web开发啊,Web前端那主要就是H cm2CSS,它是做这个页面的布局和展示,那JSJS,这就是要用WEB3GS跟我们的区块链去做交互了,对吧?这一部分也是我们非常重要的部分,那这一部分大家注意啊。我们跟IPFS的交互是在前端这一部分做的。就是这是我们的架构的一个设计。所以大家注意一下啊,这其实是借鉴了我们就像传统的如果一个中心化的外部服务器去做大数大文件存储的时候,用一个阿里云的oss服务器,我们也是这样的架构。
02:09
也是前端直接去调oss那边接口放到那边去,最多跟后端那边是比方说拿一个这个token啊,那个这个token就是令牌了,对吧,不是我们说的代币啊,或者说是从后端那边去申请一个它的密钥,然后去就直接传到跟oss服务器那边腾讯就可以了,我们这边的架构其实是非常类似的,等一下大家看图啊。另外我们这里还涉及到的呢,也要涉及到IPFS对吧?IPFS主要的作用就是把我们的这些产品的图片和大文本介绍,大的文件数据都传上去,做存存储,另外还涉及到两个东西,一个叫mango,一个叫noe的服务器,他们是做什么事情呢?那这一部分其实主要就是说我们要构建一个链下的后端服务。
03:03
它的作用是干什么呢?主要就是说链上你做查询做交易,这不是很慢嘛,对吧,那我们交易的话,这个记录,记录必须记到链上,那没办法,你就慢就慢点,毕竟这个交易这个动作也是你会谨慎一点,对吧,但是你在那儿刷网页的时候,那这个速度可能是要求非踌快的,呃,大家一般刷的时候都是啪啪啪直接往过过的,你这个如果要是用链上的一些数据,可能就很慢了,所以我们就想到为了性能考虑,单独再搭建一个node后台服务器,然后数据库用什么呢?用mango啊,这就是我们的一个想法啊,我们看一下这个架构图吧。这个架构图大家会发现我们这里边的核心其实是我们的web前端,对吧,这里看起来好像是就是这是我们整个架构交互上的核心,因为人就是在这里去交互的,对吧?所以绝大多数的东西都是以这里作为一个基准的,大家看到它和我们的block这个区块链这方面互相之间交互,也就是说我们的核心的后台逻辑都放在这个区块链上。
04:16
那还有一部分查询方面的逻辑会放在node和mango这边。所以大家可以认为整个的这一块啊,都是我们的后台。就是大家看到下面的区块链,还有这个note和mango这一块,都是我们的后台前台,就是我们的这个web页面。核心的数据还有交易。这些不可篡改的数据放在区块链上,那。大文件这些东西存哪里呢?前端上传之后直接存到IPFS上,然后IPFS返回一个哈希给到前台,前台再把这个传到写到我们的区块链上去,所以是这样的一个流程,大家可以梳理一下这个过程啊,也就是说大家可以想象就是我们一开始是在这个web前端去上传一些图片,对吧?上传一些产品的信息,这个时候我们要存这些信息往哪存呢?大文件直接往这边存。
05:17
IPS。然后拿到哈希之后,跟连同产品的那些基本信息,小的那些信息对吧,方便存储的信息全塞到区块链当中去啊,这就我们的基本的数据就有了,然后要做交易的时候,也是我们在web这里去点我们JS定义各种各样的页面的点击的事件,对吧,各种各样的这种处理,然后去跟我们的以太坊区块链去做交互,把数据存进来,那我们如果要做想要去加速性能,去做快速查询的话,把查询的这一块。一些基本的数据在同时放到这个mango DB来,那用什么去查呢?我们再起一个note server,一个服务器,我们的前端页面查询的时候可以直接访问他,他的数据从man里面来拿。
06:09
所大家可以看到这个流程是怎么样的啊,就涉及的模块有点多,我们之前的话就相当于没有这一部分对吧,也没有这一部分就是一个web前端,还有一个区块链,所以我们的区块链就是后台对不对,前端后台对吧?所以大家其实学完了之后都是前全站,所以就是这就是我们为什么说区块链这一部分要求很高,就是大家就是什么东西都得学,什么东西都得懂,真正学完了之后,那那就是全站,而且还不是一般的全战,是这个什么IP FS mongo nod myq,什么东西都懂,对吧?所以这是对大家的一个要求,也是大家的一个基本的目标啊。好,接下来我们看一下这个应用的流程。应用流程图,这个是它也就是在上面这个架构图上面给了一些数字,那就标出我们到底是怎么样的一个怎么样的一个过程,大家可以看到啊,首先大家就会看到,刚才其实我们也已经说了,第一步就是在web前端这里做的,对吧?用户输入这个产品的一些细节,然后保存,保存的时候web前端是要生成一个HTML表格的,对吧,有一个form,然后我们把这个提交表格提交之后,提交的这个动作我们是要。
07:31
怎么样去保存呢?大家会看到第二步是先把这些大文件存到IPS。然后第三步,IPFS返回一个哈希。然后第四步,我们前端收到了所有的产品信息,把这些就是比较简短的信息全部传到区块链上去。然后区块链当然会返回给前端一些当前的这个状态信息,对吧,前端根据查询到的状态信息展示我们的页面啊,这就是我们这个这一部分的这个流程,那之后呢,大家会发现啊,我们有了这样的一些存储之后,我们怎么样去把这个同时存到这个网购DV里边去呢?
08:19
这里给大家列出了这个处理的流程,我们会在这个第四步,第五步这里啊,我们让它存入区块链的时候触发一个事件,我们定义一个event,大家还记得我们之前合约的时候讲过事件吗?我们之前好像都没怎么用过,对吧?这里我们会有用途了,那这里定义了事件之后,那大就会想到你既然写到这个区块链上了,我是不是在。别的地方node那里我就可以去监听这个事件啊,你这里一写node监听到之后,然后就把对应的数据同时也写入mango里面去,这就实现了mango这里数据跟我们区块链上数据的一个同步,对吧,而且实时更新。
09:07
所以这就是这样的一个过程,那至于之后用户还想去快速查询的时候,那就走这条线到note服务器去做查询就可以了,然后note服务器直接可以通过mango里边的数据返回给web前端,这就是我们整个的一个操作和处理的流程。大家应该整个有这样的一个一个框架在头脑当中啊,啊接下来说一下我们具体用到哪些工具,和我们要学习的这个前后的这个实践步骤啊,首先我们这个项目呢,还是穿。还是基于我们之前已经用到的这个穿框架,因为它确实好用,对吧,做测试也快,所以我们还是用这个,最后一个项目可能我们就会把trouble抛开,因为我们可能会用就是web1.0的WEB3JS1.0的一些写法,一些语法去给大家去做一些操作,那到时候我们可能就自己去用到我们之前的那个自动化编译和自动化部署的那些脚本,对吧,他会发现我们那套脚本其实跟窗户差不多,只不过没他这么没他这么包装的好而已,所以呃,现在我们还是用trouble啊,那当然了,写合约就是solidity了,呃。
10:23
然后我们部署的时候,我们开发环境直接用GA纳就可以,呃,后续的话,大家想部署到四店,想部署到这个测试网络都是可以的,然后接下来我们写先写合约,写完合约之后我们学IPFS。然后我们安装好这个IIPFS的命令行,跟他去交互,然后我们后台的这一部分基本上就学完了,就是就是区块链相关的后台就学完了,然后讲完了,那之后呢,我们会去构建前端。把页外部页面写出来,写JS去跟我们的后台交互,呃,那这一部分呢,就会有很多,比方说怎么样出价,怎么样拍卖,怎么样显示,对吧,怎么样,后面大家看到还有这个托管账户对不对啊,这一步写在最后面,其实我们在前面就都都需要把它去实现啊啊然后就是还可以去撤回资金什么的,呃,然后这些东西都完成之后呢,最后我们还要去安装一个网购DB。
11:29
然后再起一个node JS server。我们去做一个快速查询对吧,监听他的事件,然后做快速查询。好,这就是整个我们要学习的几大部分和我们大概的一个步骤,好,接下来我们就不要说太多废话了,就准备写合约吧,呃,那这个还得先多说一句啊,就是我们现在的这一个窗口项目呢,大家最好还是新建一个目录,当然我这里给大家举例,可能我就我我就懒对吧,就就直接用我们之前的目录了,因为整个这个呃,大家去重新travelle on box pack的时候,可能也会还得花花一点时间的,所以呃,大家可以先不管这个,但是就是今天我们也也还用不到,我们今天只是写一个基本的合约嘛,所以大家就是知道该怎么做就可以了,怎么做呢,新建一个目录,然后进去之后trouble on box还是把wipa那个包拿下来,对吧,拿下来之后,可以把它默认的那个ma coin和convert lab那个源文件都删掉了,呃,我们接下来自己去构建自己的文件。
12:39
好,那接下来大家注意啊,就是我们这里边的合约有哪几个需要实现的场景呢?首先合约里边我们能够让用户添加产品。能够创建产品出来,能够把这个产品的信息存储到区块链上,这是第一个基本需求。然后第二个。
13:02
能够,呃,我我们肯定就要实现这个把产品加入到区块链的函数了,对吧,我们首先要定义产品的数据结构,然后要实现把产品加入到区块链里面的这个函数,然后我们应该要实现一个能够出价的功能,意思是什么呢?就是说我们要去竞价拍卖。核心功能对吧,然后我们还要去实现一个证明出价金额的函数啊,这个所谓的证明出价金额是什么呢?其实就是揭示自己的报价,然后大家要一揭示报价全部揭示了,那相当于大家现在就可以这个拍卖就结束了,就可以确定谁到底拍卖成功对吧,这个谁到底竞拍成功,所以这是我们的核心业务逻辑啊,就一个是出价拍卖,出价竞价,一个是揭示竞价。把我们的这个结果揭示出来,所以这是两个核心的业务逻辑,今天我们可能先写前面两个,简单一点的就是先定艺术结构,然后把我们的这个产品能够添加到区块链里面来啊,这个应该比较简单,对吧,大家能想到就是个存储嘛,好,接下来我们就来具体来做了啊。
14:13
首先contracts目录下面建一个新的文件叫e commerce store电商对吧,电子商场这么一个文件,好,然后呢,大家,呃,我先跟大家先过一下它的这个介绍啊,首先我们要定义数据结构,主要的数据结构有哪些呢?首先我们应该想到。我们这是一个电商,电子商场的一个合约,那里边有商场,它是不是应该有商品啊,所以我们肯定要有一个叫做product的一个对象,它里面肯定包含很多信息,对吧?所以我们构建一个结构体叫做product product,然后呢,我们里面会包含哪些信息呢?可能会大家可以看到下面啊,有各种各样的信息,对不对,等一下我们敲一遍就可以了。
15:02
然后大家会想到,我们还应该有什么样的东西呢?呃,这里边给大家提到了啊,就是说我们还应该有一些枚举类型,比如说什么呢,我们去存储产品状态。产品应该有状态,对吧,你到底现在是不是可以去拍卖呢?你是不是已经拍卖结束了呢?现在是不是他已经卖出去了呢?还是说他拍卖结束根本没卖出去呢?这些可能都是需要查询出来给用户看的,所以我们那大家直接如果直接在里边去写这个状态是零是是一,这个其实不太好,所以我们定义一个枚举类型,这个可读性就会好很多了,对吧?另外还有一个枚举类型,就是可能这个,呃,每一个商品它还有一个基本的一个状态,就是它是二手的还是新品啊,这可能也是需要去标注一下的,对吧,这也是一个枚举类型。好,那接下来我们还应该有一个数据结构,大家看到加入了一个计数器。
16:05
就是给每个加入到商店的商品都赋予一个ID,那这个ID怎么赋予呢?就是什么时候这个商品加进来,当时的那个计数器是什么,我们就给他付给这个商品作为他的ID,然后就加一等下一个商品,对吧?所以相当于是一个序列号,所以在别的一些数据库里边,比如说呃,Mexico啊,Mongo啊,他可能大家知道这个就就有一个自增的ID,对吧?这些东西大家可能就比较实现,这个比较简单,我们这里面没有,那怎么样去实现呢?我们自己给它加一个计数器,加一个ID,叫做product index,这就是我们产品ID。好,那接下来我们有了ID了,那应该就可以去检索我们的呃,产品对不对,但是这里大家需要知道啊,就是我们首先怎么样去查这个商品呢?我们应该是根据产品ID去查对吧。
17:10
是不是这样啊,所以大家注意啊,这里边实现的方法是大家可能会想到我们在查询的时候有两种模式,可能需要根据产品ID去查产品,另外还得根据用户。去查他到底创建过哪些产品对不对,就是对于我们的这个应用来讲,可能用户这个角度是更重要的。所以我们在这里首先需要实现的是用户和他的发布的产品的一个对应的关系,所以这当然就应该是一个mapping了,对吧?所以大家可以看啊,我们会有一个stores的一个mapping,通过这个mapping呢,我们记录谁插入了商品,所以这个mapping应该是一个什么东西呢?它就是一个从一个地址,一个用户到一个产品的一个一个mapping,对吧,一个映射。
18:07
那这个产品我们怎么样去检索呢?所以大家可以等一下,可以看到就是它的实现是又嵌套了一个map。就是我们怎么样再去简单的能检索到这个产品,他的那个编号是哪个呢?对吧,因为这个人他可能上架了很多产品嘛,怎么样去检索呢,然后我们再用产品的编号,再去对应到产品的这个结构体,所以是这样的一个过程。那接下来大家可能就又会想到,那假如说我们知道了一个产品的编号的话,我们怎么样去查呢?那这里就又定义了一个一个mapping,是我可以定义一个mapping,从知道产品编号之后查到他属于哪一个人。查到他的那个上架他的那个创建者,那这个是不是根据创建者就又能够到对应的这个mapp里边去查到他的具体信息了,所以它是这样绕了一下,然后节省了一些数据存储的结构,对吧,大家也可以做一个冗余,把这个拆开,那就得多存几个mapping了。
19:19
那大家注意,就是我们如果要想尽量的节省这种存储的耗费,节省gas,节省我们的这种交易费用的话,那就尽量的少定义一些结构,所以这里面是相当于是一个优化。好,那接下来接下来我们来给大家实现一下,在我们的这个代码里面实现一下啊,我这里边就很简单的,在我这里直接新建一个。叫做什么来着,Commercial commercial commercial是吧?叫什么?Commerce啊,这个商业这个不太不太好写啊,这个单词commerce store也就是电商对吧,So。
20:08
好,那么接下来我们就来看我们敲一个合约,Pragma solidity,呃,这个合约的话,我们版本其实还是用大家熟悉的版本,4.1几就可以啊,随便给一个4.17吧,然后contract名字一样E。Commerce store store对吧?再看一眼啊,这个总怕写错。好,Commerce store,这是我们的合约,然后大家会想到,首先我们一般最先定义的是枚举类型啊,我们先把枚举类型写出来,这个比较简单一呢,然后比方说我们定义一个,呃,Product status,对吧,我们前面说了它有这个状态,那这个状态它有哪些,哪些状态呢?呃,就是它是否是这个可以去竞价的状态,对吧?呃,我们就像这个一样,就是用一个open来表示吧。
21:19
Open,然后还应该有什么状态啊,就是是否已经竞拍结束卖出去了,或者是竞拍结束没卖出去,对吧,有一个so的状态,有一个UN sold。啊,那大家知道,就是在这个的呃,枚举类型里边,其实它指代的这个值是什么呢?就是012对吧?啊就就是一个整形整数,所以这个其实没有什么特别的地方啊好另外再定义一个product,它应该叫condition对吧。Condition它本身所处的状况,那这个状况呢,就是它是一个新品还是一个二手的new,或者是news,是这样的一个枚举类型啊,这个已经定义出来就可以了,这个比较简单啊,那接下来大家会记得我们还定义了一个叫做它的那个index,对吧?每一个产品进来之后有一个单独的编号,这个是我们一个全局的状态变量,它是一个计数器。
22:27
所以product index。我们按照这个来写。好,接下来我们要定义mapping了,对吧,首先大家记得我们会有一个从产品是不是到用户的一个一个mapping啊。对,我们本身是以用户作为根本的,那产品怎么样去具体查询呢?我们把它关联到用户上面去,好,那么这个mapping我们叫做product。
23:00
呃,这这个叫什么吧,这个叫product owner吗?啊,不是啊,这个里边它定义的叫product ID install啊,这个我为了防止以后再出现这种命名的错误,还是还是跟它命名的一样吧,因为这个项目大了之后,到后面可能会越来越乱,对吧?ID in store in store,好,这是我们定义了一个mapping,就是从一个产品的ID关联到它的创建者,那同样大家会想到,那我们是不是得把这个创建者跟这个产品的具体信息要结合在一起啊。呃,所以这里其实是应该他直接关联到,大家可能会想到是不是应该直接关联到一个product类型,对吧,但是大家会注意啊,这里会有问题,如果我们直接关联到一个product类型的话,那假如说我现在想要去查询ID是一的那个产品,我这个结构只能查到。
24:10
他属于谁对吧,比方说属于爱丽丝。然后Alice这里边存储的这个数据,这是不是应该是一个结构体啊,它应该不可,呃,它是应该应该应该是一个数组,对不对,他不可能只存了一个,上传了一个产品,对吧?那我们要去想要拿到对应这个ID的产品,是不是我们得遍历这个数组啊。但是我们跟大家说了,以太坊的存储结构里边,便利这个事情是做不到的,因为它是一个很大的存储空间,靠哈希哈希出去的,你去便利的话,这个成本太高了,所以大家要注意我们这里边,要不然你就另外再去做一个mapping去做对应,那我们这里的处理方法呢,就是mapping再套一个mapping,这个设计还是比较巧妙的,大家看一下,那这个mapping是怎么做的呢里面啊。
25:06
里边定义一个UT到product的一个映射,那有了这个映射之后,大家可能就会发现,这是不是就是相当于我们一个人他对应的账户,然后就能找到他上传的所有的。产品这是一组对吧,一个mapping,那这一个mapping我们用什么样去访问呢?用它的编号直接就可以访问,这个就方便多了,对吧?我们知道它的ID就完全可以查出来了,再看一下它叫什么啊,这个就叫stores,所以大家可以从这个命名上看出来,本身这个就是这个这个项目的原作者,他对这个产品设计的一个思路是什么呢?就是说我们这里边定义了每个人他的产品的一个一个一个这个存储,对吧?从另外一个角度讲,这是不是就相当于一个商家啊,对,这就相当于一个商店,所以一个账户背后就代表着一个商店,那么这里为什么定义成叫product?
26:23
这是product ID吗?是不是写错了啊,是product ID啊,为什么写成product ID store呢?因为这个关系就是我们在这个这个address表示一个商家对吧?表示一个商店,所以说这是不是就是一个product的编号对应这个商店的一个关系啊,是不是就是他在这个商店里边的一个状态,所以说通过这个命名也能够看出来啊,啊这里大家看到我这里已经报错了,那报错了肯定就是这个product我们还没定义对吧?所以这个东西我们来定一下吧,这是一个product。
27:03
好,里边这个我们就能想到的,直接往出写了,首先应该有一个ID对不对,好,再来瞄一眼啊,好,所以大家就会看到里边基本的东西,Name,这肯定是要有的,对不对?呃,然后它的这个产商品的这个名称是什么,然后如果是电商商品的话,肯定还要有一个归类,对吧,归类叫category吧。怎么拼来着?瑞对这个好,那接下来我们是不是还应该存他的这个产品图片和产品说明啊,那这里边我们看叫image link和description link,就是DEC link对吧?这两个大家可以想象到为什么叫link呢?对,因为我们本身是不不准备存它的,对吧,美,我们这里要存的其实只是它的一个link对吧,所以真正的这个文件是要放到到时候放到IPFS上的。
28:07
所以d link,好,那接下来大家就会想到我们竞拍了,竞拍呢,应该还应该有个时间,对不对,会有一个竞拍的开始时间,会有一个竞拍的结束时间,好,那这个时间的话,我们用一个时间戳,你在晚上时间戳就是一个整数,对吧,所以定一个unit,然后竞拍叫auction啊auction start start。同样,我们还应该有一个竞拍的结束时间,And time。有了这两个东西之后。大家会看到还有什么东西呢?呃,还有这个start price,你的起拍的价格对吧?这也是一个U类型,然后还有大家注意啊,这里剩下的东西大家可能现在还不知道他干什么,这是就涉及到我们之后的这个竞拍的规则,什么规则呢?就是呃,我们到时候是一个按标的竞拍,是一个盲拍,所以最后的标准是要知道,首先大家能想到,首先我得知道最高的这个竞价者对吧,他最后要赢,然后最后呢,还需要知道第二高的竞价。
29:22
这个是干什么用的呢?就是最后这个他支付的不是他自己拍出去的那个价格,最后支付的是第二高的那个价格,所以是这样的啊好,那么我们这里就直接照着这个先敲上去,这个之后可以再慢慢给大家解释,好那么我们这里会有一个u int,叫做呃,Start price,对吧。然后会有一个address,叫做highest。Highest bit竞拍者对吧?好,那接下来有这个竞拍者,就会有他的竞拍的那个数数字,Highest bit,那除了最高的high highest bit之外,还有那个第二高的,对吧?也也得记下来,Second highest。
30:21
Bit,好,这几个都是要,都是要记下来的,另外还得记录一个,就是这个商品总共有多少个竞价,这个也是商品的一个,会显示给大家看的,对吧?这个商品很热,有多少个人在竞价,Total bit,这个也是要的啊,好,我们最后再看一下还有哪几个好,这就是status和condition,对吧?我们上面定义的这两个枚举类型,这个在初始化的时候肯定也是要把它写进去的,所以就是product status status对吧,这个枚举类型,然后给一个status。
31:07
给一个condition。好,我们把这个数据类型就基本上就定义好了,那定义完数据类型之后,大家肯定会想到我们一个基本的合约是不是至少要有一个constructor啊,Constructor里面大家看一看我们的这些状态变量哪个是可以初始化的,我们这是枚举类型,这是一个结构体,好像这些都不能初始化,对吧?这它本来是一个数据类型嘛,那我们看变量,变量里边这个product。ID store,这是商品在商店里面的ID,还有就是商店这些你一开始都没人啊,对吧,也没人,也没商品,什么都不能初始化,所以我们唯一能初始化的就是product index。这是我们的计数器对吧?所以一开始我们是不是得给一个零啊,对,所以大家能够想到啊,我们的初始化product in index等于零,好,所以这就完成了我们整个的这个初始化,好那么大家可以看到我们基础的数据结构就这样已经实现出来了,当然这里我们呃应该把这个public加上啊,大家看这里有一个warning的对吧,我们把这个显示的写出来public,所以这一部分我们就做完了。
我来说两句