diff --git a/lbry/extras/daemon/daemon.py b/lbry/extras/daemon/daemon.py index b097c5556..e16f3e763 100644 --- a/lbry/extras/daemon/daemon.py +++ b/lbry/extras/daemon/daemon.py @@ -2254,7 +2254,7 @@ class Daemon(metaclass=JSONRPCServerType): Usage: claim_list [--claim_type=...] [--claim_id=...] [--name=...] [--is_spent] [--channel_id=...] [--account_id=] [--wallet_id=] - [--page=] [--page_size=] + [--has_source | --has_no_source] [--page=] [--page_size=] [--resolve] [--order_by=] [--no_totals] [--include_received_tips] Options: @@ -2265,6 +2265,8 @@ class Daemon(metaclass=JSONRPCServerType): --is_spent : (bool) shows previous claim updates and abandons --account_id= : (str) id of the account to query --wallet_id= : (str) restrict results to specific wallet + --has_source : (bool) list claims containing a source field + --has_no_source : (bool) list claims not containing a source field --page= : (int) page to return during paginating --page_size= : (int) number of items on page during pagination --resolve : (bool) resolves each claim to provide additional metadata @@ -4351,6 +4353,7 @@ class Daemon(metaclass=JSONRPCServerType): claim_id=None, channel_id=None, not_channel_id=None, name=None, reposted_claim_id=None, is_spent=False, is_not_spent=False, + has_source=None, has_no_source=None, is_my_input_or_output=None, exclude_internal_transfers=False, is_my_output=None, is_not_my_output=None, is_my_input=None, is_not_my_input=None): @@ -4358,6 +4361,10 @@ class Daemon(metaclass=JSONRPCServerType): constraints['is_spent'] = True elif is_not_spent: constraints['is_spent'] = False + if has_source: + constraints['has_source'] = True + elif has_no_source: + constraints['has_source'] = False constraints['exclude_internal_transfers'] = exclude_internal_transfers if is_my_input_or_output is True: constraints['is_my_input_or_output'] = True diff --git a/lbry/wallet/database.py b/lbry/wallet/database.py index 2c5777c23..7950c0474 100644 --- a/lbry/wallet/database.py +++ b/lbry/wallet/database.py @@ -592,7 +592,7 @@ def get_and_reserve_spendable_utxos(transaction: sqlite3.Connection, accounts: L class Database(SQLiteMixin): - SCHEMA_VERSION = "1.5" + SCHEMA_VERSION = "1.6" PRAGMAS = """ pragma journal_mode=WAL; @@ -646,6 +646,7 @@ class Database(SQLiteMixin): txo_type integer not null default 0, claim_id text, claim_name text, + has_source bool, channel_id text, reposted_claim_id text @@ -690,7 +691,8 @@ class Database(SQLiteMixin): 'address': txo.get_address(self.ledger), 'position': txo.position, 'amount': txo.amount, - 'script': sqlite3.Binary(txo.script.source) + 'script': sqlite3.Binary(txo.script.source), + 'has_source': False, } if txo.is_claim: if txo.can_decode_claim: @@ -698,8 +700,11 @@ class Database(SQLiteMixin): row['txo_type'] = TXO_TYPES.get(claim.claim_type, TXO_TYPES['stream']) if claim.is_repost: row['reposted_claim_id'] = claim.repost.reference.claim_id + row['has_source'] = True if claim.is_signed: row['channel_id'] = claim.signing_channel_id + if claim.is_stream: + row['has_source'] = claim.stream.has_source else: row['txo_type'] = TXO_TYPES['stream'] elif txo.is_support: diff --git a/tests/integration/blockchain/test_claim_commands.py b/tests/integration/blockchain/test_claim_commands.py index 142dede55..014f18211 100644 --- a/tests/integration/blockchain/test_claim_commands.py +++ b/tests/integration/blockchain/test_claim_commands.py @@ -78,6 +78,17 @@ class ClaimSearchCommand(ClaimTestCase): f"(expected {claim['outputs'][0]['name']}) != (got {result['name']})" ) + async def assertListsClaims(self, claims, **kwargs): + kwargs.setdefault('order_by', 'height') + results = await self.claim_list(**kwargs) + self.assertEqual(len(claims), len(results)) + for claim, result in zip(claims, results): + self.assertEqual( + (claim['txid'], self.get_claim_id(claim)), + (result['txid'], result['claim_id']), + f"(expected {claim['outputs'][0]['name']}) != (got {result['name']})" + ) + @skip("doesnt happen on ES...?") async def test_disconnect_on_memory_error(self): claim_ids = [ @@ -186,8 +197,11 @@ class ClaimSearchCommand(ClaimTestCase): normal_repost = await self.stream_repost(self.get_claim_id(normal), 'normal-repost') no_source_repost = await self.stream_repost(self.get_claim_id(no_source), 'no-source-repost') await self.assertFindsClaims([no_source_repost, no_source, channel], has_no_source=True) + await self.assertListsClaims([no_source, channel], has_no_source=True) await self.assertFindsClaims([normal_repost, normal, channel], has_source=True) + await self.assertListsClaims([no_source_repost, normal_repost, normal], has_source=True) await self.assertFindsClaims([no_source_repost, normal_repost, normal, no_source, channel]) + await self.assertListsClaims([no_source_repost, normal_repost, normal, no_source, channel]) async def test_pagination(self): await self.create_channel()