Update spl-token to v2.0 (bp #11884) (#11897)

* Update spl-token to v2.0 (#11884)

* Update account-decoder to spl-token v2.0

* Update transaction-status to spl-token v2.0

* Update rpc to spl-token v2.0

* Update getTokenSupply to pull from Mint directly

* Fixup to spl-token v2.0.1

(cherry picked from commit 76be36c9ce)

# Conflicts:
#	Cargo.lock
#	account-decoder/Cargo.toml
#	core/Cargo.toml

* Fix conflicts

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
This commit is contained in:
mergify[bot]
2020-08-28 23:36:53 +00:00
committed by GitHub
parent 1a25889f72
commit 2a649e990d
10 changed files with 989 additions and 374 deletions

115
Cargo.lock generated
View File

@ -403,24 +403,6 @@ dependencies = [
"rustc_version", "rustc_version",
] ]
[[package]]
name = "cbindgen"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "104ca409bbff8293739438c71820a2606111b5f8f81835536dc673dfd807369e"
dependencies = [
"clap",
"heck",
"log 0.4.8",
"proc-macro2 1.0.19",
"quote 1.0.6",
"serde",
"serde_json",
"syn 1.0.27",
"tempfile",
"toml",
]
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.49" version = "1.0.49"
@ -1259,15 +1241,6 @@ dependencies = [
"byteorder", "byteorder",
] ]
[[package]]
name = "heck"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
dependencies = [
"unicode-segmentation",
]
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.1.13" version = "0.1.13"
@ -2109,6 +2082,28 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "num_enum"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "226b45a5c2ac4dd696ed30fa6b94b057ad909c7b7fc2e0d0808192bced894066"
dependencies = [
"derivative",
"num_enum_derive",
]
[[package]]
name = "num_enum_derive"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c0fd9eba1d5db0994a239e09c1be402d35622277e35468ba891aa5e3188ce7e"
dependencies = [
"proc-macro-crate",
"proc-macro2 1.0.19",
"quote 1.0.6",
"syn 1.0.27",
]
[[package]] [[package]]
name = "number_prefix" name = "number_prefix"
version = "0.3.0" version = "0.3.0"
@ -3562,7 +3557,7 @@ dependencies = [
"solana-rayon-threadlimit", "solana-rayon-threadlimit",
"solana-runtime", "solana-runtime",
"solana-sdk 1.3.6", "solana-sdk 1.3.6",
"solana-sdk-macro-frozen-abi", "solana-sdk-macro-frozen-abi 1.3.6",
"solana-stake-program", "solana-stake-program",
"solana-storage-bigtable", "solana-storage-bigtable",
"solana-streamer", "solana-streamer",
@ -3584,9 +3579,9 @@ dependencies = [
[[package]] [[package]]
name = "solana-crate-features" name = "solana-crate-features"
version = "1.2.17" version = "1.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "610ba71932d0bf4abf88eabb081ee43fa1ee6bb5137c4fa6776ea9dd8630ca5c" checksum = "3e93b888ccc34b2c7a7fa3e1c804ce5f1a4b521d09b8779de3a80e70e3be2f82"
dependencies = [ dependencies = [
"backtrace", "backtrace",
"bytes 0.4.12", "bytes 0.4.12",
@ -3927,9 +3922,9 @@ dependencies = [
[[package]] [[package]]
name = "solana-logger" name = "solana-logger"
version = "1.2.17" version = "1.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc703cb2807e9d713f70df32ac8c3a7a9c8af437dd0d468b1b77cfd8e8b4cbc8" checksum = "7c8d27af0c30536bf91abbf40db5133e905bfd61ed24b8096c6e0a5cfb92c1e6"
dependencies = [ dependencies = [
"env_logger", "env_logger",
"lazy_static", "lazy_static",
@ -4165,7 +4160,7 @@ dependencies = [
"solana-noop-program", "solana-noop-program",
"solana-rayon-threadlimit", "solana-rayon-threadlimit",
"solana-sdk 1.3.6", "solana-sdk 1.3.6",
"solana-sdk-macro-frozen-abi", "solana-sdk-macro-frozen-abi 1.3.6",
"solana-stake-program", "solana-stake-program",
"solana-vote-program", "solana-vote-program",
"symlink", "symlink",
@ -4185,9 +4180,9 @@ dependencies = [
[[package]] [[package]]
name = "solana-sdk" name = "solana-sdk"
version = "1.2.17" version = "1.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a556c1b456609b760ff47b933912f27563ea8a9a1692864cbc1014c02f5b981e" checksum = "15ca11bc0623ec67bb2dfbf5eff025c67c099f0ac808e192a12210a317417b9b"
dependencies = [ dependencies = [
"assert_matches", "assert_matches",
"bincode", "bincode",
@ -4195,6 +4190,7 @@ dependencies = [
"bv", "bv",
"byteorder", "byteorder",
"chrono", "chrono",
"curve25519-dalek",
"ed25519-dalek", "ed25519-dalek",
"generic-array 0.14.3", "generic-array 0.14.3",
"hex", "hex",
@ -4214,9 +4210,10 @@ dependencies = [
"serde_derive", "serde_derive",
"serde_json", "serde_json",
"sha2", "sha2",
"solana-crate-features 1.2.17", "solana-crate-features 1.3.4",
"solana-logger 1.2.17", "solana-logger 1.3.4",
"solana-sdk-macro 1.2.17", "solana-sdk-macro 1.3.4",
"solana-sdk-macro-frozen-abi 1.3.5",
"thiserror", "thiserror",
] ]
@ -4253,16 +4250,16 @@ dependencies = [
"solana-crate-features 1.3.6", "solana-crate-features 1.3.6",
"solana-logger 1.3.6", "solana-logger 1.3.6",
"solana-sdk-macro 1.3.6", "solana-sdk-macro 1.3.6",
"solana-sdk-macro-frozen-abi", "solana-sdk-macro-frozen-abi 1.3.6",
"thiserror", "thiserror",
"tiny-bip39", "tiny-bip39",
] ]
[[package]] [[package]]
name = "solana-sdk-macro" name = "solana-sdk-macro"
version = "1.2.17" version = "1.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38bc386020de692562a29c0696a71c14a3d94455a9a785a97c7b254c38d6a2c8" checksum = "d5ef3b2acbb22a28edc32e36ed5d3b0c902007befe51f28f46c3e78a825acf71"
dependencies = [ dependencies = [
"bs58", "bs58",
"proc-macro2 1.0.19", "proc-macro2 1.0.19",
@ -4282,6 +4279,19 @@ dependencies = [
"syn 1.0.27", "syn 1.0.27",
] ]
[[package]]
name = "solana-sdk-macro-frozen-abi"
version = "1.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a9b012fab0634311c8b6176ee1d6874a39f7b0bad8b647fe2cf36f687151728"
dependencies = [
"lazy_static",
"proc-macro2 1.0.19",
"quote 1.0.6",
"rustc_version",
"syn 1.0.27",
]
[[package]] [[package]]
name = "solana-sdk-macro-frozen-abi" name = "solana-sdk-macro-frozen-abi"
version = "1.3.6" version = "1.3.6"
@ -4366,7 +4376,7 @@ dependencies = [
"solana-logger 1.3.6", "solana-logger 1.3.6",
"solana-metrics", "solana-metrics",
"solana-sdk 1.3.6", "solana-sdk 1.3.6",
"solana-sdk-macro-frozen-abi", "solana-sdk-macro-frozen-abi 1.3.6",
"solana-vote-program", "solana-vote-program",
"thiserror", "thiserror",
] ]
@ -4520,7 +4530,7 @@ dependencies = [
"serde_derive", "serde_derive",
"solana-logger 1.3.6", "solana-logger 1.3.6",
"solana-sdk 1.3.6", "solana-sdk 1.3.6",
"solana-sdk-macro-frozen-abi", "solana-sdk-macro-frozen-abi 1.3.6",
] ]
[[package]] [[package]]
@ -4553,7 +4563,7 @@ dependencies = [
"solana-logger 1.3.6", "solana-logger 1.3.6",
"solana-metrics", "solana-metrics",
"solana-sdk 1.3.6", "solana-sdk 1.3.6",
"solana-sdk-macro-frozen-abi", "solana-sdk-macro-frozen-abi 1.3.6",
"thiserror", "thiserror",
] ]
@ -4623,20 +4633,21 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b303bab17e0c696de6d7550ba6f05a5a6dbf5c5d1597e68a4592899072e1c07a" checksum = "b303bab17e0c696de6d7550ba6f05a5a6dbf5c5d1597e68a4592899072e1c07a"
dependencies = [ dependencies = [
"solana-sdk 1.2.17", "solana-sdk 1.3.4",
] ]
[[package]] [[package]]
name = "spl-token" name = "spl-token"
version = "1.0.8" version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e8bee8b59279b46d0627490b544c3bc38e440ff4da9851a34a26ab0a24bfe7d" checksum = "89ee48031d5b189a9da7295076ba07bf0ccd407e0fee1279281fb2c3258fa9fb"
dependencies = [ dependencies = [
"cbindgen", "arrayref",
"num-derive 0.3.0", "num-derive 0.3.0",
"num-traits", "num-traits",
"num_enum",
"remove_dir_all", "remove_dir_all",
"solana-sdk 1.2.17", "solana-sdk 1.3.4",
"thiserror", "thiserror",
] ]
@ -5665,12 +5676,6 @@ dependencies = [
"smallvec 1.4.0", "smallvec 1.4.0",
] ]
[[package]]
name = "unicode-segmentation"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
[[package]] [[package]]
name = "unicode-width" name = "unicode-width"
version = "0.1.7" version = "0.1.7"

View File

@ -22,7 +22,7 @@ solana-config-program = { path = "../programs/config", version = "1.3.6" }
solana-sdk = { path = "../sdk", version = "1.3.6" } solana-sdk = { path = "../sdk", version = "1.3.6" }
solana-stake-program = { path = "../programs/stake", version = "1.3.6" } solana-stake-program = { path = "../programs/stake", version = "1.3.6" }
solana-vote-program = { path = "../programs/vote", version = "1.3.6" } solana-vote-program = { path = "../programs/vote", version = "1.3.6" }
spl-token-v1-0 = { package = "spl-token", version = "1.0.8", features = ["skip-no-mangle"] } spl-token-v2-0 = { package = "spl-token", version = "2.0.1", features = ["skip-no-mangle"] }
thiserror = "1.0" thiserror = "1.0"
[package.metadata.docs.rs] [package.metadata.docs.rs]

View File

@ -3,7 +3,7 @@ use crate::{
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_v1_0}, parse_token::{parse_token, spl_token_id_v2_0},
parse_vote::parse_vote, parse_vote::parse_vote,
}; };
use inflector::Inflector; use inflector::Inflector;
@ -17,7 +17,7 @@ lazy_static! {
static ref STAKE_PROGRAM_ID: Pubkey = solana_stake_program::id(); static ref STAKE_PROGRAM_ID: Pubkey = solana_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_v1_0(); static ref TOKEN_PROGRAM_ID: Pubkey = spl_token_id_v2_0();
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();

View File

@ -3,32 +3,32 @@ use crate::{
StringAmount, StringAmount,
}; };
use solana_sdk::pubkey::Pubkey; use solana_sdk::pubkey::Pubkey;
use spl_token_v1_0::{ use spl_token_v2_0::{
option::COption, option::COption,
pack::Pack,
solana_sdk::pubkey::Pubkey as SplTokenPubkey, solana_sdk::pubkey::Pubkey as SplTokenPubkey,
state::{unpack, Account, Mint, Multisig}, state::{Account, AccountState, Mint, Multisig},
}; };
use std::{mem::size_of, str::FromStr}; use std::{mem::size_of, str::FromStr};
// A helper function to convert spl_token_v1_0::id() as spl_sdk::pubkey::Pubkey to // A helper function to convert spl_token_v2_0::id() as spl_sdk::pubkey::Pubkey to
// solana_sdk::pubkey::Pubkey // solana_sdk::pubkey::Pubkey
pub fn spl_token_id_v1_0() -> Pubkey { pub fn spl_token_id_v2_0() -> Pubkey {
Pubkey::from_str(&spl_token_v1_0::id().to_string()).unwrap() Pubkey::from_str(&spl_token_v2_0::id().to_string()).unwrap()
} }
// A helper function to convert spl_token_v1_0::native_mint::id() as spl_sdk::pubkey::Pubkey to // A helper function to convert spl_token_v2_0::native_mint::id() as spl_sdk::pubkey::Pubkey to
// solana_sdk::pubkey::Pubkey // solana_sdk::pubkey::Pubkey
pub fn spl_token_v1_0_native_mint() -> Pubkey { pub fn spl_token_v2_0_native_mint() -> Pubkey {
Pubkey::from_str(&spl_token_v1_0::native_mint::id().to_string()).unwrap() Pubkey::from_str(&spl_token_v2_0::native_mint::id().to_string()).unwrap()
} }
pub fn parse_token( pub fn parse_token(
data: &[u8], data: &[u8],
mint_decimals: Option<u8>, mint_decimals: Option<u8>,
) -> Result<TokenAccountType, ParseAccountError> { ) -> Result<TokenAccountType, ParseAccountError> {
let mut data = data.to_vec();
if data.len() == size_of::<Account>() { if data.len() == size_of::<Account>() {
let account: Account = *unpack(&mut data) let account = Account::unpack(data)
.map_err(|_| ParseAccountError::AccountNotParsable(ParsableAccount::SplToken))?; .map_err(|_| ParseAccountError::AccountNotParsable(ParsableAccount::SplToken))?;
let decimals = mint_decimals.ok_or_else(|| { let decimals = mint_decimals.ok_or_else(|| {
ParseAccountError::AdditionalDataMissing( ParseAccountError::AdditionalDataMissing(
@ -43,8 +43,12 @@ pub fn parse_token(
COption::Some(pubkey) => Some(pubkey.to_string()), COption::Some(pubkey) => Some(pubkey.to_string()),
COption::None => None, COption::None => None,
}, },
is_initialized: account.is_initialized, state: account.state.into(),
is_native: account.is_native, is_native: account.is_native(),
rent_exempt_reserve: match account.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.delegate.is_none() {
None None
} else { } else {
@ -53,20 +57,29 @@ pub fn parse_token(
decimals, decimals,
)) ))
}, },
})) close_authority: match account.close_authority {
} else if data.len() == size_of::<Mint>() {
let mint: Mint = *unpack(&mut data)
.map_err(|_| ParseAccountError::AccountNotParsable(ParsableAccount::SplToken))?;
Ok(TokenAccountType::Mint(UiMint {
owner: match mint.owner {
COption::Some(pubkey) => Some(pubkey.to_string()), COption::Some(pubkey) => Some(pubkey.to_string()),
COption::None => None, COption::None => None,
}, },
}))
} else if data.len() == size_of::<Mint>() {
let mint = Mint::unpack(data)
.map_err(|_| ParseAccountError::AccountNotParsable(ParsableAccount::SplToken))?;
Ok(TokenAccountType::Mint(UiMint {
mint_authority: match mint.mint_authority {
COption::Some(pubkey) => Some(pubkey.to_string()),
COption::None => None,
},
supply: mint.supply.to_string(),
decimals: mint.decimals, decimals: mint.decimals,
is_initialized: mint.is_initialized, is_initialized: mint.is_initialized,
freeze_authority: match mint.freeze_authority {
COption::Some(pubkey) => Some(pubkey.to_string()),
COption::None => None,
},
})) }))
} else if data.len() == size_of::<Multisig>() { } else if data.len() == size_of::<Multisig>() {
let multisig: Multisig = *unpack(&mut data) let multisig = Multisig::unpack(data)
.map_err(|_| ParseAccountError::AccountNotParsable(ParsableAccount::SplToken))?; .map_err(|_| ParseAccountError::AccountNotParsable(ParsableAccount::SplToken))?;
Ok(TokenAccountType::Multisig(UiMultisig { Ok(TokenAccountType::Multisig(UiMultisig {
num_required_signers: multisig.m, num_required_signers: multisig.m,
@ -107,10 +120,32 @@ pub struct UiTokenAccount {
pub token_amount: UiTokenAmount, pub token_amount: UiTokenAmount,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub delegate: Option<String>, pub delegate: Option<String>,
pub is_initialized: bool, pub state: UiAccountState,
pub is_native: bool, pub is_native: bool,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub rent_exempt_reserve: Option<UiTokenAmount>,
#[serde(skip_serializing_if = "Option::is_none")]
pub delegated_amount: Option<UiTokenAmount>, pub delegated_amount: Option<UiTokenAmount>,
#[serde(skip_serializing_if = "Option::is_none")]
pub close_authority: Option<String>,
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub enum UiAccountState {
Uninitialized,
Initialized,
Frozen,
}
impl From<AccountState> for UiAccountState {
fn from(state: AccountState) -> Self {
match state {
AccountState::Uninitialized => UiAccountState::Uninitialized,
AccountState::Initialized => UiAccountState::Initialized,
AccountState::Frozen => UiAccountState::Frozen,
}
}
} }
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
@ -134,9 +169,11 @@ pub fn token_amount_to_ui_amount(amount: u64, decimals: u8) -> UiTokenAmount {
#[derive(Debug, Serialize, Deserialize, PartialEq)] #[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct UiMint { pub struct UiMint {
pub owner: Option<String>, pub mint_authority: Option<String>,
pub supply: StringAmount,
pub decimals: u8, pub decimals: u8,
pub is_initialized: bool, pub is_initialized: bool,
pub freeze_authority: Option<String>,
} }
#[derive(Debug, Serialize, Deserialize, PartialEq)] #[derive(Debug, Serialize, Deserialize, PartialEq)]
@ -159,18 +196,23 @@ pub fn get_token_account_mint(data: &[u8]) -> Option<Pubkey> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use spl_token_v1_0::state::unpack_unchecked;
#[test] #[test]
fn test_parse_token() { fn test_parse_token() {
let mint_pubkey = SplTokenPubkey::new(&[2; 32]); let mint_pubkey = SplTokenPubkey::new(&[2; 32]);
let owner_pubkey = SplTokenPubkey::new(&[3; 32]); let owner_pubkey = SplTokenPubkey::new(&[3; 32]);
let mut account_data = [0; size_of::<Account>()]; let mut account_data = [0; size_of::<Account>()];
let mut account: &mut Account = unpack_unchecked(&mut account_data).unwrap(); Account::unpack_unchecked_mut(&mut account_data, &mut |account: &mut Account| {
account.mint = mint_pubkey; account.mint = mint_pubkey;
account.owner = owner_pubkey; account.owner = owner_pubkey;
account.amount = 42; account.amount = 42;
account.is_initialized = true; account.state = AccountState::Initialized;
account.is_native = COption::None;
account.close_authority = COption::Some(owner_pubkey);
Ok(())
})
.unwrap();
assert!(parse_token(&account_data, None).is_err()); assert!(parse_token(&account_data, None).is_err());
assert_eq!( assert_eq!(
parse_token(&account_data, Some(2)).unwrap(), parse_token(&account_data, Some(2)).unwrap(),
@ -183,23 +225,33 @@ mod test {
amount: "42".to_string() amount: "42".to_string()
}, },
delegate: None, delegate: None,
is_initialized: true, state: UiAccountState::Initialized,
is_native: false, is_native: false,
rent_exempt_reserve: None,
delegated_amount: None, delegated_amount: None,
close_authority: Some(owner_pubkey.to_string()),
}), }),
); );
let mut mint_data = [0; size_of::<Mint>()]; let mut mint_data = [0; size_of::<Mint>()];
let mut mint: &mut Mint = unpack_unchecked(&mut mint_data).unwrap(); Mint::unpack_unchecked_mut(&mut mint_data, &mut |mint: &mut Mint| {
mint.owner = COption::Some(owner_pubkey); mint.mint_authority = COption::Some(owner_pubkey);
mint.decimals = 3; mint.supply = 42;
mint.is_initialized = true; mint.decimals = 3;
mint.is_initialized = true;
mint.freeze_authority = COption::Some(owner_pubkey);
Ok(())
})
.unwrap();
assert_eq!( assert_eq!(
parse_token(&mint_data, None).unwrap(), parse_token(&mint_data, None).unwrap(),
TokenAccountType::Mint(UiMint { TokenAccountType::Mint(UiMint {
owner: Some(owner_pubkey.to_string()), mint_authority: Some(owner_pubkey.to_string()),
supply: 42.to_string(),
decimals: 3, decimals: 3,
is_initialized: true, is_initialized: true,
freeze_authority: Some(owner_pubkey.to_string()),
}), }),
); );
@ -207,15 +259,18 @@ mod test {
let signer2 = SplTokenPubkey::new(&[2; 32]); let signer2 = SplTokenPubkey::new(&[2; 32]);
let signer3 = SplTokenPubkey::new(&[3; 32]); let signer3 = SplTokenPubkey::new(&[3; 32]);
let mut multisig_data = [0; size_of::<Multisig>()]; let mut multisig_data = [0; size_of::<Multisig>()];
let mut multisig: &mut Multisig = unpack_unchecked(&mut multisig_data).unwrap();
let mut signers = [SplTokenPubkey::default(); 11]; let mut signers = [SplTokenPubkey::default(); 11];
signers[0] = signer1; signers[0] = signer1;
signers[1] = signer2; signers[1] = signer2;
signers[2] = signer3; signers[2] = signer3;
multisig.m = 2; Multisig::unpack_unchecked_mut(&mut multisig_data, &mut |multisig: &mut Multisig| {
multisig.n = 3; multisig.m = 2;
multisig.is_initialized = true; multisig.n = 3;
multisig.signers = signers; multisig.is_initialized = true;
multisig.signers = signers;
Ok(())
})
.unwrap();
assert_eq!( assert_eq!(
parse_token(&multisig_data, None).unwrap(), parse_token(&multisig_data, None).unwrap(),
TokenAccountType::Multisig(UiMultisig { TokenAccountType::Multisig(UiMultisig {
@ -238,8 +293,11 @@ mod test {
fn test_get_token_account_mint() { fn test_get_token_account_mint() {
let mint_pubkey = SplTokenPubkey::new(&[2; 32]); let mint_pubkey = SplTokenPubkey::new(&[2; 32]);
let mut account_data = [0; size_of::<Account>()]; let mut account_data = [0; size_of::<Account>()];
let mut account: &mut Account = unpack_unchecked(&mut account_data).unwrap(); Account::unpack_unchecked_mut(&mut account_data, &mut |account: &mut Account| {
account.mint = mint_pubkey; account.mint = mint_pubkey;
Ok(())
})
.unwrap();
let expected_mint_pubkey = Pubkey::new(&[2; 32]); let expected_mint_pubkey = Pubkey::new(&[2; 32]);
assert_eq!( assert_eq!(

View File

@ -69,7 +69,7 @@ solana-transaction-status = { path = "../transaction-status", version = "1.3.6"
solana-version = { path = "../version", version = "1.3.6" } solana-version = { path = "../version", version = "1.3.6" }
solana-vote-program = { path = "../programs/vote", version = "1.3.6" } solana-vote-program = { path = "../programs/vote", version = "1.3.6" }
solana-vote-signer = { path = "../vote-signer", version = "1.3.6" } solana-vote-signer = { path = "../vote-signer", version = "1.3.6" }
spl-token-v1-0 = { package = "spl-token", version = "1.0.8", features = ["skip-no-mangle"] } spl-token-v2-0 = { package = "spl-token", version = "2.0.1", features = ["skip-no-mangle"] }
tempfile = "3.1.0" tempfile = "3.1.0"
thiserror = "1.0" thiserror = "1.0"
tokio_01 = { version = "0.1", package = "tokio" } tokio_01 = { version = "0.1", package = "tokio" }

View File

@ -11,7 +11,7 @@ use jsonrpc_derive::rpc;
use solana_account_decoder::{ use solana_account_decoder::{
parse_account_data::AccountAdditionalData, parse_account_data::AccountAdditionalData,
parse_token::{ parse_token::{
get_token_account_mint, spl_token_id_v1_0, spl_token_v1_0_native_mint, get_token_account_mint, spl_token_id_v2_0, spl_token_v2_0_native_mint,
token_amount_to_ui_amount, UiTokenAmount, token_amount_to_ui_amount, UiTokenAmount,
}, },
UiAccount, UiAccountEncoding, UiAccount, UiAccountEncoding,
@ -58,7 +58,10 @@ use solana_transaction_status::{
ConfirmedBlock, ConfirmedTransaction, TransactionStatus, UiTransactionEncoding, ConfirmedBlock, ConfirmedTransaction, TransactionStatus, UiTransactionEncoding,
}; };
use solana_vote_program::vote_state::{VoteState, MAX_LOCKOUT_HISTORY}; use solana_vote_program::vote_state::{VoteState, MAX_LOCKOUT_HISTORY};
use spl_token_v1_0::state::{Account as TokenAccount, Mint}; use spl_token_v2_0::{
pack::Pack,
state::{Account as TokenAccount, Mint},
};
use std::{ use std::{
cmp::{max, min}, cmp::{max, min},
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
@ -247,7 +250,7 @@ impl JsonRpcRequestProcessor {
check_slice_and_encoding(&encoding, config.data_slice.is_some())?; check_slice_and_encoding(&encoding, config.data_slice.is_some())?;
let mut response = None; let mut response = None;
if let Some(account) = bank.get_account(pubkey) { if let Some(account) = bank.get_account(pubkey) {
if account.owner == spl_token_id_v1_0() && encoding == UiAccountEncoding::JsonParsed { if account.owner == spl_token_id_v2_0() && encoding == UiAccountEncoding::JsonParsed {
response = Some(get_parsed_token_account(bank.clone(), pubkey, account)); response = Some(get_parsed_token_account(bank.clone(), pubkey, account));
} else if (encoding == UiAccountEncoding::Binary } else if (encoding == UiAccountEncoding::Binary
|| encoding == UiAccountEncoding::Base58) || encoding == UiAccountEncoding::Base58)
@ -295,7 +298,7 @@ impl JsonRpcRequestProcessor {
check_slice_and_encoding(&encoding, data_slice_config.is_some())?; check_slice_and_encoding(&encoding, data_slice_config.is_some())?;
let keyed_accounts = get_filtered_program_accounts(&bank, program_id, filters); let keyed_accounts = get_filtered_program_accounts(&bank, program_id, filters);
let result = let result =
if program_id == &spl_token_id_v1_0() && encoding == UiAccountEncoding::JsonParsed { if program_id == &spl_token_id_v2_0() && encoding == UiAccountEncoding::JsonParsed {
get_parsed_token_accounts(bank, keyed_accounts).collect() get_parsed_token_accounts(bank, keyed_accounts).collect()
} else { } else {
keyed_accounts keyed_accounts
@ -1025,16 +1028,14 @@ 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_v1_0() { if account.owner != spl_token_id_v2_0() {
return Err(Error::invalid_params( return Err(Error::invalid_params(
"Invalid param: not a v1.0 Token account".to_string(), "Invalid param: not a v2.0 Token account".to_string(),
)); ));
} }
let mut data = account.data.to_vec(); let token_account = TokenAccount::unpack(&account.data).map_err(|_| {
let token_account = Error::invalid_params("Invalid param: not a v2.0 Token account".to_string())
spl_token_v1_0::state::unpack::<TokenAccount>(&mut data).map_err(|_| { })?;
Error::invalid_params("Invalid param: not a v1.0 Token account".to_string())
})?;
let mint = &Pubkey::from_str(&token_account.mint.to_string()) let mint = &Pubkey::from_str(&token_account.mint.to_string())
.expect("Token account mint should be convertible to Pubkey"); .expect("Token account mint should be convertible to Pubkey");
let (_, decimals) = get_mint_owner_and_decimals(&bank, &mint)?; let (_, decimals) = get_mint_owner_and_decimals(&bank, &mint)?;
@ -1048,32 +1049,19 @@ impl JsonRpcRequestProcessor {
commitment: Option<CommitmentConfig>, commitment: Option<CommitmentConfig>,
) -> Result<RpcResponse<UiTokenAmount>> { ) -> Result<RpcResponse<UiTokenAmount>> {
let bank = self.bank(commitment); let bank = self.bank(commitment);
let (mint_owner, decimals) = get_mint_owner_and_decimals(&bank, mint)?; let mint_account = bank.get_account(mint).ok_or_else(|| {
if mint_owner != spl_token_id_v1_0() { Error::invalid_params("Invalid param: could not find account".to_string())
})?;
if mint_account.owner != spl_token_id_v2_0() {
return Err(Error::invalid_params( return Err(Error::invalid_params(
"Invalid param: not a v1.0 Token mint".to_string(), "Invalid param: not a v2.0 Token mint".to_string(),
)); ));
} }
let mint = Mint::unpack(&mint_account.data).map_err(|_| {
Error::invalid_params("Invalid param: mint could not be unpacked".to_string())
})?;
let filters = vec![ let supply = token_amount_to_ui_amount(mint.supply, mint.decimals);
// Filter on Mint address
RpcFilterType::Memcmp(Memcmp {
offset: 0,
bytes: MemcmpEncodedBytes::Binary(mint.to_string()),
encoding: None,
}),
// Filter on Token Account state
RpcFilterType::DataSize(size_of::<TokenAccount>() as u64),
];
let supply = get_filtered_program_accounts(&bank, &mint_owner, filters)
.map(|(_pubkey, account)| {
let mut data = account.data.to_vec();
spl_token_v1_0::state::unpack(&mut data)
.map(|account: &mut TokenAccount| account.amount)
.unwrap_or(0)
})
.sum();
let supply = token_amount_to_ui_amount(supply, decimals);
Ok(new_response(&bank, supply)) Ok(new_response(&bank, supply))
} }
@ -1084,9 +1072,9 @@ 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_v1_0() { if mint_owner != spl_token_id_v2_0() {
return Err(Error::invalid_params( return Err(Error::invalid_params(
"Invalid param: not a v1.0 Token mint".to_string(), "Invalid param: not a v2.0 Token mint".to_string(),
)); ));
} }
let filters = vec![ let filters = vec![
@ -1102,9 +1090,8 @@ impl JsonRpcRequestProcessor {
let mut token_balances: Vec<RpcTokenAccountBalance> = let mut token_balances: Vec<RpcTokenAccountBalance> =
get_filtered_program_accounts(&bank, &mint_owner, filters) get_filtered_program_accounts(&bank, &mint_owner, filters)
.map(|(address, account)| { .map(|(address, account)| {
let mut data = account.data.to_vec(); let amount = TokenAccount::unpack(&account.data)
let amount = spl_token_v1_0::state::unpack(&mut data) .map(|account| account.amount)
.map(|account: &mut TokenAccount| account.amount)
.unwrap_or(0); .unwrap_or(0);
let amount = token_amount_to_ui_amount(amount, decimals); let amount = token_amount_to_ui_amount(amount, decimals);
RpcTokenAccountBalance { RpcTokenAccountBalance {
@ -1368,15 +1355,15 @@ 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_v1_0() { if mint_owner != spl_token_id_v2_0() {
return Err(Error::invalid_params( return Err(Error::invalid_params(
"Invalid param: not a v1.0 Token mint".to_string(), "Invalid param: not a v2.0 Token mint".to_string(),
)); ));
} }
Ok((mint_owner, Some(mint))) Ok((mint_owner, Some(mint)))
} }
TokenAccountsFilter::ProgramId(program_id) => { TokenAccountsFilter::ProgramId(program_id) => {
if program_id == spl_token_id_v1_0() { if program_id == spl_token_id_v2_0() {
Ok((program_id, None)) Ok((program_id, None))
} else { } else {
Err(Error::invalid_params( Err(Error::invalid_params(
@ -1390,8 +1377,8 @@ fn get_token_program_id_and_mint(
/// Analyze a mint Pubkey that may be the native_mint and get the mint-account owner (token /// Analyze a mint Pubkey that may be the native_mint and get the mint-account owner (token
/// program_id) and decimals /// program_id) and decimals
fn get_mint_owner_and_decimals(bank: &Arc<Bank>, mint: &Pubkey) -> Result<(Pubkey, u8)> { fn get_mint_owner_and_decimals(bank: &Arc<Bank>, mint: &Pubkey) -> Result<(Pubkey, u8)> {
if mint == &spl_token_v1_0_native_mint() { if mint == &spl_token_v2_0_native_mint() {
Ok((spl_token_id_v1_0(), spl_token_v1_0::native_mint::DECIMALS)) Ok((spl_token_id_v2_0(), spl_token_v2_0::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())
@ -1402,12 +1389,11 @@ fn get_mint_owner_and_decimals(bank: &Arc<Bank>, mint: &Pubkey) -> Result<(Pubke
} }
fn get_mint_decimals(data: &[u8]) -> Result<u8> { fn get_mint_decimals(data: &[u8]) -> Result<u8> {
let mut data = data.to_vec(); Mint::unpack(data)
spl_token_v1_0::state::unpack(&mut data)
.map_err(|_| { .map_err(|_| {
Error::invalid_params("Invalid param: Token mint could not be unpacked".to_string()) Error::invalid_params("Invalid param: Token mint could not be unpacked".to_string())
}) })
.map(|mint: &mut Mint| mint.decimals) .map(|mint| mint.decimals)
} }
#[rpc] #[rpc]
@ -1692,7 +1678,7 @@ pub trait RpcSol {
) -> Result<RpcStakeActivation>; ) -> Result<RpcStakeActivation>;
// SPL Token-specific RPC endpoints // SPL Token-specific RPC endpoints
// See https://github.com/solana-labs/solana-program-library/releases/tag/token-v1.0.0 for // See https://github.com/solana-labs/solana-program-library/releases/tag/token-v2.0.0 for
// program details // program details
#[rpc(meta, name = "getTokenAccountBalance")] #[rpc(meta, name = "getTokenAccountBalance")]
@ -2505,8 +2491,9 @@ pub mod tests {
vote_instruction, vote_instruction,
vote_state::{Vote, VoteInit, MAX_LOCKOUT_HISTORY}, vote_state::{Vote, VoteInit, MAX_LOCKOUT_HISTORY},
}; };
use spl_token_v1_0::{ use spl_token_v2_0::{
option::COption, solana_sdk::pubkey::Pubkey as SplTokenPubkey, state::Mint, option::COption, solana_sdk::pubkey::Pubkey as SplTokenPubkey,
state::AccountState as TokenAccountState, state::Mint,
}; };
use std::collections::HashMap; use std::collections::HashMap;
@ -4762,24 +4749,27 @@ pub mod tests {
let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&Pubkey::new_rand()); let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&Pubkey::new_rand());
let mut account_data = [0; size_of::<TokenAccount>()]; let mut account_data = [0; size_of::<TokenAccount>()];
let account: &mut TokenAccount =
spl_token_v1_0::state::unpack_unchecked(&mut account_data).unwrap();
let mint = SplTokenPubkey::new(&[2; 32]); let mint = SplTokenPubkey::new(&[2; 32]);
let owner = SplTokenPubkey::new(&[3; 32]); let owner = SplTokenPubkey::new(&[3; 32]);
let delegate = SplTokenPubkey::new(&[4; 32]); let delegate = SplTokenPubkey::new(&[4; 32]);
*account = TokenAccount { TokenAccount::unpack_unchecked_mut(&mut account_data, &mut |account: &mut TokenAccount| {
mint, *account = TokenAccount {
owner, mint,
delegate: COption::Some(delegate), owner,
amount: 420, delegate: COption::Some(delegate),
is_initialized: true, amount: 420,
is_native: false, state: TokenAccountState::Initialized,
delegated_amount: 30, is_native: COption::None,
}; delegated_amount: 30,
close_authority: COption::Some(owner),
};
Ok(())
})
.unwrap();
let token_account = Account { let token_account = Account {
lamports: 111, lamports: 111,
data: account_data.to_vec(), data: account_data.to_vec(),
owner: spl_token_id_v1_0(), owner: spl_token_id_v2_0(),
..Account::default() ..Account::default()
}; };
let token_account_pubkey = Pubkey::new_rand(); let token_account_pubkey = Pubkey::new_rand();
@ -4787,17 +4777,21 @@ pub mod tests {
// Add the mint // Add the mint
let mut mint_data = [0; size_of::<Mint>()]; let mut mint_data = [0; size_of::<Mint>()];
let mint_state: &mut Mint = Mint::unpack_unchecked_mut(&mut mint_data, &mut |mint: &mut Mint| {
spl_token_v1_0::state::unpack_unchecked(&mut mint_data).unwrap(); *mint = Mint {
*mint_state = Mint { mint_authority: COption::Some(owner),
owner: COption::Some(owner), supply: 500,
decimals: 2, decimals: 2,
is_initialized: true, is_initialized: true,
}; freeze_authority: COption::Some(owner),
};
Ok(())
})
.unwrap();
let mint_account = Account { let mint_account = Account {
lamports: 111, lamports: 111,
data: mint_data.to_vec(), data: mint_data.to_vec(),
owner: spl_token_id_v1_0(), owner: spl_token_id_v2_0(),
..Account::default() ..Account::default()
}; };
bank.store_account(&Pubkey::from_str(&mint.to_string()).unwrap(), &mint_account); bank.store_account(&Pubkey::from_str(&mint.to_string()).unwrap(), &mint_account);
@ -4826,10 +4820,7 @@ pub mod tests {
.expect("actual response deserialization"); .expect("actual response deserialization");
assert!(result.get("error").is_some()); assert!(result.get("error").is_some());
// Add another token account to ensure getTokenSupply sums all mint accounts // Test get token supply, pulls supply from mint
let other_token_account_pubkey = Pubkey::new_rand();
bank.store_account(&other_token_account_pubkey, &token_account);
let req = format!( let req = format!(
r#"{{"jsonrpc":"2.0","id":1,"method":"getTokenSupply","params":["{}"]}}"#, r#"{{"jsonrpc":"2.0","id":1,"method":"getTokenSupply","params":["{}"]}}"#,
mint, mint,
@ -4840,8 +4831,8 @@ pub mod tests {
let supply: UiTokenAmount = let supply: UiTokenAmount =
serde_json::from_value(result["result"]["value"].clone()).unwrap(); serde_json::from_value(result["result"]["value"].clone()).unwrap();
let error = f64::EPSILON; let error = f64::EPSILON;
assert!((supply.ui_amount - 2.0 * 4.2).abs() < error); assert!((supply.ui_amount - 5.0).abs() < error);
assert_eq!(supply.amount, (2 * 420).to_string()); assert_eq!(supply.amount, 500.to_string());
assert_eq!(supply.decimals, 2); assert_eq!(supply.decimals, 2);
// Test non-existent mint address // Test non-existent mint address
@ -4854,24 +4845,31 @@ pub mod tests {
.expect("actual response deserialization"); .expect("actual response deserialization");
assert!(result.get("error").is_some()); assert!(result.get("error").is_some());
// Add another token account with the same owner, delegate, and mint
let other_token_account_pubkey = Pubkey::new_rand();
bank.store_account(&other_token_account_pubkey, &token_account);
// Add another token account with the same owner and delegate but different mint // Add another token account with the same owner and delegate but different mint
let mut account_data = [0; size_of::<TokenAccount>()]; let mut account_data = [0; size_of::<TokenAccount>()];
let account: &mut TokenAccount =
spl_token_v1_0::state::unpack_unchecked(&mut account_data).unwrap();
let new_mint = SplTokenPubkey::new(&[5; 32]); let new_mint = SplTokenPubkey::new(&[5; 32]);
*account = TokenAccount { TokenAccount::unpack_unchecked_mut(&mut account_data, &mut |account: &mut TokenAccount| {
mint: new_mint, *account = TokenAccount {
owner, mint: new_mint,
delegate: COption::Some(delegate), owner,
amount: 42, delegate: COption::Some(delegate),
is_initialized: true, amount: 42,
is_native: false, state: TokenAccountState::Initialized,
delegated_amount: 30, is_native: COption::None,
}; delegated_amount: 30,
close_authority: COption::Some(owner),
};
Ok(())
})
.unwrap();
let token_account = Account { let token_account = Account {
lamports: 111, lamports: 111,
data: account_data.to_vec(), data: account_data.to_vec(),
owner: spl_token_id_v1_0(), owner: spl_token_id_v2_0(),
..Account::default() ..Account::default()
}; };
let token_with_different_mint_pubkey = Pubkey::new_rand(); let token_with_different_mint_pubkey = Pubkey::new_rand();
@ -4886,7 +4884,7 @@ pub mod tests {
"params":["{}", {{"programId": "{}"}}] "params":["{}", {{"programId": "{}"}}]
}}"#, }}"#,
owner, owner,
spl_token_id_v1_0(), spl_token_id_v2_0(),
); );
let res = io.handle_request_sync(&req, meta.clone()); let res = io.handle_request_sync(&req, meta.clone());
let result: Value = serde_json::from_str(&res.expect("actual response")) let result: Value = serde_json::from_str(&res.expect("actual response"))
@ -4904,7 +4902,7 @@ pub mod tests {
"params":["{}", {{"programId": "{}"}}, {{"encoding": "jsonParsed"}}] "params":["{}", {{"programId": "{}"}}, {{"encoding": "jsonParsed"}}]
}}"#, }}"#,
owner, owner,
spl_token_id_v1_0(), spl_token_id_v2_0(),
); );
let res = io.handle_request_sync(&req, meta.clone()); let res = io.handle_request_sync(&req, meta.clone());
let result: Value = serde_json::from_str(&res.expect("actual response")) let result: Value = serde_json::from_str(&res.expect("actual response"))
@ -4968,7 +4966,7 @@ pub mod tests {
"params":["{}", {{"programId": "{}"}}] "params":["{}", {{"programId": "{}"}}]
}}"#, }}"#,
Pubkey::new_rand(), Pubkey::new_rand(),
spl_token_id_v1_0(), spl_token_id_v2_0(),
); );
let res = io.handle_request_sync(&req, meta.clone()); let res = io.handle_request_sync(&req, meta.clone());
let result: Value = serde_json::from_str(&res.expect("actual response")) let result: Value = serde_json::from_str(&res.expect("actual response"))
@ -4986,7 +4984,7 @@ pub mod tests {
"params":["{}", {{"programId": "{}"}}] "params":["{}", {{"programId": "{}"}}]
}}"#, }}"#,
delegate, delegate,
spl_token_id_v1_0(), spl_token_id_v2_0(),
); );
let res = io.handle_request_sync(&req, meta.clone()); let res = io.handle_request_sync(&req, meta.clone());
let result: Value = serde_json::from_str(&res.expect("actual response")) let result: Value = serde_json::from_str(&res.expect("actual response"))
@ -5051,7 +5049,7 @@ pub mod tests {
"params":["{}", {{"programId": "{}"}}] "params":["{}", {{"programId": "{}"}}]
}}"#, }}"#,
Pubkey::new_rand(), Pubkey::new_rand(),
spl_token_id_v1_0(), spl_token_id_v2_0(),
); );
let res = io.handle_request_sync(&req, meta.clone()); let res = io.handle_request_sync(&req, meta.clone());
let result: Value = serde_json::from_str(&res.expect("actual response")) let result: Value = serde_json::from_str(&res.expect("actual response"))
@ -5062,17 +5060,21 @@ pub mod tests {
// Add new_mint, and another token account on new_mint with different balance // Add new_mint, and another token account on new_mint with different balance
let mut mint_data = [0; size_of::<Mint>()]; let mut mint_data = [0; size_of::<Mint>()];
let mint_state: &mut Mint = Mint::unpack_unchecked_mut(&mut mint_data, &mut |mint: &mut Mint| {
spl_token_v1_0::state::unpack_unchecked(&mut mint_data).unwrap(); *mint = Mint {
*mint_state = Mint { mint_authority: COption::Some(owner),
owner: COption::Some(owner), supply: 500,
decimals: 2, decimals: 2,
is_initialized: true, is_initialized: true,
}; freeze_authority: COption::Some(owner),
};
Ok(())
})
.unwrap();
let mint_account = Account { let mint_account = Account {
lamports: 111, lamports: 111,
data: mint_data.to_vec(), data: mint_data.to_vec(),
owner: spl_token_id_v1_0(), owner: spl_token_id_v2_0(),
..Account::default() ..Account::default()
}; };
bank.store_account( bank.store_account(
@ -5080,21 +5082,24 @@ pub mod tests {
&mint_account, &mint_account,
); );
let mut account_data = [0; size_of::<TokenAccount>()]; let mut account_data = [0; size_of::<TokenAccount>()];
let account: &mut TokenAccount = TokenAccount::unpack_unchecked_mut(&mut account_data, &mut |account: &mut TokenAccount| {
spl_token_v1_0::state::unpack_unchecked(&mut account_data).unwrap(); *account = TokenAccount {
*account = TokenAccount { mint: new_mint,
mint: new_mint, owner,
owner, delegate: COption::Some(delegate),
delegate: COption::Some(delegate), amount: 10,
amount: 10, state: TokenAccountState::Initialized,
is_initialized: true, is_native: COption::None,
is_native: false, delegated_amount: 30,
delegated_amount: 30, close_authority: COption::Some(owner),
}; };
Ok(())
})
.unwrap();
let token_account = Account { let token_account = Account {
lamports: 111, lamports: 111,
data: account_data.to_vec(), data: account_data.to_vec(),
owner: spl_token_id_v1_0(), owner: spl_token_id_v2_0(),
..Account::default() ..Account::default()
}; };
let token_with_smaller_balance = Pubkey::new_rand(); let token_with_smaller_balance = Pubkey::new_rand();
@ -5138,24 +5143,27 @@ pub mod tests {
let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&Pubkey::new_rand()); let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&Pubkey::new_rand());
let mut account_data = [0; size_of::<TokenAccount>()]; let mut account_data = [0; size_of::<TokenAccount>()];
let account: &mut TokenAccount =
spl_token_v1_0::state::unpack_unchecked(&mut account_data).unwrap();
let mint = SplTokenPubkey::new(&[2; 32]); let mint = SplTokenPubkey::new(&[2; 32]);
let owner = SplTokenPubkey::new(&[3; 32]); let owner = SplTokenPubkey::new(&[3; 32]);
let delegate = SplTokenPubkey::new(&[4; 32]); let delegate = SplTokenPubkey::new(&[4; 32]);
*account = TokenAccount { TokenAccount::unpack_unchecked_mut(&mut account_data, &mut |account: &mut TokenAccount| {
mint, *account = TokenAccount {
owner, mint,
delegate: COption::Some(delegate), owner,
amount: 420, delegate: COption::Some(delegate),
is_initialized: true, amount: 420,
is_native: false, state: TokenAccountState::Initialized,
delegated_amount: 30, is_native: COption::Some(10),
}; delegated_amount: 30,
close_authority: COption::Some(owner),
};
Ok(())
})
.unwrap();
let token_account = Account { let token_account = Account {
lamports: 111, lamports: 111,
data: account_data.to_vec(), data: account_data.to_vec(),
owner: spl_token_id_v1_0(), owner: spl_token_id_v2_0(),
..Account::default() ..Account::default()
}; };
let token_account_pubkey = Pubkey::new_rand(); let token_account_pubkey = Pubkey::new_rand();
@ -5163,17 +5171,21 @@ pub mod tests {
// Add the mint // Add the mint
let mut mint_data = [0; size_of::<Mint>()]; let mut mint_data = [0; size_of::<Mint>()];
let mint_state: &mut Mint = Mint::unpack_unchecked_mut(&mut mint_data, &mut |mint: &mut Mint| {
spl_token_v1_0::state::unpack_unchecked(&mut mint_data).unwrap(); *mint = Mint {
*mint_state = Mint { mint_authority: COption::Some(owner),
owner: COption::Some(owner), supply: 500,
decimals: 2, decimals: 2,
is_initialized: true, is_initialized: true,
}; freeze_authority: COption::Some(owner),
};
Ok(())
})
.unwrap();
let mint_account = Account { let mint_account = Account {
lamports: 111, lamports: 111,
data: mint_data.to_vec(), data: mint_data.to_vec(),
owner: spl_token_id_v1_0(), owner: spl_token_id_v2_0(),
..Account::default() ..Account::default()
}; };
bank.store_account(&Pubkey::from_str(&mint.to_string()).unwrap(), &mint_account); bank.store_account(&Pubkey::from_str(&mint.to_string()).unwrap(), &mint_account);
@ -5189,7 +5201,7 @@ pub mod tests {
result["result"]["value"]["data"], result["result"]["value"]["data"],
json!({ json!({
"program": "spl-token", "program": "spl-token",
"space": 120, "space": 176,
"parsed": { "parsed": {
"type": "account", "type": "account",
"info": { "info": {
@ -5201,13 +5213,19 @@ pub mod tests {
"amount": "420", "amount": "420",
}, },
"delegate": delegate.to_string(), "delegate": delegate.to_string(),
"isInitialized": true, "state": "initialized",
"isNative": false, "isNative": true,
"rentExemptReserve": {
"uiAmount": 0.1,
"decimals": 2,
"amount": "10",
},
"delegatedAmount": { "delegatedAmount": {
"uiAmount": 0.3, "uiAmount": 0.3,
"decimals": 2, "decimals": 2,
"amount": "30", "amount": "30",
}, },
"closeAuthority": owner.to_string(),
} }
} }
}) })
@ -5225,13 +5243,15 @@ pub mod tests {
result["result"]["value"]["data"], result["result"]["value"]["data"],
json!({ json!({
"program": "spl-token", "program": "spl-token",
"space": 40, "space": 88,
"parsed": { "parsed": {
"type": "mint", "type": "mint",
"info": { "info": {
"owner": owner.to_string(), "mintAuthority": owner.to_string(),
"decimals": 2, "decimals": 2,
"supply": "500".to_string(),
"isInitialized": true, "isInitialized": true,
"freezeAuthority": owner.to_string(),
} }
} }
}) })

View File

@ -8,7 +8,7 @@ use jsonrpc_pubsub::{
SubscriptionId, SubscriptionId,
}; };
use serde::Serialize; use serde::Serialize;
use solana_account_decoder::{parse_token::spl_token_id_v1_0, UiAccount, UiAccountEncoding}; use solana_account_decoder::{parse_token::spl_token_id_v2_0, UiAccount, UiAccountEncoding};
use solana_client::{ use solana_client::{
rpc_config::{RpcAccountInfoConfig, RpcProgramAccountsConfig}, rpc_config::{RpcAccountInfoConfig, RpcProgramAccountsConfig},
rpc_filter::RpcFilterType, rpc_filter::RpcFilterType,
@ -256,7 +256,7 @@ fn filter_account_result(
// and should notify that the account state has been reverted. // and should notify that the account state has been reverted.
if fork != last_notified_slot { if fork != last_notified_slot {
let encoding = encoding.unwrap_or(UiAccountEncoding::Binary); let encoding = encoding.unwrap_or(UiAccountEncoding::Binary);
if account.owner == spl_token_id_v1_0() && encoding == UiAccountEncoding::JsonParsed { if account.owner == spl_token_id_v2_0() && encoding == UiAccountEncoding::JsonParsed {
let bank = bank.unwrap(); // If result.is_some(), bank must also be Some let bank = bank.unwrap(); // If result.is_some(), bank must also be Some
return ( return (
Box::new(iter::once(get_parsed_token_account(bank, pubkey, account))), Box::new(iter::once(get_parsed_token_account(bank, pubkey, account))),

View File

@ -19,7 +19,7 @@ solana-sdk = { path = "../sdk", version = "1.3.6" }
solana-stake-program = { path = "../programs/stake", version = "1.3.6" } solana-stake-program = { path = "../programs/stake", version = "1.3.6" }
solana-vote-program = { path = "../programs/vote", version = "1.3.6" } solana-vote-program = { path = "../programs/vote", version = "1.3.6" }
spl-memo-v1-0 = { package = "spl-memo", version = "1.0.7", features = ["skip-no-mangle"] } spl-memo-v1-0 = { package = "spl-memo", version = "1.0.7", features = ["skip-no-mangle"] }
spl-token-v1-0 = { package = "spl-token", version = "1.0.8", features = ["skip-no-mangle"] } spl-token-v2-0 = { package = "spl-token", version = "2.0.1", features = ["skip-no-mangle"] }
serde = "1.0.112" serde = "1.0.112"
serde_derive = "1.0.103" serde_derive = "1.0.103"
serde_json = "1.0.56" serde_json = "1.0.56"

View File

@ -1,7 +1,7 @@
use crate::parse_token::parse_token; use crate::parse_token::parse_token;
use inflector::Inflector; use inflector::Inflector;
use serde_json::Value; use serde_json::Value;
use solana_account_decoder::parse_token::spl_token_id_v1_0; use solana_account_decoder::parse_token::spl_token_id_v2_0;
use solana_sdk::{instruction::CompiledInstruction, pubkey::Pubkey}; use solana_sdk::{instruction::CompiledInstruction, pubkey::Pubkey};
use std::{ use std::{
collections::HashMap, collections::HashMap,
@ -12,7 +12,7 @@ use thiserror::Error;
lazy_static! { lazy_static! {
static ref MEMO_PROGRAM_ID: Pubkey = static ref MEMO_PROGRAM_ID: Pubkey =
Pubkey::from_str(&spl_memo_v1_0::id().to_string()).unwrap(); Pubkey::from_str(&spl_memo_v1_0::id().to_string()).unwrap();
static ref TOKEN_PROGRAM_ID: Pubkey = spl_token_id_v1_0(); static ref TOKEN_PROGRAM_ID: Pubkey = spl_token_id_v2_0();
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();
m.insert(*MEMO_PROGRAM_ID, ParsableProgram::SplMemo); m.insert(*MEMO_PROGRAM_ID, ParsableProgram::SplMemo);

File diff suppressed because it is too large Load Diff