javascript
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/docsCommands:Compile: truffle compileMigrate: truffle migrateTest: 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 definedat 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.jsReplacing Migrations...Migrations: 0xdc59c5de4e7b1dcf23f864425a704020e53666b5 Saving successful migration to network... Saving artifacts... Running migration: 2_deploy_contracts.jsReplacing ConvertLib...ConvertLib: 0x19cf958fede2e0f082cbcf5629f1a1344b221bf3Linking ConvertLib to MetaCoinReplacing MetaCoin...MetaCoin: 0x39073d502491f57537f999584071691d19cf5f24Replacing 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:56contract.abi.filter(function (json) {^TypeError: Cannot read property 'filter' of undefinedat 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 [4] 。
語法注意
對于新的Truffle3.0語法,需要注意的是函數調用方式要遵循調用規則 [3] 。對于一個不會改寫區塊鏈狀態的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: [] }參考資料
[1] : Truffle contract的github地址及文檔: https://github.com/trufflesuite/truffle-contract
[2] : 5. 移植詳解
[3] : 合約交互詳解
[4] : 關于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
原文地址:https://bitshuo.com/topic/58e2552c9a87f1a331fa292b
總結
以上是生活随笔為你收集整理的Truffle3.0集成NodeJS并完全跑通(附详细实例,可能的错误)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 智能合约调用示例
- 下一篇: 以太坊虚拟机EVM的缺陷与不足