sof_tx/submit/
client_builder.rs1use std::sync::Arc;
4
5use super::{
6 DirectSubmitConfig, DirectSubmitTransport, JitoJsonRpcTransport, JitoSubmitConfig,
7 JitoSubmitTransport, JsonRpcTransport, RpcSubmitConfig, RpcSubmitTransport, SubmitReliability,
8 SubmitTransportError, TxFlowSafetySource, TxSubmitClient, TxSubmitGuardPolicy,
9 TxSubmitOutcomeReporter, UdpDirectTransport,
10};
11use crate::{
12 providers::{
13 LeaderProvider, RecentBlockhashProvider, RpcRecentBlockhashProvider, StaticLeaderProvider,
14 StaticRecentBlockhashProvider,
15 },
16 routing::RoutingPolicy,
17};
18
19pub struct TxSubmitClientBuilder {
21 blockhash_provider: Arc<dyn RecentBlockhashProvider>,
23 on_demand_blockhash_provider: Option<Arc<RpcRecentBlockhashProvider>>,
25 leader_provider: Arc<dyn LeaderProvider>,
27 backups: Vec<crate::providers::LeaderTarget>,
29 policy: RoutingPolicy,
31 rpc_transport: Option<Arc<dyn RpcSubmitTransport>>,
33 jito_transport: Option<Arc<dyn JitoSubmitTransport>>,
35 direct_transport: Option<Arc<dyn DirectSubmitTransport>>,
37 rpc_config: RpcSubmitConfig,
39 jito_config: JitoSubmitConfig,
41 direct_config: DirectSubmitConfig,
43 reliability: Option<SubmitReliability>,
45 flow_safety_source: Option<Arc<dyn TxFlowSafetySource>>,
47 guard_policy: TxSubmitGuardPolicy,
49 outcome_reporter: Option<Arc<dyn TxSubmitOutcomeReporter>>,
51}
52
53impl Default for TxSubmitClientBuilder {
54 fn default() -> Self {
55 Self {
56 blockhash_provider: Arc::new(StaticRecentBlockhashProvider::new(None)),
57 on_demand_blockhash_provider: None,
58 leader_provider: Arc::new(StaticLeaderProvider::default()),
59 backups: Vec::new(),
60 policy: RoutingPolicy::default(),
61 rpc_transport: None,
62 jito_transport: None,
63 direct_transport: None,
64 rpc_config: RpcSubmitConfig::default(),
65 jito_config: JitoSubmitConfig::default(),
66 direct_config: DirectSubmitConfig::default(),
67 reliability: None,
68 flow_safety_source: None,
69 guard_policy: TxSubmitGuardPolicy::default(),
70 outcome_reporter: None,
71 }
72 }
73}
74
75impl TxSubmitClientBuilder {
76 #[must_use]
78 pub fn new() -> Self {
79 Self::default()
80 }
81
82 #[must_use]
84 pub fn with_blockhash_provider(mut self, provider: Arc<dyn RecentBlockhashProvider>) -> Self {
85 self.blockhash_provider = provider;
86 self.on_demand_blockhash_provider = None;
87 self
88 }
89
90 pub fn with_blockhash_via_rpc(
96 mut self,
97 rpc_url: impl Into<String>,
98 ) -> Result<Self, SubmitTransportError> {
99 let provider = Arc::new(RpcRecentBlockhashProvider::new(rpc_url.into())?);
100 self.blockhash_provider = provider.clone();
101 self.on_demand_blockhash_provider = Some(provider);
102 Ok(self)
103 }
104
105 #[must_use]
107 pub fn with_leader_provider(mut self, provider: Arc<dyn LeaderProvider>) -> Self {
108 self.leader_provider = provider;
109 self
110 }
111
112 #[must_use]
114 pub fn without_leaders(mut self) -> Self {
115 self.leader_provider = Arc::new(StaticLeaderProvider::default());
116 self
117 }
118
119 #[must_use]
121 pub fn with_backups(mut self, backups: Vec<crate::providers::LeaderTarget>) -> Self {
122 self.backups = backups;
123 self
124 }
125
126 #[must_use]
128 pub const fn with_routing_policy(mut self, policy: RoutingPolicy) -> Self {
129 self.policy = policy;
130 self
131 }
132
133 pub fn with_rpc_defaults(
140 self,
141 rpc_url: impl Into<String>,
142 ) -> Result<Self, SubmitTransportError> {
143 let rpc_url = rpc_url.into();
144 let transport = Arc::new(JsonRpcTransport::new(rpc_url.clone())?);
145 Ok(self
146 .with_blockhash_via_rpc(rpc_url)?
147 .with_rpc_transport(transport))
148 }
149
150 #[must_use]
152 pub fn with_rpc_transport(mut self, transport: Arc<dyn RpcSubmitTransport>) -> Self {
153 self.rpc_transport = Some(transport);
154 self
155 }
156
157 pub fn with_jito_defaults(
164 self,
165 rpc_url: impl Into<String>,
166 ) -> Result<Self, SubmitTransportError> {
167 Ok(self
168 .with_blockhash_via_rpc(rpc_url)?
169 .with_jito_transport(Arc::new(JitoJsonRpcTransport::new()?)))
170 }
171
172 #[must_use]
174 pub fn with_jito_transport(mut self, transport: Arc<dyn JitoSubmitTransport>) -> Self {
175 self.jito_transport = Some(transport);
176 self
177 }
178
179 #[must_use]
181 pub fn with_direct_udp(mut self) -> Self {
182 self.direct_transport = Some(Arc::new(UdpDirectTransport::new()));
183 self
184 }
185
186 #[must_use]
188 pub fn with_direct_transport(mut self, transport: Arc<dyn DirectSubmitTransport>) -> Self {
189 self.direct_transport = Some(transport);
190 self
191 }
192
193 #[must_use]
195 pub fn with_rpc_config(mut self, config: RpcSubmitConfig) -> Self {
196 self.rpc_config = config;
197 self
198 }
199
200 #[must_use]
202 pub const fn with_jito_config(mut self, config: JitoSubmitConfig) -> Self {
203 self.jito_config = config;
204 self
205 }
206
207 #[must_use]
209 pub const fn with_direct_config(mut self, config: DirectSubmitConfig) -> Self {
210 self.direct_config = config;
211 self.reliability = None;
212 self
213 }
214
215 #[must_use]
217 pub const fn with_reliability(mut self, reliability: SubmitReliability) -> Self {
218 self.reliability = Some(reliability);
219 self
220 }
221
222 #[must_use]
224 pub fn with_flow_safety_source(mut self, source: Arc<dyn TxFlowSafetySource>) -> Self {
225 self.flow_safety_source = Some(source);
226 self
227 }
228
229 #[must_use]
231 pub const fn with_guard_policy(mut self, policy: TxSubmitGuardPolicy) -> Self {
232 self.guard_policy = policy;
233 self
234 }
235
236 #[must_use]
238 pub fn with_outcome_reporter(mut self, reporter: Arc<dyn TxSubmitOutcomeReporter>) -> Self {
239 self.outcome_reporter = Some(reporter);
240 self
241 }
242
243 #[must_use]
245 pub fn build(self) -> TxSubmitClient {
246 let mut client = TxSubmitClient::new(self.blockhash_provider, self.leader_provider)
247 .with_backups(self.backups)
248 .with_routing_policy(self.policy)
249 .with_rpc_config(self.rpc_config)
250 .with_jito_config(self.jito_config)
251 .with_guard_policy(self.guard_policy);
252 if let Some(provider) = self.on_demand_blockhash_provider {
253 client = client.with_rpc_blockhash_provider(provider);
254 }
255 if let Some(reliability) = self.reliability {
256 client = client.with_reliability(reliability);
257 } else {
258 client = client.with_direct_config(self.direct_config);
259 }
260 if let Some(transport) = self.rpc_transport {
261 client = client.with_rpc_transport(transport);
262 }
263 if let Some(transport) = self.jito_transport {
264 client = client.with_jito_transport(transport);
265 }
266 if let Some(transport) = self.direct_transport {
267 client = client.with_direct_transport(transport);
268 }
269 if let Some(source) = self.flow_safety_source {
270 client = client.with_flow_safety_source(source);
271 }
272 if let Some(reporter) = self.outcome_reporter {
273 client = client.with_outcome_reporter(reporter);
274 }
275 client
276 }
277}