主页 > imtoken官网下载安全吗 > 以太坊 DApp 开发教程 (1) 环境配置和松露入门
以太坊 DApp 开发教程 (1) 环境配置和松露入门
要安装 Nodejs 环境,请选择对应的平台,然后下载 LTS 版本。安装完成后,在终端中输入以下命令查看,如果版本号正常输出,则安装成功
node -v
图片.png
要安装
松露框架,输入以下命令进行安装
sudo npm install -g truffle
安装
甘纳许并下载相应的平台安装包进行安装。Ganache是一个图形化的以太坊私有链程序,打开后可以在本地构建以太坊私有链,方便快捷。启动Ganache后,将有10个默认帐户,所有帐户都具有100Eth以太坊开发教程,当然,这只是用于测试,因为它在您的私有链上。安装完成后,请启用 Ganache,稍后部署合约时会用到
图片.png
下载小狐狸钱包。出于网络原因,我们使用 firfox 或 Opera 版本的插件。当然,您也可以直接下载浏览器。为您的第一次编程体验创建目录
首先,我们创建一个目录。不用说,我的目录叫做SmartContart
图片.png
在当前文件夹下输入松露命令以取消装箱项目
truffle unbox pet-shop
图片.png
使用您的编辑器打开此项目以太坊开发教程,我使用的是 Atom,该文件夹如图所示。需要注意的是,migrations 是部署合约的一个文件夹,是通过 js 部署的(图中对迁移的解释是错误的,请忽略)。
图片.png
让我们创建一个名为 Election.sol 的新智能合约,并编写以下代码:
pragma solidity ^0.4.2; //这句声明了我们的solidity版本
//声明一个合约 contract是关键字,Election是合约名字,合约名字和文件名要一致
contract Election {
/* 声明一个public 的string类型的状态变量(可以理解为成员变量) */
string public candidate;
/* constractor 函数名和合约名一样的函数就是构造函数,与C++相似*/
/* 构造函数是public的,因为需要外部来调用 */
function Election() public{
candidate = "Candidate 1";
}
}
此代码声明一个协定,然后将一个值分配给构造函数中的状态变量 candicate,仅此而已。
在终端中打开项目目录,输入以下命令部署合约
truffle migrate
图片.png
部署后,进入松露
控制台,打开松露终端,然后输入以下代码行
Election.deployed().then(function(instance) { app = instance})
你会得到一个未定义的错误,我们现在把它放在
然后输入应用程序地址,您将看到打印的地址,
即合约地址,然后输入 app.candicate(),您将看到打印的值是我们在构造函数中分配给 candicate 状态变量的值
图片.png
当我们声明 Candicate 状态变量时
作为 public,会自动生成一个同名的 get 函数来获取这个状态变量的值,我们通过创建的 app 对象访问 Candicate 来获取 Candicate 的值。此时,打开您的 Ganache,您会发现您有一个以太币较少的帐户,这是部署合约的成本。
图片.png
至此,我们已经部署了一个非常简单的合约,只有读取变量的函数。让我们向 Election.sol 文件添加一些代码。我们将 Candidate 替换为结构体,并添加了一个映射和 addCandidate 方法。我们希望通过候选人保存候选人的选票,并通过addCandidate 创建候选人
pragma solidity ^0.4.2; //这句声明了我们的solidity版本
//声明一个合约 contract是关键字,Election是合约名字,合约名字和文件名要一致
contract Election {
/* 声明一个candicate结构 */
struct Candidate{
uint id;
string name;
uint voteCount;
}
/* 匹配到一个Candicate结构,通过一个mapping来做
mapping是key-value的,uint类型作为key,可以对应Candicate
结构里的id,而value则是一个Candicate对象
mapping操作会改变合约状态,将candicates放在区块链上存储*/
mapping (uint => Candidate) public candidates;
/* 我们需要手动记录mapping的大小,因为mapping不能被遍历
mapping的key对应的value如果不存在,则返回value类型的默认值
比如unit类型返回的是0,Candidate类型就返回空Candidate对象 */
uint public candidatesCount;
/* constractor 函数名和合约名一样的函数就是构造函数,与C++相似*/
/* 构造函数是public的,因为需要外部来调用 */
function Election() public{
addCandidate("candidate 1");
addCandidate("candidate 2");
}
/* 变量前加下划线表明这个变量是局部变量,不是状态变量 */
function addCandidate(string _name) private {
candidatesCount ++;
candidates[candidatesCount] = Candidate(candidatesCount, _name, 0);
}
}
修改代码后,在终端中输入松露迁移--reset重新部署合约。添加 --reset 是因为之前的合约已经记录在区块链上,无法修改,只能重新部署一组合约,重新部署的合约会生成一个新的合约地址
部署成功后,进入松露终端,输入以下代码创建对象
Election.deployed().then(function(instance) { app = instance})
然后输入下面的代码以创建候选人
app.candidates(1).then(function(c) { candidate = c;})
图片.png
上图中访问候选项的成员 ID 无法通过 .算子访问结构体中的成员,EVM不识别结构,结构只是Solidity中的句法糖,大家很容易写出来。我们需要通过下标访问候选人中的成员。打印的 id 显示为 BigNumber,这是 JavaScript 表示,c 对应于我们创建的值,即 id 为 1。
如果需要显示正常,可以使用toNumber()方法和toString()方法来获得正常结果
图片.png
调用以太坊接口
上面的程序已经可以记录候选人的票数,但选民如何投票呢?在解决这个问题之前,我们先来看看如何远程调用以太坊提供的函数
以太坊提供了一个 web3 .js库来访问以太坊内部的方法或命令。我们可以在松露终端中调用 web3
方法,在松露终端中键入 web3.eth,你会得到一堆输出
图片.png
这是 eth 在 web3 中提供的功能,让我们试试账户,它会列出 Ganache 网络中账户的地址。此命令与您自己构建的私有链中查看帐户的方式不同,因为 web3 被添加到前面
图片.png
合同测试
因为智能合约一旦部署,就无法更改,合约的bug将在区块链上永垂不朽。如果要修复 bug,就必须重新部署合约,这对用户体验影响很大,所以要毫不犹豫地测试合约。测试文件可以用 Solidity 或 JavaScript 编写。让我们先来看看 JavaScript 是如何编写测试的。
准备
我们需要使用 MOCHA 测试框架和 CHAI 断言库,我们可以使用以下命令安装它们
sudo npm install --global mocha
sudo npm install chai
编写测试脚本
为测试文件夹中的选举.js创建测试脚本
图片.png测试
脚本的代码如下,更多关于 MOCHA 测试框架和 CHAI 断言库的教程可以在线搜索
var Election = artifacts.require("./Election.sol");
// 声明合约 第一个参数是段描述,描述你的测试,第二个参数是个函数
//函数中的it 是一个测试用例,一个contract可以包含多个it
contract("Election", function(accounts){
it("init with two candidates", function(accounts){
return Election.deployed().then(function (instance){
return instance.candidatesCount();
}).then(function(count){
assert.equal(count, 2);
});
});
});
写好后,在终端中打开项目目录,进入松露测试,如果看到如下输出,测试通过
图片.png
写在背面第一个教程暂时
写到这里,希望对大家有所帮助,后续教程来了
引用