diff --git a/binance/async_client.py b/binance/async_client.py index f0a01b8ef..cb191dbf0 100644 --- a/binance/async_client.py +++ b/binance/async_client.py @@ -2165,6 +2165,42 @@ async def futures_coin_stream_keepalive(self, listenKey): "put", "listenKey", signed=False, data=params ) + async def futures_coin_account_order_history_download(self, **params): + return await self._request_futures_coin_api( + "get", "order/asyn", True, data=params + ) + + futures_coin_account_order_history_download.__doc__ = ( + Client.futures_coin_account_order_history_download.__doc__ + ) + + async def futures_coin_account_order_history_download_link(self, **params): + return await self._request_futures_coin_api( + "get", "order/asyn/id", True, data=params + ) + + futures_coin_account_order_history_download_link.__doc__ = ( + Client.futures_coin_accout_order_history_download_link.__doc__ + ) + + async def futures_coin_account_trade_history_download(self, **params): + return await self._request_futures_coin_api( + "get", "trade/asyn", True, data=params + ) + + futures_coin_account_trade_history_download.__doc__ = ( + Client.futures_coin_account_trade_history_download.__doc__ + ) + + async def futures_coin_account_trade_history_download_link(self, **params): + return await self._request_futures_coin_api( + "get", "trade/asyn/id", True, data=params + ) + + futures_coin_account_trade_history_download_link.__doc__ = ( + Client.futures_coin_account_trade_history_download_link.__doc__ + ) + async def futures_coin_stream_close(self, listenKey): params = {"listenKey": listenKey} return await self._request_futures_coin_api( diff --git a/binance/client.py b/binance/client.py index b9c0b5571..eaeca5c99 100755 --- a/binance/client.py +++ b/binance/client.py @@ -8093,6 +8093,146 @@ def futures_coin_stream_close(self, listenKey): "delete", "listenKey", signed=False, data=params ) + def futures_coin_account_order_history_download(self, **params): + """Get Download Id For Futures Order History + + https://developers.binance.com/docs/derivatives/coin-margined-futures/account/Get-Download-Id-For-Futures-Order-History + + :param startTime: required - Start timestamp in ms + :type startTime: int + :param endTime: required - End timestamp in ms + :type endTime: int + :param recvWindow: optional + :type recvWindow: int + + :returns: API response + + .. code-block:: python + + { + "avgCostTimestampOfLast30d": 7241837, # Average time taken for data download in the past 30 days + "downloadId": "546975389218332672" + } + + Note: + - Request Limitation is 10 times per month, shared by front end download page and rest api + - The time between startTime and endTime can not be longer than 1 year + + :raises: BinanceRequestException, BinanceAPIException + + """ + return self._request_futures_coin_api( + "get", "order/asyn", signed=True, data=params + ) + + def futures_coin_accout_order_history_download_link(self, **params): + """Get futures order history download link by Id + + https://developers.binance.com/docs/derivatives/usds-margined-futures/account/rest-api/Get-Futures-Order-History-Download-Link-by-Id + + :param downloadId: required - Download ID obtained from futures_coin_download_id + :type downloadId: str + :param recvWindow: optional + :type recvWindow: int + + :returns: API response + + .. code-block:: python + + { + "downloadId": "545923594199212032", + "status": "completed", # Enum:completed,processing + "url": "www.binance.com", # The link is mapped to download id + "notified": true, # ignore + "expirationTimestamp": 1645009771000, # The link would expire after this timestamp + "isExpired": null + } + + # OR (Response when server is processing) + { + "downloadId": "545923594199212032", + "status": "processing", + "url": "", + "notified": false, + "expirationTimestamp": -1, + "isExpired": null + } + + Note: + - Download link expiration: 24h + + :raises: BinanceRequestException, BinanceAPIException + + """ + return self._request_futures_coin_api("get", "order/asyn/id", True, data=params) + + def futures_coin_account_trade_history_download(self, **params): + """Get Download Id For Futures Trade History (USER_DATA) + + https://developers.binance.com/docs/derivatives/coin-margined-futures/account/Get-Download-Id-For-Futures-Trade-History + + :param startTime: required - Start timestamp in ms + :type startTime: int + :param endTime: required - End timestamp in ms + :type endTime: int + + :returns: API response + + .. code-block:: python + + { + "avgCostTimestampOfLast30d": 7241837, # Average time taken for data download in the past 30 days + "downloadId": "546975389218332672" + } + + Note: + - Request Limitation is 5 times per month, shared by front end download page and rest api + - The time between startTime and endTime can not be longer than 1 year + + :raises: BinanceRequestException, BinanceAPIException + + """ + return self._request_futures_coin_api("get", "trade/asyn", True, data=params) + + def futures_coin_account_trade_history_download_link(self, **params): + """Get futures trade download link by Id + + https://developers.binance.com/docs/derivatives/coin-margined-futures/account/Get-Futures-Trade-Download-Link-by-Id + + :param downloadId: required - Download ID obtained from futures_coin_trade_download_id + :type downloadId: str + + :returns: API response + + .. code-block:: python + + { + "downloadId": "545923594199212032", + "status": "completed", # Enum:completed,processing + "url": "www.binance.com", # The link is mapped to download id + "notified": true, # ignore + "expirationTimestamp": 1645009771000, # The link would expire after this timestamp + "isExpired": null + } + + # OR (Response when server is processing) + { + "downloadId": "545923594199212032", + "status": "processing", + "url": "", + "notified": false, + "expirationTimestamp": -1, + "isExpired": null + } + + Note: + - Download link expiration: 24h + + :raises: BinanceRequestException, BinanceAPIException + + """ + return self._request_futures_coin_api("get", "trade/asyn/id", True, data=params) + def get_all_coins_info(self, **params): """Get information of coins (available for deposit and withdraw) for user. diff --git a/tests/test_async_client_futures.py b/tests/test_async_client_futures.py index d636f1929..7dabf7027 100644 --- a/tests/test_async_client_futures.py +++ b/tests/test_async_client_futures.py @@ -579,3 +579,23 @@ async def test_futures_coin_get_position_mode(futuresClientAsync): async def test_futures_coin_stream_close(futuresClientAsync): listen_key = await futuresClientAsync.futures_coin_stream_get_listen_key() await futuresClientAsync.futures_coin_stream_close(listenKey=listen_key) + + +@pytest.mark.skip(reason="No sandbox support") +async def test_futures_coin_account_order_history_download(futuresClientAsync): + await futuresClientAsync.futures_coin_account_order_download() + + +@pytest.mark.skip(reason="No sandbox support") +async def test_futures_coin_account_order_download_id(futuresClientAsync): + await futuresClientAsync.futures_coin_account_order_download_link(downloadId="123") + + +@pytest.mark.skip(reason="No sandbox support") +async def test_futures_coin_account_trade_history_download(futuresClientAsync): + await futuresClientAsync.futures_coin_account_trade_history_download() + + +@pytest.mark.skip(reason="No sandbox support") +async def test_futures_coin_account_trade_download_id(futuresClientAsync): + await futuresClientAsync.futures_coin_account_trade_history_download_link(downloadId="123") diff --git a/tests/test_client_futures.py b/tests/test_client_futures.py index b4a8b8e1f..c9b3478f9 100644 --- a/tests/test_client_futures.py +++ b/tests/test_client_futures.py @@ -1,6 +1,8 @@ from datetime import datetime +import re import pytest +import requests_mock from .test_order import assert_contract_order from .test_get_order_book import assert_ob @@ -536,21 +538,18 @@ def test_futures_coin_change_position_margin(futuresClient): futuresClient.futures_coin_change_position_margin() -@pytest.mark.skip(reason="Not implemented") def test_futures_coin_position_margin_history(futuresClient): - futuresClient.futures_coin_position_margin_history() + futuresClient.futures_coin_position_margin_history(symbol="LTCUSD_PERP") def test_futures_coin_position_information(futuresClient): futuresClient.futures_coin_position_information() -@pytest.mark.skip(reason="Not implemented") def test_futures_coin_account_trades(futuresClient): futuresClient.futures_coin_account_trades() -@pytest.mark.skip(reason="Not implemented") def test_futures_coin_income_history(futuresClient): futuresClient.futures_coin_income_history() @@ -567,3 +566,109 @@ def test_futures_coin_get_position_mode(futuresClient): def test_futures_coin_stream_close(futuresClient): listen_key = futuresClient.futures_coin_stream_get_listen_key() futuresClient.futures_coin_stream_close(listenKey=listen_key) + +######################################################## +# Test block trades +######################################################## + +@pytest.mark.skip(reason="No sandbox support") +def test_futures_coin_account_order_history_download(futuresClient): + futuresClient.futures_coin_account_order_download() + + +@pytest.mark.skip(reason="No sandbox support") +def test_futures_coin_account_order_download_id(futuresClient): + futuresClient.futures_coin_account_order_download_link(downloadId="123") + + +@pytest.mark.skip(reason="No sandbox support") +def test_futures_coin_account_trade_history_download(futuresClient): + futuresClient.futures_coin_account_trade_history_download() + + +@pytest.mark.skip(reason="No sandbox support") +def test_futures_coin_account_trade_download_id(futuresClient): + futuresClient.futures_coin_account_trade_history_download_link(downloadId="123") + + +def test_futures_coin_account_order_history_download_mock(futuresClient): + expected_response = { + "avgCostTimestampOfLast30d": 7241837, + "downloadId": "546975389218332672", + } + url_pattern = re.compile( + r"https://(?:testnet\.)?binancefuture\.com/dapi/v1/order/asyn" + r"\?recvWindow=\d+" + r"×tamp=\d+" + r"&signature=[a-f0-9]{64}" + ) + + with requests_mock.mock() as m: + m.get( + url_pattern, + json=expected_response, + ) + response = futuresClient.futures_coin_account_order_history_download() + assert response == expected_response + + +def test_futures_coin_account_order_download_id_mock(futuresClient): + expected_response = {"link": "hello"} + url_pattern = re.compile( + r"https://(?:testnet\.)?binancefuture\.com/dapi/v1/order/asyn/id" + r"\?downloadId=123" + r"&recvWindow=\d+" + r"×tamp=\d+" + r"&signature=.+" + ) + with requests_mock.mock() as m: + m.get( + url_pattern, + json=expected_response, + ) + + response = futuresClient.futures_coin_accout_order_history_download_link( + downloadId="123" + ) + assert response == expected_response + +def test_futures_coin_account_trade_history_download_id_mock(futuresClient): + expected_response = { + "avgCostTimestampOfLast30d": 7241837, + "downloadId": "546975389218332672", + } + url_pattern = re.compile( + r"https://(?:testnet\.)?binancefuture\.com/dapi/v1/trade/asyn" + r"\?recvWindow=\d+" + r"×tamp=\d+" + r"&signature=[a-f0-9]{64}" + ) + + with requests_mock.mock() as m: + m.get( + url_pattern, + json=expected_response, + ) + response = futuresClient.futures_coin_account_trade_history_download() + assert response == expected_response + + +def test_futures_coin_account_trade_history_download_link_mock(futuresClient): + expected_response = {"link": "hello"} + url_pattern = re.compile( + r"https://(?:testnet\.)?binancefuture\.com/dapi/v1/trade/asyn/id" + r"\?downloadId=123" + r"&recvWindow=\d+" + r"×tamp=\d+" + r"&signature=.+" + ) + with requests_mock.mock() as m: + m.get( + url_pattern, + json=expected_response, + ) + + response = futuresClient.futures_coin_account_trade_history_download_link( + downloadId="123" + ) + assert response == expected_response