gemachain_client/
nonce_utils.rs

1use {
2    crate::rpc_client::RpcClient,
3    gemachain_sdk::{
4        account::{Account, ReadableAccount},
5        account_utils::StateMut,
6        commitment_config::CommitmentConfig,
7        nonce::{
8            state::{Data, Versions},
9            State,
10        },
11        pubkey::Pubkey,
12        system_program,
13    },
14};
15
16#[derive(Debug, thiserror::Error, PartialEq)]
17pub enum Error {
18    #[error("invalid account owner")]
19    InvalidAccountOwner,
20    #[error("invalid account data")]
21    InvalidAccountData,
22    #[error("unexpected account data size")]
23    UnexpectedDataSize,
24    #[error("query hash does not match stored hash")]
25    InvalidHash,
26    #[error("query authority does not match account authority")]
27    InvalidAuthority,
28    #[error("invalid state for requested operation")]
29    InvalidStateForOperation,
30    #[error("client error: {0}")]
31    Client(String),
32}
33
34pub fn get_account(rpc_client: &RpcClient, nonce_pubkey: &Pubkey) -> Result<Account, Error> {
35    get_account_with_commitment(rpc_client, nonce_pubkey, CommitmentConfig::default())
36}
37
38pub fn get_account_with_commitment(
39    rpc_client: &RpcClient,
40    nonce_pubkey: &Pubkey,
41    commitment: CommitmentConfig,
42) -> Result<Account, Error> {
43    rpc_client
44        .get_account_with_commitment(nonce_pubkey, commitment)
45        .map_err(|e| Error::Client(format!("{}", e)))
46        .and_then(|result| {
47            result
48                .value
49                .ok_or_else(|| Error::Client(format!("AccountNotFound: pubkey={}", nonce_pubkey)))
50        })
51        .and_then(|a| account_identity_ok(&a).map(|()| a))
52}
53
54pub fn account_identity_ok<T: ReadableAccount>(account: &T) -> Result<(), Error> {
55    if account.owner() != &system_program::id() {
56        Err(Error::InvalidAccountOwner)
57    } else if account.data().is_empty() {
58        Err(Error::UnexpectedDataSize)
59    } else {
60        Ok(())
61    }
62}
63
64pub fn state_from_account<T: ReadableAccount + StateMut<Versions>>(
65    account: &T,
66) -> Result<State, Error> {
67    account_identity_ok(account)?;
68    StateMut::<Versions>::state(account)
69        .map_err(|_| Error::InvalidAccountData)
70        .map(|v| v.convert_to_current())
71}
72
73pub fn data_from_account<T: ReadableAccount + StateMut<Versions>>(
74    account: &T,
75) -> Result<Data, Error> {
76    account_identity_ok(account)?;
77    state_from_account(account).and_then(|ref s| data_from_state(s).map(|d| d.clone()))
78}
79
80pub fn data_from_state(state: &State) -> Result<&Data, Error> {
81    match state {
82        State::Uninitialized => Err(Error::InvalidStateForOperation),
83        State::Initialized(data) => Ok(data),
84    }
85}