以太坊开发:如何在Windows下开发一个简易Dapp
linux-dash
A beautiful web dashboard for Linux
项目地址:https://gitcode.com/gh_mirrors/li/linux-dash
免费下载资源
·
这是我粗浅地翻译了国外的一篇以太坊开发的文章,加入了一些个人的理解。原文是在linux下开发的,但经过我尝试,Windows下也能实现。
原文地址:https://medium.com/@mvmurthy/full-stack-hello-world-voting-ethereum-dapp-tutorial-part-1-40d2d0d807c2 需要翻墙
一、环境配置
安装nodejs,npm,git,web3,solc
nodejs:官网下载最新版本
https://nodejs.org/en/download/current/
npm:在Windows下安装nodejs会自带npm
git:官网下载即可
https://git-scm.com/downloads
web3:直接采用npm install web3在Windows下会报错,需要配置大量环境,不建议使用。如果确实需要,可以参考下面这篇文章。
建议用npm install
web3@0.20.0
,表示安装0.20.0的版本。0.20.0是我写这篇文章时候的最新稳定版本。或者在
https://www.npmjs.com/package/web3
查询当前的稳定版本。将0.20.0替换即可。
solc:直接npm install solc即可
二、用Solidity编写智能合约并使用solc编译
我们这里写一个简单的投票智能合约,可以通过Dapp对给定的候选人投票并计算每个候选人获得的票数。这个合约有四个方法,分别是构造方法,查询票数,投票,和判断是否是候选人,逻辑非常简单,甚至不需要懂得Solidity语法都可以看得懂。
pragma solidity ^0.4.11;
// We have to specify what version of compiler this code will compile with
contract Voting {
/* mapping field below is equivalent to an associative array or hash.
The key of the mapping is candidate name stored as type bytes32 and value is
an unsigned integer to store the vote count
*/
mapping (bytes32 => uint8) public votesReceived;
/* Solidity doesn't let you pass in an array of strings in the constructor (yet).
We will use an array of bytes32 instead to store the list of candidates
*/
bytes32[] public candidateList;
/* This is the constructor which will be called once when you
deploy the contract to the blockchain. When we deploy the contract,
we will pass an array of candidates who will be contesting in the election
*/
function Voting(bytes32[] candidateNames) {
candidateList = candidateNames;
}
// This function returns the total votes a candidate has received so far
function totalVotesFor(bytes32 candidate) returns (uint8) {
if (validCandidate(candidate) == false) throw;
return votesReceived[candidate];
}
// This function increments the vote count for the specified candidate. This
// is equivalent to casting a vote
function voteForCandidate(bytes32 candidate) {
if (validCandidate(candidate) == false) throw;
votesReceived[candidate] += 1;
}
function validCandidate(bytes32 candidate) returns (bool) {
for(uint i = 0; i < candidateList.length; i++) {
if (candidateList[i] == candidate) {
return true;
}
}
return false;
}
}
进入node,然后输入以下语句:
> Web3 = require('web3')
> web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
这样我们就初始化了一个web3对象,并可以利用这个web3对象来和区块链进行交互。比如,可以通过这个web3对象来查询它所连接到的区块链的账户信息:
> web3.eth.accounts
那么我们如何编译呢?很简单,使用我们之前安装的solc:
> solc = require('solc')
>code = fs.readFileSync('Voting.sol').toString()
>compiledCode = solc.compile(code)
这几条命令执行完了之后我们就把编译好了的代码存到了compiledCode当中。
三、部署智能合约
testrpc安装语句:
npm install ethereumjs-testrpc web3
在部署之前首先我们要先安装并打开testRPC,可以理解为一个测试链,会自动生成十个账户,并且每个账户中都会初始有100个以太币(当然是假的以太币)。
另外开启一个控制台,进入node,输入以下命令:
//abiDefinition中保存的是该智能合约的界面信息,JSON.parse() 方法解析一个JSON字符串,构造由字符串描述的JavaScript值或对象。也就是说,把JSON字符串解析为JavaScript值。
> abiDefinition = JSON.parse(compiledCode.contracts[':Voting'].interface)
//这句代码的作用相当于初始化一个只有外壳和界面的投票合约对象
> VotingContract = web3.eth.contract(abiDefinition)
//将这些字节码存到byteCode这个变量中去
> byteCode = compiledCode.contracts[':Voting'].bytecode
//VotingContract.new就将这个合约部署到了以太链上去了,这里VotingContract本身就有abiDefinition,这里把byteCode作为data传入,因此就把其界面和比特码同时利用上了。
> deployedContract = VotingContract.new(['Rama','Nick','Jose'],{data: byteCode, from: web3.eth.accounts[0], gas: 4700000})
//到上一句,实际上智能合约就部署好了,这里我们使用这个命令来获取这个合约的地址
> deployedContract.address
这里其实只是相当于作了一个名称的简化
> contractInstance = VotingContract.at(deployedContract.address)
四、在控制台中与智能合约进行交互
可以参考下面的代码,理解起来比较简单,不作过多解释。
> contractInstance.totalVotesFor.call('Rama')
{ [String: '0'] s: 1, e: 0, c: [ 0 ] }
> contractInstance.voteForCandidate('Rama', {from: web3.eth.accounts[0]})
'0xdedc7ae544c3dde74ab5a0b07422c5a51b5240603d31074f5b75c0ebc786bf53'
> contractInstance.voteForCandidate('Rama', {from: web3.eth.accounts[0]})
'0x02c054d238038d68b65d55770fabfca592a5cf6590229ab91bbe7cd72da46de9'
> contractInstance.voteForCandidate('Rama', {from: web3.eth.accounts[0]})
'0x3da069a09577514f2baaa11bc3015a16edf26aad28dffbcd126bde2e71f2b76f'
> contractInstance.totalVotesFor.call('Rama').toLocaleString()
'3'
五、利用网页与智能合约进行交互
在上一步的交互中我们是在nodejs中进行投票和查询的,现在我们就要把这些命令写到js中,并写一个简单的html文件,通过网页来与智能合约进行交互。html和js文件见下。把这两个文件放到与Voting.sol同级别的目录下。
index.html
<!DOCTYPE html>
<html>
<head>
<title>Hello World DApp</title>
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'>
<link href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css' rel='stylesheet' type='text/css'>
</head>
<body class="container">
<h1>SSC VOTING APPLICATION</h1>
<div class="table-responsive">
<table class="table table-bordered">
<thead>
<tr>
<th>Candidate</th>
<th>Votes</th>
</tr>
</thead>
<tbody>
<tr>
<td>Rama</td>
<td id="candidate-1"></td>
</tr>
<tr>
<td>Nick</td>
<td id="candidate-2"></td>
</tr>
<tr>
<td>Jose</td>
<td id="candidate-3"></td>
</tr>
</tbody>
</table>
</div>
<input type="text" id="candidate" />
<a href="#" οnclick="voteForCandidate()" class="btn btn-primary">Vote</a>
</body>
<script src="https://cdn.rawgit.com/ethereum/web3.js/develop/dist/web3.js"></script>
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js"></script>
<script src="./index.js"></script>
</html>
web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
abi = JSON.parse('[{"constant":false,"inputs":[{"name":"candidate","type":"bytes32"}],"name":"totalVotesFor","outputs":[{"name":"","type":"uint8"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"candidate","type":"bytes32"}],"name":"validCandidate","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"votesReceived","outputs":[{"name":"","type":"uint8"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"x","type":"bytes32"}],"name":"bytes32ToString","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"candidateList","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"candidate","type":"bytes32"}],"name":"voteForCandidate","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"contractOwner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"inputs":[{"name":"candidateNames","type":"bytes32[]"}],"payable":false,"type":"constructor"}]')
VotingContract = web3.eth.contract(abi);
//在你的控制台中, 执行contractInstance.address,并将获得的地址替换下面这个0x413a...地址
contractInstance = VotingContract.at('0x4131a0f92d36932d3ec3b7a0581546f2e662ad0b');
candidates = {"Rama": "candidate-1", "Nick": "candidate-2", "Jose": "candidate-3"}
function voteForCandidate(candidate) {
candidateName = $("#candidate").val();
contractInstance.voteForCandidate(candidateName, {from: web3.eth.accounts[0]}, function() {
let div_id = candidates[candidateName];
$("#" + div_id).html(contractInstance.totalVotesFor.call(candidateName).toString());
});
}
$(document).ready(function() {
candidateNames = Object.keys(candidates);
for (var i = 0; i < candidateNames.length; i++) {
let name = candidateNames[i];
let val = contractInstance.totalVotesFor.call(name).toString()
$("#" + candidates[name]).html(val);
}
});
在index.js中把合约的地址替换之后打开index.html即可在网页上进行我们的投票操作,同时可以通过MetaMask看到我们的交易和以太币的变动情况。
GitHub 加速计划 / li / linux-dash
6
1
下载
A beautiful web dashboard for Linux
最近提交(Master分支:3 个月前 )
186a802e
added ecosystem file for PM2 4 年前
5def40a3
Add host customization support for the NodeJS version 4 年前
更多推荐
已为社区贡献1条内容
所有评论(0)