Browse Source

Merge pull request #8091 from zouppen/convert_currency_cmd

Add command for currency conversions
master
SomberNight 3 years ago
parent
commit
f86229f169
No known key found for this signature in database
GPG Key ID: B33B5F232C6271E9
  1. 42
      electrum/commands.py
  2. 11
      electrum/exchange_rate.py

42
electrum/commands.py

@ -36,7 +36,7 @@ import inspect
from collections import defaultdict from collections import defaultdict
from functools import wraps, partial from functools import wraps, partial
from itertools import repeat from itertools import repeat
from decimal import Decimal from decimal import Decimal, InvalidOperation
from typing import Optional, TYPE_CHECKING, Dict, List from typing import Optional, TYPE_CHECKING, Dict, List
import os import os
@ -1322,6 +1322,43 @@ class Commands:
'onchain_amount': format_satoshis(onchain_amount_sat), '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: def eval_bool(x: str) -> bool:
if x == 'false': return False if x == 'false': return False
@ -1400,6 +1437,9 @@ command_options = {
'connection_string': (None, "Lightning network node ID or network address"), 'connection_string': (None, "Lightning network node ID or network address"),
'new_fee_rate': (None, "The Updated/Increased Transaction fee rate (in sat/byte)"), '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' "), '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"),
} }

11
electrum/exchange_rate.py

@ -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, 'JOD': 3, 'JPY': 0, 'KMF': 0, 'KRW': 0, 'KWD': 3,
'LYD': 3, 'MGA': 1, 'MRO': 1, 'OMR': 3, 'PYG': 0, 'LYD': 3, 'MGA': 1, 'MRO': 1, 'OMR': 3, 'PYG': 0,
'RWF': 0, 'TND': 3, 'UGX': 0, 'UYI': 0, 'VND': 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: 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: def get_cached_spot_quote(self, ccy: str) -> Decimal:
"""Returns the cached exchange rate as a Decimal""" """Returns the cached exchange rate as a Decimal"""
if ccy == 'BTC':
return Decimal(1)
rate = self._quotes.get(ccy) rate = self._quotes.get(ccy)
if rate is None: if rate is None:
return Decimal('NaN') return Decimal('NaN')
@ -554,8 +559,8 @@ class FxThread(ThreadJob, EventListener):
def remove_thousands_separator(text): def remove_thousands_separator(text):
return text.replace(',', '') # FIXME use THOUSAND_SEPARATOR in util return text.replace(',', '') # FIXME use THOUSAND_SEPARATOR in util
def ccy_amount_str(self, amount, commas): def ccy_amount_str(self, amount, commas, ccy=None):
prec = CCY_PRECISIONS.get(self.ccy, 2) 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 fmt_str = "{:%s.%df}" % ("," if commas else "", max(0, prec)) # FIXME use util.THOUSAND_SEPARATOR and util.DECIMAL_POINT
try: try:
rounded_amount = round(amount, prec) rounded_amount = round(amount, prec)

Loading…
Cancel
Save