core_preview/hooked/
plugin.rs1use borsh::BorshDeserialize;
2use solana_program::account_info::AccountInfo;
3
4use crate::{
5 accounts::{BaseAssetV1, PluginHeaderV1, PluginRegistryV1},
6 errors::MplCoreError,
7 types::{Plugin, PluginAuthority, PluginType, RegistryRecord},
8 AttributesPlugin, BaseAuthority, BasePlugin, BurnDelegatePlugin, DataBlob,
9 FreezeDelegatePlugin, PermanentBurnDelegatePlugin, PermanentFreezeDelegatePlugin,
10 PermanentTransferDelegatePlugin, PluginsList, RoyaltiesPlugin, SolanaAccount,
11 TransferDelegatePlugin, UpdateDelegatePlugin,
12};
13
14pub fn fetch_plugin<T: DataBlob + SolanaAccount, U: BorshDeserialize>(
16 account: &AccountInfo,
17 plugin_type: PluginType,
18) -> Result<(PluginAuthority, U, usize), std::io::Error> {
19 let asset = T::load(account, 0)?;
20
21 if asset.get_size() == account.data_len() {
22 return Err(std::io::Error::new(
23 std::io::ErrorKind::Other,
24 MplCoreError::PluginNotFound.to_string(),
25 ));
26 }
27
28 let header = PluginHeaderV1::load(account, asset.get_size())?;
29 let PluginRegistryV1 { registry, .. } =
30 PluginRegistryV1::load(account, header.plugin_registry_offset as usize)?;
31
32 let registry_record = registry
34 .iter()
35 .find(|record| record.plugin_type == plugin_type)
36 .ok_or(std::io::Error::new(
37 std::io::ErrorKind::Other,
38 MplCoreError::PluginNotFound.to_string(),
39 ))?;
40
41 let plugin =
43 Plugin::deserialize(&mut &(*account.data).borrow()[(registry_record.offset as usize)..])?;
44
45 if PluginType::from(&plugin) != plugin_type {
46 return Err(std::io::Error::new(
47 std::io::ErrorKind::Other,
48 MplCoreError::PluginNotFound.to_string(),
49 ));
50 }
51
52 let inner = U::deserialize(
53 &mut &(*account.data).borrow()[registry_record.offset.checked_add(1).ok_or(
54 std::io::Error::new(
55 std::io::ErrorKind::Other,
56 MplCoreError::NumericalOverflow.to_string(),
57 ),
58 )? as usize..],
59 )?;
60
61 Ok((
63 registry_record.authority.clone(),
64 inner,
65 registry_record.offset as usize,
66 ))
67}
68
69pub fn fetch_plugins(account: &[u8]) -> Result<Vec<RegistryRecord>, std::io::Error> {
71 let asset = BaseAssetV1::from_bytes(account)?;
72
73 let header = PluginHeaderV1::from_bytes(&account[asset.get_size()..])?;
74 let PluginRegistryV1 { registry, .. } =
75 PluginRegistryV1::from_bytes(&account[(header.plugin_registry_offset as usize)..])?;
76
77 Ok(registry)
78}
79
80pub fn list_plugins(account: &[u8]) -> Result<Vec<PluginType>, std::io::Error> {
82 let asset = BaseAssetV1::from_bytes(account)?;
83
84 let header = PluginHeaderV1::from_bytes(&account[asset.get_size()..])?;
85 let PluginRegistryV1 { registry, .. } =
86 PluginRegistryV1::from_bytes(&account[(header.plugin_registry_offset as usize)..])?;
87
88 Ok(registry
89 .iter()
90 .map(|registry_record| registry_record.plugin_type.clone())
91 .collect())
92}
93
94pub fn registry_records_to_plugin_list(
95 registry_records: &[RegistryRecord],
96 account_data: &[u8],
97) -> Result<PluginsList, std::io::Error> {
98 let result = registry_records
99 .iter()
100 .try_fold(PluginsList::default(), |mut acc, record| {
101 let authority: BaseAuthority = record.authority.clone().into();
102 let base = BasePlugin {
103 authority,
104 offset: Some(record.offset),
105 };
106 let plugin = Plugin::deserialize(&mut &account_data[record.offset as usize..])?;
107
108 match plugin {
109 Plugin::Royalties(royalties) => {
110 acc.royalties = Some(RoyaltiesPlugin { base, royalties });
111 }
112 Plugin::FreezeDelegate(freeze_delegate) => {
113 acc.freeze_delegate = Some(FreezeDelegatePlugin {
114 base,
115 freeze_delegate,
116 });
117 }
118 Plugin::BurnDelegate(burn_delegate) => {
119 acc.burn_delegate = Some(BurnDelegatePlugin {
120 base,
121 burn_delegate,
122 });
123 }
124 Plugin::TransferDelegate(transfer_delegate) => {
125 acc.transfer_delegate = Some(TransferDelegatePlugin {
126 base,
127 transfer_delegate,
128 });
129 }
130 Plugin::UpdateDelegate(update_delegate) => {
131 acc.update_delegate = Some(UpdateDelegatePlugin {
132 base,
133 update_delegate,
134 });
135 }
136 Plugin::PermanentFreezeDelegate(permanent_freeze_delegate) => {
137 acc.permanent_freeze_delegate = Some(PermanentFreezeDelegatePlugin {
138 base,
139 permanent_freeze_delegate,
140 });
141 }
142 Plugin::Attributes(attributes) => {
143 acc.attributes = Some(AttributesPlugin { base, attributes });
144 }
145 Plugin::PermanentTransferDelegate(permanent_transfer_delegate) => {
146 acc.permanent_transfer_delegate = Some(PermanentTransferDelegatePlugin {
147 base,
148 permanent_transfer_delegate,
149 })
150 }
151 Plugin::PermanentBurnDelegate(permanent_burn_delegate) => {
152 acc.permanent_burn_delegate = Some(PermanentBurnDelegatePlugin {
153 base,
154 permanent_burn_delegate,
155 })
156 }
157 };
158
159 Ok(acc)
160 });
161
162 result
163}