+/// A wrapper around [`ChannelInfo`] representing information about the channel as directed from a
+/// source node to a target node.
+#[derive(Clone)]
+pub struct DirectedChannelInfo<'a> {
+ channel: &'a ChannelInfo,
+ direction: Option<&'a ChannelUpdateInfo>,
+}
+
+impl<'a> DirectedChannelInfo<'a> {
+ /// Returns information for the channel.
+ pub fn channel(&self) -> &'a ChannelInfo { self.channel }
+
+ /// Returns information for the direction.
+ pub fn direction(&self) -> Option<&'a ChannelUpdateInfo> { self.direction }
+
+ /// Returns the [`EffectiveCapacity`] of the channel in the direction.
+ ///
+ /// This is either the total capacity from the funding transaction, if known, or the
+ /// `htlc_maximum_msat` for the direction as advertised by the gossip network, if known,
+ /// whichever is smaller.
+ pub fn effective_capacity(&self) -> EffectiveCapacity {
+ let capacity_msat = self.channel.capacity_sats.map(|capacity_sats| capacity_sats * 1000);
+ self.direction
+ .and_then(|direction| direction.htlc_maximum_msat)
+ .map(|max_htlc_msat| {
+ let capacity_msat = capacity_msat.unwrap_or(u64::max_value());
+ if max_htlc_msat < capacity_msat {
+ EffectiveCapacity::MaximumHTLC { amount_msat: max_htlc_msat }
+ } else {
+ EffectiveCapacity::Total { capacity_msat }
+ }
+ })
+ .or_else(|| capacity_msat.map(|capacity_msat|
+ EffectiveCapacity::Total { capacity_msat }))
+ .unwrap_or(EffectiveCapacity::Unknown)
+ }
+
+ /// Returns `Some` if [`ChannelUpdateInfo`] is available in the direction.
+ pub(super) fn with_update(self) -> Option<DirectedChannelInfoWithUpdate<'a>> {
+ match self.direction {
+ Some(_) => Some(DirectedChannelInfoWithUpdate { inner: self }),
+ None => None,
+ }
+ }
+}
+
+impl<'a> fmt::Debug for DirectedChannelInfo<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+ f.debug_struct("DirectedChannelInfo")
+ .field("channel", &self.channel)
+ .finish()
+ }
+}
+
+/// A [`DirectedChannelInfo`] with [`ChannelUpdateInfo`] available in its direction.
+#[derive(Clone)]
+pub(super) struct DirectedChannelInfoWithUpdate<'a> {
+ inner: DirectedChannelInfo<'a>,
+}
+
+impl<'a> DirectedChannelInfoWithUpdate<'a> {
+ /// Returns information for the channel.
+ #[inline]
+ pub(super) fn channel(&self) -> &'a ChannelInfo { &self.inner.channel }
+
+ /// Returns information for the direction.
+ #[inline]
+ pub(super) fn direction(&self) -> &'a ChannelUpdateInfo { self.inner.direction.unwrap() }
+
+ /// Returns the [`EffectiveCapacity`] of the channel in the direction.
+ #[inline]
+ pub(super) fn effective_capacity(&self) -> EffectiveCapacity { self.inner.effective_capacity() }
+}
+
+impl<'a> fmt::Debug for DirectedChannelInfoWithUpdate<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+ self.inner.fmt(f)
+ }
+}
+
+/// The effective capacity of a channel for routing purposes.
+///
+/// While this may be smaller than the actual channel capacity, amounts greater than
+/// [`Self::as_msat`] should not be routed through the channel.
+pub enum EffectiveCapacity {
+ /// The available liquidity in the channel known from being a channel counterparty, and thus a
+ /// direct hop.
+ ExactLiquidity {
+ /// Either the inbound or outbound liquidity depending on the direction, denominated in
+ /// millisatoshi.
+ liquidity_msat: u64,
+ },
+ /// The maximum HTLC amount in one direction as advertised on the gossip network.
+ MaximumHTLC {
+ /// The maximum HTLC amount denominated in millisatoshi.
+ amount_msat: u64,
+ },
+ /// The total capacity of the channel as determined by the funding transaction.
+ Total {
+ /// The funding amount denominated in millisatoshi.
+ capacity_msat: u64,
+ },
+ /// A capacity sufficient to route any payment, typically used for private channels provided by
+ /// an invoice.
+ Infinite,
+ /// A capacity that is unknown possibly because either the chain state is unavailable to know
+ /// the total capacity or the `htlc_maximum_msat` was not advertised on the gossip network.
+ Unknown,
+}
+
+/// The presumed channel capacity denominated in millisatoshi for [`EffectiveCapacity::Unknown`] to
+/// use when making routing decisions.
+pub const UNKNOWN_CHANNEL_CAPACITY_MSAT: u64 = 250_000 * 1000;
+
+impl EffectiveCapacity {
+ /// Returns the effective capacity denominated in millisatoshi.
+ pub fn as_msat(&self) -> u64 {
+ match self {
+ EffectiveCapacity::ExactLiquidity { liquidity_msat } => *liquidity_msat,
+ EffectiveCapacity::MaximumHTLC { amount_msat } => *amount_msat,
+ EffectiveCapacity::Total { capacity_msat } => *capacity_msat,
+ EffectiveCapacity::Infinite => u64::max_value(),
+ EffectiveCapacity::Unknown => UNKNOWN_CHANNEL_CAPACITY_MSAT,
+ }
+ }
+}