Skip to content

Instantly share code, notes, and snippets.

@korrio
Created August 7, 2024 04:18
Show Gist options
  • Save korrio/a5799bfd55c64a0e10555ca822dd5c5c to your computer and use it in GitHub Desktop.
Save korrio/a5799bfd55c64a0e10555ca822dd5c5c to your computer and use it in GitHub Desktop.
bot4.py
import asyncio
import time
from web3 import Web3
from web3.middleware import geth_poa_middleware
import aiohttp
from colorama import Fore, Style, init
import ssl
import certifi
from decimal import Decimal
init(autoreset=True)
# Configuration
POLYGON_RPC_URL = "https://polygon-mainnet.g.alchemy.com/v2/jssjArgnoSmS2Uv5RMVwQAySLhkBsOnJ"
PRIVATE_KEY = ''
WALLET_ADDRESS = ''
PARASWAP_API_URL = "https://apiv5.paraswap.io"
# Connect to Polygon network
w3 = Web3(Web3.HTTPProvider(POLYGON_RPC_URL))
w3.middleware_onion.inject(geth_poa_middleware, layer=0)
# Token and contract addresses
WMATIC = w3.to_checksum_address("0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270")
USDC = w3.to_checksum_address("0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174")
SUSHISWAP_ROUTER = w3.to_checksum_address("0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506")
QUICKSWAP_ROUTER = w3.to_checksum_address("0xa5E0829CaCEd8fFDD4De3c43696c57F7D7A678ff")
# ABIs
ERC20_ABI = [
{"constant":True,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"type":"function"},
{"constant":False,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"success","type":"bool"}],"type":"function"},
{"constant":True,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"type":"function"},
]
ROUTER_ABI = [
{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},
{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"}],"name":"getAmountsOut","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},
]
WMATIC_ABI = [
{"constant": True,"inputs": [],"name": "name","outputs": [{"name": "","type": "string"}],"type": "function"},
{"constant": False,"inputs": [{"name": "guy","type": "address"},{"name": "wad","type": "uint256"}],"name": "approve","outputs": [{"name": "","type": "bool"}],"type": "function"},
{"constant": True,"inputs": [],"name": "totalSupply","outputs": [{"name": "","type": "uint256"}],"type": "function"},
{"constant": False,"inputs": [{"name": "src","type": "address"},{"name": "dst","type": "address"},{"name": "wad","type": "uint256"}],"name": "transferFrom","outputs": [{"name": "","type": "bool"}],"type": "function"},
{"constant": False,"inputs": [{"name": "wad","type": "uint256"}],"name": "withdraw","outputs": [],"type": "function"},
{"constant": True,"inputs": [],"name": "decimals","outputs": [{"name": "","type": "uint8"}],"type": "function"},
{"constant": True,"inputs": [{"name": "","type": "address"}],"name": "balanceOf","outputs": [{"name": "","type": "uint256"}],"type": "function"},
{"constant": True,"inputs": [],"name": "symbol","outputs": [{"name": "","type": "string"}],"type": "function"},
{"constant": False,"inputs": [{"name": "dst","type": "address"},{"name": "wad","type": "uint256"}],"name": "transfer","outputs": [{"name": "","type": "bool"}],"type": "function"},
{"constant": False,"inputs": [],"name": "deposit","outputs": [],"type": "function"},
{"constant": True,"inputs": [{"name": "","type": "address"},{"name": "","type": "address"}],"name": "allowance","outputs": [{"name": "","type": "uint256"}],"type": "function"},
{"payable": True,"type": "fallback"},
{"anonymous": False,"inputs": [{"indexed": True,"name": "src","type": "address"},{"indexed": True,"name": "guy","type": "address"},{"indexed": False,"name": "wad","type": "uint256"}],"name": "Approval","type": "event"},
{"anonymous": False,"inputs": [{"indexed": True,"name": "src","type": "address"},{"indexed": True,"name": "dst","type": "address"},{"indexed": False,"name": "wad","type": "uint256"}],"name": "Transfer","type": "event"},
{"anonymous": False,"inputs": [{"indexed": True,"name": "dst","type": "address"},{"indexed": False,"name": "wad","type": "uint256"}],"name": "Deposit","type": "event"},
{"anonymous": False,"inputs": [{"indexed": True,"name": "src","type": "address"},{"indexed": False,"name": "wad","type": "uint256"}],"name": "Withdrawal","type": "event"}
]
# Contract instances
wmatic_contract = w3.eth.contract(address=WMATIC, abi=WMATIC_ABI)
usdc_contract = w3.eth.contract(address=USDC, abi=ERC20_ABI)
sushiswap_contract = w3.eth.contract(address=SUSHISWAP_ROUTER, abi=ROUTER_ABI)
quickswap_contract = w3.eth.contract(address=QUICKSWAP_ROUTER, abi=ROUTER_ABI)
async def get_paraswap_price(session, src_token, dst_token, amount):
url = f"{PARASWAP_API_URL}/prices"
params = {
"srcToken": src_token,
"destToken": dst_token,
"amount": amount,
"srcDecimals": 18 if src_token == WMATIC else 6,
"destDecimals": 18 if dst_token == WMATIC else 6,
"side": "SELL",
"network": 137,
"userAddress": WALLET_ADDRESS
}
try:
# สร้าง SSL context ที่ไม่ตรวจสอบ certificate
ssl_context = ssl.create_default_context()
ssl_context.check_hostname = False
ssl_context.verify_mode = ssl.CERT_NONE
print(f"{Fore.YELLOW}คำเตือน: กำลังใช้การเชื่อมต่อที่ไม่ปลอดภัย (ไม่ตรวจสอบ SSL certificate)")
connector = aiohttp.TCPConnector(ssl=ssl_context)
async with aiohttp.ClientSession(connector=connector) as new_session:
async with new_session.get(url, params=params) as response:
if response.status != 200:
print(f"{Fore.RED}ParaSwap API error: {await response.text()}")
return None
data = await response.json()
print(f"ParaSwap Price API Response: {data}") # เพิ่มการ log ข้อมูลที่ได้รับ
if 'priceRoute' not in data:
print(f"{Fore.RED}Missing 'priceRoute' in ParaSwap API response")
return None
return data['priceRoute']
except Exception as e:
print(f"{Fore.RED}Unexpected error fetching ParaSwap price: {e}")
return None
def check_wmatic_allowance(spender_address):
allowance = wmatic_contract.functions.allowance(WALLET_ADDRESS, spender_address).call()
print(f"การอนุมัติ WMATIC ปัจจุบันสำหรับ {spender_address}: {w3.from_wei(allowance, 'ether')} WMATIC")
return allowance
async def approve_token(token_address, spender, amount):
token_contract = w3.eth.contract(address=token_address, abi=ERC20_ABI)
try:
# ตรวจสอบการอนุมัติปัจจุบัน
current_allowance = token_contract.functions.allowance(WALLET_ADDRESS, spender).call()
if current_allowance >= amount:
print(f"{Fore.GREEN}มีการอนุมัติเพียงพออยู่แล้ว")
return True
# อนุมัติจำนวนใหม่
print(f"{Fore.YELLOW}กำลังอนุมัติโทเคน...")
approve_txn = token_contract.functions.approve(spender, amount).build_transaction({
'from': WALLET_ADDRESS,
'gas': 100000,
'gasPrice': w3.eth.gas_price,
'nonce': w3.eth.get_transaction_count(WALLET_ADDRESS),
})
signed_txn = w3.eth.account.sign_transaction(approve_txn, PRIVATE_KEY)
tx_hash = w3.eth.send_raw_transaction(signed_txn.rawTransaction)
receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
if receipt['status'] == 1:
print(f"{Fore.GREEN}การอนุมัติโทเคนสำเร็จ Transaction hash: {receipt['transactionHash'].hex()}")
return True
else:
print(f"{Fore.RED}การอนุมัติโทเคนล้มเหลว")
return False
except Exception as e:
print(f"{Fore.RED}เกิดข้อผิดพลาดในการอนุมัติโทเคน: {str(e)}")
return False
async def approve_wmatic(spender_address, amount):
approve_txn = wmatic_contract.functions.approve(spender_address, amount).build_transaction({
'from': WALLET_ADDRESS,
'gas': 100000,
'gasPrice': w3.eth.gas_price,
'nonce': w3.eth.get_transaction_count(WALLET_ADDRESS),
})
signed_txn = w3.eth.account.sign_transaction(approve_txn, PRIVATE_KEY)
tx_hash = w3.eth.send_raw_transaction(signed_txn.rawTransaction)
receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
if receipt['status'] == 1:
print(f"{Fore.GREEN}การอนุมัติ WMATIC สำเร็จ: {w3.from_wei(amount, 'ether')} WMATIC")
return True
else:
print(f"{Fore.RED}การอนุมัติ WMATIC ล้มเหลว")
return False
async def check_price_difference(token_a, token_b, amount, wallet_address):
token_a_name = "WMATIC" if token_a == WMATIC else "USDC"
token_b_name = "USDC" if token_b == USDC else "WMATIC"
print(f"{Fore.CYAN}ตรวจสอบราคา {token_a_name}/{token_b_name}")
print(f"{Fore.CYAN}จำนวนเงิน: {w3.from_wei(amount, 'ether' if token_a == WMATIC else 'mwei')} {token_a_name}")
path = [token_a, token_b]
# ดึงราคาจาก DEX ต่างๆ
prices = {}
for dex, contract in [("QuickSwap", quickswap_contract), ("SushiSwap", sushiswap_contract)]:
try:
amounts_out = contract.functions.getAmountsOut(amount, path).call()
prices[dex] = amounts_out[1]
except Exception as e:
print(f"{Fore.RED}ไม่สามารถดึงราคาจาก {dex}: {e}")
# ดึงราคาจาก ParaSwap
async with aiohttp.ClientSession() as session:
paraswap_price = await get_paraswap_price(session, token_a, token_b, str(amount))
if paraswap_price:
prices["ParaSwap"] = int(paraswap_price['destAmount'])
if len(prices) < 2:
print(f"{Fore.RED}ไม่สามารถเปรียบเทียบราคาได้ เนื่องจากมีข้อมูลไม่เพียงพอ")
return None
best_dex = max(prices, key=prices.get)
worst_dex = min(prices, key=prices.get)
best_price = prices[best_dex]
worst_price = prices[worst_dex]
difference = best_price - worst_price
profit_percentage = (difference / worst_price) * 100
print(f"\n{Fore.GREEN}ผลการตรวจสอบโอกาสอาร์บิทราจ:")
for dex, price in prices.items():
print(f"{Fore.YELLOW}{dex}: {w3.from_wei(price, 'mwei' if token_b == USDC else 'ether')} {token_b_name}")
print(f"{Fore.CYAN}ส่วนต่างราคาสูงสุด: {w3.from_wei(difference, 'mwei' if token_b == USDC else 'ether')} {token_b_name}")
print(f"{Fore.CYAN}เปอร์เซ็นต์กำไรที่เป็นไปได้: {profit_percentage:.2f}%")
if profit_percentage > 0.7:
print(f"{Fore.GREEN}พบโอกาสอาร์บิทราจ: ซื้อบน {worst_dex}, ขายบน {best_dex}")
return worst_dex, best_dex, amount, profit_percentage
else:
print(f"{Fore.YELLOW}ไม่พบโอกาสอาร์บิทราจที่คุ้มค่า (กำไรน้อยกว่า 0.5%)")
return None
async def swap_on_paraswap(token_in, token_out, amount_in, max_retries=3):
for attempt in range(max_retries):
try:
# ตรวจสอบยอดคงเหลือ
balance = await check_token_balance(token_in, WALLET_ADDRESS)
if balance < amount_in:
return {'success': False, 'error': f'ยอดคงเหลือไม่เพียงพอ: มี {w3.from_wei(balance, "ether" if token_in == WMATIC else "mwei")}, ต้องการ {w3.from_wei(amount_in, "ether" if token_in == WMATIC else "mwei")}'}
# บันทึกยอดคงเหลือเริ่มต้นของโทเคนที่จะได้รับ
initial_out_balance = await check_token_balance(token_out, WALLET_ADDRESS)
ssl_context = ssl.create_default_context()
ssl_context.check_hostname = False
ssl_context.verify_mode = ssl.CERT_NONE
print(f"{Fore.YELLOW}คำเตือน: กำลังใช้การเชื่อมต่อที่ไม่ปลอดภัย (ไม่ตรวจสอบ SSL certificate)")
connector = aiohttp.TCPConnector(ssl=ssl_context)
async with aiohttp.ClientSession(connector=connector) as session:
price_route = await get_paraswap_price(session, token_in, token_out, str(amount_in))
if not price_route:
return {'success': False, 'error': 'Failed to get ParaSwap price route'}
token_proxy = Web3.to_checksum_address(price_route['tokenTransferProxy'])
# ตรวจสอบและอนุมัติโทเคน (ถ้าจำเป็น)
if token_in != WMATIC:
allowance = await check_token_allowance(token_in, WALLET_ADDRESS, token_proxy)
if allowance < amount_in:
approve_result = await approve_token(token_in, token_proxy, 2**256 - 1) # Max approval
if not approve_result:
return {'success': False, 'error': 'Failed to approve token'}
url = f"{PARASWAP_API_URL}/transactions/137"
payload = {
"srcToken": token_in,
"destToken": token_out,
"srcAmount": str(amount_in),
"destAmount": str(price_route['destAmount']),
"priceRoute": price_route,
"userAddress": WALLET_ADDRESS,
"partner": "paraswap.io",
"receiver": WALLET_ADDRESS
}
async with session.post(url, json=payload) as response:
if response.status != 200:
error_text = await response.text()
if "The rate has changed" in error_text:
print(f"{Fore.YELLOW}ราคาเปลี่ยนแปลง กำลังลองใหม่... (ครั้งที่ {attempt + 1})")
continue
print(f"{Fore.RED}ParaSwap API error: {error_text}")
return {'success': False, 'error': f"ParaSwap API error: {error_text}"}
transaction = await response.json()
print(f"ParaSwap API Response: {transaction}")
required_keys = ['to', 'from', 'data', 'value', 'gasPrice', 'gas']
if not all(key in transaction for key in required_keys):
print(f"{Fore.RED}Missing required transaction data")
return {'success': False, 'error': 'Incomplete transaction data'}
tx = transaction
tx['nonce'] = w3.eth.get_transaction_count(WALLET_ADDRESS)
# แปลงค่า gasPrice, gas และ value เป็น integer
tx['gasPrice'] = int(tx['gasPrice'])
tx['gas'] = int(tx['gas'])
tx['value'] = int(tx['value'])
# ตรวจสอบและแก้ไขค่า 'value'
if token_in == WMATIC:
if tx['value'] == 0:
tx['value'] = amount_in
print(f"Swapping WMATIC, value set to: {tx['value']}")
else:
tx['value'] = 0
print(f"Swapping {token_in}, value set to: {tx['value']}")
signed_txn = w3.eth.account.sign_transaction(tx, PRIVATE_KEY)
tx_hash = w3.eth.send_raw_transaction(signed_txn.rawTransaction)
print(f"{Fore.YELLOW}ส่งธุรกรรม ParaSwap แล้ว Hash: {tx_hash.hex()}")
receipt = await wait_for_transaction_receipt_with_timeout(tx_hash, timeout=300)
if receipt['status'] == 1:
print(f"{Fore.GREEN}การสวอปผ่าน ParaSwap สำเร็จ")
# ตรวจสอบจำนวนโทเคนที่ได้รับจริง
final_out_balance = await check_token_balance(token_out, WALLET_ADDRESS)
actual_amount_out = final_out_balance - initial_out_balance
print(f"ได้รับ {w3.from_wei(actual_amount_out, 'ether' if token_out == WMATIC else 'mwei')} {token_out}")
return {'success': True, 'amount_out': actual_amount_out, 'tx_hash': tx_hash.hex()}
else:
print(f"{Fore.RED}การสวอปผ่าน ParaSwap ล้มเหลว")
return {'success': False, 'error': 'Transaction failed', 'receipt': receipt}
except Exception as e:
print(f"{Fore.RED}เกิดข้อผิดพลาดในการสวอปผ่าน ParaSwap: {str(e)}")
if attempt < max_retries - 1:
print(f"{Fore.YELLOW}กำลังลองใหม่... (ครั้งที่ {attempt + 2})")
else:
return {'success': False, 'error': str(e)}
return {'success': False, 'error': 'Max retries reached'}
async def check_token_balance(token_address, wallet_address):
token_contract = w3.eth.contract(address=token_address, abi=ERC20_ABI)
balance = token_contract.functions.balanceOf(wallet_address).call()
return balance
async def check_token_allowance(token_address, owner, spender):
token_contract = w3.eth.contract(address=token_address, abi=ERC20_ABI)
allowance = token_contract.functions.allowance(owner, spender).call()
return allowance
async def approve_token(token_address, spender, amount):
token_contract = w3.eth.contract(address=token_address, abi=ERC20_ABI)
try:
tx = token_contract.functions.approve(spender, amount).build_transaction({
'from': WALLET_ADDRESS,
'nonce': w3.eth.get_transaction_count(WALLET_ADDRESS),
})
signed_tx = w3.eth.account.sign_transaction(tx, PRIVATE_KEY)
tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction)
receipt = await wait_for_transaction_receipt_with_timeout(tx_hash)
if receipt['status'] == 1:
print(f"{Fore.GREEN}Token approval successful")
return True
else:
print(f"{Fore.RED}Token approval failed")
return False
except Exception as e:
print(f"{Fore.RED}Error in token approval: {str(e)}")
return False
async def wait_for_transaction_receipt_with_timeout(tx_hash, timeout=300):
start_time = time.time()
while time.time() - start_time < timeout:
try:
receipt = w3.eth.get_transaction_receipt(tx_hash)
if receipt is not None:
return receipt
except Exception as e:
print(f"Error getting receipt: {e}")
await asyncio.sleep(1)
raise TimeoutError(f"Transaction not mined within {timeout} seconds")
async def swap_on_dex(dex, token_in, token_out, amount_in):
router_contract = sushiswap_contract if dex == "SushiSwap" else quickswap_contract
path = [token_in, token_out]
deadline = int(time.time()) + 300 # 5 minutes
try:
# ตรวจสอบยอดคงเหลือและการอนุมัติ
balance = wmatic_contract.functions.balanceOf(WALLET_ADDRESS).call()
allowance = wmatic_contract.functions.allowance(WALLET_ADDRESS, router_contract.address).call()
print(f"ยอด WMATIC คงเหลือ: {w3.from_wei(balance, 'ether')}")
print(f"การอนุมัติ WMATIC ปัจจุบัน: {w3.from_wei(allowance, 'ether')}")
if balance < amount_in:
print(f"{Fore.RED}ยอดคงเหลือไม่เพียงพอสำหรับการสวอป")
return {'success': False, 'error': 'Insufficient balance'}
if allowance < amount_in:
print(f"{Fore.YELLOW}กำลังอนุมัติ WMATIC...")
await approve_wmatic(router_contract.address, 2**256 - 1)
# คำนวณจำนวนขั้นต่ำที่จะได้รับ
amounts_out = router_contract.functions.getAmountsOut(amount_in, path).call()
min_amount_out = int(amounts_out[1] * 0.95) # 5% slippage
print(f"จำนวนที่คาดว่าจะได้รับ: {w3.from_wei(amounts_out[1], 'mwei' if token_out == USDC else 'ether')} {token_out}")
print(f"จำนวนขั้นต่ำที่จะได้รับ: {w3.from_wei(min_amount_out, 'mwei' if token_out == USDC else 'ether')} {token_out}")
# สร้างและส่งธุรกรรม
swap_txn = router_contract.functions.swapExactTokensForTokens(
amount_in,
min_amount_out,
path,
WALLET_ADDRESS,
deadline
).build_transaction({
'from': WALLET_ADDRESS,
'gas': 300000, # เพิ่ม gas limit
'gasPrice': w3.eth.gas_price,
'nonce': w3.eth.get_transaction_count(WALLET_ADDRESS),
})
signed_txn = w3.eth.account.sign_transaction(swap_txn, PRIVATE_KEY)
tx_hash = w3.eth.send_raw_transaction(signed_txn.rawTransaction)
print(f"ส่งธุรกรรมแล้ว Hash: {tx_hash.hex()}")
receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
if receipt['status'] == 1:
print(f"{Fore.GREEN}การสวอปสำเร็จ")
return {'success': True, 'amount_out': amounts_out[1], 'tx_hash': tx_hash.hex()}
else:
print(f"{Fore.RED}การสวอปล้มเหลว")
print(f"รายละเอียดธุรกรรม: {receipt}")
return {'success': False, 'error': 'Transaction failed', 'receipt': receipt}
except Exception as e:
print(f"{Fore.RED}เกิดข้อผิดพลาดในการสวอปบน {dex}: {str(e)}")
return {'success': False, 'error': str(e)}
async def execute_arbitrage(amount, buy_dex, sell_dex, max_retries=3):
try:
# ตรวจสอบยอด MATIC เริ่มต้น
initial_matic_balance = w3.eth.get_balance(WALLET_ADDRESS)
print(f"ยอด MATIC เริ่มต้น: {w3.from_wei(initial_matic_balance, 'ether')} MATIC")
# ห่อ MATIC เป็น WMATIC ถ้าจำเป็น
wmatic_contract = w3.eth.contract(address=WMATIC, abi=WMATIC_ABI)
wmatic_balance = await check_token_balance(WMATIC, WALLET_ADDRESS)
if wmatic_balance < amount:
wrap_amount = amount - wmatic_balance
wrap_tx = wmatic_contract.functions.deposit().build_transaction({
'from': WALLET_ADDRESS,
'value': wrap_amount,
'gas': 100000,
'gasPrice': get_polygon_gas_price(),
'nonce': w3.eth.get_transaction_count(WALLET_ADDRESS),
})
signed_tx = w3.eth.account.sign_transaction(wrap_tx, PRIVATE_KEY)
tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction)
await wait_for_transaction_receipt_with_timeout(tx_hash)
print(f"Wrapped {w3.from_wei(wrap_amount, 'ether')} MATIC to WMATIC")
# ซื้อ USDC ด้วย WMATIC
if buy_dex == "ParaSwap":
buy_result = await swap_on_paraswap(WMATIC, USDC, amount, max_retries)
else:
buy_result = await swap_on_dex(buy_dex, WMATIC, USDC, amount)
if not buy_result['success']:
print(f"{Fore.RED}การซื้อบน {buy_dex} ล้มเหลว: {buy_result.get('error', 'Unknown error')}")
return False
usdc_amount = buy_result['amount_out']
print(f"{Fore.GREEN}การซื้อสำเร็จ ได้รับ {w3.from_wei(usdc_amount, 'mwei')} USDC")
# ตรวจสอบยอด USDC ที่ได้รับจริง
actual_usdc_balance = await check_token_balance(USDC, WALLET_ADDRESS)
print(f"ยอด USDC ที่มีจริง: {w3.from_wei(actual_usdc_balance, 'mwei')} USDC")
if actual_usdc_balance < usdc_amount:
print(f"{Fore.YELLOW}คำเตือน: ยอด USDC ที่ได้รับน้อยกว่าที่คาดการณ์")
usdc_amount = actual_usdc_balance
# ขาย USDC เพื่อรับ WMATIC
if sell_dex == "ParaSwap":
sell_result = await swap_on_paraswap(USDC, WMATIC, usdc_amount, max_retries)
else:
sell_result = await swap_on_dex(sell_dex, USDC, WMATIC, usdc_amount)
if not sell_result['success']:
print(f"{Fore.RED}การขายบน {sell_dex} ล้มเหลว: {sell_result.get('error', 'Unknown error')}")
print(f"{Fore.YELLOW}คำเตือน: การซื้อสำเร็จแล้ว แต่การขายล้มเหลว")
print(f"{Fore.YELLOW}กำลังพยายามคืน USDC เป็น WMATIC...")
revert_result = await swap_on_dex(buy_dex, USDC, WMATIC, usdc_amount)
if revert_result['success']:
print(f"{Fore.GREEN}คืน USDC เป็น WMATIC สำเร็จ")
wmatic_received = revert_result['amount_out']
loss = Decimal(str(amount)) - Decimal(str(wmatic_received))
print(f"{Fore.YELLOW}การสูญเสียจากการคืน: {w3.from_wei(w3.to_wei(loss, 'ether'), 'ether')} WMATIC")
else:
print(f"{Fore.RED}ไม่สามารถคืน USDC เป็น WMATIC ได้ โปรดดำเนินการด้วยตนเอง")
print(f"{Fore.RED}USDC ที่ติดอยู่: {w3.from_wei(usdc_amount, 'mwei')} USDC")
return False
final_wmatic_balance = await check_token_balance(WMATIC, WALLET_ADDRESS)
wmatic_received = Decimal(str(final_wmatic_balance)) - Decimal(str(amount))
profit = wmatic_received if wmatic_received > 0 else Decimal('0')
loss = -wmatic_received if wmatic_received < 0 else Decimal('0')
profit_wei = w3.to_wei(profit, 'ether')
loss_wei = w3.to_wei(loss, 'ether')
print(f"{Fore.GREEN}อาร์บิทราจเสร็จสิ้น")
print(f"WMATIC ที่ใช้: {w3.from_wei(amount, 'ether')}")
print(f"WMATIC ที่ได้รับ: {w3.from_wei(final_wmatic_balance, 'ether')}")
if profit > 0:
print(f"กำไร: {w3.from_wei(profit_wei, 'ether')} WMATIC")
if loss > 0:
print(f"ขาดทุน: {w3.from_wei(loss_wei, 'ether')} WMATIC")
# ปิดการแปลง WMATIC กลับเป็น MATIC
# unwrap_tx = wmatic_contract.functions.withdraw(final_wmatic_balance).build_transaction({
# 'from': WALLET_ADDRESS,
# 'gas': 100000,
# 'gasPrice': get_polygon_gas_price(),
# 'nonce': w3.eth.get_transaction_count(WALLET_ADDRESS),
# })
# signed_tx = w3.eth.account.sign_transaction(unwrap_tx, PRIVATE_KEY)
# tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction)
# await wait_for_transaction_receipt_with_timeout(tx_hash)
# print(f"Unwrapped {w3.from_wei(final_wmatic_balance, 'ether')} WMATIC to MATIC")
# final_matic_balance = w3.eth.get_balance(WALLET_ADDRESS)
# total_profit = Decimal(str(final_matic_balance)) - Decimal(str(initial_matic_balance))
# print(f"กำไร/ขาดทุนสุทธิ: {w3.from_wei(w3.to_wei(total_profit, 'ether'), 'ether')} MATIC")
return True
except Exception as e:
print(f"{Fore.RED}เกิดข้อผิดพลาดระหว่างการทำอาร์บิทราจ: {e}")
return False
def get_polygon_gas_price():
gas_price = w3.eth.gas_price
return int(gas_price * 1.1) # เพิ่ม gas price อีก 10% เพื่อให้แน่ใจว่าธุรกรรมจะผ่าน
async def check_token_balance(token_address, wallet_address):
token_contract = w3.eth.contract(address=token_address, abi=ERC20_ABI)
balance = token_contract.functions.balanceOf(wallet_address).call()
return int(balance)
async def wait_for_transaction_receipt_with_timeout(tx_hash, timeout=300):
start_time = time.time()
while time.time() - start_time < timeout:
try:
receipt = w3.eth.get_transaction_receipt(tx_hash)
if receipt is not None:
return receipt
except Exception as e:
print(f"Error getting receipt: {e}")
await asyncio.sleep(1)
raise TimeoutError(f"Transaction not mined within {timeout} seconds")
async def run_arbitrage_bot():
AMOUNT_IN = w3.to_wei(1, 'ether') # 1 WMATIC
while True:
try:
print(f"\n{Fore.CYAN}{Style.BRIGHT}เริ่มตรวจสอบโอกาสอาร์บิทราจ...")
opportunity = await check_price_difference(WMATIC, USDC, AMOUNT_IN, WALLET_ADDRESS)
if opportunity:
worst_dex, best_dex, amount, profit_percentage = opportunity
print(f"{Fore.GREEN}พบโอกาสอาร์บิทราจ: ซื้อบน {worst_dex}, ขายบน {best_dex}")
if await execute_arbitrage(amount, worst_dex, best_dex):
print(f"{Fore.GREEN}อาร์บิทราจสำเร็จ กำไร: {profit_percentage:.2f}%")
else:
print(f"{Fore.RED}การทำอาร์บิทราจล้มเหลว")
else:
print(f"{Fore.YELLOW}ไม่พบโอกาสอาร์บิทราจในรอบนี้")
except Exception as e:
print(f'{Fore.RED}เกิดข้อผิดพลาดในลูปหลัก: {e}')
print(f"{Fore.CYAN}รอ 10 วินาทีก่อนตรวจสอบครั้งถัดไป...")
await asyncio.sleep(10)
async def main():
print(f"{Fore.GREEN}{Style.BRIGHT}เริ่มต้นบอทอาร์บิทราจ...")
if not w3.is_connected():
print(f"{Fore.RED}ไม่สามารถเชื่อมต่อกับ Polygon network ได้")
return
print(f"{Fore.GREEN}เชื่อมต่อกับ Polygon network สำเร็จ")
print(f"{Fore.YELLOW}กระเป๋าเงินที่ใช้: {WALLET_ADDRESS}")
# ตรวจสอบยอดคงเหลือ
wmatic_balance = wmatic_contract.functions.balanceOf(WALLET_ADDRESS).call()
usdc_balance = usdc_contract.functions.balanceOf(WALLET_ADDRESS).call()
print(f"{Fore.CYAN}ยอด WMATIC คงเหลือ: {w3.from_wei(wmatic_balance, 'ether')} WMATIC")
print(f"{Fore.CYAN}ยอด USDC คงเหลือ: {w3.from_wei(usdc_balance, 'mwei')} USDC")
try:
await run_arbitrage_bot()
except KeyboardInterrupt:
print(f"{Fore.YELLOW}บอทถูกหยุดโดยผู้ใช้")
if __name__ == "__main__":
asyncio.run(main())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment