Skip to main content

hopr_ticket_manager/
chain_sync.rs

1use std::sync::Arc;
2
3use futures::StreamExt;
4use hopr_api::chain::{ChainReadChannelOperations, ChannelSelector};
5
6use crate::{HoprTicketFactory, HoprTicketManager, RedbStore, RedbTicketQueue, TicketManagerError};
7
8/// Creates a [`HoprTicketFactory`] backed by a temporary [`RedbStore`] and pre-seeds it
9/// from the node's current outgoing channels.
10///
11/// Use this when building an edge (entry/exit) node that issues tickets but does not
12/// relay them. For relay nodes that also manage incoming tickets, use
13/// [`ticket_manager_from_chain`] instead.
14pub async fn ticket_factory_from_chain<C>(
15    connector: &C,
16) -> Result<Arc<HoprTicketFactory<RedbStore>>, TicketManagerError>
17where
18    C: ChainReadChannelOperations,
19    C::Error: std::fmt::Display,
20{
21    let backend = RedbStore::new_temp().map_err(TicketManagerError::store)?;
22    let factory = Arc::new(HoprTicketFactory::new(backend));
23
24    let me = *connector.me();
25    let outgoing: Vec<_> = connector
26        .stream_channels(ChannelSelector::default().with_source(me))
27        .map_err(|e| TicketManagerError::Other(anyhow::anyhow!("failed to stream outgoing channels: {e}")))?
28        .collect()
29        .await;
30
31    factory.sync_from_outgoing_channels(&outgoing)?;
32    Ok(factory)
33}
34
35/// Creates a [`HoprTicketManager`] and its companion [`HoprTicketFactory`], both backed
36/// by a temporary [`RedbStore`], and pre-seeds them from the node's current channel state.
37///
38/// Use this when building a full relay node that both issues and redeems tickets.
39/// The factory is pre-seeded from outgoing channels and the manager from incoming channels.
40/// For edge nodes that do not redeem tickets, use [`ticket_factory_from_chain`] instead.
41pub async fn ticket_manager_from_chain<C>(
42    connector: &C,
43) -> Result<
44    (
45        Arc<HoprTicketManager<RedbStore, RedbTicketQueue>>,
46        Arc<HoprTicketFactory<RedbStore>>,
47    ),
48    TicketManagerError,
49>
50where
51    C: ChainReadChannelOperations,
52    C::Error: std::fmt::Display,
53{
54    let backend = RedbStore::new_temp().map_err(TicketManagerError::store)?;
55    let (manager, factory) = HoprTicketManager::new_with_factory(backend);
56    let manager = Arc::new(manager);
57    let factory = Arc::new(factory);
58
59    let me = *connector.me();
60    let incoming_stream = connector
61        .stream_channels(ChannelSelector::default().with_destination(me))
62        .map_err(|e| TicketManagerError::Other(anyhow::anyhow!("failed to stream incoming channels: {e}")))?;
63    let outgoing_stream = connector
64        .stream_channels(ChannelSelector::default().with_source(me))
65        .map_err(|e| TicketManagerError::Other(anyhow::anyhow!("failed to stream outgoing channels: {e}")))?;
66
67    let (incoming, outgoing): (Vec<_>, Vec<_>) = futures::join!(incoming_stream.collect(), outgoing_stream.collect());
68
69    manager.sync_from_incoming_channels(&incoming)?;
70    factory.sync_from_outgoing_channels(&outgoing)?;
71
72    Ok((manager, factory))
73}