From 683c174f071df830b7a6a09f2e1c6ef4b66516fe Mon Sep 17 00:00:00 2001 From: Andre Popovitch Date: Tue, 3 Sep 2024 06:28:26 -0500 Subject: [PATCH] chore(sns): Move ClaimSwapNeuronsRequest into Swap, so the version in Governance can be changed independently --- .../swap/proto/ic_sns_swap/pb/v1/swap.proto | 110 ++++++++++++ rs/sns/swap/protobuf_generator/src/lib.rs | 4 + rs/sns/swap/src/clients.rs | 8 +- rs/sns/swap/src/gen/ic_sns_swap.pb.v1.rs | 159 +++++++++++++++++- rs/sns/swap/src/swap.rs | 65 +++---- rs/sns/swap/src/types.rs | 46 ++++- rs/sns/swap/tests/common/doubles.rs | 9 +- rs/sns/swap/tests/swap.rs | 33 ++-- 8 files changed, 372 insertions(+), 62 deletions(-) diff --git a/rs/sns/swap/proto/ic_sns_swap/pb/v1/swap.proto b/rs/sns/swap/proto/ic_sns_swap/pb/v1/swap.proto index 4edea3de7222..c7d55bdf15f2 100644 --- a/rs/sns/swap/proto/ic_sns_swap/pb/v1/swap.proto +++ b/rs/sns/swap/proto/ic_sns_swap/pb/v1/swap.proto @@ -1548,3 +1548,113 @@ message NotifyPaymentFailureRequest {} message NotifyPaymentFailureResponse { optional Ticket ticket = 1; } + + +// TODO(NNS1-3306): Remove this message once SNS Governance uses the same request type. +// A sequence of NeuronIds, which is used to get prost to generate a type isomorphic to Option>. +message NeuronIds { + repeated NeuronId neuron_ids = 1; +} + + +// The request for the `claim_swap_neurons` method. +// Copied from sns governance.proto. TODO(NNS1-3306): Remove this message once +// SNS Governance uses the same request type. +message ClaimSwapNeuronsRequest { + // This type has been replaced by NeuronRecipe and should not be used. + // TODO(NNS1-3198): Remove this message once `NeuronRecipe` is used systematically. + message NeuronParameters { + reserved "memo"; + reserved 4; + + // The PrincipalId that will have permissions when the neuron is created. + // The permissions that are granted are controlled my + // `NervousSystemParameters::neuron_claimer_permissions`. This field + // is required. + ic_base_types.pb.v1.PrincipalId controller = 1; + + // For Community Fund participants, in addition to the controller (that is + // set to the NNS governance), this is another PrincipalId with permissions. + // Specifically, the PrincipalId who is the controller of the NNS neuron + // that invested in the decentralization sale via the Community Fund will + // be granted the following permissions: + // - NeuronPermissionType::SubmitProposal + // - NeuronPermissionType::Vote + // This field is not set for other types of participants, therefore it is optional. + ic_base_types.pb.v1.PrincipalId hotkey = 2; + + // The stake of the neuron in e8s (10E-8 of a token) that the neuron will be + // created with. This field is required. + optional uint64 stake_e8s = 3; + + // The duration in seconds that the neuron's dissolve delay will be set to. Neurons + // that are for Community Fund investors will be automatically set to dissolving, + // while direct investors will be automatically set to non-dissolving. + optional uint64 dissolve_delay_seconds = 5; + + // The ID of the NNS neuron whose Community Fund participation resulted in the + // creation of this SNS neuron. + optional uint64 source_nns_neuron_id = 6; + + // The ID of the SNS Neuron to be created for the participant. If a Neuron with + // this NeuronId already exists in SNS Governance, the `ClaimSwapNeuronsResponse` + // will return a`ClaimedSwapNeuronStatus::AlreadyExists` for this NeuronId. + // This field is required. + optional NeuronId neuron_id = 7; + + // The list of NeuronIds that the created Neuron will follow on all SNS Proposal + // Actions known to governance at the time. Additional followees and following + // relations can be added after neuron creation. + repeated NeuronId followees = 8; + } + + // Replacement for NeuronParameters. Contains the information needed to set up + // a neuron for a swap participant. + message NeuronRecipe { + // The info that for a participant in the Neurons' Fund + message NeuronsFund { + // The neuron ID of the NNS neuron that participated in the Neurons' Fund. + optional uint64 nns_neuron_id = 1; + // The controller of the NNS neuron that participated in the Neurons' Fund. + optional ic_base_types.pb.v1.PrincipalId nns_neuron_controller = 2; + // The hotkeys of the NNS neuron that participated in the Neurons' Fund. + optional ic_nervous_system.pb.v1.Principals nns_neuron_hotkeys = 3; + } + + // The info that for a direct participant + message Direct {} + + // The principal that should be the controller of the SNS neuron + optional ic_base_types.pb.v1.PrincipalId controller = 1; + // The ID of the SNS neuron + optional NeuronId neuron_id = 2; + + // The SNS neuron's stake in e8s (10E-8 of a token) + optional uint64 stake_e8s = 3; + + // The duration in seconds that the neuron's dissolve delay will be set to. + optional uint64 dissolve_delay_seconds = 4; + // The neurons this neuron should follow + optional NeuronIds followees = 5; + + oneof participant { + Direct direct = 6; + NeuronsFund neurons_fund = 7; + } + } + + // Needed to cause prost to generate a type isomorphic to + // Optional>. + message NeuronRecipes { + repeated NeuronRecipe neuron_recipes = 1; + } + + // The set of parameters that define the neurons created in `claim_swap_neurons`. For + // each NeuronRecipe, one neuron will be created. + optional NeuronRecipes neuron_recipes = 2; + + // The set of parameters that define the neurons created in `claim_swap_neurons`. For + // each NeuronParameter, one neuron will be created. + // Deprecated. Use [`neuron_recipes`] instead. + repeated NeuronParameters neuron_parameters = 1 [deprecated = true]; +} \ No newline at end of file diff --git a/rs/sns/swap/protobuf_generator/src/lib.rs b/rs/sns/swap/protobuf_generator/src/lib.rs index 7eb96ae0a9c2..fcdca7e381e2 100644 --- a/rs/sns/swap/protobuf_generator/src/lib.rs +++ b/rs/sns/swap/protobuf_generator/src/lib.rs @@ -61,6 +61,10 @@ pub fn generate_prost_files(proto: ProtoPaths<'_>, out: &Path) { ".ic_sns_swap.pb.v1.IdealMatchedParticipationFunction", "#[derive(Eq)]", ); + config.type_attribute( + ".ic_sns_swap.pb.v1.NeuronId", + "#[derive(Eq, Ord, PartialOrd)]", + ); // Add serde_bytes for efficiently parsing blobs. let blob_fields = vec!["NeuronId.id"]; diff --git a/rs/sns/swap/src/clients.rs b/rs/sns/swap/src/clients.rs index e15bb8e4d81f..d67137853a38 100644 --- a/rs/sns/swap/src/clients.rs +++ b/rs/sns/swap/src/clients.rs @@ -1,12 +1,12 @@ use crate::pb::v1::{ - CanisterCallError, SetDappControllersRequest, SetDappControllersResponse, - SettleNeuronsFundParticipationRequest, SettleNeuronsFundParticipationResponse, + CanisterCallError, ClaimSwapNeuronsRequest, SetDappControllersRequest, + SetDappControllersResponse, SettleNeuronsFundParticipationRequest, + SettleNeuronsFundParticipationResponse, }; use async_trait::async_trait; use ic_base_types::CanisterId; use ic_sns_governance::pb::v1::{ - ClaimSwapNeuronsRequest, ClaimSwapNeuronsResponse, ManageNeuron, ManageNeuronResponse, SetMode, - SetModeResponse, + ClaimSwapNeuronsResponse, ManageNeuron, ManageNeuronResponse, SetMode, SetModeResponse, }; #[async_trait] diff --git a/rs/sns/swap/src/gen/ic_sns_swap.pb.v1.rs b/rs/sns/swap/src/gen/ic_sns_swap.pb.v1.rs index 9889f5617a97..4094f794b28f 100644 --- a/rs/sns/swap/src/gen/ic_sns_swap.pb.v1.rs +++ b/rs/sns/swap/src/gen/ic_sns_swap.pb.v1.rs @@ -1546,7 +1546,15 @@ pub mod settle_neurons_fund_participation_response { } /// The id of a specific neuron, which equals the neuron's subaccount on /// the ledger canister (the account that holds the neuron's staked tokens). -#[derive(candid::CandidType, candid::Deserialize, serde::Serialize, comparable::Comparable)] +#[derive( + candid::CandidType, + candid::Deserialize, + serde::Serialize, + comparable::Comparable, + Eq, + Ord, + PartialOrd, +)] #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct NeuronId { @@ -2147,6 +2155,155 @@ pub struct NotifyPaymentFailureResponse { #[prost(message, optional, tag = "1")] pub ticket: ::core::option::Option, } +/// TODO(NNS1-3306): Remove this message once SNS Governance uses the same request type. +/// A sequence of NeuronIds, which is used to get prost to generate a type isomorphic to Option>. +#[derive(candid::CandidType, candid::Deserialize, serde::Serialize, comparable::Comparable)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct NeuronIds { + #[prost(message, repeated, tag = "1")] + pub neuron_ids: ::prost::alloc::vec::Vec, +} +/// The request for the `claim_swap_neurons` method. +/// Copied from sns governance.proto. TODO(NNS1-3306): Remove this message once +/// SNS Governance uses the same request type. +#[derive(candid::CandidType, candid::Deserialize, serde::Serialize, comparable::Comparable)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ClaimSwapNeuronsRequest { + /// The set of parameters that define the neurons created in `claim_swap_neurons`. For + /// each NeuronRecipe, one neuron will be created. + #[prost(message, optional, tag = "2")] + pub neuron_recipes: ::core::option::Option, + /// The set of parameters that define the neurons created in `claim_swap_neurons`. For + /// each NeuronParameter, one neuron will be created. + /// Deprecated. Use \[`neuron_recipes`\] instead. + #[deprecated] + #[prost(message, repeated, tag = "1")] + pub neuron_parameters: ::prost::alloc::vec::Vec, +} +/// Nested message and enum types in `ClaimSwapNeuronsRequest`. +pub mod claim_swap_neurons_request { + /// This type has been replaced by NeuronRecipe and should not be used. + /// TODO(NNS1-3198): Remove this message once `NeuronRecipe` is used systematically. + #[derive(candid::CandidType, candid::Deserialize, serde::Serialize, comparable::Comparable)] + #[allow(clippy::derive_partial_eq_without_eq)] + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct NeuronParameters { + /// The PrincipalId that will have permissions when the neuron is created. + /// The permissions that are granted are controlled my + /// `NervousSystemParameters::neuron_claimer_permissions`. This field + /// is required. + #[prost(message, optional, tag = "1")] + pub controller: ::core::option::Option<::ic_base_types::PrincipalId>, + /// For Community Fund participants, in addition to the controller (that is + /// set to the NNS governance), this is another PrincipalId with permissions. + /// Specifically, the PrincipalId who is the controller of the NNS neuron + /// that invested in the decentralization sale via the Community Fund will + /// be granted the following permissions: + /// - NeuronPermissionType::SubmitProposal + /// - NeuronPermissionType::Vote + /// This field is not set for other types of participants, therefore it is optional. + #[prost(message, optional, tag = "2")] + pub hotkey: ::core::option::Option<::ic_base_types::PrincipalId>, + /// The stake of the neuron in e8s (10E-8 of a token) that the neuron will be + /// created with. This field is required. + #[prost(uint64, optional, tag = "3")] + pub stake_e8s: ::core::option::Option, + /// The duration in seconds that the neuron's dissolve delay will be set to. Neurons + /// that are for Community Fund investors will be automatically set to dissolving, + /// while direct investors will be automatically set to non-dissolving. + #[prost(uint64, optional, tag = "5")] + pub dissolve_delay_seconds: ::core::option::Option, + /// The ID of the NNS neuron whose Community Fund participation resulted in the + /// creation of this SNS neuron. + #[prost(uint64, optional, tag = "6")] + pub source_nns_neuron_id: ::core::option::Option, + /// The ID of the SNS Neuron to be created for the participant. If a Neuron with + /// this NeuronId already exists in SNS Governance, the `ClaimSwapNeuronsResponse` + /// will return a`ClaimedSwapNeuronStatus::AlreadyExists` for this NeuronId. + /// This field is required. + #[prost(message, optional, tag = "7")] + pub neuron_id: ::core::option::Option, + /// The list of NeuronIds that the created Neuron will follow on all SNS Proposal + /// Actions known to governance at the time. Additional followees and following + /// relations can be added after neuron creation. + #[prost(message, repeated, tag = "8")] + pub followees: ::prost::alloc::vec::Vec, + } + /// Replacement for NeuronParameters. Contains the information needed to set up + /// a neuron for a swap participant. + #[derive(candid::CandidType, candid::Deserialize, serde::Serialize, comparable::Comparable)] + #[allow(clippy::derive_partial_eq_without_eq)] + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct NeuronRecipe { + /// The principal that should be the controller of the SNS neuron + #[prost(message, optional, tag = "1")] + pub controller: ::core::option::Option<::ic_base_types::PrincipalId>, + /// The ID of the SNS neuron + #[prost(message, optional, tag = "2")] + pub neuron_id: ::core::option::Option, + /// The SNS neuron's stake in e8s (10E-8 of a token) + #[prost(uint64, optional, tag = "3")] + pub stake_e8s: ::core::option::Option, + /// The duration in seconds that the neuron's dissolve delay will be set to. + #[prost(uint64, optional, tag = "4")] + pub dissolve_delay_seconds: ::core::option::Option, + /// The neurons this neuron should follow + #[prost(message, optional, tag = "5")] + pub followees: ::core::option::Option, + #[prost(oneof = "neuron_recipe::Participant", tags = "6, 7")] + pub participant: ::core::option::Option, + } + /// Nested message and enum types in `NeuronRecipe`. + pub mod neuron_recipe { + /// The info that for a participant in the Neurons' Fund + #[derive( + candid::CandidType, candid::Deserialize, serde::Serialize, comparable::Comparable, + )] + #[allow(clippy::derive_partial_eq_without_eq)] + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct NeuronsFund { + /// The neuron ID of the NNS neuron that participated in the Neurons' Fund. + #[prost(uint64, optional, tag = "1")] + pub nns_neuron_id: ::core::option::Option, + /// The controller of the NNS neuron that participated in the Neurons' Fund. + #[prost(message, optional, tag = "2")] + pub nns_neuron_controller: ::core::option::Option<::ic_base_types::PrincipalId>, + /// The hotkeys of the NNS neuron that participated in the Neurons' Fund. + #[prost(message, optional, tag = "3")] + pub nns_neuron_hotkeys: + ::core::option::Option<::ic_nervous_system_proto::pb::v1::Principals>, + } + /// The info that for a direct participant + #[derive( + candid::CandidType, candid::Deserialize, serde::Serialize, comparable::Comparable, + )] + #[allow(clippy::derive_partial_eq_without_eq)] + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct Direct {} + #[derive( + candid::CandidType, candid::Deserialize, serde::Serialize, comparable::Comparable, + )] + #[allow(clippy::derive_partial_eq_without_eq)] + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Participant { + #[prost(message, tag = "6")] + Direct(Direct), + #[prost(message, tag = "7")] + NeuronsFund(NeuronsFund), + } + } + /// Needed to cause prost to generate a type isomorphic to + /// Optional>. + #[derive(candid::CandidType, candid::Deserialize, serde::Serialize, comparable::Comparable)] + #[allow(clippy::derive_partial_eq_without_eq)] + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct NeuronRecipes { + #[prost(message, repeated, tag = "1")] + pub neuron_recipes: ::prost::alloc::vec::Vec, + } +} /// Lifecycle states of the swap canister. The details of their meanings /// are provided in the documentation of the `Swap` message. #[derive( diff --git a/rs/sns/swap/src/swap.rs b/rs/sns/swap/src/swap.rs index fdde2fff0c6c..91f096c6a8b3 100644 --- a/rs/sns/swap/src/swap.rs +++ b/rs/sns/swap/src/swap.rs @@ -5,26 +5,28 @@ use crate::{ logs::{ERROR, INFO}, memory, pb::v1::{ + claim_swap_neurons_request::{neuron_recipe, NeuronRecipe, NeuronRecipes}, get_open_ticket_response, new_sale_ticket_response, set_dapp_controllers_call_result, set_mode_call_result, set_mode_call_result::SetModeResult, settle_neurons_fund_participation_request, settle_neurons_fund_participation_response, sns_neuron_recipe::{ClaimedStatus, Investor, NeuronAttributes}, - BuyerState, CanisterCallError, CfInvestment, CfNeuron, CfParticipant, DerivedState, - DirectInvestment, ErrorRefundIcpRequest, ErrorRefundIcpResponse, FinalizeSwapResponse, - GetAutoFinalizationStatusRequest, GetAutoFinalizationStatusResponse, GetBuyerStateRequest, - GetBuyerStateResponse, GetBuyersTotalResponse, GetDerivedStateResponse, GetInitRequest, - GetInitResponse, GetLifecycleRequest, GetLifecycleResponse, GetOpenTicketRequest, - GetOpenTicketResponse, GetSaleParametersRequest, GetSaleParametersResponse, - GetStateResponse, Icrc1Account, Init, Lifecycle, ListCommunityFundParticipantsRequest, - ListCommunityFundParticipantsResponse, ListDirectParticipantsRequest, - ListDirectParticipantsResponse, ListSnsNeuronRecipesRequest, ListSnsNeuronRecipesResponse, - NeuronBasketConstructionParameters, NeuronId as SwapNeuronId, NewSaleTicketRequest, - NewSaleTicketResponse, NotifyPaymentFailureResponse, Participant, - RefreshBuyerTokensResponse, SetDappControllersCallResult, SetDappControllersRequest, - SetDappControllersResponse, SetModeCallResult, SettleNeuronsFundParticipationRequest, - SettleNeuronsFundParticipationResponse, SettleNeuronsFundParticipationResult, - SnsNeuronRecipe, Swap, SweepResult, Ticket, TransferableAmount, + BuyerState, CanisterCallError, CfInvestment, CfNeuron, CfParticipant, + ClaimSwapNeuronsRequest, DerivedState, DirectInvestment, ErrorRefundIcpRequest, + ErrorRefundIcpResponse, FinalizeSwapResponse, GetAutoFinalizationStatusRequest, + GetAutoFinalizationStatusResponse, GetBuyerStateRequest, GetBuyerStateResponse, + GetBuyersTotalResponse, GetDerivedStateResponse, GetInitRequest, GetInitResponse, + GetLifecycleRequest, GetLifecycleResponse, GetOpenTicketRequest, GetOpenTicketResponse, + GetSaleParametersRequest, GetSaleParametersResponse, GetStateResponse, Icrc1Account, Init, + Lifecycle, ListCommunityFundParticipantsRequest, ListCommunityFundParticipantsResponse, + ListDirectParticipantsRequest, ListDirectParticipantsResponse, ListSnsNeuronRecipesRequest, + ListSnsNeuronRecipesResponse, NeuronBasketConstructionParameters, NeuronId as SwapNeuronId, + NeuronIds, NewSaleTicketRequest, NewSaleTicketResponse, NotifyPaymentFailureResponse, + Participant, RefreshBuyerTokensResponse, SetDappControllersCallResult, + SetDappControllersRequest, SetDappControllersResponse, SetModeCallResult, + SettleNeuronsFundParticipationRequest, SettleNeuronsFundParticipationResponse, + SettleNeuronsFundParticipationResult, SnsNeuronRecipe, Swap, SweepResult, Ticket, + TransferableAmount, }, types::{NeuronsFundNeuron, ScheduledVestingEvent, TransferResult}, }; @@ -38,14 +40,9 @@ use ic_nervous_system_common::{ }; use ic_nervous_system_proto::pb::v1::Principals; use ic_neurons_fund::{MatchedParticipationFunction, PolynomialNeuronsFundParticipation}; -use ic_sns_governance::pb::v1::claim_swap_neurons_request::{ - neuron_recipe, NeuronRecipe, NeuronRecipes, -}; -use ic_sns_governance::pb::v1::NeuronIds; use ic_sns_governance::pb::v1::{ claim_swap_neurons_response::{ClaimSwapNeuronsResult, SwapNeuron}, - governance, ClaimSwapNeuronsError, ClaimSwapNeuronsRequest, ClaimedSwapNeuronStatus, NeuronId, - SetMode, SetModeResponse, + governance, ClaimSwapNeuronsError, ClaimedSwapNeuronStatus, NeuronId, SetMode, SetModeResponse, }; use ic_stable_structures::storable::Bound; use ic_stable_structures::{storable::Blob, GrowFailed, Storable}; @@ -1698,7 +1695,7 @@ impl Swap { async fn batch_claim_swap_neurons( sns_governance_client: &mut impl SnsGovernanceClient, neuron_recipes: &mut Vec, - claimable_neurons_index: &mut BTreeMap, + claimable_neurons_index: &mut BTreeMap, ) -> SweepResult { log!( INFO, @@ -1811,7 +1808,7 @@ impl Swap { /// status of the SwapNeuron. Return a SweepResult to be consumed by claim_swap_neurons fn process_swap_neuron( swap_neuron: SwapNeuron, - claimable_neurons_index: &mut BTreeMap, + claimable_neurons_index: &mut BTreeMap, ) -> SweepResult { let mut sweep_result = SweepResult::default(); @@ -1836,7 +1833,8 @@ impl Swap { } }; - let Some(recipe) = claimable_neurons_index.get_mut(neuron_id) else { + let Some(recipe) = claimable_neurons_index.get_mut(&SwapNeuronId::from(neuron_id.clone())) + else { log!( ERROR, "Unable to find neuron {:?} (ID {}) in claimable_neurons_index.", @@ -3541,8 +3539,8 @@ impl SnsNeuronRecipe { } }; - let neuron_id = Some(NeuronId::from(compute_neuron_staking_subaccount_bytes( - controller, *memo, + let neuron_id = Some(SwapNeuronId::from(NeuronId::from( + compute_neuron_staking_subaccount_bytes(controller, *memo), ))); let followees = followees @@ -3550,7 +3548,14 @@ impl SnsNeuronRecipe { .cloned() .map(NeuronId::from) .collect::>(); - let followees = Some(NeuronIds::from(followees.clone())); + let followees = Some(NeuronIds::from( + followees + .clone() + // TODO(NNS1-3306): This transition will no longer be necessary + .into_iter() + .map(SwapNeuronId::from) + .collect::>(), + )); // Since claim_swap_neurons is a permission-ed API on governance, account for // the transfer_fee that is applied with the sns ledger transfer. @@ -3968,9 +3973,9 @@ mod tests { }; let mut index = btreemap! { - NeuronId::new_test_neuron_id(1) => &mut successful_recipe, - NeuronId::new_test_neuron_id(2) => &mut failed_recipe, - NeuronId::new_test_neuron_id(3) => &mut invalid_recipe, + SwapNeuronId::from(NeuronId::new_test_neuron_id(1)) => &mut successful_recipe, + SwapNeuronId::from(NeuronId::new_test_neuron_id(2)) => &mut failed_recipe, + SwapNeuronId::from(NeuronId::new_test_neuron_id(3)) => &mut invalid_recipe, }; // Process first to satisfy the borrow checker diff --git a/rs/sns/swap/src/types.rs b/rs/sns/swap/src/types.rs index c61c6071c8cd..91ff7780b4d4 100644 --- a/rs/sns/swap/src/types.rs +++ b/rs/sns/swap/src/types.rs @@ -3,13 +3,14 @@ use crate::{ environment::{CanisterClients, CanisterEnvironment}, logs::{ERROR, INFO}, pb::v1::{ - error_refund_icp_response, set_dapp_controllers_call_result, set_mode_call_result, - set_mode_call_result::SetModeResult, + claim_swap_neurons_request::{NeuronRecipe, NeuronRecipes}, + error_refund_icp_response, set_dapp_controllers_call_result, + set_mode_call_result::{self, SetModeResult}, settle_neurons_fund_participation_result, sns_neuron_recipe::{ClaimedStatus, Investor}, BuyerState, CfInvestment, CfNeuron, CfParticipant, DirectInvestment, ErrorRefundIcpResponse, FinalizeSwapResponse, Init, Lifecycle, NeuronId as SwapNeuronId, - Params, SetDappControllersCallResult, SetModeCallResult, + NeuronIds as SwapNeuronIds, Params, SetDappControllersCallResult, SetModeCallResult, SettleNeuronsFundParticipationResult, SnsNeuronRecipe, SweepResult, TransferableAmount, }, swap::is_valid_principal, @@ -19,7 +20,7 @@ use ic_canister_log::log; use ic_ledger_core::Tokens; use ic_nervous_system_common::{ledger::ICRC1Ledger, ONE_DAY_SECONDS}; use ic_nervous_system_proto::pb::v1::Principals; -use ic_sns_governance::pb::v1::{ClaimedSwapNeuronStatus, NeuronId}; +use ic_sns_governance::pb::v1::{ClaimedSwapNeuronStatus, NeuronId, NeuronIds}; use icrc_ledger_types::icrc1::account::{Account, Subaccount}; use std::str::FromStr; @@ -1082,6 +1083,43 @@ impl From for NeuronId { } } +// TODO(NNS1-3306): This From implementation will no longer be necessary and should be removed +impl From> for SwapNeuronIds { + fn from(neuron_ids: Vec) -> Self { + SwapNeuronIds { neuron_ids } + } +} + +// TODO(NNS1-3306): This From implementation will no longer be necessary and should be removed +impl From> for SwapNeuronIds { + fn from(neuron_ids: Vec) -> Self { + SwapNeuronIds { + neuron_ids: neuron_ids.into_iter().map(SwapNeuronId::from).collect(), + } + } +} + +// TODO(NNS1-3306): This From implementation will no longer be necessary and should be removed +impl From for Vec { + fn from(neuron_ids: SwapNeuronIds) -> Self { + neuron_ids.neuron_ids + } +} + +// TODO(NNS1-3306): This From implementation will no longer be necessary and should be removed +impl From> for NeuronRecipes { + fn from(neuron_recipes: Vec) -> Self { + NeuronRecipes { neuron_recipes } + } +} + +// TODO(NNS1-3306): This From implementation will no longer be necessary and should be removed +impl From for Vec { + fn from(neuron_recipes: NeuronRecipes) -> Self { + neuron_recipes.neuron_recipes + } +} + /// Internal definition of a NeuronsFundNeuron. This is the simplified version with /// all options removed. /// diff --git a/rs/sns/swap/tests/common/doubles.rs b/rs/sns/swap/tests/common/doubles.rs index d4169ae5f831..7faed8ddae78 100644 --- a/rs/sns/swap/tests/common/doubles.rs +++ b/rs/sns/swap/tests/common/doubles.rs @@ -5,16 +5,15 @@ use ic_nervous_system_common::{ledger::ICRC1Ledger, NervousSystemError}; use ic_nervous_system_common_test_utils::SpyLedger; use ic_sns_governance::pb::v1::{ manage_neuron_response, manage_neuron_response::ClaimOrRefreshResponse, - ClaimSwapNeuronsRequest, ClaimSwapNeuronsResponse, ManageNeuron, ManageNeuronResponse, SetMode, - SetModeResponse, + ClaimSwapNeuronsResponse, ManageNeuron, ManageNeuronResponse, SetMode, SetModeResponse, }; use ic_sns_swap::{ clients::{NnsGovernanceClient, SnsGovernanceClient, SnsRootClient}, environment::CanisterClients, pb::v1::{ - set_dapp_controllers_request::CanisterIds, CanisterCallError, SetDappControllersRequest, - SetDappControllersResponse, SettleNeuronsFundParticipationRequest, - SettleNeuronsFundParticipationResponse, + set_dapp_controllers_request::CanisterIds, CanisterCallError, ClaimSwapNeuronsRequest, + SetDappControllersRequest, SetDappControllersResponse, + SettleNeuronsFundParticipationRequest, SettleNeuronsFundParticipationResponse, }, }; use icrc_ledger_types::icrc1::account::{Account, Subaccount}; diff --git a/rs/sns/swap/tests/swap.rs b/rs/sns/swap/tests/swap.rs index 6fa4897f0040..db49a5404d5d 100644 --- a/rs/sns/swap/tests/swap.rs +++ b/rs/sns/swap/tests/swap.rs @@ -39,20 +39,20 @@ use ic_neurons_fund::{ PolynomialMatchingFunction, SerializableFunction, }; use ic_sns_governance::pb::v1::{ - claim_swap_neurons_request::{neuron_recipe, NeuronRecipe, NeuronRecipes}, - claim_swap_neurons_response::ClaimSwapNeuronsResult, - governance, ClaimSwapNeuronsRequest, ClaimSwapNeuronsResponse, NeuronId, NeuronIds, SetMode, - SetModeResponse, + claim_swap_neurons_response::ClaimSwapNeuronsResult, governance, ClaimSwapNeuronsResponse, + NeuronId, SetMode, SetModeResponse, }; use ic_sns_swap::{ environment::CanisterClients, memory, pb::v1::{ + claim_swap_neurons_request::{neuron_recipe, NeuronRecipe, NeuronRecipes}, settle_neurons_fund_participation_response::NeuronsFundNeuron, sns_neuron_recipe::{ClaimedStatus, Investor, Investor::CommunityFund, NeuronAttributes}, + ClaimSwapNeuronsRequest, Lifecycle::{Aborted, Committed, Open, Pending, Unspecified}, - NeuronBasketConstructionParameters, SetDappControllersRequest, SetDappControllersResponse, - *, + NeuronBasketConstructionParameters, NeuronId as SwapNeuronId, NeuronIds as SwapNeuronIds, + SetDappControllersRequest, SetDappControllersResponse, *, }, swap::{ apportion_approximately_equally, principal_to_subaccount, CLAIM_SWAP_NEURONS_BATCH_SIZE, @@ -3512,28 +3512,25 @@ async fn test_claim_swap_neuron_correctly_creates_neuron_recipes() { neuron_recipes: vec![ NeuronRecipe { controller: Some(*TEST_USER1_PRINCIPAL), - neuron_id: Some(NeuronId::from(compute_neuron_staking_subaccount_bytes( - *TEST_USER1_PRINCIPAL, - 10, + neuron_id: Some(SwapNeuronId::from(NeuronId::from( + compute_neuron_staking_subaccount_bytes(*TEST_USER1_PRINCIPAL, 10), ))), stake_e8s: Some((10 * E8) - init().transaction_fee_e8s()), dissolve_delay_seconds: Some(ONE_MONTH_SECONDS), - followees: Some(NeuronIds { - neuron_ids: vec![NeuronId::new_test_neuron_id(10)], - }), + followees: Some(SwapNeuronIds::from(vec![NeuronId::new_test_neuron_id(10)])), participant: Some(neuron_recipe::Participant::Direct(neuron_recipe::Direct {})), }, NeuronRecipe { controller: Some(NNS_GOVERNANCE_CANISTER_ID.get()), - neuron_id: Some(NeuronId::from(compute_neuron_staking_subaccount_bytes( - NNS_GOVERNANCE_CANISTER_ID.get(), - 0, + neuron_id: Some(SwapNeuronId::from(NeuronId::from( + compute_neuron_staking_subaccount_bytes( + NNS_GOVERNANCE_CANISTER_ID.get(), + 0, + ), ))), stake_e8s: Some((20 * E8) - init().transaction_fee_e8s()), dissolve_delay_seconds: Some(0), - followees: Some(NeuronIds { - neuron_ids: vec![NeuronId::new_test_neuron_id(20)], - }), + followees: Some(SwapNeuronIds::from(vec![NeuronId::new_test_neuron_id(20)])), participant: Some(neuron_recipe::Participant::NeuronsFund( neuron_recipe::NeuronsFund { nns_neuron_id: Some(100),