diff --git a/namecheap/namecheap.py b/namecheap/namecheap.py index 85e0883..4ec34c9 100644 --- a/namecheap/namecheap.py +++ b/namecheap/namecheap.py @@ -36,7 +36,7 @@ from namecheap.helpers import api_string from namecheap.exceptions import ApiError from namecheap.objects import CamelSnakeDictable, CreateDomainResponse, Domain, DomainCheck, DomainDetails, DomainRecord, NamecheapTLD, \ - TLDPrice + TLDPrice, Balance __all__ = [ 'NAMECHEAP_ENDPOINTS', 'ENDPOINTS', 'NAMESPACE', 'DEFAULT_ATTEMPTS_COUNT', 'DEFAULT_ATTEMPTS_DELAY', 'Api' @@ -1348,3 +1348,49 @@ def domains_getInfo(self, domain: str, hostname: str = None, **user_payload) -> return DomainDetails.from_dict(info_result) get_domain_info = domains_getInfo + + # https://www.namecheap.com/support/api/methods/users/get-balances/ + def get_balances(self, force_dict: bool = False) -> Union[Balance, Dict[str, Balance]]: + """ + + Example: + + >>> balance = self.get_balances() + >>> print(balance) + Balance( + currency='USD', + error_no=None, + description='', + AvailableBalance=Decimal('8971.68'), + AccountBalance=Decimal('8971.68'), + EarnedAmount=Decimal('0.0000'), + WithdrawableAmount=Decimal('0.0000'), + FundsRequiredForAutoRenew=Decimal('0.0000') + ) + >>> balance.available_balance + '8971.68' + >>> balance.currency + 'USD' + + Method may return Dict[str, Balance] if more than 1 currency is on the account, or if force_dict=True + >>> balance = self.get_balances(force_dict=True) + >>> print(balance) + { + 'USD': Balance( + currency='USD', + error_no=None, + description='', + AvailableBalance=Decimal('8971.68'), + AccountBalance=Decimal('8971.68'), + EarnedAmount=Decimal('0.0000'), + WithdrawableAmount=Decimal('0.0000'), + FundsRequiredForAutoRenew=Decimal('0.0000')) + } + + """ + xml = self.call('namecheap.users.getBalances') + xpath = f'.//{{{NAMESPACE}}}CommandResponse/{{{NAMESPACE}}}UserGetBalancesResult' + results = {} + for check_result in xml.findall(xpath): + results[check_result.attrib['Currency']] = Balance.from_dict(dict(check_result.items())) + return results if force_dict or len(results) > 1 else results[list(results.keys())[0]] diff --git a/namecheap/objects.py b/namecheap/objects.py index 528c0a7..75f8fcb 100644 --- a/namecheap/objects.py +++ b/namecheap/objects.py @@ -10,7 +10,7 @@ __all__ = [ 'CamelSnakeDictable', 'CreateDomainResponse', 'DomainRecord', 'Domain', 'DomainCheck', - 'TLDPrice', 'DomainDetails', 'NamecheapTLD' + 'TLDPrice', 'DomainDetails', 'NamecheapTLD', 'Balance' ] @@ -384,3 +384,32 @@ def __post_init__(self): v = getattr(self, k, None) if not empty(v) and not isinstance(v, int): setattr(self, k, int(v)) + +@dataclass +class Balance(CamelSnakeDictable): + class DictConfig: + dict_convert_mode = None + stringify_all = True + currency: str + available_balance: Decimal = field(default_factory=Decimal) + account_balance: Decimal = field(default_factory=Decimal) + earned_amount: Decimal = field(default_factory=Decimal) + withdrawable_amount: Decimal = field(default_factory=Decimal) + funds_required_for_auto_renew: Decimal = field(default_factory=Decimal) + raw_data: Union[dict, DictObject] = field(default_factory=DictObject, repr=False) + + def __post_init__(self): + conv_dec_keys = [ + 'available_balance', + 'account_balance', + 'earned_amount', + 'withdrawable_amount', + 'funds_required_for_auto_renew', + ] + for k in conv_dec_keys: + v = getattr(self, k, None) + if empty(v): + log.debug("Skipping %s - is empty", k) + continue + log.debug("Converting %s to decimal", k) + setattr(self, k, dec_round(Decimal(v), dp=2))