diff --git a/packages/wasm-sdk/api-definitions.json b/packages/wasm-sdk/api-definitions.json index 67e39c11d6..4e959b3c52 100644 --- a/packages/wasm-sdk/api-definitions.json +++ b/packages/wasm-sdk/api-definitions.json @@ -848,6 +848,7 @@ "getEvonodesProposedEpochBlocksByIds": { "label": "Get Evonodes Proposed Epoch Blocks by IDs", "description": "Get proposed blocks by evonode IDs", + "supportsProof": false, "inputs": [ { "name": "epoch", @@ -867,6 +868,7 @@ "getEvonodesProposedEpochBlocksByRange": { "label": "Get Evonodes Proposed Epoch Blocks by Range", "description": "Get proposed blocks by range", + "supportsProof": false, "inputs": [ { "name": "epoch", @@ -1121,11 +1123,13 @@ "getStatus": { "label": "Get Status", "description": "Get system status", + "supportsProof": false, "inputs": [] }, "getCurrentQuorumsInfo": { "label": "Get Current Quorums Info", "description": "Get information about current quorums", + "supportsProof": false, "inputs": [] }, "getPrefundedSpecializedBalance": { @@ -1167,6 +1171,7 @@ "waitForStateTransitionResult": { "label": "Wait for State Transition Result", "description": "Internal query to wait for and retrieve the result of a previously submitted state transition", + "supportsProof": false, "inputs": [ { "name": "stateTransitionHash", diff --git a/packages/wasm-sdk/index.html b/packages/wasm-sdk/index.html index 93f8083832..a830f4dbad 100644 --- a/packages/wasm-sdk/index.html +++ b/packages/wasm-sdk/index.html @@ -161,6 +161,10 @@

Query Parameters

+ + @@ -4171,6 +4175,7 @@

Results

document.getElementById('queryType').style.display = 'none'; document.getElementById('queryInputs').style.display = 'none'; document.getElementById('proofToggleContainer').style.display = 'none'; + document.getElementById('noProofInfoContainer').style.display = 'none'; document.getElementById('executeQuery').style.display = 'none'; document.getElementById('queryDescription').style.display = 'none'; }); @@ -4190,6 +4195,7 @@

Results

// Hide inputs and button queryInputs.style.display = 'none'; document.getElementById('proofToggleContainer').style.display = 'none'; + document.getElementById('noProofInfoContainer').style.display = 'none'; executeButton.style.display = 'none'; queryDescription.style.display = 'none'; @@ -4364,12 +4370,22 @@

Results

queryInputs.style.display = 'block'; executeButton.style.display = 'block'; - // Show proof toggle for queries only + // Show proof toggle for queries that support proofs const proofToggleContainer = document.getElementById('proofToggleContainer'); + const noProofInfoContainer = document.getElementById('noProofInfoContainer'); if (operationType === 'queries') { - proofToggleContainer.style.display = 'block'; + // Check if query supports proof (defaults to true if not specified) + const supportsProof = definition?.supportsProof !== false; + if (supportsProof) { + proofToggleContainer.style.display = 'block'; + noProofInfoContainer.style.display = 'none'; + } else { + proofToggleContainer.style.display = 'none'; + noProofInfoContainer.style.display = 'block'; + } } else { proofToggleContainer.style.display = 'none'; + noProofInfoContainer.style.display = 'none'; } // Update button text based on operation type @@ -4454,6 +4470,7 @@

Results

} else { queryInputs.style.display = 'none'; document.getElementById('proofToggleContainer').style.display = 'none'; + document.getElementById('noProofInfoContainer').style.display = 'none'; executeButton.style.display = 'none'; queryDescription.style.display = 'none'; } diff --git a/packages/wasm-sdk/src/queries/system.rs b/packages/wasm-sdk/src/queries/system.rs index e34d781fd7..90d0d8999d 100644 --- a/packages/wasm-sdk/src/queries/system.rs +++ b/packages/wasm-sdk/src/queries/system.rs @@ -5,13 +5,103 @@ use serde::{Serialize, Deserialize}; use serde::ser::Serialize as _; use dash_sdk::dpp::core_types::validator_set::v0::ValidatorSetV0Getters; +// Response structures for the gRPC getStatus endpoint #[derive(Serialize, Deserialize, Debug)] #[serde(rename_all = "camelCase")] -struct PlatformStatus { - version: u32, - network: String, - block_height: Option, - core_height: Option, +struct StatusResponse { + version: StatusVersion, + node: StatusNode, + chain: StatusChain, + network: StatusNetwork, + state_sync: StatusStateSync, + time: StatusTime, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +struct StatusVersion { + software: StatusSoftware, + protocol: StatusProtocol, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +struct StatusSoftware { + dapi: String, + drive: Option, + tenderdash: Option, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +struct StatusProtocol { + tenderdash: StatusTenderdashProtocol, + drive: StatusDriveProtocol, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +struct StatusTenderdashProtocol { + p2p: u32, + block: u32, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +struct StatusDriveProtocol { + latest: u32, + current: u32, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +struct StatusNode { + id: String, + pro_tx_hash: Option, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +struct StatusChain { + catching_up: bool, + latest_block_hash: String, + latest_app_hash: String, + latest_block_height: String, + earliest_block_hash: String, + earliest_app_hash: String, + earliest_block_height: String, + max_peer_block_height: String, + core_chain_locked_height: Option, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +struct StatusNetwork { + chain_id: String, + peers_count: u32, + listening: bool, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +struct StatusStateSync { + total_synced_time: String, + remaining_time: String, + total_snapshots: u32, + chunk_process_avg_time: String, + snapshot_height: String, + snapshot_chunks_count: String, + backfilled_blocks: String, + backfill_blocks_total: String, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +struct StatusTime { + local: String, + block: Option, + genesis: Option, + epoch: Option, } #[derive(Serialize, Deserialize, Debug)] @@ -61,38 +151,160 @@ struct PathElement { #[wasm_bindgen] pub async fn get_status(sdk: &WasmSdk) -> Result { - use dash_sdk::platform::fetch_current_no_parameters::FetchCurrent; - use dash_sdk::dpp::block::extended_epoch_info::ExtendedEpochInfo; - use dash_sdk::dpp::block::extended_epoch_info::v0::ExtendedEpochInfoV0Getters; - - // Get the network from SDK - let network_str = match sdk.network { - dash_sdk::dpp::dashcore::Network::Dash => "mainnet", - dash_sdk::dpp::dashcore::Network::Testnet => "testnet", - dash_sdk::dpp::dashcore::Network::Devnet => "devnet", - dash_sdk::dpp::dashcore::Network::Regtest => "regtest", - _ => "unknown", - }.to_string(); - - // Try to fetch current epoch info to get block heights - let (block_height, core_height) = match ExtendedEpochInfo::fetch_current(sdk.as_ref()).await { - Ok(epoch_info) => { - // Extract heights from epoch info - let platform_height = Some(epoch_info.first_block_height()); - let core_height = Some(epoch_info.first_core_block_height() as u64); - (platform_height, core_height) - } - Err(_) => { - // If we can't fetch epoch info, heights remain None - (None, None) - } + use dapi_grpc::platform::v0::get_status_request::{Version, GetStatusRequestV0}; + use dapi_grpc::platform::v0::GetStatusRequest; + use dash_sdk::RequestSettings; + use rs_dapi_client::DapiRequestExecutor; + + // Create the gRPC request + let request = GetStatusRequest { + version: Some(Version::V0(GetStatusRequestV0 {})), }; - let status = PlatformStatus { - version: sdk.version(), - network: network_str, - block_height, - core_height, + // Execute the request + let response = sdk + .as_ref() + .execute(request, RequestSettings::default()) + .await + .map_err(|e| JsError::new(&format!("Failed to get status: {}", e)))?; + + // Parse the response + use dapi_grpc::platform::v0::get_status_response::Version as ResponseVersion; + + let v0_response = match response.inner.version { + Some(ResponseVersion::V0(v0)) => v0, + None => return Err(JsError::new("No version in GetStatus response")), + }; + + // Map the response to our StatusResponse structure + let status = StatusResponse { + version: StatusVersion { + software: StatusSoftware { + dapi: v0_response.version.as_ref() + .map(|v| v.software.as_ref()) + .flatten() + .map(|s| s.dapi.clone()) + .unwrap_or_else(|| "unknown".to_string()), + drive: v0_response.version.as_ref() + .and_then(|v| v.software.as_ref()) + .and_then(|s| s.drive.clone()), + tenderdash: v0_response.version.as_ref() + .and_then(|v| v.software.as_ref()) + .and_then(|s| s.tenderdash.clone()), + }, + protocol: StatusProtocol { + tenderdash: StatusTenderdashProtocol { + p2p: v0_response.version.as_ref() + .and_then(|v| v.protocol.as_ref()) + .and_then(|p| p.tenderdash.as_ref()) + .map(|t| t.p2p) + .unwrap_or(0), + block: v0_response.version.as_ref() + .and_then(|v| v.protocol.as_ref()) + .and_then(|p| p.tenderdash.as_ref()) + .map(|t| t.block) + .unwrap_or(0), + }, + drive: StatusDriveProtocol { + latest: v0_response.version.as_ref() + .and_then(|v| v.protocol.as_ref()) + .and_then(|p| p.drive.as_ref()) + .map(|d| d.latest) + .unwrap_or(0), + current: v0_response.version.as_ref() + .and_then(|v| v.protocol.as_ref()) + .and_then(|p| p.drive.as_ref()) + .map(|d| d.current) + .unwrap_or(0), + }, + }, + }, + node: StatusNode { + id: v0_response.node.as_ref() + .map(|n| hex::encode(&n.id)) + .unwrap_or_else(|| "unknown".to_string()), + pro_tx_hash: v0_response.node.as_ref() + .and_then(|n| n.pro_tx_hash.as_ref()) + .map(|hash| hex::encode(hash)), + }, + chain: StatusChain { + catching_up: v0_response.chain.as_ref() + .map(|c| c.catching_up) + .unwrap_or(false), + latest_block_hash: v0_response.chain.as_ref() + .map(|c| hex::encode(&c.latest_block_hash)) + .unwrap_or_else(|| "unknown".to_string()), + latest_app_hash: v0_response.chain.as_ref() + .map(|c| hex::encode(&c.latest_app_hash)) + .unwrap_or_else(|| "unknown".to_string()), + latest_block_height: v0_response.chain.as_ref() + .map(|c| c.latest_block_height.to_string()) + .unwrap_or_else(|| "0".to_string()), + earliest_block_hash: v0_response.chain.as_ref() + .map(|c| hex::encode(&c.earliest_block_hash)) + .unwrap_or_else(|| "unknown".to_string()), + earliest_app_hash: v0_response.chain.as_ref() + .map(|c| hex::encode(&c.earliest_app_hash)) + .unwrap_or_else(|| "unknown".to_string()), + earliest_block_height: v0_response.chain.as_ref() + .map(|c| c.earliest_block_height.to_string()) + .unwrap_or_else(|| "0".to_string()), + max_peer_block_height: v0_response.chain.as_ref() + .map(|c| c.max_peer_block_height.to_string()) + .unwrap_or_else(|| "0".to_string()), + core_chain_locked_height: v0_response.chain.as_ref() + .and_then(|c| c.core_chain_locked_height), + }, + network: StatusNetwork { + chain_id: v0_response.network.as_ref() + .map(|n| n.chain_id.clone()) + .unwrap_or_else(|| "unknown".to_string()), + peers_count: v0_response.network.as_ref() + .map(|n| n.peers_count) + .unwrap_or(0), + listening: v0_response.network.as_ref() + .map(|n| n.listening) + .unwrap_or(false), + }, + state_sync: StatusStateSync { + total_synced_time: v0_response.state_sync.as_ref() + .map(|s| s.total_synced_time.to_string()) + .unwrap_or_else(|| "0".to_string()), + remaining_time: v0_response.state_sync.as_ref() + .map(|s| s.remaining_time.to_string()) + .unwrap_or_else(|| "0".to_string()), + total_snapshots: v0_response.state_sync.as_ref() + .map(|s| s.total_snapshots) + .unwrap_or(0), + chunk_process_avg_time: v0_response.state_sync.as_ref() + .map(|s| s.chunk_process_avg_time.to_string()) + .unwrap_or_else(|| "0".to_string()), + snapshot_height: v0_response.state_sync.as_ref() + .map(|s| s.snapshot_height.to_string()) + .unwrap_or_else(|| "0".to_string()), + snapshot_chunks_count: v0_response.state_sync.as_ref() + .map(|s| s.snapshot_chunks_count.to_string()) + .unwrap_or_else(|| "0".to_string()), + backfilled_blocks: v0_response.state_sync.as_ref() + .map(|s| s.backfilled_blocks.to_string()) + .unwrap_or_else(|| "0".to_string()), + backfill_blocks_total: v0_response.state_sync.as_ref() + .map(|s| s.backfill_blocks_total.to_string()) + .unwrap_or_else(|| "0".to_string()), + }, + time: StatusTime { + local: v0_response.time.as_ref() + .map(|t| t.local.to_string()) + .unwrap_or_else(|| "0".to_string()), + block: v0_response.time.as_ref() + .and_then(|t| t.block) + .map(|b| b.to_string()), + genesis: v0_response.time.as_ref() + .and_then(|t| t.genesis) + .map(|g| g.to_string()), + epoch: v0_response.time.as_ref() + .and_then(|t| t.epoch), + }, }; serde_wasm_bindgen::to_value(&status) diff --git a/packages/wasm-sdk/test/ui-automation/tests/query-execution.spec.js b/packages/wasm-sdk/test/ui-automation/tests/query-execution.spec.js index 6a03e604f3..cfa1610556 100644 --- a/packages/wasm-sdk/test/ui-automation/tests/query-execution.spec.js +++ b/packages/wasm-sdk/test/ui-automation/tests/query-execution.spec.js @@ -496,7 +496,9 @@ test.describe('WASM SDK Query Execution Tests', () => { needsParameters: false, validateFn: (result) => { expect(result).toBeDefined(); - expect(result).toContain('version'); + expect(Object.keys(JSON.parse(result))).toEqual(expect.arrayContaining([ + 'version', 'node', 'chain', 'network', 'stateSync', 'time' + ])); } }, {