use std::sync::Arc;
use super::{
DirectSubmitConfig, DirectSubmitTransport, JitoJsonRpcTransport, JitoSubmitConfig,
JitoSubmitTransport, JsonRpcTransport, RpcSubmitConfig, RpcSubmitTransport, SubmitReliability,
SubmitTransportError, TxFlowSafetySource, TxSubmitClient, TxSubmitGuardPolicy,
TxSubmitOutcomeReporter, UdpDirectTransport,
};
use crate::{
providers::{
LeaderProvider, RecentBlockhashProvider, RpcRecentBlockhashProvider, StaticLeaderProvider,
StaticRecentBlockhashProvider,
},
routing::RoutingPolicy,
};
pub struct TxSubmitClientBuilder {
blockhash_provider: Arc<dyn RecentBlockhashProvider>,
on_demand_blockhash_provider: Option<Arc<RpcRecentBlockhashProvider>>,
leader_provider: Arc<dyn LeaderProvider>,
backups: Vec<crate::providers::LeaderTarget>,
policy: RoutingPolicy,
rpc_transport: Option<Arc<dyn RpcSubmitTransport>>,
jito_transport: Option<Arc<dyn JitoSubmitTransport>>,
direct_transport: Option<Arc<dyn DirectSubmitTransport>>,
rpc_config: RpcSubmitConfig,
jito_config: JitoSubmitConfig,
direct_config: DirectSubmitConfig,
reliability: Option<SubmitReliability>,
flow_safety_source: Option<Arc<dyn TxFlowSafetySource>>,
guard_policy: TxSubmitGuardPolicy,
outcome_reporter: Option<Arc<dyn TxSubmitOutcomeReporter>>,
}
impl Default for TxSubmitClientBuilder {
fn default() -> Self {
Self {
blockhash_provider: Arc::new(StaticRecentBlockhashProvider::new(None)),
on_demand_blockhash_provider: None,
leader_provider: Arc::new(StaticLeaderProvider::default()),
backups: Vec::new(),
policy: RoutingPolicy::default(),
rpc_transport: None,
jito_transport: None,
direct_transport: None,
rpc_config: RpcSubmitConfig::default(),
jito_config: JitoSubmitConfig::default(),
direct_config: DirectSubmitConfig::default(),
reliability: None,
flow_safety_source: None,
guard_policy: TxSubmitGuardPolicy::default(),
outcome_reporter: None,
}
}
}
impl TxSubmitClientBuilder {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn with_blockhash_provider(mut self, provider: Arc<dyn RecentBlockhashProvider>) -> Self {
self.blockhash_provider = provider;
self.on_demand_blockhash_provider = None;
self
}
pub fn with_blockhash_via_rpc(
mut self,
rpc_url: impl Into<String>,
) -> Result<Self, SubmitTransportError> {
let provider = Arc::new(RpcRecentBlockhashProvider::new(rpc_url.into())?);
self.blockhash_provider = provider.clone();
self.on_demand_blockhash_provider = Some(provider);
Ok(self)
}
#[must_use]
pub fn with_leader_provider(mut self, provider: Arc<dyn LeaderProvider>) -> Self {
self.leader_provider = provider;
self
}
#[must_use]
pub fn without_leaders(mut self) -> Self {
self.leader_provider = Arc::new(StaticLeaderProvider::default());
self
}
#[must_use]
pub fn with_backups(mut self, backups: Vec<crate::providers::LeaderTarget>) -> Self {
self.backups = backups;
self
}
#[must_use]
pub const fn with_routing_policy(mut self, policy: RoutingPolicy) -> Self {
self.policy = policy;
self
}
pub fn with_rpc_defaults(
self,
rpc_url: impl Into<String>,
) -> Result<Self, SubmitTransportError> {
let rpc_url = rpc_url.into();
let transport = Arc::new(JsonRpcTransport::new(rpc_url.clone())?);
Ok(self
.with_blockhash_via_rpc(rpc_url)?
.with_rpc_transport(transport))
}
#[must_use]
pub fn with_rpc_transport(mut self, transport: Arc<dyn RpcSubmitTransport>) -> Self {
self.rpc_transport = Some(transport);
self
}
pub fn with_jito_defaults(
self,
rpc_url: impl Into<String>,
) -> Result<Self, SubmitTransportError> {
Ok(self
.with_blockhash_via_rpc(rpc_url)?
.with_jito_transport(Arc::new(JitoJsonRpcTransport::new()?)))
}
#[must_use]
pub fn with_jito_transport(mut self, transport: Arc<dyn JitoSubmitTransport>) -> Self {
self.jito_transport = Some(transport);
self
}
#[must_use]
pub fn with_direct_udp(mut self) -> Self {
self.direct_transport = Some(Arc::new(UdpDirectTransport::new()));
self
}
#[must_use]
pub fn with_direct_transport(mut self, transport: Arc<dyn DirectSubmitTransport>) -> Self {
self.direct_transport = Some(transport);
self
}
#[must_use]
pub fn with_rpc_config(mut self, config: RpcSubmitConfig) -> Self {
self.rpc_config = config;
self
}
#[must_use]
pub const fn with_jito_config(mut self, config: JitoSubmitConfig) -> Self {
self.jito_config = config;
self
}
#[must_use]
pub const fn with_direct_config(mut self, config: DirectSubmitConfig) -> Self {
self.direct_config = config;
self.reliability = None;
self
}
#[must_use]
pub const fn with_reliability(mut self, reliability: SubmitReliability) -> Self {
self.reliability = Some(reliability);
self
}
#[must_use]
pub fn with_flow_safety_source(mut self, source: Arc<dyn TxFlowSafetySource>) -> Self {
self.flow_safety_source = Some(source);
self
}
#[must_use]
pub const fn with_guard_policy(mut self, policy: TxSubmitGuardPolicy) -> Self {
self.guard_policy = policy;
self
}
#[must_use]
pub fn with_outcome_reporter(mut self, reporter: Arc<dyn TxSubmitOutcomeReporter>) -> Self {
self.outcome_reporter = Some(reporter);
self
}
#[must_use]
pub fn build(self) -> TxSubmitClient {
let mut client = TxSubmitClient::new(self.blockhash_provider, self.leader_provider)
.with_backups(self.backups)
.with_routing_policy(self.policy)
.with_rpc_config(self.rpc_config)
.with_jito_config(self.jito_config)
.with_guard_policy(self.guard_policy);
if let Some(provider) = self.on_demand_blockhash_provider {
client = client.with_rpc_blockhash_provider(provider);
}
if let Some(reliability) = self.reliability {
client = client.with_reliability(reliability);
} else {
client = client.with_direct_config(self.direct_config);
}
if let Some(transport) = self.rpc_transport {
client = client.with_rpc_transport(transport);
}
if let Some(transport) = self.jito_transport {
client = client.with_jito_transport(transport);
}
if let Some(transport) = self.direct_transport {
client = client.with_direct_transport(transport);
}
if let Some(source) = self.flow_safety_source {
client = client.with_flow_safety_source(source);
}
if let Some(reporter) = self.outcome_reporter {
client = client.with_outcome_reporter(reporter);
}
client
}
}