docs: 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