Merge pull request #190 from itsdeka/movement

Combined all old unmerged PRs
This commit is contained in:
Vigan Abdurrahmani
2022-01-21 17:46:49 +01:00
committed by GitHub
9 changed files with 142 additions and 21 deletions

View File

@@ -1,3 +1,8 @@
2.0.0
-) Implemented Movement endpoints (REST)
-) Fixed unawaited stop
-) Changed account's trade execution (te) and trade update (tu) handling
1.3.4 1.3.4
-) Fixed undefined p_sub issue in subscription_manager.py -) Fixed undefined p_sub issue in subscription_manager.py
-) Added submit cancel all funding orders endpoint (REST) -) Added submit cancel all funding orders endpoint (REST)

View File

@@ -5,7 +5,8 @@ This module is used to interact with the bitfinex api
from .version import __version__ from .version import __version__
from .client import Client from .client import Client
from .models import (Order, Trade, OrderBook, Subscription, Wallet, from .models import (Order, Trade, OrderBook, Subscription, Wallet,
Position, FundingLoan, FundingOffer, FundingCredit) Position, FundingLoan, FundingOffer, FundingCredit,
Movement)
from .websockets.generic_websocket import GenericWebsocket, Socket from .websockets.generic_websocket import GenericWebsocket, Socket
from .websockets.bfx_websocket import BfxWebsocket from .websockets.bfx_websocket import BfxWebsocket
from .utils.decimal import Decimal from .utils.decimal import Decimal

View File

@@ -22,5 +22,6 @@ from .ledger import Ledger
from .funding_trade import FundingTrade from .funding_trade import FundingTrade
from .margin_info import MarginInfo from .margin_info import MarginInfo
from .margin_info_base import MarginInfoBase from .margin_info_base import MarginInfoBase
from .movement import Movement
NAME = "models" NAME = "models"

76
bfxapi/models/movement.py Normal file
View File

@@ -0,0 +1,76 @@
"""
Module used to describe movement data types
"""
import time
import datetime
class MovementModel:
"""
Enum used index the different values in a raw movement array
"""
ID = 0
CURRENCY = 1
CURRENCY_NAME = 2
MTS_STARTED = 5
MTS_UPDATED = 6
STATUS = 9
AMOUNT = 12
FEES = 13
DESTINATION_ADDRESS = 16
TRANSACTION_ID = 20
class Movement:
"""
ID String Movement identifier
CURRENCY String The symbol of the currency (ex. "BTC")
CURRENCY_NAME String The extended name of the currency (ex. "BITCOIN")
MTS_STARTED Date Movement started at
MTS_UPDATED Date Movement last updated at
STATUS String Current status
AMOUNT String Amount of funds moved
FEES String Tx Fees applied
DESTINATION_ADDRESS String Destination address
TRANSACTION_ID String Transaction identifier
"""
def __init__(self, mid, currency, mts_started, mts_updated, status, amount, fees, dst_address, tx_id):
self.id = mid
self.currency = currency
self.mts_started = mts_started
self.mts_updated = mts_updated
self.status = status
self.amount = amount
self.fees = fees
self.dst_address = dst_address
self.tx_id = tx_id
self.date = datetime.datetime.fromtimestamp(mts_started/1000.0)
@staticmethod
def from_raw_movement(raw_movement):
"""
Parse a raw movement object into a Movement object
@return Movement
"""
mid = raw_movement[MovementModel.ID]
currency = raw_movement[MovementModel.CURRENCY]
mts_started = raw_movement[MovementModel.MTS_STARTED]
mts_updated = raw_movement[MovementModel.MTS_UPDATED]
status = raw_movement[MovementModel.STATUS]
amount = raw_movement[MovementModel.AMOUNT]
fees = raw_movement[MovementModel.FEES]
dst_address = raw_movement[MovementModel.DESTINATION_ADDRESS]
tx_id = raw_movement[MovementModel.TRANSACTION_ID]
return Movement(mid, currency, mts_started, mts_updated, status, amount, fees, dst_address, tx_id)
def __str__(self):
''' Allow us to print the Movement object in a pretty format '''
text = "Movement <'{}' amount={} fees={} mts_created={} mts_updated={} status='{}' destination_address={} transaction_id={}>"
return text.format(self.currency, self.amount, self.fees,
self.mts_started, self.mts_updated, self.status, self.dst_address, self.tx_id)

View File

@@ -11,7 +11,7 @@ import datetime
from ..utils.custom_logger import CustomLogger from ..utils.custom_logger import CustomLogger
from ..utils.auth import generate_auth_headers, calculate_order_flags, gen_unique_cid from ..utils.auth import generate_auth_headers, calculate_order_flags, gen_unique_cid
from ..models import Wallet, Order, Position, Trade, FundingLoan, FundingOffer, FundingTrade, MarginInfoBase, MarginInfo from ..models import Wallet, Order, Position, Trade, FundingLoan, FundingOffer, FundingTrade, MarginInfoBase, MarginInfo
from ..models import FundingCredit, Notification, Ledger from ..models import FundingCredit, Notification, Ledger, Movement
class BfxRest: class BfxRest:
@@ -609,6 +609,22 @@ class BfxRest:
raw_ledgers = await self.post(endpoint, params=params) raw_ledgers = await self.post(endpoint, params=params)
return [Ledger.from_raw_ledger(rl) for rl in raw_ledgers] return [Ledger.from_raw_ledger(rl) for rl in raw_ledgers]
async def get_movement_history(self, currency, start="", end="", limit=25):
"""
Get all of the deposits and withdraws between the start and end period associated with API_KEY
- Requires authentication.
# Attributes
@param currency string: pair symbol i.e BTC
@param start int: millisecond start time
@param end int: millisecond end time
@param limit int: max number of items in response
@return Array <models.Movement>
"""
endpoint = "auth/r/movements/{}/hist".format(currency)
params = "?start={}&end={}&limit={}".format(start, end, limit)
raw_movements = await self.post(endpoint, params=params)
return [Movement.from_raw_movement(rm) for rm in raw_movements]
async def submit_funding_offer(self, symbol, amount, rate, period, async def submit_funding_offer(self, symbol, amount, rate, period,
funding_type=FundingOffer.Type.LIMIT, hidden=False): funding_type=FundingOffer.Type.LIMIT, hidden=False):
""" """

View File

@@ -2,4 +2,4 @@
This module contains the current version of the bfxapi lib This module contains the current version of the bfxapi lib
""" """
__version__ = '1.3.4' __version__ = '2.0.0'

View File

@@ -66,6 +66,37 @@ def _parse_trade(tData, symbol):
'symbol': symbol 'symbol': symbol
} }
def _parse_account_trade(tData):
return {
'id': tData[0],
'symbol': tData[1],
'mts_create': tData[2],
'order_id': tData[3],
'exec_amount': tData[4],
'exec_price': tData[5],
'order_type': tData[6],
'order_price': tData[7],
'maker': tData[8],
'cid': tData[11],
}
def _parse_account_trade_update(tData):
return {
'id': tData[0],
'symbol': tData[1],
'mts_create': tData[2],
'order_id': tData[3],
'exec_amount': tData[4],
'exec_price': tData[5],
'order_type': tData[6],
'order_price': tData[7],
'maker': tData[8],
'fee': tData[9],
'fee_currency': tData[10],
'cid': tData[11],
}
def _parse_deriv_status_update(sData, symbol): def _parse_deriv_status_update(sData, symbol):
return { return {
'symbol': symbol, 'symbol': symbol,
@@ -278,19 +309,15 @@ class BfxWebsocket(GenericWebsocket):
async def _trade_update_handler(self, data): async def _trade_update_handler(self, data):
tData = data[2] tData = data[2]
# [209, 'tu', [312372989, 1542303108930, 0.35, 5688.61834032]] # [0,"tu",[738045455,"tTESTBTC:TESTUSD",1622169615771,66635385225,0.001,38175,"EXCHANGE LIMIT",39000,-1,-0.000002,"TESTBTC",1622169615685]]
if self.subscriptionManager.is_subscribed(data[0]): tradeObj = _parse_account_trade_update(tData)
symbol = self.subscriptionManager.get(data[0]).symbol self._emit('trade_update', tradeObj)
tradeObj = _parse_trade(tData, symbol)
self._emit('trade_update', tradeObj)
async def _trade_executed_handler(self, data): async def _trade_executed_handler(self, data):
tData = data[2] tData = data[2]
# [209, 'te', [312372989, 1542303108930, 0.35, 5688.61834032]] # [0,"te",[738045455,"tTESTBTC:TESTUSD",1622169615771,66635385225,0.001,38175,"EXCHANGE LIMIT",39000,-1,null,null,1622169615685]]
if self.subscriptionManager.is_subscribed(data[0]): tradeObj = _parse_account_trade(tData)
symbol = self.subscriptionManager.get(data[0]).symbol self._emit('new_trade', tradeObj)
tradeObj = _parse_trade(tData, symbol)
self._emit('new_trade', tradeObj)
async def _wallet_update_handler(self, data): async def _wallet_update_handler(self, data):
# [0,"wu",["exchange","USD",89134.66933283,0]] # [0,"wu",["exchange","USD",89134.66933283,0]]
@@ -409,12 +436,7 @@ class BfxWebsocket(GenericWebsocket):
# connection # connection
data.reverse() data.reverse()
for t in data: for t in data:
trade = { trade = _parse_trade(t, symbol)
'mts': t[1],
'amount': t[2],
'price': t[3],
'symbol': symbol
}
self._emit('seed_trade', trade) self._emit('seed_trade', trade)
async def _candle_handler(self, data): async def _candle_handler(self, data):

View File

@@ -208,7 +208,7 @@ class GenericWebsocket:
""" """
This is used by the HF data server. This is used by the HF data server.
""" """
self.stop() await self.stop()
async def on_open(self): async def on_open(self):
""" """

View File

@@ -11,7 +11,7 @@ from os import path
here = path.abspath(path.dirname(__file__)) here = path.abspath(path.dirname(__file__))
setup( setup(
name='bitfinex-api-py', name='bitfinex-api-py',
version='1.3.4', version='2.0.0',
description='Official Bitfinex Python API', description='Official Bitfinex Python API',
long_description='A Python reference implementation of the Bitfinex API for both REST and websocket interaction', long_description='A Python reference implementation of the Bitfinex API for both REST and websocket interaction',
long_description_content_type='text/markdown', long_description_content_type='text/markdown',