這篇文章的內容緊接著上章的內容粘昨,上一篇講了truffle
合約部署的基本操作壹哺,文章最后講了通過console
來調用部署成功的合約中的方法抄伍,之所以truffle console
能夠直接調用合約中的方式,是因為truffle console
默認集成了web3
管宵。如果想在NodeJS
環(huán)境使用Truffle
合約逝慧,就要手動集成這兩個模塊昔脯。
集成NodeJS
1.首先需要安裝npm
包管理器,這里就不講安裝過程笛臣,如果已經安裝過最好把npm
更新到最新版本云稚,不然在后面的操作中可能會報錯,以下就是我在操作過程中遇到的一個錯誤沈堡。
var BigNumber = (new Web3()).toBigNumber(0).constructor;
^
TypeError: (intermediate value).toBigNumber is not a function
2.創(chuàng)建工程的npm
包管理器静陈,這里我們還是以上一個項目為例,進入項目所在的目錄诞丽,使用npm init
來初始化工程的npm
包管理環(huán)境鲸拥。
$ 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>` afterwards to install a package and
save it as a dependency in the package.json file.
Press ^C at any time to quit.
package name: (truffletest) truffletest //回車或輸入括號內的包名
version: (1.0.0) 1.0.0 //同上
license: (ISC) //同上
About to write to /Users/cyril/Desktop/truffleTest/package.json:
{
"name": "truffletest",
"version": "1.0.0",
"description": "truffle with nodejs",
"main": "main.js",
"directories": {
"test": "test"
},
"scripts": {
"test": "truffletest"
},
"repository": {
"type": "git",
"url": "main.js"
},
"keywords": [
"truffletest"
],
"author": "cyril",
"license": "ISC",
"dependencies": {
"truffle-contract": "^3.0.6",
"web3": "^1.0.0-beta2"
}
}
Is this OK? (yes) yes //同前面的操作
這個時候項目會生成package.json
和package-lock.json
同時會添加node-modules
相關的庫依賴,生成的這些文件沒必要去修改
項目結構如下:
安裝
NodeJS
中用到的Truffle
合約抽象層運行環(huán)境truffle-contract
是Truffle
提供的僧免,用于在NodeJS
和瀏覽器中集成Truffle
的合約抽象運行環(huán)境刑赶。
$ npm install truffle-contract
npm notice created a lockfile as package-lock.json. You should commit this file.
+ truffle-contract@3.0.6
added 24 packages from 18 contributors and audited 25 packages in 13.15s
found 0 vulnerabilities
安裝NodeJS
中用到的Truffle
運行時需要的web3
環(huán)境
$ npm install web3
npm WARN deprecated web3@1.0.0-beta2: This version has faulty dependecy links.
+ web3@1.0.0-beta2
added 1 package from 1 contributor and audited 26 packages in 1.752s
found 0 vulnerabilities
測試合約
這里就用前面的Test.sol
和Greeter.sol
,部署流程就不講了懂衩,在項目根目錄下創(chuàng)建main.js
撞叨,內容大體結構如下
//引入依賴,并初始化一個實例Web3
var Web3 = require('web3');
var provider = new Web3.providers.HttpProvider("http://localhost:8545");
//省略了無關代碼
//合約初始化
var Test = contract(/*合約JSON*/);//合約的元數據
//設置連接
Test.setProvider(provider);
//設置默認地址
Test.defaults({
from : "0x299127d72e28cb92d09f856aaedeb139d1e7e74a"
});
//函數調用
//TODO
我們拿Test
舉個例子:
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({
"contractName": "Test",
"abi": [
{
"constant": true,
"inputs": [],
"name": "f",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "pure",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "g",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "pure",
"type": "function"
}
],
"networks": {
"1536568575803": {
"events": {},
"links": {},
"address": "0x57fec0a6d60ce7a133bbc6f7ac64f99a7b97425f",
"transactionHash": "0x84463c7b8bce644a4df200ed1afdb3714514696cb32eef443854ca2dc2e56a70"
},
"1536655141628": {
"events": {},
"links": {},
"address": "0x03873f72987988a143d514f43a6c548fe8d252b9",
"transactionHash": "0xd3b7577fb5aae6a5950c0b2e04e1211f26ce487dda065d264bf6c61e2b453983"
}
},
"schemaVersion": "2.0.1",
"updatedAt": "2018-09-11T09:04:16.743Z"
});
Test.setProvider(provider);
//隨便從testrpc提供的地址中拷貝一個
Test.defaults({
from: "0x807b0d9ffc27ecdc481bd1fc84fd3d4fb054c324"
});
//調用合約方法
var instance;
Test.deployed().then(function (func) {
instance = func;
return instance.f.call();
}).then(function (value) {
console.log(value);
return instance.g.call();
}).then(function (value) {
console.log(value);
});
注意:
1.最好原封不動的把json文件的內容拷貝過來浊洞,為了節(jié)約篇幅牵敷,我就只粘貼了部分,雖然不影響正常測試法希,但可能遇到下面的錯誤:node_modules/truffle->contract/node_modules/web3/lib/web3/contract.js:56 contract.abi.filter(function (json) { ^ TypeError: Cannot read property 'filter' of undefined
2.必須設置默認賬戶枷餐,
truffle-contract
框架默認沒有讀取coinbase
的默認地址,所以需要主動設置苫亦,不然會報如下錯誤:(node:26922) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error: invalid address
運行main.js
運行main.js
毛肋,然后報了如下錯:
$ node main.js
module.js:487
throw err;
^
Error: Cannot find module 'web3-requestManager'
這個問題就是我開篇說的一定要注意運行環(huán)境的版本,這個問題是因為package.json
中依賴的web3
版本是^1.0.0-beta2
屋剑,這個問題可以通過安裝依賴解決
$ npm install ethereum/web3.js
+ web3@0.20.7
added 4 packages from 4 contributors, updated 1 package and audited 32 packages in 58.834s
found 0 vulnerabilities
再次查看package.json
中的web3
版本已經變成了github:ethereum/web3.js
润匙,然后再次運行main.js
$ node main.js
method f()
method g()
輸出結果跟上篇內容的一樣,也在預料之中饼丘。不論是合約中的f()
方法還是g()
方法趁桃,都不會改寫區(qū)塊鏈狀態(tài),使用instance.f.call()調用肄鸽;而對于一個會改寫區(qū)塊鏈狀態(tài)的函數f()
卫病,使用instance.f()
調用,我們在以Greeter.sol
為例來演示一下
下面的代碼依然是放在main.js
里
var Web3 = require('web3');
var contract = require("truffle-contract");
var provider = new Web3.providers.HttpProvider("http://localhost:8545");
var Greeter = contract({
"contractName": "Greeter",
"abi": [
{
"inputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"constant": true,
"inputs": [],
"name": "greet",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_newgreeting",
"type": "string"
}
],
"name": "setGreeting",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [],
"name": "kill",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
}
],
"networks": {
"1536568575803": {
"events": {},
"links": {},
"address": "0x4cf91392df7740176d74f63faf9991ec838a6473",
"transactionHash": "0x33b9776384f25342d51799970744b44dcfedf55a36093d55a72c5323dcbc8cf5"
},
"1536655141628": {
"events": {},
"links": {},
"address": "0x2eb0113712145ffb42889c9421a6881e864ff2b4",
"transactionHash": "0x748948df55b1597223d54cc6184d7a43ac47a04a559fafd9eb49e3c02c1abe98"
}
},
"schemaVersion": "2.0.1",
"updatedAt": "2018-09-11T09:04:16.744Z"
});
Greeter.setProvider(provider);
Greeter.defaults({
from: "0xd10e318f0ef3e74c6e75e0827b840b2d00a49af5"
});
var ins;
Greeter.deployed().then(function (value) {
ins = value;
return ins.setGreeting("hello");
}).then(function (value) {
console.log(value);
return ins.greet.call();
}).then(function (value) {
console.log(value);
});
運行
$ node main.js
{ tx: '0x887d1043feb6f1e65bd90c71840b6b8fe8b2eea6ac19ad82dbd3c61c8eccae4c',
receipt:
{ transactionHash: '0x887d1043feb6f1e65bd90c71840b6b8fe8b2eea6ac19ad82dbd3c61c8eccae4c',
transactionIndex: 0,
blockHash: '0x323b5d22dbea9f4d7c1e70da5a0dc2b4b96f453afd6a3ae80c989470804c6562',
blockNumber: 17,
gasUsed: 33090,
cumulativeGasUsed: 33090,
contractAddress: null,
logs: [],
status: 1 },
logs: [] }
//greet()方法輸出內容
hello
因為ins.setGreeting ()
方法會改變區(qū)塊鏈狀態(tài)典徘,所以需要消耗gas
蟀苛,同時在調用的時候返回對應的交易狀態(tài)結果。