趣旨
DEXを扱う時はJavaScriptの方が遥かに扱いやすいのですが、Pythonでも扱えるといろいろと便利だなと思い、価格取得と注文を出すのだけ簡潔にできる方法を探してみました。
- 間違えてプライベートキーを流出させないように環境変数を利用しています。
- Infuraの活用方法は割愛します。
- EthereumはETHの単位を合わせるのが大変ですね。
- CEXとは違って小さなミスが命取りになりかねないです。
- ロジックなどはなく一通りとりあえず動くものを準備しました。
- 便利そうだったのでUnipyを利用しています。
コード
Pythonが読める方なら、ドキュメント読みながら以下のコードを何度かいじくりまわしながら実行すると数十分で扱えるようになると思います。
from uniswap import Uniswap
from dotenv import dotenv_values
import os
from web3 import Web3
# 環境変数をセットしています。
current_directory = os.path.dirname(os.path.realpath(__file__))
env_path = os.path.join(current_directory, '.env')
config = dotenv_values(env_path)
address = config.get('WALLET_ADDRESS')
private_key = config.get('WALLET_PRIVATE_KEY')
# Uniswapのバージョン変更も以下の数字を変えるだけでできます!超便利。
version = 3
provider = config.get('INFURA_URL')
uniswap = Uniswap(address=address, private_key=private_key, version=version, provider=provider)
# 以下EtherscanやGoogle検索で取ってこれる情報です。
eth = "0x0000000000000000000000000000000000000000"
bat = "0x0D8775F648430679A709E98d2b0Cb6250d2887EF"
dai = "0x6B175474E89094C44Da98b954EedeAC495271d0F"
usdc = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
# eth_input = uniswap.get_price_input(eth, dai, 10**18) show eth value in dai
# eth = Web3.from_wei(eth_input, 'ether')
# print(uniswap.get_price_output(eth, dai, 1_000 * 10**18)) show dai value in eth
# 以下、WEIの扱いの部分で直感的には分かりづらい数値を扱うので結構だるいです。
# Example conversion for printing ETH balance in Ether instead of Wei
eth_balance_wei = uniswap.get_eth_balance()
eth_balance_eth = Web3.from_wei(eth_balance_wei, 'ether')
print(f"ETH Balance: {eth_balance_eth} ETH")
eth_amount_to_get_1000_dai = Web3.from_wei(uniswap.get_price_output(eth, dai, 1_000 * 10**18), 'ether')
print(f"ETH amount to get 1000 DAI: {eth_amount_to_get_1000_dai} ETH")
eth_amount_to_get_1000_usdc = Web3.from_wei(uniswap.get_price_output(eth, usdc, 1_000 * 10**6), 'ether')
print(f"ETH amount to get 1000 USDC: {eth_amount_to_get_1000_usdc} ETH")
# 1 ETHを購入するのにどれくらいのUSDCが必要になるか計算しています。
eth_amount_in_wei = 1 * 10**18
# Get the USDC amount required to buy 1 ETH, in USDC's smallest unit
usdc_amount = uniswap.get_price_input(eth, usdc, eth_amount_in_wei)
# Since USDC uses 6 decimal places, we don't need to convert it from wei to ether
print(f"USDC amount to get 1 ETH: {usdc_amount / 1e6} USDC")
# ETHをWEIにWEIをETHに変えています。
ether_amount = 1
wei_amount = Web3.to_wei(ether_amount, 'ether')
print(f"{ether_amount} ETH is {wei_amount} Wei")
wei_amount = 1000000000000000000 # 1e18
ether_amount = Web3.from_wei(wei_amount, 'ether')
print(f"{wei_amount} Wei is {ether_amount} ETH")
# 適当なメイン関数を置いてIF分で条件分岐させてみました。資金をいれていないウォレットだったので毎回エラーで返ってきました。
def main():
if eth_amount_to_get_1000_usdc < 0.2:
order = uniswap.make_trade(eth, usdc, 1*10**18, fee=500)
print(order)
elif usdc_amount / 1e6 > 3000:
order = uniswap.make_trade_output(eth, bat, 3000*10**18) # buy ETH for 3000 USDC
print(order)
else:
print('nothing happened')
if __name__ == '__main__':
main()