Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract account-decoder-client-types #2872

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ split-debuginfo = "packed"
[workspace]
members = [
"account-decoder",
"account-decoder-client-types",
"accounts-bench",
"accounts-cluster-bench",
"accounts-db",
Expand Down Expand Up @@ -367,6 +368,7 @@ socket2 = "0.5.7"
soketto = "0.7"
solana-account = { path = "sdk/account", version = "=2.1.0" }
solana-account-decoder = { path = "account-decoder", version = "=2.1.0" }
solana-account-decoder-client-types = { path = "account-decoder-client-types", version = "=2.1.0" }
solana-account-info = { path = "sdk/account-info", version = "=2.1.0" }
solana-accounts-db = { path = "accounts-db", version = "=2.1.0" }
solana-address-lookup-table-program = { path = "programs/address-lookup-table", version = "=2.1.0" }
Expand Down
28 changes: 28 additions & 0 deletions account-decoder-client-types/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
[package]
name = "solana-account-decoder-client-types"
description = "Core RPC client types for solana-account-decoder"
documentation = "https://docs.rs/solana-account-decoder-client-types"
version = { workspace = true }
authors = { workspace = true }
repository = { workspace = true }
homepage = { workspace = true }
license = { workspace = true }
edition = { workspace = true }

[dependencies]
base64 = { workspace = true }
bs58 = { workspace = true }
serde = { workspace = true }
serde_derive = { workspace = true }
serde_json = { workspace = true }
solana-account = { workspace = true }
solana-pubkey = { workspace = true }
zstd = { workspace = true, optional = true }

[features]
zstd = ["dep:zstd"]

[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
all-features = true
rustdoc-args = ["--cfg=docsrs"]
Comment on lines +27 to +28

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these extra keys necessary here? I don't see them used anywhere else in the monorepo.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

they were added to the monorepo the other day: #3121

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just checked and it doesn't make a difference here. But may as well leave it in imo in case someone comes along later and does something that would benefit from it

99 changes: 99 additions & 0 deletions account-decoder-client-types/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
//! Core RPC client types for solana-account-decoder
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#[cfg(feature = "zstd")]
use std::io::Read;
use {
base64::{prelude::BASE64_STANDARD, Engine},
core::str::FromStr,
serde_derive::{Deserialize, Serialize},
serde_json::Value,
solana_account::WritableAccount,
solana_pubkey::Pubkey,
};
pub mod token;

/// A duplicate representation of an Account for pretty JSON serialization
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct UiAccount {
pub lamports: u64,
pub data: UiAccountData,
pub owner: String,
pub executable: bool,
pub rent_epoch: u64,
pub space: Option<u64>,
}

#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", untagged)]
pub enum UiAccountData {
LegacyBinary(String), // Legacy. Retained for RPC backwards compatibility
Json(ParsedAccount),
Binary(String, UiAccountEncoding),
}

impl UiAccountData {
/// Returns decoded account data in binary format if possible
pub fn decode(&self) -> Option<Vec<u8>> {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not also make this one a free function, like its encode counterpart? Then you can drop the bs_58 dependency from this crate, possibly more.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh because rpc-client still needs the decode() methods, so I could make them free functions but I'd still want them in this crate for now

match self {
UiAccountData::Json(_) => None,
UiAccountData::LegacyBinary(blob) => bs58::decode(blob).into_vec().ok(),
UiAccountData::Binary(blob, encoding) => match encoding {
UiAccountEncoding::Base58 => bs58::decode(blob).into_vec().ok(),
UiAccountEncoding::Base64 => BASE64_STANDARD.decode(blob).ok(),
#[cfg(feature = "zstd")]
UiAccountEncoding::Base64Zstd => {
BASE64_STANDARD.decode(blob).ok().and_then(|zstd_data| {
let mut data = vec![];
zstd::stream::read::Decoder::new(zstd_data.as_slice())
.and_then(|mut reader| reader.read_to_end(&mut data))
.map(|_| data)
.ok()
})
}
#[cfg(not(feature = "zstd"))]
UiAccountEncoding::Base64Zstd => None,
UiAccountEncoding::Binary | UiAccountEncoding::JsonParsed => None,
},
}
}
}

#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[serde(rename_all = "camelCase")]
pub enum UiAccountEncoding {
Binary, // Legacy. Retained for RPC backwards compatibility
Base58,
Base64,
JsonParsed,
#[serde(rename = "base64+zstd")]
Base64Zstd,
}

impl UiAccount {
pub fn decode<T: WritableAccount>(&self) -> Option<T> {
let data = self.data.decode()?;
Some(T::create(
self.lamports,
data,
Pubkey::from_str(&self.owner).ok()?,
self.executable,
self.rent_epoch,
))
}
}

#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct ParsedAccount {
pub program: String,
pub parsed: Value,
pub space: u64,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UiDataSliceConfig {
pub offset: usize,
pub length: usize,
}
Loading
Loading