主页 > imtoken钱包苹果版价值 > 以太坊开发去中心化投票 DApp 和智能合约

以太坊开发去中心化投票 DApp 和智能合约

imtoken钱包苹果版价值 2023-04-09 05:58:36

环境准备

Ubuntu 16.04,64 位

还需要安装以太坊相关环境:

可以参考我之前的一篇文章:

另外本文也会用到webpack,网上有很多安装教程。 如果您对这部分内容不熟悉,请自行查阅和研究。 需要注意的是,本文我使用的webpack版本是3.x,写这篇文章的时候webpack4.x已经发布了。 4.x的变化比较大。 建议您使用 3.x 版本运行本文中的代码示例。

编写智能合约

首先在用户目录下创建会议目录,进入该目录执行truffle init,该命令会创建如下子目录和文件:

修改truffle.js文件如下:

module.exports = {
  networks: {
        development: {
            host: "localhost",
            port: 8545,
            network_id: "*" // 匹配任何network id
         }
    }
};

这里是我们设置后面部署智能合约的位置,否则会报网络错误。

打开终端并输入 testrpc 以运行测试节点。 testrpc是内存中完整的区块链测试环境。 启动testrpc后以太坊web开发,默认会创建10个账号。 Available Accounts 为账户列表,Private Keys 为对应的账户密钥。

进入contracts目录,这里是存放合约代码的地方。 我们可以使用sublime等工具编写测试合约代码。 我这里只贴出部分代码,完整源码地址会在文末给出。

pragma solidity ^0.4.19;
contract Conference {  // can be killed, so the owner gets sent the money in the end
    address public organizer;
    mapping (address => uint) public registrantsPaid;
    uint public numRegistrants;
    uint public quota;
    event Deposit(address _from, uint _amount); // so you can log the event
    event Refund(address _to, uint _amount); // so you can log the event
    function Conference() {
        organizer = msg.sender;     
        quota = 100;
        numRegistrants = 0;
    }
...

契约的内容很简单。 它是会议的智能合约,与会者可以通过它购买门票,主办方可以设置与会人数上限和退款政策。

编译和部署智能合约

修改migrations下的1_initial_migration.js文件如下:

//var Migrations = artifacts.require("./Migrations.sol");
var Conference = artifacts.require("./Conference.sol");
module.exports = function(deployer) {
  //deployer.deploy(Migrations);
  deployer.deploy(Conference);
};

编译,

$ sudo truffle compile --compile-all

注意看是否有错误。

默认情况下,Truffle 只编译自上次编译以来修改过的文件,以减少不必要的编译。 如果要编译所有文件,可以使用 --compile-all 选项。

然后会多出一个build目录,这个目录下的文件不要做任何修改。

部署,

$ sudo truffle migrate --reset

此命令将执行 migrations 目录中的所有 js 文件。 如果之前执行过truffle migrate命令,再次执行的话,只会部署新的js文件。 如果没有新的js文件,则不会有任何效果。 如果使用--reset参数,所有脚本的部署都会重新执行。

测试下,在test目录下添加一个conference.js测试文件,

var Conference = artifacts.require("./Conference.sol");
contract('Conference', function(accounts) {
  console.log("start testing");
    //console.log(accounts);
    var owner_account = accounts[0];
  var sender_account = accounts[1];
  it("Initial conference settings should match", function(done) {
    
    Conference.new({from: owner_account}).then(
        function(conference) {
            conference.quota.call().then(
                function(quota) { 
                    assert.equal(quota, 100, "Quota doesn't match!"); 
            }).then(
                function() { 
                    return conference.numRegistrants.call(); 
            }).then(
                function(num) { 
                    assert.equal(num, 0, "Registrants doesn't match!");
                    return conference.organizer.call();
            }).then(
                function(organizer) { 
                    assert.equal(organizer, owner_account, "Owner doesn't match!");
                    done();
            }).catch(done);
    }).catch(done);
  });
  
  ...
  

这里只贴出部分代码,四个测试用例,运行truffle test查看测试结果。

$ truffle test
Using network 'development'.
start testing
  Contract: Conference
    ✓ Initial conference settings should match (191ms)
    ✓ Should update quota (174ms)
    ✓ Should let you buy a ticket (717ms)
    ✓ Should issue a refund by owner only (714ms)
  4 passing (2s)

编写网络应用程序

在会议目录下执行npm init,然后一路回车,会生成一个名为package.json的文件,编辑这个文件,在scripts部分添加两条命令,最终结果如下:

{
  "name": "conference",
  "version": "1.0.0",
  "description": "",
  "main": "truffle-config.js",
  "directories": {
    "test": "test"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack",
    "server": "webpack-dev-server --open"
  },
  "author": "",
  "license": "ISC"
}

package.json文件定义了本项目所需的各个模块,以及项目配置信息(如名称、版本、许可证等元数据)。 npm命令会根据这个配置文件自动下载所需的模块,即配置项目所需的运行和开发环境。

然后在conference目录下新建app目录,并新建index.html文件,如下:




  Conference DApp2
  
  
  


  

Conference DApp

Contract deployed at:
Organizer:
Quota:
Registrants: 0

然后在app目录下创建javascripts目录和styleheets目录,分别存放js脚本文件和css样式文件。 真正与合约交互的是脚本文件。

脚本文件名为app.js,部分代码如下:

import "../stylesheets/app.css";
import {  default as Web3 } from 'web3';
import {  default as contract } from 'truffle-contract';
import conference_artifacts from '../../build/contracts/Conference.json'
var accounts, sim;
var Conference = contract(conference_artifacts);
window.addEventListener('load', function() {
    //alert("aaaaa");
    // Checking if Web3 has been injected by the browser (Mist/MetaMask)
    if (typeof web3 !== 'undefined') {
        console.warn("Using web3 detected from external source. If you find that your accounts don't appear or you have 0 MetaCoin, ensure you've configured that source properly. If using MetaMask, see the following link. Feel free to delete this warning. :) http://truffleframework.com/tutorials/truffle-and-metamask")
        // Use Mist/MetaMask's provider
        window.web3 = new Web3(web3.currentProvider);
    } else {
        console.warn("No web3 detected. Falling back to http://localhost:8545. You should remove this fallback when you deploy live, as it's inherently insecure. Consider switching to Metamask for development. More info here: http://truffleframework.com/tutorials/truffle-and-metamask");
        // fallback - use your fallback strategy (local node / hosted node + in-dapp id mgmt / fail)
        window.web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
    }
    Conference.setProvider(web3.currentProvider);
    App.start();
    $("#changeQuota").click(function() {
        var newquota = $("#confQuota").val();
        App.changeQuota(newquota);
    });
    // Wire up the UI elements
});
...

这段代码我不打算过多解释,主要就是用JS加上wweb3 API调用合约的功能。

至此,web部分基本准备好了,我们只需要使用webpack打包部署即可。 Webpack 打包还需要一个名为 webpack.config.js 的配置文件。 这个文件告诉webpack打包的规则以太坊web开发,涉及到webpack的使用。 我不会在这里解释太多。

打包和部署 Web 应用程序

包部署需要安装webpack及相关组件。 安装方式有两种:全局安装和本地安装。 所谓部分安装,就是将组件全部安装在项目目录下(conference/node_modules)。 我这里使用的是部分安装。 根据我们项目的实际情况,需要安装以下组件,

npm install --save-dev webpack@3.0.0
npm install babel-loader --save-dev
npm install babel-core --save-dev
npm install html-loader --save-dev
npm install --save-dev webpack-dev-server@2.11.0
npm install html-webpack-plugin --save-dev
npm install truffle-contract --save-dev
npm install --save-dev style-loader css-loader

环境已安装并准备打包。

$ sudo npm run start
> conference@1.0.0 start /home/pony/ethereum/conference
> webpack
Hash: ec8b764f75c05b477d9d
Version: webpack 3.0.0
Time: 2686ms
       Asset       Size  Chunks                    Chunk Names
   bundle.js    3.36 MB       0  [emitted]  [big]  main
./index.html  740 bytes          [emitted]         
  [10] (webpack)/buildin/global.js 509 bytes {0} [built]
  [16] (webpack)/buildin/module.js 517 bytes {0} [built]
  [47] ./app/javascripts/app.js 3.85 kB {0} [built]
  [48] ./app/stylesheets/app.css 1.08 kB {0} [built]
  [49] ./node_modules/css-loader!./app/stylesheets/app.css 413 bytes {0} [built]
 [175] ./build/contracts/Conference.json 71.1 kB {0} [built]
    + 170 hidden modules
Child html-webpack-plugin for "index.html":
       [0] ./node_modules/html-webpack-plugin/lib/loader.js!./app/index.html 706 bytes {0} [built]

如果没有报错,进入build目录,可以看到bundle.js和index.html两个文件,这是最终打包好的网页文件。

然后部署,

$ sudo npm run server
> conference@1.0.0 server /home/pony/ethereum/conference
> webpack-dev-server --open
Project is running at http://localhost:8080/
webpack output is served from /
Content not from webpack is served from ./build
404s will fallback to /index.html
Hash: ecae3662137376f80de0
Version: webpack 3.0.0
...

这相当于运行一个小型的 nodejs 服务器。 我们可以在浏览器中输入:8080/看看效果:

基于以太坊开发还是基于eos_以太坊web开发_sitebitecoin.com 以太坊的代币开发

剪贴板.png

可以看到合约的发布地址和会议组织者的地址(msg.sender)已经显示成功,可以通过点击更改按钮更改quota的值。

我已经将这篇文章的代码上传到github。

参考