account management

This commit is contained in:
Lex Berezhny 2018-08-30 00:04:25 -04:00
parent 7698ab7053
commit 8399f2ab33
3 changed files with 99 additions and 41 deletions

View file

@ -1118,47 +1118,50 @@ class Daemon(AuthJSONRPCServer):
) )
@requires("wallet") @requires("wallet")
def jsonrpc_account_list(self, account_name=None, confirmations=6, include_reserved=False, def jsonrpc_account_list(self, account_id=None, confirmations=6, include_reserved=False,
include_claims=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: Usage:
account_list [<account_name>] [--confirmations=<confirmations>] account_list [<account_id>] [--confirmations=<confirmations>]
[--include_reserved] [--include_claims] [--include_reserved] [--include_claims] [--show_seed]
Options: Options:
--account=<account_name> : (str) If provided only the balance for this --account=<account_id> : (str) If provided only the balance for this
account will be given account will be given
--confirmations=<confirmations> : (int) required confirmations (default: 6) --confirmations=<confirmations> : (int) required confirmations (default: 6)
--include_reserved : (bool) include reserved UTXOs (default: false) --include_reserved : (bool) include reserved UTXOs (default: false)
--include_claims : (bool) include claims, requires than a --include_claims : (bool) include claims, requires than a
LBC account is specified (default: false) LBC account is specified (default: false)
--show_seed : (bool) show the seed for the account
Returns: Returns:
(map) balance of account(s) (map) balance of account(s)
""" """
if account_name: if account_id:
for account in self.wallet_manager.accounts: 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): if include_claims and not isinstance(account, LBCAccount):
raise Exception( raise Exception(
"'--include-claims' requires specifying an LBC ledger account. " "'--include-claims' requires specifying an LBC ledger account. "
"Found '{}', but it's an {} ledger account." "Found '{}', but it's an {} ledger account."
.format(account_name, account.ledger.symbol) .format(account_id, account.ledger.symbol)
) )
args = { args = {
'confirmations': confirmations, 'confirmations': confirmations,
'include_reserved': include_reserved 'include_reserved': include_reserved,
'include_seed': show_seed
} }
if include_claims: if include_claims:
args['include_claims'] = True args['include_claims'] = True
return account.get_balance(**args) return account.get_details(**args)
raise Exception("Couldn't find an account named: '{}'.".format(account_name)) raise Exception("Couldn't find an account: '{}'.".format(account_id))
else: else:
if include_claims: if include_claims:
raise Exception("'--include-claims' requires specifying an LBC account.") raise Exception("'--include-claims' requires specifying an LBC account by id.")
return self.wallet_manager.get_balances(confirmations) return self.wallet_manager.get_detailed_accounts(
confirmations=confirmations, show_seed=show_seed)
@requires("wallet") @requires("wallet")
@defer.inlineCallbacks @defer.inlineCallbacks
@ -1182,9 +1185,10 @@ class Daemon(AuthJSONRPCServer):
dewies = yield self.default_account.get_balance( dewies = yield self.default_account.get_balance(
0 if include_unconfirmed else 6 0 if include_unconfirmed else 6
) )
defer.returnValue(round(dewies / COIN, 3)) return round(dewies / COIN, 3)
@requires("wallet") @requires("wallet")
@defer.inlineCallbacks
def jsonrpc_account_add( def jsonrpc_account_add(
self, account_name, single_key=False, seed=None, private_key=None, public_key=None): 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 (map) added account details
""" """
self.error_if_account_exists(account_name)
account = LBCAccount.from_dict( account = LBCAccount.from_dict(
self.wallet_manager.get_or_create_ledger('lbc_mainnet'), self.ledger, self.default_wallet, {
self.default_wallet, {
'name': account_name, 'name': account_name,
'seed': seed, 'seed': seed,
'private_key': private_key, '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() self.default_wallet.save()
result = account.to_dict() result = account.to_dict()
@ -1229,6 +1235,7 @@ class Daemon(AuthJSONRPCServer):
return result return result
@requires("wallet") @requires("wallet")
@defer.inlineCallbacks
def jsonrpc_account_create(self, account_name, single_key=False): def jsonrpc_account_create(self, account_name, single_key=False):
""" """
Create a new account. Specify --single_key if you want to use Create a new account. Specify --single_key if you want to use
@ -1245,13 +1252,15 @@ class Daemon(AuthJSONRPCServer):
(map) new account details (map) new account details
""" """
self.error_if_account_exists(account_name)
account = LBCAccount.generate( account = LBCAccount.generate(
self.wallet_manager.get_or_create_ledger('lbc_mainnet'), self.ledger, self.default_wallet, account_name, {
self.default_wallet, account_name, {
'name': SingleKey.name if single_key else HierarchicalDeterministic.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() self.default_wallet.save()
result = account.to_dict() result = account.to_dict()
@ -1261,21 +1270,21 @@ class Daemon(AuthJSONRPCServer):
return result return result
@requires("wallet") @requires("wallet")
def jsonrpc_account_remove(self, account_name): def jsonrpc_account_remove(self, account_id):
""" """
Remove an existing account. Remove an existing account.
Usage: Usage:
account (<account_name> | --account_name=<account_name>) account (<account_id> | --account_id=<account_id>)
Options: Options:
--account_name=<account_name> : (str) name of the account to remove --account_id=<account_id> : (str) id of the account to remove
Returns: 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.accounts.remove(account)
self.default_wallet.save() self.default_wallet.save()
result = account.to_dict() result = account.to_dict()
@ -1285,19 +1294,21 @@ class Daemon(AuthJSONRPCServer):
@requires("wallet") @requires("wallet")
def jsonrpc_account_set( 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_gap=None, change_max_uses=None, receiving_gap=None, receiving_max_uses=None):
""" """
Change various settings on an account. Change various settings on an account.
Usage: Usage:
account (<account_name> | --account_name=<account_name>) [--default] account (<account_id> | --account_id=<account_id>)
[--change_gap=<change_gap>] [--change_max_uses=<change_max_uses>] [--default] [--new_name=<new_name>]
[--receiving_gap=<receiving_gap>] [--receiving_max_uses=<receiving_max_uses>] [--change_gap=<change_gap>] [--change_max_uses=<change_max_uses>]
[--receiving_gap=<receiving_gap>] [--receiving_max_uses=<receiving_max_uses>]
Options: Options:
--account_name=<account_name> : (str) name of the account to change --account_id=<account_id> : (str) id of the account to change
--default : (bool) make this account the default --default : (bool) make this account the default
--new_name=<new_name> : (str) new name for the account
--receiving_gap=<receiving_gap> : (int) set the gap for receiving addresses --receiving_gap=<receiving_gap> : (int) set the gap for receiving addresses
--receiving_max_uses=<receiving_max_uses> : (int) set the maximum number of times to --receiving_max_uses=<receiving_max_uses> : (int) set the maximum number of times to
use a receiving address use a receiving address
@ -1309,7 +1320,7 @@ class Daemon(AuthJSONRPCServer):
(map) updated account details (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 change_made = False
if account.receiving.name == HierarchicalDeterministic.name: if account.receiving.name == HierarchicalDeterministic.name:
@ -1324,6 +1335,10 @@ class Daemon(AuthJSONRPCServer):
setattr(chain, attr, value) setattr(chain, attr, value)
change_made = True change_made = True
if new_name is not None:
account.name = new_name
change_made = True
if default: if default:
self.default_wallet.accounts.remove(account) self.default_wallet.accounts.remove(account)
self.default_wallet.accounts.insert(0, account) self.default_wallet.accounts.insert(0, account)
@ -3273,22 +3288,17 @@ class Daemon(AuthJSONRPCServer):
response['head_blob_availability'].get('is_available') response['head_blob_availability'].get('is_available')
defer.returnValue(response) 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: 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): if lbc_only and not isinstance(account, LBCAccount):
raise ValueError( raise ValueError(
"Found '{}', but it's an {} ledger account. " "Found '{}', but it's an {} ledger account. "
"'{}' requires specifying an LBC ledger account." "'{}' requires specifying an LBC ledger account."
.format(account_name, account.ledger.symbol, argument) .format(account_id, account.ledger.symbol, argument)
) )
return account return account
raise ValueError("Couldn't find an account named: '{}'.".format(account_name)) raise ValueError("Couldn't find account: {}.".format(account_id))
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))
@staticmethod @staticmethod
def get_dewies_or_error(argument: str, amount: Union[str, int, float]): def get_dewies_or_error(argument: str, amount: Union[str, int, float]):

View file

@ -160,5 +160,11 @@ class Account(BaseAccount):
d['certificates'] = self.certificates d['certificates'] = self.certificates
return d 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): def get_claim(self, claim_id):
return self.ledger.db.get_claim(self, claim_id) return self.ledger.db.get_claim(self, claim_id)

View file

@ -298,3 +298,45 @@ class EpicAdventuresOfChris45(CommandTestCase):
# And now check that the claim doesn't resolve anymore. # And now check that the claim doesn't resolve anymore.
response = yield self.out(self.daemon.jsonrpc_resolve(uri='lbry://@spam/hovercraft')) response = yield self.out(self.daemon.jsonrpc_resolve(uri='lbry://@spam/hovercraft'))
self.assertNotIn('claim', response['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')