Prepare RPC subsystem for multiple SPL Token program ids
This commit is contained in:
@ -5,7 +5,7 @@ use {
|
|||||||
parse_nonce::parse_nonce,
|
parse_nonce::parse_nonce,
|
||||||
parse_stake::parse_stake,
|
parse_stake::parse_stake,
|
||||||
parse_sysvar::parse_sysvar,
|
parse_sysvar::parse_sysvar,
|
||||||
parse_token::{parse_token, spl_token_id},
|
parse_token::{parse_token, spl_token_ids},
|
||||||
parse_vote::parse_vote,
|
parse_vote::parse_vote,
|
||||||
},
|
},
|
||||||
inflector::Inflector,
|
inflector::Inflector,
|
||||||
@ -21,7 +21,6 @@ lazy_static! {
|
|||||||
static ref STAKE_PROGRAM_ID: Pubkey = stake::program::id();
|
static ref STAKE_PROGRAM_ID: Pubkey = stake::program::id();
|
||||||
static ref SYSTEM_PROGRAM_ID: Pubkey = system_program::id();
|
static ref SYSTEM_PROGRAM_ID: Pubkey = system_program::id();
|
||||||
static ref SYSVAR_PROGRAM_ID: Pubkey = sysvar::id();
|
static ref SYSVAR_PROGRAM_ID: Pubkey = sysvar::id();
|
||||||
static ref TOKEN_PROGRAM_ID: Pubkey = spl_token_id();
|
|
||||||
static ref VOTE_PROGRAM_ID: Pubkey = solana_vote_program::id();
|
static ref VOTE_PROGRAM_ID: Pubkey = solana_vote_program::id();
|
||||||
pub static ref PARSABLE_PROGRAM_IDS: HashMap<Pubkey, ParsableAccount> = {
|
pub static ref PARSABLE_PROGRAM_IDS: HashMap<Pubkey, ParsableAccount> = {
|
||||||
let mut m = HashMap::new();
|
let mut m = HashMap::new();
|
||||||
@ -31,7 +30,9 @@ lazy_static! {
|
|||||||
);
|
);
|
||||||
m.insert(*CONFIG_PROGRAM_ID, ParsableAccount::Config);
|
m.insert(*CONFIG_PROGRAM_ID, ParsableAccount::Config);
|
||||||
m.insert(*SYSTEM_PROGRAM_ID, ParsableAccount::Nonce);
|
m.insert(*SYSTEM_PROGRAM_ID, ParsableAccount::Nonce);
|
||||||
m.insert(*TOKEN_PROGRAM_ID, ParsableAccount::SplToken);
|
for spl_token_id in spl_token_ids() {
|
||||||
|
m.insert(spl_token_id, ParsableAccount::SplToken);
|
||||||
|
}
|
||||||
m.insert(*STAKE_PROGRAM_ID, ParsableAccount::Stake);
|
m.insert(*STAKE_PROGRAM_ID, ParsableAccount::Stake);
|
||||||
m.insert(*SYSVAR_PROGRAM_ID, ParsableAccount::Sysvar);
|
m.insert(*SYSVAR_PROGRAM_ID, ParsableAccount::Sysvar);
|
||||||
m.insert(*VOTE_PROGRAM_ID, ParsableAccount::Vote);
|
m.insert(*VOTE_PROGRAM_ID, ParsableAccount::Vote);
|
||||||
|
@ -15,16 +15,31 @@ use {
|
|||||||
|
|
||||||
// A helper function to convert spl_token::id() as spl_sdk::pubkey::Pubkey to
|
// A helper function to convert spl_token::id() as spl_sdk::pubkey::Pubkey to
|
||||||
// solana_sdk::pubkey::Pubkey
|
// solana_sdk::pubkey::Pubkey
|
||||||
pub fn spl_token_id() -> Pubkey {
|
fn spl_token_id() -> Pubkey {
|
||||||
Pubkey::new_from_array(spl_token::id().to_bytes())
|
Pubkey::new_from_array(spl_token::id().to_bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns all known SPL Token program ids
|
||||||
|
pub fn spl_token_ids() -> Vec<Pubkey> {
|
||||||
|
vec![spl_token_id()]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the provided program id as a known SPL Token program id
|
||||||
|
pub fn is_known_spl_token_id(program_id: &Pubkey) -> bool {
|
||||||
|
*program_id == spl_token_id()
|
||||||
|
}
|
||||||
|
|
||||||
// A helper function to convert spl_token::native_mint::id() as spl_sdk::pubkey::Pubkey to
|
// A helper function to convert spl_token::native_mint::id() as spl_sdk::pubkey::Pubkey to
|
||||||
// solana_sdk::pubkey::Pubkey
|
// solana_sdk::pubkey::Pubkey
|
||||||
pub fn spl_token_native_mint() -> Pubkey {
|
pub fn spl_token_native_mint() -> Pubkey {
|
||||||
Pubkey::new_from_array(spl_token::native_mint::id().to_bytes())
|
Pubkey::new_from_array(spl_token::native_mint::id().to_bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The program id of the `spl_token_native_mint` account
|
||||||
|
pub fn spl_token_native_mint_program_id() -> Pubkey {
|
||||||
|
spl_token_id()
|
||||||
|
}
|
||||||
|
|
||||||
// A helper function to convert a solana_sdk::pubkey::Pubkey to spl_sdk::pubkey::Pubkey
|
// A helper function to convert a solana_sdk::pubkey::Pubkey to spl_sdk::pubkey::Pubkey
|
||||||
pub fn spl_token_pubkey(pubkey: &Pubkey) -> SplTokenPubkey {
|
pub fn spl_token_pubkey(pubkey: &Pubkey) -> SplTokenPubkey {
|
||||||
SplTokenPubkey::new_from_array(pubkey.to_bytes())
|
SplTokenPubkey::new_from_array(pubkey.to_bytes())
|
||||||
|
@ -2,7 +2,9 @@ use {
|
|||||||
jsonrpc_core::{Error, Result},
|
jsonrpc_core::{Error, Result},
|
||||||
solana_account_decoder::{
|
solana_account_decoder::{
|
||||||
parse_account_data::AccountAdditionalData,
|
parse_account_data::AccountAdditionalData,
|
||||||
parse_token::{get_token_account_mint, spl_token_id, spl_token_native_mint},
|
parse_token::{
|
||||||
|
get_token_account_mint, spl_token_native_mint, spl_token_native_mint_program_id,
|
||||||
|
},
|
||||||
UiAccount, UiAccountData, UiAccountEncoding,
|
UiAccount, UiAccountData, UiAccountEncoding,
|
||||||
},
|
},
|
||||||
solana_client::rpc_response::RpcKeyedAccount,
|
solana_client::rpc_response::RpcKeyedAccount,
|
||||||
@ -75,7 +77,10 @@ where
|
|||||||
/// program_id) and decimals
|
/// program_id) and decimals
|
||||||
pub fn get_mint_owner_and_decimals(bank: &Arc<Bank>, mint: &Pubkey) -> Result<(Pubkey, u8)> {
|
pub fn get_mint_owner_and_decimals(bank: &Arc<Bank>, mint: &Pubkey) -> Result<(Pubkey, u8)> {
|
||||||
if mint == &spl_token_native_mint() {
|
if mint == &spl_token_native_mint() {
|
||||||
Ok((spl_token_id(), spl_token::native_mint::DECIMALS))
|
Ok((
|
||||||
|
spl_token_native_mint_program_id(),
|
||||||
|
spl_token::native_mint::DECIMALS,
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
let mint_account = bank.get_account(mint).ok_or_else(|| {
|
let mint_account = bank.get_account(mint).ok_or_else(|| {
|
||||||
Error::invalid_params("Invalid param: could not find mint".to_string())
|
Error::invalid_params("Invalid param: could not find mint".to_string())
|
||||||
|
@ -11,7 +11,7 @@ use {
|
|||||||
jsonrpc_derive::rpc,
|
jsonrpc_derive::rpc,
|
||||||
serde::{Deserialize, Serialize},
|
serde::{Deserialize, Serialize},
|
||||||
solana_account_decoder::{
|
solana_account_decoder::{
|
||||||
parse_token::{spl_token_id, token_amount_to_ui_amount, UiTokenAmount},
|
parse_token::{is_known_spl_token_id, token_amount_to_ui_amount, UiTokenAmount},
|
||||||
UiAccount, UiAccountEncoding, UiDataSliceConfig, MAX_BASE58_BYTES,
|
UiAccount, UiAccountEncoding, UiDataSliceConfig, MAX_BASE58_BYTES,
|
||||||
},
|
},
|
||||||
solana_client::{
|
solana_client::{
|
||||||
@ -405,14 +405,15 @@ impl JsonRpcRequestProcessor {
|
|||||||
optimize_filters(&mut filters);
|
optimize_filters(&mut filters);
|
||||||
let keyed_accounts = {
|
let keyed_accounts = {
|
||||||
if let Some(owner) = get_spl_token_owner_filter(program_id, &filters) {
|
if let Some(owner) = get_spl_token_owner_filter(program_id, &filters) {
|
||||||
self.get_filtered_spl_token_accounts_by_owner(&bank, &owner, filters)?
|
self.get_filtered_spl_token_accounts_by_owner(&bank, program_id, &owner, filters)?
|
||||||
} else if let Some(mint) = get_spl_token_mint_filter(program_id, &filters) {
|
} else if let Some(mint) = get_spl_token_mint_filter(program_id, &filters) {
|
||||||
self.get_filtered_spl_token_accounts_by_mint(&bank, &mint, filters)?
|
self.get_filtered_spl_token_accounts_by_mint(&bank, program_id, &mint, filters)?
|
||||||
} else {
|
} else {
|
||||||
self.get_filtered_program_accounts(&bank, program_id, filters)?
|
self.get_filtered_program_accounts(&bank, program_id, filters)?
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let accounts = if program_id == &spl_token_id() && encoding == UiAccountEncoding::JsonParsed
|
let accounts = if is_known_spl_token_id(program_id)
|
||||||
|
&& encoding == UiAccountEncoding::JsonParsed
|
||||||
{
|
{
|
||||||
get_parsed_token_accounts(bank.clone(), keyed_accounts.into_iter()).collect()
|
get_parsed_token_accounts(bank.clone(), keyed_accounts.into_iter()).collect()
|
||||||
} else {
|
} else {
|
||||||
@ -1709,7 +1710,7 @@ impl JsonRpcRequestProcessor {
|
|||||||
Error::invalid_params("Invalid param: could not find account".to_string())
|
Error::invalid_params("Invalid param: could not find account".to_string())
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if account.owner() != &spl_token_id() {
|
if !is_known_spl_token_id(account.owner()) {
|
||||||
return Err(Error::invalid_params(
|
return Err(Error::invalid_params(
|
||||||
"Invalid param: not a Token account".to_string(),
|
"Invalid param: not a Token account".to_string(),
|
||||||
));
|
));
|
||||||
@ -1732,7 +1733,7 @@ impl JsonRpcRequestProcessor {
|
|||||||
let mint_account = bank.get_account(mint).ok_or_else(|| {
|
let mint_account = bank.get_account(mint).ok_or_else(|| {
|
||||||
Error::invalid_params("Invalid param: could not find account".to_string())
|
Error::invalid_params("Invalid param: could not find account".to_string())
|
||||||
})?;
|
})?;
|
||||||
if mint_account.owner() != &spl_token_id() {
|
if !is_known_spl_token_id(mint_account.owner()) {
|
||||||
return Err(Error::invalid_params(
|
return Err(Error::invalid_params(
|
||||||
"Invalid param: not a Token mint".to_string(),
|
"Invalid param: not a Token mint".to_string(),
|
||||||
));
|
));
|
||||||
@ -1752,13 +1753,13 @@ impl JsonRpcRequestProcessor {
|
|||||||
) -> Result<RpcResponse<Vec<RpcTokenAccountBalance>>> {
|
) -> Result<RpcResponse<Vec<RpcTokenAccountBalance>>> {
|
||||||
let bank = self.bank(commitment);
|
let bank = self.bank(commitment);
|
||||||
let (mint_owner, decimals) = get_mint_owner_and_decimals(&bank, mint)?;
|
let (mint_owner, decimals) = get_mint_owner_and_decimals(&bank, mint)?;
|
||||||
if mint_owner != spl_token_id() {
|
if !is_known_spl_token_id(&mint_owner) {
|
||||||
return Err(Error::invalid_params(
|
return Err(Error::invalid_params(
|
||||||
"Invalid param: not a Token mint".to_string(),
|
"Invalid param: not a Token mint".to_string(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
let mut token_balances: Vec<RpcTokenAccountBalance> = self
|
let mut token_balances: Vec<RpcTokenAccountBalance> = self
|
||||||
.get_filtered_spl_token_accounts_by_mint(&bank, mint, vec![])?
|
.get_filtered_spl_token_accounts_by_mint(&bank, &mint_owner, mint, vec![])?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(address, account)| {
|
.map(|(address, account)| {
|
||||||
let amount = TokenAccount::unpack(account.data())
|
let amount = TokenAccount::unpack(account.data())
|
||||||
@ -1794,7 +1795,7 @@ impl JsonRpcRequestProcessor {
|
|||||||
let encoding = config.encoding.unwrap_or(UiAccountEncoding::Binary);
|
let encoding = config.encoding.unwrap_or(UiAccountEncoding::Binary);
|
||||||
let data_slice_config = config.data_slice;
|
let data_slice_config = config.data_slice;
|
||||||
check_slice_and_encoding(&encoding, data_slice_config.is_some())?;
|
check_slice_and_encoding(&encoding, data_slice_config.is_some())?;
|
||||||
let (_, mint) = get_token_program_id_and_mint(&bank, token_account_filter)?;
|
let (token_program_id, mint) = get_token_program_id_and_mint(&bank, token_account_filter)?;
|
||||||
|
|
||||||
let mut filters = vec![];
|
let mut filters = vec![];
|
||||||
if let Some(mint) = mint {
|
if let Some(mint) = mint {
|
||||||
@ -1806,8 +1807,12 @@ impl JsonRpcRequestProcessor {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
let keyed_accounts =
|
let keyed_accounts = self.get_filtered_spl_token_accounts_by_owner(
|
||||||
self.get_filtered_spl_token_accounts_by_owner(&bank, owner, filters)?;
|
&bank,
|
||||||
|
&token_program_id,
|
||||||
|
owner,
|
||||||
|
filters,
|
||||||
|
)?;
|
||||||
let accounts = if encoding == UiAccountEncoding::JsonParsed {
|
let accounts = if encoding == UiAccountEncoding::JsonParsed {
|
||||||
get_parsed_token_accounts(bank.clone(), keyed_accounts.into_iter()).collect()
|
get_parsed_token_accounts(bank.clone(), keyed_accounts.into_iter()).collect()
|
||||||
} else {
|
} else {
|
||||||
@ -1853,7 +1858,7 @@ impl JsonRpcRequestProcessor {
|
|||||||
];
|
];
|
||||||
// Optional filter on Mint address, uses mint account index for scan
|
// Optional filter on Mint address, uses mint account index for scan
|
||||||
let keyed_accounts = if let Some(mint) = mint {
|
let keyed_accounts = if let Some(mint) = mint {
|
||||||
self.get_filtered_spl_token_accounts_by_mint(&bank, &mint, filters)?
|
self.get_filtered_spl_token_accounts_by_mint(&bank, &token_program_id, &mint, filters)?
|
||||||
} else {
|
} else {
|
||||||
// Filter on Token Account state
|
// Filter on Token Account state
|
||||||
filters.push(RpcFilterType::DataSize(
|
filters.push(RpcFilterType::DataSize(
|
||||||
@ -1932,6 +1937,7 @@ impl JsonRpcRequestProcessor {
|
|||||||
fn get_filtered_spl_token_accounts_by_owner(
|
fn get_filtered_spl_token_accounts_by_owner(
|
||||||
&self,
|
&self,
|
||||||
bank: &Arc<Bank>,
|
bank: &Arc<Bank>,
|
||||||
|
program_id: &Pubkey,
|
||||||
owner_key: &Pubkey,
|
owner_key: &Pubkey,
|
||||||
mut filters: Vec<RpcFilterType>,
|
mut filters: Vec<RpcFilterType>,
|
||||||
) -> RpcCustomResult<Vec<(Pubkey, AccountSharedData)>> {
|
) -> RpcCustomResult<Vec<(Pubkey, AccountSharedData)>> {
|
||||||
@ -1965,7 +1971,7 @@ impl JsonRpcRequestProcessor {
|
|||||||
.get_filtered_indexed_accounts(
|
.get_filtered_indexed_accounts(
|
||||||
&IndexKey::SplTokenOwner(*owner_key),
|
&IndexKey::SplTokenOwner(*owner_key),
|
||||||
|account| {
|
|account| {
|
||||||
account.owner() == &spl_token_id()
|
account.owner() == program_id
|
||||||
&& filters.iter().all(|filter_type| match filter_type {
|
&& filters.iter().all(|filter_type| match filter_type {
|
||||||
RpcFilterType::DataSize(size) => {
|
RpcFilterType::DataSize(size) => {
|
||||||
account.data().len() as u64 == *size
|
account.data().len() as u64 == *size
|
||||||
@ -1982,7 +1988,7 @@ impl JsonRpcRequestProcessor {
|
|||||||
message: e.to_string(),
|
message: e.to_string(),
|
||||||
})?)
|
})?)
|
||||||
} else {
|
} else {
|
||||||
self.get_filtered_program_accounts(bank, &spl_token_id(), filters)
|
self.get_filtered_program_accounts(bank, program_id, filters)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1990,6 +1996,7 @@ impl JsonRpcRequestProcessor {
|
|||||||
fn get_filtered_spl_token_accounts_by_mint(
|
fn get_filtered_spl_token_accounts_by_mint(
|
||||||
&self,
|
&self,
|
||||||
bank: &Arc<Bank>,
|
bank: &Arc<Bank>,
|
||||||
|
program_id: &Pubkey,
|
||||||
mint_key: &Pubkey,
|
mint_key: &Pubkey,
|
||||||
mut filters: Vec<RpcFilterType>,
|
mut filters: Vec<RpcFilterType>,
|
||||||
) -> RpcCustomResult<Vec<(Pubkey, AccountSharedData)>> {
|
) -> RpcCustomResult<Vec<(Pubkey, AccountSharedData)>> {
|
||||||
@ -2022,7 +2029,7 @@ impl JsonRpcRequestProcessor {
|
|||||||
.get_filtered_indexed_accounts(
|
.get_filtered_indexed_accounts(
|
||||||
&IndexKey::SplTokenMint(*mint_key),
|
&IndexKey::SplTokenMint(*mint_key),
|
||||||
|account| {
|
|account| {
|
||||||
account.owner() == &spl_token_id()
|
account.owner() == program_id
|
||||||
&& filters.iter().all(|filter_type| match filter_type {
|
&& filters.iter().all(|filter_type| match filter_type {
|
||||||
RpcFilterType::DataSize(size) => {
|
RpcFilterType::DataSize(size) => {
|
||||||
account.data().len() as u64 == *size
|
account.data().len() as u64 == *size
|
||||||
@ -2039,7 +2046,7 @@ impl JsonRpcRequestProcessor {
|
|||||||
message: e.to_string(),
|
message: e.to_string(),
|
||||||
})?)
|
})?)
|
||||||
} else {
|
} else {
|
||||||
self.get_filtered_program_accounts(bank, &spl_token_id(), filters)
|
self.get_filtered_program_accounts(bank, program_id, filters)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2217,7 +2224,7 @@ fn get_encoded_account(
|
|||||||
) -> Result<Option<UiAccount>> {
|
) -> Result<Option<UiAccount>> {
|
||||||
match bank.get_account(pubkey) {
|
match bank.get_account(pubkey) {
|
||||||
Some(account) => {
|
Some(account) => {
|
||||||
let response = if account.owner() == &spl_token_id()
|
let response = if is_known_spl_token_id(account.owner())
|
||||||
&& encoding == UiAccountEncoding::JsonParsed
|
&& encoding == UiAccountEncoding::JsonParsed
|
||||||
{
|
{
|
||||||
get_parsed_token_account(bank.clone(), pubkey, account)
|
get_parsed_token_account(bank.clone(), pubkey, account)
|
||||||
@ -2257,7 +2264,7 @@ fn encode_account<T: ReadableAccount>(
|
|||||||
/// NOTE: `optimize_filters()` should almost always be called before using this method because of
|
/// NOTE: `optimize_filters()` should almost always be called before using this method because of
|
||||||
/// the strict match on `MemcmpEncodedBytes::Bytes`.
|
/// the strict match on `MemcmpEncodedBytes::Bytes`.
|
||||||
fn get_spl_token_owner_filter(program_id: &Pubkey, filters: &[RpcFilterType]) -> Option<Pubkey> {
|
fn get_spl_token_owner_filter(program_id: &Pubkey, filters: &[RpcFilterType]) -> Option<Pubkey> {
|
||||||
if program_id != &spl_token_id() {
|
if !is_known_spl_token_id(program_id) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let mut data_size_filter: Option<u64> = None;
|
let mut data_size_filter: Option<u64> = None;
|
||||||
@ -2299,7 +2306,7 @@ fn get_spl_token_owner_filter(program_id: &Pubkey, filters: &[RpcFilterType]) ->
|
|||||||
/// NOTE: `optimize_filters()` should almost always be called before using this method because of
|
/// NOTE: `optimize_filters()` should almost always be called before using this method because of
|
||||||
/// the strict match on `MemcmpEncodedBytes::Bytes`.
|
/// the strict match on `MemcmpEncodedBytes::Bytes`.
|
||||||
fn get_spl_token_mint_filter(program_id: &Pubkey, filters: &[RpcFilterType]) -> Option<Pubkey> {
|
fn get_spl_token_mint_filter(program_id: &Pubkey, filters: &[RpcFilterType]) -> Option<Pubkey> {
|
||||||
if program_id != &spl_token_id() {
|
if !is_known_spl_token_id(program_id) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let mut data_size_filter: Option<u64> = None;
|
let mut data_size_filter: Option<u64> = None;
|
||||||
@ -2345,7 +2352,7 @@ fn get_token_program_id_and_mint(
|
|||||||
match token_account_filter {
|
match token_account_filter {
|
||||||
TokenAccountsFilter::Mint(mint) => {
|
TokenAccountsFilter::Mint(mint) => {
|
||||||
let (mint_owner, _) = get_mint_owner_and_decimals(bank, &mint)?;
|
let (mint_owner, _) = get_mint_owner_and_decimals(bank, &mint)?;
|
||||||
if mint_owner != spl_token_id() {
|
if !is_known_spl_token_id(&mint_owner) {
|
||||||
return Err(Error::invalid_params(
|
return Err(Error::invalid_params(
|
||||||
"Invalid param: not a Token mint".to_string(),
|
"Invalid param: not a Token mint".to_string(),
|
||||||
));
|
));
|
||||||
@ -2353,7 +2360,7 @@ fn get_token_program_id_and_mint(
|
|||||||
Ok((mint_owner, Some(mint)))
|
Ok((mint_owner, Some(mint)))
|
||||||
}
|
}
|
||||||
TokenAccountsFilter::ProgramId(program_id) => {
|
TokenAccountsFilter::ProgramId(program_id) => {
|
||||||
if program_id == spl_token_id() {
|
if is_known_spl_token_id(&program_id) {
|
||||||
Ok((program_id, None))
|
Ok((program_id, None))
|
||||||
} else {
|
} else {
|
||||||
Err(Error::invalid_params(
|
Err(Error::invalid_params(
|
||||||
@ -4422,6 +4429,10 @@ pub mod tests {
|
|||||||
std::collections::HashMap,
|
std::collections::HashMap,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fn spl_token_id() -> Pubkey {
|
||||||
|
solana_account_decoder::parse_token::spl_token_ids()[0]
|
||||||
|
}
|
||||||
|
|
||||||
const TEST_MINT_LAMPORTS: u64 = 1_000_000;
|
const TEST_MINT_LAMPORTS: u64 = 1_000_000;
|
||||||
const TEST_SLOTS_PER_EPOCH: u64 = DELINQUENT_VALIDATOR_SLOT_DISTANCE + 1;
|
const TEST_SLOTS_PER_EPOCH: u64 = DELINQUENT_VALIDATOR_SLOT_DISTANCE + 1;
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ use {
|
|||||||
crossbeam_channel::{Receiver, RecvTimeoutError, SendError, Sender},
|
crossbeam_channel::{Receiver, RecvTimeoutError, SendError, Sender},
|
||||||
rayon::prelude::*,
|
rayon::prelude::*,
|
||||||
serde::Serialize,
|
serde::Serialize,
|
||||||
solana_account_decoder::{parse_token::spl_token_id, UiAccount, UiAccountEncoding},
|
solana_account_decoder::{parse_token::is_known_spl_token_id, UiAccount, UiAccountEncoding},
|
||||||
solana_client::{
|
solana_client::{
|
||||||
rpc_filter::RpcFilterType,
|
rpc_filter::RpcFilterType,
|
||||||
rpc_response::{
|
rpc_response::{
|
||||||
@ -330,7 +330,9 @@ fn filter_account_result(
|
|||||||
// If last_modified_slot < last_notified_slot this means that we last notified for a fork
|
// If last_modified_slot < last_notified_slot this means that we last notified for a fork
|
||||||
// and should notify that the account state has been reverted.
|
// and should notify that the account state has been reverted.
|
||||||
let results: Box<dyn Iterator<Item = UiAccount>> = if last_modified_slot != last_notified_slot {
|
let results: Box<dyn Iterator<Item = UiAccount>> = if last_modified_slot != last_notified_slot {
|
||||||
if account.owner() == &spl_token_id() && params.encoding == UiAccountEncoding::JsonParsed {
|
if is_known_spl_token_id(account.owner())
|
||||||
|
&& params.encoding == UiAccountEncoding::JsonParsed
|
||||||
|
{
|
||||||
Box::new(iter::once(get_parsed_token_account(
|
Box::new(iter::once(get_parsed_token_account(
|
||||||
bank,
|
bank,
|
||||||
¶ms.pubkey,
|
¶ms.pubkey,
|
||||||
@ -381,19 +383,20 @@ fn filter_program_results(
|
|||||||
RpcFilterType::Memcmp(compare) => compare.bytes_match(account.data()),
|
RpcFilterType::Memcmp(compare) => compare.bytes_match(account.data()),
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
let accounts: Box<dyn Iterator<Item = RpcKeyedAccount>> = if params.pubkey == spl_token_id()
|
let accounts: Box<dyn Iterator<Item = RpcKeyedAccount>> =
|
||||||
&& params.encoding == UiAccountEncoding::JsonParsed
|
if is_known_spl_token_id(¶ms.pubkey)
|
||||||
&& !accounts_is_empty
|
&& params.encoding == UiAccountEncoding::JsonParsed
|
||||||
{
|
&& !accounts_is_empty
|
||||||
Box::new(get_parsed_token_accounts(bank, keyed_accounts))
|
{
|
||||||
} else {
|
Box::new(get_parsed_token_accounts(bank, keyed_accounts))
|
||||||
Box::new(
|
} else {
|
||||||
keyed_accounts.map(move |(pubkey, account)| RpcKeyedAccount {
|
Box::new(
|
||||||
pubkey: pubkey.to_string(),
|
keyed_accounts.map(move |(pubkey, account)| RpcKeyedAccount {
|
||||||
account: UiAccount::encode(&pubkey, &account, encoding, None, None),
|
pubkey: pubkey.to_string(),
|
||||||
}),
|
account: UiAccount::encode(&pubkey, &account, encoding, None, None),
|
||||||
)
|
}),
|
||||||
};
|
)
|
||||||
|
};
|
||||||
(accounts, last_notified_slot)
|
(accounts, last_notified_slot)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ use {
|
|||||||
},
|
},
|
||||||
inflector::Inflector,
|
inflector::Inflector,
|
||||||
serde_json::Value,
|
serde_json::Value,
|
||||||
solana_account_decoder::parse_token::spl_token_id,
|
solana_account_decoder::parse_token::spl_token_ids,
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
instruction::CompiledInstruction, message::AccountKeys, pubkey::Pubkey, stake,
|
instruction::CompiledInstruction, message::AccountKeys, pubkey::Pubkey, stake,
|
||||||
system_program,
|
system_program,
|
||||||
@ -30,7 +30,6 @@ lazy_static! {
|
|||||||
static ref MEMO_V3_PROGRAM_ID: Pubkey = spl_memo_id_v3();
|
static ref MEMO_V3_PROGRAM_ID: Pubkey = spl_memo_id_v3();
|
||||||
static ref STAKE_PROGRAM_ID: Pubkey = stake::program::id();
|
static ref STAKE_PROGRAM_ID: Pubkey = stake::program::id();
|
||||||
static ref SYSTEM_PROGRAM_ID: Pubkey = system_program::id();
|
static ref SYSTEM_PROGRAM_ID: Pubkey = system_program::id();
|
||||||
static ref TOKEN_PROGRAM_ID: Pubkey = spl_token_id();
|
|
||||||
static ref VOTE_PROGRAM_ID: Pubkey = solana_vote_program::id();
|
static ref VOTE_PROGRAM_ID: Pubkey = solana_vote_program::id();
|
||||||
static ref PARSABLE_PROGRAM_IDS: HashMap<Pubkey, ParsableProgram> = {
|
static ref PARSABLE_PROGRAM_IDS: HashMap<Pubkey, ParsableProgram> = {
|
||||||
let mut m = HashMap::new();
|
let mut m = HashMap::new();
|
||||||
@ -40,7 +39,9 @@ lazy_static! {
|
|||||||
);
|
);
|
||||||
m.insert(*MEMO_V1_PROGRAM_ID, ParsableProgram::SplMemo);
|
m.insert(*MEMO_V1_PROGRAM_ID, ParsableProgram::SplMemo);
|
||||||
m.insert(*MEMO_V3_PROGRAM_ID, ParsableProgram::SplMemo);
|
m.insert(*MEMO_V3_PROGRAM_ID, ParsableProgram::SplMemo);
|
||||||
m.insert(*TOKEN_PROGRAM_ID, ParsableProgram::SplToken);
|
for spl_token_id in spl_token_ids() {
|
||||||
|
m.insert(spl_token_id, ParsableProgram::SplToken);
|
||||||
|
}
|
||||||
m.insert(*BPF_LOADER_PROGRAM_ID, ParsableProgram::BpfLoader);
|
m.insert(*BPF_LOADER_PROGRAM_ID, ParsableProgram::BpfLoader);
|
||||||
m.insert(
|
m.insert(
|
||||||
*BPF_UPGRADEABLE_LOADER_PROGRAM_ID,
|
*BPF_UPGRADEABLE_LOADER_PROGRAM_ID,
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use {
|
use {
|
||||||
crate::TransactionTokenBalance,
|
crate::TransactionTokenBalance,
|
||||||
solana_account_decoder::parse_token::{
|
solana_account_decoder::parse_token::{
|
||||||
pubkey_from_spl_token, spl_token_id, spl_token_native_mint, token_amount_to_ui_amount,
|
is_known_spl_token_id, pubkey_from_spl_token, spl_token_native_mint,
|
||||||
UiTokenAmount,
|
token_amount_to_ui_amount, UiTokenAmount,
|
||||||
},
|
},
|
||||||
solana_measure::measure::Measure,
|
solana_measure::measure::Measure,
|
||||||
solana_metrics::datapoint_debug,
|
solana_metrics::datapoint_debug,
|
||||||
@ -35,10 +35,6 @@ impl TransactionTokenBalancesSet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_token_program(program_id: &Pubkey) -> bool {
|
|
||||||
program_id == &spl_token_id()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_mint_decimals(bank: &Bank, mint: &Pubkey) -> Option<u8> {
|
fn get_mint_decimals(bank: &Bank, mint: &Pubkey) -> Option<u8> {
|
||||||
if mint == &spl_token_native_mint() {
|
if mint == &spl_token_native_mint() {
|
||||||
Some(spl_token::native_mint::DECIMALS)
|
Some(spl_token::native_mint::DECIMALS)
|
||||||
@ -63,12 +59,12 @@ pub fn collect_token_balances(
|
|||||||
|
|
||||||
for transaction in batch.sanitized_transactions() {
|
for transaction in batch.sanitized_transactions() {
|
||||||
let account_keys = transaction.message().account_keys();
|
let account_keys = transaction.message().account_keys();
|
||||||
let has_token_program = account_keys.iter().any(is_token_program);
|
let has_token_program = account_keys.iter().any(is_known_spl_token_id);
|
||||||
|
|
||||||
let mut transaction_balances: Vec<TransactionTokenBalance> = vec![];
|
let mut transaction_balances: Vec<TransactionTokenBalance> = vec![];
|
||||||
if has_token_program {
|
if has_token_program {
|
||||||
for (index, account_id) in account_keys.iter().enumerate() {
|
for (index, account_id) in account_keys.iter().enumerate() {
|
||||||
if transaction.message().is_invoked(index) || is_token_program(account_id) {
|
if transaction.message().is_invoked(index) || is_known_spl_token_id(account_id) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user