spl_governance_chat/
processor.rs1use {
4 crate::{
5 error::GovernanceChatError,
6 instruction::GovernanceChatInstruction,
7 state::{
8 assert_is_valid_chat_message, ChatMessage, GovernanceChatAccountType, MessageBody,
9 },
10 },
11 borsh::BorshDeserialize,
12 solana_program::{
13 account_info::{next_account_info, AccountInfo},
14 clock::Clock,
15 entrypoint::ProgramResult,
16 msg,
17 program_error::ProgramError,
18 pubkey::Pubkey,
19 sysvar::Sysvar,
20 },
21 spl_governance::state::{
22 governance::get_governance_data_for_realm, proposal::get_proposal_data_for_governance,
23 realm::get_realm_data, realm_config::get_realm_config_data_for_realm,
24 token_owner_record::get_token_owner_record_data_for_realm,
25 },
26 spl_governance_addin_api::voter_weight::VoterWeightAction,
27 spl_governance_tools::account::create_and_serialize_account,
28};
29
30pub fn process_instruction(
32 program_id: &Pubkey,
33 accounts: &[AccountInfo],
34 input: &[u8],
35) -> ProgramResult {
36 msg!("VERSION:{:?}", env!("CARGO_PKG_VERSION"));
37
38 let instruction = GovernanceChatInstruction::try_from_slice(input)
39 .map_err(|_| ProgramError::InvalidInstructionData)?;
40
41 match instruction {
42 GovernanceChatInstruction::PostMessage { body, is_reply } => {
43 msg!("GOVERNANCE-CHAT-INSTRUCTION: PostMessage");
44 process_post_message(program_id, accounts, body, is_reply)
45 }
46 }
47}
48
49pub fn process_post_message(
51 program_id: &Pubkey,
52 accounts: &[AccountInfo],
53 body: MessageBody,
54 is_reply: bool,
55) -> ProgramResult {
56 let account_info_iter = &mut accounts.iter();
57
58 let governance_program_info = next_account_info(account_info_iter)?; let realm_info = next_account_info(account_info_iter)?; let governance_info = next_account_info(account_info_iter)?; let proposal_info = next_account_info(account_info_iter)?; let token_owner_record_info = next_account_info(account_info_iter)?; let governance_authority_info = next_account_info(account_info_iter)?; let chat_message_info = next_account_info(account_info_iter)?; let payer_info = next_account_info(account_info_iter)?; let system_info = next_account_info(account_info_iter)?; let reply_to_address = if is_reply {
71 let reply_to_info = next_account_info(account_info_iter)?; assert_is_valid_chat_message(program_id, reply_to_info)?;
73 Some(*reply_to_info.key)
74 } else {
75 None
76 };
77
78 let governance_program_id = governance_program_info.key;
79 let realm_data = get_realm_data(governance_program_id, realm_info)?;
80
81 let governance_data =
82 get_governance_data_for_realm(governance_program_id, governance_info, realm_info.key)?;
83
84 let token_owner_record_data = get_token_owner_record_data_for_realm(
85 governance_program_id,
86 token_owner_record_info,
87 &governance_data.realm,
88 )?;
89
90 token_owner_record_data.assert_token_owner_or_delegate_is_signer(governance_authority_info)?;
91
92 let _proposal_data = get_proposal_data_for_governance(
95 governance_program_id,
96 proposal_info,
97 governance_info.key,
98 )?;
99
100 let realm_config_info = next_account_info(account_info_iter)?; let realm_config_data =
103 get_realm_config_data_for_realm(governance_program_id, realm_config_info, realm_info.key)?;
104
105 let voter_weight = token_owner_record_data.resolve_voter_weight(
106 account_info_iter, &realm_data,
108 &realm_config_data,
109 VoterWeightAction::CommentProposal,
110 proposal_info.key,
111 )?;
112
113 if voter_weight < 1 {
118 return Err(GovernanceChatError::NotEnoughTokensToCommentProposal.into());
119 }
120
121 let clock = Clock::get()?;
122
123 let chat_message_data = ChatMessage {
124 account_type: GovernanceChatAccountType::ChatMessage,
125 proposal: *proposal_info.key,
126 author: token_owner_record_data.governing_token_owner,
127 posted_at: clock.unix_timestamp,
128 reply_to: reply_to_address,
129 body,
130 };
131
132 create_and_serialize_account(
133 payer_info,
134 chat_message_info,
135 &chat_message_data,
136 program_id,
137 system_info,
138 )?;
139
140 Ok(())
141}