v0.2.8-pre.002
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-onchain-transport-lib/src/lib.rs
|
||||
// version: 29
|
||||
// version: 30
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![deny(unreachable_pub)]
|
||||
@@ -24,7 +24,8 @@
|
||||
//! routing. `0.2.7-pre.007` adds finite reconnect, deterministic resubscribe and continuity-gap tracking. `0.2.7-pre.008` makes per-subscription notification
|
||||
//! backpressure terminal and observable, preserves safe terminal error codes, performs best-effort remote cleanup and proves bounded capacity reuse.
|
||||
//! `0.2.7-pre.009` opens the first stable typed WebSocket wrappers for account, program-account and transaction-log subscriptions without exposing a raw
|
||||
//! provider-extension subscription API.
|
||||
//! provider-extension subscription API. `0.2.8-pre.002` adds a Helius LaserStream WebSocket protocol discriminator and two typed protocol facades while
|
||||
//! keeping the `WsSession` actor/socket implementation unique and the historical generic constructor standard-only.
|
||||
|
||||
mod client;
|
||||
mod constants;
|
||||
@@ -47,6 +48,7 @@ mod ws_accounts;
|
||||
mod ws_blocks;
|
||||
mod ws_cluster;
|
||||
mod ws_lifecycle;
|
||||
mod ws_protocol_session;
|
||||
mod ws_session;
|
||||
mod ws_settings;
|
||||
mod ws_subscription;
|
||||
@@ -350,7 +352,11 @@ pub use self::ws_lifecycle::WsSubscriptionKind;
|
||||
pub use self::ws_lifecycle::WsSubscriptionSnapshot;
|
||||
/// Observable lifecycle state of one logical WebSocket subscription.
|
||||
pub use self::ws_lifecycle::WsSubscriptionState;
|
||||
/// Shareable handle for one explicitly created physical WebSocket session.
|
||||
/// Typed facade for one Helius LaserStream WebSocket physical session.
|
||||
pub use self::ws_protocol_session::HeliusLaserStreamWsSession;
|
||||
/// Typed facade for one standard Solana WebSocket physical session.
|
||||
pub use self::ws_protocol_session::SolanaStandardWsSession;
|
||||
/// Shareable compatibility handle for one explicitly created standard Solana physical WebSocket session.
|
||||
pub use self::ws_session::WsSession;
|
||||
/// Open cluster or network descriptor used by WebSocket endpoint settings.
|
||||
pub use self::ws_settings::WsClusterName;
|
||||
|
||||
182
crates/ksp-onchain-transport-lib/src/ws_protocol_session.rs
Normal file
182
crates/ksp-onchain-transport-lib/src/ws_protocol_session.rs
Normal file
@@ -0,0 +1,182 @@
|
||||
// file: crates/ksp-onchain-transport-lib/src/ws_protocol_session.rs
|
||||
// version: 1
|
||||
|
||||
/// Typed facade for one standard Solana WebSocket physical session.
|
||||
///
|
||||
/// The facade delegates to the same [`crate::WsSession`] actor used by the compatibility API. It owns no socket, registry, reconnect loop or queue of its
|
||||
/// own and therefore does not duplicate the physical WebSocket runtime.
|
||||
#[derive(Clone)]
|
||||
pub struct SolanaStandardWsSession {
|
||||
inner: crate::WsSession,
|
||||
}
|
||||
|
||||
impl SolanaStandardWsSession {
|
||||
/// Opens one standard Solana WebSocket session through the shared physical actor.
|
||||
pub async fn connect(endpoint: crate::WsEndpointSettings) -> ksp_core_lib::Result<Self> {
|
||||
let connected = crate::WsSession::connect_for_protocol(endpoint, crate::WsProtocolKind::SolanaStandard).await;
|
||||
return match connected {
|
||||
std::result::Result::Ok(inner) => std::result::Result::Ok(Self { inner }),
|
||||
std::result::Result::Err(error) => std::result::Result::Err(error),
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns the stable local session identity.
|
||||
#[must_use]
|
||||
pub const fn id(&self) -> crate::WsSessionId {
|
||||
return self.inner.id();
|
||||
}
|
||||
|
||||
/// Returns the latest safe runtime snapshot published by the shared actor.
|
||||
#[must_use]
|
||||
pub fn snapshot(&self) -> crate::WsSessionSnapshot {
|
||||
return self.inner.snapshot();
|
||||
}
|
||||
|
||||
/// Returns the latest observable physical-session state.
|
||||
#[must_use]
|
||||
pub fn state(&self) -> crate::WsSessionState {
|
||||
return self.inner.state();
|
||||
}
|
||||
|
||||
/// Explicitly closes the shared physical session under its configured close timeout.
|
||||
pub async fn close(&self) -> ksp_core_lib::Result<()> {
|
||||
return self.inner.close().await;
|
||||
}
|
||||
|
||||
/// Subscribes to changes for one Solana account through standard `accountSubscribe`.
|
||||
pub async fn account_subscribe(
|
||||
&self,
|
||||
account: &ksp_core_lib::Pubkey,
|
||||
config: std::option::Option<&crate::SolanaAccountSubscribeConfig>,
|
||||
) -> ksp_core_lib::Result<crate::WsSubscription<crate::SolanaRpcResponse<crate::SolanaAccount>>> {
|
||||
return self.inner.account_subscribe(account, config).await;
|
||||
}
|
||||
|
||||
/// Subscribes to unstable standard Solana block notifications through `blockSubscribe`.
|
||||
pub async fn block_subscribe(
|
||||
&self,
|
||||
filter: &crate::SolanaBlockSubscribeFilter,
|
||||
config: std::option::Option<&crate::SolanaBlockSubscribeConfig>,
|
||||
) -> ksp_core_lib::Result<crate::WsSubscription<crate::SolanaRpcResponse<crate::SolanaBlockNotification>>> {
|
||||
return self.inner.block_subscribe(filter, config).await;
|
||||
}
|
||||
|
||||
/// Subscribes to Solana transaction logs through standard `logsSubscribe`.
|
||||
pub async fn logs_subscribe(
|
||||
&self,
|
||||
filter: &crate::SolanaLogsSubscribeFilter,
|
||||
config: std::option::Option<&crate::SolanaCommitmentConfig>,
|
||||
) -> ksp_core_lib::Result<crate::WsSubscription<crate::SolanaRpcResponse<crate::SolanaLogsNotification>>> {
|
||||
return self.inner.logs_subscribe(filter, config).await;
|
||||
}
|
||||
|
||||
/// Subscribes to account changes owned by one Solana program through standard `programSubscribe`.
|
||||
pub async fn program_subscribe(
|
||||
&self,
|
||||
program_id: &ksp_core_lib::Pubkey,
|
||||
config: std::option::Option<&crate::SolanaProgramSubscribeConfig>,
|
||||
) -> ksp_core_lib::Result<crate::WsSubscription<crate::SolanaProgramNotification>> {
|
||||
return self.inner.program_subscribe(program_id, config).await;
|
||||
}
|
||||
|
||||
/// Subscribes to standard Solana root-slot notifications through `rootSubscribe`.
|
||||
pub async fn root_subscribe(&self) -> ksp_core_lib::Result<crate::WsSubscription<u64>> {
|
||||
return self.inner.root_subscribe().await;
|
||||
}
|
||||
|
||||
/// Subscribes to one Solana transaction signature through standard `signatureSubscribe`.
|
||||
pub async fn signature_subscribe(
|
||||
&self,
|
||||
signature: &str,
|
||||
config: std::option::Option<&crate::SolanaSignatureSubscribeConfig>,
|
||||
) -> ksp_core_lib::Result<crate::WsSubscription<crate::SolanaRpcResponse<crate::SolanaSignatureNotification>>> {
|
||||
return self.inner.signature_subscribe(signature, config).await;
|
||||
}
|
||||
|
||||
/// Subscribes to standard Solana slot-processing notifications through `slotSubscribe`.
|
||||
pub async fn slot_subscribe(&self) -> ksp_core_lib::Result<crate::WsSubscription<crate::SolanaSlotNotification>> {
|
||||
return self.inner.slot_subscribe().await;
|
||||
}
|
||||
|
||||
/// Subscribes to unstable standard Solana slot-lifecycle notifications through `slotsUpdatesSubscribe`.
|
||||
pub async fn slots_updates_subscribe(&self) -> ksp_core_lib::Result<crate::WsSubscription<crate::SolanaSlotUpdate>> {
|
||||
return self.inner.slots_updates_subscribe().await;
|
||||
}
|
||||
|
||||
/// Subscribes to unstable pre-consensus gossip vote notifications through `voteSubscribe`.
|
||||
pub async fn vote_subscribe(&self) -> ksp_core_lib::Result<crate::WsSubscription<crate::SolanaVoteNotification>> {
|
||||
return self.inner.vote_subscribe().await;
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for SolanaStandardWsSession {
|
||||
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
return formatter.debug_struct("SolanaStandardWsSession").field("id", &self.id()).field("snapshot", &self.snapshot()).finish();
|
||||
}
|
||||
}
|
||||
|
||||
/// Typed facade for one Helius LaserStream WebSocket physical session.
|
||||
///
|
||||
/// `0.2.8-pre.002` intentionally exposes only physical-session lifecycle through this facade. The six Helius-supported standard subscription wrappers are
|
||||
/// added in the next tranche after exact delegation and API-absence canaries are established. No public inner handle is exposed, so callers cannot bypass
|
||||
/// the provider-specific surface by recovering a generic [`crate::WsSession`].
|
||||
///
|
||||
/// ```compile_fail
|
||||
/// async fn unsupported(session: &ksp_onchain_transport_lib::HeliusLaserStreamWsSession) {
|
||||
/// let _ = session.block_subscribe().await;
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ```compile_fail
|
||||
/// fn no_escape_hatch(session: ksp_onchain_transport_lib::HeliusLaserStreamWsSession) {
|
||||
/// let _ = session.into_inner();
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Clone)]
|
||||
pub struct HeliusLaserStreamWsSession {
|
||||
inner: crate::WsSession,
|
||||
}
|
||||
|
||||
impl HeliusLaserStreamWsSession {
|
||||
/// Opens one Helius LaserStream WebSocket session through the shared physical actor.
|
||||
pub async fn connect(endpoint: crate::WsEndpointSettings) -> ksp_core_lib::Result<Self> {
|
||||
let connected = crate::WsSession::connect_for_protocol(endpoint, crate::WsProtocolKind::HeliusLaserStream).await;
|
||||
return match connected {
|
||||
std::result::Result::Ok(inner) => std::result::Result::Ok(Self { inner }),
|
||||
std::result::Result::Err(error) => std::result::Result::Err(error),
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns the stable local session identity.
|
||||
#[must_use]
|
||||
pub const fn id(&self) -> crate::WsSessionId {
|
||||
return self.inner.id();
|
||||
}
|
||||
|
||||
/// Returns the latest safe runtime snapshot published by the shared actor.
|
||||
#[must_use]
|
||||
pub fn snapshot(&self) -> crate::WsSessionSnapshot {
|
||||
return self.inner.snapshot();
|
||||
}
|
||||
|
||||
/// Returns the latest observable physical-session state.
|
||||
#[must_use]
|
||||
pub fn state(&self) -> crate::WsSessionState {
|
||||
return self.inner.state();
|
||||
}
|
||||
|
||||
/// Explicitly closes the shared physical session under its configured close timeout.
|
||||
pub async fn close(&self) -> ksp_core_lib::Result<()> {
|
||||
return self.inner.close().await;
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for HeliusLaserStreamWsSession {
|
||||
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
return formatter.debug_struct("HeliusLaserStreamWsSession").field("id", &self.id()).field("snapshot", &self.snapshot()).finish();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "../unit_tests/ws_protocol_session.rs"]
|
||||
mod tests;
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-onchain-transport-lib/src/ws_session.rs
|
||||
// version: 12
|
||||
// version: 13
|
||||
|
||||
use futures_util::SinkExt; // rust-rules: trait-import
|
||||
use futures_util::StreamExt; // rust-rules: trait-import
|
||||
@@ -24,15 +24,32 @@ pub struct WsSession {
|
||||
}
|
||||
|
||||
impl WsSession {
|
||||
/// Opens one physical WebSocket connection for the supplied endpoint settings.
|
||||
/// Opens one physical standard Solana WebSocket connection for the supplied endpoint settings.
|
||||
///
|
||||
/// Calling this function twice with the same endpoint creates two independent physical sessions. The function returns only after the WebSocket
|
||||
/// handshake succeeds or the configured command timeout expires.
|
||||
/// This historical constructor remains standard-only after provider-specific protocol kinds are added. Calling this function twice with the same endpoint
|
||||
/// creates two independent physical sessions. Provider-specific callers must use their typed protocol facade instead of obtaining a generic handle.
|
||||
pub async fn connect(endpoint: crate::WsEndpointSettings) -> ksp_core_lib::Result<Self> {
|
||||
return Self::connect_for_protocol(endpoint, crate::WsProtocolKind::SolanaStandard).await;
|
||||
}
|
||||
|
||||
/// Opens one physical WebSocket connection after validating the typed facade protocol.
|
||||
pub(crate) async fn connect_for_protocol(endpoint: crate::WsEndpointSettings, expected_protocol: crate::WsProtocolKind) -> ksp_core_lib::Result<Self> {
|
||||
let validation = crate::WsTransportSettings::new(std::vec![endpoint.clone()]).validate();
|
||||
if let std::result::Result::Err(error) = validation {
|
||||
return std::result::Result::Err(error);
|
||||
}
|
||||
if endpoint.protocol() != expected_protocol {
|
||||
return std::result::Result::Err(
|
||||
ksp_core_lib::Error::new(crate::ERROR_CODE_INVALID_SETTINGS, "WebSocket session constructor does not accept the endpoint protocol")
|
||||
.with_context("field", "ws_endpoints.protocol")
|
||||
.with_context("expected_protocol", expected_protocol.as_str())
|
||||
.with_context("actual_protocol", endpoint.protocol().as_str()),
|
||||
);
|
||||
}
|
||||
return Self::connect_physical(endpoint).await;
|
||||
}
|
||||
|
||||
async fn connect_physical(endpoint: crate::WsEndpointSettings) -> ksp_core_lib::Result<Self> {
|
||||
let id_result = next_session_id();
|
||||
let id = match id_result {
|
||||
std::result::Result::Ok(id) => id,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-onchain-transport-lib/src/ws_settings.rs
|
||||
// version: 3
|
||||
// version: 4
|
||||
|
||||
const DEFAULT_WS_CLOSE_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(5);
|
||||
const DEFAULT_WS_COMMAND_QUEUE_CAPACITY: usize = 128;
|
||||
@@ -119,13 +119,15 @@ impl WsClusterName {
|
||||
|
||||
/// WebSocket protocol family understood by KSP Transport.
|
||||
///
|
||||
/// `0.2.7` exposes only standard Solana WebSocket. The non-exhaustive contract allows later provider-specific families without changing the common endpoint
|
||||
/// container or injecting provider-only options into [`WsSessionSettings`].
|
||||
/// The protocol discriminator belongs specifically to the WebSocket runtime. Provider products using another transport, including a future Helius
|
||||
/// LaserStream gRPC backend, require a distinct transport-owned descriptor instead of reusing this enum.
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
#[non_exhaustive]
|
||||
pub enum WsProtocolKind {
|
||||
/// Standard Solana JSON-RPC WebSocket PubSub.
|
||||
SolanaStandard,
|
||||
/// Helius LaserStream WebSocket protocol surface.
|
||||
HeliusLaserStream,
|
||||
}
|
||||
|
||||
impl WsProtocolKind {
|
||||
@@ -134,6 +136,7 @@ impl WsProtocolKind {
|
||||
pub const fn as_str(self) -> &'static str {
|
||||
return match self {
|
||||
Self::SolanaStandard => "solana_standard",
|
||||
Self::HeliusLaserStream => "helius_laserstream",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-onchain-transport-lib/tests/public_api.rs
|
||||
// version: 33
|
||||
// version: 34
|
||||
|
||||
//! Integration tests for the public `ksp-onchain-transport-lib` consumer contract.
|
||||
|
||||
@@ -676,3 +676,25 @@ fn public_v0_2_7_pre_012_complete_standard_websocket_surface_is_available_from_c
|
||||
];
|
||||
assert_eq!(kinds.len(), 9);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn public_v0_2_8_pre_002_protocol_facades_are_available_without_replacing_the_standard_session_contract() {
|
||||
assert_eq!(ksp_onchain_transport_lib::WsProtocolKind::SolanaStandard.as_str(), "solana_standard");
|
||||
assert_eq!(ksp_onchain_transport_lib::WsProtocolKind::HeliusLaserStream.as_str(), "helius_laserstream");
|
||||
let _historical_connect = ksp_onchain_transport_lib::WsSession::connect;
|
||||
let _standard_connect = ksp_onchain_transport_lib::SolanaStandardWsSession::connect;
|
||||
let _standard_close = ksp_onchain_transport_lib::SolanaStandardWsSession::close;
|
||||
let _standard_snapshot = ksp_onchain_transport_lib::SolanaStandardWsSession::snapshot;
|
||||
let _standard_account = ksp_onchain_transport_lib::SolanaStandardWsSession::account_subscribe;
|
||||
let _standard_block = ksp_onchain_transport_lib::SolanaStandardWsSession::block_subscribe;
|
||||
let _standard_logs = ksp_onchain_transport_lib::SolanaStandardWsSession::logs_subscribe;
|
||||
let _standard_program = ksp_onchain_transport_lib::SolanaStandardWsSession::program_subscribe;
|
||||
let _standard_root = ksp_onchain_transport_lib::SolanaStandardWsSession::root_subscribe;
|
||||
let _standard_signature = ksp_onchain_transport_lib::SolanaStandardWsSession::signature_subscribe;
|
||||
let _standard_slot = ksp_onchain_transport_lib::SolanaStandardWsSession::slot_subscribe;
|
||||
let _standard_slots_updates = ksp_onchain_transport_lib::SolanaStandardWsSession::slots_updates_subscribe;
|
||||
let _standard_vote = ksp_onchain_transport_lib::SolanaStandardWsSession::vote_subscribe;
|
||||
let _helius_connect = ksp_onchain_transport_lib::HeliusLaserStreamWsSession::connect;
|
||||
let _helius_close = ksp_onchain_transport_lib::HeliusLaserStreamWsSession::close;
|
||||
let _helius_snapshot = ksp_onchain_transport_lib::HeliusLaserStreamWsSession::snapshot;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-onchain-transport-lib/tests/release_completeness.rs
|
||||
// version: 24
|
||||
// version: 25
|
||||
|
||||
//! Release-level completeness canaries for staged HTTP and WebSocket Transport coverage.
|
||||
|
||||
@@ -769,3 +769,29 @@ fn release_v0_2_7_pre_012_http_inventory_remains_52_current_plus_14_historical()
|
||||
assert!(current.iter().all(|descriptor| return descriptor.runtime_status() == ksp_onchain_transport_lib::RpcRuntimeStatus::Supported));
|
||||
assert!(historical.iter().all(|descriptor| return descriptor.runtime_status() == ksp_onchain_transport_lib::RpcRuntimeStatus::Removed));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn release_v0_2_8_pre_002_protocol_facades_preserve_the_standard_partition() {
|
||||
assert_eq!(ksp_onchain_transport_lib::WsProtocolKind::SolanaStandard.as_str(), "solana_standard");
|
||||
assert_eq!(ksp_onchain_transport_lib::WsProtocolKind::HeliusLaserStream.as_str(), "helius_laserstream");
|
||||
let standard_kinds = [
|
||||
ksp_onchain_transport_lib::WsSubscriptionKind::Account,
|
||||
ksp_onchain_transport_lib::WsSubscriptionKind::Block,
|
||||
ksp_onchain_transport_lib::WsSubscriptionKind::Logs,
|
||||
ksp_onchain_transport_lib::WsSubscriptionKind::Program,
|
||||
ksp_onchain_transport_lib::WsSubscriptionKind::Root,
|
||||
ksp_onchain_transport_lib::WsSubscriptionKind::Signature,
|
||||
ksp_onchain_transport_lib::WsSubscriptionKind::Slot,
|
||||
ksp_onchain_transport_lib::WsSubscriptionKind::SlotsUpdates,
|
||||
ksp_onchain_transport_lib::WsSubscriptionKind::Vote,
|
||||
];
|
||||
assert_eq!(standard_kinds.len(), 9);
|
||||
assert_eq!(
|
||||
std::any::type_name::<ksp_onchain_transport_lib::SolanaStandardWsSession>().rsplit("::").next(),
|
||||
std::option::Option::Some("SolanaStandardWsSession")
|
||||
);
|
||||
assert_eq!(
|
||||
std::any::type_name::<ksp_onchain_transport_lib::HeliusLaserStreamWsSession>().rsplit("::").next(),
|
||||
std::option::Option::Some("HeliusLaserStreamWsSession")
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
// file: crates/ksp-onchain-transport-lib/unit_tests/ws_protocol_session.rs
|
||||
// version: 1
|
||||
|
||||
use futures_util::StreamExt; // rust-rules: trait-import
|
||||
|
||||
fn endpoint(url: &str, protocol: crate::WsProtocolKind) -> crate::WsEndpointSettings {
|
||||
return crate::WsEndpointSettings::new(
|
||||
"local_protocol_fixture",
|
||||
true,
|
||||
crate::WsProviderName::new("local-fixture"),
|
||||
crate::WsClusterName::new("local"),
|
||||
protocol,
|
||||
crate::WsEndpointUrl::parse(url).expect("local WebSocket URL must parse"),
|
||||
crate::WsSessionSettings::default(),
|
||||
);
|
||||
}
|
||||
|
||||
async fn bind_local_listener() -> (tokio::net::TcpListener, std::string::String) {
|
||||
let listener = tokio::net::TcpListener::bind("127.0.0.1:0").await.expect("local listener must bind");
|
||||
let address = listener.local_addr().expect("local listener must expose address");
|
||||
return (listener, format!("ws://{address}"));
|
||||
}
|
||||
|
||||
async fn accept_until_close(listener: tokio::net::TcpListener) {
|
||||
let (stream, _) = listener.accept().await.expect("local peer must accept connection");
|
||||
let mut websocket = tokio_tungstenite::accept_async(stream).await.expect("local WebSocket handshake must succeed");
|
||||
while let std::option::Option::Some(message) = websocket.next().await {
|
||||
let message = message.expect("local peer message must decode");
|
||||
if message.is_close() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn protocol_facades_share_the_existing_physical_session_path() {
|
||||
let (standard_listener, standard_url) = bind_local_listener().await;
|
||||
let standard_server = tokio::spawn(accept_until_close(standard_listener));
|
||||
let standard = crate::SolanaStandardWsSession::connect(endpoint(standard_url.as_str(), crate::WsProtocolKind::SolanaStandard))
|
||||
.await
|
||||
.expect("standard facade must connect");
|
||||
assert_eq!(standard.snapshot().protocol(), crate::WsProtocolKind::SolanaStandard);
|
||||
standard.close().await.expect("standard facade must close");
|
||||
standard_server.await.expect("standard peer task must finish");
|
||||
let (helius_listener, helius_url) = bind_local_listener().await;
|
||||
let helius_server = tokio::spawn(accept_until_close(helius_listener));
|
||||
let helius_url = format!("{helius_url}/?api-key=SECRET-CANARY");
|
||||
let helius = crate::HeliusLaserStreamWsSession::connect(endpoint(helius_url.as_str(), crate::WsProtocolKind::HeliusLaserStream))
|
||||
.await
|
||||
.expect("Helius facade must connect");
|
||||
assert_eq!(helius.snapshot().protocol(), crate::WsProtocolKind::HeliusLaserStream);
|
||||
let rendered = format!("{helius:?}");
|
||||
assert!(!rendered.contains("SECRET-CANARY"));
|
||||
assert!(!rendered.contains(helius_url.as_str()));
|
||||
helius.close().await.expect("Helius facade must close");
|
||||
helius_server.await.expect("Helius peer task must finish");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn historical_generic_constructor_remains_standard_only_before_network_io() {
|
||||
let endpoint = endpoint("ws://127.0.0.1:9", crate::WsProtocolKind::HeliusLaserStream);
|
||||
let error = crate::WsSession::connect(endpoint).await.expect_err("generic historical constructor must reject Helius protocol");
|
||||
assert_eq!(error.code(), crate::ERROR_CODE_INVALID_SETTINGS);
|
||||
assert_eq!(
|
||||
error.context().iter().find(|entry| entry.key() == "expected_protocol").map(|entry| entry.value()),
|
||||
std::option::Option::Some("solana_standard")
|
||||
);
|
||||
assert_eq!(
|
||||
error.context().iter().find(|entry| entry.key() == "actual_protocol").map(|entry| entry.value()),
|
||||
std::option::Option::Some("helius_laserstream")
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn typed_facades_reject_protocol_mismatch_before_network_io() {
|
||||
let helius_error = crate::HeliusLaserStreamWsSession::connect(endpoint("ws://127.0.0.1:9", crate::WsProtocolKind::SolanaStandard))
|
||||
.await
|
||||
.expect_err("Helius facade must reject standard endpoint");
|
||||
assert_eq!(helius_error.code(), crate::ERROR_CODE_INVALID_SETTINGS);
|
||||
let standard_error = crate::SolanaStandardWsSession::connect(endpoint("ws://127.0.0.1:9", crate::WsProtocolKind::HeliusLaserStream))
|
||||
.await
|
||||
.expect_err("standard facade must reject Helius endpoint");
|
||||
assert_eq!(standard_error.code(), crate::ERROR_CODE_INVALID_SETTINGS);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn protocol_facades_define_no_second_actor_socket_or_public_inner_escape_hatch() {
|
||||
let source = include_str!("../src/ws_protocol_session.rs");
|
||||
assert!(!source.contains("tokio::spawn"));
|
||||
assert!(!source.contains("tokio_tungstenite"));
|
||||
assert!(!source.contains("WsSessionCommand"));
|
||||
assert!(!source.contains("pub fn inner("));
|
||||
assert!(!source.contains("pub fn into_inner("));
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-onchain-transport-lib/unit_tests/ws_settings.rs
|
||||
// version: 1
|
||||
// version: 2
|
||||
|
||||
fn valid_endpoint(name: &str, url_text: &str) -> crate::WsEndpointSettings {
|
||||
return crate::WsEndpointSettings::new(
|
||||
@@ -47,8 +47,10 @@ fn websocket_endpoint_url_errors_do_not_echo_sensitive_url() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn websocket_protocol_kind_is_extensible_but_only_standard_is_available_now() {
|
||||
fn websocket_protocol_kind_distinguishes_standard_and_helius_laserstream_websocket() {
|
||||
assert_eq!(crate::WsProtocolKind::SolanaStandard.as_str(), "solana_standard");
|
||||
assert_eq!(crate::WsProtocolKind::HeliusLaserStream.as_str(), "helius_laserstream");
|
||||
assert_ne!(crate::WsProtocolKind::SolanaStandard, crate::WsProtocolKind::HeliusLaserStream);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user