Files
khadhroony-solana-project/crates/ksp-app-raw-transaction-ingest-desk/src/dto_route.rs
2026-09-13 17:36:06 +02:00

314 lines
14 KiB
Rust

// file: crates/ksp-app-raw-transaction-ingest-desk/src/dto_route.rs
// version: 4
//! Safe route-identity, Config-composability and lifecycle DTOs for Raw Transaction Ingest Desk.
use ts_rs::TS; // rust-rules: trait-import
/// Stable logical V1 route identifiers owned by Raw Transaction Ingest Desk.
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
#[serde(rename_all = "kebab-case")]
#[ts(export, export_to = "../frontend/ts/bindings/ksp_app_raw_transaction_ingest_desk/dto_route/RawIngestRouteId.ts")]
pub(crate) enum RawIngestRouteId {
/// Yellowstone Subscribe plus same-network HTTP hydration.
YellowstoneHydrated,
/// Standard Solana logs subscription plus same-network HTTP hydration.
StandardLogsHydrated,
/// Standard Solana block subscription with direct RAW projection.
StandardBlockDirect,
/// Helius transaction subscription plus same-network HTTP hydration.
HeliusTransactionHydrated,
/// HTTP block polling and direct block material projection.
HttpBlockPolling,
}
impl crate::RawIngestRouteId {
/// Returns all V1 route identifiers in stable UI order.
#[must_use]
pub(crate) fn all() -> std::vec::Vec<Self> {
return vec![
Self::YellowstoneHydrated,
Self::StandardLogsHydrated,
Self::StandardBlockDirect,
Self::HeliusTransactionHydrated,
Self::HttpBlockPolling,
];
}
/// Returns the application-owned route family used by safe UI projections.
#[must_use]
pub(crate) const fn family(self) -> crate::RawIngestRouteFamily {
return match self {
Self::YellowstoneHydrated => crate::RawIngestRouteFamily::Yellowstone,
Self::StandardLogsHydrated => crate::RawIngestRouteFamily::StandardLogs,
Self::StandardBlockDirect => crate::RawIngestRouteFamily::StandardBlock,
Self::HeliusTransactionHydrated => crate::RawIngestRouteFamily::HeliusTransaction,
Self::HttpBlockPolling => crate::RawIngestRouteFamily::HttpBlockPolling,
};
}
/// Returns the stable operator-facing route label without exposing physical endpoint metadata.
#[must_use]
pub(crate) const fn label(self) -> &'static str {
return match self {
Self::YellowstoneHydrated => "Yellowstone + HTTP hydration",
Self::StandardLogsHydrated => "Standard Logs + HTTP hydration",
Self::StandardBlockDirect => "Standard Block direct",
Self::HeliusTransactionHydrated => "Helius Transaction + HTTP hydration",
Self::HttpBlockPolling => "HTTP Block Polling",
};
}
/// Returns the stable kebab-case route identifier used by safe logs and IPC.
#[must_use]
pub(crate) const fn as_str(self) -> &'static str {
return match self {
Self::YellowstoneHydrated => "yellowstone-hydrated",
Self::StandardLogsHydrated => "standard-logs-hydrated",
Self::StandardBlockDirect => "standard-block-direct",
Self::HeliusTransactionHydrated => "helius-transaction-hydrated",
Self::HttpBlockPolling => "http-block-polling",
};
}
}
/// Start-time commitments accepted by Raw Transaction Ingest Desk.
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
#[serde(rename_all = "snake_case")]
#[ts(export, export_to = "../frontend/ts/bindings/ksp_app_raw_transaction_ingest_desk/dto_route/RawIngestCommitment.ts")]
pub(crate) enum RawIngestCommitment {
/// Confirmed commitment.
Confirmed,
/// Finalized commitment.
Finalized,
}
impl crate::RawIngestCommitment {
/// Returns the stable wire label.
#[must_use]
pub(crate) const fn as_str(self) -> &'static str {
return match self {
Self::Confirmed => "confirmed",
Self::Finalized => "finalized",
};
}
/// Maps the application-owned bounded commitment into the Transport contract.
#[must_use]
pub(crate) const fn into_transport(self) -> ksp_onchain_transport_lib::SolanaCommitment {
return match self {
Self::Confirmed => ksp_onchain_transport_lib::SolanaCommitment::Confirmed,
Self::Finalized => ksp_onchain_transport_lib::SolanaCommitment::Finalized,
};
}
}
/// Safe request used to revalidate and reconstruct one future route Start without accepting physical resources from the frontend.
#[derive(Clone, Debug, serde::Deserialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export, export_to = "../frontend/ts/bindings/ksp_app_raw_transaction_ingest_desk/dto_route/RawIngestRouteStartRequestDto.ts")]
pub(crate) struct RawIngestRouteStartRequestDto {
/// Confirmed/finalized commitment selected for the future Worker.
pub(crate) commitment: crate::RawIngestCommitment,
/// Inventory generation observed by the caller.
pub(crate) inventory_generation: u32,
/// Safe logical network-profile identifier selected from the current inventory.
pub(crate) profile_id: String,
/// Stable logical route identifier.
pub(crate) route_id: crate::RawIngestRouteId,
}
/// Safe acknowledgement that exact Start-time Transport resources were reconstructed and validated without Worker launch.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export, export_to = "../frontend/ts/bindings/ksp_app_raw_transaction_ingest_desk/dto_route/RawIngestRouteStartValidationDto.ts")]
pub(crate) struct RawIngestRouteStartValidationDto {
/// Commitment validated by the exact Worker source constructor.
pub(crate) commitment: crate::RawIngestCommitment,
/// Inventory generation validated against backend state.
pub(crate) inventory_generation: u32,
/// Logical network re-proven from Store and Transport Config.
pub(crate) network: String,
/// Safe logical network-profile identifier.
pub(crate) profile_id: String,
/// Exact logical route whose Transport resources were reconstructed.
pub(crate) route_id: crate::RawIngestRouteId,
}
/// Stable application-owned route families used only for safe presentation and orchestration.
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Serialize, TS)]
#[serde(rename_all = "snake_case")]
#[ts(export, export_to = "../frontend/ts/bindings/ksp_app_raw_transaction_ingest_desk/dto_route/RawIngestRouteFamily.ts")]
pub(crate) enum RawIngestRouteFamily {
/// Yellowstone gRPC subscription route.
Yellowstone,
/// Standard Solana logs WebSocket route.
StandardLogs,
/// Standard Solana block WebSocket route.
StandardBlock,
/// Helius transaction WebSocket route.
HeliusTransaction,
/// HTTP block polling route.
HttpBlockPolling,
}
/// Safe reasons explaining why one logical route cannot currently be composed from Config.
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Serialize, TS)]
#[serde(rename_all = "snake_case")]
#[ts(export, export_to = "../frontend/ts/bindings/ksp_app_raw_transaction_ingest_desk/dto_route/RawIngestRouteUnavailableReason.ts")]
pub(crate) enum RawIngestRouteUnavailableReason {
/// The selected composite or one of its typed Config components could not be resolved safely.
ProfileUnresolved,
/// Transport and Store do not prove one identical logical network.
NetworkMismatch,
/// No HTTP role can satisfy `getTransaction` for same-network hydration.
MissingHttpGetTransaction,
/// No HTTP role can satisfy the complete block-polling method set.
MissingHttpBlockScan,
/// No enabled standard WebSocket endpoint explicitly declares `Logs`.
MissingWsLogsCapability,
/// No enabled standard WebSocket endpoint explicitly declares `Block`.
MissingWsBlockCapability,
/// No enabled Helius WebSocket endpoint explicitly declares `HeliusTransaction`.
MissingHeliusTransactionCapability,
/// No enabled same-network Yellowstone gRPC endpoint is configured.
MissingYellowstoneGrpc,
/// A required Config secret is not resolved for the selected composite profile.
MissingRequiredSecret,
}
/// Stable Raw Transaction Ingest Desk route lifecycle states.
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Serialize, TS)]
#[serde(rename_all = "snake_case")]
#[ts(export, export_to = "../frontend/ts/bindings/ksp_app_raw_transaction_ingest_desk/dto_route/RawIngestRouteState.ts")]
pub(crate) enum RawIngestRouteState {
/// Required Config composition is incomplete or incoherent.
Unavailable,
/// Config proves composability but no runtime Worker is active.
Configured,
/// Runtime resources are being revalidated and assembled.
Starting,
/// One Worker instance is active for the logical route.
Running,
/// Stop has been requested and bounded termination is pending.
Stopping,
/// The route Worker terminated normally and its handle was removed.
Stopped,
/// Start or runtime failed with a safe projected code.
Faulted,
}
impl crate::RawIngestRouteState {
/// Returns all lifecycle states in stable presentation order.
#[must_use]
pub(crate) fn all() -> std::vec::Vec<Self> {
return vec![Self::Unavailable, Self::Configured, Self::Starting, Self::Running, Self::Stopping, Self::Stopped, Self::Faulted];
}
}
/// Static route/state foundation retained as the bounded vocabulary behind the live Config inventory.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export, export_to = "../frontend/ts/bindings/ksp_app_raw_transaction_ingest_desk/dto_route/RawIngestRouteFoundationDto.ts")]
pub(crate) struct RawIngestRouteFoundationDto {
/// Five stable V1 logical route identifiers; this is not a composability claim.
pub(crate) route_ids: std::vec::Vec<crate::RawIngestRouteId>,
/// Stable lifecycle state vocabulary reserved for runtime projections.
pub(crate) states: std::vec::Vec<crate::RawIngestRouteState>,
}
impl crate::RawIngestRouteFoundationDto {
/// Builds the bounded route/state vocabulary without resolving endpoints, secrets or Worker resources.
#[must_use]
pub(crate) fn scaffold() -> Self {
return Self { route_ids: crate::RawIngestRouteId::all(), states: crate::RawIngestRouteState::all() };
}
}
/// Safe Config-only composability projection for one logical route.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export, export_to = "../frontend/ts/bindings/ksp_app_raw_transaction_ingest_desk/dto_route/RawIngestRouteDto.ts")]
pub(crate) struct RawIngestRouteDto {
/// Stable route family used for presentation and bounded orchestration.
pub(crate) family: crate::RawIngestRouteFamily,
/// Stable operator-facing label with no physical resource identity.
pub(crate) label: String,
/// Logical network proven by Config when available.
pub(crate) network: std::option::Option<String>,
/// Safe reason explaining an unavailable route.
pub(crate) reason: std::option::Option<crate::RawIngestRouteUnavailableReason>,
/// Stable logical V1 route identifier.
pub(crate) route_id: crate::RawIngestRouteId,
/// Whether all Config requirements for the route are currently composable.
pub(crate) selectable: bool,
/// Config-level lifecycle projection; `Configured` is not a runtime health claim.
pub(crate) state: crate::RawIngestRouteState,
}
impl crate::RawIngestRouteDto {
/// Builds one route that is composable from Config without claiming runtime operability.
#[must_use]
pub(crate) fn configured(route_id: crate::RawIngestRouteId, network: &str) -> Self {
return Self {
family: route_id.family(),
label: route_id.label().to_owned(),
network: std::option::Option::Some(network.to_owned()),
reason: std::option::Option::None,
route_id,
selectable: true,
state: crate::RawIngestRouteState::Configured,
};
}
/// Builds one route that is not composable from the current Config profile.
#[must_use]
pub(crate) fn unavailable(
route_id: crate::RawIngestRouteId,
network: std::option::Option<&str>,
reason: crate::RawIngestRouteUnavailableReason,
) -> Self {
return Self {
family: route_id.family(),
label: route_id.label().to_owned(),
network: network.map(str::to_owned),
reason: std::option::Option::Some(reason),
route_id,
selectable: false,
state: crate::RawIngestRouteState::Unavailable,
};
}
}
/// Safe route inventory for one logical Raw Transaction Ingest Desk composite profile.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export, export_to = "../frontend/ts/bindings/ksp_app_raw_transaction_ingest_desk/dto_route/RawIngestProfileInventoryDto.ts")]
pub(crate) struct RawIngestProfileInventoryDto {
/// Whether this profile is the composite's autonomous default.
pub(crate) is_default: bool,
/// Logical network proven from the resolved Config profile when available.
pub(crate) network: std::option::Option<String>,
/// Stable composite profile identifier.
pub(crate) profile_id: String,
/// Logical routes applicable to this network profile in stable V1 presentation order; provider-specific routes may be absent when their Config source is not declared.
pub(crate) routes: std::vec::Vec<crate::RawIngestRouteDto>,
}
/// Deterministic Config-only route inventory returned to the frontend.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export, export_to = "../frontend/ts/bindings/ksp_app_raw_transaction_ingest_desk/dto_route/RawIngestRouteInventoryDto.ts")]
pub(crate) struct RawIngestRouteInventoryDto {
/// Composite default profile identifier.
pub(crate) default_profile: String,
/// Monotonic application-owned generation incremented after each successful inventory rebuild.
pub(crate) generation: u32,
/// Safe inventories for every validated composite profile in source order.
pub(crate) profiles: std::vec::Vec<crate::RawIngestProfileInventoryDto>,
}
#[cfg(test)]
#[path = "../unit_tests/dto_route.rs"]
mod tests;