概要
ハッカソンに向けて、web3.jsとMetamaskを使ってコントラクトと繋げようとしたときに、ぶち当たった問題とその自分なりの解決策を書いていこうと思う。
なお、当方プログラミング初心者なのでおかしな点があるかもしれないが、コメントいただけると助かる。
環境
geth 1.8.14
web3.js@0.20.0
metamask 4.16.0
Metamask経由であればrequire("web3")は必要ない
Metamaskでは自動的にWeb3インスタンスをインストールしてくれるので、下記のコード
var Web3 = require('web3');
var web3 = new Web3();
は必要ない。(Metamaskを使わない場合は必要)
Metamask前提であればこれを入れると、競合して動かなくなってしまう。
なので、このように置き換えれば動作する。
if (typeof web3 !== "undefined") {
web3js = new Web3(web3.currentProvider);
console.log("injecting web3js success");
} else {
console.log("Can NOT access to provider...");
window.alert("MetaMaskにアクセスできません");
return;
}
ローカル上ではMetamaskが動かない
file://
で始まってる場合はセキュリティーの問題でMetamaskは動作しない。
localhost
上でテストすべし。
CryptoZombieのサンプルコードでは動かない
該当するコードを示す。
cryptoZombies = new web3js.eth.Contract(cryptoZombiesABI, cryptoZombiesAddress);
これだとweb3のバージョンが原因で動かない。これはweb3@1.0.0で動作する。
現状、Metamaskが用意するwb3のバージョンは0.20.0なのでそれに合ったコードである必要があり、下記のコードで動作する。
contract = web3js.eth.contract(abi).at(address);
Metamask経由ではcallbackが必須
Metamask使わない場合ではこの限りではないが、callbackを使う必要がある。
主に2パターン、callとsendTransaction、についてそれぞれサンプルを乗せる
call
contract.MyMethods.call((err,res) => {
if(!err){
//成功
}else{
//失敗
}
});
sendTransaction
contract.MyMethods.sendTransaction(
params,
{from: hostAddress, gas:3000000, value:web3.toWei(_amount, "ether")},
(err,res) => {
if(!err){
//成功
}else{
//失敗
}}
);
その他
あと、プライベートネットの構築においても一つ絶対に守らなければいけない決まり事が存在する。
それは、genesis.json
のchainIdの値と、geth --networkId ~
の値を一致させる必要があるということだ。(考えてみれば当たり前)
これらの決まりごとがしっかりとは明記されていないので、注意してほしい。