1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
use chain_impl_mockchain::fragment::FragmentId;
use jormungandr_lib::interfaces::FragmentStatus;
use jortestkit::load::RequestStatusProvider;
use jortestkit::load::{Id, Status};
use thiserror::Error;
use valgrind::{ValgrindClient, ValgrindSettings};

/// Responsible for providing information about status for given ids collection.
/// It can work over a batch of ids by preparing request to Jormungandr V1 REST Api. Basically it query
/// statues for given ids and prepare `Status` struct for each id
pub struct VoteStatusProvider {
    backend: ValgrindClient,
}

impl VoteStatusProvider {
    /// Creates object based on address and verbosity
    ///
    /// # Errors
    ///
    /// On connectivity issues
    pub fn new(backend_address: String, debug: bool) -> Result<Self, Error> {
        let mut backend = ValgrindClient::new(backend_address, ValgrindSettings::default())?;
        if debug {
            backend.enable_logs();
        } else {
            backend.disable_logs();
        }
        Ok(Self { backend })
    }
}

impl RequestStatusProvider for VoteStatusProvider {
    fn get_statuses(&self, ids: &[Id]) -> Vec<Status> {
        match self
            .backend
            .fragments_statuses(ids.iter().map(ToString::to_string).collect())
        {
            Ok(fragments_statuses) => fragments_statuses
                .iter()
                .map(|(id, fragment_log)| into_status(fragment_log, id))
                .collect(),
            Err(_) => vec![],
        }
    }
}

fn into_status(fragment_status: &FragmentStatus, id: &FragmentId) -> Status {
    match fragment_status {
        FragmentStatus::Pending => {
            Status::new_pending(std::time::Duration::from_secs(0), id.to_string())
        }
        FragmentStatus::Rejected { reason } => Status::new_failure(
            std::time::Duration::from_secs(0),
            id.to_string(),
            reason.to_string(),
        ),
        FragmentStatus::InABlock { .. } => {
            Status::new_success(std::time::Duration::from_secs(0), id.to_string())
        }
    }
}

#[derive(Debug, Error)]
pub enum Error {
    #[error("wallet error")]
    Wallet(#[from] crate::wallet::Error),
    #[error("wallet error")]
    Backend(#[from] valgrind::Error),
    #[error("controller error")]
    Controller(#[from] crate::ControllerError),
    #[error("pin read error")]
    PinRead(#[from] crate::utils::qr::Error),
    #[error("wallet time error")]
    WalletTime(#[from] wallet::time::Error),
}