美文网首页Blockchain 区块链
以太坊ETH DAPP开发(1):实战开发基于truffle

以太坊ETH DAPP开发(1):实战开发基于truffle

作者: JKinJS | 来源:发表于2018-11-24 01:31 被阅读0次

    一、开发环境配置

    1、硬件配置


    image

    2、依赖工具版本

    ~/eth_workspace$geth version
    Geth
    Version: 1.8.18-stable
    Architecture: amd64
    Protocol Versions: [63 62]
    Network Id: 1
    Go Version: go1.11.2
    Operating System: darwin
    GOPATH=/Users/wujinquan/go
    GOROOT=/usr/local/Cellar/go/1.10.3/libexec
    ~/eth_workspace$npm -v
    6.4.1
    ~/eth_workspace$node -v
    v11.2.0
    ~/eth_workspace$truffle version
    Truffle v4.1.14 (core: 4.1.14)
    Solidity v0.4.24 (solc-js)
    ~/eth_workspace$
    

    二、智能合约开发部署过程

    1、项目源码地址

    2、建立一个独立的目录

    ~/gitmakenoise/conference$ls
    README.md
    ~/gitmakenoise/conference$mkdir truffle
    ~/gitmakenoise/conference$cd truffle/
    

    3、运行truffle init创建默认的合约项目

    • contracts/: 智能合约存放的目录,默认情况下已经帮你创建 Migrations.sol合约。
    • migrations/: 存放部署脚本
    • test/: 存放测试脚本
    • truffle.js: truffle的配置文件
    ~/gitmakenoise/conference/truffle$truffle init
    Downloading...
    Unpacking...
    Setting up...
    Unbox successful. Sweet!
    
    Commands:
    
      Compile:        truffle compile
      Migrate:        truffle migrate
      Test contracts: truffle test
    ~/gitmakenoise/conference/truffle$tree
    .
    ├── contracts
    │   └── Migrations.sol
    ├── migrations
    │   └── 1_initial_migration.js
    ├── test
    ├── truffle-config.js
    └── truffle.js
    
    3 directories, 4 files
    ~/gitmakenoise/conference/truffle$
    

    4、修改truffle.js文件,改成如下:

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

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

    5、修改/新建、编译智能合约

    (1)进入contracts目录,这里是存放合约代码的地方,这里新建 Conference.sol合约

    合约内容很简单,是一个针对会议的智能合约,通过它参会者可以买票,组织者可以设置参会人数上限,以及退款策略。

    (2)编译智能合约

    修改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);
    };
    
    

    6、编译合约项目

    truffle compile --compile-all
    Truffle仅默认编译自上次编译后被修改过的文件,来减少不必要的编译。如果你想编译全部文件,可以使用--compile-all选项。

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

    ~/gitmakenoise/conference/truffle$truffle compile --compile-all
    Compiling ./contracts/Conference.sol...
    Compiling ./contracts/Migrations.sol...
    
    Compilation warnings encountered:
    
    /Users/wujinquan/gitmakenoise/conference/truffle/contracts/Conference.sol:13:2: Warning: Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
        function Conference() {
     ^ (Relevant source part starts here and spans across multiple lines).
    ,/Users/wujinquan/gitmakenoise/conference/truffle/contracts/Conference.sol:21:4: Warning: "throw" is deprecated in favour of "revert()", "require()" and "assert()".
                throw; // throw ensures funds will be returned
                ^---^
    ,/Users/wujinquan/gitmakenoise/conference/truffle/contracts/Conference.sol:25:3: Warning: Invoking events without "emit" prefix is deprecated.
            Deposit(msg.sender, msg.value);
            ^----------------------------^
    ,/Users/wujinquan/gitmakenoise/conference/truffle/contracts/Conference.sol:38:5: Warning: Failure condition of 'send' ignored. Consider using 'transfer' instead.
                    recipient.send(amount);
                    ^--------------------^
    ,/Users/wujinquan/gitmakenoise/conference/truffle/contracts/Conference.sol:39:5: Warning: Invoking events without "emit" prefix is deprecated.
                    Refund(recipient, amount);
                    ^-----------------------^
    ,/Users/wujinquan/gitmakenoise/conference/truffle/contracts/Conference.sol:49:4: Warning: "suicide" has been deprecated in favour of "selfdestruct"
                suicide(organizer);
                ^----------------^
    ,/Users/wujinquan/gitmakenoise/conference/truffle/contracts/Conference.sol:13:2: Warning: No visibility specified. Defaulting to "public".
        function Conference() {
     ^ (Relevant source part starts here and spans across multiple lines).
    ,/Users/wujinquan/gitmakenoise/conference/truffle/contracts/Conference.sol:47:2: Warning: No visibility specified. Defaulting to "public".
        function destroy() {
     ^ (Relevant source part starts here and spans across multiple lines).
    
    Writing artifacts to ./build/contracts
    
    ~/gitmakenoise/conference/truffle$
    

    7、运行testrpc

    开启一个终端,输入testrpc运行测试节点。testrpc是一个完整的在内存中的区块链测试环境,启动 testrpc 经后,会默认创建10个帐号,Available Accounts是帐号列表,Private Keys是相对应的帐号密钥。

    ~/eth_workspace$testrpc
    EthereumJS TestRPC v6.0.3 (ganache-core: 2.0.2)
    
    Available Accounts
    ==================
    (0) 0x91d16ebaf685844a45f78f539b9f391445509937
    (1) 0x1602a3cc58b3884bceb22c3cdfc57d73ecdc705d
    (2) 0x4b675ac76bd27870c3b301098d4445f7bd1c3095
    (3) 0xe2790185a701a21d2d36fccbe5761c4ac637e743
    (4) 0x3071e412a0a2b158bb3c48de60eede057c47dfbf
    (5) 0x9398d2b8e6265bf0a4e583145caec839ef0257fb
    (6) 0xa47f8c5d8acc4cd2c3c4e5e4a8a0b16f1eb35d7a
    (7) 0xff719fd90a008cbc7433bea42cc9944667bc4624
    (8) 0x8e0407dec67002c5fb99602dbe24dc2f544b7501
    (9) 0xbeb3a9b7b0a0ff13e4bdc1c6f0e075325e4214b4
    
    Private Keys
    ==================
    (0) 1a54e7b8c8ceaa63ff2c02890dd12e654eea0829c5ef86fd8ec2a94b80d85a9a
    (1) 9434af16caf5be665bb39aab976637341bba69b21994fab3094c391efa4afee1
    (2) 0d963e5fa979650fa4cbfe49edcb0a358f356549ff040adeaf60329b26b2077c
    (3) 206f6dbacf5e02fd379dcc5692cd9f3ee3bf31c21846c7cc7017874a1113831d
    (4) 24cd5f53246c0012e2d6e0c3af8213bea5ab754ce5a11057adbcd113633c5384
    (5) a01d3901222ae73a9a67a6a2aeac32214748237e47b001feb1f0236671e41a80
    (6) 12a864c793fd71fbfee6d5e18d7c5f0c5cedaffd14eb3b513db9cf405f682c12
    (7) fa4a1aa1869f618a987927433366b2511f988b4a48d315c90bb6f39066408c54
    (8) a6694dd3dad7b4399a8ab50649667ef7435a2c0ef7e88c3d8452194b062f9929
    (9) d9c8ca783379dea8b272062dce2919f163656749c98c571fe5502789281bd2f7
    
    HD Wallet
    ==================
    Mnemonic:      assume atom always scene enroll group cave chest veteran security tail zoo
    Base HD Path:  m/44'/60'/0'/0/{account_index}
    
    Listening on localhost:8545
    

    8、truffle调用以太坊的接口

    (1) 进入truffle 终端

    ~/gitmakenoise/conference/truffle$truffle console
    truffle(development)>
    

    (2) 调用以太坊接口

    以太坊提供了一个web3.js库来访问以太坊内部的方法或者命令。
    我们可以在truffle终端中调用下web3的方法,在truffle终端中输入web3.eth,你会得到一堆输出

    truffle(development)> web3.eth
    Eth {
      _requestManager:
       RequestManager {
         provider:
          HttpProvider {
            host: 'http://localhost:8545',
            timeout: 0,
            user: undefined,
            password: undefined,
            headers: undefined,
            send: [Function],
            sendAsync: [Function],
            _alreadyWrapped: true },
         polls: {},
         timeout: null },
      getBalance:
       { [Function: send] request: [Function: bound ], call: 'eth_getBalance' },
      getStorageAt:
       { [Function: send] request: [Function: bound ], call: 'eth_getStorageAt' },
      getCode:
       { [Function: send] request: [Function: bound ], call: 'eth_getCode' },
      getBlock:
       { [Function: send] request: [Function: bound ], call: [Function: blockCall] },
      getUncle:
       { [Function: send] request: [Function: bound ], call: [Function: uncleCall] },
      getCompilers:
       { [Function: send] request: [Function: bound ], call: 'eth_getCompilers' },
      getBlockTransactionCount:
       { [Function: send]
         request: [Function: bound ],
         call: [Function: getBlockTransactionCountCall] },
      getBlockUncleCount:
       { [Function: send]
         request: [Function: bound ],
         call: [Function: uncleCountCall] },
      getTransaction:
       { [Function: send]
         request: [Function: bound ],
         call: 'eth_getTransactionByHash' },
      getTransactionFromBlock:
       { [Function: send]
         request: [Function: bound ],
         call: [Function: transactionFromBlockCall] },
      getTransactionReceipt:
       { [Function: send]
         request: [Function: bound ],
         call: 'eth_getTransactionReceipt' },
      getTransactionCount:
       { [Function: send] request: [Function: bound ], call: 'eth_getTransactionCount' },
      call:
       { [Function: send] request: [Function: bound ], call: 'eth_call' },
      estimateGas:
       { [Function: send] request: [Function: bound ], call: 'eth_estimateGas' },
      sendRawTransaction:
       { [Function: send] request: [Function: bound ], call: 'eth_sendRawTransaction' },
      signTransaction:
       { [Function: send] request: [Function: bound ], call: 'eth_signTransaction' },
      sendTransaction:
       { [Function: send] request: [Function: bound ], call: 'eth_sendTransaction' },
      sign:
       { [Function: send] request: [Function: bound ], call: 'eth_sign' },
      compile:
       { solidity:
          { [Function: send] request: [Function: bound ], call: 'eth_compileSolidity' },
         lll:
          { [Function: send] request: [Function: bound ], call: 'eth_compileLLL' },
         serpent:
          { [Function: send] request: [Function: bound ], call: 'eth_compileSerpent' } },
      submitWork:
       { [Function: send] request: [Function: bound ], call: 'eth_submitWork' },
      getWork:
       { [Function: send] request: [Function: bound ], call: 'eth_getWork' },
      coinbase: [Getter],
      getCoinbase: { [Function: get] request: [Function: bound ] },
      mining: [Getter],
      getMining: { [Function: get] request: [Function: bound ] },
      hashrate: [Getter],
      getHashrate: { [Function: get] request: [Function: bound ] },
      syncing: [Getter],
      getSyncing: { [Function: get] request: [Function: bound ] },
      gasPrice: [Getter],
      getGasPrice: { [Function: get] request: [Function: bound ] },
      accounts: [Getter],
      getAccounts: { [Function: get] request: [Function: bound ] },
      blockNumber: [Getter],
      getBlockNumber: { [Function: get] request: [Function: bound ] },
      protocolVersion: [Getter],
      getProtocolVersion: { [Function: get] request: [Function: bound ] },
      iban:
      ....
    

    9、部署合约到testrpc

    truffle migrate --reset
    这个命令会执行所有migrations目录下的js文件。如果之前执行过truffle migrate命令,再次执行,只会部署新的js文件,如果没有新的js文件,不会起任何作用。如果使用--reset参数,则会重新的执行所有脚本的部署。

    ~/gitmakenoise/conference/truffle$truffle migrate --reset
    Using network 'development'.
    
    Running migration: 1_initial_migration.js
      Deploying Conference...
      # 部署成功的txid
      ... 0xe1a21217d843a13df1613f6b3fe22200626aef0bc4281a8fc1cc3b2f3e7dd289
      # 合约地址
      Conference: 0x2233e07a9db44e0ca74e057b0589ef928e5113f8
    Saving artifacts...
    ~/gitmakenoise/conference/truffle$
    

    例如查询账户

    truffle(development)> web3.eth.accounts
    [ '0x91d16ebaf685844a45f78f539b9f391445509937',
      '0x1602a3cc58b3884bceb22c3cdfc57d73ecdc705d',
      '0x4b675ac76bd27870c3b301098d4445f7bd1c3095',
      '0xe2790185a701a21d2d36fccbe5761c4ac637e743',
      '0x3071e412a0a2b158bb3c48de60eede057c47dfbf',
      '0x9398d2b8e6265bf0a4e583145caec839ef0257fb',
      '0xa47f8c5d8acc4cd2c3c4e5e4a8a0b16f1eb35d7a',
      '0xff719fd90a008cbc7433bea42cc9944667bc4624',
      '0x8e0407dec67002c5fb99602dbe24dc2f544b7501',
      '0xbeb3a9b7b0a0ff13e4bdc1c6f0e075325e4214b4' ]
    truffle(development)>
    

    10、在testrpc窗口

    Listening on localhost:8545
    net_version
    eth_accounts
    eth_accounts
    net_version
    net_version
    eth_sendTransaction
     # Transaction为第8中的txid
      Transaction: 0xe1a21217d843a13df1613f6b3fe22200626aef0bc4281a8fc1cc3b2f3e7dd289
      # Contract为为第8中的合约地址
      Contract created: 0x2233e07a9db44e0ca74e057b0589ef928e5113f8
      Gas usage: 528285
      Block Number: 1
      Block Time: Fri Nov 23 2018 20:30:10 GMT+0800 (中国标准时间)
    

    11、在truffle 终端中查看合约相关信息

    通过truffle框架教程查看相关命令,确认合约部署成功

    #将合约重命名为app并生成命令用于调试
    truffle(development)> Conference.deployed().then(function(instance) { app = instance})
    undefined  #原因暂时忽略
    truffle(development)> app.address #查看合约地址,可见与第10点中合约地址一致
    '0x2233e07a9db44e0ca74e057b0589ef928e5113f8'
    truffle(development)> app.quota() #查看合约中的变量,可见与contracts/Conference.sol中一致
    BigNumber { s: 1, e: 2, c: [ 100 ] }
    truffle(development)> app.organizer() #查看合约的部署者,可见为第9点中testrpc中的第一个账户
    '0x91d16ebaf685844a45f78f539b9f391445509937'
    

    12、在test目录新增一个conference.js测试文件

    执行 truffle test

    ~/gitmakenoise/conference/truffle$truffle test
    Using network 'development'.
    
    start testing
    
    
      Contract: Conference
        ✓ Initial conference settings should match (132ms)
        ✓ Should update quota (118ms)
        ✓ Should let you buy a ticket (555ms)
        ✓ Should issue a refund by owner only (687ms)
    
    
      4 passing (2s)
    
    ~/gitmakenoise/conference/truffle$truffle -h
    

    可在testrpc窗口见到相应的打印信息

    三、编写web应用

    1、 执行npm init,然后一路回车

    ~/gitmakenoise/conference/truffle$npm init
    This utility will walk you through creating a package.json file.
    It only covers the most common items, and tries to guess sensible defaults.
    
    See `npm help json` for definitive documentation on these fields
    and exactly what they do.
    
    Use `npm install <pkg>` afterwards to install a package and
    save it as a dependency in the package.json file.
    
    Press ^C at any time to quit.
    package name: (truffle)
    version: (1.0.0)
    description:
    entry point: (truffle.js)
    test command:
    git repository:
    keywords:
    author:
    license: (ISC)
    About to write to /Users/wujinquan/gitmakenoise/conference/truffle/package.json:
    
    {
      "name": "truffle",
      "version": "1.0.0",
      "description": "",
      "main": "truffle.js",
      "directories": {
        "test": "test"
      },
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "author": "",
      "license": "ISC"
    }
    
    
    Is this OK? (yes)
    ~/gitmakenoise/conference/truffle$
    

    生成一个名为package.json的文件,定义了这个项目所需要的各种模块,以及项目的配置信息(比如名称、版本、许可证等元数据)。npm 命令根据这个配置文件,自动下载所需的模块,也就是配置项目所需的运行和开发环境。
    编辑这个文件,在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"
    }
    

    2、在truffle目录下新建app目录

    此目录主要存放web前段html、js 、css文件,不多解释

    3、使用webpack打包部署web

    webpack环境问题,解决中,...未完待续

    四、总结

    1、Truffle框架开发优势

    Truffle是一个世界级的开发环境,测试框架,以太坊的资源管理通道,致力于让以太坊上的开发变得简单,Truffle有以下优点:

    • 内置的智能合约编译,链接,部署和二进制文件的管理。
    • 快速开发下的自动合约测试。
    • 脚本化的,可扩展的部署与发布框架。
    • 部署到不管多少的公网或私网的网络环境管理功能
    • 使用EthPM&NPM提供的包管理,使用ERC190标准。
    • 与合约直接通信的直接交互控制台(写完合约就可以命令行里验证了)。
    • 可配的构建流程,支持紧密集成。
    • 在Truffle环境里支持执行外部的脚本。

    相关文章

      网友评论

        本文标题:以太坊ETH DAPP开发(1):实战开发基于truffle

        本文链接:https://www.haomeiwen.com/subject/ynceqqtx.html