使用 Parity 的原生套件開發 DApp

Source: pixabay

本篇簡單介紹一下幾種主流 DApp 開發方式,並著重在 Parity 開發方式的介紹。這是公司開發過程草草的筆記,因此撰文目的是讓需要重新調查的讀者有些關鍵字可以參考,並沒有提供詳細範例。

目前幾種主流 DApp 開發方式

我只用過第三個,前面兩個只簡單看過

  • Truffle box: 整合了 create-react-app 、 Testrpc ,可以使用 React 開發,並且用 Truffle 架構對合約做測試。 Chen Yao-Hsin 有專文詳細介紹
  • Meteor Ethereum: 整合 Meteor 全端架構。可以重複使用 Mist 錢包、瀏覽器上面顯示地址、區塊高度的部件。
  • Parity: 也是基於 React 的架構,但使用一系列 Parity 專用的 npm 套件來和 Parity 全節點 Api 互動。

由於公司近期開發的 DApp 初期會優先考慮做在 Parity 上,因此研究了 Parity 的開發方式。

DApp 的資料邏輯

了解 DApp 的資料邏輯,有助於理解 Parity 套件的設計方式

資料取得

理想中的 DApp 要求使用者裝載全節點,資料的取得完全來自:

  • 鏈上:也就是同步在自己電腦上幾 10GB 的鏈資料。
  • 去中心化儲存服務如 ipfs or swarm :靜態資源如圖檔、 html、 JavaScript 等。
  • 可信任的 Chain Explorer:例如 Etherscan.io 或自製 Explorer 。

其中鏈上資料的特性與一般基於 HTTP 的網站不同。前者是狀態隨著區塊高度而變化,後者則是要設計每隔一段時間向伺服器詢問。

因此鏈資料很適合使用 Reactive 的設計。只要新區塊一到,畫面上的元件立刻反應出狀態的變化。前面的 Meteor 和 React 都具有這樣的性質。

但同樣是 React , Truffle box 並沒對 Web3js 再做包裝,資料同步的邏輯需要自行實作。 Parity 則是有新的類別來整資料同步的邏輯,理解上會累一點,但是理解後使用起來很方便。

資料更新

鏈資料的取得很容易,但更新麻煩些。要改變智能合約上的變數,必須對契約地址發一筆交易、交易擴散到網路、交易被礦工接收、礦工擴散新區塊、使用者同步到新區塊,整個狀態的變更才算完成。在以太坊上大概是個 10~20 秒的過程。

因此在使用者體驗的設計上,必須想辦法讓使用者在交易完成前之間能做其他事情。範例可參考 Parity 本身發交易的介面,或是在 Google Cloud Platform 開主機時的介面設計。

Parity 傳送交易時會在右下角顯示正在進行中的交易,使用者在交易完成前能做其他事

Parity 的原生套件

主要需要了解以下五個 npm 套件的作用。官方教材 有十個關卡,雖然有點小過時,但能夠了解五個套件的使用方式。另外, Parity Technologies Github 的幾個 dapp- 開頭的 repo 也是很好的學習範例。

js-api

和 Parity 節點 JSON API 互動的套件,姑且稱之 Web3 of parity。
在瀏覽器開發人員介面使用 window.parity.api.eth 觀察,記得如下圖切換到 127.0.0.1 。 因為 Dapp 上面有層 iframe 罩著。

在 jsx 中的使用方式
import { Api } from '@parity/parity.js';

oo7

基礎類別,用來保證綁定資料的持續更新。

Bond, TimeBond, tie

用法官網範例若不太好懂,可用下面這個例子供思考。假設要比對契約中的擁有者地址和目前預設帳號(下文 bonds 圖解釋)是否相同,很直覺會想寫成如下樣式。

this.contract.owner() === bonds.me

但這樣寫不會產生想要的結果 true 。因為兩者都是 TransformBond 物件。正確寫法要產生一個新 Bond:

this.ownerAndMe = Bond.all([this.contract.owner(), bonds.me]);

this.ownerAndMe.map(([owner, me]) => owner === me);

oo7-parity

bonds 幾乎是 web3 eth 的功能,可以取得鏈資料、帳號資料。可以布合約

詳細功能見 oo7-Parity-Reference

另外是 bonds 居然沒有佈需要初始化合約的函數。暫時解法:

oo7-react

ReactiveComponent 用來取代 React 的 Component ,讓 Bond 物件的值可以用 React 的 state 取得。

ReactiveComponent, Rspan, Rdiv, Ra, Rimg, Hash

契約吐出的物件都是 Bond ,擺在 Rspan 裡就會即時更新了
<Rspan>{this.contract.name() || ''}</Rspan>;

parity-reactive-ui

建立在 ReactiveComponent 之上, Parity 提供一些會大量重複使用的元件。以下複製貼上官方文件的,供參考。

Account 資訊類

  • `AccountIcon` (an identicon image for a given account);
  • `AccountLabel` (a full Semantic UI label for a given account);
  • `InlineAccount` (a simple display component for an account designed to flow in text);

交易狀態

  • `TransactButton` (a button which posts a transaction when clicked and displays the progress to the user);
  • `TransactionProgressLabel` (a full Semantic UI label for displaying the progress of a transaction);

輸入類

  • `BButton` (a Semantic UI derived `Button` that accepts Bonds for certain props);
  • `InputBond` (a Semantic UI derived `Input` component that accepts a Bond for its output);
  • `AddressInputBond` (an `InputBond`-like component for addresses);
  • `HashBond` (an `InputBond`-like component for 32 byte hashes);
  • `URLBond` (an `InputBond`-like component for URLs).

Parity 上 DApp 的設計建議

依照智能合約的設計,寫出相對應的 Component 。例如:

  • 你有 Cat 合約,就先設計一個 Cat Component
  • 裡面建構子使用 bonds.makeContract 取得契約物件。
  • Cat Component 實做各種函式把契約內的值做必要的轉換。
  • 之後前端工程師就能繼承 Cat Component 再設計出各種精美元件來使用。

參考資料