Skip to main content

pwr_rs/rpc/
types.rs

1use reqwest::{Client};
2use serde::{Deserialize, Serialize};
3use url::Url;
4use std::sync::atomic::AtomicBool;
5use std::sync::Arc;
6use crate::transaction::types::VidaDataTransaction;
7use std::future::Future;
8use std::pin::Pin;
9
10pub struct RPC {
11    pub http_client: Client,
12    pub node_url: Url,
13    pub chain_id: u8,
14}
15
16#[derive(Debug)]
17pub enum RpcError {
18    FailedToBroadcastTransaction(String),
19    InvalidRpcUrl,
20    Network(reqwest::Error),
21    Deserialization(reqwest::Error),
22    JsonDeserialization(String),
23}
24
25#[derive(Serialize, Deserialize, Debug)]
26pub struct BroadcastResponse {
27    pub success: bool,
28    pub data: Option<String>,
29    pub error: String,
30}
31
32#[derive(Serialize, Deserialize, Debug)]
33pub struct ResponseData {
34    pub message: String,
35}
36
37#[derive(Serialize)]
38pub struct BroadcastRequest {
39    pub txn: String,
40}
41
42/// Trait for block saving functionality that supports both sync and async implementations
43pub trait BlockSaver: Send + Sync {
44    fn save_block(&self, block_number: u64) -> Pin<Box<dyn Future<Output = ()> + Send + '_>>;
45}
46
47/// Implementation for synchronous functions that return nothing
48impl<F> BlockSaver for F
49where
50    F: Fn(u64) + Send + Sync,
51{
52    fn save_block(&self, block_number: u64) -> Pin<Box<dyn Future<Output = ()> + Send + '_>> {
53        self(block_number);
54        Box::pin(async move { })
55    }
56}
57
58/// Wrapper for async functions
59pub struct AsyncBlockSaver<F, Fut>
60where
61    F: Fn(u64) -> Fut + Send + Sync,
62    Fut: Future<Output = ()> + Send,
63{
64    func: F,
65}
66
67impl<F, Fut> AsyncBlockSaver<F, Fut>
68where
69    F: Fn(u64) -> Fut + Send + Sync,
70    Fut: Future<Output = ()> + Send,
71{
72    pub fn new(func: F) -> Self {
73        Self { func }
74    }
75}
76
77impl<F, Fut> BlockSaver for AsyncBlockSaver<F, Fut>
78where
79    F: Fn(u64) -> Fut + Send + Sync,
80    Fut: Future<Output = ()> + Send + 'static,
81{
82    fn save_block(&self, block_number: u64) -> Pin<Box<dyn Future<Output = ()> + Send + '_>> {
83        Box::pin((self.func)(block_number))
84    }
85}
86
87/// Convenience functions for creating BlockSaver instances
88pub mod block_saver {
89    use super::*;
90    use std::future::Future;
91
92    /// Create a BoxedBlockSaver from a synchronous function
93    /// 
94    /// # Example
95    /// ```rust
96    /// use pwr_rs::rpc::block_saver;
97    /// 
98    /// let sync_saver = block_saver::from_sync(|block_num| {
99    ///     println!("Saving block: {}", block_num);
100    ///     // Save to file, update database, etc.
101    /// });
102    /// ```
103    pub fn from_sync<F>(func: F) -> Box<dyn BlockSaver>
104    where
105        F: Fn(u64) + Send + Sync + 'static,
106    {
107        Box::new(func)
108    }
109
110    /// Create a BoxedBlockSaver from an async function
111    /// 
112    /// # Example
113    /// ```rust
114    /// use pwr_rs::rpc::block_saver;
115    /// 
116    /// let async_saver = block_saver::from_async(|block_num| async move {
117    ///     // Simulate async database save
118    ///     tokio::time::sleep(std::time::Duration::from_millis(10)).await;
119    ///     println!("Async saving block: {}", block_num);
120    /// });
121    /// ```
122    pub fn from_async<F, Fut>(func: F) -> Box<dyn BlockSaver>
123    where
124        F: Fn(u64) -> Fut + Send + Sync + 'static,
125        Fut: Future<Output = ()> + Send + 'static,
126    {
127        Box::new(AsyncBlockSaver::new(func))
128    }
129}
130
131pub struct VidaTransactionSubscription {
132    pub pwrrs: Arc<RPC>,
133    pub vida_id: u64,
134    pub starting_block: u64,
135    pub poll_interval: u64,
136    pub latest_checked_block: Arc<std::sync::atomic::AtomicU64>,
137    pub handler: ProcessVidaTransactions,
138    pub block_saver: Option<Box<dyn BlockSaver>>,
139    pub wants_to_pause: Arc<AtomicBool>,
140    pub paused: Arc<AtomicBool>,
141    pub stop: Arc<AtomicBool>,
142    pub running: Arc<AtomicBool>,
143}
144
145pub type ProcessVidaTransactions = fn(transaction: VidaDataTransaction);