From d7c9b1fd08d526a9ed8e7f2a93519cb7356018fa Mon Sep 17 00:00:00 2001 From: "ivan.z-apx" Date: Thu, 22 Jan 2026 20:17:02 +0800 Subject: [PATCH 1/5] eip172 --- aster-finance-futures-api-v3.md | 365 +++++++---------------------- aster-finance-futures-api-v3_CN.md | 353 +++++++--------------------- 2 files changed, 161 insertions(+), 557 deletions(-) diff --git a/aster-finance-futures-api-v3.md b/aster-finance-futures-api-v3.md index 5842451..aebe160 100644 --- a/aster-finance-futures-api-v3.md +++ b/aster-finance-futures-api-v3.md @@ -12,8 +12,6 @@ - [Timing Security](#timing-security) - [Endpoints requiring signature](#endpoints-requiring-signature) - [POST /fapi/v3/order example](#example-of-post-fapiv3order) - - [GET /fapi/v3/order example](#Eexample-of-get-fapiv3order) - - [python script](#python-script) - [Public Endpoints Info](#public-endpoints-info) - [Terminology](#terminology) - [ENUM definitions](#enum-definitions) @@ -254,326 +252,125 @@ if (timestamp < (serverTime + 1000) && (serverTime - timestamp) <= recvWindow){ | privateKey | 0x4fd0a42218f3eae43a6ce26d22544e986139a01e5b34a62db53757ffca81bae1 |[Click Here](https://www.asterdex.com/en/api-wallet) | #### The nonce parameter is the current system time in microseconds. If it exceeds the system time or lags behind it by more than 5 seconds, the request is considered invalid. - ```python #python nonce = math.trunc(time.time()*1000000) print(nonce) #1748310859508867 ``` - ```java +#python //java Instant now = Instant.now(); long microsecond = now.getEpochSecond() * 1000000 + now.getNano() / 1000; ``` -#### Example: The following parameters are business request parameters. - -```python -my_dict = {'symbol': 'SANDUSDT', 'positionSide': 'BOTH', 'type': 'LIMIT', 'side': 'BUY', - 'timeInForce': 'GTC', 'quantity': "190", 'price': 0.28694} -``` -#### Example: All parameters are sent via form body (using Python as an example). +#### Example: Post an order (using Python as an example). -> **Step 1: Convert all business parameters to strings, then sort them in ASCII order to generate a string.** ```python - #Define all element values as strings. - def _trim_dict(my_dict) : - for key in my_dict: - value = my_dict[key] - if isinstance(value, list): - new_value = [] - for item in value: - if isinstance(item, dict): - new_value.append(json.dumps(_trim_dict(item))) - else: - new_value.append(str(item)) - my_dict[key] = json.dumps(new_value) - continue - if isinstance(value, dict): - my_dict[key] = json.dumps(_trim_dict(value)) - continue - my_dict[key] = str(value) - - return my_dict - - #Remove elements with null (empty) values. - my_dict = {key: value for key, value in my_dict.items() if value is not None} - my_dict['recvWindow'] = 50000 - my_dict['timestamp'] = int(round(time.time()*1000)) - # my_dict['timestamp'] = 1749545309665 - #Convert elements to strings. - _trim_dict(my_dict) - #Generate a string sorted by ASCII values and remove special characters. - json_str = json.dumps(my_dict, sort_keys=True).replace(' ', '').replace('\'','\"') - print(json_str) - #{"positionSide":"BOTH","price":"0.28694","quantity":"190","recvWindow":"50000","side":"BUY","symbol":"SANDUSDT","timeInForce":"GTC","timestamp":"1749545309665","type":"LIMIT"} -``` +import time +import requests +from eth_account.messages import encode_structured_data +from eth_account import Account -> **Step 2: Take the string generated in Step 1 and encode it together with the account information and nonce using ABI encoding to generate a hash string.** +typed_data = { + "types": { + "EIP712Domain": [ + {"name": "name", "type": "string"}, + {"name": "version", "type": "string"}, + {"name": "chainId", "type": "uint256"}, + {"name": "verifyingContract", "type": "address"} + ], + "Message": [ + { "name": "msg", "type": "string" } + ] + }, + "primaryType": "Message", + "domain": { + "name": "AsterSignTransaction", + "version": "1", + "chainId": 1666, + "verifyingContract": "0x0000000000000000000000000000000000000000" + }, + "message": { + "msg": "$msg" + } +} -```python - from eth_abi import encode - from web3 import Web3 - #Use Web3 ABI to encode the generated string along with user, signer, and nonce. - encoded = encode(['string', 'address', 'address', 'uint256'], [json_str, user, signer, nonce]) - print(encoded.hex()) - #000000000000000000000000000000000000000000000000000000000000008000000000000000000000000063dd5acc6b1aa0f563956c0e534dd30b6dcf7c4e00000000000000000000000021cf8ae13bb72632562c6fff438652ba1a151bb00000000000000000000000000000000000000000000000000006361457bcec8300000000000000000000000000000000000000000000000000000000000000af7b22706f736974696f6e53696465223a22424f5448222c227072696365223a22302e3238363934222c227175616e74697479223a22313930222c227265637657696e646f77223a223530303030222c2273696465223a22425559222c2273796d626f6c223a2253414e4455534454222c2274696d65496e466f726365223a22475443222c2274696d657374616d70223a2231373439353435333039363635222c2274797065223a224c494d4954227d0000000000000000000000000000000000 - #keccak hex - keccak_hex =Web3.keccak(encoded).hex() - print(keccak_hex) - #9e0273fc91323f5cdbcb00c358be3dee2854afb2d3e4c68497364a2f27a377fc -``` +headers = { + 'Content-Type': 'application/x-www-form-urlencoded', + 'User-Agent': 'PythonApp/1.0' +} +order_url = 'https://fapi.asterdex-testnet.com/fapi/v3/order' -> **Step 3: Sign the hash generated in Step 2 using the privateKey.** +# config your user and agent info here +user = '*' +signer = '*' +private_key = "*" -```python - from eth_account import Account - from eth_abi import encode - from web3 import Web3, EthereumTesterProvider - from eth_account.messages import encode_defunct - - signable_msg = encode_defunct(hexstr=keccak_hex) - signed_message = Account.sign_message(signable_message=signable_msg, private_key=priKey) - signature = '0x'+signed_message.signature.hex() - print(signature) - #0x0337dd720a21543b80ff861cd3c26646b75b3a6a4b5d45805d4c1d6ad6fc33e65f0722778dd97525466560c69fbddbe6874eb4ed6f5fa7e576e486d9b5da67f31b -``` +def get_url(my_dict) -> str: + return '&'.join(f'{key}={str(value)}'for key, value in my_dict.items()) -> **Step 4: Combine all parameters along with the signature generated in Step 3 into the request body.** +_last_ms = 0 +_i = 0 -```python - my_dict['nonce'] = nonce - my_dict['user'] = user - my_dict['signer'] = signer - my_dict['signature'] = '0x'+signed_message.signature.hex() - url ='https://fapi.asterdex.com/fapi/v3/order' - headers = { - 'Content-Type': 'application/x-www-form-urlencoded', - 'User-Agent': 'PythonApp/1.0' - } - res = requests.post(url,data=my_dict,headers=headers) - print(url) - #curl -X POST 'https://fapi.asterdex.com/fapi/v3/order' -d 'symbol=SANDUSDT&positionSide=BOTH&type=LIMIT&side=BUY&timeInForce=GTC&quantity=190&price=0.28694&recvWindow=50000×tamp=1749545309665&nonce=1748310859508867&user=0x63DD5aCC6b1aa0f563956C0e534DD30B6dcF7C4e&signer=0x21cF8Ae13Bb72632562c6Fff438652Ba1a151bb0&signature=0x0337dd720a21543b80ff861cd3c26646b75b3a6a4b5d45805d4c1d6ad6fc33e65f0722778dd97525466560c69fbddbe6874eb4ed6f5fa7e576e486d9b5da67f31b' -``` +def get_nonce(): + global _last_ms, _i + now_ms = int(time.time()) -## Example of POST /fapi/v3/order + if now_ms == _last_ms: + _i += 1 + else: + _last_ms = now_ms + _i = 0 -#### Example: All parameters are sent through the query string (Python 3.9.6). + return now_ms * 1_000_000 + _i -#### Example: The following parameters are API registration information. user, signer, and privateKey are for demonstration purposes only (where privateKey is the private key of the agent). +def send_by_url() : + param = 'symbol=ASTERUSDT&side=BUY&type=LIMIT&quantity=10&price=0.6&timeInForce=GTC' -| Key | Value | -| ---------- | ------------------------------------------------------------------ | -| user | 0x63DD5aCC6b1aa0f563956C0e534DD30B6dcF7C4e | -| signer | 0x21cF8Ae13Bb72632562c6Fff438652Ba1a151bb0 | -| privateKey | 0x4fd0a42218f3eae43a6ce26d22544e986139a01e5b34a62db53757ffca81bae1 | + param += '&nonce=' + str(get_nonce()) + param += '&user=' + user + param += '&signer=' + signer -#### Example: The nonce parameter should be the current system timestamp in microseconds. If it exceeds the current time or lags behind the system time by more than 5 seconds, it will be considered an invalid request. + typed_data['message']['msg'] = param + message = encode_structured_data(typed_data) + signed = Account.sign_message(message, private_key=private_key) + print(signed.signature.hex()) -```python -#python -nonce = math.trunc(time.time()*1000000) -print(nonce) -#1748310859508867 -``` + url = order_url + '?' + param + '&signature=' + signed.signature.hex() -```java -//java -Instant now = Instant.now(); -long microsecond = now.getEpochSecond() * 1000000 + now.getNano() / 1000; -``` - -#### Example: The following parameters are business request parameters. - -```python -my_dict = {'symbol':'SANDUSDT','side':"SELL","type":'LIMIT','orderId':2194215} -``` - -> **Step 1: Convert all business parameters to strings and generate a sorted string based on ASCII order.** - -```python - #Define all element values as strings. - def _trim_dict(my_dict) : - # 假设待删除的字典为d - for key in my_dict: - value = my_dict[key] - if isinstance(value, list): - new_value = [] - for item in value: - if isinstance(item, dict): - new_value.append(json.dumps(_trim_dict(item))) - else: - new_value.append(str(item)) - my_dict[key] = json.dumps(new_value) - continue - if isinstance(value, dict): - my_dict[key] = json.dumps(_trim_dict(value)) - continue - my_dict[key] = str(value) - - return my_dict - - - #Remove elements with empty values. - my_dict = {key: value for key, value in my_dict.items() if value is not None} - my_dict['recvWindow'] = 50000 - my_dict['timestamp'] = int(round(time.time()*1000)) - # my_dict['timestamp'] = 1749545309665 - #Convert all elements to strings. - _trim_dict(my_dict) - #Generate a string sorted by ASCII values and remove special characters. - json_str = json.dumps(my_dict, sort_keys=True).replace(' ', '').replace('\'','\"') - print(json_str) - #{"orderId":"2194215","recvWindow":"50000","side":"BUY","symbol":"SANDUSDT","timestamp":"1749545309665","type":"LIMIT"} -``` - -> **Step 2: Use ABI encoding to combine the string from step 1 with the account information (user, signer) and nonce, then generate a hash string from the encoded result.** - -```python - from eth_abi import encode - from web3 import Web3 - - #Use WEB3 ABI to encode the generated string together with user, signer, and nonce. - encoded = encode(['string', 'address', 'address', 'uint256'], [json_str, user, signer, nonce]) - print(encoded.hex()) - #000000000000000000000000000000000000000000000000000000000000008000000000000000000000000063dd5acc6b1aa0f563956c0e534dd30b6dcf7c4e00000000000000000000000021cf8ae13bb72632562c6fff438652ba1a151bb00000000000000000000000000000000000000000000000000006361457bcec8300000000000000000000000000000000000000000000000000000000000000767b226f726465724964223a2232313934323135222c227265637657696e646f77223a223530303030222c2273696465223a22425559222c2273796d626f6c223a2253414e4455534454222c2274696d657374616d70223a2231373439353435333039363635222c2274797065223a224c494d4954227d00000000000000000000 - keccak_hex =Web3.keccak(encoded).hex() - print(keccak_hex) - #6ad9569ea1355bf62de1b09b33b267a9404239af6d9227fa59e3633edae19e2a -``` + print(url) + res = requests.post(url, headers=headers) -> **Step 3: Sign the hash generated in Step 2 using the privateKey.** + print(res.text) -```python -from eth_account import Account - from eth_abi import encode - from web3 import Web3, EthereumTesterProvider - from eth_account.messages import encode_defunct - - signable_msg = encode_defunct(hexstr=keccak_hex) - signed_message = Account.sign_message(signable_message=signable_msg, private_key=priKey) - signature = '0x'+signed_message.signature.hex() - print(signature) - #0x4f5e36e91f0d4cf5b29b6559ebc2c808d3c808ebb13b2bcaaa478b98fb4195642c7473f0d1aa101359aaf278126af1a53bcb482fb05003bfb6bdc03de03c63151b -``` +def send_by_body() : + my_dict = {"symbol": "ASTERUSDT", "type": "LIMIT", "side": "BUY", + "timeInForce": "GTC", "quantity": "10", "price": "0.6"} -> **Step 4: Combine all parameters and the signature from Step 3 into the request body.** + my_dict['nonce'] = str(get_nonce()) + my_dict['user'] = user + my_dict['signer'] = signer -```python - my_dict['nonce'] = nonce - my_dict['user'] = user - my_dict['signer'] = signer - my_dict['signature'] = '0x'+signed_message.signature.hex() + content = get_url(my_dict) + typed_data['message']['msg'] = content + message = encode_structured_data(typed_data) - url ='https://fapi.asterdex.com/fapi/v3/order' + signed = Account.sign_message(message, private_key=private_key) + print(signed.signature.hex()) - res = requests.get(url, params=my_dict) - print(url) - #curl -X GET 'https://fapi.asterdex.com/fapi/v3/order?symbol=SANDUSDT&side=BUY&type=LIMIT&orderId=2194215&recvWindow=50000×tamp=1749545309665&nonce=1748310859508867&user=0x63DD5aCC6b1aa0f563956C0e534DD30B6dcF7C4e&signer=0x21cF8Ae13Bb72632562c6Fff438652Ba1a151bb0&signature=0x4f5e36e91f0d4cf5b29b6559ebc2c808d3c808ebb13b2bcaaa478b98fb4195642c7473f0d1aa101359aaf278126af1a53bcb482fb05003bfb6bdc03de03c63151b' -``` + my_dict['signature'] = signed.signature.hex() -## python script + print(my_dict) + res = requests.post(order_url, data=my_dict, headers=headers) -```python -#Python 3.9.6 -#Python 3.9.6 -#eth-account~=0.13.7 -#eth-abi~=5.2.0 -#web3~=7.11.0 -#requests~=2.32.3 - -import json -import math -import time -import requests - -from eth_abi import encode -from eth_account import Account -from eth_account.messages import encode_defunct -from web3 import Web3 - -user = '0x63DD5aCC6b1aa0f563956C0e534DD30B6dcF7C4e' -signer='0x21cF8Ae13Bb72632562c6Fff438652Ba1a151bb0' -priKey = "0x4fd0a42218f3eae43a6ce26d22544e986139a01e5b34a62db53757ffca81bae1" -host = 'https://fapi.asterdex.com' -placeOrder = {'url': '/fapi/v3/order', 'method': 'POST', - 'params':{'symbol': 'SANDUSDT', 'positionSide': 'BOTH', 'type': 'LIMIT', 'side': 'BUY', - 'timeInForce': 'GTC', 'quantity': "30", 'price': 0.325,'reduceOnly': True}} -getOrder = {'url':'/fapi/v3/order','method':'GET','params':{'symbol':'SANDUSDT','side':"BUY","type":'LIMIT','orderId':2194215}} - -def call(api): - nonce = math.trunc(time.time() * 1000000) - my_dict = api['params'] - send(api['url'],api['method'],sign(my_dict,nonce)) - -def sign(my_dict,nonce): - my_dict = {key: value for key, value in my_dict.items() if value is not None} - my_dict['recvWindow'] = 50000 - my_dict['timestamp'] = int(round(time.time()*1000)) - msg = trim_param(my_dict,nonce) - signable_msg = encode_defunct(hexstr=msg) - signed_message = Account.sign_message(signable_message=signable_msg, private_key=priKey) - my_dict['nonce'] = nonce - my_dict['user'] = user - my_dict['signer'] = signer - my_dict['signature'] = '0x'+signed_message.signature.hex() - - print(my_dict['signature']) - return my_dict - -def trim_param(my_dict,nonce) -> str: - _trim_dict(my_dict) - json_str = json.dumps(my_dict, sort_keys=True).replace(' ', '').replace('\'','\"') - print(json_str) - encoded = encode(['string', 'address', 'address', 'uint256'], [json_str, user, signer, nonce]) - print(encoded.hex()) - keccak_hex =Web3.keccak(encoded).hex() - print(keccak_hex) - return keccak_hex - -def _trim_dict(my_dict) : - for key in my_dict: - value = my_dict[key] - if isinstance(value, list): - new_value = [] - for item in value: - if isinstance(item, dict): - new_value.append(json.dumps(_trim_dict(item))) - else: - new_value.append(str(item)) - my_dict[key] = json.dumps(new_value) - continue - if isinstance(value, dict): - my_dict[key] = json.dumps(_trim_dict(value)) - continue - my_dict[key] = str(value) - - return my_dict - -def send(url, method, my_dict): - url = host + url - print(url) - print(my_dict) - if method == 'POST': - headers = { - 'Content-Type': 'application/x-www-form-urlencoded', - 'User-Agent': 'PythonApp/1.0' - } - res = requests.post(url, data=my_dict, headers=headers) - print(res.text) - if method == 'GET': - res = requests.get(url, params=my_dict) - print(res.text) - if method == 'DELETE': - res = requests.delete(url, data=my_dict) - print(res.text) + print(res.text) if __name__ == '__main__': - call(placeOrder) - # call(getOrder) + send_by_url() + # send_by_body() ``` ## Public Endpoints Info diff --git a/aster-finance-futures-api-v3_CN.md b/aster-finance-futures-api-v3_CN.md index 649a3fe..f45078a 100644 --- a/aster-finance-futures-api-v3_CN.md +++ b/aster-finance-futures-api-v3_CN.md @@ -11,8 +11,6 @@ - [需要签名的接口](#需要签名的接口) - [时间同步安全](#时间同步安全) - [POST /fapi/v3/order 的示例](#post-fapiv3order-的示例) - - [GET /fapi/v3/order 的示例](#get-fapiv3order-的示例) - - [完整python脚本示例](#完整python脚本示例) - [公开API参数](#公开api参数) - [术语解释](#术语解释) - [枚举定义](#枚举定义) @@ -250,302 +248,111 @@ Instant now = Instant.now(); long microsecond = now.getEpochSecond() * 1000000 + now.getNano() / 1000; ``` -#### 示例 : 以下参数为业务请求参数 +#### 示例 : 下单 (方法以python为例) ```python - my_dict = {'symbol': 'SANDUSDT', 'positionSide': 'BOTH', 'type': 'LIMIT', 'side': 'BUY', - 'timeInForce': 'GTC', 'quantity': "190", 'price': 0.28694} -``` +import time +import requests +from eth_account.messages import encode_structured_data +from eth_account import Account -#### 示例 : 所有参数通过 form body 发送(方法以python为例) +typed_data = { + "types": { + "EIP712Domain": [ + {"name": "name", "type": "string"}, + {"name": "version", "type": "string"}, + {"name": "chainId", "type": "uint256"}, + {"name": "verifyingContract", "type": "address"} + ], + "Message": [ + { "name": "msg", "type": "string" } + ] + }, + "primaryType": "Message", + "domain": { + "name": "AsterSignTransaction", + "version": "1", + "chainId": 1666, + "verifyingContract": "0x0000000000000000000000000000000000000000" + }, + "message": { + "msg": "$msg" + } +} -> **第一步将所有业务参数转字符串后按照ascII排序生成字符串:** +headers = { + 'Content-Type': 'application/x-www-form-urlencoded', + 'User-Agent': 'PythonApp/1.0' +} +order_url = 'https://fapi.asterdex-testnet.com/fapi/v3/order' -```python - #定义所有元素取值转换为字符串 - def _trim_dict(my_dict) : - # 假设待删除的字典为d - for key in my_dict: - value = my_dict[key] - if isinstance(value, list): - new_value = [] - for item in value: - if isinstance(item, dict): - new_value.append(json.dumps(_trim_dict(item))) - else: - new_value.append(str(item)) - my_dict[key] = json.dumps(new_value) - continue - if isinstance(value, dict): - my_dict[key] = json.dumps(_trim_dict(value)) - continue - my_dict[key] = str(value) - - return my_dict - - #移除空值元素 - my_dict = {key: value for key, value in my_dict.items() if value is not None} - my_dict['recvWindow'] = 50000 - my_dict['timestamp'] = int(round(time.time()*1000)) - # my_dict['timestamp'] = 1749545309665 - #将元素转换为字符串 - _trim_dict(my_dict) - #根据ASCII排序生成字符串并移除特殊字符 - json_str = json.dumps(my_dict, sort_keys=True).replace(' ', '').replace('\'','\"') - print(json_str) - {"positionSide":"BOTH","price":"0.28694","quantity":"190","recvWindow":"50000","side":"BUY","symbol":"SANDUSDT","timeInForce":"GTC","timestamp":"1749545309665","type":"LIMIT"} -``` +# config your user and agent info here +user = '*' +signer = '*' +private_key = "*" -> **第二步将第一步生成的字符串与账户信息以及nonce进行abi编码生成hash字符串:** +def get_url(my_dict) -> str: + return '&'.join(f'{key}={str(value)}'for key, value in my_dict.items()) -```python - from eth_abi import encode - from web3 import Web3 - #使用WEB3 ABI对生成的字符串和user, signer, nonce进行编码 - encoded = encode(['string', 'address', 'address', 'uint256'], [json_str, user, signer, nonce]) - print(encoded.hex()) - #000000000000000000000000000000000000000000000000000000000000008000000000000000000000000063dd5acc6b1aa0f563956c0e534dd30b6dcf7c4e00000000000000000000000021cf8ae13bb72632562c6fff438652ba1a151bb00000000000000000000000000000000000000000000000000006361457bcec8300000000000000000000000000000000000000000000000000000000000000af7b22706f736974696f6e53696465223a22424f5448222c227072696365223a22302e3238363934222c227175616e74697479223a22313930222c227265637657696e646f77223a223530303030222c2273696465223a22425559222c2273796d626f6c223a2253414e4455534454222c2274696d65496e466f726365223a22475443222c2274696d657374616d70223a2231373439353435333039363635222c2274797065223a224c494d4954227d0000000000000000000000000000000000 - #keccak hex - keccak_hex =Web3.keccak(encoded).hex() - print(keccak_hex) - #9e0273fc91323f5cdbcb00c358be3dee2854afb2d3e4c68497364a2f27a377fc -``` -> **第三步将第二步生成的hash用privateKey进行签名:** -```python - from eth_account import Account - from eth_abi import encode - from web3 import Web3, EthereumTesterProvider - from eth_account.messages import encode_defunct - - signable_msg = encode_defunct(hexstr=keccak_hex) - signed_message = Account.sign_message(signable_message=signable_msg, private_key=priKey) - signature = '0x'+signed_message.signature.hex() - print(signature) - #0x0337dd720a21543b80ff861cd3c26646b75b3a6a4b5d45805d4c1d6ad6fc33e65f0722778dd97525466560c69fbddbe6874eb4ed6f5fa7e576e486d9b5da67f31b -``` -> **第四步将所有参数以及第三步生成的signature组装成请求体:** +_last_ms = 0 +_i = 0 -```python - my_dict['nonce'] = nonce - my_dict['user'] = user - my_dict['signer'] = signer - my_dict['signature'] = '0x'+signed_message.signature.hex() - url ='https://fapi.asterdex.com/fapi/v3/order' - headers = { - 'Content-Type': 'application/x-www-form-urlencoded', - 'User-Agent': 'PythonApp/1.0' - } - res = requests.post(url,data=my_dict,headers=headers) - print(url) - #curl -X POST 'https://fapi.asterdex.com/fapi/v3/order' -d 'symbol=SANDUSDT&positionSide=BOTH&type=LIMIT&side=BUY&timeInForce=GTC&quantity=190&price=0.28694&recvWindow=50000×tamp=1749545309665&nonce=1748310859508867&user=0x63DD5aCC6b1aa0f563956C0e534DD30B6dcF7C4e&signer=0x21cF8Ae13Bb72632562c6Fff438652Ba1a151bb0&signature=0x0337dd720a21543b80ff861cd3c26646b75b3a6a4b5d45805d4c1d6ad6fc33e65f0722778dd97525466560c69fbddbe6874eb4ed6f5fa7e576e486d9b5da67f31b' +def get_nonce(): + global _last_ms, _i + now_ms = int(time.time()) -``` + if now_ms == _last_ms: + _i += 1 + else: + _last_ms = now_ms + _i = 0 -## GET /fapi/v3/order 的示例 -#### 示例 : 所有参数通过 query string 发送(Python 3.9.6) + return now_ms * 1_000_000 + _i -#### 示例 : 以下参数为api注册信息,user,signer,privateKey仅供示范(privateKey为agent的私钥) +def send_by_url() : + param = 'symbol=ASTERUSDT&side=BUY&type=LIMIT&quantity=10&price=0.6&timeInForce=GTC' -Key | Value ------------- | ------------ -user | 0x63DD5aCC6b1aa0f563956C0e534DD30B6dcF7C4e -signer | 0x21cF8Ae13Bb72632562c6Fff438652Ba1a151bb0 -privateKey | 0x4fd0a42218f3eae43a6ce26d22544e986139a01e5b34a62db53757ffca81bae1 + param += '&nonce=' + str(get_nonce()) + param += '&user=' + user + param += '&signer=' + signer -#### 示例 : nonce参数为当前系统微秒值,超过系统时间50s,或者落后系统时间超过5s为非法请求 -```python -#python -nonce = math.trunc(time.time()*1000000) -print(nonce) -#1748310859508867 -``` -```java -//java -Instant now = Instant.now(); -long microsecond = now.getEpochSecond() * 1000000 + now.getNano() / 1000; -``` + typed_data['message']['msg'] = param + message = encode_structured_data(typed_data) + signed = Account.sign_message(message, private_key=private_key) + print(signed.signature.hex()) -#### 示例 : 以下参数为业务请求参数 -```python -my_dict = {'symbol':'SANDUSDT','side':"SELL","type":'LIMIT','orderId':2194215} -``` + url = order_url + '?' + param + '&signature=' + signed.signature.hex() -> **第一步将所有业务参数转字符串后按照ascII排序生成字符串:** + print(url) + res = requests.post(url, headers=headers) -```python - #定义所有元素取值转换为字符串 - def _trim_dict(my_dict) : - for key in my_dict: - value = my_dict[key] - if isinstance(value, list): - new_value = [] - for item in value: - if isinstance(item, dict): - new_value.append(json.dumps(_trim_dict(item))) - else: - new_value.append(str(item)) - my_dict[key] = json.dumps(new_value) - continue - if isinstance(value, dict): - my_dict[key] = json.dumps(_trim_dict(value)) - continue - my_dict[key] = str(value) - - return my_dict - - #移除空值元素 - my_dict = {key: value for key, value in my_dict.items() if value is not None} - my_dict['recvWindow'] = 50000 - my_dict['timestamp'] = int(round(time.time()*1000)) - # my_dict['timestamp'] = 1749545309665 - #将元素转换为字符串 - _trim_dict(my_dict) - #根据ASCII排序生成字符串并移除特殊字符 - json_str = json.dumps(my_dict, sort_keys=True).replace(' ', '').replace('\'','\"') - print(json_str) - #{"orderId":"2194215","recvWindow":"50000","side":"BUY","symbol":"SANDUSDT","timestamp":"1749545309665","type":"LIMIT"} -``` + print(res.text) -> **第二步将第一步生成的字符串与账户信息以及nonce进行abi编码生成hash字符串:** +def send_by_body() : + my_dict = {"symbol": "ASTERUSDT", "type": "LIMIT", "side": "BUY", + "timeInForce": "GTC", "quantity": "10", "price": "0.6"} -```python - from eth_abi import encode - from web3 import Web3 - - #使用WEB3 ABI对生成的字符串和user, signer, nonce进行编码 - encoded = encode(['string', 'address', 'address', 'uint256'], [json_str, user, signer, nonce]) - print(encoded.hex()) - #000000000000000000000000000000000000000000000000000000000000008000000000000000000000000063dd5acc6b1aa0f563956c0e534dd30b6dcf7c4e00000000000000000000000021cf8ae13bb72632562c6fff438652ba1a151bb00000000000000000000000000000000000000000000000000006361457bcec8300000000000000000000000000000000000000000000000000000000000000767b226f726465724964223a2232313934323135222c227265637657696e646f77223a223530303030222c2273696465223a22425559222c2273796d626f6c223a2253414e4455534454222c2274696d657374616d70223a2231373439353435333039363635222c2274797065223a224c494d4954227d00000000000000000000 - keccak_hex =Web3.keccak(encoded).hex() - print(keccak_hex) - #6ad9569ea1355bf62de1b09b33b267a9404239af6d9227fa59e3633edae19e2a -``` -> **第三步将第二步生成的hash用privateKey进行签名:** -```python - from eth_account import Account - from eth_abi import encode - from web3 import Web3, EthereumTesterProvider - from eth_account.messages import encode_defunct - - signable_msg = encode_defunct(hexstr=keccak_hex) - signed_message = Account.sign_message(signable_message=signable_msg, private_key=priKey) - signature = '0x'+signed_message.signature.hex() - print(signature) - #0x4f5e36e91f0d4cf5b29b6559ebc2c808d3c808ebb13b2bcaaa478b98fb4195642c7473f0d1aa101359aaf278126af1a53bcb482fb05003bfb6bdc03de03c63151b -``` -> **第四步将所有参数以及第三步生成的signature组装成请求体:** + my_dict['nonce'] = str(get_nonce()) + my_dict['user'] = user + my_dict['signer'] = signer -```python - my_dict['nonce'] = nonce - my_dict['user'] = user - my_dict['signer'] = signer - my_dict['signature'] = '0x'+signed_message.signature.hex() + content = get_url(my_dict) + typed_data['message']['msg'] = content + message = encode_structured_data(typed_data) - url ='https://fapi.asterdex.com/fapi/v3/order' + signed = Account.sign_message(message, private_key=private_key) + print(signed.signature.hex()) - res = requests.get(url, params=my_dict) - print(url) - #curl -X GET 'https://fapi.asterdex.com/fapi/v3/order?symbol=SANDUSDT&side=BUY&type=LIMIT&orderId=2194215&recvWindow=50000×tamp=1749545309665&nonce=1748310859508867&user=0x63DD5aCC6b1aa0f563956C0e534DD30B6dcF7C4e&signer=0x21cF8Ae13Bb72632562c6Fff438652Ba1a151bb0&signature=0x4f5e36e91f0d4cf5b29b6559ebc2c808d3c808ebb13b2bcaaa478b98fb4195642c7473f0d1aa101359aaf278126af1a53bcb482fb05003bfb6bdc03de03c63151b' + my_dict['signature'] = signed.signature.hex() -``` -## 完整python脚本示例 -```python -#Python 3.9.6 -#eth-account~=0.13.7 -#eth-abi~=5.2.0 -#web3~=7.11.0 -#requests~=2.32.3 - -import json -import math -import time -import requests + print(my_dict) + res = requests.post(order_url, data=my_dict, headers=headers) -from eth_abi import encode -from eth_account import Account -from eth_account.messages import encode_defunct -from web3 import Web3 - -user = '0x63DD5aCC6b1aa0f563956C0e534DD30B6dcF7C4e' -signer='0x21cF8Ae13Bb72632562c6Fff438652Ba1a151bb0' -priKey = "0x4fd0a42218f3eae43a6ce26d22544e986139a01e5b34a62db53757ffca81bae1" -host = 'https://fapi.asterdex.com' -placeOrder = {'url': '/fapi/v3/order', 'method': 'POST', - 'params':{'symbol': 'SANDUSDT', 'positionSide': 'BOTH', 'type': 'LIMIT', 'side': 'BUY', - 'timeInForce': 'GTC', 'quantity': "30", 'price': 0.325,'reduceOnly': True}} -getOrder = {'url':'/fapi/v3/order','method':'GET','params':{'symbol':'SANDUSDT','side':"BUY","type":'LIMIT','orderId':2194215}} - -def call(api): - nonce = math.trunc(time.time() * 1000000) - my_dict = api['params'] - send(api['url'],api['method'],sign(my_dict,nonce)) - -def sign(my_dict,nonce): - my_dict = {key: value for key, value in my_dict.items() if value is not None} - my_dict['recvWindow'] = 50000 - my_dict['timestamp'] = int(round(time.time()*1000)) - msg = trim_param(my_dict,nonce) - signable_msg = encode_defunct(hexstr=msg) - signed_message = Account.sign_message(signable_message=signable_msg, private_key=priKey) - my_dict['nonce'] = nonce - my_dict['user'] = user - my_dict['signer'] = signer - my_dict['signature'] = '0x'+signed_message.signature.hex() - - print(my_dict['signature']) - return my_dict - -def trim_param(my_dict,nonce) -> str: - _trim_dict(my_dict) - json_str = json.dumps(my_dict, sort_keys=True).replace(' ', '').replace('\'','\"') - print(json_str) - encoded = encode(['string', 'address', 'address', 'uint256'], [json_str, user, signer, nonce]) - print(encoded.hex()) - keccak_hex =Web3.keccak(encoded).hex() - print(keccak_hex) - return keccak_hex - -def _trim_dict(my_dict) : - for key in my_dict: - value = my_dict[key] - if isinstance(value, list): - new_value = [] - for item in value: - if isinstance(item, dict): - new_value.append(json.dumps(_trim_dict(item))) - else: - new_value.append(str(item)) - my_dict[key] = json.dumps(new_value) - continue - if isinstance(value, dict): - my_dict[key] = json.dumps(_trim_dict(value)) - continue - my_dict[key] = str(value) - - return my_dict - -def send(url, method, my_dict): - url = host + url - print(url) - print(my_dict) - if method == 'POST': - headers = { - 'Content-Type': 'application/x-www-form-urlencoded', - 'User-Agent': 'PythonApp/1.0' - } - res = requests.post(url, data=my_dict, headers=headers) - print(res.text) - if method == 'GET': - res = requests.get(url, params=my_dict) - print(res.text) - if method == 'DELETE': - res = requests.delete(url, data=my_dict) - print(res.text) + print(res.text) if __name__ == '__main__': - call(placeOrder) - # call(getOrder) - + send_by_url() + # send_by_body() ``` ## 公开API参数 From 40a38d01656ccc6435e45f1a1b685bfa0b0d31e8 Mon Sep 17 00:00:00 2001 From: "ivan.z-apx" Date: Tue, 27 Jan 2026 15:40:19 +0800 Subject: [PATCH 2/5] funding config --- aster-finance-futures-api-v3.md | 41 ++++++++++++++++++++++++++++++ aster-finance-futures-api-v3_CN.md | 39 ++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/aster-finance-futures-api-v3.md b/aster-finance-futures-api-v3.md index aebe160..8f9ed16 100644 --- a/aster-finance-futures-api-v3.md +++ b/aster-finance-futures-api-v3.md @@ -1201,6 +1201,47 @@ Mark Price and Funding Rate * If the number of data between `startTime` and `endTime` is larger than `limit`, return as `startTime` + `limit`. * In ascending order. + +## Get Funding Rate Config + +> **Response:** + +```javascript +[ + { + "symbol": "INJUSDT", + "interestRate": "0.00010000", + "time": 1756197479000, + "fundingIntervalHours": 8, + "fundingFeeCap": 0.03, + "fundingFeeFloor": -0.03 + }, + { + "symbol": "ZORAUSDT", + "interestRate": "0.00005000", + "time": 1756197479000, + "fundingIntervalHours": 4, + "fundingFeeCap": 0.02, + "fundingFeeFloor": -0.02 + } +] +``` + +`` +GET /fapi/v3/fundingInfo +`` + + +**Weight:** +1 + +**Parameters:** + +Name | Type | Mandatory | Description +------------ | ------------ | ------------ | ------------ +symbol | STRING | NO | + + ## 24hr Ticker Price Change Statistics > **Response:** diff --git a/aster-finance-futures-api-v3_CN.md b/aster-finance-futures-api-v3_CN.md index f45078a..df1b771 100644 --- a/aster-finance-futures-api-v3_CN.md +++ b/aster-finance-futures-api-v3_CN.md @@ -1205,6 +1205,45 @@ limit | INT | NO | 默认值:100 最大值:1000 * 如果 `startTime` 和 `endTime` 之间的数据量大于 `limit`, 返回 `startTime` + `limit`情况下的数据。 +## 查询资金费率配置 + +> **响应:** + +```javascript +[ + { + "symbol": "INJUSDT", // 交易对 + "interestRate": "0.00010000", // 利率 + "time": 1756197479000, // 更新时间 + "fundingIntervalHours": 8, // 资金费间隔小时数 + "fundingFeeCap": 0.03, // 资金费上限 + "fundingFeeFloor": -0.03 // 资金费下限 + }, + { + "symbol": "ZORAUSDT", + "interestRate": "0.00005000", + "time": 1756197479000, + "fundingIntervalHours": 4, + "fundingFeeCap": 0.02, + "fundingFeeFloor": -0.02 + } +] +``` + +`` +GET /fapi/v3/fundingInfo +`` + +**权重:** +1 + +**参数:** + + 名称 | 类型 | 是否必需 | 描述 +--------- | ------ | -------- | ----------------------------------------------------- +symbol | STRING | NO | 交易对 + + ## 24hr价格变动情况 > **响应:** From 5dbbd79d716990e26bdd9fd2d2aea58d2d8ca505 Mon Sep 17 00:00:00 2001 From: "ivan.z-apx" Date: Tue, 27 Jan 2026 19:07:11 +0800 Subject: [PATCH 3/5] change host --- aster-finance-futures-api-v3.md | 2 +- aster-finance-futures-api-v3_CN.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aster-finance-futures-api-v3.md b/aster-finance-futures-api-v3.md index 8f9ed16..a5beebc 100644 --- a/aster-finance-futures-api-v3.md +++ b/aster-finance-futures-api-v3.md @@ -302,7 +302,7 @@ headers = { 'Content-Type': 'application/x-www-form-urlencoded', 'User-Agent': 'PythonApp/1.0' } -order_url = 'https://fapi.asterdex-testnet.com/fapi/v3/order' +order_url = 'https://fapi.asterdex.com/fapi/v3/order' # config your user and agent info here user = '*' diff --git a/aster-finance-futures-api-v3_CN.md b/aster-finance-futures-api-v3_CN.md index df1b771..97c7447 100644 --- a/aster-finance-futures-api-v3_CN.md +++ b/aster-finance-futures-api-v3_CN.md @@ -284,7 +284,7 @@ headers = { 'Content-Type': 'application/x-www-form-urlencoded', 'User-Agent': 'PythonApp/1.0' } -order_url = 'https://fapi.asterdex-testnet.com/fapi/v3/order' +order_url = 'https://fapi.asterdex.com/fapi/v3/order' # config your user and agent info here user = '*' From 9a1a99b34156a541ea4b54a2df74d7af6d135c32 Mon Sep 17 00:00:00 2001 From: "ivan.z-apx" Date: Tue, 27 Jan 2026 19:14:59 +0800 Subject: [PATCH 4/5] add aster code demo --- demo/aster-code.py | 242 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 242 insertions(+) create mode 100644 demo/aster-code.py diff --git a/demo/aster-code.py b/demo/aster-code.py new file mode 100644 index 0000000..bbfdc21 --- /dev/null +++ b/demo/aster-code.py @@ -0,0 +1,242 @@ +import time + +import requests +from eth_account import Account +from eth_account.messages import encode_structured_data +from copy import deepcopy +import json + +host = 'https://fapi.asterdex.com' +aster_chain = 'Mainnet' +chain_id = 1666 + +# aster_chain = 'Testnet' +# chain_id = 714 + +user = '0x014c85ffb0fF2F2972237AA950B452f92C69Ae1D' +main_private_key = '*' + + +signer = '0xC98Fd64eBc39E28b92849d9cCef9495663439014' +priKey = '*' + +builder = '0x014c85ffb0fF2F2972237AA950B452f92C69Ae1D' +approveAgent = {'url': '/fapi/v3/approveAgent', 'method': 'POST', + 'params':{'agentName': 'ivanbuilder','agentAddress':signer, + 'ipWhitelist':'', 'expired':1967945395040,'canSpotTrade':True, + 'canPerpTrade':False, 'canWithdraw':False} + ,'main':True,"primary_type":"ApproveAgent"} + +updateAgent = {'url': '/fapi/v3/updateAgent', 'method': 'POST', + 'params':{'agentAddress':signer,'ipWhitelist':'101.198.86.182,192.168.1.100,192.168.1.101', + 'canSpotTrade':False, 'canPerpTrade':True, 'canWithdraw':False},'main':True,"primary_type":"UpdateAgent"} + +delAgent = {'url': '/fapi/v3/agent', 'method': 'DELETE', + 'params':{'agentAddress':signer},'main':True,"primary_type":"DelAgent"} + +getAgents = {'url': '/fapi/v3/agent', 'method': 'GET', + 'params':{}} + +approveBuilder = {'url': '/fapi/v3/approveBuilder', 'method': 'POST', + 'params': {'builder': builder, + 'maxFeeRate': '0.00001','builderName':'ivan3' }, 'main': True,"primary_type":"ApproveBuilder"} + +updateBuilder = {'url': '/fapi/v3/updateBuilder', 'method': 'POST', + 'params':{'builder': builder,'maxFeeRate': '0.00002'},'main':True,"primary_type":"UpdateBuilder"} + +delBuilder = {'url': '/fapi/v3/builder', 'method': 'DELETE', + 'params':{'builder':builder},'main':True,"primary_type":"DelBuilder"} +getBuilders = {'url': '/fapi/v3/builder', 'method': 'GET', 'params':{}} + +placeOrder = {'url': '/fapi/v3/order', 'method': 'POST', + 'params':{'symbol': 'BTCUSDT', 'type': 'MARKET','builder':builder,'feeRate':0.00001, 'side': 'BUY','quantity': "0.03"}} + + + +# 模板只包含 EIP712Domain +eip712_template = { + "types": { + "EIP712Domain": [ + {"name": "name", "type": "string"}, + {"name": "version", "type": "string"}, + {"name": "chainId", "type": "uint256"}, + {"name": "verifyingContract", "type": "address"} + ] + }, + "primaryType": "", + "domain": { + "name": "AsterSignTransaction", + "version": "1", + "chainId": 56, + "verifyingContract": "0x0000000000000000000000000000000000000000" + }, + "message": {} +} + +def infer_eip712_type(value): + """根据 Python 值推断 EIP-712 类型""" + if isinstance(value, bool): + return "bool" + elif isinstance(value, int): + # 这里假设所有整数都是 uint256 + return "uint256" + else: + return "string" + +def build_dynamic_eip712_with_infer(template: dict, primary_type: str, values: dict) -> dict: + eip712_data = deepcopy(template) + eip712_data["primaryType"] = primary_type + + # 自动生成主类型 fields + type_fields = [] + for name, val in values.items(): + type_fields.append({"name": name, "type": infer_eip712_type(val)}) + + eip712_data["types"][primary_type] = type_fields + + # 填充 message + eip712_data["message"] = values + return eip712_data + +def sign_v3_eip712(private_key, message, primary_type) -> str: + new_dict = {k[:1].upper() + k[1:]: v for k, v in message.items()} + + sign_data = build_dynamic_eip712_with_infer( + template=eip712_template, + primary_type=primary_type, + values=new_dict + ) + # sign_data['message'] = new_dict + + data = json.dumps(sign_data, indent=2) + print(data) + + print(sign_data) + msg = encode_structured_data(sign_data) + signed = Account.sign_message(msg, private_key=private_key) + return signed.signature.hex() + +def get_url(my_dict) -> str: + if my_dict is None: + return '' + if len(my_dict) == 0: + return '' + return '&'.join(f'{key}={str(value)}'for key, value in my_dict.items()) + +def sign_v3(private_key, message) -> str: + typed_data_sign = { + "types": { + "EIP712Domain": [ + {"name": "name", "type": "string"}, + {"name": "version", "type": "string"}, + {"name": "chainId", "type": "uint256"}, + {"name": "verifyingContract", "type": "address"} + ], + "Message": [ + {"name": "msg", "type": "string"} + ] + }, + "primaryType": "Message", + "domain": { + "name": "AsterSignTransaction", + "version": "1", + "chainId": chain_id, + "verifyingContract": "0x0000000000000000000000000000000000000000" + }, + "message": { + "msg": message + } + } + # print(typed_data_sign) + # print(message) + + msg = encode_structured_data(typed_data_sign) + signed = Account.sign_message(msg, private_key=private_key) + print(signed.signature.hex()) + + return signed.signature.hex() + +_last_ms = 0 +_i = 0 + +def get_nonce(): + global _last_ms, _i + now_ms = int(time.time()) + + if now_ms == _last_ms: + _i += 1 + else: + _last_ms = now_ms + _i = 0 + + return now_ms * 1_000_000 + _i + +def send_by_url(method_config): + param = method_config['params'] + config_url = method_config['url'] + method = method_config['method'] + primary_type = method_config.get('primary_type') + sign_private_key = main_private_key + main = method_config.get('main') is not None + + param['asterChain'] = aster_chain + param['user'] = user + if not main: + sign_private_key = priKey + param['signer'] = signer + + nonce = get_nonce() + param['nonce'] = nonce + + url = '' + signature ='' + if main: + signature = sign_v3_eip712(sign_private_key, param, primary_type) + param['signature'] = signature + param['signatureChainId'] = 56 + + # url = host + config_url + '?' + get_url(param) + url = host + config_url + + else: + url_param = get_url(param) + url = host + config_url + '?' + url_param + signature = sign_v3(sign_private_key, url_param) + url = url + '&signature=' + signature + + + print(signature) + print(url) + + headers = { + 'Content-Type': 'application/x-www-form-urlencoded', + 'User-Agent': 'PythonApp/1.0' + } + + if method == 'POST': + res = requests.post(url, headers=headers,data=param) + print(res.text) + if method == 'GET': + res = requests.get(url, headers=headers) + print(res.text) + if method == 'DELETE': + # res = requests.delete(url, headers=headers) + res = requests.delete(url, headers=headers,data=param) + + print(res.text) + + +if __name__ == '__main__': + send_by_url(approveAgent) + # send_by_url(updateAgent) + # send_by_url(getAgents) + # send_by_url(delAgent) + + # send_by_url(approveBuilder) + # send_by_url(getBuilders) + # send_by_url(updateBuilder) + # send_by_url(delBuilder) + # send_by_url(placeOrder) + + + From 22c2fff033454f7d0eb79ae190f67d51b7bf6236 Mon Sep 17 00:00:00 2001 From: "ivan.z-apx" Date: Tue, 27 Jan 2026 20:18:29 +0800 Subject: [PATCH 5/5] transfer --- aster-finance-futures-api-v3.md | 4 ++-- aster-finance-futures-api-v3_CN.md | 31 ++++++++++++++++++++++++++++++ aster-finance-futures-api.md | 2 +- aster-finance-futures-api_CN.md | 2 +- 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/aster-finance-futures-api-v3.md b/aster-finance-futures-api-v3.md index a5beebc..dfc07c4 100644 --- a/aster-finance-futures-api-v3.md +++ b/aster-finance-futures-api-v3.md @@ -2316,7 +2316,7 @@ Additional mandatory parameters based on `type`: * The order of returned contents for batch orders is the same as the order of the order list. -## Transfer Between Futures And Spot (USER_DATA) +## Transfer Between Futures And Spot (TRANSFER) > **Response:** @@ -2328,7 +2328,7 @@ Additional mandatory parameters based on `type`: ``` `` -POST /fapi/v3/asset/wallet/transfer (HMAC SHA256) +POST /fapi/v3/asset/wallet/transfer (TRANSFER) `` **Weight:** diff --git a/aster-finance-futures-api-v3_CN.md b/aster-finance-futures-api-v3_CN.md index 97c7447..ef4da52 100644 --- a/aster-finance-futures-api-v3_CN.md +++ b/aster-finance-futures-api-v3_CN.md @@ -2395,6 +2395,37 @@ newOrderRespType | ENUM | NO | "ACK", "RESULT", 默认 "ACK" +## 期货现货互转 (TRANSFER) + +> **响应:** + +```javascript +{ + "tranId": 21841, //交易id + "status": "SUCCESS" //状态 +} +``` + +`` +POST /fapi/v3/asset/wallet/transfer (TRANSFER) +`` + +**权重:** +5 + +**参数:** + + +名称 | 类型 | 是否必需 | 描述 +---------------- | ------- | -------- | ---- +amount | DECIMAL | YES | 数量 +asset | STRING | YES | 资产 +clientTranId | STRING | YES | 交易id +kindType | STRING | YES | 交易类型 +timestamp | LONG | YES | 时间戳 + +* kindType 取值为FUTURE_SPOT(期货转现货),SPOT_FUTURE(现货转期货) + ## 查询订单 (USER_DATA) diff --git a/aster-finance-futures-api.md b/aster-finance-futures-api.md index 21c4833..1d11082 100644 --- a/aster-finance-futures-api.md +++ b/aster-finance-futures-api.md @@ -2464,7 +2464,7 @@ newOrderRespType | ENUM | NO | "ACK", "RESULT", default "ACK" * Batch orders are processed concurrently, and the order of matching is not guaranteed. * The order of returned contents for batch orders is the same as the order of the order list. -## Transfer Between Futures And Spot (USER_DATA) +## Transfer Between Futures And Spot (TRANSFER) > **Response:** diff --git a/aster-finance-futures-api_CN.md b/aster-finance-futures-api_CN.md index 231c9d5..ecc383b 100644 --- a/aster-finance-futures-api_CN.md +++ b/aster-finance-futures-api_CN.md @@ -2372,7 +2372,7 @@ newOrderRespType | ENUM | NO | "ACK", "RESULT", 默认 "ACK" * 批量下单采取并发处理,不保证订单撮合顺序 * 批量下单的返回内容顺序,与订单列表顺序一致 -## 期货现货互转 (TRADE) +## 期货现货互转 (TRANSFER) > **响应:**