This commit is contained in:
2026-04-21 09:16:54 +02:00
parent ff3b20f13b
commit dcee5c9447
6 changed files with 176 additions and 81 deletions

View File

@@ -8,3 +8,4 @@
0.3.0 - Registre subscriptions / notifications
0.3.1 - Ajout de subscribe/unsubscribe hlpers à WsClient
0.3.2 - Ajout de notifications typés
0.3.3 - Ajout du suffix _raw au fonction raw pour avoir des fonction subscribe _typed et _raw

View File

@@ -8,7 +8,7 @@ members = [
]
[workspace.package]
version = "0.3.2"
version = "0.3.3"
edition = "2024"
license = "MIT"
repository = "https://git.sasedev.com/Sasedev/khadhroony-bobobot"

View File

@@ -23,10 +23,8 @@ fs2.workspace = true
kb_lib = { path = "../kb_lib" }
rustls.workspace = true
serde.workspace = true
serde_json.workspace = true
tauri.workspace = true
tauri-plugin-tracing.workspace = true
tokio.workspace = true
tracing.workspace = true
ts-rs.workspace = true
uuid.workspace = true

View File

@@ -9,39 +9,21 @@ authors.workspace = true
publish.workspace = true
[dependencies]
async-trait.workspace = true
base64.workspace = true
chrono.workspace = true
futures-util.workspace = true
reqwest.workspace = true
rustls.workspace = true
serde.workspace = true
serde_json.workspace = true
solana-account-decoder-client-types.workspace = true
solana-address-lookup-table-interface.workspace = true
solana-client.workspace = true
solana-compute-budget-interface.workspace = true
solana-rpc-client-api.workspace = true
solana-rpc-client-types.workspace = true
solana-sdk.workspace = true
solana-sdk-ids.workspace = true
solana-system-interface.workspace = true
solana-transaction-status-client-types.workspace = true
spl-associated-token-account-interface.workspace = true
spl-memo-interface.workspace = true
spl-token-2022-interface.workspace = true
spl-token-interface.workspace = true
sqlx.workspace = true
tokio.workspace = true
tokio-stream.workspace = true
tokio-tungstenite.workspace = true
tracing.workspace = true
tracing-appender.workspace = true
tracing-subscriber.workspace = true
yellowstone-grpc-client.workspace = true
yellowstone-grpc-proto.workspace = true
uuid.workspace = true
[dev-dependencies]
tempfile.workspace = true

View File

@@ -204,7 +204,7 @@ impl crate::WsClient {
Ok(config_value) => config_value,
Err(error) => return Err(error),
};
self.account_subscribe(pubkey, config_value).await
self.account_subscribe_raw(pubkey, config_value).await
}
/// Typed helper for `blockSubscribe`.
@@ -224,7 +224,7 @@ impl crate::WsClient {
Ok(config_value) => config_value,
Err(error) => return Err(error),
};
self.block_subscribe(filter_value, config_value).await
self.block_subscribe_raw(filter_value, config_value).await
}
/// Typed helper for `logsSubscribe`.
@@ -244,7 +244,7 @@ impl crate::WsClient {
Ok(config_value) => config_value,
Err(error) => return Err(error),
};
self.logs_subscribe(filter_value, config_value).await
self.logs_subscribe_raw(filter_value, config_value).await
}
/// Typed helper for `programSubscribe`.
@@ -259,7 +259,7 @@ impl crate::WsClient {
Ok(config_value) => config_value,
Err(error) => return Err(error),
};
self.program_subscribe(program_id, config_value).await
self.program_subscribe_raw(program_id, config_value).await
}
/// Typed helper for `signatureSubscribe`.
@@ -274,7 +274,7 @@ impl crate::WsClient {
Ok(config_value) => config_value,
Err(error) => return Err(error),
};
self.signature_subscribe(signature, config_value).await
self.signature_subscribe_raw(signature, config_value).await
}
}

View File

@@ -557,8 +557,8 @@ impl WsClient {
}
}
/// Subscribes to account change notifications.
pub async fn account_subscribe(
/// Subscribes to account change notifications using raw JSON values.
pub async fn account_subscribe_raw(
&self,
pubkey: std::string::String,
config: std::option::Option<serde_json::Value>,
@@ -568,8 +568,11 @@ impl WsClient {
.await
}
/// Unsubscribes from an account change subscription.
pub async fn account_unsubscribe(&self, subscription_id: u64) -> Result<u64, crate::KbError> {
/// Unsubscribes from an account change subscription using raw JSON values.
pub async fn account_unsubscribe_raw(
&self,
subscription_id: u64,
) -> Result<u64, crate::KbError> {
self.send_json_rpc_request(
"accountUnsubscribe".to_string(),
vec![serde_json::Value::from(subscription_id)],
@@ -577,10 +580,10 @@ impl WsClient {
.await
}
/// Subscribes to block notifications.
/// Subscribes to block notifications using raw JSON values.
///
/// The Solana RPC documentation marks this subscription as unstable.
pub async fn block_subscribe(
pub async fn block_subscribe_raw(
&self,
filter: serde_json::Value,
config: std::option::Option<serde_json::Value>,
@@ -590,8 +593,8 @@ impl WsClient {
.await
}
/// Unsubscribes from a block notification subscription.
pub async fn block_unsubscribe(&self, subscription_id: u64) -> Result<u64, crate::KbError> {
/// Unsubscribes from a block notification subscription using raw JSON values.
pub async fn block_unsubscribe_raw(&self, subscription_id: u64) -> Result<u64, crate::KbError> {
self.send_json_rpc_request(
"blockUnsubscribe".to_string(),
vec![serde_json::Value::from(subscription_id)],
@@ -599,8 +602,8 @@ impl WsClient {
.await
}
/// Subscribes to transaction log notifications.
pub async fn logs_subscribe(
/// Subscribes to transaction log notifications using raw JSON values.
pub async fn logs_subscribe_raw(
&self,
filter: serde_json::Value,
config: std::option::Option<serde_json::Value>,
@@ -610,8 +613,8 @@ impl WsClient {
.await
}
/// Unsubscribes from a logs subscription.
pub async fn logs_unsubscribe(&self, subscription_id: u64) -> Result<u64, crate::KbError> {
/// Unsubscribes from a logs subscription using raw JSON values.
pub async fn logs_unsubscribe_raw(&self, subscription_id: u64) -> Result<u64, crate::KbError> {
self.send_json_rpc_request(
"logsUnsubscribe".to_string(),
vec![serde_json::Value::from(subscription_id)],
@@ -619,8 +622,8 @@ impl WsClient {
.await
}
/// Subscribes to program-owned account notifications.
pub async fn program_subscribe(
/// Subscribes to program-owned account notifications using raw JSON values.
pub async fn program_subscribe_raw(
&self,
program_id: std::string::String,
config: std::option::Option<serde_json::Value>,
@@ -630,8 +633,11 @@ impl WsClient {
.await
}
/// Unsubscribes from a program subscription.
pub async fn program_unsubscribe(&self, subscription_id: u64) -> Result<u64, crate::KbError> {
/// Unsubscribes from a program subscription using raw JSON values.
pub async fn program_unsubscribe_raw(
&self,
subscription_id: u64,
) -> Result<u64, crate::KbError> {
self.send_json_rpc_request(
"programUnsubscribe".to_string(),
vec![serde_json::Value::from(subscription_id)],
@@ -654,8 +660,8 @@ impl WsClient {
.await
}
/// Subscribes to one transaction signature status.
pub async fn signature_subscribe(
/// Subscribes to one transaction signature status using raw JSON values.
pub async fn signature_subscribe_raw(
&self,
signature: std::string::String,
config: std::option::Option<serde_json::Value>,
@@ -665,8 +671,11 @@ impl WsClient {
.await
}
/// Unsubscribes from a signature subscription.
pub async fn signature_unsubscribe(&self, subscription_id: u64) -> Result<u64, crate::KbError> {
/// Unsubscribes from a signature subscription using raw JSON values.
pub async fn signature_unsubscribe_raw(
&self,
subscription_id: u64,
) -> Result<u64, crate::KbError> {
self.send_json_rpc_request(
"signatureUnsubscribe".to_string(),
vec![serde_json::Value::from(subscription_id)],
@@ -1924,7 +1933,7 @@ mod tests {
client.disconnect().await.expect("disconnect must succeed");
server.shutdown().await;
}
#[tokio::test]
async fn helper_methods_send_expected_subscribe_method_names() {
let server = TestWsServer::spawn_json_rpc_server().await;
@@ -1934,59 +1943,104 @@ mod tests {
client.connect().await.expect("connect must succeed");
let _ = recv_event(&mut receiver).await;
let _ = client
.account_subscribe(
.account_subscribe_raw(
"CM78CPUeXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNH12".to_string(),
Some(serde_json::json!({"encoding": "jsonParsed"})),
)
.await
.expect("account_subscribe must succeed");
let _ = client
.block_subscribe(
.block_subscribe_raw(
serde_json::json!("all"),
Some(serde_json::json!({"commitment": "confirmed"})),
)
.await
.expect("block_subscribe must succeed");
let _ = client
.logs_subscribe(
.logs_subscribe_raw(
serde_json::json!("all"),
Some(serde_json::json!({"commitment": "finalized"})),
)
.await
.expect("logs_subscribe must succeed");
let _ = client
.program_subscribe(
.program_subscribe_raw(
"11111111111111111111111111111111".to_string(),
Some(serde_json::json!({"encoding": "base64"})),
)
.await
.expect("program_subscribe must succeed");
let _ = client.root_subscribe().await.expect("root_subscribe must succeed");
let _ = client
.signature_subscribe(
.root_subscribe()
.await
.expect("root_subscribe must succeed");
let _ = client
.signature_subscribe_raw(
"2EBVM6cB8vAAD93Ktr6Vd8p67XPbQzCJX47MpReuiCXJAtcjaxpvWpcg9Ege1Nr5Tk3a2GFrByT7WPBjdsTycY9b".to_string(),
Some(serde_json::json!({"commitment": "confirmed"})),
)
.await
.expect("signature_subscribe must succeed");
let _ = client.slot_subscribe().await.expect("slot_subscribe must succeed");
let _ = client
.slot_subscribe()
.await
.expect("slot_subscribe must succeed");
let _ = client
.slots_updates_subscribe()
.await
.expect("slots_updates_subscribe must succeed");
let _ = client.vote_subscribe().await.expect("vote_subscribe must succeed");
let _ = client
.vote_subscribe()
.await
.expect("vote_subscribe must succeed");
tokio::time::sleep(std::time::Duration::from_millis(150)).await;
let observed_methods = server.observed_methods_snapshot().await;
assert!(observed_methods.iter().any(|method| method == "accountSubscribe"));
assert!(observed_methods.iter().any(|method| method == "blockSubscribe"));
assert!(observed_methods.iter().any(|method| method == "logsSubscribe"));
assert!(observed_methods.iter().any(|method| method == "programSubscribe"));
assert!(observed_methods.iter().any(|method| method == "rootSubscribe"));
assert!(observed_methods.iter().any(|method| method == "signatureSubscribe"));
assert!(observed_methods.iter().any(|method| method == "slotSubscribe"));
assert!(observed_methods.iter().any(|method| method == "slotsUpdatesSubscribe"));
assert!(observed_methods.iter().any(|method| method == "voteSubscribe"));
assert!(
observed_methods
.iter()
.any(|method| method == "accountSubscribe")
);
assert!(
observed_methods
.iter()
.any(|method| method == "blockSubscribe")
);
assert!(
observed_methods
.iter()
.any(|method| method == "logsSubscribe")
);
assert!(
observed_methods
.iter()
.any(|method| method == "programSubscribe")
);
assert!(
observed_methods
.iter()
.any(|method| method == "rootSubscribe")
);
assert!(
observed_methods
.iter()
.any(|method| method == "signatureSubscribe")
);
assert!(
observed_methods
.iter()
.any(|method| method == "slotSubscribe")
);
assert!(
observed_methods
.iter()
.any(|method| method == "slotsUpdatesSubscribe")
);
assert!(
observed_methods
.iter()
.any(|method| method == "voteSubscribe")
);
client.disconnect().await.expect("disconnect must succeed");
server.shutdown().await;
}
@@ -1999,29 +2053,89 @@ mod tests {
let mut receiver = client.subscribe_events();
client.connect().await.expect("connect must succeed");
let _ = recv_event(&mut receiver).await;
let _ = client.account_unsubscribe(10).await.expect("account_unsubscribe must succeed");
let _ = client.block_unsubscribe(11).await.expect("block_unsubscribe must succeed");
let _ = client.logs_unsubscribe(12).await.expect("logs_unsubscribe must succeed");
let _ = client.program_unsubscribe(13).await.expect("program_unsubscribe must succeed");
let _ = client.root_unsubscribe(14).await.expect("root_unsubscribe must succeed");
let _ = client.signature_unsubscribe(15).await.expect("signature_unsubscribe must succeed");
let _ = client.slot_unsubscribe(16).await.expect("slot_unsubscribe must succeed");
let _ = client
.account_unsubscribe_raw(10)
.await
.expect("account_unsubscribe must succeed");
let _ = client
.block_unsubscribe_raw(11)
.await
.expect("block_unsubscribe must succeed");
let _ = client
.logs_unsubscribe_raw(12)
.await
.expect("logs_unsubscribe must succeed");
let _ = client
.program_unsubscribe_raw(13)
.await
.expect("program_unsubscribe must succeed");
let _ = client
.root_unsubscribe(14)
.await
.expect("root_unsubscribe must succeed");
let _ = client
.signature_unsubscribe_raw(15)
.await
.expect("signature_unsubscribe must succeed");
let _ = client
.slot_unsubscribe(16)
.await
.expect("slot_unsubscribe must succeed");
let _ = client
.slots_updates_unsubscribe(17)
.await
.expect("slots_updates_unsubscribe must succeed");
let _ = client.vote_unsubscribe(18).await.expect("vote_unsubscribe must succeed");
let _ = client
.vote_unsubscribe(18)
.await
.expect("vote_unsubscribe must succeed");
tokio::time::sleep(std::time::Duration::from_millis(150)).await;
let observed_methods = server.observed_methods_snapshot().await;
assert!(observed_methods.iter().any(|method| method == "accountUnsubscribe"));
assert!(observed_methods.iter().any(|method| method == "blockUnsubscribe"));
assert!(observed_methods.iter().any(|method| method == "logsUnsubscribe"));
assert!(observed_methods.iter().any(|method| method == "programUnsubscribe"));
assert!(observed_methods.iter().any(|method| method == "rootUnsubscribe"));
assert!(observed_methods.iter().any(|method| method == "signatureUnsubscribe"));
assert!(observed_methods.iter().any(|method| method == "slotUnsubscribe"));
assert!(observed_methods.iter().any(|method| method == "slotsUpdatesUnsubscribe"));
assert!(observed_methods.iter().any(|method| method == "voteUnsubscribe"));
assert!(
observed_methods
.iter()
.any(|method| method == "accountUnsubscribe")
);
assert!(
observed_methods
.iter()
.any(|method| method == "blockUnsubscribe")
);
assert!(
observed_methods
.iter()
.any(|method| method == "logsUnsubscribe")
);
assert!(
observed_methods
.iter()
.any(|method| method == "programUnsubscribe")
);
assert!(
observed_methods
.iter()
.any(|method| method == "rootUnsubscribe")
);
assert!(
observed_methods
.iter()
.any(|method| method == "signatureUnsubscribe")
);
assert!(
observed_methods
.iter()
.any(|method| method == "slotUnsubscribe")
);
assert!(
observed_methods
.iter()
.any(|method| method == "slotsUpdatesUnsubscribe")
);
assert!(
observed_methods
.iter()
.any(|method| method == "voteUnsubscribe")
);
client.disconnect().await.expect("disconnect must succeed");
server.shutdown().await;
}