hopli/
win_prob.rs

1//! This module contains arguments and functions to interact with the Winning Probability contract for a privileged
2//! account. It can set the global minimum winning probability and read the current global minimum winning probability.
3//! Some sample commands:
4//! - Set winning probability:
5//! ```text
6//! hopli win-prob set \
7//!     --network anvil-localhost \
8//!     --contracts-root "../ethereum/contracts" \
9//!     --winning-probability 0.5 \
10//!     --private-key ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \
11//!     --provider-url "http://localhost:8545"
12//! ```
13//! - Get winning probability:
14//! ```text
15//! hopli win-prob get \
16//!     --network anvil-localhost \
17//!     --contracts-root "../ethereum/contracts" \
18//!     --provider-url "http://localhost:8545"
19//! ```
20use alloy::primitives::aliases::U56;
21use clap::Parser;
22use hopr_bindings::hoprwinningprobabilityoracle::HoprWinningProbabilityOracle;
23use hopr_internal_types::{prelude::WinningProbability, tickets::EncodedWinProb};
24use tracing::{debug, info};
25
26use crate::{
27    environment_config::NetworkProviderArgs,
28    key_pair::{ArgEnvReader, PrivateKeyArgs},
29    utils::{Cmd, HelperErrors},
30};
31
32/// CLI arguments for `hopli win-prob`
33#[derive(Clone, Debug, Parser)]
34pub enum WinProbSubcommands {
35    /// Set the global minimum ticket winning probability as an owner
36    #[command(visible_alias = "s")]
37    Set {
38        /// Network name, contracts config file root, and customized provider, if available
39        #[command(flatten)]
40        network_provider: NetworkProviderArgs,
41
42        /// New winning probability
43        #[clap(help = "New winning probability", short = 'w', long, default_value_t = 1.0f64)]
44        winning_probability: f64,
45
46        /// Access to the private key of a manager of Network Registry contract
47        #[command(flatten)]
48        private_key: PrivateKeyArgs,
49    },
50
51    /// Read the current global minimum winning probability
52    #[command(visible_alias = "g")]
53    Get {
54        /// Network name, contracts config file root, and customized provider, if available
55        #[command(flatten)]
56        network_provider: NetworkProviderArgs,
57    },
58}
59
60impl WinProbSubcommands {
61    pub async fn execute_set_win_prob(
62        network_provider: NetworkProviderArgs,
63        winning_probability: f64,
64        private_key: PrivateKeyArgs,
65    ) -> Result<(), HelperErrors> {
66        // Read the private key from arguments or the "PRIVATE_KEY" environment variable
67        let signer_private_key = private_key.read("PRIVATE_KEY")?;
68
69        // get RPC provider for the given network and environment
70        let rpc_provider = network_provider.get_provider_with_signer(&signer_private_key).await?;
71        let contract_addresses = network_provider.get_network_details_from_name()?;
72
73        let hopr_win_prob = HoprWinningProbabilityOracle::new(
74            contract_addresses.addresses.winning_probability_oracle.into(),
75            rpc_provider.clone(),
76        );
77
78        // convert the winning probability to the format required by the contract
79        let winning_probability_val = WinningProbability::try_from(winning_probability).map_err(|_| {
80            HelperErrors::ParseError("Failed to convert winning probability to the required format".into())
81        })?;
82
83        info!(
84            winning_probability = %winning_probability_val,
85            win_prob_uint56 = %winning_probability,
86            "Setting the global minimum winning probability"
87        );
88
89        hopr_win_prob
90            .setWinProb(U56::from_be_slice(&winning_probability_val.as_encoded()))
91            .send()
92            .await?
93            .watch()
94            .await?;
95        Ok(())
96    }
97
98    pub async fn execute_get_win_prob(network_provider: NetworkProviderArgs) -> Result<f64, HelperErrors> {
99        // get RPC provider for the given network and environment
100        let rpc_provider = network_provider.get_provider_without_signer().await?;
101        let contract_addresses = network_provider.get_network_details_from_name()?;
102
103        let hopr_win_prob = HoprWinningProbabilityOracle::new(
104            contract_addresses.addresses.winning_probability_oracle.into(),
105            rpc_provider.clone(),
106        );
107
108        // get winning probability from the contract
109        let current_win_prob =
110            hopr_win_prob.currentWinProb().call().await.map_err(|e| {
111                HelperErrors::MiddlewareError(format!("Failed to get current winning probability: {}", e))
112            })?;
113
114        // convert into f64
115        let mut tmp: EncodedWinProb = Default::default();
116        tmp.copy_from_slice(&current_win_prob.to_be_bytes::<7>());
117        let current_win_prob = WinningProbability::from(tmp);
118        let current_win_prob_f64 = current_win_prob.as_f64();
119        info!(
120            current_win_prob_f64 = %current_win_prob_f64,
121            current_win_prob_uint56 = %current_win_prob,
122            "Current global minimum winning probability"
123        );
124        Ok(current_win_prob_f64)
125    }
126}
127
128impl Cmd for WinProbSubcommands {
129    /// Run the execute_register function.
130    /// By default, registration is done by manager wallet
131    fn run(self) -> Result<(), HelperErrors> {
132        Ok(())
133    }
134
135    async fn async_run(self) -> Result<(), HelperErrors> {
136        match self {
137            WinProbSubcommands::Set {
138                network_provider,
139                winning_probability,
140                private_key,
141            } => {
142                WinProbSubcommands::execute_set_win_prob(network_provider, winning_probability, private_key).await?;
143            }
144            WinProbSubcommands::Get { network_provider } => {
145                let win_prob = WinProbSubcommands::execute_get_win_prob(network_provider).await?;
146                debug!("Current global minimum winning probability is: {}", win_prob);
147            }
148        }
149        Ok(())
150    }
151}