def next_channel_from_routes( available_routes: typing.List[RouteState], channelidentifiers_to_channels: typing.ChannelMap, transfer_amount: typing.TokenAmount, ) -> typing.Optional[NettingChannelState]: """ Returns the first channel that can be used to start the transfer. The routing service can race with local changes, so the recommended routes must be validated. """ for route in available_routes: channel_identifier = route.channel_identifier channel_state = channelidentifiers_to_channels.get(channel_identifier) if not channel_state: continue if channel.get_status(channel_state) != CHANNEL_STATE_OPENED: continue pending_transfers = channel.get_number_of_pending_transfers( channel_state.our_state) if pending_transfers >= MAXIMUM_PENDING_TRANSFERS: continue distributable = channel.get_distributable( channel_state.our_state, channel_state.partner_state, ) if transfer_amount > distributable: continue if channel.is_valid_amount(channel_state.our_state, transfer_amount): return channel_state return None
def next_channel_from_routes( available_routes: List['RouteState'], channelidentifiers_to_channels: Dict, transfer_amount: int, timeout_blocks: int, ) -> NettingChannelState: """ Returns the first route that may be used to mediated the transfer. The routing service can race with local changes, so the recommended routes must be validated. Args: available_routes: Current available routes that may be used, it's assumed that the available_routes list is ordered from best to worst. channelidentifiers_to_channels: Mapping from channel identifier to NettingChannelState. transfer_amount: The amount of tokens that will be transferred through the given route. timeout_blocks: Base number of available blocks used to compute the lock timeout. Returns: The next route. """ for route in available_routes: channel_identifier = route.channel_identifier channel_state = channelidentifiers_to_channels.get(channel_identifier) if not channel_state: continue if channel.get_status(channel_state) != CHANNEL_STATE_OPENED: continue pending_transfers = channel.get_number_of_pending_transfers( channel_state.our_state) if pending_transfers >= MAXIMUM_PENDING_TRANSFERS: continue distributable = channel.get_distributable( channel_state.our_state, channel_state.partner_state, ) if transfer_amount > distributable: continue lock_timeout = timeout_blocks - channel_state.reveal_timeout if lock_timeout <= 0: continue if channel.is_valid_amount(channel_state.our_state, transfer_amount): return channel_state return None
def is_channel_usable(candidate_channel_state, transfer_amount, lock_timeout): pending_transfers = channel.get_number_of_pending_transfers( candidate_channel_state.our_state) distributable = channel.get_distributable( candidate_channel_state.our_state, candidate_channel_state.partner_state, ) return (lock_timeout > 0 and channel.get_status(candidate_channel_state) == CHANNEL_STATE_OPENED and candidate_channel_state.settle_timeout >= lock_timeout and candidate_channel_state.reveal_timeout < lock_timeout and pending_transfers < MAXIMUM_PENDING_TRANSFERS and transfer_amount <= distributable and channel.is_valid_amount( candidate_channel_state.our_state, transfer_amount))