diff --git a/lbry/db/database.py b/lbry/db/database.py index 25a5a1ede..5b72fd239 100644 --- a/lbry/db/database.py +++ b/lbry/db/database.py @@ -2,7 +2,7 @@ import os import asyncio import tempfile import multiprocessing as mp -from typing import List, Optional, Iterable, Iterator, TypeVar, Generic, TYPE_CHECKING, Dict +from typing import List, Optional, Iterable, Iterator, TypeVar, Generic, TYPE_CHECKING, Dict, Tuple from concurrent.futures import Executor, ThreadPoolExecutor, ProcessPoolExecutor from functools import partial @@ -288,7 +288,8 @@ class Database: async def search_supports(self, **constraints) -> Result[Output]: return await self.fetch_result(q.search_supports, **constraints) - async def sum_supports(self, claim_hash, include_channel_content=False, exclude_own_supports=False) -> List[Dict]: + async def sum_supports(self, claim_hash, include_channel_content=False, exclude_own_supports=False) \ + -> Tuple[List[Dict], int]: return await self.run(q.sum_supports, claim_hash, include_channel_content, exclude_own_supports) async def resolve(self, urls, **kwargs) -> Dict[str, Output]: diff --git a/lbry/db/queries/search.py b/lbry/db/queries/search.py index 19defebc8..10eda7f29 100644 --- a/lbry/db/queries/search.py +++ b/lbry/db/queries/search.py @@ -62,7 +62,7 @@ def search_supports(**constraints) -> Tuple[List[Output], Optional[int]]: return txos, total -def sum_supports(claim_hash, include_channel_content=False, exclude_own_supports=False) -> List[Dict]: +def sum_supports(claim_hash, include_channel_content=False, exclude_own_supports=False) -> Tuple[List[Dict], int]: supporter = Claim.alias("supporter") content = Claim.alias("content") where_condition = (content.c.claim_hash == claim_hash) @@ -91,10 +91,7 @@ def sum_supports(claim_hash, include_channel_content=False, exclude_own_supports result = context().fetchall(q) total = sum([row['staked'] for row in result]) - for row in result: - row['percent'] = round(row['staked']/total*100, 4) - - return result + return result, total def search_support_count(**constraints) -> int: diff --git a/lbry/service/api.py b/lbry/service/api.py index ac55e661c..46a0b8ee3 100644 --- a/lbry/service/api.py +++ b/lbry/service/api.py @@ -2594,7 +2594,11 @@ class API: support sum [--inculde_channel_content] {kwargs} """ - return await self.service.sum_supports(hex_str_to_hash(claim_id), include_channel_content, exclude_own_supports) + items, total = await self.service.sum_supports(hex_str_to_hash(claim_id), include_channel_content, exclude_own_supports) + return { + 'items': dict_values_to_lbc(items), + 'total': dewies_to_lbc(total), + } async def support_abandon( self, diff --git a/lbry/service/base.py b/lbry/service/base.py index ec48fcb14..2f9c86f05 100644 --- a/lbry/service/base.py +++ b/lbry/service/base.py @@ -153,7 +153,7 @@ class Service: raise NotImplementedError async def sum_supports(self, claim_hash: bytes, include_channel_content=False, exclude_own_supports=False) \ - -> List[Dict]: + -> Tuple[List[Dict], int]: raise NotImplementedError async def announce_addresses(self, address_manager, addresses: List[str]): diff --git a/lbry/service/full_node.py b/lbry/service/full_node.py index ddc816a32..fb75e513d 100644 --- a/lbry/service/full_node.py +++ b/lbry/service/full_node.py @@ -1,6 +1,6 @@ import logging from binascii import hexlify, unhexlify -from typing import List, Dict +from typing import List, Dict, Tuple from lbry.blockchain.lbrycrd import Lbrycrd from lbry.blockchain.sync import BlockchainSync @@ -70,5 +70,5 @@ class FullNode(Service): return await self.db.protobuf_resolve(urls, **kwargs) async def sum_supports(self, claim_hash: bytes, include_channel_content=False, exclude_own_supports=False) \ - -> List[Dict]: + -> Tuple[List[Dict], int]: return await self.db.sum_supports(claim_hash, include_channel_content, exclude_own_supports) diff --git a/lbry/service/light_client.py b/lbry/service/light_client.py index fd72a511d..34e32aa97 100644 --- a/lbry/service/light_client.py +++ b/lbry/service/light_client.py @@ -1,5 +1,5 @@ import logging -from typing import List, Dict +from typing import List, Dict, Tuple from lbry.conf import Config from lbry.blockchain import Ledger, Transaction @@ -47,5 +47,5 @@ class LightClient(Service): pass async def sum_supports(self, claim_hash: bytes, include_channel_content=False, exclude_own_supports=False) \ - -> List[Dict]: + -> Tuple[List[Dict], int]: return await self.client.sum_supports(claim_hash, include_channel_content, exclude_own_supports) diff --git a/tests/integration/blockchain/test_blockchain.py b/tests/integration/blockchain/test_blockchain.py index b384838db..491584f5f 100644 --- a/tests/integration/blockchain/test_blockchain.py +++ b/tests/integration/blockchain/test_blockchain.py @@ -967,11 +967,12 @@ class TestGeneralBlockchainSync(SyncingBlockchainTestCase): await self.generate(1) # check that supports sum correctly - results = await self.db.sum_supports(channel_a.claim_hash) + results, total = await self.db.sum_supports(channel_a.claim_hash) self.assertEqual(results, [ - {'supporter': ch_b.meta['short_url'], 'staked': 1000000000, 'percent': 62.5}, - {'supporter': ch_c.meta['short_url'], 'staked': 600000000, 'percent': 37.5}, + {'supporter': ch_b.meta['short_url'], 'staked': 1000000000}, + {'supporter': ch_c.meta['short_url'], 'staked': 600000000}, ]) + self.assertEqual(total, 1600000000) # create a claim in channel A and have channel B support that claim claim_a = await self.get_claim(await self.create_claim(name="bob", amount='2.0', sign=channel_a)) @@ -979,57 +980,65 @@ class TestGeneralBlockchainSync(SyncingBlockchainTestCase): await self.generate(1) # supports for just the channel claim should be unaffected ... - results = await self.db.sum_supports(channel_a.claim_hash) + results, total = await self.db.sum_supports(channel_a.claim_hash) self.assertEqual(results, [ - {'supporter': ch_b.meta['short_url'], 'staked': 1000000000, 'percent': 62.5}, - {'supporter': ch_c.meta['short_url'], 'staked': 600000000, 'percent': 37.5}, + {'supporter': ch_b.meta['short_url'], 'staked': 1000000000}, + {'supporter': ch_c.meta['short_url'], 'staked': 600000000}, ]) + self.assertEqual(total, 1600000000) # ... but when you include supports for content in the channel, the support for claim_a is added in - results = await self.db.sum_supports(channel_a.claim_hash, include_channel_content=True) + results, total = await self.db.sum_supports(channel_a.claim_hash, include_channel_content=True) self.assertEqual(results, [ - {'supporter': ch_b.meta['short_url'], 'staked': 1100000000, 'percent': 64.7059}, - {'supporter': ch_c.meta['short_url'], 'staked': 600000000, 'percent': 35.2941}, + {'supporter': ch_b.meta['short_url'], 'staked': 1100000000}, + {'supporter': ch_c.meta['short_url'], 'staked': 600000000}, ]) + self.assertEqual(total, 1700000000) # check that sum_supports works as expected for a non-channel claim (with and without including channel content) - results = await self.db.sum_supports(claim_a.claim_hash, include_channel_content=False) - self.assertEqual(results, [{'supporter': ch_b.meta['short_url'], 'staked': 100000000, 'percent': 100}]) - results = await self.db.sum_supports(claim_a.claim_hash, include_channel_content=True) - self.assertEqual(results, [{'supporter': ch_b.meta['short_url'], 'staked': 100000000, 'percent': 100}]) + results, total = await self.db.sum_supports(claim_a.claim_hash, include_channel_content=False) + self.assertEqual(results, [{'supporter': ch_b.meta['short_url'], 'staked': 100000000}]) + self.assertEqual(total, 100000000) + results, total = await self.db.sum_supports(claim_a.claim_hash, include_channel_content=True) + self.assertEqual(results, [{'supporter': ch_b.meta['short_url'], 'staked': 100000000}]) + self.assertEqual(total, 100000000) # if a support is abandoned, it stops counting await self.abandon_support(support_b) await self.generate(1) - results = await self.db.sum_supports(channel_a.claim_hash) + results, total = await self.db.sum_supports(channel_a.claim_hash) self.assertEqual(results, [ - {'supporter': ch_c.meta['short_url'], 'staked': 600000000, 'percent': 54.5455}, - {'supporter': ch_b.meta['short_url'], 'staked': 500000000, 'percent': 45.4545}, + {'supporter': ch_c.meta['short_url'], 'staked': 600000000}, + {'supporter': ch_b.meta['short_url'], 'staked': 500000000}, ]) + self.assertEqual(total, 1100000000) # but if a creator unlocks a tip, that still counts as the tipping channel's contribution await self.abandon_support(tip_b) await self.abandon_support(tip_c) await self.generate(1) - results = await self.db.sum_supports(channel_a.claim_hash) + results, total = await self.db.sum_supports(channel_a.claim_hash) self.assertEqual(results, [ - {'supporter': ch_c.meta['short_url'], 'staked': 600000000, 'percent': 54.5455}, - {'supporter': ch_b.meta['short_url'], 'staked': 500000000, 'percent': 45.4545}, + {'supporter': ch_c.meta['short_url'], 'staked': 600000000}, + {'supporter': ch_b.meta['short_url'], 'staked': 500000000}, ]) + self.assertEqual(total, 1100000000) # a channel's own supports don't count if you exclude them await self.support_claim(channel_a, '10.0', sign=channel_a) await self.generate(1) - results = await self.db.sum_supports(channel_a.claim_hash, exclude_own_supports=False) + results, total = await self.db.sum_supports(channel_a.claim_hash, exclude_own_supports=False) self.assertEqual(results, [ - {'supporter': ch_a.meta['short_url'], 'staked': 1000000000, 'percent': 47.6190}, - {'supporter': ch_c.meta['short_url'], 'staked': 600000000, 'percent': 28.5714}, - {'supporter': ch_b.meta['short_url'], 'staked': 500000000, 'percent': 23.8095}, + {'supporter': ch_a.meta['short_url'], 'staked': 1000000000}, + {'supporter': ch_c.meta['short_url'], 'staked': 600000000}, + {'supporter': ch_b.meta['short_url'], 'staked': 500000000}, ]) - results = await self.db.sum_supports(channel_a.claim_hash, exclude_own_supports=True) + self.assertEqual(total, 2100000000) + results, total = await self.db.sum_supports(channel_a.claim_hash, exclude_own_supports=True) self.assertEqual(results, [ - {'supporter': ch_c.meta['short_url'], 'staked': 600000000, 'percent': 54.5455}, - {'supporter': ch_b.meta['short_url'], 'staked': 500000000, 'percent': 45.4545}, + {'supporter': ch_c.meta['short_url'], 'staked': 600000000}, + {'supporter': ch_b.meta['short_url'], 'staked': 500000000}, ]) + self.assertEqual(total, 1100000000) async def test_meta_fields_are_translated_to_protobuf(self): chan_ab = await self.get_claim(