From 8399f2ab336bb7bc98123dec7997d9b78592667c Mon Sep 17 00:00:00 2001 From: Lex Berezhny Date: Thu, 30 Aug 2018 00:04:25 -0400 Subject: [PATCH] account management --- lbrynet/daemon/Daemon.py | 92 +++++++++++++---------- lbrynet/wallet/account.py | 6 ++ tests/integration/wallet/test_commands.py | 42 +++++++++++ 3 files changed, 99 insertions(+), 41 deletions(-) diff --git a/lbrynet/daemon/Daemon.py b/lbrynet/daemon/Daemon.py index d5667ecd7..4d6081e97 100644 --- a/lbrynet/daemon/Daemon.py +++ b/lbrynet/daemon/Daemon.py @@ -1118,47 +1118,50 @@ class Daemon(AuthJSONRPCServer): ) @requires("wallet") - def jsonrpc_account_list(self, account_name=None, confirmations=6, include_reserved=False, - include_claims=False): + def jsonrpc_account_list(self, account_id=None, confirmations=6, include_reserved=False, + include_claims=False, show_seed=False): """ - Return details of an individual account or all of the accounts. + List details of all of the accounts or a specific account. Usage: - account_list [] [--confirmations=] - [--include_reserved] [--include_claims] + account_list [] [--confirmations=] + [--include_reserved] [--include_claims] [--show_seed] Options: - --account= : (str) If provided only the balance for this + --account= : (str) If provided only the balance for this account will be given --confirmations= : (int) required confirmations (default: 6) --include_reserved : (bool) include reserved UTXOs (default: false) --include_claims : (bool) include claims, requires than a LBC account is specified (default: false) + --show_seed : (bool) show the seed for the account Returns: (map) balance of account(s) """ - if account_name: + if account_id: for account in self.wallet_manager.accounts: - if account.name == account_name: + if account.id == account_id: if include_claims and not isinstance(account, LBCAccount): raise Exception( "'--include-claims' requires specifying an LBC ledger account. " "Found '{}', but it's an {} ledger account." - .format(account_name, account.ledger.symbol) + .format(account_id, account.ledger.symbol) ) args = { 'confirmations': confirmations, - 'include_reserved': include_reserved + 'include_reserved': include_reserved, + 'include_seed': show_seed } if include_claims: args['include_claims'] = True - return account.get_balance(**args) - raise Exception("Couldn't find an account named: '{}'.".format(account_name)) + return account.get_details(**args) + raise Exception("Couldn't find an account: '{}'.".format(account_id)) else: if include_claims: - raise Exception("'--include-claims' requires specifying an LBC account.") - return self.wallet_manager.get_balances(confirmations) + raise Exception("'--include-claims' requires specifying an LBC account by id.") + return self.wallet_manager.get_detailed_accounts( + confirmations=confirmations, show_seed=show_seed) @requires("wallet") @defer.inlineCallbacks @@ -1182,9 +1185,10 @@ class Daemon(AuthJSONRPCServer): dewies = yield self.default_account.get_balance( 0 if include_unconfirmed else 6 ) - defer.returnValue(round(dewies / COIN, 3)) + return round(dewies / COIN, 3) @requires("wallet") + @defer.inlineCallbacks def jsonrpc_account_add( self, account_name, single_key=False, seed=None, private_key=None, public_key=None): """ @@ -1207,10 +1211,8 @@ class Daemon(AuthJSONRPCServer): (map) added account details """ - self.error_if_account_exists(account_name) account = LBCAccount.from_dict( - self.wallet_manager.get_or_create_ledger('lbc_mainnet'), - self.default_wallet, { + self.ledger, self.default_wallet, { 'name': account_name, 'seed': seed, 'private_key': private_key, @@ -1220,6 +1222,10 @@ class Daemon(AuthJSONRPCServer): } } ) + + if self.ledger.network.is_connected: + yield self.ledger.update_account(account) + self.default_wallet.save() result = account.to_dict() @@ -1229,6 +1235,7 @@ class Daemon(AuthJSONRPCServer): return result @requires("wallet") + @defer.inlineCallbacks def jsonrpc_account_create(self, account_name, single_key=False): """ Create a new account. Specify --single_key if you want to use @@ -1245,13 +1252,15 @@ class Daemon(AuthJSONRPCServer): (map) new account details """ - self.error_if_account_exists(account_name) account = LBCAccount.generate( - self.wallet_manager.get_or_create_ledger('lbc_mainnet'), - self.default_wallet, account_name, { + self.ledger, self.default_wallet, account_name, { 'name': SingleKey.name if single_key else HierarchicalDeterministic.name } ) + + if self.ledger.network.is_connected: + yield self.ledger.update_account(account) + self.default_wallet.save() result = account.to_dict() @@ -1261,21 +1270,21 @@ class Daemon(AuthJSONRPCServer): return result @requires("wallet") - def jsonrpc_account_remove(self, account_name): + def jsonrpc_account_remove(self, account_id): """ Remove an existing account. Usage: - account ( | --account_name=) + account ( | --account_id=) Options: - --account_name= : (str) name of the account to remove + --account_id= : (str) id of the account to remove Returns: - (map) removed account details + (map) details of removed account """ - account = self.get_account_or_error('account_name', account_name) + account = self.get_account_or_error('account_id', account_id) self.default_wallet.accounts.remove(account) self.default_wallet.save() result = account.to_dict() @@ -1285,19 +1294,21 @@ class Daemon(AuthJSONRPCServer): @requires("wallet") def jsonrpc_account_set( - self, account_name, default=False, + self, account_id, default=False, new_name=None, change_gap=None, change_max_uses=None, receiving_gap=None, receiving_max_uses=None): """ Change various settings on an account. Usage: - account ( | --account_name=) [--default] - [--change_gap=] [--change_max_uses=] - [--receiving_gap=] [--receiving_max_uses=] + account ( | --account_id=) + [--default] [--new_name=] + [--change_gap=] [--change_max_uses=] + [--receiving_gap=] [--receiving_max_uses=] Options: - --account_name= : (str) name of the account to change + --account_id= : (str) id of the account to change --default : (bool) make this account the default + --new_name= : (str) new name for the account --receiving_gap= : (int) set the gap for receiving addresses --receiving_max_uses= : (int) set the maximum number of times to use a receiving address @@ -1309,7 +1320,7 @@ class Daemon(AuthJSONRPCServer): (map) updated account details """ - account = self.get_account_or_error('account_name', account_name) + account = self.get_account_or_error('account_id', account_id) change_made = False if account.receiving.name == HierarchicalDeterministic.name: @@ -1324,6 +1335,10 @@ class Daemon(AuthJSONRPCServer): setattr(chain, attr, value) change_made = True + if new_name is not None: + account.name = new_name + change_made = True + if default: self.default_wallet.accounts.remove(account) self.default_wallet.accounts.insert(0, account) @@ -3273,22 +3288,17 @@ class Daemon(AuthJSONRPCServer): response['head_blob_availability'].get('is_available') defer.returnValue(response) - def get_account_or_error(self, argument: str, account_name: str, lbc_only=True): + def get_account_or_error(self, argument: str, account_id: str, lbc_only=True): for account in self.default_wallet.accounts: - if account.name == account_name: + if account.id == account_id: if lbc_only and not isinstance(account, LBCAccount): raise ValueError( "Found '{}', but it's an {} ledger account. " "'{}' requires specifying an LBC ledger account." - .format(account_name, account.ledger.symbol, argument) + .format(account_id, account.ledger.symbol, argument) ) return account - raise ValueError("Couldn't find an account named: '{}'.".format(account_name)) - - def error_if_account_exists(self, account_name: str): - for account in self.default_wallet.accounts: - if account.name == account_name: - raise ValueError("Account with name '{}' already exists.".format(account_name)) + raise ValueError("Couldn't find account: {}.".format(account_id)) @staticmethod def get_dewies_or_error(argument: str, amount: Union[str, int, float]): diff --git a/lbrynet/wallet/account.py b/lbrynet/wallet/account.py index b401e5532..89a8e90e2 100644 --- a/lbrynet/wallet/account.py +++ b/lbrynet/wallet/account.py @@ -160,5 +160,11 @@ class Account(BaseAccount): d['certificates'] = self.certificates return d + @defer.inlineCallbacks + def get_details(self, **kwargs): + details = yield super().get_details(**kwargs) + details['certificates'] = len(self.certificates) + return details + def get_claim(self, claim_id): return self.ledger.db.get_claim(self, claim_id) diff --git a/tests/integration/wallet/test_commands.py b/tests/integration/wallet/test_commands.py index f83758f7a..c02dbe78b 100644 --- a/tests/integration/wallet/test_commands.py +++ b/tests/integration/wallet/test_commands.py @@ -298,3 +298,45 @@ class EpicAdventuresOfChris45(CommandTestCase): # And now check that the claim doesn't resolve anymore. response = yield self.out(self.daemon.jsonrpc_resolve(uri='lbry://@spam/hovercraft')) self.assertNotIn('claim', response['lbry://@spam/hovercraft']) + + +class AccountManagement(CommandTestCase): + + VERBOSE = False + + @defer.inlineCallbacks + def test_performing_account_management_commands(self): + # check initial account + response = yield self.daemon.jsonrpc_account_list() + self.assertEqual(len(response['lbc_regtest']), 1) + + # change account name + account_id = response['lbc_regtest'][0]['id'] + yield self.daemon.jsonrpc_account_set(account_id=account_id, new_name='test account') + response = yield self.daemon.jsonrpc_account_list() + self.assertEqual(response['lbc_regtest'][0]['name'], 'test account') + + # create another account + yield self.daemon.jsonrpc_account_create('second account') + response = yield self.daemon.jsonrpc_account_list() + self.assertEqual(len(response['lbc_regtest']), 2) + self.assertEqual(response['lbc_regtest'][1]['name'], 'second account') + account_id2 = response['lbc_regtest'][1]['id'] + + # make new account the default + self.daemon.jsonrpc_account_set(account_id=account_id2, default=True) + response = yield self.daemon.jsonrpc_account_list(show_seed=True) + self.assertEqual(response['lbc_regtest'][0]['name'], 'second account') + + account_seed = response['lbc_regtest'][1]['seed'] + + # remove account + yield self.daemon.jsonrpc_account_remove(response['lbc_regtest'][1]['id']) + response = yield self.daemon.jsonrpc_account_list() + self.assertEqual(len(response['lbc_regtest']), 1) + + # add account + yield self.daemon.jsonrpc_account_add('recreated account', seed=account_seed) + response = yield self.daemon.jsonrpc_account_list() + self.assertEqual(len(response['lbc_regtest']), 2) + self.assertEqual(response['lbc_regtest'][1]['name'], 'recreated account')