Skip to content

Commit 2e1e018

Browse files
authored
feat: Provider and PubSub configs (#59)
* feat: Provider and PubSub configs * feat: connect fns
1 parent c2e593d commit 2e1e018

File tree

3 files changed

+144
-1
lines changed

3 files changed

+144
-1
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ name = "init4-bin-base"
44
description = "Internal utilities for binaries produced by the init4 team"
55
keywords = ["init4", "bin", "base"]
66

7-
version = "0.9.0"
7+
version = "0.9.1"
88
edition = "2021"
99
rust-version = "1.81"
1010
authors = ["init4", "James Prestwich"]

src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ pub mod utils {
3434
/// OpenTelemetry utilities.
3535
pub mod otlp;
3636

37+
#[cfg(feature = "alloy")]
38+
/// Alloy Provider configuration and instantiation
39+
pub mod provider;
40+
3741
#[cfg(feature = "alloy")]
3842
/// Signer using a local private key or AWS KMS key.
3943
pub mod signer;

src/utils/provider.rs

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
use crate::utils::from_env::{FromEnvErr, FromEnvVar};
2+
use alloy::{
3+
providers::{IpcConnect, RootProvider, WsConnect},
4+
pubsub::{ConnectionHandle, PubSubConnect},
5+
rpc::client::BuiltInConnectionString,
6+
transports::{
7+
BoxTransport, TransportConnect, TransportError, TransportErrorKind, TransportResult,
8+
},
9+
};
10+
11+
impl FromEnvVar for BuiltInConnectionString {
12+
type Error = TransportError;
13+
14+
fn from_env_var(env_var: &str) -> Result<Self, FromEnvErr<Self::Error>> {
15+
let conn_str = String::from_env_var(env_var).map_err(FromEnvErr::infallible_into)?;
16+
conn_str.parse().map_err(Into::into)
17+
}
18+
}
19+
20+
/// Configuration for an Alloy provider, sourced from an environment variable.
21+
#[derive(Debug, Clone, PartialEq, Eq)]
22+
pub struct ProviderConfig {
23+
connection_string: BuiltInConnectionString,
24+
}
25+
26+
impl ProviderConfig {
27+
/// Creates a new `ProviderConfig` from a connection string.
28+
pub const fn new(connection_string: BuiltInConnectionString) -> Self {
29+
Self { connection_string }
30+
}
31+
32+
/// Returns the connection string.
33+
pub const fn connection_string(&self) -> &BuiltInConnectionString {
34+
&self.connection_string
35+
}
36+
37+
/// Connects to the provider using the connection string.
38+
pub async fn connect(&self) -> TransportResult<RootProvider> {
39+
RootProvider::connect_with(self.clone()).await
40+
}
41+
}
42+
43+
impl FromEnvVar for ProviderConfig {
44+
type Error = TransportError;
45+
46+
fn from_env_var(env_var: &str) -> Result<Self, FromEnvErr<Self::Error>> {
47+
let connection_string = BuiltInConnectionString::from_env_var(env_var)?;
48+
Ok(Self { connection_string })
49+
}
50+
}
51+
52+
impl TransportConnect for ProviderConfig {
53+
fn is_local(&self) -> bool {
54+
self.connection_string.is_local()
55+
}
56+
57+
fn get_transport(
58+
&self,
59+
) -> alloy::transports::impl_future!(<Output = Result<BoxTransport, TransportError>>) {
60+
self.connection_string.get_transport()
61+
}
62+
}
63+
64+
/// Configuration for an Alloy provider, used to create a client, enforces
65+
/// pubsub availability (WS or IPC connection).
66+
#[derive(Debug, Clone, PartialEq, Eq)]
67+
pub struct PubSubConfig {
68+
connection_string: BuiltInConnectionString,
69+
}
70+
71+
impl PubSubConfig {
72+
/// Returns the connection string.
73+
pub const fn connection_string(&self) -> &BuiltInConnectionString {
74+
&self.connection_string
75+
}
76+
77+
/// Connects to the provider using the connection string.
78+
pub async fn connect(&self) -> TransportResult<RootProvider> {
79+
RootProvider::connect_with(self.clone()).await
80+
}
81+
}
82+
83+
impl TryFrom<BuiltInConnectionString> for PubSubConfig {
84+
type Error = TransportError;
85+
86+
fn try_from(connection_string: BuiltInConnectionString) -> Result<Self, Self::Error> {
87+
if !matches!(
88+
connection_string,
89+
BuiltInConnectionString::Ws(_, _) | BuiltInConnectionString::Ipc(_)
90+
) {
91+
return Err(TransportErrorKind::pubsub_unavailable());
92+
}
93+
Ok(Self { connection_string })
94+
}
95+
}
96+
97+
impl FromEnvVar for PubSubConfig {
98+
type Error = TransportError;
99+
100+
fn from_env_var(env_var: &str) -> Result<Self, FromEnvErr<Self::Error>> {
101+
let cs = BuiltInConnectionString::from_env_var(env_var)?;
102+
Self::try_from(cs).map_err(FromEnvErr::ParseError)
103+
}
104+
}
105+
106+
impl TransportConnect for PubSubConfig {
107+
fn is_local(&self) -> bool {
108+
self.connection_string.is_local()
109+
}
110+
111+
fn get_transport(
112+
&self,
113+
) -> alloy::transports::impl_future!(<Output = Result<BoxTransport, TransportError>>) {
114+
self.connection_string.get_transport()
115+
}
116+
}
117+
118+
impl PubSubConnect for PubSubConfig {
119+
fn is_local(&self) -> bool {
120+
self.connection_string.is_local()
121+
}
122+
123+
fn connect(
124+
&self,
125+
) -> alloy::transports::impl_future!(<Output = TransportResult<ConnectionHandle>>) {
126+
async move {
127+
match &self.connection_string {
128+
BuiltInConnectionString::Ws(ws, auth) => {
129+
WsConnect::new(ws.as_str())
130+
.with_auth_opt(auth.clone())
131+
.connect()
132+
.await
133+
}
134+
BuiltInConnectionString::Ipc(ipc) => IpcConnect::new(ipc.clone()).connect().await,
135+
_ => unreachable!("can't instantiate http variant"),
136+
}
137+
}
138+
}
139+
}

0 commit comments

Comments
 (0)