Add Binary64 option for account data (#11474)
* Add Binary64 option for account data * Decode into binary64 * Reword docs
This commit is contained in:
parent
4d918f83ff
commit
068d23f298
|
@ -3204,6 +3204,7 @@ name = "solana-account-decoder"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"Inflector",
|
"Inflector",
|
||||||
|
"base64 0.12.3",
|
||||||
"bincode",
|
"bincode",
|
||||||
"bs58",
|
"bs58",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
|
|
@ -9,6 +9,7 @@ license = "Apache-2.0"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
base64 = "0.12.3"
|
||||||
bincode = "1.3.1"
|
bincode = "1.3.1"
|
||||||
bs58 = "0.3.1"
|
bs58 = "0.3.1"
|
||||||
Inflector = "0.11.4"
|
Inflector = "0.11.4"
|
||||||
|
|
|
@ -30,6 +30,7 @@ pub struct UiAccount {
|
||||||
pub enum UiAccountData {
|
pub enum UiAccountData {
|
||||||
Binary(String),
|
Binary(String),
|
||||||
Json(ParsedAccount),
|
Json(ParsedAccount),
|
||||||
|
Binary64(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Vec<u8>> for UiAccountData {
|
impl From<Vec<u8>> for UiAccountData {
|
||||||
|
@ -43,6 +44,7 @@ impl From<Vec<u8>> for UiAccountData {
|
||||||
pub enum UiAccountEncoding {
|
pub enum UiAccountEncoding {
|
||||||
Binary,
|
Binary,
|
||||||
JsonParsed,
|
JsonParsed,
|
||||||
|
Binary64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UiAccount {
|
impl UiAccount {
|
||||||
|
@ -53,6 +55,7 @@ impl UiAccount {
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let data = match encoding {
|
let data = match encoding {
|
||||||
UiAccountEncoding::Binary => account.data.into(),
|
UiAccountEncoding::Binary => account.data.into(),
|
||||||
|
UiAccountEncoding::Binary64 => UiAccountData::Binary64(base64::encode(account.data)),
|
||||||
UiAccountEncoding::JsonParsed => {
|
UiAccountEncoding::JsonParsed => {
|
||||||
if let Ok(parsed_data) =
|
if let Ok(parsed_data) =
|
||||||
parse_account_data(&account.owner, &account.data, additional_data)
|
parse_account_data(&account.owner, &account.data, additional_data)
|
||||||
|
@ -76,6 +79,7 @@ impl UiAccount {
|
||||||
let data = match &self.data {
|
let data = match &self.data {
|
||||||
UiAccountData::Json(_) => None,
|
UiAccountData::Json(_) => None,
|
||||||
UiAccountData::Binary(blob) => bs58::decode(blob).into_vec().ok(),
|
UiAccountData::Binary(blob) => bs58::decode(blob).into_vec().ok(),
|
||||||
|
UiAccountData::Binary64(blob) => base64::decode(blob).ok(),
|
||||||
}?;
|
}?;
|
||||||
Some(Account {
|
Some(Account {
|
||||||
lamports: self.lamports,
|
lamports: self.lamports,
|
||||||
|
|
|
@ -350,7 +350,7 @@ mod tests {
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let nonce_pubkey = Pubkey::new(&[4u8; 32]);
|
let nonce_pubkey = Pubkey::new(&[4u8; 32]);
|
||||||
let rpc_nonce_account = UiAccount::encode(nonce_account, UiAccountEncoding::Binary, None);
|
let rpc_nonce_account = UiAccount::encode(nonce_account, UiAccountEncoding::Binary64, None);
|
||||||
let get_account_response = json!(Response {
|
let get_account_response = json!(Response {
|
||||||
context: RpcResponseContext { slot: 1 },
|
context: RpcResponseContext { slot: 1 },
|
||||||
value: json!(Some(rpc_nonce_account)),
|
value: json!(Some(rpc_nonce_account)),
|
||||||
|
|
|
@ -2,6 +2,7 @@ use crate::{
|
||||||
client_error::{ClientError, ClientErrorKind, Result as ClientResult},
|
client_error::{ClientError, ClientErrorKind, Result as ClientResult},
|
||||||
http_sender::HttpSender,
|
http_sender::HttpSender,
|
||||||
mock_sender::{MockSender, Mocks},
|
mock_sender::{MockSender, Mocks},
|
||||||
|
rpc_config::RpcAccountInfoConfig,
|
||||||
rpc_config::{
|
rpc_config::{
|
||||||
RpcGetConfirmedSignaturesForAddress2Config, RpcLargestAccountsConfig,
|
RpcGetConfirmedSignaturesForAddress2Config, RpcLargestAccountsConfig,
|
||||||
RpcSendTransactionConfig, RpcTokenAccountsFilter,
|
RpcSendTransactionConfig, RpcTokenAccountsFilter,
|
||||||
|
@ -20,6 +21,8 @@ use solana_account_decoder::{
|
||||||
UiTokenAmount,
|
UiTokenAmount,
|
||||||
},
|
},
|
||||||
UiAccount,
|
UiAccount,
|
||||||
|
UiAccountData::{Binary, Binary64},
|
||||||
|
UiAccountEncoding,
|
||||||
};
|
};
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account::Account,
|
account::Account,
|
||||||
|
@ -466,9 +469,13 @@ impl RpcClient {
|
||||||
pubkey: &Pubkey,
|
pubkey: &Pubkey,
|
||||||
commitment_config: CommitmentConfig,
|
commitment_config: CommitmentConfig,
|
||||||
) -> RpcResult<Option<Account>> {
|
) -> RpcResult<Option<Account>> {
|
||||||
|
let config = RpcAccountInfoConfig {
|
||||||
|
encoding: Some(UiAccountEncoding::Binary64),
|
||||||
|
commitment: Some(commitment_config),
|
||||||
|
};
|
||||||
let response = self.sender.send(
|
let response = self.sender.send(
|
||||||
RpcRequest::GetAccountInfo,
|
RpcRequest::GetAccountInfo,
|
||||||
json!([pubkey.to_string(), commitment_config]),
|
json!([pubkey.to_string(), config]),
|
||||||
);
|
);
|
||||||
|
|
||||||
response
|
response
|
||||||
|
@ -480,8 +487,17 @@ impl RpcClient {
|
||||||
}
|
}
|
||||||
let Response {
|
let Response {
|
||||||
context,
|
context,
|
||||||
value: rpc_account,
|
value: mut rpc_account,
|
||||||
} = serde_json::from_value::<Response<Option<UiAccount>>>(result_json)?;
|
} = serde_json::from_value::<Response<Option<UiAccount>>>(result_json)?;
|
||||||
|
if let Some(ref mut account) = rpc_account {
|
||||||
|
if let Binary(_) = &account.data {
|
||||||
|
let tmp = Binary64(String::new());
|
||||||
|
match std::mem::replace(&mut account.data, tmp) {
|
||||||
|
Binary(new_data) => account.data = Binary64(new_data),
|
||||||
|
_ => panic!("should have gotten binary here."),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
trace!("Response account {:?} {:?}", pubkey, rpc_account);
|
trace!("Response account {:?} {:?}", pubkey, rpc_account);
|
||||||
let account = rpc_account.and_then(|rpc_account| rpc_account.decode());
|
let account = rpc_account.and_then(|rpc_account| rpc_account.decode());
|
||||||
Ok(Response {
|
Ok(Response {
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::{
|
||||||
rpc_health::*, validator::ValidatorExit,
|
rpc_health::*, validator::ValidatorExit,
|
||||||
};
|
};
|
||||||
use bincode::{config::Options, serialize};
|
use bincode::{config::Options, serialize};
|
||||||
use jsonrpc_core::{Error, Metadata, Result};
|
use jsonrpc_core::{types::error, Error, Metadata, Result};
|
||||||
use jsonrpc_derive::rpc;
|
use jsonrpc_derive::rpc;
|
||||||
use solana_account_decoder::{
|
use solana_account_decoder::{
|
||||||
parse_account_data::AccountAdditionalData,
|
parse_account_data::AccountAdditionalData,
|
||||||
|
@ -240,21 +240,27 @@ impl JsonRpcRequestProcessor {
|
||||||
&self,
|
&self,
|
||||||
pubkey: &Pubkey,
|
pubkey: &Pubkey,
|
||||||
config: Option<RpcAccountInfoConfig>,
|
config: Option<RpcAccountInfoConfig>,
|
||||||
) -> RpcResponse<Option<UiAccount>> {
|
) -> Result<RpcResponse<Option<UiAccount>>> {
|
||||||
let config = config.unwrap_or_default();
|
let config = config.unwrap_or_default();
|
||||||
let bank = self.bank(config.commitment);
|
let bank = self.bank(config.commitment);
|
||||||
let encoding = config.encoding.unwrap_or(UiAccountEncoding::Binary);
|
let encoding = config.encoding.unwrap_or(UiAccountEncoding::Binary);
|
||||||
new_response(
|
let mut response = None;
|
||||||
&bank,
|
if let Some(account) = bank.get_account(pubkey) {
|
||||||
bank.get_account(pubkey).and_then(|account| {
|
if account.owner == spl_token_id_v1_0() && encoding == UiAccountEncoding::JsonParsed {
|
||||||
if account.owner == spl_token_id_v1_0() && encoding == UiAccountEncoding::JsonParsed
|
response = get_parsed_token_account(bank.clone(), account);
|
||||||
{
|
} else if encoding == UiAccountEncoding::Binary && account.data.len() > 128 {
|
||||||
get_parsed_token_account(bank.clone(), account)
|
let message = "Encoded binary (base 58) data should be less than 128 bytes, please use Binary64 encoding.".to_string();
|
||||||
} else {
|
return Err(error::Error {
|
||||||
Some(UiAccount::encode(account, encoding, None))
|
code: error::ErrorCode::InvalidRequest,
|
||||||
}
|
message,
|
||||||
}),
|
data: None,
|
||||||
)
|
});
|
||||||
|
} else {
|
||||||
|
response = Some(UiAccount::encode(account, encoding, None));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(new_response(&bank, response))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_minimum_balance_for_rent_exemption(
|
pub fn get_minimum_balance_for_rent_exemption(
|
||||||
|
@ -1701,7 +1707,7 @@ impl RpcSol for RpcSolImpl {
|
||||||
) -> Result<RpcResponse<Option<UiAccount>>> {
|
) -> Result<RpcResponse<Option<UiAccount>>> {
|
||||||
debug!("get_account_info rpc request received: {:?}", pubkey_str);
|
debug!("get_account_info rpc request received: {:?}", pubkey_str);
|
||||||
let pubkey = verify_pubkey(pubkey_str)?;
|
let pubkey = verify_pubkey(pubkey_str)?;
|
||||||
Ok(meta.get_account_info(&pubkey, config))
|
meta.get_account_info(&pubkey, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_minimum_balance_for_rent_exemption(
|
fn get_minimum_balance_for_rent_exemption(
|
||||||
|
|
|
@ -100,6 +100,19 @@ fn test_rpc_send_tx() {
|
||||||
|
|
||||||
assert_eq!(confirmed_tx, true);
|
assert_eq!(confirmed_tx, true);
|
||||||
|
|
||||||
|
use solana_account_decoder::UiAccountEncoding;
|
||||||
|
use solana_client::rpc_config::RpcAccountInfoConfig;
|
||||||
|
let config = RpcAccountInfoConfig {
|
||||||
|
encoding: Some(UiAccountEncoding::Binary64),
|
||||||
|
commitment: None,
|
||||||
|
};
|
||||||
|
let req = json_req!(
|
||||||
|
"getAccountInfo",
|
||||||
|
json!([bs58::encode(bob_pubkey).into_string(), config])
|
||||||
|
);
|
||||||
|
let json: Value = post_rpc(req, &leader_data);
|
||||||
|
info!("{:?}", json["result"]["value"]);
|
||||||
|
|
||||||
server.close().unwrap();
|
server.close().unwrap();
|
||||||
remove_dir_all(ledger_path).unwrap();
|
remove_dir_all(ledger_path).unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -156,7 +156,7 @@ Returns all information associated with the account of provided Pubkey
|
||||||
- `<string>` - Pubkey of account to query, as base-58 encoded string
|
- `<string>` - Pubkey of account to query, as base-58 encoded string
|
||||||
- `<object>` - (optional) Configuration object containing the following optional fields:
|
- `<object>` - (optional) Configuration object containing the following optional fields:
|
||||||
- (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
|
- (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
|
||||||
- (optional) `encoding: <string>` - encoding for Account data, either "binary" or jsonParsed". If parameter not provided, the default encoding is binary.
|
- (optional) `encoding: <string>` - encoding for Account data, either "binary", "binary64", or jsonParsed". If parameter not provided, the default encoding is "binary". "binary" is base-58 encoded and limited to Account data of less than 128 bytes. "binary64" will return base64 encoded data for Account data of any size.
|
||||||
Parsed-JSON encoding attempts to use program-specific state parsers to return more human-readable and explicit account state data. If parsed-JSON is requested but a parser cannot be found, the field falls back to binary encoding, detectable when the `data` field is type `<string>`. **jsonParsed encoding is UNSTABLE**
|
Parsed-JSON encoding attempts to use program-specific state parsers to return more human-readable and explicit account state data. If parsed-JSON is requested but a parser cannot be found, the field falls back to binary encoding, detectable when the `data` field is type `<string>`. **jsonParsed encoding is UNSTABLE**
|
||||||
|
|
||||||
#### Results:
|
#### Results:
|
||||||
|
|
Loading…
Reference in New Issue