以太坊学习笔记(六)——Truffle开发框架

357 阅读7分钟

前一篇文章讲了以太坊Dapp开发的一些内容,在尝试Truffle的时候总是遇到各种各样的问题,通过多次尝试能够正常的运行一个demo了,问题主要是出在我的环境上,另外,网上的大部分文章都有些过时了,Truffle框架现在都已经到V4+了有些内容做出了比较大的调整,智能合约的语法也有了一些变化。

首先,我纠正一下testrpc的配置

sudo npm install -g ethereumjs-testrpc
//输出信息
+ ethereumjs-testrpc@6.0.3
added 404 packages in 37.952s

启动testrpc

testrpc
EthereumJS TestRPC v6.0.3 (ganache-core: 2.0.2)

Available Accounts
==================
(0) 0xd4c36cbc13aa269faef90cc33c21a16640b800db
(1) 0xdb2d100405b0377ab2ae1dd5ec0a42321703dca2
(2) 0x5ed80126ca200092418c14bca9c4b0a4a904f09b
(3) 0xaf7725ea608587ee44b40ad64c5bec38488d26c6
(4) 0x150856925c1101a21b4c9d57f2f34756888f99e5
(5) 0x57a70d1e1bd6de833c2e2f27728a36f108959b99
(6) 0x3c9c6fedb1e392b9430bad68b1abc97c80920e9f
(7) 0xbff334262de85a163c93dfe9485d741dda9c9b29
(8) 0x4bce3e355105bbfc228bfd0a2e0a55d3871fb984
(9) 0x598aacba1f1a78a241daab9f0126b6bf39063a40

Private Keys
==================
(0) c48b4eb2d42a085e163f6572958f63682e8f2b06fcafa838b205dca2640bc659
(1) 7fd8408c0b55d9550a310fb17a77ad82e1d55d856b574b7ac34a7a17c4c3847c
(2) 7340d2122c72b8e420acb703842c06bdf2170ac5e2adcd1f7bf4038a369edf1b
(3) b1916c4681d6ee9792f1fee10637aeecb357176ee00a434a18c5e5d3cfd11f83
(4) 7cda59f01f3aab76d2271c2497e6a4dd15a28faa67c143ec7d40ce25dfcdade5
(5) 26dedc489c16dc34292af820f11b430533d5a8fd8b30444cc8f51f5c1cbc511e
(6) 090b31a5d810327007c801601f830287a9d6031e805770d3e0516d232505ce80
(7) d110c83aed65532dc0a02e628bc4ebfa33e11f5b6742fcb865d1a7027298d0de
(8) e1c0874f40b94e165011671de60158770c1dd34679f830c6df2480501ed63d3d
(9) e87d1739ca3f543fc17cfe4c9007c61e5a1f7debfc3b670ca05da71c602c1da4

HD Wallet
==================
Mnemonic:      math organ body menu burger say leave simple sketch decorate throw city
Base HD Path:  m/44'/60'/0'/0/{account_index}

Listening on localhost:8545

备注:testrpc这种方式已经不推荐了,官方推荐使用Ganache

Truffle
1.创建项目文件夹

mkdir /你的路径/truffleTest
cd /你的路径/truffleTest

2.初始化项目

$ truffle init
Downloading...
Unpacking...
Setting up...
Unbox successful. Sweet!

Commands:

  Compile:        truffle compile
  Migrate:        truffle migrate
  Test contracts: truffle test

此时的项目结构如下:

$ tree
.
├── contracts
│   └── Migrations.sol
├── migrations
│   └── 1_initial_migration.js
├── test
├── truffle-config.js
└── truffle.js

3 directories, 4 files

3.编写智能合约,初始化的项目/contracts文件夹里只有Migrations.sol这个合约,不要修改里面的内容,我们写两个简单的合约用来测试。
第一个合约Test.sol

pragma solidity ^0.4.0;

contract Test{
    function f() public pure returns (string){
        return "method f()";
    }
    function g() public pure returns (string){
        return "method g()";
    }
}

第二个合约Greeter.sol

pragma solidity ^0.4.0;

contract Greeter
{
    address creator;
    string greeting;

    constructor() public{
        creator = msg.sender;
    }

    function greet() public constant returns (string){
        return greeting;
    }

    function setGreeting(string _newgreeting) public {
        greeting = _newgreeting;
    }

    function kill() public {
        if (msg.sender == creator)
            selfdestruct(creator);
        // kills this contract and sends remaining funds back to creator
    }

}

备注:因为没有比较复杂的内容,就没太关注solidity语法版本。另外,上面的合约语法可能在以后也会有所变化,可能需要适当修改。

4.初始化的项目/migrations/里只有一个1_initial_migration.js文件,需要手动创建一个2_deploy_contracts.js

var Greeter = artifacts.require('./Greeter.sol')
var Test = artifacts.require('./Test.sol')

module.exports = function (deployer) {
    deployer.deploy(Greeter);
    deployer.deploy(Test);
}

注意:移植脚本文件名以数字开头,一个描述性的后缀结尾。数字前缀是必须的,用于记录移植是否成功,后缀仅仅是为了提高可读性,以方便理解。

补充:如果有库文件需要按照如下的方式连接库和合约

var ConvertLib = artifacts.require("ConvertLib.sol");
var MetaCoin = artifacts.require("MetaCoin.sol");

module.exports = function(deployer) {
 deployer.deploy(ConvertLib);
 deployer.link(ConvertLib, MetaCoin);
 deployer.deploy(MetaCoin);
};

5.修改配置文件truffle.js文件中声明了项目的一些配置信息

module.exports = {
    // See <http://truffleframework.com/docs/advanced/configuration>
    // to customize your Truffle configuration!
    networks: {
        development: {
            host: '127.0.0.1',
            port: 8545,
            network_id: '*' //匹配任何id
        }
    }
};

提示:这里我只配置了需要用的网络环境,可以配置多个,更多详细的配置请阅读Truffle Doc

6.启动一个测试节点,测试节点启动方式很多,这里使用testrpc,参见文首。因为之前环境配置有问题,后面的操作就遇到了以下的错误信息

Error: No network specified. Cannot determine current network.

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

$ truffle compile --compile-all
Compiling ./contracts/Greeter.sol...
Compiling ./contracts/Migrations.sol...
Compiling ./contracts/Test.sol...
Writing artifacts to ./build/contracts

编译完成之后项目/build/下生产了几个json文件,这些就是合约的元数据

8.部署合约,在使用truffle migrate部署合约的时候,可以通过--network development来指定部署的网络节点,development就是在truffle.js中配置的参数

$ truffle migrate --network development
Using network 'development'.

Running migration: 1_initial_migration.js
  Replacing Migrations...
  ... 0x42b2d96809816765b609ca1b5e3505858a6d03ea1145f2ae47359fd66a6ebd69
  Migrations: 0xe331f52a830f6abd8eb8e143fbde110edd28b9b8
Saving successful migration to network...
  ... 0x95f6e662c20a0350ff1903216a61cd1c878c8a571cb4a214b62d44a28e38a22d
Saving artifacts...
Running migration: 2_deploy_contracts.js
  Replacing Greeter...
  ... 0x33b9776384f25342d51799970744b44dcfedf55a36093d55a72c5323dcbc8cf5
  Greeter: 0x4cf91392df7740176d74f63faf9991ec838a6473
  Replacing Test...
  ... 0x84463c7b8bce644a4df200ed1afdb3714514696cb32eef443854ca2dc2e56a70
  Test: 0x57fec0a6d60ce7a133bbc6f7ac64f99a7b97425f
Saving successful migration to network...
  ... 0xc8902db446771ad43bf55b50acf6ae0e5c7972a48e72e7ff924104e5a8fbf6b0
Saving artifacts...

提示:如果你之前的移植是成功执行的。truffle migrate仅会执行新创建的移植。如果没有新的移植脚本,这个命令不同执行任何操作。如果报错出现了一些你之前编译部署过,但你已经不需要的合约,可以用truffle migrate --reset来重置部署

9.验证合约,上一步操作已经成功部署了合约,其实验证合约应该是通过web3.js在应用里调用合约的方法,但我们的合约内容简单,我们通过console来验证

$ truffle console
truffle(development)> 

//调用Test合约的g()方法
truffle(development)> Test.deployed().then(function(func){return func.g.call();});
'method g()'
//调用Test合约的f()方法
truffle(development)> Test.deployed().then(function(func){return func.f.call();});
'method f()'
//调用Greeter合约的setGreeting()方法
truffle(development)>  Greeter.deployed().then(function(func){return func.setGreeting("hello");});
{ tx: '0x2660bc0b7a769d995b32f68a9a1166d0ef93d8adb4a77a9fcb31cdccba000c41',
  receipt: 
   { transactionHash: '0x2660bc0b7a769d995b32f68a9a1166d0ef93d8adb4a77a9fcb31cdccba000c41',
     transactionIndex: 0,
     blockHash: '0x1fd9b5431279aadf9076a561aae7de355fbc3ba3ec4646c892de3cf577dd02a0',
     blockNumber: 18,
     gasUsed: 43033,
     cumulativeGasUsed: 43033,
     contractAddress: null,
     logs: [],
     status: 1 },
  logs: [] }
//调用Greeter合约的greet()方法
truffle(development)> Greeter.deployed().then(function(func){return func.greet();});
'hello'
//退出控制台
truffle(development)> .exit

关于Dapp开发的Truffle框架Ⅰ的内容就先写到这里,后面就开始讲web3调用的内容,Truffle框架的高级应用在以后的内容中遇到了再详细讲吧。至于智能合约的语法solidity目前我还不是很熟练,就暂时不深讲了,多读读文档,多动手尝试编写一些智能合约。