Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Token Type Filter in search_assets fuction #186

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions blockbuster/src/programs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ use bubblegum::BubblegumInstruction;
use mpl_core_program::MplCoreAccountState;
use token_account::TokenProgramAccount;
use token_extensions::TokenExtensionsProgramAccount;
use token_inscriptions::TokenInscriptionAccount;
use token_metadata::TokenMetadataAccountState;

pub mod bubblegum;
pub mod mpl_core_program;
pub mod token_account;
pub mod token_extensions;
pub mod token_inscriptions;
pub mod token_metadata;

// Note: `ProgramParseResult` used to contain the following variants that have been deprecated and
Expand All @@ -30,5 +32,6 @@ pub enum ProgramParseResult<'a> {
TokenMetadata(&'a TokenMetadataAccountState),
TokenProgramAccount(&'a TokenProgramAccount),
TokenExtensionsProgramAccount(&'a TokenExtensionsProgramAccount),
TokenInscriptionAccount(&'a TokenInscriptionAccount),
Unknown,
}
17 changes: 0 additions & 17 deletions blockbuster/src/programs/token_extensions/extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ use spl_token_2022::extension::{
default_account_state::DefaultAccountState,
group_member_pointer::GroupMemberPointer,
group_pointer::GroupPointer,
immutable_owner::ImmutableOwner,
interest_bearing_mint::{BasisPoints, InterestBearingConfig},
memo_transfer::MemoTransfer,
metadata_pointer::MetadataPointer,
Expand Down Expand Up @@ -77,9 +76,6 @@ pub struct ShadowDefaultAccountState {
pub state: PodAccountState,
}

#[derive(Clone, Copy, Debug, Default, PartialEq, Zeroable, Serialize, Deserialize)]
pub struct ShadowImmutableOwner;

#[derive(Clone, Copy, Debug, Default, PartialEq, Zeroable, Serialize, Deserialize)]
pub struct ShadowInterestBearingConfig {
pub rate_authority: OptionalNonZeroPubkey,
Expand All @@ -97,20 +93,16 @@ pub struct ShadowMemoTransfer {

#[derive(Clone, Copy, Debug, Default, PartialEq, Zeroable, Serialize, Deserialize)]
pub struct ShadowMetadataPointer {
pub authority: OptionalNonZeroPubkey,
pub metadata_address: OptionalNonZeroPubkey,
}

#[derive(Clone, Copy, Debug, Default, PartialEq, Zeroable, Serialize, Deserialize)]
pub struct ShadowGroupMemberPointer {
pub authority: OptionalNonZeroPubkey,
pub member_address: OptionalNonZeroPubkey,
}

#[derive(Clone, Copy, Debug, Default, PartialEq, Zeroable, Serialize, Deserialize)]
pub struct ShadowGroupPointer {
/// Authority that can set the group address
pub authority: OptionalNonZeroPubkey,
/// Account address that holds the group
pub group_address: OptionalNonZeroPubkey,
}
Expand Down Expand Up @@ -348,12 +340,6 @@ impl From<DefaultAccountState> for ShadowDefaultAccountState {
}
}

impl From<ImmutableOwner> for ShadowImmutableOwner {
fn from(_: ImmutableOwner) -> Self {
ShadowImmutableOwner
}
}

impl From<ConfidentialTransferFeeAmount> for ShadowConfidentialTransferFeeAmount {
fn from(original: ConfidentialTransferFeeAmount) -> Self {
ShadowConfidentialTransferFeeAmount {
Expand Down Expand Up @@ -381,7 +367,6 @@ impl From<MemoTransfer> for ShadowMemoTransfer {
impl From<MetadataPointer> for ShadowMetadataPointer {
fn from(original: MetadataPointer) -> Self {
ShadowMetadataPointer {
authority: original.authority,
metadata_address: original.metadata_address,
}
}
Expand All @@ -390,7 +375,6 @@ impl From<MetadataPointer> for ShadowMetadataPointer {
impl From<GroupPointer> for ShadowGroupPointer {
fn from(original: GroupPointer) -> Self {
ShadowGroupPointer {
authority: original.authority,
group_address: original.group_address,
}
}
Expand Down Expand Up @@ -420,7 +404,6 @@ impl From<TokenGroupMember> for ShadowTokenGroupMember {
impl From<GroupMemberPointer> for ShadowGroupMemberPointer {
fn from(original: GroupMemberPointer) -> Self {
ShadowGroupMemberPointer {
authority: original.authority,
member_address: original.member_address,
}
}
Expand Down
43 changes: 35 additions & 8 deletions blockbuster/src/programs/token_extensions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::{
program_handler::{ParseResult, ProgramParser},
programs::ProgramParseResult,
};

use serde::{Deserialize, Serialize};
use solana_sdk::{pubkey::Pubkey, pubkeys};
use spl_token_2022::{
Expand All @@ -14,10 +15,12 @@ use spl_token_2022::{
default_account_state::DefaultAccountState,
group_member_pointer::GroupMemberPointer,
group_pointer::GroupPointer,
immutable_owner::ImmutableOwner,
interest_bearing_mint::InterestBearingConfig,
memo_transfer::MemoTransfer,
metadata_pointer::MetadataPointer,
mint_close_authority::MintCloseAuthority,
non_transferable::{NonTransferable, NonTransferableAccount},
permanent_delegate::PermanentDelegate,
transfer_fee::{TransferFeeAmount, TransferFeeConfig},
transfer_hook::TransferHook,
Expand All @@ -41,7 +44,6 @@ use self::extension::{
pub struct MintAccountExtensions {
pub default_account_state: Option<ShadowDefaultAccountState>,
pub confidential_transfer_mint: Option<ShadowConfidentialTransferMint>,
pub confidential_transfer_account: Option<ShadowConfidentialTransferAccount>,
pub confidential_transfer_fee_config: Option<ShadowConfidentialTransferFeeConfig>,
pub interest_bearing_config: Option<ShadowInterestBearingConfig>,
pub transfer_fee_config: Option<ShadowTransferFeeConfig>,
Expand All @@ -54,13 +56,16 @@ pub struct MintAccountExtensions {
pub token_group: Option<ShadowTokenGroup>,
pub group_member_pointer: Option<ShadowGroupMemberPointer>,
pub token_group_member: Option<ShadowTokenGroupMember>,
// TODO : add this when spl-token-2022 is updated
// pub scaled_ui_amount: Option<ShadowScaledUiAmount>,
pub non_transferable: Option<bool>,
pub immutable_owner: Option<bool>,
}

impl MintAccountExtensions {
pub fn is_some(&self) -> bool {
self.default_account_state.is_some()
|| self.confidential_transfer_mint.is_some()
|| self.confidential_transfer_account.is_some()
|| self.confidential_transfer_fee_config.is_some()
|| self.interest_bearing_config.is_some()
|| self.transfer_fee_config.is_some()
Expand All @@ -82,6 +87,8 @@ pub struct TokenAccountExtensions {
pub cpi_guard: Option<ShadowCpiGuard>,
pub memo_transfer: Option<ShadowMemoTransfer>,
pub transfer_fee_amount: Option<ShadowTransferFeeAmount>,
pub immutable_owner: Option<bool>,
pub non_transferable_account: Option<bool>,
}

impl TokenAccountExtensions {
Expand Down Expand Up @@ -163,6 +170,16 @@ impl ProgramParser for Token2022AccountParser {
let cpi_guard = account.get_extension::<CpiGuard>().ok().copied();
let memo_transfer = account.get_extension::<MemoTransfer>().ok().copied();
let transfer_fee_amount = account.get_extension::<TransferFeeAmount>().ok().copied();
let immutable_owner = account
.get_extension::<ImmutableOwner>()
.ok()
.copied()
.map(|_| true);
let non_transferable_account = account
.get_extension::<NonTransferableAccount>()
.ok()
.copied()
.map(|_| true);

// Create a structured account with extensions
let structured_account = TokenAccount {
Expand All @@ -173,6 +190,8 @@ impl ProgramParser for Token2022AccountParser {
cpi_guard: cpi_guard.map(ShadowCpiGuard::from),
memo_transfer: memo_transfer.map(ShadowMemoTransfer::from),
transfer_fee_amount: transfer_fee_amount.map(ShadowTransferFeeAmount::from),
immutable_owner,
non_transferable_account,
},
};

Expand All @@ -182,10 +201,7 @@ impl ProgramParser for Token2022AccountParser {
.get_extension::<ConfidentialTransferMint>()
.ok()
.copied();
let confidential_transfer_account = mint
.get_extension::<ConfidentialTransferAccount>()
.ok()
.copied();

let confidential_transfer_fee_config = mint
.get_extension::<ConfidentialTransferFeeConfig>()
.ok()
Expand All @@ -203,14 +219,23 @@ impl ProgramParser for Token2022AccountParser {
let group_member_pointer = mint.get_extension::<GroupMemberPointer>().ok().copied();
let token_group_member = mint.get_extension::<TokenGroupMember>().ok().copied();
let transfer_hook = mint.get_extension::<TransferHook>().ok().copied();
let non_transferable = mint
.get_extension::<NonTransferable>()
.ok()
.copied()
.map(|_| true);

let immutable_owner = mint
.get_extension::<ImmutableOwner>()
.ok()
.copied()
.map(|_| true);

let structured_mint = MintAccount {
account: mint.base,
extensions: MintAccountExtensions {
confidential_transfer_mint: confidential_transfer_mint
.map(ShadowConfidentialTransferMint::from),
confidential_transfer_account: confidential_transfer_account
.map(ShadowConfidentialTransferAccount::from),
confidential_transfer_fee_config: confidential_transfer_fee_config
.map(ShadowConfidentialTransferFeeConfig::from),
default_account_state: default_account_state
Expand All @@ -227,6 +252,8 @@ impl ProgramParser for Token2022AccountParser {
token_group: token_group.map(ShadowTokenGroup::from),
group_member_pointer: group_member_pointer.map(ShadowGroupMemberPointer::from),
token_group_member: token_group_member.map(ShadowTokenGroupMember::from),
non_transferable,
immutable_owner,
},
};
result = TokenExtensionsProgramAccount::MintAccount(structured_mint);
Expand Down
141 changes: 141 additions & 0 deletions blockbuster/src/programs/token_inscriptions/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
use serde::{Deserialize, Serialize};
use solana_sdk::{pubkey::Pubkey, pubkeys};

use crate::{
error::BlockbusterError,
program_handler::{ParseResult, ProgramParser},
};

use super::ProgramParseResult;

pubkeys!(
inscription_program_id,
"inscokhJarcjaEs59QbQ7hYjrKz25LEPRfCbP8EmdUp"
);

pub struct TokenInscriptionParser;

#[derive(Debug, Serialize, Deserialize)]
pub struct InscriptionData {
pub authority: String,
pub root: String,
pub content: String,
pub encoding: String,
pub inscription_data: String,
pub order: u64,
pub size: u32,
pub validation_hash: Option<String>,
}

impl InscriptionData {
pub const BASE_SIZE: usize = 121;
pub const INSCRIPTION_ACC_DATA_DISC: [u8; 8] = [232, 120, 205, 47, 153, 239, 229, 224];

pub fn try_unpack_data(data: &[u8]) -> Result<Self, BlockbusterError> {
let acc_disc = &data[0..8];

if acc_disc != Self::INSCRIPTION_ACC_DATA_DISC {
return Err(BlockbusterError::InvalidAccountType);
}

if data.len() < Self::BASE_SIZE {
return Err(BlockbusterError::CustomDeserializationError(
"Inscription Data is too short".to_string(),
));
}

let authority = Pubkey::try_from(&data[8..40]).unwrap();
let mint = Pubkey::try_from(&data[40..72]).unwrap();
let inscription_data = Pubkey::try_from(&data[72..104]).unwrap();
let order = u64::from_le_bytes(data[104..112].try_into().unwrap());
let size = u32::from_le_bytes(data[112..116].try_into().unwrap());
let content_type_len = u32::from_le_bytes(data[116..120].try_into().unwrap()) as usize;
let content = String::from_utf8(data[120..120 + content_type_len].to_vec()).unwrap();
let encoding_len = u32::from_le_bytes(
data[120 + content_type_len..124 + content_type_len]
.try_into()
.unwrap(),
) as usize;

let encoding = String::from_utf8(
data[124 + content_type_len..124 + content_type_len + encoding_len].to_vec(),
)
.unwrap();

let validation_exists = u8::from_le_bytes(
data[124 + content_type_len + encoding_len..124 + content_type_len + encoding_len + 1]
.try_into()
.unwrap(),
);

let validation_hash = if validation_exists == 1 {
let validation_hash_len = u32::from_le_bytes(
data[124 + content_type_len + encoding_len + 1
..128 + content_type_len + encoding_len + 1]
.try_into()
.unwrap(),
) as usize;
Some(
String::from_utf8(
data[128 + content_type_len + encoding_len + 1
..128 + content_type_len + encoding_len + 1 + validation_hash_len]
.to_vec(),
)
.unwrap(),
)
} else {
None
};
Ok(InscriptionData {
authority: authority.to_string(),
root: mint.to_string(),
content,
encoding,
inscription_data: inscription_data.to_string(),
order,
size,
validation_hash,
})
}
}

pub struct TokenInscriptionAccount {
pub data: InscriptionData,
}

impl ParseResult for TokenInscriptionAccount {
fn result(&self) -> &Self
where
Self: Sized,
{
self
}
fn result_type(&self) -> ProgramParseResult {
ProgramParseResult::TokenInscriptionAccount(self)
}
}

impl ProgramParser for TokenInscriptionParser {
fn key(&self) -> Pubkey {
inscription_program_id()
}
fn key_match(&self, key: &Pubkey) -> bool {
key == &inscription_program_id()
}

fn handles_account_updates(&self) -> bool {
true
}

fn handles_instructions(&self) -> bool {
false
}

fn handle_account(
&self,
account_data: &[u8],
) -> Result<Box<(dyn ParseResult + 'static)>, BlockbusterError> {
let data = InscriptionData::try_unpack_data(account_data)?;
Ok(Box::new(TokenInscriptionAccount { data }))
}
}
Loading