2021-03-26 20:26:06 -07:00
|
|
|
use {
|
|
|
|
crate::rpc_client::RpcClient,
|
|
|
|
solana_sdk::{
|
|
|
|
account::{Account, ReadableAccount},
|
|
|
|
account_utils::StateMut,
|
|
|
|
commitment_config::CommitmentConfig,
|
|
|
|
nonce::{
|
|
|
|
state::{Data, Versions},
|
|
|
|
State,
|
|
|
|
},
|
|
|
|
pubkey::Pubkey,
|
|
|
|
system_program,
|
2020-09-21 12:55:44 -07:00
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2020-09-21 12:26:06 -07:00
|
|
|
#[derive(Debug, thiserror::Error, PartialEq)]
|
|
|
|
pub enum Error {
|
|
|
|
#[error("invalid account owner")]
|
|
|
|
InvalidAccountOwner,
|
|
|
|
#[error("invalid account data")]
|
|
|
|
InvalidAccountData,
|
|
|
|
#[error("unexpected account data size")]
|
|
|
|
UnexpectedDataSize,
|
|
|
|
#[error("query hash does not match stored hash")]
|
|
|
|
InvalidHash,
|
|
|
|
#[error("query authority does not match account authority")]
|
|
|
|
InvalidAuthority,
|
|
|
|
#[error("invalid state for requested operation")]
|
|
|
|
InvalidStateForOperation,
|
|
|
|
#[error("client error: {0}")]
|
|
|
|
Client(String),
|
|
|
|
}
|
2020-09-21 12:55:44 -07:00
|
|
|
|
|
|
|
pub fn get_account(rpc_client: &RpcClient, nonce_pubkey: &Pubkey) -> Result<Account, Error> {
|
|
|
|
get_account_with_commitment(rpc_client, nonce_pubkey, CommitmentConfig::default())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_account_with_commitment(
|
|
|
|
rpc_client: &RpcClient,
|
|
|
|
nonce_pubkey: &Pubkey,
|
|
|
|
commitment: CommitmentConfig,
|
|
|
|
) -> Result<Account, Error> {
|
|
|
|
rpc_client
|
|
|
|
.get_account_with_commitment(nonce_pubkey, commitment)
|
|
|
|
.map_err(|e| Error::Client(format!("{}", e)))
|
|
|
|
.and_then(|result| {
|
|
|
|
result
|
|
|
|
.value
|
|
|
|
.ok_or_else(|| Error::Client(format!("AccountNotFound: pubkey={}", nonce_pubkey)))
|
|
|
|
})
|
2021-04-08 11:40:37 -07:00
|
|
|
.and_then(|a| account_identity_ok(&a).map(|()| a))
|
2020-09-21 12:55:44 -07:00
|
|
|
}
|
|
|
|
|
2021-03-09 13:06:07 -08:00
|
|
|
pub fn account_identity_ok<T: ReadableAccount>(account: &T) -> Result<(), Error> {
|
|
|
|
if account.owner() != &system_program::id() {
|
2020-09-21 12:55:44 -07:00
|
|
|
Err(Error::InvalidAccountOwner)
|
2021-03-09 13:06:07 -08:00
|
|
|
} else if account.data().is_empty() {
|
2020-09-21 12:55:44 -07:00
|
|
|
Err(Error::UnexpectedDataSize)
|
|
|
|
} else {
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-09 13:06:07 -08:00
|
|
|
pub fn state_from_account<T: ReadableAccount + StateMut<Versions>>(
|
|
|
|
account: &T,
|
|
|
|
) -> Result<State, Error> {
|
2020-09-21 12:55:44 -07:00
|
|
|
account_identity_ok(account)?;
|
|
|
|
StateMut::<Versions>::state(account)
|
|
|
|
.map_err(|_| Error::InvalidAccountData)
|
|
|
|
.map(|v| v.convert_to_current())
|
|
|
|
}
|
|
|
|
|
2021-03-09 13:06:07 -08:00
|
|
|
pub fn data_from_account<T: ReadableAccount + StateMut<Versions>>(
|
|
|
|
account: &T,
|
|
|
|
) -> Result<Data, Error> {
|
2020-09-21 12:55:44 -07:00
|
|
|
account_identity_ok(account)?;
|
|
|
|
state_from_account(account).and_then(|ref s| data_from_state(s).map(|d| d.clone()))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn data_from_state(state: &State) -> Result<&Data, Error> {
|
|
|
|
match state {
|
|
|
|
State::Uninitialized => Err(Error::InvalidStateForOperation),
|
|
|
|
State::Initialized(data) => Ok(data),
|
|
|
|
}
|
|
|
|
}
|