Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/grpc-ingest' into triton-build
Browse files Browse the repository at this point in the history
  • Loading branch information
kespinola committed Jan 15, 2025
2 parents ecde43d + a464fd3 commit c24b6d4
Show file tree
Hide file tree
Showing 184 changed files with 5,851 additions and 506 deletions.
504 changes: 256 additions & 248 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ lru = "0.12.3"
metrics = "0.20.1"
migration = { path = "migration" }
mime_guess = "2.0.4"
mpl-bubblegum = "1.2.0"
mpl-account-compression = "0.4.2"
mpl-bubblegum = "1.4.0"
mpl-core = { version = "0.8.0-beta.1", features = ["serde"] }
mpl-noop = "0.2.1"
mpl-token-metadata = "4.1.1"
Expand Down
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
70 changes: 63 additions & 7 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,6 +56,29 @@ 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_fee_config.is_some()
|| self.interest_bearing_config.is_some()
|| self.transfer_fee_config.is_some()
|| self.mint_close_authority.is_some()
|| self.permanent_delegate.is_some()
|| self.metadata_pointer.is_some()
|| self.metadata.is_some()
|| self.transfer_hook.is_some()
|| self.group_pointer.is_some()
|| self.token_group.is_some()
|| self.group_member_pointer.is_some()
|| self.token_group_member.is_some()
}
}

#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
Expand All @@ -62,6 +87,17 @@ 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 {
pub fn is_some(&self) -> bool {
self.confidential_transfer.is_some()
|| self.cpi_guard.is_some()
|| self.memo_transfer.is_some()
|| self.transfer_fee_amount.is_some()
}
}
#[derive(Debug, PartialEq)]
pub struct TokenAccount {
Expand Down Expand Up @@ -134,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 @@ -144,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 @@ -153,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 @@ -174,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 @@ -198,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

0 comments on commit c24b6d4

Please sign in to comment.