diff --git a/lbrynet/extras/daemon/storage.py b/lbrynet/extras/daemon/storage.py index 25065e84c..f817c691c 100644 --- a/lbrynet/extras/daemon/storage.py +++ b/lbrynet/extras/daemon/storage.py @@ -2,12 +2,11 @@ import logging import os import sqlite3 import traceback +import typing from binascii import hexlify, unhexlify -from decimal import Decimal from twisted.internet import defer, task, threads from twisted.enterprise import adbapi -from torba.client.constants import COIN - +from lbrynet.extras.wallet.dewies import dewies_to_lbc, lbc_to_dewies from lbrynet import conf from lbrynet.schema.claim import ClaimDict from lbrynet.schema.decode import smart_decode @@ -17,6 +16,12 @@ from lbrynet.dht.constants import dataExpireTimeout log = logging.getLogger(__name__) +def calculate_effective_amount(amount: str, supports: typing.Optional[typing.List[typing.Dict]] = None) -> str: + return dewies_to_lbc( + lbc_to_dewies(amount) + sum([lbc_to_dewies(support['amount']) for support in supports]) + ) + + def _get_next_available_file_name(download_directory, file_name): base_name, ext = os.path.splitext(file_name) i = 0 @@ -557,7 +562,7 @@ class SQLiteStorage: for support in supports: transaction.execute( "insert into support values (?, ?, ?, ?)", - ("%s:%i" % (support['txid'], support['nout']), claim_id, int(support['amount'] * COIN), + ("%s:%i" % (support['txid'], support['nout']), claim_id, lbc_to_dewies(support['amount']), support.get('address', "")) ) return self.db.runInteraction(_save_support) @@ -568,7 +573,7 @@ class SQLiteStorage: "txid": outpoint.split(":")[0], "nout": int(outpoint.split(":")[1]), "claim_id": supported_id, - "amount": float(Decimal(amount) / Decimal(COIN)), + "amount": dewies_to_lbc(amount), "address": address, } @@ -595,7 +600,7 @@ class SQLiteStorage: outpoint = "%s:%i" % (claim_info['txid'], claim_info['nout']) claim_id = claim_info['claim_id'] name = claim_info['name'] - amount = int(COIN * claim_info['amount']) + amount = lbc_to_dewies(claim_info['amount']) height = claim_info['height'] address = claim_info['address'] sequence = claim_info['claim_sequence'] @@ -744,9 +749,7 @@ class SQLiteStorage: if result and include_supports: supports = yield self.get_supports(result['claim_id']) result['supports'] = supports - result['effective_amount'] = float( - sum([support['amount'] for support in supports]) + result['amount'] - ) + result['effective_amount'] = calculate_effective_amount(result['amount'], supports) defer.returnValue(result) @defer.inlineCallbacks @@ -787,9 +790,7 @@ class SQLiteStorage: claim = claims[stream_hash] supports = all_supports.get(claim['claim_id'], []) claim['supports'] = supports - claim['effective_amount'] = float( - sum([support['amount'] for support in supports]) + claim['amount'] - ) + claim['effective_amount'] = calculate_effective_amount(claim['amount'], supports) claims[stream_hash] = claim defer.returnValue(claims) @@ -811,9 +812,7 @@ class SQLiteStorage: if include_supports: supports = yield self.get_supports(result['claim_id']) result['supports'] = supports - result['effective_amount'] = float( - sum([support['amount'] for support in supports]) + result['amount'] - ) + result['effective_amount'] = calculate_effective_amount(result['amount'], supports) defer.returnValue(result) def get_unknown_certificate_ids(self): @@ -881,7 +880,7 @@ def _format_claim_response(outpoint, claim_id, name, amount, height, serialized, "claim_sequence": claim_sequence, "value": ClaimDict.deserialize(unhexlify(serialized)).claim_dict, "height": height, - "amount": float(Decimal(amount) / Decimal(COIN)), + "amount": dewies_to_lbc(amount), "nout": int(outpoint.split(":")[1]), "txid": outpoint.split(":")[0], "channel_claim_id": channel_id, diff --git a/lbrynet/extras/wallet/dewies.py b/lbrynet/extras/wallet/dewies.py index 1dd85eae0..3e70c1da9 100644 --- a/lbrynet/extras/wallet/dewies.py +++ b/lbrynet/extras/wallet/dewies.py @@ -2,7 +2,7 @@ import textwrap from torba.client.util import coins_to_satoshis, satoshis_to_coins -def lbc_to_dewies(lbc): +def lbc_to_dewies(lbc: str) -> int: try: return coins_to_satoshis(lbc) except ValueError: @@ -29,5 +29,5 @@ def lbc_to_dewies(lbc): )) -def dewies_to_lbc(dewies): +def dewies_to_lbc(dewies) -> str: return satoshis_to_coins(dewies) diff --git a/lbrynet/extras/wallet/manager.py b/lbrynet/extras/wallet/manager.py index 4c2c243e0..b6bc91f1b 100644 --- a/lbrynet/extras/wallet/manager.py +++ b/lbrynet/extras/wallet/manager.py @@ -275,9 +275,9 @@ class LbryWalletManager(BaseWalletManager): ledger: MainNetLedger = self.default_account.ledger results = await ledger.resolve(page, page_size, *uris) if 'error' not in results: - await self.old_db.save_claims_for_resolve( - (value for value in results.values() if 'error' not in value) - ).asFuture(asyncio.get_event_loop()) + await self.old_db.save_claims_for_resolve([ + value for value in results.values() if 'error' not in value + ]).asFuture(asyncio.get_event_loop()) return results async def get_claims_for_name(self, name: str): @@ -431,7 +431,7 @@ class LbryWalletManager(BaseWalletManager): raise NameError(f"More than one other claim exists with the name '{name}'.") await account.ledger.broadcast(tx) await self.old_db.save_claims([self._old_get_temp_claim_info( - tx, tx.outputs[0], claim_address, claim_dict, name, amount + tx, tx.outputs[0], claim_address, claim_dict, name, dewies_to_lbc(amount) )]).asFuture(asyncio.get_event_loop()) # TODO: release reserved tx outputs in case anything fails by this point return tx @@ -440,6 +440,13 @@ class LbryWalletManager(BaseWalletManager): holding_address = await account.receiving.get_or_create_usable_address() tx = await Transaction.support(claim_name, claim_id, amount, holding_address, [account], account) await account.ledger.broadcast(tx) + await self.old_db.save_supports(claim_id, [{ + 'txid': tx.id, + 'nout': tx.position, + 'address': holding_address, + 'claim_id': claim_id, + 'amount': dewies_to_lbc(amount) + }]).asFuture(asyncio.get_event_loop()) return tx async def tip_claim(self, amount, claim_id, account): @@ -448,6 +455,13 @@ class LbryWalletManager(BaseWalletManager): claim_to_tip['name'], claim_id, amount, claim_to_tip['address'], [account], account ) await account.ledger.broadcast(tx) + await self.old_db.save_supports(claim_id, [{ + 'txid': tx.id, + 'nout': tx.position, + 'address': claim_to_tip['address'], + 'claim_id': claim_id, + 'amount': dewies_to_lbc(amount) + }]).asFuture(asyncio.get_event_loop()) return tx async def abandon_claim(self, claim_id, txid, nout, account): @@ -467,6 +481,10 @@ class LbryWalletManager(BaseWalletManager): await account.ledger.broadcast(tx) account.add_certificate_private_key(tx.outputs[0].ref, key.decode()) # TODO: release reserved tx outputs in case anything fails by this point + + await self.old_db.save_claims([self._old_get_temp_claim_info( + tx, tx.outputs[0], address, cert, channel_name, dewies_to_lbc(amount) + )]).asFuture(asyncio.get_event_loop()) return tx def _old_get_temp_claim_info(self, tx, txo, address, claim_dict, name, bid): diff --git a/lbrynet/extras/wallet/resolve.py b/lbrynet/extras/wallet/resolve.py index f996b0451..ed0b8d41f 100644 --- a/lbrynet/extras/wallet/resolve.py +++ b/lbrynet/extras/wallet/resolve.py @@ -2,7 +2,7 @@ import logging from ecdsa import BadSignatureError from binascii import unhexlify, hexlify - +from lbrynet.extras.wallet.dewies import dewies_to_lbc from lbrynet.p2p.Error import UnknownNameError, UnknownClaimID, UnknownURI, UnknownOutpoint from lbrynet.schema.address import is_address from lbrynet.schema.claim import ClaimDict @@ -189,7 +189,7 @@ class Resolver: if 'height' in claim_result and claim_result['height'] is None: claim_result['height'] = -1 - if 'amount' in claim_result and not isinstance(claim_result['amount'], float): + if 'amount' in claim_result: claim_result = format_amount_value(claim_result) claim_result['permanent_url'] = _get_permanent_url(claim_result) @@ -287,14 +287,13 @@ class Resolver: # Format value to be hex encoded string # TODO: refactor. Came from lbryum, there could be another part of torba doing it def format_amount_value(obj): - COIN = 100000000 if isinstance(obj, dict): for k, v in obj.items(): if k in ('amount', 'effective_amount'): if not isinstance(obj[k], float): - obj[k] = float(obj[k]) / float(COIN) + obj[k] = dewies_to_lbc(obj[k]) elif k == 'supports' and isinstance(v, list): - obj[k] = [{'txid': txid, 'nout': nout, 'amount': float(amount) / float(COIN)} + obj[k] = [{'txid': txid, 'nout': nout, 'amount': dewies_to_lbc(amount)} for (txid, nout, amount) in v] elif isinstance(v, (list, dict)): obj[k] = format_amount_value(v) @@ -437,6 +436,7 @@ def _decode_claim_result(claim): claim['error'] = "Failed to decode value" return claim + def _handle_claim_result(results): if not results: #TODO: cannot determine what name we searched for here diff --git a/tests/integration/wallet/test_commands.py b/tests/integration/wallet/test_commands.py index 27032236f..11b1a8428 100644 --- a/tests/integration/wallet/test_commands.py +++ b/tests/integration/wallet/test_commands.py @@ -360,7 +360,9 @@ class EpicAdventuresOfChris45(CommandTestCase): # And check if his support showed up resolve_result = await self.out(self.daemon.jsonrpc_resolve(uri=uri)) # It obviously did! Because, blockchain baby \O/ - self.assertEqual(resolve_result[uri]['claim']['supports'][0]['amount'], 0.2) + self.assertEqual(resolve_result[uri]['claim']['amount'], '1.0') + self.assertEqual(resolve_result[uri]['claim']['effective_amount'], '1.2') + self.assertEqual(resolve_result[uri]['claim']['supports'][0]['amount'], '0.2') self.assertEqual(resolve_result[uri]['claim']['supports'][0]['txid'], tx['txid']) await self.generate(5) @@ -373,7 +375,7 @@ class EpicAdventuresOfChris45(CommandTestCase): # And again checks if it went to the just right place resolve_result = await self.out(self.daemon.jsonrpc_resolve(uri=uri)) # Which it obviously did. Because....????? - self.assertEqual(resolve_result[uri]['claim']['supports'][1]['amount'], 0.3) + self.assertEqual(resolve_result[uri]['claim']['supports'][1]['amount'], '0.3') self.assertEqual(resolve_result[uri]['claim']['supports'][1]['txid'], tx['txid']) await self.generate(5) @@ -384,7 +386,7 @@ class EpicAdventuresOfChris45(CommandTestCase): # And check if his support showed up resolve_result = await self.out(self.daemon.jsonrpc_resolve(uri=uri)) # It did! - self.assertEqual(resolve_result[uri]['claim']['supports'][2]['amount'], 0.4) + self.assertEqual(resolve_result[uri]['claim']['supports'][2]['amount'], '0.4') self.assertEqual(resolve_result[uri]['claim']['supports'][2]['txid'], tx['txid']) await self.generate(5) diff --git a/tests/unit/database/test_SQLiteStorage.py b/tests/unit/database/test_SQLiteStorage.py index e8794bbb7..71d6d0ee4 100644 --- a/tests/unit/database/test_SQLiteStorage.py +++ b/tests/unit/database/test_SQLiteStorage.py @@ -55,8 +55,8 @@ fake_claim_info = { } }, 'height': 10000, - 'amount': 1.0, - 'effective_amount': 1.0, + 'amount': '1.0', + 'effective_amount': '1.0', 'nout': 0, 'txid': "deadbeef" * 8, 'supports': [], @@ -168,7 +168,7 @@ class SupportsStorageTests(StorageTest): "txid": random_lbry_hash(), "nout": i, "address": f"addr{i}", - "amount": i + "amount": f"{i}.0" } for i in range(20)] expected_supports = {} for idx, claim_id in enumerate(claim_ids):