Merge branch Davi0kProgramsThings:fix/refactoring into branch bitfinexcom:master. (#238)

# Description
<!--- Describe your changes in detail -->
PR includes some global refactoring in preparation for the v3.0.0 stable release.

## Motivation and Context
<!--- Why is this change required? What problem does it solve? -->
-

## Related Issue
<!--- If suggesting a new feature or change, please discuss it in an issue first -->
<!--- If fixing a bug, there should be an issue describing it with steps to reproduce -->
<!--- Please link to the issue here: -->
PR fixes the following issue: -

## Type of change
<!-- Select the most suitable choice and remove the others from the checklist -->

- [X] Bug fix (non-breaking change which fixes an issue);

# Checklist:

- [X] I've done a self-review of my code;
- [X] I've made corresponding changes to the documentation;
- [X] I've made sure my changes generate no warnings;
- [X] mypy returns no errors when run on the root package;
<!-- If you use pre-commit hooks you can always check off the following tasks -->
- [X] I've run black to format my code;
- [X] I've run isort to format my code's import statements;
- [X] flake8 reports no errors when run on the entire code base;
This commit is contained in:
Davide Casale
2024-04-03 22:34:23 +02:00
committed by GitHub
parent 3136b9cfe4
commit bdd78a817d
15 changed files with 274 additions and 283 deletions

View File

@@ -0,0 +1,3 @@
from .rest_auth_endpoints import RestAuthEndpoints
from .rest_merchant_endpoints import RestMerchantEndpoints
from .rest_public_endpoints import RestPublicEndpoints

View File

@@ -0,0 +1,629 @@
from decimal import Decimal
from typing import Any, Dict, List, Literal, Optional, Tuple, Union
from bfxapi.rest._interface import Interface
from bfxapi.types import (
BalanceAvailable,
BaseMarginInfo,
DepositAddress,
DerivativePositionCollateral,
DerivativePositionCollateralLimits,
FundingAutoRenew,
FundingCredit,
FundingInfo,
FundingLoan,
FundingOffer,
FundingTrade,
Ledger,
LightningNetworkInvoice,
LoginHistory,
Movement,
Notification,
Order,
OrderTrade,
Position,
PositionAudit,
PositionClaim,
PositionHistory,
PositionIncrease,
PositionIncreaseInfo,
PositionSnapshot,
SymbolMarginInfo,
Trade,
Transfer,
UserInfo,
Wallet,
Withdrawal,
serializers,
)
from bfxapi.types.serializers import _Notification
class RestAuthEndpoints(Interface):
def get_user_info(self) -> UserInfo:
return serializers.UserInfo.parse(*self._m.post("auth/r/info/user"))
def get_login_history(self) -> List[LoginHistory]:
return [
serializers.LoginHistory.parse(*sub_data)
for sub_data in self._m.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:
body = {"symbol": symbol, "type": type, "dir": dir, "rate": rate, "lev": lev}
return serializers.BalanceAvailable.parse(
*self._m.post("auth/calc/order/avail", body=body)
)
def get_wallets(self) -> List[Wallet]:
return [
serializers.Wallet.parse(*sub_data)
for sub_data in self._m.post("auth/r/wallets")
]
def get_orders(
self, *, symbol: Optional[str] = None, ids: Optional[List[str]] = None
) -> List[Order]:
if symbol is None:
endpoint = "auth/r/orders"
else:
endpoint = f"auth/r/orders/{symbol}"
return [
serializers.Order.parse(*sub_data)
for sub_data in self._m.post(endpoint, body={"id": ids})
]
def submit_order(
self,
type: str,
symbol: str,
amount: Union[str, float, Decimal],
price: Union[str, float, Decimal],
*,
lev: Optional[int] = None,
price_trailing: Optional[Union[str, float, Decimal]] = None,
price_aux_limit: Optional[Union[str, float, Decimal]] = None,
price_oco_stop: Optional[Union[str, float, Decimal]] = None,
gid: Optional[int] = None,
cid: Optional[int] = None,
flags: Optional[int] = None,
tif: Optional[str] = None,
meta: Optional[Dict[str, Any]] = None,
) -> Notification[Order]:
body = {
"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,
}
return _Notification[Order](serializers.Order).parse(
*self._m.post("auth/w/order/submit", body=body)
)
def update_order(
self,
id: int,
*,
amount: Optional[Union[str, float, Decimal]] = None,
price: Optional[Union[str, float, Decimal]] = None,
cid: Optional[int] = None,
cid_date: Optional[str] = None,
gid: Optional[int] = None,
flags: Optional[int] = None,
lev: Optional[int] = None,
delta: Optional[Union[str, float, Decimal]] = None,
price_aux_limit: Optional[Union[str, float, Decimal]] = None,
price_trailing: Optional[Union[str, float, Decimal]] = None,
tif: Optional[str] = None,
) -> Notification[Order]:
body = {
"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,
}
return _Notification[Order](serializers.Order).parse(
*self._m.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]:
return _Notification[Order](serializers.Order).parse(
*self._m.post(
"auth/w/order/cancel", body={"id": id, "cid": cid, "cid_date": cid_date}
)
)
def cancel_order_multi(
self,
*,
id: Optional[List[int]] = None,
cid: Optional[List[Tuple[int, str]]] = None,
gid: Optional[List[int]] = None,
all: Optional[bool] = None,
) -> Notification[List[Order]]:
body = {"id": id, "cid": cid, "gid": gid, "all": all}
return _Notification[List[Order]](serializers.Order, is_iterable=True).parse(
*self._m.post("auth/w/order/cancel/multi", body=body)
)
def get_orders_history(
self,
*,
symbol: Optional[str] = None,
ids: Optional[List[int]] = None,
start: Optional[str] = None,
end: Optional[str] = None,
limit: Optional[int] = None,
) -> List[Order]:
if symbol is None:
endpoint = "auth/r/orders/hist"
else:
endpoint = f"auth/r/orders/{symbol}/hist"
body = {"id": ids, "start": start, "end": end, "limit": limit}
return [
serializers.Order.parse(*sub_data)
for sub_data in self._m.post(endpoint, body=body)
]
def get_order_trades(self, symbol: str, id: int) -> List[OrderTrade]:
return [
serializers.OrderTrade.parse(*sub_data)
for sub_data in self._m.post(f"auth/r/order/{symbol}:{id}/trades")
]
def get_trades_history(
self,
*,
symbol: Optional[str] = None,
sort: Optional[int] = None,
start: Optional[str] = None,
end: Optional[str] = None,
limit: Optional[int] = None,
) -> List[Trade]:
if symbol is None:
endpoint = "auth/r/trades/hist"
else:
endpoint = f"auth/r/trades/{symbol}/hist"
body = {"sort": sort, "start": start, "end": end, "limit": limit}
return [
serializers.Trade.parse(*sub_data)
for sub_data in self._m.post(endpoint, body=body)
]
def get_ledgers(
self,
currency: str,
*,
category: Optional[int] = None,
start: Optional[str] = None,
end: Optional[str] = None,
limit: Optional[int] = None,
) -> List[Ledger]:
body = {"category": category, "start": start, "end": end, "limit": limit}
return [
serializers.Ledger.parse(*sub_data)
for sub_data in self._m.post(f"auth/r/ledgers/{currency}/hist", body=body)
]
def get_base_margin_info(self) -> BaseMarginInfo:
return serializers.BaseMarginInfo.parse(
*(self._m.post("auth/r/info/margin/base")[1])
)
def get_symbol_margin_info(self, symbol: str) -> SymbolMarginInfo:
return serializers.SymbolMarginInfo.parse(
*self._m.post(f"auth/r/info/margin/{symbol}")
)
def get_all_symbols_margin_info(self) -> List[SymbolMarginInfo]:
return [
serializers.SymbolMarginInfo.parse(*sub_data)
for sub_data in self._m.post("auth/r/info/margin/sym_all")
]
def get_positions(self) -> List[Position]:
return [
serializers.Position.parse(*sub_data)
for sub_data in self._m.post("auth/r/positions")
]
def claim_position(
self, id: int, *, amount: Optional[Union[str, float, Decimal]] = None
) -> Notification[PositionClaim]:
return _Notification[PositionClaim](serializers.PositionClaim).parse(
*self._m.post("auth/w/position/claim", body={"id": id, "amount": amount})
)
def increase_position(
self, symbol: str, amount: Union[str, float, Decimal]
) -> Notification[PositionIncrease]:
return _Notification[PositionIncrease](serializers.PositionIncrease).parse(
*self._m.post(
"auth/w/position/increase", body={"symbol": symbol, "amount": amount}
)
)
def get_increase_position_info(
self, symbol: str, amount: Union[str, float, Decimal]
) -> PositionIncreaseInfo:
return serializers.PositionIncreaseInfo.parse(
*self._m.post(
"auth/r/position/increase/info",
body={"symbol": symbol, "amount": amount},
)
)
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._m.post(
"auth/r/positions/hist",
body={"start": start, "end": end, "limit": limit},
)
]
def get_positions_snapshot(
self,
*,
start: Optional[str] = None,
end: Optional[str] = None,
limit: Optional[int] = None,
) -> List[PositionSnapshot]:
return [
serializers.PositionSnapshot.parse(*sub_data)
for sub_data in self._m.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]:
body = {"ids": ids, "start": start, "end": end, "limit": limit}
return [
serializers.PositionAudit.parse(*sub_data)
for sub_data in self._m.post("auth/r/positions/audit", body=body)
]
def set_derivative_position_collateral(
self, symbol: str, collateral: Union[str, float, Decimal]
) -> DerivativePositionCollateral:
return serializers.DerivativePositionCollateral.parse(
*(
self._m.post(
"auth/w/deriv/collateral/set",
body={"symbol": symbol, "collateral": collateral},
)[0]
)
)
def get_derivative_position_collateral_limits(
self, symbol: str
) -> DerivativePositionCollateralLimits:
return serializers.DerivativePositionCollateralLimits.parse(
*self._m.post("auth/calc/deriv/collateral/limit", body={"symbol": symbol})
)
def get_funding_offers(self, *, symbol: Optional[str] = None) -> List[FundingOffer]:
if symbol is None:
endpoint = "auth/r/funding/offers"
else:
endpoint = f"auth/r/funding/offers/{symbol}"
return [
serializers.FundingOffer.parse(*sub_data)
for sub_data in self._m.post(endpoint)
]
def submit_funding_offer(
self,
type: str,
symbol: str,
amount: Union[str, float, Decimal],
rate: Union[str, float, Decimal],
period: int,
*,
flags: Optional[int] = None,
) -> Notification[FundingOffer]:
body = {
"type": type,
"symbol": symbol,
"amount": amount,
"rate": rate,
"period": period,
"flags": flags,
}
return _Notification[FundingOffer](serializers.FundingOffer).parse(
*self._m.post("auth/w/funding/offer/submit", body=body)
)
def cancel_funding_offer(self, id: int) -> Notification[FundingOffer]:
return _Notification[FundingOffer](serializers.FundingOffer).parse(
*self._m.post("auth/w/funding/offer/cancel", body={"id": id})
)
def cancel_all_funding_offers(self, currency: str) -> Notification[Literal[None]]:
return _Notification[Literal[None]](None).parse(
*self._m.post(
"auth/w/funding/offer/cancel/all", body={"currency": currency}
)
)
def submit_funding_close(self, id: int) -> Notification[Literal[None]]:
return _Notification[Literal[None]](None).parse(
*self._m.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]:
body = {
"status": status,
"currency": currency,
"amount": amount,
"rate": rate,
"period": period,
}
return _Notification[FundingAutoRenew](serializers.FundingAutoRenew).parse(
*self._m.post("auth/w/funding/auto", body=body)
)
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 _Notification[Literal[None]](None).parse(
*self._m.post(
"auth/w/funding/keep",
body={"type": type, "id": ids, "changes": changes},
)
)
def get_funding_offers_history(
self,
*,
symbol: Optional[str] = None,
start: Optional[str] = None,
end: Optional[str] = None,
limit: Optional[int] = None,
) -> List[FundingOffer]:
if symbol is None:
endpoint = "auth/r/funding/offers/hist"
else:
endpoint = f"auth/r/funding/offers/{symbol}/hist"
return [
serializers.FundingOffer.parse(*sub_data)
for sub_data in self._m.post(
endpoint, body={"start": start, "end": end, "limit": limit}
)
]
def get_funding_loans(self, *, symbol: Optional[str] = None) -> List[FundingLoan]:
if symbol is None:
endpoint = "auth/r/funding/loans"
else:
endpoint = f"auth/r/funding/loans/{symbol}"
return [
serializers.FundingLoan.parse(*sub_data)
for sub_data in self._m.post(endpoint)
]
def get_funding_loans_history(
self,
*,
symbol: Optional[str] = None,
start: Optional[str] = None,
end: Optional[str] = None,
limit: Optional[int] = None,
) -> List[FundingLoan]:
if symbol is None:
endpoint = "auth/r/funding/loans/hist"
else:
endpoint = f"auth/r/funding/loans/{symbol}/hist"
return [
serializers.FundingLoan.parse(*sub_data)
for sub_data in self._m.post(
endpoint, body={"start": start, "end": end, "limit": limit}
)
]
def get_funding_credits(
self, *, symbol: Optional[str] = None
) -> List[FundingCredit]:
if symbol is None:
endpoint = "auth/r/funding/credits"
else:
endpoint = f"auth/r/funding/credits/{symbol}"
return [
serializers.FundingCredit.parse(*sub_data)
for sub_data in self._m.post(endpoint)
]
def get_funding_credits_history(
self,
*,
symbol: Optional[str] = None,
start: Optional[str] = None,
end: Optional[str] = None,
limit: Optional[int] = None,
) -> List[FundingCredit]:
if symbol is None:
endpoint = "auth/r/funding/credits/hist"
else:
endpoint = f"auth/r/funding/credits/{symbol}/hist"
return [
serializers.FundingCredit.parse(*sub_data)
for sub_data in self._m.post(
endpoint, body={"start": start, "end": end, "limit": limit}
)
]
def get_funding_trades_history(
self,
*,
symbol: Optional[str] = None,
sort: Optional[int] = None,
start: Optional[str] = None,
end: Optional[str] = None,
limit: Optional[int] = None,
) -> List[FundingTrade]:
if symbol is None:
endpoint = "auth/r/funding/trades/hist"
else:
endpoint = f"auth/r/funding/trades/{symbol}/hist"
body = {"sort": sort, "start": start, "end": end, "limit": limit}
return [
serializers.FundingTrade.parse(*sub_data)
for sub_data in self._m.post(endpoint, body=body)
]
def get_funding_info(self, key: str) -> FundingInfo:
return serializers.FundingInfo.parse(
*(self._m.post(f"auth/r/info/funding/{key}")[2])
)
def transfer_between_wallets(
self,
from_wallet: str,
to_wallet: str,
currency: str,
currency_to: str,
amount: Union[str, float, Decimal],
) -> Notification[Transfer]:
body = {
"from": from_wallet,
"to": to_wallet,
"currency": currency,
"currency_to": currency_to,
"amount": amount,
}
return _Notification[Transfer](serializers.Transfer).parse(
*self._m.post("auth/w/transfer", body=body)
)
def submit_wallet_withdrawal(
self, wallet: str, method: str, address: str, amount: Union[str, float, Decimal]
) -> Notification[Withdrawal]:
body = {
"wallet": wallet,
"method": method,
"address": address,
"amount": amount,
}
return _Notification[Withdrawal](serializers.Withdrawal).parse(
*self._m.post("auth/w/withdraw", body=body)
)
def get_deposit_address(
self, wallet: str, method: str, op_renew: bool = False
) -> Notification[DepositAddress]:
return _Notification[DepositAddress](serializers.DepositAddress).parse(
*self._m.post(
"auth/w/deposit/address",
body={"wallet": wallet, "method": method, "op_renew": op_renew},
)
)
def generate_deposit_invoice(
self, wallet: str, currency: str, amount: Union[str, float, Decimal]
) -> LightningNetworkInvoice:
return serializers.LightningNetworkInvoice.parse(
*self._m.post(
"auth/w/deposit/invoice",
body={"wallet": wallet, "currency": currency, "amount": amount},
)
)
def get_movements(
self,
*,
currency: Optional[str] = None,
start: Optional[str] = None,
end: Optional[str] = None,
limit: Optional[int] = None,
) -> List[Movement]:
if currency is None:
endpoint = "auth/r/movements/hist"
else:
endpoint = f"auth/r/movements/{currency}/hist"
return [
serializers.Movement.parse(*sub_data)
for sub_data in self._m.post(
endpoint, body={"start": start, "end": end, "limit": limit}
)
]

View File

@@ -0,0 +1,192 @@
from decimal import Decimal
from typing import Any, Dict, List, Literal, Optional, Union
from bfxapi.rest._interface import Interface
from bfxapi.types import (
CurrencyConversion,
InvoicePage,
InvoiceStats,
InvoiceSubmission,
MerchantDeposit,
MerchantUnlinkedDeposit,
)
class RestMerchantEndpoints(Interface):
def submit_invoice(
self,
amount: Union[str, float, Decimal],
currency: str,
order_id: str,
customer_info: Dict[str, Any],
pay_currencies: List[str],
*,
duration: Optional[int] = None,
webhook: Optional[str] = None,
redirect_url: Optional[str] = None,
) -> InvoiceSubmission:
body = {
"amount": amount,
"currency": currency,
"orderId": order_id,
"customerInfo": customer_info,
"payCurrencies": pay_currencies,
"duration": duration,
"webhook": webhook,
"redirectUrl": redirect_url,
}
data = self._m.post("auth/w/ext/pay/invoice/create", body=body)
return InvoiceSubmission.parse(data)
def get_invoices(
self,
*,
id: Optional[str] = None,
start: Optional[str] = None,
end: Optional[str] = None,
limit: Optional[int] = None,
) -> List[InvoiceSubmission]:
body = {"id": id, "start": start, "end": end, "limit": limit}
data = self._m.post("auth/r/ext/pay/invoices", body=body)
return [InvoiceSubmission.parse(sub_data) for sub_data in data]
def get_invoices_paginated(
self,
page: int = 1,
page_size: int = 10,
sort: Literal["asc", "desc"] = "asc",
sort_field: Literal["t", "amount", "status"] = "t",
*,
status: Optional[
List[Literal["CREATED", "PENDING", "COMPLETED", "EXPIRED"]]
] = None,
fiat: Optional[List[str]] = None,
crypto: Optional[List[str]] = None,
id: Optional[str] = None,
order_id: Optional[str] = None,
) -> InvoicePage:
body = {
"page": page,
"pageSize": page_size,
"sort": sort,
"sortField": sort_field,
"status": status,
"fiat": fiat,
"crypto": crypto,
"id": id,
"orderId": order_id,
}
data = self._m.post("auth/r/ext/pay/invoices/paginated", body=body)
return InvoicePage.parse(data)
def get_invoice_count_stats(
self, status: Literal["CREATED", "PENDING", "COMPLETED", "EXPIRED"], format: str
) -> List[InvoiceStats]:
return [
InvoiceStats(**sub_data)
for sub_data in self._m.post(
"auth/r/ext/pay/invoice/stats/count",
body={"status": status, "format": format},
)
]
def get_invoice_earning_stats(
self, currency: str, format: str
) -> List[InvoiceStats]:
return [
InvoiceStats(**sub_data)
for sub_data in self._m.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:
body = {
"id": id,
"payCcy": pay_currency,
"depositId": deposit_id,
"ledgerId": ledger_id,
}
data = self._m.post("auth/w/ext/pay/invoice/complete", body=body)
return InvoiceSubmission.parse(data)
def expire_invoice(self, id: str) -> InvoiceSubmission:
body = {"id": id}
data = self._m.post("auth/w/ext/pay/invoice/expire", body=body)
return InvoiceSubmission.parse(data)
def get_currency_conversion_list(self) -> List[CurrencyConversion]:
return [
CurrencyConversion(**sub_data)
for sub_data in self._m.post("auth/r/ext/pay/settings/convert/list")
]
def add_currency_conversion(self, base_ccy: str, convert_ccy: str) -> bool:
return bool(
self._m.post(
"auth/w/ext/pay/settings/convert/create",
body={"baseCcy": base_ccy, "convertCcy": convert_ccy},
)
)
def remove_currency_conversion(self, base_ccy: str, convert_ccy: str) -> bool:
return bool(
self._m.post(
"auth/w/ext/pay/settings/convert/remove",
body={"baseCcy": base_ccy, "convertCcy": convert_ccy},
)
)
def set_merchant_settings(self, key: str, val: Any) -> bool:
return bool(
self._m.post("auth/w/ext/pay/settings/set", body={"key": key, "val": val})
)
def get_merchant_settings(self, key: str) -> Any:
return self._m.post("auth/r/ext/pay/settings/get", body={"key": key})
def list_merchant_settings(
self, keys: Optional[List[str]] = None
) -> Dict[str, Any]:
return self._m.post("auth/r/ext/pay/settings/list", body={"keys": keys or []})
def get_deposits(
self,
start: int,
to: int,
*,
ccy: Optional[str] = None,
unlinked: Optional[bool] = None,
) -> List[MerchantDeposit]:
body = {"from": start, "to": to, "ccy": ccy, "unlinked": unlinked}
data = self._m.post("auth/r/ext/pay/deposits", body=body)
return [MerchantDeposit(**sub_data) for sub_data in data]
def get_unlinked_deposits(
self, ccy: str, *, start: Optional[int] = None, end: Optional[int] = None
) -> List[MerchantUnlinkedDeposit]:
body = {"ccy": ccy, "start": start, "end": end}
data = self._m.post("/auth/r/ext/pay/deposits/unlinked", body=body)
return [MerchantUnlinkedDeposit(**sub_data) for sub_data in data]

View File

@@ -0,0 +1,379 @@
from decimal import Decimal
from typing import Any, Dict, List, Literal, Optional, Union, cast
from bfxapi.rest._interface import Interface
from bfxapi.types import (
Candle,
DerivativesStatus,
FundingCurrencyBook,
FundingCurrencyRawBook,
FundingCurrencyTicker,
FundingCurrencyTrade,
FundingMarketAveragePrice,
FundingStatistic,
FxRate,
Leaderboard,
Liquidation,
PlatformStatus,
PulseMessage,
PulseProfile,
Statistic,
TickersHistory,
TradingMarketAveragePrice,
TradingPairBook,
TradingPairRawBook,
TradingPairTicker,
TradingPairTrade,
serializers,
)
class RestPublicEndpoints(Interface):
def conf(self, config: str) -> Any:
return self._m.get(f"conf/{config}")[0]
def get_platform_status(self) -> PlatformStatus:
return serializers.PlatformStatus.parse(*self._m.get("platform/status"))
def get_tickers(
self, symbols: List[str]
) -> Dict[str, Union[TradingPairTicker, FundingCurrencyTicker]]:
data = self._m.get("tickers", params={"symbols": ",".join(symbols)})
parsers = {
"t": serializers.TradingPairTicker.parse,
"f": serializers.FundingCurrencyTicker.parse,
}
return {
symbol: cast(
Union[TradingPairTicker, FundingCurrencyTicker],
parsers[symbol[0]](*sub_data),
)
for sub_data in data
if (symbol := sub_data.pop(0))
}
def get_t_tickers(
self, symbols: Union[List[str], Literal["ALL"]]
) -> Dict[str, TradingPairTicker]:
if isinstance(symbols, str) and symbols == "ALL":
return {
symbol: cast(TradingPairTicker, sub_data)
for symbol, sub_data in self.get_tickers(["ALL"]).items()
if symbol.startswith("t")
}
data = self.get_tickers(list(symbols))
return cast(Dict[str, TradingPairTicker], data)
def get_f_tickers(
self, symbols: Union[List[str], Literal["ALL"]]
) -> Dict[str, FundingCurrencyTicker]:
if isinstance(symbols, str) and symbols == "ALL":
return {
symbol: cast(FundingCurrencyTicker, sub_data)
for symbol, sub_data in self.get_tickers(["ALL"]).items()
if symbol.startswith("f")
}
data = self.get_tickers(list(symbols))
return cast(Dict[str, FundingCurrencyTicker], data)
def get_t_ticker(self, symbol: str) -> TradingPairTicker:
return serializers.TradingPairTicker.parse(*self._m.get(f"ticker/{symbol}"))
def get_f_ticker(self, symbol: str) -> FundingCurrencyTicker:
return serializers.FundingCurrencyTicker.parse(*self._m.get(f"ticker/{symbol}"))
def get_tickers_history(
self,
symbols: List[str],
*,
start: Optional[str] = None,
end: Optional[str] = None,
limit: Optional[int] = None,
) -> List[TickersHistory]:
return [
serializers.TickersHistory.parse(*sub_data)
for sub_data in self._m.get(
"tickers/hist",
params={
"symbols": ",".join(symbols),
"start": start,
"end": end,
"limit": limit,
},
)
]
def get_t_trades(
self,
pair: str,
*,
limit: Optional[int] = None,
start: Optional[str] = None,
end: Optional[str] = None,
sort: Optional[int] = None,
) -> List[TradingPairTrade]:
params = {"limit": limit, "start": start, "end": end, "sort": sort}
data = self._m.get(f"trades/{pair}/hist", params=params)
return [serializers.TradingPairTrade.parse(*sub_data) for sub_data in data]
def get_f_trades(
self,
currency: str,
*,
limit: Optional[int] = None,
start: Optional[str] = None,
end: Optional[str] = None,
sort: Optional[int] = None,
) -> List[FundingCurrencyTrade]:
params = {"limit": limit, "start": start, "end": end, "sort": sort}
data = self._m.get(f"trades/{currency}/hist", params=params)
return [serializers.FundingCurrencyTrade.parse(*sub_data) for sub_data in data]
def get_t_book(
self,
pair: str,
precision: Literal["P0", "P1", "P2", "P3", "P4"],
*,
len: Optional[Literal[1, 25, 100]] = None,
) -> List[TradingPairBook]:
return [
serializers.TradingPairBook.parse(*sub_data)
for sub_data in self._m.get(f"book/{pair}/{precision}", params={"len": len})
]
def get_f_book(
self,
currency: str,
precision: Literal["P0", "P1", "P2", "P3", "P4"],
*,
len: Optional[Literal[1, 25, 100]] = None,
) -> List[FundingCurrencyBook]:
return [
serializers.FundingCurrencyBook.parse(*sub_data)
for sub_data in self._m.get(
f"book/{currency}/{precision}", params={"len": len}
)
]
def get_t_raw_book(
self, pair: str, *, len: Optional[Literal[1, 25, 100]] = None
) -> List[TradingPairRawBook]:
return [
serializers.TradingPairRawBook.parse(*sub_data)
for sub_data in self._m.get(f"book/{pair}/R0", params={"len": len})
]
def get_f_raw_book(
self, currency: str, *, len: Optional[Literal[1, 25, 100]] = None
) -> List[FundingCurrencyRawBook]:
return [
serializers.FundingCurrencyRawBook.parse(*sub_data)
for sub_data in self._m.get(f"book/{currency}/R0", params={"len": len})
]
def get_stats_hist(
self,
resource: str,
*,
sort: Optional[int] = None,
start: Optional[str] = None,
end: Optional[str] = None,
limit: Optional[int] = None,
) -> List[Statistic]:
params = {"sort": sort, "start": start, "end": end, "limit": limit}
data = self._m.get(f"stats1/{resource}/hist", params=params)
return [serializers.Statistic.parse(*sub_data) for sub_data in data]
def get_stats_last(
self,
resource: str,
*,
sort: Optional[int] = None,
start: Optional[str] = None,
end: Optional[str] = None,
limit: Optional[int] = None,
) -> Statistic:
params = {"sort": sort, "start": start, "end": end, "limit": limit}
data = self._m.get(f"stats1/{resource}/last", params=params)
return serializers.Statistic.parse(*data)
def get_candles_hist(
self,
symbol: str,
tf: str = "1m",
*,
sort: Optional[int] = None,
start: Optional[str] = None,
end: Optional[str] = None,
limit: Optional[int] = None,
) -> List[Candle]:
params = {"sort": sort, "start": start, "end": end, "limit": limit}
data = self._m.get(f"candles/trade:{tf}:{symbol}/hist", params=params)
return [serializers.Candle.parse(*sub_data) for sub_data in data]
def get_candles_last(
self,
symbol: str,
tf: str = "1m",
*,
sort: Optional[int] = None,
start: Optional[str] = None,
end: Optional[str] = None,
limit: Optional[int] = None,
) -> Candle:
params = {"sort": sort, "start": start, "end": end, "limit": limit}
data = self._m.get(f"candles/trade:{tf}:{symbol}/last", params=params)
return serializers.Candle.parse(*data)
def get_derivatives_status(
self, keys: Union[List[str], Literal["ALL"]]
) -> Dict[str, DerivativesStatus]:
if keys == "ALL":
params = {"keys": "ALL"}
else:
params = {"keys": ",".join(keys)}
data = self._m.get("status/deriv", params=params)
return {
key: serializers.DerivativesStatus.parse(*sub_data)
for sub_data in data
if (key := sub_data.pop(0))
}
def get_derivatives_status_history(
self,
key: str,
*,
sort: Optional[int] = None,
start: Optional[str] = None,
end: Optional[str] = None,
limit: Optional[int] = None,
) -> List[DerivativesStatus]:
params = {"sort": sort, "start": start, "end": end, "limit": limit}
data = self._m.get(f"status/deriv/{key}/hist", params=params)
return [serializers.DerivativesStatus.parse(*sub_data) for sub_data in data]
def get_liquidations(
self,
*,
sort: Optional[int] = None,
start: Optional[str] = None,
end: Optional[str] = None,
limit: Optional[int] = None,
) -> List[Liquidation]:
params = {"sort": sort, "start": start, "end": end, "limit": limit}
data = self._m.get("liquidations/hist", params=params)
return [serializers.Liquidation.parse(*sub_data[0]) for sub_data in data]
def get_seed_candles(
self,
symbol: str,
tf: str = "1m",
*,
sort: Optional[int] = None,
start: Optional[str] = None,
end: Optional[str] = None,
limit: Optional[int] = None,
) -> List[Candle]:
params = {"sort": sort, "start": start, "end": end, "limit": limit}
data = self._m.get(f"candles/trade:{tf}:{symbol}/hist", params=params)
return [serializers.Candle.parse(*sub_data) for sub_data in data]
def get_leaderboards_hist(
self,
resource: str,
*,
sort: Optional[int] = None,
start: Optional[str] = None,
end: Optional[str] = None,
limit: Optional[int] = None,
) -> List[Leaderboard]:
params = {"sort": sort, "start": start, "end": end, "limit": limit}
data = self._m.get(f"rankings/{resource}/hist", params=params)
return [serializers.Leaderboard.parse(*sub_data) for sub_data in data]
def get_leaderboards_last(
self,
resource: str,
*,
sort: Optional[int] = None,
start: Optional[str] = None,
end: Optional[str] = None,
limit: Optional[int] = None,
) -> Leaderboard:
params = {"sort": sort, "start": start, "end": end, "limit": limit}
data = self._m.get(f"rankings/{resource}/last", params=params)
return serializers.Leaderboard.parse(*data)
def get_funding_stats(
self,
symbol: str,
*,
start: Optional[str] = None,
end: Optional[str] = None,
limit: Optional[int] = None,
) -> List[FundingStatistic]:
params = {"start": start, "end": end, "limit": limit}
data = self._m.get(f"funding/stats/{symbol}/hist", params=params)
return [serializers.FundingStatistic.parse(*sub_data) for sub_data in data]
def get_pulse_profile_details(self, nickname: str) -> PulseProfile:
return serializers.PulseProfile.parse(*self._m.get(f"pulse/profile/{nickname}"))
def get_pulse_message_history(
self, *, end: Optional[str] = None, limit: Optional[int] = None
) -> List[PulseMessage]:
messages = []
for sub_data in self._m.get("pulse/hist", params={"end": end, "limit": limit}):
sub_data[18] = sub_data[18][0]
message = serializers.PulseMessage.parse(*sub_data)
messages.append(message)
return messages
def get_trading_market_average_price(
self,
symbol: str,
amount: Union[str, float, Decimal],
*,
price_limit: Optional[Union[str, float, Decimal]] = None,
) -> TradingMarketAveragePrice:
return serializers.TradingMarketAveragePrice.parse(
*self._m.post(
"calc/trade/avg",
body={"symbol": symbol, "amount": amount, "price_limit": price_limit},
)
)
def get_funding_market_average_price(
self,
symbol: str,
amount: Union[str, float, Decimal],
period: int,
*,
rate_limit: Optional[Union[str, float, Decimal]] = None,
) -> FundingMarketAveragePrice:
return serializers.FundingMarketAveragePrice.parse(
*self._m.post(
"calc/trade/avg",
body={
"symbol": symbol,
"amount": amount,
"period": period,
"rate_limit": rate_limit,
},
)
)
def get_fx_rate(self, ccy1: str, ccy2: str) -> FxRate:
return serializers.FxRate.parse(
*self._m.post("calc/fx", body={"ccy1": ccy1, "ccy2": ccy2})
)