1pub mod multisig {
2 use std::collections::{HashMap, HashSet};
3
4 use candid::{CandidType, Deserialize, Principal};
5 use ic_kit::ic;
6 use serde::Serialize;
7
8 #[derive(CandidType, Deserialize, Clone)]
9 pub struct Settings {
10 pub threshold: usize,
12 pub open_transaction_limit: Option<usize>,
14 pub command_history_limit: Option<usize>,
16 }
17
18 impl Default for Settings {
19 fn default() -> Self {
20 Settings {
21 threshold: 1,
22 open_transaction_limit: Some(25),
23 command_history_limit: None,
24 }
25 }
26 }
27
28 #[derive(CandidType, Clone, Deserialize, Debug)]
29 pub struct Transaction {
30 pub description: String,
33 pub commands: Vec<Command>,
36 pub proposed_by: Principal,
38 pub proposed_at: u64,
40 pub status: TransactionStatus,
42 pub approved: HashSet<Principal>,
44 pub rejected: HashSet<Principal>,
46 pub transaction_id: usize,
48 }
49
50 #[derive(CandidType, Deserialize, Serialize, Clone, Debug)]
51 pub enum Command {
52 Call {
54 canister: Principal,
56 method_name: String,
58 args_blob: Vec<u8>,
60 cycles: u64,
62 response: Option<Vec<u8>>,
66 },
67 AddOrRemoveSigner {
70 principals: HashSet<UpdateOwner>,
72 threshold: usize,
74 },
75 }
76
77 #[derive(CandidType, Clone, Deserialize, PartialEq, Eq, Serialize, Debug)]
78 pub enum TransactionStatus {
79 Open,
81 Executing,
84 Completed,
86 Failed,
88 Rejected,
90 }
91
92 pub type TransactionId = usize;
93
94 #[derive(CandidType, Deserialize)]
95 pub struct OpenTransactionRequest {
96 pub description: String,
97 pub commands: Vec<Command>,
98 }
99
100 #[derive(CandidType, Serialize, Deserialize, Debug)]
101 pub enum Failure {
102 NotAuthorized,
103 TransactionNotFound,
104 AlreadyVoted,
105 OpenTransactionLimit,
106 DescriptionOver512Chars,
107 TransactionNotOpen,
108 HandleOpenTxns,
109 InvalidThreshold,
110 CantRemoveAllSigners,
111 CommandBesidesSignerChange,
112 Unknown(String),
113 }
114
115 pub struct CallResults {
116 pub completed: bool,
117 pub responses: HashMap<usize, Vec<u8>>,
118 }
119
120 #[derive(CandidType, Serialize, Deserialize)]
121 pub struct TransactionBrief {
122 pub id: TransactionId,
123 pub approved: HashSet<Principal>,
124 pub rejected: HashSet<Principal>,
125 pub status: TransactionStatus,
126 pub command_info: Vec<(Principal, String)>,
127 pub proposed_at: u64,
128 }
129
130 impl From<Transaction> for TransactionBrief {
131 fn from(transaction: Transaction) -> Self {
132 let command_info = transaction
133 .commands
134 .iter()
135 .map(|t| match t {
136 Command::Call {
137 canister,
138 method_name,
139 ..
140 } => (*canister, method_name.clone()),
141 Command::AddOrRemoveSigner { .. } => {
142 (ic::id(), "AddOrRemoveSigner".to_string())
143 }
144 })
145 .collect();
146
147 TransactionBrief {
148 id: transaction.transaction_id,
149 approved: transaction.approved,
150 rejected: transaction.rejected,
151 status: transaction.status,
152 proposed_at: transaction.proposed_at,
153 command_info,
154 }
155 }
156 }
157
158 #[derive(CandidType, Deserialize, Clone, Serialize)]
159 pub struct SignersVec {
160 pub vector: Vec<(Principal, u64)>,
161 }
162
163 #[derive(CandidType, Deserialize, Clone, Serialize, PartialEq, Eq, Hash, Debug)]
164 pub enum UpdateOwner {
165 Remove(Principal),
166 Add(Principal),
167 }
168}