gemachain_account_decoder/
parse_nonce.rs

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