はじめに
あまり日本語の説明がなく、gasPriceとgasLimitの設定など少し手こずったので、
Web3.jsを使ったEthereumを送金するサンプルとポイントの覚書です。
private環境では、適当にGasを設定していても、
マイニングされていたのが、mainnet上では上手に設定しないと、マイナーに処理してもらえないので、
適切にGasPriceとGasLimitを設定してあげることが必要となります。
エラー例
GasPriceとGasLimitが適切でない場合は下記のようなエラーに遭遇します。
Unhandled rejection Error: Transaction was not mined within 50 blocks, please make sure your transaction was properly send. Be aware that it might still be mined!
GasPriceとGasLimitが低いため、マイナーが処理してくれない可能性がある
Unhandled rejection Error: Returned error: insufficient funds for gas * price + value
GasPriceとGasLimitの設定が不適切で、送金元に所持しているEtherを超えている可能性がある
Returned error: exceeds block gas limit
GasLimitの設定が大きすぎる
使用するモジュール
(トランザクションの送信)
https://www.npmjs.com/package/ethereumjs-tx
(ウォレットの作成)
https://www.npmjs.com/package/ethereumjs-wallet
送金する
1.読み込み
HttpProvierとして設定するのは、自身の環境として作成したGethのURL。
ここではINFRAを設定。
(参考) INFRA : https://infura.io/
npm install web3@0.20.0
var Web3 = require('web3');
web3 = new Web3(new Web3.providers.HttpProvider('https://mainnet.infura.io/自分のアカウント'));
2.ethereumjs-txの読み込み
var Tx = require('ethereumjs-tx');
var privateKey = new Buffer('---private key---', 'hex');
3.rawTxの設定(gasPriceとgasLimitを設定する)
var rawTx = {
nonce: '0x07',
gasPrice: web3.utils.toHex(web3.utils.toWei('0.00000009', 'ether')),
gasLimit: web3.utils.toHex(22000),
to: '0x418d0ABF2Bdfa98A8873fFA3CcD538AE76b9E21e',
value: web3.utils.numberToHex(web3.utils.toWei('0.0001', 'ether')),
data: web3.utils.asciiToHex('hello')
}
4.トランザクションの送信
var tx = new Tx(rawTx);
tx.sign(privateKey);
var serializedTx = tx.serialize();
console.log(serializedTx.toString('hex'));
web3.eth.sendSignedTransaction('0x' + serializedTx.toString('hex'))
.on('receipt', console.log);
5.結果
6.設定値の取得
rawTxに設定するGasPriceやTransactionの件数などは下記を実行することで参考値を取得できます。
//gasPrice
web3.eth.getGasPrice(function(error, result){console.log("gasPrice:");console.log(result);console.log(web3.utils.toHex(result)); });
//transactionCnt
web3.eth.getTransactionCount(fromAddress,function(error, result){console.log("transactionCnt:");console.log(result); });
//chainId
web3.eth.net.getId(function(error, result){console.log("chainId:");console.log(result); });
//blockNumber
web3.eth.getBlock(function(error, result){console.log("blockNumber:");console.log(result); });
//estimateGas
web3.eth.estimateGas(txData,function(error, result){console.log("gasLimit:");console.log(result);console.log(web3.utils.toHex(result)); });
どれも非同期処理なので、Promiseを用いるなど工夫が必要
const getGasPrice = () => {
return new Promise((resolve, reject) => {
web3.eth.getGasPrice((error, result) => {
if (error) reject(error);
resolve(web3.toHex(result.toNumber()));
});
});
};
Walletの作成
サンプル
送金に使用するwalletなどもethereumjs-wallet/hdkey
を利用することで作成することができます。
下記はbip39を用いることで秘密鍵から、人間が覚えやすいパスワードの生成を行なっています。
function generatewallet() {
var bip39 = require('bip39')
var mnemonic = bip39.generateMnemonic()
const hdkey = require('ethereumjs-wallet/hdkey')
privateKey = hdkey.fromMasterSeed(mnemonic)._hdkey._privateKey
const Wallet = require('ethereumjs-wallet')
const wallet = Wallet.fromPrivateKey(privateKey)
console.log("address:" + wallet.getChecksumAddressString());
console.log("mnemonic:" + mnemonic);
}
function importwallet(mnemonic) {
const hdkey = require('ethereumjs-wallet/hdkey')
privateKey = hdkey.fromMasterSeed(mnemonic)._hdkey._privateKey
console.log("privatekey:" + privateKey);
const Wallet = require('ethereumjs-wallet')
const wallet = Wallet.fromPrivateKey(privateKey);
}