def test_rename(self): with TemporaryPocketBookRoot() as ctx: entity = Entity() key_store = KeyStore(root=ctx.root) key_store.add_key('sample', SUPER_SECURE_PASSWORD, entity) self.assertTrue(key_store.rename_key('sample', 'sample2')) self.assertIn('sample2', key_store.list_keys()) self.assertNotIn('sample', key_store.list_keys())
def test_loading_of_multiple_stores(self): with TemporaryPocketBookRoot() as ctx: entity = Entity() key_store1 = KeyStore(root=ctx.root) key_store1.add_key('sample', SUPER_SECURE_PASSWORD, entity) key_store2 = KeyStore(root=ctx.root) self.assertEqual(set(key_store2.list_keys()), set(key_store1.list_keys()))
def run_create(args): from getpass import getpass from fetchai.ledger.crypto import Entity from pocketbook.key_store import KeyStore key_store = KeyStore() existing_keys = set(key_store.list_keys()) # get the name for the new key while True: name = input('Enter name for key: ') if name in existing_keys: print('Key name already exists') continue break # prompt the user for the password while True: password = getpass('Enter password for key...: ') if not Entity.is_strong_password(password): print('Password too simple, try again') continue confirm = getpass('Confirm password for key.: ') if password != confirm: print('Passwords did not match, try again') continue break key_store.add_key(name, password, Entity())
def test_add_key(self): with TemporaryPocketBookRoot() as ctx: key_store = KeyStore(root=ctx.root) # create an entity and add it to the store entity = Entity() key_store.add_key('sample', SUPER_SECURE_PASSWORD, entity) self.assertEqual(len(key_store.list_keys()), 1)
def run_rename(args): from pocketbook.address_book import AddressBook from pocketbook.key_store import KeyStore address_book = AddressBook() key_store = KeyStore() # make sure that the new name is not present either as a key, or as an address new_present = args.new in address_book.keys( ) or args.new in key_store.list_keys() if new_present: print( '{} is already present, please choose a different destination name' .format(args.new)) return 1 # check the old address or key name old_is_address = args.old in address_book.keys() old_is_key = args.old in key_store.list_keys() success = False if old_is_address and old_is_key: raise RuntimeError( 'Data store corrupting, key looks like an address + key') elif old_is_address: success = address_book.rename(args.old, args.new) elif old_is_key: success = key_store.rename_key(args.old, args.new) else: print( '{} doesn\'t appear to be a valid key or address name, please check and try again' .format(args.old)) return 1 if not success: print('Failed to rename {} to {}'.format(args.old, args.new)) return 1 return 0
def run_delete(args): from pocketbook.key_store import KeyStore from pocketbook.address_book import AddressBook key_store = KeyStore() address_book = AddressBook() is_key = args.name in key_store.list_keys() is_address = args.name in address_book.keys() def address_delete(): return address_book.remove(args.name) def key_delete(): return key_store.remove_key(args.name) if is_key and is_address: raise RuntimeError('Corrected database, account is both an address and a key') elif is_key: warning = True handler = key_delete elif is_address: warning = False handler = address_delete else: print('Unknown key or address: {}. Please check and try again'.format(args.name)) return 1 # double check that the user really want to remove the key if warning: input_address = input(KEY_WARNING_TEMPLATE.format(args.name)) address = key_store.lookup_address(args.name) if str(address) != input_address: print('The input address for key {} does not match. Please double check and try again') return 1 # perform the removal if not handler(): print('Failed to remove the specified key or address') return 1 return 0
def run_transfer(args): from getpass import getpass from fetchai.ledger.crypto import Address from fetchai.ledger.api.token import TokenTxFactory from pocketbook.address_book import AddressBook from pocketbook.key_store import KeyStore from pocketbook.utils import create_api, from_canonical, token_amount address_book = AddressBook() key_store = KeyStore() # choose the destination destination_name = '{}:'.format(args.destination) if args.destination in address_book.keys(): destination = address_book.lookup_address(args.destination) else: destination = key_store.lookup_address(args.destination) if destination is None: destination = Address(args.destination) destination_name = '' # convert the amount amount = args.amount charge_rate = args.charge_rate computed_amount = from_canonical(amount) # check all the signers make sense for signer in args.signers: if signer not in key_store.list_keys(): raise RuntimeError('Unknown key: {}'.format(signer)) # determine the from account from_address_name = None if len(args.signers) == 1 and args.from_address is None: from_address_name = args.signers[0] elif len(args.signers) >= 1 and args.from_address is not None: present = args.from_address in key_store.list_keys() or args.from_address in address_book.keys() from_address_name = args.from_address if not present: raise RuntimeError('Unknown from address: {}'.format(args.from_address)) else: raise RuntimeError('Unable to determine from account') required_ops = len(args.signers) fee = required_ops * charge_rate computed_fee = from_canonical(fee) computed_total = computed_amount + computed_fee computed_charge_rate = from_canonical(charge_rate) print('Network....:', args.network) print('From.......:', str(from_address_name)) print('Signer(s)..:', ','.join(args.signers)) print('Destination:', destination_name, str(destination)) print('Amount.....:', token_amount(computed_amount)) print('Fee........:', token_amount(computed_fee)) # only display extended fee information if something other than the default it selected if charge_rate != 1: print(' : {} ops @ {}'.format(required_ops, token_amount(computed_charge_rate))) print('Total......:', token_amount(computed_total), '(Amount + Fee)') print() input('Press enter to continue') api = create_api(args.network) # start unsealing the private keys entities = {} for signer in args.signers: entity = key_store.load_key(signer, getpass('Enter password for key {}: '.format(signer))) entities[signer] = entity from_address = None if from_address_name in entities: from_address = Address(entities[from_address_name]) elif from_address_name in address_book.keys(): from_address = Address(address_book.lookup_address(from_address_name)) # cache the signers signers = list(entities.values()) # build up the basic transaction information tx = TokenTxFactory.transfer(Address(from_address), destination, amount, 0, signers) tx.charge_rate = charge_rate tx.charge_limit = required_ops api.set_validity_period(tx) for entity in signers: tx.sign(entity) tx_digest = api.submit_signed_tx(tx) print('TX: 0x{} submitted'.format(tx_digest)) # submit the transaction print('Waiting for transaction to be confirmed...') api.sync(tx_digest) print('Waiting for transaction to be confirmed...complete') # determine if there is a block explorer link to be printed explorer_link = None if args.network == 'mainnet': explorer_link = 'https://explore.fetch.ai/transactions/0x{}'.format(tx_digest) elif args.network == 'testnet': explorer_link = 'https://explore-testnet.fetch.ai/transactions/0x{}'.format(tx_digest) if explorer_link is not None: print() print('See {} for more details'.format(explorer_link))
def test_init(self): with TemporaryPocketBookRoot() as ctx: key_store = KeyStore(root=ctx.root) self.assertEqual(len(key_store.list_keys()), 0)
def run_list(args): from pocketbook.address_book import AddressBook from pocketbook.key_store import KeyStore from pocketbook.table import Table from pocketbook.utils import create_api, get_balance, get_stake, token_amount # the latest version of SDK will generate warning because we are using the staking API warnings.simplefilter('ignore') address_book = AddressBook() key_store = KeyStore() keys = key_store.list_keys() if len(keys) == 0: print('No keys present') else: # select the columns cols = ['name', 'type', 'balance', 'stake'] if args.verbose: cols.append('address') api = create_api(args.network) table = Table(cols) for key in keys: if not _should_display(key, args.pattern): continue address = key_store.lookup_address(key) balance = get_balance(api, address) stake = get_stake(api, address) row_data = { 'name': key, 'type': 'key', 'balance': token_amount(balance), 'stake': token_amount(stake), 'address': str(address), } table.add_row(**row_data) for name, address in address_book.items(): if not _should_display(name, args.pattern): continue balance = get_balance(api, address) stake = get_stake(api, address) row_data = { 'name': name, 'type': 'addr', 'balance': token_amount(balance), 'stake': token_amount(stake), 'address': str(address), } table.add_row(**row_data) table.display()