| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670 |
- 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--- 所有测试完成 ---")
|