mirror of
https://github.com/aljazceru/bitfinex-api-py.git
synced 2025-12-20 07:14:20 +01:00
Move _Delay local class in global scope (bfxapi.websocket.client.bfx_websocket_client).
Apply pylint's linting rules to bfxapi/rest/__init__.py, bfxapi/rest/enums.py, bfxapi/rest/exceptions.py, bfxapi/rest/serializers.py and bfxapi/rest/types.py." Apply pylint's linting rules to bfxapi/rest/endpoints/__init__.py, bfxapi/rest/endpoints/bfx_rest_interface.py and bfxapi/rest/endpoints/rest_public_endpoints.py.
This commit is contained in:
@@ -10,6 +10,7 @@ disable=
|
|||||||
multiple-imports,
|
multiple-imports,
|
||||||
missing-docstring,
|
missing-docstring,
|
||||||
too-few-public-methods,
|
too-few-public-methods,
|
||||||
|
too-many-public-methods,
|
||||||
too-many-instance-attributes,
|
too-many-instance-attributes,
|
||||||
dangerous-default-value,
|
dangerous-default-value,
|
||||||
inconsistent-return-statements,
|
inconsistent-return-statements,
|
||||||
@@ -19,7 +20,7 @@ disable=
|
|||||||
|
|
||||||
max-line-length=120
|
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]
|
[TYPECHECK]
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
from typing import Optional
|
|
||||||
|
|
||||||
from .rest_public_endpoints import RestPublicEndpoints
|
from .rest_public_endpoints import RestPublicEndpoints
|
||||||
from .rest_authenticated_endpoints import RestAuthenticatedEndpoints
|
from .rest_authenticated_endpoints import RestAuthenticatedEndpoints
|
||||||
from .rest_merchant_endpoints import RestMerchantEndpoints
|
from .rest_merchant_endpoints import RestMerchantEndpoints
|
||||||
|
|
||||||
class BfxRestInterface(object):
|
class BfxRestInterface:
|
||||||
VERSION = 2
|
VERSION = 2
|
||||||
|
|
||||||
def __init__(self, host, credentials = None):
|
def __init__(self, host, credentials = None):
|
||||||
API_KEY, API_SECRET = credentials and \
|
api_key, api_secret = (credentials['api_key'], credentials['api_secret']) if credentials else (None, None)
|
||||||
(credentials["api_key"], credentials["api_secret"]) or (None, None)
|
|
||||||
|
|
||||||
self.public = RestPublicEndpoints(host=host)
|
self.public = RestPublicEndpoints(host=host)
|
||||||
self.auth = RestAuthenticatedEndpoints(host=host, API_KEY=API_KEY, API_SECRET=API_SECRET)
|
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)
|
self.merchant = RestMerchantEndpoints(host=host, api_key=api_key, api_secret=api_secret)
|
||||||
|
|||||||
@@ -10,19 +10,19 @@ from .. middleware import Middleware
|
|||||||
|
|
||||||
class RestAuthenticatedEndpoints(Middleware):
|
class RestAuthenticatedEndpoints(Middleware):
|
||||||
def get_user_info(self) -> UserInfo:
|
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]:
|
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:
|
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,
|
"symbol": symbol, "type": type, "dir": dir,
|
||||||
"rate": rate, "lev": lev
|
"rate": rate, "lev": lev
|
||||||
}))
|
}))
|
||||||
|
|
||||||
def get_wallets(self) -> List[Wallet]:
|
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]:
|
def get_orders(self, symbol: Optional[str] = None, ids: Optional[List[str]] = None) -> List[Order]:
|
||||||
endpoint = "auth/r/orders"
|
endpoint = "auth/r/orders"
|
||||||
@@ -30,7 +30,7 @@ class RestAuthenticatedEndpoints(Middleware):
|
|||||||
if symbol != None:
|
if symbol != None:
|
||||||
endpoint += f"/{symbol}"
|
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],
|
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: Optional[Union[Decimal, float, str]] = None, lev: Optional[int] = None,
|
||||||
@@ -45,7 +45,7 @@ class RestAuthenticatedEndpoints(Middleware):
|
|||||||
"flags": flags, "tif": tif, "meta": meta
|
"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,
|
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,
|
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
|
"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]:
|
def cancel_order(self, id: Optional[int] = None, cid: Optional[int] = None, cid_date: Optional[str] = None) -> Notification[Order]:
|
||||||
body = {
|
body = {
|
||||||
@@ -67,7 +67,7 @@ class RestAuthenticatedEndpoints(Middleware):
|
|||||||
"cid_date": cid_date
|
"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]]:
|
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 = {
|
body = {
|
||||||
@@ -78,7 +78,7 @@ class RestAuthenticatedEndpoints(Middleware):
|
|||||||
"all": int(all)
|
"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]:
|
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:
|
if symbol == None:
|
||||||
@@ -91,10 +91,10 @@ class RestAuthenticatedEndpoints(Middleware):
|
|||||||
"limit": limit
|
"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]:
|
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]:
|
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:
|
if symbol == None:
|
||||||
@@ -107,7 +107,7 @@ class RestAuthenticatedEndpoints(Middleware):
|
|||||||
"limit": limit
|
"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]:
|
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 = {
|
body = {
|
||||||
@@ -116,51 +116,51 @@ class RestAuthenticatedEndpoints(Middleware):
|
|||||||
"limit": limit
|
"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:
|
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:
|
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]
|
data = [response[1]] + response[2]
|
||||||
return serializers.SymbolMarginInfo.parse(*data)
|
return serializers.SymbolMarginInfo.parse(*data)
|
||||||
|
|
||||||
def get_all_symbols_margin_info(self) -> List[SymbolMarginInfo]:
|
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]:
|
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]:
|
def claim_position(self, id: int, amount: Optional[Union[Decimal, float, str]] = None) -> Notification[PositionClaim]:
|
||||||
return serializers._Notification[PositionClaim](serializers.PositionClaim).parse(
|
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]:
|
def increase_position(self, symbol: str, amount: Union[Decimal, float, str]) -> Notification[PositionIncrease]:
|
||||||
return serializers._Notification[PositionIncrease](serializers.PositionIncrease).parse(
|
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:
|
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]
|
data = response[0] + [response[1][0]] + response[1][1] + [response[1][2]] + response[4] + response[5]
|
||||||
return serializers.PositionIncreaseInfo.parse(*data)
|
return serializers.PositionIncreaseInfo.parse(*data)
|
||||||
|
|
||||||
def get_positions_history(self, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None) -> List[PositionHistory]:
|
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]:
|
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]:
|
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:
|
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:
|
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]:
|
def get_funding_offers(self, symbol: Optional[str] = None) -> List[FundingOffer]:
|
||||||
endpoint = "auth/r/funding/offers"
|
endpoint = "auth/r/funding/offers"
|
||||||
@@ -168,7 +168,7 @@ class RestAuthenticatedEndpoints(Middleware):
|
|||||||
if symbol != None:
|
if symbol != None:
|
||||||
endpoint += f"/{symbol}"
|
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],
|
def submit_funding_offer(self, type: FundingOfferType, symbol: str, amount: Union[Decimal, float, str],
|
||||||
rate: Union[Decimal, float, str], period: int,
|
rate: Union[Decimal, float, str], period: int,
|
||||||
@@ -179,30 +179,30 @@ class RestAuthenticatedEndpoints(Middleware):
|
|||||||
"flags": flags
|
"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]:
|
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]]:
|
def cancel_all_funding_offers(self, currency: str) -> Notification[Literal[None]]:
|
||||||
return serializers._Notification[Literal[None]](None).parse(
|
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]]:
|
def submit_funding_close(self, id: int) -> Notification[Literal[None]]:
|
||||||
return serializers._Notification[Literal[None]](None).parse(
|
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]:
|
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),
|
"status": int(status),
|
||||||
"currency": currency, "amount": amount,
|
"currency": currency, "amount": amount,
|
||||||
"rate": rate, "period": period
|
"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]]:
|
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,
|
"type": type,
|
||||||
"id": ids,
|
"id": ids,
|
||||||
"changes": changes
|
"changes": changes
|
||||||
@@ -218,14 +218,14 @@ class RestAuthenticatedEndpoints(Middleware):
|
|||||||
"limit": limit
|
"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]:
|
def get_funding_loans(self, symbol: Optional[str] = None) -> List[FundingLoan]:
|
||||||
if symbol == None:
|
if symbol == None:
|
||||||
endpoint = "auth/r/funding/loans"
|
endpoint = "auth/r/funding/loans"
|
||||||
else: endpoint = f"auth/r/funding/loans/{symbol}"
|
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]:
|
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:
|
if symbol == None:
|
||||||
@@ -237,14 +237,14 @@ class RestAuthenticatedEndpoints(Middleware):
|
|||||||
"limit": limit
|
"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]:
|
def get_funding_credits(self, symbol: Optional[str] = None) -> List[FundingCredit]:
|
||||||
if symbol == None:
|
if symbol == None:
|
||||||
endpoint = "auth/r/funding/credits"
|
endpoint = "auth/r/funding/credits"
|
||||||
else: endpoint = f"auth/r/funding/credits/{symbol}"
|
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]:
|
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:
|
if symbol == None:
|
||||||
@@ -256,7 +256,7 @@ class RestAuthenticatedEndpoints(Middleware):
|
|||||||
"limit": limit
|
"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]:
|
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:
|
if symbol == None:
|
||||||
@@ -269,10 +269,10 @@ class RestAuthenticatedEndpoints(Middleware):
|
|||||||
"limit": limit
|
"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:
|
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]
|
data = [response[1]] + response[2]
|
||||||
return serializers.FundingInfo.parse(*data)
|
return serializers.FundingInfo.parse(*data)
|
||||||
|
|
||||||
@@ -283,10 +283,10 @@ class RestAuthenticatedEndpoints(Middleware):
|
|||||||
"amount": amount
|
"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]:
|
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,
|
"wallet": wallet, "method": method,
|
||||||
"address": address, "amount": amount,
|
"address": address, "amount": amount,
|
||||||
}))
|
}))
|
||||||
@@ -298,7 +298,7 @@ class RestAuthenticatedEndpoints(Middleware):
|
|||||||
"renew": int(renew)
|
"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:
|
def generate_deposit_invoice(self, wallet: str, currency: str, amount: Union[Decimal, float, str]) -> LightningNetworkInvoice:
|
||||||
body = {
|
body = {
|
||||||
@@ -306,7 +306,7 @@ class RestAuthenticatedEndpoints(Middleware):
|
|||||||
"amount": amount
|
"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]:
|
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:
|
if currency == None:
|
||||||
@@ -318,4 +318,4 @@ class RestAuthenticatedEndpoints(Middleware):
|
|||||||
"limit": limit
|
"limit": limit
|
||||||
}
|
}
|
||||||
|
|
||||||
return [ serializers.Movement.parse(*sub_data) for sub_data in self._POST(endpoint, body=body) ]
|
return [ serializers.Movement.parse(*sub_data) for sub_data in self._post(endpoint, body=body) ]
|
||||||
@@ -24,12 +24,12 @@ class RestMerchantEndpoints(Middleware):
|
|||||||
"webhook": webhook, "redirect_url": redirect_url
|
"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)
|
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]:
|
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,
|
"id": id, "start": start, "end": end,
|
||||||
"limit": limit
|
"limit": limit
|
||||||
})) ]
|
})) ]
|
||||||
@@ -43,24 +43,24 @@ class RestMerchantEndpoints(Middleware):
|
|||||||
"crypto": crypto, "id": id, "order_id": order_id
|
"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)
|
return InvoicePage.parse(data)
|
||||||
|
|
||||||
def get_invoice_count_stats(self, status: Literal["CREATED", "PENDING", "COMPLETED", "EXPIRED"], format: str) -> List[InvoiceStats]:
|
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]:
|
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:
|
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,
|
"id": id, "payCcy": pay_currency, "depositId": deposit_id,
|
||||||
"ledgerId": ledger_id
|
"ledgerId": ledger_id
|
||||||
})))
|
})))
|
||||||
|
|
||||||
def expire_invoice(self, id: str) -> InvoiceSubmission:
|
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]:
|
def get_currency_conversion_list(self) -> List[CurrencyConversion]:
|
||||||
return [
|
return [
|
||||||
@@ -68,36 +68,36 @@ class RestMerchantEndpoints(Middleware):
|
|||||||
base_currency=sub_data["baseCcy"],
|
base_currency=sub_data["baseCcy"],
|
||||||
convert_currency=sub_data["convertCcy"],
|
convert_currency=sub_data["convertCcy"],
|
||||||
created=sub_data["created"]
|
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:
|
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,
|
"baseCcy": base_currency,
|
||||||
"convertCcy": convert_currency
|
"convertCcy": convert_currency
|
||||||
}))
|
}))
|
||||||
|
|
||||||
def remove_currency_conversion(self, base_currency: str, convert_currency: str) -> bool:
|
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,
|
"baseCcy": base_currency,
|
||||||
"convertCcy": convert_currency
|
"convertCcy": convert_currency
|
||||||
}))
|
}))
|
||||||
|
|
||||||
def set_merchant_settings(self, key: MerchantSettingsKey, val: Any) -> bool:
|
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:
|
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]:
|
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]:
|
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
|
"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]:
|
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
|
"ccy": ccy, "start": start, "end": end
|
||||||
})) ]
|
})) ]
|
||||||
@@ -1,7 +1,17 @@
|
|||||||
|
#pylint: disable=redefined-builtin
|
||||||
|
|
||||||
from typing import List, Union, Literal, Optional, Any, cast
|
from typing import List, Union, Literal, Optional, Any, cast
|
||||||
|
|
||||||
from decimal import Decimal
|
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 .. import serializers
|
||||||
from .. enums import Config, Sort
|
from .. enums import Config, Sort
|
||||||
@@ -9,103 +19,151 @@ from .. middleware import Middleware
|
|||||||
|
|
||||||
class RestPublicEndpoints(Middleware):
|
class RestPublicEndpoints(Middleware):
|
||||||
def conf(self, config: Config) -> Any:
|
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:
|
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]]:
|
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 }
|
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]:
|
def get_t_tickers(self, pairs: Union[List[str], Literal["ALL"]]) -> List[TradingPairTicker]:
|
||||||
if isinstance(pairs, str) and pairs == "ALL":
|
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)
|
return cast(List[TradingPairTicker], data)
|
||||||
|
|
||||||
def get_f_tickers(self, currencies: Union[List[str], Literal["ALL"]]) -> List[FundingCurrencyTicker]:
|
def get_f_tickers(self, currencies: Union[List[str], Literal["ALL"]]) -> List[FundingCurrencyTicker]:
|
||||||
if isinstance(currencies, str) and currencies == "ALL":
|
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)
|
return cast(List[FundingCurrencyTicker], data)
|
||||||
|
|
||||||
def get_t_ticker(self, pair: str) -> TradingPairTicker:
|
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:
|
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]:
|
def get_tickers_history(self,
|
||||||
return [ serializers.TickersHistory.parse(*sub_data) for sub_data in self._GET("tickers/hist", params={
|
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),
|
"symbols": ",".join(symbols),
|
||||||
"start": start, "end": end,
|
"start": start, "end": end,
|
||||||
"limit": limit
|
"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 }
|
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 ]
|
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 }
|
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 ]
|
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]:
|
def get_t_book(self,
|
||||||
return [ serializers.TradingPairBook.parse(*sub_data) for sub_data in self._GET(f"book/{pair}/{precision}", params={ "len": len }) ]
|
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]:
|
def get_f_book(self,
|
||||||
return [ serializers.FundingCurrencyBook.parse(*sub_data) for sub_data in self._GET(f"book/{currency}/{precision}", params={ "len": len }) ]
|
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]:
|
def get_t_raw_book(self,
|
||||||
return [ serializers.TradingPairRawBook.parse(*sub_data) for sub_data in self._GET(f"book/{pair}/R0", params={ "len": len }) ]
|
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]:
|
def get_f_raw_book(self,
|
||||||
return [ serializers.FundingCurrencyRawBook.parse(*sub_data) for sub_data in self._GET(f"book/{currency}/R0", params={ "len": len }) ]
|
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(
|
def get_stats_hist(self,
|
||||||
self,
|
resource: str,
|
||||||
resource: str,
|
*,
|
||||||
sort: Optional[Sort] = None, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None
|
sort: Optional[Sort] = None,
|
||||||
) -> List[Statistic]:
|
start: Optional[str] = None,
|
||||||
|
end: Optional[str] = None,
|
||||||
|
limit: Optional[int] = None) -> List[Statistic]:
|
||||||
params = { "sort": sort, "start": start, "end": end, "limit": limit }
|
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 ]
|
return [ serializers.Statistic.parse(*sub_data) for sub_data in data ]
|
||||||
|
|
||||||
def get_stats_last(
|
def get_stats_last(self,
|
||||||
self,
|
resource: str,
|
||||||
resource: str,
|
*,
|
||||||
sort: Optional[Sort] = None, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None
|
sort: Optional[Sort] = None,
|
||||||
) -> Statistic:
|
start: Optional[str] = None,
|
||||||
|
end: Optional[str] = None,
|
||||||
|
limit: Optional[int] = None) -> Statistic:
|
||||||
params = { "sort": sort, "start": start, "end": end, "limit": limit }
|
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)
|
return serializers.Statistic.parse(*data)
|
||||||
|
|
||||||
def get_candles_hist(
|
def get_candles_hist(self,
|
||||||
self,
|
symbol: str,
|
||||||
symbol: str, tf: str = "1m",
|
tf: str = "1m",
|
||||||
sort: Optional[Sort] = None, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None
|
*,
|
||||||
) -> List[Candle]:
|
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 }
|
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 ]
|
return [ serializers.Candle.parse(*sub_data) for sub_data in data ]
|
||||||
|
|
||||||
def get_candles_last(
|
def get_candles_last(self,
|
||||||
self,
|
symbol: str,
|
||||||
symbol: str, tf: str = "1m",
|
tf: str = "1m",
|
||||||
sort: Optional[Sort] = None, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None
|
*,
|
||||||
) -> Candle:
|
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 }
|
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)
|
return serializers.Candle.parse(*data)
|
||||||
|
|
||||||
def get_derivatives_status(self, keys: Union[List[str], Literal["ALL"]]) -> List[DerivativesStatus]:
|
def get_derivatives_status(self, keys: Union[List[str], Literal["ALL"]]) -> List[DerivativesStatus]:
|
||||||
@@ -113,74 +171,109 @@ class RestPublicEndpoints(Middleware):
|
|||||||
params = { "keys": "ALL" }
|
params = { "keys": "ALL" }
|
||||||
else: params = { "keys": ",".join(keys) }
|
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 ]
|
return [ serializers.DerivativesStatus.parse(*sub_data) for sub_data in data ]
|
||||||
|
|
||||||
def get_derivatives_status_history(
|
def get_derivatives_status_history(self,
|
||||||
self,
|
type: str,
|
||||||
type: str, symbol: str,
|
symbol: str,
|
||||||
sort: Optional[Sort] = None, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None
|
*,
|
||||||
) -> List[DerivativesStatus]:
|
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 }
|
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 ]
|
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 }
|
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 ]
|
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}
|
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 ]
|
return [ serializers.Candle.parse(*sub_data) for sub_data in data ]
|
||||||
|
|
||||||
def get_leaderboards_hist(
|
def get_leaderboards_hist(self,
|
||||||
self,
|
resource: str,
|
||||||
resource: str,
|
*,
|
||||||
sort: Optional[Sort] = None, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None
|
sort: Optional[Sort] = None,
|
||||||
) -> List[Leaderboard]:
|
start: Optional[str] = None,
|
||||||
|
end: Optional[str] = None,
|
||||||
|
limit: Optional[int] = None) -> List[Leaderboard]:
|
||||||
params = { "sort": sort, "start": start, "end": end, "limit": limit }
|
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 ]
|
return [ serializers.Leaderboard.parse(*sub_data) for sub_data in data ]
|
||||||
|
|
||||||
def get_leaderboards_last(
|
def get_leaderboards_last(self,
|
||||||
self,
|
resource: str,
|
||||||
resource: str,
|
*,
|
||||||
sort: Optional[Sort] = None, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None
|
sort: Optional[Sort] = None,
|
||||||
) -> Leaderboard:
|
start: Optional[str] = None,
|
||||||
|
end: Optional[str] = None,
|
||||||
|
limit: Optional[int] = None) -> Leaderboard:
|
||||||
params = { "sort": sort, "start": start, "end": end, "limit": limit }
|
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)
|
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 }
|
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 ]
|
return [ serializers.FundingStatistic.parse(*sub_data) for sub_data in data ]
|
||||||
|
|
||||||
def get_pulse_profile(self, nickname: str) -> PulseProfile:
|
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]:
|
def get_pulse_history(self, *, end: Optional[str] = None, limit: Optional[int] = None) -> List[PulseMessage]:
|
||||||
messages = list()
|
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]
|
subdata[18] = subdata[18][0]
|
||||||
message = serializers.PulseMessage.parse(*subdata)
|
message = serializers.PulseMessage.parse(*subdata)
|
||||||
messages.append(message)
|
messages.append(message)
|
||||||
|
|
||||||
return messages
|
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:
|
def get_trading_market_average_price(self,
|
||||||
return serializers.TradingMarketAveragePrice.parse(*self._POST("calc/trade/avg", body={
|
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
|
"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:
|
def get_funding_market_average_price(self,
|
||||||
return serializers.FundingMarketAveragePrice.parse(*self._POST("calc/trade/avg", body={
|
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
|
"symbol": symbol, "amount": amount, "period": period, "rate_limit": rate_limit
|
||||||
}))
|
}))
|
||||||
|
|
||||||
def get_fx_rate(self, ccy1: str, ccy2: str) -> FxRate:
|
def get_fx_rate(self, ccy1: str, ccy2: str) -> FxRate:
|
||||||
return serializers.FxRate.parse(*self._POST("calc/fx", body={ "ccy1": ccy1, "ccy2": ccy2 }))
|
return serializers.FxRate.parse(*self._post("calc/fx", body={ "ccy1": ccy1, "ccy2": ccy2 }))
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#pylint: disable-next=wildcard-import,unused-wildcard-import
|
||||||
from ..enums import *
|
from ..enums import *
|
||||||
|
|
||||||
class Config(str, Enum):
|
class Config(str, Enum):
|
||||||
|
|||||||
@@ -14,32 +14,22 @@ class BfxRestException(BfxBaseException):
|
|||||||
Base class for all custom exceptions in bfxapi/rest/exceptions.py.
|
Base class for all custom exceptions in bfxapi/rest/exceptions.py.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pass
|
|
||||||
|
|
||||||
class ResourceNotFound(BfxRestException):
|
class ResourceNotFound(BfxRestException):
|
||||||
"""
|
"""
|
||||||
This error indicates a failed HTTP request to a non-existent resource.
|
This error indicates a failed HTTP request to a non-existent resource.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pass
|
|
||||||
|
|
||||||
class RequestParametersError(BfxRestException):
|
class RequestParametersError(BfxRestException):
|
||||||
"""
|
"""
|
||||||
This error indicates that there are some invalid parameters sent along with an HTTP request.
|
This error indicates that there are some invalid parameters sent along with an HTTP request.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pass
|
|
||||||
|
|
||||||
class InvalidAuthenticationCredentials(BfxRestException):
|
class InvalidAuthenticationCredentials(BfxRestException):
|
||||||
"""
|
"""
|
||||||
This error indicates that the user has provided incorrect credentials (API-KEY and API-SECRET) for authentication.
|
This error indicates that the user has provided incorrect credentials (API-KEY and API-SECRET) for authentication.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pass
|
|
||||||
|
|
||||||
class UnknownGenericError(BfxRestException):
|
class UnknownGenericError(BfxRestException):
|
||||||
"""
|
"""
|
||||||
This error indicates an undefined problem processing an HTTP request sent to the APIs.
|
This error indicates an undefined problem processing an HTTP request sent to the APIs.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pass
|
|
||||||
@@ -1,32 +1,34 @@
|
|||||||
import time, hmac, hashlib, json, requests
|
from typing import TYPE_CHECKING, Optional, Any
|
||||||
|
|
||||||
from typing import TYPE_CHECKING, Optional, Any, cast
|
|
||||||
|
|
||||||
from http import HTTPStatus
|
from http import HTTPStatus
|
||||||
|
|
||||||
|
import time, hmac, hashlib, json, requests
|
||||||
|
|
||||||
from ..enums import Error
|
from ..enums import Error
|
||||||
from ..exceptions import ResourceNotFound, RequestParametersError, InvalidAuthenticationCredentials, UnknownGenericError
|
from ..exceptions import ResourceNotFound, RequestParametersError, InvalidAuthenticationCredentials, UnknownGenericError
|
||||||
|
|
||||||
from ...utils.json_encoder import JSONEncoder
|
from ...utils.json_encoder import JSONEncoder
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from requests.sessions import _Params
|
from requests.sessions import _Params
|
||||||
|
|
||||||
class Middleware(object):
|
class Middleware:
|
||||||
def __init__(self, host: str, API_KEY: Optional[str] = None, API_SECRET: Optional[str] = None):
|
TIMEOUT = 30
|
||||||
self.host, self.API_KEY, self.API_SECRET = host, API_KEY, API_SECRET
|
|
||||||
|
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):
|
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"
|
"API_KEY and API_SECRET must be both str to call __build_authentication_headers"
|
||||||
|
|
||||||
nonce = str(round(time.time() * 1_000_000))
|
nonce = str(round(time.time() * 1_000_000))
|
||||||
|
|
||||||
if data == None:
|
if data is None:
|
||||||
path = f"/api/v2/{endpoint}{nonce}"
|
path = f"/api/v2/{endpoint}{nonce}"
|
||||||
else: path = f"/api/v2/{endpoint}{nonce}{data}"
|
else: path = f"/api/v2/{endpoint}{nonce}{data}"
|
||||||
|
|
||||||
signature = hmac.new(
|
signature = hmac.new(
|
||||||
self.API_SECRET.encode("utf8"),
|
self.api_secret.encode("utf8"),
|
||||||
path.encode("utf8"),
|
path.encode("utf8"),
|
||||||
hashlib.sha384
|
hashlib.sha384
|
||||||
).hexdigest()
|
).hexdigest()
|
||||||
@@ -34,11 +36,15 @@ class Middleware(object):
|
|||||||
return {
|
return {
|
||||||
"bfx-nonce": nonce,
|
"bfx-nonce": nonce,
|
||||||
"bfx-signature": signature,
|
"bfx-signature": signature,
|
||||||
"bfx-apikey": self.API_KEY
|
"bfx-apikey": self.api_key
|
||||||
}
|
}
|
||||||
|
|
||||||
def _GET(self, endpoint: str, params: Optional["_Params"] = None) -> Any:
|
def _get(self, endpoint: str, params: Optional["_Params"] = None) -> Any:
|
||||||
response = requests.get(f"{self.host}/{endpoint}", params=params)
|
response = requests.get(
|
||||||
|
url=f"{self.host}/{endpoint}",
|
||||||
|
params=params,
|
||||||
|
timeout=Middleware.TIMEOUT
|
||||||
|
)
|
||||||
|
|
||||||
if response.status_code == HTTPStatus.NOT_FOUND:
|
if response.status_code == HTTPStatus.NOT_FOUND:
|
||||||
raise ResourceNotFound(f"No resources found at endpoint <{endpoint}>.")
|
raise ResourceNotFound(f"No resources found at endpoint <{endpoint}>.")
|
||||||
@@ -47,22 +53,31 @@ class Middleware(object):
|
|||||||
|
|
||||||
if len(data) and data[0] == "error":
|
if len(data) and data[0] == "error":
|
||||||
if data[1] == Error.ERR_PARAMS:
|
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:
|
if data[1] is 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]}>.")
|
raise UnknownGenericError("The server replied to the request with "
|
||||||
|
+ f"a generic error with message: <{data[2]}>.")
|
||||||
|
|
||||||
return data
|
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
|
data = body and json.dumps(body, cls=JSONEncoder) or None
|
||||||
|
|
||||||
headers = { "Content-Type": "application/json" }
|
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) }
|
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:
|
if response.status_code == HTTPStatus.NOT_FOUND:
|
||||||
raise ResourceNotFound(f"No resources found at endpoint <{endpoint}>.")
|
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 isinstance(data, list) and len(data) and data[0] == "error":
|
||||||
if data[1] == Error.ERR_PARAMS:
|
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:
|
if data[1] == Error.ERR_AUTH_FAIL:
|
||||||
raise InvalidAuthenticationCredentials("Cannot authenticate with given API-KEY and API-SECRET.")
|
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:
|
if data[1] is 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]}>.")
|
raise UnknownGenericError("The server replied to the request with "
|
||||||
|
+ f"a generic error with message: <{data[2]}>.")
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,13 @@
|
|||||||
|
#pylint: disable-next=wildcard-import,unused-wildcard-import
|
||||||
from typing import *
|
from typing import *
|
||||||
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
|
||||||
from .. labeler import _Type, partial, compose
|
from .. labeler import _Type, partial, compose
|
||||||
|
|
||||||
|
#pylint: disable-next=unused-import
|
||||||
from .. notification import Notification
|
from .. notification import Notification
|
||||||
|
|
||||||
from ..utils.json_encoder import JSON
|
from ..utils.json_encoder import JSON
|
||||||
|
|
||||||
#region Type hinting for Rest Public Endpoints
|
#region Type hinting for Rest Public Endpoints
|
||||||
@@ -586,16 +590,16 @@ class InvoiceSubmission(_Type):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parse(cls, data: Dict[str, Any]) -> "InvoiceSubmission":
|
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"])
|
data["customer_info"] = InvoiceSubmission.CustomerInfo(**data["customer_info"])
|
||||||
|
|
||||||
for index, invoice in enumerate(data["invoices"]):
|
for index, invoice in enumerate(data["invoices"]):
|
||||||
data["invoices"][index] = InvoiceSubmission.Invoice(**invoice)
|
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"])
|
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"]):
|
for index, additional_payment in enumerate(data["additional_payments"]):
|
||||||
data["additional_payments"][index] = InvoiceSubmission.Payment(**additional_payment)
|
data["additional_payments"][index] = InvoiceSubmission.Payment(**additional_payment)
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,27 @@ def _require_websocket_authentication(function: F) -> F:
|
|||||||
|
|
||||||
return cast(F, wrapper)
|
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:
|
class BfxWebsocketClient:
|
||||||
VERSION = BfxWebsocketBucket.VERSION
|
VERSION = BfxWebsocketBucket.VERSION
|
||||||
|
|
||||||
@@ -135,27 +156,6 @@ class BfxWebsocketClient:
|
|||||||
if message[0] == 0 and message[1] != _HEARTBEAT:
|
if message[0] == 0 and message[1] != _HEARTBEAT:
|
||||||
self.handler.handle(message[1], message[2])
|
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:
|
while True:
|
||||||
if reconnection.status:
|
if reconnection.status:
|
||||||
await asyncio.sleep(delay.next())
|
await asyncio.sleep(delay.next())
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#pylint: disable=redefined-builtin,too-many-arguments
|
#pylint: disable=redefined-builtin
|
||||||
|
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
@@ -15,6 +15,7 @@ class BfxWebsocketInputs:
|
|||||||
type: OrderType,
|
type: OrderType,
|
||||||
symbol: str,
|
symbol: str,
|
||||||
amount: Union[Decimal, float, str],
|
amount: Union[Decimal, float, str],
|
||||||
|
*,
|
||||||
price: Optional[Union[Decimal, float, str]] = None,
|
price: Optional[Union[Decimal, float, str]] = None,
|
||||||
lev: Optional[int] = None,
|
lev: Optional[int] = None,
|
||||||
price_trailing: Optional[Union[Decimal, float, str]] = None,
|
price_trailing: Optional[Union[Decimal, float, str]] = None,
|
||||||
@@ -35,6 +36,7 @@ class BfxWebsocketInputs:
|
|||||||
|
|
||||||
async def update_order(self,
|
async def update_order(self,
|
||||||
id: int,
|
id: int,
|
||||||
|
*,
|
||||||
amount: Optional[Union[Decimal, float, str]] = None,
|
amount: Optional[Union[Decimal, float, str]] = None,
|
||||||
price: Optional[Union[Decimal, float, str]] = None,
|
price: Optional[Union[Decimal, float, str]] = None,
|
||||||
cid: Optional[int] = None,
|
cid: Optional[int] = None,
|
||||||
@@ -54,6 +56,7 @@ class BfxWebsocketInputs:
|
|||||||
})
|
})
|
||||||
|
|
||||||
async def cancel_order(self,
|
async def cancel_order(self,
|
||||||
|
*,
|
||||||
id: Optional[int] = None,
|
id: Optional[int] = None,
|
||||||
cid: Optional[int] = None,
|
cid: Optional[int] = None,
|
||||||
cid_date: Optional[str] = None):
|
cid_date: Optional[str] = None):
|
||||||
@@ -62,6 +65,7 @@ class BfxWebsocketInputs:
|
|||||||
})
|
})
|
||||||
|
|
||||||
async def cancel_order_multi(self,
|
async def cancel_order_multi(self,
|
||||||
|
*,
|
||||||
ids: Optional[List[int]] = None,
|
ids: Optional[List[int]] = None,
|
||||||
cids: Optional[List[Tuple[int, str]]] = None,
|
cids: Optional[List[Tuple[int, str]]] = None,
|
||||||
gids: Optional[List[int]] = None,
|
gids: Optional[List[int]] = None,
|
||||||
@@ -71,12 +75,14 @@ class BfxWebsocketInputs:
|
|||||||
"all": int(all)
|
"all": int(all)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
#pylint: disable-next=too-many-arguments
|
||||||
async def submit_funding_offer(self,
|
async def submit_funding_offer(self,
|
||||||
type: FundingOfferType,
|
type: FundingOfferType,
|
||||||
symbol: str,
|
symbol: str,
|
||||||
amount: Union[Decimal, float, str],
|
amount: Union[Decimal, float, str],
|
||||||
rate: Union[Decimal, float, str],
|
rate: Union[Decimal, float, str],
|
||||||
period: int,
|
period: int,
|
||||||
|
*,
|
||||||
flags: Optional[int] = 0):
|
flags: Optional[int] = 0):
|
||||||
await self.__handle_websocket_input("fon", {
|
await self.__handle_websocket_input("fon", {
|
||||||
"type": type, "symbol": symbol, "amount": amount,
|
"type": type, "symbol": symbol, "amount": amount,
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ from typing import *
|
|||||||
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
from .. labeler import _Type
|
||||||
|
|
||||||
#pylint: disable-next=unused-import
|
#pylint: disable-next=unused-import
|
||||||
from .. notification import Notification
|
from .. notification import Notification
|
||||||
|
|
||||||
from .. labeler import _Type
|
|
||||||
|
|
||||||
from ..utils.json_encoder import JSON
|
from ..utils.json_encoder import JSON
|
||||||
|
|
||||||
#region Type hinting for Websocket Public Channels
|
#region Type hinting for Websocket Public Channels
|
||||||
|
|||||||
Reference in New Issue
Block a user