原文发表于: 以太坊智能合约开发第六篇: truffle 开发框架 https://www.marser.cn/article/141.html
在前面几篇教程中, 我们实现了一个简单的 Hello 合约, 并通过 solc 编译器将合约代码编译后, 部署在私有链 Ganache 上. 本篇将介绍通过 truffle 框架来构建自动编译, 部署合约代码.
truffle 框架
Truffle 是基于 Solidity 语言的一套开发框架, 它简化了去中心化应用 (Dapp) 的构建和管理流程. 本身是采用 Javascript 编写, 支持智能合约的编译, 部署和测试.
truffle 开发框架提供了很多功能, 简化了我们的开发, 编译, 部署与调试过程:
内置了智能合约编译, 链接, 部署和二进制文件的管理
方便快速开发的合约自动化测试
方便扩展的, 脚本化的部署与发布框架
方便的网络管理功能. 不论是公有网络还是私有网络
基于 ERC190 https://github.com/ethereum/EIPs/issues/190 标准, 使用 EthPM & NPM 进行依赖包管理
内置控制台功能. 项目构建后, 可以直接在命令行调用输出结果, 方便了开发调试
可配的构建流程, 支持持续集成.
支持外部脚本的执行
接下来, 我们将通过 truffle 框架来构建 Hello 合约的编译, 部署过程.
truffle 安装
npm install -g truffle
安装好后, 查看一下版本信息:
truffle version
本篇示例基于如下版本:
Truffle v4.0.1 (core: 4.0.1)
Solidity v0.4.18 (solc-js)
初始化项目
truffle 提供了很多项目模板, 可以快速搭建一个去中心化应用的代码骨架. 我们使用 webpack 项目模板来构建 Hello 合约. 在 smartcontract 目录下, 执行如下命令:
truffle unbox webpack
初始化项目的时候, 它会创建运行一个完整 Dapp 所需的文件和目录. 我们将 strings.sol 和 Hello.sol 两个合约文件移动到 contracts 目录下, 并删除 contracts 目录下原有的 ConvertLib.sol 和 MetaCoin.sol 文件(Migrations.sol 合约用来管理应用合约的部署, 因此请勿删除). 目录结构如下:
- smartcontract
- app
- contracts
Hello.sol
Migrations.sol
strings.sol
migrations
1_initial_migration.js
2_deploy_contracts.js
- node_modules
- package.json
- test
truffle.js
webpack.config.js
修改部署脚本
目录 migrations (迁移的意思) 非常重要. truffle 使用该目录下的脚本来管理合约的部署. 在前面几篇教程中, 我们是通过自己编写编译部署脚本 deploy.js , 并在 node 控制台中运行来将 Hello 合约部署到区块链上的. 有了 truffle, 以后再也不用这么做了.
第一个脚本 1_initial_migration.js 的作用是向区块链部署 Migrations 合约. 这个合约的作用是存储并跟踪已经部署的最新合约. 每次运行脚本时, truffle 就会向区块链查询获取已部署好的合约, 然后部署新的合约. 部署完成后, 这个脚本会更新 Migrations 合约中的 last_completed_migration 字段指向最新部署的合约.
我们可以简单地把 Migrations 合约当成是一个数据库表, 字段 last_completed_migration 总是保持最新状态.
我们来修改第二个脚本 2_deploy_contracts.js :
- //artifacts 对象为 truffle 框架提供
- //artifacts.require()方法与 Node 中的 require()方法类似
- // 编译合约代码. 自动调用 solc 编译器来编译合约代码并返回编译结果对象
- var stringsContract = artifacts.require("./strings.sol");
- var HelloContract = artifacts.require("./Hello.sol");
- // 部署器对象 deployer 为 truffle 框架提供
- module.exports = function(deployer) {
- // 部署 string.sol 合约
- deployer.deploy(stringsContract);
- // 将已部署的 strings 合约类库连接到 Hello 合约
- deployer.link(stringsContract, HelloContract);
- // 部署 Hello.sol 合约
- deployer.deploy(HelloContract);
- };
代码不难, 加上了注释很容易理解.
修改 truffle 配置
部署脚本修改完后, 我们还需要在配置文件中声明要连接的以太坊节点地址, 这里使用 Ganache 的地址
- http://localhost:7545
- :
- require('babel-register')
- module.exports = {
- networks: {
- development: {
- host: 'localhost',
- port: 7545,
- network_id: '*'
- }
- }
- }
注意 development 关键字. truffle 支持将合约部署到多个区块链网络, 例如开发网络, 私有网络, 测试网或公网. 在上面的配置中, 我们只定义了一个用于开发的网络.
编译合约
在 smartcontract 目录下执行 truffle compile 命令, 终端输出如下:
Compiling ./contracts/Hello.sol...
Compiling ./contracts/Migrations.sol...
Compiling ./contracts/strings.sol...
Writing artifacts to ./build/contracts
可以看到, contracts 目录下的三个合约文件都编译了, 并且在当前目录下生成了 build/contracts 目录, 同时也产生了三个文件:
smartcontract/build/contracts
Hello.json
Migrations.json
strings.json
这三个都是 abi 文件(abi 概念的解释, 可以翻看以太坊智能合约开发第二篇: 理解以太坊相关概念 https://www.marser.cn/article/136.html ).
部署合约
合约编译成功后, 就可以部署了. 在 smartcontract 目录下执行部署命令 truffle migrate , 可以看到终端上输出了部署日志:
关键信息可以标注出来. 我们也可以在 Ganache 中的 LOGS 面板中查看 transaction id 和 合约地址:
合约调用
合约部署成功后, 我们可以通过 truffle console 命令进入控制台. 在控制台里调用刚才部署的合约:
- $ truffle console
- truffle(development)> Hello.deployed().then(function(contractInstance){contractInstance.say.call('Guys').then(function(result){console.log(result)})})
truffle(development)> Hello Guys
需要注意的是, truffle 的所有调用都会返回 promise (node 语法), 所以每个响应都被包裹在 then() 函数里.
至此, 通过 truffle 框架进行合约的编译, 部署与调用就介绍完了. 和之前手动编写编译部署脚本, 及调用脚本的方式相比, 是不是更方便快捷? 而且代码量还更少更精炼. 通过 truffle 框架, 编译和部署都用一条命令即可搞定.
抛砖引玉
本篇中合约的调用是在 truffle 控制台中, 如何通过网页调用合约呢?
我的专栏: 智能合约 https://www.jianshu.com/c/4d3800411cfa
来源: https://segmentfault.com/a/1190000014375490