来源 | 《深入理解EOS·原理解析与开发实战》
作者 | 李万才、林琪钧
编辑 | 乔治
出品 | 区块链大本营(blockchain_camp)
hi,老铁们!今天营长分享一篇干货文章。营长将为你详细介绍去中心化应用(DApp )的设计思想与开发流程,也会手把手教你基于 EOS 进行网页发币的开发实战。
本文分为以下3部分:
1、DApp 概念哲学及开发流程
2、基于 EOS 的 DApp 开发(25步!!!)
3、实战:网页发币!!
根据实际情况,自行选择跳读哈,文末送书、送书、送书。
先来个小调查
话不多说,赶快上车学习吧!!!
一、你真的了解 DApp?
上车之前,你要先搞清楚到底什么是 DApp,掏心窝子想一想,你确实清楚吗?
一般对于 DApp 的定义是,运行在分布式网络上,参与者的信息被安全保护(也可能是匿名的),通过网络节点进行去中心化操作的应用。具有以下三点特征:
去中心化应用应该适用于所有应用场景;
去中心化应用不局限在金融方面;
去中心化应用需要有前端代码和用任何语言编写的用户界面(就像应用程序一样),可以调用作为程序后端的智能合约。此外,前端最好选择托管在去中心化存储网络中,比如 Swarm 或 IPFS。
所以,DApp = 前端 + 智能合约(+其他支持类设备)。
1、比特币是第一个 DApp!
中本聪(Satoshi Nakamoto)将比特币描述为“对等电子现金系统”。通过使用点对点的分布式账本技术,比特币已被证明可以有效地解决无信任和可扩展电子现金系统带来的问题。然而,除了作为点对点电子现金系统之外,比特币也是用户可以通过计算机软件进行交互的应用程序。为什么这么说?原因如下:
所有比特币软件应用程序都是开源的,没有任何实体(政府、公司或组织)控制比特币,所有与比特币使用相关的记录都是开放和公开的。
比特币使用无法更改的预定算法生成其 Token,这些 Token 是比特币运行所必需的。比特币矿工因其在保护比特币网络方面的贡献而获得比特币奖励。
比特币的所有变更必须通过工作量证明机制获得其用户的多数共识。
2、DApp 是一个公司?BM又乱说
在 EOS 创始人 Daniel Larimer 撰写的一篇文章中,去中心化应用程序最初被描述为分布式自治公司(DAC)。但我们尽量避免使用“公司”一词,有如下两个原因。
首先,因为它带有不必要的歧义。例如,一个合法公司需要拥有股份、一个 CEO、员工等。像比特币一样的 DApp 显然没有这些特征。此外,考虑到命名对于各种国家对 DApp 的看法非常重要。
由于比特币在某种程度上具有了货币的概念,政府努力思考该如何管理比特币。如果使用“公司”这个名词,政府可能不得不继续去考虑管理作为去中心化应用的开源计算机程序,为技术的发展设置一些不必要的枷锁。
其次,因为传统公司可能会采用多种技术来筹集资金(例如出售其股票并支付股息或借入股票并支付利息),然而 DApp 不需要。
原因就这么简单。
二、DApp 开发的一般流程
在搞清楚什么是 DApp 之后,又如何开发一款 DApp 呢?别急,营长将详细为你一一道来。
1、建立共识机制
首先你的开发团队需要设计好待开发DApp的共识机制,看到这里,你可能会有些茫然,区块链不是有共识机制吗?那为什么基于区块链开发的DApp还需要设计共识机制呢(其实区块链本身就是一种去中心化应用)?
答案很简单,任何去中心化应用程序都不应属于某个独立第三方,而是属于一个类似于董事会的社群。DApp的每一次更新升级,或者说其发展道路是应该由社群来决定的而非一个CEO来决定,那么,在这个复杂的社群中如何对某个决策达成一致决定呢?这就需要共识机制了。
下面我们介绍一下常见的DApp共识机制,必须要说的是,现在大部分DApp采用混合式共识机制,但是在这里我们分别介绍每一种共识机制的概念。
工作量证明(PoW):我们知道比特币、以太坊等公链采用的共识算法就是 PoW,即在这个系统中,为网络安全做的工作越多,按理来说,回报就应该更高,多劳多得,公平合理。采用这一共识算法的 DApp 一般会为社群指定工作量考量规则,为 DApp 发展做了更多工作的用户将会在决策或分红中获得更大的权重。
贡献量证明(PoC):贡献量证明这个概念与工作量证明机制类似,即为 DApp 贡献更多的用户将会在决策或分红中获得更大权重,采用这种共识算法的 DApp 需要将“贡献”定义清楚,就像 steemit 一样,用户的贡献就是在平台上发布了多少优质评论,并根据评论获得的点赞数量量化贡献大小,并返回相应数量的 Token。这种模式灵活度更高,而且可以培养开发团队与社群之间的黏性,使双方成为利益共同体。
权益证明(PoS):权益证明与前两种方式相比就显得粗暴的多,持有自身 Token 数量越多,拥有的权重越高。因为如果用户花更多的钱用来持有自身 Token,那么从经济激励的角度考虑,该用户就越没有作恶的动力,就会做出有益于 DApp 发展的正确决策。
2、设计分发 Token 的机制
Token 这个概念可能是当前区块链中最重要的概念了,现在通常翻译成“通证”,顾名思义,就是可流通的权益证明。元道先生的解释最为透彻到点:Token 是区块链上可流通的加密数字权益证明,其目的是允许持有者访问指定的去中心化应用程序提供的服务。
例如,个人必须拥有多个比特币才能在比特币网络上执行任何交易。DApp 中的代币不代表任何相关资产,它们不赋予股息权利,也不代表股权。虽然 DApp Token 的价值可能会随着时间的推移而增加或减少,但 Token 不是股本证券。可以说一个 DApp 项目是否成功的关键评价标准就是其 Token 的市场价值。
所以 DApp 项目中最为关键的流程就是 Token 的分发,DApp 项目方在开发初期就需要仔细考虑其 Token 的设计,包括 Token 总量模型以及 Token 的分发机制。
其中 Token 总量模型决定了 Token 的市场价格,来源于一个最简单的金融学知识—价值等于总价值除以总量,因此必须仔细考虑 Token 的总量模型,常见的有两种总量模型。
a)Token 总量有上限
应用型 Token 的设计普遍采取积分+股份相结合的形式,可以完全把 Token 看作项目所有权的代表。
应用型 Token 总量固定,一方面,类似积分的特性,许多团队许诺 Token 持有者可以享受使用 Token 换取某种服务或抵扣某种费用的权利,比如某些交易所提出的 Token 抵扣交易手续费等;此外,团队还可以制定运营方案,利用积分发放的方式来免费发放 Token,以此提升社区活跃度。
另一方面,因为 Token 具备股份特性,使得 Token 的持有者可以通过项目团队主导的 Token 分红、Token 回购销毁等方式来享有项目发展的红利。在为应用设计 Token 时,要注意应用的市值通常较小,大部分市值可能落在1亿~100亿,因此,应用型 Token 的发行数量不宜超过100亿,应根据估值将总币量设定在1000万~100亿,以便以法币计价时,每个币的价格在0.01-1000元之间,有利于投资者间的沟通和交易。
以 BNB(币安币)为例:BNB 总量被限定为2亿个,50%归 ICO 投资人所有,40%归团队,剩下10%归私募投资人所有。持有 BNB 的用户,在币安平台上交易,在前5年可以享有逐年递减的手续费折扣优惠。此外,项目团队会在每季度拿出当季净利润的20%用于回购 BNB,并将回购来的 BNB 销毁,直至所有 BNB 总量为1亿个为止。
设计应用总量有上限的 Token 时,一共有4个可调整的关键参数。
Token 总量;
投资人、团队、基金会、矿工等利益相关群体的分配比例;
积分运营方案:运营活动中 Token 的免费发放/使用系统时实行费用抵扣;
股份分红方案:将净利润用于回购 Token 再销毁/将净利润按照持币比例直接分配给持币人(净利润通常为另一种 Token,比如 BTC、ETH 等)。
b)Token 总量无上限(股份增发)
无论是现实中的公司,还是区块链项目,都可能存在再融资的需求,这时可能面临配股、增发或是发行可转债等情景。由于应用型 Token 基于公链创建,所有特性受制于公链所能提供的功能。比如在公链项目 Waves 中,提供了资产增发的选项,基于 Waves 发行的应用型 Token,均可实现 Token 增发的功能。
另一方面,Token 的分发机制也需要做详细考虑。因为确定总量后,你总得把这些 Token 分发出来。一个优秀的 Token 分发机制可以保证项目的可持续发展,可以通过三种常见机制分配其代币:挖矿、募资和开发,而且在设计 Token 释放计划时,需要充分考虑以下三种分配机制。
挖掘机制:Token 分发给那些为 DApp 操作贡献最多工作的人。以比特币为例,比特币通过预定算法分发给矿工,验证交易并维护比特币区块链。
募资机制:将代币分发给那些资助 DApp 初期发展的人。这里涉及一个很重要的概念—私募,就是一个区块链项目在进行 ICO 之前进行的非公开融资,私募者资助的数字货币(常用ETH)将支持项目早期开发过程的开销,项目方将承诺在项目正式开发完成后,按照一个高于市场价格的返还比例返回资助者指定数量的项目 Token。
奖励机制:可以设置一定的奖励机制激励贡献者继续提供贡献,这是 DApp 是否可以充分利用社群力量达成自身可持续发展的关键因素。举个例子,由于 DApp 项目需要开源,一个优秀开源项目一定是可以吸引大量开发者共同开发的,所以为了奖励这部分开发者,可以设置相应的奖励机制用于奖励这些代码贡献者。
3、常见 DApp 开发阶段
去中心化应用程序的开发分三个步骤进行。
a)发布描述 DApp 及其功能的白皮书
与比特币的情况一样,DApp 最常见的形式是公开发布描述协议、其功能和实现的白皮书。公开发布后,社区的反馈对于发展议程的进一步发展是必要的。
b)分发初始 Token
如果 DApp 使用挖掘机制来分发其 Token,则会发布参考软件程序,以便可以将其用于挖掘。在比特币的情况下,发布了参考软件程序并创建了初始事务块。如果 DApp 正在使用筹资机制,则 DApp 的利益相关者可以使用钱包软件,以便他们可以交换 DApp 的 Token。如果 DApp 正在使用奖励机制,则会建立一个赏金系统,允许执行任务的建议,跟踪正在执行这些任务的人员以及奖励的标准。
c)DApp 的所有权权益被分散
随着采矿、筹款和奖励的代币分发给更多的参与者,DApp 的所有权变得越来越分散,而在早期持有多数股权的参与者控制越来越少。随着 DApp 的成熟,具有更多不同技能的参与者将被激励做出有价值的贡献,并且 DApp 的所有权将进一步分配。通过市场力量,DApp 的代币被转移给那些最重视它的人。那些人可以在他们拥有专业知识的领域为 DApp 的发展做出贡献。
比特币的情况说明了这一点。根据一些估计,中本聪开采了前1000000比特币中的许多比特币。随着开发人员为比特币贡献代码并且矿工为比特币网络贡献了计算能力,市场开始更加重视比特币。随着系统日趋成熟,具有不同技能的人们开始重视比特币并为其发展做出贡献。现在超过1200万比特币正在流通,而中本聪的原始所有权股份已被稀释。
三、基于 EOS 的 DApp 开发思路
下面营长将结合具体案例,详细叙述一下如何开发一个基于区块链的 DApp。
一个简单的 DApp 由两部分组成:前端界面/客户端+后端智能合约,两者之间的信息交互就依赖于 eosjs 库,eosjs 提供了使用 js 代码调用 eosio 相关 api 接口,开发者可以利用这个库,实现前后端相连,下面我们介绍一些该库提供的常用方法。
1、安装 eosjs
在 nodejs 中安装 eosjs 的流程如下:
npm install eosjs
npm install eosjs-api
注意 nodejs 需要最新版,如安装过程发生错误,请用 node-v 和 npm-v 查看版本。
2、建立 eosjs 与链的连接
接下来就需要通过 eosjs 库使网页端与 eos 节点连接,具体过程如下所示。
Eos = require('eosjs')
// 配置选项
config = {
keyProvider: ['PrivateKeys...'], // 配置私钥字符串
httpEndpoint: 'http://178.62.196.196:8888', //DEV开发链url与端口
chainId: "0b08e71a2f8caaccc2dc13244b788f5eba29462ecd5d5dea1ad8cbe9581e885a", // 通过cleos get info可以获取chainId
mockTransactions: () => null, // 如果要广播,需要设为null
transactionHeaders: (expireInSeconds, callback) => {
callback(null/*error*/, headers) //手动设置交易记录头,该方法中的callback 回调函数每次交易都会被调用
},
expireInSeconds: 60,
broadcast: true,
debug: false,
sign: true,
authorization: null // 该参数用于在多签名情况下,识别签名账号与权限,格式如:
account@permission
}
eos = Eos(config)
3、建立 eosjs-api 与链的连接
如果加载了 eosjs 后,默认加载 eosjs-api,无需单独链接 eosjs-api 与链。
EosApi = require('eosjs-api')
// everything is optional
options = {
httpEndpoint: 'http://178.62.196.196:8888',
verbose: false, // API logging
logger: { // Default logging functions
//log: config.verbose
error: console.error
},
fetchConfiguration: {}
}
eos = EosApi(options)
4、获取帮助
不添加如何参数,可以获取该方法的使用说明。
eos.getBlock()
5、获取链上最新出块信息
通过如下代码获取链上最新出块信息。
eos.getInfo({}).then(result => {
console.log(result)
})
返回:
server_version: 'b195012b',
chain_id: '0b08e71a2f8caaccc2dc13244b788f5eba29462ecd5d5dea1ad8cbe9581e885a', head_block_num: 209307,
last_irreversible_block_num: 209267,
'00033173a9ccd4bdd60a92d257e9354023b0457b134797be472a236cd908bc31', :
'0003319ba8ddc60d80c3cd0c7a70695cfd951f51ace9a798c913384cfbae659c', :
head_block_time: '2018-07-15T01:51:07.500',
head_block_producer: 'eoshackathon',
virtual_block_cpu_limit: 100000000,
virtual_block_net_limit: 1048576000,
block_cpu_limit: 99900,
block_net_limit: 1048576
}
如果需要拿到某一个数据值,比如 head_block_producer,则使用:
eos.getInfo({}).then(result => {
console.log(result.head_block_producer) //以对象属性方式获取head_block_producer
})
6、获取指定区块信息
获取指定区块信息方法如下。
eos.getBlock(200000).then(result => { console.log(result) }) //获取第200000个区块
或者
eos.getBlock({block_num_or_id:200000}).then(result=>{console.log(result)})//获取第200000个区块
或者
eos.getBlock('00030d4011a6744857533a6e6d907037a94c27a2dc006b4d28125f76bed2b355').then(result=>{console.log(result)})//根据id获取区块
或者
eos.getBlock({block_num_or_id:'00030d4011a6744857533a6e6d907037a94c27a2dc006b4d28125f76bed2b355'}).then(result=>{console.log(result)})//根据id获取区块
或者将返回值传到回调函数 callback 中处理。
callback=(err,res)=>{err?console.error(err):console.log(res)}
eos.getBlock(200000,callback)
7、获取账户余额
获取账户余额代码如下:
eos.getCurrencyBalance({code:"eosio.Token",account:"eosio",symbol:"DEV"}).then(result=>console.log(result))
以上命令相当于:
cleos get currency balance eosio.Token eosio DEV
8、获取某代币的信息
获取某代币信息的代码如下:
eos.getCurrencyStats({code:"eosio.Token",symbol:"DEV"},callback)//用上面出现的callback
9、获取账户信息
获取某指定账户信息代码如下:
eos.getAccount({account_name:"eoshackathon"},callback)//获取eoshackathon账户的信息
相当于:
cleos get account eoshackathon
返回
{ account_name: 'eoshackathon',
head_block_num: 219997,
head_block_time: '2018-07-15T03:20:12.500',
privileged: false,
last_code_update: '1970-01-01T00:00:00.000',
created: '2018-07-13T20:54:28.000',
ram_quota: 8148,
net_weight: 500000,
cpu_weight: 500000,
net_limit: { used: 145, available: 120795486, max: 120795631 },
cpu_limit: { used: 1511, available: 11518458, max: 11519969 },
ram_usage: 3414,
permissions:
[ { perm_name: 'active', parent: 'owner', required_auth: [Object] },
{ perm_name: 'owner', parent: '', required_auth: [Object] } ],
total_resources:
{ owner: 'eoshackathon',
net_weight: '50.0000 DEV',
cpu_weight: '50.0000 DEV',
ram_bytes: 8148 },
self_delegated_bandwidth: null,
refund_request: null,
voter_info: null
}
10、获取智能合约代码
获取 eosio 账户的所有合约代码如下:
eos.getCode({account_name:"eosio"},callback)
11、获取智能合约 ABI
获取智能合约 ABI 的代码如下:
eos.getAbi({account_name:"eosio"},callback)
12、获取 Table 行数据
获取 table 中行数据的代码如下:
eosjs.getTableRows({"scope":contract_name,"code":contract_name,"table":
"game","json":true}).then(result=>{}
13、获取账户的 Actions 列表
获取某账户 Actions 列表的代码如下:
eos.getActions({account_name:"eoshackathon",PoS:0,offset:15},callback)
//PoS和offset是指:从第PoS条记录开始获取offset条Actions
14、获取公钥对应的账户
获取公钥对应账户的代码如下:
eos.getKeyAccounts({public_key:公钥字符串},callback)
如果查找到账号,则返回[],如果该公钥没有对应账号,则报错。
cleos get accounts 公钥
15、获取主账号控制的其他账号
获取主账户控制的其他账号信息的代码如下:
eos.getControlledAccounts({controlling_account:"eoshackathon"},callback)
16、获取 transaction 交易细节
该指令有 bug,慎用!
eos.getTransaction({id:"xxxx"},callback)
17、转账交易
首先,在链接配置 config中,keyProvider 表示发送方私钥;其次,可以按如下方式设置 options 参数。
options = {
authorization: '发送方账号@active',
broadcast: true,
sign: true
}
完成转账交易的方式如下。
方式1:通过 transfer 函数完成转账。
eos.transfer('发送方账号','接收方账号','0.3000DEV','memo')
如果需要对返回值处理:
eos.transfer('发送方账号','接收方账号','0.3000DEV','memo',callback)
如果有 options 参数,则:
eos.transfer('发送方账号','接收方账号','0.3000DEV','memo',options,callback)
方式2:使用对象完成转账。
eos.transfer({ from: '发送方账号', to: '接收方账号', quantity: '0.1000 DEV',
memo: '备注', callback })
如果不想广播交易,可以使用以下简便指令:
eos.transfer('发送方账号','接收方账号','0.3000DEV','memo',false)//在最后加上false,不广播
方式3:使用 eos.transaction,构造对象执行如下命令。
eos.transaction(
{
// ...headers,
actions: [
{
account: 'eosio.Token',
name: 'transfer',
authorization: [{
actor: '发送方账号',
permission: 'active'
}],
data: {
from: '发送方账号',
to: '接收方账号',
quantity: '0.3000 DEV',
memo: '备注'
}
}
}
}
// options -- example: {broadcast: false}
)
以上命令与以下 cleos 相同:
cleos push action eosio.Token transfer '[ "发送方账号", "接收方账号", "0.3000 DEV", "备注" ]' -p 发送方账号
18、新建账号
通过 eosjs 创建新账号的代码如下:
creatoraccount = "testtesttest" //主账号
newaccount = "testtest1113" //新账号
newaccount_pubkey = "EOS5LUYdLZAd3uHF5XGAeE61aTeSXWqvqxBSUq3uhqYH7kY15Drjf"
//新账号的公钥
//构建transaction对象
> { =
tr.newaccount({
creatoraccount, :
newaccount, :
newaccount_pubkey, :
newaccount_pubkey :
})
//为新账号充值RAM
tr.buyrambytes({
payer: creatoraccount,
receiver: newaccount,
bytes: 8192
})
//为新账号抵押CPU和NET资源
tr.delegatebw({
from: creatoraccount,
receiver: newaccount,
stake_net_quantity: '1.0000 DEV',
stake_cpu_quantity: '1.0000 DEV',
transfer: 0
})
})
19、购买RAM
通过 eosjs 为指定账户购买 RAM 的代码如下:
creatoraccount="testtesttest"//主账号
newaccount="testtest1113"//新账号
eos.transaction(tr=>{
tr.buyrambytes({
payer:creatoraccount,
receiver:newaccount,
bytes:8192
})
或者
eos.transaction(tr => {
tr.buyram({
payer: creatoraccount,
receiver: newaccount,
quant: 8 //以k为单位的内存,8k=8192字节
})
20、出售 RAM
通过 eosjs 实现岀售 RAM 功能的代码如下:
eos.transaction(tr => {
tr.sellram({
account: 'testtesttest',
bytes: 1024 //出售1k内存
})
})
21、竞拍账号名
通过 eosjs 竞拍指定账号名的代码如下:
eos.transaction(tr => {
tr.bidname ({
bidder: "testtesttest",
newname: "竞拍的名字",
bid: 价格
})
})
22、抵押 CPU 和 Net
通过 eosjs 为指定账户抵押 CPU 与 Net 资源的代码如下:
eos.transaction(tr => {
tr.delegatebw({
from: "testtesttest",
receiver: "testtesttest", //testtesttest账户为自己抵押
stake_net_quantity: "1.0000 DEV",
stake_cpu_quantity: "1.0000 DEV",
transfer: 0
})
})
23、取消抵押(赎回))CPU 和 Net
通过 eosjs 赎回已抵押的 CPU 和 Net 资源的代码如下:
eos.transaction(tr => {
tr.undelegatebw({
from: "testtesttest",
receiver: "testtesttest",
unstake_net_quantity: "0.1000 DEV", //赎回0.1个DEV
unstake_cpu_quantity: "0.1000 DEV"
})
})
24、智能合约部署
如果加载的是 wasm 合约,不用使用 binaryen;如果加载 wast 合约,需要安装并使用 binaryen。
npm install binaryen@39.0.0
并用以下方式导入到 js:
binaryen = require('binaryen')
eos = Eos({keyProvider, binaryen})
部署合约的流程以官方自带的 hello 合约为例进行介绍:
fs = require('fs')
wasm = fs.readFileSync(`contracts/hello/hello.wasm`)
abi = fs.readFileSync(`contracts/hello/hello.abi`)
eos.setcode('contract_name', 0, 0, wasm) // contract_name 为合约名
eos.setabi('contract_name', JSON.parse(abi)) // @returns {Promise}
25、智能合约的执行
对智能合约进行调用的方法如下。
方法一:通过.contract函数完成调用。
eos.contract("contract_name").then(hello => { //hello随便起的变量名
hello.hi('axay', {//hi是方法名, 'axay'是该hello合约hi方法的参数
authorization:['testtesttest']//testtesttest是建立该合约的用户
}).then(result => {
console.log(result)
});
});
方法二:通过 transaction 函数完成调用。
eos.transaction(
{
actions: [
{
account: 'contract_name', //合约名
name: 'hi', //方法名,该方法在官方的hello合约中有
authorization: [{
actor: 'testtesttest',
permission: 'active'
}],
data: {
user: 'axay'
}
}
}
}
// options -- example: {broadcast: false}
).then(result => console.log(result))
四、EOS DApp 开发实战
下面我们将手把手带你开发一个 DApp 的网页发币模块,包括前后端整个流程。在学习之前你应该具有以下基础:html5、css、JavaScript、react。
1、创建钱包
为了构建实际与钱包和账户交互的 DApp,我们需要设置它们。在终端中输入
cleos wallet create。
这将返回密码,将其保存在安全的地方,因为你很快就会再次需要它。
注意:本教程采用 docker 运行 EOS节点程序,如果上面的指令不起作用,则表示你没有在上面的步骤1中为“cleos”添加别名。请务必遵循 EOSIO 提供的整个 docker-quickstart 指南。
如果你遇到钱包被锁定的问题,请输入cleos wallet unlock,然后输入你之前保存的密码。
2、创建账户
为了与 DApps 互动,你需要在钱包内设置一个账户。我们首先将两组密钥导入我们的钱包,一个是 OwnerKey,一个是 ActiveKey,确保保存两个密钥对。OwnerKey 应始终保持高度安全。
a)首先创建你的 OwnerKey
在你的终端中,键入 cleos create key,终端将返回私钥和公钥。
接下来,输入 cleos wallet import(上面创建的私钥),终端将返回导入的公钥值。
b)创建 ActiveKey(与创建 OwnerKey 的步骤相同)
在你的终端中,键入 cleos create key,终端将返回一组新的私钥和公钥。
接下来,输入 cleos wallet import(上面创建的私钥),终端将返回导入的公钥值。
c)创建你的第一个账户
在你的终端中键入如下命令:
cleos create account eosio user1[Owner Public Key][Active Public Key]
创建完第一个账户后,你可以按照相同的步骤创建第二个账户(例如,如果你的应用程序让用户将代币发送给另一个账户),那么我就假设你创建了一个名为 user2 的第二个账户。
d)创建 Token
我们下面将创建一种新的 Token。与以太坊不同,使用 EOS 创建 Token 生态系统非常简单,可以从终端完成。我们将部署 EOS 附带的标准代币,但你可以轻松地修改和自定义 eosio.Token 合约,或从头开始构建自己的代币合约。
首先,我们将创建部署代币合约的账户。按照创建账户中的步骤生成 OwnerKey 和 ActiveKey。
然后,在你的终端输入如下命令:
cleos create account eosio eosio.Token[New Owner public key][New Active public key]
接下来,我们将标准的代币合约部署到这个新创建的账户中。
cleos set contract eosio.Tokenbuild/contracts/eosio.Token -p eosio.Token
请注意,在上面的行中,-p eosio.Token 表示账户 eosio.Token 授予部署合同的权限。你的钱包可能会被锁定,在这种情况下,你需要按照创建钱包中的解锁步骤解锁钱包。
当你创建自己的自定义合同时,你将按照我们在此处所做的方式部署它们,但 cleos set contract eosio.Token 你将替换 eosio.Token 为自定义合同。
接下来,我们将使用刚刚创建的代币合约创建一种新的 Token。你可以根据需要为 Token 命名,并设置发出的 Token 总数。
cleos push action eosio.Token create‘[“eosio”,“1000000000.0000TOK”]’-p eosio.Token
上面的示例创建了以“eosio”作为发行者的10亿总量的 TOK 代币。最后一步是向我们的一个账户发放代币。请注意,“memo”是一种将字符串描述附加到事务的方法。此外,我们现在从 eosio 而不是 eosio.Token 获得许可(通过-p),因为 eosio 账户拥有所有10亿个 Token。
cleos push actione osio.Token issue'["user1","100.0000TOK","memo"]'-p eosio
e)使用 eosjs 将 eos 连接到你的 DApp
接下来将向你展示如何利用 react 实现前端与智能合约之间的交互。如果你尚未设置 react 应用程序,请键入:
create-react-app[name of your react app]
在该生成的初始目录中打开终端,在终端中键入以下内容以安装 eosjs 并将其添加到 package.json 中。
npm install eosjs -s
然后在你的 App.js 文件中,你将要使用以下命令导入 eosjs:
import Eos from “eosjs”;
我们必须初始化一个 eosjs 实例才能在我们的应用程序中使用它。通过将以下内容添加到全局范围来执行此操作。需要注意的是 user1ActivePrivKey 和 user2ActivePrivKey 是我们在创建账户创建的私有密钥,注意尽量不要在这里使用 Owner 密钥,使用 Active 密钥更安全。
const eos = Eos({
[ :
user1ActivePrivKey,
user2ActivePrivKey
]
});
现在,我们可以轻松地与本地 EOS 节点进行交互。我们的第一步是检查两个用户账户的代币余额。
eos.getCurrencyBalance(“eosio.Token”, 'user1').then(TokenBalance => {
console.log(TokenBalance)
});
由于我们在上一节中向用户1发出了代币,因此你应该看到当前代币余额为100.0000TOK。如果我们检查 user2 的代币余额,你应该看不到任何余额。
eos.getCurrencyBalance(“eosio.Token”, 'user2').then(TokenBalance => {
console.log(TokenBalance)
});
在这个示例 DApp 中,我们使用了一些非常基本的功能。我们假设user1正在接收一些值,并且作为交换,将代币发送给 user2。在 eosjs 中,最好的方法是通过“交易”。在这里,我们将发送5个TOK。
eos
.transaction({
[ :
{
“eosio.Token”, :
“transfer”, :
[ :
{
actor:“user1”,
permission:“active”
}
],
data:{
from:“user1”,
to:“user2”,
quantity:`5.0000 TOK`,
“包含交易的一些描述” } :
}
}
]
}).then
> { =
//再次检查代币余额。
//账户中看到5 TOK,在user1的账户中看到95TOK
});
最后,在前端 html 页面中调用这些函数,就可以完成智能合约的交互啦。
试一试,OK了吗?
本期话题:谈谈你对 DApp 开发的理解(50字以上)。
请在文末畅所欲言,营长将从精选留言用户中抽取5位幸运读者,免费送书一本!
截止时间4月16日(下周二)中午12点!
感谢华章科技大力支持
推荐阅读:
微软加速器檀林: 5G 会催生一个新的 Web3.0时代 | 视频访谈
V神玩起freestyle! 5位以太坊核心大咖在悉尼的演讲精华全在这了!| 直击EDCON
偷电、挖矿、赚快钱,这些大学生到底怎么了?
频繁跳槽涨工资?会影响征信的! | 畅言
京东或将裁员 12000 人!雷军年薪百亿;马云:阿里没人敢跟我打赌 | 极客头条
39个国外SCI抢发6万篇中国英文论文?然而,真正的问题是……
终于有人把5G和边缘计算的关系说清楚了 | 技术头条
曝光!月薪 5 万的程序员面试题:73% 人都做错,你敢试吗?
猛戳"阅读原文"有惊喜哟
老铁在看了吗??