Skip to main content

ic_query/sns/report/
mod.rs

1//! Module: sns::report
2//!
3//! Responsibility: assemble the reusable SNS query and report surface.
4//! Does not own: CLI parsing, process output, or generic cache-file mechanics.
5//! Boundary: keeps SNS lookup, live sources, caches, reports, and renderers together.
6
7#[cfg(feature = "host")]
8mod assemble;
9#[cfg(feature = "host")]
10mod build;
11#[cfg(feature = "host")]
12mod cache_attempt;
13#[cfg(feature = "host")]
14mod cache_paths;
15#[cfg(feature = "host")]
16mod cache_refresh;
17#[cfg(feature = "host")]
18mod cache_status;
19#[cfg(feature = "host")]
20mod cache_storage;
21#[cfg(feature = "host")]
22mod cache_summary;
23#[cfg(feature = "host")]
24mod catalog_cache;
25#[cfg(feature = "host")]
26mod live;
27#[cfg(feature = "host")]
28mod lookup;
29mod model;
30#[cfg(feature = "host")]
31mod neurons_cache;
32#[cfg(feature = "host")]
33mod proposals_cache;
34#[cfg(feature = "host")]
35mod reward_checkpoint_file;
36mod reward_diff;
37#[cfg(feature = "host")]
38mod source;
39mod text;
40#[cfg(feature = "host")]
41mod view;
42
43#[cfg(all(test, feature = "host"))]
44mod tests;
45
46#[cfg(feature = "host")]
47use crate::hex::hex_bytes;
48#[cfg(all(test, feature = "host"))]
49use crate::icrc::{
50    IcrcMetadataValueKind,
51    ledger::{IcrcMetadataValue, metadata_row},
52};
53#[cfg(all(test, feature = "host"))]
54use crate::subnet_catalog::{MAINNET_NETWORK, format_utc_timestamp_secs};
55#[cfg(all(test, feature = "host"))]
56use neurons_cache::{
57    SNS_NEURONS_CACHE_LIST_REPORT_SCHEMA_VERSION, SNS_NEURONS_CACHE_SCHEMA_VERSION,
58    SNS_NEURONS_CACHE_STATUS_REPORT_SCHEMA_VERSION,
59};
60#[cfg(all(test, feature = "host"))]
61pub(in crate::sns::report) use source::validate_mainnet_sns_reward_neuron_page;
62#[cfg(feature = "host")]
63pub(in crate::sns::report) use source::{
64    JoinedMainnetSnsInventory, SNS_SWAP_QUERY_COUNT, SNS_UPGRADE_QUERY_COUNT,
65    SnsRewardCollectionState,
66};
67
68#[cfg(feature = "host")]
69pub use build::{
70    build_sns_canister_report, build_sns_canister_report_with_source, build_sns_info_report,
71    build_sns_info_report_with_source, build_sns_list_report, build_sns_list_report_with_source,
72    build_sns_metrics_report, build_sns_metrics_report_with_source, build_sns_neuron_detail_report,
73    build_sns_neuron_detail_report_with_source, build_sns_neurons_report,
74    build_sns_neurons_report_with_source, build_sns_params_report,
75    build_sns_params_report_with_source, build_sns_proposal_report,
76    build_sns_proposal_report_with_source, build_sns_proposals_report,
77    build_sns_proposals_report_with_progress, build_sns_proposals_report_with_source,
78    build_sns_reward_checkpoint_report, build_sns_reward_checkpoint_report_with_source,
79    build_sns_swap_report, build_sns_swap_report_with_source, build_sns_token_report,
80    build_sns_token_report_with_source, build_sns_upgrade_report,
81    build_sns_upgrade_report_with_source,
82};
83#[cfg(feature = "host")]
84pub(in crate::sns::report) use cache_summary::{
85    build_sns_cache_list_report, find_sns_cache_summary_by_id, load_sns_cache_summary_at,
86    parse_sns_root_canister_input,
87};
88#[cfg(feature = "host")]
89pub use catalog_cache::{
90    DEFAULT_SNS_CATALOG_REFRESH_LOCK_STALE_SECONDS, DEFAULT_SNS_CATALOG_STALE_AFTER_SECONDS,
91    SnsCatalogCacheRequest, SnsCatalogRefreshReport, SnsCatalogRefreshRequest,
92    build_sns_list_report_from_cache, build_sns_list_report_from_cache_or_refresh,
93    build_sns_list_report_from_cache_or_refresh_with_source, refresh_sns_catalog,
94    refresh_sns_catalog_with_source, sns_catalog_cache_path, sns_catalog_refresh_lock_path,
95    sns_catalog_refresh_report_text,
96};
97#[cfg(feature = "host")]
98pub use live::LiveSnsSource;
99pub use model::{
100    DEFAULT_SNS_METRICS_TIME_WINDOW_SECONDS, MAX_SNS_METRICS_TIME_WINDOW_SECONDS,
101    SnsCanisterCallType, SnsCanisterCycleBalanceStatus, SnsCanisterGap, SnsCanisterGapKind,
102    SnsCanisterHealthQueryGap, SnsCanisterMethod, SnsCanisterReport, SnsCanisterRole,
103    SnsCanisterRow, SnsCanisterStatus, SnsCustomProposalCriticality, SnsDefaultFollowees,
104    SnsDefaultFolloweesRow, SnsGovernanceParameters, SnsInfoReport, SnsListReport, SnsListRequest,
105    SnsListRow, SnsListSort, SnsLookupRequest, SnsMaturityDisbursementRow, SnsMetricsReport,
106    SnsMetricsRequest, SnsNeuronAccount, SnsNeuronDetail, SnsNeuronDetailReport,
107    SnsNeuronDissolveState, SnsNeuronFolloweeRow, SnsNeuronFolloweesRow, SnsNeuronPermissionList,
108    SnsNeuronPermissionRow, SnsNeuronPermissionValue, SnsNeuronRow, SnsNeuronTopicFolloweesRow,
109    SnsParamsReport, SnsPendingUpgrade, SnsPolicyObservationStatus, SnsProposalAction,
110    SnsProposalBallotRow, SnsProposalDecisionState, SnsProposalEligibilityFilter,
111    SnsProposalFailureReason, SnsProposalReport, SnsProposalRequest, SnsProposalRow,
112    SnsProposalSortDirection, SnsProposalStatusFilter, SnsProposalTally, SnsProposalTopicFilter,
113    SnsProposalVote, SnsProposalsReport, SnsProposalsRequest, SnsProposalsSort,
114    SnsRewardAllocationStatus, SnsRewardCheckpointReport, SnsRewardCheckpointRow,
115    SnsRewardCheckpointValidationError, SnsRewardCollectionStatus, SnsRewardDiffCheckpointRef,
116    SnsRewardDiffInvalidReason, SnsRewardDiffInvalidReasonKind, SnsRewardDiffReport,
117    SnsRewardDiffRow, SnsRewardEvent, SnsRewardProposalId, SnsRunningVersionResponse,
118    SnsSwapComponent, SnsSwapDerivedState, SnsSwapLifecycle,
119    SnsSwapNeuronBasketConstructionParameters, SnsSwapQueryGap, SnsSwapReport,
120    SnsSwapSaleParameters, SnsTokenMetadataRow, SnsTokenReport, SnsTokenStandardRow,
121    SnsTreasuryKind, SnsTreasuryMetricRow, SnsUpgradeQueryGap, SnsUpgradeReport, SnsVersion,
122    SnsVotingPowerMetrics, SnsVotingRewardsParameters, sns_neuron_permission_name,
123    validate_sns_reward_checkpoint_report,
124};
125#[cfg(feature = "host")]
126pub(in crate::sns::report) use model::{
127    SNS_PROPOSAL_STATUS_ADOPTED_CODE, SNS_PROPOSAL_STATUS_REJECTED_CODE,
128};
129#[cfg(all(test, feature = "host"))]
130pub(in crate::sns::report) use model::{
131    SNS_PROPOSAL_STATUS_EXECUTED_CODE, SNS_PROPOSAL_STATUS_OPEN_CODE,
132};
133#[cfg(feature = "host")]
134pub use model::{
135    SnsCacheListReport, SnsCacheListRequest, SnsCacheStatusReport, SnsCacheStatusRequest,
136    SnsCacheSummary, SnsHostError, SnsNeuronRequest, SnsNeuronsRefreshReport,
137    SnsNeuronsRefreshRequest, SnsNeuronsReport, SnsNeuronsRequest, SnsNeuronsSort,
138    SnsProposalsRefreshReport, SnsProposalsRefreshRequest, SnsRefreshAttemptStatus,
139    SnsRewardCheckpointRequest,
140};
141pub(in crate::sns::report) use model::{
142    SnsRewardCheckpointSummary, recompute_reward_checkpoint_summary,
143};
144#[cfg(feature = "host")]
145pub(in crate::sns::report) use model::{
146    validate_sns_reward_checkpoint_parameter_evidence, validate_sns_reward_event_evidence,
147    validate_sns_reward_running_version_evidence,
148};
149#[cfg(feature = "host")]
150pub use neurons_cache::{
151    DEFAULT_SNS_NEURONS_REFRESH_LOCK_STALE_SECONDS, build_sns_neurons_cache_list_report,
152    build_sns_neurons_cache_status_report, refresh_sns_neurons_cache,
153    refresh_sns_neurons_cache_with_progress, refresh_sns_neurons_cache_with_source,
154    sns_neurons_cache_path, sns_neurons_refresh_attempt_path, sns_neurons_refresh_lock_path,
155};
156#[cfg(feature = "host")]
157pub use proposals_cache::{
158    DEFAULT_SNS_PROPOSALS_REFRESH_LOCK_STALE_SECONDS, build_sns_proposals_cache_list_report,
159    build_sns_proposals_cache_status_report, refresh_sns_proposals_cache,
160    refresh_sns_proposals_cache_with_progress, refresh_sns_proposals_cache_with_source,
161    sns_proposals_cache_path, sns_proposals_refresh_attempt_path, sns_proposals_refresh_lock_path,
162};
163#[cfg(feature = "host")]
164pub use reward_checkpoint_file::{
165    build_sns_reward_diff_report_from_paths, load_sns_reward_checkpoint,
166};
167pub use reward_diff::build_sns_reward_diff_report;
168#[cfg(feature = "host")]
169pub use source::{
170    MainnetSns, MainnetSnsCanisterInventory, MainnetSnsCanisters, MainnetSnsInventory,
171    MainnetSnsLifecycle, MainnetSnsMetadata, MainnetSnsMetrics, MainnetSnsNeuron,
172    MainnetSnsNeuronPage, MainnetSnsNeurons, MainnetSnsProposal, MainnetSnsProposalPage,
173    MainnetSnsProposals, MainnetSnsRewardNeuronPage, MainnetSnsSwap, MainnetSnsToken,
174    MainnetSnsUpgrade, SnsCanisterSource, SnsCatalogSource, SnsDiscoverySource, SnsMetricsSource,
175    SnsNeuronId, SnsNeuronSource, SnsNeuronsSource, SnsParamsSource, SnsProposalSource,
176    SnsProposalsSource, SnsRewardSource, SnsSourceRequest, SnsSwapSource, SnsTokenSource,
177    SnsUpgradeSource,
178};
179pub use text::{
180    sns_canister_report_text, sns_info_report_text, sns_list_report_text, sns_metrics_report_text,
181    sns_neuron_detail_report_text, sns_params_report_text, sns_proposal_report_text,
182    sns_proposals_report_text, sns_reward_checkpoint_report_text, sns_reward_diff_report_text,
183    sns_swap_report_text, sns_token_report_text, sns_upgrade_report_text,
184};
185#[cfg(feature = "host")]
186pub use text::{
187    sns_neurons_cache_list_report_text, sns_neurons_cache_status_report_text,
188    sns_neurons_refresh_report_text, sns_neurons_report_text, sns_proposals_cache_list_report_text,
189    sns_proposals_cache_status_report_text, sns_proposals_refresh_report_text,
190};
191
192pub const DEFAULT_SNS_SOURCE_ENDPOINT: &str = "https://icp-api.io";
193pub const MAINNET_SNS_WASM_CANISTER_ID: &str = "qaa6y-5yaaa-aaaaa-aaafa-cai";
194#[cfg(feature = "host")]
195/// Largest page size accepted by an SNS refresh request.
196pub const SNS_REFRESH_MAX_PAGE_SIZE: u32 = 100;
197
198#[cfg(feature = "host")]
199const SNS_LIST_REPORT_SCHEMA_VERSION: u32 = 1;
200#[cfg(feature = "host")]
201const SNS_CANISTER_REPORT_SCHEMA_VERSION: u32 = 1;
202#[cfg(feature = "host")]
203const SNS_INFO_REPORT_SCHEMA_VERSION: u32 = 1;
204#[cfg(feature = "host")]
205const SNS_METRICS_REPORT_SCHEMA_VERSION: u32 = 1;
206#[cfg(feature = "host")]
207const SNS_TOKEN_REPORT_SCHEMA_VERSION: u32 = 1;
208#[cfg(feature = "host")]
209const SNS_PARAMS_REPORT_SCHEMA_VERSION: u32 = 1;
210#[cfg(feature = "host")]
211const SNS_SWAP_REPORT_SCHEMA_VERSION: u32 = 1;
212#[cfg(feature = "host")]
213const SNS_UPGRADE_REPORT_SCHEMA_VERSION: u32 = 1;
214#[cfg(feature = "host")]
215const SNS_PROPOSAL_REPORT_SCHEMA_VERSION: u32 = 1;
216#[cfg(feature = "host")]
217const SNS_PROPOSALS_REPORT_SCHEMA_VERSION: u32 = 1;
218#[cfg(feature = "host")]
219const SNS_NEURONS_REPORT_SCHEMA_VERSION: u32 = 1;
220#[cfg(feature = "host")]
221const SNS_NEURON_DETAIL_REPORT_SCHEMA_VERSION: u32 = 1;
222const SNS_REWARD_CHECKPOINT_REPORT_SCHEMA_VERSION: u32 = 1;
223const SNS_REWARD_CHECKPOINT_MAX_NEURONS: u64 = 200_000;
224const SNS_REWARD_CHECKPOINT_PAGE_SIZE: u32 = 100;
225const SNS_REWARD_DIFF_REPORT_SCHEMA_VERSION: u32 = 1;
226const COMPACT_PRINCIPAL_CHARS: usize = 5;
227#[cfg(feature = "host")]
228const SNS_METADATA_CONCURRENCY: usize = 16;
229
230#[cfg(feature = "host")]
231pub(in crate::sns::report) fn enforce_mainnet_network(network: &str) -> Result<(), SnsHostError> {
232    crate::network::enforce_mainnet_network_with(network, |network| {
233        SnsHostError::UnsupportedNetwork { network }
234    })
235}
236
237pub(super) fn short_principal(value: &str) -> String {
238    value.chars().take(COMPACT_PRINCIPAL_CHARS).collect()
239}