保有しているEthereumベースのトークン残高を日本円に換算する

##やったこと
自分の保有しているトークン価格が
市場ベースでいくらほどなのか知りたいときがある。

これまでドルベースでは[ethplorer](https://ethplorer.io)のサービスから把握できていたが、最近のICOの人気のせいか、レスポンスが遅い。


そこで、せっかくEthereumの自ノードも立てているため、
自前で日本円に換算してみるスクリプトを書いてみた。

↓こんな感じでプロンプト上からトークンの保有残高と日本円を標準出力する。
![sample.png](https://qiita-image-store.s3.amazonaws.com/0/142016/9eba84df-7e27-96a6-9e42-6c655224d14d.png)


##前提
Ethereumの自ノードを構築し、[json-rpcでブロックチェーンの情報を取得できる環境](http://qiita.com/umidachi/items/44a50ce86e94ff0df8f2) で確認する。

[「スクレイピング: 仮想通貨の時価総額推移について」](http://qiita.com/umidachi/items/73eab1ef13e5dbb8fca5)でも紹介したCryptoCurrency MarketCapitalizationsのAPIを利用する。

[CryptoCurrency MarketCapitalizations](https://coinmarketcap.com/api/)

##Step0.全体のイメージ

やっていることは、 [自身のトークン残高を取得する方法](http://qiita.com/umidachi/items/aa7055eda740c946ac01)からそんなに変わらない。
海外サービスからAPIでトークン市場取引価格を取得し、自身のトークン残高と掛け算をするだけ。


##Step1. APIを利用してトークンあたりの市場取引価格を取得する。

CryptoCurrency MarketCapitalizationsのAPIの説明でもわかるように
下記URLのようにトークンあたりの市場取引価格をJPYベースでgetする。

```http:Token

https://api.coinmarketcap.com/v1/ticker/?convert=JPY

```

```json:レスポンス（例）
[
    {
        "id": "bitcoin", 
        "name": "Bitcoin", 
        "symbol": "BTC", 
        "rank": "1", 
        "price_usd": "4551.16", 
        "price_btc": "1.0", 
        "24h_volume_usd": "1980450000.0", 
        "market_cap_usd": "75247855429.0", 
        "available_supply": "16533775.0", 
        "total_supply": "16533775.0", 
        "percent_change_1h": "0.29", 
        "percent_change_24h": "-0.99", 
        "percent_change_7d": "9.22", 
        "last_updated": "1504128263", 
        "price_jpy": "501968.371736", 
        "24h_volume_jpy": "218432940570.0000000000", 
        "market_cap_jpy": "8299432115399"
    }, 
    {
        "id": "ethereum", 
        "name": "Ethereum", 
        "symbol": "ETH", 
        "rank": "2", 
        "price_usd": "380.237", 
        "price_btc": "0.0830763", 
        "24h_volume_usd": "1374760000.0", 
        "market_cap_usd": "35870045070.0", 
        "available_supply": "94336020.0", 
        "total_supply": "94336020.0", 
        "percent_change_1h": "-0.27", 
        "percent_change_24h": "2.48", 
        "percent_change_7d": "19.33", 
        "last_updated": "1504128261", 
        "price_jpy": "41938.0878202", 
        "24h_volume_jpy": "151628604296.0000000000", 
        "market_cap_jpy": "3956272272978"
    },....
]

```
上記APIのレスポンスで

 - "symbol":トークン名称
 - "price_jpy":取引価格(日本円)

となっていることがわかる。



##Step2 pythonで記述する。
上記APIでアクセスする際に、抽出したいのが
トークン名称"symbol"ごとの取引価格"price_jpy"なので
その全ての関係を返す関数を作っておく。

```py3:APIリクエストサンプル
import json
import requests as rs

def get_market_cap(url):

    res=rs.get(url)
    data=json.loads(res.text)
    dict_price = {}

    for i in data:
        d=i['symbol']
        n=i['price_jpy']
        dict_price.update({d:n})

    return dict_price;

```

また、自身が持っているトークン種別と、トークンのコントラクトアドレス、
トークンの桁数(decimals)の関係を仕込んでおく。


```python3:初期化処理

token_symboles=["SNT","MCO","VSL","BAT","BNT","GNT","MGO","REP","SNM","TKN","BET"]

    dict_address={"SNT":"0x744d70FDBE2Ba4CF95131626614a1763DF805B9E",
                  "MCO":"0xB63B606Ac810a52cCa15e44bB630fd42D8d1d83d",
                  "VSL":"0x5c543e7AE0A1104f78406C340E9C64FD9fCE5170",
                  "BAT":"0x0d8775f648430679a709e98d2b0cb6250d2887ef",
                  "BNT":"0x1f573d6fb3f13d689ff844b4ce37794d79a7ff1c",
                  "GNT":"0xa74476443119A942dE498590Fe1f2454d7D4aC0d",
                  "MGO":"0x40395044Ac3c0C57051906dA938B54BD6557F212",
                  "SNM":"0x983f6d60db79ea8ca4eb9968c6aff8cfa04b3c63",
                  "TKN":"0xaaaf91d9b90df800df4f55c205fd6989c977e73a",
                  "BET":"0x8aa33a7899fcc8ea5fbe6a608a109c3893a1b8b2",
                  "REP":"0xe94327d07fc17907b4db788e5adf2ed424addff6",
                  }

    dict_decimals={"SNT":18,"MCO":8,"VSL":18,"BAT":18,"BNT":18,"GNT":18,
                    "MGO":8,"SNM":18,"TKN":8,"BET":18,"REP":18}

```
##スクリプト全体

```py3:Token2jpy.py
import json
import requests as rs

def get_market_cap(url):

	res=rs.get(url)
	data=json.loads(res.text)
	dict_price = {}

	for i in data:
		d=i['symbol']
		n=i['price_jpy']
		dict_price.update({d:n})

	return dict_price;

def eth_call(url,to,data):
	headers = {'content-type': 'application/json'}
	payload = {
		"jsonrpc": "2.0",
		"method": "eth_call",
		"params":[{"to":to,
				   "data":data},
				   "latest"],
		"id": 0
	}

	response = rs.post(url, data=json.dumps(payload), headers=headers).json()
	i=int(response["result"],16)

	return i;

def get_tokenBalance(contract_address):
	url = "http://localhost:8545"
	a="0x○○○○○○○○○○○○○○○○○○○○○○○○○○○○○" #トークンを保管しているアドレス
	b="0x70a08231" #コントラクトメソッド(balanceOf(addres)のハッシュ値)
	c='000000000000000000000000'
	d=a[2:42]	   #先頭0xの表記を省略

	data= b + c + d
	balance=eth_call(url,contract_address,data)

	return balance;


if __name__ == "__main__":

	url_market_cap="https://api.coinmarketcap.com/v1/ticker/?convert=JPY&limit=500"

	token_symboles=["SNT","MCO","VSL","BAT","BNT","GNT","MGO","REP","SNM","TKN","BET"]

	dict_address={"SNT":"0x744d70FDBE2Ba4CF95131626614a1763DF805B9E",
				  "MCO":"0xB63B606Ac810a52cCa15e44bB630fd42D8d1d83d",
				  "VSL":"0x5c543e7AE0A1104f78406C340E9C64FD9fCE5170",
				  "BAT":"0x0d8775f648430679a709e98d2b0cb6250d2887ef",
				  "BNT":"0x1f573d6fb3f13d689ff844b4ce37794d79a7ff1c",
				  "GNT":"0xa74476443119A942dE498590Fe1f2454d7D4aC0d",
				  "MGO":"0x40395044Ac3c0C57051906dA938B54BD6557F212",
				  "SNM":"0x983f6d60db79ea8ca4eb9968c6aff8cfa04b3c63",
				  "TKN":"0xaaaf91d9b90df800df4f55c205fd6989c977e73a",
				  "BET":"0x8aa33a7899fcc8ea5fbe6a608a109c3893a1b8b2",
				  "REP":"0xe94327d07fc17907b4db788e5adf2ed424addff6",
				  }

	dict_decimals={"SNT":18,"MCO":8,"VSL":18,"BAT":18,"BNT":18,"GNT":18,
					"MGO":8,"SNM":18,"TKN":8,"BET":18,"REP":18}

	dict_price=get_market_cap(url_market_cap)
	Total_asset=0;
	for token in token_symboles:

		token_decimal=dict_decimals[token]
		token_balance=get_tokenBalance(dict_address[token]) / pow(10,token_decimal)
		token_yen=token_balance*float(dict_price[token])
		Total_asset+=token_yen

		print("トークン:",token)
		print("保有トークン数:",token_balance)
		print("日本円換算:",token_yen,"円")
		print("(1トークンあたり):",dict_price[token],"円")
		print("--------------")


	print("総額:",Total_asset)

```
##出力結果

```text:（例）出力結果
トークン: SNT
保有トークン数: 3232.58036728
日本円換算: 16960.2763496179 円
(1トークンあたり): 5.2466681173 円
--------------
トークン: MCO
保有トークン数: 22.80000912
日本円換算: 47004.36136561702 円
(1トークンあたり): 2061.5939721 円
--------------
トークン: VSL
保有トークン数: 276.44170415
日本円換算: 31065.573047326245 円
(1トークンあたり): 112.376579152 円
--------------
トークン: BAT
保有トークン数: 621.84391775
日本円換算: 16295.043185794791 円
(1トークンあたり): 26.204394255 円
--------------
トークン: BNT
保有トークン数: 36.22750590057683
日本円換算: 12385.770558238028 円
(1トークンあたり): 341.888580247 円
--------------
トークン: GNT
保有トークン数: 99.66515485
日本円換算: 3434.502622963604 円
(1トークンあたり): 34.4604152588 円
--------------
トークン: MGO
保有トークン数: 62.98742702
日本円換算: 6127.409746267665 円
(1トークンあたり): 97.279886418 円
--------------
トークン: REP
保有トークン数: 5.6
日本円換算: 15007.39522464 円
(1トークンあたり): 2679.8920044 円
--------------
トークン: SNM
保有トークン数: 871.36448801
日本円換算: 7955.87581581428 円
(1トークンあたり): 9.1303649911 円
--------------
トークン: TKN
保有トークン数: 142.77681278
日本円換算: 43070.72642552058 円
(1トークンあたり): 301.664714227 円
--------------
トークン: BET
保有トークン数: 504.0
日本円換算: 6400.203260724 円
(1トークンあたり): 12.6988159935 円
--------------
総額: 205707.13760252408

```

自身の保有するトークン残高が日本円ベースで確認できる。