Include token owners in TransactionTokenBalances (#20642)
* Cache owners in TransactionTokenBalances * Light cleanup * Use return struct, and remove pub * Single-use statements * Why not, just do the whole crate * Add metrics * Make datapoint_debug to prevent spam unless troubleshooting
This commit is contained in:
parent
13462d63a2
commit
e806fa6904
|
@ -5758,10 +5758,13 @@ dependencies = [
|
|||
"bincode",
|
||||
"bs58 0.4.0",
|
||||
"lazy_static",
|
||||
"log 0.4.14",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"solana-account-decoder",
|
||||
"solana-measure",
|
||||
"solana-metrics",
|
||||
"solana-runtime",
|
||||
"solana-sdk",
|
||||
"solana-vote-program",
|
||||
|
|
|
@ -8361,6 +8361,7 @@ pub mod tests {
|
|||
amount: "11".to_string(),
|
||||
ui_amount_string: "1.1".to_string(),
|
||||
},
|
||||
owner: Pubkey::new_unique().to_string(),
|
||||
}]),
|
||||
post_token_balances: Some(vec![TransactionTokenBalance {
|
||||
account_index: 0,
|
||||
|
@ -8371,6 +8372,7 @@ pub mod tests {
|
|||
amount: "11".to_string(),
|
||||
ui_amount_string: "1.1".to_string(),
|
||||
},
|
||||
owner: Pubkey::new_unique().to_string(),
|
||||
}]),
|
||||
rewards: Some(vec![Reward {
|
||||
pubkey: "My11111111111111111111111111111111111111111".to_string(),
|
||||
|
|
|
@ -3394,10 +3394,13 @@ dependencies = [
|
|||
"bincode",
|
||||
"bs58 0.4.0",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"solana-account-decoder",
|
||||
"solana-measure",
|
||||
"solana-metrics",
|
||||
"solana-runtime",
|
||||
"solana-sdk",
|
||||
"solana-vote-program",
|
||||
|
|
|
@ -66,6 +66,7 @@ message TokenBalance {
|
|||
uint32 account_index = 1;
|
||||
string mint = 2;
|
||||
UiTokenAmount ui_token_amount = 3;
|
||||
string owner = 4;
|
||||
}
|
||||
|
||||
message UiTokenAmount {
|
||||
|
|
|
@ -408,6 +408,7 @@ impl From<TransactionTokenBalance> for generated::TokenBalance {
|
|||
amount: value.ui_token_amount.amount,
|
||||
ui_amount_string: value.ui_token_amount.ui_amount_string,
|
||||
}),
|
||||
owner: value.owner,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -435,6 +436,7 @@ impl From<generated::TokenBalance> for TransactionTokenBalance {
|
|||
)
|
||||
},
|
||||
},
|
||||
owner: value.owner,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,6 +111,8 @@ pub struct StoredTransactionTokenBalance {
|
|||
pub account_index: u8,
|
||||
pub mint: String,
|
||||
pub ui_token_amount: StoredTokenAmount,
|
||||
#[serde(deserialize_with = "default_on_eof")]
|
||||
pub owner: String,
|
||||
}
|
||||
|
||||
impl From<StoredTransactionTokenBalance> for TransactionTokenBalance {
|
||||
|
@ -119,11 +121,13 @@ impl From<StoredTransactionTokenBalance> for TransactionTokenBalance {
|
|||
account_index,
|
||||
mint,
|
||||
ui_token_amount,
|
||||
owner,
|
||||
} = value;
|
||||
Self {
|
||||
account_index,
|
||||
mint,
|
||||
ui_token_amount: ui_token_amount.into(),
|
||||
owner,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -134,11 +138,13 @@ impl From<TransactionTokenBalance> for StoredTransactionTokenBalance {
|
|||
account_index,
|
||||
mint,
|
||||
ui_token_amount,
|
||||
owner,
|
||||
} = value;
|
||||
Self {
|
||||
account_index,
|
||||
mint,
|
||||
ui_token_amount: ui_token_amount.into(),
|
||||
owner,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,10 +15,13 @@ bincode = "1.3.3"
|
|||
bs58 = "0.4.0"
|
||||
Inflector = "0.11.4"
|
||||
lazy_static = "1.4.0"
|
||||
log = "0.4.14"
|
||||
serde = "1.0.130"
|
||||
serde_derive = "1.0.103"
|
||||
serde_json = "1.0.68"
|
||||
solana-account-decoder = { path = "../account-decoder", version = "=1.9.0" }
|
||||
solana-measure = { path = "../measure", version = "=1.9.0" }
|
||||
solana-metrics = { path = "../metrics", version = "=1.9.0" }
|
||||
solana-runtime = { path = "../runtime", version = "=1.9.0" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.9.0" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "=1.9.0" }
|
||||
|
|
|
@ -15,25 +15,26 @@ pub mod parse_token;
|
|||
pub mod parse_vote;
|
||||
pub mod token_balances;
|
||||
|
||||
pub use crate::extract_memos::extract_and_fmt_memos;
|
||||
use crate::{
|
||||
parse_accounts::{parse_accounts, ParsedAccount},
|
||||
parse_instruction::{parse, ParsedInstruction},
|
||||
pub use {crate::extract_memos::extract_and_fmt_memos, solana_runtime::bank::RewardType};
|
||||
use {
|
||||
crate::{
|
||||
parse_accounts::{parse_accounts, ParsedAccount},
|
||||
parse_instruction::{parse, ParsedInstruction},
|
||||
},
|
||||
solana_account_decoder::parse_token::UiTokenAmount,
|
||||
solana_sdk::{
|
||||
clock::{Slot, UnixTimestamp},
|
||||
commitment_config::CommitmentConfig,
|
||||
deserialize_utils::default_on_eof,
|
||||
instruction::CompiledInstruction,
|
||||
message::{Message, MessageHeader},
|
||||
pubkey::Pubkey,
|
||||
sanitize::Sanitize,
|
||||
signature::Signature,
|
||||
transaction::{Result, Transaction, TransactionError},
|
||||
},
|
||||
std::fmt,
|
||||
};
|
||||
use solana_account_decoder::parse_token::UiTokenAmount;
|
||||
pub use solana_runtime::bank::RewardType;
|
||||
use solana_sdk::{
|
||||
clock::{Slot, UnixTimestamp},
|
||||
commitment_config::CommitmentConfig,
|
||||
deserialize_utils::default_on_eof,
|
||||
instruction::CompiledInstruction,
|
||||
message::{Message, MessageHeader},
|
||||
pubkey::Pubkey,
|
||||
sanitize::Sanitize,
|
||||
signature::Signature,
|
||||
transaction::{Result, Transaction, TransactionError},
|
||||
};
|
||||
use std::fmt;
|
||||
/// A duplicate representation of an Instruction for pretty JSON serialization
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase", untagged)]
|
||||
|
@ -126,6 +127,7 @@ pub struct TransactionTokenBalance {
|
|||
pub account_index: u8,
|
||||
pub mint: String,
|
||||
pub ui_token_amount: UiTokenAmount,
|
||||
pub owner: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
|
@ -134,6 +136,8 @@ pub struct UiTransactionTokenBalance {
|
|||
pub account_index: u8,
|
||||
pub mint: String,
|
||||
pub ui_token_amount: UiTokenAmount,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub owner: Option<String>,
|
||||
}
|
||||
|
||||
impl From<TransactionTokenBalance> for UiTransactionTokenBalance {
|
||||
|
@ -142,6 +146,11 @@ impl From<TransactionTokenBalance> for UiTransactionTokenBalance {
|
|||
account_index: token_balance.account_index,
|
||||
mint: token_balance.mint,
|
||||
ui_token_amount: token_balance.ui_token_amount,
|
||||
owner: if !token_balance.owner.is_empty() {
|
||||
Some(token_balance.owner)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,8 +22,7 @@ pub fn parse_accounts(message: &Message) -> Vec<ParsedAccount> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use solana_sdk::message::MessageHeader;
|
||||
use {super::*, solana_sdk::message::MessageHeader};
|
||||
|
||||
#[test]
|
||||
fn test_parse_accounts() {
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
use crate::parse_instruction::{
|
||||
check_num_accounts, ParsableProgram, ParseInstructionError, ParsedInstructionEnum,
|
||||
use {
|
||||
crate::parse_instruction::{
|
||||
check_num_accounts, ParsableProgram, ParseInstructionError, ParsedInstructionEnum,
|
||||
},
|
||||
serde_json::json,
|
||||
solana_sdk::{instruction::CompiledInstruction, pubkey::Pubkey},
|
||||
};
|
||||
use serde_json::json;
|
||||
use solana_sdk::{instruction::CompiledInstruction, pubkey::Pubkey};
|
||||
|
||||
// A helper function to convert spl_associated_token_account_v1_0::id() as spl_sdk::pubkey::Pubkey
|
||||
// to solana_sdk::pubkey::Pubkey
|
||||
|
@ -47,12 +49,14 @@ fn check_num_associated_token_accounts(
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use spl_associated_token_account_v1_0::{
|
||||
create_associated_token_account,
|
||||
solana_program::{
|
||||
instruction::CompiledInstruction as SplAssociatedTokenCompiledInstruction,
|
||||
message::Message, pubkey::Pubkey as SplAssociatedTokenPubkey,
|
||||
use {
|
||||
super::*,
|
||||
spl_associated_token_account_v1_0::{
|
||||
create_associated_token_account,
|
||||
solana_program::{
|
||||
instruction::CompiledInstruction as SplAssociatedTokenCompiledInstruction,
|
||||
message::Message, pubkey::Pubkey as SplAssociatedTokenPubkey,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
use crate::parse_instruction::{
|
||||
check_num_accounts, ParsableProgram, ParseInstructionError, ParsedInstructionEnum,
|
||||
};
|
||||
use bincode::deserialize;
|
||||
use serde_json::json;
|
||||
use solana_sdk::{
|
||||
instruction::CompiledInstruction, loader_instruction::LoaderInstruction,
|
||||
loader_upgradeable_instruction::UpgradeableLoaderInstruction, pubkey::Pubkey,
|
||||
use {
|
||||
crate::parse_instruction::{
|
||||
check_num_accounts, ParsableProgram, ParseInstructionError, ParsedInstructionEnum,
|
||||
},
|
||||
bincode::deserialize,
|
||||
serde_json::json,
|
||||
solana_sdk::{
|
||||
instruction::CompiledInstruction, loader_instruction::LoaderInstruction,
|
||||
loader_upgradeable_instruction::UpgradeableLoaderInstruction, pubkey::Pubkey,
|
||||
},
|
||||
};
|
||||
|
||||
pub fn parse_bpf_loader(
|
||||
|
@ -154,9 +156,11 @@ fn check_num_bpf_upgradeable_loader_accounts(
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use serde_json::Value;
|
||||
use solana_sdk::{message::Message, pubkey};
|
||||
use {
|
||||
super::*,
|
||||
serde_json::Value,
|
||||
solana_sdk::{message::Message, pubkey},
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn test_parse_bpf_loader_instructions() {
|
||||
|
|
|
@ -1,21 +1,23 @@
|
|||
use crate::{
|
||||
extract_memos::{spl_memo_id_v1, spl_memo_id_v3},
|
||||
parse_associated_token::{parse_associated_token, spl_associated_token_id_v1_0},
|
||||
parse_bpf_loader::{parse_bpf_loader, parse_bpf_upgradeable_loader},
|
||||
parse_stake::parse_stake,
|
||||
parse_system::parse_system,
|
||||
parse_token::parse_token,
|
||||
parse_vote::parse_vote,
|
||||
use {
|
||||
crate::{
|
||||
extract_memos::{spl_memo_id_v1, spl_memo_id_v3},
|
||||
parse_associated_token::{parse_associated_token, spl_associated_token_id_v1_0},
|
||||
parse_bpf_loader::{parse_bpf_loader, parse_bpf_upgradeable_loader},
|
||||
parse_stake::parse_stake,
|
||||
parse_system::parse_system,
|
||||
parse_token::parse_token,
|
||||
parse_vote::parse_vote,
|
||||
},
|
||||
inflector::Inflector,
|
||||
serde_json::Value,
|
||||
solana_account_decoder::parse_token::spl_token_id_v2_0,
|
||||
solana_sdk::{instruction::CompiledInstruction, pubkey::Pubkey, stake, system_program},
|
||||
std::{
|
||||
collections::HashMap,
|
||||
str::{from_utf8, Utf8Error},
|
||||
},
|
||||
thiserror::Error,
|
||||
};
|
||||
use inflector::Inflector;
|
||||
use serde_json::Value;
|
||||
use solana_account_decoder::parse_token::spl_token_id_v2_0;
|
||||
use solana_sdk::{instruction::CompiledInstruction, pubkey::Pubkey, stake, system_program};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
str::{from_utf8, Utf8Error},
|
||||
};
|
||||
use thiserror::Error;
|
||||
|
||||
lazy_static! {
|
||||
static ref ASSOCIATED_TOKEN_PROGRAM_ID: Pubkey = spl_associated_token_id_v1_0();
|
||||
|
@ -150,8 +152,7 @@ pub(crate) fn check_num_accounts(
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use serde_json::json;
|
||||
use {super::*, serde_json::json};
|
||||
|
||||
#[test]
|
||||
fn test_parse() {
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
use crate::parse_instruction::{
|
||||
check_num_accounts, ParsableProgram, ParseInstructionError, ParsedInstructionEnum,
|
||||
};
|
||||
use bincode::deserialize;
|
||||
use serde_json::{json, Map};
|
||||
use solana_sdk::{
|
||||
instruction::CompiledInstruction, pubkey::Pubkey, stake::instruction::StakeInstruction,
|
||||
use {
|
||||
crate::parse_instruction::{
|
||||
check_num_accounts, ParsableProgram, ParseInstructionError, ParsedInstructionEnum,
|
||||
},
|
||||
bincode::deserialize,
|
||||
serde_json::{json, Map},
|
||||
solana_sdk::{
|
||||
instruction::CompiledInstruction, pubkey::Pubkey, stake::instruction::StakeInstruction,
|
||||
},
|
||||
};
|
||||
|
||||
pub fn parse_stake(
|
||||
|
@ -275,13 +277,15 @@ fn check_num_stake_accounts(accounts: &[u8], num: usize) -> Result<(), ParseInst
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use solana_sdk::{
|
||||
message::Message,
|
||||
pubkey::Pubkey,
|
||||
stake::{
|
||||
instruction::{self, LockupArgs},
|
||||
state::{Authorized, Lockup, StakeAuthorize},
|
||||
use {
|
||||
super::*,
|
||||
solana_sdk::{
|
||||
message::Message,
|
||||
pubkey::Pubkey,
|
||||
stake::{
|
||||
instruction::{self, LockupArgs},
|
||||
state::{Authorized, Lockup, StakeAuthorize},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
use crate::parse_instruction::{
|
||||
check_num_accounts, ParsableProgram, ParseInstructionError, ParsedInstructionEnum,
|
||||
};
|
||||
use bincode::deserialize;
|
||||
use serde_json::json;
|
||||
use solana_sdk::{
|
||||
instruction::CompiledInstruction, pubkey::Pubkey, system_instruction::SystemInstruction,
|
||||
use {
|
||||
crate::parse_instruction::{
|
||||
check_num_accounts, ParsableProgram, ParseInstructionError, ParsedInstructionEnum,
|
||||
},
|
||||
bincode::deserialize,
|
||||
serde_json::json,
|
||||
solana_sdk::{
|
||||
instruction::CompiledInstruction, pubkey::Pubkey, system_instruction::SystemInstruction,
|
||||
},
|
||||
};
|
||||
|
||||
pub fn parse_system(
|
||||
|
@ -197,8 +199,10 @@ fn check_num_system_accounts(accounts: &[u8], num: usize) -> Result<(), ParseIns
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use solana_sdk::{message::Message, pubkey::Pubkey, system_instruction};
|
||||
use {
|
||||
super::*,
|
||||
solana_sdk::{message::Message, pubkey::Pubkey, system_instruction},
|
||||
};
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::same_item_push)]
|
||||
|
|
|
@ -1,15 +1,19 @@
|
|||
use crate::parse_instruction::{
|
||||
check_num_accounts, ParsableProgram, ParseInstructionError, ParsedInstructionEnum,
|
||||
};
|
||||
use serde_json::{json, Map, Value};
|
||||
use solana_account_decoder::parse_token::{pubkey_from_spl_token_v2_0, token_amount_to_ui_amount};
|
||||
use solana_sdk::{
|
||||
instruction::{AccountMeta, CompiledInstruction, Instruction},
|
||||
pubkey::Pubkey,
|
||||
};
|
||||
use spl_token_v2_0::{
|
||||
instruction::{AuthorityType, TokenInstruction},
|
||||
solana_program::{instruction::Instruction as SplTokenInstruction, program_option::COption},
|
||||
use {
|
||||
crate::parse_instruction::{
|
||||
check_num_accounts, ParsableProgram, ParseInstructionError, ParsedInstructionEnum,
|
||||
},
|
||||
serde_json::{json, Map, Value},
|
||||
solana_account_decoder::parse_token::{pubkey_from_spl_token_v2_0, token_amount_to_ui_amount},
|
||||
solana_sdk::{
|
||||
instruction::{AccountMeta, CompiledInstruction, Instruction},
|
||||
pubkey::Pubkey,
|
||||
},
|
||||
spl_token_v2_0::{
|
||||
instruction::{AuthorityType, TokenInstruction},
|
||||
solana_program::{
|
||||
instruction::Instruction as SplTokenInstruction, program_option::COption,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
pub fn parse_token(
|
||||
|
@ -452,16 +456,18 @@ pub fn spl_token_v2_0_instruction(instruction: SplTokenInstruction) -> Instructi
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use solana_sdk::instruction::CompiledInstruction;
|
||||
use spl_token_v2_0::{
|
||||
instruction::*,
|
||||
solana_program::{
|
||||
instruction::CompiledInstruction as SplTokenCompiledInstruction, message::Message,
|
||||
pubkey::Pubkey as SplTokenPubkey,
|
||||
use {
|
||||
super::*,
|
||||
solana_sdk::instruction::CompiledInstruction,
|
||||
spl_token_v2_0::{
|
||||
instruction::*,
|
||||
solana_program::{
|
||||
instruction::CompiledInstruction as SplTokenCompiledInstruction, message::Message,
|
||||
pubkey::Pubkey as SplTokenPubkey,
|
||||
},
|
||||
},
|
||||
std::str::FromStr,
|
||||
};
|
||||
use std::str::FromStr;
|
||||
|
||||
fn convert_pubkey(pubkey: Pubkey) -> SplTokenPubkey {
|
||||
SplTokenPubkey::from_str(&pubkey.to_string()).unwrap()
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
use crate::parse_instruction::{
|
||||
check_num_accounts, ParsableProgram, ParseInstructionError, ParsedInstructionEnum,
|
||||
use {
|
||||
crate::parse_instruction::{
|
||||
check_num_accounts, ParsableProgram, ParseInstructionError, ParsedInstructionEnum,
|
||||
},
|
||||
bincode::deserialize,
|
||||
serde_json::json,
|
||||
solana_sdk::{instruction::CompiledInstruction, pubkey::Pubkey},
|
||||
solana_vote_program::vote_instruction::VoteInstruction,
|
||||
};
|
||||
use bincode::deserialize;
|
||||
use serde_json::json;
|
||||
use solana_sdk::{instruction::CompiledInstruction, pubkey::Pubkey};
|
||||
use solana_vote_program::vote_instruction::VoteInstruction;
|
||||
|
||||
pub fn parse_vote(
|
||||
instruction: &CompiledInstruction,
|
||||
|
@ -143,11 +145,13 @@ fn check_num_vote_accounts(accounts: &[u8], num: usize) -> Result<(), ParseInstr
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use solana_sdk::{hash::Hash, message::Message, pubkey::Pubkey};
|
||||
use solana_vote_program::{
|
||||
vote_instruction,
|
||||
vote_state::{Vote, VoteAuthorize, VoteInit},
|
||||
use {
|
||||
super::*,
|
||||
solana_sdk::{hash::Hash, message::Message, pubkey::Pubkey},
|
||||
solana_vote_program::{
|
||||
vote_instruction,
|
||||
vote_state::{Vote, VoteAuthorize, VoteInit},
|
||||
},
|
||||
};
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -1,14 +1,19 @@
|
|||
use crate::TransactionTokenBalance;
|
||||
use solana_account_decoder::parse_token::{
|
||||
spl_token_id_v2_0, spl_token_v2_0_native_mint, token_amount_to_ui_amount, UiTokenAmount,
|
||||
use {
|
||||
crate::TransactionTokenBalance,
|
||||
solana_account_decoder::parse_token::{
|
||||
pubkey_from_spl_token_v2_0, spl_token_id_v2_0, spl_token_v2_0_native_mint,
|
||||
token_amount_to_ui_amount, UiTokenAmount,
|
||||
},
|
||||
solana_measure::measure::Measure,
|
||||
solana_metrics::datapoint_debug,
|
||||
solana_runtime::{bank::Bank, transaction_batch::TransactionBatch},
|
||||
solana_sdk::{account::ReadableAccount, pubkey::Pubkey},
|
||||
spl_token_v2_0::{
|
||||
solana_program::program_pack::Pack,
|
||||
state::{Account as TokenAccount, Mint},
|
||||
},
|
||||
std::collections::HashMap,
|
||||
};
|
||||
use solana_runtime::{bank::Bank, transaction_batch::TransactionBatch};
|
||||
use solana_sdk::{account::ReadableAccount, pubkey::Pubkey};
|
||||
use spl_token_v2_0::{
|
||||
solana_program::program_pack::Pack,
|
||||
state::{Account as TokenAccount, Mint},
|
||||
};
|
||||
use std::{collections::HashMap, str::FromStr};
|
||||
|
||||
pub type TransactionTokenBalances = Vec<Vec<TransactionTokenBalance>>;
|
||||
|
||||
|
@ -54,6 +59,7 @@ pub fn collect_token_balances(
|
|||
mint_decimals: &mut HashMap<Pubkey, u8>,
|
||||
) -> TransactionTokenBalances {
|
||||
let mut balances: TransactionTokenBalances = vec![];
|
||||
let mut collect_time = Measure::start("collect_token_balances");
|
||||
|
||||
for transaction in batch.sanitized_transactions() {
|
||||
let has_token_program = transaction
|
||||
|
@ -68,41 +74,56 @@ pub fn collect_token_balances(
|
|||
continue;
|
||||
}
|
||||
|
||||
if let Some((mint, ui_token_amount)) =
|
||||
collect_token_balance_from_account(bank, account_id, mint_decimals)
|
||||
if let Some(TokenBalanceData {
|
||||
mint,
|
||||
ui_token_amount,
|
||||
owner,
|
||||
}) = collect_token_balance_from_account(bank, account_id, mint_decimals)
|
||||
{
|
||||
transaction_balances.push(TransactionTokenBalance {
|
||||
account_index: index as u8,
|
||||
mint,
|
||||
ui_token_amount,
|
||||
owner,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
balances.push(transaction_balances);
|
||||
}
|
||||
collect_time.stop();
|
||||
datapoint_debug!(
|
||||
"collect_token_balances",
|
||||
("collect_time_us", collect_time.as_us(), i64),
|
||||
);
|
||||
balances
|
||||
}
|
||||
|
||||
pub fn collect_token_balance_from_account(
|
||||
struct TokenBalanceData {
|
||||
mint: String,
|
||||
owner: String,
|
||||
ui_token_amount: UiTokenAmount,
|
||||
}
|
||||
|
||||
fn collect_token_balance_from_account(
|
||||
bank: &Bank,
|
||||
account_id: &Pubkey,
|
||||
mint_decimals: &mut HashMap<Pubkey, u8>,
|
||||
) -> Option<(String, UiTokenAmount)> {
|
||||
) -> Option<TokenBalanceData> {
|
||||
let account = bank.get_account(account_id)?;
|
||||
|
||||
let token_account = TokenAccount::unpack(account.data()).ok()?;
|
||||
let mint_string = &token_account.mint.to_string();
|
||||
let mint = &Pubkey::from_str(mint_string).unwrap_or_default();
|
||||
let mint = pubkey_from_spl_token_v2_0(&token_account.mint);
|
||||
|
||||
let decimals = mint_decimals.get(mint).cloned().or_else(|| {
|
||||
let decimals = get_mint_decimals(bank, mint)?;
|
||||
mint_decimals.insert(*mint, decimals);
|
||||
let decimals = mint_decimals.get(&mint).cloned().or_else(|| {
|
||||
let decimals = get_mint_decimals(bank, &mint)?;
|
||||
mint_decimals.insert(mint, decimals);
|
||||
Some(decimals)
|
||||
})?;
|
||||
|
||||
Some((
|
||||
mint_string.to_string(),
|
||||
token_amount_to_ui_amount(token_account.amount, decimals),
|
||||
))
|
||||
Some(TokenBalanceData {
|
||||
mint: token_account.mint.to_string(),
|
||||
owner: token_account.owner.to_string(),
|
||||
ui_token_amount: token_amount_to_ui_amount(token_account.amount, decimals),
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue