Skip to main content

mpl_bubblegum/
traits.rs

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
10// LeafSchema
11
12impl 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
133// TODO where is this used
134impl 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
147// Version
148
149impl 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
165/// MetadataArgs
166/// Differences:
167/// `edition_nonce` not present in V2, default to `None`
168/// `collection` is always considered verified in V2
169/// `uses` not present in V2, default to `None`
170/// `token_program_version` not present in V2, default to `TokenProgramVersion::Original`
171impl 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, // Not present in V2, default to `None`
181            token_standard: v2.token_standard,
182            collection: v2.collection.map(|key| Collection {
183                key,
184                verified: true, // `collection` is always considered verified in V2
185            }),
186            uses: None, // Not present in V2, default to `None`
187            token_program_version: TokenProgramVersion::Original, // Default value
188            creators: v2.creators,
189        }
190    }
191}
192
193// UpdateArgs
194
195impl 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}