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的根底应用》
如有侵权请与咱们分割删除。