diff --git a/rs/nervous_system/agent/src/nns/management_canister.rs b/rs/nervous_system/agent/src/nns/management_canister.rs index e69de29bb2d..8b137891791 100644 --- a/rs/nervous_system/agent/src/nns/management_canister.rs +++ b/rs/nervous_system/agent/src/nns/management_canister.rs @@ -0,0 +1 @@ + diff --git a/rs/nervous_system/agent/src/sns/governance.rs b/rs/nervous_system/agent/src/sns/governance.rs index 35c873536bf..d209aae6722 100644 --- a/rs/nervous_system/agent/src/sns/governance.rs +++ b/rs/nervous_system/agent/src/sns/governance.rs @@ -1,17 +1,26 @@ use crate::{null_request::NullRequest, CallCanisters}; use ic_base_types::PrincipalId; use ic_sns_governance::pb::v1::{ - manage_neuron, GetMetadataRequest, GetMetadataResponse, GetMode, GetModeResponse, - GetRunningSnsVersionRequest, GetRunningSnsVersionResponse, ManageNeuron, ManageNeuronResponse, - NervousSystemParameters, NeuronId, + manage_neuron, manage_neuron_response, GetMetadataRequest, GetMetadataResponse, GetMode, + GetModeResponse, GetRunningSnsVersionRequest, GetRunningSnsVersionResponse, ManageNeuron, + ManageNeuronResponse, NervousSystemParameters, NeuronId, Proposal, ProposalId, }; use serde::{Deserialize, Serialize}; +use std::error::Error; #[derive(Copy, Clone, Debug, Deserialize, Serialize)] pub struct GovernanceCanister { pub canister_id: PrincipalId, } +#[derive(Debug, thiserror::Error)] +pub enum SubmitProposalError { + #[error("Failed to call SNS Governance")] + CallGovernanceError(#[source] C), + #[error("SNS Governance did not confirm that the proposal was made: {0:?}")] + ProposalNotMade(ManageNeuronResponse), +} + impl GovernanceCanister { pub async fn metadata( &self, @@ -57,6 +66,33 @@ impl GovernanceCanister { }; agent.call(self.canister_id, request).await } + + pub async fn submit_proposal( + &self, + agent: &C, + neuron_id: NeuronId, + proposal: Proposal, + ) -> Result> { + let response = self + .manage_neuron( + agent, + neuron_id, + manage_neuron::Command::MakeProposal(proposal), + ) + .await + .map_err(SubmitProposalError::CallGovernanceError)?; + + if let Some(manage_neuron_response::Command::MakeProposal( + manage_neuron_response::MakeProposalResponse { + proposal_id: Some(proposal_id), + }, + )) = response.command + { + Ok(proposal_id) + } else { + Err(SubmitProposalError::ProposalNotMade(response)) + } + } } impl GovernanceCanister { diff --git a/rs/sns/cli/src/upgrade_sns_controlled_canister.rs b/rs/sns/cli/src/upgrade_sns_controlled_canister.rs index 6533b9ce597..d64f0086801 100644 --- a/rs/sns/cli/src/upgrade_sns_controlled_canister.rs +++ b/rs/sns/cli/src/upgrade_sns_controlled_canister.rs @@ -139,12 +139,12 @@ pub async fn exec(args: UpgradeSnsControlledCanisterArgs, agent: &Agent) -> Resu canister_id: sns.governance.canister_id, }; - let command = manage_neuron::Command::MakeProposal(Proposal { + let proposal = Proposal { title: format!( "Upgrade SNS-controlled canister {}", target_canister_id.get() ), - summary: format!(""), + summary: format!(""), // TODO: allow the user to specify a summary url: proposal_url.to_string(), action: Some(Action::UpgradeSnsControlledCanister( UpgradeSnsControlledCanister { @@ -155,23 +155,12 @@ pub async fn exec(args: UpgradeSnsControlledCanisterArgs, agent: &Agent) -> Resu // TODO: use `uploaded_chunk_hashes` / `sha256_hash` }, )), - }); + }; - let ManageNeuronResponse { command } = sns_governance - .manage_neuron(agent, sns_neuron_id.0, command) + let proposal_id = sns_governance + .submit_proposal(agent, sns_neuron_id.0, proposal) .await?; - let proposal_id = match command { - Some(manage_neuron_response::Command::MakeProposal( - manage_neuron_response::MakeProposalResponse { - proposal_id: Some(proposal_id), - }, - )) => proposal_id, - _ => { - bail!("SNS Governance did not confirm that the proposal was made ({command:?}).") - } - }; - let proposal_url = format!( "https://nns.ic0.app/proposal/?u={}&proposal={}", root_canister_id.get(),