Truffle 2.0升級3.0升級指南
備註:這個指南同樣適用於從beta 3.0.0-9
升級到3.0.1
的使用者。
介紹
3.0
版本引入了大量的新特性,這些特性為我們帶來了大量的重要革新性變化。讓我們的network
的管理更簡單,新的抽象的合約層,允許你從第三方引入各種依賴檔案。伴隨以太坊的開發工具逐步成熟,我們認為這樣的革新非常有價值。下面我們將一步步指引你來享受這些新特性帶來的好處。
為了展示2.0到3.0版本的變化,後續會使用下面示例這種對比的方式。
v2.0
// 2.0版本程式碼
v3.0
// 3.0版本程式碼
先說最重要的:配置(Configuration)
Truffle 2.0中我們使用了一個不舒服的配置方式。你不僅可以使用一個default
,匿名的網路設定(通過rpc
配置項);同時你也可以使用命名的網路設定,比如ropsten
,或者live
。由此帶來的一個後果是,你可能會無意中覆蓋了網路配置,或者部署到錯誤的網路。在Truffle 3.0中,我們解決了這個問題,代價是對配置方式的調整。
在2.0版本中,一個命名網路的宣告方式示例如下:
module.exports = {
rpc: {
host: "localhost",
port: 8545
},
networks: {
staging: {
host: "localhost",
port: 8546,
network_id: 1337
},
ropsten: {
host: "158.253.8.12",
port: 8545,
network_id: 3
}
}
};
在3.0中,我們改為了下述的方式。
module.exports = {
networks: {
development: {
host: "localhost",
port: 8545,
network_id: "*"
},
staging: {
host: "localhost",
port: 8546,
network_id: 1337
},
ropsten: {
host: "158.253.8.12",
port: 8545,
network_id: 3
}
}
};
變化點如下:
- 預設網路配置項
rpc
被移除了。取而代之的是在networks
配置項下的一個專門的名為development
的網路配置項。development
中會指定的ip
和port
,和配置的網路型別1,預設是任意*
。 - 如果沒有指定網路,在執行
migrate
等命令時預設使用名為development
的網路。 - 為了避免出現部署到錯誤網路的情況,你也可以完全移除配置項
development
。如果已經移除development
的網路配置,但在truffle migrate
等命令時不指定網路會有下述錯誤發生:
$ truffle migrate
Compiling ./contracts/ConvertLib.sol...
Compiling ./contracts/MetaCoin.sol...
Compiling ./contracts/Migrations.sol...
Writing artifacts to ./build/contracts
Error: No network specified. Cannot determine current network.
at Object.detect (/usr/local/lib/node_modules/truffle/lib/environment.js:27:23)
at /usr/local/lib/node_modules/truffle/lib/commands/migrate.js:33:19
at /usr/local/lib/node_modules/truffle/lib/contracts.js:51:11
at /usr/local/lib/node_modules/truffle/lib/contracts.js:83:9
如果要指定網路,如ropsten
,使用命令:
truffle migrate --network ropsten
另外每個網路配置項,都需要指定一個網路ID1,這可以算是一種安全機制來保證部署的安全性,來保證一定是部署到你想要部署的網路。development
這樣的網路環境,可以使用*
來表示任意,以方便調測。
移植和測試依賴(Migrations and Test Dependencies)
在沒有引入包管理前,Truffle可以假設所有你寫的智慧合約都是需要移植和測試的。在有了包管理之後,由於依賴可以來自多個不同的地方,我們不再進行預設關聯,如果需要關聯,你必須明確指定。以減少自動關聯帶來的潛在問題。下面來看一個migration(移植)
的手動引入關聯的例子。
2.0版本中的./migrations/2_deploy_contracts.js
module.exports = function(deployer) {
deployer.deploy(ConvertLib);
deployer.autolink();
deployer.deploy(MetaCoin);
};
3.0版本中的./migrations/2_deploy_contracts.js
var ConvertLib = artifacts.require("ConvertLib.sol");
var MetaCoin = artifacts.require("MetaCoin.sol");
module.exports = function(deployer) {
deployer.deploy(ConvertLib);
deployer.link(ConvertLib, MetaCoin);
deployer.deploy(MetaCoin);
};
改進之處如下:
- 我們提供了
artifacts.require()
方法,類似Node.js
的require()
語句,用於宣告依賴。 - 你可以通過
artifacts.require()
來引入一個本地的Solidity檔案。或者是包中依賴路徑,這個方法將負責引入對應的檔案。 Javascript
中的測試用例也需要通過artifacts.require()
語句來引入依賴。
Migrations
(移植)不再提供autolink
(自動關聯)
正如上一部分所述,自動關聯為依賴問題的解決帶來了一點點方便。但隨著包管理的引入,我們不再可能自動判斷在你的移植中所真正需要的所有的依賴。我們提供了替代方案是,通過明確指定的方式來關聯你的庫。可以參考上一節的artifacts.require()
例子。
合約抽象:JSON格式(不再使用.sol.js
!)
Truffle之前將合約定義為Javascript的格式,以.sol.js
為字尾的檔案儲存。存為這樣的格式的考慮,主要是打算你可以在任何地方容易的使用。但最終發現,我們考慮的並不完善。不僅Javascript中存在一些情況中難以直接使用,更在非Javascript環境完全不可用。為解決這樣的侷限性,Truffle3.0將所有合約編譯後的結果存為JSON
格式,以能隨時隨地的,跨環境使用。
如果你已經使用Truffle2.0生成了許多的檔案,我們提供了一個工具來進行轉換。
如果你要升級Truffle2.0生成的.sol.js
,請先安裝truffle-soljs-updater
$ npm install -g truffle-soljs-updater
安裝好後,你可以通過sjsu
命令來使用這個工具。使用方法如下:
$ cd ./build/contracts
$ sjsu
Converting ConvertLib.sol.js...
Converting MetaCoin.sol.js...
Converting Migrations.sol.js...
Files converted successfully.
具體使用方法是,進入到你的.sol.js
檔案所在目錄,這裡是./build/contracts
。然後執行sjsu
即可。
預設情況下sjsu
命令只會建立新格式的.json
字尾結尾的檔案,並不會刪除你的原始檔案,你需要手動刪除舊的.sol.js
來保證Truffle3.0能正常工作。請注意,建議刪除前將舊的.sol.js
的檔案備份到其它地方。最終確認生成的.json
檔案正確的情況下再刪除。
另外一種選擇是使用強制模式,sjsu -f
,通過加-f
引數,這樣sjsu
會刪除舊的.sol.js
檔案,並生成生的.json
檔案。但請務必保證舊的檔案已提前進行了妥善的儲存,以避免造成不必要的損失。
$ cd ./build/contracts
//務必保證你已經備份了舊的`.sol.js`檔案
//`-f`引數會強制刪除舊的`.sol.js`檔案
$ sjsu -f
Converting ConvertLib.sol.js...
Converting MetaCoin.sol.js...
Converting Migrations.sol.js...
Files converted successfully.
Successfully deleted old .sol.js files.
合約互動抽象層: .deployed()
現在提供了then()
這個改變,會影響你的Migrations
(移植),測試,應用程式碼
在Truffle2.0中,合約抽象層使用原生的方式來管理網路。提供上面章節中提到的default
的方式,引發潛在的網路不正確的可能,導致可能的部署到錯誤的網路的問題。
原抽象層提供了一個精心考慮,方便使用的語法,MyContract.deployed().myFunction(...)
,但將錯誤直接暴露給了開發者。在Truffle3.0中,我們改變了這個語法,為.deployed()
提供了類似promise
的語法。同時,當前的合約抽象層可以與以太坊的包管理標準,EIP190
eip190,進行無縫整合。但這意味著大家必須改變原有程式碼的語法。
v2.0版本的語法:
MyContract.setProvider(someWeb3Provider);
MyContract.deployed().someFunction().then(function(tx) {
});
v3.0版本的語法:
MyContract.setProvider(someWeb3Provider);
MyContract.deployed().then(function(instance) {
return instance.someFunction();
}).then(function(result) {
});
語法上有些囉嗦,但目的是保證合約抽象層連線到了正確的網路。
我們來看看新語法的例子:
MyContract.setProvider(someWeb3Provider);
var deployed;
MyContract.deployed().then(function(instance) {
deployed = instance;
return deployed.someFunction();
}).then(function(result) {
return deployed.anotherFunction();
}).then(function(result) {
});
這裡需要注意的是
- 如果合約方法
f()
不會改變區塊鏈上的資料的,那麼呼叫時要使用instance.f.call()
。 - 如果合約方法
f()
會改變區塊鏈上的資料的,則需使用instance.f()
來進行呼叫。 - 如果你想在一個
promise
鏈中呼叫多個方法,需要注意示例中的instance
的作用域。可以在外部定義一個物件,檢視上例中var deployed;
的定義。
一個能跑通的完整例子參考附錄2。
合約抽象層:交易結果物件
大家一直以來有個麻煩的事,關於在Web3
中監聽事件。在大多數情況下,事件一般不是通過主動跟蹤事件,而是我們進行了對應的操作,從而引發對應的事件產生。
儘管主動監聽事件的方式仍然支援,但為了讓後一種情況實現起來更加簡單,我們調整了transaction
的返回結果。
在Truffle2.0版本中,transaction
簡單的返回了一個交易的雜湊串,而在Truffle3.0中,我們將返回一個包含交易詳情的結果物件2。
v2.0
MyContract.deployed().someFunction().then(function(tx) {
});
v3.0
MyContract.deployed().then(function(instance) {
deployed = instance;
return deployed.someFunction();
}).then(function(result) {
//
});
在Truffle3.0中通過返回transaction
的詳情資訊,我們可以更加方便的決定我們是否要觸發某些相應的行為。下面是一個假想的關注合約釋出事件的例子。
var assert = require("assert");
var PackageIndex = artifacts.require("PackageIndex.sol");
contract("PackageIndex", function(accounts) {
it("publishes a release correctly", function() {
return PackageIndex.deployed().then(function(deployed) {
return deployed.publish("v2.0.0");
}).then(function(result) {
var found_published_event = false;
for (var i = 0; i < result.logs.length; i++) {
var log = result.logs[i];
if (log.event == "ReleasePublished") {
found_published_event = true;
break;
}
}
assert(found_published_event, "Uh oh! We didn't find the published event!")
});
});
});
雖然這樣的話,我們需要在所有返回結果中,去找我們感興趣的事件,但也許是比PackageIndex.ReleasePublished.watch(...)
更好的一種方式,因為我們可以在當前的程式碼中管理事件邏輯,而不是分散在程式碼各處。
一個能跑通的完整例子參考附錄2。
構建流:預設不再需要構建器
Truffle1.0和Truffle2.0中,我們將Web應用與整個框架緊緊的捆綁在一起。所以Truffle打包提供了一個預設的構建流,以便你可以快速的建立你的dapp
,並執行起來。雖然在有些情況下,這帶來了極大的便利,但在其它的場景下卻顯得極為雞肋。
去年中,基於以太坊的應用持續的在增加。從開始的僅僅支援Web
的dapp
應用,發展為可以支援原生語言,在手機或電腦上獨立執行。支援各種各樣的使用者場景,一直是Truffle的初衷,所以我們決定移除預設的構建流。如果你想使用Truffle來整合你的應用,你仍然可以編寫自定義的構建流3,因為Truffle打算專注做智慧合約相關的最好用工具。所以關於構建,通過整合更好工具,如webpack
,browserify
,Grunt
,Metalsmith
,來實現。
儘管構建流預設被移除了,但並不意味著你沒得選擇。在Truffle中我們非常注重開發者的使用體驗,也永遠不會對大家棄之不顧,所以下面我們提供了兩種可選方式,後一種選擇會讓你深度繫結到你最終選擇的構建工具上,如webpack
。我們來一起看看,可用的選擇吧。
在Truffle3.0中使用舊的構建器
如果你在Truffle2.0中使用了預設的構建器,而你又想升級到Truffle3.0。我們升級了預設構建器4,所以它完全可以與Truffle3.0相容。但這將是最後一次升級預設的構建器,因為要使之相容所有的場景,將是一件工程非常複雜的事。所以我們推薦你最終選用後面提到的其它構建系統。
預設構建器,並未整合在Truffle3.0中。所以要使用它,你需要安裝truffle-default-builder
,並做為一個依賴進行引入。在你的工程目錄執行下面的命令:
$ npm install truffle-default-builder --save
一旦安裝,你可以在你的truffle.js
配置檔案中,使用預設構建器。我們來看看配置檔案的前後變化。
v2.0:Truffle.js
module.exports = {
build: {
"index.html": "index.html",
"app.js": [
"javascripts/app.js"
],
"app.css": [
"stylesheets/app.css"
],
"images/": "images/"
},
rpc: {
host: "localhost",
port: 8545
}
};
v3.0: truffle.js
var DefaultBuilder = require("truffle-default-builder");
module.exports = {
build: new DefaultBuilder({
"index.html": "index.html",
"app.js": [
"javascripts/app.js"
],
"app.css": [
"stylesheets/app.css"
],
"images/": "images/"
}),
networks: {
development: {
host: "localhost",
port: 8545,
network_id: "*" // Match any network id
}
}
};
你會發現,除了需要引入作為依賴的預設構建器包,放入構建器需要的配置檔案以外。其它是完全一致的。
由於預設構建器已經使用了最新的合約抽象層5。所以上面提到的所有版本升級需要進行的調整,都適用使用預設構建器。
使用自定義構建流程/構建工具
自定義構建流程並沒有想像中難以使用,真正的難點在於寫一個構建流程能相容各種各樣的構建需求。我推薦你去看看適合你自己專案的構建工具,比如之前提及的webpack
,browserify
,Grunt
,Metalsmith
。最終哪個的特效能滿足你的需要,需要視你的專案及構建需求來定。
無論你想構建一個瀏覽器應用,命令列工具,JS庫,還是原生 的手機應用。合約的初始化,部署合約的使用均遵循通用的流程。
當你配置你的自定義工具或應用時,應遵循下述的流程:
- 編譯合約檔案,將生成的
.json
結果放到./build/contracts
目錄下。 - 通過
truffle-contract
5,將你編譯的合約結果,轉為合約抽象層,來方便你的使用。 - 為你的合約抽象層設定
web3 provider
。需要注意的是在Metamask
和Mist
中,環境內會自動提供。但在其它情況下,你需要手動通過配置完成指定。
下面是整合NodeJS
的一個例子:
//1. 引入編譯好的合約檔案結果
var json = require("./build/contracts/MyContract.json");
// 2. 將合約轉為合約抽象層例項
var contract = require("truffle-contract");
var MyContract = contract(json);
// 3. 設定合約抽象層例項的web3 provider
MyContract.setProvider(new Web3.providers.HttpProvider("http://localhost:8545"));
// 4. 現在你可以使用啦
MyContract.deployed().then(function(deployed) {
return deployed.someFunction();
});
所有的構建流程,均遵循上述的流程。核心關注點是保證自定義流程要載入所有的合約資源,並正確的設定合約抽象層。
一個能跑通的完整例子參考附錄2。
關於network_id的配置項說明,參考這裡 https://github.com/ethereum/go-ethereum/wiki/Command-Line-Options。 ↩
編寫你自己的構建流: http://truffleframework.com/tutorials/upgrading-from-truffle-2-to-3 ↩
Truffle的預設構建器 https://github.com/trufflesuite/truffle-default-builder ↩
Truffle的合約抽象層,即執行框架工具包 https://github.com/trufflesuite/truffle-contract ↩
相關文章
- Zurmo – – 升級指南
- Conflux Truffle 使用完全指南UX
- Vue 3.0 升級指南Vue
- HTTPS 升級指南HTTP
- iview 升級指南 —— MenuItem 篇ViewUI
- Polymer 1.0 升級指南
- ABP Framework 手動升級指南:從6.0.1升級到7.0.0Framework
- Oracle 12c升級指南Oracle
- 輕量級orm框架——gzero指南ORM框架
- babel 7 簡單升級指南Babel
- Laravel 8 升級指南搶先看Laravel
- 入門級TRIZ使用指南
- spring 4 升級踩雷指南Spring
- nsight 初級使用指南
- Gamasutra:頂級遊戲坑錢指南GAM遊戲
- 服務端指南 | 微服務初級設計指南服務端微服務
- SSL伺服器配置評級指南伺服器
- 精讀《webpack4.0 升級指南》Web
- linux系統升級指南(轉)Linux
- Hexo6 升級踩坑指南Hexo
- 極狐GitLab Runner 升級指南!Gitlab
- Truffle框架框架
- [譯] ESLint v4.0.0 升級指南EsLint
- 保姆級教程!玩轉 ChunJun 詳細指南
- React 同構應用 PWA 升級指南React
- Windows安全指南之域級別策略(轉)Windows
- 等保2.0|您要的定級指南來啦
- Java工程師學習指南(初級篇)Java工程師
- Java工程師學習指南(中級篇)Java工程師
- kubernetes 1.14 升級安裝指南
- Java工程師學習指南 初級篇Java工程師
- Java工程師學習指南 中級篇Java工程師
- [分享]個人電腦初級防黑指南(轉)
- Truffle實踐
- 以太坊Solidity程式語言開發框架————16、Truffle命令指南Solid框架
- 微軟送出一個升級指南:敦促Win7使用者升級Win10微軟Win7Win10
- 海思hi3536 PCIE級聯應用指南
- SRE 實用指南:事件嚴重性級別 - rootly事件