async def create(self, seed: str) -> 'Wallet': """ Create wallet as configured and store DID. Raise ExtantWallet if wallet already exists on current name. :param seed: seed :return: current object """ LOGGER.debug('Wallet.create >>> seed: [SEED]') try: await wallet.create_wallet( config=json.dumps(self.config), credentials=json.dumps(self.access_creds or Wallet.DEFAULT_ACCESS_CREDS)) LOGGER.info('Created wallet %s', self.name) except IndyError as x_indy: if x_indy.error_code == ErrorCode.WalletAlreadyExistsError: LOGGER.info('Wallet %s already exists', self.name) raise ExtantWallet('Wallet {} already exists'.format( self.name)) else: LOGGER.debug( 'Wallet.create <!< indy error code %s on creation of wallet %s', x_indy.error_code, self.name) raise self._handle = await wallet.open_wallet( json.dumps(self.config), json.dumps(self.access_creds or Wallet.DEFAULT_ACCESS_CREDS)) LOGGER.info('Opened wallet %s on handle %s', self.name, self.handle) try: (self._did, self.verkey) = await did.create_and_store_my_did( self.handle, json.dumps({'seed': seed})) LOGGER.debug('Wallet %s stored new DID %s, verkey %s from seed', self.name, self.did, self.verkey) await did.set_did_metadata( self.handle, self.did, json.dumps({ 'anchor': True, 'since': int(time()) })) LOGGER.info('Wallet %s set seed hash metadata for DID %s', self.name, self.did) finally: await wallet.close_wallet( self.handle) # bypass self.close() in case auto-remove set self._handle = None LOGGER.debug('Wallet.create <<<') return self
async def create(self, config: dict = None, access: str = None, replace: bool = False) -> Wallet: """ Create wallet on input name with given configuration and access credential value. Raise ExtantWallet if wallet on input name exists already and replace parameter is False. Raise BadAccess on replacement for bad access credentials value. FAIR WARNING: specifying replace=True attempts to remove any matching wallet before proceeding; to succeed, the existing wallet must use the same access credentials that the input configuration has. :param config: configuration data for both indy-sdk and VON anchor wallet: - 'name' or 'id': wallet name - 'storage_type': storage type - 'freshness_time': freshness time - 'did': (optional) DID to use - 'seed': (optional) seed to use - 'auto_create': whether to create the wallet on first open (persists past close, can work with auto_remove) - 'auto_remove': whether to remove the wallet on next close - 'link_secret_label': (optional) link secret label to use to create link secret :param access: indy wallet access credential ('key') value, if different than default :param replace: whether to replace old wallet if it exists :return: wallet created """ LOGGER.debug( 'WalletManager.create >>> config %s, access %s, replace %s', config, access, replace) assert {'name', 'id'} & {k for k in config} wallet_name = config.get('name', config.get('id')) if replace: von_wallet = self.get(config, access) if not await von_wallet.remove(): LOGGER.debug( 'WalletManager.create <!< Failed to remove wallet %s for replacement', wallet_name) raise ExtantWallet( 'Failed to remove wallet {} for replacement'.format( wallet_name)) indy_config = self._config2indy(config) von_config = self._config2von(config, access) rv = Wallet(indy_config, von_config) await rv.create() LOGGER.debug('WalletManager.create <<< %s', rv) return rv
async def create(self) -> None: """ Persist the wallet. Raise ExtantWallet if it already exists. Actuators should prefer WalletManager.create() to calling this method directly - the wallet manager filters wallet configuration through preset defaults. """ LOGGER.debug('Wallet.create >>>') try: await wallet.create_wallet( config=json.dumps(self.config), credentials=json.dumps(self.access_creds)) LOGGER.info('Created wallet %s', self.name) except IndyError as x_indy: if x_indy.error_code == ErrorCode.WalletAlreadyExistsError: LOGGER.debug('Wallet.create <!< Wallet %s already exists', self.name) raise ExtantWallet('Wallet {} already exists'.format(self.name)) LOGGER.debug( 'Wallet.create <!< indy error code %s on creation of wallet %s', x_indy.error_code, self.name) raise auto_remove = self.auto_remove self.auto_remove = False # defer past this creation process async with self: did_info = await self.create_local_did( self._von_config.get('seed', None), self._von_config.get('did', None), {'anchor': True}) self.did = did_info.did self.verkey = did_info.verkey if 'link_secret_label' in self._von_config: await self.create_link_secret(self._von_config['link_secret_label']) self.auto_remove = auto_remove LOGGER.debug('Wallet.create <<<')
async def setnym(ini_path: str) -> int: """ Set configuration. Open pool, trustee anchor, and wallet of anchor whose nym to send. Register exit hooks to close pool and trustee anchor. Engage trustee anchor to send nym for VON anchor, if it differs on the ledger from configuration. :param ini_path: path to configuration file :return: 0 for OK, 1 for failure """ config = inis2dict(ini_path) if config['Trustee Anchor']['name'] == config['VON Anchor']['name']: raise ExtantWallet( 'Wallet names must differ between VON Anchor and Trustee Anchor') cfg_van_role = config['VON Anchor'].get( 'role', None) or None # nudge empty value from '' to None if not ok_role(cfg_van_role): raise BadRole('Configured role {} is not valid'.format(cfg_van_role)) pool_data = NodePoolData( config['Node Pool']['name'], config['Node Pool'].get('genesis.txn.path', None) or None) an_data = { 'tan': AnchorData( Role.TRUSTEE, config['Trustee Anchor']['name'], config['Trustee Anchor'].get('seed', None) or None, config['Trustee Anchor'].get('did', None) or None, config['Trustee Anchor'].get('wallet.create', '0').lower() in ['1', 'true', 'yes'], config['Trustee Anchor'].get('wallet.type', None) or None, config['Trustee Anchor'].get('wallet.access', None) or None), 'van': AnchorData( Role.get(cfg_van_role), config['VON Anchor']['name'], config['VON Anchor'].get('seed', None) or None, config['VON Anchor'].get('did', None) or None, config['VON Anchor'].get('wallet.create', '0').lower() in ['1', 'true', 'yes'], config['VON Anchor'].get('wallet.type', None) or None, config['VON Anchor'].get('wallet.access', None) or None) } an_wallet = await _set_wallets(an_data) p_mgr = NodePoolManager() if pool_data.name not in await p_mgr.list(): if pool_data.genesis_txn_path: await p_mgr.add_config(pool_data.name, pool_data.genesis_txn_path) else: raise AbsentPool( 'Node pool {} has no ledger configuration, but {} specifies no genesis txn path' .format(pool_data.name, ini_path)) async with an_wallet['tan'] as w_tan, (an_wallet['van']) as w_van, ( p_mgr.get(pool_data.name)) as pool, (TrusteeAnchor( w_tan, pool)) as tan, (NominalAnchor(w_van, pool)) as van: send_verkey = van.verkey try: nym_role = await tan.get_nym_role(van.did) if an_data['van'].role == nym_role: return 0 # ledger is as per configuration send_verkey = None # only owner can touch verkey if nym_role != Role.USER: # only remove role when it is not already None on the ledger await tan.send_nym(van.did, send_verkey, van.wallet.name, Role.ROLE_REMOVE) except AbsentNym: pass # cryptonym not there yet, fall through await tan.send_nym(van.did, send_verkey, van.wallet.name, an_data['van'].role) return 0
async def setnym(ini_path: str) -> int: """ Set configuration. Open pool, trustee anchor, and wallet of anchor whose nym to send. Register exit hooks to close pool and trustee anchor. Engage trustee anchor to send nym for VON anchor, if it differs on the ledger from configuration. :param ini_path: path to configuration file :return: 0 for OK, 1 for failure """ config = inis2dict(ini_path) cfg_van_role = config['VON Anchor'].get( 'role', None) or None # nudge empty value from '' to None if not ok_role(cfg_van_role): raise BadRole('Configured role {} is not valid'.format(cfg_van_role)) if config['Trustee Anchor']['wallet.name'] == config['VON Anchor'][ 'wallet.name']: raise ExtantWallet( 'Wallet names must differ between VON Anchor and Trustee Anchor') pool_data = NodePoolData( config['Node Pool']['name'], config['Node Pool'].get('genesis.txn.path', None) or None) an_data = { 'tan': AnchorData(Role.TRUSTEE, config['Trustee Anchor'].get('seed', None) or None, config['Trustee Anchor']['wallet.name'], config['Trustee Anchor'].get('wallet.type', None) or None, config['Trustee Anchor'].get('wallet.key', None) or None), 'van': AnchorData(Role.get(cfg_van_role), config['VON Anchor'].get('seed', None) or None, config['VON Anchor']['wallet.name'], config['VON Anchor'].get('wallet.type', None) or None, config['VON Anchor'].get('wallet.key', None) or None) } an_wallet = { an: Wallet(an_data[an].wallet_name, an_data[an].wallet_type, None, {'key': an_data[an].wallet_key} if an_data[an].wallet_key else None) for an in an_data } for anchor in an_data: # create wallet if seed configured, silently continue if extant if an_data[anchor].seed: try: await an_wallet[anchor].create(an_data[anchor].seed) except ExtantWallet: pass manager = NodePoolManager() if pool_data.name not in await manager.list(): if pool_data.genesis_txn_path: await manager.add_config(pool_data.name, pool_data.genesis_txn_path) else: raise AbsentPool( 'Node pool {} has no ledger configuration, but {} specifies no genesis txn path' .format(pool_data.name, ini_path)) async with an_wallet['tan'] as w_tan, (an_wallet['van']) as w_van, ( manager.get(pool_data.name)) as pool, (TrusteeAnchor( w_tan, pool)) as tan, (NominalAnchor(w_van, pool)) as van: send_verkey = van.verkey try: nym_role = await tan.get_nym_role(van.did) if an_data['van'].role == nym_role: return 0 # ledger is as per configuration send_verkey = None # only owner can touch verkey await tan.send_nym(van.did, send_verkey, van.wallet.name, Role.ROLE_REMOVE) except AbsentNym: pass # cryptonym not there yet, fall through await tan.send_nym(van.did, send_verkey, van.wallet.name, an_data['van'].role) return 0