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
This commit is contained in:
parent
0a8523b349
commit
76be36c9ce
|
@ -403,24 +403,6 @@ dependencies = [
|
|||
"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]]
|
||||
name = "cc"
|
||||
version = "1.0.49"
|
||||
|
@ -1268,15 +1250,6 @@ dependencies = [
|
|||
"autocfg 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
|
||||
dependencies = [
|
||||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.13"
|
||||
|
@ -2119,6 +2092,28 @@ dependencies = [
|
|||
"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]]
|
||||
name = "number_prefix"
|
||||
version = "0.3.0"
|
||||
|
@ -3569,7 +3564,7 @@ dependencies = [
|
|||
"solana-rayon-threadlimit",
|
||||
"solana-runtime",
|
||||
"solana-sdk 1.4.0",
|
||||
"solana-sdk-macro-frozen-abi",
|
||||
"solana-sdk-macro-frozen-abi 1.4.0",
|
||||
"solana-stake-program",
|
||||
"solana-storage-bigtable",
|
||||
"solana-streamer",
|
||||
|
@ -3591,9 +3586,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "solana-crate-features"
|
||||
version = "1.2.17"
|
||||
version = "1.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "610ba71932d0bf4abf88eabb081ee43fa1ee6bb5137c4fa6776ea9dd8630ca5c"
|
||||
checksum = "3e93b888ccc34b2c7a7fa3e1c804ce5f1a4b521d09b8779de3a80e70e3be2f82"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes 0.4.12",
|
||||
|
@ -3934,9 +3929,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "solana-logger"
|
||||
version = "1.2.17"
|
||||
version = "1.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc703cb2807e9d713f70df32ac8c3a7a9c8af437dd0d468b1b77cfd8e8b4cbc8"
|
||||
checksum = "7c8d27af0c30536bf91abbf40db5133e905bfd61ed24b8096c6e0a5cfb92c1e6"
|
||||
dependencies = [
|
||||
"env_logger",
|
||||
"lazy_static",
|
||||
|
@ -4172,7 +4167,7 @@ dependencies = [
|
|||
"solana-noop-program",
|
||||
"solana-rayon-threadlimit",
|
||||
"solana-sdk 1.4.0",
|
||||
"solana-sdk-macro-frozen-abi",
|
||||
"solana-sdk-macro-frozen-abi 1.4.0",
|
||||
"solana-stake-program",
|
||||
"solana-vote-program",
|
||||
"symlink",
|
||||
|
@ -4192,9 +4187,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "solana-sdk"
|
||||
version = "1.2.17"
|
||||
version = "1.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a556c1b456609b760ff47b933912f27563ea8a9a1692864cbc1014c02f5b981e"
|
||||
checksum = "15ca11bc0623ec67bb2dfbf5eff025c67c099f0ac808e192a12210a317417b9b"
|
||||
dependencies = [
|
||||
"assert_matches",
|
||||
"bincode",
|
||||
|
@ -4202,6 +4197,7 @@ dependencies = [
|
|||
"bv",
|
||||
"byteorder",
|
||||
"chrono",
|
||||
"curve25519-dalek",
|
||||
"ed25519-dalek",
|
||||
"generic-array 0.14.3",
|
||||
"hex",
|
||||
|
@ -4221,9 +4217,10 @@ dependencies = [
|
|||
"serde_derive",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
"solana-crate-features 1.2.17",
|
||||
"solana-logger 1.2.17",
|
||||
"solana-sdk-macro 1.2.17",
|
||||
"solana-crate-features 1.3.4",
|
||||
"solana-logger 1.3.4",
|
||||
"solana-sdk-macro 1.3.4",
|
||||
"solana-sdk-macro-frozen-abi 1.3.4",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
|
@ -4260,16 +4257,16 @@ dependencies = [
|
|||
"solana-crate-features 1.4.0",
|
||||
"solana-logger 1.4.0",
|
||||
"solana-sdk-macro 1.4.0",
|
||||
"solana-sdk-macro-frozen-abi",
|
||||
"solana-sdk-macro-frozen-abi 1.4.0",
|
||||
"thiserror",
|
||||
"tiny-bip39",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "solana-sdk-macro"
|
||||
version = "1.2.17"
|
||||
version = "1.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38bc386020de692562a29c0696a71c14a3d94455a9a785a97c7b254c38d6a2c8"
|
||||
checksum = "d5ef3b2acbb22a28edc32e36ed5d3b0c902007befe51f28f46c3e78a825acf71"
|
||||
dependencies = [
|
||||
"bs58",
|
||||
"proc-macro2 1.0.19",
|
||||
|
@ -4289,6 +4286,19 @@ dependencies = [
|
|||
"syn 1.0.27",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "solana-sdk-macro-frozen-abi"
|
||||
version = "1.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6cd736a8433b19b8bdf420689219db3403a1f2959f0f8baae57462ddc2fe6911"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"proc-macro2 1.0.19",
|
||||
"quote 1.0.6",
|
||||
"rustc_version",
|
||||
"syn 1.0.27",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "solana-sdk-macro-frozen-abi"
|
||||
version = "1.4.0"
|
||||
|
@ -4373,7 +4383,7 @@ dependencies = [
|
|||
"solana-logger 1.4.0",
|
||||
"solana-metrics",
|
||||
"solana-sdk 1.4.0",
|
||||
"solana-sdk-macro-frozen-abi",
|
||||
"solana-sdk-macro-frozen-abi 1.4.0",
|
||||
"solana-vote-program",
|
||||
"thiserror",
|
||||
]
|
||||
|
@ -4531,7 +4541,7 @@ dependencies = [
|
|||
"serde_derive",
|
||||
"solana-logger 1.4.0",
|
||||
"solana-sdk 1.4.0",
|
||||
"solana-sdk-macro-frozen-abi",
|
||||
"solana-sdk-macro-frozen-abi 1.4.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4564,7 +4574,7 @@ dependencies = [
|
|||
"solana-logger 1.4.0",
|
||||
"solana-metrics",
|
||||
"solana-sdk 1.4.0",
|
||||
"solana-sdk-macro-frozen-abi",
|
||||
"solana-sdk-macro-frozen-abi 1.4.0",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
|
@ -4634,20 +4644,21 @@ version = "1.0.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b303bab17e0c696de6d7550ba6f05a5a6dbf5c5d1597e68a4592899072e1c07a"
|
||||
dependencies = [
|
||||
"solana-sdk 1.2.17",
|
||||
"solana-sdk 1.3.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spl-token"
|
||||
version = "1.0.8"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e8bee8b59279b46d0627490b544c3bc38e440ff4da9851a34a26ab0a24bfe7d"
|
||||
checksum = "89ee48031d5b189a9da7295076ba07bf0ccd407e0fee1279281fb2c3258fa9fb"
|
||||
dependencies = [
|
||||
"cbindgen",
|
||||
"arrayref",
|
||||
"num-derive 0.3.0",
|
||||
"num-traits",
|
||||
"num_enum",
|
||||
"remove_dir_all",
|
||||
"solana-sdk 1.2.17",
|
||||
"solana-sdk 1.3.4",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
|
@ -5676,12 +5687,6 @@ dependencies = [
|
|||
"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]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.7"
|
||||
|
|
|
@ -19,7 +19,7 @@ solana-config-program = { path = "../programs/config", version = "1.4.0" }
|
|||
solana-sdk = { path = "../sdk", version = "1.4.0" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.4.0" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.4.0" }
|
||||
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_derive = "1.0.103"
|
||||
serde_json = "1.0.56"
|
||||
|
|
|
@ -3,7 +3,7 @@ use crate::{
|
|||
parse_nonce::parse_nonce,
|
||||
parse_stake::parse_stake,
|
||||
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,
|
||||
};
|
||||
use inflector::Inflector;
|
||||
|
@ -17,7 +17,7 @@ lazy_static! {
|
|||
static ref STAKE_PROGRAM_ID: Pubkey = solana_stake_program::id();
|
||||
static ref SYSTEM_PROGRAM_ID: Pubkey = system_program::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();
|
||||
pub static ref PARSABLE_PROGRAM_IDS: HashMap<Pubkey, ParsableAccount> = {
|
||||
let mut m = HashMap::new();
|
||||
|
|
|
@ -3,32 +3,32 @@ use crate::{
|
|||
StringAmount,
|
||||
};
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use spl_token_v1_0::{
|
||||
use spl_token_v2_0::{
|
||||
option::COption,
|
||||
pack::Pack,
|
||||
solana_sdk::pubkey::Pubkey as SplTokenPubkey,
|
||||
state::{unpack, Account, Mint, Multisig},
|
||||
state::{Account, AccountState, Mint, Multisig},
|
||||
};
|
||||
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
|
||||
pub fn spl_token_id_v1_0() -> Pubkey {
|
||||
Pubkey::from_str(&spl_token_v1_0::id().to_string()).unwrap()
|
||||
pub fn spl_token_id_v2_0() -> Pubkey {
|
||||
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
|
||||
pub fn spl_token_v1_0_native_mint() -> Pubkey {
|
||||
Pubkey::from_str(&spl_token_v1_0::native_mint::id().to_string()).unwrap()
|
||||
pub fn spl_token_v2_0_native_mint() -> Pubkey {
|
||||
Pubkey::from_str(&spl_token_v2_0::native_mint::id().to_string()).unwrap()
|
||||
}
|
||||
|
||||
pub fn parse_token(
|
||||
data: &[u8],
|
||||
mint_decimals: Option<u8>,
|
||||
) -> Result<TokenAccountType, ParseAccountError> {
|
||||
let mut data = data.to_vec();
|
||||
if data.len() == size_of::<Account>() {
|
||||
let account: Account = *unpack(&mut data)
|
||||
let account = Account::unpack(data)
|
||||
.map_err(|_| ParseAccountError::AccountNotParsable(ParsableAccount::SplToken))?;
|
||||
let decimals = mint_decimals.ok_or_else(|| {
|
||||
ParseAccountError::AdditionalDataMissing(
|
||||
|
@ -43,8 +43,12 @@ pub fn parse_token(
|
|||
COption::Some(pubkey) => Some(pubkey.to_string()),
|
||||
COption::None => None,
|
||||
},
|
||||
is_initialized: account.is_initialized,
|
||||
is_native: account.is_native,
|
||||
state: account.state.into(),
|
||||
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() {
|
||||
None
|
||||
} else {
|
||||
|
@ -53,20 +57,29 @@ pub fn parse_token(
|
|||
decimals,
|
||||
))
|
||||
},
|
||||
}))
|
||||
} 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 {
|
||||
close_authority: match account.close_authority {
|
||||
COption::Some(pubkey) => Some(pubkey.to_string()),
|
||||
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,
|
||||
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>() {
|
||||
let multisig: Multisig = *unpack(&mut data)
|
||||
let multisig = Multisig::unpack(data)
|
||||
.map_err(|_| ParseAccountError::AccountNotParsable(ParsableAccount::SplToken))?;
|
||||
Ok(TokenAccountType::Multisig(UiMultisig {
|
||||
num_required_signers: multisig.m,
|
||||
|
@ -107,10 +120,32 @@ pub struct UiTokenAccount {
|
|||
pub token_amount: UiTokenAmount,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub delegate: Option<String>,
|
||||
pub is_initialized: bool,
|
||||
pub state: UiAccountState,
|
||||
pub is_native: bool,
|
||||
#[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>,
|
||||
#[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)]
|
||||
|
@ -134,9 +169,11 @@ pub fn token_amount_to_ui_amount(amount: u64, decimals: u8) -> UiTokenAmount {
|
|||
#[derive(Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct UiMint {
|
||||
pub owner: Option<String>,
|
||||
pub mint_authority: Option<String>,
|
||||
pub supply: StringAmount,
|
||||
pub decimals: u8,
|
||||
pub is_initialized: bool,
|
||||
pub freeze_authority: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq)]
|
||||
|
@ -159,18 +196,23 @@ pub fn get_token_account_mint(data: &[u8]) -> Option<Pubkey> {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use spl_token_v1_0::state::unpack_unchecked;
|
||||
|
||||
#[test]
|
||||
fn test_parse_token() {
|
||||
let mint_pubkey = SplTokenPubkey::new(&[2; 32]);
|
||||
let owner_pubkey = SplTokenPubkey::new(&[3; 32]);
|
||||
let mut account_data = [0; size_of::<Account>()];
|
||||
let mut account: &mut Account = unpack_unchecked(&mut account_data).unwrap();
|
||||
account.mint = mint_pubkey;
|
||||
account.owner = owner_pubkey;
|
||||
account.amount = 42;
|
||||
account.is_initialized = true;
|
||||
Account::unpack_unchecked_mut(&mut account_data, &mut |account: &mut Account| {
|
||||
account.mint = mint_pubkey;
|
||||
account.owner = owner_pubkey;
|
||||
account.amount = 42;
|
||||
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_eq!(
|
||||
parse_token(&account_data, Some(2)).unwrap(),
|
||||
|
@ -183,23 +225,33 @@ mod test {
|
|||
amount: "42".to_string()
|
||||
},
|
||||
delegate: None,
|
||||
is_initialized: true,
|
||||
state: UiAccountState::Initialized,
|
||||
is_native: false,
|
||||
rent_exempt_reserve: None,
|
||||
delegated_amount: None,
|
||||
close_authority: Some(owner_pubkey.to_string()),
|
||||
}),
|
||||
);
|
||||
|
||||
let mut mint_data = [0; size_of::<Mint>()];
|
||||
let mut mint: &mut Mint = unpack_unchecked(&mut mint_data).unwrap();
|
||||
mint.owner = COption::Some(owner_pubkey);
|
||||
mint.decimals = 3;
|
||||
mint.is_initialized = true;
|
||||
Mint::unpack_unchecked_mut(&mut mint_data, &mut |mint: &mut Mint| {
|
||||
mint.mint_authority = COption::Some(owner_pubkey);
|
||||
mint.supply = 42;
|
||||
mint.decimals = 3;
|
||||
mint.is_initialized = true;
|
||||
mint.freeze_authority = COption::Some(owner_pubkey);
|
||||
Ok(())
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
parse_token(&mint_data, None).unwrap(),
|
||||
TokenAccountType::Mint(UiMint {
|
||||
owner: Some(owner_pubkey.to_string()),
|
||||
mint_authority: Some(owner_pubkey.to_string()),
|
||||
supply: 42.to_string(),
|
||||
decimals: 3,
|
||||
is_initialized: true,
|
||||
freeze_authority: Some(owner_pubkey.to_string()),
|
||||
}),
|
||||
);
|
||||
|
||||
|
@ -207,15 +259,18 @@ mod test {
|
|||
let signer2 = SplTokenPubkey::new(&[2; 32]);
|
||||
let signer3 = SplTokenPubkey::new(&[3; 32]);
|
||||
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];
|
||||
signers[0] = signer1;
|
||||
signers[1] = signer2;
|
||||
signers[2] = signer3;
|
||||
multisig.m = 2;
|
||||
multisig.n = 3;
|
||||
multisig.is_initialized = true;
|
||||
multisig.signers = signers;
|
||||
Multisig::unpack_unchecked_mut(&mut multisig_data, &mut |multisig: &mut Multisig| {
|
||||
multisig.m = 2;
|
||||
multisig.n = 3;
|
||||
multisig.is_initialized = true;
|
||||
multisig.signers = signers;
|
||||
Ok(())
|
||||
})
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
parse_token(&multisig_data, None).unwrap(),
|
||||
TokenAccountType::Multisig(UiMultisig {
|
||||
|
@ -238,8 +293,11 @@ mod test {
|
|||
fn test_get_token_account_mint() {
|
||||
let mint_pubkey = SplTokenPubkey::new(&[2; 32]);
|
||||
let mut account_data = [0; size_of::<Account>()];
|
||||
let mut account: &mut Account = unpack_unchecked(&mut account_data).unwrap();
|
||||
account.mint = mint_pubkey;
|
||||
Account::unpack_unchecked_mut(&mut account_data, &mut |account: &mut Account| {
|
||||
account.mint = mint_pubkey;
|
||||
Ok(())
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let expected_mint_pubkey = Pubkey::new(&[2; 32]);
|
||||
assert_eq!(
|
||||
|
|
|
@ -67,7 +67,7 @@ solana-transaction-status = { path = "../transaction-status", version = "1.4.0"
|
|||
solana-version = { path = "../version", version = "1.4.0" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.4.0" }
|
||||
solana-vote-signer = { path = "../vote-signer", version = "1.4.0" }
|
||||
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"
|
||||
thiserror = "1.0"
|
||||
tokio = { version = "0.2.22", features = ["full"] }
|
||||
|
|
294
core/src/rpc.rs
294
core/src/rpc.rs
|
@ -11,7 +11,7 @@ use jsonrpc_derive::rpc;
|
|||
use solana_account_decoder::{
|
||||
parse_account_data::AccountAdditionalData,
|
||||
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,
|
||||
},
|
||||
UiAccount, UiAccountEncoding,
|
||||
|
@ -58,7 +58,10 @@ use solana_transaction_status::{
|
|||
ConfirmedBlock, ConfirmedTransaction, TransactionStatus, UiTransactionEncoding,
|
||||
};
|
||||
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::{
|
||||
cmp::{max, min},
|
||||
collections::{HashMap, HashSet},
|
||||
|
@ -242,7 +245,7 @@ impl JsonRpcRequestProcessor {
|
|||
check_slice_and_encoding(&encoding, config.data_slice.is_some())?;
|
||||
let mut response = None;
|
||||
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));
|
||||
} else if (encoding == UiAccountEncoding::Binary
|
||||
|| encoding == UiAccountEncoding::Base58)
|
||||
|
@ -290,7 +293,7 @@ impl JsonRpcRequestProcessor {
|
|||
check_slice_and_encoding(&encoding, data_slice_config.is_some())?;
|
||||
let keyed_accounts = get_filtered_program_accounts(&bank, program_id, filters);
|
||||
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()
|
||||
} else {
|
||||
keyed_accounts
|
||||
|
@ -1020,16 +1023,14 @@ impl JsonRpcRequestProcessor {
|
|||
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(
|
||||
"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 =
|
||||
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 token_account = TokenAccount::unpack(&account.data).map_err(|_| {
|
||||
Error::invalid_params("Invalid param: not a v2.0 Token account".to_string())
|
||||
})?;
|
||||
let mint = &Pubkey::from_str(&token_account.mint.to_string())
|
||||
.expect("Token account mint should be convertible to Pubkey");
|
||||
let (_, decimals) = get_mint_owner_and_decimals(&bank, &mint)?;
|
||||
|
@ -1043,32 +1044,19 @@ impl JsonRpcRequestProcessor {
|
|||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<RpcResponse<UiTokenAmount>> {
|
||||
let bank = self.bank(commitment);
|
||||
let (mint_owner, decimals) = get_mint_owner_and_decimals(&bank, mint)?;
|
||||
if mint_owner != spl_token_id_v1_0() {
|
||||
let mint_account = bank.get_account(mint).ok_or_else(|| {
|
||||
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(
|
||||
"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![
|
||||
// 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);
|
||||
let supply = token_amount_to_ui_amount(mint.supply, mint.decimals);
|
||||
Ok(new_response(&bank, supply))
|
||||
}
|
||||
|
||||
|
@ -1079,9 +1067,9 @@ impl JsonRpcRequestProcessor {
|
|||
) -> Result<RpcResponse<Vec<RpcTokenAccountBalance>>> {
|
||||
let bank = self.bank(commitment);
|
||||
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(
|
||||
"Invalid param: not a v1.0 Token mint".to_string(),
|
||||
"Invalid param: not a v2.0 Token mint".to_string(),
|
||||
));
|
||||
}
|
||||
let filters = vec![
|
||||
|
@ -1097,9 +1085,8 @@ impl JsonRpcRequestProcessor {
|
|||
let mut token_balances: Vec<RpcTokenAccountBalance> =
|
||||
get_filtered_program_accounts(&bank, &mint_owner, filters)
|
||||
.map(|(address, account)| {
|
||||
let mut data = account.data.to_vec();
|
||||
let amount = spl_token_v1_0::state::unpack(&mut data)
|
||||
.map(|account: &mut TokenAccount| account.amount)
|
||||
let amount = TokenAccount::unpack(&account.data)
|
||||
.map(|account| account.amount)
|
||||
.unwrap_or(0);
|
||||
let amount = token_amount_to_ui_amount(amount, decimals);
|
||||
RpcTokenAccountBalance {
|
||||
|
@ -1363,15 +1350,15 @@ fn get_token_program_id_and_mint(
|
|||
match token_account_filter {
|
||||
TokenAccountsFilter::Mint(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(
|
||||
"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)))
|
||||
}
|
||||
TokenAccountsFilter::ProgramId(program_id) => {
|
||||
if program_id == spl_token_id_v1_0() {
|
||||
if program_id == spl_token_id_v2_0() {
|
||||
Ok((program_id, None))
|
||||
} else {
|
||||
Err(Error::invalid_params(
|
||||
|
@ -1385,8 +1372,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
|
||||
/// program_id) and decimals
|
||||
fn get_mint_owner_and_decimals(bank: &Arc<Bank>, mint: &Pubkey) -> Result<(Pubkey, u8)> {
|
||||
if mint == &spl_token_v1_0_native_mint() {
|
||||
Ok((spl_token_id_v1_0(), spl_token_v1_0::native_mint::DECIMALS))
|
||||
if mint == &spl_token_v2_0_native_mint() {
|
||||
Ok((spl_token_id_v2_0(), spl_token_v2_0::native_mint::DECIMALS))
|
||||
} else {
|
||||
let mint_account = bank.get_account(mint).ok_or_else(|| {
|
||||
Error::invalid_params("Invalid param: could not find mint".to_string())
|
||||
|
@ -1397,12 +1384,11 @@ fn get_mint_owner_and_decimals(bank: &Arc<Bank>, mint: &Pubkey) -> Result<(Pubke
|
|||
}
|
||||
|
||||
fn get_mint_decimals(data: &[u8]) -> Result<u8> {
|
||||
let mut data = data.to_vec();
|
||||
spl_token_v1_0::state::unpack(&mut data)
|
||||
Mint::unpack(data)
|
||||
.map_err(|_| {
|
||||
Error::invalid_params("Invalid param: Token mint could not be unpacked".to_string())
|
||||
})
|
||||
.map(|mint: &mut Mint| mint.decimals)
|
||||
.map(|mint| mint.decimals)
|
||||
}
|
||||
|
||||
#[rpc]
|
||||
|
@ -1687,7 +1673,7 @@ pub trait RpcSol {
|
|||
) -> Result<RpcStakeActivation>;
|
||||
|
||||
// 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
|
||||
|
||||
#[rpc(meta, name = "getTokenAccountBalance")]
|
||||
|
@ -2500,8 +2486,9 @@ pub mod tests {
|
|||
vote_instruction,
|
||||
vote_state::{Vote, VoteInit, MAX_LOCKOUT_HISTORY},
|
||||
};
|
||||
use spl_token_v1_0::{
|
||||
option::COption, solana_sdk::pubkey::Pubkey as SplTokenPubkey, state::Mint,
|
||||
use spl_token_v2_0::{
|
||||
option::COption, solana_sdk::pubkey::Pubkey as SplTokenPubkey,
|
||||
state::AccountState as TokenAccountState, state::Mint,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
|
||||
|
@ -4741,24 +4728,27 @@ pub mod tests {
|
|||
let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&Pubkey::new_rand());
|
||||
|
||||
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 owner = SplTokenPubkey::new(&[3; 32]);
|
||||
let delegate = SplTokenPubkey::new(&[4; 32]);
|
||||
*account = TokenAccount {
|
||||
mint,
|
||||
owner,
|
||||
delegate: COption::Some(delegate),
|
||||
amount: 420,
|
||||
is_initialized: true,
|
||||
is_native: false,
|
||||
delegated_amount: 30,
|
||||
};
|
||||
TokenAccount::unpack_unchecked_mut(&mut account_data, &mut |account: &mut TokenAccount| {
|
||||
*account = TokenAccount {
|
||||
mint,
|
||||
owner,
|
||||
delegate: COption::Some(delegate),
|
||||
amount: 420,
|
||||
state: TokenAccountState::Initialized,
|
||||
is_native: COption::None,
|
||||
delegated_amount: 30,
|
||||
close_authority: COption::Some(owner),
|
||||
};
|
||||
Ok(())
|
||||
})
|
||||
.unwrap();
|
||||
let token_account = Account {
|
||||
lamports: 111,
|
||||
data: account_data.to_vec(),
|
||||
owner: spl_token_id_v1_0(),
|
||||
owner: spl_token_id_v2_0(),
|
||||
..Account::default()
|
||||
};
|
||||
let token_account_pubkey = Pubkey::new_rand();
|
||||
|
@ -4766,17 +4756,21 @@ pub mod tests {
|
|||
|
||||
// Add the mint
|
||||
let mut mint_data = [0; size_of::<Mint>()];
|
||||
let mint_state: &mut Mint =
|
||||
spl_token_v1_0::state::unpack_unchecked(&mut mint_data).unwrap();
|
||||
*mint_state = Mint {
|
||||
owner: COption::Some(owner),
|
||||
decimals: 2,
|
||||
is_initialized: true,
|
||||
};
|
||||
Mint::unpack_unchecked_mut(&mut mint_data, &mut |mint: &mut Mint| {
|
||||
*mint = Mint {
|
||||
mint_authority: COption::Some(owner),
|
||||
supply: 500,
|
||||
decimals: 2,
|
||||
is_initialized: true,
|
||||
freeze_authority: COption::Some(owner),
|
||||
};
|
||||
Ok(())
|
||||
})
|
||||
.unwrap();
|
||||
let mint_account = Account {
|
||||
lamports: 111,
|
||||
data: mint_data.to_vec(),
|
||||
owner: spl_token_id_v1_0(),
|
||||
owner: spl_token_id_v2_0(),
|
||||
..Account::default()
|
||||
};
|
||||
bank.store_account(&Pubkey::from_str(&mint.to_string()).unwrap(), &mint_account);
|
||||
|
@ -4805,10 +4799,7 @@ pub mod tests {
|
|||
.expect("actual response deserialization");
|
||||
assert!(result.get("error").is_some());
|
||||
|
||||
// Add another token account to ensure getTokenSupply sums all mint accounts
|
||||
let other_token_account_pubkey = Pubkey::new_rand();
|
||||
bank.store_account(&other_token_account_pubkey, &token_account);
|
||||
|
||||
// Test get token supply, pulls supply from mint
|
||||
let req = format!(
|
||||
r#"{{"jsonrpc":"2.0","id":1,"method":"getTokenSupply","params":["{}"]}}"#,
|
||||
mint,
|
||||
|
@ -4819,8 +4810,8 @@ pub mod tests {
|
|||
let supply: UiTokenAmount =
|
||||
serde_json::from_value(result["result"]["value"].clone()).unwrap();
|
||||
let error = f64::EPSILON;
|
||||
assert!((supply.ui_amount - 2.0 * 4.2).abs() < error);
|
||||
assert_eq!(supply.amount, (2 * 420).to_string());
|
||||
assert!((supply.ui_amount - 5.0).abs() < error);
|
||||
assert_eq!(supply.amount, 500.to_string());
|
||||
assert_eq!(supply.decimals, 2);
|
||||
|
||||
// Test non-existent mint address
|
||||
|
@ -4833,24 +4824,31 @@ pub mod tests {
|
|||
.expect("actual response deserialization");
|
||||
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
|
||||
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]);
|
||||
*account = TokenAccount {
|
||||
mint: new_mint,
|
||||
owner,
|
||||
delegate: COption::Some(delegate),
|
||||
amount: 42,
|
||||
is_initialized: true,
|
||||
is_native: false,
|
||||
delegated_amount: 30,
|
||||
};
|
||||
TokenAccount::unpack_unchecked_mut(&mut account_data, &mut |account: &mut TokenAccount| {
|
||||
*account = TokenAccount {
|
||||
mint: new_mint,
|
||||
owner,
|
||||
delegate: COption::Some(delegate),
|
||||
amount: 42,
|
||||
state: TokenAccountState::Initialized,
|
||||
is_native: COption::None,
|
||||
delegated_amount: 30,
|
||||
close_authority: COption::Some(owner),
|
||||
};
|
||||
Ok(())
|
||||
})
|
||||
.unwrap();
|
||||
let token_account = Account {
|
||||
lamports: 111,
|
||||
data: account_data.to_vec(),
|
||||
owner: spl_token_id_v1_0(),
|
||||
owner: spl_token_id_v2_0(),
|
||||
..Account::default()
|
||||
};
|
||||
let token_with_different_mint_pubkey = Pubkey::new_rand();
|
||||
|
@ -4865,7 +4863,7 @@ pub mod tests {
|
|||
"params":["{}", {{"programId": "{}"}}]
|
||||
}}"#,
|
||||
owner,
|
||||
spl_token_id_v1_0(),
|
||||
spl_token_id_v2_0(),
|
||||
);
|
||||
let res = io.handle_request_sync(&req, meta.clone());
|
||||
let result: Value = serde_json::from_str(&res.expect("actual response"))
|
||||
|
@ -4883,7 +4881,7 @@ pub mod tests {
|
|||
"params":["{}", {{"programId": "{}"}}, {{"encoding": "jsonParsed"}}]
|
||||
}}"#,
|
||||
owner,
|
||||
spl_token_id_v1_0(),
|
||||
spl_token_id_v2_0(),
|
||||
);
|
||||
let res = io.handle_request_sync(&req, meta.clone());
|
||||
let result: Value = serde_json::from_str(&res.expect("actual response"))
|
||||
|
@ -4947,7 +4945,7 @@ pub mod tests {
|
|||
"params":["{}", {{"programId": "{}"}}]
|
||||
}}"#,
|
||||
Pubkey::new_rand(),
|
||||
spl_token_id_v1_0(),
|
||||
spl_token_id_v2_0(),
|
||||
);
|
||||
let res = io.handle_request_sync(&req, meta.clone());
|
||||
let result: Value = serde_json::from_str(&res.expect("actual response"))
|
||||
|
@ -4965,7 +4963,7 @@ pub mod tests {
|
|||
"params":["{}", {{"programId": "{}"}}]
|
||||
}}"#,
|
||||
delegate,
|
||||
spl_token_id_v1_0(),
|
||||
spl_token_id_v2_0(),
|
||||
);
|
||||
let res = io.handle_request_sync(&req, meta.clone());
|
||||
let result: Value = serde_json::from_str(&res.expect("actual response"))
|
||||
|
@ -5030,7 +5028,7 @@ pub mod tests {
|
|||
"params":["{}", {{"programId": "{}"}}]
|
||||
}}"#,
|
||||
Pubkey::new_rand(),
|
||||
spl_token_id_v1_0(),
|
||||
spl_token_id_v2_0(),
|
||||
);
|
||||
let res = io.handle_request_sync(&req, meta.clone());
|
||||
let result: Value = serde_json::from_str(&res.expect("actual response"))
|
||||
|
@ -5041,17 +5039,21 @@ pub mod tests {
|
|||
|
||||
// Add new_mint, and another token account on new_mint with different balance
|
||||
let mut mint_data = [0; size_of::<Mint>()];
|
||||
let mint_state: &mut Mint =
|
||||
spl_token_v1_0::state::unpack_unchecked(&mut mint_data).unwrap();
|
||||
*mint_state = Mint {
|
||||
owner: COption::Some(owner),
|
||||
decimals: 2,
|
||||
is_initialized: true,
|
||||
};
|
||||
Mint::unpack_unchecked_mut(&mut mint_data, &mut |mint: &mut Mint| {
|
||||
*mint = Mint {
|
||||
mint_authority: COption::Some(owner),
|
||||
supply: 500,
|
||||
decimals: 2,
|
||||
is_initialized: true,
|
||||
freeze_authority: COption::Some(owner),
|
||||
};
|
||||
Ok(())
|
||||
})
|
||||
.unwrap();
|
||||
let mint_account = Account {
|
||||
lamports: 111,
|
||||
data: mint_data.to_vec(),
|
||||
owner: spl_token_id_v1_0(),
|
||||
owner: spl_token_id_v2_0(),
|
||||
..Account::default()
|
||||
};
|
||||
bank.store_account(
|
||||
|
@ -5059,21 +5061,24 @@ pub mod tests {
|
|||
&mint_account,
|
||||
);
|
||||
let mut account_data = [0; size_of::<TokenAccount>()];
|
||||
let account: &mut TokenAccount =
|
||||
spl_token_v1_0::state::unpack_unchecked(&mut account_data).unwrap();
|
||||
*account = TokenAccount {
|
||||
mint: new_mint,
|
||||
owner,
|
||||
delegate: COption::Some(delegate),
|
||||
amount: 10,
|
||||
is_initialized: true,
|
||||
is_native: false,
|
||||
delegated_amount: 30,
|
||||
};
|
||||
TokenAccount::unpack_unchecked_mut(&mut account_data, &mut |account: &mut TokenAccount| {
|
||||
*account = TokenAccount {
|
||||
mint: new_mint,
|
||||
owner,
|
||||
delegate: COption::Some(delegate),
|
||||
amount: 10,
|
||||
state: TokenAccountState::Initialized,
|
||||
is_native: COption::None,
|
||||
delegated_amount: 30,
|
||||
close_authority: COption::Some(owner),
|
||||
};
|
||||
Ok(())
|
||||
})
|
||||
.unwrap();
|
||||
let token_account = Account {
|
||||
lamports: 111,
|
||||
data: account_data.to_vec(),
|
||||
owner: spl_token_id_v1_0(),
|
||||
owner: spl_token_id_v2_0(),
|
||||
..Account::default()
|
||||
};
|
||||
let token_with_smaller_balance = Pubkey::new_rand();
|
||||
|
@ -5117,24 +5122,27 @@ pub mod tests {
|
|||
let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&Pubkey::new_rand());
|
||||
|
||||
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 owner = SplTokenPubkey::new(&[3; 32]);
|
||||
let delegate = SplTokenPubkey::new(&[4; 32]);
|
||||
*account = TokenAccount {
|
||||
mint,
|
||||
owner,
|
||||
delegate: COption::Some(delegate),
|
||||
amount: 420,
|
||||
is_initialized: true,
|
||||
is_native: false,
|
||||
delegated_amount: 30,
|
||||
};
|
||||
TokenAccount::unpack_unchecked_mut(&mut account_data, &mut |account: &mut TokenAccount| {
|
||||
*account = TokenAccount {
|
||||
mint,
|
||||
owner,
|
||||
delegate: COption::Some(delegate),
|
||||
amount: 420,
|
||||
state: TokenAccountState::Initialized,
|
||||
is_native: COption::Some(10),
|
||||
delegated_amount: 30,
|
||||
close_authority: COption::Some(owner),
|
||||
};
|
||||
Ok(())
|
||||
})
|
||||
.unwrap();
|
||||
let token_account = Account {
|
||||
lamports: 111,
|
||||
data: account_data.to_vec(),
|
||||
owner: spl_token_id_v1_0(),
|
||||
owner: spl_token_id_v2_0(),
|
||||
..Account::default()
|
||||
};
|
||||
let token_account_pubkey = Pubkey::new_rand();
|
||||
|
@ -5142,17 +5150,21 @@ pub mod tests {
|
|||
|
||||
// Add the mint
|
||||
let mut mint_data = [0; size_of::<Mint>()];
|
||||
let mint_state: &mut Mint =
|
||||
spl_token_v1_0::state::unpack_unchecked(&mut mint_data).unwrap();
|
||||
*mint_state = Mint {
|
||||
owner: COption::Some(owner),
|
||||
decimals: 2,
|
||||
is_initialized: true,
|
||||
};
|
||||
Mint::unpack_unchecked_mut(&mut mint_data, &mut |mint: &mut Mint| {
|
||||
*mint = Mint {
|
||||
mint_authority: COption::Some(owner),
|
||||
supply: 500,
|
||||
decimals: 2,
|
||||
is_initialized: true,
|
||||
freeze_authority: COption::Some(owner),
|
||||
};
|
||||
Ok(())
|
||||
})
|
||||
.unwrap();
|
||||
let mint_account = Account {
|
||||
lamports: 111,
|
||||
data: mint_data.to_vec(),
|
||||
owner: spl_token_id_v1_0(),
|
||||
owner: spl_token_id_v2_0(),
|
||||
..Account::default()
|
||||
};
|
||||
bank.store_account(&Pubkey::from_str(&mint.to_string()).unwrap(), &mint_account);
|
||||
|
@ -5168,7 +5180,7 @@ pub mod tests {
|
|||
result["result"]["value"]["data"],
|
||||
json!({
|
||||
"program": "spl-token",
|
||||
"space": 120,
|
||||
"space": 176,
|
||||
"parsed": {
|
||||
"type": "account",
|
||||
"info": {
|
||||
|
@ -5180,13 +5192,19 @@ pub mod tests {
|
|||
"amount": "420",
|
||||
},
|
||||
"delegate": delegate.to_string(),
|
||||
"isInitialized": true,
|
||||
"isNative": false,
|
||||
"state": "initialized",
|
||||
"isNative": true,
|
||||
"rentExemptReserve": {
|
||||
"uiAmount": 0.1,
|
||||
"decimals": 2,
|
||||
"amount": "10",
|
||||
},
|
||||
"delegatedAmount": {
|
||||
"uiAmount": 0.3,
|
||||
"decimals": 2,
|
||||
"amount": "30",
|
||||
},
|
||||
"closeAuthority": owner.to_string(),
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -5204,13 +5222,15 @@ pub mod tests {
|
|||
result["result"]["value"]["data"],
|
||||
json!({
|
||||
"program": "spl-token",
|
||||
"space": 40,
|
||||
"space": 88,
|
||||
"parsed": {
|
||||
"type": "mint",
|
||||
"info": {
|
||||
"owner": owner.to_string(),
|
||||
"mintAuthority": owner.to_string(),
|
||||
"decimals": 2,
|
||||
"supply": "500".to_string(),
|
||||
"isInitialized": true,
|
||||
"freezeAuthority": owner.to_string(),
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -8,7 +8,7 @@ use jsonrpc_pubsub::{
|
|||
SubscriptionId,
|
||||
};
|
||||
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::{
|
||||
rpc_config::{RpcAccountInfoConfig, RpcProgramAccountsConfig},
|
||||
rpc_filter::RpcFilterType,
|
||||
|
@ -256,7 +256,7 @@ fn filter_account_result(
|
|||
// and should notify that the account state has been reverted.
|
||||
if fork != last_notified_slot {
|
||||
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
|
||||
return (
|
||||
Box::new(iter::once(get_parsed_token_account(bank, pubkey, account))),
|
||||
|
|
|
@ -19,7 +19,7 @@ solana-sdk = { path = "../sdk", version = "1.4.0" }
|
|||
solana-stake-program = { path = "../programs/stake", version = "1.4.0" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.4.0" }
|
||||
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_derive = "1.0.103"
|
||||
serde_json = "1.0.56"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::parse_token::parse_token;
|
||||
use inflector::Inflector;
|
||||
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 std::{
|
||||
collections::HashMap,
|
||||
|
@ -12,7 +12,7 @@ use thiserror::Error;
|
|||
lazy_static! {
|
||||
static ref MEMO_PROGRAM_ID: Pubkey =
|
||||
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> = {
|
||||
let mut m = HashMap::new();
|
||||
m.insert(*MEMO_PROGRAM_ID, ParsableProgram::SplMemo);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue