0.7.27 +Refactor
This commit is contained in:
@@ -10,7 +10,7 @@
|
||||
|
||||
/// Typed Solana PubSub notification payload.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum KbSolanaWsTypedNotification {
|
||||
pub enum SolanaWsTypedNotification {
|
||||
/// `accountNotification`
|
||||
Account(solana_rpc_client_api::response::Response<solana_rpc_client_api::response::UiAccount>),
|
||||
/// `blockNotification`
|
||||
@@ -40,16 +40,16 @@ pub enum KbSolanaWsTypedNotification {
|
||||
}
|
||||
|
||||
/// Parses a Solana JSON-RPC notification into an official typed payload.
|
||||
pub fn parse_kb_solana_ws_typed_notification(
|
||||
notification: &crate::KbJsonRpcWsNotification,
|
||||
) -> Result<KbSolanaWsTypedNotification, crate::KbError> {
|
||||
pub fn parse_solana_ws_typed_notification(
|
||||
notification: &crate::JsonRpcWsNotification,
|
||||
) -> Result<SolanaWsTypedNotification, crate::Error> {
|
||||
if notification.method == "accountNotification" {
|
||||
let parse_result = serde_json::from_value::<
|
||||
solana_rpc_client_api::response::Response<solana_rpc_client_api::response::UiAccount>,
|
||||
>(notification.params.result.clone());
|
||||
return match parse_result {
|
||||
Ok(value) => Ok(KbSolanaWsTypedNotification::Account(value)),
|
||||
Err(error) => Err(crate::KbError::Json(format!(
|
||||
Ok(value) => Ok(SolanaWsTypedNotification::Account(value)),
|
||||
Err(error) => Err(crate::Error::Json(format!(
|
||||
"cannot parse accountNotification payload: {error}"
|
||||
))),
|
||||
};
|
||||
@@ -59,10 +59,10 @@ pub fn parse_kb_solana_ws_typed_notification(
|
||||
notification.params.result.clone(),
|
||||
);
|
||||
return match parse_result {
|
||||
Ok(value) => Ok(KbSolanaWsTypedNotification::Block(value)),
|
||||
Err(error) => Err(crate::KbError::Json(format!(
|
||||
"cannot parse blockNotification payload: {error}"
|
||||
))),
|
||||
Ok(value) => Ok(SolanaWsTypedNotification::Block(value)),
|
||||
Err(error) => {
|
||||
Err(crate::Error::Json(format!("cannot parse blockNotification payload: {error}")))
|
||||
},
|
||||
};
|
||||
}
|
||||
if notification.method == "logsNotification" {
|
||||
@@ -72,9 +72,9 @@ pub fn parse_kb_solana_ws_typed_notification(
|
||||
>,
|
||||
>(notification.params.result.clone());
|
||||
return match parse_result {
|
||||
Ok(value) => Ok(KbSolanaWsTypedNotification::Logs(value)),
|
||||
Ok(value) => Ok(SolanaWsTypedNotification::Logs(value)),
|
||||
Err(error) => {
|
||||
Err(crate::KbError::Json(format!("cannot parse logsNotification payload: {error}")))
|
||||
Err(crate::Error::Json(format!("cannot parse logsNotification payload: {error}")))
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -85,8 +85,8 @@ pub fn parse_kb_solana_ws_typed_notification(
|
||||
>,
|
||||
>(notification.params.result.clone());
|
||||
return match parse_result {
|
||||
Ok(value) => Ok(KbSolanaWsTypedNotification::Program(value)),
|
||||
Err(error) => Err(crate::KbError::Json(format!(
|
||||
Ok(value) => Ok(SolanaWsTypedNotification::Program(value)),
|
||||
Err(error) => Err(crate::Error::Json(format!(
|
||||
"cannot parse programNotification payload: {error}"
|
||||
))),
|
||||
};
|
||||
@@ -94,8 +94,8 @@ pub fn parse_kb_solana_ws_typed_notification(
|
||||
if notification.method == "rootNotification" {
|
||||
let root_option = notification.params.result.as_u64();
|
||||
return match root_option {
|
||||
Some(root) => Ok(KbSolanaWsTypedNotification::Root(root)),
|
||||
None => Err(crate::KbError::Json(
|
||||
Some(root) => Ok(SolanaWsTypedNotification::Root(root)),
|
||||
None => Err(crate::Error::Json(
|
||||
"cannot parse rootNotification payload: result is not a u64".to_string(),
|
||||
)),
|
||||
};
|
||||
@@ -107,8 +107,8 @@ pub fn parse_kb_solana_ws_typed_notification(
|
||||
>,
|
||||
>(notification.params.result.clone());
|
||||
return match parse_result {
|
||||
Ok(value) => Ok(KbSolanaWsTypedNotification::Signature(value)),
|
||||
Err(error) => Err(crate::KbError::Json(format!(
|
||||
Ok(value) => Ok(SolanaWsTypedNotification::Signature(value)),
|
||||
Err(error) => Err(crate::Error::Json(format!(
|
||||
"cannot parse signatureNotification payload: {error}"
|
||||
))),
|
||||
};
|
||||
@@ -118,9 +118,9 @@ pub fn parse_kb_solana_ws_typed_notification(
|
||||
notification.params.result.clone(),
|
||||
);
|
||||
return match parse_result {
|
||||
Ok(value) => Ok(KbSolanaWsTypedNotification::Slot(value)),
|
||||
Ok(value) => Ok(SolanaWsTypedNotification::Slot(value)),
|
||||
Err(error) => {
|
||||
Err(crate::KbError::Json(format!("cannot parse slotNotification payload: {error}")))
|
||||
Err(crate::Error::Json(format!("cannot parse slotNotification payload: {error}")))
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -129,8 +129,8 @@ pub fn parse_kb_solana_ws_typed_notification(
|
||||
notification.params.result.clone(),
|
||||
);
|
||||
return match parse_result {
|
||||
Ok(value) => Ok(KbSolanaWsTypedNotification::SlotsUpdates(value)),
|
||||
Err(error) => Err(crate::KbError::Json(format!(
|
||||
Ok(value) => Ok(SolanaWsTypedNotification::SlotsUpdates(value)),
|
||||
Err(error) => Err(crate::Error::Json(format!(
|
||||
"cannot parse slotsUpdatesNotification payload: {error}"
|
||||
))),
|
||||
};
|
||||
@@ -140,13 +140,13 @@ pub fn parse_kb_solana_ws_typed_notification(
|
||||
notification.params.result.clone(),
|
||||
);
|
||||
return match parse_result {
|
||||
Ok(value) => Ok(KbSolanaWsTypedNotification::Vote(value)),
|
||||
Ok(value) => Ok(SolanaWsTypedNotification::Vote(value)),
|
||||
Err(error) => {
|
||||
Err(crate::KbError::Json(format!("cannot parse voteNotification payload: {error}")))
|
||||
Err(crate::Error::Json(format!("cannot parse voteNotification payload: {error}")))
|
||||
},
|
||||
};
|
||||
}
|
||||
return Err(crate::KbError::Json(format!(
|
||||
return Err(crate::Error::Json(format!(
|
||||
"unsupported Solana websocket notification method '{}'",
|
||||
notification.method
|
||||
)));
|
||||
@@ -158,34 +158,34 @@ pub fn parse_kb_solana_ws_typed_notification(
|
||||
/// - `Ok(Some(...))` for JSON-RPC notification-bearing events
|
||||
/// - `Ok(None)` for events that do not carry a notification
|
||||
/// - `Err(...)` when a notification is present but cannot be decoded
|
||||
pub fn parse_kb_solana_ws_typed_notification_from_event(
|
||||
pub fn parse_solana_ws_typed_notification_from_event(
|
||||
event: &crate::WsEvent,
|
||||
) -> Result<std::option::Option<KbSolanaWsTypedNotification>, crate::KbError> {
|
||||
) -> Result<std::option::Option<SolanaWsTypedNotification>, crate::Error> {
|
||||
match event {
|
||||
crate::WsEvent::SubscriptionNotification { notification, .. } => {
|
||||
let parse_result = parse_kb_solana_ws_typed_notification(notification);
|
||||
let parse_result = parse_solana_ws_typed_notification(notification);
|
||||
match parse_result {
|
||||
Ok(value) => return Ok(Some(value)),
|
||||
Err(error) => return Err(error),
|
||||
}
|
||||
},
|
||||
crate::WsEvent::JsonRpcNotificationWithoutSubscription { notification, .. } => {
|
||||
let parse_result = parse_kb_solana_ws_typed_notification(notification);
|
||||
let parse_result = parse_solana_ws_typed_notification(notification);
|
||||
match parse_result {
|
||||
Ok(value) => return Ok(Some(value)),
|
||||
Err(error) => return Err(error),
|
||||
}
|
||||
},
|
||||
crate::WsEvent::JsonRpcMessage { message, .. } => match message {
|
||||
crate::KbJsonRpcWsIncomingMessage::Notification(notification) => {
|
||||
let parse_result = parse_kb_solana_ws_typed_notification(notification);
|
||||
crate::JsonRpcWsIncomingMessage::Notification(notification) => {
|
||||
let parse_result = parse_solana_ws_typed_notification(notification);
|
||||
match parse_result {
|
||||
Ok(value) => return Ok(Some(value)),
|
||||
Err(error) => return Err(error),
|
||||
}
|
||||
},
|
||||
crate::KbJsonRpcWsIncomingMessage::SuccessResponse(_) => return Ok(None),
|
||||
crate::KbJsonRpcWsIncomingMessage::ErrorResponse(_) => return Ok(None),
|
||||
crate::JsonRpcWsIncomingMessage::SuccessResponse(_) => return Ok(None),
|
||||
crate::JsonRpcWsIncomingMessage::ErrorResponse(_) => return Ok(None),
|
||||
},
|
||||
_ => return Ok(None),
|
||||
}
|
||||
@@ -197,9 +197,9 @@ impl crate::WsClient {
|
||||
&self,
|
||||
pubkey: std::string::String,
|
||||
config: std::option::Option<solana_rpc_client_api::config::RpcAccountInfoConfig>,
|
||||
) -> Result<u64, crate::KbError> {
|
||||
) -> Result<u64, crate::Error> {
|
||||
let config_value_result =
|
||||
kb_serialize_optional_config_value(config, "accountSubscribe config");
|
||||
serialize_optional_config_value(config, "accountSubscribe config");
|
||||
let config_value = match config_value_result {
|
||||
Ok(config_value) => config_value,
|
||||
Err(error) => return Err(error),
|
||||
@@ -212,14 +212,13 @@ impl crate::WsClient {
|
||||
&self,
|
||||
filter: solana_rpc_client_api::config::RpcBlockSubscribeFilter,
|
||||
config: std::option::Option<solana_rpc_client_api::config::RpcBlockSubscribeConfig>,
|
||||
) -> Result<u64, crate::KbError> {
|
||||
let filter_value_result = kb_serialize_required_value(filter, "blockSubscribe filter");
|
||||
) -> Result<u64, crate::Error> {
|
||||
let filter_value_result = serialize_required_value(filter, "blockSubscribe filter");
|
||||
let filter_value = match filter_value_result {
|
||||
Ok(filter_value) => filter_value,
|
||||
Err(error) => return Err(error),
|
||||
};
|
||||
let config_value_result =
|
||||
kb_serialize_optional_config_value(config, "blockSubscribe config");
|
||||
let config_value_result = serialize_optional_config_value(config, "blockSubscribe config");
|
||||
let config_value = match config_value_result {
|
||||
Ok(config_value) => config_value,
|
||||
Err(error) => return Err(error),
|
||||
@@ -232,14 +231,13 @@ impl crate::WsClient {
|
||||
&self,
|
||||
filter: solana_rpc_client_api::config::RpcTransactionLogsFilter,
|
||||
config: std::option::Option<solana_rpc_client_api::config::RpcTransactionLogsConfig>,
|
||||
) -> Result<u64, crate::KbError> {
|
||||
let filter_value_result = kb_serialize_required_value(filter, "logsSubscribe filter");
|
||||
) -> Result<u64, crate::Error> {
|
||||
let filter_value_result = serialize_required_value(filter, "logsSubscribe filter");
|
||||
let filter_value = match filter_value_result {
|
||||
Ok(filter_value) => filter_value,
|
||||
Err(error) => return Err(error),
|
||||
};
|
||||
let config_value_result =
|
||||
kb_serialize_optional_config_value(config, "logsSubscribe config");
|
||||
let config_value_result = serialize_optional_config_value(config, "logsSubscribe config");
|
||||
let config_value = match config_value_result {
|
||||
Ok(config_value) => config_value,
|
||||
Err(error) => return Err(error),
|
||||
@@ -252,9 +250,9 @@ impl crate::WsClient {
|
||||
&self,
|
||||
program_id: std::string::String,
|
||||
config: std::option::Option<solana_rpc_client_api::config::RpcProgramAccountsConfig>,
|
||||
) -> Result<u64, crate::KbError> {
|
||||
) -> Result<u64, crate::Error> {
|
||||
let config_value_result =
|
||||
kb_serialize_optional_config_value(config, "programSubscribe config");
|
||||
serialize_optional_config_value(config, "programSubscribe config");
|
||||
let config_value = match config_value_result {
|
||||
Ok(config_value) => config_value,
|
||||
Err(error) => return Err(error),
|
||||
@@ -267,9 +265,9 @@ impl crate::WsClient {
|
||||
&self,
|
||||
signature: std::string::String,
|
||||
config: std::option::Option<solana_rpc_client_api::config::RpcSignatureSubscribeConfig>,
|
||||
) -> Result<u64, crate::KbError> {
|
||||
) -> Result<u64, crate::Error> {
|
||||
let config_value_result =
|
||||
kb_serialize_optional_config_value(config, "signatureSubscribe config");
|
||||
serialize_optional_config_value(config, "signatureSubscribe config");
|
||||
let config_value = match config_value_result {
|
||||
Ok(config_value) => config_value,
|
||||
Err(error) => return Err(error),
|
||||
@@ -278,10 +276,7 @@ impl crate::WsClient {
|
||||
}
|
||||
}
|
||||
|
||||
fn kb_serialize_required_value<T>(
|
||||
value: T,
|
||||
label: &str,
|
||||
) -> Result<serde_json::Value, crate::KbError>
|
||||
fn serialize_required_value<T>(value: T, label: &str) -> Result<serde_json::Value, crate::Error>
|
||||
where
|
||||
T: serde::Serialize,
|
||||
{
|
||||
@@ -289,15 +284,15 @@ where
|
||||
match value_result {
|
||||
Ok(value) => return Ok(value),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Json(format!("cannot serialize {}: {error}", label)));
|
||||
return Err(crate::Error::Json(format!("cannot serialize {}: {error}", label)));
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn kb_serialize_optional_config_value<T>(
|
||||
fn serialize_optional_config_value<T>(
|
||||
value: std::option::Option<T>,
|
||||
label: &str,
|
||||
) -> Result<std::option::Option<serde_json::Value>, crate::KbError>
|
||||
) -> Result<std::option::Option<serde_json::Value>, crate::Error>
|
||||
where
|
||||
T: serde::Serialize,
|
||||
{
|
||||
@@ -307,10 +302,7 @@ where
|
||||
match value_result {
|
||||
Ok(value) => return Ok(Some(value)),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Json(format!(
|
||||
"cannot serialize {}: {error}",
|
||||
label
|
||||
)));
|
||||
return Err(crate::Error::Json(format!("cannot serialize {}: {error}", label)));
|
||||
},
|
||||
}
|
||||
},
|
||||
@@ -321,7 +313,7 @@ where
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
fn make_test_ws_client() -> crate::WsClient {
|
||||
let endpoint = crate::KbWsEndpointConfig {
|
||||
let endpoint = crate::WsEndpointConfig {
|
||||
name: "test_ws".to_string(),
|
||||
enabled: true,
|
||||
provider: "test".to_string(),
|
||||
@@ -341,18 +333,18 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn parse_root_notification_works() {
|
||||
let notification = crate::KbJsonRpcWsNotification {
|
||||
let notification = crate::JsonRpcWsNotification {
|
||||
jsonrpc: "2.0".to_string(),
|
||||
method: "rootNotification".to_string(),
|
||||
params: crate::KbJsonRpcWsNotificationParams {
|
||||
params: crate::JsonRpcWsNotificationParams {
|
||||
result: serde_json::Value::from(123u64),
|
||||
subscription: 7,
|
||||
},
|
||||
};
|
||||
let parsed = crate::parse_kb_solana_ws_typed_notification(¬ification)
|
||||
let parsed = crate::parse_solana_ws_typed_notification(¬ification)
|
||||
.expect("typed root notification parse must succeed");
|
||||
match parsed {
|
||||
crate::KbSolanaWsTypedNotification::Root(root) => {
|
||||
crate::SolanaWsTypedNotification::Root(root) => {
|
||||
assert_eq!(root, 123);
|
||||
},
|
||||
other => {
|
||||
@@ -363,10 +355,10 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn parse_slot_notification_works() {
|
||||
let notification = crate::KbJsonRpcWsNotification {
|
||||
let notification = crate::JsonRpcWsNotification {
|
||||
jsonrpc: "2.0".to_string(),
|
||||
method: "slotNotification".to_string(),
|
||||
params: crate::KbJsonRpcWsNotificationParams {
|
||||
params: crate::JsonRpcWsNotificationParams {
|
||||
result: serde_json::json!({
|
||||
"parent": 10,
|
||||
"root": 11,
|
||||
@@ -376,10 +368,10 @@ mod tests {
|
||||
},
|
||||
};
|
||||
|
||||
let parsed = crate::parse_kb_solana_ws_typed_notification(¬ification)
|
||||
let parsed = crate::parse_solana_ws_typed_notification(¬ification)
|
||||
.expect("typed slot notification parse must succeed");
|
||||
match parsed {
|
||||
crate::KbSolanaWsTypedNotification::Slot(slot_info) => {
|
||||
crate::SolanaWsTypedNotification::Slot(slot_info) => {
|
||||
assert_eq!(slot_info.parent, 10);
|
||||
assert_eq!(slot_info.root, 11);
|
||||
assert_eq!(slot_info.slot, 12);
|
||||
@@ -393,11 +385,10 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn account_subscribe_typed_uses_same_send_path() {
|
||||
let client = make_test_ws_client();
|
||||
let result = client
|
||||
.account_subscribe_typed("11111111111111111111111111111111".to_string(), None)
|
||||
.await;
|
||||
let result =
|
||||
client.account_subscribe_typed(crate::SYSTEM_PROGRAM_ID.to_string(), None).await;
|
||||
match result {
|
||||
Err(crate::KbError::NotConnected(_)) => {},
|
||||
Err(crate::Error::NotConnected(_)) => {},
|
||||
other => {
|
||||
panic!("unexpected result: {other:?}");
|
||||
},
|
||||
@@ -414,7 +405,7 @@ mod tests {
|
||||
)
|
||||
.await;
|
||||
match result {
|
||||
Err(crate::KbError::NotConnected(_)) => {},
|
||||
Err(crate::Error::NotConnected(_)) => {},
|
||||
other => {
|
||||
panic!("unexpected result: {other:?}");
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user