diff --git a/gui/stdio.py b/gui/stdio.py index bea7a43f9781..c46a16707b4c 100644 --- a/gui/stdio.py +++ b/gui/stdio.py @@ -1,4 +1,4 @@ -from decimal import Decimal +from decimal import Decimal as PyDecimal _ = lambda x:x #from i18n import _ from electroncash import WalletStorage, Wallet @@ -113,11 +113,11 @@ def get_balance(self): msg = _( "Synchronizing..." ) else: c, u, x = self.wallet.get_balance() - msg = _("Balance")+": %f "%(Decimal(c) / COIN) + msg = _("Balance")+": %f "%(PyDecimal(c) / COIN) if u: - msg += " [%f unconfirmed]"%(Decimal(u) / COIN) + msg += " [%f unconfirmed]"%(PyDecimal(u) / COIN) if x: - msg += " [%f unmatured]"%(Decimal(x) / COIN) + msg += " [%f unmatured]"%(PyDecimal(x) / COIN) else: msg = _( "Not connected" ) @@ -167,12 +167,12 @@ def do_send(self): print(_('Invalid Bitcoin address')) return try: - amount = int(Decimal(self.str_amount) * COIN) + amount = int(PyDecimal(self.str_amount) * COIN) except Exception: print(_('Invalid Amount')) return try: - fee = int(Decimal(self.str_fee) * COIN) + fee = int(PyDecimal(self.str_fee) * COIN) except Exception: print(_('Invalid Fee')) return diff --git a/gui/text.py b/gui/text.py index e286ca1363f1..3e9288b4d822 100644 --- a/gui/text.py +++ b/gui/text.py @@ -1,6 +1,6 @@ import tty, sys import curses, datetime, locale -from decimal import Decimal +from decimal import Decimal as PyDecimal import getpass import electrum @@ -134,11 +134,11 @@ def print_balance(self): msg = _("Synchronizing...") else: c, u, x = self.wallet.get_balance() - msg = _("Balance")+": %f "%(Decimal(c) / COIN) + msg = _("Balance")+": %f "%(PyDecimal(c) / COIN) if u: - msg += " [%f unconfirmed]"%(Decimal(u) / COIN) + msg += " [%f unconfirmed]"%(PyDecimal(u) / COIN) if x: - msg += " [%f unmatured]"%(Decimal(x) / COIN) + msg += " [%f unmatured]"%(PyDecimal(x) / COIN) else: msg = _("Not connected") @@ -324,12 +324,12 @@ def do_send(self): self.show_message(_('Invalid Bitcoin address')) return try: - amount = int(Decimal(self.str_amount) * COIN) + amount = int(PyDecimal(self.str_amount) * COIN) except Exception: self.show_message(_('Invalid Amount')) return try: - fee = int(Decimal(self.str_fee) * COIN) + fee = int(PyDecimal(self.str_fee) * COIN) except Exception: self.show_message(_('Invalid Fee')) return @@ -397,13 +397,13 @@ def network_dialog(self): self.network.set_parameters(host, port, protocol, proxy, auto_connect) def settings_dialog(self): - fee = str(Decimal(self.config.fee_per_kb()) / COIN) + fee = str(PyDecimal(self.config.fee_per_kb()) / COIN) out = self.run_dialog('Settings', [ {'label':'Default fee', 'type':'satoshis', 'value': fee } ], buttons = 1) if out: if out.get('Default fee'): - fee = int(Decimal(out['Default fee']) * COIN) + fee = int(PyDecimal(out['Default fee']) * COIN) self.config.set_key('fee_per_kb', fee, True) diff --git a/lib/commands.py b/lib/commands.py index d8e0f48cec41..8fe8d7ff0965 100644 --- a/lib/commands.py +++ b/lib/commands.py @@ -30,7 +30,7 @@ import ast import base64 from functools import wraps -from decimal import Decimal +from decimal import Decimal as PyDecimal # Qt 5.12 also exports Decimal from .import util from .util import bfh, bh2u, format_satoshis, json_decode, print_error @@ -47,7 +47,7 @@ def satoshis(amount): # satoshi conversion must not be performed by the parser - return int(COIN*Decimal(amount)) if amount not in ['!', None] else amount + return int(COIN*PyDecimal(amount)) if amount not in ['!', None] else amount class Command: @@ -233,7 +233,7 @@ def listunspent(self): l = self.wallet.get_utxos(exclude_frozen=False) for i in l: v = i["value"] - i["value"] = str(Decimal(v)/COIN) if v is not None else None + i["value"] = str(PyDecimal(v)/COIN) if v is not None else None i["address"] = i["address"].to_ui_string() return l @@ -359,11 +359,11 @@ def getpubkeys(self, address): def getbalance(self): """Return the balance of your wallet. """ c, u, x = self.wallet.get_balance() - out = {"confirmed": str(Decimal(c)/COIN)} + out = {"confirmed": str(PyDecimal(c)/COIN)} if u: - out["unconfirmed"] = str(Decimal(u)/COIN) + out["unconfirmed"] = str(PyDecimal(u)/COIN) if x: - out["unmatured"] = str(Decimal(x)/COIN) + out["unmatured"] = str(PyDecimal(x)/COIN) return out @command('n') @@ -373,8 +373,8 @@ def getaddressbalance(self, address): """ sh = Address.from_string(address).to_scripthash_hex() out = self.network.synchronous_get(('blockchain.scripthash.get_balance', [sh])) - out["confirmed"] = str(Decimal(out["confirmed"])/COIN) - out["unconfirmed"] = str(Decimal(out["unconfirmed"])/COIN) + out["confirmed"] = str(PyDecimal(out["confirmed"])/COIN) + out["unconfirmed"] = str(PyDecimal(out["unconfirmed"])/COIN) return out @command('n') @@ -802,7 +802,7 @@ def help(self): # don't use floats because of rounding errors from .transaction import tx_from_str -json_loads = lambda x: json.loads(x, parse_float=lambda x: str(Decimal(x))) +json_loads = lambda x: json.loads(x, parse_float=lambda x: str(PyDecimal(x))) arg_types = { 'num': int, 'nbits': int, @@ -814,8 +814,8 @@ def help(self): 'jsontx': json_loads, 'inputs': json_loads, 'outputs': json_loads, - 'fee': lambda x: str(Decimal(x)) if x is not None else None, - 'amount': lambda x: str(Decimal(x)) if x != '!' else '!', + 'fee': lambda x: str(PyDecimal(x)) if x is not None else None, + 'amount': lambda x: str(PyDecimal(x)) if x != '!' else '!', 'locktime': int, } diff --git a/lib/exchange_rate.py b/lib/exchange_rate.py index 8c5708600054..4a48251b0842 100644 --- a/lib/exchange_rate.py +++ b/lib/exchange_rate.py @@ -9,7 +9,7 @@ import time import csv import decimal -from decimal import Decimal +from decimal import Decimal as PyDecimal # Qt 5.12 also exports Decimal from .bitcoin import COIN from .i18n import _ @@ -123,7 +123,7 @@ class BitcoinAverage(ExchangeBase): def get_rates(self, ccy): json = self.get_json('apiv2.bitcoinaverage.com', '/indices/global/ticker/short') - return dict([(r.replace("BCH", ""), Decimal(json[r]['last'])) + return dict([(r.replace("BCH", ""), PyDecimal(json[r]['last'])) for r in json if r != 'timestamp']) def history_ccys(self): @@ -142,21 +142,21 @@ class Bitmarket(ExchangeBase): def get_rates(self, ccy): json = self.get_json('www.bitmarket.pl', '/json/BCCPLN/ticker.json') - return {'PLN': Decimal(json['last'])} + return {'PLN': PyDecimal(json['last'])} class BitPay(ExchangeBase): def get_rates(self, ccy): json = self.get_json('bitpay.com', '/api/rates/BCH') - return dict([(r['code'], Decimal(r['rate'])) for r in json]) + return dict([(r['code'], PyDecimal(r['rate'])) for r in json]) class Bitso(ExchangeBase): def get_rates(self, ccy): json = self.get_json('api.bitso.com', '/v2/ticker/?book=bch_btc') - return {'BTC': Decimal(json['last'])} + return {'BTC': PyDecimal(json['last'])} class BitStamp(ExchangeBase): @@ -166,9 +166,9 @@ def get_rates(self, ccy): json_eur = self.get_json('www.bitstamp.net', '/api/v2/ticker/bcheur') json_btc = self.get_json('www.bitstamp.net', '/api/v2/ticker/bchbtc') return { - 'USD': Decimal(json_usd['last']), - 'EUR': Decimal(json_eur['last']), - 'BTC': Decimal(json_btc['last'])} + 'USD': PyDecimal(json_usd['last']), + 'EUR': PyDecimal(json_eur['last']), + 'BTC': PyDecimal(json_btc['last'])} class Coinbase(ExchangeBase): @@ -176,7 +176,7 @@ class Coinbase(ExchangeBase): def get_rates(self, ccy): json = self.get_json('coinbase.com', '/api/v1/currencies/exchange_rates') - return dict([(r[7:].upper(), Decimal(json[r])) + return dict([(r[7:].upper(), PyDecimal(json[r])) for r in json if r.startswith('bch_to_')]) class Kraken(ExchangeBase): @@ -186,7 +186,7 @@ def get_rates(self, ccy): pairs = ['BCH%s' % c for c in ccys] json = self.get_json('api.kraken.com', '/0/public/Ticker?pair=%s' % ','.join(pairs)) - return dict((k[-3:], Decimal(float(v['c'][0]))) + return dict((k[-3:], PyDecimal(float(v['c'][0]))) for k, v in json['result'].items()) @@ -194,7 +194,7 @@ class CoinFloor(ExchangeBase): # CoinFloor API only supports GBP on public API def get_rates(self, ccy): json = self.get_json('webapi.coinfloor.co.uk:8090/bist/BCH/GBP', '/ticker/') - return {'GBP': Decimal(json['last'])} + return {'GBP': PyDecimal(json['last'])} class WEX(ExchangeBase): @@ -207,20 +207,20 @@ def get_rates(self, ccy): json_ltc = self.get_json('wex.nz', '/api/3/ticker/bch_ltc') json_eth = self.get_json('wex.nz', '/api/3/ticker/bch_eth') json_dsh = self.get_json('wex.nz', '/api/3/ticker/bch_dsh') - return {'EUR': Decimal(json_eur['bch_eur']['last']), - 'RUB': Decimal(json_rub['bch_rur']['last']), - 'USD': Decimal(json_usd['bch_usd']['last']), - 'BTC': Decimal(json_btc['bch_btc']['last']), - 'LTC': Decimal(json_ltc['bch_ltc']['last']), - 'ETH': Decimal(json_eth['bch_eth']['last']), - 'DSH': Decimal(json_dsh['bch_dsh']['last'])} + return {'EUR': PyDecimal(json_eur['bch_eur']['last']), + 'RUB': PyDecimal(json_rub['bch_rur']['last']), + 'USD': PyDecimal(json_usd['bch_usd']['last']), + 'BTC': PyDecimal(json_btc['bch_btc']['last']), + 'LTC': PyDecimal(json_ltc['bch_ltc']['last']), + 'ETH': PyDecimal(json_eth['bch_eth']['last']), + 'DSH': PyDecimal(json_dsh['bch_dsh']['last'])} class CoinCap(ExchangeBase): def get_rates(self, ccy): json = self.get_json('api.coincap.io', '/v2/rates/bitcoin-cash/') - return {'USD': Decimal(json['data']['rateUsd'])} + return {'USD': PyDecimal(json['data']['rateUsd'])} def history_ccys(self): return ['USD'] @@ -241,7 +241,7 @@ class CoinGecko(ExchangeBase): def get_rates(self, ccy): json = self.get_json('api.coingecko.com', '/api/v3/coins/bitcoin-cash?localization=False&sparkline=false') prices = json["market_data"]["current_price"] - return dict([(a[0].upper(),Decimal(a[1])) for a in prices.items()]) + return dict([(a[0].upper(),PyDecimal(a[1])) for a in prices.items()]) def history_ccys(self): return ['AED', 'ARS', 'AUD', 'BTD', 'BHD', 'BMD', 'BRL', 'BTC', @@ -403,10 +403,10 @@ def on_history(self): self.network.trigger_callback('on_history') def exchange_rate(self): - '''Returns None, or the exchange rate as a Decimal''' + '''Returns None, or the exchange rate as a PyDecimal''' rate = self.exchange.quotes.get(self.ccy) if rate: - return Decimal(rate) + return PyDecimal(rate) def format_amount_and_units(self, btc_balance): amount_str = self.format_amount(btc_balance) @@ -428,7 +428,7 @@ def value_str(self, satoshis, rate, default_prec = 2 ): if satoshis is None: # Can happen with incomplete history return _("Unknown") if rate: - value = Decimal(satoshis) / COIN * Decimal(rate) + value = PyDecimal(satoshis) / COIN * PyDecimal(rate) return "%s" % (self.ccy_amount_str(value, True, default_prec)) return _("No data") @@ -439,7 +439,7 @@ def history_rate(self, d_t): if rate is None and (datetime.today().date() - d_t.date()).days <= 2: rate = self.exchange.quotes.get(self.ccy) self.history_used_spot = True - return Decimal(rate) if rate is not None else None + return PyDecimal(rate) if rate is not None else None def historical_value_str(self, satoshis, d_t): rate = self.history_rate(d_t) @@ -448,7 +448,7 @@ def historical_value_str(self, satoshis, d_t): def historical_value(self, satoshis, d_t): rate = self.history_rate(d_t) if rate: - return Decimal(satoshis) / COIN * Decimal(rate) + return PyDecimal(satoshis) / COIN * PyDecimal(rate) def timestamp_rate(self, timestamp): from .util import timestamp_to_datetime diff --git a/lib/tests/test_commands.py b/lib/tests/test_commands.py index 33cceb58026b..fa27cf221f91 100644 --- a/lib/tests/test_commands.py +++ b/lib/tests/test_commands.py @@ -1,5 +1,5 @@ import unittest -from decimal import Decimal +from decimal import Decimal as PyDecimal from ..commands import Commands @@ -9,7 +9,7 @@ class TestCommands(unittest.TestCase): def test_setconfig_non_auth_number(self): self.assertEqual(7777, Commands._setconfig_normalize_value('rpcport', "7777")) self.assertEqual(7777, Commands._setconfig_normalize_value('rpcport', '7777')) - self.assertAlmostEqual(Decimal(2.3), Commands._setconfig_normalize_value('somekey', '2.3')) + self.assertAlmostEqual(PyDecimal(2.3), Commands._setconfig_normalize_value('somekey', '2.3')) def test_setconfig_non_auth_number_as_string(self): self.assertEqual("7777", Commands._setconfig_normalize_value('somekey', "'7777'")) diff --git a/lib/util.py b/lib/util.py index 1466c5737b2f..413893a20791 100644 --- a/lib/util.py +++ b/lib/util.py @@ -25,8 +25,8 @@ import os, sys, re, json, time from collections import defaultdict from datetime import datetime -from decimal import Decimal -import decimal +from decimal import Decimal as PyDecimal # Qt 5.12 also exports Decimal +import decimal # for SLP-specific function format_satoshis_plain_nofloat import traceback import threading import hmac @@ -234,7 +234,7 @@ def json_encode(obj): def json_decode(x): try: - return json.loads(x, parse_float=Decimal) + return json.loads(x, parse_float=PyDecimal) except: return x @@ -416,7 +416,7 @@ def format_satoshis_plain(x, decimal_point = 8): """Display a satoshi amount scaled. Always uses a '.' as a decimal point and has no thousands separator""" scale_factor = pow(10, decimal_point) - return "{:.8f}".format(Decimal(x) / scale_factor).rstrip('0').rstrip('.') + return "{:.8f}".format(PyDecimal(x) / scale_factor).rstrip('0').rstrip('.') def format_satoshis(x, num_zeros=0, decimal_point=8, precision=None, is_diff=False, whitespaces=False): diff --git a/lib/wallet.py b/lib/wallet.py index bcee1e1f95f5..867723ea2917 100644 --- a/lib/wallet.py +++ b/lib/wallet.py @@ -36,7 +36,7 @@ import copy import errno from collections import defaultdict -from decimal import Decimal +from decimal import Decimal as PyDecimal # Qt 5.12 also exports Decimal from functools import partial from .i18n import _ diff --git a/lib/web.py b/lib/web.py index c1d06ff54216..a3605f020269 100644 --- a/lib/web.py +++ b/lib/web.py @@ -21,7 +21,7 @@ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -from decimal import Decimal +from decimal import Decimal as PyDecimal # Qt 5.12 also exports Decimal import os import re import shutil @@ -157,9 +157,9 @@ def parse_URI(uri, on_pr=None): m = re.match(r'([0-9\.]+)X([0-9])', am) if m: k = int(m.group(2)) - 8 - amount = Decimal(m.group(1)) * pow(10, k) + amount = PyDecimal(m.group(1)) * pow(10, k) else: - amount = Decimal(am) * bitcoin.COIN + amount = PyDecimal(am) * bitcoin.COIN out['amount'] = int(amount) if 'message' in out: out['message'] = out['message']