spl_governance_chat/
state.rs

1//! Program state
2
3use {
4    borsh::{BorshDeserialize, BorshSchema, BorshSerialize},
5    solana_program::{
6        account_info::AccountInfo, clock::UnixTimestamp, program_error::ProgramError,
7        pubkey::Pubkey,
8    },
9    spl_governance_tools::account::{assert_is_valid_account_of_type, AccountMaxSize},
10};
11
12/// Defines all GovernanceChat accounts types
13#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
14pub enum GovernanceChatAccountType {
15    /// Default uninitialized account state
16    Uninitialized,
17
18    /// Chat message
19    ChatMessage,
20}
21
22/// Chat message body
23#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
24pub enum MessageBody {
25    /// Text message encoded as utf-8 string
26    Text(String),
27
28    /// Emoticon encoded using utf-8 characters
29    /// In the UI reactions are displayed together under the parent message (as
30    /// opposed to hierarchical replies)
31    Reaction(String),
32}
33
34/// Chat message
35#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
36pub struct ChatMessage {
37    /// Account type
38    pub account_type: GovernanceChatAccountType,
39
40    /// The proposal the message is for
41    pub proposal: Pubkey,
42
43    /// Author of the message
44    pub author: Pubkey,
45
46    /// Message timestamp
47    pub posted_at: UnixTimestamp,
48
49    /// Parent message
50    pub reply_to: Option<Pubkey>,
51
52    /// Body of the message
53    pub body: MessageBody,
54}
55
56impl AccountMaxSize for ChatMessage {
57    fn get_max_size(&self) -> Option<usize> {
58        let body_size = match &self.body {
59            MessageBody::Text(body) => body.len(),
60            MessageBody::Reaction(body) => body.len(),
61        };
62
63        Some(body_size + 111)
64    }
65}
66
67/// Checks whether Chat account exists, is initialized and  owned by
68/// governance-chat program
69pub fn assert_is_valid_chat_message(
70    program_id: &Pubkey,
71    chat_message_info: &AccountInfo,
72) -> Result<(), ProgramError> {
73    assert_is_valid_account_of_type(
74        program_id,
75        chat_message_info,
76        GovernanceChatAccountType::ChatMessage,
77    )
78}
79
80#[cfg(test)]
81mod test {
82
83    use super::*;
84
85    #[test]
86    fn test_max_size() {
87        let message = ChatMessage {
88            account_type: GovernanceChatAccountType::ChatMessage,
89            proposal: Pubkey::new_unique(),
90            author: Pubkey::new_unique(),
91            posted_at: 10,
92            reply_to: Some(Pubkey::new_unique()),
93            body: MessageBody::Text("message".to_string()),
94        };
95        let size = message.try_to_vec().unwrap().len();
96
97        assert_eq!(message.get_max_size(), Some(size));
98    }
99}