diff --git a/binance/async_client.py b/binance/async_client.py index bbcad7a9..6cfb3118 100644 --- a/binance/async_client.py +++ b/binance/async_client.py @@ -131,7 +131,7 @@ async def _request_api( **kwargs, ): uri = self._create_api_uri(path, signed, version) - force_params = kwargs.pop('force_params', False) + force_params = kwargs.pop("force_params", False) return await self._request(method, uri, signed, force_params, **kwargs) async def _request_futures_api( @@ -139,14 +139,14 @@ async def _request_futures_api( ) -> Dict: version = self._get_version(version, **kwargs) uri = self._create_futures_api_uri(path, version=version) - force_params = kwargs.pop('force_params', False) + force_params = kwargs.pop("force_params", False) return await self._request(method, uri, signed, force_params, **kwargs) async def _request_futures_data_api( self, method, path, signed=False, **kwargs ) -> Dict: uri = self._create_futures_data_api_uri(path) - force_params = kwargs.pop('force_params', False) + force_params = kwargs.pop("force_params", False) return await self._request(method, uri, signed, force_params, **kwargs) async def _request_futures_coin_api( @@ -154,7 +154,7 @@ async def _request_futures_coin_api( ) -> Dict: version = self._get_version(version, **kwargs) uri = self._create_futures_coin_api_url(path, version=version) - force_params = kwargs.pop('force_params', False) + force_params = kwargs.pop("force_params", False) return await self._request(method, uri, signed, force_params, **kwargs) async def _request_futures_coin_data_api( @@ -163,12 +163,12 @@ async def _request_futures_coin_data_api( version = self._get_version(version, **kwargs) uri = self._create_futures_coin_data_api_url(path, version=version) - force_params = kwargs.pop('force_params', False) + force_params = kwargs.pop("force_params", False) return await self._request(method, uri, signed, force_params, **kwargs) async def _request_options_api(self, method, path, signed=False, **kwargs) -> Dict: uri = self._create_options_api_uri(path) - force_params = kwargs.pop('force_params', True) + force_params = kwargs.pop("force_params", True) return await self._request(method, uri, signed, force_params, **kwargs) @@ -178,7 +178,7 @@ async def _request_margin_api( version = self._get_version(version, **kwargs) uri = self._create_margin_api_uri(path, version) - force_params = kwargs.pop('force_params', False) + force_params = kwargs.pop("force_params", False) return await self._request(method, uri, signed, force_params, **kwargs) async def _request_papi_api( @@ -187,7 +187,7 @@ async def _request_papi_api( version = self._get_version(version, **kwargs) uri = self._create_papi_api_uri(path, version) - force_params = kwargs.pop('force_params', False) + force_params = kwargs.pop("force_params", False) return await self._request(method, uri, signed, force_params, **kwargs) async def _request_website(self, method, path, signed=False, **kwargs) -> Dict: @@ -1797,7 +1797,9 @@ async def futures_place_batch_order(self, **params): query_string = urlencode(params).replace("%40", "@").replace("%27", "%22") params["batchOrders"] = query_string[12:] - return await self._request_futures_api("post", "batchOrders", True, data=params, force_params=True) + return await self._request_futures_api( + "post", "batchOrders", True, data=params, force_params=True + ) async def futures_get_order(self, **params): return await self._request_futures_api("get", "order", True, data=params) @@ -3610,3 +3612,51 @@ async def ws_futures_account_status(self, **params): https://developers.binance.com/docs/derivatives/usds-margined-futures/account/websocket-api/Account-Information """ return await self._ws_futures_api_request("account.status", True, params) + + #################################################### + # Gift Card API Endpoints + #################################################### + + async def gift_card_fetch_token_limit(self, **params): + return await self._request_margin_api( + "get", "giftcard/buyCode/token-limit", signed=True, data=params + ) + + gift_card_fetch_token_limit.__doc__ = Client.gift_card_fetch_token_limit.__doc__ + + async def gift_card_fetch_rsa_public_key(self, **params): + return await self._request_margin_api( + "get", "giftcard/cryptography/rsa-public-key", signed=True, data=params + ) + + gift_card_fetch_rsa_public_key.__doc__ = ( + Client.gift_card_fetch_rsa_public_key.__doc__ + ) + + async def gift_card_verify(self, **params): + return await self._request_margin_api( + "get", "giftcard/verify", signed=True, data=params + ) + + gift_card_verify.__doc__ = Client.gift_card_verify.__doc__ + + async def gift_card_redeem(self, **params): + return await self._request_margin_api( + "post", "giftcard/redeemCode", signed=True, data=params + ) + + gift_card_redeem.__doc__ = Client.gift_card_redeem.__doc__ + + async def gift_card_create(self, **params): + return await self._request_margin_api( + "post", "giftcard/createCode", signed=True, data=params + ) + + gift_card_create.__doc__ = Client.gift_card_create.__doc__ + + async def gift_card_create_dual_token(self, **params): + return await self._request_margin_api( + "post", "giftcard/buyCode", signed=True, data=params + ) + + gift_card_create_dual_token.__doc__ = Client.gift_card_create_dual_token.__doc__ diff --git a/binance/client.py b/binance/client.py index 6bc84052..7016c777 100755 --- a/binance/client.py +++ b/binance/client.py @@ -87,8 +87,8 @@ def _request_futures_api( ) -> Dict: version = self._get_version(version, **kwargs) uri = self._create_futures_api_uri(path, version) - force_params = kwargs.pop('force_params', False) - + force_params = kwargs.pop("force_params", False) + return self._request(method, uri, signed, force_params, **kwargs) def _request_futures_data_api(self, method, path, signed=False, **kwargs) -> Dict: @@ -7441,7 +7441,9 @@ def futures_place_batch_order(self, **params): query_string = urlencode(params) query_string = query_string.replace("%27", "%22") params["batchOrders"] = query_string[12:] - return self._request_futures_api("post", "batchOrders", True, data=params, force_params=True) + return self._request_futures_api( + "post", "batchOrders", True, data=params, force_params=True + ) def futures_get_order(self, **params): """Check an order's status. @@ -10525,3 +10527,192 @@ def ws_futures_account_status(self, **params): https://developers.binance.com/docs/derivatives/usds-margined-futures/account/websocket-api/Account-Information """ return self._ws_futures_api_request_sync("account.status", True, params) + + ############################################### + ### Gift card api + ############################################### + def gift_card_fetch_token_limit(self, **params): + """Verify which tokens are available for you to create Stablecoin-Denominated gift cards + https://developers.binance.com/docs/gift_card/market-data/Fetch-Token-Limit + + :param baseToken: The token you want to pay, example: BUSD + :type baseToken: str + :return: api response + .. code-block:: python + { + "code": "000000", + "message": "success", + "data": [ + { + "coin": "BNB", + "fromMin": "0.01", + "fromMax": "1" + } + ], + "success": true + } + """ + return self._request_margin_api( + "get", "giftcard/buyCode/token-limit", signed=True, data=params + ) + + def gift_card_fetch_rsa_public_key(self, **params): + """This API is for fetching the RSA Public Key. This RSA Public key will be used to encrypt the card code. + + Important Note: + The RSA Public key fetched is valid only for the current day. + + https://developers.binance.com/docs/gift_card/market-data/Fetch-RSA-Public-Key + :param recvWindow: The receive window for the request in milliseconds (optional) + :type recvWindow: int + :return: api response + .. code-block:: python + { + "code": "000000", + "message": "success", + "data": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCXBBVKLAc1GQ5FsIFFqOHrPTox5noBONIKr+IAedTR9FkVxq6e65updEbfdhRNkMOeYIO2i0UylrjGC0X8YSoIszmrVHeV0l06Zh1oJuZos1+7N+WLuz9JvlPaawof3GUakTxYWWCa9+8KIbLKsoKMdfS96VT+8iOXO3quMGKUmQIDAQAB", + "success": true + } + """ + return self._request_margin_api( + "get", "giftcard/cryptography/rsa-public-key", signed=True, data=params + ) + + def gift_card_verify(self, **params): + """This API is for verifying whether the Binance Gift Card is valid or not by entering Gift Card Number. + + Important Note: + If you enter the wrong Gift Card Number 5 times within an hour, you will no longer be able + to verify any Gift Card Number for that hour. + + https://developers.binance.com/docs/gift_card/market-data/Verify-Binance-Gift-Card-by-Gift-Card-Number + + :param referenceNo: Enter the Gift Card Number + :type referenceNo: str + :return: api response + .. code-block:: python + { + "code": "000000", + "message": "success", + "data": { + "valid": true, + "token": "BNB", # coin + "amount": "0.00000001" # amount + }, + "success": true + } + """ + return self._request_margin_api( + "get", "giftcard/verify", signed=True, data=params + ) + + def gift_card_redeem(self, **params): + """This API is for redeeming a Binance Gift Card. Once redeemed, the coins will be deposited in your funding wallet. + + Important Note: + If you enter the wrong redemption code 5 times within 24 hours, you will no longer be able to + redeem any Binance Gift Cards that day. + + Code Format Options: + - Plaintext + - Encrypted (Recommended for better security) + + For encrypted format: + 1. Fetch RSA public key from the RSA public key endpoint + 2. Encrypt the code using algorithm: RSA/ECB/OAEPWithSHA-256AndMGF1Padding + + https://developers.binance.com/docs/gift_card/market-data/Redeem-a-Binance-Gift-Card + :param code: Redemption code of Binance Gift Card to be redeemed, supports both Plaintext & Encrypted code + :type code: str + :param externalUid: External unique ID representing a user on the partner platform. + Helps identify redemption behavior and control risks/limits. + Max 400 characters. (optional) + :type externalUid: str + :param recvWindow: The receive window for the request in milliseconds (optional) + :type recvWindow: int + :return: api response + .. code-block:: python + { + "code": "000000", + "message": "success", + "data": { + "referenceNo": "0033002328060227", + "identityNo": "10317392647411060736", + "token": "BNB", + "amount": "0.00000001" + }, + "success": true + } + """ + return self._request_margin_api( + "post", "giftcard/redeemCode", signed=True, data=params + ) + + def gift_card_create(self, **params): + """ + This API is for creating a Binance Gift Card. + + To get started with, please make sure: + + - You have a Binance account + - You have passed KYB + - You have a sufficient balance(Gift Card amount and fee amount) in your Binance funding wallet + - You need Enable Withdrawals for the API Key which requests this endpoint. + + https://developers.binance.com/docs/gift_card/market-data + + :param token: The token type contained in the Binance Gift Card + :type token: str + :param amount: The amount of the token contained in the Binance Gift Card + :type amount: float + :return: api response + .. code-block:: python + { + "code": "000000", + "message": "success", + "data": { + "referenceNo": "0033002144060553", + "code": "6H9EKF5ECCWFBHGE", + "expiredTime": 1727417154000 + }, + "success": true + } + """ + return self._request_margin_api( + "post", "giftcard/createCode", signed=True, data=params + ) + + def gift_card_create_dual_token(self, **params): + """This API is for creating a dual-token ( stablecoin-denominated) Binance Gift Card. You may create a gift card using USDT as baseToken, that is redeemable to another designated token (faceToken). For example, you can create a fixed-value BTC gift card and pay with 100 USDT plus 1 USDT fee. This gift card can keep the value fixed at 100 USDT before redemption, and will be redeemable to BTC equivalent to 100 USDT upon redemption. + + Once successfully created, the amount of baseToken (e.g. USDT) in the fixed-value gift card along with the fee would be deducted from your funding wallet. + + To get started with, please make sure: + - You have a Binance account + - You have passed KYB + - You have a sufficient balance(Gift Card amount and fee amount) in your Binance funding wallet + - You need Enable Withdrawals for the API Key which requests this endpoint. + + https://developers.binance.com/docs/gift_card/market-data/Create-a-dual-token-gift-card + :param baseToken: The token you want to pay, example: BUSD + :type baseToken: str + :param faceToken: The token you want to buy, example: BNB. If faceToken = baseToken, it's the same as createCode endpoint. + :type faceToken: str + :param discount: Stablecoin-denominated card discount percentage, Example: 1 for 1% discount. Scale should be less than 6. + :type discount: float + :return: api response + .. code-block:: python + { + "code": "000000", + "message": "success", + "data": { + "referenceNo": "0033002144060553", + "code": "6H9EKF5ECCWFBHGE", + "expiredTime": 1727417154000 + }, + "success": true + } + """ + return self._request_margin_api( + "post", "giftcard/buyCode", signed=True, data=params + ) diff --git a/tests/conftest.py b/tests/conftest.py index 5973d17c..3ea949ad 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -48,7 +48,7 @@ def client(): @pytest.fixture(scope="function") -def optionsClient(): +def liveClient(): return Client(api_key, api_secret, {"proxies": proxies}, testnet=False) @@ -72,7 +72,7 @@ def futuresClientAsync(): @pytest.fixture(scope="function") -def optionsClientAsync(): +def liveClientAsync(): return AsyncClient(api_key, api_secret, https_proxy=proxy, testnet=False) @@ -105,6 +105,12 @@ def pytest_addoption(parser): default=False, help="Run portfolio tests", ) + parser.addoption( + "--run-gift-card", + action="store_true", + default=False, + help="Run gift card tests", + ) def pytest_configure(config): @@ -118,6 +124,9 @@ def pytest_configure(config): config.addinivalue_line( "markers", "portfolio: mark a test as part of the portfolio tests" ) + config.addinivalue_line( + "markers", "gift_card: mark a test as part of the gift card tests" + ) def pytest_collection_modifyitems(config, items): @@ -125,6 +134,7 @@ def pytest_collection_modifyitems(config, items): skip_futures = pytest.mark.skip(reason="need --run-futures option to run") skip_margin = pytest.mark.skip(reason="need --run-margin option to run") skip_portfolio = pytest.mark.skip(reason="need --run-portfolio option to run") + skip_gift_card = pytest.mark.skip(reason="need --run-gift-card option to run") for item in items: if "spot" in item.keywords and not config.getoption("--run-spot"): item.add_marker(skip_spot) @@ -134,3 +144,5 @@ def pytest_collection_modifyitems(config, items): item.add_marker(skip_margin) if "portfolio" in item.keywords and not config.getoption("--run-portfolio"): item.add_marker(skip_portfolio) + if "gift_card" in item.keywords and not config.getoption("--run-gift-card"): + item.add_marker(skip_gift_card) diff --git a/tests/test_async_client_futures.py b/tests/test_async_client_futures.py index d34ca40b..67d6a996 100644 --- a/tests/test_async_client_futures.py +++ b/tests/test_async_client_futures.py @@ -232,7 +232,7 @@ async def test_futures_place_batch_order_and_cancel(futuresClientAsync): "quantity": "0.1", "symbol": ticker["symbol"], "timeInForce": "GTC", - } + }, ] ) for order in orders: diff --git a/tests/test_async_client_gift_card copy.py b/tests/test_async_client_gift_card copy.py new file mode 100644 index 00000000..4b76b929 --- /dev/null +++ b/tests/test_async_client_gift_card copy.py @@ -0,0 +1,46 @@ +import pytest + +pytestmark = [pytest.mark.gift_card, pytest.mark.asyncio] + + +async def test_gift_card_fetch_token_limit(liveClientAsync): + await liveClientAsync.gift_card_fetch_token_limit(baseToken="BUSD") + + +async def test_gift_card_fetch_rsa_public_key(liveClientAsync): + await liveClientAsync.gift_card_fetch_rsa_public_key() + + +async def test_gift_card_create_verify_and_redeem(liveClientAsync): + # create a gift card + response = await liveClientAsync.gift_card_create(token="USDT", amount=1.0) + assert response["data"]["referenceNo"] is not None + assert response["data"]["code"] is not None + # verify the gift card + response = await liveClientAsync.gift_card_verify( + referenceNo=response["data"]["referenceNo"] + ) + assert response["data"]["valid"] == "SUCCESS" + # redeem the gift card + redeem_response = await liveClientAsync.gift_card_redeem( + code=response["data"]["code"], + ) + assert response["data"]["referenceNo"] == redeem_response["data"]["referenceNo"] + + +async def test_gift_card_create_dual_token_and_redeem(liveClientAsync): + response = await liveClientAsync.gift_card_create_dual_token( + baseToken="USDT", faceToken="BNB", baseTokenAmount=1.0 + ) + assert response["data"]["referenceNo"] is not None + assert response["data"]["code"] is not None + # verify the gift card + response = await liveClientAsync.gift_card_verify( + referenceNo=response["data"]["referenceNo"] + ) + assert response["data"]["valid"] == "SUCCESS" + # redeem the gift card + redeem_response = await liveClientAsync.gift_card_redeem( + code=response["data"]["code"], + ) + assert response["data"]["referenceNo"] == redeem_response["data"]["referenceNo"] diff --git a/tests/test_async_client_options.py b/tests/test_async_client_options.py index 7e3ce25c..d78287eb 100644 --- a/tests/test_async_client_options.py +++ b/tests/test_async_client_options.py @@ -5,119 +5,119 @@ @pytest.fixture -def options_symbol(optionsClient): - prices = optionsClient.options_price() +def options_symbol(liveClient): + prices = liveClient.options_price() return prices[0]["symbol"] -async def test_options_ping(optionsClientAsync): - await optionsClientAsync.options_ping() +async def test_options_ping(liveClientAsync): + await liveClientAsync.options_ping() -async def test_options_time(optionsClientAsync): - await optionsClientAsync.options_time() +async def test_options_time(liveClientAsync): + await liveClientAsync.options_time() @pytest.mark.skip(reason="Not implemented") -async def test_options_info(optionsClientAsync): - await optionsClientAsync.options_info() +async def test_options_info(liveClientAsync): + await liveClientAsync.options_info() -async def test_options_exchange_info(optionsClientAsync): - await optionsClientAsync.options_exchange_info() +async def test_options_exchange_info(liveClientAsync): + await liveClientAsync.options_exchange_info() -async def test_options_index_price(optionsClientAsync): - await optionsClientAsync.options_index_price(underlying="BTCUSDT") +async def test_options_index_price(liveClientAsync): + await liveClientAsync.options_index_price(underlying="BTCUSDT") -async def test_options_price(optionsClientAsync): - prices = await optionsClientAsync.options_price() +async def test_options_price(liveClientAsync): + prices = await liveClientAsync.options_price() -async def test_options_mark_price(optionsClientAsync): - await optionsClientAsync.options_mark_price() +async def test_options_mark_price(liveClientAsync): + await liveClientAsync.options_mark_price() -async def test_options_order_book(optionsClientAsync, options_symbol): - await optionsClientAsync.options_order_book(symbol=options_symbol) +async def test_options_order_book(liveClientAsync, options_symbol): + await liveClientAsync.options_order_book(symbol=options_symbol) -async def test_options_klines(optionsClientAsync, options_symbol): - await optionsClientAsync.options_klines(symbol=options_symbol, interval="1m") +async def test_options_klines(liveClientAsync, options_symbol): + await liveClientAsync.options_klines(symbol=options_symbol, interval="1m") -async def test_options_recent_trades(optionsClientAsync, options_symbol): - await optionsClientAsync.options_recent_trades(symbol=options_symbol) +async def test_options_recent_trades(liveClientAsync, options_symbol): + await liveClientAsync.options_recent_trades(symbol=options_symbol) -async def test_options_historical_trades(optionsClientAsync, options_symbol): - await optionsClientAsync.options_historical_trades(symbol=options_symbol) +async def test_options_historical_trades(liveClientAsync, options_symbol): + await liveClientAsync.options_historical_trades(symbol=options_symbol) # Account and trading interface endpoints @pytest.mark.skip(reason="No sandbox to environmnet to test") -async def test_options_account_info(optionsClientAsync): - await optionsClientAsync.options_account_info() +async def test_options_account_info(liveClientAsync): + await liveClientAsync.options_account_info() @pytest.mark.skip(reason="No sandbox to environmnet to test") -async def test_options_funds_transfer(optionsClientAsync): - await optionsClientAsync.options_funds_transfer() +async def test_options_funds_transfer(liveClientAsync): + await liveClientAsync.options_funds_transfer() @pytest.mark.skip(reason="No sandbox to environmnet to test") -async def test_options_positions(optionsClientAsync): - await optionsClientAsync.options_positions() +async def test_options_positions(liveClientAsync): + await liveClientAsync.options_positions() @pytest.mark.skip(reason="No sandbox to environmnet to test") -async def test_options_bill(optionsClientAsync): - await optionsClientAsync.options_bill() +async def test_options_bill(liveClientAsync): + await liveClientAsync.options_bill() @pytest.mark.skip(reason="No sandbox to environmnet to test") -async def test_options_place_order(optionsClientAsync): - await optionsClientAsync.options_place_order() +async def test_options_place_order(liveClientAsync): + await liveClientAsync.options_place_order() @pytest.mark.skip(reason="No sandbox to environmnet to test") -async def test_test_options_place_batch_order(optionsClientAsync): - await optionsClientAsync.test_options_place_batch_order() +async def test_test_options_place_batch_order(liveClientAsync): + await liveClientAsync.test_options_place_batch_order() @pytest.mark.skip(reason="No sandbox to environmnet to test") -async def test_options_cancel_order(optionsClientAsync): - await optionsClientAsync.options_cancel_order() +async def test_options_cancel_order(liveClientAsync): + await liveClientAsync.options_cancel_order() @pytest.mark.skip(reason="No sandbox to environmnet to test") -async def test_options_cancel_batch_order(optionsClientAsync): - await optionsClientAsync.options_cancel_batch_order() +async def test_options_cancel_batch_order(liveClientAsync): + await liveClientAsync.options_cancel_batch_order() @pytest.mark.skip(reason="No sandbox to environmnet to test") -async def test_options_cancel_all_orders(optionsClientAsync): - await optionsClientAsync.options_cancel_all_orders() +async def test_options_cancel_all_orders(liveClientAsync): + await liveClientAsync.options_cancel_all_orders() @pytest.mark.skip(reason="No sandbox to environmnet to test") -async def test_options_query_order(optionsClientAsync): - await optionsClientAsync.options_query_order() +async def test_options_query_order(liveClientAsync): + await liveClientAsync.options_query_order() @pytest.mark.skip(reason="No sandbox to environmnet to test") -async def test_options_query_pending_orders(optionsClientAsync): - await optionsClientAsync.options_query_pending_orders() +async def test_options_query_pending_orders(liveClientAsync): + await liveClientAsync.options_query_pending_orders() @pytest.mark.skip(reason="No sandbox to environmnet to test") -async def test_options_query_order_history(optionsClientAsync): - await optionsClientAsync.options_query_order_history() +async def test_options_query_order_history(liveClientAsync): + await liveClientAsync.options_query_order_history() @pytest.mark.skip(reason="No sandbox to environmnet to test") -async def test_options_user_trades(optionsClientAsync): - await optionsClientAsync.options_user_trades() +async def test_options_user_trades(liveClientAsync): + await liveClientAsync.options_user_trades() diff --git a/tests/test_client_gift_card.py b/tests/test_client_gift_card.py new file mode 100644 index 00000000..0525783b --- /dev/null +++ b/tests/test_client_gift_card.py @@ -0,0 +1,62 @@ +import pytest +import requests_mock + +pytestmark = pytest.mark.gift_card + + +def test_mock_gift_card_fetch_token_limit(liveClient): + """Test gift card token limit endpoint with mocked response""" + expected_response = { + "code": "000000", + "message": "success", + "data": [{"coin": "BNB", "fromMin": "0.01", "fromMax": "1"}], + "success": True, + } + + with requests_mock.mock() as m: + m.get( + "https://api.binance.com/sapi/v1/giftcard/buyCode/token-limit", + json=expected_response, + ) + + response = liveClient.gift_card_fetch_token_limit(baseToken="BUSD") + assert response == expected_response + + +def test_gift_card_fetch_token_limit(liveClient): + liveClient.gift_card_fetch_token_limit(baseToken="BUSD") + + +def test_gift_card_fetch_rsa_public_key(liveClient): + liveClient.gift_card_fetch_rsa_public_key() + + +def test_gift_card_create_verify_and_redeem(liveClient): + # create a gift card + response = liveClient.gift_card_create(token="USDT", amount=1.0) + assert response["data"]["referenceNo"] is not None + assert response["data"]["code"] is not None + # verify the gift card + response = liveClient.gift_card_verify(referenceNo=response["data"]["referenceNo"]) + assert response["data"]["valid"] == "SUCCESS" + # redeem the gift card + redeem_response = liveClient.gift_card_redeem( + code=response["data"]["code"], + ) + assert response["data"]["referenceNo"] == redeem_response["data"]["referenceNo"] + + +def test_gift_card_create_dual_token_and_redeem(liveClient): + response = liveClient.gift_card_create_dual_token( + baseToken="USDT", faceToken="BNB", baseTokenAmount=1.0 + ) + assert response["data"]["referenceNo"] is not None + assert response["data"]["code"] is not None + # verify the gift card + response = liveClient.gift_card_verify(referenceNo=response["data"]["referenceNo"]) + assert response["data"]["valid"] == "SUCCESS" + # redeem the gift card + redeem_response = liveClient.gift_card_redeem( + code=response["data"]["code"], + ) + assert response["data"]["referenceNo"] == redeem_response["data"]["referenceNo"] diff --git a/tests/test_client_options.py b/tests/test_client_options.py index efcf6d5e..8b6d09ba 100644 --- a/tests/test_client_options.py +++ b/tests/test_client_options.py @@ -5,119 +5,119 @@ @pytest.fixture -def options_symbol(optionsClient): - prices = optionsClient.options_price() +def options_symbol(liveClient): + prices = liveClient.options_price() return prices[0]["symbol"] -def test_options_ping(optionsClient): - optionsClient.options_ping() +def test_options_ping(liveClient): + liveClient.options_ping() -def test_options_time(optionsClient): - optionsClient.options_time() +def test_options_time(liveClient): + liveClient.options_time() @pytest.mark.skip(reason="Not implemented") -def test_options_info(optionsClient): - optionsClient.options_info() +def test_options_info(liveClient): + liveClient.options_info() -def test_options_exchange_info(optionsClient): - optionsClient.options_exchange_info() +def test_options_exchange_info(liveClient): + liveClient.options_exchange_info() -def test_options_index_price(optionsClient): - optionsClient.options_index_price(underlying="BTCUSDT") +def test_options_index_price(liveClient): + liveClient.options_index_price(underlying="BTCUSDT") -def test_options_price(optionsClient): - optionsClient.options_price() +def test_options_price(liveClient): + liveClient.options_price() -def test_options_mark_price(optionsClient): - optionsClient.options_mark_price() +def test_options_mark_price(liveClient): + liveClient.options_mark_price() -def test_options_order_book(optionsClient, options_symbol): - optionsClient.options_order_book(symbol=options_symbol) +def test_options_order_book(liveClient, options_symbol): + liveClient.options_order_book(symbol=options_symbol) -def test_options_klines(optionsClient, options_symbol): - optionsClient.options_klines(symbol=options_symbol, interval="1m") +def test_options_klines(liveClient, options_symbol): + liveClient.options_klines(symbol=options_symbol, interval="1m") -def test_options_recent_trades(optionsClient, options_symbol): - optionsClient.options_recent_trades(symbol=options_symbol) +def test_options_recent_trades(liveClient, options_symbol): + liveClient.options_recent_trades(symbol=options_symbol) -def test_options_historical_trades(optionsClient, options_symbol): - optionsClient.options_historical_trades(symbol=options_symbol) +def test_options_historical_trades(liveClient, options_symbol): + liveClient.options_historical_trades(symbol=options_symbol) # Account and trading interface endpoints @pytest.mark.skip(reason="No sandbox to environmnet to test") -def test_options_account_info(optionsClient): - optionsClient.options_account_info() +def test_options_account_info(liveClient): + liveClient.options_account_info() @pytest.mark.skip(reason="No sandbox to environmnet to test") -def test_options_funds_transfer(optionsClient): - optionsClient.options_funds_transfer() +def test_options_funds_transfer(liveClient): + liveClient.options_funds_transfer() @pytest.mark.skip(reason="No sandbox to environmnet to test") -def test_options_positions(optionsClient): - optionsClient.options_positions() +def test_options_positions(liveClient): + liveClient.options_positions() @pytest.mark.skip(reason="No sandbox to environmnet to test") -def test_options_bill(optionsClient): - optionsClient.options_bill() +def test_options_bill(liveClient): + liveClient.options_bill() @pytest.mark.skip(reason="No sandbox to environmnet to test") -def test_options_place_order(optionsClient): - optionsClient.options_place_order() +def test_options_place_order(liveClient): + liveClient.options_place_order() @pytest.mark.skip(reason="No sandbox to environmnet to test") -def test_test_options_place_batch_order(optionsClient): - optionsClient.test_options_place_batch_order() +def test_test_options_place_batch_order(liveClient): + liveClient.test_options_place_batch_order() @pytest.mark.skip(reason="No sandbox to environmnet to test") -def test_options_cancel_order(optionsClient): - optionsClient.options_cancel_order() +def test_options_cancel_order(liveClient): + liveClient.options_cancel_order() @pytest.mark.skip(reason="No sandbox to environmnet to test") -def test_options_cancel_batch_order(optionsClient): - optionsClient.options_cancel_batch_order() +def test_options_cancel_batch_order(liveClient): + liveClient.options_cancel_batch_order() @pytest.mark.skip(reason="No sandbox to environmnet to test") -def test_options_cancel_all_orders(optionsClient): - optionsClient.options_cancel_all_orders() +def test_options_cancel_all_orders(liveClient): + liveClient.options_cancel_all_orders() @pytest.mark.skip(reason="No sandbox to environmnet to test") -def test_options_query_order(optionsClient): - optionsClient.options_query_order() +def test_options_query_order(liveClient): + liveClient.options_query_order() @pytest.mark.skip(reason="No sandbox to environmnet to test") -def test_options_query_pending_orders(optionsClient): - optionsClient.options_query_pending_orders() +def test_options_query_pending_orders(liveClient): + liveClient.options_query_pending_orders() @pytest.mark.skip(reason="No sandbox to environmnet to test") -def test_options_query_order_history(optionsClient): - optionsClient.options_query_order_history() +def test_options_query_order_history(liveClient): + liveClient.options_query_order_history() @pytest.mark.skip(reason="No sandbox to environmnet to test") -def test_options_user_trades(optionsClient): - optionsClient.options_user_trades() +def test_options_user_trades(liveClient): + liveClient.options_user_trades()