diff --git a/lbrynet/extras/daemon/Daemon.py b/lbrynet/extras/daemon/Daemon.py index 90cd7aff4..8c5d46ef9 100644 --- a/lbrynet/extras/daemon/Daemon.py +++ b/lbrynet/extras/daemon/Daemon.py @@ -1616,7 +1616,7 @@ class Daemon(metaclass=JSONRPCServerType): return result CLAIM_DOC = """ - List, search and abandon all types of claims. + List and search all types of claims. """ @requires(WALLET_COMPONENT) @@ -1694,55 +1694,8 @@ class Daemon(metaclass=JSONRPCServerType): sort_claim_results(claims) return {"items": claims, "total_pages": 1, "page": 1, "page_size": len(claims)} - @requires(WALLET_COMPONENT, conditions=[WALLET_IS_UNLOCKED]) - async def jsonrpc_claim_abandon( - self, claim_id=None, txid=None, nout=None, account_id=None, - preview=False, blocking=True): - """ - Abandon one of my channel or stream claims. - - Usage: - claim_abandon [ | --claim_id=] - [ | --txid=] [ | --nout=] - [--account_id=] - [--preview] [--blocking] - - Options: - --claim_id= : (str) claim_id of the claim to abandon - --txid= : (str) txid of the claim to abandon - --nout= : (int) nout of the claim to abandon - --account_id= : (str) id of the account to use - --preview : (bool) do not broadcast the transaction - --blocking : (bool) wait until abandon is in mempool - """ - account = self.get_account_or_default(account_id) - - if txid is not None and nout is not None: - claims = await account.get_claims(**{'txo.txid': txid, 'txo.position': nout}) - elif claim_id is not None: - claims = await account.get_claims(claim_id=claim_id) - else: - raise Exception('Must specify claim_id, or txid and nout') - - if not claims: - raise Exception('No claim found for the specified claim_id or txid:nout') - - tx = await Transaction.create( - [Input.spend(txo) for txo in claims], [], [account], account - ) - - if not preview: - await account.ledger.broadcast(tx) - await self.analytics_manager.send_claim_action('abandon') - if blocking: - await account.ledger.wait(tx) - else: - await account.ledger.release_tx(tx) - - return tx - CHANNEL_DOC = """ - Create, update and list your channel claims. + Create, update, abandon and list your channel claims. """ @deprecated('channel_create') @@ -1977,6 +1930,53 @@ class Daemon(metaclass=JSONRPCServerType): return tx + @requires(WALLET_COMPONENT, conditions=[WALLET_IS_UNLOCKED]) + async def jsonrpc_channel_abandon( + self, claim_id=None, txid=None, nout=None, account_id=None, + preview=False, blocking=True): + """ + Abandon one of my channel claims. + + Usage: + channel_abandon [ | --claim_id=] + [ | --txid=] [ | --nout=] + [--account_id=] + [--preview] [--blocking] + + Options: + --claim_id= : (str) claim_id of the claim to abandon + --txid= : (str) txid of the claim to abandon + --nout= : (int) nout of the claim to abandon + --account_id= : (str) id of the account to use + --preview : (bool) do not broadcast the transaction + --blocking : (bool) wait until abandon is in mempool + """ + account = self.get_account_or_default(account_id) + + if txid is not None and nout is not None: + claims = await account.get_claims(**{'txo.txid': txid, 'txo.position': nout}) + elif claim_id is not None: + claims = await account.get_claims(claim_id=claim_id) + else: + raise Exception('Must specify claim_id, or txid and nout') + + if not claims: + raise Exception('No claim found for the specified claim_id or txid:nout') + + tx = await Transaction.create( + [Input.spend(txo) for txo in claims], [], [account], account + ) + + if not preview: + await account.ledger.broadcast(tx) + await self.analytics_manager.send_claim_action('abandon') + if blocking: + await account.ledger.wait(tx) + else: + await account.ledger.release_tx(tx) + + return tx + @requires(WALLET_COMPONENT) def jsonrpc_channel_list(self, account_id=None, page=None, page_size=None): """ @@ -2037,7 +2037,7 @@ class Daemon(metaclass=JSONRPCServerType): return await self.wallet_manager.import_certificate_info(serialized_certificate_info) STREAM_DOC = """ - Create, update, list and inspect your stream claims. + Create, update, abandon, list and inspect your stream claims. """ @requires(WALLET_COMPONENT, STREAM_MANAGER_COMPONENT, BLOB_COMPONENT, DATABASE_COMPONENT, @@ -2466,6 +2466,53 @@ class Daemon(metaclass=JSONRPCServerType): return tx + @requires(WALLET_COMPONENT, conditions=[WALLET_IS_UNLOCKED]) + async def jsonrpc_stream_abandon( + self, claim_id=None, txid=None, nout=None, account_id=None, + preview=False, blocking=True): + """ + Abandon one of my stream claims. + + Usage: + stream_abandon [ | --claim_id=] + [ | --txid=] [ | --nout=] + [--account_id=] + [--preview] [--blocking] + + Options: + --claim_id= : (str) claim_id of the claim to abandon + --txid= : (str) txid of the claim to abandon + --nout= : (int) nout of the claim to abandon + --account_id= : (str) id of the account to use + --preview : (bool) do not broadcast the transaction + --blocking : (bool) wait until abandon is in mempool + """ + account = self.get_account_or_default(account_id) + + if txid is not None and nout is not None: + claims = await account.get_claims(**{'txo.txid': txid, 'txo.position': nout}) + elif claim_id is not None: + claims = await account.get_claims(claim_id=claim_id) + else: + raise Exception('Must specify claim_id, or txid and nout') + + if not claims: + raise Exception('No claim found for the specified claim_id or txid:nout') + + tx = await Transaction.create( + [Input.spend(txo) for txo in claims], [], [account], account + ) + + if not preview: + await account.ledger.broadcast(tx) + await self.analytics_manager.send_claim_action('abandon') + if blocking: + await account.ledger.wait(tx) + else: + await account.ledger.release_tx(tx) + + return tx + @requires(WALLET_COMPONENT) def jsonrpc_stream_list(self, account_id=None, page=None, page_size=None): """ diff --git a/tests/integration/test_chris45.py b/tests/integration/test_chris45.py index 303979dda..048a04d28 100644 --- a/tests/integration/test_chris45.py +++ b/tests/integration/test_chris45.py @@ -81,7 +81,7 @@ class EpicAdventuresOfChris45(CommandTestCase): # After some soul searching Chris decides that his story needs more # heart and a better ending. He takes down the story and begins the rewrite. - abandon = await self.out(self.daemon.jsonrpc_claim_abandon(claim_id, blocking=False)) + abandon = await self.out(self.daemon.jsonrpc_stream_abandon(claim_id, blocking=False)) self.assertEqual(abandon['inputs'][0]['claim_id'], claim_id) await self.confirm_tx(abandon['txid']) @@ -183,7 +183,7 @@ class EpicAdventuresOfChris45(CommandTestCase): # But sadly Ramsey wasn't so pleased. It was hard for him to tell Chris... # Chris, though a bit heartbroken, abandoned the claim for now, but instantly started working on new hit lyrics - abandon = await self.out(self.daemon.jsonrpc_claim_abandon(txid=tx['txid'], nout=0, blocking=False)) + abandon = await self.out(self.daemon.jsonrpc_stream_abandon(txid=tx['txid'], nout=0, blocking=False)) self.assertTrue(abandon['inputs'][0]['txid'], tx['txid']) await self.confirm_tx(abandon['txid']) diff --git a/tests/integration/test_claim_commands.py b/tests/integration/test_claim_commands.py index 2487c8df3..a42a74999 100644 --- a/tests/integration/test_claim_commands.py +++ b/tests/integration/test_claim_commands.py @@ -379,7 +379,7 @@ class StreamCommands(CommandTestCase): self.assertEqual(txs[0]['fee'], '-0.000184') await self.assertBalance(self.account, '8.979709') - await self.claim_abandon(claim_id) + await self.stream_abandon(claim_id) txs = await self.out(self.daemon.jsonrpc_transaction_list()) self.assertEqual(len(txs[0]['abandon_info']), 1) self.assertEqual(txs[0]['abandon_info'][0]['balance_delta'], '1.0') @@ -392,7 +392,7 @@ class StreamCommands(CommandTestCase): await self.assertBalance(self.account, '10.0') tx = await self.stream_create(bid='0.0001') await self.assertBalance(self.account, '9.979793') - await self.claim_abandon(tx['outputs'][0]['claim_id']) + await self.stream_abandon(tx['outputs'][0]['claim_id']) await self.assertBalance(self.account, '9.97968399') async def test_publish(self): @@ -422,8 +422,8 @@ class StreamCommands(CommandTestCase): with self.assertRaisesRegex(Exception, "There are 2 claims for 'foo'"): await self.daemon.jsonrpc_publish('foo') - # abandon duplicate channel - await self.claim_abandon(tx3['outputs'][0]['claim_id']) + # abandon duplicate stream + await self.stream_abandon(tx3['outputs'][0]['claim_id']) # publish to a channel await self.channel_create('@abc') @@ -458,7 +458,7 @@ class StreamCommands(CommandTestCase): claims = await self.claim_search(claim_id=channel_id) self.assertEqual(claims[0]['value'], value) - await self.claim_abandon(txid=txid, nout=0) + await self.channel_abandon(txid=txid, nout=0) self.assertEqual(len(await self.claim_search(txid=txid, nout=0)), 0) # search stream claims @@ -481,9 +481,9 @@ class StreamCommands(CommandTestCase): claims = await self.claim_search(channel_id=channel_id) self.assertEqual(len(claims), 3) - await self.claim_abandon(claim_id=claims[0]['claim_id']) - await self.claim_abandon(claim_id=claims[1]['claim_id']) - await self.claim_abandon(claim_id=claims[2]['claim_id']) + await self.stream_abandon(claim_id=claims[0]['claim_id']) + await self.stream_abandon(claim_id=claims[1]['claim_id']) + await self.stream_abandon(claim_id=claims[2]['claim_id']) claims = await self.claim_search(channel_id=channel_id) self.assertEqual(len(claims), 0) @@ -518,7 +518,7 @@ class StreamCommands(CommandTestCase): async def test_abandoned_channel_with_signed_claims(self): channel = (await self.channel_create('@abc', '1.0'))['outputs'][0] orphan_claim = await self.stream_create('on-channel-claim', '0.0001', channel_id=channel['claim_id']) - await self.claim_abandon(txid=channel['txid'], nout=0) + await self.channel_abandon(txid=channel['txid'], nout=0) channel = (await self.channel_create('@abc', '1.0'))['outputs'][0] orphan_claim_id = orphan_claim['outputs'][0]['claim_id'] @@ -531,7 +531,7 @@ class StreamCommands(CommandTestCase): direct_uri = 'lbry://on-channel-claim#' + orphan_claim_id response = await self.resolve(direct_uri) self.assertFalse(response[direct_uri]['claim']['signature_is_valid']) - await self.claim_abandon(claim_id=orphan_claim_id) + await self.stream_abandon(claim_id=orphan_claim_id) uri = 'lbry://@abc/on-channel-claim' # now, claim something on this channel (it will update the invalid claim, but we save and forcefully restore) diff --git a/tests/integration/testcase.py b/tests/integration/testcase.py index e45b8357b..6663ff43f 100644 --- a/tests/integration/testcase.py +++ b/tests/integration/testcase.py @@ -186,6 +186,16 @@ class CommandTestCase(IntegrationTestCase): await self.on_transaction_dict(claim) return claim + async def stream_abandon(self, *args, confirm=True, **kwargs): + if 'blocking' not in kwargs: + kwargs['blocking'] = False + tx = await self.out(self.daemon.jsonrpc_stream_abandon(*args, **kwargs)) + if confirm: + await self.on_transaction_dict(tx) + await self.generate(1) + await self.on_transaction_dict(tx) + return tx + async def publish(self, name, *args, confirm=True, **kwargs): claim = await self.out(self.daemon.jsonrpc_publish(name, *args, **kwargs)) self.assertEqual(claim['outputs'][0]['name'], name) @@ -213,10 +223,10 @@ class CommandTestCase(IntegrationTestCase): await self.on_transaction_dict(channel) return channel - async def claim_abandon(self, *args, confirm=True, **kwargs): + async def channel_abandon(self, *args, confirm=True, **kwargs): if 'blocking' not in kwargs: kwargs['blocking'] = False - tx = await self.out(self.daemon.jsonrpc_claim_abandon(*args, **kwargs)) + tx = await self.out(self.daemon.jsonrpc_channel_abandon(*args, **kwargs)) if confirm: await self.on_transaction_dict(tx) await self.generate(1)