From 25c1bb0227d9970f5673b908817d7c4962b29911 Mon Sep 17 00:00:00 2001 From: Arshavir Ter-Gabrielyan Date: Fri, 29 Nov 2024 18:50:36 +0100 Subject: [PATCH] feat(sns): Use human readable date-time in AdvanceSnsTargetVersion proposal rendering (#2896) This PR improves the rendering of AdvanceSnsTargetVersion proposals by using a human-readable date-time format rather than raw Unix timestamps. Also, a potentially confusing remark is dropped from the disclaimer. --------- Co-authored-by: Yusef Habib Co-authored-by: IDX GitHub Automation --- Cargo.lock | 1 + rs/sns/governance/BUILD.bazel | 1 + rs/sns/governance/Cargo.toml | 2 +- rs/sns/governance/src/proposal.rs | 30 ++++++++++++++++--- .../proposal/advance_sns_target_version.rs | 25 +++++++++++++++- 5 files changed, 53 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cad39cd54bc..564a235be64 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11856,6 +11856,7 @@ dependencies = [ "strum", "strum_macros", "tempfile", + "time", "tokio", "tokio-test", ] diff --git a/rs/sns/governance/BUILD.bazel b/rs/sns/governance/BUILD.bazel index 39adaf9000f..0b98210b77b 100644 --- a/rs/sns/governance/BUILD.bazel +++ b/rs/sns/governance/BUILD.bazel @@ -61,6 +61,7 @@ DEPENDENCIES = [ "@crate_index//:serde", "@crate_index//:serde_bytes", "@crate_index//:strum", + "@crate_index//:time", ] MACRO_DEPENDENCIES = [ diff --git a/rs/sns/governance/Cargo.toml b/rs/sns/governance/Cargo.toml index d66babf4a6a..86db0a34d3c 100644 --- a/rs/sns/governance/Cargo.toml +++ b/rs/sns/governance/Cargo.toml @@ -27,7 +27,6 @@ path = "tests/proposal.rs" [dependencies] build-info = { workspace = true } - async-trait = { workspace = true } base64 = { workspace = true } candid = { workspace = true } @@ -81,6 +80,7 @@ serde = { workspace = true } serde_bytes = { workspace = true } strum = { workspace = true } strum_macros = { workspace = true } +time = { workspace = true } [target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] ic-types = { path = "../../types/types" } diff --git a/rs/sns/governance/src/proposal.rs b/rs/sns/governance/src/proposal.rs index e82d3e77591..c1a30b86f86 100644 --- a/rs/sns/governance/src/proposal.rs +++ b/rs/sns/governance/src/proposal.rs @@ -52,6 +52,7 @@ use std::{ convert::TryFrom, fmt::Write, }; +use time; /// The maximum number of bytes in an SNS proposal's title. pub const PROPOSAL_TITLE_BYTES_MAX: usize = 256; @@ -1716,6 +1717,21 @@ fn validate_and_render_manage_dapp_canister_settings( } } +/// Attempts to format `` as a human-readable string. +/// +/// For example: +/// ``` +/// assert_eq!(format_timestamp(1732896850), Some("2024-11-29 16:14:10 UTC".to_string())); +/// ``` +fn format_timestamp(timestamp_seconds: u64) -> Option { + let timestamp_seconds = i64::try_from(timestamp_seconds).ok()?; + let dt_offset = time::OffsetDateTime::from_unix_timestamp(timestamp_seconds).ok()?; + let format = + time::format_description::parse("[year]-[month]-[day] [hour]:[minute]:[second] UTC") + .ok()?; + dt_offset.format(&format).ok() +} + /// Attempts to validate an `AdvanceSnsTargetVersion` action and render its human-readable text. /// Invalidates the action in the following cases: /// - There are no pending upgrades. @@ -1737,7 +1753,14 @@ fn validate_and_render_advance_sns_target_version_proposal( let (upgrade_steps, target_version) = governance_proto .validate_new_target_version(advance_sns_target_version.new_target.clone())?; - let valid_timestamp_seconds = upgrade_steps.approximate_time_of_validity_timestamp_seconds(); + let time_of_validity = { + let timestamp_seconds = upgrade_steps.approximate_time_of_validity_timestamp_seconds(); + // This fallback should not occur unless `timestamp_seconds` is outside of the range + // from +1970-01-01 00:00:00 UTC (0) + // till +9999-12-31 23:59:59 UTC (253402300799). + format_timestamp(timestamp_seconds) + .unwrap_or_else(|| format!("timestamp {} seconds", timestamp_seconds)) + }; let current_target_versions_render = render_two_versions_as_markdown_table(upgrade_steps.current(), &target_version); @@ -1753,9 +1776,8 @@ fn validate_and_render_advance_sns_target_version_proposal( ### Upgrade steps\n\n\ {upgrade_steps}\n\n\ ### Monitoring the upgrade process\n\n\ - Please note: the upgrade steps above (valid around timestamp {valid_timestamp_seconds} \ - seconds) might change during this proposal's voting period. Such changes are unlikely and \ - are subject to NNS community's approval.\n\n\ + Please note: the upgrade steps mentioned above (valid around {time_of_validity}) \ + might change during this proposal's voting period.\n\n\ The **upgrade journal** provides up-to-date information on this SNS's upgrade process:\n\n\ {upgrade_journal_url_render}" ); diff --git a/rs/sns/governance/src/proposal/advance_sns_target_version.rs b/rs/sns/governance/src/proposal/advance_sns_target_version.rs index d98bf263ae7..628b69de1ee 100644 --- a/rs/sns/governance/src/proposal/advance_sns_target_version.rs +++ b/rs/sns/governance/src/proposal/advance_sns_target_version.rs @@ -5,6 +5,7 @@ use crate::pb::v1::Governance as GovernancePb; use crate::types::test_helpers::NativeEnvironment; use futures::FutureExt; use ic_test_utilities_types::ids::canister_test_id; +use pretty_assertions::assert_eq; fn sns_version_for_tests() -> Version { Version { @@ -65,6 +66,28 @@ fn standard_governance_proto_for_tests(deployed_version: Option) -> Gov } } +#[test] +fn test_format_timestamp() { + for (expected, timestamp_seconds) in [ + (Some("1970-01-01 00:00:00 UTC"), 0), + (Some("2024-11-29 16:14:10 UTC"), 1732896850), + (Some("2038-01-19 03:14:07 UTC"), i32::MAX as u64), + (Some("4571-09-24 08:52:47 UTC"), 82102668767), + (Some("9999-12-31 23:59:59 UTC"), 253402300799), + (None, 253402300800), + (None, i64::MAX as u64), + (None, u64::MAX), + ] { + let observed = format_timestamp(timestamp_seconds); + assert_eq!( + observed, + expected.map(|s| s.to_string()), + "unexpected result from format_timestamp({})", + timestamp_seconds, + ); + } +} + #[test] fn test_validate_and_render_advance_target_version_action() { // Prepare the world. @@ -176,7 +199,7 @@ fn test_validate_and_render_advance_target_version_action() { ### Monitoring the upgrade process -Please note: the upgrade steps above (valid around timestamp 0 seconds) might change during this proposal's voting period. Such changes are unlikely and are subject to NNS community's approval. +Please note: the upgrade steps mentioned above (valid around 1970-01-01 00:00:00 UTC) might change during this proposal's voting period. The **upgrade journal** provides up-to-date information on this SNS's upgrade process: