openzeppelin_relayer/domain/relayer/stellar/
mod.rs

1mod stellar_relayer;
2pub use stellar_relayer::*;
3
4mod gas_abstraction;
5mod token_swap;
6
7pub mod xdr_utils;
8pub use xdr_utils::*;
9
10pub use crate::services::stellar_dex::StellarDexServiceTrait;
11
12use std::sync::Arc;
13
14use crate::{
15    constants::{STELLAR_HORIZON_MAINNET_URL, STELLAR_HORIZON_TESTNET_URL},
16    jobs::JobProducerTrait,
17    models::{
18        NetworkRepoModel, NetworkType, RelayerError, RelayerRepoModel, SignerRepoModel,
19        StellarNetwork, StellarSwapStrategy, TransactionRepoModel,
20    },
21    repositories::{
22        NetworkRepository, RelayerRepository, Repository, TransactionCounterTrait,
23        TransactionRepository,
24    },
25    services::{
26        provider::get_network_provider,
27        signer::StellarSignerFactory,
28        stellar_dex::{DexServiceWrapper, OrderBookService, StellarDexService},
29        TransactionCounterService,
30    },
31};
32
33/// Function to create a Stellar relayer instance
34pub async fn create_stellar_relayer<
35    J: JobProducerTrait + 'static,
36    TR: TransactionRepository + Repository<TransactionRepoModel, String> + Send + Sync + 'static,
37    NR: NetworkRepository + Repository<NetworkRepoModel, String> + Send + Sync + 'static,
38    RR: RelayerRepository + Repository<RelayerRepoModel, String> + Send + Sync + 'static,
39    TCR: TransactionCounterTrait + Send + Sync + 'static,
40>(
41    relayer: RelayerRepoModel,
42    signer: SignerRepoModel,
43    relayer_repository: Arc<RR>,
44    network_repository: Arc<NR>,
45    transaction_repository: Arc<TR>,
46    job_producer: Arc<J>,
47    transaction_counter_store: Arc<TCR>,
48) -> Result<DefaultStellarRelayer<J, TR, NR, RR, TCR>, RelayerError> {
49    let network_repo = network_repository
50        .get_by_name(NetworkType::Stellar, &relayer.network)
51        .await
52        .ok()
53        .flatten()
54        .ok_or_else(|| {
55            RelayerError::NetworkConfiguration(format!("Network {} not found", relayer.network))
56        })?;
57
58    let network = StellarNetwork::try_from(network_repo.clone())?;
59    let provider = get_network_provider(&network, relayer.custom_rpc_urls.clone())
60        .map_err(|e| RelayerError::NetworkConfiguration(e.to_string()))?;
61
62    // Create signer once and wrap in Arc for shared use
63    let stellar_signer = Arc::new(StellarSignerFactory::create_stellar_signer(&signer.into())?);
64
65    let transaction_counter_service = Arc::new(TransactionCounterService::new(
66        relayer.id.clone(),
67        relayer.address.clone(),
68        transaction_counter_store,
69    ));
70
71    // Create DEX services based on configured strategies
72    let horizon_url = network.horizon_url.clone().unwrap_or_else(|| {
73        if network.is_testnet() {
74            STELLAR_HORIZON_TESTNET_URL.to_string()
75        } else {
76            STELLAR_HORIZON_MAINNET_URL.to_string()
77        }
78    });
79    let provider_arc = Arc::new(provider.clone());
80    let signer_arc = stellar_signer.clone();
81
82    // Get strategies from policy (default to OrderBook if none specified)
83    let strategies = relayer
84        .policies
85        .get_stellar_policy()
86        .get_swap_config()
87        .and_then(|config| {
88            if config.strategies.is_empty() {
89                None
90            } else {
91                Some(config.strategies.clone())
92            }
93        })
94        .unwrap_or_else(|| vec![StellarSwapStrategy::OrderBook]);
95
96    // Create DEX services for each strategy
97    // Type parameters are inferred from provider and signer_arc
98    let mut dex_services: Vec<DexServiceWrapper<_, _>> = Vec::new();
99    for strategy in &strategies {
100        match strategy {
101            StellarSwapStrategy::OrderBook => {
102                let order_book_service = Arc::new(
103                    OrderBookService::new(
104                        horizon_url.clone(),
105                        provider_arc.clone(),
106                        signer_arc.clone(),
107                    )
108                    .map_err(|e| {
109                        RelayerError::NetworkConfiguration(format!(
110                            "Failed to create OrderBook DEX service: {e}"
111                        ))
112                    })?,
113                );
114                dex_services.push(DexServiceWrapper::OrderBook(order_book_service));
115            }
116            StellarSwapStrategy::Soroswap => {
117                // TODO: Implement Soroswap service when available
118                // For now, skip if not available
119                tracing::warn!("Soroswap strategy is not yet implemented, skipping");
120            }
121        }
122    }
123
124    // Create multi-strategy DEX service with the configured strategies
125    let dex_service = Arc::new(StellarDexService::new(dex_services));
126
127    let relayer = DefaultStellarRelayer::<J, TR, NR, RR, TCR>::new(
128        relayer,
129        stellar_signer.clone(),
130        provider,
131        StellarRelayerDependencies::new(
132            relayer_repository,
133            network_repository,
134            transaction_repository,
135            transaction_counter_service,
136            job_producer,
137        ),
138        dex_service,
139    )
140    .await?;
141
142    Ok(relayer)
143}