main.netでethereumを送金するサンプル(Web3.js)

#はじめに

あまり日本語の説明がなく、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
```


```js
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.結果

<img width="878" alt="スクリーンショット 2017-11-17 19.19.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/43766/ce9626f8-224a-fc95-d83e-09bcca2a7dca.png">




##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);
}

```

#おしまい