feat: show XvB stats to Status Tab

This commit is contained in:
Louis-Marie Baer 2024-03-04 12:03:14 +01:00
parent f164184044
commit 7f8b1b2089
10 changed files with 381 additions and 22 deletions

11
Cargo.lock generated
View file

@ -2327,6 +2327,7 @@ dependencies = [
"arti-hyper", "arti-hyper",
"benri", "benri",
"bytes", "bytes",
"derive_more",
"dirs", "dirs",
"eframe", "eframe",
"egui", "egui",
@ -2348,6 +2349,7 @@ dependencies = [
"regex", "regex",
"rfd", "rfd",
"serde", "serde",
"serde-this-or-that",
"serde_json", "serde_json",
"static_vcruntime", "static_vcruntime",
"strip-ansi-escapes", "strip-ansi-escapes",
@ -4165,6 +4167,15 @@ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]]
name = "serde-this-or-that"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "634c5a3cb041e56cc2964386151c67d520f845445789da3bd46bfb1c94f5e3bb"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "serde-value" name = "serde-value"
version = "0.7.0" version = "0.7.0"

View file

@ -75,7 +75,8 @@ walkdir = "2.4.0"
zeroize = "1.7.0" zeroize = "1.7.0"
strsim = "0.11.0" strsim = "0.11.0"
strip-ansi-escapes = "0.2.0" strip-ansi-escapes = "0.2.0"
derive_more = {version="0.99.17", default-features=false, features=["display"]}
serde-this-or-that = "0.4.2"
# Unix dependencies # Unix dependencies
[target.'cfg(unix)'.dependencies] [target.'cfg(unix)'.dependencies]
tar = "0.4.40" tar = "0.4.40"

View file

@ -18,6 +18,7 @@ use crate::helper::p2pool::ImgP2pool;
use crate::helper::p2pool::PubP2poolApi; use crate::helper::p2pool::PubP2poolApi;
use crate::helper::xmrig::ImgXmrig; use crate::helper::xmrig::ImgXmrig;
use crate::helper::xmrig::PubXmrigApi; use crate::helper::xmrig::PubXmrigApi;
use crate::helper::xvb::PubXvbApi;
use crate::helper::Helper; use crate::helper::Helper;
use crate::helper::Process; use crate::helper::Process;
use crate::helper::ProcessName; use crate::helper::ProcessName;
@ -103,6 +104,7 @@ pub struct App {
pub xmrig: Arc<Mutex<Process>>, // [XMRig] process state pub xmrig: Arc<Mutex<Process>>, // [XMRig] process state
pub p2pool_api: Arc<Mutex<PubP2poolApi>>, // Public ready-to-print P2Pool API made by the "helper" thread pub p2pool_api: Arc<Mutex<PubP2poolApi>>, // Public ready-to-print P2Pool API made by the "helper" thread
pub xmrig_api: Arc<Mutex<PubXmrigApi>>, // Public ready-to-print XMRig API made by the "helper" thread pub xmrig_api: Arc<Mutex<PubXmrigApi>>, // Public ready-to-print XMRig API made by the "helper" thread
pub xvb_api: Arc<Mutex<PubXvbApi>>, // Public XvB API
pub p2pool_img: Arc<Mutex<ImgP2pool>>, // A one-time snapshot of what data P2Pool started with pub p2pool_img: Arc<Mutex<ImgP2pool>>, // A one-time snapshot of what data P2Pool started with
pub xmrig_img: Arc<Mutex<ImgXmrig>>, // A one-time snapshot of what data XMRig started with pub xmrig_img: Arc<Mutex<ImgXmrig>>, // A one-time snapshot of what data XMRig started with
// STDIN Buffer // STDIN Buffer
@ -181,6 +183,7 @@ impl App {
)); ));
let p2pool_api = arc_mut!(PubP2poolApi::new()); let p2pool_api = arc_mut!(PubP2poolApi::new());
let xmrig_api = arc_mut!(PubXmrigApi::new()); let xmrig_api = arc_mut!(PubXmrigApi::new());
let xvb_api = arc_mut!(PubXvbApi::new());
let p2pool_img = arc_mut!(ImgP2pool::new()); let p2pool_img = arc_mut!(ImgP2pool::new());
let xmrig_img = arc_mut!(ImgXmrig::new()); let xmrig_img = arc_mut!(ImgXmrig::new());
@ -243,6 +246,7 @@ impl App {
xmrig.clone(), xmrig.clone(),
p2pool_api.clone(), p2pool_api.clone(),
xmrig_api.clone(), xmrig_api.clone(),
xvb_api.clone(),
p2pool_img.clone(), p2pool_img.clone(),
xmrig_img.clone(), xmrig_img.clone(),
arc_mut!(GupaxP2poolApi::new()) arc_mut!(GupaxP2poolApi::new())
@ -250,6 +254,7 @@ impl App {
p2pool, p2pool,
xmrig, xmrig,
p2pool_api, p2pool_api,
xvb_api,
xmrig_api, xmrig_api,
p2pool_img, p2pool_img,
xmrig_img, xmrig_img,

View file

@ -143,7 +143,7 @@ path_xmr: {:#?}\n
} }
Tab::Status => { Tab::Status => {
debug!("App | Entering [Status] Tab"); debug!("App | Entering [Status] Tab");
crate::disk::state::Status::show(&mut self.state.status, &self.pub_sys, &self.p2pool_api, &self.xmrig_api, &self.p2pool_img, &self.xmrig_img, p2pool_is_alive, xmrig_is_alive, self.max_threads, &self.gupax_p2pool_api, &self.benchmarks, self.width, self.height, ctx, ui); crate::disk::state::Status::show(&mut self.state.status, &self.pub_sys, &self.p2pool_api, &self.xmrig_api, &self.xvb_api,&self.p2pool_img, &self.xmrig_img, p2pool_is_alive, xmrig_is_alive, self.max_threads, &self.gupax_p2pool_api, &self.benchmarks, self.width, self.height, ctx, ui);
} }
Tab::Gupax => { Tab::Gupax => {
debug!("App | Entering [Gupax] Tab"); debug!("App | Entering [Gupax] Tab");

View file

@ -21,6 +21,7 @@ use crate::{
helper::{ helper::{
p2pool::{ImgP2pool, PubP2poolApi}, p2pool::{ImgP2pool, PubP2poolApi},
xmrig::{ImgXmrig, PubXmrigApi}, xmrig::{ImgXmrig, PubXmrigApi},
xvb::PubXvbApi,
Sys, Sys,
}, },
}; };
@ -38,6 +39,7 @@ impl Status {
sys: &Arc<Mutex<Sys>>, sys: &Arc<Mutex<Sys>>,
p2pool_api: &Arc<Mutex<PubP2poolApi>>, p2pool_api: &Arc<Mutex<PubP2poolApi>>,
xmrig_api: &Arc<Mutex<PubXmrigApi>>, xmrig_api: &Arc<Mutex<PubXmrigApi>>,
xvb_api: &Arc<Mutex<PubXvbApi>>,
p2pool_img: &Arc<Mutex<ImgP2pool>>, p2pool_img: &Arc<Mutex<ImgP2pool>>,
xmrig_img: &Arc<Mutex<ImgXmrig>>, xmrig_img: &Arc<Mutex<ImgXmrig>>,
p2pool_alive: bool, p2pool_alive: bool,
@ -59,10 +61,11 @@ impl Status {
ui, ui,
p2pool_alive, p2pool_alive,
p2pool_api, p2pool_api,
p2pool_img,
xmrig_alive, xmrig_alive,
xmrig_api, xmrig_api,
p2pool_img,
xmrig_img, xmrig_img,
xvb_api,
max_threads, max_threads,
); );
//---------------------------------------------------------------------------------------------------- [P2Pool] //---------------------------------------------------------------------------------------------------- [P2Pool]

View file

@ -1,9 +1,10 @@
use egui::Ui; use egui::{ScrollArea, Ui};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use crate::disk::state::Status; use crate::disk::state::Status;
use crate::helper::p2pool::{ImgP2pool, PubP2poolApi}; use crate::helper::p2pool::{ImgP2pool, PubP2poolApi};
use crate::helper::xmrig::{ImgXmrig, PubXmrigApi}; use crate::helper::xmrig::{ImgXmrig, PubXmrigApi};
use crate::helper::xvb::{PubXvbApi, XvbRound};
use crate::helper::Sys; use crate::helper::Sys;
use crate::utils::macros::lock; use crate::utils::macros::lock;
use egui::TextStyle; use egui::TextStyle;
@ -21,13 +22,14 @@ impl Status {
ui: &mut egui::Ui, ui: &mut egui::Ui,
p2pool_alive: bool, p2pool_alive: bool,
p2pool_api: &Arc<Mutex<PubP2poolApi>>, p2pool_api: &Arc<Mutex<PubP2poolApi>>,
p2pool_img: &Arc<Mutex<ImgP2pool>>,
xmrig_alive: bool, xmrig_alive: bool,
xmrig_api: &Arc<Mutex<PubXmrigApi>>, xmrig_api: &Arc<Mutex<PubXmrigApi>>,
p2pool_img: &Arc<Mutex<ImgP2pool>>,
xmrig_img: &Arc<Mutex<ImgXmrig>>, xmrig_img: &Arc<Mutex<ImgXmrig>>,
xvb_api: &Arc<Mutex<PubXvbApi>>,
max_threads: usize, max_threads: usize,
) { ) {
let width = (width / 3.0) - (SPACE * 1.666); let width = (width / 4.0) - (SPACE * 1.7500);
let min_height = height - SPACE; let min_height = height - SPACE;
let height = height / 25.0; let height = height / 25.0;
ui.horizontal(|ui| { ui.horizontal(|ui| {
@ -54,6 +56,8 @@ impl Status {
xmrig_img, xmrig_img,
max_threads, max_threads,
); );
// [XvB]
xvb(ui, min_height, width, height, xvb_api);
}); });
} }
} }
@ -346,3 +350,139 @@ fn xmrig(
}) })
}); });
} }
fn xvb(ui: &mut Ui, min_height: f32, width: f32, height: f32, xvb_api: &Arc<Mutex<PubXvbApi>>) {
//
let api = lock!(xvb_api);
// if this field is empty, it means nothing was received from the API.
let enabled = !api.reward_yearly.is_empty();
ScrollArea::vertical().show(ui, |ui| {
ui.group(|ui| {
ui.vertical(|ui| {
debug!("Status Tab | Rendering [XvB]");
ui.set_enabled(enabled); // for now there is no API ping or /health, so we verify if the field reward_yearly is empty or not.
ui.set_min_height(min_height);
ui.add_sized(
[width, height],
Label::new(
RichText::new("[XvB]")
.color(LIGHT_GRAY)
.text_style(TextStyle::Name("MonospaceLarge".into())),
),
)
.on_hover_text("XvB API stats")
.on_disabled_hover_text("No data received from XvB API");
// [Round Type]
ui.add_sized(
[width, height],
Label::new(RichText::new("Round Type").underline().color(BONE)),
)
.on_hover_text(STATUS_XVB_ROUND_TYPE);
ui.add_sized([width, height], Label::new(api.round_type.to_string()));
// [Time Remaining]
ui.add_sized(
[width, height],
Label::new(
RichText::new("Raffle Round Time Remaining")
.underline()
.color(BONE),
),
)
.on_hover_text(STATUS_XVB_TIME_REMAIN);
ui.add_sized(
[width, height],
Label::new(format!("{} minutes left", api.time_remain)),
);
// Donated Hashrate
ui.add_sized(
[width, height],
Label::new(RichText::new("Donated Hashrate").underline().color(BONE)),
)
.on_hover_text(STATUS_XVB_DONATED_HR);
ui.add_sized(
[width, height],
Label::new(format!(
"Bonus HR\n{}kH/s\n+\n{}kH/s\ndonated by\n{} donors\n with\n{} miners",
api.bonus_hr, api.donate_hr, api.donate_miners, api.donate_workers
)),
);
// Players
ui.add_sized(
[width, height],
Label::new(RichText::new("Players").underline().color(BONE)),
)
.on_hover_text(STATUS_XVB_PLAYERS);
ui.add_sized(
[width, height],
Label::new(format!(
"[Registered: {}]\n[Playing: {}]",
api.players, api.players_round
)),
);
// Winner
ui.add_sized(
[width, height],
Label::new(RichText::new("Winner").underline().color(BONE)),
)
.on_hover_text(STATUS_XVB_WINNER);
ui.add_sized([width, height], Label::new(&api.winner));
// Share effort
ui.add_sized(
[width, height],
Label::new(RichText::new("Share Effort").underline().color(BONE)),
)
.on_hover_text(STATUS_XVB_SHARE);
ui.add_sized([width, height], Label::new(format!("{}", api.share_effort)));
// Block reward
ui.add_sized(
[width, height],
Label::new(RichText::new("Block Reward").underline().color(BONE)),
)
.on_hover_text(STATUS_XVB_BLOCK_REWARD);
ui.add_sized([width, height], Label::new(format!("{}", api.block_reward)));
//block height
ui.add_sized(
[width, height],
Label::new(RichText::new("Block Height").underline().color(BONE)),
)
.on_hover_text(STATUS_XVB_BLOCK_HEIGHT);
ui.add_sized([width, height], Label::new(format!("{}", api.block_height)));
// block hash
ui.add_sized(
[width, height],
Label::new(RichText::new("Block Hash").underline().color(BONE)),
)
.on_hover_text(STATUS_XVB_BLOCK_HASH);
ui.add_sized([width, height], Label::new(format!("{}", api.block_hash)));
// reward yearly
ui.add_sized(
[width, height],
Label::new(RichText::new("Reward Yearly").underline().color(BONE)),
)
.on_hover_text(STATUS_XVB_YEARLY);
if api.reward_yearly.is_empty() {
ui.add_sized([width, height], Label::new("No information".to_string()));
} else {
ui.add_sized(
[width, height],
Label::new(format!(
"{}: {} XMR\n{}: {} XMR\n{}: {} XMR\n{}: {} XMR\n{}: {} XMR",
XvbRound::Vip,
api.reward_yearly[0],
XvbRound::Donor,
api.reward_yearly[1],
XvbRound::DonorVip,
api.reward_yearly[2],
XvbRound::DonorWhale,
api.reward_yearly[3],
XvbRound::DonorMega,
api.reward_yearly[4]
)),
);
}
drop(api);
});
// by round
});
});
}

View file

@ -47,8 +47,11 @@ use std::{
thread, thread,
time::*, time::*,
}; };
use self::xvb::PubXvbApi;
pub mod p2pool; pub mod p2pool;
pub mod xmrig; pub mod xmrig;
pub mod xvb;
//---------------------------------------------------------------------------------------------------- Constants //---------------------------------------------------------------------------------------------------- Constants
// The max amount of bytes of process output we are willing to // The max amount of bytes of process output we are willing to
@ -71,10 +74,12 @@ pub struct Helper {
pub xmrig: Arc<Mutex<Process>>, // XMRig process state pub xmrig: Arc<Mutex<Process>>, // XMRig process state
pub gui_api_p2pool: Arc<Mutex<PubP2poolApi>>, // P2Pool API state (for GUI thread) pub gui_api_p2pool: Arc<Mutex<PubP2poolApi>>, // P2Pool API state (for GUI thread)
pub gui_api_xmrig: Arc<Mutex<PubXmrigApi>>, // XMRig API state (for GUI thread) pub gui_api_xmrig: Arc<Mutex<PubXmrigApi>>, // XMRig API state (for GUI thread)
pub gui_api_xvb: Arc<Mutex<PubXvbApi>>, // XMRig API state (for GUI thread)
pub img_p2pool: Arc<Mutex<ImgP2pool>>, // A static "image" of the data P2Pool started with pub img_p2pool: Arc<Mutex<ImgP2pool>>, // A static "image" of the data P2Pool started with
pub img_xmrig: Arc<Mutex<ImgXmrig>>, // A static "image" of the data XMRig started with pub img_xmrig: Arc<Mutex<ImgXmrig>>, // A static "image" of the data XMRig started with
pub_api_p2pool: Arc<Mutex<PubP2poolApi>>, // P2Pool API state (for Helper/P2Pool thread) pub_api_p2pool: Arc<Mutex<PubP2poolApi>>, // P2Pool API state (for Helper/P2Pool thread)
pub_api_xmrig: Arc<Mutex<PubXmrigApi>>, // XMRig API state (for Helper/XMRig thread) pub_api_xmrig: Arc<Mutex<PubXmrigApi>>, // XMRig API state (for Helper/XMRig thread)
pub_api_xvb: Arc<Mutex<PubXvbApi>>, // XvB API state (for Helper/XvB thread)
pub gupax_p2pool_api: Arc<Mutex<GupaxP2poolApi>>, // pub gupax_p2pool_api: Arc<Mutex<GupaxP2poolApi>>, //
} }
@ -273,6 +278,7 @@ impl Helper {
xmrig: Arc<Mutex<Process>>, xmrig: Arc<Mutex<Process>>,
gui_api_p2pool: Arc<Mutex<PubP2poolApi>>, gui_api_p2pool: Arc<Mutex<PubP2poolApi>>,
gui_api_xmrig: Arc<Mutex<PubXmrigApi>>, gui_api_xmrig: Arc<Mutex<PubXmrigApi>>,
gui_api_xvb: Arc<Mutex<PubXvbApi>>,
img_p2pool: Arc<Mutex<ImgP2pool>>, img_p2pool: Arc<Mutex<ImgP2pool>>,
img_xmrig: Arc<Mutex<ImgXmrig>>, img_xmrig: Arc<Mutex<ImgXmrig>>,
gupax_p2pool_api: Arc<Mutex<GupaxP2poolApi>>, gupax_p2pool_api: Arc<Mutex<GupaxP2poolApi>>,
@ -283,11 +289,13 @@ impl Helper {
uptime: HumanTime::into_human(instant.elapsed()), uptime: HumanTime::into_human(instant.elapsed()),
pub_api_p2pool: arc_mut!(PubP2poolApi::new()), pub_api_p2pool: arc_mut!(PubP2poolApi::new()),
pub_api_xmrig: arc_mut!(PubXmrigApi::new()), pub_api_xmrig: arc_mut!(PubXmrigApi::new()),
pub_api_xvb: arc_mut!(PubXvbApi::new()),
// These are created when initializing [App], since it needs a handle to it as well // These are created when initializing [App], since it needs a handle to it as well
p2pool, p2pool,
xmrig, xmrig,
gui_api_p2pool, gui_api_p2pool,
gui_api_xmrig, gui_api_xmrig,
gui_api_xvb,
img_p2pool, img_p2pool,
img_xmrig, img_xmrig,
gupax_p2pool_api, gupax_p2pool_api,
@ -402,8 +410,10 @@ impl Helper {
let pub_sys = Arc::clone(&lock.pub_sys); let pub_sys = Arc::clone(&lock.pub_sys);
let gui_api_p2pool = Arc::clone(&lock.gui_api_p2pool); let gui_api_p2pool = Arc::clone(&lock.gui_api_p2pool);
let gui_api_xmrig = Arc::clone(&lock.gui_api_xmrig); let gui_api_xmrig = Arc::clone(&lock.gui_api_xmrig);
let gui_api_xvb = Arc::clone(&lock.gui_api_xvb);
let pub_api_p2pool = Arc::clone(&lock.pub_api_p2pool); let pub_api_p2pool = Arc::clone(&lock.pub_api_p2pool);
let pub_api_xmrig = Arc::clone(&lock.pub_api_xmrig); let pub_api_xmrig = Arc::clone(&lock.pub_api_xmrig);
let pub_api_xvb = Arc::clone(&lock.pub_api_xvb);
drop(lock); drop(lock);
let sysinfo_cpu = sysinfo::CpuRefreshKind::everything(); let sysinfo_cpu = sysinfo::CpuRefreshKind::everything();
@ -423,21 +433,25 @@ impl Helper {
// 2. Lock... EVERYTHING! // 2. Lock... EVERYTHING!
let mut lock = lock!(helper); let mut lock = lock!(helper);
debug!("Helper | Locking (1/9) ... [helper]"); debug!("Helper | Locking (1/10) ... [helper]");
let p2pool = lock!(p2pool); let p2pool = lock!(p2pool);
debug!("Helper | Locking (2/9) ... [p2pool]"); debug!("Helper | Locking (2/10) ... [p2pool]");
let xmrig = lock!(xmrig); let xmrig = lock!(xmrig);
debug!("Helper | Locking (3/9) ... [xmrig]"); debug!("Helper | Locking (3/10) ... [xmrig]");
let mut lock_pub_sys = lock!(pub_sys); let mut lock_pub_sys = lock!(pub_sys);
debug!("Helper | Locking (5/9) ... [pub_sys]"); debug!("Helper | Locking (4/10) ... [pub_sys]");
let mut gui_api_p2pool = lock!(gui_api_p2pool); let mut gui_api_p2pool = lock!(gui_api_p2pool);
debug!("Helper | Locking (6/9) ... [gui_api_p2pool]"); debug!("Helper | Locking (5/10) ... [gui_api_p2pool]");
let mut gui_api_xmrig = lock!(gui_api_xmrig); let mut gui_api_xmrig = lock!(gui_api_xmrig);
debug!("Helper | Locking (7/9) ... [gui_api_xmrig]"); debug!("Helper | Locking (6/10) ... [gui_api_xmrig]");
let mut gui_api_xvb = lock!(gui_api_xvb);
debug!("Helper | Locking (7/10) ... [gui_api_xvb]");
let mut pub_api_p2pool = lock!(pub_api_p2pool); let mut pub_api_p2pool = lock!(pub_api_p2pool);
debug!("Helper | Locking (8/9) ... [pub_api_p2pool]"); debug!("Helper | Locking (8/10) ... [pub_api_p2pool]");
let mut pub_api_xmrig = lock!(pub_api_xmrig); let mut pub_api_xmrig = lock!(pub_api_xmrig);
debug!("Helper | Locking (9/9) ... [pub_api_xmrig]"); debug!("Helper | Locking (9/10) ... [pub_api_xmrig]");
let mut pub_api_xvb = lock!(pub_api_xvb);
debug!("Helper | Locking (10/10) ... [pub_api_xvb]");
// Calculate Gupax's uptime always. // Calculate Gupax's uptime always.
lock.uptime = HumanTime::into_human(lock.instant.elapsed()); lock.uptime = HumanTime::into_human(lock.instant.elapsed());
// If [P2Pool] is alive... // If [P2Pool] is alive...
@ -454,6 +468,9 @@ impl Helper {
} else { } else {
debug!("Helper | XMRig is dead! Skipping..."); debug!("Helper | XMRig is dead! Skipping...");
} }
// XvB API is considered always available
debug!("Helper | XvB is alive! Running [combine_gui_pub_api()]");
PubXvbApi::combine_gui_pub_api(&mut gui_api_xvb, &mut pub_api_xvb);
// 2. Selectively refresh [sysinfo] for only what we need (better performance). // 2. Selectively refresh [sysinfo] for only what we need (better performance).
sysinfo.refresh_cpu_specifics(sysinfo_cpu); sysinfo.refresh_cpu_specifics(sysinfo_cpu);
@ -473,21 +490,25 @@ impl Helper {
// 3. Drop... (almost) EVERYTHING... IN REVERSE! // 3. Drop... (almost) EVERYTHING... IN REVERSE!
drop(lock_pub_sys); drop(lock_pub_sys);
debug!("Helper | Unlocking (1/9) ... [pub_sys]"); debug!("Helper | Unlocking (1/10) ... [pub_sys]");
drop(xmrig); drop(xmrig);
debug!("Helper | Unlocking (2/9) ... [xmrig]"); debug!("Helper | Unlocking (2/10) ... [xmrig]");
drop(p2pool); drop(p2pool);
debug!("Helper | Unlocking (3/9) ... [p2pool]"); debug!("Helper | Unlocking (3/10) ... [p2pool]");
drop(pub_api_xvb);
debug!("Helper | Unlocking (4/10) ... [pub_api_xvb]");
drop(pub_api_xmrig); drop(pub_api_xmrig);
debug!("Helper | Unlocking (4/9) ... [pub_api_xmrig]"); debug!("Helper | Unlocking (5/10) ... [pub_api_xmrig]");
drop(pub_api_p2pool); drop(pub_api_p2pool);
debug!("Helper | Unlocking (5/9) ... [pub_api_p2pool]"); debug!("Helper | Unlocking (6/10) ... [pub_api_p2pool]");
drop(gui_api_xvb);
debug!("Helper | Unlocking (7/10) ... [gui_api_xvb]");
drop(gui_api_xmrig); drop(gui_api_xmrig);
debug!("Helper | Unlocking (6/9) ... [gui_api_xmrig]"); debug!("Helper | Unlocking (8/10) ... [gui_api_xmrig]");
drop(gui_api_p2pool); drop(gui_api_p2pool);
debug!("Helper | Unlocking (7/9) ... [gui_api_p2pool]"); debug!("Helper | Unlocking (9/10) ... [gui_api_p2pool]");
drop(lock); drop(lock);
debug!("Helper | Unlocking (8/9) ... [helper]"); debug!("Helper | Unlocking (10/10) ... [helper]");
// 4. Calculate if we should sleep or not. // 4. Calculate if we should sleep or not.
// If we should sleep, how long? // If we should sleep, how long?

162
src/helper/xvb.rs Normal file
View file

@ -0,0 +1,162 @@
use derive_more::Display;
use hyper::client::HttpConnector;
use hyper_tls::HttpsConnector;
use log::{debug, info, warn};
use serde::Deserialize;
use std::{
sync::{Arc, Mutex},
thread,
time::Instant,
};
use crate::utils::{constants::XVB_URL_PUBLIC_API, macros::lock};
use super::Helper;
impl Helper {
pub fn start_xvb(helper: &Arc<Mutex<Self>>) {
let https = HttpsConnector::new();
let client = hyper::Client::builder().build(https);
let gui_api = Arc::clone(&lock!(helper).gui_api_xvb);
let pub_api = Arc::clone(&lock!(helper).pub_api_xvb);
thread::spawn(move || {
Self::spawn_xvb_watchdog(client, gui_api, pub_api);
});
}
#[tokio::main]
async fn spawn_xvb_watchdog(
client: hyper::Client<HttpsConnector<HttpConnector>>,
gui_api: Arc<Mutex<PubXvbApi>>,
pub_api: Arc<Mutex<PubXvbApi>>,
) {
info!("XvB started");
// Reset stats before loop
*lock!(pub_api) = PubXvbApi::new();
*lock!(gui_api) = PubXvbApi::new();
info!("XvB | Entering watchdog mode... woof!");
loop {
// Set timer
let now = Instant::now();
debug!("XvB Watchdog | ----------- Start of loop -----------");
// Send an HTTP API request
debug!("XvB Watchdog | Attempting HTTP API request...");
match PubXvbApi::request_xvb_public_api(client.clone(), XVB_URL_PUBLIC_API).await {
Ok(new_data) => {
debug!("XvB Watchdog | HTTP API request OK");
let mut data = lock!(&pub_api);
*data = new_data;
}
Err(err) => {
warn!(
"XvB Watchdog | Could not send HTTP API request to: {}\n:{}",
XVB_URL_PUBLIC_API, err
);
}
}
// XvB Status do not need to be refreshed like others because combine_with_gui do not refresh if no data is changed.
let elapsed = now.elapsed().as_secs();
if elapsed < 59 {
let sleep = (60 - elapsed) as u64;
debug!("XvB Watchdog | END OF LOOP - Sleeping for [{}]s...", sleep);
std::thread::sleep(std::time::Duration::from_secs(sleep))
} else {
debug!("XMRig Watchdog | END OF LOOP - Not sleeping!");
}
}
}
}
//---------------------------------------------------------------------------------------------------- Public XvB API
use serde_this_or_that::as_u64;
#[derive(Debug, Clone, Default, Deserialize)]
pub struct PubXvbApi {
pub time_remain: u32, // remaining time of round in minutes
pub bonus_hr: f64,
pub donate_hr: f64, // donated hr from all donors
pub donate_miners: u32, // numbers of donors
pub donate_workers: u32, // numbers of workers from donors
pub players: u32,
pub players_round: u32,
pub winner: String,
pub share_effort: String,
pub block_reward: String,
pub round_type: XvbRound,
#[serde(deserialize_with = "as_u64")]
pub block_height: u64,
pub block_hash: String,
#[serde(deserialize_with = "as_u64")]
pub roll_winner: u64,
#[serde(deserialize_with = "as_u64")]
pub roll_round: u64,
pub reward_yearly: Vec<f64>,
}
#[derive(Debug, Clone, Default, Display, Deserialize)]
pub enum XvbRound {
#[default]
#[serde(alias = "vip")]
Vip,
#[serde(alias = "donor")]
Donor,
#[serde(alias = "donor_vip")]
DonorVip,
#[serde(alias = "donor_whale")]
DonorWhale,
#[serde(alias = "donor_mega")]
DonorMega,
}
impl PubXvbApi {
pub fn new() -> Self {
Self::default()
}
pub(super) fn combine_gui_pub_api(gui_api: &mut Self, pub_api: &mut Self) {
// update only if there is data, if no new data, pub_api fields are on default value.
if !pub_api.reward_yearly.is_empty() {
*gui_api = std::mem::take(pub_api)
}
}
#[inline]
// Send an HTTP request to XvB's API, serialize it into [Self] and return it
async fn request_xvb_public_api(
client: hyper::Client<HttpsConnector<HttpConnector>>,
api_uri: &str,
) -> std::result::Result<Self, anyhow::Error> {
let request = hyper::Request::builder()
.method("GET")
.uri(api_uri)
.body(hyper::Body::empty())?;
let response =
tokio::time::timeout(std::time::Duration::from_secs(8), client.request(request))
.await?;
// let response = client.request(request).await;
let body = hyper::body::to_bytes(response?.body_mut()).await?;
Ok(serde_json::from_slice::<Self>(&body)?)
}
}
//---------------------------------------------------------------------------------------------------- TEST
#[cfg(test)]
mod test {
use std::thread;
use super::PubXvbApi;
use crate::utils::constants::XVB_URL_PUBLIC_API;
use hyper::Client;
use hyper_tls::HttpsConnector;
#[test]
fn public_api_deserialize() {
let https = HttpsConnector::new();
let client = hyper::Client::builder().build(https);
let new_data = thread::spawn(move || corr(client)).join().unwrap();
assert!(!new_data.reward_yearly.is_empty());
dbg!(new_data);
}
#[tokio::main]
async fn corr(client: Client<HttpsConnector<hyper::client::HttpConnector>>) -> PubXvbApi {
PubXvbApi::request_xvb_public_api(client, XVB_URL_PUBLIC_API)
.await
.unwrap()
}
}

View file

@ -206,4 +206,7 @@ pub fn init_auto(app: &mut App) {
} else { } else {
info!("Skipping auto-xmrig..."); info!("Skipping auto-xmrig...");
} }
// [XvB]
// For now, the XvB client of the API for receiving public informations is always enabled.
Helper::start_xvb(&app.helper);
} }

View file

@ -181,6 +181,18 @@ pub const STATUS_XMRIG_DIFFICULTY: &str = "The current difficulty of the job XMR
pub const STATUS_XMRIG_SHARES: &str = "The amount of accepted and rejected shares"; pub const STATUS_XMRIG_SHARES: &str = "The amount of accepted and rejected shares";
pub const STATUS_XMRIG_POOL: &str = "The pool XMRig is currently mining to"; pub const STATUS_XMRIG_POOL: &str = "The pool XMRig is currently mining to";
pub const STATUS_XMRIG_THREADS: &str = "The amount of threads XMRig is currently using"; pub const STATUS_XMRIG_THREADS: &str = "The amount of threads XMRig is currently using";
//--
pub const STATUS_XVB_TIME_REMAIN: &str = "Minutes left before end of round";
pub const STATUS_XVB_ROUND_TYPE: &str = "The current round type";
pub const STATUS_XVB_PLAYERS: &str =
"Numbers of registred players and currently playing in the round";
pub const STATUS_XVB_DONATED_HR: &str = "Hashrate donated to the raffle";
pub const STATUS_XVB_WINNER: &str = "Current Raffle Winner";
pub const STATUS_XVB_SHARE: &str = "Share effort";
pub const STATUS_XVB_BLOCK_REWARD: &str = "Block reward";
pub const STATUS_XVB_BLOCK_HEIGHT: &str = "height of the current block";
pub const STATUS_XVB_BLOCK_HASH: &str = "hash of the block that is being worked on";
pub const STATUS_XVB_YEARLY: &str = "Average yearly reward per round type";
// Status Submenus // Status Submenus
pub const STATUS_SUBMENU_PROCESSES: &str = pub const STATUS_SUBMENU_PROCESSES: &str =
"View the status of process related data for [Gupax|P2Pool|XMRig]"; "View the status of process related data for [Gupax|P2Pool|XMRig]";
@ -390,6 +402,7 @@ pub const XMRIG_PATH_EMPTY: &str = "XMRig PATH is empty! To fix: goto the [G
// XvB // XvB
pub const XVB_HELP: &str = "You need to register an account by clicking on the link above to get your token with the same p2pool XMR address you use for payment."; pub const XVB_HELP: &str = "You need to register an account by clicking on the link above to get your token with the same p2pool XMR address you use for payment.";
pub const XVB_URL: &str = "https://xmrvsbeast.com"; pub const XVB_URL: &str = "https://xmrvsbeast.com";
pub const XVB_URL_PUBLIC_API: &str = "https://xmrvsbeast.com/p2pool/stats";
// CLI argument messages // CLI argument messages
pub const ARG_HELP: &str = r#"USAGE: ./gupax [--flag] pub const ARG_HELP: &str = r#"USAGE: ./gupax [--flag]