mpl_token_metadata/state/
mod.rs1pub(crate) mod asset_data;
2pub(crate) mod collection;
3pub(crate) mod creator;
4pub(crate) mod data;
5pub(crate) mod delegate;
6pub(crate) mod edition;
7pub(crate) mod edition_marker;
8pub(crate) mod escrow;
9pub(crate) mod master_edition;
10pub(crate) mod metadata;
11pub(crate) mod migrate;
12pub(crate) mod programmable;
13pub(crate) mod reservation;
14pub(crate) mod token_auth_payload;
15pub(crate) mod uses;
16
17use std::io::ErrorKind;
18
19pub use asset_data::*;
20use borsh::{maybestd::io::Error as BorshError, BorshDeserialize, BorshSerialize};
21pub use collection::*;
22pub use creator::*;
23pub use data::*;
24pub use delegate::*;
25pub use edition::*;
26pub use edition_marker::*;
27pub use escrow::*;
28pub use master_edition::*;
29pub use metadata::*;
30pub use migrate::*;
31use mpl_utils::resize_or_reallocate_account_raw;
32use num_derive::FromPrimitive;
33use num_traits::FromPrimitive;
34pub use programmable::*;
35pub use reservation::*;
36use shank::ShankAccount;
37use solana_program::{
38 account_info::AccountInfo, entrypoint::ProgramResult, program_error::ProgramError,
39 pubkey::Pubkey,
40};
41use spl_token::state::Account as TokenAccount;
42pub use uses::*;
43#[cfg(feature = "serde-feature")]
44use {
45 serde::{Deserialize, Deserializer, Serialize},
46 serde_with::{As, DisplayFromStr},
47 std::str::FromStr,
48};
49
50pub use crate::pda::{BURN, COLLECTION_AUTHORITY, EDITION, PREFIX, USER};
52use crate::{
53 assertions::assert_owned_by,
54 error::MetadataError,
55 utils::{meta_deser_unchecked, try_from_slice_checked},
56 ID,
57};
58
59pub const DISCRIMINATOR_INDEX: usize = 0;
61
62#[repr(C)]
63#[cfg_attr(feature = "serde-feature", derive(Serialize, Deserialize))]
64#[derive(BorshSerialize, BorshDeserialize, PartialEq, Eq, Debug, Clone, Copy, FromPrimitive)]
65pub enum TokenStandard {
66 NonFungible, FungibleAsset, Fungible, NonFungibleEdition, ProgrammableNonFungible, }
72
73pub trait TokenMetadataAccount: BorshDeserialize {
74 fn key() -> Key;
75
76 fn size() -> usize;
77
78 fn is_correct_account_type(data: &[u8], data_type: Key, data_size: usize) -> bool {
79 if data.is_empty() {
80 return false;
81 }
82
83 let key: Option<Key> = Key::from_u8(data[0]);
84 match key {
85 Some(key) => {
86 (key == data_type || key == Key::Uninitialized) && (data.len() == data_size)
87 }
88 None => false,
89 }
90 }
91
92 fn pad_length(buf: &mut Vec<u8>) -> Result<(), MetadataError> {
93 let padding_length = Self::size()
94 .checked_sub(buf.len())
95 .ok_or(MetadataError::NumericalOverflowError)?;
96 buf.extend(vec![0; padding_length]);
97 Ok(())
98 }
99
100 fn safe_deserialize(mut data: &[u8]) -> Result<Self, BorshError> {
101 if !Self::is_correct_account_type(data, Self::key(), Self::size()) {
102 return Err(BorshError::new(ErrorKind::Other, "DataTypeMismatch"));
103 }
104
105 let result = Self::deserialize(&mut data)?;
106
107 Ok(result)
108 }
109
110 fn from_account_info(a: &AccountInfo) -> Result<Self, ProgramError>
111where {
112 let data = &a.data.borrow_mut();
113
114 let ua = Self::safe_deserialize(data).map_err(|_| MetadataError::DataTypeMismatch)?;
115
116 assert_owned_by(a, &ID)?;
118
119 Ok(ua)
120 }
121}
122
123#[repr(C)]
124#[cfg_attr(feature = "serde-feature", derive(Serialize, Deserialize))]
125#[derive(BorshSerialize, BorshDeserialize, PartialEq, Eq, Debug, Clone, Copy, FromPrimitive)]
126pub enum Key {
127 Uninitialized,
128 EditionV1,
129 MasterEditionV1,
130 ReservationListV1,
131 MetadataV1,
132 ReservationListV2,
133 MasterEditionV2,
134 EditionMarker,
135 UseAuthorityRecord,
136 CollectionAuthorityRecord,
137 TokenOwnedEscrow,
138 TokenRecord,
139 MetadataDelegate,
140}
141
142#[cfg(feature = "serde-feature")]
143fn deser_option_pubkey<'de, D>(deserializer: D) -> Result<Option<Pubkey>, D::Error>
144where
145 D: Deserializer<'de>,
146{
147 <Option<String> as serde::de::Deserialize>::deserialize(deserializer)?
148 .map(|s| Pubkey::from_str(&s))
149 .transpose()
150 .map_err(serde::de::Error::custom)
151}
152
153#[cfg(feature = "serde-feature")]
154fn ser_option_pubkey<S>(pubkey: &Option<Pubkey>, serializer: S) -> Result<S::Ok, S::Error>
155where
156 S: serde::Serializer,
157{
158 let pubkey_string = pubkey.as_ref().map(|p| p.to_string());
159 serde::ser::Serialize::serialize(&pubkey_string, serializer)
160}
161
162pub trait Resizable: TokenMetadataAccount + BorshSerialize {
170 fn save<'a>(
175 &self,
176 account_info: &'a AccountInfo<'a>,
177 payer_info: &'a AccountInfo<'a>,
178 system_program_info: &'a AccountInfo<'a>,
179 ) -> Result<(), ProgramError> {
180 let required_size = Self::size();
182
183 if account_info.data_len() != required_size {
184 resize_or_reallocate_account_raw(
185 account_info,
186 payer_info,
187 system_program_info,
188 required_size,
189 )?;
190 }
191
192 let mut account_data = account_info.data.borrow_mut();
193 let mut storage = &mut account_data[..required_size];
196 BorshSerialize::serialize(self, &mut storage)?;
197
198 Ok(())
199 }
200
201 fn from_bytes(data: &[u8]) -> Result<Self, ProgramError>;
206}