From f7728ee5b8494b5c817c97c84bccfa83afb64065 Mon Sep 17 00:00:00 2001 From: Kirill Fomichev Date: Wed, 21 Feb 2024 16:50:46 -0500 Subject: [PATCH] program_transformers: remove plerkle --- Cargo.lock | 33 +++-- Cargo.toml | 3 + .../tests/integration_tests/common.rs | 35 +++++- nft_ingester/src/account_updates.rs | 19 ++- nft_ingester/src/lib.rs | 2 +- nft_ingester/src/main.rs | 1 + nft_ingester/src/plerkle.rs | 116 ++++++++++++++++++ nft_ingester/src/transaction_notifications.rs | 26 +++- program_transformers/Cargo.toml | 2 +- program_transformers/src/bubblegum/mint_v1.rs | 4 +- .../src/bubblegum/update_metadata.rs | 2 +- program_transformers/src/lib.rs | 94 +++++++------- program_transformers/src/token/mod.rs | 38 +++--- .../src/token_metadata/master_edition.rs | 13 +- .../src/token_metadata/mod.rs | 17 ++- .../src/token_metadata/v1_asset.rs | 7 +- 16 files changed, 297 insertions(+), 115 deletions(-) create mode 100644 nft_ingester/src/plerkle.rs diff --git a/Cargo.lock b/Cargo.lock index 2b52079e1..3e854b632 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1000,20 +1000,18 @@ checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" [[package]] name = "blockbuster" version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e71e288e73543fddc5c0f099ef7cdca8d01ca278996f73f386b9ab6d65c2b4" +source = "git+https://github.com/rpcpool/blockbuster.git?tag=blockbuster-v1.0.1-no-plerkle#4b814daa10a69dddafb1bb434f544aac864c7ffe" dependencies = [ "anchor-lang", "async-trait", "borsh 0.10.3", "bs58 0.4.0", - "flatbuffers", "lazy_static", "log", "mpl-bubblegum", "mpl-token-metadata", - "plerkle_serialization", "solana-sdk", + "solana-transaction-status", "spl-account-compression", "spl-noop", "spl-token", @@ -1826,9 +1824,9 @@ dependencies = [ [[package]] name = "deunicode" -version = "1.4.1" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a1abaf4d861455be59f64fd2b55606cb151fce304ede7165f410243ce96bde6" +checksum = "b6e854126756c496b8c81dec88f9a706b15b875c5849d4097a3854476b9fdf94" [[package]] name = "dialoguer" @@ -2113,9 +2111,9 @@ dependencies = [ [[package]] name = "fake" -version = "2.9.1" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26221445034074d46b276e13eb97a265ebdb8ed8da705c4dddd3dd20b66b45d2" +checksum = "1c25829bde82205da46e1823b2259db6273379f626fc211f126f65654a2669be" dependencies = [ "deunicode", "rand 0.8.5", @@ -2833,9 +2831,9 @@ checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" [[package]] name = "insta" -version = "1.34.0" +version = "1.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d64600be34b2fcfc267740a243fa7744441bb4947a619ac4e5bb6507f35fbfc" +checksum = "7c985c1bef99cf13c58fade470483d81a2bfe846ebde60ed28cc2dddec2df9e2" dependencies = [ "console", "lazy_static", @@ -3385,7 +3383,7 @@ dependencies = [ "num-derive 0.3.3", "num-traits", "serde", - "serde_with 3.6.0", + "serde_with 3.6.1", "solana-program", "thiserror", ] @@ -4142,10 +4140,10 @@ dependencies = [ "futures", "mpl-bubblegum", "num-traits", - "plerkle_serialization", "sea-orm", "serde_json", "solana-sdk", + "solana-transaction-status", "spl-account-compression", "spl-token", "sqlx", @@ -5206,9 +5204,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.6.0" +version = "3.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b0ed1662c5a68664f45b76d18deb0e234aff37207086803165c961eb695e981" +checksum = "15d167997bd841ec232f5b2b8e0e26606df2e7caa4c31b95ea9ca52b200bd270" dependencies = [ "base64 0.21.4", "chrono", @@ -5216,8 +5214,9 @@ dependencies = [ "indexmap 1.9.3", "indexmap 2.0.2", "serde", + "serde_derive", "serde_json", - "serde_with_macros 3.6.0", + "serde_with_macros 3.6.1", "time 0.3.29", ] @@ -5235,9 +5234,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.6.0" +version = "3.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "568577ff0ef47b879f736cd66740e022f3672788cdf002a05a4e609ea5a6fb15" +checksum = "865f9743393e638991566a8b7a479043c2c8da94a33e0a31f18214c9cae0a64d" dependencies = [ "darling", "proc-macro2 1.0.69", diff --git a/Cargo.toml b/Cargo.toml index dc9e15726..a148537a1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -118,6 +118,9 @@ clone_on_ref_ptr = "deny" missing_const_for_fn = "deny" trivially_copy_pass_by_ref = "deny" +[patch.crates-io] +blockbuster = { git = "https://github.com/rpcpool/blockbuster.git", tag = "blockbuster-v1.0.1-no-plerkle" } + [profile.release] codegen-units = 1 lto = true diff --git a/integration_tests/tests/integration_tests/common.rs b/integration_tests/tests/integration_tests/common.rs index b9d9da335..24f91e9de 100644 --- a/integration_tests/tests/integration_tests/common.rs +++ b/integration_tests/tests/integration_tests/common.rs @@ -12,13 +12,19 @@ use migration::sea_orm::{ use migration::{Migrator, MigratorTrait}; use mpl_token_metadata::accounts::Metadata; -use nft_ingester::config; +use nft_ingester::{ + config, + plerkle::{ + parse_account_keys, parse_message_instructions, parse_meta_inner_instructions, + parse_pubkey, parse_signature, parse_slice, + }, +}; use once_cell::sync::Lazy; use plerkle_serialization::root_as_account_info; use plerkle_serialization::root_as_transaction_info; use plerkle_serialization::serializer::serialize_account; use plerkle_serialization::solana_geyser_plugin_interface_shims::ReplicaAccountInfoV2; -use program_transformers::ProgramTransformer; +use program_transformers::{AccountInfo, ProgramTransformer, TransactionInfo}; use solana_client::nonblocking::rpc_client::RpcClient; use solana_sdk::pubkey::Pubkey; @@ -356,7 +362,12 @@ pub async fn index_account_bytes(setup: &TestSetup, account_bytes: Vec) { setup .transformer - .handle_account_update(account) + .handle_account_update(&AccountInfo { + slot: account.slot(), + pubkey: &parse_pubkey(account.pubkey()).expect("failed to parse account"), + owner: &parse_pubkey(account.owner()).expect("failed to parse account"), + data: parse_slice(account.data()).expect("failed to parse account"), + }) .await .unwrap(); } @@ -419,7 +430,23 @@ async fn cached_fetch_transaction(setup: &TestSetup, sig: Signature) -> Vec pub async fn index_transaction(setup: &TestSetup, sig: Signature) { let txn_bytes: Vec = cached_fetch_transaction(setup, sig).await; let txn = root_as_transaction_info(&txn_bytes).unwrap(); - setup.transformer.handle_transaction(&txn).await.unwrap(); + setup + .transformer + .handle_transaction(&TransactionInfo { + slot: txn.slot(), + signature: &parse_signature(txn.signature()).expect("failed to parse transaction"), + account_keys: &parse_account_keys(txn.account_keys()) + .expect("failed to parse transaction"), + message_instructions: &parse_message_instructions(txn.outer_instructions()) + .expect("failed to parse transaction"), + meta_inner_instructions: &parse_meta_inner_instructions( + txn.compiled_inner_instructions(), + txn.inner_instructions(), + ) + .expect("failed to parse transaction"), + }) + .await + .unwrap(); } async fn cached_fetch_largest_token_account_id(client: &RpcClient, mint: Pubkey) -> Pubkey { diff --git a/nft_ingester/src/account_updates.rs b/nft_ingester/src/account_updates.rs index 354aaf9c6..c49b6cd5e 100644 --- a/nft_ingester/src/account_updates.rs +++ b/nft_ingester/src/account_updates.rs @@ -2,6 +2,7 @@ use { crate::{ metric, metrics::capture_result, + plerkle::{parse_pubkey, parse_slice}, tasks::{create_download_metadata_notifier, TaskData}, }, cadence_macros::{is_global_default_set, statsd_count, statsd_time}, @@ -9,7 +10,7 @@ use { log::{debug, error}, plerkle_messenger::{ConsumptionType, Messenger, MessengerConfig, RecvData}, plerkle_serialization::root_as_account_info, - program_transformers::ProgramTransformer, + program_transformers::{error::ProgramTransformerResult, AccountInfo, ProgramTransformer}, sqlx::{Pool, Postgres}, std::sync::Arc, tokio::{ @@ -103,7 +104,7 @@ async fn handle_account( account = Some(bs58::encode(pubkey.0.as_slice()).into_string()); } let begin_processing = Instant::now(); - let res = manager.handle_account_update(account_update).await; + let res = handle_account_update(manager, account_update).await; let should_ack = capture_result( id.clone(), stream_key, @@ -120,3 +121,17 @@ async fn handle_account( } ret_id } + +async fn handle_account_update<'a>( + manager: Arc, + account_update: plerkle_serialization::AccountInfo<'_>, +) -> ProgramTransformerResult<()> { + manager + .handle_account_update(&AccountInfo { + slot: account_update.slot(), + pubkey: &parse_pubkey(account_update.pubkey())?, + owner: &parse_pubkey(account_update.owner())?, + data: parse_slice(account_update.data())?, + }) + .await +} diff --git a/nft_ingester/src/lib.rs b/nft_ingester/src/lib.rs index 9aee9c6ba..9569da43a 100644 --- a/nft_ingester/src/lib.rs +++ b/nft_ingester/src/lib.rs @@ -1,10 +1,10 @@ -pub mod account_updates; pub mod ack; pub mod backfiller; pub mod config; pub mod database; pub mod error; pub mod metrics; +pub mod plerkle; pub mod stream; pub mod tasks; pub mod transaction_notifications; diff --git a/nft_ingester/src/main.rs b/nft_ingester/src/main.rs index aeaf8b0fe..caf2c26f1 100644 --- a/nft_ingester/src/main.rs +++ b/nft_ingester/src/main.rs @@ -5,6 +5,7 @@ pub mod config; mod database; pub mod error; pub mod metrics; +mod plerkle; mod stream; pub mod tasks; mod transaction_notifications; diff --git a/nft_ingester/src/plerkle.rs b/nft_ingester/src/plerkle.rs new file mode 100644 index 000000000..9a3bd33ba --- /dev/null +++ b/nft_ingester/src/plerkle.rs @@ -0,0 +1,116 @@ +use { + flatbuffers::{ForwardsUOffset, Vector}, + plerkle_serialization::{ + CompiledInnerInstructions as FBCompiledInnerInstructions, + CompiledInstruction as FBCompiledInstruction, InnerInstructions as FBInnerInstructions, + Pubkey as FBPubkey, + }, + program_transformers::error::{ProgramTransformerError, ProgramTransformerResult}, + solana_sdk::{instruction::CompiledInstruction, pubkey::Pubkey, signature::Signature}, + solana_transaction_status::{InnerInstruction, InnerInstructions}, +}; + +fn deser_err() -> ProgramTransformerError { + ProgramTransformerError::DeserializationError("Could not deserialize data".to_owned()) +} + +pub fn parse_pubkey(pubkey: Option<&FBPubkey>) -> ProgramTransformerResult { + Ok(Pubkey::try_from(pubkey.ok_or_else(deser_err)?.0.as_slice()) + .expect("valid key from FlatBuffer")) +} + +pub fn parse_slice(data: Option>) -> ProgramTransformerResult<&[u8]> { + data.map(|data| data.bytes()).ok_or_else(deser_err) +} + +pub fn parse_signature(data: Option<&str>) -> ProgramTransformerResult { + data.ok_or_else(deser_err)? + .parse() + .map_err(|_error| deser_err()) +} + +pub fn parse_account_keys( + keys: Option>, +) -> ProgramTransformerResult> { + keys.ok_or_else(deser_err).map(|keys| { + keys.iter() + .map(|key| Pubkey::try_from(key.0.as_slice()).expect("valid key from FlatBuffer")) + .collect() + }) +} + +pub fn parse_message_instructions( + vec_cix: Option>>, +) -> ProgramTransformerResult> { + vec_cix.ok_or_else(deser_err).and_then(|vec| { + vec.iter() + .map(|cix| { + Ok(CompiledInstruction { + program_id_index: cix.program_id_index(), + accounts: cix.accounts().ok_or_else(deser_err)?.bytes().to_vec(), + data: cix.data().ok_or_else(deser_err)?.bytes().to_vec(), + }) + }) + .collect() + }) +} + +pub fn parse_meta_inner_instructions( + vec_ciixs: Option>>, + vec_iixs: Option>>, +) -> ProgramTransformerResult> { + if let Some(vec_ciixs) = vec_ciixs { + vec_ciixs + .iter() + .map(|ciix| { + Ok(InnerInstructions { + index: ciix.index(), + instructions: ciix + .instructions() + .ok_or_else(deser_err)? + .iter() + .map(|ix| { + let cix = ix.compiled_instruction().ok_or_else(deser_err)?; + Ok(InnerInstruction { + instruction: CompiledInstruction { + program_id_index: cix.program_id_index(), + accounts: cix + .accounts() + .ok_or_else(deser_err)? + .bytes() + .to_vec(), + data: cix.data().ok_or_else(deser_err)?.bytes().to_vec(), + }, + stack_height: Some(ix.stack_height() as u32), + }) + }) + .collect::>()?, + }) + }) + .collect() + } else if let Some(vec_iixs) = vec_iixs { + vec_iixs + .iter() + .map(|iixs| { + Ok(InnerInstructions { + index: iixs.index(), + instructions: iixs + .instructions() + .expect("valid instructions") + .iter() + .map(|cix| InnerInstruction { + instruction: CompiledInstruction { + program_id_index: cix.program_id_index(), + accounts: cix.accounts().expect("valid accounts").bytes().to_vec(), + data: cix.data().expect("valid data").bytes().to_vec(), + }, + stack_height: Some(0), + }) + .collect(), + }) + }) + .collect() + } else { + Err(deser_err()) + } +} diff --git a/nft_ingester/src/transaction_notifications.rs b/nft_ingester/src/transaction_notifications.rs index e3932eaf6..5d20d3dd4 100644 --- a/nft_ingester/src/transaction_notifications.rs +++ b/nft_ingester/src/transaction_notifications.rs @@ -2,6 +2,10 @@ use { crate::{ metric, metrics::capture_result, + plerkle::{ + parse_account_keys, parse_message_instructions, parse_meta_inner_instructions, + parse_signature, + }, tasks::{create_download_metadata_notifier, TaskData}, }, cadence_macros::{is_global_default_set, statsd_count, statsd_time}, @@ -9,7 +13,7 @@ use { log::{debug, error}, plerkle_messenger::{ConsumptionType, Messenger, MessengerConfig, RecvData}, plerkle_serialization::root_as_transaction_info, - program_transformers::ProgramTransformer, + program_transformers::{error::ProgramTransformerResult, ProgramTransformer, TransactionInfo}, sqlx::{Pool, Postgres}, std::sync::Arc, tokio::{ @@ -101,7 +105,7 @@ async fn handle_transaction( } let begin = Instant::now(); - let res = manager.handle_transaction(&tx).await; + let res = handle_transaction_update(manager, tx).await; let should_ack = capture_result( id.clone(), stream_key, @@ -118,3 +122,21 @@ async fn handle_transaction( } ret_id } + +async fn handle_transaction_update<'a>( + manager: Arc, + tx: plerkle_serialization::TransactionInfo<'_>, +) -> ProgramTransformerResult<()> { + manager + .handle_transaction(&TransactionInfo { + slot: tx.slot(), + signature: &parse_signature(tx.signature())?, + account_keys: &parse_account_keys(tx.account_keys())?, + message_instructions: &parse_message_instructions(tx.outer_instructions())?, + meta_inner_instructions: &parse_meta_inner_instructions( + tx.compiled_inner_instructions(), + tx.inner_instructions(), + )?, + }) + .await +} diff --git a/program_transformers/Cargo.toml b/program_transformers/Cargo.toml index 76cb6c0d7..5c58e7fde 100644 --- a/program_transformers/Cargo.toml +++ b/program_transformers/Cargo.toml @@ -14,10 +14,10 @@ digital_asset_types = { workspace = true, features = ["json_types", "sql_types"] futures = { workspace = true } mpl-bubblegum = { workspace = true } num-traits = { workspace = true } -plerkle_serialization = { workspace = true } sea-orm = { workspace = true } serde_json = { workspace = true } solana-sdk = { workspace = true } +solana-transaction-status = { workspace = true } spl-account-compression = { workspace = true, features = ["no-entrypoint"] } spl-token = { workspace = true, features = ["no-entrypoint"] } sqlx = { workspace = true } diff --git a/program_transformers/src/bubblegum/mint_v1.rs b/program_transformers/src/bubblegum/mint_v1.rs index a293eef8c..641156cb9 100644 --- a/program_transformers/src/bubblegum/mint_v1.rs +++ b/program_transformers/src/bubblegum/mint_v1.rs @@ -148,7 +148,7 @@ where &multi_txn, id_bytes.to_vec(), nonce as i64, - tree_id.to_vec(), + tree_id.to_bytes().to_vec(), le.leaf_hash.to_vec(), le.schema.data_hash(), le.schema.creator_hash(), @@ -183,7 +183,7 @@ where upsert_asset_authority( &multi_txn, id_bytes.to_vec(), - authority.to_vec(), + authority.to_bytes().to_vec(), seq as i64, slot_i, ) diff --git a/program_transformers/src/bubblegum/update_metadata.rs b/program_transformers/src/bubblegum/update_metadata.rs index 19d9ca615..fd01a930e 100644 --- a/program_transformers/src/bubblegum/update_metadata.rs +++ b/program_transformers/src/bubblegum/update_metadata.rs @@ -166,7 +166,7 @@ where &multi_txn, id_bytes.to_vec(), nonce as i64, - tree_id.to_vec(), + tree_id.to_bytes().to_vec(), le.leaf_hash.to_vec(), le.schema.data_hash(), le.schema.creator_hash(), diff --git a/program_transformers/src/lib.rs b/program_transformers/src/lib.rs index f11e2a0da..66dc736c4 100644 --- a/program_transformers/src/lib.rs +++ b/program_transformers/src/lib.rs @@ -14,9 +14,9 @@ use { }, }, futures::future::BoxFuture, - plerkle_serialization::{AccountInfo, Pubkey as FBPubkey, TransactionInfo}, sea_orm::{DatabaseConnection, SqlxPostgresConnector}, - solana_sdk::pubkey::Pubkey, + solana_sdk::{instruction::CompiledInstruction, pubkey::Pubkey, signature::Signature}, + solana_transaction_status::InnerInstructions, sqlx::PgPool, std::collections::{HashMap, HashSet, VecDeque}, tracing::{debug, error, info}, @@ -28,6 +28,23 @@ pub mod error; mod token; mod token_metadata; +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct AccountInfo<'a> { + pub slot: u64, + pub pubkey: &'a Pubkey, + pub owner: &'a Pubkey, + pub data: &'a [u8], +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct TransactionInfo<'a> { + pub slot: u64, + pub signature: &'a Signature, + pub account_keys: &'a [Pubkey], + pub message_instructions: &'a [CompiledInstruction], + pub meta_inner_instructions: &'a [InnerInstructions], +} + #[derive(Debug, Clone, PartialEq, Eq)] pub struct DownloadMetadataInfo { asset_data_id: Vec, @@ -90,52 +107,42 @@ impl ProgramTransformer { } } - pub fn break_transaction<'i>( + pub fn break_transaction<'a>( &self, - tx: &'i TransactionInfo<'i>, - ) -> VecDeque<(IxPair<'i>, Option>>)> { - let ref_set: HashSet<&[u8]> = self.key_set.iter().map(|k| k.as_ref()).collect(); - order_instructions(ref_set, tx) + tx_info: &'a TransactionInfo<'_>, + ) -> VecDeque<(IxPair<'a>, Option>>)> { + order_instructions( + &self.key_set, + tx_info.account_keys, + tx_info.message_instructions, + tx_info.meta_inner_instructions, + ) } #[allow(clippy::borrowed_box)] - pub fn match_program(&self, key: &FBPubkey) -> Option<&Box> { - match Pubkey::try_from(key.0.as_slice()) { - Ok(pubkey) => self.parsers.get(&pubkey), - Err(_error) => { - error!("failed to parse key: {key:?}"); - None - } - } + pub fn match_program(&self, key: &Pubkey) -> Option<&Box> { + self.parsers.get(key) } - pub async fn handle_transaction<'a>( + pub async fn handle_transaction( &self, - tx: &'a TransactionInfo<'a>, + tx_info: &TransactionInfo<'_>, ) -> ProgramTransformerResult<()> { - let sig: Option<&str> = tx.signature(); - info!("Handling Transaction: {:?}", sig); - let instructions = self.break_transaction(tx); - let accounts = tx.account_keys().unwrap_or_default(); - let slot = tx.slot(); - let txn_id = tx.signature().unwrap_or(""); - let mut keys: Vec = Vec::with_capacity(accounts.len()); - for k in accounts.into_iter() { - keys.push(*k); - } + info!("Handling Transaction: {:?}", tx_info.signature); + let instructions = self.break_transaction(tx_info); let mut not_impl = 0; let ixlen = instructions.len(); debug!("Instructions: {}", ixlen); let contains = instructions .iter() - .filter(|(ib, _inner)| ib.0 .0.as_ref() == mpl_bubblegum::ID.as_ref()); + .filter(|(ib, _inner)| ib.0 == mpl_bubblegum::ID); debug!("Instructions bgum: {}", contains.count()); for (outer_ix, inner_ix) in instructions { let (program, instruction) = outer_ix; - let ix_accounts = instruction.accounts().unwrap().iter().collect::>(); + let ix_accounts = &instruction.accounts; let ix_account_len = ix_accounts.len(); let max = ix_accounts.iter().max().copied().unwrap_or(0) as usize; - if keys.len() < max { + if tx_info.account_keys.len() < max { return Err(ProgramTransformerError::DeserializationError( "Missing Accounts in Serialized Ixn/Txn".to_string(), )); @@ -144,21 +151,22 @@ impl ProgramTransformer { ix_accounts .iter() .fold(Vec::with_capacity(ix_account_len), |mut acc, a| { - if let Some(key) = keys.get(*a as usize) { + if let Some(key) = tx_info.account_keys.get(*a as usize) { acc.push(*key); } acc }); let ix = InstructionBundle { - txn_id, + txn_id: &tx_info.signature.to_string(), program, instruction: Some(instruction), inner_ix, keys: ix_accounts.as_slice(), - slot, + slot: tx_info.slot, }; - if let Some(program) = self.match_program(&ix.program) { + let program_key = ix.program; + if let Some(program) = self.match_program(&program_key) { debug!("Found a ix for program: {:?}", program.key()); let result = program.handle_instruction(&ix)?; let concrete = result.result_type(); @@ -175,7 +183,7 @@ impl ProgramTransformer { .map_err(|err| { error!( "Failed to handle bubblegum instruction for txn {:?}: {:?}", - sig, err + tx_info.signature, err ); err })?; @@ -194,18 +202,16 @@ impl ProgramTransformer { Ok(()) } - pub async fn handle_account_update<'b>( + pub async fn handle_account_update( &self, - acct: AccountInfo<'b>, + account_info: &AccountInfo<'_>, ) -> ProgramTransformerResult<()> { - let owner = acct.owner().unwrap(); - if let Some(program) = self.match_program(owner) { - let result = program.handle_account(&acct)?; - let concrete = result.result_type(); - match concrete { + if let Some(program) = self.match_program(account_info.owner) { + let result = program.handle_account(account_info.data)?; + match result.result_type() { ProgramParseResult::TokenMetadata(parsing_result) => { handle_token_metadata_account( - &acct, + account_info, parsing_result, &self.storage, &self.download_metadata_notifier, @@ -214,7 +220,7 @@ impl ProgramTransformer { } ProgramParseResult::TokenProgramAccount(parsing_result) => { handle_token_program_account( - &acct, + account_info, parsing_result, &self.storage, &self.download_metadata_notifier, diff --git a/program_transformers/src/token/mod.rs b/program_transformers/src/token/mod.rs index 8b0590cce..2dd5d990f 100644 --- a/program_transformers/src/token/mod.rs +++ b/program_transformers/src/token/mod.rs @@ -4,12 +4,11 @@ use { upsert_assets_mint_account_columns, upsert_assets_token_account_columns, AssetMintAccountColumns, AssetTokenAccountColumns, }, - error::{ProgramTransformerError, ProgramTransformerResult}, - DownloadMetadataNotifier, + error::ProgramTransformerResult, + AccountInfo, DownloadMetadataNotifier, }, blockbuster::programs::token_account::TokenProgramAccount, digital_asset_types::dao::{asset, sea_orm_active_enums::OwnerType, token_accounts, tokens}, - plerkle_serialization::AccountInfo, sea_orm::{ entity::{ActiveValue, ColumnTrait}, query::{QueryFilter, QueryTrait}, @@ -21,14 +20,13 @@ use { }; pub async fn handle_token_program_account<'a, 'b, 'c>( - account_update: &'a AccountInfo<'a>, + account_info: &'a AccountInfo<'a>, parsing_result: &'b TokenProgramAccount, db: &'c DatabaseConnection, _download_metadata_notifier: &DownloadMetadataNotifier, ) -> ProgramTransformerResult<()> { - let key = *account_update.pubkey().unwrap(); - let key_bytes = key.0.to_vec(); - let spl_token_program = account_update.owner().unwrap().0.to_vec(); + let account_key = account_info.pubkey.to_bytes().to_vec(); + let account_owner = account_info.owner.to_bytes().to_vec(); match &parsing_result { TokenProgramAccount::TokenAccount(ta) => { let mint = ta.mint.to_bytes().to_vec(); @@ -39,14 +37,14 @@ pub async fn handle_token_program_account<'a, 'b, 'c>( let frozen = matches!(ta.state, AccountState::Frozen); let owner = ta.owner.to_bytes().to_vec(); let model = token_accounts::ActiveModel { - pubkey: ActiveValue::Set(key_bytes), + pubkey: ActiveValue::Set(account_key.clone()), mint: ActiveValue::Set(mint.clone()), delegate: ActiveValue::Set(delegate.clone()), owner: ActiveValue::Set(owner.clone()), frozen: ActiveValue::Set(frozen), delegated_amount: ActiveValue::Set(ta.delegated_amount as i64), - token_program: ActiveValue::Set(spl_token_program), - slot_updated: ActiveValue::Set(account_update.slot() as i64), + token_program: ActiveValue::Set(account_owner.clone()), + slot_updated: ActiveValue::Set(account_info.slot as i64), amount: ActiveValue::Set(ta.amount as i64), close_authority: ActiveValue::Set(None), }; @@ -89,7 +87,7 @@ pub async fn handle_token_program_account<'a, 'b, 'c>( owner: Some(owner.clone()), frozen, delegate, - slot_updated_token_account: Some(account_update.slot() as i64), + slot_updated_token_account: Some(account_info.slot as i64), }, &txn, ) @@ -109,9 +107,9 @@ pub async fn handle_token_program_account<'a, 'b, 'c>( COption::None => None, }; let model = tokens::ActiveModel { - mint: ActiveValue::Set(key_bytes.clone()), - token_program: ActiveValue::Set(spl_token_program), - slot_updated: ActiveValue::Set(account_update.slot() as i64), + mint: ActiveValue::Set(account_key.clone()), + token_program: ActiveValue::Set(account_owner), + slot_updated: ActiveValue::Set(account_info.slot as i64), supply: ActiveValue::Set(m.supply as i64), decimals: ActiveValue::Set(m.decimals as i32), close_authority: ActiveValue::Set(None), @@ -142,7 +140,7 @@ pub async fn handle_token_program_account<'a, 'b, 'c>( ); db.execute(query).await?; - let asset_update: Option = asset::Entity::find_by_id(key_bytes.clone()) + let asset_update: Option = asset::Entity::find_by_id(account_key.clone()) .filter( asset::Column::OwnerType .eq(OwnerType::Single) @@ -155,10 +153,10 @@ pub async fn handle_token_program_account<'a, 'b, 'c>( if let Some(_asset) = asset_update { upsert_assets_mint_account_columns( AssetMintAccountColumns { - mint: key_bytes.clone(), - suppply_mint: Some(key_bytes), + mint: account_key.clone(), + suppply_mint: Some(account_key), supply: m.supply, - slot_updated_mint_account: account_update.slot(), + slot_updated_mint_account: account_info.slot, }, db, ) @@ -167,7 +165,5 @@ pub async fn handle_token_program_account<'a, 'b, 'c>( Ok(()) } - _ => Err(ProgramTransformerError::NotImplemented), - }?; - Ok(()) + } } diff --git a/program_transformers/src/token_metadata/master_edition.rs b/program_transformers/src/token_metadata/master_edition.rs index e62d89932..7f76fa4b0 100644 --- a/program_transformers/src/token_metadata/master_edition.rs +++ b/program_transformers/src/token_metadata/master_edition.rs @@ -8,17 +8,17 @@ use { asset, asset_v1_account_attachments, extensions, sea_orm_active_enums::{SpecificationAssetClass, V1AccountAttachments}, }, - plerkle_serialization::Pubkey as FBPubkey, sea_orm::{ entity::{ActiveModelTrait, ActiveValue, EntityTrait, RelationTrait}, query::{JoinType, QuerySelect, QueryTrait}, sea_query::query::OnConflict, ConnectionTrait, DatabaseTransaction, DbBackend, }, + solana_sdk::pubkey::Pubkey, }; pub async fn save_v2_master_edition( - id: FBPubkey, + id: Pubkey, slot: u64, me_data: &MasterEdition, txn: &DatabaseTransaction, @@ -34,7 +34,7 @@ pub async fn save_v2_master_edition( } pub async fn save_v1_master_edition( - id: FBPubkey, + id: Pubkey, slot: u64, me_data: &DeprecatedMasterEditionV1, txn: &DatabaseTransaction, @@ -55,16 +55,17 @@ pub async fn save_v1_master_edition( ) .await } + pub async fn save_master_edition( version: V1AccountAttachments, - id: FBPubkey, + id: Pubkey, slot: u64, me_data: &MasterEdition, txn: &DatabaseTransaction, ) -> ProgramTransformerResult<()> { - let id_bytes = id.0.to_vec(); + let id_bytes = id.to_bytes().to_vec(); let master_edition: Option<(asset_v1_account_attachments::Model, Option)> = - asset_v1_account_attachments::Entity::find_by_id(id.0.to_vec()) + asset_v1_account_attachments::Entity::find_by_id(id.to_bytes().to_vec()) .find_also_related(asset::Entity) .join( JoinType::InnerJoin, diff --git a/program_transformers/src/token_metadata/mod.rs b/program_transformers/src/token_metadata/mod.rs index beb2f3a97..9f9d2783b 100644 --- a/program_transformers/src/token_metadata/mod.rs +++ b/program_transformers/src/token_metadata/mod.rs @@ -5,10 +5,9 @@ use { master_edition::{save_v1_master_edition, save_v2_master_edition}, v1_asset::{burn_v1_asset, save_v1_asset}, }, - DownloadMetadataNotifier, + AccountInfo, DownloadMetadataNotifier, }, blockbuster::programs::token_metadata::{TokenMetadataAccountData, TokenMetadataAccountState}, - plerkle_serialization::AccountInfo, sea_orm::{DatabaseConnection, TransactionTrait}, }; @@ -16,25 +15,24 @@ mod master_edition; mod v1_asset; pub async fn handle_token_metadata_account<'a, 'b, 'c>( - account_update: &'a AccountInfo<'a>, + account_info: &'a AccountInfo<'a>, parsing_result: &'b TokenMetadataAccountState, db: &'c DatabaseConnection, download_metadata_notifier: &DownloadMetadataNotifier, ) -> ProgramTransformerResult<()> { - let key = *account_update.pubkey().unwrap(); match &parsing_result.data { TokenMetadataAccountData::EmptyAccount => { - burn_v1_asset(db, key, account_update.slot()).await?; + burn_v1_asset(db, *account_info.pubkey, account_info.slot).await?; Ok(()) } TokenMetadataAccountData::MasterEditionV1(m) => { let txn = db.begin().await?; - save_v1_master_edition(key, account_update.slot(), m, &txn).await?; + save_v1_master_edition(*account_info.pubkey, account_info.slot, m, &txn).await?; txn.commit().await?; Ok(()) } TokenMetadataAccountData::MetadataV1(m) => { - if let Some(info) = save_v1_asset(db, m, account_update.slot()).await? { + if let Some(info) = save_v1_asset(db, m, account_info.slot).await? { download_metadata_notifier(info) .await .map_err(ProgramTransformerError::DownloadMetadataNotify)?; @@ -43,7 +41,7 @@ pub async fn handle_token_metadata_account<'a, 'b, 'c>( } TokenMetadataAccountData::MasterEditionV2(m) => { let txn = db.begin().await?; - save_v2_master_edition(key, account_update.slot(), m, &txn).await?; + save_v2_master_edition(*account_info.pubkey, account_info.slot, m, &txn).await?; txn.commit().await?; Ok(()) } @@ -51,6 +49,5 @@ pub async fn handle_token_metadata_account<'a, 'b, 'c>( // TokenMetadataAccountData::UseAuthorityRecord(_) => {} // TokenMetadataAccountData::CollectionAuthorityRecord(_) => {} _ => Err(ProgramTransformerError::NotImplemented), - }?; - Ok(()) + } } diff --git a/program_transformers/src/token_metadata/v1_asset.rs b/program_transformers/src/token_metadata/v1_asset.rs index fefaa0aad..95b860c3b 100644 --- a/program_transformers/src/token_metadata/v1_asset.rs +++ b/program_transformers/src/token_metadata/v1_asset.rs @@ -24,7 +24,6 @@ use { }, json::ChainDataV1, }, - plerkle_serialization::Pubkey as FBPubkey, sea_orm::{ entity::{ActiveValue, ColumnTrait, EntityTrait}, query::{JsonValue, Order, QueryFilter, QueryOrder, QueryTrait, Select}, @@ -38,12 +37,12 @@ use { pub async fn burn_v1_asset( conn: &T, - id: FBPubkey, + id: Pubkey, slot: u64, ) -> ProgramTransformerResult<()> { - let (id, slot_i) = (id.0, slot as i64); + let (id, slot_i) = (id, slot as i64); let model = asset::ActiveModel { - id: ActiveValue::Set(id.to_vec()), + id: ActiveValue::Set(id.to_bytes().to_vec()), slot_updated: ActiveValue::Set(Some(slot_i)), burnt: ActiveValue::Set(true), ..Default::default()