// file: crates/ksp-app-wallet-desk/tests/wallet_desk_devnet_smoke.rs // version: 2 //! Opt-in live composition smoke owned by the Wallet Desk orchestration surface. fn workspace_engine() -> ksp_core_lib::Result { let workspace = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../.."); let bootstrap = ksp_config_lib::ConfigBootstrapOptions::from_paths(workspace.join("config"), workspace.join("config/schemas")); let bootstrap = match bootstrap { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; let registry = ksp_config_lib::ConfigFileRegistry::defaults(); return match registry { std::result::Result::Ok(value) => std::result::Result::Ok(ksp_config_lib::ConfigDocumentEngine::new(bootstrap, value)), std::result::Result::Err(error) => std::result::Result::Err(error), }; } #[tokio::test(flavor = "current_thread")] #[ignore = "opt-in live Wallet Desk Devnet smoke; creates one temporary .kspwallet under the Config-selected root and performs an external getBalance request"] async fn committed_wallet_desk_composite_creates_wallet_and_reaches_devnet_balance() { let engine = workspace_engine(); assert!(engine.is_ok(), "workspace Config engine should be constructible"); let engine = match engine { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return, }; let file_id = ksp_config_lib::ConfigFileId::new(ksp_config_lib::FILE_ID_COMPOSITE_KSP_APP_WALLET_DESK); assert!(file_id.is_ok(), "Wallet Desk composite file_id should be valid"); let file_id = match file_id { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return, }; let composite = engine.load_resolved_composite(&file_id, std::option::Option::None); assert!(composite.is_ok(), "committed Wallet Desk composite should resolve"); let composite = match composite { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return, }; assert_eq!(composite.profile_id(), "devnet"); let environment = ksp_config_lib::ConfigEnvironment::load(); assert!(environment.is_ok(), "Config-owned environment snapshot should load"); let environment = match environment { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return, }; let wallet_component = composite.component("wallet"); assert!(wallet_component.is_some(), "Wallet Desk composite should contain Wallet"); let wallet_component = match wallet_component { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let wallet_config = engine.resolve_wallet_config_profile(wallet_component.resolved(), &environment); assert!(wallet_config.is_ok(), "composite-selected Wallet profile should map"); let wallet_config = match wallet_config { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return, }; assert_eq!(wallet_config.selection_source(), ksp_config_lib::ConfigProfileSelectionSource::Composite); let wallet_root = wallet_config.effective_wallets_directory().to_path_buf(); assert!(!wallet_root.as_os_str().is_empty()); let directory = tokio::fs::create_dir_all(wallet_root.as_path()).await; assert!(directory.is_ok(), "Config-selected Wallet smoke directory should be creatable"); if directory.is_err() { return; } let stamp = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH); assert!(stamp.is_ok(), "system clock should be after Unix epoch"); let stamp = match stamp { std::result::Result::Ok(value) => value.as_nanos(), std::result::Result::Err(_) => return, }; let wallet_path = wallet_root.join(std::format!("wallet-desk-pre013-smoke-{}-{stamp}.kspwallet", std::process::id())); let owner = ksp_wallet_lib::create_wallet_file( wallet_path.as_path(), ksp_wallet_lib::OwnerPassword::new("ksp-pre013-devnet-owner".to_owned()), std::option::Option::Some(ksp_wallet_lib::ViewPassword::new("ksp-pre013-devnet-view".to_owned())), ksp_wallet_lib::WalletCreateMetadataV1::new(std::option::Option::Some("pre013-devnet-smoke".to_owned()), std::vec::Vec::new()), ) .await; assert!(owner.is_ok(), "Wallet smoke file should be created through the public Wallet API"); let owner = match owner { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return, }; let locked = ksp_wallet_lib::inspect_locked_wallet_file(wallet_path.as_path()).await; assert!(locked.is_ok(), "created smoke wallet should inspect while locked"); if let std::result::Result::Ok(locked) = locked { assert_eq!(locked.format_version(), ksp_wallet_lib::KSPWALLET_FORMAT_VERSION_V2); assert!(locked.view_enabled()); } let view = ksp_wallet_lib::open_wallet_view_file(wallet_path.as_path(), ksp_wallet_lib::ViewPassword::new("ksp-pre013-devnet-view".to_owned())).await; assert!(view.is_ok(), "created smoke wallet should open with VIEW"); let view = match view { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { let _ = tokio::fs::remove_file(wallet_path.as_path()).await; return; }, }; assert_eq!(owner.pubkey(), view.pubkey()); let transport_component = composite.component("transport"); assert!(transport_component.is_some(), "Wallet Desk composite should contain Transport"); let transport_component = match transport_component { std::option::Option::Some(value) => value, std::option::Option::None => { let _ = tokio::fs::remove_file(wallet_path.as_path()).await; return; }, }; let transport = engine.resolve_transport_config_profile(transport_component.resolved(), &environment); assert!(transport.is_ok(), "composite-selected Transport profile should map"); let transport = match transport { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { let _ = tokio::fs::remove_file(wallet_path.as_path()).await; return; }, }; assert_eq!(transport.selection_source(), ksp_config_lib::ConfigProfileSelectionSource::Composite); let pool = ksp_onchain_transport_lib::HttpTransportPool::new(transport.into_settings()); assert!(pool.is_ok(), "composite-selected Transport should construct the HTTP pool"); let pool = match pool { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { let _ = tokio::fs::remove_file(wallet_path.as_path()).await; return; }, }; let role = ksp_onchain_transport_lib::HttpRoleName::new("default"); let config = ksp_onchain_transport_lib::GetBalanceConfig::new( std::option::Option::Some(ksp_onchain_transport_lib::SolanaCommitment::Confirmed), std::option::Option::None, ); let balance = pool.get_balance(&role, view.pubkey(), std::option::Option::Some(&config)).await; let cleanup = tokio::fs::remove_file(wallet_path.as_path()).await; assert!(cleanup.is_ok(), "Wallet Desk Devnet smoke wallet should be removed after the request"); assert!(balance.is_ok(), "Wallet Desk Config -> Wallet -> Transport getBalance smoke should succeed"); if let std::result::Result::Ok(balance) = balance { assert!(balance.context().slot() > 0); } }