Commit 443e21e4 by haojie

Initial commit

parents
/venv
/recharge_error.log
/test.py
/callback.py
\ No newline at end of file
# 默认忽略的文件
/shelf/
/workspace.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/venv" />
</content>
<orderEntry type="jdk" jdkName="Python 3.8 (inscription-trade-py)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="PyDocumentationSettings">
<option name="format" value="PLAIN" />
<option name="myDocStringFormat" value="Plain" />
</component>
</module>
\ No newline at end of file
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.8 (inscription-trade-py)" project-jdk-type="Python SDK" />
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/inscription-trade-py.iml" filepath="$PROJECT_DIR$/.idea/inscription-trade-py.iml" />
</modules>
</component>
</project>
\ No newline at end of file
import time
import json
import redis
import random
import requests
from fake_useragent import UserAgent
from aredis import StrictRedis, ConnectionPool
from web3 import Web3
from web3.eth import AsyncEth
uni256Max = 2**256
class RedisConnSingleton(object):
_instance = None
def __new__(cls, *args, **kwargs):
"""
redis connection
:param args:
:param kwargs:
"""
if cls._instance is None:
cls._instance = redis.ConnectionPool(max_connections=1000, host='127.0.0.1', port=6379, db=0, password='12345678')
return cls._instance
class RedisConnectionPoolSingleton(object):
_instance = None
def __new__(cls, *args, **kwargs):
"""
aredis connection
:param args:
:param kwargs:
"""
if cls._instance is None:
cls._instance = ConnectionPool(max_connections=1000, host='127.0.0.1', port=6379, db=0, password='12345678')
return cls._instance
class RedisCon:
@staticmethod
def RedisConn():
"""
Redis connect
:return:
"""
redis_con = redis.Redis(connection_pool=RedisConnSingleton())
return redis_con
@staticmethod
def delete_task_data(redis_key, key):
"""
redis hdel
:param redis_key:
:param key:
:return:
"""
redis_con = redis.Redis(connection_pool=RedisConnSingleton())
try:
redis_con.hdel(redis_key, key)
except Exception as e:
print("Redis hdel error", e)
@staticmethod
def save_data(redis_key, key, value):
"""
redis hset
:param redis_key:
:param key:
:param value:
:return:
"""
redis_con = redis.Redis(connection_pool=RedisConnSingleton())
try:
redis_con.hset(redis_key, key, value)
except Exception as e:
print("Redis hset error", e)
@staticmethod
def query_contrast(redis_key, key):
"""
redis hget
:param redis_key:
:param key:
:return:
"""
redis_con = redis.Redis(connection_pool=RedisConnSingleton())
try:
res = redis_con.hget(redis_key, key)
return res
except Exception as e:
print("Redis hget error:", e)
@staticmethod
def task_list(key, value):
"""
redis rpush
:param key:
:param value:
:return:
"""
redis_con = redis.Redis(connection_pool=RedisConnSingleton())
try:
redis_con.rpush(key, value)
except Exception as e:
print("Redis rpush error:", e)
@staticmethod
def get_task(key):
"""
redis lpop
:param key:
:return:
"""
redis_con = redis.Redis(connection_pool=RedisConnSingleton())
try:
task = redis_con.lpop(key)
return task
except Exception as e:
print("Redis lpop error:", e)
@staticmethod
def del_task(key, value):
"""
redis lrem
:param key:
:param value:
:return:
"""
redis_con = redis.Redis(connection_pool=RedisConnSingleton())
try:
redis_con.lrem(key, 0, value)
except Exception as e:
print("Redis lrem error:", e)
@staticmethod
def ex_data(key, v_time, value):
"""
redis setex
:param key:
:param v_time:
:param value:
:return:
"""
redis_con = redis.Redis(connection_pool=RedisConnSingleton())
try:
redis_con.setex(key, v_time, value)
except Exception as e:
print("Redis setex error:", e)
@staticmethod
def get_task_num(key):
"""
redis llen
:param key:
:return:
"""
redis_con = redis.Redis(connection_pool=RedisConnSingleton())
try:
num = redis_con.llen(key)
if num is not None:
return num
else:
return 0
except Exception as e:
print("Redis llen error:", e)
class Helper:
"""公共基础类"""
@staticmethod
def getProxyLst():
"""获取代理列表"""
proxy_lst = list()
for i in range(5):
try:
response = requests.get("https://proxy.webshare.io/api/v2/proxy/list/download/pgewrawzvvqtzwdzjfdfswvkwcjasmofoucnfyyq/-/any/username/direct/-/").text
a = response.split('\r\n')
proxy_lst = a[:-1]
proxy_lst = list(map(lambda x: x.split(":"), proxy_lst))
proxy_lst = list(map(lambda x: x[2] + ':' + x[3] + '@' + x[0] + ':' + x[1], proxy_lst))
if proxy_lst != []:
# print("代理获取成功!")
break
except:
# 等待 1s 重试
time.sleep(2)
RedisCon.save_data("chain:pLst", "proxy", json.dumps(proxy_lst))
RedisCon.save_data("chain:pLst", "date", json.dumps(int(time.time())))
return proxy_lst
@staticmethod
def updateProxyLst():
status = 0
proxy_date = RedisCon.query_contrast("chain:pLst", "date")
if proxy_date:
proxy_date = json.loads(proxy_date)
if int(time.time()) - proxy_date > 1800:
status = 1
else:
status = 1
return status
@staticmethod
def getProxyList():
proxy = RedisCon.query_contrast("chain:pLst", "proxy")
if proxy:
proxy = json.loads(proxy)
# 代理获取失败,重新获取代理!
if not proxy:
proxy = Helper.getProxyLst()
else:
proxy = Helper.getProxyLst()
return proxy
@staticmethod
def tran_str():
"""
transfer str
:return:
"""
return '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'
@staticmethod
async def query_hash(redis_key, key):
"""
aredis hget
:param redis_key:
:param key:
:return:
"""
redis_con = StrictRedis(connection_pool=RedisConnectionPoolSingleton())
try:
res = await redis_con.hget(redis_key, key)
return res
except Exception as e:
print("Redis hget error:", e)
@staticmethod
async def task_list(key, value):
"""
aredis rpush
:param key:
:param value:
:return:
"""
redis_con = StrictRedis(connection_pool=RedisConnectionPoolSingleton())
try:
await redis_con.rpush(key, value)
except Exception as e:
print("Redis rpush error:", e)
@staticmethod
async def get_task(key):
"""
aredis lpop
:param key:
:return:
"""
redis_con = StrictRedis(connection_pool=RedisConnectionPoolSingleton())
try:
task = await redis_con.lpop(key)
return task
except Exception as e:
print("Redis lpop error:", e)
@staticmethod
def hex2bsc(address):
"""
change hex-address
:param address:
:return:
"""
address = '0x' + address[26:]
return address
@staticmethod
def getWeb3Bsc():
"""
async bsc web3
:return:
"""
bsc = "https://rpc.ankr.com/bsc"
# proxy = Helper.aiohttp_proxy_pool()
# request_kwargs={"proxy": proxy}
web_async = Web3(Web3.AsyncHTTPProvider(bsc), modules={'eth': (AsyncEth,)},
middlewares=[])
return web_async
@staticmethod
def getWeb3Eth():
eth_list = ["https://eth-mainnet.g.alchemy.com/v2/fH-3go199OKvbKSovc84gAC6xa5Givlb",
"https://eth-mainnet.g.alchemy.com/v2/V3-I2bBqYoA_DfOZrhaWx-t4-6LTZawj",
"https://eth-mainnet.g.alchemy.com/v2/D2l8IHN-2UUYcZpzXDY5FvZlcDF7eb0Q",
"https://eth-mainnet.g.alchemy.com/v2/tvHBgnSsj41XjKC9Rqv_Hl-rQJ-VupbD",
"https://eth-mainnet.g.alchemy.com/v2/6nk8lAti4uVJ6WnqadrrPsx2mUxYM8rW"]
eth = eth_list[0]
# proxy = Helper.aiohttp_proxy_pool()
# request_kwargs={"proxy": proxy}
web_async = Web3(Web3.AsyncHTTPProvider(eth), modules={'eth': (AsyncEth,)},
middlewares=[])
return web_async
@staticmethod
def aiohttp_proxy_pool():
"""
get aiohttp proxy
:return:
"""
proxy_lst = Helper.getProxyList()
index = random.randint(0, 999)
proxy = proxy_lst[index]
proxies = f"http://{proxy}"
return proxies
@staticmethod
def getHeaders():
"""
get http headers
:return:
"""
ua = UserAgent()
headers = {
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
'accept-language': 'zh-CN,zh;q=0.9',
'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="99", "Google Chrome";v="99"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
'sec-fetch-dest': 'iframe',
'sec-fetch-mode': 'navigate',
'sec-fetch-site': 'same-origin',
'sec-fetch-user': '?1',
'upgrade-insecure-requests': '1',
'user-agent': ua.chrome
}
return headers
if __name__ == '__main__':
# a = Helper.updateProxyLst()
# if a[0] == 0:
# print("代理未过期!")
# else:
# proxyLst = a[1]
# print(proxyLst)
print(Helper.getProxyLst())
import asyncio
import json
import time
import traceback
import requests
from Helper import RedisCon, Helper
import logging
logging.basicConfig(level=logging.ERROR, filename='recharge_error.log', datefmt='%Y/%m/%d %H:%M:%S',
format='%(asctime)s - %(name)s - %(levelname)s - %(lineno)d - %(module)s - %(message)s')
logger = logging.getLogger(__name__)
logger.setLevel(level=logging.DEBUG)
def pay_order_status(status, url, data):
header = {
'User-Agent': 'Apipost client Runtime/+https://www.apipost.cn/',
}
data['status'] = status
print('准备回调', data)
result = requests.post(url, headers=header, data=data)
print(result)
# if result.text == 'success':
# print("请求成功!")
# else:
# print("请求失败!")
logger.debug(f">>>>tx_hash:{data['hash']} status:{status} url:{url}"
f" 请求状态码:{result.status_code}")
async def rechargeList(web3, data):
tx_hash = data['hash'] # 交易 hash
url = data['notify_url']
to_address = data['to'].lower()
# 交易类型
tran_type = data['type']
status = 3 # 默认充值失败
if 'retry' in data:
await asyncio.sleep(1)
try:
if tran_type == 2:
# 转账
receipt = await web3.eth.get_transaction_receipt(tx_hash)
print('下面是回调')
print(receipt)
if receipt:
log = receipt['logs'][0]
amount = data['amount']
pay_type = log['topics'][0].hex()
# pay_amount = eval(log['data'].replace('\x00', '')) / (10 ** 6)
pay_amount = int(log['data'].hex(), 16) / (10 ** 6)
pay_to_address = (Helper.hex2bsc(log['topics'][2].hex())).lower()
# transfer交易, 交易金额正确!
if pay_type == tran_str and pay_amount >= amount:
if pay_to_address == to_address:
# print("支付成功,接收地址正确!")
status = 2
else:
# print("支付成功,接收地址错误!")
status = 4
elif tran_type == 1:
inscription_hash = data['inscription_hash']
# 铭文转移-直接查钱包铭文列表
check_url = "https://mainnet-api.ethscriptions.com/api/ethscriptions/owned_by/" + to_address
result = requests.get(check_url).text
# json转list
result = json.loads(result)
# 检测5次
for i in range(0, 5):
for item in result:
# 判断是否存在
if item['transaction_hash'] == inscription_hash:
status = 2
data['inscription'] = item
break
if status == 2:
break
else:
time.sleep(3)
pay_order_status(status, url, data)
except Exception as e:
print(e)
if 'retry' in data:
data['retry'] += 1
else:
# 进入队列重试,添加重试标志
data['retry'] = 1
if data['retry'] <= 5:
RedisCon.task_list(key, json.dumps(data))
else:
# 重试多次无法获取交易 hash
pay_order_status(5, url, data)
logger.error(f"Recharge Fail:>>>>tx_hash:{tx_hash}>>>>{traceback.format_exc()}")
def main():
while True:
tasks = list()
task_num = RedisCon.get_task_num(key)
print(task_num, '个任务')
nums = 10
if task_num and task_num > 0:
if task_num < nums:
process = task_num
else:
process = nums
loop = asyncio.get_event_loop()
for i in range(process):
task = RedisCon.get_task(key)
if task:
web3 = Helper.getWeb3Eth()
task = json.loads(task)
# task
tasks.append(rechargeList(web3, task))
loop.run_until_complete((asyncio.wait(tasks, timeout=30)))
else:
time.sleep(3)
continue
if __name__ == '__main__':
key = 'laravel_database_admin_check_receipt'
tran_str = Helper.tran_str()
main()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment