イーサリアムのノードとの通信の際にJSON形式でのやりとりを簡素化してくれるのがWeb3.js
<script language="javascript" type="text/javascript" src="web3.min.js"></script>
自分自身でノードを持たなくてもイーサリアムブロックチェーンにメッセージを送受信してくれるサービス、それがinfura。
infuraをweb3プロバイダとして使う宣言をする
var web3 = new Web3(new Web3.providers.WebsocketProvider("wss://mainnet.infura.io/ws"));
そして、DAppで複数ユーザーが使用することを想定した時に、ユーザーの秘密鍵をどのように管理するかの解として、Metamaskの紹介をしてくれている。
MetamaskはChromeとFirefoxの拡張機能。
イーサリアムと通信を行うサイトでweb3プロバイダを持つかを常にチェックするjavascriptを埋め込んでおく。
window.addEventListener('load', function() {
// Web3がブラウザにインジェクトされているかチェック (Mist/MetaMask)
if (typeof web3 !== 'undefined') {
// Mist/MetaMaskのプロバイダの使用
web3js = new Web3(web3.currentProvider);
} else {
// ユーザーがweb3を持たない場合の対処。
// アプリを使用するためにMetamaskをインストールするよう
// 伝えるメッセージを表示。
}
// アプリのスタート&Web3.jsへの自由なアクセスが可能に:
startApp()
})
コントラクトABI
レッスン6はまだまだ新しいのが出てくる。ABIはWeb3.jsがイーサリアムコントラクトの関数群へのアクセス方法をJSON形式で定義したもの。ABIはSolidityコンパイラで勝手に出来上がる?
// myContractをインスタンス化
var myContract = new web3js.eth.Contract(myABI, myContractAddress);
これまでせっせとSolidityで書いたゾンビを扱うcontractの関数をクライアントからバシバシと呼び出していくレッスンが続く。
Call コントラクト上の view / pure 関数にアクセスする際のWeb3.js側の呼び出しメソッド。view / pure なのでブロックチェーン上のデータは更新されないのでガスも不要。
Send ブロックチェーン上のデータの変更要求。ガスの支払いを要求する必要があるので、必然的にMetamaskでの署名を強要する(署名なければ画面ポップアップする仕組み)
・Metamaskのアカウント切り替えに応じて、選択中アカウントが所有するゾンビを画面に再描画する。
・Metamaskを通じてsendして新しいゾンビを作成する(ブロックチェーンを変更する)。
・kittyを食わせて新しいゾンビを作成する
・Payable関数を使ってゾンビのレベルアップをする。この中でetherの最小単位であるWeiの扱いが照会される。1ether=10^18wei。Weiはとても小さい単位のようです。payableを使ってetherの送金料を指定する際はweiで指定する必ようがあるとのことで、以下の変換を使う必要があるとのこと。これきっちり守らないと事故起こしそう。
// これが1 ETHをWeiに変換してくれる
web3js.utils.toWei("1", "ether");
※サンプルのとおり"ether"指定するとエラーとなった。web3.jsのバージョンの違いかな?
・Eventの有用な使用方法。ブロックチェーンに書かなかったものもEventログを漁れば戦闘ログとして使える、とか。
このあたりはHTML+Javascriptの経験がないと厳しいかも。逆に知ってれば簡単。手探りだけど「ほうほう」という感じでなかなか楽しい。頭空っぽの状態でスラスラかけるようになるにはまだまだ練習はいりそうだけど、基本やりたいことを積み重ねてコードにしていくだけ、ではある。
レッスン6の内容はCryptoZombiesの学習サイトではなく、自前で実装してやってみるほうがよさそうだしその手引きを最終チャプターでちゃんと紹介してくれいている。これは後程必ず試したいと思っている。
画面描画にかかわるサンプル実装していてその結果が具体的に見えないのはちょっと悲しかったから。
以下、クライアント側の自前実装のためのメモ
このレッスンは、あえて基本的なものとした。スマートコントラクトとやりとりするために必要なコアロジックお見せたかったが、コードのWeb3.js部分はかなり繰り返しが多く、完全に実装するのにあまりたくさんの時間を使いたくなかったし、これ以上レッスンをやって新しい概念を紹介するつもりはない。
だからこの実装は基礎的なものにした。以下は、お主が自分で構築を行う場合にフロントエンドにゾンビゲームを完全に実装させるための概念のチェックリストだ:
1.attackおよびchangeName、changeDna関数、そしてERC721のtransfer、 ownerOf、balanceOf関数などの実装。これらの関数の実装は、我々がやった他のsendトランザクションと同じだ。
2.setKittyContractAddressやsetLevelUpFee、さらにwithdrawを実行できる"管理者ページ"の実装。ここでもフロントエンドに特別なロジックはなく、これらの実装はすでに説明した関数と同じである。onlyOwner修飾子があるので、コントラクトをデプロイのと同じEthereumアドレスから呼び出したことを確認しなければならないだけだ。
3.アプリに実装したい異なった閲覧ページがいくつかある:
a. 特定のゾンビの情報を閲覧できる、パーマリンク付きの個別のゾンビのページ。このページはゾンビの外見を表し、その名前やオーナー(ユーザーのプロフィールページへのリンク付きで)、また勝敗のカウントやバトル履歴を表示する。
b. パーマリンクでユーザーのゾンビ軍団を見ることができるユーザーページ。個別のゾンビをクリックしてページを表示し、またユーザーがMetaMaskにログイン済みでゾンビ軍隊を所有している場合は、そのクリックすることでそのゾンビを攻撃することになる。
c. 現在のユーザーのゾンビ軍団を表示するホームページ。ユーザーページのバリエーションとして(これは我々がindex.htmlで実装を開始したページだ)。
4.ユーザーがCryptoKittiesを捕食できるようにするUIのメソッド。ホームページ上の各ゾンビに「Feed Me」と表示するボタンをつけ、それをクリックするとユーザーにキティのIDを入力するよう要求するテキストボックスを作ればよい(またはキティのURL。例: https://www.cryptokitties.co/kitty/578397)。これでfeedOnKitty関数のトリガーを引く。
5.別のユーザーのゾンビを攻撃するための、ユーザー向けUIのメソッド。
この実装方法の1つとして、ユーザーが別のユーザーのページを閲覧している時に「このゾンビを攻撃する」ボタンがあるとよい。 ユーザーがボタンをクリックすると、そのユーザーのゾンビ軍団を含むモーダルがポップアップし「どのゾンビで攻撃しますか?」と促す。
6.ユーザーのホームページには、各ゾンビに「ゾンビを攻撃する」というボタンをつけることもできる。ユーザーがそれをクリックするとモーダルの検索フィールドが表示されるので、ゾンビのIDを入力して検索する。または「ランダムなゾンビを攻撃する」というオプションで、ランダムな番号を検索する。
またクールダウン期間が経過していないユーザーのゾンビをグレーアウトして、そのゾンビではまだ攻撃ができないことと、どれくらい待たなければならないかをUIでユーザーに示すこともできる。
7.ユーザーのホームページには、ゾンビごとに名前の変更、DNAの変更、レベルアップ(有料)のオプションもある。ユーザーがまだ十分なレベルでない場合、オプションはグレーアウトされる。
新規ユーザーの場合、最初のゾンビをゾンビ軍団の中に作成するよう促すメッセージを表示し、createRandomZombie()関数を呼び出す必要がある。
8.最後のチャプターで説明したように、Attackイベントと一緒に、ユーザーのaddressをindexedプロパティとしてスマートコントラクトに追加したい。こうしてリアルタイム通知をの作成が可能になる — ユーザーのゾンビ1体が攻撃されたときにポップアップアラートを表示できるので、彼らは攻撃したユーザーやゾンビを閲覧して反撃することができる。
9.同一データへのリクエストでInfuraを常に使うわけではないから、ある種のフロントエンドキャッシュレイヤーを実装したい。(現在のdisplayZombiesの実装は、インターフェースをリフレッシュするたびにゾンビごとにgetZombieDetailsを呼び出すが、実際は軍団に追加された新しいゾンビに対してこの関数を呼び出す必要がある)。
10.リアルタイムのチャットルーム。これでゾンビ軍団を倒す時に、所有者のプレーヤーたちに話しかけられるぞ?Yes、プリーズ!
これはスタートに過ぎない。これはすでに大きなリストだが、我々はもっと多くの機能を思いつくはずだ。
HTML、CSS、JavaScript、ReactやVue.jsのようなフレームワークなど、完全なインターフェイスを作成していくための多くのフロントエンドコードが存在するから、このフロントエンド全体を構築するのはおそらくそれだけで10レッスンのフルコースとなってしまう。だからかっこよく実装をするのはお主の宿題だ。
注: スマートコントラクトは分散されていますが、DAppとやりとりするためのこのフロントエンドは、どこかのWebサーバーに完全に集約化されます。
しかし Loom Networkで開発中のSDKを使って、もうすぐ集中化されたウェブサーバーの代わりに専用のDAppチェーンからこういったフロントエンドを提供することができるようになります。こうしてイーサリアムとLoom DAppチェーン間で、あなたのアプリは100%ブロックチェーン上で動くことになります。
いよいよ次のレッスン7ではイーサリアムへのスマートコントラクトのデプロイを扱うとのこと。これが公開されればテストアプリが乱立するでしょう、私も乗っかっていきたいと思っています。