1#![allow(clippy::derivable_impls)]
2use borsh::{BorshDeserialize, BorshSerialize};
3use solana_program::{keccak, pubkey::Pubkey};
4
5use crate::types::{
6 Collection, Creator, LeafSchema, MetadataArgs, MetadataArgsV2, TokenProgramVersion,
7 TokenStandard, UpdateArgs, Version,
8};
9
10impl LeafSchema {
13 pub fn hash(&self) -> [u8; 32] {
14 match self {
15 LeafSchema::V1 {
16 id,
17 owner,
18 delegate,
19 nonce,
20 data_hash,
21 creator_hash,
22 } => keccak::hashv(&[
23 &[self.version().to_bytes()],
24 id.as_ref(),
25 owner.as_ref(),
26 delegate.as_ref(),
27 nonce.to_le_bytes().as_ref(),
28 data_hash.as_ref(),
29 creator_hash.as_ref(),
30 ])
31 .to_bytes(),
32 LeafSchema::V2 {
33 id,
34 owner,
35 delegate,
36 nonce,
37 data_hash,
38 creator_hash,
39 collection_hash,
40 asset_data_hash,
41 flags,
42 } => keccak::hashv(&[
43 &[self.version().to_bytes()],
44 id.as_ref(),
45 owner.as_ref(),
46 delegate.as_ref(),
47 nonce.to_le_bytes().as_ref(),
48 data_hash.as_ref(),
49 creator_hash.as_ref(),
50 collection_hash.as_ref(),
51 asset_data_hash.as_ref(),
52 &[*flags],
53 ])
54 .to_bytes(),
55 }
56 }
57
58 pub fn version(&self) -> Version {
59 match self {
60 LeafSchema::V1 { .. } => Version::V1,
61 LeafSchema::V2 { .. } => Version::V2,
62 }
63 }
64
65 pub fn id(&self) -> Pubkey {
66 match self {
67 LeafSchema::V1 { id, .. } => *id,
68 LeafSchema::V2 { id, .. } => *id,
69 }
70 }
71
72 pub fn owner(&self) -> Pubkey {
73 match self {
74 LeafSchema::V1 { owner, .. } => *owner,
75 LeafSchema::V2 { owner, .. } => *owner,
76 }
77 }
78
79 pub fn delegate(&self) -> Pubkey {
80 match self {
81 LeafSchema::V1 { delegate, .. } => *delegate,
82 LeafSchema::V2 { delegate, .. } => *delegate,
83 }
84 }
85
86 pub fn nonce(&self) -> u64 {
87 match self {
88 LeafSchema::V1 { nonce, .. } => *nonce,
89 LeafSchema::V2 { nonce, .. } => *nonce,
90 }
91 }
92
93 pub fn data_hash(&self) -> [u8; 32] {
94 match self {
95 LeafSchema::V1 { data_hash, .. } => *data_hash,
96 LeafSchema::V2 { data_hash, .. } => *data_hash,
97 }
98 }
99
100 pub fn creator_hash(&self) -> [u8; 32] {
101 match self {
102 LeafSchema::V1 { creator_hash, .. } => *creator_hash,
103 LeafSchema::V2 { creator_hash, .. } => *creator_hash,
104 }
105 }
106
107 pub fn collection_hash(&self) -> [u8; 32] {
108 match self {
109 LeafSchema::V1 { .. } => [0; 32],
110 LeafSchema::V2 {
111 collection_hash, ..
112 } => *collection_hash,
113 }
114 }
115
116 pub fn asset_data_hash(&self) -> [u8; 32] {
117 match self {
118 LeafSchema::V1 { .. } => [0; 32],
119 LeafSchema::V2 {
120 asset_data_hash, ..
121 } => *asset_data_hash,
122 }
123 }
124
125 pub fn flags(&self) -> u8 {
126 match self {
127 LeafSchema::V1 { .. } => 0,
128 LeafSchema::V2 { flags, .. } => *flags,
129 }
130 }
131}
132
133impl Default for LeafSchema {
135 fn default() -> Self {
136 Self::V1 {
137 id: Default::default(),
138 owner: Default::default(),
139 delegate: Default::default(),
140 nonce: 0,
141 data_hash: [0; 32],
142 creator_hash: [0; 32],
143 }
144 }
145}
146
147impl Version {
150 pub fn to_bytes(&self) -> u8 {
151 match self {
152 Version::V1 => 1,
153 Version::V2 => 2,
154 }
155 }
156}
157
158#[allow(clippy::derivable_impls)]
159impl Default for Version {
160 fn default() -> Self {
161 Version::V1
162 }
163}
164
165impl From<MetadataArgsV2> for MetadataArgs {
172 fn from(v2: MetadataArgsV2) -> Self {
173 MetadataArgs {
174 name: v2.name,
175 symbol: v2.symbol,
176 uri: v2.uri,
177 seller_fee_basis_points: v2.seller_fee_basis_points,
178 primary_sale_happened: v2.primary_sale_happened,
179 is_mutable: v2.is_mutable,
180 edition_nonce: None, token_standard: v2.token_standard,
182 collection: v2.collection.map(|key| Collection {
183 key,
184 verified: true, }),
186 uses: None, token_program_version: TokenProgramVersion::Original, creators: v2.creators,
189 }
190 }
191}
192
193impl Default for UpdateArgs {
196 fn default() -> Self {
197 Self {
198 creators: None,
199 is_mutable: None,
200 name: None,
201 primary_sale_happened: None,
202 seller_fee_basis_points: None,
203 symbol: None,
204 uri: None,
205 }
206 }
207}
208
209pub trait MetadataArgsCommon: BorshSerialize + BorshDeserialize {
210 fn version(&self) -> Version;
211
212 fn name(&self) -> &str;
213 fn set_name(&mut self, name: String);
214
215 fn symbol(&self) -> &str;
216 fn set_symbol(&mut self, symbol: String);
217
218 fn uri(&self) -> &str;
219 fn set_uri(&mut self, uri: String);
220
221 fn seller_fee_basis_points(&self) -> u16;
222 fn set_seller_fee_basis_points(&mut self, fee: u16);
223
224 fn primary_sale_happened(&self) -> bool;
225 fn set_primary_sale_happened(&mut self, primary_sale_happened: bool);
226
227 fn is_mutable(&self) -> bool;
228 fn set_is_mutable(&mut self, is_mutable: bool);
229
230 fn token_standard(&self) -> Option<&TokenStandard>;
231 fn set_token_standard(&mut self, standard: Option<TokenStandard>);
232
233 fn creators(&self) -> &Vec<Creator>;
234 fn set_creators(&mut self, creators: Vec<Creator>);
235
236 fn collection_key(&self) -> Option<Pubkey>;
237 fn collection_verified(&self) -> bool;
238}
239
240impl MetadataArgsCommon for MetadataArgs {
241 fn version(&self) -> Version {
242 Version::V1
243 }
244
245 fn name(&self) -> &str {
246 &self.name
247 }
248 fn set_name(&mut self, name: String) {
249 self.name = name;
250 }
251
252 fn symbol(&self) -> &str {
253 &self.symbol
254 }
255 fn set_symbol(&mut self, symbol: String) {
256 self.symbol = symbol;
257 }
258
259 fn uri(&self) -> &str {
260 &self.uri
261 }
262 fn set_uri(&mut self, uri: String) {
263 self.uri = uri;
264 }
265
266 fn seller_fee_basis_points(&self) -> u16 {
267 self.seller_fee_basis_points
268 }
269 fn set_seller_fee_basis_points(&mut self, fee: u16) {
270 self.seller_fee_basis_points = fee;
271 }
272
273 fn primary_sale_happened(&self) -> bool {
274 self.primary_sale_happened
275 }
276 fn set_primary_sale_happened(&mut self, primary_sale_happened: bool) {
277 self.primary_sale_happened = primary_sale_happened;
278 }
279
280 fn is_mutable(&self) -> bool {
281 self.is_mutable
282 }
283 fn set_is_mutable(&mut self, is_mutable: bool) {
284 self.is_mutable = is_mutable;
285 }
286
287 fn token_standard(&self) -> Option<&TokenStandard> {
288 self.token_standard.as_ref()
289 }
290 fn set_token_standard(&mut self, standard: Option<TokenStandard>) {
291 self.token_standard = standard;
292 }
293
294 fn creators(&self) -> &Vec<Creator> {
295 &self.creators
296 }
297 fn set_creators(&mut self, creators: Vec<Creator>) {
298 self.creators = creators;
299 }
300
301 fn collection_key(&self) -> Option<Pubkey> {
302 self.collection.as_ref().map(|collection| collection.key)
303 }
304 fn collection_verified(&self) -> bool {
305 self.collection
306 .as_ref()
307 .map_or(false, |collection| collection.verified)
308 }
309}
310
311impl MetadataArgsCommon for MetadataArgsV2 {
312 fn version(&self) -> Version {
313 Version::V2
314 }
315
316 fn name(&self) -> &str {
317 &self.name
318 }
319 fn set_name(&mut self, name: String) {
320 self.name = name;
321 }
322
323 fn symbol(&self) -> &str {
324 &self.symbol
325 }
326 fn set_symbol(&mut self, symbol: String) {
327 self.symbol = symbol;
328 }
329
330 fn uri(&self) -> &str {
331 &self.uri
332 }
333 fn set_uri(&mut self, uri: String) {
334 self.uri = uri;
335 }
336
337 fn seller_fee_basis_points(&self) -> u16 {
338 self.seller_fee_basis_points
339 }
340 fn set_seller_fee_basis_points(&mut self, fee: u16) {
341 self.seller_fee_basis_points = fee;
342 }
343
344 fn primary_sale_happened(&self) -> bool {
345 self.primary_sale_happened
346 }
347 fn set_primary_sale_happened(&mut self, primary_sale_happened: bool) {
348 self.primary_sale_happened = primary_sale_happened;
349 }
350
351 fn is_mutable(&self) -> bool {
352 self.is_mutable
353 }
354 fn set_is_mutable(&mut self, is_mutable: bool) {
355 self.is_mutable = is_mutable;
356 }
357
358 fn token_standard(&self) -> Option<&TokenStandard> {
359 self.token_standard.as_ref()
360 }
361 fn set_token_standard(&mut self, standard: Option<TokenStandard>) {
362 self.token_standard = standard;
363 }
364
365 fn creators(&self) -> &Vec<Creator> {
366 &self.creators
367 }
368 fn set_creators(&mut self, creators: Vec<Creator>) {
369 self.creators = creators;
370 }
371
372 fn collection_key(&self) -> Option<Pubkey> {
373 self.collection
374 }
375 fn collection_verified(&self) -> bool {
376 self.collection.is_some()
377 }
378}