ERC20準拠のEthereumトークンをweb3とflaskでAPI化してみる[ソースコード付き]

Ethereum
Ethereum Solidity
スポンサーリンク

概要

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

ERC20準拠のEthereumトークンをローカル環境にデプロイする方法

前回の記事でローカル環境にデプロイしたEthereumトークンをAPIで動かす方法を解説します。
ローカル環境へのトークンのデプロイをしていない方は↓の記事を参考にデプロイしてください。

ERC20準拠のEthereumトークンをローカル環境にデプロイする方法[ソースコード付き]
ERC20とは?端的に言うと、ETHトークンの規格です。特定のルールに則って作られた通貨とも言えるかと思います。ICOに用いられる事が多く、6つの機能と2つのイベントを有している事が求められます。6つの機能と2つのイベントは以下の通りです。function totalSupply() constant returns (uint totalSupply);function balanc...

ソースコード

kenshow8/eth_erc20_token_python_api
Contribute to kenshow8/eth_erc20_token_python_api development by creating an account on GitHub.

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

モジュールのインストール

必須モジュールのweb3flaskをインストールします。

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のデプロイを行います。
APIプログラムのデプロイ
※Dockerfileを用いたbuild済みの状態です。

次に、ganacheのURLを確認します。
デフォルトでは127.0.0.1:7545になっているので、Dockerの場合にはそれをプライベートIPアドレスに変更してください。
※コンテナ内部からホストに対してのアクセスをかけるために行う設定変更です。
ganacheの設定変更

ここから実際に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で動かすということを実践してみてもらいたいです。

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