Support token-2022 in RPC account parsing (#24619)
* Use token-2022 in parsed_token_account * Parse token-2022 accounts
This commit is contained in:
parent
674c0d7602
commit
d2dad51b8c
|
@ -5514,6 +5514,7 @@ dependencies = [
|
|||
"solana-version",
|
||||
"solana-vote-program",
|
||||
"spl-token",
|
||||
"spl-token-2022",
|
||||
"stream-cancel",
|
||||
"symlink",
|
||||
"thiserror",
|
||||
|
|
|
@ -4,7 +4,9 @@ use {
|
|||
StringAmount, StringDecimals,
|
||||
},
|
||||
solana_sdk::pubkey::Pubkey,
|
||||
spl_token::{
|
||||
spl_token_2022::{
|
||||
extension::StateWithExtensions,
|
||||
generic_token_account::GenericTokenAccount,
|
||||
solana_program::{
|
||||
program_option::COption, program_pack::Pack, pubkey::Pubkey as SplTokenPubkey,
|
||||
},
|
||||
|
@ -60,58 +62,56 @@ pub fn parse_token(
|
|||
data: &[u8],
|
||||
mint_decimals: Option<u8>,
|
||||
) -> Result<TokenAccountType, ParseAccountError> {
|
||||
if data.len() == Account::get_packed_len() {
|
||||
let account = Account::unpack(data)
|
||||
.map_err(|_| ParseAccountError::AccountNotParsable(ParsableAccount::SplToken))?;
|
||||
if let Ok(account) = StateWithExtensions::<Account>::unpack(data) {
|
||||
let decimals = mint_decimals.ok_or_else(|| {
|
||||
ParseAccountError::AdditionalDataMissing(
|
||||
"no mint_decimals provided to parse spl-token account".to_string(),
|
||||
)
|
||||
})?;
|
||||
Ok(TokenAccountType::Account(UiTokenAccount {
|
||||
mint: account.mint.to_string(),
|
||||
owner: account.owner.to_string(),
|
||||
token_amount: token_amount_to_ui_amount(account.amount, decimals),
|
||||
delegate: match account.delegate {
|
||||
return Ok(TokenAccountType::Account(UiTokenAccount {
|
||||
mint: account.base.mint.to_string(),
|
||||
owner: account.base.owner.to_string(),
|
||||
token_amount: token_amount_to_ui_amount(account.base.amount, decimals),
|
||||
delegate: match account.base.delegate {
|
||||
COption::Some(pubkey) => Some(pubkey.to_string()),
|
||||
COption::None => None,
|
||||
},
|
||||
state: account.state.into(),
|
||||
is_native: account.is_native(),
|
||||
rent_exempt_reserve: match account.is_native {
|
||||
state: account.base.state.into(),
|
||||
is_native: account.base.is_native(),
|
||||
rent_exempt_reserve: match account.base.is_native {
|
||||
COption::Some(reserve) => Some(token_amount_to_ui_amount(reserve, decimals)),
|
||||
COption::None => None,
|
||||
},
|
||||
delegated_amount: if account.delegate.is_none() {
|
||||
delegated_amount: if account.base.delegate.is_none() {
|
||||
None
|
||||
} else {
|
||||
Some(token_amount_to_ui_amount(
|
||||
account.delegated_amount,
|
||||
account.base.delegated_amount,
|
||||
decimals,
|
||||
))
|
||||
},
|
||||
close_authority: match account.close_authority {
|
||||
close_authority: match account.base.close_authority {
|
||||
COption::Some(pubkey) => Some(pubkey.to_string()),
|
||||
COption::None => None,
|
||||
},
|
||||
}))
|
||||
} else if data.len() == Mint::get_packed_len() {
|
||||
let mint = Mint::unpack(data)
|
||||
.map_err(|_| ParseAccountError::AccountNotParsable(ParsableAccount::SplToken))?;
|
||||
Ok(TokenAccountType::Mint(UiMint {
|
||||
mint_authority: match mint.mint_authority {
|
||||
}));
|
||||
}
|
||||
if let Ok(mint) = StateWithExtensions::<Mint>::unpack(data) {
|
||||
return Ok(TokenAccountType::Mint(UiMint {
|
||||
mint_authority: match mint.base.mint_authority {
|
||||
COption::Some(pubkey) => Some(pubkey.to_string()),
|
||||
COption::None => None,
|
||||
},
|
||||
supply: mint.supply.to_string(),
|
||||
decimals: mint.decimals,
|
||||
is_initialized: mint.is_initialized,
|
||||
freeze_authority: match mint.freeze_authority {
|
||||
supply: mint.base.supply.to_string(),
|
||||
decimals: mint.base.decimals,
|
||||
is_initialized: mint.base.is_initialized,
|
||||
freeze_authority: match mint.base.freeze_authority {
|
||||
COption::Some(pubkey) => Some(pubkey.to_string()),
|
||||
COption::None => None,
|
||||
},
|
||||
}))
|
||||
} else if data.len() == Multisig::get_packed_len() {
|
||||
}));
|
||||
}
|
||||
if data.len() == Multisig::get_packed_len() {
|
||||
let multisig = Multisig::unpack(data)
|
||||
.map_err(|_| ParseAccountError::AccountNotParsable(ParsableAccount::SplToken))?;
|
||||
Ok(TokenAccountType::Multisig(UiMultisig {
|
||||
|
@ -265,7 +265,7 @@ pub struct UiMultisig {
|
|||
}
|
||||
|
||||
pub fn get_token_account_mint(data: &[u8]) -> Option<Pubkey> {
|
||||
if data.len() == Account::get_packed_len() {
|
||||
if Account::valid_account_data(data) {
|
||||
Some(Pubkey::new(&data[0..32]))
|
||||
} else {
|
||||
None
|
||||
|
@ -370,6 +370,7 @@ mod test {
|
|||
let mut account_data = vec![0; Account::get_packed_len()];
|
||||
let mut account = Account::unpack_unchecked(&account_data).unwrap();
|
||||
account.mint = mint_pubkey;
|
||||
account.state = AccountState::Initialized;
|
||||
Account::pack(account, &mut account_data).unwrap();
|
||||
|
||||
let expected_mint_pubkey = Pubkey::new(&[2; 32]);
|
||||
|
|
|
@ -4870,6 +4870,7 @@ dependencies = [
|
|||
"solana-version",
|
||||
"solana-vote-program",
|
||||
"spl-token",
|
||||
"spl-token-2022",
|
||||
"stream-cancel",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
|
|
|
@ -49,6 +49,7 @@ solana-transaction-status = { path = "../transaction-status", version = "=1.11.0
|
|||
solana-version = { path = "../version", version = "=1.11.0" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "=1.11.0" }
|
||||
spl-token = { version = "=3.3.0", features = ["no-entrypoint"] }
|
||||
spl-token-2022 = { version = "=0.2.0", features = ["no-entrypoint"] }
|
||||
stream-cancel = "0.8.1"
|
||||
thiserror = "1.0"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
|
|
|
@ -13,7 +13,7 @@ use {
|
|||
account::{AccountSharedData, ReadableAccount},
|
||||
pubkey::Pubkey,
|
||||
},
|
||||
spl_token::{solana_program::program_pack::Pack, state::Mint},
|
||||
spl_token_2022::{extension::StateWithExtensions, state::Mint},
|
||||
std::{collections::HashMap, sync::Arc},
|
||||
};
|
||||
|
||||
|
@ -91,9 +91,9 @@ pub fn get_mint_owner_and_decimals(bank: &Arc<Bank>, mint: &Pubkey) -> Result<(P
|
|||
}
|
||||
|
||||
fn get_mint_decimals(data: &[u8]) -> Result<u8> {
|
||||
Mint::unpack(data)
|
||||
StateWithExtensions::<Mint>::unpack(data)
|
||||
.map_err(|_| {
|
||||
Error::invalid_params("Invalid param: Token mint could not be unpacked".to_string())
|
||||
})
|
||||
.map(|mint| mint.decimals)
|
||||
.map(|mint| mint.base.decimals)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue