villagerHの日記

勉強したことや苦労した事などを書き綴ります

Python web3

Pythonでのコントラクトへのアクセスプロジェクトを少しずつですが作成し始めました。

軽く調べたりしましたがJavaScriptからアクセスする形よりも資料が少ないので非常に苦戦しそうです!

簡単にですが現時点でなんとなく理解したこととかをまとめてみます。

Pythonにもweb3のライブラリがあるのでそれを用いることでアクセスすることが可能です。

インストール

pip3 install web3

実際に使用するための準備

from web3 import Web3,HTTPProvider

web3 = Web3(HTTPProvider("http://127.0.0.1:7545")) # Ganacheなどで動かしているアドレスとポート

これだけでローカルで動作させているブロックチェーンには接続できます。
blockNumber = web3.eth.blockNumber
とかやれば情報が取得できるので確認できます。


これだけだとコントラクトのメソッドを呼び出せないので自作したコントラクトのインスタンスを取得する必要があります。

JavaScriptの時は以下の感じでした。

import artifacts from '../build/contracts/UnitFactory.json'
const UnitFactory = contract(artifacts)

大変今更なのですが今回Pythonを触ったことでここの処理が何をしているのかようやく把握しました。

  • Truffleでmigrateを行うとbuild以下のフォルダにjsonが吐き出される
  • 吐き出されたjsonにはアップロードしたコントラクトのアドレス等の必要な情報がjson形式で保存される
  • そのjsonをweb3に渡すことでインスタンスが取得できる

というような形になっているようです。

Python版も流れは一緒のようです。

ドキュメントを見ると

# get bytecode
>>> bytecode = compiled_sol['contracts']['Greeter.sol']['Greeter']['evm']['bytecode']['object']

# get abi
>>> abi = json.loads(compiled_sol['contracts']['Greeter.sol']['Greeter']['metadata'])['output']['abi']

>>> Greeter = w3.eth.contract(abi=abi, bytecode=bytecode)

abiとbytecodeを生成してますがtruffleの吐き出したjsonを覗くとその辺りの情報はありそうなのでjsonをそのまま読み込めば使えそうです。

json読み込み処理

import json

f = open("UnitFactory.json", 'r')
json_data = json.load(f) 

読み込んだjson_dataを投げてインスタンスを生成してみます!

UnitFactory = web3.eth.contract(json_data) 

実行してみたらエラーが出ました!

    UnitFactory = web3.eth.contract(json_data)
  File "/usr/local/lib/python3.7/site-packages/web3/eth.py", line 438, in contract
    return ContractFactory(address)
  File "/usr/local/lib/python3.7/site-packages/web3/contract.py", line 286, in __init__
    self.address = normalize_address(self.web3.ens, address)
  File "/usr/local/lib/python3.7/site-packages/web3/_utils/normalizers.py", line 212, in normalize_address
    validate_address(address)
  File "/usr/local/lib/python3.7/site-packages/web3/_utils/validation.py", line 152, in validate_address
    raise TypeError('Address {} must be provided as a string'.format(value))

アドレス周りが原因っぽい感じですが…?

もやっとしてますが時間が無くなってしまったので今日はここまで><