Skip to content

Commit

Permalink
Merge pull request #19 from guilyx/tests
Browse files Browse the repository at this point in the history
Validate POST endpoints
  • Loading branch information
guilyx authored Oct 5, 2022
2 parents ff03e97 + 88a5b0b commit 24256a4
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 58 deletions.
8 changes: 4 additions & 4 deletions docs/endpoints.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,19 @@ client.get_price_quote(pair="BTC/ETH", amount="1.0", side="buy")

### Order

* **POST** /api/v1/orders (Places an order.)
* **POST** /api/v1/orders (Places an order.) ✔️

```python3
client.place_order(pair="BTC/ETH", quantity="1.0", side="buy")
```

* **POST** /api/v1/orders/trigger (Places a trigger order.)
* **POST** /api/v1/orders/trigger (Places a trigger order.) ✔️

```python3
client.place_trigger_order(pair="BTC/ETH", trigger_type="takeProfit", side="buy", trigger_price="15.0", amount="2.0")
```

* **POST** /api/v1/orders/advanced (Places an advanced order.)
* **POST** /api/v1/orders/advanced (Places an advanced order.) ✔️

```python3
client.place_advanced_order(pair="BTC/USDT", side="buy", stop_loss_price="18000", tak_profit_price="22000", amount="0.001")
Expand Down Expand Up @@ -74,7 +74,7 @@ client.get_order_details(id="1324")
client.get_trade_history(pairs=["BTC/ETH", "BTC/USDT"], start_date="1232424242424", end_date="131415535356", page_size="30", page_num="3")
```

* **GET** /api/v1/transactionInfo (Gets a transaction information.)
* **GET** /api/v1/transactionInfo (Gets a transaction information.)

```python3
client.get_price_quote(transaction_id="22442")
Expand Down
2 changes: 2 additions & 0 deletions examples/get_account_balances.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import os
from dotenv import load_dotenv

import time

load_dotenv()

key = os.getenv("NEXO_PUBLIC_KEY")
Expand Down
28 changes: 28 additions & 0 deletions examples/place_order.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import sys
from os import path

sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))

import nexo
import os
from dotenv import load_dotenv


load_dotenv()

key = os.getenv("NEXO_PUBLIC_KEY")
secret = os.getenv("NEXO_SECRET_KEY")

client = nexo.Client(key, secret)

# Buys 0.03 ETH with USDT at market price
order_resp = client.place_order("ETH/USDT", "buy", "market", "0.03", serialize_json_to_object=True)
print(order_resp)

# Gets order details
order = client.get_order_details(str(order_resp.order_id))
print(order)

# Sells 0.03 ETH for USDT at limit price 2000 USDT
order_resp = client.place_order("ETH/USDT", "sell", "limit", "0.03", "1500", serialize_json_to_object=True)
print(order_resp)
51 changes: 4 additions & 47 deletions nexo/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,51 +69,6 @@ def _generate_signature(
)
return base64.b64encode(m.digest())

@staticmethod
def _order_params(data: Dict) -> List[Tuple[str, str]]:
"""Convert params to list
:param data:
:return:
"""
data = dict(filter(lambda el: el[1] is not None, data.items()))
params = []
for key, value in data.items():
params.append((key, str(value)))
# sort parameters by key
params.sort(key=itemgetter(0))
return params

def _get_request_kwargs(self, method, force_params: bool = False, **kwargs) -> Dict:

# set default requests timeout
# kwargs['timeout'] = self.REQUEST_TIMEOUT

data = kwargs.get("data", None)

if data and isinstance(data, dict):
kwargs["data"] = data

# sort get and post params to match signature order
if data:
# sort post params and remove any arguments with values of None
kwargs["data"] = self._order_params(kwargs["data"])
# Remove any arguments with values of None.
null_args = [
i for i, (_, value) in enumerate(kwargs["data"]) if value is None
]
for i in reversed(null_args):
del kwargs["data"][i]

# if get request assign data array to params value for requests lib
if data and (method == "get" or force_params):
kwargs["params"] = "&".join(
"%s=%s" % (data[0], data[1]) for data in kwargs["data"]
)
del kwargs["data"]

return kwargs


class Client(BaseClient):
def __init__(self, api_key, api_secret):
super().__init__(api_key, api_secret)
Expand All @@ -126,7 +81,7 @@ def _handle_response(response: requests.Response):
json_response = response.json()
except Exception:
if not response.ok:
raise NexoRequestException("Failed to get API response: %s" % response.status_code)
raise NexoRequestException(f"Failed to get API response: \nCode: {response.status_code}\nRequest: {str(response.request.body)}")

try:
if "errorCode" in json_response:
Expand All @@ -139,10 +94,12 @@ def _handle_response(response: requests.Response):
else:
if not response.ok:
raise NexoRequestException(f"Failed to get API response: \nCode: {response.status_code}\nRequest: {str(response.request.body)}")

return json_response

return json_response
except ValueError:
raise NexoRequestException("Invalid Response: %s" % json_response)


def _request(
self, method, path: str, version=BaseClient.PUBLIC_API_VERSION, **kwargs
Expand Down
11 changes: 6 additions & 5 deletions nexo/response_serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,17 +71,18 @@ class OrderResponse(BaseSerializedResponse):
def __init__(self, json_dictionary: Dict):
super().__init__(json_dictionary)

if "dealId" in json_dictionary:
self.deal_id = json_dictionary["dealId"]
if "orderId" in json_dictionary:
self.order_id = json_dictionary["orderId"]


# POST /orders/twap
class AdvancedOrderResponse(BaseSerializedResponse):
def __init__(self, json_dictionary: Dict):
if "dealId" in json_dictionary:
super().__init__(json_dictionary)
super().__init__(json_dictionary)

if "orderId" in json_dictionary:
self.order_id = json_dictionary["orderId"]

self.deal_id = json_dictionary["dealId"]
if "amount" in json_dictionary:
self.amount = json_dictionary["amount"]

Expand Down
139 changes: 137 additions & 2 deletions tests/test_serialized_responses.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,22 @@
from nexo.response_serializers import *
import pytest

def test_base_class():
balances_json = {
'balances': [
{
'assetName': 'BTC',
'totalBalance': '0.00000000',
'availableBalance': '0.00000000',
'lockedBalance': '0.00000000',
'debt': '0.00000000',
'interest': '0.00000000'
}
]
}
base = BaseSerializedResponse(balances_json)
assert(str(base) == str(balances_json))

def test_balances():
balances_json = {
'balances': [
Expand Down Expand Up @@ -87,9 +103,128 @@ def test_pairs():

pairs = Pairs(pairs_json)


with pytest.raises(AttributeError):
assert(pairs.min_limits == {'BNB/USDT': 0.355, 'MKR_BTC': 0.002})

with pytest.raises(AttributeError):
assert(pairs.max_limits == {'BNB/USDT': 3435.5, 'MKR_BTC': 42.4})

def test_quote():
quote_json = {
'pair': 'BNB/USDT',
'amount': "1000.0",
'price': "10.0",
'timestamp': "123424243",
'random': "34343"
}

quote = Quote(quote_json)

assert(quote.pair == 'BNB/USDT')
assert(quote.amount == '1000.0')
assert(quote.price == '10.0')
assert(quote.timestamp == "123424243")

with pytest.raises(AttributeError):
assert(quote.random == "34343")


def test_trade_for_order():
trade_json = {
"id": "234",
"symbol": "NEXO/USDT",
"type": "market",
"orderAmount": "100",
"amountFilled": "100",
"executedPrice": "1.324",
"timestamp": 1314242424,
"status": "completed",
"random": "random"
}

trade = TradeForOrder(trade_json)

assert(trade.id == "234")
assert(trade.symbol == "NEXO/USDT")
assert(trade.type == "market")
assert(trade.order_amount == "100")
assert(trade.amount_filled == "100")
assert(trade.executed_price == "1.324")
assert(trade.timestamp == 1314242424)
assert(trade.status == "completed")

with pytest.raises(AttributeError):
assert(trade.random == "random")

def test_order_details():
order_det_json = {
"id": "234",
"pair": "NEXO/USDT",
"side": "buy",
"quantity": "100",
"exchangeRate": "100",
"exchangeQuantity": "1.324",
"timestamp": 1314242424,
"status": "completed",
"random": "random",
"trades": [
{
"id": "234",
"symbol": "NEXO/USDT",
"type": "market",
"orderAmount": "100",
"amountFilled": "100",
"executedPrice": "1.324",
"timestamp": 1314242424,
"status": "completed",
"random": "random"
},
{
"id": "237",
"symbol": "NEXO/USDT",
"type": "market",
"orderAmount": "100",
"amountFilled": "100",
"executedPrice": "1.324",
"timestamp": 1314242424,
"status": "completed",
"random": "random"
}
]
}

order_details = OrderDetails(order_det_json)

assert(len(order_details.trades) == 2)
assert(order_details.trades[0].id == "234")
assert(order_details.trades[0].symbol == "NEXO/USDT")
assert(order_details.trades[0].type == "market")
assert(order_details.trades[0].order_amount == "100")
assert(order_details.trades[0].amount_filled == "100")
assert(order_details.trades[0].executed_price == "1.324")
assert(order_details.trades[0].timestamp == 1314242424)
assert(order_details.trades[0].status == "completed")

assert(order_details.trades[1].id == "237")
assert(order_details.trades[1].symbol == "NEXO/USDT")
assert(order_details.trades[1].type == "market")
assert(order_details.trades[1].order_amount == "100")
assert(order_details.trades[1].amount_filled == "100")
assert(order_details.trades[1].executed_price == "1.324")
assert(order_details.trades[1].timestamp == 1314242424)
assert(order_details.trades[1].status == "completed")

with pytest.raises(AttributeError):
assert(order_details.random == "random")

assert(order_details.id == "234")
assert(order_details.side == "buy")
assert(order_details.exchange_rate == "100")
assert(order_details.exchange_quantity == "1.324")
assert(order_details.timestamp == 1314242424)

with pytest.raises(AttributeError):
assert(order_details.random == "random")

with pytest.raises(AttributeError):
assert(pairs.max_limits == {'BNB/USDT': 3435.5, 'MKR_BTC': 42.4})
assert(order_details.status == "completed")

0 comments on commit 24256a4

Please sign in to comment.