Connect to the network.

        Subsequent calls to `connect` are allowed, but will only affect the spendable
        funds and the connection strategy parameters for the future. `connect` will not
        close any channels.

        Note: the ConnectionManager does not discriminate manually opened channels from
        automatically opened ones. If the user manually opened channels, those deposit
        amounts will affect the funding per channel and the number of new channels opened.

        Args:
            funds: Target amount of tokens spendable to join the network.
            initial_channel_target: Target number of channels to open.
            joinable_funds_target: Amount of funds not initially assigned.

def connect(
            self,
            funds: typing.TokenAmount,
            initial_channel_target: int = 3,
            joinable_funds_target: float = 0.4,
    ):
        """Connect to the network.

        Subsequent calls to `connect` are allowed, but will only affect the spendable
        funds and the connection strategy parameters for the future. `connect` will not
        close any channels.

        Note: the ConnectionManager does not discriminate manually opened channels from
        automatically opened ones. If the user manually opened channels, those deposit
        amounts will affect the funding per channel and the number of new channels opened.

        Args:
            funds: Target amount of tokens spendable to join the network.
            initial_channel_target: Target number of channels to open.
            joinable_funds_target: Amount of funds not initially assigned.
        """
        token = self.raiden.chain.token(self.token_address)
        token_balance = token.balance_of(self.raiden.address)

        if token_balance < funds:
            raise InvalidAmount(
                f'Insufficient balance for token {pex(self.token_address)}',
            )

        if funds <= 0:
            raise InvalidAmount(
                'The funds to use in the connection need to be a positive integer',
            )

        if joinable_funds_target < 0 or joinable_funds_target > 1:
            raise InvalidAmount(
                f'joinable_funds_target should be between 0 and 1. Given: {joinable_funds_target}',
            )

        with self.lock:
            self.funds = funds
            self.initial_channel_target = initial_channel_target
            self.joinable_funds_target = joinable_funds_target

            log_open_channels(self.raiden, self.registry_address, self.token_address, funds)

            qty_network_channels = views.count_token_network_channels(
                views.state_from_raiden(self.raiden),
                self.registry_address,
                self.token_address,
            )

            if not qty_network_channels:
                log.info(
                    'Bootstrapping token network.',
                    node=pex(self.raiden.address),
                    network_id=pex(self.registry_address),
                    token_id=pex(self.token_address),
                )
                self.api.channel_open(
                    self.registry_address,
                    self.token_address,
                    self.BOOTSTRAP_ADDR,
                )
            else:
                self._open_channels()