Skip to content

Commit b06e6d8

Browse files
committed
Add SpecificationAssetClass and searchable Interface for BubblegumV2 assets. (#265)
* Fix docker build * Fix clippy error * Add category to RPC response for content, if present * Add BubblegumV2 specification asset class enum value * Regenerate SeaORM active enums * Use BubblegumV2 interface * Update integration test results
1 parent edc39c9 commit b06e6d8

File tree

25 files changed

+186
-123
lines changed

25 files changed

+186
-123
lines changed

blockbuster/src/programs/bubblegum/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use mpl_bubblegum::{
1616
types::{BubblegumEventType, MetadataArgs, UpdateArgs},
1717
};
1818
pub use mpl_bubblegum::{
19-
types::{LeafSchema, UseMethod},
19+
types::{LeafSchema, UseMethod, Version},
2020
InstructionName, LeafSchemaEvent, ID,
2121
};
2222
use solana_sdk::pubkey::Pubkey;

digital_asset_types/src/dao/generated/sea_orm_active_enums.rs

Lines changed: 88 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,80 @@
33
use sea_orm::entity::prelude::*;
44
use serde::{Deserialize, Serialize};
55

6+
#[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Serialize, Deserialize)]
7+
#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "task_status")]
8+
pub enum TaskStatus {
9+
#[sea_orm(string_value = "failed")]
10+
Failed,
11+
#[sea_orm(string_value = "pending")]
12+
Pending,
13+
#[sea_orm(string_value = "running")]
14+
Running,
15+
#[sea_orm(string_value = "success")]
16+
Success,
17+
}
18+
#[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Serialize, Deserialize)]
19+
#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "mutability")]
20+
pub enum Mutability {
21+
#[sea_orm(string_value = "immutable")]
22+
Immutable,
23+
#[sea_orm(string_value = "mutable")]
24+
Mutable,
25+
#[sea_orm(string_value = "unknown")]
26+
Unknown,
27+
}
28+
#[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Serialize, Deserialize)]
29+
#[sea_orm(
30+
rs_type = "String",
31+
db_type = "Enum",
32+
enum_name = "specification_versions"
33+
)]
34+
pub enum SpecificationVersions {
35+
#[sea_orm(string_value = "unknown")]
36+
Unknown,
37+
#[sea_orm(string_value = "v0")]
38+
V0,
39+
#[sea_orm(string_value = "v1")]
40+
V1,
41+
#[sea_orm(string_value = "v2")]
42+
V2,
43+
}
44+
#[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Serialize, Deserialize)]
45+
#[sea_orm(
46+
rs_type = "String",
47+
db_type = "Enum",
48+
enum_name = "v1_account_attachments"
49+
)]
50+
pub enum V1AccountAttachments {
51+
#[sea_orm(string_value = "edition")]
52+
Edition,
53+
#[sea_orm(string_value = "edition_marker")]
54+
EditionMarker,
55+
#[sea_orm(string_value = "master_edition_v1")]
56+
MasterEditionV1,
57+
#[sea_orm(string_value = "master_edition_v2")]
58+
MasterEditionV2,
59+
#[sea_orm(string_value = "token_inscription")]
60+
TokenInscription,
61+
#[sea_orm(string_value = "unknown")]
62+
Unknown,
63+
}
64+
#[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Serialize, Deserialize)]
65+
#[sea_orm(
66+
rs_type = "String",
67+
db_type = "Enum",
68+
enum_name = "royalty_target_type"
69+
)]
70+
pub enum RoyaltyTargetType {
71+
#[sea_orm(string_value = "creators")]
72+
Creators,
73+
#[sea_orm(string_value = "fanout")]
74+
Fanout,
75+
#[sea_orm(string_value = "single")]
76+
Single,
77+
#[sea_orm(string_value = "unknown")]
78+
Unknown,
79+
}
680
#[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Serialize, Deserialize)]
781
#[sea_orm(
882
rs_type = "String",
@@ -16,6 +90,8 @@ pub enum SpecificationAssetClass {
1690
FungibleToken,
1791
#[sea_orm(string_value = "IDENTITY_NFT")]
1892
IdentityNft,
93+
#[sea_orm(string_value = "MPL_BUBBLEGUM_V2")]
94+
MplBubblegumV2,
1995
#[sea_orm(string_value = "MPL_CORE_ASSET")]
2096
MplCoreAsset,
2197
#[sea_orm(string_value = "MPL_CORE_COLLECTION")]
@@ -36,46 +112,14 @@ pub enum SpecificationAssetClass {
36112
Unknown,
37113
}
38114
#[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Serialize, Deserialize)]
39-
#[sea_orm(
40-
rs_type = "String",
41-
db_type = "Enum",
42-
enum_name = "royalty_target_type"
43-
)]
44-
pub enum RoyaltyTargetType {
45-
#[sea_orm(string_value = "creators")]
46-
Creators,
47-
#[sea_orm(string_value = "fanout")]
48-
Fanout,
49-
#[sea_orm(string_value = "single")]
50-
Single,
51-
#[sea_orm(string_value = "unknown")]
52-
Unknown,
53-
}
54-
#[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Serialize, Deserialize)]
55-
#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "owner_type")]
56-
pub enum OwnerType {
57-
#[sea_orm(string_value = "single")]
58-
Single,
59-
#[sea_orm(string_value = "token")]
60-
Token,
61-
#[sea_orm(string_value = "unknown")]
62-
Unknown,
63-
}
64-
#[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Serialize, Deserialize)]
65-
#[sea_orm(
66-
rs_type = "String",
67-
db_type = "Enum",
68-
enum_name = "specification_versions"
69-
)]
70-
pub enum SpecificationVersions {
115+
#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "chain_mutability")]
116+
pub enum ChainMutability {
117+
#[sea_orm(string_value = "immutable")]
118+
Immutable,
119+
#[sea_orm(string_value = "mutable")]
120+
Mutable,
71121
#[sea_orm(string_value = "unknown")]
72122
Unknown,
73-
#[sea_orm(string_value = "v0")]
74-
V0,
75-
#[sea_orm(string_value = "v1")]
76-
V1,
77-
#[sea_orm(string_value = "v2")]
78-
V2,
79123
}
80124
#[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Serialize, Deserialize)]
81125
#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "instruction")]
@@ -142,54 +186,12 @@ pub enum Instruction {
142186
VerifyCreatorV2,
143187
}
144188
#[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Serialize, Deserialize)]
145-
#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "mutability")]
146-
pub enum Mutability {
147-
#[sea_orm(string_value = "immutable")]
148-
Immutable,
149-
#[sea_orm(string_value = "mutable")]
150-
Mutable,
151-
#[sea_orm(string_value = "unknown")]
152-
Unknown,
153-
}
154-
#[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Serialize, Deserialize)]
155-
#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "task_status")]
156-
pub enum TaskStatus {
157-
#[sea_orm(string_value = "failed")]
158-
Failed,
159-
#[sea_orm(string_value = "pending")]
160-
Pending,
161-
#[sea_orm(string_value = "running")]
162-
Running,
163-
#[sea_orm(string_value = "success")]
164-
Success,
165-
}
166-
#[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Serialize, Deserialize)]
167-
#[sea_orm(
168-
rs_type = "String",
169-
db_type = "Enum",
170-
enum_name = "v1_account_attachments"
171-
)]
172-
pub enum V1AccountAttachments {
173-
#[sea_orm(string_value = "edition")]
174-
Edition,
175-
#[sea_orm(string_value = "edition_marker")]
176-
EditionMarker,
177-
#[sea_orm(string_value = "master_edition_v1")]
178-
MasterEditionV1,
179-
#[sea_orm(string_value = "master_edition_v2")]
180-
MasterEditionV2,
181-
#[sea_orm(string_value = "token_inscription")]
182-
TokenInscription,
183-
#[sea_orm(string_value = "unknown")]
184-
Unknown,
185-
}
186-
#[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Serialize, Deserialize)]
187-
#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "chain_mutability")]
188-
pub enum ChainMutability {
189-
#[sea_orm(string_value = "immutable")]
190-
Immutable,
191-
#[sea_orm(string_value = "mutable")]
192-
Mutable,
189+
#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "owner_type")]
190+
pub enum OwnerType {
191+
#[sea_orm(string_value = "single")]
192+
Single,
193+
#[sea_orm(string_value = "token")]
194+
Token,
193195
#[sea_orm(string_value = "unknown")]
194196
Unknown,
195197
}

digital_asset_types/src/dapi/common/asset.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,16 @@ pub fn asset_to_rpc(asset: FullAsset, options: &Options) -> Result<RpcAsset, DbE
382382
let rpc_authorities = to_authority(authorities);
383383
let rpc_creators = to_creators(creators);
384384
let rpc_groups = to_grouping(groups, options)?;
385-
let interface = get_interface(&asset)?;
385+
386+
// Hardcode interface if it's a BubblegumV2 asset that was indexed before the specific
387+
// interface was created. We infer this by checking if the asset is compressed and has
388+
// a saved collection hash.
389+
let interface = if asset.compressed && asset.collection_hash.is_some() {
390+
Interface::MplBubblegumV2
391+
} else {
392+
get_interface(&asset)?
393+
};
394+
386395
let content = get_content(&data);
387396
let mut chain_data_selector_fn = jsonpath_lib::selector(&data.chain_data);
388397
let chain_data_selector = &mut chain_data_selector_fn;
@@ -510,11 +519,13 @@ pub fn asset_to_rpc(asset: FullAsset, options: &Options) -> Result<RpcAsset, DbE
510519
.map(|o| bs58::encode(o).into_string())
511520
.unwrap_or("".to_string()),
512521
}),
522+
513523
supply: match interface {
514524
Interface::V1NFT
515525
| Interface::LEGACY_NFT
516526
| Interface::Nft
517527
| Interface::ProgrammableNFT
528+
| Interface::MplBubblegumV2
518529
| Interface::Custom => Some(Supply {
519530
edition_nonce,
520531
print_current_supply: 0,

digital_asset_types/src/rpc/asset.rs

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ pub enum Interface {
4747
MplCoreAsset,
4848
#[serde(rename = "MplCoreCollection")]
4949
MplCoreCollection,
50+
#[serde(rename = "MplBubblegumV2")]
51+
MplBubblegumV2,
5052
#[default]
5153
#[serde(rename = "Custom")]
5254
Custom,
@@ -55,20 +57,21 @@ pub enum Interface {
5557
impl From<(Option<&SpecificationVersions>, &SpecificationAssetClass)> for Interface {
5658
fn from(i: (Option<&SpecificationVersions>, &SpecificationAssetClass)) -> Self {
5759
match i {
60+
(_, SpecificationAssetClass::FungibleAsset) => Interface::FungibleAsset,
61+
(_, SpecificationAssetClass::FungibleToken) => Interface::FungibleToken,
62+
(_, SpecificationAssetClass::MplBubblegumV2) => Interface::MplBubblegumV2,
63+
(_, SpecificationAssetClass::MplCoreAsset) => Interface::MplCoreAsset,
64+
(_, SpecificationAssetClass::MplCoreCollection) => Interface::MplCoreCollection,
65+
(Some(SpecificationVersions::V0), SpecificationAssetClass::Nft) => {
66+
Interface::LEGACY_NFT
67+
}
5868
(Some(SpecificationVersions::V1), SpecificationAssetClass::Nft) => Interface::V1NFT,
5969
(Some(SpecificationVersions::V1), SpecificationAssetClass::PrintableNft) => {
6070
Interface::V1NFT
6171
}
62-
(Some(SpecificationVersions::V0), SpecificationAssetClass::Nft) => {
63-
Interface::LEGACY_NFT
64-
}
6572
(Some(SpecificationVersions::V1), SpecificationAssetClass::ProgrammableNft) => {
6673
Interface::ProgrammableNFT
6774
}
68-
(_, SpecificationAssetClass::MplCoreAsset) => Interface::MplCoreAsset,
69-
(_, SpecificationAssetClass::MplCoreCollection) => Interface::MplCoreCollection,
70-
(_, SpecificationAssetClass::FungibleAsset) => Interface::FungibleAsset,
71-
(_, SpecificationAssetClass::FungibleToken) => Interface::FungibleToken,
7275
_ => Interface::Custom,
7376
}
7477
}
@@ -78,16 +81,20 @@ impl From<Interface> for (SpecificationVersions, SpecificationAssetClass) {
7881
fn from(interface: Interface) -> (SpecificationVersions, SpecificationAssetClass) {
7982
match interface {
8083
Interface::V1NFT => (SpecificationVersions::V1, SpecificationAssetClass::Nft),
81-
Interface::LEGACY_NFT => (SpecificationVersions::V0, SpecificationAssetClass::Nft),
82-
Interface::ProgrammableNFT => (
83-
SpecificationVersions::V1,
84-
SpecificationAssetClass::ProgrammableNft,
85-
),
8684
Interface::V1PRINT => (SpecificationVersions::V1, SpecificationAssetClass::Print),
85+
Interface::LEGACY_NFT => (SpecificationVersions::V0, SpecificationAssetClass::Nft),
8786
Interface::FungibleAsset => (
8887
SpecificationVersions::V1,
8988
SpecificationAssetClass::FungibleAsset,
9089
),
90+
Interface::FungibleToken => (
91+
SpecificationVersions::V1,
92+
SpecificationAssetClass::FungibleToken,
93+
),
94+
Interface::ProgrammableNFT => (
95+
SpecificationVersions::V1,
96+
SpecificationAssetClass::ProgrammableNft,
97+
),
9198
Interface::MplCoreAsset => (
9299
SpecificationVersions::V1,
93100
SpecificationAssetClass::MplCoreAsset,
@@ -96,9 +103,9 @@ impl From<Interface> for (SpecificationVersions, SpecificationAssetClass) {
96103
SpecificationVersions::V1,
97104
SpecificationAssetClass::MplCoreCollection,
98105
),
99-
Interface::FungibleToken => (
106+
Interface::MplBubblegumV2 => (
100107
SpecificationVersions::V1,
101-
SpecificationAssetClass::FungibleToken,
108+
SpecificationAssetClass::MplBubblegumV2,
102109
),
103110
_ => (SpecificationVersions::V1, SpecificationAssetClass::Unknown),
104111
}

integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests_v2_leaf_schema__add_asset_to_collection_using_set_collection_v2.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ assertion_line: 33
44
expression: response
55
---
66
{
7-
"interface": "V1_NFT",
7+
"interface": "MplBubblegumV2",
88
"id": "5fADezYRRBaiLcRrSMC5Wsqj4mpd4BJkJvjTTQBWaB5T",
99
"content": {
1010
"$schema": "https://schema.metaplex.com/nft1.0.json",

integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests_v2_leaf_schema__change_collection_using_set_collection_v2.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ assertion_line: 33
44
expression: response
55
---
66
{
7-
"interface": "V1_NFT",
7+
"interface": "MplBubblegumV2",
88
"id": "7xNZ8rh4zH9EoACqEWymt5FSwgjbkDM1uFQ6MSB6kwc8",
99
"content": {
1010
"$schema": "https://schema.metaplex.com/nft1.0.json",

integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests_v2_leaf_schema__delegate_and_freeze_v2.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ assertion_line: 33
44
expression: response
55
---
66
{
7-
"interface": "V1_NFT",
7+
"interface": "MplBubblegumV2",
88
"id": "5ryKjZ554B9aSKWyEH4kprdjQSvRk3ioAVPgsxRqcDAf",
99
"content": {
1010
"$schema": "https://schema.metaplex.com/nft1.0.json",

integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests_v2_leaf_schema__delegate_v2.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ assertion_line: 33
44
expression: response
55
---
66
{
7-
"interface": "V1_NFT",
7+
"interface": "MplBubblegumV2",
88
"id": "6F3Dv73qYxay78WtGMqjB4voY7E8GSmYvbq8nDNroAeC",
99
"content": {
1010
"$schema": "https://schema.metaplex.com/nft1.0.json",

integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests_v2_leaf_schema__freeze_v2.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ assertion_line: 33
44
expression: response
55
---
66
{
7-
"interface": "V1_NFT",
7+
"interface": "MplBubblegumV2",
88
"id": "4ynkSgr8S9pq3a2ynNHVfJbAcBrBxJUFkRCkwmjEc3TS",
99
"content": {
1010
"$schema": "https://schema.metaplex.com/nft1.0.json",

integration_tests/tests/integration_tests/snapshots/integration_tests__cnft_tests_v2_leaf_schema__freeze_v2_using_permanent_delegate.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ assertion_line: 33
44
expression: response
55
---
66
{
7-
"interface": "V1_NFT",
7+
"interface": "MplBubblegumV2",
88
"id": "9j8QfKwJvzjiHwcRyi1TCK7sZgm8iEBpGn8sRyGF5Wy8",
99
"content": {
1010
"$schema": "https://schema.metaplex.com/nft1.0.json",

0 commit comments

Comments
 (0)