クリプトゾンビ cryptoZombies
イーサリウムでゲームを構築する方法が学べる無料オープンソーススクール クリプトゾンビ(cryptoZombies) チャプター 14: Web3.js学習時の覚書(memo)です。
Web3.js
web3.jsは、JavascriptがHTTP、IPC、またはWebSocketを使用してローカルまたはリモートのイーサリアムノードとやり取りできるライブラリです。
<script language="javascript" type="text/javascript" src="web3.min.js"></script> <script language="javascript" type="text/javascript" src="web3.js"></script>var cryptoZombies; function startApp() { var cryptoZombiesAddress = "YOUR_CONTRACT_ADDRESS"; cryptoZombies = new web3js.eth.Contract(cryptoZombiesABI, cryptoZombiesAddress); }Web3プロバイダのノードと通信(関数call)
これは非同期通信
cryptoZombies.methods.zombies(id).call()Web3.jsを使って123をパラメーターにする。
myMethodという名の関数を呼び出すトランザクションをsend。
myContract.methods.myMethod(123).send()Metamaskの使用
MetamaskはChromeとFirefoxのブラウザ拡張機能。 ユーザーのイーサリアム・アカウントと秘密鍵を安全に管理。 そのアカウントでWeb3.jsを使用しているウェブサイトとやりとりする
ユーザーがMetamaskをインストール済みかを検出
インストールしていなければMetamaskのインストールが必要だと伝える
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
Web3.jsがコントラクトにアクセスするために ABI が必要。
ABIとは、Application Binary Interfaceの略。 これはコントラクトのメソッドをJSON形式で表している。
(関数コールをコントラクトが理解できるにフォーマットする方法をWeb3.jsに提供。)
コントラクトをコンパイルする際、SolidityコンパイラがABIを提供。
コントラクトアドレスとABIをコピーして保存する必要あり。
コントラクトをデプロイするとコントラクトアドレスが決定。
Web3.jsコントラクトのインスタンス化
// myContractをインスタンス化
var myContract = new web3js.eth.Contract(myABI, myContractAddress);チャプター 14: Web3.js サンプルコード
// これがコントラクトにアクセスする方法だ: var abi = /* abi generated by the compiler */ var ZombieFactoryContract = web3.eth.contract(abi) var contractAddress = /* our contract address on Ethereum after deploying */ var ZombieFactory = ZombieFactoryContract.at(contractAddress) // `ZombieFactory`はコントラクトのpublic関数とイベントにアクセスできるようになったぞ。 // 入力テキストを取得する類のイベントのリスナーだ: $("#ourButton").click(function(e) { var name = $("#nameInput").val() // `createRandomZombie`関数を呼び出す部分だ: ZombieFactory.createRandomZombie(name) }) // `NewZombie`イベントをリッスンしてUIを更新する部分だ var event = ZombieFactory.NewZombie(function(error, result) { if (error) return generateZombie(result.zombieId, result.name, result.dna) }) // ゾンビのdnaを取得して画像を更新する部分だ function generateZombie(id, name, dna) { let dnaStr = String(dna) // 16桁未満の場合はDNAの先頭に0をつける部分だ while (dnaStr.length < 16) dnaStr = "0" + dnaStr let zombieDetails = { // 最初の2桁は頭の部分だ。頭部は7種類用意してあるから、%7して // 0から6の番号を取得したら、そこに1を足して1から7にするのだ。 // これを基にして、"head1.png" から"head7.png"までの // 画像ファイルを用意する部分だ: headChoice: dnaStr.substring(0, 2) % 7 + 1, // 次の2桁は目の部分だ。11種類用意してあるぞ: eyeChoice: dnaStr.substring(2, 4) % 11 + 1, // シャツの部分は6種類用意してある: shirtChoice: dnaStr.substring(4, 6) % 6 + 1, // 最後の6桁は色の部分だ。 CSSのフィルタを使用して更新できる。 // 360度の色相回転(hue-rotate)を使うぞ: skinColorChoice: parseInt(dnaStr.substring(6, 8) / 100 * 360), eyeColorChoice: parseInt(dnaStr.substring(8, 10) / 100 * 360), clothesColorChoice: parseInt(dnaStr.substring(10, 12) / 100 * 360), zombieName: name, zombieDescription: "A Level 1 CryptoZombie", } return zombieDetails }チャプター 15: Web3.js サンプルコード
var abi = /* abi generated by the compiler */ var ZombieFeedingContract = web3.eth.contract(abi) var contractAddress = /* our contract address on Ethereum after deploying */ var ZombieFeeding = ZombieFeedingContract.at(contractAddress) // ゾンビのIDと捕食したい子猫のIDをすでに持っているものとする。 let zombieId = 1; let kittyId = 1; // クリプトキティの画像を取得するにはweb APIに照会する必要がある。 // この情報はブロックチェーンにはない。ウェブサーバーにあるだけだ。 // もし全ての情報がブロックチェーン上に格納されていれば、サーバーの // 障害を心配することはなくなるがな。まぁこのゾンビゲームを気に入ってもらえなければ、 // APIを変更するか我々のアクセスをブロックするだけだ。問題ない ;) let apiUrl = "https://api.cryptokitties.co/kitties/" + kittyId $.get(apiUrl, function(data) { let imgUrl = data.image_url // 画像を表示する部分だ }) // ユーザーが子猫をクリックししたときの処理だ: $(".kittyImage").click(function(e) { // コントラクトの`feedOnKitty` メソッドを呼び出す ZombieFeeding.feedOnKitty(zombieId, kittyId) }) // コントラクトのNewZombieイベントをリッスンして表示できるようにする部分だ: ZombieFactory.NewZombie(function(error, result) { if (error) return // この関数はレッスン1でやったのと同じようにゾンビを表示するものだ: generateZombie(result.zombieId, result.name, result.dna) })