概要
自作したEthereumeトークンを操作するにあたり、素の状態では面倒なので、pythonモジュールのweb3を使って操作します。
それをプログラムのままで動かすのもこれまた面倒であったり、web上で活用しづらいので、flaskを使ってAPI化します。
これをまたさらにデプロイするのが面倒なので、Dockerコンテナ化するところまで構築しました。
※ローカル上にデプロイすることも可能です。
といってもローカルで遊ぶ程度のためのプログラムですが、テスト環境のベースとして用いるにはそれなりに便利だと思います。
ERC20準拠のEthereumトークンをローカル環境にデプロイする方法
前回の記事でローカル環境にデプロイしたEthereumトークンをAPIで動かす方法を解説します。
ローカル環境へのトークンのデプロイをしていない方は↓の記事を参考にデプロイしてください。

ソースコード
API実装の方法
今回は以下の2パターンの方法を用意しました。
- Dockerを使ってコンテナ内にAPIプログラムをデプロイ
- ローカル環境上にAPIプログラムをデプロイ
どちらの方法もこの記事内で解説していきます。
Dockerを使ってコンテナ内にAPIプログラムをデプロイ
検証環境
macOS Catalina : 10.15.5
Docker version 19.03.8, build afacb8b(Docker Desktop)
ソースコードの取得
まずはソースコードを取得します。
git clone https://github.com/kenshow8/eth_erc20_token_python_api.git
環境変数の追加
.zshrc にホストのIPアドレスを出力する環境変数LOCAL_HOST_IP
を追加
※macOS Catalina以前の場合は.bashrcに追記してください。
vi ~/.zshrc
# 追記内容
export LOCAL_HOST_IP=`ifconfig en0 | grep inet | grep -v inet6 | sed -E "s/inet ([0-9]{1,3}.[0-9]{1,3}.[0-9].{1,3}.[0-9]{1,3}) .*$/\1/" | tr -d "\t"`
docker-composeを実行
docker-compose コマンドでコンテナを設置します。
※最初にdockerイメージを作成する工程を挟むため、数分程度の時間を要します。
cd ./eth_erc20_token_python_api/docker
mv .env.sample .env
vi .env
docker-compose up -d
viエディタで編集する.envファイルには、コントラクトアドレスとコントラクトのオーナーアドレスを入力する場所があります。
これらを入力の上、docker-compose up -d
を実行してください。
以上で完了です。
ここから先は、docker-composeファイルとdockerファイルの中身と解説を記載していきます。
docker-compopse.yml
version: '3.3'
services:
kenshow8_eth_api:
image: kenshow8/python3:1.0
build: .
container_name: 'kenshow8_eth_api'
ports:
- '8080:8080'
environment:
WEB3_URL: 'http://$LOCAL_HOST_IP:7545' # ローカルホスト以外にトークンをデプロイしている場合は編集してください。
CONTRACT_ADDRESS: '${CONTRACT_ADDRESS}'
OWNER_ADDRESS: '${OWNER_ADDRESS}'
command: >
bash -c "
python /app/eth_erc20_token_python_api/config_make_docker.py &&
cat /app/eth_erc20_token_python_api/config/setting.ini &&
python /app/eth_erc20_token_python_api/coin_api.py
"
dockerイメージは同階層にあるDockerfileを使います。
そのため、build: .
を記載しています。
環境変数は、デプロイするプログラム内の設定項目を入力するために利用しています。
具体的には、config/setting.ini
が該当します。command:
を見ると分かりますが、APIを起動する前に、python /app/eth_erc20_token_python_api/config_make_docker.py
を実行しています。
このプログラムの中身は以下の通りです。
config_make_docker.py
# coding:utf-8
import os
import configparser
from pathlib import Path
file_dir = Path(__file__).parent
file_name = 'config/setting.ini'
file_path = file_dir.joinpath(file_name)
config = configparser.ConfigParser()
# コントラクト設定
config_web3 = 'web3_config'
config.add_section(config_web3)
## web3 設定 ##
## 環境変数用
config.set(config_web3, 'web3_url', os.environ['WEB3_URL'])
config.set(config_web3, 'contract_address', os.environ['CONTRACT_ADDRESS'])
config.set(config_web3, 'owner_address', os.environ['OWNER_ADDRESS'])
with open(file_path, 'w') as file:
config.write(file)
19〜21行目にos.environ['HOGE']
があり、環境変数を取得している事がわかります。
これらの値を使って、config/setting.ini
ファイルを生成しています。
その後、確認用にcat /app/eth_erc20_token_python_api/config/setting.ini
で設定ファイルの内容を出力します。
そして、python /app/eth_erc20_token_python_api/coin_api.py
でAPIプログラムを実行しています。
これが、docker-composeの一連の流れです。
その元になっているDockerfileの内容は以下の通りです。
Dockerfile
FROM python:3.7
USER root
WORKDIR /app
ENV DEBCONF_NOWARNINGS yes
RUN apt-get update && apt-get -y install locales && \
localedef -f UTF-8 -i ja_JP ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8
ENV TZ JST-9
ENV TERM xterm
RUN apt-get install -y vim less
RUN pip install --upgrade pip
RUN pip install --upgrade setuptools
RUN pip install web3
RUN pip install flask
RUN git clone https://github.com/kenshow8/eth_erc20_token_python_api.git
EXPOSE 8080
SHELL ["/bin/bash", "-c"]
CMD ["/bin/bash"]
基本的にはpythonのイメージを呼び出して、必要なモジュール(flask, web3)のインストールとプログラムの取得を行うだけです。
ローカル環境上にAPIプログラムをデプロイ
検証環境
macOS Catalina : 10.15.5
python: Python 3.6.10 :: Anaconda
module: web3, flask
ソースコードの取得
まずはソースコードを取得します。
git clone https://github.com/kenshow8/eth_erc20_token_python_api.git
モジュールのインストール
必須モジュールのweb3
とflask
をインストールします。
pip install web3
pip install flask
設定ファイルを作成
config_make.py
を利用して設定ファイルを作成します。
cd eth_erc20_token_python_api
vi config_make.py
python config_make.py
viエディタで編集するconfig_make.py
には19,20行目にコントラクトアドレスとコントラクトのオーナーアドレスを入力する項目があります。
これらを入力の上、python config_make.py
を実行してください。
config_make.py
ファイルの中身は以下の通りです。
config_make.py
# coding:utf-8
import os
import configparser
from pathlib import Path
file_dir = Path(__file__).parent
file_name = 'config/setting.ini'
file_path = file_dir.joinpath(file_name)
config = configparser.ConfigParser()
# コントラクト設定
config_web3 = 'web3_config'
config.add_section(config_web3)
## web3 設定 ##
config.set(config_web3, 'web3_url', 'http://127.0.0.1:7545') # contractのデプロイ先に応じて変更してください。
config.set(config_web3, 'contract_address', '0x238f011262D73a07c0bfACdf5f851CE467bc94ee') # contract addressを入力してください。
config.set(config_web3, 'owner_address', '0xB66d64EF0fACCebFd6F5E10Ece3dcBd3a65B82F1') # contractのowner addressを入力してください。
with open(file_path, 'w') as file:
config.write(file)
APIを稼働
ここまでで設定ファイルの準備が完了したので、APIを稼働させます。
python coin_api.py
バックグラウンドで稼働させたい場合は以下のようにしてください。
nohup python coin_api.py &
以上で完了です。
APIの仕様
このAPIは2つの機能を有しています。
- 残高確認
- 送金
それぞれの仕様は以下の通りです。
残高確認
POST
/balance
Content-Type : application/json
Body:
{
"wallet_address": "0xaE7A6b72C2Ac93D79a9F6D744366cd9d752ecB7A"
}
Response:
{
"name": "KenshowCoin",
"balance": 10.0,
"symbol": "KSC",
"decimals": 18
}
送金
POST
/send
Content-Type : application/json
Body:
{
"from_wallet_address": "0xaE7A6b72C2Ac93D79a9F6D744366cd9d752ecB7A",
"to_wallet_address": "0xB66d64EF0fACCebFd6F5E10Ece3dcBd3a65B82F1",
"send_number": 100.0
}
Response-0:
{
"response_code": 200,
"code": 0,
"message": "success."
}
Response-1:
{
"response_code": 200,
"code": 1,
"message": "failed. need to check balance of send from."
}
いずれの機能もエラーハンドリングは400,404,500を提供しています。
実験
Dockerを使ってコンテナ内にAPIプログラムをデプロイ方法で実験を行います。
まずは、APIのデプロイを行います。
※Dockerfileを用いたbuild済みの状態です。
次に、ganacheのURLを確認します。
デフォルトでは127.0.0.1:7545
になっているので、Dockerの場合にはそれをプライベートIPアドレスに変更してください。
※コンテナ内部からホストに対してのアクセスをかけるために行う設定変更です。
ここから実際にAPIの動作を実験します。
postmanを用います。
●残高確認
残高確認で、0xaE7A6b72C2Ac93D79a9F6D744366cd9d752ecB7A
は10.0枚のトークンを保有している事がわかります。
●送金
先程残高確認した0xaE7A6b72C2Ac93D79a9F6D744366cd9d752ecB7A
から0xB66d64EF0fACCebFd6F5E10Ece3dcBd3a65B82F1
に10.0枚のトークンを送金します。
初回の送金は、送金が成功しているパターンです。それにより0xaE7A6b72C2Ac93D79a9F6D744366cd9d752ecB7A
アドレスのトークン残高が0になります。
なので、2回目の送金は失敗している事がわかります。
これで、残高確認と送金が正常に行えていることがわかります。
まとめ
一般的にはweb3はjavascriptで使うことの方が多いかと思います。
そのため、pythonでweb3??と少し不思議に思った方もいらっしゃったのではないでしょうか。
ですが、実はあるのです。pythonのweb3
使い方は、ソースコードを読んで確認してみてください。基本的にはtruffleでコンパイルした際に作成されるjsonファイルからabiの部分だけ抽出。それをabi.jsonとして保存。それを読み込んで、その中に定義されている関数を実行していくという流れです。
そのため、このプログラムを応用することで、トークン以外のsolidityプログラムをpythonで実行させることも可能となります。
今回は、サンプルとして理解しやすいトークンで話を進めていますが、是非Ethereumに色々なプログラムをデプロイして、pythonで動かすということを実践してみてもらいたいです。