RPC: Add API version to context response (#25134)
* RPC: Add API version to context response * restore backwards compatibility
This commit is contained in:
parent
9d18fe019b
commit
a118af069e
|
@ -6103,6 +6103,7 @@ version = "1.11.0"
|
|||
dependencies = [
|
||||
"log",
|
||||
"rustc_version",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"solana-frozen-abi 1.11.0",
|
||||
|
|
|
@ -163,7 +163,10 @@ mod tests {
|
|||
fn test_check_account_for_fees() {
|
||||
let account_balance = 1;
|
||||
let account_balance_response = json!(Response {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
context: RpcResponseContext {
|
||||
slot: 1,
|
||||
api_version: None
|
||||
},
|
||||
value: json!(account_balance),
|
||||
});
|
||||
let pubkey = solana_sdk::pubkey::new_rand();
|
||||
|
@ -183,7 +186,10 @@ mod tests {
|
|||
check_account_for_fee(&rpc_client, &pubkey, &message0).expect("unexpected result");
|
||||
|
||||
let check_fee_response = json!(Response {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
context: RpcResponseContext {
|
||||
slot: 1,
|
||||
api_version: None
|
||||
},
|
||||
value: json!(2),
|
||||
});
|
||||
let mut mocks = HashMap::new();
|
||||
|
@ -193,7 +199,10 @@ mod tests {
|
|||
assert!(check_account_for_fee(&rpc_client, &pubkey, &message1).is_err());
|
||||
|
||||
let check_fee_response = json!(Response {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
context: RpcResponseContext {
|
||||
slot: 1,
|
||||
api_version: None
|
||||
},
|
||||
value: json!(2),
|
||||
});
|
||||
let mut mocks = HashMap::new();
|
||||
|
@ -206,11 +215,17 @@ mod tests {
|
|||
|
||||
let account_balance = 2;
|
||||
let account_balance_response = json!(Response {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
context: RpcResponseContext {
|
||||
slot: 1,
|
||||
api_version: None
|
||||
},
|
||||
value: json!(account_balance),
|
||||
});
|
||||
let check_fee_response = json!(Response {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
context: RpcResponseContext {
|
||||
slot: 1,
|
||||
api_version: None
|
||||
},
|
||||
value: json!(1),
|
||||
});
|
||||
|
||||
|
@ -227,7 +242,10 @@ mod tests {
|
|||
fn test_check_account_for_balance() {
|
||||
let account_balance = 50;
|
||||
let account_balance_response = json!(Response {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
context: RpcResponseContext {
|
||||
slot: 1,
|
||||
api_version: None
|
||||
},
|
||||
value: json!(account_balance),
|
||||
});
|
||||
let pubkey = solana_sdk::pubkey::new_rand();
|
||||
|
@ -244,7 +262,10 @@ mod tests {
|
|||
#[test]
|
||||
fn test_get_fee_for_messages() {
|
||||
let check_fee_response = json!(Response {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
context: RpcResponseContext {
|
||||
slot: 1,
|
||||
api_version: None
|
||||
},
|
||||
value: json!(1),
|
||||
});
|
||||
let mut mocks = HashMap::new();
|
||||
|
@ -263,7 +284,10 @@ mod tests {
|
|||
|
||||
// No signatures, no fee.
|
||||
let check_fee_response = json!(Response {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
context: RpcResponseContext {
|
||||
slot: 1,
|
||||
api_version: None
|
||||
},
|
||||
value: json!(0),
|
||||
});
|
||||
let mut mocks = HashMap::new();
|
||||
|
|
|
@ -1986,7 +1986,10 @@ mod tests {
|
|||
assert!(result.is_ok());
|
||||
|
||||
let vote_account_info_response = json!(Response {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
context: RpcResponseContext {
|
||||
slot: 1,
|
||||
api_version: None
|
||||
},
|
||||
value: json!({
|
||||
"data": ["KLUv/QBYNQIAtAIBAAAAbnoc3Smwt4/ROvTFWY/v9O8qlxZuPKby5Pv8zYBQW/EFAAEAAB8ACQD6gx92zAiAAecDP4B2XeEBSIx7MQeung==", "base64+zstd"],
|
||||
"lamports": 42,
|
||||
|
@ -2272,7 +2275,10 @@ mod tests {
|
|||
// Success case
|
||||
let mut config = CliConfig::default();
|
||||
let account_info_response = json!(Response {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
context: RpcResponseContext {
|
||||
slot: 1,
|
||||
api_version: None
|
||||
},
|
||||
value: Value::Null,
|
||||
});
|
||||
let mut mocks = HashMap::new();
|
||||
|
|
|
@ -355,7 +355,10 @@ mod tests {
|
|||
let rpc_blockhash = hash(&[1u8]);
|
||||
let rpc_fee_calc = FeeCalculator::new(42);
|
||||
let get_recent_blockhash_response = json!(Response {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
context: RpcResponseContext {
|
||||
slot: 1,
|
||||
api_version: None
|
||||
},
|
||||
value: json!(RpcFees {
|
||||
blockhash: rpc_blockhash.to_string(),
|
||||
fee_calculator: rpc_fee_calc.clone(),
|
||||
|
@ -364,7 +367,10 @@ mod tests {
|
|||
}),
|
||||
});
|
||||
let get_fee_calculator_for_blockhash_response = json!(Response {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
context: RpcResponseContext {
|
||||
slot: 1,
|
||||
api_version: None
|
||||
},
|
||||
value: json!(RpcFeeCalculator {
|
||||
fee_calculator: rpc_fee_calc.clone()
|
||||
}),
|
||||
|
@ -428,7 +434,10 @@ mod tests {
|
|||
None,
|
||||
);
|
||||
let get_account_response = json!(Response {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
context: RpcResponseContext {
|
||||
slot: 1,
|
||||
api_version: None
|
||||
},
|
||||
value: json!(Some(rpc_nonce_account)),
|
||||
});
|
||||
|
||||
|
|
|
@ -108,15 +108,15 @@ impl RpcSender for MockSender {
|
|||
|
||||
let val = match method.as_str().unwrap() {
|
||||
"getAccountInfo" => serde_json::to_value(Response {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
context: RpcResponseContext { slot: 1, api_version: None },
|
||||
value: Value::Null,
|
||||
})?,
|
||||
"getBalance" => serde_json::to_value(Response {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
context: RpcResponseContext { slot: 1, api_version: None },
|
||||
value: Value::Number(Number::from(50)),
|
||||
})?,
|
||||
"getRecentBlockhash" => serde_json::to_value(Response {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
context: RpcResponseContext { slot: 1, api_version: None },
|
||||
value: (
|
||||
Value::String(PUBKEY.to_string()),
|
||||
serde_json::to_value(FeeCalculator::default()).unwrap(),
|
||||
|
@ -137,16 +137,16 @@ impl RpcSender for MockSender {
|
|||
serde_json::to_value(Some(FeeCalculator::default())).unwrap()
|
||||
};
|
||||
serde_json::to_value(Response {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
context: RpcResponseContext { slot: 1, api_version: None },
|
||||
value,
|
||||
})?
|
||||
}
|
||||
"getFeeRateGovernor" => serde_json::to_value(Response {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
context: RpcResponseContext { slot: 1, api_version: None },
|
||||
value: serde_json::to_value(FeeRateGovernor::default()).unwrap(),
|
||||
})?,
|
||||
"getFees" => serde_json::to_value(Response {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
context: RpcResponseContext { slot: 1, api_version: None },
|
||||
value: serde_json::to_value(RpcFees {
|
||||
blockhash: PUBKEY.to_string(),
|
||||
fee_calculator: FeeCalculator::default(),
|
||||
|
@ -185,7 +185,7 @@ impl RpcSender for MockSender {
|
|||
.map(|_| status.clone())
|
||||
.collect();
|
||||
serde_json::to_value(Response {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
context: RpcResponseContext { slot: 1, api_version: None },
|
||||
value: statuses,
|
||||
})?
|
||||
}
|
||||
|
@ -248,7 +248,7 @@ impl RpcSender for MockSender {
|
|||
"getBlockProduction" => {
|
||||
if params.is_null() {
|
||||
json!(Response {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
context: RpcResponseContext { slot: 1, api_version: None },
|
||||
value: RpcBlockProduction {
|
||||
by_identity: HashMap::new(),
|
||||
range: RpcBlockProductionRange {
|
||||
|
@ -266,7 +266,7 @@ impl RpcSender for MockSender {
|
|||
let config_range = config.range.unwrap_or_default();
|
||||
|
||||
json!(Response {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
context: RpcResponseContext { slot: 1, api_version: None },
|
||||
value: RpcBlockProduction {
|
||||
by_identity,
|
||||
range: RpcBlockProductionRange {
|
||||
|
@ -289,7 +289,7 @@ impl RpcSender for MockSender {
|
|||
inactive: 12,
|
||||
}),
|
||||
"getSupply" => json!(Response {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
context: RpcResponseContext { slot: 1, api_version: None },
|
||||
value: RpcSupply {
|
||||
total: 100000000,
|
||||
circulating: 50000,
|
||||
|
@ -304,7 +304,7 @@ impl RpcSender for MockSender {
|
|||
};
|
||||
|
||||
json!(Response {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
context: RpcResponseContext { slot: 1, api_version: None },
|
||||
value: vec![rpc_account_balance],
|
||||
})
|
||||
}
|
||||
|
@ -335,7 +335,7 @@ impl RpcSender for MockSender {
|
|||
Value::String(signature)
|
||||
}
|
||||
"simulateTransaction" => serde_json::to_value(Response {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
context: RpcResponseContext { slot: 1, api_version: None },
|
||||
value: RpcSimulateTransactionResult {
|
||||
err: None,
|
||||
logs: None,
|
||||
|
@ -353,14 +353,14 @@ impl RpcSender for MockSender {
|
|||
})
|
||||
}
|
||||
"getLatestBlockhash" => serde_json::to_value(Response {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
context: RpcResponseContext { slot: 1, api_version: None },
|
||||
value: RpcBlockhash {
|
||||
blockhash: PUBKEY.to_string(),
|
||||
last_valid_block_height: 1234,
|
||||
},
|
||||
})?,
|
||||
"getFeeForMessage" => serde_json::to_value(Response {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
context: RpcResponseContext { slot: 1, api_version: None },
|
||||
value: json!(Some(0)),
|
||||
})?,
|
||||
"getClusterNodes" => serde_json::to_value(vec![RpcContactInfo {
|
||||
|
@ -441,7 +441,7 @@ impl RpcSender for MockSender {
|
|||
"minimumLedgerSlot" => json![123],
|
||||
"getMaxRetransmitSlot" => json![123],
|
||||
"getMultipleAccounts" => serde_json::to_value(Response {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
context: RpcResponseContext { slot: 1, api_version: None },
|
||||
value: vec![Value::Null, Value::Null]
|
||||
})?,
|
||||
"getProgramAccounts" => {
|
||||
|
|
|
@ -419,7 +419,7 @@ impl RpcClient {
|
|||
/// // Create a mock with a custom repsonse to the `GetBalance` request
|
||||
/// let account_balance = 50;
|
||||
/// let account_balance_response = json!(Response {
|
||||
/// context: RpcResponseContext { slot: 1 },
|
||||
/// context: RpcResponseContext { slot: 1, api_version: None },
|
||||
/// value: json!(account_balance),
|
||||
/// });
|
||||
///
|
||||
|
@ -5394,7 +5394,10 @@ pub fn create_rpc_client_mocks() -> crate::mock_sender::Mocks {
|
|||
|
||||
let get_account_request = RpcRequest::GetAccountInfo;
|
||||
let get_account_response = serde_json::to_value(Response {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
context: RpcResponseContext {
|
||||
slot: 1,
|
||||
api_version: None,
|
||||
},
|
||||
value: {
|
||||
let pubkey = Pubkey::from_str("BgvYtJEfmZYdVKiptmMjxGzv8iQoo4MWjsP3QsTkhhxa").unwrap();
|
||||
let account = Account {
|
||||
|
|
|
@ -448,7 +448,7 @@ impl RpcClient {
|
|||
/// // Create a mock with a custom repsonse to the `GetBalance` request
|
||||
/// let account_balance = 50;
|
||||
/// let account_balance_response = json!(Response {
|
||||
/// context: RpcResponseContext { slot: 1 },
|
||||
/// context: RpcResponseContext { slot: 1, api_version: None },
|
||||
/// value: json!(account_balance),
|
||||
/// });
|
||||
///
|
||||
|
@ -4061,7 +4061,10 @@ pub fn create_rpc_client_mocks() -> crate::mock_sender::Mocks {
|
|||
|
||||
let get_account_request = RpcRequest::GetAccountInfo;
|
||||
let get_account_response = serde_json::to_value(Response {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
context: RpcResponseContext {
|
||||
slot: 1,
|
||||
api_version: None,
|
||||
},
|
||||
value: {
|
||||
let pubkey = Pubkey::from_str("BgvYtJEfmZYdVKiptmMjxGzv8iQoo4MWjsP3QsTkhhxa").unwrap();
|
||||
let account = Account {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use {
|
||||
crate::client_error,
|
||||
serde::{Deserialize, Deserializer, Serialize, Serializer},
|
||||
solana_account_decoder::{parse_token::UiTokenAmount, UiAccount},
|
||||
solana_sdk::{
|
||||
clock::{Epoch, Slot, UnixTimestamp},
|
||||
|
@ -12,15 +13,64 @@ use {
|
|||
solana_transaction_status::{
|
||||
ConfirmedTransactionStatusWithSignature, TransactionConfirmationStatus, UiConfirmedBlock,
|
||||
},
|
||||
std::{collections::HashMap, fmt, net::SocketAddr},
|
||||
std::{collections::HashMap, fmt, net::SocketAddr, str::FromStr},
|
||||
thiserror::Error,
|
||||
};
|
||||
|
||||
pub type RpcResult<T> = client_error::Result<Response<T>>;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RpcResponseContext {
|
||||
pub slot: u64,
|
||||
pub slot: Slot,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub api_version: Option<RpcApiVersion>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct RpcApiVersion(semver::Version);
|
||||
|
||||
impl std::ops::Deref for RpcApiVersion {
|
||||
type Target = semver::Version;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for RpcApiVersion {
|
||||
fn default() -> Self {
|
||||
Self(solana_version::Version::default().as_semver_version())
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for RpcApiVersion {
|
||||
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_str(&self.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for RpcApiVersion {
|
||||
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let s: String = Deserialize::deserialize(deserializer)?;
|
||||
Ok(RpcApiVersion(
|
||||
semver::Version::from_str(&s).map_err(serde::de::Error::custom)?,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl RpcResponseContext {
|
||||
pub fn new(slot: Slot) -> Self {
|
||||
Self {
|
||||
slot,
|
||||
api_version: Some(RpcApiVersion::default()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
|
|
|
@ -5379,6 +5379,7 @@ version = "1.11.0"
|
|||
dependencies = [
|
||||
"log",
|
||||
"rustc_version",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"solana-frozen-abi 1.11.0",
|
||||
|
|
|
@ -116,8 +116,10 @@ pub const PERFORMANCE_SAMPLES_LIMIT: usize = 720;
|
|||
const MAX_RPC_EPOCH_CREDITS_HISTORY: usize = 5;
|
||||
|
||||
fn new_response<T>(bank: &Bank, value: T) -> RpcResponse<T> {
|
||||
let context = RpcResponseContext { slot: bank.slot() };
|
||||
RpcResponse { context, value }
|
||||
RpcResponse {
|
||||
context: RpcResponseContext::new(bank.slot()),
|
||||
value,
|
||||
}
|
||||
}
|
||||
|
||||
/// Wrapper for rpc return types of methods that provide responses both with and without context.
|
||||
|
@ -774,7 +776,7 @@ impl JsonRpcRequestProcessor {
|
|||
|
||||
if let Some((slot, accounts)) = self.get_cached_largest_accounts(&config.filter) {
|
||||
Ok(RpcResponse {
|
||||
context: RpcResponseContext { slot },
|
||||
context: RpcResponseContext::new(slot),
|
||||
value: accounts,
|
||||
})
|
||||
} else {
|
||||
|
@ -4814,7 +4816,7 @@ pub mod tests {
|
|||
let expected = json!({
|
||||
"jsonrpc": "2.0",
|
||||
"result": {
|
||||
"context":{"slot":0},
|
||||
"context": {"slot": 0, "apiVersion": RpcApiVersion::default()},
|
||||
"value":20,
|
||||
},
|
||||
"id": 1,
|
||||
|
@ -5211,7 +5213,7 @@ pub mod tests {
|
|||
);
|
||||
let result: Value = parse_success_result(rpc.handle_request_sync(request));
|
||||
let expected = json!({
|
||||
"context": {"slot": 0},
|
||||
"context": {"slot": 0, "apiVersion": RpcApiVersion::default()},
|
||||
"value":{
|
||||
"owner": "11111111111111111111111111111111",
|
||||
"lamports": 1_000_000,
|
||||
|
@ -5396,7 +5398,7 @@ pub mod tests {
|
|||
let result: RpcResponse<Vec<RpcKeyedAccount>> =
|
||||
parse_success_result(rpc.handle_request_sync(request));
|
||||
let expected = RpcResponse {
|
||||
context: RpcResponseContext { slot: 0 },
|
||||
context: RpcResponseContext::new(0),
|
||||
value: expected_value,
|
||||
};
|
||||
assert_eq!(result, expected);
|
||||
|
@ -5562,7 +5564,7 @@ pub mod tests {
|
|||
let expected = json!({
|
||||
"jsonrpc": "2.0",
|
||||
"result": {
|
||||
"context":{"slot":0},
|
||||
"context": {"slot": 0, "apiVersion": RpcApiVersion::default()},
|
||||
"value":{
|
||||
"accounts": [
|
||||
null,
|
||||
|
@ -5658,7 +5660,7 @@ pub mod tests {
|
|||
let expected = json!({
|
||||
"jsonrpc": "2.0",
|
||||
"result": {
|
||||
"context":{"slot":0},
|
||||
"context": {"slot": 0, "apiVersion": RpcApiVersion::default()},
|
||||
"value":{
|
||||
"accounts":null,
|
||||
"err":null,
|
||||
|
@ -5687,7 +5689,7 @@ pub mod tests {
|
|||
let expected = json!({
|
||||
"jsonrpc": "2.0",
|
||||
"result": {
|
||||
"context":{"slot":0},
|
||||
"context": {"slot": 0, "apiVersion": RpcApiVersion::default()},
|
||||
"value":{
|
||||
"accounts":null,
|
||||
"err":null,
|
||||
|
@ -5740,7 +5742,7 @@ pub mod tests {
|
|||
let expected = json!({
|
||||
"jsonrpc":"2.0",
|
||||
"result": {
|
||||
"context":{"slot":0},
|
||||
"context": {"slot": 0, "apiVersion": RpcApiVersion::default()},
|
||||
"value":{
|
||||
"err":"BlockhashNotFound",
|
||||
"accounts":null,
|
||||
|
@ -5767,7 +5769,7 @@ pub mod tests {
|
|||
let expected = json!({
|
||||
"jsonrpc": "2.0",
|
||||
"result": {
|
||||
"context":{"slot":0},
|
||||
"context": {"slot": 0, "apiVersion": RpcApiVersion::default()},
|
||||
"value":{
|
||||
"accounts":null,
|
||||
"err":null,
|
||||
|
@ -5906,13 +5908,14 @@ pub mod tests {
|
|||
let expected = json!({
|
||||
"jsonrpc": "2.0",
|
||||
"result": {
|
||||
"context":{"slot":0},
|
||||
"context": {"slot": 0, "apiVersion": RpcApiVersion::default()},
|
||||
"value":{
|
||||
"blockhash": recent_blockhash.to_string(),
|
||||
"feeCalculator": {
|
||||
"lamportsPerSignature": 0,
|
||||
}
|
||||
}},
|
||||
},
|
||||
},
|
||||
"id": 1
|
||||
});
|
||||
let expected: Response =
|
||||
|
@ -5934,7 +5937,7 @@ pub mod tests {
|
|||
let expected = json!({
|
||||
"jsonrpc": "2.0",
|
||||
"result": {
|
||||
"context": {"slot": 0},
|
||||
"context": {"slot": 0, "apiVersion": RpcApiVersion::default()},
|
||||
"value": {
|
||||
"blockhash": recent_blockhash.to_string(),
|
||||
"feeCalculator": {
|
||||
|
@ -5973,7 +5976,7 @@ pub mod tests {
|
|||
let expected = json!({
|
||||
"jsonrpc": "2.0",
|
||||
"result": {
|
||||
"context":{"slot":0},
|
||||
"context": {"slot": 0, "apiVersion": RpcApiVersion::default()},
|
||||
"value":fee_calculator,
|
||||
},
|
||||
"id": 1
|
||||
|
@ -5993,7 +5996,7 @@ pub mod tests {
|
|||
let expected = json!({
|
||||
"jsonrpc": "2.0",
|
||||
"result": {
|
||||
"context":{"slot":0},
|
||||
"context": {"slot": 0, "apiVersion": RpcApiVersion::default()},
|
||||
"value":Value::Null,
|
||||
},
|
||||
"id": 1
|
||||
|
@ -6014,7 +6017,7 @@ pub mod tests {
|
|||
let expected = json!({
|
||||
"jsonrpc": "2.0",
|
||||
"result": {
|
||||
"context":{"slot":0},
|
||||
"context": {"slot": 0, "apiVersion": RpcApiVersion::default()},
|
||||
"value":{
|
||||
"feeRateGovernor": {
|
||||
"burnPercent": DEFAULT_BURN_PERCENT,
|
||||
|
@ -6023,7 +6026,8 @@ pub mod tests {
|
|||
"targetLamportsPerSignature": 0,
|
||||
"targetSignaturesPerSlot": 0
|
||||
}
|
||||
}},
|
||||
},
|
||||
},
|
||||
"id": 1
|
||||
});
|
||||
let expected: Response =
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
//! The `pubsub` module implements a threaded subscription service on client RPC request
|
||||
|
||||
use {
|
||||
crate::{
|
||||
optimistically_confirmed_bank_tracker::OptimisticallyConfirmedBank,
|
||||
|
@ -16,7 +17,7 @@ use {
|
|||
serde::Serialize,
|
||||
solana_account_decoder::{parse_token::is_known_spl_token_id, UiAccount, UiAccountEncoding},
|
||||
solana_client::rpc_response::{
|
||||
ProcessedSignatureResult, ReceivedSignatureResult, Response, RpcBlockUpdate,
|
||||
ProcessedSignatureResult, ReceivedSignatureResult, Response as RpcResponse, RpcBlockUpdate,
|
||||
RpcBlockUpdateError, RpcKeyedAccount, RpcLogsResponse, RpcResponseContext,
|
||||
RpcSignatureResult, RpcVote, SlotInfo, SlotUpdate,
|
||||
},
|
||||
|
@ -153,10 +154,10 @@ where
|
|||
filter_results(results, params, *w_last_notified_slot, bank);
|
||||
for result in filter_results {
|
||||
notifier.notify(
|
||||
Response {
|
||||
context: RpcResponseContext { slot },
|
||||
RpcResponse::from(RpcNotificationResponse {
|
||||
context: RpcNotificationContext { slot },
|
||||
value: result,
|
||||
},
|
||||
}),
|
||||
subscription,
|
||||
is_final,
|
||||
);
|
||||
|
@ -176,6 +177,33 @@ pub struct RpcNotification {
|
|||
pub created_at: Instant,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
struct RpcNotificationResponse<T> {
|
||||
context: RpcNotificationContext,
|
||||
value: T,
|
||||
}
|
||||
|
||||
impl<T> From<RpcNotificationResponse<T>> for RpcResponse<T> {
|
||||
fn from(notification: RpcNotificationResponse<T>) -> Self {
|
||||
let RpcNotificationResponse {
|
||||
context: RpcNotificationContext { slot },
|
||||
value,
|
||||
} = notification;
|
||||
Self {
|
||||
context: RpcResponseContext {
|
||||
slot,
|
||||
api_version: None,
|
||||
},
|
||||
value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
struct RpcNotificationContext {
|
||||
slot: Slot,
|
||||
}
|
||||
|
||||
const RPC_NOTIFICATIONS_METRICS_SUBMISSION_INTERVAL_MS: Duration = Duration::from_millis(2_000);
|
||||
|
||||
struct RecentItems {
|
||||
|
@ -839,12 +867,12 @@ impl RpcSubscriptions {
|
|||
{
|
||||
if params.enable_received_notification {
|
||||
notifier.notify(
|
||||
Response {
|
||||
context: RpcResponseContext { slot },
|
||||
RpcResponse::from(RpcNotificationResponse {
|
||||
context: RpcNotificationContext { slot },
|
||||
value: RpcSignatureResult::ReceivedSignature(
|
||||
ReceivedSignatureResult::ReceivedSignature,
|
||||
),
|
||||
},
|
||||
}),
|
||||
subscription,
|
||||
false,
|
||||
);
|
||||
|
@ -987,10 +1015,10 @@ impl RpcSubscriptions {
|
|||
Ok(block_update) => {
|
||||
if let Some(block_update) = block_update {
|
||||
notifier.notify(
|
||||
Response {
|
||||
context: RpcResponseContext { slot: s },
|
||||
RpcResponse::from(RpcNotificationResponse {
|
||||
context: RpcNotificationContext { slot: s },
|
||||
value: block_update,
|
||||
},
|
||||
}),
|
||||
subscription,
|
||||
false,
|
||||
);
|
||||
|
@ -1004,14 +1032,14 @@ impl RpcSubscriptions {
|
|||
// we don't advance `w_last_unnotified_slot` so that
|
||||
// it'll retry on the next notification trigger
|
||||
notifier.notify(
|
||||
Response {
|
||||
context: RpcResponseContext { slot: s },
|
||||
RpcResponse::from(RpcNotificationResponse {
|
||||
context: RpcNotificationContext { slot: s },
|
||||
value: RpcBlockUpdate {
|
||||
slot,
|
||||
block: None,
|
||||
err: Some(err),
|
||||
},
|
||||
},
|
||||
}),
|
||||
subscription,
|
||||
false,
|
||||
);
|
||||
|
|
|
@ -11,6 +11,7 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
log = "0.4.17"
|
||||
semver = "1.0.9"
|
||||
serde = "1.0.137"
|
||||
serde_derive = "1.0.103"
|
||||
solana-frozen-abi = { path = "../frozen-abi", version = "=1.11.0" }
|
||||
|
|
|
@ -29,6 +29,12 @@ pub struct Version {
|
|||
pub feature_set: u32, // first 4 bytes of the FeatureSet identifier
|
||||
}
|
||||
|
||||
impl Version {
|
||||
pub fn as_semver_version(&self) -> semver::Version {
|
||||
semver::Version::new(self.major as u64, self.minor as u64, self.patch as u64)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LegacyVersion> for Version {
|
||||
fn from(legacy_version: LegacyVersion) -> Self {
|
||||
Self {
|
||||
|
|
Loading…
Reference in New Issue