diff --git a/.pylintrc b/.pylintrc index 7798ffd..7768472 100644 --- a/.pylintrc +++ b/.pylintrc @@ -10,6 +10,7 @@ disable= multiple-imports, missing-docstring, too-few-public-methods, + too-many-public-methods, too-many-instance-attributes, dangerous-default-value, inconsistent-return-statements, @@ -19,7 +20,7 @@ disable= max-line-length=120 -good-names=id,on,pl,t,A,B,C,D,E,F +good-names=id,on,pl,t,ip,tf,A,B,C,D,E,F [TYPECHECK] diff --git a/bfxapi/rest/__init__.py b/bfxapi/rest/__init__.py index 71e3b54..4f17f62 100644 --- a/bfxapi/rest/__init__.py +++ b/bfxapi/rest/__init__.py @@ -1,4 +1,4 @@ from .endpoints import BfxRestInterface, RestPublicEndpoints, RestAuthenticatedEndpoints, \ RestMerchantEndpoints -NAME = "rest" \ No newline at end of file +NAME = "rest" diff --git a/bfxapi/rest/endpoints/__init__.py b/bfxapi/rest/endpoints/__init__.py index e35d6fb..ef82b97 100644 --- a/bfxapi/rest/endpoints/__init__.py +++ b/bfxapi/rest/endpoints/__init__.py @@ -4,4 +4,4 @@ from .rest_public_endpoints import RestPublicEndpoints from .rest_authenticated_endpoints import RestAuthenticatedEndpoints from .rest_merchant_endpoints import RestMerchantEndpoints -NAME = "endpoints" \ No newline at end of file +NAME = "endpoints" diff --git a/bfxapi/rest/endpoints/bfx_rest_interface.py b/bfxapi/rest/endpoints/bfx_rest_interface.py index fdc05a3..12a06f4 100644 --- a/bfxapi/rest/endpoints/bfx_rest_interface.py +++ b/bfxapi/rest/endpoints/bfx_rest_interface.py @@ -1,16 +1,13 @@ -from typing import Optional - from .rest_public_endpoints import RestPublicEndpoints from .rest_authenticated_endpoints import RestAuthenticatedEndpoints from .rest_merchant_endpoints import RestMerchantEndpoints -class BfxRestInterface(object): +class BfxRestInterface: VERSION = 2 def __init__(self, host, credentials = None): - API_KEY, API_SECRET = credentials and \ - (credentials["api_key"], credentials["api_secret"]) or (None, None) + api_key, api_secret = (credentials['api_key'], credentials['api_secret']) if credentials else (None, None) - self.public = RestPublicEndpoints(host=host) - self.auth = RestAuthenticatedEndpoints(host=host, API_KEY=API_KEY, API_SECRET=API_SECRET) - self.merchant = RestMerchantEndpoints(host=host, API_KEY=API_KEY, API_SECRET=API_SECRET) \ No newline at end of file + self.public = RestPublicEndpoints(host=host) + self.auth = RestAuthenticatedEndpoints(host=host, api_key=api_key, api_secret=api_secret) + self.merchant = RestMerchantEndpoints(host=host, api_key=api_key, api_secret=api_secret) diff --git a/bfxapi/rest/endpoints/rest_authenticated_endpoints.py b/bfxapi/rest/endpoints/rest_authenticated_endpoints.py index 69c3737..0ed2241 100644 --- a/bfxapi/rest/endpoints/rest_authenticated_endpoints.py +++ b/bfxapi/rest/endpoints/rest_authenticated_endpoints.py @@ -10,19 +10,19 @@ from .. middleware import Middleware class RestAuthenticatedEndpoints(Middleware): def get_user_info(self) -> UserInfo: - return serializers.UserInfo.parse(*self._POST(f"auth/r/info/user")) + return serializers.UserInfo.parse(*self._post(f"auth/r/info/user")) def get_login_history(self) -> List[LoginHistory]: - return [ serializers.LoginHistory.parse(*sub_data) for sub_data in self._POST("auth/r/logins/hist") ] + return [ serializers.LoginHistory.parse(*sub_data) for sub_data in self._post("auth/r/logins/hist") ] def get_balance_available_for_orders_or_offers(self, symbol: str, type: str, dir: Optional[int] = None, rate: Optional[str] = None, lev: Optional[str] = None) -> BalanceAvailable: - return serializers.BalanceAvailable.parse(*self._POST("auth/calc/order/avail", body={ + return serializers.BalanceAvailable.parse(*self._post("auth/calc/order/avail", body={ "symbol": symbol, "type": type, "dir": dir, "rate": rate, "lev": lev })) def get_wallets(self) -> List[Wallet]: - return [ serializers.Wallet.parse(*sub_data) for sub_data in self._POST("auth/r/wallets") ] + return [ serializers.Wallet.parse(*sub_data) for sub_data in self._post("auth/r/wallets") ] def get_orders(self, symbol: Optional[str] = None, ids: Optional[List[str]] = None) -> List[Order]: endpoint = "auth/r/orders" @@ -30,7 +30,7 @@ class RestAuthenticatedEndpoints(Middleware): if symbol != None: endpoint += f"/{symbol}" - return [ serializers.Order.parse(*sub_data) for sub_data in self._POST(endpoint, body={ "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, @@ -45,7 +45,7 @@ class RestAuthenticatedEndpoints(Middleware): "flags": flags, "tif": tif, "meta": meta } - return serializers._Notification[Order](serializers.Order).parse(*self._POST("auth/w/order/submit", body=body)) + 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, @@ -58,7 +58,7 @@ class RestAuthenticatedEndpoints(Middleware): "price_aux_limit": price_aux_limit, "price_trailing": price_trailing, "tif": tif } - return serializers._Notification[Order](serializers.Order).parse(*self._POST("auth/w/order/update", body=body)) + 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]: body = { @@ -67,7 +67,7 @@ class RestAuthenticatedEndpoints(Middleware): "cid_date": cid_date } - return serializers._Notification[Order](serializers.Order).parse(*self._POST("auth/w/order/cancel", body=body)) + 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]]: body = { @@ -78,7 +78,7 @@ class RestAuthenticatedEndpoints(Middleware): "all": int(all) } - return serializers._Notification[List[Order]](serializers.Order, is_iterable=True).parse(*self._POST("auth/w/order/cancel/multi", body=body)) + 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: @@ -91,10 +91,10 @@ class RestAuthenticatedEndpoints(Middleware): "limit": limit } - return [ serializers.Order.parse(*sub_data) for sub_data in self._POST(endpoint, body=body) ] + 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") ] + return [ serializers.OrderTrade.parse(*sub_data) for sub_data in self._post(f"auth/r/order/{symbol}:{id}/trades") ] def get_trades_history(self, symbol: Optional[str] = None, sort: Optional[Sort] = None, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None) -> List[Trade]: if symbol == None: @@ -107,7 +107,7 @@ class RestAuthenticatedEndpoints(Middleware): "limit": limit } - return [ serializers.Trade.parse(*sub_data) for sub_data in self._POST(endpoint, body=body) ] + 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]: body = { @@ -116,51 +116,51 @@ class RestAuthenticatedEndpoints(Middleware): "limit": limit } - return [ serializers.Ledger.parse(*sub_data) for sub_data in self._POST(f"auth/r/ledgers/{currency}/hist", body=body) ] + 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])) + return serializers.BaseMarginInfo.parse(*(self._post(f"auth/r/info/margin/base")[1])) def get_symbol_margin_info(self, symbol: str) -> SymbolMarginInfo: - response = self._POST(f"auth/r/info/margin/{symbol}") + response = self._post(f"auth/r/info/margin/{symbol}") data = [response[1]] + response[2] return serializers.SymbolMarginInfo.parse(*data) def get_all_symbols_margin_info(self) -> List[SymbolMarginInfo]: - return [ serializers.SymbolMarginInfo.parse(*([sub_data[1]] + sub_data[2])) for sub_data in self._POST(f"auth/r/info/margin/sym_all") ] + return [ serializers.SymbolMarginInfo.parse(*([sub_data[1]] + sub_data[2])) for sub_data in self._post(f"auth/r/info/margin/sym_all") ] def get_positions(self) -> List[Position]: - return [ serializers.Position.parse(*sub_data) for sub_data in self._POST("auth/r/positions") ] + 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](serializers.PositionClaim).parse( - *self._POST("auth/w/position/claim", body={ "id": id, "amount": amount }) + *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](serializers.PositionIncrease).parse( - *self._POST("auth/w/position/increase", body={ "symbol": symbol, "amount": amount }) + *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", body={ "symbol": symbol, "amount": amount }) + response = self._post(f"auth/r/position/increase/info", body={ "symbol": symbol, "amount": amount }) data = response[0] + [response[1][0]] + response[1][1] + [response[1][2]] + response[4] + response[5] return serializers.PositionIncreaseInfo.parse(*data) 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", body={ "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", body={ "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", body={ "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", body={ "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", body={ "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" @@ -168,7 +168,7 @@ class RestAuthenticatedEndpoints(Middleware): if symbol != None: endpoint += f"/{symbol}" - return [ serializers.FundingOffer.parse(*sub_data) for sub_data in self._POST(endpoint) ] + return [ serializers.FundingOffer.parse(*sub_data) for sub_data in self._post(endpoint) ] def submit_funding_offer(self, type: FundingOfferType, symbol: str, amount: Union[Decimal, float, str], rate: Union[Decimal, float, str], period: int, @@ -179,30 +179,30 @@ class RestAuthenticatedEndpoints(Middleware): "flags": flags } - return serializers._Notification[FundingOffer](serializers.FundingOffer).parse(*self._POST("auth/w/funding/offer/submit", body=body)) + 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](serializers.FundingOffer).parse(*self._POST("auth/w/funding/offer/cancel", body={ "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]](None).parse( - *self._POST("auth/w/funding/offer/cancel/all", body={ "currency": currency }) + *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]](None).parse( - *self._POST("auth/w/funding/close", body={ "id": id }) + *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](serializers.FundingAutoRenew).parse(*self._POST("auth/w/funding/auto", body={ + 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_funding(self, type: Literal["credit", "loan"], ids: Optional[List[int]] = None, changes: Optional[Dict[int, Literal[1, 2]]] = None) -> Notification[Literal[None]]: - return serializers._Notification[Literal[None]](None).parse(*self._POST("auth/w/funding/keep", body={ + return serializers._Notification[Literal[None]](None).parse(*self._post("auth/w/funding/keep", body={ "type": type, "id": ids, "changes": changes @@ -218,14 +218,14 @@ class RestAuthenticatedEndpoints(Middleware): "limit": limit } - return [ serializers.FundingOffer.parse(*sub_data) for sub_data in self._POST(endpoint, body=body) ] + 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: endpoint = "auth/r/funding/loans" else: endpoint = f"auth/r/funding/loans/{symbol}" - return [ serializers.FundingLoan.parse(*sub_data) for sub_data in self._POST(endpoint) ] + return [ serializers.FundingLoan.parse(*sub_data) for sub_data in self._post(endpoint) ] def get_funding_loans_history(self, symbol: Optional[str] = None, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None) -> List[FundingLoan]: if symbol == None: @@ -237,14 +237,14 @@ class RestAuthenticatedEndpoints(Middleware): "limit": limit } - return [ serializers.FundingLoan.parse(*sub_data) for sub_data in self._POST(endpoint, body=body) ] + 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: endpoint = "auth/r/funding/credits" else: endpoint = f"auth/r/funding/credits/{symbol}" - return [ serializers.FundingCredit.parse(*sub_data) for sub_data in self._POST(endpoint) ] + return [ serializers.FundingCredit.parse(*sub_data) for sub_data in self._post(endpoint) ] def get_funding_credits_history(self, symbol: Optional[str] = None, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None) -> List[FundingCredit]: if symbol == None: @@ -256,7 +256,7 @@ class RestAuthenticatedEndpoints(Middleware): "limit": limit } - return [ serializers.FundingCredit.parse(*sub_data) for sub_data in self._POST(endpoint, body=body) ] + 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: @@ -269,10 +269,10 @@ class RestAuthenticatedEndpoints(Middleware): "limit": limit } - return [ serializers.FundingTrade.parse(*sub_data) for sub_data in self._POST(endpoint, body=body) ] + 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}") + response = self._post(f"auth/r/info/funding/{key}") data = [response[1]] + response[2] return serializers.FundingInfo.parse(*data) @@ -283,10 +283,10 @@ class RestAuthenticatedEndpoints(Middleware): "amount": amount } - return serializers._Notification[Transfer](serializers.Transfer).parse(*self._POST("auth/w/transfer", body=body)) + 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](serializers.Withdrawal).parse(*self._POST("auth/w/withdraw", body={ + return serializers._Notification[Withdrawal](serializers.Withdrawal).parse(*self._post("auth/w/withdraw", body={ "wallet": wallet, "method": method, "address": address, "amount": amount, })) @@ -298,7 +298,7 @@ class RestAuthenticatedEndpoints(Middleware): "renew": int(renew) } - return serializers._Notification[DepositAddress](serializers.DepositAddress).parse(*self._POST("auth/w/deposit/address", body=body)) + 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]) -> LightningNetworkInvoice: body = { @@ -306,7 +306,7 @@ class RestAuthenticatedEndpoints(Middleware): "amount": amount } - return serializers.LightningNetworkInvoice.parse(*self._POST("auth/w/deposit/invoice", body=body)) + return serializers.LightningNetworkInvoice.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: @@ -318,4 +318,4 @@ class RestAuthenticatedEndpoints(Middleware): "limit": limit } - return [ serializers.Movement.parse(*sub_data) for sub_data in self._POST(endpoint, body=body) ] \ 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/endpoints/rest_merchant_endpoints.py b/bfxapi/rest/endpoints/rest_merchant_endpoints.py index 2e445ce..d237aab 100644 --- a/bfxapi/rest/endpoints/rest_merchant_endpoints.py +++ b/bfxapi/rest/endpoints/rest_merchant_endpoints.py @@ -24,12 +24,12 @@ class RestMerchantEndpoints(Middleware): "webhook": webhook, "redirect_url": redirect_url }) - data = to_snake_case_keys(self._POST("auth/w/ext/pay/invoice/create", body=body)) + data = to_snake_case_keys(self._post("auth/w/ext/pay/invoice/create", body=body)) return InvoiceSubmission.parse(data) def get_invoices(self, id: Optional[str] = None, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None) -> List[InvoiceSubmission]: - return [ InvoiceSubmission.parse(sub_data) for sub_data in to_snake_case_keys(self._POST("auth/r/ext/pay/invoices", body={ + return [ InvoiceSubmission.parse(sub_data) for sub_data in to_snake_case_keys(self._post("auth/r/ext/pay/invoices", body={ "id": id, "start": start, "end": end, "limit": limit })) ] @@ -43,24 +43,24 @@ class RestMerchantEndpoints(Middleware): "crypto": crypto, "id": id, "order_id": order_id }) - data = to_snake_case_keys(self._POST("auth/r/ext/pay/invoices/paginated", body=body)) + data = to_snake_case_keys(self._post("auth/r/ext/pay/invoices/paginated", body=body)) return InvoicePage.parse(data) def get_invoice_count_stats(self, status: Literal["CREATED", "PENDING", "COMPLETED", "EXPIRED"], format: str) -> List[InvoiceStats]: - return [ InvoiceStats(**sub_data) for sub_data in self._POST("auth/r/ext/pay/invoice/stats/count", body={ "status": status, "format": format }) ] + return [ InvoiceStats(**sub_data) for sub_data in self._post("auth/r/ext/pay/invoice/stats/count", body={ "status": status, "format": format }) ] def get_invoice_earning_stats(self, currency: str, format: str) -> List[InvoiceStats]: - return [ InvoiceStats(**sub_data) for sub_data in self._POST("auth/r/ext/pay/invoice/stats/earning", body={ "currency": currency, "format": format }) ] + return [ InvoiceStats(**sub_data) for sub_data in self._post("auth/r/ext/pay/invoice/stats/earning", body={ "currency": currency, "format": format }) ] def complete_invoice(self, id: str, pay_currency: str, deposit_id: Optional[int] = None, ledger_id: Optional[int] = None) -> InvoiceSubmission: - return InvoiceSubmission.parse(to_snake_case_keys(self._POST("auth/w/ext/pay/invoice/complete", body={ + return InvoiceSubmission.parse(to_snake_case_keys(self._post("auth/w/ext/pay/invoice/complete", body={ "id": id, "payCcy": pay_currency, "depositId": deposit_id, "ledgerId": ledger_id }))) def expire_invoice(self, id: str) -> InvoiceSubmission: - return InvoiceSubmission.parse(to_snake_case_keys(self._POST("auth/w/ext/pay/invoice/expire", body={ "id": id }))) + return InvoiceSubmission.parse(to_snake_case_keys(self._post("auth/w/ext/pay/invoice/expire", body={ "id": id }))) def get_currency_conversion_list(self) -> List[CurrencyConversion]: return [ @@ -68,36 +68,36 @@ class RestMerchantEndpoints(Middleware): base_currency=sub_data["baseCcy"], convert_currency=sub_data["convertCcy"], created=sub_data["created"] - ) for sub_data in self._POST("auth/r/ext/pay/settings/convert/list") + ) for sub_data in self._post("auth/r/ext/pay/settings/convert/list") ] def add_currency_conversion(self, base_currency: str, convert_currency: str) -> bool: - return bool(self._POST("auth/w/ext/pay/settings/convert/create", body={ + return bool(self._post("auth/w/ext/pay/settings/convert/create", body={ "baseCcy": base_currency, "convertCcy": convert_currency })) def remove_currency_conversion(self, base_currency: str, convert_currency: str) -> bool: - return bool(self._POST("auth/w/ext/pay/settings/convert/remove", body={ + return bool(self._post("auth/w/ext/pay/settings/convert/remove", body={ "baseCcy": base_currency, "convertCcy": convert_currency })) def set_merchant_settings(self, key: MerchantSettingsKey, val: Any) -> bool: - return bool(self._POST("auth/w/ext/pay/settings/set", body={ "key": key, "val": val })) + return bool(self._post("auth/w/ext/pay/settings/set", body={ "key": key, "val": val })) def get_merchant_settings(self, key: MerchantSettingsKey) -> Any: - return self._POST("auth/r/ext/pay/settings/get", body={ "key": key }) + return self._post("auth/r/ext/pay/settings/get", body={ "key": key }) def list_merchant_settings(self, keys: List[MerchantSettingsKey] = list()) -> Dict[MerchantSettingsKey, Any]: - return self._POST("auth/r/ext/pay/settings/list", body={ "keys": keys }) + return self._post("auth/r/ext/pay/settings/list", body={ "keys": keys }) def get_deposits(self, start: int, end: int, ccy: Optional[str] = None, unlinked: Optional[bool] = None) -> List[MerchantDeposit]: - return [ MerchantDeposit(**sub_data) for sub_data in to_snake_case_keys(self._POST("auth/r/ext/pay/deposits", body={ + return [ MerchantDeposit(**sub_data) for sub_data in to_snake_case_keys(self._post("auth/r/ext/pay/deposits", body={ "from": start, "to": end, "ccy": ccy, "unlinked": unlinked })) ] def get_unlinked_deposits(self, ccy: str, start: Optional[int] = None, end: Optional[int] = None) -> List[MerchantUnlinkedDeposit]: - return [ MerchantUnlinkedDeposit(**sub_data) for sub_data in to_snake_case_keys(self._POST("/auth/r/ext/pay/deposits/unlinked", body={ + return [ MerchantUnlinkedDeposit(**sub_data) for sub_data in to_snake_case_keys(self._post("/auth/r/ext/pay/deposits/unlinked", body={ "ccy": ccy, "start": start, "end": end })) ] \ No newline at end of file diff --git a/bfxapi/rest/endpoints/rest_public_endpoints.py b/bfxapi/rest/endpoints/rest_public_endpoints.py index b5313fd..66382f4 100644 --- a/bfxapi/rest/endpoints/rest_public_endpoints.py +++ b/bfxapi/rest/endpoints/rest_public_endpoints.py @@ -1,7 +1,17 @@ +#pylint: disable=redefined-builtin + from typing import List, Union, Literal, Optional, Any, cast + from decimal import Decimal -from .. types import * +from .. types import \ + PlatformStatus, TradingPairTicker, FundingCurrencyTicker, \ + TickersHistory, TradingPairTrade, FundingCurrencyTrade, \ + TradingPairBook, FundingCurrencyBook, TradingPairRawBook, \ + FundingCurrencyRawBook, Statistic, Candle, \ + DerivativesStatus, Liquidation, Leaderboard, \ + FundingStatistic, PulseProfile, PulseMessage, \ + TradingMarketAveragePrice, FundingMarketAveragePrice, FxRate from .. import serializers from .. enums import Config, Sort @@ -9,103 +19,151 @@ from .. middleware import Middleware class RestPublicEndpoints(Middleware): def conf(self, config: Config) -> Any: - return self._GET(f"conf/{config}")[0] + return self._get(f"conf/{config}")[0] def get_platform_status(self) -> PlatformStatus: - return serializers.PlatformStatus.parse(*self._GET("platform/status")) + return serializers.PlatformStatus.parse(*self._get("platform/status")) def get_tickers(self, symbols: List[str]) -> List[Union[TradingPairTicker, FundingCurrencyTicker]]: - data = self._GET("tickers", params={ "symbols": ",".join(symbols) }) - + data = self._get("tickers", params={ "symbols": ",".join(symbols) }) + parsers = { "t": serializers.TradingPairTicker.parse, "f": serializers.FundingCurrencyTicker.parse } - - return [ cast(Union[TradingPairTicker, FundingCurrencyTicker], parsers[sub_data[0][0]](*sub_data)) for sub_data in data ] + + return [ cast(Union[TradingPairTicker, FundingCurrencyTicker], \ + parsers[sub_data[0][0]](*sub_data)) for sub_data in data ] def get_t_tickers(self, pairs: Union[List[str], Literal["ALL"]]) -> List[TradingPairTicker]: if isinstance(pairs, str) and pairs == "ALL": - return [ cast(TradingPairTicker, sub_data) for sub_data in self.get_tickers([ "ALL" ]) if cast(str, sub_data.symbol).startswith("t") ] + return [ cast(TradingPairTicker, sub_data) for sub_data in self.get_tickers([ "ALL" ]) \ + if cast(str, sub_data.symbol).startswith("t") ] - data = self.get_tickers([ pair for pair in pairs ]) + data = self.get_tickers(list(pairs)) return cast(List[TradingPairTicker], data) def get_f_tickers(self, currencies: Union[List[str], Literal["ALL"]]) -> List[FundingCurrencyTicker]: if isinstance(currencies, str) and currencies == "ALL": - return [ cast(FundingCurrencyTicker, sub_data) for sub_data in self.get_tickers([ "ALL" ]) if cast(str, sub_data.symbol).startswith("f") ] + return [ cast(FundingCurrencyTicker, sub_data) for sub_data in self.get_tickers([ "ALL" ]) \ + if cast(str, sub_data.symbol).startswith("f") ] - data = self.get_tickers([ currency for currency in currencies ]) + data = self.get_tickers(list(currencies)) return cast(List[FundingCurrencyTicker], data) def get_t_ticker(self, pair: str) -> TradingPairTicker: - return serializers.TradingPairTicker.parse(*self._GET(f"ticker/t{pair}"), skip=["SYMBOL"]) + return serializers.TradingPairTicker.parse(*self._get(f"ticker/t{pair}"), skip=["SYMBOL"]) def get_f_ticker(self, currency: str) -> FundingCurrencyTicker: - return serializers.FundingCurrencyTicker.parse(*self._GET(f"ticker/f{currency}"), skip=["SYMBOL"]) + return serializers.FundingCurrencyTicker.parse(*self._get(f"ticker/f{currency}"), skip=["SYMBOL"]) - def get_tickers_history(self, symbols: List[str], start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None) -> List[TickersHistory]: - return [ serializers.TickersHistory.parse(*sub_data) for sub_data in self._GET("tickers/hist", params={ + def get_tickers_history(self, + symbols: List[str], + *, + start: Optional[str] = None, + end: Optional[str] = None, + limit: Optional[int] = None) -> List[TickersHistory]: + return [ serializers.TickersHistory.parse(*sub_data) for sub_data in self._get("tickers/hist", params={ "symbols": ",".join(symbols), "start": start, "end": end, "limit": limit }) ] - def get_t_trades(self, pair: str, limit: Optional[int] = None, start: Optional[str] = None, end: Optional[str] = None, sort: Optional[Sort] = None) -> List[TradingPairTrade]: + def get_t_trades(self, + pair: str, + *, + limit: Optional[int] = None, + start: Optional[str] = None, + end: Optional[str] = None, + sort: Optional[Sort] = None) -> List[TradingPairTrade]: params = { "limit": limit, "start": start, "end": end, "sort": sort } - data = self._GET(f"trades/{pair}/hist", params=params) + data = self._get(f"trades/{pair}/hist", params=params) return [ serializers.TradingPairTrade.parse(*sub_data) for sub_data in data ] - def get_f_trades(self, currency: str, limit: Optional[int] = None, start: Optional[str] = None, end: Optional[str] = None, sort: Optional[Sort] = None) -> List[FundingCurrencyTrade]: + def get_f_trades(self, + currency: str, + *, + limit: Optional[int] = None, + start: Optional[str] = None, + end: Optional[str] = None, + sort: Optional[Sort] = None) -> List[FundingCurrencyTrade]: params = { "limit": limit, "start": start, "end": end, "sort": sort } - data = self._GET(f"trades/{currency}/hist", params=params) + data = self._get(f"trades/{currency}/hist", params=params) return [ serializers.FundingCurrencyTrade.parse(*sub_data) for sub_data in data ] - def get_t_book(self, pair: str, precision: Literal["P0", "P1", "P2", "P3", "P4"], len: Optional[Literal[1, 25, 100]] = None) -> List[TradingPairBook]: - return [ serializers.TradingPairBook.parse(*sub_data) for sub_data in self._GET(f"book/{pair}/{precision}", params={ "len": len }) ] + def get_t_book(self, + pair: str, + precision: Literal["P0", "P1", "P2", "P3", "P4"], + *, + len: Optional[Literal[1, 25, 100]] = None) -> List[TradingPairBook]: + return [ serializers.TradingPairBook.parse(*sub_data) \ + for sub_data in self._get(f"book/{pair}/{precision}", params={ "len": len }) ] - def get_f_book(self, currency: str, precision: Literal["P0", "P1", "P2", "P3", "P4"], len: Optional[Literal[1, 25, 100]] = None) -> List[FundingCurrencyBook]: - return [ serializers.FundingCurrencyBook.parse(*sub_data) for sub_data in self._GET(f"book/{currency}/{precision}", params={ "len": len }) ] + def get_f_book(self, + currency: str, + precision: Literal["P0", "P1", "P2", "P3", "P4"], + *, + len: Optional[Literal[1, 25, 100]] = None) -> List[FundingCurrencyBook]: + return [ serializers.FundingCurrencyBook.parse(*sub_data) \ + for sub_data in self._get(f"book/{currency}/{precision}", params={ "len": len }) ] - def get_t_raw_book(self, pair: str, len: Optional[Literal[1, 25, 100]] = None) -> List[TradingPairRawBook]: - return [ serializers.TradingPairRawBook.parse(*sub_data) for sub_data in self._GET(f"book/{pair}/R0", params={ "len": len }) ] + def get_t_raw_book(self, + pair: str, + *, + len: Optional[Literal[1, 25, 100]] = None) -> List[TradingPairRawBook]: + return [ serializers.TradingPairRawBook.parse(*sub_data) \ + for sub_data in self._get(f"book/{pair}/R0", params={ "len": len }) ] - def get_f_raw_book(self, currency: str, len: Optional[Literal[1, 25, 100]] = None) -> List[FundingCurrencyRawBook]: - return [ serializers.FundingCurrencyRawBook.parse(*sub_data) for sub_data in self._GET(f"book/{currency}/R0", params={ "len": len }) ] + def get_f_raw_book(self, + currency: str, + *, + len: Optional[Literal[1, 25, 100]] = None) -> List[FundingCurrencyRawBook]: + return [ serializers.FundingCurrencyRawBook.parse(*sub_data) \ + for sub_data in self._get(f"book/{currency}/R0", params={ "len": len }) ] - def get_stats_hist( - self, - resource: str, - sort: Optional[Sort] = None, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None - ) -> List[Statistic]: + def get_stats_hist(self, + resource: str, + *, + sort: Optional[Sort] = None, + start: Optional[str] = None, + end: Optional[str] = None, + limit: Optional[int] = None) -> List[Statistic]: params = { "sort": sort, "start": start, "end": end, "limit": limit } - data = self._GET(f"stats1/{resource}/hist", params=params) + data = self._get(f"stats1/{resource}/hist", params=params) return [ serializers.Statistic.parse(*sub_data) for sub_data in data ] - def get_stats_last( - self, - resource: str, - sort: Optional[Sort] = None, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None - ) -> Statistic: + def get_stats_last(self, + resource: str, + *, + sort: Optional[Sort] = None, + start: Optional[str] = None, + end: Optional[str] = None, + limit: Optional[int] = None) -> Statistic: params = { "sort": sort, "start": start, "end": end, "limit": limit } - data = self._GET(f"stats1/{resource}/last", params=params) + data = self._get(f"stats1/{resource}/last", params=params) return serializers.Statistic.parse(*data) - def get_candles_hist( - self, - symbol: str, tf: str = "1m", - sort: Optional[Sort] = None, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None - ) -> List[Candle]: + def get_candles_hist(self, + symbol: str, + tf: str = "1m", + *, + sort: Optional[Sort] = None, + start: Optional[str] = None, + end: Optional[str] = None, + limit: Optional[int] = None) -> List[Candle]: params = { "sort": sort, "start": start, "end": end, "limit": limit } - data = self._GET(f"candles/trade:{tf}:{symbol}/hist", params=params) + data = self._get(f"candles/trade:{tf}:{symbol}/hist", params=params) return [ serializers.Candle.parse(*sub_data) for sub_data in data ] - def get_candles_last( - self, - symbol: str, tf: str = "1m", - sort: Optional[Sort] = None, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None - ) -> Candle: + def get_candles_last(self, + symbol: str, + tf: str = "1m", + *, + sort: Optional[Sort] = None, + start: Optional[str] = None, + end: Optional[str] = None, + limit: Optional[int] = None) -> Candle: params = { "sort": sort, "start": start, "end": end, "limit": limit } - data = self._GET(f"candles/trade:{tf}:{symbol}/last", params=params) + data = self._get(f"candles/trade:{tf}:{symbol}/last", params=params) return serializers.Candle.parse(*data) def get_derivatives_status(self, keys: Union[List[str], Literal["ALL"]]) -> List[DerivativesStatus]: @@ -113,74 +171,109 @@ class RestPublicEndpoints(Middleware): params = { "keys": "ALL" } else: params = { "keys": ",".join(keys) } - data = self._GET(f"status/deriv", params=params) + data = self._get("status/deriv", params=params) return [ serializers.DerivativesStatus.parse(*sub_data) for sub_data in data ] - def get_derivatives_status_history( - self, - type: str, symbol: str, - sort: Optional[Sort] = None, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None - ) -> List[DerivativesStatus]: + def get_derivatives_status_history(self, + type: str, + symbol: str, + *, + sort: Optional[Sort] = None, + start: Optional[str] = None, + end: Optional[str] = None, + limit: Optional[int] = None) -> List[DerivativesStatus]: params = { "sort": sort, "start": start, "end": end, "limit": limit } - data = self._GET(f"status/{type}/{symbol}/hist", params=params) + data = self._get(f"status/{type}/{symbol}/hist", params=params) return [ serializers.DerivativesStatus.parse(*sub_data, skip=[ "KEY" ]) for sub_data in data ] - def get_liquidations(self, sort: Optional[Sort] = None, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None) -> List[Liquidation]: + def get_liquidations(self, + *, + sort: Optional[Sort] = None, + start: Optional[str] = None, + end: Optional[str] = None, + limit: Optional[int] = None) -> List[Liquidation]: params = { "sort": sort, "start": start, "end": end, "limit": limit } - data = self._GET("liquidations/hist", params=params) + data = self._get("liquidations/hist", params=params) return [ serializers.Liquidation.parse(*sub_data[0]) for sub_data in data ] - def get_seed_candles(self, symbol: str, tf: str = '1m', sort: Optional[Sort] = None, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None) -> List[Candle]: + def get_seed_candles(self, + symbol: str, + tf: str = "1m", + *, + sort: Optional[Sort] = None, + start: Optional[str] = None, + end: Optional[str] = None, + limit: Optional[int] = None) -> List[Candle]: params = {"sort": sort, "start": start, "end": end, "limit": limit} - data = self._GET(f"candles/trade:{tf}:{symbol}/hist?limit={limit}&start={start}&end={end}&sort={sort}", params=params) + data = self._get(f"candles/trade:{tf}:{symbol}/hist", params=params) return [ serializers.Candle.parse(*sub_data) for sub_data in data ] - def get_leaderboards_hist( - self, - resource: str, - sort: Optional[Sort] = None, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None - ) -> List[Leaderboard]: + def get_leaderboards_hist(self, + resource: str, + *, + sort: Optional[Sort] = None, + start: Optional[str] = None, + end: Optional[str] = None, + limit: Optional[int] = None) -> List[Leaderboard]: params = { "sort": sort, "start": start, "end": end, "limit": limit } - data = self._GET(f"rankings/{resource}/hist", params=params) + data = self._get(f"rankings/{resource}/hist", params=params) return [ serializers.Leaderboard.parse(*sub_data) for sub_data in data ] - def get_leaderboards_last( - self, - resource: str, - sort: Optional[Sort] = None, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None - ) -> Leaderboard: + def get_leaderboards_last(self, + resource: str, + *, + sort: Optional[Sort] = None, + start: Optional[str] = None, + end: Optional[str] = None, + limit: Optional[int] = None) -> Leaderboard: params = { "sort": sort, "start": start, "end": end, "limit": limit } - data = self._GET(f"rankings/{resource}/last", params=params) + data = self._get(f"rankings/{resource}/last", params=params) return serializers.Leaderboard.parse(*data) - def get_funding_stats(self, symbol: str, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None) -> List[FundingStatistic]: + def get_funding_stats(self, + symbol: str, + *, + start: Optional[str] = None, + end: Optional[str] = None, + limit: Optional[int] = None) -> List[FundingStatistic]: params = { "start": start, "end": end, "limit": limit } - data = self._GET(f"funding/stats/{symbol}/hist", params=params) + data = self._get(f"funding/stats/{symbol}/hist", params=params) return [ serializers.FundingStatistic.parse(*sub_data) for sub_data in data ] def get_pulse_profile(self, nickname: str) -> PulseProfile: - return serializers.PulseProfile.parse(*self._GET(f"pulse/profile/{nickname}")) + return serializers.PulseProfile.parse(*self._get(f"pulse/profile/{nickname}")) - def get_pulse_history(self, end: Optional[str] = None, limit: Optional[int] = None) -> List[PulseMessage]: - messages = list() + def get_pulse_history(self, *, end: Optional[str] = None, limit: Optional[int] = None) -> List[PulseMessage]: + messages = [] - for subdata in self._GET("pulse/hist", params={ "end": end, "limit": limit }): + for subdata in self._get("pulse/hist", params={ "end": end, "limit": limit }): subdata[18] = subdata[18][0] message = serializers.PulseMessage.parse(*subdata) messages.append(message) 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", body={ + 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", 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", body={ + 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", 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", body={ "ccy1": ccy1, "ccy2": ccy2 })) \ No newline at end of file + return serializers.FxRate.parse(*self._post("calc/fx", body={ "ccy1": ccy1, "ccy2": ccy2 })) diff --git a/bfxapi/rest/enums.py b/bfxapi/rest/enums.py index c256a34..17b3753 100644 --- a/bfxapi/rest/enums.py +++ b/bfxapi/rest/enums.py @@ -1,3 +1,4 @@ +#pylint: disable-next=wildcard-import,unused-wildcard-import from ..enums import * class Config(str, Enum): @@ -43,4 +44,4 @@ class MerchantSettingsKey(str, Enum): NOTIFY_AUTOCONVERT_EXECUTED = "bfx_pay_notify_autoconvert_executed" DUST_BALANCE_UI = "bfx_pay_dust_balance_ui" MERCHANT_CUSTOMER_SUPPORT_URL = "bfx_pay_merchant_customer_support_url" - MERCHANT_UNDERPAID_THRESHOLD = "bfx_pay_merchant_underpaid_threshold" \ No newline at end of file + MERCHANT_UNDERPAID_THRESHOLD = "bfx_pay_merchant_underpaid_threshold" diff --git a/bfxapi/rest/exceptions.py b/bfxapi/rest/exceptions.py index 9fbf3a4..8ea47c3 100644 --- a/bfxapi/rest/exceptions.py +++ b/bfxapi/rest/exceptions.py @@ -14,32 +14,22 @@ class BfxRestException(BfxBaseException): Base class for all custom exceptions in bfxapi/rest/exceptions.py. """ - pass - class ResourceNotFound(BfxRestException): """ This error indicates a failed HTTP request to a non-existent resource. """ - pass - class RequestParametersError(BfxRestException): """ This error indicates that there are some invalid parameters sent along with an HTTP request. """ - pass - class InvalidAuthenticationCredentials(BfxRestException): """ This error indicates that the user has provided incorrect credentials (API-KEY and API-SECRET) for authentication. """ - pass - class UnknownGenericError(BfxRestException): """ This error indicates an undefined problem processing an HTTP request sent to the APIs. """ - - pass \ No newline at end of file diff --git a/bfxapi/rest/middleware/__init__.py b/bfxapi/rest/middleware/__init__.py index d7e276b..d7f9c42 100644 --- a/bfxapi/rest/middleware/__init__.py +++ b/bfxapi/rest/middleware/__init__.py @@ -1,3 +1,3 @@ from .middleware import Middleware -NAME = "middleware" \ No newline at end of file +NAME = "middleware" diff --git a/bfxapi/rest/middleware/middleware.py b/bfxapi/rest/middleware/middleware.py index db98723..04c0f6c 100644 --- a/bfxapi/rest/middleware/middleware.py +++ b/bfxapi/rest/middleware/middleware.py @@ -1,45 +1,51 @@ -import time, hmac, hashlib, json, requests - -from typing import TYPE_CHECKING, Optional, Any, cast +from typing import TYPE_CHECKING, Optional, Any from http import HTTPStatus + +import time, hmac, hashlib, json, requests + from ..enums import Error from ..exceptions import ResourceNotFound, RequestParametersError, InvalidAuthenticationCredentials, UnknownGenericError - from ...utils.json_encoder import JSONEncoder if TYPE_CHECKING: from requests.sessions import _Params -class Middleware(object): - 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 +class Middleware: + TIMEOUT = 30 + + 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: str, data: Optional[str] = None): - assert isinstance(self.API_KEY, str) and isinstance(self.API_SECRET, 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(round(time.time() * 1_000_000)) - if data == None: + if data is None: path = f"/api/v2/{endpoint}{nonce}" else: path = f"/api/v2/{endpoint}{nonce}{data}" signature = hmac.new( - self.API_SECRET.encode("utf8"), + self.api_secret.encode("utf8"), path.encode("utf8"), - hashlib.sha384 + hashlib.sha384 ).hexdigest() return { "bfx-nonce": nonce, "bfx-signature": signature, - "bfx-apikey": self.API_KEY + "bfx-apikey": self.api_key } - def _GET(self, endpoint: str, params: Optional["_Params"] = None) -> Any: - response = requests.get(f"{self.host}/{endpoint}", params=params) - + def _get(self, endpoint: str, params: Optional["_Params"] = None) -> Any: + response = requests.get( + url=f"{self.host}/{endpoint}", + params=params, + timeout=Middleware.TIMEOUT + ) + if response.status_code == HTTPStatus.NOT_FOUND: raise ResourceNotFound(f"No resources found at endpoint <{endpoint}>.") @@ -47,23 +53,32 @@ class Middleware(object): if len(data) and data[0] == "error": if data[1] == Error.ERR_PARAMS: - raise RequestParametersError(f"The request was rejected with the following parameter error: <{data[2]}>") + raise RequestParametersError("The request was rejected with the " + + f"following parameter error: <{data[2]}>") - if data[1] == None or data[1] == Error.ERR_UNK or data[1] == Error.ERR_GENERIC: - raise UnknownGenericError(f"The server replied to the request with a generic error with message: <{data[2]}>.") + if data[1] is None or data[1] == Error.ERR_UNK or data[1] == Error.ERR_GENERIC: + raise UnknownGenericError("The server replied to the request with " + + f"a generic error with message: <{data[2]}>.") return data - def _POST(self, endpoint: str, params: Optional["_Params"] = None, body: Optional[Any] = None, _ignore_authentication_headers: bool = False) -> Any: + def _post(self, endpoint: str, params: Optional["_Params"] = None, + body: Optional[Any] = None, _ignore_authentication_headers: bool = False) -> Any: data = body and json.dumps(body, cls=JSONEncoder) or None headers = { "Content-Type": "application/json" } - if self.API_KEY and self.API_SECRET and _ignore_authentication_headers == False: + if self.api_key and self.api_secret and not _ignore_authentication_headers: headers = { **headers, **self.__build_authentication_headers(endpoint, data) } - response = requests.post(f"{self.host}/{endpoint}", params=params, data=data, headers=headers) - + response = requests.post( + url=f"{self.host}/{endpoint}", + params=params, + data=data, + headers=headers, + timeout=Middleware.TIMEOUT + ) + if response.status_code == HTTPStatus.NOT_FOUND: raise ResourceNotFound(f"No resources found at endpoint <{endpoint}>.") @@ -71,12 +86,14 @@ class Middleware(object): if isinstance(data, list) and len(data) and data[0] == "error": if data[1] == Error.ERR_PARAMS: - raise RequestParametersError(f"The request was rejected with the following parameter error: <{data[2]}>") + raise RequestParametersError("The request was rejected with the " + + f"following parameter error: <{data[2]}>") if data[1] == Error.ERR_AUTH_FAIL: raise InvalidAuthenticationCredentials("Cannot authenticate with given API-KEY and API-SECRET.") - if data[1] == None or data[1] == Error.ERR_UNK or data[1] == Error.ERR_GENERIC: - raise UnknownGenericError(f"The server replied to the request with a generic error with message: <{data[2]}>.") + if data[1] is None or data[1] == Error.ERR_UNK or data[1] == Error.ERR_GENERIC: + raise UnknownGenericError("The server replied to the request with " + + f"a generic error with message: <{data[2]}>.") return data diff --git a/bfxapi/rest/serializers.py b/bfxapi/rest/serializers.py index bcdc7f3..3a2b673 100644 --- a/bfxapi/rest/serializers.py +++ b/bfxapi/rest/serializers.py @@ -2,6 +2,7 @@ from . import types from .. labeler import generate_labeler_serializer, generate_recursive_serializer +#pylint: disable-next=unused-import from .. notification import _Notification __serializers__ = [ @@ -27,723 +28,928 @@ __serializers__ = [ #region Serializers definition for Rest Public Endpoints -PlatformStatus = generate_labeler_serializer("PlatformStatus", klass=types.PlatformStatus, labels=[ - "status" -]) +PlatformStatus = generate_labeler_serializer( + name="PlatformStatus", + klass=types.PlatformStatus, + labels=[ + "status" + ] +) -TradingPairTicker = generate_labeler_serializer("TradingPairTicker", klass=types.TradingPairTicker, labels=[ - "symbol", - "bid", - "bid_size", - "ask", - "ask_size", - "daily_change", - "daily_change_relative", - "last_price", - "volume", - "high", - "low" -]) +TradingPairTicker = generate_labeler_serializer( + name="TradingPairTicker", + klass=types.TradingPairTicker, + labels=[ + "symbol", + "bid", + "bid_size", + "ask", + "ask_size", + "daily_change", + "daily_change_relative", + "last_price", + "volume", + "high", + "low" + ] +) -FundingCurrencyTicker = generate_labeler_serializer("FundingCurrencyTicker", klass=types.FundingCurrencyTicker, labels=[ - "symbol", - "frr", - "bid", - "bid_period", - "bid_size", - "ask", - "ask_period", - "ask_size", - "daily_change", - "daily_change_relative", - "last_price", - "volume", - "high", - "low", - "_PLACEHOLDER", - "_PLACEHOLDER", - "frr_amount_available" -]) +FundingCurrencyTicker = generate_labeler_serializer( + name="FundingCurrencyTicker", + klass=types.FundingCurrencyTicker, + labels=[ + "symbol", + "frr", + "bid", + "bid_period", + "bid_size", + "ask", + "ask_period", + "ask_size", + "daily_change", + "daily_change_relative", + "last_price", + "volume", + "high", + "low", + "_PLACEHOLDER", + "_PLACEHOLDER", + "frr_amount_available" + ] +) -TickersHistory = generate_labeler_serializer("TickersHistory", klass=types.TickersHistory, labels=[ - "symbol", - "bid", - "_PLACEHOLDER", - "ask", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "mts" -]) +TickersHistory = generate_labeler_serializer( + name="TickersHistory", + klass=types.TickersHistory, + labels=[ + "symbol", + "bid", + "_PLACEHOLDER", + "ask", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "mts" + ] +) -TradingPairTrade = generate_labeler_serializer("TradingPairTrade", klass=types.TradingPairTrade, labels=[ - "id", - "mts", - "amount", - "price" -]) +TradingPairTrade = generate_labeler_serializer( + name="TradingPairTrade", + klass=types.TradingPairTrade, + labels=[ + "id", + "mts", + "amount", + "price" + ] +) -FundingCurrencyTrade = generate_labeler_serializer("FundingCurrencyTrade", klass=types.FundingCurrencyTrade, labels=[ - "id", - "mts", - "amount", - "rate", - "period" -]) +FundingCurrencyTrade = generate_labeler_serializer( + name="FundingCurrencyTrade", + klass=types.FundingCurrencyTrade, + labels=[ + "id", + "mts", + "amount", + "rate", + "period" + ] +) -TradingPairBook = generate_labeler_serializer("TradingPairBook", klass=types.TradingPairBook, labels=[ - "price", - "count", - "amount" -]) +TradingPairBook = generate_labeler_serializer( + name="TradingPairBook", + klass=types.TradingPairBook, + labels=[ + "price", + "count", + "amount" + ] +) -FundingCurrencyBook = generate_labeler_serializer("FundingCurrencyBook", klass=types.FundingCurrencyBook, labels=[ - "rate", - "period", - "count", - "amount" -]) +FundingCurrencyBook = generate_labeler_serializer( + name="FundingCurrencyBook", + klass=types.FundingCurrencyBook, + labels=[ + "rate", + "period", + "count", + "amount" + ] +) -TradingPairRawBook = generate_labeler_serializer("TradingPairRawBook", klass=types.TradingPairRawBook, labels=[ - "order_id", - "price", - "amount" -]) +TradingPairRawBook = generate_labeler_serializer( + name="TradingPairRawBook", + klass=types.TradingPairRawBook, + labels=[ + "order_id", + "price", + "amount" + ] +) -FundingCurrencyRawBook = generate_labeler_serializer("FundingCurrencyRawBook", klass=types.FundingCurrencyRawBook, labels=[ - "offer_id", - "period", - "rate", - "amount" -]) +FundingCurrencyRawBook = generate_labeler_serializer( + name="FundingCurrencyRawBook", + klass=types.FundingCurrencyRawBook, + labels=[ + "offer_id", + "period", + "rate", + "amount" + ] +) -Statistic = generate_labeler_serializer("Statistic", klass=types.Statistic, labels=[ - "mts", - "value" -]) +Statistic = generate_labeler_serializer( + name="Statistic", + klass=types.Statistic, + labels=[ + "mts", + "value" + ] +) -Candle = generate_labeler_serializer("Candle", klass=types.Candle, labels=[ - "mts", - "open", - "close", - "high", - "low", - "volume" -]) +Candle = generate_labeler_serializer( + name="Candle", + klass=types.Candle, + labels=[ + "mts", + "open", + "close", + "high", + "low", + "volume" + ] +) -DerivativesStatus = generate_labeler_serializer("DerivativesStatus", klass=types.DerivativesStatus, labels=[ - "key", - "mts", - "_PLACEHOLDER", - "deriv_price", - "spot_price", - "_PLACEHOLDER", - "insurance_fund_balance", - "_PLACEHOLDER", - "next_funding_evt_timestamp_ms", - "next_funding_accrued", - "next_funding_step", - "_PLACEHOLDER", - "current_funding", - "_PLACEHOLDER", - "_PLACEHOLDER", - "mark_price", - "_PLACEHOLDER", - "_PLACEHOLDER", - "open_interest", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "clamp_min", - "clamp_max" -]) +DerivativesStatus = generate_labeler_serializer( + name="DerivativesStatus", + klass=types.DerivativesStatus, + labels=[ + "key", + "mts", + "_PLACEHOLDER", + "deriv_price", + "spot_price", + "_PLACEHOLDER", + "insurance_fund_balance", + "_PLACEHOLDER", + "next_funding_evt_timestamp_ms", + "next_funding_accrued", + "next_funding_step", + "_PLACEHOLDER", + "current_funding", + "_PLACEHOLDER", + "_PLACEHOLDER", + "mark_price", + "_PLACEHOLDER", + "_PLACEHOLDER", + "open_interest", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "clamp_min", + "clamp_max" + ] +) -Liquidation = generate_labeler_serializer("Liquidation", klass=types.Liquidation, labels=[ - "_PLACEHOLDER", - "pos_id", - "mts", - "_PLACEHOLDER", - "symbol", - "amount", - "base_price", - "_PLACEHOLDER", - "is_match", - "is_market_sold", - "_PLACEHOLDER", - "price_acquired" -]) +Liquidation = generate_labeler_serializer( + name="Liquidation", + klass=types.Liquidation, + labels=[ + "_PLACEHOLDER", + "pos_id", + "mts", + "_PLACEHOLDER", + "symbol", + "amount", + "base_price", + "_PLACEHOLDER", + "is_match", + "is_market_sold", + "_PLACEHOLDER", + "price_acquired" + ] +) -Leaderboard = generate_labeler_serializer("Leaderboard", klass=types.Leaderboard, labels=[ - "mts", - "_PLACEHOLDER", - "username", - "ranking", - "_PLACEHOLDER", - "_PLACEHOLDER", - "value", - "_PLACEHOLDER", - "_PLACEHOLDER", - "twitter_handle" -]) +Leaderboard = generate_labeler_serializer( + name="Leaderboard", + klass=types.Leaderboard, + labels=[ + "mts", + "_PLACEHOLDER", + "username", + "ranking", + "_PLACEHOLDER", + "_PLACEHOLDER", + "value", + "_PLACEHOLDER", + "_PLACEHOLDER", + "twitter_handle" + ] +) -FundingStatistic = generate_labeler_serializer("FundingStatistic", klass=types.FundingStatistic, labels=[ - "timestamp", - "_PLACEHOLDER", - "_PLACEHOLDER", - "frr", - "avg_period", - "_PLACEHOLDER", - "_PLACEHOLDER", - "funding_amount", - "funding_amount_used", - "_PLACEHOLDER", - "_PLACEHOLDER", - "funding_below_threshold" -]) +FundingStatistic = generate_labeler_serializer( + name="FundingStatistic", + klass=types.FundingStatistic, + labels=[ + "timestamp", + "_PLACEHOLDER", + "_PLACEHOLDER", + "frr", + "avg_period", + "_PLACEHOLDER", + "_PLACEHOLDER", + "funding_amount", + "funding_amount_used", + "_PLACEHOLDER", + "_PLACEHOLDER", + "funding_below_threshold" + ] +) -PulseProfile = generate_labeler_serializer("PulseProfile", klass=types.PulseProfile, labels=[ - "puid", - "mts", - "_PLACEHOLDER", - "nickname", - "_PLACEHOLDER", - "picture", - "text", - "_PLACEHOLDER", - "_PLACEHOLDER", - "twitter_handle", - "_PLACEHOLDER", - "followers", - "following", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "tipping_status" -]) +PulseProfile = generate_labeler_serializer( + name="PulseProfile", + klass=types.PulseProfile, + labels=[ + "puid", + "mts", + "_PLACEHOLDER", + "nickname", + "_PLACEHOLDER", + "picture", + "text", + "_PLACEHOLDER", + "_PLACEHOLDER", + "twitter_handle", + "_PLACEHOLDER", + "followers", + "following", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "tipping_status" + ] +) -PulseMessage = generate_recursive_serializer("PulseMessage", klass=types.PulseMessage, serializers={ "profile": PulseProfile }, labels=[ - "pid", - "mts", - "_PLACEHOLDER", - "puid", - "_PLACEHOLDER", - "title", - "content", - "_PLACEHOLDER", - "_PLACEHOLDER", - "is_pin", - "is_public", - "comments_disabled", - "tags", - "attachments", - "meta", - "likes", - "_PLACEHOLDER", - "_PLACEHOLDER", - "profile", - "comments", - "_PLACEHOLDER", - "_PLACEHOLDER" -]) +PulseMessage = generate_recursive_serializer( + name="PulseMessage", + klass=types.PulseMessage, + serializers={ "profile": PulseProfile }, + labels=[ + "pid", + "mts", + "_PLACEHOLDER", + "puid", + "_PLACEHOLDER", + "title", + "content", + "_PLACEHOLDER", + "_PLACEHOLDER", + "is_pin", + "is_public", + "comments_disabled", + "tags", + "attachments", + "meta", + "likes", + "_PLACEHOLDER", + "_PLACEHOLDER", + "profile", + "comments", + "_PLACEHOLDER", + "_PLACEHOLDER" + ] +) -TradingMarketAveragePrice = generate_labeler_serializer("TradingMarketAveragePrice", klass=types.TradingMarketAveragePrice, labels=[ - "price_avg", - "amount" -]) +TradingMarketAveragePrice = generate_labeler_serializer( + name="TradingMarketAveragePrice", + klass=types.TradingMarketAveragePrice, + labels=[ + "price_avg", + "amount" + ] +) -FundingMarketAveragePrice = generate_labeler_serializer("FundingMarketAveragePrice", klass=types.FundingMarketAveragePrice, labels=[ - "rate_avg", - "amount" -]) +FundingMarketAveragePrice = generate_labeler_serializer( + name="FundingMarketAveragePrice", + klass=types.FundingMarketAveragePrice, + labels=[ + "rate_avg", + "amount" + ] +) -FxRate = generate_labeler_serializer("FxRate", klass=types.FxRate, labels=[ - "current_rate" -]) +FxRate = generate_labeler_serializer( + name="FxRate", + klass=types.FxRate, + labels=[ + "current_rate" + ] +) #endregion #region Serializers definition for Rest Authenticated Endpoints -UserInfo = generate_labeler_serializer("UserInfo", klass=types.UserInfo, labels=[ - "id", - "email", - "username", - "mts_account_create", - "verified", - "verification_level", - "_PLACEHOLDER", - "timezone", - "locale", - "company", - "email_verified", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "mts_master_account_create", - "group_id", - "master_account_id", - "inherit_master_account_verification", - "is_group_master", - "group_withdraw_enabled", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "ppt_enabled", - "merchant_enabled", - "competition_enabled", - "two_factors_authentication_modes", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "is_securities_master", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "securities_enabled", - "allow_disable_ctxswitch", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "time_last_login", - "_PLACEHOLDER", - "_PLACEHOLDER", - "ctxtswitch_disabled", - "_PLACEHOLDER", - "comp_countries", - "compl_countries_resid", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "is_merchant_enterprise" -]) +UserInfo = generate_labeler_serializer( + name="UserInfo", + klass=types.UserInfo, + labels=[ + "id", + "email", + "username", + "mts_account_create", + "verified", + "verification_level", + "_PLACEHOLDER", + "timezone", + "locale", + "company", + "email_verified", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "mts_master_account_create", + "group_id", + "master_account_id", + "inherit_master_account_verification", + "is_group_master", + "group_withdraw_enabled", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "ppt_enabled", + "merchant_enabled", + "competition_enabled", + "two_factors_authentication_modes", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "is_securities_master", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "securities_enabled", + "allow_disable_ctxswitch", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "time_last_login", + "_PLACEHOLDER", + "_PLACEHOLDER", + "ctxtswitch_disabled", + "_PLACEHOLDER", + "comp_countries", + "compl_countries_resid", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "is_merchant_enterprise" + ] +) -LoginHistory = generate_labeler_serializer("LoginHistory", klass=types.LoginHistory, labels=[ - "id", - "_PLACEHOLDER", - "time", - "_PLACEHOLDER", - "ip", - "_PLACEHOLDER", - "_PLACEHOLDER", - "extra_info" -]) +LoginHistory = generate_labeler_serializer( + name="LoginHistory", + klass=types.LoginHistory, + labels=[ + "id", + "_PLACEHOLDER", + "time", + "_PLACEHOLDER", + "ip", + "_PLACEHOLDER", + "_PLACEHOLDER", + "extra_info" + ] +) -BalanceAvailable = generate_labeler_serializer("BalanceAvailable", klass=types.BalanceAvailable, labels=[ - "amount" -]) +BalanceAvailable = generate_labeler_serializer( + name="BalanceAvailable", + klass=types.BalanceAvailable, + labels=[ + "amount" + ] +) -Order = generate_labeler_serializer("Order", klass=types.Order, labels=[ - "id", - "gid", - "cid", - "symbol", - "mts_create", - "mts_update", - "amount", - "amount_orig", - "order_type", - "type_prev", - "mts_tif", - "_PLACEHOLDER", - "flags", - "order_status", - "_PLACEHOLDER", - "_PLACEHOLDER", - "price", - "price_avg", - "price_trailing", - "price_aux_limit", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "notify", - "hidden", - "placed_id", - "_PLACEHOLDER", - "_PLACEHOLDER", - "routing", - "_PLACEHOLDER", - "_PLACEHOLDER", - "meta" -]) +Order = generate_labeler_serializer( + name="Order", + klass=types.Order, + labels=[ + "id", + "gid", + "cid", + "symbol", + "mts_create", + "mts_update", + "amount", + "amount_orig", + "order_type", + "type_prev", + "mts_tif", + "_PLACEHOLDER", + "flags", + "order_status", + "_PLACEHOLDER", + "_PLACEHOLDER", + "price", + "price_avg", + "price_trailing", + "price_aux_limit", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "notify", + "hidden", + "placed_id", + "_PLACEHOLDER", + "_PLACEHOLDER", + "routing", + "_PLACEHOLDER", + "_PLACEHOLDER", + "meta" + ] +) -Position = generate_labeler_serializer("Position", klass=types.Position, labels=[ - "symbol", - "status", - "amount", - "base_price", - "margin_funding", - "margin_funding_type", - "pl", - "pl_perc", - "price_liq", - "leverage", - "_PLACEHOLDER", - "position_id", - "mts_create", - "mts_update", - "_PLACEHOLDER", - "type", - "_PLACEHOLDER", - "collateral", - "collateral_min", - "meta" -]) +Position = generate_labeler_serializer( + name="Position", + klass=types.Position, + labels=[ + "symbol", + "status", + "amount", + "base_price", + "margin_funding", + "margin_funding_type", + "pl", + "pl_perc", + "price_liq", + "leverage", + "_PLACEHOLDER", + "position_id", + "mts_create", + "mts_update", + "_PLACEHOLDER", + "type", + "_PLACEHOLDER", + "collateral", + "collateral_min", + "meta" + ] +) -Trade = generate_labeler_serializer("Trade", klass=types.Trade, labels=[ - "id", - "symbol", - "mts_create", - "order_id", - "exec_amount", - "exec_price", - "order_type", - "order_price", - "maker", - "fee", - "fee_currency", - "cid" -]) +Trade = generate_labeler_serializer( + name="Trade", + klass=types.Trade, + labels=[ + "id", + "symbol", + "mts_create", + "order_id", + "exec_amount", + "exec_price", + "order_type", + "order_price", + "maker", + "fee", + "fee_currency", + "cid" + ] +) -FundingTrade = generate_labeler_serializer("FundingTrade", klass=types.FundingTrade, labels=[ - "id", - "currency", - "mts_create", - "offer_id", - "amount", - "rate", - "period" -]) +FundingTrade = generate_labeler_serializer( + name="FundingTrade", + klass=types.FundingTrade, + labels=[ + "id", + "currency", + "mts_create", + "offer_id", + "amount", + "rate", + "period" + ] +) -OrderTrade = generate_labeler_serializer("OrderTrade", klass=types.OrderTrade, labels=[ - "id", - "symbol", - "mts_create", - "order_id", - "exec_amount", - "exec_price", - "_PLACEHOLDER", - "_PLACEHOLDER", - "maker", - "fee", - "fee_currency", - "cid" -]) +OrderTrade = generate_labeler_serializer( + name="OrderTrade", + klass=types.OrderTrade, + labels=[ + "id", + "symbol", + "mts_create", + "order_id", + "exec_amount", + "exec_price", + "_PLACEHOLDER", + "_PLACEHOLDER", + "maker", + "fee", + "fee_currency", + "cid" + ] +) -Ledger = generate_labeler_serializer("Ledger", klass=types.Ledger, labels=[ - "id", - "currency", - "_PLACEHOLDER", - "mts", - "_PLACEHOLDER", - "amount", - "balance", - "_PLACEHOLDER", - "description" -]) +Ledger = generate_labeler_serializer( + name="Ledger", + klass=types.Ledger, + labels=[ + "id", + "currency", + "_PLACEHOLDER", + "mts", + "_PLACEHOLDER", + "amount", + "balance", + "_PLACEHOLDER", + "description" + ] +) -FundingOffer = generate_labeler_serializer("FundingOffer", klass=types.FundingOffer, labels=[ - "id", - "symbol", - "mts_create", - "mts_update", - "amount", - "amount_orig", - "offer_type", - "_PLACEHOLDER", - "_PLACEHOLDER", - "flags", - "offer_status", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "rate", - "period", - "notify", - "hidden", - "_PLACEHOLDER", - "renew", - "_PLACEHOLDER" -]) +FundingOffer = generate_labeler_serializer( + name="FundingOffer", + klass=types.FundingOffer, + labels=[ + "id", + "symbol", + "mts_create", + "mts_update", + "amount", + "amount_orig", + "offer_type", + "_PLACEHOLDER", + "_PLACEHOLDER", + "flags", + "offer_status", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "rate", + "period", + "notify", + "hidden", + "_PLACEHOLDER", + "renew", + "_PLACEHOLDER" + ] +) -FundingCredit = generate_labeler_serializer("FundingCredit", klass=types.FundingCredit, labels=[ - "id", - "symbol", - "side", - "mts_create", - "mts_update", - "amount", - "flags", - "status", - "rate_type", - "_PLACEHOLDER", - "_PLACEHOLDER", - "rate", - "period", - "mts_opening", - "mts_last_payout", - "notify", - "hidden", - "_PLACEHOLDER", - "renew", - "_PLACEHOLDER", - "no_close", - "position_pair" -]) +FundingCredit = generate_labeler_serializer( + name="FundingCredit", + klass=types.FundingCredit, + labels=[ + "id", + "symbol", + "side", + "mts_create", + "mts_update", + "amount", + "flags", + "status", + "rate_type", + "_PLACEHOLDER", + "_PLACEHOLDER", + "rate", + "period", + "mts_opening", + "mts_last_payout", + "notify", + "hidden", + "_PLACEHOLDER", + "renew", + "_PLACEHOLDER", + "no_close", + "position_pair" + ] +) -FundingLoan = generate_labeler_serializer("FundingLoan", klass=types.FundingLoan, labels=[ - "id", - "symbol", - "side", - "mts_create", - "mts_update", - "amount", - "flags", - "status", - "rate_type", - "_PLACEHOLDER", - "_PLACEHOLDER", - "rate", - "period", - "mts_opening", - "mts_last_payout", - "notify", - "hidden", - "_PLACEHOLDER", - "renew", - "_PLACEHOLDER", - "no_close" -]) +FundingLoan = generate_labeler_serializer( + name="FundingLoan", + klass=types.FundingLoan, + labels=[ + "id", + "symbol", + "side", + "mts_create", + "mts_update", + "amount", + "flags", + "status", + "rate_type", + "_PLACEHOLDER", + "_PLACEHOLDER", + "rate", + "period", + "mts_opening", + "mts_last_payout", + "notify", + "hidden", + "_PLACEHOLDER", + "renew", + "_PLACEHOLDER", + "no_close" + ] +) -FundingAutoRenew = generate_labeler_serializer("FundingAutoRenew", klass=types.FundingAutoRenew, labels=[ - "currency", - "period", - "rate", - "threshold" -]) +FundingAutoRenew = generate_labeler_serializer( + name="FundingAutoRenew", + klass=types.FundingAutoRenew, + labels=[ + "currency", + "period", + "rate", + "threshold" + ] +) -FundingInfo = generate_labeler_serializer("FundingInfo", klass=types.FundingInfo, labels=[ - "symbol", - "yield_loan", - "yield_lend", - "duration_loan", - "duration_lend" -]) +FundingInfo = generate_labeler_serializer( + name="FundingInfo", + klass=types.FundingInfo, + labels=[ + "symbol", + "yield_loan", + "yield_lend", + "duration_loan", + "duration_lend" + ] +) -Wallet = generate_labeler_serializer("Wallet", klass=types.Wallet, labels=[ - "wallet_type", - "currency", - "balance", - "unsettled_interest", - "available_balance", - "last_change", - "trade_details" -]) +Wallet = generate_labeler_serializer( + name="Wallet", + klass=types.Wallet, + labels=[ + "wallet_type", + "currency", + "balance", + "unsettled_interest", + "available_balance", + "last_change", + "trade_details" + ] +) -Transfer = generate_labeler_serializer("Transfer", klass=types.Transfer, labels=[ - "mts", - "wallet_from", - "wallet_to", - "_PLACEHOLDER", - "currency", - "currency_to", - "_PLACEHOLDER", - "amount" -]) +Transfer = generate_labeler_serializer( + name="Transfer", + klass=types.Transfer, + labels=[ + "mts", + "wallet_from", + "wallet_to", + "_PLACEHOLDER", + "currency", + "currency_to", + "_PLACEHOLDER", + "amount" + ] +) -Withdrawal = generate_labeler_serializer("Withdrawal", klass=types.Withdrawal, labels=[ - "withdrawal_id", - "_PLACEHOLDER", - "method", - "payment_id", - "wallet", - "amount", - "_PLACEHOLDER", - "_PLACEHOLDER", - "withdrawal_fee" -]) +Withdrawal = generate_labeler_serializer( + name="Withdrawal", + klass=types.Withdrawal, + labels=[ + "withdrawal_id", + "_PLACEHOLDER", + "method", + "payment_id", + "wallet", + "amount", + "_PLACEHOLDER", + "_PLACEHOLDER", + "withdrawal_fee" + ] +) -DepositAddress = generate_labeler_serializer("DepositAddress", klass=types.DepositAddress, labels=[ - "_PLACEHOLDER", - "method", - "currency_code", - "_PLACEHOLDER", - "address", - "pool_address" -]) +DepositAddress = generate_labeler_serializer( + name="DepositAddress", + klass=types.DepositAddress, + labels=[ + "_PLACEHOLDER", + "method", + "currency_code", + "_PLACEHOLDER", + "address", + "pool_address" + ] +) -LightningNetworkInvoice = generate_labeler_serializer("LightningNetworkInvoice", klass=types.LightningNetworkInvoice, labels=[ - "invoice_hash", - "invoice", - "_PLACEHOLDER", - "_PLACEHOLDER", - "amount" -]) +LightningNetworkInvoice = generate_labeler_serializer( + name="LightningNetworkInvoice", + klass=types.LightningNetworkInvoice, + labels=[ + "invoice_hash", + "invoice", + "_PLACEHOLDER", + "_PLACEHOLDER", + "amount" + ] +) -Movement = generate_labeler_serializer("Movement", klass=types.Movement, labels=[ - "id", - "currency", - "currency_name", - "_PLACEHOLDER", - "_PLACEHOLDER", - "mts_start", - "mts_update", - "_PLACEHOLDER", - "_PLACEHOLDER", - "status", - "_PLACEHOLDER", - "_PLACEHOLDER", - "amount", - "fees", - "_PLACEHOLDER", - "_PLACEHOLDER", - "destination_address", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "transaction_id", - "withdraw_transaction_note" -]) +Movement = generate_labeler_serializer( + name="Movement", + klass=types.Movement, + labels=[ + "id", + "currency", + "currency_name", + "_PLACEHOLDER", + "_PLACEHOLDER", + "mts_start", + "mts_update", + "_PLACEHOLDER", + "_PLACEHOLDER", + "status", + "_PLACEHOLDER", + "_PLACEHOLDER", + "amount", + "fees", + "_PLACEHOLDER", + "_PLACEHOLDER", + "destination_address", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "transaction_id", + "withdraw_transaction_note" + ] +) -SymbolMarginInfo = generate_labeler_serializer("SymbolMarginInfo", klass=types.SymbolMarginInfo, labels=[ - "symbol", - "tradable_balance", - "gross_balance", - "buy", - "sell" -]) +SymbolMarginInfo = generate_labeler_serializer( + name="SymbolMarginInfo", + klass=types.SymbolMarginInfo, + labels=[ + "symbol", + "tradable_balance", + "gross_balance", + "buy", + "sell" + ] +) -BaseMarginInfo = generate_labeler_serializer("BaseMarginInfo", klass=types.BaseMarginInfo, labels=[ - "user_pl", - "user_swaps", - "margin_balance", - "margin_net", - "margin_min" -]) +BaseMarginInfo = generate_labeler_serializer( + name="BaseMarginInfo", + klass=types.BaseMarginInfo, + labels=[ + "user_pl", + "user_swaps", + "margin_balance", + "margin_net", + "margin_min" + ] +) -PositionClaim = generate_labeler_serializer("PositionClaim", klass=types.PositionClaim, labels=[ - "symbol", - "position_status", - "amount", - "base_price", - "margin_funding", - "margin_funding_type", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "position_id", - "mts_create", - "mts_update", - "_PLACEHOLDER", - "pos_type", - "_PLACEHOLDER", - "collateral", - "min_collateral", - "meta" -]) +PositionClaim = generate_labeler_serializer( + name="PositionClaim", + klass=types.PositionClaim, + labels=[ + "symbol", + "position_status", + "amount", + "base_price", + "margin_funding", + "margin_funding_type", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "position_id", + "mts_create", + "mts_update", + "_PLACEHOLDER", + "pos_type", + "_PLACEHOLDER", + "collateral", + "min_collateral", + "meta" + ] +) -PositionIncreaseInfo = generate_labeler_serializer("PositionIncreaseInfo", klass=types.PositionIncreaseInfo, labels=[ - "max_pos", - "current_pos", - "base_currency_balance", - "tradable_balance_quote_currency", - "tradable_balance_quote_total", - "tradable_balance_base_currency", - "tradable_balance_base_total", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "funding_avail", - "funding_value", - "funding_required", - "funding_value_currency", - "funding_required_currency" -]) +PositionIncreaseInfo = generate_labeler_serializer( + name="PositionIncreaseInfo", + klass=types.PositionIncreaseInfo, + labels=[ + "max_pos", + "current_pos", + "base_currency_balance", + "tradable_balance_quote_currency", + "tradable_balance_quote_total", + "tradable_balance_base_currency", + "tradable_balance_base_total", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "funding_avail", + "funding_value", + "funding_required", + "funding_value_currency", + "funding_required_currency" + ] +) -PositionIncrease = generate_labeler_serializer("PositionIncrease", klass=types.PositionIncrease, labels=[ - "symbol", - "_PLACEHOLDER", - "amount", - "base_price" -]) +PositionIncrease = generate_labeler_serializer( + name="PositionIncrease", + klass=types.PositionIncrease, + labels=[ + "symbol", + "_PLACEHOLDER", + "amount", + "base_price" + ] +) -PositionHistory = generate_labeler_serializer("PositionHistory", klass=types.PositionHistory, labels=[ - "symbol", - "status", - "amount", - "base_price", - "funding", - "funding_type", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "position_id", - "mts_create", - "mts_update" -]) +PositionHistory = generate_labeler_serializer( + name="PositionHistory", + klass=types.PositionHistory, + labels=[ + "symbol", + "status", + "amount", + "base_price", + "funding", + "funding_type", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "position_id", + "mts_create", + "mts_update" + ] +) -PositionSnapshot = generate_labeler_serializer("PositionSnapshot", klass=types.PositionSnapshot, labels=[ - "symbol", - "status", - "amount", - "base_price", - "funding", - "funding_type", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "position_id", - "mts_create", - "mts_update" -]) +PositionSnapshot = generate_labeler_serializer( + name="PositionSnapshot", + klass=types.PositionSnapshot, + labels=[ + "symbol", + "status", + "amount", + "base_price", + "funding", + "funding_type", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "position_id", + "mts_create", + "mts_update" + ] +) -PositionAudit = generate_labeler_serializer("PositionAudit", klass=types.PositionAudit, labels=[ - "symbol", - "status", - "amount", - "base_price", - "funding", - "funding_type", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "_PLACEHOLDER", - "position_id", - "mts_create", - "mts_update", - "_PLACEHOLDER", - "type", - "_PLACEHOLDER", - "collateral", - "collateral_min", - "meta" -]) +PositionAudit = generate_labeler_serializer( + name="PositionAudit", + klass=types.PositionAudit, + labels=[ + "symbol", + "status", + "amount", + "base_price", + "funding", + "funding_type", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "_PLACEHOLDER", + "position_id", + "mts_create", + "mts_update", + "_PLACEHOLDER", + "type", + "_PLACEHOLDER", + "collateral", + "collateral_min", + "meta" + ] +) -DerivativePositionCollateral = generate_labeler_serializer("DerivativePositionCollateral", klass=types.DerivativePositionCollateral, labels=[ - "status" -]) +DerivativePositionCollateral = generate_labeler_serializer( + name="DerivativePositionCollateral", + klass=types.DerivativePositionCollateral, + labels=[ + "status" + ] +) -DerivativePositionCollateralLimits = generate_labeler_serializer("DerivativePositionCollateralLimits", klass=types.DerivativePositionCollateralLimits, labels=[ - "min_collateral", - "max_collateral" -]) +DerivativePositionCollateralLimits = generate_labeler_serializer( + name="DerivativePositionCollateralLimits", + klass=types.DerivativePositionCollateralLimits, + labels=[ + "min_collateral", + "max_collateral" + ] +) -#endregion \ No newline at end of file +#endregion diff --git a/bfxapi/rest/types.py b/bfxapi/rest/types.py index 32c2a9b..65d5423 100644 --- a/bfxapi/rest/types.py +++ b/bfxapi/rest/types.py @@ -1,9 +1,13 @@ +#pylint: disable-next=wildcard-import,unused-wildcard-import from typing import * from dataclasses import dataclass from .. labeler import _Type, partial, compose + +#pylint: disable-next=unused-import from .. notification import Notification + from ..utils.json_encoder import JSON #region Type hinting for Rest Public Endpoints @@ -11,7 +15,7 @@ from ..utils.json_encoder import JSON @dataclass class PlatformStatus(_Type): status: int - + @dataclass class TradingPairTicker(_Type): symbol: Optional[str] @@ -53,43 +57,43 @@ class TickersHistory(_Type): @dataclass class TradingPairTrade(_Type): - id: int - mts: int - amount: float + id: int + mts: int + amount: float price: float @dataclass class FundingCurrencyTrade(_Type): - id: int - mts: int - amount: float - rate: float + id: int + mts: int + amount: float + rate: float period: int @dataclass class TradingPairBook(_Type): - price: float - count: int + price: float + count: int amount: float - + @dataclass class FundingCurrencyBook(_Type): - rate: float - period: int - count: int + rate: float + period: int + count: int amount: float -@dataclass +@dataclass class TradingPairRawBook(_Type): order_id: int - price: float + price: float amount: float -@dataclass +@dataclass class FundingCurrencyRawBook(_Type): - offer_id: int - period: int - rate: float + offer_id: int + period: int + rate: float amount: float @dataclass @@ -142,7 +146,7 @@ class Leaderboard(_Type): twitter_handle: Optional[str] @dataclass -class FundingStatistic(_Type): +class FundingStatistic(_Type): timestamp: int frr: float avg_period: float @@ -286,14 +290,14 @@ class Position(_Type): @dataclass class Trade(_Type): - id: int - symbol: str + id: int + symbol: str mts_create: int - order_id: int - exec_amount: float - exec_price: float - order_type: str - order_price: float + order_id: int + exec_amount: float + exec_price: float + order_type: str + order_price: float maker:int fee: float fee_currency: str @@ -311,12 +315,12 @@ class FundingTrade(_Type): @dataclass class OrderTrade(_Type): - id: int - symbol: str + id: int + symbol: str mts_create: int - order_id: int - exec_amount: float - exec_price: float + order_id: int + exec_amount: float + exec_price: float maker:int fee: float fee_currency: str @@ -325,7 +329,7 @@ class OrderTrade(_Type): @dataclass class Ledger(_Type): id: int - currency: str + currency: str mts: int amount: float balance: float @@ -413,7 +417,7 @@ class Wallet(_Type): available_balance: float last_change: str trade_details: JSON - + @dataclass class Transfer(_Type): mts: int @@ -458,7 +462,7 @@ class Movement(_Type): destination_address: str transaction_id: str withdraw_transaction_note: str - + @dataclass class SymbolMarginInfo(_Type): symbol: str @@ -586,16 +590,16 @@ class InvoiceSubmission(_Type): @classmethod def parse(cls, data: Dict[str, Any]) -> "InvoiceSubmission": - if "customer_info" in data and data["customer_info"] != None: + if "customer_info" in data and data["customer_info"] is not None: data["customer_info"] = InvoiceSubmission.CustomerInfo(**data["customer_info"]) for index, invoice in enumerate(data["invoices"]): data["invoices"][index] = InvoiceSubmission.Invoice(**invoice) - if "payment" in data and data["payment"] != None: + if "payment" in data and data["payment"] is not None: data["payment"] = InvoiceSubmission.Payment(**data["payment"]) - if "additional_payments" in data and data["additional_payments"] != None: + if "additional_payments" in data and data["additional_payments"] is not None: for index, additional_payment in enumerate(data["additional_payments"]): data["additional_payments"][index] = InvoiceSubmission.Payment(**additional_payment) @@ -694,4 +698,4 @@ class MerchantUnlinkedDeposit(_Type): status: str note: Optional[str] -#endregion \ No newline at end of file +#endregion diff --git a/bfxapi/websocket/client/bfx_websocket_client.py b/bfxapi/websocket/client/bfx_websocket_client.py index 360f840..88cb853 100644 --- a/bfxapi/websocket/client/bfx_websocket_client.py +++ b/bfxapi/websocket/client/bfx_websocket_client.py @@ -29,6 +29,27 @@ def _require_websocket_authentication(function: F) -> F: return cast(F, wrapper) +class _Delay: + BACKOFF_MIN, BACKOFF_MAX = 1.92, 60.0 + + BACKOFF_INITIAL = 5.0 + + def __init__(self, backoff_factor): + self.__backoff_factor = backoff_factor + self.__backoff_delay = _Delay.BACKOFF_MIN + self.__initial_delay = random.random() * _Delay.BACKOFF_INITIAL + + def next(self): + backoff_delay = self.peek() + __backoff_delay = self.__backoff_delay * self.__backoff_factor + self.__backoff_delay = min(__backoff_delay, _Delay.BACKOFF_MAX) + + return backoff_delay + + def peek(self): + return (self.__backoff_delay == _Delay.BACKOFF_MIN) \ + and self.__initial_delay or self.__backoff_delay + class BfxWebsocketClient: VERSION = BfxWebsocketBucket.VERSION @@ -135,27 +156,6 @@ class BfxWebsocketClient: if message[0] == 0 and message[1] != _HEARTBEAT: self.handler.handle(message[1], message[2]) - class _Delay: - BACKOFF_MIN, BACKOFF_MAX = 1.92, 60.0 - - BACKOFF_INITIAL = 5.0 - - def __init__(self, backoff_factor): - self.__backoff_factor = backoff_factor - self.__backoff_delay = _Delay.BACKOFF_MIN - self.__initial_delay = random.random() * _Delay.BACKOFF_INITIAL - - def next(self): - backoff_delay = self.peek() - __backoff_delay = self.__backoff_delay * self.__backoff_factor - self.__backoff_delay = min(__backoff_delay, _Delay.BACKOFF_MAX) - - return backoff_delay - - def peek(self): - return (self.__backoff_delay == _Delay.BACKOFF_MIN) \ - and self.__initial_delay or self.__backoff_delay - while True: if reconnection.status: await asyncio.sleep(delay.next()) diff --git a/bfxapi/websocket/client/bfx_websocket_inputs.py b/bfxapi/websocket/client/bfx_websocket_inputs.py index 25ad8b4..77a1521 100644 --- a/bfxapi/websocket/client/bfx_websocket_inputs.py +++ b/bfxapi/websocket/client/bfx_websocket_inputs.py @@ -1,4 +1,4 @@ -#pylint: disable=redefined-builtin,too-many-arguments +#pylint: disable=redefined-builtin from decimal import Decimal from datetime import datetime @@ -15,6 +15,7 @@ class BfxWebsocketInputs: 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, @@ -35,6 +36,7 @@ class BfxWebsocketInputs: 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, @@ -54,6 +56,7 @@ class BfxWebsocketInputs: }) async def cancel_order(self, + *, id: Optional[int] = None, cid: Optional[int] = None, cid_date: Optional[str] = None): @@ -62,6 +65,7 @@ class BfxWebsocketInputs: }) async def cancel_order_multi(self, + *, ids: Optional[List[int]] = None, cids: Optional[List[Tuple[int, str]]] = None, gids: Optional[List[int]] = None, @@ -71,12 +75,14 @@ class BfxWebsocketInputs: "all": int(all) }) + #pylint: disable-next=too-many-arguments 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): await self.__handle_websocket_input("fon", { "type": type, "symbol": symbol, "amount": amount, diff --git a/bfxapi/websocket/types.py b/bfxapi/websocket/types.py index 2909030..fa0972a 100644 --- a/bfxapi/websocket/types.py +++ b/bfxapi/websocket/types.py @@ -3,11 +3,11 @@ from typing import * from dataclasses import dataclass +from .. labeler import _Type + #pylint: disable-next=unused-import from .. notification import Notification -from .. labeler import _Type - from ..utils.json_encoder import JSON #region Type hinting for Websocket Public Channels