tg4_engagement/msg.rs
1use cosmwasm_std::{Addr, Coin, Decimal, Timestamp};
2use schemars::JsonSchema;
3use serde::{Deserialize, Serialize};
4
5use tg4::Member;
6use tg_bindings::{Evidence, PrivilegeChangeMsg};
7use tg_utils::Duration;
8
9#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, JsonSchema, Debug)]
10#[serde(rename_all = "snake_case")]
11pub struct InstantiateMsg {
12 /// The admin is the only account that can update the group state.
13 /// Omit it to make the group immutable.
14 pub admin: Option<String>,
15 pub members: Vec<Member>,
16 #[serde(default)]
17 pub preauths_hooks: u64,
18 #[serde(default)]
19 pub preauths_slashing: u64,
20 pub halflife: Option<Duration>,
21 /// Denom of tokens which may be distributed by this contract.
22 pub denom: String,
23}
24
25#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, JsonSchema, Debug)]
26#[serde(rename_all = "snake_case")]
27pub enum ExecuteMsg {
28 /// Change the admin
29 UpdateAdmin { admin: Option<String> },
30 /// apply a diff to the existing members.
31 /// remove is applied after add, so if an address is in both, it is removed
32 UpdateMembers {
33 remove: Vec<String>,
34 add: Vec<Member>,
35 },
36 /// Add points to member's address
37 AddPoints { addr: String, points: u64 },
38 /// Add a new hook to be informed of all membership changes. Must be called by Admin
39 AddHook { addr: String },
40 /// Remove a hook. Must be called by Admin
41 RemoveHook { addr: String },
42 /// Distributes rewards sent with this message, and all rewards transferred since last call of this
43 /// to members, proportionally to their points. Rewards are not immediately send to members, but
44 /// assigned to them for later withdrawal (see: `ExecuteMsg::WithdrawFunds`)
45 DistributeRewards {
46 /// Original source of rewards, informational. If present overwrites "sender" field on
47 /// propagated event.
48 sender: Option<String>,
49 },
50 /// Withdraws rewards which were previously distributed and assigned to sender.
51 WithdrawRewards {
52 /// Account from which assigned rewards would be withdrawn; `sender` by default. `sender` has
53 /// to be eligible for withdrawal from `owner` address to perform this call (`owner` has to
54 /// call `DelegateWithdrawal { delegated: sender }` before)
55 owner: Option<String>,
56 /// Address where to transfer funds. If not present, funds would be sent to `sender`.
57 receiver: Option<String>,
58 },
59 /// Sets given address as allowed for senders funds withdrawal. Funds still can be withdrawn by
60 /// sender himself, but this additional account is allowed to perform it as well. There can be only
61 /// one account delegated for withdrawal for any owner at any single time.
62 DelegateWithdrawal {
63 /// Account delegated for withdrawal. To disallow current withdrawal, the best is to set it
64 /// to own address.
65 delegated: String,
66 },
67 /// Adds slasher for contract if there are enough `slasher_preauths` left
68 AddSlasher { addr: String },
69 /// Removes slasher for contract
70 RemoveSlasher { addr: String },
71 /// Slash engagement points from address
72 Slash { addr: String, portion: Decimal },
73}
74
75#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, JsonSchema, Debug)]
76#[serde(rename_all = "snake_case")]
77pub enum QueryMsg {
78 /// Return AdminResponse
79 Admin {},
80 /// Return TotalPointsResponse
81 TotalPoints {},
82 /// Returns MemberListResponse
83 ListMembers {
84 start_after: Option<String>,
85 limit: Option<u32>,
86 },
87 /// Returns MemberListResponse, sorted by points descending
88 ListMembersByPoints {
89 start_after: Option<Member>,
90 limit: Option<u32>,
91 },
92 /// Returns MemberResponse
93 Member {
94 addr: String,
95 at_height: Option<u64>,
96 },
97 /// Shows all registered hooks. Returns HooksResponse.
98 Hooks {},
99 /// Return the current number of preauths. Returns PreauthResponse.
100 Preauths {},
101 /// Return how many rewards are assigned for withdrawal from the given address. Returns
102 /// `RewardsResponse`.
103 WithdrawableRewards { owner: String },
104 /// Return how many rewards were distributed in total by this contract. Returns
105 /// `RewardsResponse`.
106 DistributedRewards {},
107 /// Return how many funds were sent to this contract since last `ExecuteMsg::DistributeFunds`,
108 /// and await for distribution. Returns `RewardsResponse`.
109 UndistributedRewards {},
110 /// Return address allowed for withdrawal of the funds assigned to owner. Returns `DelegateResponse`
111 Delegated { owner: String },
112 /// Returns information about the half-life, including the duration in seconds, the last
113 /// and the next occurrence.
114 Halflife {},
115 /// Returns information (bool) about whether the given address is an active slasher
116 IsSlasher { addr: String },
117 /// Returns all active slashers as a vector of addresses
118 ListSlashers {},
119 /// Returns rewards distribution data
120 DistributionData {},
121 /// Returns withdraw adjustment data
122 WithdrawAdjustmentData { addr: String },
123}
124
125#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, JsonSchema, Debug)]
126#[serde(rename_all = "snake_case")]
127pub enum SudoMsg {
128 /// This will be delivered every block if the contract is currently registered for Begin Block
129 /// types based on subset of https://github.com/tendermint/tendermint/blob/v0.34.8/proto/tendermint/abci/types.proto#L81
130 BeginBlock {
131 /// This is proven evidence of malice and the basis for slashing validators
132 evidence: Vec<Evidence>,
133 },
134 /// This will be delivered every block if the contract is currently registered for End Block
135 /// Block height and time is already in Env.
136 EndBlock {},
137 /// This will be delivered after all end blockers if this is registered for ValidatorUpdates.
138 /// If it sets Response.data, it must be a JSON-encoded ValidatorDiff,
139 /// which will be used to change the validator set.
140 EndWithValidatorUpdate {},
141 PrivilegeChange(PrivilegeChangeMsg),
142 /// This allows updating group membership via sudo.
143 /// Use case: for post-genesis validators, we want to set some initial engagement points.
144 /// Note: If the member already exists, its points will be reset to the points sent here.
145 UpdateMember(Member),
146}
147
148#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, JsonSchema, Debug)]
149pub struct PreauthResponse {
150 pub preauths: u64,
151}
152
153#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, JsonSchema, Debug)]
154pub struct RewardsResponse {
155 pub rewards: Coin,
156}
157
158#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, JsonSchema, Debug)]
159pub struct DelegatedResponse {
160 pub delegated: Addr,
161}
162
163#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, JsonSchema, Debug)]
164pub struct HalflifeResponse {
165 // `None` means the halflife functionality is disabled for this instance.
166 pub halflife_info: Option<HalflifeInfo>,
167}
168
169#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, JsonSchema, Debug)]
170pub struct HalflifeInfo {
171 pub last_halflife: Timestamp,
172 pub halflife: Duration,
173 pub next_halflife: Timestamp,
174}
175
176#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, JsonSchema, Debug)]
177pub struct SlasherResponse {
178 pub is_slasher: bool,
179}
180
181#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, JsonSchema, Debug)]
182pub struct ListSlashersResponse {
183 pub slashers: Vec<String>,
184}
185
186#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, JsonSchema, Debug)]
187#[serde(rename_all = "snake_case")]
188pub struct MigrateMsg {
189 pub halflife: Option<Duration>,
190}
191
192#[cfg(test)]
193mod tests {
194 use super::*;
195
196 #[test]
197 fn deserialize_json_to_sudo_msg() {
198 let message = r#"{"update_member": {"addr": "xxx", "points": 123}}"#;
199 assert_eq!(
200 SudoMsg::UpdateMember(Member {
201 addr: "xxx".to_string(),
202 points: 123,
203 start_height: None
204 }),
205 cosmwasm_std::from_slice::<SudoMsg>(message.as_bytes()).unwrap()
206 );
207 }
208}