import json
import time
from web3 import Web3
from eth_account import Account

# MetamaskとTrust WalletのRPCエンドポイント
ETH_RPC_URL = "https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID"  # Ethereum Mainnet
BSC_RPC_URL = "https://bsc-dataseed.binance.org/"  # BSC Mainnet

# UniswapとPancakeSwapのルーターアドレス
UNISWAP_ROUTER_ADDRESS = "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f"  # Uniswap V2 Router
PANCAKESWAP_ROUTER_ADDRESS = "0x10ED43C718714eb63d5aA57B78B54704E256024E"  # PancakeSwap V2 Router

# Web3の設定
eth_web3 = Web3(Web3.HTTPProvider(ETH_RPC_URL))
bsc_web3 = Web3(Web3.HTTPProvider(BSC_RPC_URL))

# ウォレットのプライベートキー
ETH_PRIVATE_KEY = "your_ethereum_wallet_private_key"
BSC_PRIVATE_KEY = "your_bsc_wallet_private_key"

eth_account = Account.privateKeyToAccount(ETH_PRIVATE_KEY)
bsc_account = Account.privateKeyToAccount(BSC_PRIVATE_KEY)

# UniswapとPancakeSwapのABI（スマートコントラクトの関数定義）
uniswap_abi = json.loads('[ABI for Uniswap Router]')  # Uniswap Router ABI
pancakeswap_abi = json.loads('[ABI for PancakeSwap Router]')  # PancakeSwap Router ABI

# スマートコントラクトインスタンス
uniswap_contract = eth_web3.eth.contract(address=UNISWAP_ROUTER_ADDRESS, abi=uniswap_abi)
pancakeswap_contract = bsc_web3.eth.contract(address=PANCAKESWAP_ROUTER_ADDRESS, abi=pancakeswap_abi)

# トークンアドレス
TOKEN_ADDRESS = "トークンのアドレス"  # 例えばUSDTやETHなど

# DEX手数料の設定（一般的に0.3%）
DEX_FEE_PERCENTAGE = 0.003

# ガス代を考慮して、価格を取得する関数
def get_token_prices():
    # Uniswapでの価格取得
    uniswap_price = uniswap_contract.functions.getAmountsOut(
        Web3.toWei(1, 'ether'),  # 購入するトークン量
        [eth_web3.toChecksumAddress("0xETH_TOKEN_ADDRESS"), eth_web3.toChecksumAddress(TOKEN_ADDRESS)]
    ).call()

    # PancakeSwapでの価格取得
    pancakeswap_price = pancakeswap_contract.functions.getAmountsOut(
        Web3.toWei(1, 'ether'),
        [bsc_web3.toChecksumAddress("0xBSC_TOKEN_ADDRESS"), bsc_web3.toChecksumAddress(TOKEN_ADDRESS)]
    ).call()

    return uniswap_price, pancakeswap_price

# ガス代を取得する関数
def estimate_gas_cost(web3, tx):
    return web3.eth.estimateGas(tx) * web3.eth.gas_price

# 利益を計算する関数（手数料・ガス代考慮）
def calculate_profit(buy_price, sell_price, gas_cost, amount):
    # 手数料を考慮
    buy_price_with_fee = buy_price * (1 + DEX_FEE_PERCENTAGE)
    sell_price_with_fee = sell_price * (1 - DEX_FEE_PERCENTAGE)

    # 予想利益の計算
    profit = (sell_price_with_fee - buy_price_with_fee) * amount

    # ガス代を差し引いた最終的な利益
    return profit - gas_cost

# アービトラージ機会をチェックする関数
def check_arbitrage_opportunity():
    uniswap_price, pancakeswap_price = get_token_prices()

    # ガス代の見積もり
    eth_gas_cost = estimate_gas_cost(eth_web3, {})
    bsc_gas_cost = estimate_gas_cost(bsc_web3, {})
    
    total_gas_cost = eth_gas_cost + bsc_gas_cost  # 両方のガス代を合算

    # トークンの量を指定
    amount = Web3.toWei(1, 'ether')

    # Uniswapで購入してPancakeSwapで売却する場合の利益
    profit_uniswap_to_pancake = calculate_profit(uniswap_price, pancakeswap_price, total_gas_cost, amount)

    # PancakeSwapで購入してUniswapで売却する場合の利益
    profit_pancake_to_uniswap = calculate_profit(pancakeswap_price, uniswap_price, total_gas_cost, amount)

    if profit_uniswap_to_pancake > 0:
        print(f"アービトラージ機会あり！Uniswapで購入し、PancakeSwapで売却。予想利益: {profit_uniswap_to_pancake}")
        execute_arbitrage('uniswap', 'pancakeswap', uniswap_price, pancakeswap_price)
    elif profit_pancake_to_uniswap > 0:
        print(f"アービトラージ機会あり！PancakeSwapで購入し、Uniswapで売却。予想利益: {profit_pancake_to_uniswap}")
        execute_arbitrage('pancakeswap', 'uniswap', pancakeswap_price, uniswap_price)
    else:
        print("アービトラージ機会なし")

# トランザクションを送信する関数
def send_transaction(web3, private_key, tx):
    signed_tx = web3.eth.account.sign_transaction(tx, private_key)
    tx_hash = web3.eth.sendRawTransaction(signed_tx.rawTransaction)
    return tx_hash

# 購入および売却の実行
def execute_arbitrage(buy_dex, sell_dex, buy_price, sell_price):
    amount = Web3.toWei(1, 'ether')  # アービトラージするトークン量

    if buy_dex == 'uniswap':
        print(f"Uniswapで {amount} トークンを {buy_price} で購入します")
        tx = uniswap_contract.functions.swapExactETHForTokens(
            0,  # 最小受取量
            [eth_web3.toChecksumAddress("0xETH_TOKEN_ADDRESS"), eth_web3.toChecksumAddress(TOKEN_ADDRESS)],
            eth_account.address,  # 送信先アドレス
            int(time.time()) + 60  # 期限
        ).buildTransaction({
            'from': eth_account.address,
            'value': amount,
            'gas': 2000000,
            'gasPrice': eth_web3.eth.gas_price,
            'nonce': eth_web3.eth.getTransactionCount(eth_account.address)
        })
        tx_hash = send_transaction(eth_web3, ETH_PRIVATE_KEY, tx)
        print(f"Uniswap購入トランザクション送信: {tx_hash.hex()}")

    if sell_dex == 'pancakeswap':
        print(f"PancakeSwapで {amount} トークンを {sell_price} で売却します")
        tx = pancakeswap_contract.functions.swapExactTokensForETH(
            amount,  # 売却するトークン量
            0,  # 最小受取量
            [bsc_web3.toChecksumAddress(TOKEN_ADDRESS), bsc_web3.toChecksumAddress("0xBSC_TOKEN_ADDRESS")],
            bsc_account.address,  # 送信先アドレス
            int(time.time()) + 60  # 期限
        ).buildTransaction({
            'from': bsc_account.address,
            'gas': 2000000,
            'gasPrice': bsc_web3.eth.gas_price,
            'nonce': bsc_web3.eth.getTransactionCount(bsc_account.address)
        })
        tx_hash = send_transaction(bsc_web3, BSC_PRIVATE_KEY, tx)
        print(f"PancakeSwap売却トランザクション送信: {tx_hash.hex()}")

# メインループ
while True:
    check_arbitrage_opportunity()
    time.sleep(30)  # 30秒ごとにチェック


これは完全でしょうか？(・ω・)