diff --git a/bfxapi/notification.py b/bfxapi/notification.py index f4301b3..bf4818a 100644 --- a/bfxapi/notification.py +++ b/bfxapi/notification.py @@ -1,7 +1,5 @@ from typing import List, Dict, Union, Optional, Any, TypedDict, Generic, TypeVar, cast - from dataclasses import dataclass - from .labeler import _Type, _Serializer T = TypeVar("T") @@ -19,10 +17,10 @@ class Notification(_Type, Generic[T]): class _Notification(_Serializer, Generic[T]): __LABELS = [ "mts", "type", "message_id", "_PLACEHOLDER", "notify_info", "code", "status", "text" ] - def __init__(self, serializer: Optional[_Serializer] = None, iterate: bool = False): + def __init__(self, serializer: Optional[_Serializer] = None, is_iterable: bool = False): super().__init__("Notification", Notification, _Notification.__LABELS, IGNORE = [ "_PLACEHOLDER" ]) - self.serializer, self.iterate = serializer, iterate + self.serializer, self.is_iterable = serializer, is_iterable def parse(self, *values: Any, skip: Optional[List[str]] = None) -> Notification[T]: notification = cast(Notification[T], Notification(**dict(self._serialize(*values)))) @@ -30,7 +28,7 @@ class _Notification(_Serializer, Generic[T]): if isinstance(self.serializer, _Serializer): NOTIFY_INFO = cast(List[Any], notification.notify_info) - if self.iterate == False: + if self.is_iterable == False: if len(NOTIFY_INFO) == 1 and isinstance(NOTIFY_INFO[0], list): NOTIFY_INFO = NOTIFY_INFO[0] diff --git a/bfxapi/rest/_Requests.py b/bfxapi/rest/_Requests.py index 8103d03..70557cb 100644 --- a/bfxapi/rest/_Requests.py +++ b/bfxapi/rest/_Requests.py @@ -1,21 +1,29 @@ import time, hmac, hashlib, json, requests +from typing import TYPE_CHECKING, Optional, Any + from http import HTTPStatus from .enums import Error from .exceptions import ResourceNotFound, RequestParametersError, InvalidAuthenticationCredentials, UnknownGenericError from ..utils.JSONEncoder import JSONEncoder +if TYPE_CHECKING: + from requests.sessions import _Params + class _Requests(object): - def __init__(self, host, API_KEY = None, API_SECRET = None): + def __init__(self, host: str, API_KEY: Optional[str] = None, API_SECRET: Optional[str] = None): self.host, self.API_KEY, self.API_SECRET = host, API_KEY, API_SECRET - def __build_authentication_headers(self, endpoint, data): + def __build_authentication_headers(self, endpoint: str, data: str): + assert isinstance(self.API_KEY, str) and isinstance(self.API_SECRET, str), \ + "API_KEY and API_SECRET must be both str to call __build_authentication_headers" + nonce = str(int(time.time()) * 1000) - path = f"/api/v2/{endpoint}{nonce}" - - if data != None: path += data + if data == None: + path = f"/api/v2/{endpoint}{nonce}" + else: path = f"/api/v2/{endpoint}{nonce}{data}" signature = hmac.new( self.API_SECRET.encode("utf8"), @@ -29,7 +37,7 @@ class _Requests(object): "bfx-apikey": self.API_KEY } - def _GET(self, endpoint, params = None): + def _GET(self, endpoint: str, params: Optional["_Params"] = None) -> Any: response = requests.get(f"{self.host}/{endpoint}", params=params) if response.status_code == HTTPStatus.NOT_FOUND: @@ -46,11 +54,10 @@ class _Requests(object): return data - def _POST(self, endpoint, params = None, data = None, _ignore_authentication_headers = False): - headers = { "Content-Type": "application/json" } + def _POST(self, endpoint: str, params: Optional["_Params"] = None, body: Optional[Any] = None, _ignore_authentication_headers: bool = False) -> Any: + data = json.dumps(body, cls=JSONEncoder) - if isinstance(data, dict): - data = json.dumps({ key: value for key, value in data.items() if value != None}, cls=JSONEncoder) + headers = { "Content-Type": "application/json" } if self.API_KEY and self.API_SECRET and _ignore_authentication_headers == False: headers = { **headers, **self.__build_authentication_headers(endpoint, data) } diff --git a/bfxapi/rest/_RestAuthenticatedEndpoints.py b/bfxapi/rest/_RestAuthenticatedEndpoints.py index 6113e9c..ab4b9bc 100644 --- a/bfxapi/rest/_RestAuthenticatedEndpoints.py +++ b/bfxapi/rest/_RestAuthenticatedEndpoints.py @@ -20,14 +20,14 @@ class _RestAuthenticatedEndpoints(_Requests): if symbol != None: endpoint += f"/{symbol}" - return [ serializers.Order.parse(*sub_data) for sub_data in self._POST(endpoint, data={ "id": ids }) ] + return [ serializers.Order.parse(*sub_data) for sub_data in self._POST(endpoint, body={ "id": ids }) ] def submit_order(self, type: OrderType, symbol: str, amount: Union[Decimal, float, str], price: Optional[Union[Decimal, float, str]] = None, lev: Optional[int] = None, price_trailing: Optional[Union[Decimal, float, str]] = None, price_aux_limit: Optional[Union[Decimal, float, str]] = None, price_oco_stop: Optional[Union[Decimal, float, str]] = None, gid: Optional[int] = None, cid: Optional[int] = None, flags: Optional[int] = 0, tif: Optional[Union[datetime, str]] = None, meta: Optional[JSON] = None) -> Notification[Order]: - data = { + body = { "type": type, "symbol": symbol, "amount": amount, "price": price, "lev": lev, "price_trailing": price_trailing, "price_aux_limit": price_aux_limit, "price_oco_stop": price_oco_stop, @@ -35,32 +35,32 @@ class _RestAuthenticatedEndpoints(_Requests): "flags": flags, "tif": tif, "meta": meta } - return serializers._Notification[Order](serializer=serializers.Order).parse(*self._POST("auth/w/order/submit", data=data)) + return serializers._Notification[Order](serializers.Order).parse(*self._POST("auth/w/order/submit", body=body)) def update_order(self, id: int, amount: Optional[Union[Decimal, float, str]] = None, price: Optional[Union[Decimal, float, str]] = None, cid: Optional[int] = None, cid_date: Optional[str] = None, gid: Optional[int] = None, flags: Optional[int] = 0, lev: Optional[int] = None, delta: Optional[Union[Decimal, float, str]] = None, price_aux_limit: Optional[Union[Decimal, float, str]] = None, price_trailing: Optional[Union[Decimal, float, str]] = None, tif: Optional[Union[datetime, str]] = None) -> Notification[Order]: - data = { + body = { "id": id, "amount": amount, "price": price, "cid": cid, "cid_date": cid_date, "gid": gid, "flags": flags, "lev": lev, "delta": delta, "price_aux_limit": price_aux_limit, "price_trailing": price_trailing, "tif": tif } - return serializers._Notification[Order](serializer=serializers.Order).parse(*self._POST("auth/w/order/update", data=data)) + return serializers._Notification[Order](serializers.Order).parse(*self._POST("auth/w/order/update", body=body)) def cancel_order(self, id: Optional[int] = None, cid: Optional[int] = None, cid_date: Optional[str] = None) -> Notification[Order]: - data = { + body = { "id": id, "cid": cid, "cid_date": cid_date } - return serializers._Notification[Order](serializer=serializers.Order).parse(*self._POST("auth/w/order/cancel", data=data)) + return serializers._Notification[Order](serializers.Order).parse(*self._POST("auth/w/order/cancel", body=body)) def cancel_order_multi(self, ids: Optional[List[int]] = None, cids: Optional[List[Tuple[int, str]]] = None, gids: Optional[List[int]] = None, all: bool = False) -> Notification[List[Order]]: - data = { + body = { "ids": ids, "cids": cids, "gids": gids, @@ -68,20 +68,20 @@ class _RestAuthenticatedEndpoints(_Requests): "all": int(all) } - return serializers._Notification[List[Order]](serializer=serializers.Order, iterate=True).parse(*self._POST("auth/w/order/cancel/multi", data=data)) + return serializers._Notification[List[Order]](serializers.Order, is_iterable=True).parse(*self._POST("auth/w/order/cancel/multi", body=body)) def get_orders_history(self, symbol: Optional[str] = None, ids: Optional[List[int]] = None, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None) -> List[Order]: if symbol == None: endpoint = "auth/r/orders/hist" else: endpoint = f"auth/r/orders/{symbol}/hist" - data = { + body = { "id": ids, "start": start, "end": end, "limit": limit } - return [ serializers.Order.parse(*sub_data) for sub_data in self._POST(endpoint, data=data) ] + return [ serializers.Order.parse(*sub_data) for sub_data in self._POST(endpoint, body=body) ] def get_order_trades(self, symbol: str, id: int) -> List[OrderTrade]: return [ serializers.OrderTrade.parse(*sub_data) for sub_data in self._POST(f"auth/r/order/{symbol}:{id}/trades") ] @@ -91,22 +91,22 @@ class _RestAuthenticatedEndpoints(_Requests): endpoint = "auth/r/trades/hist" else: endpoint = f"auth/r/trades/{symbol}/hist" - data = { + body = { "sort": sort, "start": start, "end": end, "limit": limit } - return [ serializers.Trade.parse(*sub_data) for sub_data in self._POST(endpoint, data=data) ] + return [ serializers.Trade.parse(*sub_data) for sub_data in self._POST(endpoint, body=body) ] def get_ledgers(self, currency: str, category: Optional[int] = None, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None) -> List[Ledger]: - data = { + body = { "category": category, "start": start, "end": end, "limit": limit } - return [ serializers.Ledger.parse(*sub_data) for sub_data in self._POST(f"auth/r/ledgers/{currency}/hist", data=data) ] + return [ serializers.Ledger.parse(*sub_data) for sub_data in self._POST(f"auth/r/ledgers/{currency}/hist", body=body) ] def get_base_margin_info(self) -> BaseMarginInfo: return serializers.BaseMarginInfo.parse(*(self._POST(f"auth/r/info/margin/base")[1])) @@ -123,36 +123,36 @@ class _RestAuthenticatedEndpoints(_Requests): return [ serializers.Position.parse(*sub_data) for sub_data in self._POST("auth/r/positions") ] def claim_position(self, id: int, amount: Optional[Union[Decimal, float, str]] = None) -> Notification[PositionClaim]: - return serializers._Notification[PositionClaim](serializer=serializers.PositionClaim).parse( - *self._POST("auth/w/position/claim", data={ "id": id, "amount": amount }) + return serializers._Notification[PositionClaim](serializers.PositionClaim).parse( + *self._POST("auth/w/position/claim", body={ "id": id, "amount": amount }) ) def increase_position(self, symbol: str, amount: Union[Decimal, float, str]) -> Notification[PositionIncrease]: - return serializers._Notification[PositionIncrease](serializer=serializers.PositionIncrease).parse( - *self._POST("auth/w/position/increase", data={ "symbol": symbol, "amount": amount }) + return serializers._Notification[PositionIncrease](serializers.PositionIncrease).parse( + *self._POST("auth/w/position/increase", body={ "symbol": symbol, "amount": amount }) ) def get_increase_position_info(self, symbol: str, amount: Union[Decimal, float, str]) -> PositionIncreaseInfo: - response = self._POST(f"auth/r/position/increase/info", data={ "symbol": symbol, "amount": amount }) + response = self._POST(f"auth/r/position/increase/info", body={ "symbol": symbol, "amount": amount }) return serializers.PositionIncreaseInfo.parse(*( response[0] + [response[1][0]] + response[1][1] + [response[1][2]] + response[4] + response[5] )) def get_positions_history(self, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None) -> List[PositionHistory]: - return [ serializers.PositionHistory.parse(*sub_data) for sub_data in self._POST("auth/r/positions/hist", data={ "start": start, "end": end, "limit": limit }) ] + return [ serializers.PositionHistory.parse(*sub_data) for sub_data in self._POST("auth/r/positions/hist", body={ "start": start, "end": end, "limit": limit }) ] def get_positions_snapshot(self, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None) -> List[PositionSnapshot]: - return [ serializers.PositionSnapshot.parse(*sub_data) for sub_data in self._POST("auth/r/positions/snap", data={ "start": start, "end": end, "limit": limit }) ] + return [ serializers.PositionSnapshot.parse(*sub_data) for sub_data in self._POST("auth/r/positions/snap", body={ "start": start, "end": end, "limit": limit }) ] def get_positions_audit(self, ids: Optional[List[int]] = None, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None) -> List[PositionAudit]: - return [ serializers.PositionAudit.parse(*sub_data) for sub_data in self._POST("auth/r/positions/audit", data={ "ids": ids, "start": start, "end": end, "limit": limit }) ] + return [ serializers.PositionAudit.parse(*sub_data) for sub_data in self._POST("auth/r/positions/audit", body={ "ids": ids, "start": start, "end": end, "limit": limit }) ] def set_derivative_position_collateral(self, symbol: str, collateral: Union[Decimal, float, str]) -> DerivativePositionCollateral: - return serializers.DerivativePositionCollateral.parse(*(self._POST("auth/w/deriv/collateral/set", data={ "symbol": symbol, "collateral": collateral })[0])) + return serializers.DerivativePositionCollateral.parse(*(self._POST("auth/w/deriv/collateral/set", body={ "symbol": symbol, "collateral": collateral })[0])) def get_derivative_position_collateral_limits(self, symbol: str) -> DerivativePositionCollateralLimits: - return serializers.DerivativePositionCollateralLimits.parse(*self._POST("auth/calc/deriv/collateral/limits", data={ "symbol": symbol })) + return serializers.DerivativePositionCollateralLimits.parse(*self._POST("auth/calc/deriv/collateral/limits", body={ "symbol": symbol })) def get_funding_offers(self, symbol: Optional[str] = None) -> List[FundingOffer]: endpoint = "auth/r/funding/offers" @@ -165,36 +165,36 @@ class _RestAuthenticatedEndpoints(_Requests): def submit_funding_offer(self, type: FundingOfferType, symbol: str, amount: Union[Decimal, float, str], rate: Union[Decimal, float, str], period: int, flags: Optional[int] = 0) -> Notification[FundingOffer]: - data = { + body = { "type": type, "symbol": symbol, "amount": amount, "rate": rate, "period": period, "flags": flags } - return serializers._Notification[FundingOffer](serializer=serializers.FundingOffer).parse(*self._POST("auth/w/funding/offer/submit", data=data)) + return serializers._Notification[FundingOffer](serializers.FundingOffer).parse(*self._POST("auth/w/funding/offer/submit", body=body)) def cancel_funding_offer(self, id: int) -> Notification[FundingOffer]: - return serializers._Notification[FundingOffer](serializer=serializers.FundingOffer).parse(*self._POST("auth/w/funding/offer/cancel", data={ "id": id })) + return serializers._Notification[FundingOffer](serializers.FundingOffer).parse(*self._POST("auth/w/funding/offer/cancel", body={ "id": id })) def cancel_all_funding_offers(self, currency: str) -> Notification[Literal[None]]: - return serializers._Notification[Literal[None]](serializer=None).parse( - *self._POST("auth/w/funding/offer/cancel/all", data={ "currency": currency }) + return serializers._Notification[Literal[None]](None).parse( + *self._POST("auth/w/funding/offer/cancel/all", body={ "currency": currency }) ) def submit_funding_close(self, id: int) -> Notification[Literal[None]]: - return serializers._Notification[Literal[None]](serializer=None).parse( - *self._POST("auth/w/funding/close", data={ "id": id }) + return serializers._Notification[Literal[None]](None).parse( + *self._POST("auth/w/funding/close", body={ "id": id }) ) def toggle_auto_renew(self, status: bool, currency: str, amount: Optional[str] = None, rate: Optional[int] = None, period: Optional[int] = None) -> Notification[FundingAutoRenew]: - return serializers._Notification[FundingAutoRenew](serializer=serializers.FundingAutoRenew).parse(*self._POST("auth/w/funding/auto", data={ + return serializers._Notification[FundingAutoRenew](serializers.FundingAutoRenew).parse(*self._POST("auth/w/funding/auto", body={ "status": int(status), "currency": currency, "amount": amount, "rate": rate, "period": period })) def toggle_keep(self, type: Literal["credit", "loan"], ids: Optional[List[int]] = None, changes: Optional[Dict[int, bool]] = None) -> Notification[Literal[None]]: - return serializers._Notification[Literal[None]](serializer=None).parse(*self._POST("auth/w/funding/keep", data={ + return serializers._Notification[Literal[None]](None).parse(*self._POST("auth/w/funding/keep", body={ "type": type, "id": ids, "changes": changes @@ -205,12 +205,12 @@ class _RestAuthenticatedEndpoints(_Requests): endpoint = "auth/r/funding/offers/hist" else: endpoint = f"auth/r/funding/offers/{symbol}/hist" - data = { + body = { "start": start, "end": end, "limit": limit } - return [ serializers.FundingOffer.parse(*sub_data) for sub_data in self._POST(endpoint, data=data) ] + return [ serializers.FundingOffer.parse(*sub_data) for sub_data in self._POST(endpoint, body=body) ] def get_funding_loans(self, symbol: Optional[str] = None) -> List[FundingLoan]: if symbol == None: @@ -224,12 +224,12 @@ class _RestAuthenticatedEndpoints(_Requests): endpoint = "auth/r/funding/loans/hist" else: endpoint = f"auth/r/funding/loans/{symbol}/hist" - data = { + body = { "start": start, "end": end, "limit": limit } - return [ serializers.FundingLoan.parse(*sub_data) for sub_data in self._POST(endpoint, data=data) ] + return [ serializers.FundingLoan.parse(*sub_data) for sub_data in self._POST(endpoint, body=body) ] def get_funding_credits(self, symbol: Optional[str] = None) -> List[FundingCredit]: if symbol == None: @@ -243,25 +243,25 @@ class _RestAuthenticatedEndpoints(_Requests): endpoint = "auth/r/funding/credits/hist" else: endpoint = f"auth/r/funding/credits/{symbol}/hist" - data = { + body = { "start": start, "end": end, "limit": limit } - return [ serializers.FundingCredit.parse(*sub_data) for sub_data in self._POST(endpoint, data=data) ] + return [ serializers.FundingCredit.parse(*sub_data) for sub_data in self._POST(endpoint, body=body) ] def get_funding_trades_history(self, symbol: Optional[str] = None, sort: Optional[Sort] = None, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None) -> List[FundingTrade]: if symbol == None: endpoint = "auth/r/funding/trades/hist" else: endpoint = f"auth/r/funding/trades/{symbol}/hist" - data = { + body = { "sort": sort, "start": start, "end": end, "limit": limit } - return [ serializers.FundingTrade.parse(*sub_data) for sub_data in self._POST(endpoint, data=data) ] + return [ serializers.FundingTrade.parse(*sub_data) for sub_data in self._POST(endpoint, body=body) ] def get_funding_info(self, key: str) -> FundingInfo: response = self._POST(f"auth/r/info/funding/{key}") @@ -269,45 +269,45 @@ class _RestAuthenticatedEndpoints(_Requests): return serializers.FundingInfo.parse(*([response[1]] + response[2])) def transfer_between_wallets(self, from_wallet: str, to_wallet: str, currency: str, currency_to: str, amount: Union[Decimal, float, str]) -> Notification[Transfer]: - data = { + body = { "from": from_wallet, "to": to_wallet, "currency": currency, "currency_to": currency_to, "amount": amount } - return serializers._Notification[Transfer](serializer=serializers.Transfer).parse(*self._POST("auth/w/transfer", data=data)) + return serializers._Notification[Transfer](serializers.Transfer).parse(*self._POST("auth/w/transfer", body=body)) def submit_wallet_withdrawal(self, wallet: str, method: str, address: str, amount: Union[Decimal, float, str]) -> Notification[Withdrawal]: - return serializers._Notification[Withdrawal](serializer=serializers.Withdrawal).parse(*self._POST("auth/w/withdraw", data={ + return serializers._Notification[Withdrawal](serializers.Withdrawal).parse(*self._POST("auth/w/withdraw", body={ "wallet": wallet, "method": method, "address": address, "amount": amount, })) def get_deposit_address(self, wallet: str, method: str, renew: bool = False) -> Notification[DepositAddress]: - data = { + body = { "wallet": wallet, "method": method, "renew": int(renew) } - return serializers._Notification[DepositAddress](serializer=serializers.DepositAddress).parse(*self._POST("auth/w/deposit/address", data=data)) + return serializers._Notification[DepositAddress](serializers.DepositAddress).parse(*self._POST("auth/w/deposit/address", body=body)) def generate_deposit_invoice(self, wallet: str, currency: str, amount: Union[Decimal, float, str]) -> Invoice: - data = { + body = { "wallet": wallet, "currency": currency, "amount": amount } - return serializers.Invoice.parse(*self._POST("auth/w/deposit/invoice", data=data)) + return serializers.Invoice.parse(*self._POST("auth/w/deposit/invoice", body=body)) def get_movements(self, currency: Optional[str] = None, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None) -> List[Movement]: if currency == None: endpoint = "auth/r/movements/hist" else: endpoint = f"auth/r/movements/{currency}/hist" - data = { + body = { "start": start, "end": end, "limit": limit } - return [ serializers.Movement.parse(*sub_data) for sub_data in self._POST(endpoint, data=data) ] \ No newline at end of file + return [ serializers.Movement.parse(*sub_data) for sub_data in self._POST(endpoint, body=body) ] \ No newline at end of file diff --git a/bfxapi/rest/_RestPublicEndpoints.py b/bfxapi/rest/_RestPublicEndpoints.py index 5157256..c3d2071 100644 --- a/bfxapi/rest/_RestPublicEndpoints.py +++ b/bfxapi/rest/_RestPublicEndpoints.py @@ -175,14 +175,14 @@ class _RestPublicEndpoints(_Requests): return messages def get_trading_market_average_price(self, symbol: str, amount: Union[Decimal, float, str], price_limit: Optional[Union[Decimal, float, str]] = None) -> TradingMarketAveragePrice: - return serializers.TradingMarketAveragePrice.parse(*self._POST("calc/trade/avg", data={ + return serializers.TradingMarketAveragePrice.parse(*self._POST("calc/trade/avg", body={ "symbol": symbol, "amount": amount, "price_limit": price_limit })) def get_funding_market_average_price(self, symbol: str, amount: Union[Decimal, float, str], period: int, rate_limit: Optional[Union[Decimal, float, str]] = None) -> FundingMarketAveragePrice: - return serializers.FundingMarketAveragePrice.parse(*self._POST("calc/trade/avg", data={ + return serializers.FundingMarketAveragePrice.parse(*self._POST("calc/trade/avg", body={ "symbol": symbol, "amount": amount, "period": period, "rate_limit": rate_limit })) def get_fx_rate(self, ccy1: str, ccy2: str) -> FxRate: - return serializers.FxRate.parse(*self._POST("calc/fx", data={ "ccy1": ccy1, "ccy2": ccy2 })) \ No newline at end of file + return serializers.FxRate.parse(*self._POST("calc/fx", body={ "ccy1": ccy1, "ccy2": ccy2 })) \ No newline at end of file diff --git a/bfxapi/utils/JSONEncoder.py b/bfxapi/utils/JSONEncoder.py index 885ab91..506bad1 100644 --- a/bfxapi/utils/JSONEncoder.py +++ b/bfxapi/utils/JSONEncoder.py @@ -8,13 +8,16 @@ JSON = Union[Dict[str, "JSON"], List["JSON"], bool, int, float, str, Type[None]] class JSONEncoder(json.JSONEncoder): def encode(self, obj: JSON) -> str: + def _strip(dictionary: Dict) -> Dict: + return { key: value for key, value in dictionary.items() if value != None} + def _convert_float_to_str(data: JSON) -> JSON: if isinstance(data, float): return format(Decimal(repr(data)), "f") elif isinstance(data, list): return [ _convert_float_to_str(sub_data) for sub_data in data ] elif isinstance(data, dict): - return { key: _convert_float_to_str(value) for key, value in data.items() } + return _strip({ key: _convert_float_to_str(value) for key, value in data.items() }) else: return data data = _convert_float_to_str(obj) diff --git a/bfxapi/websocket/_BfxWebsocketInputs.py b/bfxapi/websocket/_BfxWebsocketInputs.py index 041405f..0d9ee0b 100644 --- a/bfxapi/websocket/_BfxWebsocketInputs.py +++ b/bfxapi/websocket/_BfxWebsocketInputs.py @@ -5,9 +5,6 @@ from typing import Union, Optional, List, Tuple from .types import JSON from .enums import OrderType, FundingOfferType -def _strip(dictionary): - return { key: value for key, value in dictionary.items() if value != None} - class _BfxWebsocketInputs(object): def __init__(self, __handle_websocket_input): self.__handle_websocket_input = __handle_websocket_input @@ -17,59 +14,44 @@ class _BfxWebsocketInputs(object): price_trailing: Optional[Union[Decimal, float, str]] = None, price_aux_limit: Optional[Union[Decimal, float, str]] = None, price_oco_stop: Optional[Union[Decimal, float, str]] = None, gid: Optional[int] = None, cid: Optional[int] = None, flags: Optional[int] = 0, tif: Optional[Union[datetime, str]] = None, meta: Optional[JSON] = None): - data = _strip({ + await self.__handle_websocket_input("on", { "type": type, "symbol": symbol, "amount": amount, "price": price, "lev": lev, "price_trailing": price_trailing, "price_aux_limit": price_aux_limit, "price_oco_stop": price_oco_stop, "gid": gid, "cid": cid, "flags": flags, "tif": tif, "meta": meta }) - - await self.__handle_websocket_input("on", data) async def update_order(self, id: int, amount: Optional[Union[Decimal, float, str]] = None, price: Optional[Union[Decimal, float, str]] = None, cid: Optional[int] = None, cid_date: Optional[str] = None, gid: Optional[int] = None, flags: Optional[int] = 0, lev: Optional[int] = None, delta: Optional[Union[Decimal, float, str]] = None, price_aux_limit: Optional[Union[Decimal, float, str]] = None, price_trailing: Optional[Union[Decimal, float, str]] = None, tif: Optional[Union[datetime, str]] = None): - data = _strip({ + await self.__handle_websocket_input("ou", { "id": id, "amount": amount, "price": price, "cid": cid, "cid_date": cid_date, "gid": gid, "flags": flags, "lev": lev, "delta": delta, "price_aux_limit": price_aux_limit, "price_trailing": price_trailing, "tif": tif }) - - await self.__handle_websocket_input("ou", data) async def cancel_order(self, id: Optional[int] = None, cid: Optional[int] = None, cid_date: Optional[str] = None): - data = _strip({ - "id": id, - "cid": cid, - "cid_date": cid_date + await self.__handle_websocket_input("oc", { + "id": id, "cid": cid, "cid_date": cid_date }) - await self.__handle_websocket_input("oc", data) - async def cancel_order_multi(self, ids: Optional[List[int]] = None, cids: Optional[List[Tuple[int, str]]] = None, gids: Optional[List[int]] = None, all: bool = False): - data = _strip({ - "ids": ids, - "cids": cids, - "gids": gids, - + await self.__handle_websocket_input("oc_multi", { + "ids": ids, "cids": cids, "gids": gids, "all": int(all) }) - - await self.__handle_websocket_input("oc_multi", data) async def submit_funding_offer(self, type: FundingOfferType, symbol: str, amount: Union[Decimal, float, str], rate: Union[Decimal, float, str], period: int, flags: Optional[int] = 0): - data = { + await self.__handle_websocket_input("fon", { "type": type, "symbol": symbol, "amount": amount, "rate": rate, "period": period, "flags": flags - } - - await self.__handle_websocket_input("fon", data) + }) async def cancel_funding_offer(self, id: int): await self.__handle_websocket_input("foc", { "id": id })