use anchor_lang::prelude::*;
use mpl_token_metadata::{MAX_NAME_LENGTH, MAX_URI_LENGTH};
use crate::{constants::HIDDEN_SECTION, errors::CandyError, utils::replace_patterns};
#[derive(AnchorSerialize, AnchorDeserialize, Clone, Default, Debug)]
pub struct CandyMachineData {
pub items_available: u64,
pub max_supply: u64,
pub is_mutable: bool,
pub config_line_settings: Option<ConfigLineSettings>,
pub hidden_settings: Option<HiddenSettings>,
}
#[derive(AnchorSerialize, AnchorDeserialize, Clone, Default, Debug)]
pub struct HiddenSettings {
pub name: String,
pub uri: String,
pub hash: [u8; 32],
}
#[derive(AnchorSerialize, AnchorDeserialize, Clone, Default, Debug)]
pub struct ConfigLineSettings {
pub prefix_name: String,
pub name_length: u32,
pub prefix_uri: String,
pub uri_length: u32,
pub is_sequential: bool,
}
impl CandyMachineData {
pub fn get_space_for_candy(&self) -> Result<usize> {
Ok(if self.hidden_settings.is_some() {
HIDDEN_SECTION
} else {
HIDDEN_SECTION
+ 4
+ (self.items_available as usize) * self.get_config_line_size()
+ (self
.items_available
.checked_div(8)
.ok_or(CandyError::NumericalOverflowError)?
+ 1) as usize
+ (self.items_available as usize) * 4
})
}
pub fn get_config_line_size(&self) -> usize {
if let Some(config_line) = &self.config_line_settings {
(config_line.name_length + config_line.uri_length) as usize
} else {
0
}
}
pub fn validate(&self) -> Result<()> {
if let Some(hidden) = &self.hidden_settings {
if self.config_line_settings.is_some() {
return err!(CandyError::HiddenSettingsDoNotHaveConfigLines);
}
let expected = replace_patterns(hidden.name.clone(), self.items_available as usize);
if MAX_NAME_LENGTH < expected.len() {
return err!(CandyError::ExceededLengthError);
}
let expected = replace_patterns(hidden.uri.clone(), self.items_available as usize);
if MAX_URI_LENGTH < expected.len() {
return err!(CandyError::ExceededLengthError);
}
} else if let Some(config_line) = &self.config_line_settings {
let expected = replace_patterns(
config_line.prefix_name.clone(),
self.items_available as usize,
);
if MAX_NAME_LENGTH < (expected.len() + config_line.name_length as usize) {
return err!(CandyError::ExceededLengthError);
}
let expected = replace_patterns(
config_line.prefix_uri.clone(),
self.items_available as usize,
);
if MAX_URI_LENGTH < (expected.len() + config_line.uri_length as usize) {
return err!(CandyError::ExceededLengthError);
}
} else {
return err!(CandyError::MissingConfigLinesSettings);
}
Ok(())
}
}