Merge pull request #8091 from zouppen/convert_currency_cmd
Add command for currency conversions
This commit is contained in:
@@ -36,7 +36,7 @@ import inspect
|
||||
from collections import defaultdict
|
||||
from functools import wraps, partial
|
||||
from itertools import repeat
|
||||
from decimal import Decimal
|
||||
from decimal import Decimal, InvalidOperation
|
||||
from typing import Optional, TYPE_CHECKING, Dict, List
|
||||
import os
|
||||
|
||||
@@ -1322,6 +1322,43 @@ class Commands:
|
||||
'onchain_amount': format_satoshis(onchain_amount_sat),
|
||||
}
|
||||
|
||||
@command('n')
|
||||
async def convert_currency(self, from_amount=1, from_ccy = '', to_ccy = ''):
|
||||
"""Converts the given amount of currency to another using the
|
||||
configured exchange rate source.
|
||||
"""
|
||||
if not self.daemon.fx.is_enabled():
|
||||
raise Exception("FX is disabled. To enable, run: 'electrum setconfig use_exchange_rate true'")
|
||||
# Currency codes are uppercase
|
||||
from_ccy = from_ccy.upper()
|
||||
to_ccy = to_ccy.upper()
|
||||
# Default currencies
|
||||
if from_ccy == '':
|
||||
from_ccy = "BTC" if to_ccy != "BTC" else self.daemon.fx.ccy
|
||||
if to_ccy == '':
|
||||
to_ccy = "BTC" if from_ccy != "BTC" else self.daemon.fx.ccy
|
||||
# Get current rates
|
||||
rate_from = self.daemon.fx.exchange.get_cached_spot_quote(from_ccy)
|
||||
rate_to = self.daemon.fx.exchange.get_cached_spot_quote(to_ccy)
|
||||
# Test if currencies exist
|
||||
if rate_from.is_nan():
|
||||
raise Exception(f'Currency to convert from ({from_ccy}) is unknown or rate is unavailable')
|
||||
if rate_to.is_nan():
|
||||
raise Exception(f'Currency to convert to ({to_ccy}) is unknown or rate is unavailable')
|
||||
# Conversion
|
||||
try:
|
||||
from_amount = Decimal(from_amount)
|
||||
to_amount = from_amount / rate_from * rate_to
|
||||
except InvalidOperation:
|
||||
raise Exception("from_amount is not a number")
|
||||
return {
|
||||
"from_amount": self.daemon.fx.ccy_amount_str(from_amount, False, from_ccy),
|
||||
"to_amount": self.daemon.fx.ccy_amount_str(to_amount, False, to_ccy),
|
||||
"from_ccy": from_ccy,
|
||||
"to_ccy": to_ccy,
|
||||
"source": self.daemon.fx.exchange.name(),
|
||||
}
|
||||
|
||||
|
||||
def eval_bool(x: str) -> bool:
|
||||
if x == 'false': return False
|
||||
@@ -1400,6 +1437,9 @@ command_options = {
|
||||
'connection_string': (None, "Lightning network node ID or network address"),
|
||||
'new_fee_rate': (None, "The Updated/Increased Transaction fee rate (in sat/byte)"),
|
||||
'strategies': (None, "Select RBF any one or multiple RBF strategies in any order, separated by ','; Options : 'CoinChooser','DecreaseChange','DecreasePayment' "),
|
||||
'from_amount': (None, "Amount to convert (default: 1)"),
|
||||
'from_ccy': (None, "Currency to convert from"),
|
||||
'to_ccy': (None, "Currency to convert to"),
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -34,7 +34,10 @@ CCY_PRECISIONS = {'BHD': 3, 'BIF': 0, 'BYR': 0, 'CLF': 4, 'CLP': 0,
|
||||
'JOD': 3, 'JPY': 0, 'KMF': 0, 'KRW': 0, 'KWD': 3,
|
||||
'LYD': 3, 'MGA': 1, 'MRO': 1, 'OMR': 3, 'PYG': 0,
|
||||
'RWF': 0, 'TND': 3, 'UGX': 0, 'UYI': 0, 'VND': 0,
|
||||
'VUV': 0, 'XAF': 0, 'XAU': 4, 'XOF': 0, 'XPF': 0}
|
||||
'VUV': 0, 'XAF': 0, 'XAU': 4, 'XOF': 0, 'XPF': 0,
|
||||
# Cryptocurrencies
|
||||
'BTC': 8, 'LTC': 8, 'XRP': 6, 'ETH': 18,
|
||||
}
|
||||
|
||||
|
||||
def to_decimal(x: Union[str, float, int, Decimal]) -> Decimal:
|
||||
@@ -173,6 +176,8 @@ class ExchangeBase(Logger):
|
||||
|
||||
def get_cached_spot_quote(self, ccy: str) -> Decimal:
|
||||
"""Returns the cached exchange rate as a Decimal"""
|
||||
if ccy == 'BTC':
|
||||
return Decimal(1)
|
||||
rate = self._quotes.get(ccy)
|
||||
if rate is None:
|
||||
return Decimal('NaN')
|
||||
@@ -554,8 +559,8 @@ class FxThread(ThreadJob, EventListener):
|
||||
def remove_thousands_separator(text):
|
||||
return text.replace(',', '') # FIXME use THOUSAND_SEPARATOR in util
|
||||
|
||||
def ccy_amount_str(self, amount, commas):
|
||||
prec = CCY_PRECISIONS.get(self.ccy, 2)
|
||||
def ccy_amount_str(self, amount, commas, ccy=None):
|
||||
prec = CCY_PRECISIONS.get(self.ccy if ccy is None else ccy, 2)
|
||||
fmt_str = "{:%s.%df}" % ("," if commas else "", max(0, prec)) # FIXME use util.THOUSAND_SEPARATOR and util.DECIMAL_POINT
|
||||
try:
|
||||
rounded_amount = round(amount, prec)
|
||||
|
||||
Reference in New Issue
Block a user