diff --git a/bfxapi/rest/endpoints/bfx_rest_interface.py b/bfxapi/rest/endpoints/bfx_rest_interface.py index 0bddbbc..a2dc6ec 100644 --- a/bfxapi/rest/endpoints/bfx_rest_interface.py +++ b/bfxapi/rest/endpoints/bfx_rest_interface.py @@ -1,11 +1,13 @@ from typing import Optional + from .rest_public_endpoints import RestPublicEndpoints from .rest_authenticated_endpoints import RestAuthenticatedEndpoints +from .rest_merchant_endpoints import RestMerchantEndpoints class BfxRestInterface(object): VERSION = 2 def __init__(self, host: str, API_KEY: Optional[str] = None, API_SECRET: Optional[str] = None): - self.public = RestPublicEndpoints(host=host) - - self.auth = RestAuthenticatedEndpoints(host=host, API_KEY=API_KEY, API_SECRET=API_SECRET) \ No newline at end of file + self.public = RestPublicEndpoints(host=host) + 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) \ No newline at end of file diff --git a/bfxapi/rest/endpoints/rest_authenticated_endpoints.py b/bfxapi/rest/endpoints/rest_authenticated_endpoints.py index 0991336..947032b 100644 --- a/bfxapi/rest/endpoints/rest_authenticated_endpoints.py +++ b/bfxapi/rest/endpoints/rest_authenticated_endpoints.py @@ -8,14 +8,6 @@ from .. import serializers from .. enums import Sort, OrderType, FundingOfferType from .. middleware import Middleware -from ... utils.camel_and_snake_case_adapters import to_snake_case_keys, to_camel_case_keys - -_CustomerInfo = TypedDict("_CustomerInfo", { - "nationality": str, "resid_country": str, "resid_city": str, - "resid_zip_code": str, "resid_street": str, "resid_building_no": str, - "full_name": str, "email": str, "tos_accepted": bool -}) - class RestAuthenticatedEndpoints(Middleware): def get_user_info(self) -> UserInfo: return serializers.UserInfo.parse(*self._POST(f"auth/r/info/user")) @@ -326,59 +318,4 @@ class RestAuthenticatedEndpoints(Middleware): "limit": limit } - return [ serializers.Movement.parse(*sub_data) for sub_data in self._POST(endpoint, body=body) ] - - def submit_invoice(self, amount: Union[Decimal, float, str], currency: str, order_id: str, - customer_info: _CustomerInfo, pay_currencies: List[str], duration: Optional[int] = None, - webhook: Optional[str] = None, redirect_url: Optional[str] = None) -> InvoiceSubmission: - body = to_camel_case_keys({ - "amount": amount, "currency": currency, "order_id": order_id, - "customer_info": customer_info, "pay_currencies": pay_currencies, "duration": duration, - "webhook": webhook, "redirect_url": redirect_url - }) - - data = to_snake_case_keys(self._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]: - return [ InvoiceSubmission.parse(sub_data) for sub_data in self._POST("auth/r/ext/pay/invoices", body={ - "id": id, "start": start, "end": end, - "limit": limit - }) ] - - 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 }) ] - - 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 }) ] - - def complete_invoice(self, id: str, pay_currency: str, deposit_id: Optional[int] = None, ledger_id: Optional[int] = None) -> InvoiceSubmission: - return InvoiceSubmission.parse(self._POST("auth/w/ext/pay/invoice/complete", body={ - "id": id, "payCcy": pay_currency, "depositId": deposit_id, - "ledgerId": ledger_id - })) - - def expire_invoice(self, id: str) -> InvoiceSubmission: - return InvoiceSubmission.parse(self._POST("auth/w/ext/pay/invoice/expire", body={ "id": id })) - - def get_currency_conversion_list(self) -> List[CurrencyConversion]: - return [ - CurrencyConversion( - base_currency=sub_data["baseCcy"], - convert_currency=sub_data["convertCcy"], - created=sub_data["created"] - ) 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: - return bool(self._POST("auth/w/ext/pay/settings/convert/create", body={ - "baseCcy": base_currency, - "convertCcy": convert_currency - })) - - def remove_currency_conversion(self, base_currency: str, convert_currency: str) -> bool: - return bool(self._POST("auth/w/ext/pay/settings/convert/remove", body={ - "baseCcy": base_currency, - "convertCcy": convert_currency - })) \ No newline at end of file + return [ serializers.Movement.parse(*sub_data) for sub_data in self._POST(endpoint, body=body) ] \ No newline at end of file diff --git a/bfxapi/rest/endpoints/rest_merchant_endpoints.py b/bfxapi/rest/endpoints/rest_merchant_endpoints.py new file mode 100644 index 0000000..3c6f5c7 --- /dev/null +++ b/bfxapi/rest/endpoints/rest_merchant_endpoints.py @@ -0,0 +1,68 @@ +from typing import List, Union, Literal, Optional +from decimal import Decimal + +from .. types import * +from .. middleware import Middleware +from ... utils.camel_and_snake_case_adapters import to_snake_case_keys, to_camel_case_keys + +_CustomerInfo = TypedDict("_CustomerInfo", { + "nationality": str, "resid_country": str, "resid_city": str, + "resid_zip_code": str, "resid_street": str, "resid_building_no": str, + "full_name": str, "email": str, "tos_accepted": bool +}) + +class RestMerchantEndpoints(Middleware): + def submit_invoice(self, amount: Union[Decimal, float, str], currency: str, order_id: str, + customer_info: _CustomerInfo, pay_currencies: List[str], duration: Optional[int] = None, + webhook: Optional[str] = None, redirect_url: Optional[str] = None) -> InvoiceSubmission: + body = to_camel_case_keys({ + "amount": amount, "currency": currency, "order_id": order_id, + "customer_info": customer_info, "pay_currencies": pay_currencies, "duration": duration, + "webhook": webhook, "redirect_url": redirect_url + }) + + data = to_snake_case_keys(self._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]: + return [ InvoiceSubmission.parse(sub_data) for sub_data in self._POST("auth/r/ext/pay/invoices", body={ + "id": id, "start": start, "end": end, + "limit": limit + }) ] + + 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 }) ] + + 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 }) ] + + def complete_invoice(self, id: str, pay_currency: str, deposit_id: Optional[int] = None, ledger_id: Optional[int] = None) -> InvoiceSubmission: + return InvoiceSubmission.parse(self._POST("auth/w/ext/pay/invoice/complete", body={ + "id": id, "payCcy": pay_currency, "depositId": deposit_id, + "ledgerId": ledger_id + })) + + def expire_invoice(self, id: str) -> InvoiceSubmission: + return InvoiceSubmission.parse(self._POST("auth/w/ext/pay/invoice/expire", body={ "id": id })) + + def get_currency_conversion_list(self) -> List[CurrencyConversion]: + return [ + CurrencyConversion( + base_currency=sub_data["baseCcy"], + convert_currency=sub_data["convertCcy"], + created=sub_data["created"] + ) 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: + return bool(self._POST("auth/w/ext/pay/settings/convert/create", body={ + "baseCcy": base_currency, + "convertCcy": convert_currency + })) + + def remove_currency_conversion(self, base_currency: str, convert_currency: str) -> bool: + return bool(self._POST("auth/w/ext/pay/settings/convert/remove", body={ + "baseCcy": base_currency, + "convertCcy": convert_currency + })) \ No newline at end of file diff --git a/bfxapi/rest/types.py b/bfxapi/rest/types.py index a2dd647..3bd12e8 100644 --- a/bfxapi/rest/types.py +++ b/bfxapi/rest/types.py @@ -563,7 +563,7 @@ class DerivativePositionCollateralLimits(_Type): #endregion -#region Type hinting for models which are not serializable +#region Type hinting for Rest Merchant Endpoints @compose(dataclass, partial) class InvoiceSubmission(_Type): diff --git a/examples/rest/merchant.py b/examples/rest/merchant.py index 7a4c835..ec6727b 100644 --- a/examples/rest/merchant.py +++ b/examples/rest/merchant.py @@ -20,7 +20,7 @@ customer_info = { "email": "satoshi3@bitfinex.com" } -invoice = bfx.rest.auth.submit_invoice( +invoice = bfx.rest.merchant.submit_invoice( amount=1, currency="USD", duration=864000, @@ -29,15 +29,15 @@ invoice = bfx.rest.auth.submit_invoice( pay_currencies=["ETH"] ) -print(bfx.rest.auth.get_invoices()) +print(bfx.rest.merchant.get_invoices()) -print(bfx.rest.auth.get_invoice_count_stats(status="CREATED", format="Y")) +print(bfx.rest.merchant.get_invoice_count_stats(status="CREATED", format="Y")) -print(bfx.rest.auth.get_invoice_earning_stats(currency="USD", format="Y")) +print(bfx.rest.merchant.get_invoice_earning_stats(currency="USD", format="Y")) -print(bfx.rest.auth.get_currency_conversion_list()) +print(bfx.rest.merchant.get_currency_conversion_list()) -print(bfx.rest.auth.complete_invoice( +print(bfx.rest.merchant.complete_invoice( id=invoice.id, pay_currency="ETH", deposit_id=1