use {
crate::{
state::{
enums::GovernanceAccountType,
governance::{
assert_valid_create_governance_args, get_mint_governance_address_seeds,
GovernanceConfig, GovernanceV2,
},
realm::get_realm_data,
},
tools::{
spl_token::{
assert_spl_token_mint_authority_is_signer, set_spl_token_account_authority,
},
structs::Reserved119,
},
},
solana_program::{
account_info::{next_account_info, AccountInfo},
entrypoint::ProgramResult,
program_pack::Pack,
pubkey::Pubkey,
rent::Rent,
sysvar::Sysvar,
},
spl_governance_tools::account::create_and_serialize_account_signed,
spl_token::{instruction::AuthorityType, state::Mint},
};
pub fn process_create_mint_governance(
program_id: &Pubkey,
accounts: &[AccountInfo],
config: GovernanceConfig,
transfer_mint_authorities: bool,
) -> ProgramResult {
let account_info_iter = &mut accounts.iter();
let realm_info = next_account_info(account_info_iter)?; let mint_governance_info = next_account_info(account_info_iter)?;
let governed_mint_info = next_account_info(account_info_iter)?; let governed_mint_authority_info = next_account_info(account_info_iter)?;
let token_owner_record_info = next_account_info(account_info_iter)?;
let payer_info = next_account_info(account_info_iter)?; let spl_token_info = next_account_info(account_info_iter)?;
let system_info = next_account_info(account_info_iter)?;
let rent = Rent::get()?;
let create_authority_info = next_account_info(account_info_iter)?;
assert_valid_create_governance_args(program_id, &config, realm_info)?;
let realm_data = get_realm_data(program_id, realm_info)?;
realm_data.assert_create_authority_can_create_governance(
program_id,
realm_info.key,
token_owner_record_info,
create_authority_info,
account_info_iter, )?;
let mint_governance_data = GovernanceV2 {
account_type: GovernanceAccountType::MintGovernanceV2,
realm: *realm_info.key,
governed_account: *governed_mint_info.key,
config,
reserved1: 0,
reserved_v2: Reserved119::default(),
required_signatories_count: 0,
active_proposal_count: 0,
};
create_and_serialize_account_signed::<GovernanceV2>(
payer_info,
mint_governance_info,
&mint_governance_data,
&get_mint_governance_address_seeds(realm_info.key, governed_mint_info.key),
program_id,
system_info,
&rent,
0,
)?;
if transfer_mint_authorities {
set_spl_token_account_authority(
governed_mint_info,
governed_mint_authority_info,
mint_governance_info.key,
AuthorityType::MintTokens,
spl_token_info,
)?;
let mint_data = Mint::unpack(&governed_mint_info.data.borrow())?;
if mint_data.freeze_authority.is_some() {
set_spl_token_account_authority(
governed_mint_info,
governed_mint_authority_info,
mint_governance_info.key,
AuthorityType::FreezeAccount,
spl_token_info,
)?;
}
} else {
assert_spl_token_mint_authority_is_signer(
governed_mint_info,
governed_mint_authority_info,
)?;
}
Ok(())
}