* 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:
#	core/src/rpc.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
									
									
									
								
							| @@ -3525,6 +3525,7 @@ dependencies = [ | ||||
| name = "solana-core" | ||||
| version = "1.2.22" | ||||
| dependencies = [ | ||||
|  "base64 0.12.3", | ||||
|  "bincode", | ||||
|  "bs58", | ||||
|  "bv", | ||||
|   | ||||
| @@ -51,19 +51,23 @@ impl UiAccount { | ||||
|         account: Account, | ||||
|         encoding: UiAccountEncoding, | ||||
|         additional_data: Option<AccountAdditionalData>, | ||||
|         data_slice_config: Option<UiDataSliceConfig>, | ||||
|     ) -> Self { | ||||
|         let data = match encoding { | ||||
|             UiAccountEncoding::Binary => { | ||||
|                 UiAccountData::Binary(bs58::encode(account.data).into_string()) | ||||
|             } | ||||
|             UiAccountEncoding::Binary64 => UiAccountData::Binary64(base64::encode(account.data)), | ||||
|             UiAccountEncoding::Binary => UiAccountData::Binary( | ||||
|                 bs58::encode(slice_data(&account.data, data_slice_config)).into_string(), | ||||
|             ), | ||||
|             UiAccountEncoding::Binary64 => UiAccountData::Binary64(base64::encode(slice_data( | ||||
|                 &account.data, | ||||
|                 data_slice_config, | ||||
|             ))), | ||||
|             UiAccountEncoding::JsonParsed => { | ||||
|                 if let Ok(parsed_data) = | ||||
|                     parse_account_data(pubkey, &account.owner, &account.data, additional_data) | ||||
|                 { | ||||
|                     UiAccountData::Json(parsed_data) | ||||
|                 } 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]); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1230,7 +1230,13 @@ fn process_show_account( | ||||
|     let cli_account = CliAccount { | ||||
|         keyed_account: RpcKeyedAccount { | ||||
|             pubkey: account_pubkey.to_string(), | ||||
|             account: UiAccount::encode(account_pubkey, account, UiAccountEncoding::Binary64, None), | ||||
|             account: UiAccount::encode( | ||||
|                 account_pubkey, | ||||
|                 account, | ||||
|                 UiAccountEncoding::Binary64, | ||||
|                 None, | ||||
|                 None, | ||||
|             ), | ||||
|         }, | ||||
|         use_lamports_unit, | ||||
|     }; | ||||
|   | ||||
| @@ -350,6 +350,7 @@ mod tests { | ||||
|             nonce_account, | ||||
|             UiAccountEncoding::Binary64, | ||||
|             None, | ||||
|             None, | ||||
|         ); | ||||
|         let get_account_response = json!(Response { | ||||
|             context: RpcResponseContext { slot: 1 }, | ||||
|   | ||||
| @@ -480,6 +480,7 @@ impl RpcClient { | ||||
|         let config = RpcAccountInfoConfig { | ||||
|             encoding: Some(UiAccountEncoding::Binary64), | ||||
|             commitment: Some(commitment_config), | ||||
|             data_slice: None, | ||||
|         }; | ||||
|         let response = self.sender.send( | ||||
|             RpcRequest::GetAccountInfo, | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| use crate::rpc_filter::RpcFilterType; | ||||
| use solana_account_decoder::UiAccountEncoding; | ||||
| use solana_account_decoder::{UiAccountEncoding, UiDataSliceConfig}; | ||||
| use solana_sdk::{clock::Epoch, commitment_config::CommitmentConfig}; | ||||
|  | ||||
| #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] | ||||
| @@ -47,6 +47,7 @@ pub struct RpcStakeConfig { | ||||
| #[serde(rename_all = "camelCase")] | ||||
| pub struct RpcAccountInfoConfig { | ||||
|     pub encoding: Option<UiAccountEncoding>, | ||||
|     pub data_slice: Option<UiDataSliceConfig>, | ||||
|     #[serde(flatten)] | ||||
|     pub commitment: Option<CommitmentConfig>, | ||||
| } | ||||
|   | ||||
| @@ -77,6 +77,7 @@ tokio_io_01 = { version = "0.1", package = "tokio-io" } | ||||
| trees = "0.2.1" | ||||
|  | ||||
| [dev-dependencies] | ||||
| base64 = "0.12.3" | ||||
| matches = "0.1.6" | ||||
| reqwest = { version = "0.10.4", default-features = false, features = ["blocking", "rustls-tls", "json"] } | ||||
| serial_test = "0.4.0" | ||||
|   | ||||
							
								
								
									
										117
									
								
								core/src/rpc.rs
									
									
									
									
									
								
							
							
						
						
									
										117
									
								
								core/src/rpc.rs
									
									
									
									
									
								
							| @@ -190,6 +190,7 @@ impl JsonRpcRequestProcessor { | ||||
|         let config = config.unwrap_or_default(); | ||||
|         let bank = self.bank(config.commitment)?; | ||||
|         let encoding = config.encoding.unwrap_or(UiAccountEncoding::Binary); | ||||
|         check_slice_and_encoding(&encoding, config.data_slice.is_some())?; | ||||
|         let mut response = None; | ||||
|         if let Some(account) = bank.get_account(pubkey) { | ||||
|             if account.owner == spl_token_id_v1_0() && encoding == UiAccountEncoding::JsonParsed { | ||||
| @@ -202,7 +203,13 @@ impl JsonRpcRequestProcessor { | ||||
|                     data: None, | ||||
|                 }); | ||||
|             } else { | ||||
|                 response = Some(UiAccount::encode(pubkey, account, encoding, None)); | ||||
|                 response = Some(UiAccount::encode( | ||||
|                     pubkey, | ||||
|                     account, | ||||
|                     encoding, | ||||
|                     None, | ||||
|                     config.data_slice, | ||||
|                 )); | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @@ -228,19 +235,27 @@ impl JsonRpcRequestProcessor { | ||||
|         let config = config.unwrap_or_default(); | ||||
|         let bank = self.bank(config.commitment)?; | ||||
|         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 accounts = | ||||
|         let result = | ||||
|             if program_id == &spl_token_id_v1_0() && encoding == UiAccountEncoding::JsonParsed { | ||||
|                 get_parsed_token_accounts(bank, keyed_accounts).collect() | ||||
|             } else { | ||||
|                 keyed_accounts | ||||
|                     .map(|(pubkey, account)| RpcKeyedAccount { | ||||
|                         pubkey: pubkey.to_string(), | ||||
|                         account: UiAccount::encode(&pubkey, account, encoding.clone(), None), | ||||
|                         account: UiAccount::encode( | ||||
|                             &pubkey, | ||||
|                             account, | ||||
|                             encoding.clone(), | ||||
|                             None, | ||||
|                             data_slice_config, | ||||
|                         ), | ||||
|                     }) | ||||
|                     .collect() | ||||
|             }; | ||||
|         Ok(accounts) | ||||
|         Ok(result) | ||||
|     } | ||||
|  | ||||
|     pub fn get_inflation_governor( | ||||
| @@ -1058,6 +1073,8 @@ impl JsonRpcRequestProcessor { | ||||
|         let config = config.unwrap_or_default(); | ||||
|         let bank = self.bank(config.commitment)?; | ||||
|         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 mut filters = vec![ | ||||
| @@ -1085,7 +1102,13 @@ impl JsonRpcRequestProcessor { | ||||
|             keyed_accounts | ||||
|                 .map(|(pubkey, account)| RpcKeyedAccount { | ||||
|                     pubkey: pubkey.to_string(), | ||||
|                     account: UiAccount::encode(&pubkey, account, encoding.clone(), None), | ||||
|                     account: UiAccount::encode( | ||||
|                         &pubkey, | ||||
|                         account, | ||||
|                         encoding.clone(), | ||||
|                         None, | ||||
|                         data_slice_config, | ||||
|                     ), | ||||
|                 }) | ||||
|                 .collect() | ||||
|         }; | ||||
| @@ -1101,6 +1124,8 @@ impl JsonRpcRequestProcessor { | ||||
|         let config = config.unwrap_or_default(); | ||||
|         let bank = self.bank(config.commitment)?; | ||||
|         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 mut filters = vec![ | ||||
| @@ -1136,7 +1161,13 @@ impl JsonRpcRequestProcessor { | ||||
|             keyed_accounts | ||||
|                 .map(|(pubkey, account)| RpcKeyedAccount { | ||||
|                     pubkey: pubkey.to_string(), | ||||
|                     account: UiAccount::encode(&pubkey, account, encoding.clone(), None), | ||||
|                     account: UiAccount::encode( | ||||
|                         &pubkey, | ||||
|                         account, | ||||
|                         encoding.clone(), | ||||
|                         None, | ||||
|                         data_slice_config, | ||||
|                     ), | ||||
|                 }) | ||||
|                 .collect() | ||||
|         }; | ||||
| @@ -1196,6 +1227,26 @@ fn run_transaction_simulation( | ||||
|     (executed[0].0.clone().map(|_| ()), log_collector.output()) | ||||
| } | ||||
|  | ||||
| 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 | ||||
| fn get_filtered_program_accounts( | ||||
|     bank: &Arc<Bank>, | ||||
| @@ -1228,6 +1279,7 @@ pub(crate) fn get_parsed_token_account( | ||||
|         account, | ||||
|         UiAccountEncoding::JsonParsed, | ||||
|         additional_data, | ||||
|         None, | ||||
|     ) | ||||
| } | ||||
|  | ||||
| @@ -1256,6 +1308,7 @@ where | ||||
|                 account, | ||||
|                 UiAccountEncoding::JsonParsed, | ||||
|                 additional_data, | ||||
|                 None, | ||||
|             ), | ||||
|         } | ||||
|     }) | ||||
| @@ -2996,13 +3049,13 @@ pub mod tests { | ||||
|     #[test] | ||||
|     fn test_rpc_get_account_info() { | ||||
|         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!( | ||||
|             r#"{{"jsonrpc":"2.0","id":1,"method":"getAccountInfo","params":["{}"]}}"#, | ||||
|             bob_pubkey | ||||
|         ); | ||||
|         let res = io.handle_request_sync(&req, meta); | ||||
|         let res = io.handle_request_sync(&req, meta.clone()); | ||||
|         let expected = json!({ | ||||
|             "jsonrpc": "2.0", | ||||
|             "result": { | ||||
| @@ -3022,6 +3075,54 @@ pub mod tests { | ||||
|         let result: Response = serde_json::from_str(&res.expect("actual response")) | ||||
|             .expect("actual response deserialization"); | ||||
|         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] | ||||
|   | ||||
| @@ -562,6 +562,7 @@ mod tests { | ||||
|             Some(RpcAccountInfoConfig { | ||||
|                 commitment: Some(CommitmentConfig::recent()), | ||||
|                 encoding: None, | ||||
|                 data_slice: None, | ||||
|             }), | ||||
|         ); | ||||
|  | ||||
| @@ -677,6 +678,7 @@ mod tests { | ||||
|             Some(RpcAccountInfoConfig { | ||||
|                 commitment: Some(CommitmentConfig::recent()), | ||||
|                 encoding: Some(UiAccountEncoding::JsonParsed), | ||||
|                 data_slice: None, | ||||
|             }), | ||||
|         ); | ||||
|  | ||||
| @@ -806,6 +808,7 @@ mod tests { | ||||
|             Some(RpcAccountInfoConfig { | ||||
|                 commitment: Some(CommitmentConfig::root()), | ||||
|                 encoding: None, | ||||
|                 data_slice: None, | ||||
|             }), | ||||
|         ); | ||||
|  | ||||
| @@ -862,6 +865,7 @@ mod tests { | ||||
|             Some(RpcAccountInfoConfig { | ||||
|                 commitment: Some(CommitmentConfig::root()), | ||||
|                 encoding: None, | ||||
|                 data_slice: None, | ||||
|             }), | ||||
|         ); | ||||
|  | ||||
|   | ||||
| @@ -275,7 +275,7 @@ fn filter_account_result( | ||||
|             } else { | ||||
|                 return ( | ||||
|                     Box::new(iter::once(UiAccount::encode( | ||||
|                         pubkey, account, encoding, None, | ||||
|                         pubkey, account, encoding, None, None, | ||||
|                     ))), | ||||
|                     fork, | ||||
|                 ); | ||||
| @@ -326,7 +326,7 @@ fn filter_program_results( | ||||
|             Box::new( | ||||
|                 keyed_accounts.map(move |(pubkey, account)| RpcKeyedAccount { | ||||
|                     pubkey: pubkey.to_string(), | ||||
|                     account: UiAccount::encode(&pubkey, account, encoding.clone(), None), | ||||
|                     account: UiAccount::encode(&pubkey, account, encoding.clone(), None, None), | ||||
|                 }), | ||||
|             ) | ||||
|         }; | ||||
| @@ -1056,6 +1056,7 @@ pub(crate) mod tests { | ||||
|             Some(RpcAccountInfoConfig { | ||||
|                 commitment: Some(CommitmentConfig::recent()), | ||||
|                 encoding: None, | ||||
|                 data_slice: None, | ||||
|             }), | ||||
|             sub_id.clone(), | ||||
|             subscriber, | ||||
| @@ -1552,6 +1553,7 @@ pub(crate) mod tests { | ||||
|             Some(RpcAccountInfoConfig { | ||||
|                 commitment: Some(CommitmentConfig::single_gossip()), | ||||
|                 encoding: None, | ||||
|                 data_slice: None, | ||||
|             }), | ||||
|             sub_id0.clone(), | ||||
|             subscriber0, | ||||
| @@ -1620,6 +1622,7 @@ pub(crate) mod tests { | ||||
|             Some(RpcAccountInfoConfig { | ||||
|                 commitment: Some(CommitmentConfig::single_gossip()), | ||||
|                 encoding: None, | ||||
|                 data_slice: None, | ||||
|             }), | ||||
|             sub_id1.clone(), | ||||
|             subscriber1, | ||||
|   | ||||
| @@ -105,6 +105,7 @@ fn test_rpc_send_tx() { | ||||
|     let config = RpcAccountInfoConfig { | ||||
|         encoding: Some(UiAccountEncoding::Binary64), | ||||
|         commitment: None, | ||||
|         data_slice: None, | ||||
|     }; | ||||
|     let req = json_req!( | ||||
|         "getAccountInfo", | ||||
|   | ||||
| @@ -158,6 +158,7 @@ Returns all information associated with the account of provided Pubkey | ||||
|   - (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. | ||||
|     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: | ||||
|  | ||||
| @@ -845,6 +846,7 @@ Returns all accounts owned by the provided program Pubkey | ||||
|   - (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. | ||||
|     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 | ||||
|  | ||||
| ##### Filters: | ||||
| @@ -1099,6 +1101,7 @@ Returns all SPL Token accounts by approved Delegate. **UNSTABLE** | ||||
|   - (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. | ||||
|     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: | ||||
|  | ||||
| @@ -1135,6 +1138,7 @@ Returns all SPL Token accounts by token owner. **UNSTABLE** | ||||
|   - (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. | ||||
|     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: | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user