Truffle3.0整合NodeJS並完全跑通(附詳細例項,可能的錯誤)
升級到Truffle3.0
如果之前安裝的是Truffle2.0版本,需要主動升級到Truffle3.0,兩者的語法變化有點大。
由於Truffle
是一個命令列工具,需要更新全域性空間安裝的Truffle
。
$ sudo npm update -g truffle
注意需要root許可權執行命令,否則可能會報錯無足夠的訪問許可權,導致升級失敗。
安裝成功後,可以通過版本命令檢視當前的版本,如出現下述類似字樣說明升級成功:
$ truffle version
Truffle v3.1.2
初始化工程
使用Truffle3.0初始化工程
我們建立一個新工程目錄,並在truffle3
目錄內初始化Truffle框架。
$ mkdir truffle3 && cd truffle3
$ truffle init
Downloading project...
Project initialized.
Documentation: http://truffleframework.com/docs
Commands:
Compile: truffle compile
Migrate: truffle migrate
Test: truffle test
我們建立了一個新工程目錄truffle3
,進入到這個目錄,使用truffle init
命令,初始化了一個全新的Truffle 3.0
的工程,工程目錄如下:
整合NodeJS
truffle console
命令會預設整合web3
,合約抽象層。如果想要在自已的NodeJS
環境使用Truffle
合約,就要手動整合這兩個模組。在整合前,我們需要建立工程的npm
包管理環境,首先進入truffle3
工程目錄,使用npm init
來初始化工程的npm
包管理環境:
$ 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> --save` afterwards to install a package and
save it as a dependency in the package.json file.
Press ^C at any time to quit.
name: (truffle3) TruffleForTest
Sorry, name can no longer contain capital letters.
name: (truffle3) truffle3
version: (1.0.0) 1.0.0
description: This is a sample project for integrate truffle 3.0 with nodejs.
entry point: (truffle.js) main.js
test command: truffle3
git repository:main.js
keywords: truffle3.0
author: TryBlockchain
license: (ISC)
About to write to /Users/TryBlockchain/develop/blockchain_workspace/truffle3/package.json:
{
"name": "truffle3",
"version": "1.0.0",
"description": "This is a sample project for integrate truffle 3.0 with nodejs.",
"main": "main.js",
"directories": {
"test": "test"
},
"scripts": {
"test": "truffle3"
},
"keywords": [
"truffle3.0"
],
"author": "TryBlockchain",
"license": "ISC"
}
Is this ok? (yes) yes
如果不進行npm init
初始化,就進行後續模組安裝,會報如下錯誤:
$ npm install truffle-contract
/Users/TryBlockchain
└─┬ truffle-contract@1.1.10
├─┬ ethjs-abi@0.1.9
│ ├── bn.js@4.11.6
│ ├── js-sha3@0.5.5
│ └─┬ number-to-bn@1.7.0
│ ├── bn.js@4.11.6 deduped
│ └─┬ strip-hex-prefix@1.0.0
│ └── is-hex-prefixed@1.0.0
├── truffle-blockchain-utils@0.0.1
├─┬ truffle-contract-schema@0.0.5
│ └── crypto-js@3.1.9-1
└─┬ web3@0.16.0
└── bignumber.js@2.0.7 (git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2)
npm WARN enoent ENOENT: no such file or directory, open '/Users/TryBlockchain/package.json'
npm WARN TryBlockchain No description
npm WARN TryBlockchain No repository field.
npm WARN TryBlockchain No README data
npm WARN TryBlockchain No license field.
由於沒有包管理環境,所以對package.json
的包依賴寫入會失敗。報錯npm WARN enoent ENOENT: no such file or directory, open '/Users/TryBlockchain/package.json'
。要解決這個問題,需要使用npm init
來初始化當前工程的包管理環境。
安裝NodeJS
中用到的Truffle
合約抽象層執行環境
這個工具是Truffle
提供的,用於在NodeJS
和瀏覽器中整合Truffle的合約抽象執行環境1。
$ npm install truffle-contract
truffle3@1.0.0 /Users/TryBlockchain/develop/blockchain_workspace/truffle3
└─┬ truffle-contract@1.1.10
├─┬ ethjs-abi@0.1.9
│ ├── bn.js@4.11.6
│ ├── js-sha3@0.5.5
│ └─┬ number-to-bn@1.7.0
│ ├── bn.js@4.11.6 deduped
│ └─┬ strip-hex-prefix@1.0.0
│ └── is-hex-prefixed@1.0.0
├─┬ truffle-blockchain-utils@0.0.1
│ └─┬ web3@0.18.2
│ ├── bignumber.js@2.0.7 (git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2)
│ ├── crypto-js@3.1.8 deduped
│ ├── utf8@2.1.2 deduped
│ ├── xhr2@0.1.4
│ └── xmlhttprequest@1.8.0 deduped
├─┬ truffle-contract-schema@0.0.5
│ └── crypto-js@3.1.9-1
└─┬ web3@0.16.0
├── bignumber.js@2.0.7 (git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2)
├── crypto-js@3.1.8
├── utf8@2.1.2
└── xmlhttprequest@1.8.0
安裝NodeJS
中用到的Truffle執行時需要的web3
環境
$ npm install web3
- bignumber.js@2.0.7 node_modules/web3/node_modules/bignumber.js
truffle3@1.0.0 /Users/TryBlockchain/develop/blockchain_workspace/truffle3
└── web3@0.18.2
我們使用npm install web3
即可安裝web3
模組。如果沒有整合web3
環境,就跑相關的程式碼,可能會報下述錯:
$ node main.js
/Users/TryBlockchain/develop/blockchain_workspace/truffle3/main/main.js:4
var provider = new Web3.providers.HttpProvider("http://localhost:8545");
^
ReferenceError: Web3 is not defined
at Object.<anonymous> (/Users/TryBlockchain/develop/blockchain_workspace/truffle3/main/main.js:4:20)
at Module._compile (module.js:571:32)
at Object.Module._extensions..js (module.js:580:10)
at Module.load (module.js:488:32)
at tryModuleLoad (module.js:447:12)
at Function.Module._load (module.js:439:3)
at Module.runMain (module.js:605:10)
at run (bootstrap_NodeJS:420:7)
at startup (bootstrap_NodeJS:139:9)
at bootstrap_NodeJS:535:3
建立自己的合約檔案
新增加測試合約
在truffle3/contracts
目錄下建立測試合約檔案Test.sol
pragma solidity ^0.4.4;
contract Test{
function f() returns (string){
return "method f()";
}
function g() returns (string){
return "method g()";
}
}
在上述程式碼中,我們提供兩個函式,f()
和g()
。分別返回用於說明它們是哪個函式的返回結果的字串說明。
增加deploy
配置
修改migrations/2_deploy_contracts.js
為如下:
var ConvertLib = artifacts.require("./ConvertLib.sol");
var MetaCoin = artifacts.require("./MetaCoin.sol");
var Test = artifacts.require("./Test.sol");
module.exports = function(deployer) {
deployer.deploy(ConvertLib);
deployer.link(ConvertLib, MetaCoin);
deployer.deploy(MetaCoin);
deployer.deploy(Test);
};
上述程式碼主要增加兩行,一行為var Test = artifacts.require("./Test.sol");
宣告一個新的合約檔案例項並命名為Test
;增加的另一行內容deployer.deploy(Test);
用於將Test
進行部署。
編譯合約
下面我們使用truffle migrate --reset
來強制重編譯併發布所有合約,由於合約移植是懶編譯的,如果發現已經發布過,且釋出的版本號沒有變化就不會再發布,所以使用--reset
。請務必弄清楚為何使用--reset
再使用這個命令2。執行truffle migrate
前,需要確認節點處於執行狀態。
$ truffle migrate --reset
Using network 'development'.
Running migration: 1_initial_migration.js
Replacing Migrations...
Migrations: 0xdc59c5de4e7b1dcf23f864425a704020e53666b5
Saving successful migration to network...
Saving artifacts...
Running migration: 2_deploy_contracts.js
Replacing ConvertLib...
ConvertLib: 0x19cf958fede2e0f082cbcf5629f1a1344b221bf3
Linking ConvertLib to MetaCoin
Replacing MetaCoin...
MetaCoin: 0x39073d502491f57537f999584071691d19cf5f24
Replacing Test...
Test: 0x8ca770415902e5a64ef53062b5ba85626c3dd5dc
Saving successful migration to network...
Saving artifacts...
使用NodeJS
整合Truffle3.0
程式碼完整DEMO
var Web3 = require('web3');
var contract = require("truffle-contract");
var provider = new Web3.providers.HttpProvider("http://localhost:8545");
//使用truffle-contract包的contract()方法
//請務必使用你自己編譯的.json檔案內容
var Test = contract({
"contract_name": "Test",
"abi": [
{
"constant": false,
"inputs": [],
"name": "f",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [],
"name": "g",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"type": "function"
}
],
"unlinked_binary": "0x606060405234610000575b6101ff806100196000396000f300606060405263ffffffff60e060020a60003504166326121ff0811461002f578063e2179b8e146100bc575b610000565b346100005761003c610149565b604080516020808252835181830152835191928392908301918501908083838215610082575b80518252602083111561008257601f199092019160209182019101610062565b505050905090810190601f1680156100ae5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b346100005761003c61018e565b604080516020808252835181830152835191928392908301918501908083838215610082575b80518252602083111561008257601f199092019160209182019101610062565b505050905090810190601f1680156100ae5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b604080516020818101835260009091528151808301909252600a82527f6d6574686f642066282900000000000000000000000000000000000000000000908201525b90565b604080516020818101835260009091528151808301909252600a82527f6d6574686f642067282900000000000000000000000000000000000000000000908201525b905600a165627a7a72305820c238bd4de6aa330fcc88946b9948bc265c7ac1408dc5c8b7ee6e648413ae540f0029",
"networks": {
"1489826524891": {
"events": {},
"links": {},
"address": "0x9db90af99faa32ed14dccfb19326e917efac456b",
"updated_at": 1489827968151
}
},
"schema_version": "0.0.5",
"updated_at": 1489827968151
});
Test.setProvider(provider);
//沒有預設地址,會報錯
//UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 3): Error: invalid address
//務必設定為自己的錢包地址,如果不知道,檢視自己的客戶端啟動時,觀察列印到控制檯的地址
Test.defaults({
from : "0x299127d72e28cb92d09f856aaedeb139d1e7e74a"
});
var instance;
Test.deployed().then(function(contractInstance) {
instance = contractInstance;
return instance.f.call();
}).then(function(result){
console.log(result);
return instance.g.call();
}).then(function(result){
console.log(result);
});
整合示例詳解
引入web3
要在NodeJS
中使用Truffle
,我們要先引入web3
。
var Web3 = require('web3');
var provider = new Web3.providers.HttpProvider("http://localhost:8545");
//省略了無關程式碼
//合約初始化
var Test = contract(/*合約JSON*/);
//設定連線
Test.setProvider(provider);
在上例中,我們先通過var Web3 = require('web3');
引入依賴,並初始化一個例項Web3
,併為例項設定了HttpProvider
。
truffle-contract
的contract()
方法
要在NodeJS
初始化Truffle編譯好的合約,要使用contract()
方法。請將Truffle3.0編譯後的.json
檔案,一般在build/contracts/Test.json
。請將此檔案的內容放入contract()
的括號內。
var contract = require("truffle-contract");
//請使用使用Truffle3.0編譯的.json檔案內容
var Test = contract(/*引數是`JSON`物件,放入Truffle3.0生成的.json檔案內容*/)
然後使用.deployed()
或at(/*某個地址*/)
來進行呼叫1。
contract()
引入的JSON
定義有問題
如果引入的JSON
資料有問題,你可能會看到下面的錯誤:
$ node main.js
/Users/TryBlockchain/develop/blockchain_workspace/truffle3/node_modules/truffle-contract/node_modules/web3/lib/web3/contract.js:56
contract.abi.filter(function (json) {
^
TypeError: Cannot read property 'filter' of undefined
at addFunctionsToContract (/Users/TryBlockchain/develop/blockchain_workspace/truffle3/node_modules/truffle-contract/node_modules/web3/li
b/web3/contract.js:56:17)
at ContractFactory.at (/Users/TryBlockchain/develop/blockchain_workspace/truffle3/node_modules/truffle-contract/node_modules/web3/lib/we
b3/contract.js:255:5)
at TruffleContract.Contract (/Users/TryBlockchain/develop/blockchain_workspace/truffle3/node_modules/truffle-contract/contract.js:257:33
)
at new TruffleContract (/Users/TryBlockchain/develop/blockchain_workspace/truffle3/node_modules/truffle-contract/contract.js:572:25)
at Function.at (/Users/TryBlockchain/develop/blockchain_workspace/truffle3/node_modules/truffle-contract/contract.js:390:22)
at Object.<anonymous> (/Users/TryBlockchain/develop/blockchain_workspace/truffle3/main/main.js:54:6)
at Module._compile (module.js:571:32)
at Object.Module._extensions..js (module.js:580:10)
at Module.load (module.js:488:32)
at tryModuleLoad (module.js:447:12)
如果你出現了上述報錯,請再次確認是否原封不動的把合約編譯後的.json
檔案的內容,複製進contract()
的括號內的,不要加任何東西,因為.json
檔案內就是一個JSON
物件。
預設帳戶地址
truffle-contract
框架預設沒有讀取coinbase
的預設地址,所以需要按如下方式主動設定:
//沒有預設地址,會報錯
//UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 3): Error: invalid address
Test.defaults({
from : "0x299127d72e28cb92d09f856aaedeb139d1e7e74a"
});
否則會報錯UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 3): Error: invalid address
3。
語法注意
對於新的Truffle3.0語法,需要注意的是函式呼叫方式要遵循呼叫規則4。對於一個不會改寫區塊鏈狀態的f()
函式,使用instance.f.call();
;而對於一個會改寫區塊鏈狀態的函式f()
,使用instance.f()
。底層在實現呼叫上,會使用不同gas
計算方式。
var instance;
Test.deployed().then(function(contractInstance) {
instance = contractInstance;
return instance.f.call();
}).then(function(result){
console.log(result);
return instance.g.call();
}).then(function(result){
console.log(result);
});
如果對於一個不會改寫狀態f()
,使用instance.f()
會返回對應的交易狀態結果。
$ node main.js
{ tx: '0x2ac645310278d971e3911e8f880947105f582aa4eab3d3d66d14c95333391ac9',
receipt:
{ transactionHash: '0x2ac645310278d971e3911e8f880947105f582aa4eab3d3d66d14c95333391ac9',
transactionIndex: 0,
blockHash: '0x69a6788032c7bef12d6d51bc045548fa9edb0665bb0fbcf9cf55d30f9744cd61',
blockNumber: 29,
gasUsed: 21803,
cumulativeGasUsed: 21803,
contractAddress: null,
logs: [] },
logs: [] }
{ tx: '0x65aa2c4da73ef5a17221c26e74b9b329bdc353856564f8d1f49c07f6dcd055ea',
receipt:
{ transactionHash: '0x65aa2c4da73ef5a17221c26e74b9b329bdc353856564f8d1f49c07f6dcd055ea',
transactionIndex: 0,
blockHash: '0x837ec6a3df2cc4d9a8ccf8d77c14b88a13b0053a5149a74c1a984fe88a70eaa8',
blockNumber: 30,
gasUsed: 21825,
cumulativeGasUsed: 21825,
contractAddress: null,
logs: [] },
logs: [] }
Truffle contract的github地址及文件: https://github.com/trufflesuite/truffle-contract ↩
關於
invalid address
的報錯,http://ethereum.stackexchange.com/questions/12957/truffle-invalid-address 報這個錯的可能情況: http://www.bullraider.com/ethereum/tutorials/342-understanding-invalid-address-error-in-dapps-or-geth-console ↩
相關文章
- 可能比文件還詳細--VueRouter完全指北Vue
- Spring中Bean的例項化詳細流程SpringBean
- AI回答總不滿意?你的提問方式可能完全錯誤!AI
- 使用 createError 建立錯誤物件的詳細指南Error物件
- SwiftUI 官方畫圖例項詳細解析SwiftUI
- 這可能是你看過最詳細的NodeJS安裝配置教程NodeJS
- 【Spring Boot架構】整合Mybatis-Plus的例項詳解Spring Boot架構MyBatis
- nodejs打包問題解決例項NodeJS
- 杭電OJ 2048 完全錯排的可能性
- 基於QT錄製PCM音訊例項詳細QT音訊
- 史上最詳細的IDEA優雅整合Maven+SSM框架(詳細思路+附帶原始碼)IdeaMavenSSM框架原始碼
- NodeJS入門(一)---nodejs詳細安裝步驟NodeJS
- Duboo整合SpringBoot超級詳細例子(附原始碼)Spring Boot原始碼
- Spring Boot 整合 FreeMarker 例項Spring Boot
- Python例項之用Python求完全平方數Python
- 一次詳細的RAC 節點例項驅逐分析文件
- 一篇掌握SpringBoot+SpringCache+Redis超詳細例項Spring BootGCRedis
- 詳細例項教程!整合華為虛假使用者檢測,防範虛假惡意流量
- 專案整合Swagger遇到的錯誤Swagger
- ActiveMQ的使用及整合spring的使用例項MQSpring
- 例項詳解不同VLAN間通訊(轉發過程)
- 可能是最詳細的字元編碼詳解字元
- SpringBoot+Dubbo的註解方式整合例項Spring Boot
- 馬蹄疾 | 聊聊你可能並沒有完全掌握的 Flex 佈局Flex
- 一次RAC例項驅逐詳細分析及解決方案
- 【ASK_ORACLE】Relink ASM單例項資料庫詳細步驟OracleASM單例資料庫
- 附例項!實現iframe父窗體與子窗體的通訊
- Springboot整合mybatis框架(含例項Demo)Spring BootMyBatis框架
- 元件例項 $el 詳解元件
- Java的Socket通訊簡單例項Java單例
- php 對空陣列元素??並進行運算,可能觸發 Undefined index 錯誤PHP陣列UndefinedIndex
- 通過例項學習 PyTorchPyTorch
- table細線表格例項程式碼
- Hadoop3.x完全分散式搭建(詳細)Hadoop分散式
- 詳細分析 Java 中啟動執行緒的正確和錯誤方式Java執行緒
- Oracle 不完全恢復遇到的ORA-600錯誤Oracle
- win10 d盤錯誤檢查如何操作_win10 d盤錯誤檢查詳細方法Win10
- SpringBoot整合Mybatis超詳細流程Spring BootMyBatis