mirror of
https://github.com/aljazceru/bitfinex-api-py.git
synced 2025-12-19 14:54:21 +01:00
Merge pull request #15 from Davi0kProgramsThings/master
Sync branch `feature/rest` with branch `master`.
This commit is contained in:
@@ -341,3 +341,6 @@ class _RestAuthenticatedEndpoints(_Requests):
|
|||||||
}
|
}
|
||||||
|
|
||||||
return serializers._Notification(serializer=serializers.FundingOffer).parse(*self._POST("auth/w/funding/offer/submit", data=data))
|
return serializers._Notification(serializer=serializers.FundingOffer).parse(*self._POST("auth/w/funding/offer/submit", data=data))
|
||||||
|
|
||||||
|
def cancel_funding_offer(self, id: int) -> Notification:
|
||||||
|
return serializers._Notification(serializer=serializers.FundingOffer).parse(*self._POST("auth/w/funding/offer/cancel", data={ "id": id }))
|
||||||
@@ -1,12 +1,10 @@
|
|||||||
import traceback, json, asyncio, hmac, hashlib, time, uuid, websockets
|
import traceback, json, asyncio, hmac, hashlib, time, uuid, websockets
|
||||||
|
|
||||||
from typing import Tuple, Union, Literal, TypeVar, Callable, cast
|
from typing import Literal, TypeVar, Callable, cast
|
||||||
|
|
||||||
from enum import Enum
|
|
||||||
|
|
||||||
from pyee.asyncio import AsyncIOEventEmitter
|
from pyee.asyncio import AsyncIOEventEmitter
|
||||||
|
|
||||||
from .typings import Inputs
|
from ._BfxWebsocketInputs import _BfxWebsocketInputs
|
||||||
from .handlers import Channels, PublicChannelsHandler, AuthenticatedChannelsHandler
|
from .handlers import Channels, PublicChannelsHandler, AuthenticatedChannelsHandler
|
||||||
from .exceptions import ConnectionNotOpen, TooManySubscriptions, WebsocketAuthenticationRequired, InvalidAuthenticationCredentials, EventNotSupported, OutdatedClientVersion
|
from .exceptions import ConnectionNotOpen, TooManySubscriptions, WebsocketAuthenticationRequired, InvalidAuthenticationCredentials, EventNotSupported, OutdatedClientVersion
|
||||||
|
|
||||||
@@ -231,28 +229,3 @@ class _BfxWebsocketBucket(object):
|
|||||||
@_require_websocket_connection
|
@_require_websocket_connection
|
||||||
async def _close(self, code=1000, reason=str()):
|
async def _close(self, code=1000, reason=str()):
|
||||||
await self.websocket.close(code=code, reason=reason)
|
await self.websocket.close(code=code, reason=reason)
|
||||||
|
|
||||||
class _BfxWebsocketInputs(object):
|
|
||||||
def __init__(self, __handle_websocket_input):
|
|
||||||
self.__handle_websocket_input = __handle_websocket_input
|
|
||||||
|
|
||||||
async def order_new(self, data: Inputs.Order.New):
|
|
||||||
await self.__handle_websocket_input("on", data)
|
|
||||||
|
|
||||||
async def order_update(self, data: Inputs.Order.Update):
|
|
||||||
await self.__handle_websocket_input("ou", data)
|
|
||||||
|
|
||||||
async def order_cancel(self, data: Inputs.Order.Cancel):
|
|
||||||
await self.__handle_websocket_input("oc", data)
|
|
||||||
|
|
||||||
async def order_multiple_operations(self, *args: Tuple[str, Union[Inputs.Order.New, Inputs.Order.Update, Inputs.Order.Cancel]]):
|
|
||||||
await self.__handle_websocket_input("ox_multi", args)
|
|
||||||
|
|
||||||
async def offer_new(self, data: Inputs.Offer.New):
|
|
||||||
await self.__handle_websocket_input("fon", data)
|
|
||||||
|
|
||||||
async def offer_cancel(self, data: Inputs.Offer.Cancel):
|
|
||||||
await self.__handle_websocket_input("foc", data)
|
|
||||||
|
|
||||||
async def calc(self, *args: str):
|
|
||||||
await self.__handle_websocket_input("calc", list(map(lambda arg: [arg], args)))
|
|
||||||
78
bfxapi/websocket/_BfxWebsocketInputs.py
Normal file
78
bfxapi/websocket/_BfxWebsocketInputs.py
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
from decimal import Decimal
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from typing import Union, Optional, List, Tuple
|
||||||
|
from .typings import JSON
|
||||||
|
from .enums import OrderType, FundingOfferType
|
||||||
|
|
||||||
|
def _strip(dictionary):
|
||||||
|
return { key: value for key, value in dictionary.items() if value != None}
|
||||||
|
|
||||||
|
class _BfxWebsocketInputs(object):
|
||||||
|
def __init__(self, __handle_websocket_input):
|
||||||
|
self.__handle_websocket_input = __handle_websocket_input
|
||||||
|
|
||||||
|
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,
|
||||||
|
gid: Optional[int] = None, cid: Optional[int] = None,
|
||||||
|
flags: Optional[int] = 0, tif: Optional[Union[datetime, str]] = None, meta: Optional[JSON] = None):
|
||||||
|
data = _strip({
|
||||||
|
"type": type, "symbol": symbol, "amount": amount,
|
||||||
|
"price": price, "lev": lev,
|
||||||
|
"price_trailing": price_trailing, "price_aux_limit": price_aux_limit, "price_oco_stop": price_oco_stop,
|
||||||
|
"gid": gid, "cid": cid,
|
||||||
|
"flags": flags, "tif": tif, "meta": meta
|
||||||
|
})
|
||||||
|
|
||||||
|
await self.__handle_websocket_input("on", data)
|
||||||
|
|
||||||
|
async def update_order(self, id: int, amount: Optional[Union[Decimal, str]] = None, price: Optional[Union[Decimal, 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):
|
||||||
|
data = _strip({
|
||||||
|
"id": id, "amount": amount, "price": price,
|
||||||
|
"cid": cid, "cid_date": cid_date, "gid": gid,
|
||||||
|
"flags": flags, "lev": lev, "delta": delta,
|
||||||
|
"price_aux_limit": price_aux_limit, "price_trailing": price_trailing, "tif": tif
|
||||||
|
})
|
||||||
|
|
||||||
|
await self.__handle_websocket_input("ou", data)
|
||||||
|
|
||||||
|
async def cancel_order(self, id: Optional[int] = None, cid: Optional[int] = None, cid_date: Optional[str] = None):
|
||||||
|
data = _strip({
|
||||||
|
"id": id,
|
||||||
|
"cid": cid,
|
||||||
|
"cid_date": cid_date
|
||||||
|
})
|
||||||
|
|
||||||
|
await self.__handle_websocket_input("oc", data)
|
||||||
|
|
||||||
|
async def cancel_order_multi(self, ids: Optional[List[int]] = None, cids: Optional[List[Tuple[int, str]]] = None, gids: Optional[List[int]] = None, all: bool = False):
|
||||||
|
data = _strip({
|
||||||
|
"ids": ids,
|
||||||
|
"cids": cids,
|
||||||
|
"gids": gids,
|
||||||
|
|
||||||
|
"all": int(all)
|
||||||
|
})
|
||||||
|
|
||||||
|
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,
|
||||||
|
flags: Optional[int] = 0):
|
||||||
|
data = {
|
||||||
|
"type": type, "symbol": symbol, "amount": amount,
|
||||||
|
"rate": rate, "period": period,
|
||||||
|
"flags": flags
|
||||||
|
}
|
||||||
|
|
||||||
|
await self.__handle_websocket_input("fon", data)
|
||||||
|
|
||||||
|
async def cancel_funding_offer(self, id: int):
|
||||||
|
await self.__handle_websocket_input("foc", { "id": id })
|
||||||
|
|
||||||
|
async def calc(self, *args: str):
|
||||||
|
await self.__handle_websocket_input("calc", list(map(lambda arg: [arg], args)))
|
||||||
@@ -146,7 +146,13 @@ class AuthenticatedChannelsHandler(object):
|
|||||||
("bu",): serializers.BalanceInfo
|
("bu",): serializers.BalanceInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
EVENTS = [ "notification", *list(__abbreviations.values()) ]
|
EVENTS = [
|
||||||
|
"notification",
|
||||||
|
"on-req-notification", "ou-req-notification", "oc-req-notification",
|
||||||
|
"oc_multi-notification",
|
||||||
|
"fon-req-notification", "foc-req-notification",
|
||||||
|
*list(__abbreviations.values())
|
||||||
|
]
|
||||||
|
|
||||||
def __init__(self, event_emitter, strict = False):
|
def __init__(self, event_emitter, strict = False):
|
||||||
self.event_emitter, self.strict = event_emitter, strict
|
self.event_emitter, self.strict = event_emitter, strict
|
||||||
@@ -168,4 +174,13 @@ class AuthenticatedChannelsHandler(object):
|
|||||||
raise BfxWebsocketException(f"Event of type <{type}> not found in self.__handlers.")
|
raise BfxWebsocketException(f"Event of type <{type}> not found in self.__handlers.")
|
||||||
|
|
||||||
def __notification(self, stream):
|
def __notification(self, stream):
|
||||||
return self.event_emitter.emit("notification", serializers.Notification.parse(*stream))
|
if stream[1] == "on-req" or stream[1] == "ou-req" or stream[1] == "oc-req":
|
||||||
|
return self.event_emitter.emit(f"{stream[1]}-notification", serializers._Notification(serializer=serializers.Order).parse(*stream))
|
||||||
|
|
||||||
|
if stream[1] == "oc_multi-req":
|
||||||
|
return self.event_emitter.emit(f"{stream[1]}-notification", serializers._Notification(serializer=serializers.Order, iterate=True).parse(*stream))
|
||||||
|
|
||||||
|
if stream[1] == "fon-req" or stream[1] == "foc-req":
|
||||||
|
return self.event_emitter.emit(f"{stream[1]}-notification", serializers._Notification(serializer=serializers.FundingOffer).parse(*stream))
|
||||||
|
|
||||||
|
return self.event_emitter.emit("notification", serializers._Notification(serializer=None).parse(*stream))
|
||||||
@@ -2,6 +2,8 @@ from . import typings
|
|||||||
|
|
||||||
from .. labeler import _Serializer
|
from .. labeler import _Serializer
|
||||||
|
|
||||||
|
from .. notification import _Notification
|
||||||
|
|
||||||
#region Serializers definition for Websocket Public Channels
|
#region Serializers definition for Websocket Public Channels
|
||||||
|
|
||||||
TradingPairTicker = _Serializer[typings.TradingPairTicker]("TradingPairTicker", labels=[
|
TradingPairTicker = _Serializer[typings.TradingPairTicker]("TradingPairTicker", labels=[
|
||||||
@@ -293,18 +295,3 @@ BalanceInfo = _Serializer[typings.BalanceInfo]("BalanceInfo", labels=[
|
|||||||
])
|
])
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Serializers definition for Notifications channel
|
|
||||||
|
|
||||||
Notification = _Serializer[typings.Notification]("Notification", labels=[
|
|
||||||
"MTS",
|
|
||||||
"TYPE",
|
|
||||||
"MESSAGE_ID",
|
|
||||||
"_PLACEHOLDER",
|
|
||||||
"NOTIFY_INFO",
|
|
||||||
"CODE",
|
|
||||||
"STATUS",
|
|
||||||
"TEXT"
|
|
||||||
])
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
@@ -1,10 +1,6 @@
|
|||||||
from decimal import Decimal
|
|
||||||
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
from typing import Type, Tuple, List, Dict, TypedDict, Union, Optional, Any
|
from typing import Type, Tuple, List, Dict, TypedDict, Union, Optional, Any
|
||||||
|
|
||||||
from ..utils.integers import Int16, Int32, Int45, Int64
|
from .. notification import Notification
|
||||||
|
|
||||||
JSON = Union[Dict[str, "JSON"], List["JSON"], bool, int, float, str, Type[None]]
|
JSON = Union[Dict[str, "JSON"], List["JSON"], bool, int, float, str, Type[None]]
|
||||||
|
|
||||||
@@ -279,68 +275,3 @@ class BalanceInfo(TypedDict):
|
|||||||
AUM_NET: float
|
AUM_NET: float
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Type hinting for Notifications channel
|
|
||||||
|
|
||||||
class Notification(TypedDict):
|
|
||||||
MTS: int
|
|
||||||
TYPE: str
|
|
||||||
MESSAGE_ID: int
|
|
||||||
NOTIFY_INFO: JSON
|
|
||||||
CODE: int
|
|
||||||
STATUS: str
|
|
||||||
TEXT: str
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Type hinting for Websocket Authenticated Inputs
|
|
||||||
|
|
||||||
class Inputs:
|
|
||||||
class Order:
|
|
||||||
class New(TypedDict, total=False):
|
|
||||||
gid: Union[Int32, int]
|
|
||||||
cid: Union[Int45, int]
|
|
||||||
type: str
|
|
||||||
symbol: str
|
|
||||||
amount: Union[Decimal, str]
|
|
||||||
price: Union[Decimal, str]
|
|
||||||
lev: Union[Int32, int]
|
|
||||||
price_trailing: Union[Decimal, str]
|
|
||||||
price_aux_limit: Union[Decimal, str]
|
|
||||||
price_oco_stop: Union[Decimal, str]
|
|
||||||
flags: Union[Int16, int]
|
|
||||||
tif: Union[datetime, str]
|
|
||||||
meta: JSON
|
|
||||||
|
|
||||||
class Update(TypedDict, total=False):
|
|
||||||
id: Union[Int64, int]
|
|
||||||
cid: Union[Int45, int]
|
|
||||||
cid_date: str
|
|
||||||
gid: Union[Int32, int]
|
|
||||||
price: Union[Decimal, str]
|
|
||||||
amount: Union[Decimal, str]
|
|
||||||
lev: Union[Int32, int]
|
|
||||||
delta: Union[Decimal, str]
|
|
||||||
price_aux_limit: Union[Decimal, str]
|
|
||||||
price_trailing: Union[Decimal, str]
|
|
||||||
flags: Union[Int16, int]
|
|
||||||
tif: Union[datetime, str]
|
|
||||||
|
|
||||||
class Cancel(TypedDict, total=False):
|
|
||||||
id: Union[Int64, int]
|
|
||||||
cid: Union[Int45, int]
|
|
||||||
cid_date: Union[datetime, str]
|
|
||||||
|
|
||||||
class Offer:
|
|
||||||
class New(TypedDict, total=False):
|
|
||||||
type: str
|
|
||||||
symbol: str
|
|
||||||
amount: Union[Decimal, str]
|
|
||||||
rate: Union[Decimal, str]
|
|
||||||
period: Union[Int32, int]
|
|
||||||
flags: Union[Int16, int]
|
|
||||||
|
|
||||||
class Cancel(TypedDict, total=False):
|
|
||||||
id: Union[Int32, int]
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
@@ -21,6 +21,6 @@ notification = bfx.rest.auth.submit_funding_offer(
|
|||||||
|
|
||||||
print("Offer notification:", notification)
|
print("Offer notification:", notification)
|
||||||
|
|
||||||
offers = bfx.rest.auth.get_active_funding_offers()
|
offers = bfx.rest.auth.get_active_funding_offers(symbol="fUSD")
|
||||||
|
|
||||||
print("Offers:", offers)
|
print("Offers:", offers)
|
||||||
@@ -3,9 +3,8 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
from bfxapi.client import Client, Constants
|
from bfxapi.client import Client, Constants
|
||||||
from bfxapi.utils.cid import generate_unique_cid
|
|
||||||
from bfxapi.websocket.enums import Error, OrderType
|
from bfxapi.websocket.enums import Error, OrderType
|
||||||
from bfxapi.websocket.typings import Inputs
|
from bfxapi.websocket.typings import Notification, Order
|
||||||
|
|
||||||
bfx = Client(
|
bfx = Client(
|
||||||
WSS_HOST=Constants.WSS_HOST,
|
WSS_HOST=Constants.WSS_HOST,
|
||||||
@@ -18,30 +17,28 @@ def on_wss_error(code: Error, msg: str):
|
|||||||
print(code, msg)
|
print(code, msg)
|
||||||
|
|
||||||
@bfx.wss.on("authenticated")
|
@bfx.wss.on("authenticated")
|
||||||
async def on_open(event):
|
async def on_authenticated(event):
|
||||||
print(f"Auth event {event}")
|
print(f"Authentication: {event}.")
|
||||||
|
|
||||||
order: Inputs.Order.New = {
|
await bfx.wss.inputs.submit_order(
|
||||||
"gid": generate_unique_cid(),
|
type=OrderType.EXCHANGE_LIMIT,
|
||||||
"type": OrderType.EXCHANGE_LIMIT,
|
symbol="tBTCUSD",
|
||||||
"symbol": "tBTCUST",
|
amount="0.1",
|
||||||
"amount": "0.1",
|
price="10000.0"
|
||||||
"price": "10000.0"
|
)
|
||||||
}
|
|
||||||
await bfx.wss.inputs.order_new(order)
|
|
||||||
|
|
||||||
print(f"Order sent")
|
print("The order has been sent.")
|
||||||
|
|
||||||
@bfx.wss.on("notification")
|
@bfx.wss.on("on-req-notification")
|
||||||
async def on_notification(notification):
|
async def on_notification(notification: Notification):
|
||||||
print(f"Notification {notification}")
|
print(f"Notification: {notification}.")
|
||||||
|
|
||||||
@bfx.wss.on("order_new")
|
@bfx.wss.on("order_new")
|
||||||
async def on_order_new(order_new: Inputs.Order.New):
|
async def on_order_new(order_new: Order):
|
||||||
print(f"Order new {order_new}")
|
print(f"Order new: {order_new}")
|
||||||
|
|
||||||
@bfx.wss.on("subscribed")
|
@bfx.wss.on("subscribed")
|
||||||
def on_subscribed(subscription):
|
def on_subscribed(subscription):
|
||||||
print(f"Subscription successful <{subscription}>")
|
print(f"Subscription successful for <{subscription}>.")
|
||||||
|
|
||||||
bfx.wss.run()
|
bfx.wss.run()
|
||||||
Reference in New Issue
Block a user