Initialize and setup the contract proxies.

    Depending on the provided contract addresses via the CLI, the routing mode,
    the environment type and the network id try to initialize the proxies.
    Returns the initialized proxies or exits the application with an error if
    there is a problem.

    Also depending on the given arguments populate config with PFS related settings

def setup_proxies_or_exit(
        config: Dict[str, Any],
        tokennetwork_registry_contract_address: str,
        secret_registry_contract_address: str,
        endpoint_registry_contract_address: str,
        user_deposit_contract_address: str,
        service_registry_contract_address: str,
        blockchain_service: BlockChainService,
        contracts: Dict[str, Any],
        routing_mode: RoutingMode,
        pathfinding_service_address: str,
        pathfinding_eth_address: str,
) -> Proxies:
    """
    Initialize and setup the contract proxies.

    Depending on the provided contract addresses via the CLI, the routing mode,
    the environment type and the network id try to initialize the proxies.
    Returns the initialized proxies or exits the application with an error if
    there is a problem.

    Also depending on the given arguments populate config with PFS related settings
    """
    node_network_id = config['chain_id']
    environment_type = config['environment_type']
    contract_addresses_given = (
        tokennetwork_registry_contract_address is not None and
        secret_registry_contract_address is not None and
        endpoint_registry_contract_address is not None
    )

    if not contract_addresses_given and not bool(contracts):
        click.secho(
            f"There are no known contract addresses for network id '{node_network_id}'. and "
            f"environment type {environment_type}. Please provide them on the command line or "
            f"in the configuration file.",
            fg='red',
        )
        sys.exit(1)

    try:
        token_network_registry = blockchain_service.token_network_registry(
            tokennetwork_registry_contract_address or to_canonical_address(
                contracts[CONTRACT_TOKEN_NETWORK_REGISTRY]['address'],
            ),
        )
    except ContractVersionMismatch as e:
        handle_contract_version_mismatch(e)
    except AddressWithoutCode:
        handle_contract_no_code('token network registry', tokennetwork_registry_contract_address)
    except AddressWrongContract:
        handle_contract_wrong_address(
            'token network registry',
            tokennetwork_registry_contract_address,
        )

    try:
        secret_registry = blockchain_service.secret_registry(
            secret_registry_contract_address or to_canonical_address(
                contracts[CONTRACT_SECRET_REGISTRY]['address'],
            ),
        )
    except ContractVersionMismatch as e:
        handle_contract_version_mismatch(e)
    except AddressWithoutCode:
        handle_contract_no_code('secret registry', secret_registry_contract_address)
    except AddressWrongContract:
        handle_contract_wrong_address('secret registry', secret_registry_contract_address)

    # If services contracts are provided via the CLI use them instead
    if user_deposit_contract_address is not None:
        contracts[CONTRACT_USER_DEPOSIT] = user_deposit_contract_address
    if service_registry_contract_address is not None:
        contracts[CONTRACT_SERVICE_REGISTRY] = (
            service_registry_contract_address
        )

    user_deposit = None
    should_use_user_deposit = (
        environment_type == Environment.DEVELOPMENT and
        ID_TO_NETWORKNAME.get(node_network_id) != 'smoketest' and
        CONTRACT_USER_DEPOSIT in contracts
    )
    if should_use_user_deposit:
        try:
            user_deposit = blockchain_service.user_deposit(
                user_deposit_contract_address or to_canonical_address(
                    contracts[CONTRACT_USER_DEPOSIT]['address'],
                ),
            )
        except ContractVersionMismatch as e:
            handle_contract_version_mismatch(e)
        except AddressWithoutCode:
            handle_contract_no_code('user deposit', user_deposit_contract_address)
        except AddressWrongContract:
            handle_contract_wrong_address('user_deposit', user_deposit_contract_address)

    service_registry = None
    if CONTRACT_SERVICE_REGISTRY in contracts or service_registry_contract_address:
        try:
            service_registry = blockchain_service.service_registry(
                service_registry_contract_address or to_canonical_address(
                    contracts[CONTRACT_SERVICE_REGISTRY]['address'],
                ),
            )
        except ContractVersionMismatch as e:
            handle_contract_version_mismatch(e)
        except AddressWithoutCode:
            handle_contract_no_code('service registry', service_registry_contract_address)
        except AddressWrongContract:
            handle_contract_wrong_address('secret registry', service_registry_contract_address)

    if routing_mode == RoutingMode.PFS:
        if environment_type == Environment.PRODUCTION:
            click.secho(
                'Requested production mode and PFS routing mode. This is not supported',
                fg='red',
            )
            sys.exit(1)

        if not service_registry and not pathfinding_service_address:
            click.secho(
                'Requested PFS routing mode but no service registry or no specific pathfinding '
                ' service address is provided. Please provide it via either the '
                '--service-registry-contract-address or the --pathfinding-service-address '
                'argument',
                fg='red',
            )
            sys.exit(1)

        pfs_config = configure_pfs_or_exit(
            pfs_address=pathfinding_service_address,
            pfs_eth_address=pathfinding_eth_address,
            routing_mode=routing_mode,
            service_registry=service_registry,
        )
        msg = 'Eth address of selected pathfinding service is unknown.'
        assert pfs_config.eth_address is not None, msg
        config['services']['pathfinding_service_address'] = pfs_config.url
        config['services']['pathfinding_eth_address'] = pfs_config.eth_address
        config['services']['pathfinding_fee'] = pfs_config.fee
    else:
        config['services']['pathfinding_service_address'] = None
        config['services']['pathfinding_eth_address'] = None

    proxies = Proxies(
        token_network_registry=token_network_registry,
        secret_registry=secret_registry,
        user_deposit=user_deposit,
        service_registry=service_registry,
    )
    return proxies