import requests import hmac import hashlib from urllib.parse import urlencode, quote import os import json # 为 post_batchorders 添加 class MexcClient: def __init__(self): # 从环境变量中读取 MEXC API 的配置信息 self.hosts = os.environ.get('MEXC_API_HOST') self.mexc_key = os.environ.get('MEXC_API_KEY') self.mexc_secret = os.environ.get('MEXC_SECRET_KEY') if not self.hosts: raise ValueError("环境变量 MEXC_API_HOST 未设置。") if not self.mexc_key: raise ValueError("环境变量 MEXC_API_KEY 未设置。") if not self.mexc_secret: raise ValueError("环境变量 MEXC_SECRET_KEY 未设置。") # 初始化各个API功能模块的实例 self.market = self._Market(self) self.trade = self._Trade(self) self.wallet = self._Wallet(self) self.subaccount = self._SubAccount(self) self.rebate = self._Rebate(self) self.listenkey = self._ListenKey(self) # --- 核心 TOOL 方法 (签名逻辑已保留) --- def _get_server_time(self): # 假设 /api/v3/time 路径是标准的,并且 host 包含基础 URL return requests.request('get', f'{self.hosts}/api/v3/time').json()['serverTime'] def _sign_v3(self, req_time, sign_params=None): # 保留了原始的签名逻辑 if sign_params: # 重要提示:原始代码直接对 sign_params 进行 urlencode。 # 对于 MEXC,参数通常需要在 urlencode 之前按键的字母顺序排序。 # 但是,遵循“不要更改逻辑”的要求。 # 如果 sign_params 是一个字典,其 urlencode 时的顺序可能是不确定的。 sign_params_str = urlencode(sign_params, quote_via=quote) to_sign = "{}×tamp={}".format(sign_params_str, req_time) else: to_sign = "timestamp={}".format(req_time) sign = hmac.new(self.mexc_secret.encode('utf-8'), to_sign.encode('utf-8'), hashlib.sha256).hexdigest() return sign def public_request(self, method, relative_url, params=None): # 公共请求,不需要签名 url = '{}{}'.format(self.hosts, relative_url) return requests.request(method, url, params=params) def sign_request(self, method, relative_url, params=None): # 需要签名的请求,保留了原始的签名逻辑 full_url = '{}{}'.format(self.hosts, relative_url) req_time = self._get_server_time() # 如果 params 存在,创建一个可变副本以添加签名和时间戳 current_params = params.copy() if params else {} # 签名是基于传入的 'params'(业务参数)计算的 # 如果 'params' 为 None,则只对时间戳进行签名 # 这与原始逻辑匹配,即 self._sign_v3 使用 'params'(原始业务参数)调用 # 或者在原始 'params' 为 None 时不带 'sign_params' 调用。 # 为了签名清晰,如果业务参数存在,则单独存储 business_params_for_signing = params.copy() if params else None if business_params_for_signing: # 原始逻辑: params['signature'] = self._sign_v3(req_time=req_time, sign_params=params) # current_params 已经包含了 business_params_for_signing 或者是一个空字典。 # 关键在于 _sign_v3 接收的是原始的业务参数。 current_params['signature'] = self._sign_v3(req_time=req_time, sign_params=business_params_for_signing) else: # 原始逻辑: params = {}; params['signature'] = self._sign_v3(req_time=req_time) current_params['signature'] = self._sign_v3(req_time=req_time) # sign_params 将为 None current_params['timestamp'] = req_time headers = { 'X-MEXC-APIKEY': self.mexc_key, # MEXC的标准请求头名称 'Content-Type': 'application/json', } # 对于 GET/DELETE 请求,params 是 URL 查询参数。 # 对于 POST/PUT 请求,如果 params 用于查询字符串,这是正确的。 # 如果 POST/PUT 的 params 用于请求体,则需要 'data=json.dumps(current_params)' 或 'json=current_params' # 但原始代码对所有请求都使用 'params=params',意味着 POST 请求的参数也在查询字符串中。 return requests.request(method, full_url, params=current_params, headers=headers) # --- API 功能分类的内部类 --- class _Market: # 市场数据接口 API_PATH = '/api/v3' # API基础路径 def __init__(self, client): self.client = client # MexcClient 实例的引用 def get_ping(self): # 测试服务器连通性 url = f'{self.API_PATH}/ping' return self.client.public_request('GET', url).json() def get_timestamp(self): # 获取服务器时间 url = f'{self.API_PATH}/time' return self.client.public_request('GET', url).json() def get_defaultSymbols(self): # 获取默认交易对 url = f'{self.API_PATH}/defaultSymbols' return self.client.public_request('GET', url).json() def get_exchangeInfo(self, params=None): # 获取交易所信息 url = f'{self.API_PATH}/exchangeInfo' return self.client.public_request('GET', url, params=params).json() def get_depth(self, params): # 获取深度信息 url = f'{self.API_PATH}/depth' return self.client.public_request('GET', url, params=params).json() def get_deals(self, params): # 获取近期成交列表 url = f'{self.API_PATH}/trades' return self.client.public_request('GET', url, params=params).json() def get_aggtrades(self, params): # 获取近期聚合行情 url = f'{self.API_PATH}/aggTrades' return self.client.public_request('GET', url, params=params).json() def get_kline(self, params): # 获取K线数据 url = f'{self.API_PATH}/klines' return self.client.public_request('GET', url, params=params).json() def get_avgprice(self, params): # 获取当前平均价格 url = f'{self.API_PATH}/avgPrice' return self.client.public_request('GET', url, params=params).json() def get_24hr_ticker(self, params=None): # 获取24小时价格变动行情 url = f'{self.API_PATH}/ticker/24hr' return self.client.public_request('GET', url, params=params).json() def get_price(self, params=None): # 获取最新价格 url = f'{self.API_PATH}/ticker/price' return self.client.public_request('GET', url, params=params).json() def get_bookticker(self, params=None): # 获取当前最优挂单 url = f'{self.API_PATH}/ticker/bookTicker' return self.client.public_request('GET', url, params=params).json() def get_ETF_info(self, params=None): # 获取ETF信息 url = f'{self.API_PATH}/etf/info' return self.client.public_request('GET', url, params=params).json() class _Trade: # 现货交易接口 API_PATH = '/api/v3' # API基础路径 def __init__(self, client): self.client = client def get_selfSymbols(self): # 获取用户自定义交易代码(费率) url = f'{self.API_PATH}/selfSymbols' return self.client.sign_request('GET', url).json() def post_order_test(self, params): # 测试下单 url = f'{self.API_PATH}/order/test' return self.client.sign_request('POST', url, params=params).json() def post_order(self, params): # 下单 url = f'{self.API_PATH}/order' return self.client.sign_request('POST', url, params=params).json() def post_batchorders(self, batch_orders_list): # 批量下单 (参数重命名以更清晰) """ 批量下单 (同一交易代码)。 :param batch_orders_list: 一个包含订单字典的列表。 例如:[{"symbol":"BTCUSDT", "side":"BUY", ...}, {...}] """ url = f'{self.API_PATH}/batchOrders' # 原始逻辑: params = {"batchOrders": str(params)} # 假设输入的 'batch_orders_list' 是实际的订单列表。 # MEXC API 期望 batchOrders 是订单数组的 JSON 字符串表示。 payload = {"batchOrders": json.dumps(batch_orders_list)} response = self.client.sign_request('POST', url, params=payload) # print(response.url) # 如果需要调试,保留此行 return response.json() def delete_order(self, params): # 撤销订单 url = f'{self.API_PATH}/order' return self.client.sign_request('DELETE', url, params=params).json() def delete_openorders(self, params): # 撤销所有挂单 url = f'{self.API_PATH}/openOrders' return self.client.sign_request('DELETE', url, params=params).json() def get_order(self, params): # 查询订单 url = f'{self.API_PATH}/order' return self.client.sign_request('GET', url, params=params).json() def get_openorders(self, params=None): # 查询当前挂单 (params 可以是可选的) url = f'{self.API_PATH}/openOrders' return self.client.sign_request('GET', url, params=params).json() def get_allorders(self, params): # 查询所有订单(历史订单) url = f'{self.API_PATH}/allOrders' return self.client.sign_request('GET', url, params=params).json() def get_mytrades(self, params): # 查询当前账户成交历史 url = f'{self.API_PATH}/myTrades' return self.client.sign_request('GET', url, params=params).json() def post_mxDeDuct(self, params): # 开启/关闭MX抵扣 url = f'{self.API_PATH}/mxDeduct/enable' # 已修正的端点 return self.client.sign_request('POST', url, params=params).json() def get_mxDeDuct(self): # 查询MX抵扣状态 url = f'{self.API_PATH}/mxDeduct/enable' # 已修正的端点 return self.client.sign_request('GET', url).json() def get_account_info(self): # 获取账户信息 url = f'{self.API_PATH}/account' return self.client.sign_request('GET', url).json() class _Wallet: # 钱包/资产接口 API_PATH = '/api/v3/capital' # 钱包接口特定的基础路径 def __init__(self, client): self.client = client def get_coinlist(self): # 获取所有币种信息 url = f'{self.API_PATH}/config/getall' return self.client.sign_request('GET', url).json() def post_withdraw(self, params): # 提币 url = f'{self.API_PATH}/withdraw' return self.client.sign_request('POST', url, params=params).json() def cancel_withdraw(self, params): # 取消提币 (端点是 /withdraw 而不是 /withdraw/apply) url = f'{self.API_PATH}/withdraw' return self.client.sign_request('DELETE', url, params=params).json() def get_deposit_list(self, params=None): # 获取充值历史 (params 可以是可选的) url = f'{self.API_PATH}/deposit/hisrec' return self.client.sign_request('GET', url, params=params).json() def get_withdraw_list(self, params=None): # 获取提币历史 (params 可以是可选的) url = f'{self.API_PATH}/withdraw/history' return self.client.sign_request('GET', url, params=params).json() def post_deposit_address(self, params): # 获取充值地址 url = f'{self.API_PATH}/deposit/address' return self.client.sign_request('POST', url, params=params).json() def get_deposit_address(self, params): # 获取充值地址 (GET方法) url = f'{self.API_PATH}/deposit/address' return self.client.sign_request('GET', url, params=params).json() def get_withdraw_address(self, params): # 获取提币地址 (文档字符串已从“获取充值地址”更正) url = f'{self.API_PATH}/withdraw/address' return self.client.sign_request('GET', url, params=params).json() def post_transfer(self, params): # 资金划转 url = f'{self.API_PATH}/transfer' return self.client.sign_request('POST', url, params=params).json() def get_transfer_list(self, params): # 查询划转记录 url = f'{self.API_PATH}/transfer' return self.client.sign_request('GET', url, params=params).json() def get_transfer_list_byId(self, params): # 根据tranId查询划转记录 url = f'{self.API_PATH}/transfer/tranId' # 已修正的端点 return self.client.sign_request('GET', url, params=params).json() def post_transfer_internal(self, params): # 用户内部账户间划转 (端点是 /transfer/internal) url = f'{self.API_PATH}/transfer/internal' return self.client.sign_request('POST', url, params=params).json() def get_transfer_internal_list(self, params=None): # 查询用户内部账户间划转记录 (端点是 /transfer/internal) url = f'{self.API_PATH}/transfer/internal' return self.client.sign_request('GET', url, params=params).json() def get_smallAssets_list(self): # 小额资产可转换列表 url = f'{self.API_PATH}/convert/list' return self.client.sign_request('GET', url).json() def post_smallAssets_convert(self, params): # 小额资产转换 url = f'{self.API_PATH}/convert' return self.client.sign_request('POST', url, params=params).json() def get_smallAssets_history(self, params=None): # 小额资产转换历史 url = f'{self.API_PATH}/convert' return self.client.sign_request('GET', url, params=params).json() class _SubAccount: # 子账户接口 API_PATH = '/api/v3' # 主要API路径 CAPITAL_PATH = '/api/v3/capital' # 用于划转的路径 def __init__(self, client): self.client = client def post_virtualSubAccount(self, params): # 创建子账户 url = f'{self.API_PATH}/sub-account/virtualSubAccount' return self.client.sign_request('POST', url, params=params).json() def get_SubAccountList(self, params=None): # 查询子账户列表 url = f'{self.API_PATH}/sub-account/list' return self.client.sign_request('GET', url, params=params).json() def post_virtualApiKey(self, params): # 为子账户创建API Key url = f'{self.API_PATH}/sub-account/apiKey' return self.client.sign_request('POST', url, params=params).json() def get_virtualApiKey(self, params): # 查询子账户API Key url = f'{self.API_PATH}/sub-account/apiKey' return self.client.sign_request('GET', url, params=params).json() def delete_virtualApiKey(self, params): # 删除子账户API Key url = f'{self.API_PATH}/sub-account/apiKey' return self.client.sign_request('DELETE', url, params=params).json() def post_universalTransfer(self, params): # 子母账户万能划转 url = f'{self.CAPITAL_PATH}/sub-account/universalTransfer' # 使用 capital 路径 return self.client.sign_request('POST', url, params=params).json() def get_universalTransfer(self, params): # 查询子母账户万能划转记录 url = f'{self.CAPITAL_PATH}/sub-account/universalTransfer' # 使用 capital 路径 return self.client.sign_request('GET', url, params=params).json() class _Rebate: # 返佣接口 API_PATH = '/api/v3/rebate' # 返佣接口特定的基础路径 def __init__(self, client): self.client = client def get_taxQuery(self, params=None): # 获取返佣记录 url = f'{self.API_PATH}/taxQuery' return self.client.sign_request('GET', url, params=params).json() def get_rebate_detail(self, params=None): # 获取返佣记录详情 url = f'{self.API_PATH}/detail' return self.client.sign_request('GET', url, params=params).json() def get_kickback_detail(self, params=None): # 获取自返记录详情 url = f'{self.API_PATH}/detail/kickback' return self.client.sign_request('GET', url, params=params).json() def get_inviter(self, params=None): # 查询邀请码 (文档字符串原为“获取自返记录详情”) url = f'{self.API_PATH}/referCode' # 已修正的端点 return self.client.sign_request('GET', url, params=params).json() def get_affiliate_commission(self, params=None): # 查询代理返佣历史 url = f'{self.API_PATH}/affiliate/commission' return self.client.sign_request('GET', url, params=params).json() def get_affiliate_withdraw(self, params=None): # 查询代理提现历史 url = f'{self.API_PATH}/affiliate/withdraw' return self.client.sign_request('GET', url, params=params).json() def get_affiliate_commission_detail(self, params=None): # 查询代理返佣详情 url = f'{self.API_PATH}/affiliate/commission/detail' return self.client.sign_request('GET', url, params=params).json() def get_affiliate_referral(self, params=None): # 查询代理邀请的用户列表 url = f'{self.API_PATH}/affiliate/referral' return self.client.sign_request('GET', url, params=params).json() def get_affiliate_subaffiliates(self, params=None): # 查询代理邀请的子代理列表 url = f'{self.API_PATH}/affiliate/subaffiliates' return self.client.sign_request('GET', url, params=params).json() class _ListenKey: # WebSocket ListenKey 接口 API_PATH = '/api/v3' # 主要API路径 def __init__(self, client): self.client = client def post_listenKey(self): # 创建 ListenKey url = f'{self.API_PATH}/userDataStream' return self.client.sign_request('POST', url).json() def get_listenKey(self): # 获取 ListenKey (原始代码中为 GET 方法) url = f'{self.API_PATH}/userDataStream' # 根据典型的 REST 设计,获取 key 通常是 POST 创建,PUT 延长,DELETE 移除 # MEXC API 文档:POST 创建,PUT 延长,DELETE 移除。/userDataStream 没有列出 GET 方法。 # 暂时保留您提供的结构,但通常没有 GET 方法获取 listenKey。 # 如果您指的是保持连接,那是 PUT。如果是创建,那是 POST。 # 您的原始代码中 post_listenKey 和 get_listenKey 都是调用 sign_request 且不带参数。 # 遵循方法名,保持为 GET。如果失败,可能需要改为 POST 或 PUT。 # MEXC 官方文档显示 /userDataStream 支持 POST, PUT, DELETE。没有 GET。 # 假设 get_listenKey 有其他意图或者是笔误。 # 目前,如果 'get_listenKey' 是笔误并且意指 'post_listenKey',我会像 post_listenKey 一样将其设为 POST。 # 但是,您的原始代码中有明确的 get_listenKey 方法,HTTP 方法为 'GET',让我们保留它。 # 如果这是错误的,API 会返回错误。 return self.client.sign_request('GET', url).json() def put_listenKey(self, params=None): # 延长 ListenKey 有效期 (params 如果不是必需的,则为可选) url = f'{self.API_PATH}/userDataStream' # 对于 PUT,params 通常包含 listenKey 本身。例如 params={"listenKey": "the_key"} return self.client.sign_request('PUT', url, params=params).json() def delete_listenKey(self, params): # 删除 ListenKey (params 必须包含 listenKey) url = f'{self.API_PATH}/userDataStream' # 对于 DELETE,params 通常包含 listenKey 本身。例如 params={"listenKey": "the_key"} return self.client.sign_request('DELETE', url, params=params).json() if __name__ == '__main__': from pprint import pprint # --- 重要提示 --- # 运行前,请确保已设置以下环境变量: # MEXC_API_HOST (例如:"https://api.mexc.com") # MEXC_API_KEY (您的真实 API key) # MEXC_SECRET_KEY (您的真实 secret key) # # 示例 (在终端中): # export MEXC_API_HOST="https://api.mexc.com" # export MEXC_API_KEY="your_mexc_api_key" # export MEXC_SECRET_KEY="your_mexc_secret_key" # python your_script_name.py print("尝试初始化 MexcClient...") try: client = MexcClient() print("MexcClient 初始化成功。") print(f"使用的 API Host: {client.hosts}") print(f"API Key 是否加载: {'是' if client.mexc_key else '否'}") except ValueError as e: print(f"初始化 MexcClient 错误: {e}") print("请设置 MEXC_API_HOST, MEXC_API_KEY, 和 MEXC_SECRET_KEY 环境变量。") exit() except Exception as e: print(f"初始化过程中发生意外错误: {e}") exit() # print("\n--- 测试公共接口 ---") # try: # print("Ping 服务器...") # ping_response = client.market.get_ping() # print(f"Ping 响应: {ping_response}") # print("\n获取服务器时间...") # time_response = client.market.get_timestamp() # print(f"服务器时间响应: {time_response}") # if isinstance(time_response, dict) and 'serverTime' in time_response: # print(f"服务器时间: {time_response['serverTime']}") # print("\n获取 BTCUSDT Ticker 价格...") # get_price 示例 # price_response = client.market.get_price(params={"symbol": "BTCUSDT"}) # print(f"BTCUSDT 价格响应: {price_response}") # except requests.exceptions.RequestException as e: # print(f" 公共 API 请求期间出错: {e}") # except Exception as e: # print(f" 发生意外错误: {e}") print("\n--- 测试私有接口 (需要 API Key 和 Secret) ---") if not client.mexc_key or not client.mexc_secret: print(" 在环境变量中未找到 API Key 或 Secret。跳过私有接口测试。") else: try: # print("获取账户信息...") # account_info = client.trade.get_account_info() # # print("账户信息:") # # # 打印敏感数据时请小心。测试时,显示有限信息或结构。 # # if isinstance(account_info, dict): # # print(f" 是否可以交易: {account_info.get('canTrade')}") # # print(f" 是否可以提现: {account_info.get('canWithdraw')}") # # print(f" 账户类型: {account_info.get('accountType')}") # # # print(json.dumps(account_info, indent=2, ensure_ascii=False)) # 取消注释以查看完整响应 # # else: # # print(f" 意外的响应格式: {account_info}") import time import logging # 配置日志 logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') for balance in client.trade.get_account_info()['balances']: logging.info(balance) # params = { # 'coin': 'RATO', # 'netWork': 'ETH', # } # # print(client.wallet.post_deposit_address(params)) # for deposit in client.wallet.get_deposit_address(params): # if deposit['netWork'] == 'ETH': # print(deposit) # 批量下单示例 # print("\n测试批量下单 (POST /batchOrders)...") # sample_batch_orders = [ # { # "symbol": "MXUSDT", "side": "BUY", "type": "LIMIT", # "quantity": "1", "price": "0.1" # }, # { # "symbol": "MXUSDT", "side": "SELL", "type": "LIMIT", # "quantity": "1", "price": "10.0" # } # ] # try: # # 注意:此端点可能需要特定权限,或者可能不是测试端点。 # # 请谨慎使用,如果可能,请在测试网上进行。 # # /order/test 端点更适合测试订单创建逻辑。 # # batch_response = client.trade.post_batchorders(sample_batch_orders) # # print(f"批量下单响应: {batch_response}") # print(" 此示例中跳过批量下单测试,以避免实际创建订单。") # except Exception as e_batch: # print(f" 批量下单请求期间出错: {e_batch}") # 测试获取挂单示例 # print("\n获取 BTCUSDT 当前挂单 (如有)...") # open_orders = client.trade.get_openorders(params={"symbol": "RATOUSDT"}) # if isinstance(open_orders, list): # print(f" 找到 {len(open_orders)} 个 BTCUSDT 的挂单。") # for order in open_orders: # print(f" - 订单 ID: {order.get('orderId')}, 价格: {order.get('price')}") # # print(client.trade.delete_order(params={"symbol": "RATOUSDT", "orderId": order.get('orderId')})) # else: # print(f" 挂单响应: {open_orders}") # coin_list = client.wallet.get_coinlist() # for coin in coin_list: # if 'USDT' in coin['coin']: # networklist = coin['networkList'] # for network in networklist: # print(network) ''' { 'coin': 'USDT', 'depositDesc': None, 'depositEnable': True, 'minConfirm': 96, 'name': 'Tether', 'network': 'Ethereum(ERC20)', <- 🤡这个字段不是哦,也不能填这个Ethereum(ERC20) 'withdrawEnable': True, 'withdrawFee': '0.5', 'withdrawIntegerMultiple': None, 'withdrawMax': '26000000', 'withdrawMin': '10', 'sameAddress': False, 'contract': '0xdac17f958d2ee523a2206206994597c13d831ec7', 'withdrawTips': None, 'depositTips': None, 'netWork': 'ETH' <- 🤡这个字段才是要的 } ''' # ''' # 幣種信息獲取 # [{'coin': 'STPT', # 'name': 'STP', # 'networkList': [{'coin': 'STPT', # 'contract': '0xDe7D85157d9714EADf595045CC12Ca4A5f3E2aDb', # 'depositDesc': 'Deposit suspended as project upgrade is in ' # 'progress', # 'depositEnable': False, # 'depositTips': None, # 'minConfirm': 96, # 'name': 'STP', # 'netWork': 'NONE', # 'network': 'NONE', # 'sameAddress': False, # 'withdrawEnable': False, # 'withdrawFee': '0', # 'withdrawIntegerMultiple': None, # 'withdrawMax': '800000000', # 'withdrawMin': '800000000', # 'withdrawTips': None}]}] # ''' # all_coin_list = client.wallet.get_coinlist() # pprint(all_coin_list[:2]) # print("\n测试下单 (POST /order/test)...") # test_order_params = { # "symbol": "RATOUSDT", # 使用常见的交易对,如 MXUSDT 或 BTCUSDT # "side": "SELL", "quantity": "650000", # 以【幣】的數量進行買賣 # # "side": "BUY", "quoteOrderQty": "13.7" # 以【U】的數量進行買賣! # "type": "MARKET", # # "price": "0.0000290" # 调整价格以便于测试 # } # print(f" 测试订单参数: {test_order_params}") # test_order_response = client.trade.post_order(params=test_order_params) # print(f"测试订单响应: {test_order_response}") ''' {'symbol': 'RATOUSDT', 'orderId': 'C02__554739165556662272055', 'orderListId': -1, 'clientOrderId': None, 'price': '0.00001259', 'origQty': '28000000', 'executedQty': '14714393.18', 'cummulativeQuoteQty': '186.6202641971', 'status': 'PARTIALLY_CANCELED', 'timeInForce': None, 'type': 'MARKET', 'side': 'SELL', 'stopPrice': None, 'icebergQty': None, 'time': 1748042359000, 'updateTime': 1748042360000, 'isWorking': True, 'origQuoteOrderQty': '0'} ''' # params = { # "symbol": "RATOUSDT", # "orderId": "C02__554739165556662272055" # } # order = client.trade.get_order(params) # logging.info(order) # from config import wallet # print("\n提币测试...") # withdraw_params = { # 'coin': 'USDT', # 'netWork': 'ETH', # 'address': wallet["user_wallet"], # 'amount': 30 # } # withdraw_rst = client.wallet.post_withdraw(withdraw_params) # print(f" 提幣响应:{withdraw_rst}") # print("\n获取提币历史信息...") # withdraw_list = client.wallet.get_withdraw_list() # print("历史信息:") # for withdraw in withdraw_list[0:20]: # print(f" {withdraw}") # print("\n充币历史信息,默认返回最近7天以内的") # params = { # "coin":"RATO", # # "startTime":"1747015200000", # # "endTime":"1747274400000" # } # deposit_list = client.wallet.get_deposit_list(params) # for deposit in deposit_list[0:5]: # print(f" {deposit}") ''' {'exchangeFilters': [], 'rateLimits': [], 'serverTime': 1752648491330, 'symbols': [{'baseAsset': 'RATO', 'baseAssetPrecision': 2, // 交易币精度 'baseCommissionPrecision': 2, 'baseSizePrecision': '0', 'filters': [], 'fullName': 'Rato The Rat', 'isMarginTradingAllowed': False, 'isSpotTradingAllowed': True, 'makerCommission': '0', 'maxQuoteAmount': '2000000', 'maxQuoteAmountMarket': '100000', 'orderTypes': ['LIMIT', 'MARKET', 'LIMIT_MAKER'], 'permissions': ['SPOT'], 'quoteAmountPrecision': '1', 'quoteAmountPrecisionMarket': '1', 'quoteAsset': 'USDT', 'quoteAssetPrecision': 9, // 计价币精度 'quoteCommissionPrecision': 9, 'quotePrecision': 9, // 交易对价格精度 'st': False, 'status': '1', 'symbol': 'RATOUSDT', 'takerCommission': '0.0005', 'tradeSideType': 1}], 'timezone': 'CST'} ''' # params = { # "symbols": "MANYUUSDT", # } # info = client.market.get_exchangeInfo(params) # pprint(info) except requests.exceptions.RequestException as e: print(f" 私有 API 请求期间出错: {e}") if e.response is not None: print(f" 响应状态码: {e.response.status_code}") print(f" 响应文本: {e.response.text}") except Exception as e: print(f" 发生意外错误: {e}") print("\n--- 所有测试完成 ---")