v0.2.7-pre.009
This commit is contained in:
104
crates/ksp-onchain-transport-lib/src/ws_transactions.rs
Normal file
104
crates/ksp-onchain-transport-lib/src/ws_transactions.rs
Normal file
@@ -0,0 +1,104 @@
|
||||
// file: crates/ksp-onchain-transport-lib/src/ws_transactions.rs
|
||||
// version: 1
|
||||
|
||||
/// Filter accepted by the standard Solana `logsSubscribe` WebSocket method.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub enum SolanaLogsSubscribeFilter {
|
||||
/// Subscribe to all transactions except simple vote transactions.
|
||||
All,
|
||||
/// Subscribe to all transactions including simple vote transactions.
|
||||
AllWithVotes,
|
||||
/// Subscribe only to transactions mentioning exactly one public key.
|
||||
Mentions(ksp_core_lib::Pubkey),
|
||||
}
|
||||
|
||||
impl SolanaLogsSubscribeFilter {
|
||||
fn to_json_value(&self) -> serde_json::Value {
|
||||
return match self {
|
||||
Self::All => serde_json::Value::String("all".to_owned()),
|
||||
Self::AllWithVotes => serde_json::Value::String("allWithVotes".to_owned()),
|
||||
Self::Mentions(pubkey) => serde_json::json!({"mentions": [pubkey.to_string()]}),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// Typed value carried by a contextual Solana `logsNotification`.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct SolanaLogsNotification {
|
||||
signature: std::string::String,
|
||||
err: std::option::Option<serde_json::Value>,
|
||||
logs: std::vec::Vec<std::string::String>,
|
||||
}
|
||||
|
||||
impl SolanaLogsNotification {
|
||||
/// Returns the base58 transaction signature exactly as reported by the RPC node.
|
||||
#[must_use]
|
||||
pub fn signature(&self) -> &str {
|
||||
return self.signature.as_str();
|
||||
}
|
||||
|
||||
/// Returns the nullable transaction-error wire value without interpreting Program/runtime error semantics.
|
||||
#[must_use]
|
||||
pub const fn err(&self) -> std::option::Option<&serde_json::Value> {
|
||||
return self.err.as_ref();
|
||||
}
|
||||
|
||||
/// Returns the ordered transaction log messages.
|
||||
#[must_use]
|
||||
pub fn logs(&self) -> &[std::string::String] {
|
||||
return self.logs.as_slice();
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::WsSession {
|
||||
/// Subscribes to Solana transaction logs through standard `logsSubscribe`.
|
||||
pub async fn logs_subscribe(
|
||||
&self,
|
||||
filter: &crate::SolanaLogsSubscribeFilter,
|
||||
config: std::option::Option<&crate::SolanaCommitmentConfig>,
|
||||
) -> ksp_core_lib::Result<crate::WsSubscription<crate::SolanaRpcResponse<crate::SolanaLogsNotification>>> {
|
||||
let mut params = std::vec![filter.to_json_value()];
|
||||
if let std::option::Option::Some(config) = config
|
||||
&& config.commitment().is_some()
|
||||
{
|
||||
params.push(config.to_json_value());
|
||||
}
|
||||
return self.subscribe_typed(crate::WsSubscriptionKind::Logs, params, |value| decode_logs_notification("logsSubscribe", value)).await;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
struct WireRpcResponse {
|
||||
context: serde_json::Value,
|
||||
value: WireLogsNotification,
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
struct WireLogsNotification {
|
||||
signature: std::string::String,
|
||||
err: serde_json::Value,
|
||||
logs: std::vec::Vec<std::string::String>,
|
||||
}
|
||||
|
||||
fn decode_logs_notification(method: &str, value: serde_json::Value) -> ksp_core_lib::Result<crate::SolanaRpcResponse<crate::SolanaLogsNotification>> {
|
||||
let decoded = crate::decode_wire_json::<WireRpcResponse>(method, value);
|
||||
let wire = match decoded {
|
||||
std::result::Result::Ok(wire) => wire,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let context = crate::SolanaRpcContext::decode_wire(method, wire.context);
|
||||
let context = match context {
|
||||
std::result::Result::Ok(context) => context,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let err = match wire.value.err {
|
||||
serde_json::Value::Null => std::option::Option::None,
|
||||
value => std::option::Option::Some(value),
|
||||
};
|
||||
let notification = crate::SolanaLogsNotification { signature: wire.value.signature, err, logs: wire.value.logs };
|
||||
return std::result::Result::Ok(crate::SolanaRpcResponse::new(context, notification));
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "../unit_tests/ws_transactions.rs"]
|
||||
mod tests;
|
||||
Reference in New Issue
Block a user