solana_account_decoder_wasm/
parse_nonce.rs

1use serde::Deserialize;
2use serde::Serialize;
3use solana_instruction::error::InstructionError;
4use solana_nonce::state::State;
5use solana_nonce::versions::Versions;
6
7use crate::UiFeeCalculator;
8use crate::parse_account_data::ParseAccountError;
9
10pub fn parse_nonce(data: &[u8]) -> Result<UiNonceState, ParseAccountError> {
11	let nonce_versions: Versions = bincode::deserialize(data)
12		.map_err(|_| ParseAccountError::from(InstructionError::InvalidAccountData))?;
13	match nonce_versions.state() {
14		// This prevents parsing an allocated System-owned account with empty data of any non-zero
15		// length as `uninitialized` nonce. An empty account of the wrong length can never be
16		// initialized as a nonce account, and an empty account of the correct length may not be an
17		// uninitialized nonce account, since it can be assigned to another program.
18		State::Uninitialized => {
19			Err(ParseAccountError::from(
20				InstructionError::InvalidAccountData,
21			))
22		}
23		State::Initialized(data) => {
24			Ok(UiNonceState::Initialized(UiNonceData {
25				authority: data.authority.to_string(),
26				blockhash: data.blockhash().to_string(),
27				fee_calculator: data.fee_calculator.into(),
28			}))
29		}
30	}
31}
32
33/// A duplicate representation of `NonceState` for pretty JSON serialization
34#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
35#[serde(rename_all = "camelCase", tag = "type", content = "info")]
36pub enum UiNonceState {
37	Uninitialized,
38	Initialized(UiNonceData),
39}
40
41#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
42#[serde(rename_all = "camelCase")]
43pub struct UiNonceData {
44	pub authority: String,
45	pub blockhash: String,
46	pub fee_calculator: UiFeeCalculator,
47}
48
49#[cfg(test)]
50mod test {
51	use solana_hash::Hash;
52	use solana_nonce::state::Data;
53	use solana_nonce::state::State;
54	use solana_nonce::versions::Versions;
55	use solana_pubkey::Pubkey;
56
57	use super::*;
58
59	#[test]
60	fn test_parse_nonce() {
61		let nonce_data = Versions::new(State::Initialized(Data::default()));
62		let nonce_account_data = bincode::serialize(&nonce_data).unwrap();
63		assert_eq!(
64			parse_nonce(&nonce_account_data).unwrap(),
65			UiNonceState::Initialized(UiNonceData {
66				authority: Pubkey::default().to_string(),
67				blockhash: Hash::default().to_string(),
68				fee_calculator: UiFeeCalculator {
69					lamports_per_signature: 0.to_string(),
70				},
71			}),
72		);
73
74		let bad_data = vec![0; 4];
75		assert!(parse_nonce(&bad_data).is_err());
76	}
77}