AWSにてGethのインストールを行う機会があったので、忘備録。
事前準備
TCP8545, TCP/UDP30303のポートを開けておくこと。
Gethのインストール
他のサイトを参考に粛々と入れていく。
sudo add-apt-repository ppa:ethereum/ethereum
sudo apt-get update
sudo apt-get install ethereum
geth version
初期設定
# 初期化
mkdir /home/taro/eth_chain/
vi /home/taro/eth_chain/genesis.json
{
"config": {
"chainId": 15
},
"nonce": "0x0000000000000042",
"timestamp": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "",
"gasLimit": "0x8000000",
"difficulty": "0x4000",
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x3333333333333333333333333333333333333333",
"alloc": {}
}
# 基本この内容らしい
# 初期化コマンド
geth --datadir /home/taro/eth_chain init /home/taro/eth_chain/genesis.json
# 起動
/usr/bin/geth --syncmode=fast --datadir=~/mainnet --http -http.corsdomain "*" --http.addr "127.0.0.1" --http.port "8545" --http.api "web3,eth,net,personal" --allow-insecure-unlock --snapshot=false
eth.getBlock(0)
personal.newAccount()
テストネットに接続する場合
開発用にRopstenに接続する。
geth --ropsten --syncmode "light" --datadir ~/testnet
geth attach ~/testnet/geth.ipc
> eth.syncing
false
# ついでにテスト用にマイニングしておく
> miner.setEtherbase('報酬受取アドレス')
> eth.coinbase
> miner.start()
# その他よく使ったコマンド忘備録
> eth.getBalance('アドレス')
> eth.getTransaction('hash')
> web3.fromWei(val, "ether")
自動起動設定
sudo vi /etc/supervisor/conf.d/geth.conf
[program:Geth]
command=/usr/bin/geth --syncmode=fast --datadir=~/mainnet --http -http.corsdomain "*" --http.addr "127.0.0.1" --http.port "8545" --http.api "web3,eth,net,personal" --allow-insecure-unlock --snapshot=false
user=root
autorestart=true
stdout_logfile=/var/log/supervisor/jobs/geth.log
stdout_logfile_maxbytes=1MB
stdout_logfile_backups=5
stdout_capture_maxbytes=1MB
redirect_stderr=true
sudo reboot
ん?自動で起動しない。。
supervisorがうまくいっていないみたいだ。
supervisorctl version
unix:///var/run/supervisor.sock no such file
はまりそうな予感。。
何かportの開放が必要?http使ってないから?
諦めてsystemdの方で対応することに。
# vi /etc/systemd/system/geth.service
[Unit]
Description=go-ethereum
After=syslog.target network.target
[Service]
Type=simple
ExecStart=/usr/bin/geth --syncmode=fast --datadir=~/mainnet --http -http.corsdomain "*" --http.addr "127.0.0.1" --http.port "8545" --http.api "web3,eth,net,personal" --allow-insecure-unlock --snapshot=false
WorkingDirectory=/root
KillMode=process
Restart=always
User=root
Group=root
[Install]
WantedBy=multi-user.target
# systemctl enable geth
# systemctl start geth
無事自動起動設定完了。
試しにsyncingも出来ているか確認。大丈夫そうだ。
$ geth attach
# geth.ipcで失敗するときは同期前?
> eth.syncing
{
currentBlock: 247885,
highestBlock: 12631530,
knownStates: 800557,
pulledStates: 773312,
startingBlock: 416
}
PHPで操作
このライブラリをノードのサーバー内にcomposerで配置して、アドレスの発行や送金周りを作っていく。
require __DIR__ . '/vendor/autoload.php';
use Web3\Web3;
use Web3\Providers\HttpProvider;
use Web3\RequestManagers\HttpRequestManager;
$timeout = 10;
$web3 = new Web3(new HttpProvider(new HttpRequestManager('http://localhost:8545', $timeout)));
// アドレス発行
if ($params->method == "getnewaddress") {
$web3->personal->newAccount($params->phrase, function ($err, $account) {
if ($err !== null) {
echo $err->getMessage();
}
echo $account;
exit;
});
}
// 残高確認
if ($params->method == "getbalance") {
$web3->eth->getBalance($params->address, function ($err, $res) {
if ($err !== null) {
echo $err->getMessage();
}
echo $res;
exit;
});
}
// fromWei
if ($params->method == "fromWei") {
list($quotient, $residue) = $web3->utils->fromWei($params->amount, $params->unit);
$result = $quotient->toString().'.'.$residue->toString();
echo $result;
exit;
}
// toWei
if ($params->method == "toWei") {
$res = $web3->utils->toWei($params->amount, $params->unit);
echo $res;
exit;
}
// toHex
if ($params->method == "toHex") {
$res = $web3->utils->toHex($params->amount);
echo $res;
exit;
}
// アンロック
if ($params->method == "unlockAccount") {
$web3->personal->unlockAccount($params->address, $params->phrase, $params->duration, function ($err, $res) {
if ($err !== null) {
echo $err->getMessage();
}
echo $res;
exit;
});
}
// ガス量
if ($params->method == "estimateGas") {
$fromAccount = $params->from;
$toAccount = $params->to;
$eth = $web3->eth;
$eth->estimateGas([
'from' => $fromAccount,
'to' => $toAccount,
'value' => $params->amount
], function ($err, $price) use ($eth, $fromAccount, $toAccount) {
if ($err !== null) {
echo $err->getMessage();
}
echo $price;
exit;
});
}
// ガス価格
if ($params->method == "gasPrice") {
$web3->eth->gasPrice(function($err, $price) {
if ($err !== null) {
echo $err->getMessage();
}
echo $price;
exit;
});
}
// 送金
if ($params->method == "sendTransaction") {
$fromAccount = $params->from;
$toAccount = $params->to;
$eth = $web3->eth;
$eth->sendTransaction([
'from' => $fromAccount,
'to' => $toAccount,
'value' => $params->amount,
'gas' => $params->gas,
'gasPrice' => $params->gasPrice
], function ($err, $tx) use ($eth, $fromAccount, $toAccount) {
if ($err !== null) {
echo $err->getMessage();
}
echo $tx;
exit;
});
}
// 確認
if ($params->method == "getTransaction") {
$web3->eth->getTransactionByHash($params->hash, function($err, $res) {
if ($err !== null) {
echo $err->getMessage();
}
echo json_encode($res);
exit;
});
}
ERC20を操作する
USDTも取り扱いたいのだが、どうやってテストコインを入手すればいいのだろう。。
調べていたところ、こちらの方の記事がどんぴしゃかも。
Ropstenのテストネット上でERC20トークンを作成・送付してみる
現状Ropstenに接続しているので、そこで使えるテスト用USDT tokenを自分で作って使用する、ということだろうか。。
こちらのIssueにはtokenの送金方法があるが、そもそもtokenを持っていないといけない。
https://github.com/web3p/web3.php/issues/78
諦めてtokenを作るところからやってみるか。
と思ったがtruffleのインストールで早速こけたりと長丁場になりそうなのでどうしようかと思っていたところ、webで簡単に発行できるとのこと…!
https://dime.jp/genre/989928/
早速発行してみたがずっとpendingだな。。
PHPでERC20を操作
残高確認から送金までを行う。
送金時にエラーが多発したが、パラメータの数や片の調整でなんとか成功。
// 残高確認
if ($params->method == "getbalance") {
$contract->at($params->contractAddress)->call("balanceOf", $params->walletAddress, function ($err, $result) use ($web3) {
$res = $web3->utils->fromWei($result[0]->toString(), 'ether');
echo $res[0]->toString();
});
}
// ガス量
if ($params->method == "estimateGas") {
$contract->at($params->contractAddress)->estimateGas('transfer', $params->to, $params->amount, ['from' => $params->from], function ($err, $resp) {
if ($err) {
echo "estimate gas error: " . $err->getMessage();
exit;
}
$gas = $resp->toString();
echo $gas;
exit;
});
}
// ガス価格
if ($params->method == "gasPrice") {
$web3->eth->gasPrice(function ($err, $price) {
if ($err !== null) {
echo $err->getMessage();
}
echo $price;
exit;
});
}
// 送金
if ($params->method == "sendToken") {
$fromAccount = $params->from;
$toAccount = $params->to;
$contract->at($params->contractAddress)->send('transfer', $toAccount, $params->amount, [
'from' => $fromAccount,
'gas' => $params->gas,
], function ($err, $res) {
if ($err !== null) {
echo "<pre>";
var_dump($err);
echo "</pre>";
echo 'Error: ' . $err->getMessage();
exit;
}
if ($res) {
echo $res;
exit;
}
});
}