Python+Web3.pyでEthereumコントラクト学習 (その1)

Python

はじめに

Ethereumを現在学習中のこつこつイーサリアムです。イーサリアムをPythonで学習しようと思い、「Ethereum python」で検索をかけたところ、Ethereum 公式のサイト「Python開発者のためのイーサリアム」の「Intro to Web3.py · Ethereum For Python Developers」が見つかりました。

実践してみたところとても勉強になったので、勉強記録も兼ねて&ところどころ追記しながら、記事化しておこうと思います。すべてを1本の記事にすると長くなるので、3本立てとしました。

本記事ではまず、「Web3.pyとは」「アカウント残高の取得」「スマートコントラクト(ERC-20 トークン)情報の取得」まで、実施してみます!

Web3.pyのインストール、事前準備

Web3.pyとは、イーサリアム財団によって維持・管理されている、イーサリアムブロックチェーンを読み込み・書き込みするためのPythonライブラリです。

やりとりはJSON RPCという形式(PythonやJavascriptでよく使われるデータ形式)で行われるため、直感的にコマンドを作成・理解しやすいですね。

公式ドキュメントは以下↓からどうぞ。

Introduction — Web3.py 6.0.0-beta.4 documentation

Web3.pyのインストール

pythonをインストールしていない場合は事前にpython(バージョン3以上)をインストールしておきます。なお、Web3.pyのインストールは以下のコマンドを打つだけです。

$ pip install web3

ただし、インストール時に「Microsoft C++ Build Tools」がインストールされていない旨表示される場合には、以下の記事を参考にしてインストールします。

python pip実行時に「error: Microsoft Visual C++ 14.0 is required. Get it with “Build Tools for Visual Studio”」が発生した場合の対処法
pip install実行時にエラー「error: Microsoft Visual C++ 14.0 is required. Get it with

その後にWeb3.pyをインストールすれば問題なく完了するはずです。

infra.io

イーサリアムメインネットにアクセスするためには、その構成ノードへアクセスする必要があります。ノードを作成する方法(Geth/Parity)もありますが、ブロックチェーンへの大量のファイルダウンロード等手間がかかるので、別の方法で実施します。

別の方法とは、イーサリアムノードへのAPIアクセスを無料で提供しているサービスを利用することです。具体的には、「Infra」というサービスがあるので、サインアップし、APIキーを発行すればアクセスできるようになります。

Ethereum API | IPFS API & Gateway | ETH Nodes as a Service
Infura's development suite provides instant, scalable API access to the Ethereum and IPFS networks. Connect your app to Ethereum and IPFS now, for free!

Infraでサインアップをして新しいプロジェクトを作成すると、以下のようなURLが発行されるので、コピーしておきましょう。

"https://mainnet.infra.io/v3/Your_Infra_API_Key"

アカウント残高の取得

準備ができたので、いよいよWeb3.pyを使っていきましょう。

# 1. Import module
import json
from web3 import Web3

# 2. Set web3 module
infura_url = "https://mainnet.infura.io/v3/Your-Infra-API-Key"
web3 = Web3(Web3.HTTPProvider(infura_url))

# 3. Print Connection check
print(web3.isConnected())

# 4. Get Block Number
print(web3.eth.blockNumber)

# 5. Print account balances
account = "0xd26114cd6EE289AccF82350c8d8487fedB8A0C07"
balance = web3.eth.getBalance(account)
print(web3.fromWei(balance, "ether"))

1.でモジュールの読み込みを行っています。2.でWeb3モジュールによるアクセス設定(先ほど取得したInfraのURLを記載ください)、3.でコネクションの確認、4.でブロック番号の確認、5.でアカウント残高(アドレスはサンプル用で何も入っていません)を取得しています。

上記のファイルを「app01.py」等とし、「python app01.py」とコマンドを打つと、内容が実行されるはずです。実行結果のサンプルは以下の通りです。

True
13171300
0

これで、pythonを使ってEthereumネットワークにアクセスする方法がわかりましたね!実際に自分のウォレットのアドレスの残高等も、上記のプログラムでアドレスを変更すれば取得できますので、お試しくださいませ

スマートコントラクト(ERC-20 トークン) 情報の取得

次はスマートコントラクト情報の取得です。スマートコントラクトの情報については、「ABI (Application Binary Interface)」で定義された情報でやりとりされます。今回使用するABIの中身については、トークンの定義が記載されているもの、とでも解釈しておけばよいのかなと思います。では、テストスクリプトを見てみます。

# 1. Import Module
import json
from web3 import Web3

# 2. Fill in your infura API key here
infura_url = "https://mainnet.infura.io/v3/Your-Infra-API-Key"
web3 = Web3(Web3.HTTPProvider(infura_url))

# 3. Set ABI, Address
abi = [{"constant":True,"inputs":[],"name":"mintingFinished","outputs":[{"name":"","type":"bool"}],"payable":False,"type":"function"},{"constant":True,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":False,"type":"function"},{"constant":False,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[],"payable":False,"type":"function"},{"constant":True,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":False,"type":"function"},{"constant":False,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[],"payable":False,"type":"function"},{"constant":True,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint256"}],"payable":False,"type":"function"},{"constant":False,"inputs":[],"name":"unpause","outputs":[{"name":"","type":"bool"}],"payable":False,"type":"function"},{"constant":False,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"mint","outputs":[{"name":"","type":"bool"}],"payable":False,"type":"function"},{"constant":True,"inputs":[],"name":"paused","outputs":[{"name":"","type":"bool"}],"payable":False,"type":"function"},{"constant":True,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":False,"type":"function"},{"constant":False,"inputs":[],"name":"finishMinting","outputs":[{"name":"","type":"bool"}],"payable":False,"type":"function"},{"constant":False,"inputs":[],"name":"pause","outputs":[{"name":"","type":"bool"}],"payable":False,"type":"function"},{"constant":True,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":False,"type":"function"},{"constant":True,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":False,"type":"function"},{"constant":False,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[],"payable":False,"type":"function"},{"constant":False,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"},{"name":"_releaseTime","type":"uint256"}],"name":"mintTimelocked","outputs":[{"name":"","type":"address"}],"payable":False,"type":"function"},{"constant":True,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":False,"type":"function"},{"constant":False,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":False,"type":"function"},{"anonymous":False,"inputs":[{"indexed":True,"name":"to","type":"address"},{"indexed":False,"name":"value","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":False,"inputs":[],"name":"MintFinished","type":"event"},{"anonymous":False,"inputs":[],"name":"Pause","type":"event"},{"anonymous":False,"inputs":[],"name":"Unpause","type":"event"},{"anonymous":False,"inputs":[{"indexed":True,"name":"owner","type":"address"},{"indexed":True,"name":"spender","type":"address"},{"indexed":False,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":False,"inputs":[{"indexed":True,"name":"from","type":"address"},{"indexed":True,"name":"to","type":"address"},{"indexed":False,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}]
address = "0xd26114cd6EE289AccF82350c8d8487fedB8A0C07"

# 4. Access contract
contract = web3.eth.contract(address=address, abi=abi)

# 5. Get contract information

# 5.1. Contract name, symbol
print(contract.functions.name().call())
print(contract.functions.symbol().call())

# 5.2. Total Supply
totalSupply = contract.functions.totalSupply().call()
print(web3.fromWei(totalSupply, 'ether'))

# 5.3. Balance
balance = contract.functions.balanceOf(address).call()
print(web3.fromWei(balance, 'ether'))

2.まではこれまでと同じですね。3.では、ABI(今回はERC-20トークン(OmiseGo)のスマートコントラクト)を定義しています。4.でコントラクトのモジュールにアクセスし、5.で情報を取得しています。

5.1.ではコントラクト名とシンボル、5.2.では総供給量、5.4.ではトークン残高を取得しています。実行結果のサンプルは下記のとおりです。

OMGToken
OMG
140245398.245132780789239631
26624.6403596473000522

このように、ABIを使用することで、任意のトークンやスマートコントラクトの情報にアクセスすることが可能となります

おわりに

PythonのWeb3.pyを使用して、アカウント残高やスマートコントラクト情報を取得する方法をご紹介しました。

いままでEtherscanやウェブサイトを通してしか得られなかった情報が、このようにコマンドラインでデータを取得できるので、より実感が湧きやすく、データ利用の幅が広まったかなと思います。お役に立てば幸いです。

次回記事では、テスト環境を用いたイーサリアム送金についてご紹介します。

タイトルとURLをコピーしました