developing
This commit is contained in:
parent
f2d37cb5ca
commit
5c8f1acace
|
|
@ -1,5 +1,7 @@
|
|||
import requests
|
||||
|
||||
from custom_decorators import singleton
|
||||
|
||||
trc20token_info = {
|
||||
"usdt": {"tokenId": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
|
||||
"tokenAbbr": "USDT",
|
||||
|
|
@ -9,7 +11,7 @@ trc20token_info = {
|
|||
"vip": True}
|
||||
}
|
||||
|
||||
|
||||
@singleton
|
||||
class Tronscan:
|
||||
def __init__(self, api_key):
|
||||
self.api_key = api_key
|
||||
|
|
@ -25,19 +27,19 @@ class Tronscan:
|
|||
return response.json()
|
||||
|
||||
def transactions(self, start=0, limit=10, start_timestamp=None, end_timestamp=None,
|
||||
fromAddress=None, toAddress=None, tokens=None, block=None,
|
||||
type=None, method=None):
|
||||
from_address=None, to_address=None, tokens=None, block=None,
|
||||
type_=None, method=None):
|
||||
"""
|
||||
Get a list of transactions.
|
||||
:param start: Start number. Default 0
|
||||
:param limit: Number of items per page. Default 10
|
||||
:param start_timestamp: Start time
|
||||
:param end_timestamp: End time
|
||||
:param fromAddress: Sender's address.
|
||||
:param toAddress: Recipient's address.
|
||||
:param from_address: Sender's address.
|
||||
:param to_address: Recipient's address.
|
||||
:param tokens: Tokens involved
|
||||
:param block: Block
|
||||
:param type: Transaction type
|
||||
:param type_: Transaction type
|
||||
:param method: Method called in a smart contract signature. Only one value can be specified each time.
|
||||
:return: Getx a list of transactions.
|
||||
"""
|
||||
|
|
@ -52,16 +54,16 @@ class Tronscan:
|
|||
params["start_timestamp"] = start_timestamp
|
||||
if end_timestamp is not None:
|
||||
params["end_timestamp"] = end_timestamp
|
||||
if fromAddress is not None:
|
||||
params["fromAddress"] = fromAddress
|
||||
if toAddress is not None:
|
||||
params["toAddress"] = toAddress
|
||||
if from_address is not None:
|
||||
params["fromAddress"] = from_address
|
||||
if to_address is not None:
|
||||
params["toAddress"] = to_address
|
||||
if tokens is not None:
|
||||
params["tokens"] = tokens
|
||||
if block is not None:
|
||||
params["block"] = block
|
||||
if type is not None:
|
||||
params["type"] = type
|
||||
if type_ is not None:
|
||||
params["type"] = type_
|
||||
if method is not None:
|
||||
params["method"] = method
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
config = {
|
||||
'user': 'your_mysql_username',
|
||||
'password': 'your_mysql_password',
|
||||
'host': 'localhost',
|
||||
'database': 'your_database_name',
|
||||
'autocommit': False,
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
def singleton(cls):
|
||||
"""
|
||||
Decorator for making a class a singleton.
|
||||
This ensures that only one instance of the class exists.
|
||||
"""
|
||||
instances = {} # Dictionary to store the instance of the singleton class
|
||||
|
||||
def get_instance(*args, **kwargs):
|
||||
"""
|
||||
If an instance of the class does not exist, create one and store it.
|
||||
If it exists, return the existing instance.
|
||||
"""
|
||||
if cls not in instances:
|
||||
instances[cls] = cls(*args, **kwargs)
|
||||
return instances[cls]
|
||||
|
||||
return get_instance
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
from custom_decorators import singleton
|
||||
|
||||
|
||||
@singleton
|
||||
class OrderRepository:
|
||||
def __init__(self):
|
||||
self.db = None
|
||||
|
||||
def create(self, order_id, from_address, to_address):
|
||||
pass
|
||||
|
||||
def update_status(self, order_id, status):
|
||||
# 更新状态和时间
|
||||
pass
|
||||
|
||||
def get_creation_time(self, order_id):
|
||||
pass
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
loguru==0.7.2
|
||||
mysql-connector-python==9.1.0
|
||||
Requests==2.32.3
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
import uuid
|
||||
|
||||
from custom_decorators import singleton
|
||||
from repositories.order import OrderRepository
|
||||
from utils.datetime import current, current_timestamp, is_time_difference_greater_than
|
||||
|
||||
|
||||
@singleton
|
||||
class OrderService:
|
||||
def __init__(self):
|
||||
self.order_repo = OrderRepository()
|
||||
|
||||
def create_order(self, from_address, to_address, *args, **kwargs):
|
||||
date_str = current().strftime('%Y%m%d%H%M%S')
|
||||
unique_id = str(uuid.uuid4()).split('-')[0]
|
||||
order_id = f"{date_str}-{unique_id}"
|
||||
self.order_repo.create(order_id, from_address, to_address)
|
||||
return order_id
|
||||
|
||||
def finish_order(self, order_id):
|
||||
# 判断支付时间是否超过订单存活时间
|
||||
order_creation_time = self.order_repo.get_creation_time(order_id)
|
||||
if is_time_difference_greater_than(current_timestamp(), order_creation_time, minutes=15):
|
||||
status = 2
|
||||
else:
|
||||
status = 1
|
||||
self.order_repo.update_status(order_id, status)
|
||||
return status
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
from api import Tronscan
|
||||
from custom_decorators import singleton
|
||||
from utils.datetime import current_timestamp
|
||||
|
||||
|
||||
@singleton
|
||||
class Payment:
|
||||
def __init__(self, api_key):
|
||||
self.tronscan = Tronscan(api_key)
|
||||
|
||||
def check_payment(self, quant, from_address, to_address, order_create_timestamp):
|
||||
result = self.tronscan.token_trc20_transfers(from_address=from_address,
|
||||
to_address=to_address,
|
||||
start_timestamp=order_create_timestamp,
|
||||
end_timestamp=int(current_timestamp() * 1000))
|
||||
token_transfers = result['token_transfers']
|
||||
token_transfer = token_transfers[-1]
|
||||
confirmed = token_transfer['confirmed']
|
||||
correct_quant = quant == (token_transfer['quant'] / 6)
|
||||
confirmed = confirmed and correct_quant
|
||||
return confirmed
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
import datetime
|
||||
|
||||
|
||||
def current():
|
||||
return datetime.datetime.now()
|
||||
|
||||
def current_timestamp():
|
||||
datetime.datetime.now().timestamp()
|
||||
|
||||
def is_time_difference_greater_than(timestamp1, timestamp2, hours=0, minutes=0, seconds=0):
|
||||
"""
|
||||
判断两个时间戳的时间差是否大于指定的小时、分钟和秒数
|
||||
|
||||
参数:
|
||||
timestamp1 (int): 第一个时间戳
|
||||
timestamp2 (int): 第二个时间戳
|
||||
hours (int): 要比较的小时数,默认是0小时
|
||||
minutes (int): 要比较的分钟数,默认是0分钟
|
||||
seconds (int): 要比较的秒数,默认是0秒
|
||||
|
||||
返回:
|
||||
bool: 如果时间差大于指定的小时、分钟和秒数返回True,否则返回False
|
||||
"""
|
||||
# 将时间戳转换为 datetime 对象
|
||||
time1 = datetime.fromtimestamp(timestamp1)
|
||||
time2 = datetime.fromtimestamp(timestamp2)
|
||||
|
||||
# 计算时间差
|
||||
time_difference = abs(time2 - time1)
|
||||
|
||||
# 计算指定的时间差值
|
||||
threshold = datetime.timedelta(hours=hours, minutes=minutes, seconds=seconds)
|
||||
|
||||
# 判断时间差是否大于指定的时间
|
||||
return time_difference > threshold
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
from loguru import logger
|
||||
from mysql.connector import connect, Error, OperationalError
|
||||
from mysql.connector import errors as db_errors
|
||||
|
||||
from custom_decorators import singleton
|
||||
|
||||
|
||||
@singleton
|
||||
class Database:
|
||||
def __init__(self, config):
|
||||
self.connection = None
|
||||
self.config = config
|
||||
self.connect()
|
||||
|
||||
def connect(self):
|
||||
"""Establish a new database connection."""
|
||||
try:
|
||||
self.connection = connect(**self.config)
|
||||
if self.connection.is_connected():
|
||||
logger.info("Connected to MySQL database")
|
||||
except Error as e:
|
||||
logger.info(f"Error while connecting to MySQL: {e}")
|
||||
self.connection = None
|
||||
|
||||
def get_connection(self):
|
||||
"""Get the database connection, with reconnection logic."""
|
||||
if self.connection is None or not self.connection.is_connected():
|
||||
logger.info("Reconnecting to the database...")
|
||||
self.connect()
|
||||
return self.connection
|
||||
|
||||
def close_connection(self):
|
||||
if self.connection and self.connection.is_connected():
|
||||
self.connection.close()
|
||||
logger.info("MySQL connection is closed")
|
||||
|
||||
def execute_query(self, query, params=None):
|
||||
"""Execute a query with optional parameters, supports transactions."""
|
||||
cursor = None
|
||||
try:
|
||||
connection = self.get_connection()
|
||||
cursor = connection.cursor()
|
||||
cursor.execute(query, params)
|
||||
return cursor
|
||||
except OperationalError as e:
|
||||
logger.info(f"Operational error: {e}. Attempting to reconnect...")
|
||||
self.connect()
|
||||
cursor = self.get_connection().cursor()
|
||||
cursor.execute(query, params)
|
||||
return cursor
|
||||
except db_errors.Error as e:
|
||||
logger.info(f"Database error: {e}")
|
||||
raise
|
||||
finally:
|
||||
if cursor:
|
||||
cursor.close()
|
||||
|
||||
def commit(self):
|
||||
"""Commit the current transaction."""
|
||||
if self.connection:
|
||||
self.connection.commit()
|
||||
|
||||
def rollback(self):
|
||||
"""Rollback the current transaction."""
|
||||
if self.connection:
|
||||
self.connection.rollback()
|
||||
Loading…
Reference in New Issue