mirror of
https://github.com/aljazceru/bitfinex-api-py.git
synced 2025-12-19 06:44:22 +01:00
Rewrite and extend custom JSONEncoder in bfxapi/utils/encoder.py to automatically convert floats to strs. Change every Union[Decimal, str] type to Union[Decimal, float, str]. Fix type hinting bug in labeler.py.
This commit is contained in:
@@ -29,7 +29,7 @@ class _Serializer(Generic[T]):
|
||||
return cast(T, self.klass(**dict(self._serialize(*values, skip=skip))))
|
||||
|
||||
class _RecursiveSerializer(_Serializer, Generic[T]):
|
||||
def __init__(self, name: str, klass: Type[_Type], labels: List[str], serializers: Dict[str, Type[_Serializer]], IGNORE: List[str] = ["_PLACEHOLDER"]):
|
||||
def __init__(self, name: str, klass: Type[_Type], labels: List[str], serializers: Dict[str, _Serializer[Any]], IGNORE: List[str] = ["_PLACEHOLDER"]):
|
||||
super().__init__(name, klass, labels, IGNORE)
|
||||
|
||||
self.serializers = serializers
|
||||
@@ -46,5 +46,5 @@ class _RecursiveSerializer(_Serializer, Generic[T]):
|
||||
def generate_labeler_serializer(name: str, klass: Type[T], labels: List[str], IGNORE: List[str] = [ "_PLACEHOLDER" ]) -> _Serializer[T]:
|
||||
return _Serializer[T](name, klass, labels, IGNORE)
|
||||
|
||||
def generate_recursive_serializer(name: str, klass: Type[T], labels: List[str], serializers: Dict[str, Type[_Serializer]], IGNORE: List[str] = [ "_PLACEHOLDER" ]) -> _RecursiveSerializer[T]:
|
||||
def generate_recursive_serializer(name: str, klass: Type[T], labels: List[str], serializers: Dict[str, _Serializer[Any]], IGNORE: List[str] = [ "_PLACEHOLDER" ]) -> _RecursiveSerializer[T]:
|
||||
return _RecursiveSerializer[T](name, klass, labels, serializers, IGNORE)
|
||||
@@ -268,14 +268,14 @@ class _RestPublicEndpoints(_Requests):
|
||||
|
||||
return messages
|
||||
|
||||
def get_trading_market_average_price(self, symbol: str, amount: Union[Decimal, str], price_limit: Optional[Union[Decimal, str]] = None) -> TradingMarketAveragePrice:
|
||||
def get_trading_market_average_price(self, symbol: str, amount: Union[Decimal, float, str], price_limit: Optional[Union[Decimal, float, str]] = None) -> TradingMarketAveragePrice:
|
||||
data = {
|
||||
"symbol": symbol, "amount": amount, "price_limit": price_limit
|
||||
}
|
||||
|
||||
return serializers.TradingMarketAveragePrice.parse(*self._POST("calc/trade/avg", data=data))
|
||||
|
||||
def get_funding_market_average_price(self, symbol: str, amount: Union[Decimal, str], period: int, rate_limit: Optional[Union[Decimal, str]] = None) -> FundingMarketAveragePrice:
|
||||
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:
|
||||
data = {
|
||||
"symbol": symbol, "amount": amount, "period": period,
|
||||
"rate_limit": rate_limit
|
||||
@@ -301,9 +301,9 @@ class _RestAuthenticatedEndpoints(_Requests):
|
||||
def get_positions(self) -> List[Position]:
|
||||
return [ serializers.Position.parse(*sub_data) for sub_data in self._POST("auth/r/positions") ]
|
||||
|
||||
def submit_order(self, type: OrderType, symbol: str, amount: Union[Decimal, str],
|
||||
price: Optional[Union[Decimal, str]] = None, lev: Optional[int] = None,
|
||||
price_trailing: Optional[Union[Decimal, str]] = None, price_aux_limit: Optional[Union[Decimal, str]] = None, price_oco_stop: Optional[Union[Decimal, str]] = None,
|
||||
def submit_order(self, type: OrderType, symbol: str, amount: Union[Decimal, float, str],
|
||||
price: Optional[Union[Decimal, float, str]] = None, lev: Optional[int] = None,
|
||||
price_trailing: Optional[Union[Decimal, float, str]] = None, price_aux_limit: Optional[Union[Decimal, float, str]] = None, price_oco_stop: Optional[Union[Decimal, float, str]] = None,
|
||||
gid: Optional[int] = None, cid: Optional[int] = None,
|
||||
flags: Optional[int] = 0, tif: Optional[Union[datetime, str]] = None, meta: Optional[JSON] = None) -> Notification[Order]:
|
||||
data = {
|
||||
@@ -316,10 +316,10 @@ class _RestAuthenticatedEndpoints(_Requests):
|
||||
|
||||
return serializers._Notification[Order](serializer=serializers.Order).parse(*self._POST("auth/w/order/submit", data=data))
|
||||
|
||||
def update_order(self, id: int, amount: Optional[Union[Decimal, str]] = None, price: Optional[Union[Decimal, 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,
|
||||
flags: Optional[int] = 0, lev: Optional[int] = None, delta: Optional[Union[Decimal, str]] = None,
|
||||
price_aux_limit: Optional[Union[Decimal, str]] = None, price_trailing: Optional[Union[Decimal, str]] = None, tif: Optional[Union[datetime, str]] = None) -> Notification[Order]:
|
||||
flags: Optional[int] = 0, lev: Optional[int] = None, delta: Optional[Union[Decimal, float, str]] = None,
|
||||
price_aux_limit: Optional[Union[Decimal, float, str]] = None, price_trailing: Optional[Union[Decimal, float, str]] = None, tif: Optional[Union[datetime, str]] = None) -> Notification[Order]:
|
||||
data = {
|
||||
"id": id, "amount": amount, "price": price,
|
||||
"cid": cid, "cid_date": cid_date, "gid": gid,
|
||||
@@ -395,8 +395,8 @@ class _RestAuthenticatedEndpoints(_Requests):
|
||||
|
||||
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, str],
|
||||
rate: Union[Decimal, str], period: int,
|
||||
def submit_funding_offer(self, type: FundingOfferType, symbol: str, amount: Union[Decimal, float, str],
|
||||
rate: Union[Decimal, float, str], period: int,
|
||||
flags: Optional[int] = 0) -> Notification[FundingOffer]:
|
||||
data = {
|
||||
"type": type, "symbol": symbol, "amount": amount,
|
||||
@@ -440,7 +440,7 @@ class _RestAuthenticatedEndpoints(_Requests):
|
||||
|
||||
return [ serializers.FundingCredit.parse(*sub_data) for sub_data in self._POST(endpoint, data=data) ]
|
||||
|
||||
def submit_wallet_transfer(self, from_wallet: str, to_wallet: str, currency: str, currency_to: str, amount: Union[Decimal, str]) -> Notification[Transfer]:
|
||||
def submit_wallet_transfer(self, from_wallet: str, to_wallet: str, currency: str, currency_to: str, amount: Union[Decimal, float, str]) -> Notification[Transfer]:
|
||||
data = {
|
||||
"from": from_wallet, "to": to_wallet,
|
||||
"currency": currency, "currency_to": currency_to,
|
||||
@@ -449,7 +449,7 @@ class _RestAuthenticatedEndpoints(_Requests):
|
||||
|
||||
return serializers._Notification[Transfer](serializer=serializers.Transfer).parse(*self._POST("auth/w/transfer", data=data))
|
||||
|
||||
def submit_wallet_withdraw(self, wallet: str, method: str, address: str, amount: Union[Decimal, str]) -> Notification[Withdrawal]:
|
||||
def submit_wallet_withdraw(self, wallet: str, method: str, address: str, amount: Union[Decimal, float, str]) -> Notification[Withdrawal]:
|
||||
data = {
|
||||
"wallet": wallet, "method": method,
|
||||
"address": address, "amount": amount,
|
||||
@@ -466,7 +466,7 @@ class _RestAuthenticatedEndpoints(_Requests):
|
||||
|
||||
return serializers._Notification[DepositAddress](serializer=serializers.DepositAddress).parse(*self._POST("auth/w/deposit/address", data=data))
|
||||
|
||||
def get_deposit_invoice(self, wallet: str, currency: str, amount: Union[Decimal, str]) -> Invoice:
|
||||
def get_deposit_invoice(self, wallet: str, currency: str, amount: Union[Decimal, float, str]) -> Invoice:
|
||||
data = {
|
||||
"wallet": wallet, "currency": currency,
|
||||
"amount": amount
|
||||
|
||||
@@ -3,10 +3,8 @@ from typing import Type, Tuple, List, Dict, TypedDict, Union, Optional, Any
|
||||
from dataclasses import dataclass
|
||||
|
||||
from .. labeler import _Type
|
||||
|
||||
from .. notification import Notification
|
||||
|
||||
JSON = Union[Dict[str, "JSON"], List["JSON"], bool, int, float, str, Type[None]]
|
||||
from .. utils.encoder import JSON
|
||||
|
||||
#region Type hinting for Rest Public Endpoints
|
||||
|
||||
|
||||
@@ -2,8 +2,30 @@ import json
|
||||
from decimal import Decimal
|
||||
from datetime import datetime
|
||||
|
||||
from typing import Type, List, Dict, Union, Any
|
||||
|
||||
JSON = Union[Dict[str, "JSON"], List["JSON"], bool, int, float, str, Type[None]]
|
||||
|
||||
class JSONEncoder(json.JSONEncoder):
|
||||
def default(self, obj):
|
||||
if isinstance(obj, Decimal) or isinstance(obj, datetime):
|
||||
def encode(self, obj: JSON) -> str:
|
||||
def _convert_float_to_str(data: JSON) -> JSON:
|
||||
if isinstance(data, float):
|
||||
return format(Decimal(repr(data)), "f")
|
||||
elif isinstance(data, list):
|
||||
return [ _convert_float_to_str(sub_data) for sub_data in data ]
|
||||
elif isinstance(data, dict):
|
||||
return { key: _convert_float_to_str(value) for key, value in data.items() }
|
||||
else: return data
|
||||
|
||||
data = _convert_float_to_str(obj)
|
||||
|
||||
return json.JSONEncoder.encode(self, data)
|
||||
|
||||
def default(self, obj: Any) -> Any:
|
||||
if isinstance(obj, Decimal):
|
||||
return format(obj, "f")
|
||||
|
||||
if isinstance(obj, datetime):
|
||||
return str(obj)
|
||||
|
||||
return json.JSONEncoder.default(self, obj)
|
||||
@@ -12,9 +12,9 @@ class _BfxWebsocketInputs(object):
|
||||
def __init__(self, __handle_websocket_input):
|
||||
self.__handle_websocket_input = __handle_websocket_input
|
||||
|
||||
async def submit_order(self, type: OrderType, symbol: str, amount: Union[Decimal, str],
|
||||
price: Optional[Union[Decimal, str]] = None, lev: Optional[int] = None,
|
||||
price_trailing: Optional[Union[Decimal, str]] = None, price_aux_limit: Optional[Union[Decimal, str]] = None, price_oco_stop: Optional[Union[Decimal, str]] = None,
|
||||
async def submit_order(self, type: OrderType, symbol: str, amount: Union[Decimal, float, str],
|
||||
price: Optional[Union[Decimal, float, str]] = None, lev: Optional[int] = None,
|
||||
price_trailing: Optional[Union[Decimal, float, str]] = None, price_aux_limit: Optional[Union[Decimal, float, str]] = None, price_oco_stop: Optional[Union[Decimal, float, str]] = None,
|
||||
gid: Optional[int] = None, cid: Optional[int] = None,
|
||||
flags: Optional[int] = 0, tif: Optional[Union[datetime, str]] = None, meta: Optional[JSON] = None):
|
||||
data = _strip({
|
||||
@@ -27,10 +27,10 @@ class _BfxWebsocketInputs(object):
|
||||
|
||||
await self.__handle_websocket_input("on", data)
|
||||
|
||||
async def update_order(self, id: int, amount: Optional[Union[Decimal, str]] = None, price: Optional[Union[Decimal, str]] = None,
|
||||
async def update_order(self, id: int, amount: Optional[Union[Decimal, float, str]] = None, price: Optional[Union[Decimal, float, str]] = None,
|
||||
cid: Optional[int] = None, cid_date: Optional[str] = None, gid: Optional[int] = None,
|
||||
flags: Optional[int] = 0, lev: Optional[int] = None, delta: Optional[Union[Decimal, str]] = None,
|
||||
price_aux_limit: Optional[Union[Decimal, str]] = None, price_trailing: Optional[Union[Decimal, str]] = None, tif: Optional[Union[datetime, str]] = None):
|
||||
flags: Optional[int] = 0, lev: Optional[int] = None, delta: Optional[Union[Decimal, float, str]] = None,
|
||||
price_aux_limit: Optional[Union[Decimal, float, str]] = None, price_trailing: Optional[Union[Decimal, float, str]] = None, tif: Optional[Union[datetime, str]] = None):
|
||||
data = _strip({
|
||||
"id": id, "amount": amount, "price": price,
|
||||
"cid": cid, "cid_date": cid_date, "gid": gid,
|
||||
@@ -60,8 +60,8 @@ class _BfxWebsocketInputs(object):
|
||||
|
||||
await self.__handle_websocket_input("oc_multi", data)
|
||||
|
||||
async def submit_funding_offer(self, type: FundingOfferType, symbol: str, amount: Union[Decimal, str],
|
||||
rate: Union[Decimal, str], period: int,
|
||||
async def submit_funding_offer(self, type: FundingOfferType, symbol: str, amount: Union[Decimal, float, str],
|
||||
rate: Union[Decimal, float, str], period: int,
|
||||
flags: Optional[int] = 0):
|
||||
data = {
|
||||
"type": type, "symbol": symbol, "amount": amount,
|
||||
|
||||
@@ -3,10 +3,8 @@ from typing import Type, Tuple, List, Dict, TypedDict, Union, Optional, Any
|
||||
from dataclasses import dataclass
|
||||
|
||||
from ..labeler import _Type
|
||||
|
||||
from ..notification import Notification
|
||||
|
||||
JSON = Union[Dict[str, "JSON"], List["JSON"], bool, int, float, str, Type[None]]
|
||||
from .. utils.encoder import JSON
|
||||
|
||||
#region Type hinting for Websocket Public Channels
|
||||
|
||||
|
||||
Reference in New Issue
Block a user