共计 8607 个字符,预计需要花费 22 分钟才能阅读完成。
Truffle
Truffle 简介
truffle unbox webpack 一条命令因为要下载泛滥须要的模块,大略耗时 10 分钟左右,所以咱们先来理解一下 Truffle。
Truffle 是目前最风行的以太坊 DApp 开发框架,(依照官网说法)是一个世界级的开发环境和测试框架,也是所有应用了 EVM 的区块链的资产治理通道,它基于 JavaScript,致力于让以太坊上的开发变得简略。
Truffle 有以下性能:
- 内置的智能合约编译,链接,部署和二进制文件的治理。
- 合约自动测试,不便疾速开发。
- 脚本化的、可扩大的部署与公布框架。
- 可部署到任意数量公网或私网的网络环境治理性能
- 应用 EthPM 和 NPM 提供的包治理,应用 ERC190 规范。
- 与合约间接通信的间接交互控制台(写完合约就能够命令行里验证了)。
- 可配的构建流程,反对严密集成。
- 在 Truffle 环境里反对执行内部的脚本。
Truffle 的客户端
咱们之后写的智能合约必须要部署到链上进行测试,所以 truffle 构建的 DApp 也必须抉择一条链来进行部署。咱们能够抉择部署到一些公共的测试链比方 Rinkeby 或者 Ropsten 上,毛病是部署和测试工夫比拟长,而且须要破费肯定的工夫赚取假代币避免 out of gas。当然,对于 DApp 公布的正规流程,staging(模仿环境)还是应该用测试公链的。
还有一种形式就是部署到私链上,这在开发阶段是通常的抉择。Truffle 官网举荐应用以下两种客户端:
- Ganache
- truffle develop
而 truffle develop 是 truffle 内置的客户端,跟命令行版本的 Ganache 根本相似。在 truffle 目录下 bash 输出:
truffle develop
即可开启客户端,和 ganache 一样,它也会给咱们主动生成 10 个账户。惟一要留神的是在 truffle develop 里执行 truffle 命令的时候须要省略后面的“truffle”,比方“truffle compile”只须要敲“compile”就能够了
装置 Truffle
启动 geth,而后咱们来装置 truffle。truffle 是一个 dapp 的开发框架,它能够使得 dapp 的构建和治理非常容易。
你能够像这样应用 npm 装置 truffle:>npm install -g truffle 而后咱们创立一个空目录,在上面创立 truffle 我的项目:
mkdir simple_voting_by_truffle_dapp
cd simple_voting_by_truffle_dapp
npm install -g webpack
truffle unbox webpack
truffle init: 在当前目录初始化一个新的 truffle 空我的项目(我的项目文件只有 truffle-config.js 和 truffle.js;contracts 目录中只有 Migrations.sol;migrations 目录中只有 1_initial_migration.js)。
truffle unbox: 间接下载一个 truffle box,即一个事后构建好的 truffle 我的项目;unbox 的过程绝对会长一点,实现之后应该看到这样的提醒:
这里的 webpack 就是一个基于 webpack 构建流程的官网我的项目框架(truffle box),更多 truffle box 参见:
https://truffleframework.com/boxes
创立我的项目
初始化一个 truffle 我的项目时,它会创立运行一个残缺 dapp 所有必要的文件和目录。咱们间接下载 webpack 这个 truffle box,它外面的目录也是相似的:
ls
README.md contracts node_modules test
webpack.config.js truffle.js app migrations
package.json
ls app/
index.html javascripts stylesheets
ls contracts/
ConvertLib.sol MetaCoin.sol Migrations.sol
ls migrations/
1_initial_migration.js 2_deploy_contracts.js
- app/ – 你的利用文件运行的默认目录。这外面包含举荐的 javascript 文件和 css 款式文件目录,但你能够齐全决定如何应用这些目录。
- contract/ – Truffle 默认的合约文件寄存目录。
- migrations/ – 部署脚本文件的寄存目录。
- test/ – 用来测试利用和合约的测试文件目录。
- truffle.js – Truffle 的配置文件。
truffle 也会创立一个你能够疾速上手的示例利用,你能够释怀地删除我的项目上面 contracts 目录的 ConvertLib.sol 和 MetaCoin.sol 文件。
rm contracts/ConvertLib.sol contracts/MetaCoin.sol
此外,在你的我的项目目录下查找一个叫做 truffle.js 的配置文件。它外面蕴含了一个用于开发网络的配置。将端口号从 7545 改为 8545,因为咱们的私链及 ganache 默认都会在该端口运行。
Migration
migration 的概念
了解 migrations(迁徙)目录的内容十分重要。这些迁徙文件用于将合约部署到区块链上。
之前的我的项目中通过在 node 控制台中调 VotingContract.new 将投票合约部署到区块链上。当前,咱们再也不须要这么做了,truffle 将会部署和跟踪所有的部署。
Migrations(迁徙)是 JavaScript 文件,这些文件负责暂存咱们的部署工作,并且假设部署需要会随着时间推移而扭转。随着我的项目的倒退,咱们应该创立新的迁徙脚本,来扭转链上的合约状态。所有运行过的 migration 历史记录,都会通过非凡的迁徙合约记录在链上。
第一个迁徙 1_initial_migration.js 向区块链部署了一个叫做 Migrations 的合约,并用于存储你曾经部署的最新合约。每次你运行 migration 时,truffle 会向区块链查问获取最新已部署好的合约,而后部署尚未部署的任何合约。
而后它会更新 Migrations 合约中的 last_completed_migration 字段指向最新部署的合约。你能够简略地把它当成是一个数据库表,外面有一列:
last_completed_migration,该列总是放弃最新状态。
migration 文件的命名有特殊要求:前缀是一个数字(必须),用来标记迁徙是否运行胜利;后缀是一个形容词汇,只是单纯为了进步可读性,不便了解。
artifacts.require()
在脚本的开始,咱们用 artifacts.require() 办法通知 truffle 想要进行部署迁徙的合约,这跟 node 里的 require 很相似。不过须要留神,最新的官网文档告诫,应该传入定义的合约名称,而不要给文件名称——因为一个.sol 文件中可能蕴含了多个 contract。
exports 的函数
migration js 里的 exports 的函数,须要接管一个 deployer 对象作为第一个参数。这个对象在部署公布的过程中,次要是用来提供清晰的语法反对,同时提供一些通用的合约部署职责,比方保留部署的文件以备稍后应用。
deployer 对象
deployer 对象是用来暂存 (stage) 部署工作的次要操作接口。
像所有其它在 Truffle 中的代码一样,Truffle 提供了咱们本人代码的合约形象层(contract abstractions),并且进行了初始化,以不便你能够便当的与以太坊的网络交互。这些形象接口都是部署流程的一部分。
更新 migration 文件
将 2_deploy_contracts.js 的内容更新为以下信息:
var Voting = artifacts.require(“./Voting.sol”);
module.exports = function(deployer) {
deployer.deploy(Voting, [‘Alice’, ‘Bob’, ‘Cary’], {gas:
290000});
};
从下面能够看出,部署者心愿第一个参数为合约名,跟在结构函数参数前面。
在咱们的例子中,只有一个参数,就是一个候选者数组。第三个参数是一个哈希,咱们用来指定部署代码所需的 gas。gas 数量会随着你的合约大小而变动。对于投票合约,290000 就足够了。
更新 truffle 配置文件
像上面这样更新 truffle.js 的内容:
require(‘babel-register’)
module.exports = {
networks: {
development: {
host: ‘localhost’,
port: 8545,
network_id: ‘*’,
gas: 470000
} } }
你会留神到,之前的 truffle.js 与咱们更新的文件惟一区别在于 gas 选项。
这是一个会利用到所有 migration 的全局变量。比方,如果你没有指定:
2_deploy_contracts.js gas 值为 290000,migration 就会采纳默认值 470000.
合约代码 Voting.sol
之前咱们曾经实现了编码工作,毋庸额定改变即可用于 truffle。将文件从:
simple_voting_dapp 复制到 contracts 目录即可。
创立账户(可用 metamask 上账户转币)
在可能部署合约之前,咱们须要一个外面有一些以太的账户。当咱们用 ganache 的时候,它创立了 10 个测试账户,每个账户外面有 100 个测试以太。然而对于测试网和主网,咱们必须本人创立账户,并往里面打一些以太。
在之前的 ganache 利用里,咱们曾独自启动了一个 node 控制台,并初始化了 web3 对象。当咱们执行 truffle 控制台时,truffle 会帮咱们做好所有筹备,咱们会有一个立刻可用的 web3 对象。当初咱们有一个账户,地址为:
‘0x95a94979d86d9c32d1d2ab5ace2dcc8d1b446fa1’(你会失去一个不同的地址),账户余额为 0。
truffle console
// Replace ‘verystrongpassword’ with a good strong password.
truffle(development)>
web3.personal.newAccount(‘verystrongpassword’) ‘ 0xbaeec91f6390a4eedad8729aea4bf47bf8769b15’
truffle(development)>
web3.eth.getBalance(‘0xbaeec91f6390a4eedad8729aea4bf47bf8769b1
5′)
{[String: ‘0’] s: 1, e: 0, c: [0] }
truffle(development)>
web3.personal.unlockAccount(‘0xbaeec91f6390a4eedad8729aea4bf47
bf8769b15′, ‘verystrongpassword’, 15000)
部署
如果曾经有了一些以太,咱们就能够持续编译并把合约部署到区块链上。你能够在上面找到相干命令,如果一切顺利,就会呈现以下输入。
truffle compile
Compiling Migrations.sol…Compiling Voting.sol…Writing
artifacts to ./build/contracts
truffle migrate
Running migration: 1_initial_migration.js
Deploying Migrations…
Migrations: 0x3cee101c94f8a06d549334372181bc5a7b3a8bee
Saving successful migration to network…
Saving artifacts…
Running migration: 2_deploy_contracts.js
Deploying Voting…
Voting: 0xd24a32f0ee12f5e9d233a2ebab5a53d4d4986203
Saving successful migration to network…
Saving artifacts…
如果你有多个账户,确保相干账户未被锁定。默认状况,第一个账户 web3.eth.accounts[0]会用于部署。
可能呈现的问题和解决方案
- 如果因为 gas 有余而部署失败,尝试将 migrations/2_deploy_contracts.js 外面的 gas account 减少至 500000。比方:deployer.deploy(Voting, [‘Rama’,‘Nick’,‘Jose’],{gas: 500000});
- 如果你有多个账户,并且更喜爱自选一个账户,而不是 accounts[0],你能够在 truffle.js 中指定想要应用的账户地址。在 network_id 前面增加‘from: your address’,truffle 将会应用你指定的地址来部署和交互。
如果部署顺利,你能够通过控制台和网页与合约进行交互
新建 JavaScript 文件:
app/scripts/index.js
// Import the page’s CSS. Webpack will know what to do with it.
import “../styles/app.css”;
// Import libraries we need.
import {default as Web3} from ‘web3’;
import {default as contract} from ‘truffle-contract’
import voting_artifacts from ‘../../build/contracts/Voting.json’
var Voting = contract(voting_artifacts);
let candidates = {“Alice”: “candidate-1”, “Bob”: “candidate-2”,
“Cary”: “candidate-3”}
window.voteForCandidate = function(candidate) {
let candidateName = $(“#candidate”).val();
try {
$(“#msg”).html(“Vote has been submitted. The vote count
will increment as soon as the vote is recorded on the blockchain.
Please wait.”)
$(“#candidate”).val(“”);
Voting.deployed().then(function(contractInstance) {
contractInstance.voteForCandidate(candidateName,
{gas: 140000,
from:web3.eth.accounts[0]})
.then(function() {
let div_id = candidates[candidateName];
return
contractInstance.totalVotesFor
.call(candidateName).then(function(v) {
$(“#” + div_id).html(v.toString());
$(“#msg”).html(“”);
});
});
});
} catch (err) {
console.log(err);
}
}
$(document).ready(function() {
if (typeof web3 !== ‘undefined’) {
console.warn(“Using web3 detected from external
source like 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/t…k”);
// 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”));
}
Voting.setProvider(web3.currentProvider);
let candidateNames = Object.keys(candidates);
for (var i = 0; i < candidateNames.length; i++) {
let name = candidateNames[i];
Voting.deployed().then(function(contractInstance) {
contractInstance.totalVotesFor
.call(name).then(function(v) {
$(“#” + candidates[name])
.html(v.toString());
});
});
}
});
Line 7: 当你编译部署好投票合约时,truffle 会将 abi 和部署好的地址存储到一个 build 目录上面的 json 文件。咱们曾经在之前探讨了 abi。咱们会用这个信息来启动一个 Voting 形象。咱们将会随后用这个 abstraction 创立一个 Voting 合约的实例。
Line 14: Voting.deployed() 返回一个合约实例。truffle 的每一个调用会返回一个 promise,这就是为什么咱们在每一个交易调用时都应用 then().
控制台交互须要从新关上一个新的 console
truffle console
truffle(default)>
Voting.deployed().then(function(contractInstance)
{contractInstance.voteForCandidate(‘Alice’).then(function(v)
{console.log(v)})})
{blockHash:
‘0x7229f668db0ac335cdd0c4c86e0394a35dd471a1095b8fafb52ebd76714
33156′,
blockNumber: 469628,
contractAddress: null,
….
….
truffle(default)>
Voting.deployed().then(function(contractInstance)
{contractInstance.totalVotesFor.call(‘Alice’).then(function(v)
{console.log(v)})})
{[String: ‘1’] s: 1, e: 0, c: [1] }
在调用 voteForCandidate 办法之后须要稍等一下,因为发送交易须要工夫;留神,truffle 的所有调用都会返回一个 promise,这就是为什么会看到每个响应被包装在 then() 函数上面;另外 totalVoteFor() 办法也能够不加.call() 间接调用,不会发送交易。
收回的交易能够在 geth 的 log 输入文件中查到;如果咱们连贯的是测试网络,能够在 etherscan 上 https://rinkeby.etherscan.io 查问。
能够看到 truffle 默认的 gasPrice 是 100GWei,如果疼爱,能够在 truffle.js 中更改,加上 gasPrice: 1000000000 将其改为 1GWei,重启 truffle console 失效。
网页交互
在控制台用 webpack 启动服务器:
npm run dev
默认端口 8080,在浏览器拜访 localhost:8080 即可看到页面。
如果装置了 metamask,index.js 中会自动检测并应用 metamask 作为 web3 Provider;所以应该留神把 metamask 切换到咱们以后连贯的网络。
版权申明:本文为 CSDN 博主「死磕的斯坦张」的原创文章,遵循 CC 4.0 BY-SA 版权协定,转载请附上原文出处链接及本申明。
原文链接:
https://blog.csdn.net/david2000999/article/details/120472092
文章起源:CSDN 博主「死磕的斯坦张」
文章原题目:《以太坊开发框架——Truffle 的根底应用》
如有侵权请与咱们分割删除。