Co-Authored-By: itsdeka <dario.moceri@bitfinex.com>
This commit is contained in:
Davide Casale
2023-02-10 04:27:35 +01:00
parent 998eadf99b
commit 180e92fcb4
5 changed files with 119 additions and 28 deletions

View File

@@ -302,13 +302,13 @@ class RestAuthenticatedEndpoints(Middleware):
return serializers._Notification[DepositAddress](serializers.DepositAddress).parse(*self._POST("auth/w/deposit/address", body=body)) return serializers._Notification[DepositAddress](serializers.DepositAddress).parse(*self._POST("auth/w/deposit/address", body=body))
def generate_deposit_invoice(self, wallet: str, currency: str, amount: Union[Decimal, float, str]) -> Invoice: def generate_deposit_invoice(self, wallet: str, currency: str, amount: Union[Decimal, float, str]) -> LightningNetworkInvoice:
body = { body = {
"wallet": wallet, "currency": currency, "wallet": wallet, "currency": currency,
"amount": amount "amount": amount
} }
return serializers.Invoice.parse(*self._POST("auth/w/deposit/invoice", body=body)) return serializers.LightningNetworkInvoice.parse(*self._POST("auth/w/deposit/invoice", body=body))
def get_movements(self, currency: Optional[str] = None, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None) -> List[Movement]: def get_movements(self, currency: Optional[str] = None, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None) -> List[Movement]:
if currency == None: if currency == None:
@@ -321,3 +321,21 @@ class RestAuthenticatedEndpoints(Middleware):
} }
return [ serializers.Movement.parse(*sub_data) for sub_data in self._POST(endpoint, body=body) ] 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:
data = self._POST("auth/w/ext/pay/invoice/create", body={
"amount": amount, "currency": currency, "order_id": order_id,
"customer_info": customer_info, "pay_currencies": pay_currencies, "duration": duration,
"webhook": webhook, "redirect_url": redirect_url
})
if "customer_info" in data and data["customer_info"] != None:
data["customer_info"] = CustomerInfo(**data["customer_info"])
if "invoices" in data and data["invoices"] != None:
for index, invoice in enumerate(data["invoices"]):
data["invoices"][index] = Invoice(**invoice)
return InvoiceSubmission(**data)

View File

@@ -18,7 +18,7 @@ __serializers__ = [
"FundingOffer", "FundingCredit", "FundingLoan", "FundingOffer", "FundingCredit", "FundingLoan",
"FundingAutoRenew", "FundingInfo", "Wallet", "FundingAutoRenew", "FundingInfo", "Wallet",
"Transfer", "Withdrawal", "DepositAddress", "Transfer", "Withdrawal", "DepositAddress",
"Invoice", "Movement", "SymbolMarginInfo", "LightningNetworkInvoice", "Movement", "SymbolMarginInfo",
"BaseMarginInfo", "PositionClaim", "PositionIncreaseInfo", "BaseMarginInfo", "PositionClaim", "PositionIncreaseInfo",
"PositionIncrease", "PositionHistory", "PositionSnapshot", "PositionIncrease", "PositionHistory", "PositionSnapshot",
"PositionAudit", "DerivativePositionCollateral", "DerivativePositionCollateralLimits", "PositionAudit", "DerivativePositionCollateral", "DerivativePositionCollateralLimits",
@@ -581,7 +581,7 @@ DepositAddress = generate_labeler_serializer("DepositAddress", klass=types.Depos
"pool_address" "pool_address"
]) ])
Invoice = generate_labeler_serializer("Invoice", klass=types.Invoice, labels=[ LightningNetworkInvoice = generate_labeler_serializer("LightningNetworkInvoice", klass=types.LightningNetworkInvoice, labels=[
"invoice_hash", "invoice_hash",
"invoice", "invoice",
"_PLACEHOLDER", "_PLACEHOLDER",

View File

@@ -1,10 +1,12 @@
from typing import Type, Tuple, List, Dict, TypedDict, Union, Optional, Any from typing import Type, Tuple, List, Dict, TypedDict, Union, Optional, Literal, Any
from dataclasses import dataclass from dataclasses import dataclass
from types import SimpleNamespace
from .. labeler import _Type from .. labeler import _Type
from .. notification import Notification from .. notification import Notification
from ..utils.JSONEncoder import JSON from .. utils.JSONEncoder import JSON
#region Type hinting for Rest Public Endpoints #region Type hinting for Rest Public Endpoints
@@ -440,7 +442,7 @@ class DepositAddress(_Type):
pool_address: str pool_address: str
@dataclass @dataclass
class Invoice(_Type): class LightningNetworkInvoice(_Type):
invoice_hash: str invoice_hash: str
invoice: str invoice: str
amount: str amount: str
@@ -562,3 +564,43 @@ class DerivativePositionCollateralLimits(_Type):
max_collateral: float max_collateral: float
#endregion #endregion
#region Type hinting for models which are not serializable
@dataclass
class InvoiceSubmission(_Type):
id: str
t: int
type: Literal["ECOMMERCE", "POS"]
duration: int
amount: float
currency: str
order_id: str
pay_currencies: List[str]
webhook: str
redirect_url: str
status: Literal["CREATED", "PENDING", "COMPLETED", "EXPIRED"]
customer_info: Optional["CustomerInfo"]
invoices: List["Invoice"]
class CustomerInfo(SimpleNamespace):
nationality: str
resid_country: str
resid_state: str
resid_city: str
resid_zip_code: str
resid_street: str
resid_building_no: str
full_name: str
email: str
tos_accepted: bool
class Invoice(SimpleNamespace):
amount: float
currency: str
pay_currency: str
pool_currency: str
address: str
ext: JSON
#endregion

View File

@@ -2,16 +2,16 @@ import json
from decimal import Decimal from decimal import Decimal
from datetime import datetime from datetime import datetime
from types import SimpleNamespace
from typing import Type, List, Dict, Union, Any from typing import Type, List, Dict, Union, Any
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]]
class JSONEncoder(json.JSONEncoder): def _strip(dictionary: Dict) -> Dict:
def encode(self, obj: JSON) -> str:
def _strip(dictionary: Dict) -> Dict:
return { key: value for key, value in dictionary.items() if value != None} return { key: value for key, value in dictionary.items() if value != None}
def _convert_float_to_str(data: JSON) -> JSON: def _convert_float_to_str(data: JSON) -> JSON:
if isinstance(data, float): if isinstance(data, float):
return format(Decimal(repr(data)), "f") return format(Decimal(repr(data)), "f")
elif isinstance(data, list): elif isinstance(data, list):
@@ -20,15 +20,13 @@ class JSONEncoder(json.JSONEncoder):
return _strip({ key: _convert_float_to_str(value) for key, value in data.items() }) return _strip({ key: _convert_float_to_str(value) for key, value in data.items() })
else: return data else: return data
data = _convert_float_to_str(obj) class JSONEncoder(json.JSONEncoder):
def encode(self, obj: JSON) -> str:
return json.JSONEncoder.encode(self, data) return json.JSONEncoder.encode(self, _convert_float_to_str(obj))
def default(self, obj: Any) -> Any: def default(self, obj: Any) -> Any:
if isinstance(obj, Decimal): if isinstance(obj, SimpleNamespace): return _convert_float_to_str(vars(obj))
return format(obj, "f") elif isinstance(obj, Decimal): return format(obj, "f")
elif isinstance(obj, datetime): return str(obj)
if isinstance(obj, datetime):
return str(obj)
return json.JSONEncoder.default(self, obj) return json.JSONEncoder.default(self, obj)

33
examples/rest/merchant.py Normal file
View File

@@ -0,0 +1,33 @@
# python -c "import examples.rest.merchant"
import os
from bfxapi.client import Client, Constants
from bfxapi.rest.types import CustomerInfo
bfx = Client(
REST_HOST=Constants.REST_HOST,
API_KEY=os.getenv("BFX_API_KEY"),
API_SECRET=os.getenv("BFX_API_SECRET")
)
customer_info: CustomerInfo = CustomerInfo(
nationality="GB",
resid_country="DE",
resid_city="Berlin",
resid_zip_code=1,
resid_street="Timechain",
full_name="Satoshi",
email="satoshi3@bitfinex.com",
tos_accepted=None,
resid_building_no=None
)
print(bfx.rest.auth.submit_invoice(
amount=1,
currency="USD",
duration=864000,
order_id="order123",
customer_info=customer_info,
pay_currencies=["ETH"],
))