diff --git a/Cargo.lock b/Cargo.lock index 158af61..abb93bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -328,6 +328,7 @@ dependencies = [ "bitcoin", "futures", "indexer", + "jsonrpc", "rayon", "redb", "reqwest", diff --git a/cli/v2/src/main.rs b/cli/v2/src/main.rs index efa05af..9b7f5ca 100644 --- a/cli/v2/src/main.rs +++ b/cli/v2/src/main.rs @@ -34,6 +34,7 @@ use bdk_sp_oracles::{ TrustedPeer, UnboundedReceiver, Warning, }, filters::kyoto::{FilterEvent, FilterSubscriber}, + frigate::{self, FrigateClient}, tweaks::blindbit::{BlindbitSubscriber, TweakEvent}, }; use bdk_sp_wallet::{ @@ -161,6 +162,24 @@ pub enum Commands { #[clap(long)] hash: Option, }, + + ScanFrigrate { + #[clap(flatten)] + rpc_args: RpcArgs, + /// The scan private key for which outputs will be scanned for. + #[clap(long)] + scan_priv_key: String, + /// The spend public key for which outputs will be scanned for. + #[clap(long)] + spend_pub_key: String, + /// An optional start parameter from where the scanning will start. When not specified it starts from Taproot activation height. + #[clap(long)] + start: Option, + /// Optional list of labels to scan for. It always scan for change index with label 0. + #[clap(long)] + labels: Option>, + }, + Create { /// Network #[clap(long, short, default_value = "signet")] @@ -567,6 +586,22 @@ async fn main() -> anyhow::Result<()> { ); } } + Commands::ScanFrigrate { + rpc_args, + scan_priv_key, + spend_pub_key, + start, + labels, + } => { + let client = FrigateClient::new( + &rpc_args.url, + rpc_args.rpc_user.as_deref(), + rpc_args.rpc_password.as_deref(), + )?; + let histories: Vec = Vec::new(); + + loop {} + } Commands::Balance => { fn print_balances<'a>( title_str: &'a str, diff --git a/oracles/Cargo.toml b/oracles/Cargo.toml index 2313138..f3ba162 100644 --- a/oracles/Cargo.toml +++ b/oracles/Cargo.toml @@ -13,9 +13,10 @@ redb = "2.4.0" rayon = "1.11.0" reqwest = { version = "0.12.23", features = ["json", "rustls-tls", "http2", "charset"], default-features = false } serde = { version = "1.0.219", features = ["serde_derive"] } -serde_json = "1.0.142" +serde_json = { version = "1.0.142", features = ["raw_value"]} url = "2.5.4" tracing = "0.1.41" +jsonrpc = "=0.18.0" [lints] workspace = true diff --git a/oracles/src/frigate/mod.rs b/oracles/src/frigate/mod.rs new file mode 100644 index 0000000..b1b58df --- /dev/null +++ b/oracles/src/frigate/mod.rs @@ -0,0 +1,110 @@ +use bitcoin::{key::TweakedPublicKey, secp256k1::SecretKey, PublicKey}; +use jsonrpc::simple_http::{self, SimpleHttpTransport}; +use jsonrpc::Client; +use serde::{Deserialize, Serialize}; +use serde_json::value::to_raw_value; + +#[derive(Debug)] +pub enum FrigateError { + JsonRpc(jsonrpc::Error), + ParseUrl(url::ParseError), + Serde(serde_json::Error), +} + +impl From for FrigateError { + fn from(value: serde_json::Error) -> Self { + FrigateError::Serde(value) + } +} + +impl From for FrigateError { + fn from(value: url::ParseError) -> Self { + Self::ParseUrl(value) + } +} + +impl From for FrigateError { + fn from(value: jsonrpc::Error) -> Self { + Self::JsonRpc(value) + } +} + +pub struct FrigateClient { + pub host_url: String, + client: Client, +} + +#[derive(Serialize, Deserialize)] +pub struct History { + height: u64, + tx_hash: bitcoin::BlockHash, + tweak_key: TweakedPublicKey, +} + +#[derive(Serialize, Deserialize)] +pub struct NotifPayload { + scan_private_key: SecretKey, + spend_public_key: PublicKey, + address: String, + labels: Option>, + start_height: u64, + progress: f32, + history: Vec, +} + +#[derive(Serialize, Deserialize)] +pub struct SubscribeRequest { + scan_privkey: SecretKey, + spend_pubkey: PublicKey, + start_height: u64, +} + +#[derive(Serialize, Deserialize)] +pub struct UnsubscribeRequest { + scan_privkey: SecretKey, + spend_pubkey: PublicKey, +} + +#[derive(Serialize, Deserialize)] +pub struct GetRequest { + tx_hash: bitcoin::BlockHash, +} + +const SUBSCRIBE_RPC_METHOD: &str = "blockchain.silentpayments.subscribe"; +const UNSUBSCRIBE_RPC_METHOD: &str = "blockchain.silentpayments.unsubscribe"; + +impl FrigateClient { + pub fn new( + host_url: &str, + user: Option<&str>, + password: Option<&str>, + ) -> Result { + let transport = SimpleHttpTransport::builder() + .url(host_url)? + .auth(user.unwrap_or(""), password) + .build(); + + Ok(Self { + host_url: host_url.to_string(), + client: Client::with_transport(transport), + }) + } + + pub fn subscribe(&self, req: &SubscribeRequest) -> Result { + let params = to_raw_value(&serde_json::json!(req))?; + let req = self + .client + .build_request(SUBSCRIBE_RPC_METHOD, Some(¶ms)); + let res = self.client.send_request(req)?; + Ok(res.result()?) + } + + pub fn unsubscribe(&self, req: &UnsubscribeRequest) -> Result { + let params = to_raw_value(&serde_json::json!(req))?; + let req = self + .client + .build_request(UNSUBSCRIBE_RPC_METHOD, Some(¶ms)); + let res = self.client.send_request(req)?; + Ok(res.result()?) + } +} diff --git a/oracles/src/lib.rs b/oracles/src/lib.rs index 1d5a6a9..93a6146 100644 --- a/oracles/src/lib.rs +++ b/oracles/src/lib.rs @@ -1,3 +1,4 @@ pub mod filters; +pub mod frigate; pub mod tweaks; pub use bip157;