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}