diff --git a/Cargo.lock b/Cargo.lock index e69b46a..efa2455 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -564,6 +564,12 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "base64" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" + [[package]] name = "base64ct" version = "1.6.0" @@ -655,6 +661,7 @@ dependencies = [ "lazy_static", "log", "mpl-bubblegum", + "mpl-core", "mpl-token-metadata", "plerkle_serialization", "rand 0.8.5", @@ -2166,6 +2173,22 @@ dependencies = [ "thiserror", ] +[[package]] +name = "mpl-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2aa89feb937353e5744ca7d30132a07e7380127ad42278e92b90796c60c4b11" +dependencies = [ + "base64 0.22.0", + "borsh 0.10.3", + "num-derive 0.3.3", + "num-traits", + "serde", + "serde_with 3.7.0", + "solana-program", + "thiserror", +] + [[package]] name = "mpl-token-metadata" version = "4.1.2" diff --git a/blockbuster/Cargo.toml b/blockbuster/Cargo.toml index b9011f9..bf16b3d 100644 --- a/blockbuster/Cargo.toml +++ b/blockbuster/Cargo.toml @@ -14,6 +14,7 @@ spl-token-2022 = { version = "1.0", features = ["no-entrypoint"] } spl-account-compression = { version = "0.3.0", features = ["no-entrypoint"] } spl-noop = { version = "0.2.0", features = ["no-entrypoint"] } mpl-bubblegum = "1.2.0" +mpl-core = { version = "0.1.0", features = ["serde"] } mpl-token-metadata = { version = "4.1.1", features = ["serde"] } plerkle_serialization = { version = "1.6.0" } spl-token = { version = "4.0.0", features = ["no-entrypoint"] } diff --git a/blockbuster/src/lib.rs b/blockbuster/src/lib.rs index f62af2f..983c728 100644 --- a/blockbuster/src/lib.rs +++ b/blockbuster/src/lib.rs @@ -3,4 +3,5 @@ pub mod instruction; pub mod program_handler; pub mod programs; +pub use mpl_core; pub use mpl_token_metadata as token_metadata; diff --git a/blockbuster/src/programs/mod.rs b/blockbuster/src/programs/mod.rs index 5cd6f73..8da2fee 100644 --- a/blockbuster/src/programs/mod.rs +++ b/blockbuster/src/programs/mod.rs @@ -1,9 +1,11 @@ use bubblegum::BubblegumInstruction; +use mpl_core_program::MplCoreAccountState; use token_account::TokenProgramAccount; use token_extensions::TokenExtensionsProgramAccount; use token_metadata::TokenMetadataAccountState; pub mod bubblegum; +pub mod mpl_core_program; pub mod token_account; pub mod token_extensions; pub mod token_metadata; @@ -24,6 +26,7 @@ pub mod token_metadata; // though it did not depend on the `mpl-candy-machine` crate, it was also not being used by DAS. pub enum ProgramParseResult<'a> { Bubblegum(&'a BubblegumInstruction), + MplCore(&'a MplCoreAccountState), TokenMetadata(&'a TokenMetadataAccountState), TokenProgramAccount(&'a TokenProgramAccount), TokenExtensionsProgramAccount(&'a TokenExtensionsProgramAccount), diff --git a/blockbuster/src/programs/mpl_core_program/mod.rs b/blockbuster/src/programs/mpl_core_program/mod.rs new file mode 100644 index 0000000..fd4d6ff --- /dev/null +++ b/blockbuster/src/programs/mpl_core_program/mod.rs @@ -0,0 +1,91 @@ +use crate::{ + error::BlockbusterError, + program_handler::{ParseResult, ProgramParser}, + programs::ProgramParseResult, +}; +use borsh::BorshDeserialize; +use mpl_core::{types::Key, IndexableAsset}; +use solana_sdk::{pubkey::Pubkey, pubkeys}; + +pubkeys!(mpl_core_id, "CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d"); + +pub enum MplCoreAccountData { + Asset(IndexableAsset), + Collection(IndexableAsset), + HashedAsset, + EmptyAccount, +} + +pub struct MplCoreAccountState { + pub key: Key, + pub data: MplCoreAccountData, +} + +impl ParseResult for MplCoreAccountState { + fn result(&self) -> &Self + where + Self: Sized, + { + self + } + fn result_type(&self) -> ProgramParseResult { + ProgramParseResult::MplCore(self) + } +} + +pub struct MplCoreParser; + +impl ProgramParser for MplCoreParser { + fn key(&self) -> Pubkey { + mpl_core_id() + } + fn key_match(&self, key: &Pubkey) -> bool { + key == &mpl_core_id() + } + + fn handles_account_updates(&self) -> bool { + true + } + + fn handles_instructions(&self) -> bool { + false + } + + fn handle_account( + &self, + account_data: &[u8], + ) -> Result, BlockbusterError> { + if account_data.is_empty() { + return Ok(Box::new(MplCoreAccountState { + key: Key::Uninitialized, + data: MplCoreAccountData::EmptyAccount, + })); + } + let key = Key::try_from_slice(&account_data[0..1])?; + let mpl_core_account_state = match key { + Key::AssetV1 => { + let indexable_asset = IndexableAsset::fetch(key, account_data)?; + MplCoreAccountState { + key, + data: MplCoreAccountData::Asset(indexable_asset), + } + } + Key::CollectionV1 => { + let indexable_asset = IndexableAsset::fetch(key, account_data)?; + MplCoreAccountState { + key, + data: MplCoreAccountData::Collection(indexable_asset), + } + } + Key::Uninitialized => MplCoreAccountState { + key: Key::Uninitialized, + data: MplCoreAccountData::EmptyAccount, + }, + _ => { + return Err(BlockbusterError::AccountTypeNotImplemented); + } + }; + + Ok(Box::new(mpl_core_account_state)) + } +}