Truffle勉強日誌①まずはHello World
このブログをそのままやってみました。
基本的な流れはこのブログの通りにやれば良いので、補足的な情報を追加していければと思います。
詰まったところは、一通り、終えてlive-serverで起動しようとしても、MetaMaskと連動しないとhello-worldの文字が表示されませんでした。なんでかな?と思ったら、localhostをSafariで起動してしまい、MetaMaskと連動していなかったからです。
記事の中では下記のように説明されていますが、JavaScript初心者だと意味が分かりませんでした。
Metamask が有効なブラウザでページを開くと、グローバル領域に web3 オブジェクトが生成されます。名前の通り web3.js から生成されており、Metamask を介して Ethereum ネットワークと通信できる特殊な web3 オブジェクトになります。
window.onload = function() {
var contract = web3.eth.contract(abi).at(address);
contract.get((error, result) => {
document.getElementById("contract_result").textContent = result;
});
};
abiとaddressを食わせるとcotractというweb3オブジェクトが生成されます。はい、まずはオブジェクトの定義です。
JavaScript におけるオブジェクトはプロパティの集まりであり、プロパティは名前(あるいはキー)と値との関連付けから成り立っています。プロパティの値を関数にすることもでき、これはいわゆるオブジェクトのメソッドとなります。
JavaScriptでは、オブジェクトにキーとバリューを持たせたり、バリューに関数を入れることも出来ます。Pythonだと辞書型というデータの持ち方があり、キーとバリューを入れることが出来ます。登録したキーを呼ぶとバリューが出てきます。下記の例だと、var1がキーで"hello"がバリューです。
なので、object.var1()で"hello"を呼ぶことが出来ます。またobject.func()で関数も呼ぶことが出来ます。
var object = {
// var1 プロパティを登録
var1: "hello",
// func メソッドを登録
func: function() {
alert("world");
}
};
ということで、abiとaddressを食わせることでcotractというweb3オブジェクトを生成することが出来る、という意味がなんとなく分かると思います。そして、このオブジェクトはMetaMaskを通じて、Ethereumネットワークと通信して、スマートコントラクトを呼ぶことが出来るのです。
次にアロー関数を勉強しましょう。 「=>」こんなのが使われていますね。下記の記事が非常に分かりやすいです。
この記事を要約すると、JavaScriptの「this」の用法として、一つの関数の中に複数のオブジェクトを入れて同一の関数を呼び出しても、呼び出すオブジェクトによって、挙動が変わるが、アロー関数を使うと呼び出すオブジェクトを変えても挙動が変わらなくなることを説明しています。
次にgetElementByIdについてです。これはHTMLタグで指定したIDにマッチするドキュメント要素を取得するメソッドです。index.htmlで下記のように書きましたね。idに「contract_result」とあります。これを呼び出しているわけですね。
<!DOCTYPE html>
<html lang="ja">
<head>
<title>Ðapps - Hello World</title>
<script type="text/javascript" src="hello_world.js"></script>
</head>
<body>
<div id="contract_result">loading...</div>
</body>
</html>
さて、最後にtextContentです。これはwebページを表示した際の要素内容のテキスト内容を表します。getElementByIdでHTMLタグのIDを指定して、textContentでその中身、ここでは「loading...」を表示するということです。
続いて、詰まったのはテストの箇所です。下記のコードが分からない・・・
var HelloWorld = artifacts.require("HelloWorld");
contract('HelloWorld', function(accounts) {
describe('word method', function() {
var obj;
let str = "TestTest";
before(async function () {
obj = await HelloWorld.new();
});
it("should set new word", async function() {
await obj.set(str);
let result = await obj.get();
assert.equal(result, str);
});
});
});
まず、asyncとは、非同期関数を定義する関数宣言のことです。非同期ってなんやねん?という感じなんですが、JavaScriptは非同期処理(データベースに仕事を任せている間にJavaScript側での処理)が出来るのです。ただ非同期処理を複数行うと、「いつ」「どの」処理が行われるのか分かりづらくなります。そこで登場したのがPromiseという仕様です。thenメソッドとcatchメソッドというメソッドを使って、可読性を上げることが出来ます。詳しくは下記の記事に詳細が載っています。
Promiseを使うには、newを使ってインスタンスを作ってあげます。newは関数やクラスからインスタンス(実際に作ったもの)を作るときに使う演算子です。設計図(関数やクラス)から出来た、実際に作ってみたもの、というようなイメージで理解出来ます・・?記事は下記が分かりやすいです。
asyncと宣言することで、非同期関数を宣言し、Promiseを返すことが出来るのです。さて、async関数の下の行に今度はawaitというのがあります。
await HelloWorld.new()
これは、awaitで指定した関数のPromiseの結果が返されるまで、async function内の処理を一時停止することが出来ます。結果が返されたらasync内の関数を開始します。asyncとawaitを使えば、関数の実行の順番を指定することが出来るのですね。ここで言うと、まずはHelloWorldコントラクトを呼び出して、asyncで宣言した関数を処理させようとしているのですね。
asyncとawaitについては、こちらの記事が分かりやすいです。
そして、最後、hello_world.jsに更新ボタンが押されたらコントラクトを起動させる部分を書いている箇所。
window.onload = function() {
var contract = web3.eth.contract(abi).at(address);
contract.get((error, result) => {
document.getElementById("contract_result").textContent = result;
});
web3Local = new Web3(new Web3.providers.HttpProvider("http://localhost:7545"));
var eventContract = web3Local.eth.contract(abi).at(address);
eventContract.Set((error, data) => {
console.log("event callback.");
document.getElementById("contract_result").textContent = data.args.newWord;
});
document.getElementById("button_set").onclick = () => {
let time = Math.floor(new Date().getTime() / 1000);
console.log(time);
contract.set("" + time, (error, txid) => {
console.log(txid);
});
};
};
window.onloadの箇所はWindowオブジェクトのonloadイベントハンドラに、JavaScriptコードを登録しています。はい、意味が分かりません。そもそも、JavaScriptにはWindowオブジェクトというものがあり、JavaScriptコードが動作しているブラウザでドキュメントを表示するものになります。なので、このオブジェクトに入れてる関数を使って、set関数を呼び出して、Hello Worldから新しい文字を表示させることが出来るという訳です。
うーむ、やはりDapps作りたい、と意気込んでもJavaScriptが分からないと止まってしまいますね。まぁ少しずつでもいいから前に進んでいきましょう!!
この記事が気に入ったらサポートをしてみませんか?