openzeppelin_relayer/domain/relayer/stellar/
mod.rs1mod stellar_relayer;
2pub use stellar_relayer::*;
3
4mod gas_abstraction;
5mod token_swap;
6
7pub mod utils;
8pub mod xdr_utils;
9pub use xdr_utils::*;
10
11pub use crate::services::stellar_dex::StellarDexServiceTrait;
12
13use std::sync::Arc;
14
15use crate::{
16 constants::{STELLAR_HORIZON_MAINNET_URL, STELLAR_HORIZON_TESTNET_URL},
17 jobs::JobProducerTrait,
18 models::{
19 NetworkRepoModel, NetworkType, RelayerError, RelayerRepoModel, SignerRepoModel,
20 StellarNetwork, StellarSwapStrategy, TransactionRepoModel,
21 },
22 repositories::{
23 NetworkRepository, RelayerRepository, Repository, TransactionCounterTrait,
24 TransactionRepository,
25 },
26 services::{
27 provider::get_network_provider,
28 signer::StellarSignerFactory,
29 stellar_dex::{DexServiceWrapper, OrderBookService, SoroswapService, StellarDexService},
30 TransactionCounterService,
31 },
32};
33
34pub async fn create_stellar_relayer<
36 J: JobProducerTrait + 'static,
37 TR: TransactionRepository + Repository<TransactionRepoModel, String> + Send + Sync + 'static,
38 NR: NetworkRepository + Repository<NetworkRepoModel, String> + Send + Sync + 'static,
39 RR: RelayerRepository + Repository<RelayerRepoModel, String> + Send + Sync + 'static,
40 TCR: TransactionCounterTrait + Send + Sync + 'static,
41>(
42 relayer: RelayerRepoModel,
43 signer: SignerRepoModel,
44 relayer_repository: Arc<RR>,
45 network_repository: Arc<NR>,
46 transaction_repository: Arc<TR>,
47 job_producer: Arc<J>,
48 transaction_counter_store: Arc<TCR>,
49) -> Result<DefaultStellarRelayer<J, TR, NR, RR, TCR>, RelayerError> {
50 let network_repo = network_repository
51 .get_by_name(NetworkType::Stellar, &relayer.network)
52 .await
53 .ok()
54 .flatten()
55 .ok_or_else(|| {
56 RelayerError::NetworkConfiguration(format!("Network {} not found", relayer.network))
57 })?;
58
59 let network = StellarNetwork::try_from(network_repo.clone())?;
60 let provider = get_network_provider(&network, relayer.custom_rpc_urls.clone())
61 .map_err(|e| RelayerError::NetworkConfiguration(e.to_string()))?;
62
63 let stellar_signer = Arc::new(StellarSignerFactory::create_stellar_signer(&signer.into())?);
65
66 let transaction_counter_service = Arc::new(TransactionCounterService::new(
67 relayer.id.clone(),
68 relayer.address.clone(),
69 transaction_counter_store,
70 ));
71
72 let horizon_url = network.horizon_url.clone().unwrap_or_else(|| {
74 if network.is_testnet() {
75 STELLAR_HORIZON_TESTNET_URL.to_string()
76 } else {
77 STELLAR_HORIZON_MAINNET_URL.to_string()
78 }
79 });
80 let provider_arc = Arc::new(provider.clone());
81 let signer_arc = stellar_signer.clone();
82
83 let strategies = relayer
85 .policies
86 .get_stellar_policy()
87 .get_swap_config()
88 .and_then(|config| {
89 if config.strategies.is_empty() {
90 None
91 } else {
92 Some(config.strategies.clone())
93 }
94 })
95 .unwrap_or_else(|| vec![StellarSwapStrategy::OrderBook]);
96
97 let mut dex_services: Vec<DexServiceWrapper<_, _>> = Vec::new();
100 for strategy in &strategies {
101 match strategy {
102 StellarSwapStrategy::OrderBook => {
103 let order_book_service = Arc::new(
104 OrderBookService::new(
105 horizon_url.clone(),
106 provider_arc.clone(),
107 signer_arc.clone(),
108 )
109 .map_err(|e| {
110 RelayerError::NetworkConfiguration(format!(
111 "Failed to create OrderBook DEX service: {e}"
112 ))
113 })?,
114 );
115 dex_services.push(DexServiceWrapper::OrderBook(order_book_service));
116 }
117 StellarSwapStrategy::Soroswap => {
118 let is_testnet = network.is_testnet();
119 let network_label = if is_testnet { "TESTNET" } else { "MAINNET" };
120
121 let router_address =
122 crate::config::ServerConfig::resolve_stellar_soroswap_router_address(
123 is_testnet,
124 )
125 .ok_or_else(|| {
126 RelayerError::NetworkConfiguration(format!(
127 "Soroswap router address not configured. Set STELLAR_{network_label}_SOROSWAP_ROUTER_ADDRESS env var."
128 ))
129 })?;
130
131 let factory_address =
132 crate::config::ServerConfig::resolve_stellar_soroswap_factory_address(
133 is_testnet,
134 )
135 .ok_or_else(|| {
136 RelayerError::NetworkConfiguration(format!(
137 "Soroswap factory address not configured. Set STELLAR_{network_label}_SOROSWAP_FACTORY_ADDRESS env var."
138 ))
139 })?;
140
141 let native_wrapper_address =
142 crate::config::ServerConfig::resolve_stellar_soroswap_native_wrapper_address(
143 is_testnet,
144 )
145 .ok_or_else(|| {
146 RelayerError::NetworkConfiguration(format!(
147 "Soroswap native wrapper address not configured. Set STELLAR_{network_label}_SOROSWAP_NATIVE_WRAPPER_ADDRESS env var."
148 ))
149 })?;
150
151 let soroswap_service = Arc::new(SoroswapService::new(
152 router_address,
153 factory_address,
154 native_wrapper_address,
155 provider_arc.clone(),
156 network.passphrase.clone(),
157 ));
158 dex_services.push(DexServiceWrapper::Soroswap(soroswap_service));
159 tracing::info!("Soroswap DEX service initialized");
160 }
161 }
162 }
163
164 let dex_service = Arc::new(StellarDexService::new(dex_services));
166
167 let relayer = DefaultStellarRelayer::<J, TR, NR, RR, TCR>::new(
168 relayer,
169 stellar_signer.clone(),
170 provider,
171 StellarRelayerDependencies::new(
172 relayer_repository,
173 network_repository,
174 transaction_repository,
175 transaction_counter_service,
176 job_producer,
177 ),
178 dex_service,
179 )
180 .await?;
181
182 Ok(relayer)
183}