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 =
65 Arc::new(StellarSignerFactory::create_stellar_signer(signer.into()).await?);
66
67 let transaction_counter_service = Arc::new(TransactionCounterService::new(
68 relayer.id.clone(),
69 relayer.address.clone(),
70 transaction_counter_store,
71 ));
72
73 let horizon_url = network.horizon_url.clone().unwrap_or_else(|| {
75 if network.is_testnet() {
76 STELLAR_HORIZON_TESTNET_URL.to_string()
77 } else {
78 STELLAR_HORIZON_MAINNET_URL.to_string()
79 }
80 });
81 let provider_arc = Arc::new(provider.clone());
82 let signer_arc = stellar_signer.clone();
83
84 let strategies = relayer
86 .policies
87 .get_stellar_policy()
88 .get_swap_config()
89 .and_then(|config| {
90 if config.strategies.is_empty() {
91 None
92 } else {
93 Some(config.strategies.clone())
94 }
95 })
96 .unwrap_or_else(|| vec![StellarSwapStrategy::OrderBook]);
97
98 let mut dex_services: Vec<DexServiceWrapper<_, _>> = Vec::new();
101 for strategy in &strategies {
102 match strategy {
103 StellarSwapStrategy::OrderBook => {
104 let order_book_service = Arc::new(
105 OrderBookService::new(
106 horizon_url.clone(),
107 provider_arc.clone(),
108 signer_arc.clone(),
109 )
110 .map_err(|e| {
111 RelayerError::NetworkConfiguration(format!(
112 "Failed to create OrderBook DEX service: {e}"
113 ))
114 })?,
115 );
116 dex_services.push(DexServiceWrapper::OrderBook(order_book_service));
117 }
118 StellarSwapStrategy::Soroswap => {
119 let is_testnet = network.is_testnet();
120 let network_label = if is_testnet { "TESTNET" } else { "MAINNET" };
121
122 let router_address =
123 crate::config::ServerConfig::resolve_stellar_soroswap_router_address(
124 is_testnet,
125 )
126 .ok_or_else(|| {
127 RelayerError::NetworkConfiguration(format!(
128 "Soroswap router address not configured. Set STELLAR_{network_label}_SOROSWAP_ROUTER_ADDRESS env var."
129 ))
130 })?;
131
132 let factory_address =
133 crate::config::ServerConfig::resolve_stellar_soroswap_factory_address(
134 is_testnet,
135 )
136 .ok_or_else(|| {
137 RelayerError::NetworkConfiguration(format!(
138 "Soroswap factory address not configured. Set STELLAR_{network_label}_SOROSWAP_FACTORY_ADDRESS env var."
139 ))
140 })?;
141
142 let native_wrapper_address =
143 crate::config::ServerConfig::resolve_stellar_soroswap_native_wrapper_address(
144 is_testnet,
145 )
146 .ok_or_else(|| {
147 RelayerError::NetworkConfiguration(format!(
148 "Soroswap native wrapper address not configured. Set STELLAR_{network_label}_SOROSWAP_NATIVE_WRAPPER_ADDRESS env var."
149 ))
150 })?;
151
152 let soroswap_service = Arc::new(SoroswapService::new(
153 router_address,
154 factory_address,
155 native_wrapper_address,
156 provider_arc.clone(),
157 network.passphrase.clone(),
158 ));
159 dex_services.push(DexServiceWrapper::Soroswap(soroswap_service));
160 tracing::info!("Soroswap DEX service initialized");
161 }
162 }
163 }
164
165 let dex_service = Arc::new(StellarDexService::new(dex_services));
167
168 let relayer = DefaultStellarRelayer::<J, TR, NR, RR, TCR>::new(
169 relayer,
170 stellar_signer.clone(),
171 provider,
172 StellarRelayerDependencies::new(
173 relayer_repository,
174 network_repository,
175 transaction_repository,
176 transaction_counter_service,
177 job_producer,
178 ),
179 dex_service,
180 )
181 .await?;
182
183 Ok(relayer)
184}