feat: return bank/block info with block-related results (#6716)
This commit is contained in:
parent
2688ae614c
commit
5903339c17
|
@ -96,6 +96,13 @@ If commitment configuration is not provided, the node will default to `"commitme
|
|||
|
||||
Only methods that query bank state accept the commitment parameter. They are indicated in the API Reference below.
|
||||
|
||||
#### RpcResponse Structure
|
||||
Many methods that take a commitment parameter return an RpcResponse JSON object comprised of two parts:
|
||||
|
||||
* `context` : An RpcResponseContext JSON structure including a `slot` field at which the operation was evaluated.
|
||||
* `value` : The value returned by the operation itself.
|
||||
|
||||
|
||||
## JSON RPC API Reference
|
||||
|
||||
### confirmTransaction
|
||||
|
@ -109,7 +116,7 @@ Returns a transaction receipt
|
|||
|
||||
#### Results:
|
||||
|
||||
* `boolean` - Transaction status, true if Transaction is confirmed
|
||||
* `RpcResponse<boolean>` - RpcResponse JSON object with `value` field set to Transaction status, boolean true if Transaction is confirmed
|
||||
|
||||
#### Example:
|
||||
|
||||
|
@ -118,7 +125,7 @@ Returns a transaction receipt
|
|||
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0", "id":1, "method":"confirmTransaction", "params":["5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW"]}' http://localhost:8899
|
||||
|
||||
// Result
|
||||
{"jsonrpc":"2.0","result":true,"id":1}
|
||||
{"jsonrpc":"2.0","result":{"context":{"slot":1},"value":true},"id":1}
|
||||
```
|
||||
|
||||
### getAccountInfo
|
||||
|
@ -132,8 +139,9 @@ Returns all information associated with the account of provided Pubkey
|
|||
|
||||
#### Results:
|
||||
|
||||
The result field will be a JSON object with the following sub fields:
|
||||
The result value will be an RpcResponse JSON object containing an AccountInfo JSON object.
|
||||
|
||||
* `RpcResponse<AccountInfo>`, RpcResponse JSON object with `value` field set to AccountInfo, a JSON object containing:
|
||||
* `lamports`, number of lamports assigned to this account, as a signed 64-bit integer
|
||||
* `owner`, array of 32 bytes representing the program this account has been assigned to
|
||||
* `data`, array of bytes representing any data associated with the account
|
||||
|
@ -146,7 +154,7 @@ The result field will be a JSON object with the following sub fields:
|
|||
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0", "id":1, "method":"getAccountInfo", "params":["2gVkYWexTHR5Hb2aLeQN3tnngvWzisFKXDUPrgMHpdST"]}' http://localhost:8899
|
||||
|
||||
// Result
|
||||
{"jsonrpc":"2.0","result":{"executable":false,"owner":[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"lamports":1,"data":[3,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0.21.0,0,0,0,0,0,0,50,48,53,48,45,48,49,45,48,49,84,48,48,58,48,48,58,48,48,90,252,10,7,28,246,140,88,177,98,82,10,227,89,81,18,30,194,101,199,16,11,73,133,20,246,62,114,39,20,113,189,32,50,0,0,0,0,0,0,0,247,15,36,102,167,83,225,42,133,127,82,34,36,224,207,130,109,230,224,188,163,33,213,13,5,117,211,251,65,159,197,51,0,0,0,0,0,0]},"id":1}
|
||||
{"jsonrpc":"2.0","result":{"context":{"slot":1},"value":{"executable":false,"owner":[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"lamports":1,"data":[3,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0.21.0,0,0,0,0,0,0,50,48,53,48,45,48,49,45,48,49,84,48,48,58,48,48,58,48,48,90,252,10,7,28,246,140,88,177,98,82,10,227,89,81,18,30,194,101,199,16,11,73,133,20,246,62,114,39,20,113,189,32,50,0,0,0,0,0,0,0,247,15,36,102,167,83,225,42,133,127,82,34,36,224,207,130,109,230,224,188,163,33,213,13,5,117,211,251,65,159,197,51,0,0,0,0,0,0]}},"id":1}
|
||||
```
|
||||
|
||||
### getBalance
|
||||
|
@ -160,7 +168,7 @@ Returns the balance of the account of provided Pubkey
|
|||
|
||||
#### Results:
|
||||
|
||||
* `integer` - quantity, as a signed 64-bit integer
|
||||
* `RpcResponse<integer>` - RpcResponse JSON object with `value` field set to quantity, as a signed 64-bit integer
|
||||
|
||||
#### Example:
|
||||
|
||||
|
@ -169,7 +177,7 @@ Returns the balance of the account of provided Pubkey
|
|||
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0", "id":1, "method":"getBalance", "params":["83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri"]}' http://localhost:8899
|
||||
|
||||
// Result
|
||||
{"jsonrpc":"2.0","result":0,"id":1}
|
||||
{"jsonrpc":"2.0","result":{"context":{"slot":1},"value":0},"id":1}
|
||||
```
|
||||
|
||||
### getBlockCommitment
|
||||
|
@ -410,8 +418,9 @@ Returns a recent block hash from the ledger, and a fee schedule that can be used
|
|||
|
||||
#### Results:
|
||||
|
||||
An array consisting of
|
||||
An RpcResponse containing an array consisting of a string blockhash and FeeCalculator JSON object.
|
||||
|
||||
* `RpcResponse<array>` - RpcResponse JSON object with `value` field set to an array including:
|
||||
* `string` - a Hash as base-58 encoded string
|
||||
* `FeeCalculator object` - the fee schedule for this block hash
|
||||
|
||||
|
@ -422,7 +431,7 @@ An array consisting of
|
|||
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "method":"getRecentBlockhash"}' http://localhost:8899
|
||||
|
||||
// Result
|
||||
{"jsonrpc":"2.0","result":["GH7ome3EiwEr7tu9JuTh2dpYWBJK3z69Xm1ZE3MEE6JC",{"lamportsPerSignature": 0}],"id":1}
|
||||
{"jsonrpc":"2.0","result":{"context":{"slot":1},"value":["GH7ome3EiwEr7tu9JuTh2dpYWBJK3z69Xm1ZE3MEE6JC",{"lamportsPerSignature": 0}]},"id":1}
|
||||
```
|
||||
|
||||
### getSignatureStatus
|
||||
|
|
|
@ -3,7 +3,7 @@ use solana_cli::cli::{process_command, CliCommand, CliConfig};
|
|||
use solana_client::rpc_client::RpcClient;
|
||||
use solana_core::validator::new_validator_for_tests;
|
||||
use solana_drone::drone::run_local_drone;
|
||||
use solana_sdk::{bpf_loader, commitment_config::CommitmentConfig, pubkey::Pubkey};
|
||||
use solana_sdk::{bpf_loader, pubkey::Pubkey};
|
||||
use std::{
|
||||
fs::{remove_dir_all, File},
|
||||
io::Read,
|
||||
|
@ -59,10 +59,7 @@ fn test_cli_deploy_program() {
|
|||
.as_str()
|
||||
.unwrap();
|
||||
let program_id = Pubkey::from_str(&program_id_str).unwrap();
|
||||
|
||||
let account = rpc_client
|
||||
.get_account_with_commitment(&program_id, CommitmentConfig::recent())
|
||||
.unwrap();
|
||||
let account = rpc_client.get_account(&program_id).unwrap();
|
||||
assert_eq!(account.lamports, minimum_balance_for_rent_exemption);
|
||||
assert_eq!(account.owner, bpf_loader::id());
|
||||
assert_eq!(account.executable, true);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::rpc_request::{Response, RpcResponseContext};
|
||||
use crate::{
|
||||
client_error::ClientError, generic_rpc_client_request::GenericRpcClientRequest,
|
||||
rpc_request::RpcRequest,
|
||||
|
@ -48,12 +49,18 @@ impl GenericRpcClientRequest for MockRpcClientRequest {
|
|||
}
|
||||
RpcRequest::GetBalance => {
|
||||
let n = if self.url == "airdrop" { 0 } else { 50 };
|
||||
Value::Number(Number::from(n))
|
||||
serde_json::to_value(Response {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
value: Value::Number(Number::from(n)),
|
||||
})?
|
||||
}
|
||||
RpcRequest::GetRecentBlockhash => Value::Array(vec![
|
||||
Value::String(PUBKEY.to_string()),
|
||||
serde_json::to_value(FeeCalculator::default()).unwrap(),
|
||||
]),
|
||||
RpcRequest::GetRecentBlockhash => serde_json::to_value(Response {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
value: (
|
||||
Value::String(PUBKEY.to_string()),
|
||||
serde_json::to_value(FeeCalculator::default()).unwrap(),
|
||||
),
|
||||
})?,
|
||||
RpcRequest::GetSignatureStatus => {
|
||||
let response: Option<transaction::Result<()>> = if self.url == "account_in_use" {
|
||||
Some(Err(TransactionError::AccountInUse))
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::rpc_request::{Response, RpcResponse};
|
||||
use crate::{
|
||||
client_error::ClientError,
|
||||
generic_rpc_client_request::GenericRpcClientRequest,
|
||||
|
@ -55,31 +56,39 @@ impl RpcClient {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn confirm_transaction(&self, signature: &str) -> Result<bool, ClientError> {
|
||||
self.confirm_transaction_with_commitment(signature, CommitmentConfig::default())
|
||||
pub fn confirm_transaction(&self, signature: &str) -> io::Result<bool> {
|
||||
Ok(self
|
||||
.confirm_transaction_with_commitment(signature, CommitmentConfig::default())?
|
||||
.value)
|
||||
}
|
||||
|
||||
pub fn confirm_transaction_with_commitment(
|
||||
&self,
|
||||
signature: &str,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> Result<bool, ClientError> {
|
||||
) -> RpcResponse<bool> {
|
||||
let params = json!(signature);
|
||||
let response = self.client.send(
|
||||
&RpcRequest::ConfirmTransaction,
|
||||
Some(params),
|
||||
0,
|
||||
Some(commitment_config),
|
||||
)?;
|
||||
if response.as_bool().is_none() {
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"Received result of an unexpected type",
|
||||
let response = self
|
||||
.client
|
||||
.send(
|
||||
&RpcRequest::ConfirmTransaction,
|
||||
Some(params),
|
||||
0,
|
||||
Some(commitment_config),
|
||||
)
|
||||
.into())
|
||||
} else {
|
||||
Ok(response.as_bool().unwrap())
|
||||
}
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("ConfirmTransaction request failure {:?}", err),
|
||||
)
|
||||
})?;
|
||||
|
||||
serde_json::from_value::<Response<bool>>(response).map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("Received result of an unexpected type {:?}", err),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn send_transaction(&self, transaction: &Transaction) -> Result<String, ClientError> {
|
||||
|
@ -378,46 +387,69 @@ impl RpcClient {
|
|||
retries: usize,
|
||||
) -> Result<Option<u64>, Box<dyn error::Error>> {
|
||||
let params = json!(format!("{}", pubkey));
|
||||
let res = self
|
||||
let balance_json = self
|
||||
.client
|
||||
.send(&RpcRequest::GetBalance, Some(params), retries, None)?
|
||||
.as_u64();
|
||||
Ok(res)
|
||||
.send(&RpcRequest::GetBalance, Some(params), retries, None)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("RetryGetBalance request failure: {:?}", err),
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(Some(
|
||||
serde_json::from_value::<Response<u64>>(balance_json)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("RetryGetBalance parse failure: {:?}", err),
|
||||
)
|
||||
})?
|
||||
.value,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn get_account(&self, pubkey: &Pubkey) -> io::Result<Account> {
|
||||
self.get_account_with_commitment(pubkey, CommitmentConfig::default())
|
||||
Ok(self
|
||||
.get_account_with_commitment(pubkey, CommitmentConfig::default())
|
||||
.map(|x| x.value.unwrap())?)
|
||||
}
|
||||
|
||||
pub fn get_account_with_commitment(
|
||||
&self,
|
||||
pubkey: &Pubkey,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> io::Result<Account> {
|
||||
) -> RpcResponse<Option<Account>> {
|
||||
let params = json!(format!("{}", pubkey));
|
||||
let response = self.client.send(
|
||||
&RpcRequest::GetAccountInfo,
|
||||
Some(params),
|
||||
0,
|
||||
commitment_config.ok(),
|
||||
Some(commitment_config),
|
||||
);
|
||||
|
||||
response
|
||||
.and_then(|account_json| {
|
||||
let account: Account = serde_json::from_value(account_json)?;
|
||||
trace!("Response account {:?} {:?}", pubkey, account);
|
||||
Ok(account)
|
||||
.map(|result_json| {
|
||||
if result_json.is_null() {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("AccountNotFound: pubkey={}", pubkey),
|
||||
));
|
||||
}
|
||||
let result = serde_json::from_value::<Response<Option<Account>>>(result_json)?;
|
||||
trace!("Response account {:?} {:?}", pubkey, result);
|
||||
Ok(result)
|
||||
})
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("AccountNotFound: pubkey={}: {}", pubkey, err),
|
||||
)
|
||||
})
|
||||
})?
|
||||
}
|
||||
|
||||
pub fn get_account_data(&self, pubkey: &Pubkey) -> io::Result<Vec<u8>> {
|
||||
self.get_account(pubkey).map(|account| account.data)
|
||||
Ok(self.get_account(pubkey).unwrap().data)
|
||||
}
|
||||
|
||||
pub fn get_minimum_balance_for_rent_exemption(&self, data_len: usize) -> io::Result<u64> {
|
||||
|
@ -456,14 +488,16 @@ impl RpcClient {
|
|||
|
||||
/// Request the balance of the account `pubkey`.
|
||||
pub fn get_balance(&self, pubkey: &Pubkey) -> io::Result<u64> {
|
||||
self.get_balance_with_commitment(pubkey, CommitmentConfig::default())
|
||||
Ok(self
|
||||
.get_balance_with_commitment(pubkey, CommitmentConfig::default())?
|
||||
.value)
|
||||
}
|
||||
|
||||
pub fn get_balance_with_commitment(
|
||||
&self,
|
||||
pubkey: &Pubkey,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> io::Result<u64> {
|
||||
) -> RpcResponse<u64> {
|
||||
let params = json!(pubkey.to_string());
|
||||
let balance_json = self
|
||||
.client
|
||||
|
@ -479,7 +513,8 @@ impl RpcClient {
|
|||
format!("GetBalance request failure: {:?}", err),
|
||||
)
|
||||
})?;
|
||||
serde_json::from_value(balance_json).map_err(|err| {
|
||||
|
||||
serde_json::from_value::<Response<u64>>(balance_json).map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("GetBalance parse failure: {:?}", err),
|
||||
|
@ -553,13 +588,15 @@ impl RpcClient {
|
|||
}
|
||||
|
||||
pub fn get_recent_blockhash(&self) -> io::Result<(Hash, FeeCalculator)> {
|
||||
self.get_recent_blockhash_with_commitment(CommitmentConfig::default())
|
||||
Ok(self
|
||||
.get_recent_blockhash_with_commitment(CommitmentConfig::default())?
|
||||
.value)
|
||||
}
|
||||
|
||||
pub fn get_recent_blockhash_with_commitment(
|
||||
&self,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> io::Result<(Hash, FeeCalculator)> {
|
||||
) -> RpcResponse<(Hash, FeeCalculator)> {
|
||||
let response = self
|
||||
.client
|
||||
.send(
|
||||
|
@ -575,21 +612,27 @@ impl RpcClient {
|
|||
)
|
||||
})?;
|
||||
|
||||
let (blockhash, fee_calculator) =
|
||||
serde_json::from_value::<(String, FeeCalculator)>(response).map_err(|err| {
|
||||
let Response {
|
||||
context,
|
||||
value: (blockhash_str, fee_calculator),
|
||||
} = serde_json::from_value::<Response<(String, FeeCalculator)>>(response).map_err(
|
||||
|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("GetRecentBlockhash parse failure: {:?}", err),
|
||||
)
|
||||
})?;
|
||||
|
||||
let blockhash = blockhash.parse().map_err(|err| {
|
||||
},
|
||||
)?;
|
||||
let blockhash = blockhash_str.parse().map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("GetRecentBlockhash hash parse failure: {:?}", err),
|
||||
)
|
||||
})?;
|
||||
Ok((blockhash, fee_calculator))
|
||||
Ok(Response {
|
||||
context,
|
||||
value: (blockhash, fee_calculator),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_new_blockhash(&self, blockhash: &Hash) -> io::Result<(Hash, FeeCalculator)> {
|
||||
|
@ -658,7 +701,7 @@ impl RpcClient {
|
|||
loop {
|
||||
match self.get_balance_with_commitment(&pubkey, commitment_config.clone()) {
|
||||
Ok(bal) => {
|
||||
return Ok(bal);
|
||||
return Ok(bal.value);
|
||||
}
|
||||
Err(e) => {
|
||||
sleep(*polling_frequency);
|
||||
|
|
|
@ -1,9 +1,24 @@
|
|||
use jsonrpc_core::Result as JsonResult;
|
||||
use serde_json::{json, Value};
|
||||
use solana_sdk::{
|
||||
clock::{Epoch, Slot},
|
||||
commitment_config::CommitmentConfig,
|
||||
};
|
||||
use std::{error, fmt};
|
||||
use std::{error, fmt, io};
|
||||
|
||||
pub type RpcResponseIn<T> = JsonResult<Response<T>>;
|
||||
pub type RpcResponse<T> = io::Result<Response<T>>;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct RpcResponseContext {
|
||||
pub slot: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Response<T> {
|
||||
pub context: RpcResponseContext,
|
||||
pub value: T,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//! unstable and may change in future releases.
|
||||
|
||||
use crate::rpc_client::RpcClient;
|
||||
use crate::rpc_request::Response;
|
||||
use bincode::{serialize_into, serialized_size};
|
||||
use log::*;
|
||||
use solana_sdk::{
|
||||
|
@ -383,7 +384,11 @@ impl SyncClient for ThinClient {
|
|||
}
|
||||
|
||||
fn get_account(&self, pubkey: &Pubkey) -> TransportResult<Option<Account>> {
|
||||
Ok(self.rpc_client().get_account(pubkey).ok())
|
||||
let account = self.rpc_client().get_account(pubkey);
|
||||
match account {
|
||||
Ok(value) => Ok(Some(value)),
|
||||
Err(_) => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_account_with_commitment(
|
||||
|
@ -393,13 +398,12 @@ impl SyncClient for ThinClient {
|
|||
) -> TransportResult<Option<Account>> {
|
||||
Ok(self
|
||||
.rpc_client()
|
||||
.get_account_with_commitment(pubkey, commitment_config)
|
||||
.ok())
|
||||
.get_account_with_commitment(pubkey, commitment_config)?
|
||||
.value)
|
||||
}
|
||||
|
||||
fn get_balance(&self, pubkey: &Pubkey) -> TransportResult<u64> {
|
||||
let balance = self.rpc_client().get_balance(pubkey)?;
|
||||
Ok(balance)
|
||||
Ok(self.rpc_client().get_balance(pubkey)?)
|
||||
}
|
||||
|
||||
fn get_balance_with_commitment(
|
||||
|
@ -410,7 +414,7 @@ impl SyncClient for ThinClient {
|
|||
let balance = self
|
||||
.rpc_client()
|
||||
.get_balance_with_commitment(pubkey, commitment_config)?;
|
||||
Ok(balance)
|
||||
Ok(balance.value)
|
||||
}
|
||||
|
||||
fn get_recent_blockhash(&self) -> TransportResult<(Hash, FeeCalculator)> {
|
||||
|
@ -426,9 +430,9 @@ impl SyncClient for ThinClient {
|
|||
let recent_blockhash =
|
||||
self.rpc_clients[index].get_recent_blockhash_with_commitment(commitment_config);
|
||||
match recent_blockhash {
|
||||
Ok(recent_blockhash) => {
|
||||
Ok(Response { value, .. }) => {
|
||||
self.optimizer.report(index, duration_as_ms(&now.elapsed()));
|
||||
Ok(recent_blockhash)
|
||||
Ok(value)
|
||||
}
|
||||
Err(e) => {
|
||||
self.optimizer.report(index, std::u64::MAX);
|
||||
|
|
156
core/src/rpc.rs
156
core/src/rpc.rs
|
@ -12,7 +12,9 @@ use crate::{
|
|||
use bincode::serialize;
|
||||
use jsonrpc_core::{Error, Metadata, Result};
|
||||
use jsonrpc_derive::rpc;
|
||||
use solana_client::rpc_request::{RpcEpochInfo, RpcVoteAccountInfo, RpcVoteAccountStatus};
|
||||
use solana_client::rpc_request::{
|
||||
Response, RpcEpochInfo, RpcResponseContext, RpcVoteAccountInfo, RpcVoteAccountStatus,
|
||||
};
|
||||
use solana_drone::drone::request_airdrop_transaction;
|
||||
use solana_ledger::{
|
||||
bank_forks::BankForks, blocktree::Blocktree, rooted_slot_iterator::RootedSlotIterator,
|
||||
|
@ -40,6 +42,13 @@ use std::{
|
|||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
type RpcResponse<T> = Result<Response<T>>;
|
||||
|
||||
fn new_response<T>(bank: &Bank, value: T) -> RpcResponse<T> {
|
||||
let context = RpcResponseContext { slot: bank.slot() };
|
||||
Ok(Response { context, value })
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct JsonRpcConfig {
|
||||
pub enable_validator_exit: bool, // Enable the 'validatorExit' command
|
||||
|
@ -100,12 +109,14 @@ impl JsonRpcRequestProcessor {
|
|||
|
||||
pub fn get_account_info(
|
||||
&self,
|
||||
pubkey: &Pubkey,
|
||||
pubkey: Result<Pubkey>,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<Account> {
|
||||
self.bank(commitment)
|
||||
.get_account(&pubkey)
|
||||
.ok_or_else(Error::invalid_request)
|
||||
) -> RpcResponse<Option<Account>> {
|
||||
let bank = &*self.bank(commitment);
|
||||
match pubkey {
|
||||
Ok(key) => new_response(bank, bank.get_account(&key)),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_minimum_balance_for_rent_exemption(
|
||||
|
@ -141,16 +152,43 @@ impl JsonRpcRequestProcessor {
|
|||
Ok(*self.bank(None).epoch_schedule())
|
||||
}
|
||||
|
||||
pub fn get_balance(&self, pubkey: &Pubkey, commitment: Option<CommitmentConfig>) -> u64 {
|
||||
self.bank(commitment).get_balance(&pubkey)
|
||||
pub fn get_balance(
|
||||
&self,
|
||||
pubkey: Result<Pubkey>,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> RpcResponse<u64> {
|
||||
let bank = &*self.bank(commitment);
|
||||
match pubkey {
|
||||
Ok(key) => new_response(bank, bank.get_balance(&key)),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_recent_blockhash(
|
||||
&self,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> (String, FeeCalculator) {
|
||||
let (blockhash, fee_calculator) = self.bank(commitment).confirmed_last_blockhash();
|
||||
(blockhash.to_string(), fee_calculator)
|
||||
) -> RpcResponse<(String, FeeCalculator)> {
|
||||
let bank = &*self.bank(commitment);
|
||||
let (blockhash, fee_calculator) = bank.confirmed_last_blockhash();
|
||||
new_response(bank, (blockhash.to_string(), fee_calculator))
|
||||
}
|
||||
|
||||
pub fn confirm_transaction(
|
||||
&self,
|
||||
signature: Result<Signature>,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> RpcResponse<bool> {
|
||||
let bank = &*self.bank(commitment);
|
||||
match signature {
|
||||
Err(e) => Err(e),
|
||||
Ok(sig) => {
|
||||
let status = bank.get_signature_confirmation_status(&sig);
|
||||
match status {
|
||||
Some((_, result)) => new_response(bank, result.is_ok()),
|
||||
None => new_response(bank, false),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_block_commitment(&self, block: Slot) -> (Option<BlockCommitment>, u64) {
|
||||
|
@ -333,7 +371,7 @@ pub trait RpcSol {
|
|||
meta: Self::Metadata,
|
||||
signature_str: String,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<bool>;
|
||||
) -> RpcResponse<bool>;
|
||||
|
||||
#[rpc(meta, name = "getAccountInfo")]
|
||||
fn get_account_info(
|
||||
|
@ -341,7 +379,7 @@ pub trait RpcSol {
|
|||
meta: Self::Metadata,
|
||||
pubkey_str: String,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<Account>;
|
||||
) -> RpcResponse<Option<Account>>;
|
||||
|
||||
#[rpc(meta, name = "getProgramAccounts")]
|
||||
fn get_program_accounts(
|
||||
|
@ -375,7 +413,7 @@ pub trait RpcSol {
|
|||
meta: Self::Metadata,
|
||||
pubkey_str: String,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<u64>;
|
||||
) -> RpcResponse<u64>;
|
||||
|
||||
#[rpc(meta, name = "getClusterNodes")]
|
||||
fn get_cluster_nodes(&self, meta: Self::Metadata) -> Result<Vec<RpcContactInfo>>;
|
||||
|
@ -409,7 +447,7 @@ pub trait RpcSol {
|
|||
&self,
|
||||
meta: Self::Metadata,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<(String, FeeCalculator)>;
|
||||
) -> RpcResponse<(String, FeeCalculator)>;
|
||||
|
||||
#[rpc(meta, name = "getSignatureStatus")]
|
||||
fn get_signature_status(
|
||||
|
@ -521,20 +559,15 @@ impl RpcSol for RpcSolImpl {
|
|||
fn confirm_transaction(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
signature_str: String,
|
||||
id: String,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<bool> {
|
||||
debug!(
|
||||
"confirm_transaction rpc request received: {:?}",
|
||||
signature_str
|
||||
);
|
||||
self.get_signature_status(meta, signature_str, commitment)
|
||||
.map(|status_option| {
|
||||
if status_option.is_none() {
|
||||
return false;
|
||||
}
|
||||
status_option.unwrap().is_ok()
|
||||
})
|
||||
) -> RpcResponse<bool> {
|
||||
debug!("confirm_transaction rpc request received: {:?}", id);
|
||||
let signature = verify_signature(&id);
|
||||
meta.request_processor
|
||||
.read()
|
||||
.unwrap()
|
||||
.confirm_transaction(signature, commitment)
|
||||
}
|
||||
|
||||
fn get_account_info(
|
||||
|
@ -542,13 +575,13 @@ impl RpcSol for RpcSolImpl {
|
|||
meta: Self::Metadata,
|
||||
pubkey_str: String,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<Account> {
|
||||
) -> RpcResponse<Option<Account>> {
|
||||
debug!("get_account_info rpc request received: {:?}", pubkey_str);
|
||||
let pubkey = verify_pubkey(pubkey_str)?;
|
||||
let pubkey = verify_pubkey(pubkey_str);
|
||||
meta.request_processor
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_account_info(&pubkey, commitment)
|
||||
.get_account_info(pubkey, commitment)
|
||||
}
|
||||
|
||||
fn get_minimum_balance_for_rent_exemption(
|
||||
|
@ -613,14 +646,13 @@ impl RpcSol for RpcSolImpl {
|
|||
meta: Self::Metadata,
|
||||
pubkey_str: String,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<u64> {
|
||||
) -> RpcResponse<u64> {
|
||||
debug!("get_balance rpc request received: {:?}", pubkey_str);
|
||||
let pubkey = verify_pubkey(pubkey_str)?;
|
||||
Ok(meta
|
||||
.request_processor
|
||||
let pubkey = verify_pubkey(pubkey_str);
|
||||
meta.request_processor
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_balance(&pubkey, commitment))
|
||||
.get_balance(pubkey, commitment)
|
||||
}
|
||||
|
||||
fn get_cluster_nodes(&self, meta: Self::Metadata) -> Result<Vec<RpcContactInfo>> {
|
||||
|
@ -707,13 +739,12 @@ impl RpcSol for RpcSolImpl {
|
|||
&self,
|
||||
meta: Self::Metadata,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
) -> Result<(String, FeeCalculator)> {
|
||||
) -> RpcResponse<(String, FeeCalculator)> {
|
||||
debug!("get_recent_blockhash rpc request received");
|
||||
Ok(meta
|
||||
.request_processor
|
||||
meta.request_processor
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_recent_blockhash(commitment))
|
||||
.get_recent_blockhash(commitment)
|
||||
}
|
||||
|
||||
fn get_signature_status(
|
||||
|
@ -1150,10 +1181,15 @@ pub mod tests {
|
|||
bob_pubkey
|
||||
);
|
||||
let res = io.handle_request_sync(&req, meta);
|
||||
let expected = format!(r#"{{"jsonrpc":"2.0","result":20,"id":1}}"#);
|
||||
let expected: Response =
|
||||
serde_json::from_str(&expected).expect("expected response deserialization");
|
||||
let result: Response = serde_json::from_str(&res.expect("actual response"))
|
||||
let expected = json!({
|
||||
"jsonrpc": "2.0",
|
||||
"result": {
|
||||
"context":{"slot":0},
|
||||
"value":20,
|
||||
},
|
||||
"id": 1,
|
||||
});
|
||||
let result = serde_json::from_str::<Value>(&res.expect("actual response"))
|
||||
.expect("actual response deserialization");
|
||||
assert_eq!(expected, result);
|
||||
}
|
||||
|
@ -1328,19 +1364,22 @@ pub mod tests {
|
|||
bob_pubkey
|
||||
);
|
||||
let res = io.handle_request_sync(&req, meta);
|
||||
let expected = r#"{
|
||||
"jsonrpc":"2.0",
|
||||
"result":{
|
||||
let expected = json!({
|
||||
"jsonrpc": "2.0",
|
||||
"result": {
|
||||
"context":{"slot":0},
|
||||
"value":{
|
||||
"owner": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
|
||||
"lamports": 20,
|
||||
"data": [],
|
||||
"executable": false,
|
||||
"rent_epoch": 0
|
||||
},
|
||||
"id":1}
|
||||
"#;
|
||||
},
|
||||
"id": 1,
|
||||
});
|
||||
let expected: Response =
|
||||
serde_json::from_str(&expected).expect("expected response deserialization");
|
||||
serde_json::from_value(expected).expect("expected response deserialization");
|
||||
let result: Response = serde_json::from_str(&res.expect("actual response"))
|
||||
.expect("actual response deserialization");
|
||||
assert_eq!(expected, result);
|
||||
|
@ -1404,9 +1443,16 @@ pub mod tests {
|
|||
tx.signatures[0]
|
||||
);
|
||||
let res = io.handle_request_sync(&req, meta);
|
||||
let expected = format!(r#"{{"jsonrpc":"2.0","result":true,"id":1}}"#);
|
||||
let expected = json!({
|
||||
"jsonrpc": "2.0",
|
||||
"result": {
|
||||
"context":{"slot":0},
|
||||
"value":true,
|
||||
},
|
||||
"id": 1,
|
||||
});
|
||||
let expected: Response =
|
||||
serde_json::from_str(&expected).expect("expected response deserialization");
|
||||
serde_json::from_value(expected).expect("expected response deserialization");
|
||||
let result: Response = serde_json::from_str(&res.expect("actual response"))
|
||||
.expect("actual response deserialization");
|
||||
assert_eq!(expected, result);
|
||||
|
@ -1496,14 +1542,16 @@ pub mod tests {
|
|||
let res = io.handle_request_sync(&req, meta);
|
||||
let expected = json!({
|
||||
"jsonrpc": "2.0",
|
||||
"result": [ blockhash.to_string(), {
|
||||
"result": {
|
||||
"context":{"slot":0},
|
||||
"value":[ blockhash.to_string(), {
|
||||
"burnPercent": DEFAULT_BURN_PERCENT,
|
||||
"lamportsPerSignature": 0,
|
||||
"maxLamportsPerSignature": 0,
|
||||
"minLamportsPerSignature": 0,
|
||||
"targetLamportsPerSignature": 0,
|
||||
"targetSignaturesPerSlot": 0
|
||||
}],
|
||||
}]},
|
||||
"id": 1
|
||||
});
|
||||
let expected: Response =
|
||||
|
|
|
@ -229,7 +229,9 @@ mod tests {
|
|||
.request_processor
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_balance(&mint_keypair.pubkey(), None)
|
||||
.get_balance(Ok(mint_keypair.pubkey()), None)
|
||||
.unwrap()
|
||||
.value
|
||||
);
|
||||
rpc_service.exit();
|
||||
rpc_service.join().unwrap();
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use solana_client::rpc_client::RpcClient;
|
||||
use solana_core::validator::new_validator_for_tests;
|
||||
use solana_sdk::commitment_config::CommitmentConfig;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::signature::KeypairUtil;
|
||||
use solana_sdk::system_transaction;
|
||||
|
@ -22,7 +23,6 @@ fn test_rpc_client() {
|
|||
);
|
||||
|
||||
assert_eq!(client.get_balance(&bob_pubkey).unwrap(), 0);
|
||||
|
||||
assert_eq!(client.get_balance(&alice.pubkey()).unwrap(), 10000);
|
||||
|
||||
let (blockhash, _fee_calculator) = client.get_recent_blockhash().unwrap();
|
||||
|
@ -34,14 +34,13 @@ fn test_rpc_client() {
|
|||
|
||||
let now = Instant::now();
|
||||
while now.elapsed().as_secs() <= 20 {
|
||||
let response = client.confirm_transaction(signature.as_str());
|
||||
let response = client
|
||||
.confirm_transaction_with_commitment(signature.as_str(), CommitmentConfig::default())
|
||||
.unwrap();
|
||||
|
||||
match response {
|
||||
Ok(true) => {
|
||||
confirmed_tx = true;
|
||||
break;
|
||||
}
|
||||
_ => (),
|
||||
if response.value {
|
||||
confirmed_tx = true;
|
||||
break;
|
||||
}
|
||||
|
||||
sleep(Duration::from_millis(500));
|
||||
|
|
|
@ -34,7 +34,11 @@ fn test_rpc_send_tx() {
|
|||
.send()
|
||||
.unwrap();
|
||||
let json: Value = serde_json::from_str(&response.text().unwrap()).unwrap();
|
||||
let blockhash: Hash = json["result"][0].as_str().unwrap().parse().unwrap();
|
||||
let blockhash: Hash = json["result"]["value"][0]
|
||||
.as_str()
|
||||
.unwrap()
|
||||
.parse()
|
||||
.unwrap();
|
||||
|
||||
info!("blockhash: {:?}", blockhash);
|
||||
let tx = system_transaction::transfer(&alice, &bob_pubkey, 20, blockhash);
|
||||
|
@ -78,7 +82,7 @@ fn test_rpc_send_tx() {
|
|||
let response_json_text = response.text().unwrap();
|
||||
let json: Value = serde_json::from_str(&response_json_text).unwrap();
|
||||
|
||||
if true == json["result"] {
|
||||
if true == json["result"]["value"] {
|
||||
confirmed_tx = true;
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue