// file: crates/ksp-app-raw-transaction-ingest-desk/src/dto_route.rs // version: 5 //! 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 { 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, } /// Safe mono-route runtime acknowledgement containing only logical identity and lifecycle state. #[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/RawIngestRouteRuntimeDto.ts")] pub(crate) struct RawIngestRouteRuntimeDto { /// Confirmed/finalized commitment bound to the active Worker. pub(crate) commitment: crate::RawIngestCommitment, /// Inventory generation revalidated before Store opening. pub(crate) inventory_generation: u32, /// Logical network bound identically to Store and Worker. pub(crate) network: String, /// Safe logical network-profile identifier. pub(crate) profile_id: String, /// Exact logical route owned by the mono-route Worker. pub(crate) route_id: crate::RawIngestRouteId, /// Safe application-owned projection of current Worker lifecycle. pub(crate) state: crate::RawIngestRouteState, } /// 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 { 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, /// Stable lifecycle state vocabulary reserved for runtime projections. pub(crate) states: std::vec::Vec, } 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, /// Safe reason explaining an unavailable route. pub(crate) reason: std::option::Option, /// 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, /// 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, } /// 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, } #[cfg(test)] #[path = "../unit_tests/dto_route.rs"] mod tests;