摘要:首先我們需要要記住,以太坊是由共享同一份數(shù)據(jù)的相同拷貝的節(jié)點(diǎn)構(gòu)成的。你可以運(yùn)行你自己的以太坊節(jié)點(diǎn)來(lái)作為。在你部署智能合約以后,它將獲得一個(gè)以太坊上的永久地址。如果你還記得第二課,在以太坊上的地址是。
通過(guò)前邊的學(xué)習(xí),DApp 的 Solidity 合約部分就完成了。現(xiàn)在我們來(lái)做一個(gè)基本的網(wǎng)頁(yè)好讓你的用戶能玩它。 要做到這一點(diǎn),我們將使用以太坊基金發(fā)布的 JavaScript 庫(kù) —— Web3.js.一、Web3.js簡(jiǎn)介 什么是 Web3.js?
還記得么?以太坊網(wǎng)絡(luò)是由節(jié)點(diǎn)組成的,每一個(gè)節(jié)點(diǎn)都包含了區(qū)塊鏈的一份拷貝。當(dāng)你想要調(diào)用一份智能合約的一個(gè)方法,你需要從其中一個(gè)節(jié)點(diǎn)中查找并告訴它:
1、智能合約的地址
2、你想調(diào)用的方法,以及
3、你想傳入那個(gè)方法的參數(shù)
以太坊節(jié)點(diǎn)只能識(shí)別一種叫做 JSON-RPC 的語(yǔ)言。這種語(yǔ)言直接讀起來(lái)并不好懂。當(dāng)你你想調(diào)用一個(gè)合約的方法的時(shí)候,需要發(fā)送的查詢語(yǔ)句將會(huì)是這樣的:
// 哈……祝你寫所有這樣的函數(shù)調(diào)用的時(shí)候都一次通過(guò) // 往右邊拉…… ==> {"jsonrpc":"2.0","method":"eth_sendTransaction","params":[{"from":"0xb60e8dd61c5d32be8058bb8eb970870f07233155","to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","gas":"0x76c0","gasPrice":"0x9184e72a000","value":"0x9184e72a","data":"0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"}],"id":1}
幸運(yùn)的是 Web3.js 把這些令人討厭的查詢語(yǔ)句都隱藏起來(lái)了, 所以你只需要與方便易懂的 JavaScript 界面進(jìn)行交互即可。
你不需要構(gòu)建上面的查詢語(yǔ)句,在你的代碼中調(diào)用一個(gè)函數(shù)看起來(lái)將是這樣:
CryptoZombies.methods.createRandomZombie("Vitalik Nakamoto") .send({ from: "0xb60e8dd61c5d32be8058bb8eb970870f07233155", gas: "3000000" })
我們將在接下來(lái)的幾章詳細(xì)解釋這些語(yǔ)句,不過(guò)首先我們來(lái)把 Web3.js 環(huán)境搭建起來(lái)
準(zhǔn)備工作取決于你的項(xiàng)目工作流程和你的愛(ài)好,你可以用一些常用工具把 Web3.js 添加進(jìn)來(lái):
// 用 NPM npm install web3 // 用 Yarn yarn add web3 // 用 Bower bower install web3 // ...或者其他。
甚至,你可以從 github直接下載壓縮后的 .js 文件 然后包含到你的項(xiàng)目文件中:
因?yàn)槲覀儾幌胱屇慊ㄌ嘣陧?xiàng)目環(huán)境搭建上,在本教程中我們將使用上面的 script 標(biāo)簽來(lái)將 Web3.js 引入。
實(shí)戰(zhàn)演練新建一個(gè)HTML 項(xiàng)目空殼 —— index.html。假設(shè)在和 index.html 同個(gè)文件夾里有一份 web3.min.js
使用上面的 script 標(biāo)簽代碼把 web3.js 添加進(jìn)去以備接下來(lái)使用。
index.html
二、Web3提供者CryptoZombies front-end
現(xiàn)在我們的項(xiàng)目中有了Web3.js, 來(lái)初始化它然后和區(qū)塊鏈對(duì)話吧。
首先我們需要 Web3 Provider.
要記住,以太坊是由共享同一份數(shù)據(jù)的相同拷貝的 節(jié)點(diǎn) 構(gòu)成的。 在 Web3.js 里設(shè)置 Web3 的 Provider(提供者) 告訴我們的代碼應(yīng)該和 哪個(gè)節(jié)點(diǎn) 交互來(lái)處理我們的讀寫。這就好像在傳統(tǒng)的 Web 應(yīng)用程序中為你的 API 調(diào)用設(shè)置遠(yuǎn)程 Web 服務(wù)器的網(wǎng)址。
你可以運(yùn)行你自己的以太坊節(jié)點(diǎn)來(lái)作為 Provider。 不過(guò),有一個(gè)第三方的服務(wù),可以讓你的生活變得輕松點(diǎn),讓你不必為了給你的用戶提供DApp而維護(hù)一個(gè)以太坊節(jié)點(diǎn)— Infura.
InfuraInfura 是一個(gè)服務(wù),它維護(hù)了很多以太坊節(jié)點(diǎn)并提供了一個(gè)緩存層來(lái)實(shí)現(xiàn)高速讀取。你可以用他們的 API 來(lái)免費(fèi)訪問(wèn)這個(gè)服務(wù)。 用 Infura 作為節(jié)點(diǎn)提供者,你可以不用自己運(yùn)營(yíng)節(jié)點(diǎn)就能很可靠地向以太坊發(fā)送、接收信息。
你可以通過(guò)這樣把 Infura 作為你的 Web3 節(jié)點(diǎn)提供者:
var web3 = new Web3(new Web3.providers.WebsocketProvider("wss://mainnet.infura.io/ws"));
不過(guò),因?yàn)槲覀兊?DApp 將被很多人使用,這些用戶不單會(huì)從區(qū)塊鏈讀取信息,還會(huì)向區(qū)塊鏈 寫 入信息,我們需要用一個(gè)方法讓用戶可以用他們的私鑰給事務(wù)簽名。
注意: 以太坊 (以及通常意義上的 blockchains )使用一個(gè)公鑰/私鑰對(duì)來(lái)對(duì)給事務(wù)做數(shù)字簽名。把它想成一個(gè)數(shù)字簽名的異常安全的密碼。這樣當(dāng)我修改區(qū)塊鏈上的數(shù)據(jù)的時(shí)候,我可以用我的公鑰來(lái) 證明 我就是簽名的那個(gè)。但是因?yàn)闆](méi)人知道我的私鑰,所以沒(méi)人能偽造我的事務(wù)。
加密學(xué)非常復(fù)雜,所以除非你是個(gè)專家并且的確知道自己在做什么,你最好不要在你應(yīng)用的前端中管理你用戶的私鑰。
不過(guò)幸運(yùn)的是,你并不需要,已經(jīng)有可以幫你處理這件事的服務(wù)了: Metamask.
MetamaskMetamask 是 Chrome 和 Firefox 的瀏覽器擴(kuò)展, 它能讓用戶安全地維護(hù)他們的以太坊賬戶和私鑰, 并用他們的賬戶和使用 Web3.js 的網(wǎng)站互動(dòng)(如果你還沒(méi)用過(guò)它,你肯定會(huì)想去安裝的——這樣你的瀏覽器就能使用 Web3.js 了,然后你就可以和任何與以太坊區(qū)塊鏈通信的網(wǎng)站交互了)
作為開發(fā)者,如果你想讓用戶從他們的瀏覽器里通過(guò)網(wǎng)站和你的DApp交互(就像我們?cè)?CryptoZombies 游戲里一樣),你肯定會(huì)想要兼容 Metamask 的。
注意: Metamask 默認(rèn)使用 Infura 的服務(wù)器做為 web3 提供者。 就像我們上面做的那樣。不過(guò)它還為用戶提供了選擇他們自己 Web3 提供者的選項(xiàng)。所以使用 Metamask 的 web3 提供者,你就給了用戶選擇權(quán),而自己無(wú)需操心這一塊。使用Metamask的web3提供者
Metamask 把它的 web3 提供者注入到瀏覽器的全局 JavaScript對(duì)象web3中。所以你的應(yīng)用可以檢查 web3 是否存在。若存在就使用 web3.currentProvider 作為它的提供者。
這里是一些 Metamask 提供的示例代碼,用來(lái)檢查用戶是否安裝了MetaMask,如果沒(méi)有安裝就告訴用戶需要安裝MetaMask來(lái)使用我們的應(yīng)用。
window.addEventListener("load", function() { // 檢查web3是否已經(jīng)注入到(Mist/MetaMask) if (typeof web3 !== "undefined") { // 使用 Mist/MetaMask 的提供者 web3js = new Web3(web3.currentProvider); } else { // 處理用戶沒(méi)安裝的情況, 比如顯示一個(gè)消息 // 告訴他們要安裝 MetaMask 來(lái)使用我們的應(yīng)用 } // 現(xiàn)在你可以啟動(dòng)你的應(yīng)用并自由訪問(wèn) Web3.js: startApp() })
你可以在你所有的應(yīng)用中使用這段樣板代碼,好檢查用戶是否安裝以及告訴用戶安裝 MetaMask。
注意: 除了MetaMask,你的用戶也可能在使用其他他的私鑰管理應(yīng)用,比如 Mist 瀏覽器。不過(guò),它們都實(shí)現(xiàn)了相同的模式來(lái)注入 web3 變量。所以我這里描述的方法對(duì)兩者是通用的。實(shí)戰(zhàn)演練
我們?cè)贖TML文件中的
標(biāo)簽前面放置了一個(gè)空的 script 標(biāo)簽。可以把這節(jié)課的 JavaScript 代碼寫在里面。
把上面用來(lái)檢測(cè) MetaMask 是否安裝的模板代碼粘貼進(jìn)來(lái)。請(qǐng)粘貼到以 window.addEventListener 開頭的代碼塊中。
index.html
CryptoZombies front-end