* Add config param to specify offset/length for single and program account info (#11515)
* Add config param to specify dataSlice for account info and program accounts
* Use match instead of if
(cherry picked from commit 88ca04dbdb)
# Conflicts:
#	cli/src/cli.rs
* Fix conflicts
Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
			
			
This commit is contained in:
		
							
								
								
									
										1
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @@ -3460,6 +3460,7 @@ dependencies = [ | |||||||
| name = "solana-core" | name = "solana-core" | ||||||
| version = "1.3.2" | version = "1.3.2" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  |  "base64 0.12.3", | ||||||
|  "bincode", |  "bincode", | ||||||
|  "bs58", |  "bs58", | ||||||
|  "bv", |  "bv", | ||||||
|   | |||||||
| @@ -51,19 +51,23 @@ impl UiAccount { | |||||||
|         account: Account, |         account: Account, | ||||||
|         encoding: UiAccountEncoding, |         encoding: UiAccountEncoding, | ||||||
|         additional_data: Option<AccountAdditionalData>, |         additional_data: Option<AccountAdditionalData>, | ||||||
|  |         data_slice_config: Option<UiDataSliceConfig>, | ||||||
|     ) -> Self { |     ) -> Self { | ||||||
|         let data = match encoding { |         let data = match encoding { | ||||||
|             UiAccountEncoding::Binary => { |             UiAccountEncoding::Binary => UiAccountData::Binary( | ||||||
|                 UiAccountData::Binary(bs58::encode(account.data).into_string()) |                 bs58::encode(slice_data(&account.data, data_slice_config)).into_string(), | ||||||
|             } |             ), | ||||||
|             UiAccountEncoding::Binary64 => UiAccountData::Binary64(base64::encode(account.data)), |             UiAccountEncoding::Binary64 => UiAccountData::Binary64(base64::encode(slice_data( | ||||||
|  |                 &account.data, | ||||||
|  |                 data_slice_config, | ||||||
|  |             ))), | ||||||
|             UiAccountEncoding::JsonParsed => { |             UiAccountEncoding::JsonParsed => { | ||||||
|                 if let Ok(parsed_data) = |                 if let Ok(parsed_data) = | ||||||
|                     parse_account_data(pubkey, &account.owner, &account.data, additional_data) |                     parse_account_data(pubkey, &account.owner, &account.data, additional_data) | ||||||
|                 { |                 { | ||||||
|                     UiAccountData::Json(parsed_data) |                     UiAccountData::Json(parsed_data) | ||||||
|                 } else { |                 } else { | ||||||
|                     UiAccountData::Binary64(base64::encode(account.data)) |                     UiAccountData::Binary64(base64::encode(&account.data)) | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         }; |         }; | ||||||
| @@ -113,3 +117,57 @@ impl Default for UiFeeCalculator { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] | ||||||
|  | #[serde(rename_all = "camelCase")] | ||||||
|  | pub struct UiDataSliceConfig { | ||||||
|  |     pub offset: usize, | ||||||
|  |     pub length: usize, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn slice_data(data: &[u8], data_slice_config: Option<UiDataSliceConfig>) -> &[u8] { | ||||||
|  |     if let Some(UiDataSliceConfig { offset, length }) = data_slice_config { | ||||||
|  |         if offset >= data.len() { | ||||||
|  |             &[] | ||||||
|  |         } else if length > data.len() - offset { | ||||||
|  |             &data[offset..] | ||||||
|  |         } else { | ||||||
|  |             &data[offset..offset + length] | ||||||
|  |         } | ||||||
|  |     } else { | ||||||
|  |         data | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[cfg(test)] | ||||||
|  | mod test { | ||||||
|  |     use super::*; | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn test_slice_data() { | ||||||
|  |         let data = vec![1, 2, 3, 4, 5]; | ||||||
|  |         let slice_config = Some(UiDataSliceConfig { | ||||||
|  |             offset: 0, | ||||||
|  |             length: 5, | ||||||
|  |         }); | ||||||
|  |         assert_eq!(slice_data(&data, slice_config), &data[..]); | ||||||
|  |  | ||||||
|  |         let slice_config = Some(UiDataSliceConfig { | ||||||
|  |             offset: 0, | ||||||
|  |             length: 10, | ||||||
|  |         }); | ||||||
|  |         assert_eq!(slice_data(&data, slice_config), &data[..]); | ||||||
|  |  | ||||||
|  |         let slice_config = Some(UiDataSliceConfig { | ||||||
|  |             offset: 1, | ||||||
|  |             length: 2, | ||||||
|  |         }); | ||||||
|  |         assert_eq!(slice_data(&data, slice_config), &data[1..3]); | ||||||
|  |  | ||||||
|  |         let slice_config = Some(UiDataSliceConfig { | ||||||
|  |             offset: 10, | ||||||
|  |             length: 2, | ||||||
|  |         }); | ||||||
|  |         assert_eq!(slice_data(&data, slice_config), &[] as &[u8]); | ||||||
|  |     } | ||||||
|  | } | ||||||
|   | |||||||
| @@ -1235,7 +1235,13 @@ fn process_show_account( | |||||||
|     let cli_account = CliAccount { |     let cli_account = CliAccount { | ||||||
|         keyed_account: RpcKeyedAccount { |         keyed_account: RpcKeyedAccount { | ||||||
|             pubkey: account_pubkey.to_string(), |             pubkey: account_pubkey.to_string(), | ||||||
|             account: UiAccount::encode(account_pubkey, account, UiAccountEncoding::Binary, None), |             account: UiAccount::encode( | ||||||
|  |                 account_pubkey, | ||||||
|  |                 account, | ||||||
|  |                 UiAccountEncoding::Binary64, | ||||||
|  |                 None, | ||||||
|  |                 None, | ||||||
|  |             ), | ||||||
|         }, |         }, | ||||||
|         use_lamports_unit, |         use_lamports_unit, | ||||||
|     }; |     }; | ||||||
|   | |||||||
| @@ -355,6 +355,7 @@ mod tests { | |||||||
|             nonce_account, |             nonce_account, | ||||||
|             UiAccountEncoding::Binary64, |             UiAccountEncoding::Binary64, | ||||||
|             None, |             None, | ||||||
|  |             None, | ||||||
|         ); |         ); | ||||||
|         let get_account_response = json!(Response { |         let get_account_response = json!(Response { | ||||||
|             context: RpcResponseContext { slot: 1 }, |             context: RpcResponseContext { slot: 1 }, | ||||||
|   | |||||||
| @@ -472,6 +472,7 @@ impl RpcClient { | |||||||
|         let config = RpcAccountInfoConfig { |         let config = RpcAccountInfoConfig { | ||||||
|             encoding: Some(UiAccountEncoding::Binary64), |             encoding: Some(UiAccountEncoding::Binary64), | ||||||
|             commitment: Some(commitment_config), |             commitment: Some(commitment_config), | ||||||
|  |             data_slice: None, | ||||||
|         }; |         }; | ||||||
|         let response = self.sender.send( |         let response = self.sender.send( | ||||||
|             RpcRequest::GetAccountInfo, |             RpcRequest::GetAccountInfo, | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| use crate::rpc_filter::RpcFilterType; | use crate::rpc_filter::RpcFilterType; | ||||||
| use solana_account_decoder::UiAccountEncoding; | use solana_account_decoder::{UiAccountEncoding, UiDataSliceConfig}; | ||||||
| use solana_sdk::{clock::Epoch, commitment_config::CommitmentConfig}; | use solana_sdk::{clock::Epoch, commitment_config::CommitmentConfig}; | ||||||
|  |  | ||||||
| #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] | ||||||
| @@ -47,6 +47,7 @@ pub struct RpcStakeConfig { | |||||||
| #[serde(rename_all = "camelCase")] | #[serde(rename_all = "camelCase")] | ||||||
| pub struct RpcAccountInfoConfig { | pub struct RpcAccountInfoConfig { | ||||||
|     pub encoding: Option<UiAccountEncoding>, |     pub encoding: Option<UiAccountEncoding>, | ||||||
|  |     pub data_slice: Option<UiDataSliceConfig>, | ||||||
|     #[serde(flatten)] |     #[serde(flatten)] | ||||||
|     pub commitment: Option<CommitmentConfig>, |     pub commitment: Option<CommitmentConfig>, | ||||||
| } | } | ||||||
|   | |||||||
| @@ -79,6 +79,7 @@ tokio = { version = "0.2.22", features = ["full"] } | |||||||
| trees = "0.2.1" | trees = "0.2.1" | ||||||
|  |  | ||||||
| [dev-dependencies] | [dev-dependencies] | ||||||
|  | base64 = "0.12.3" | ||||||
| matches = "0.1.6" | matches = "0.1.6" | ||||||
| reqwest = { version = "0.10.6", default-features = false, features = ["blocking", "rustls-tls", "json"] } | reqwest = { version = "0.10.6", default-features = false, features = ["blocking", "rustls-tls", "json"] } | ||||||
| serial_test = "0.4.0" | serial_test = "0.4.0" | ||||||
|   | |||||||
							
								
								
									
										137
									
								
								core/src/rpc.rs
									
									
									
									
									
								
							
							
						
						
									
										137
									
								
								core/src/rpc.rs
									
									
									
									
									
								
							| @@ -244,6 +244,7 @@ impl JsonRpcRequestProcessor { | |||||||
|         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); | ||||||
|  |         check_slice_and_encoding(&encoding, config.data_slice.is_some())?; | ||||||
|         let mut response = None; |         let mut response = None; | ||||||
|         if let Some(account) = bank.get_account(pubkey) { |         if let Some(account) = bank.get_account(pubkey) { | ||||||
|             if account.owner == spl_token_id_v1_0() && encoding == UiAccountEncoding::JsonParsed { |             if account.owner == spl_token_id_v1_0() && encoding == UiAccountEncoding::JsonParsed { | ||||||
| @@ -256,7 +257,13 @@ impl JsonRpcRequestProcessor { | |||||||
|                     data: None, |                     data: None, | ||||||
|                 }); |                 }); | ||||||
|             } else { |             } else { | ||||||
|                 response = Some(UiAccount::encode(pubkey, account, encoding, None)); |                 response = Some(UiAccount::encode( | ||||||
|  |                     pubkey, | ||||||
|  |                     account, | ||||||
|  |                     encoding, | ||||||
|  |                     None, | ||||||
|  |                     config.data_slice, | ||||||
|  |                 )); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -277,21 +284,31 @@ impl JsonRpcRequestProcessor { | |||||||
|         program_id: &Pubkey, |         program_id: &Pubkey, | ||||||
|         config: Option<RpcAccountInfoConfig>, |         config: Option<RpcAccountInfoConfig>, | ||||||
|         filters: Vec<RpcFilterType>, |         filters: Vec<RpcFilterType>, | ||||||
|     ) -> Vec<RpcKeyedAccount> { |     ) -> Result<Vec<RpcKeyedAccount>> { | ||||||
|         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); | ||||||
|  |         let data_slice_config = config.data_slice; | ||||||
|  |         check_slice_and_encoding(&encoding, data_slice_config.is_some())?; | ||||||
|         let keyed_accounts = get_filtered_program_accounts(&bank, program_id, filters); |         let keyed_accounts = get_filtered_program_accounts(&bank, program_id, filters); | ||||||
|         if program_id == &spl_token_id_v1_0() && encoding == UiAccountEncoding::JsonParsed { |         let result = | ||||||
|             get_parsed_token_accounts(bank, keyed_accounts).collect() |             if program_id == &spl_token_id_v1_0() && encoding == UiAccountEncoding::JsonParsed { | ||||||
|         } else { |                 get_parsed_token_accounts(bank, keyed_accounts).collect() | ||||||
|             keyed_accounts |             } else { | ||||||
|                 .map(|(pubkey, account)| RpcKeyedAccount { |                 keyed_accounts | ||||||
|                     pubkey: pubkey.to_string(), |                     .map(|(pubkey, account)| RpcKeyedAccount { | ||||||
|                     account: UiAccount::encode(&pubkey, account, encoding.clone(), None), |                         pubkey: pubkey.to_string(), | ||||||
|                 }) |                         account: UiAccount::encode( | ||||||
|                 .collect() |                             &pubkey, | ||||||
|         } |                             account, | ||||||
|  |                             encoding.clone(), | ||||||
|  |                             None, | ||||||
|  |                             data_slice_config, | ||||||
|  |                         ), | ||||||
|  |                     }) | ||||||
|  |                     .collect() | ||||||
|  |             }; | ||||||
|  |         Ok(result) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     pub fn get_inflation_governor( |     pub fn get_inflation_governor( | ||||||
| @@ -1107,6 +1124,8 @@ impl JsonRpcRequestProcessor { | |||||||
|         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); | ||||||
|  |         let data_slice_config = config.data_slice; | ||||||
|  |         check_slice_and_encoding(&encoding, data_slice_config.is_some())?; | ||||||
|         let (token_program_id, mint) = get_token_program_id_and_mint(&bank, token_account_filter)?; |         let (token_program_id, mint) = get_token_program_id_and_mint(&bank, token_account_filter)?; | ||||||
|  |  | ||||||
|         let mut filters = vec![ |         let mut filters = vec![ | ||||||
| @@ -1134,7 +1153,13 @@ impl JsonRpcRequestProcessor { | |||||||
|             keyed_accounts |             keyed_accounts | ||||||
|                 .map(|(pubkey, account)| RpcKeyedAccount { |                 .map(|(pubkey, account)| RpcKeyedAccount { | ||||||
|                     pubkey: pubkey.to_string(), |                     pubkey: pubkey.to_string(), | ||||||
|                     account: UiAccount::encode(&pubkey, account, encoding.clone(), None), |                     account: UiAccount::encode( | ||||||
|  |                         &pubkey, | ||||||
|  |                         account, | ||||||
|  |                         encoding.clone(), | ||||||
|  |                         None, | ||||||
|  |                         data_slice_config, | ||||||
|  |                     ), | ||||||
|                 }) |                 }) | ||||||
|                 .collect() |                 .collect() | ||||||
|         }; |         }; | ||||||
| @@ -1150,6 +1175,8 @@ impl JsonRpcRequestProcessor { | |||||||
|         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); | ||||||
|  |         let data_slice_config = config.data_slice; | ||||||
|  |         check_slice_and_encoding(&encoding, data_slice_config.is_some())?; | ||||||
|         let (token_program_id, mint) = get_token_program_id_and_mint(&bank, token_account_filter)?; |         let (token_program_id, mint) = get_token_program_id_and_mint(&bank, token_account_filter)?; | ||||||
|  |  | ||||||
|         let mut filters = vec![ |         let mut filters = vec![ | ||||||
| @@ -1185,7 +1212,13 @@ impl JsonRpcRequestProcessor { | |||||||
|             keyed_accounts |             keyed_accounts | ||||||
|                 .map(|(pubkey, account)| RpcKeyedAccount { |                 .map(|(pubkey, account)| RpcKeyedAccount { | ||||||
|                     pubkey: pubkey.to_string(), |                     pubkey: pubkey.to_string(), | ||||||
|                     account: UiAccount::encode(&pubkey, account, encoding.clone(), None), |                     account: UiAccount::encode( | ||||||
|  |                         &pubkey, | ||||||
|  |                         account, | ||||||
|  |                         encoding.clone(), | ||||||
|  |                         None, | ||||||
|  |                         data_slice_config, | ||||||
|  |                     ), | ||||||
|                 }) |                 }) | ||||||
|                 .collect() |                 .collect() | ||||||
|         }; |         }; | ||||||
| @@ -1226,6 +1259,26 @@ fn verify_token_account_filter( | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | fn check_slice_and_encoding(encoding: &UiAccountEncoding, data_slice_is_some: bool) -> Result<()> { | ||||||
|  |     match encoding { | ||||||
|  |         UiAccountEncoding::JsonParsed => { | ||||||
|  |             if data_slice_is_some { | ||||||
|  |                 let message = | ||||||
|  |                     "Sliced account data can only be encoded using binary (base 58) or binary64 encoding." | ||||||
|  |                         .to_string(); | ||||||
|  |                 Err(error::Error { | ||||||
|  |                     code: error::ErrorCode::InvalidRequest, | ||||||
|  |                     message, | ||||||
|  |                     data: None, | ||||||
|  |                 }) | ||||||
|  |             } else { | ||||||
|  |                 Ok(()) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         UiAccountEncoding::Binary | UiAccountEncoding::Binary64 => Ok(()), | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| /// Use a set of filters to get an iterator of keyed program accounts from a bank | /// Use a set of filters to get an iterator of keyed program accounts from a bank | ||||||
| fn get_filtered_program_accounts( | fn get_filtered_program_accounts( | ||||||
|     bank: &Arc<Bank>, |     bank: &Arc<Bank>, | ||||||
| @@ -1258,6 +1311,7 @@ pub(crate) fn get_parsed_token_account( | |||||||
|         account, |         account, | ||||||
|         UiAccountEncoding::JsonParsed, |         UiAccountEncoding::JsonParsed, | ||||||
|         additional_data, |         additional_data, | ||||||
|  |         None, | ||||||
|     ) |     ) | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1286,6 +1340,7 @@ where | |||||||
|                 account, |                 account, | ||||||
|                 UiAccountEncoding::JsonParsed, |                 UiAccountEncoding::JsonParsed, | ||||||
|                 additional_data, |                 additional_data, | ||||||
|  |                 None, | ||||||
|             ), |             ), | ||||||
|         } |         } | ||||||
|     }) |     }) | ||||||
| @@ -1753,7 +1808,7 @@ impl RpcSol for RpcSolImpl { | |||||||
|         for filter in &filters { |         for filter in &filters { | ||||||
|             verify_filter(filter)?; |             verify_filter(filter)?; | ||||||
|         } |         } | ||||||
|         Ok(meta.get_program_accounts(&program_id, config, filters)) |         meta.get_program_accounts(&program_id, config, filters) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn get_inflation_governor( |     fn get_inflation_governor( | ||||||
| @@ -3028,13 +3083,13 @@ pub mod tests { | |||||||
|     #[test] |     #[test] | ||||||
|     fn test_rpc_get_account_info() { |     fn test_rpc_get_account_info() { | ||||||
|         let bob_pubkey = Pubkey::new_rand(); |         let bob_pubkey = Pubkey::new_rand(); | ||||||
|         let RpcHandler { io, meta, .. } = start_rpc_handler_with_tx(&bob_pubkey); |         let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&bob_pubkey); | ||||||
|  |  | ||||||
|         let req = format!( |         let req = format!( | ||||||
|             r#"{{"jsonrpc":"2.0","id":1,"method":"getAccountInfo","params":["{}"]}}"#, |             r#"{{"jsonrpc":"2.0","id":1,"method":"getAccountInfo","params":["{}"]}}"#, | ||||||
|             bob_pubkey |             bob_pubkey | ||||||
|         ); |         ); | ||||||
|         let res = io.handle_request_sync(&req, meta); |         let res = io.handle_request_sync(&req, meta.clone()); | ||||||
|         let expected = json!({ |         let expected = json!({ | ||||||
|             "jsonrpc": "2.0", |             "jsonrpc": "2.0", | ||||||
|             "result": { |             "result": { | ||||||
| @@ -3054,6 +3109,54 @@ pub mod tests { | |||||||
|         let result: Response = serde_json::from_str(&res.expect("actual response")) |         let result: Response = serde_json::from_str(&res.expect("actual response")) | ||||||
|             .expect("actual response deserialization"); |             .expect("actual response deserialization"); | ||||||
|         assert_eq!(expected, result); |         assert_eq!(expected, result); | ||||||
|  |  | ||||||
|  |         let address = Pubkey::new_rand(); | ||||||
|  |         let data = vec![1, 2, 3, 4, 5]; | ||||||
|  |         let mut account = Account::new(42, 5, &Pubkey::default()); | ||||||
|  |         account.data = data.clone(); | ||||||
|  |         bank.store_account(&address, &account); | ||||||
|  |  | ||||||
|  |         let req = format!( | ||||||
|  |             r#"{{"jsonrpc":"2.0","id":1,"method":"getAccountInfo","params":["{}", {{"encoding":"binary64"}}]}}"#, | ||||||
|  |             address | ||||||
|  |         ); | ||||||
|  |         let res = io.handle_request_sync(&req, meta.clone()); | ||||||
|  |         let result: Value = serde_json::from_str(&res.expect("actual response")) | ||||||
|  |             .expect("actual response deserialization"); | ||||||
|  |         assert_eq!(result["result"]["value"]["data"], base64::encode(&data)); | ||||||
|  |  | ||||||
|  |         let req = format!( | ||||||
|  |             r#"{{"jsonrpc":"2.0","id":1,"method":"getAccountInfo","params":["{}", {{"encoding":"binary64", "dataSlice": {{"length": 2, "offset": 1}}}}]}}"#, | ||||||
|  |             address | ||||||
|  |         ); | ||||||
|  |         let res = io.handle_request_sync(&req, meta.clone()); | ||||||
|  |         let result: Value = serde_json::from_str(&res.expect("actual response")) | ||||||
|  |             .expect("actual response deserialization"); | ||||||
|  |         assert_eq!( | ||||||
|  |             result["result"]["value"]["data"], | ||||||
|  |             base64::encode(&data[1..3]), | ||||||
|  |         ); | ||||||
|  |  | ||||||
|  |         let req = format!( | ||||||
|  |             r#"{{"jsonrpc":"2.0","id":1,"method":"getAccountInfo","params":["{}", {{"encoding":"binary", "dataSlice": {{"length": 2, "offset": 1}}}}]}}"#, | ||||||
|  |             address | ||||||
|  |         ); | ||||||
|  |         let res = io.handle_request_sync(&req, meta.clone()); | ||||||
|  |         let result: Value = serde_json::from_str(&res.expect("actual response")) | ||||||
|  |             .expect("actual response deserialization"); | ||||||
|  |         assert_eq!( | ||||||
|  |             result["result"]["value"]["data"], | ||||||
|  |             bs58::encode(&data[1..3]).into_string(), | ||||||
|  |         ); | ||||||
|  |  | ||||||
|  |         let req = format!( | ||||||
|  |             r#"{{"jsonrpc":"2.0","id":1,"method":"getAccountInfo","params":["{}", {{"encoding":"jsonParsed", "dataSlice": {{"length": 2, "offset": 1}}}}]}}"#, | ||||||
|  |             address | ||||||
|  |         ); | ||||||
|  |         let res = io.handle_request_sync(&req, meta); | ||||||
|  |         let result: Value = serde_json::from_str(&res.expect("actual response")) | ||||||
|  |             .expect("actual response deserialization"); | ||||||
|  |         result["error"].as_object().unwrap(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     #[test] |     #[test] | ||||||
|   | |||||||
| @@ -544,6 +544,7 @@ mod tests { | |||||||
|             Some(RpcAccountInfoConfig { |             Some(RpcAccountInfoConfig { | ||||||
|                 commitment: Some(CommitmentConfig::recent()), |                 commitment: Some(CommitmentConfig::recent()), | ||||||
|                 encoding: None, |                 encoding: None, | ||||||
|  |                 data_slice: None, | ||||||
|             }), |             }), | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
| @@ -653,6 +654,7 @@ mod tests { | |||||||
|             Some(RpcAccountInfoConfig { |             Some(RpcAccountInfoConfig { | ||||||
|                 commitment: Some(CommitmentConfig::recent()), |                 commitment: Some(CommitmentConfig::recent()), | ||||||
|                 encoding: Some(UiAccountEncoding::JsonParsed), |                 encoding: Some(UiAccountEncoding::JsonParsed), | ||||||
|  |                 data_slice: None, | ||||||
|             }), |             }), | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
| @@ -773,6 +775,7 @@ mod tests { | |||||||
|             Some(RpcAccountInfoConfig { |             Some(RpcAccountInfoConfig { | ||||||
|                 commitment: Some(CommitmentConfig::root()), |                 commitment: Some(CommitmentConfig::root()), | ||||||
|                 encoding: None, |                 encoding: None, | ||||||
|  |                 data_slice: None, | ||||||
|             }), |             }), | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
| @@ -822,6 +825,7 @@ mod tests { | |||||||
|             Some(RpcAccountInfoConfig { |             Some(RpcAccountInfoConfig { | ||||||
|                 commitment: Some(CommitmentConfig::root()), |                 commitment: Some(CommitmentConfig::root()), | ||||||
|                 encoding: None, |                 encoding: None, | ||||||
|  |                 data_slice: None, | ||||||
|             }), |             }), | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -265,7 +265,7 @@ fn filter_account_result( | |||||||
|             } else { |             } else { | ||||||
|                 return ( |                 return ( | ||||||
|                     Box::new(iter::once(UiAccount::encode( |                     Box::new(iter::once(UiAccount::encode( | ||||||
|                         pubkey, account, encoding, None, |                         pubkey, account, encoding, None, None, | ||||||
|                     ))), |                     ))), | ||||||
|                     fork, |                     fork, | ||||||
|                 ); |                 ); | ||||||
| @@ -316,7 +316,7 @@ fn filter_program_results( | |||||||
|             Box::new( |             Box::new( | ||||||
|                 keyed_accounts.map(move |(pubkey, account)| RpcKeyedAccount { |                 keyed_accounts.map(move |(pubkey, account)| RpcKeyedAccount { | ||||||
|                     pubkey: pubkey.to_string(), |                     pubkey: pubkey.to_string(), | ||||||
|                     account: UiAccount::encode(&pubkey, account, encoding.clone(), None), |                     account: UiAccount::encode(&pubkey, account, encoding.clone(), None, None), | ||||||
|                 }), |                 }), | ||||||
|             ) |             ) | ||||||
|         }; |         }; | ||||||
| @@ -1033,6 +1033,7 @@ pub(crate) mod tests { | |||||||
|             Some(RpcAccountInfoConfig { |             Some(RpcAccountInfoConfig { | ||||||
|                 commitment: Some(CommitmentConfig::recent()), |                 commitment: Some(CommitmentConfig::recent()), | ||||||
|                 encoding: None, |                 encoding: None, | ||||||
|  |                 data_slice: None, | ||||||
|             }), |             }), | ||||||
|             sub_id.clone(), |             sub_id.clone(), | ||||||
|             subscriber, |             subscriber, | ||||||
| @@ -1517,6 +1518,7 @@ pub(crate) mod tests { | |||||||
|             Some(RpcAccountInfoConfig { |             Some(RpcAccountInfoConfig { | ||||||
|                 commitment: Some(CommitmentConfig::single_gossip()), |                 commitment: Some(CommitmentConfig::single_gossip()), | ||||||
|                 encoding: None, |                 encoding: None, | ||||||
|  |                 data_slice: None, | ||||||
|             }), |             }), | ||||||
|             sub_id0.clone(), |             sub_id0.clone(), | ||||||
|             subscriber0, |             subscriber0, | ||||||
| @@ -1585,6 +1587,7 @@ pub(crate) mod tests { | |||||||
|             Some(RpcAccountInfoConfig { |             Some(RpcAccountInfoConfig { | ||||||
|                 commitment: Some(CommitmentConfig::single_gossip()), |                 commitment: Some(CommitmentConfig::single_gossip()), | ||||||
|                 encoding: None, |                 encoding: None, | ||||||
|  |                 data_slice: None, | ||||||
|             }), |             }), | ||||||
|             sub_id1.clone(), |             sub_id1.clone(), | ||||||
|             subscriber1, |             subscriber1, | ||||||
|   | |||||||
| @@ -105,6 +105,7 @@ fn test_rpc_send_tx() { | |||||||
|     let config = RpcAccountInfoConfig { |     let config = RpcAccountInfoConfig { | ||||||
|         encoding: Some(UiAccountEncoding::Binary64), |         encoding: Some(UiAccountEncoding::Binary64), | ||||||
|         commitment: None, |         commitment: None, | ||||||
|  |         data_slice: None, | ||||||
|     }; |     }; | ||||||
|     let req = json_req!( |     let req = json_req!( | ||||||
|         "getAccountInfo", |         "getAccountInfo", | ||||||
|   | |||||||
| @@ -158,6 +158,7 @@ Returns all information associated with the account of provided Pubkey | |||||||
|   - (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", "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. |   - (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** | ||||||
|  |   - (optional) `dataSlice: <object>` - limit the returned account data using the provided `offset: <usize>` and `length: <usize>` fields; only available for "binary" or "binary64" encoding. | ||||||
|  |  | ||||||
| #### Results: | #### Results: | ||||||
|  |  | ||||||
| @@ -845,6 +846,7 @@ Returns all accounts owned by the provided program Pubkey | |||||||
|   - (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" or jsonParsed". If parameter not provided, the default encoding is binary. | ||||||
|     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** | ||||||
|  |   - (optional) `dataSlice: <object>` - limit the returned account data using the provided `offset: <usize>` and `length: <usize>` fields; only available for "binary" or "binary64" encoding. | ||||||
|   - (optional) `filters: <array>` - filter results using various [filter objects](jsonrpc-api.md#filters); account must meet all filter criteria to be included in results |   - (optional) `filters: <array>` - filter results using various [filter objects](jsonrpc-api.md#filters); account must meet all filter criteria to be included in results | ||||||
|  |  | ||||||
| ##### Filters: | ##### Filters: | ||||||
| @@ -1099,6 +1101,7 @@ Returns all SPL Token accounts by approved Delegate. **UNSTABLE** | |||||||
|   - (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" or jsonParsed". If parameter not provided, the default encoding is binary. | ||||||
|     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** | ||||||
|  |   - (optional) `dataSlice: <object>` - limit the returned account data using the provided `offset: <usize>` and `length: <usize>` fields; only available for "binary" or "binary64" encoding. | ||||||
|  |  | ||||||
| #### Results: | #### Results: | ||||||
|  |  | ||||||
| @@ -1135,6 +1138,7 @@ Returns all SPL Token accounts by token owner. **UNSTABLE** | |||||||
|   - (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" or jsonParsed". If parameter not provided, the default encoding is binary. | ||||||
|     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** | ||||||
|  |   - (optional) `dataSlice: <object>` - limit the returned account data using the provided `offset: <usize>` and `length: <usize>` fields; only available for "binary" or "binary64" encoding. | ||||||
|  |  | ||||||
| #### Results: | #### Results: | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user