mirror of
https://github.com/Cyrix126/gupaxx.git
synced 2024-12-23 07:09:23 +00:00
feat: construct XvB tab
feat: add Hero checkbox ui and hovering help feat: add private stats ui and thread feat: debug error of API connection in console
This commit is contained in:
parent
f2d0c9a288
commit
0a9375130f
7 changed files with 234 additions and 105 deletions
|
@ -161,7 +161,7 @@ path_xmr: {:#?}\n
|
||||||
}
|
}
|
||||||
Tab::Xvb => {
|
Tab::Xvb => {
|
||||||
debug!("App | Entering [XvB] Tab");
|
debug!("App | Entering [XvB] Tab");
|
||||||
crate::disk::state::Xvb::show(&mut self.state.xvb, self.size, &self.state.p2pool.address, ctx, ui, &self.xvb_api);
|
crate::disk::state::Xvb::show(&mut self.state.xvb, self.size, &self.state.p2pool.address, ctx, ui, &self.xvb_api, lock!(self.xvb).is_alive());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -361,7 +361,7 @@ fn xvb(
|
||||||
xvb_api: &Arc<Mutex<PubXvbApi>>,
|
xvb_api: &Arc<Mutex<PubXvbApi>>,
|
||||||
) {
|
) {
|
||||||
//
|
//
|
||||||
let api = lock!(xvb_api);
|
let api = &lock!(xvb_api).stats_pub;
|
||||||
let enabled = xvb_alive;
|
let enabled = xvb_alive;
|
||||||
ScrollArea::vertical().show(ui, |ui| {
|
ScrollArea::vertical().show(ui, |ui| {
|
||||||
ui.group(|ui| {
|
ui.group(|ui| {
|
||||||
|
@ -477,7 +477,6 @@ fn xvb(
|
||||||
)),
|
)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
drop(api);
|
|
||||||
});
|
});
|
||||||
// by round
|
// by round
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use egui::TextStyle::Name;
|
use egui::TextStyle::Name;
|
||||||
use egui::{Hyperlink, Image, Label, RichText, TextEdit, Vec2};
|
use egui::{vec2, Hyperlink, Image, Layout, RichText, TextEdit, Ui, Vec2};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
|
|
||||||
use crate::helper::xvb::PubXvbApi;
|
use crate::helper::xvb::PubXvbApi;
|
||||||
use crate::utils::constants::{GREEN, LIGHT_GRAY, ORANGE, RED, XVB_HELP, XVB_TOKEN_LEN};
|
use crate::utils::constants::{
|
||||||
|
GREEN, LIGHT_GRAY, ORANGE, RED, XVB_DONATED_1H_FIELD, XVB_DONATED_24H_FIELD, XVB_FAILURE_FIELD,
|
||||||
|
XVB_HELP, XVB_HERO_SELECT, XVB_TOKEN_FIELD, XVB_TOKEN_LEN,
|
||||||
|
};
|
||||||
use crate::utils::macros::lock;
|
use crate::utils::macros::lock;
|
||||||
use crate::utils::regex::Regexes;
|
use crate::utils::regex::Regexes;
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -22,12 +25,13 @@ impl crate::disk::state::Xvb {
|
||||||
_ctx: &egui::Context,
|
_ctx: &egui::Context,
|
||||||
ui: &mut egui::Ui,
|
ui: &mut egui::Ui,
|
||||||
api: &Arc<Mutex<PubXvbApi>>,
|
api: &Arc<Mutex<PubXvbApi>>,
|
||||||
|
xvb_is_alive: bool,
|
||||||
) {
|
) {
|
||||||
|
ui.reset_style();
|
||||||
let website_height = size.y / 10.0;
|
let website_height = size.y / 10.0;
|
||||||
// let width = size.x - SPACE;
|
// let width = size.x - SPACE;
|
||||||
// let height = size.y - SPACE;
|
// let height = size.y - SPACE;
|
||||||
let width = size.x;
|
let width = size.x;
|
||||||
let text_edit = size.y / 25.0;
|
|
||||||
// logo and website link
|
// logo and website link
|
||||||
ui.vertical_centered(|ui| {
|
ui.vertical_centered(|ui| {
|
||||||
ui.add_sized(
|
ui.add_sized(
|
||||||
|
@ -61,43 +65,103 @@ impl crate::disk::state::Xvb {
|
||||||
});
|
});
|
||||||
// input token
|
// input token
|
||||||
let len_token = format!("{}", self.token.len());
|
let len_token = format!("{}", self.token.len());
|
||||||
let text_check;
|
let (text, color) = if self.token.is_empty() {
|
||||||
let color;
|
(
|
||||||
if self.token.is_empty() {
|
format!("{} [{}/{}] ➖", XVB_TOKEN_FIELD, len_token, XVB_TOKEN_LEN),
|
||||||
text_check = format!("[{}/{}] ➖", len_token, XVB_TOKEN_LEN);
|
LIGHT_GRAY,
|
||||||
color = LIGHT_GRAY;
|
)
|
||||||
} else if self.token.parse::<u32>().is_ok() && self.token.len() < XVB_TOKEN_LEN {
|
} else if self.token.parse::<u32>().is_ok() && self.token.len() < XVB_TOKEN_LEN {
|
||||||
text_check = format!("[{}/{}] ", len_token, XVB_TOKEN_LEN);
|
(
|
||||||
color = GREEN;
|
format!("{} [{}/{}]", XVB_TOKEN_FIELD, len_token, XVB_TOKEN_LEN),
|
||||||
|
GREEN,
|
||||||
|
)
|
||||||
} else if self.token.parse::<u32>().is_ok() && self.token.len() == XVB_TOKEN_LEN {
|
} else if self.token.parse::<u32>().is_ok() && self.token.len() == XVB_TOKEN_LEN {
|
||||||
text_check = "✔".to_string();
|
(format!("{} ✔", XVB_TOKEN_FIELD), GREEN)
|
||||||
color = GREEN;
|
|
||||||
} else {
|
} else {
|
||||||
text_check = format!("[{}/{}] ❌", len_token, XVB_TOKEN_LEN);
|
(
|
||||||
color = RED;
|
format!("{} [{}/{}] ❌", XVB_TOKEN_FIELD, len_token, XVB_TOKEN_LEN),
|
||||||
}
|
RED,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
// let width = width - SPACE;
|
||||||
|
// ui.spacing_mut().text_edit_width = (width) - (SPACE * 3.0);
|
||||||
ui.group(|ui| {
|
ui.group(|ui| {
|
||||||
let width = width - SPACE;
|
|
||||||
ui.spacing_mut().text_edit_width = (width) - (SPACE * 3.0);
|
|
||||||
ui.label("Your Token:");
|
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
ui.add_sized(
|
// why does this group is not centered into the parent group ?
|
||||||
[width / 8.0, text_edit],
|
ui.with_layout(Layout::left_to_right(egui::Align::Center), |ui| {
|
||||||
TextEdit::singleline(&mut self.token),
|
ui.group(|ui| {
|
||||||
|
ui.colored_label(color, text);
|
||||||
|
// ui.add_sized(
|
||||||
|
// [width / 8.0, text_edit],
|
||||||
|
// Label::new(RichText::new(text).color(color)),
|
||||||
|
// );
|
||||||
|
ui.add(
|
||||||
|
TextEdit::singleline(&mut self.token)
|
||||||
|
.char_limit(XVB_TOKEN_LEN)
|
||||||
|
.desired_width(width / 8.0)
|
||||||
|
.vertical_align(egui::Align::Center),
|
||||||
);
|
);
|
||||||
|
|
||||||
ui.add(Label::new(RichText::new(text_check).color(color)))
|
|
||||||
});
|
|
||||||
})
|
})
|
||||||
.response
|
.response
|
||||||
.on_hover_text_at_pointer(XVB_HELP);
|
.on_hover_text_at_pointer(XVB_HELP);
|
||||||
|
// hero option
|
||||||
|
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
||||||
|
ui.add_space(width / 24.0);
|
||||||
|
ui.checkbox(&mut self.hero, "Hero")
|
||||||
|
.on_hover_text(XVB_HERO_SELECT);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
})
|
||||||
|
});
|
||||||
// need to warn the user if no address is set in p2pool tab
|
// need to warn the user if no address is set in p2pool tab
|
||||||
if !Regexes::addr_ok(address) {
|
if !Regexes::addr_ok(address) {
|
||||||
debug!("XvB Tab | Rendering warning text");
|
debug!("XvB Tab | Rendering warning text");
|
||||||
ui.label(RichText::new("You don't have any payout address set in the P2pool Tab !\nXvB process needs one to function properly.")
|
ui.label(RichText::new("You don't have any payout address set in the P2pool Tab !\nXvB process needs one to function properly.")
|
||||||
.color(ORANGE));
|
.color(ORANGE));
|
||||||
}
|
}
|
||||||
// hero option
|
|
||||||
// private stats
|
// private stats
|
||||||
|
let priv_stats = &lock!(api).stats_priv;
|
||||||
|
ui.set_enabled(xvb_is_alive);
|
||||||
|
// ui.vertical_centered(|ui| {
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
// widget takes a third less space for two separator.
|
||||||
|
let width_stat =
|
||||||
|
(ui.available_width() / 3.0) - (12.0 + ui.style().spacing.item_spacing.x) / 3.0;
|
||||||
|
// 0.0 means minimum
|
||||||
|
let height_stat = 0.0;
|
||||||
|
let size_stat = vec2(width_stat, height_stat);
|
||||||
|
ui.add_sized(size_stat, |ui: &mut Ui| {
|
||||||
|
ui.group(|ui| {
|
||||||
|
let size_stat = vec2(
|
||||||
|
ui.available_width(),
|
||||||
|
0.0, // + ui.spacing().item_spacing.y,
|
||||||
|
);
|
||||||
|
ui.add_sized(size_stat, |ui: &mut Ui| {
|
||||||
|
ui.vertical_centered(|ui| {
|
||||||
|
ui.label(XVB_FAILURE_FIELD);
|
||||||
|
ui.label(priv_stats.fails.to_string());
|
||||||
|
})
|
||||||
|
.response
|
||||||
|
});
|
||||||
|
ui.separator();
|
||||||
|
ui.add_sized(size_stat, |ui: &mut Ui| {
|
||||||
|
ui.vertical_centered(|ui| {
|
||||||
|
ui.label(XVB_DONATED_1H_FIELD);
|
||||||
|
ui.label(priv_stats.donor_1hr_avg.to_string());
|
||||||
|
})
|
||||||
|
.response
|
||||||
|
});
|
||||||
|
ui.separator();
|
||||||
|
ui.add_sized(size_stat, |ui: &mut Ui| {
|
||||||
|
ui.vertical_centered(|ui| {
|
||||||
|
ui.label(XVB_DONATED_24H_FIELD);
|
||||||
|
ui.label(priv_stats.donor_24hr_avg.to_string());
|
||||||
|
})
|
||||||
|
.response
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.response
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{Result};
|
||||||
use hyper::StatusCode;
|
|
||||||
use hyper_tls::HttpsConnector;
|
|
||||||
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{components::node::RemoteNode, disk::status::*};
|
use crate::{components::node::RemoteNode, disk::status::*};
|
||||||
|
@ -246,6 +247,7 @@ pub struct Xmrig {
|
||||||
#[derive(Clone, Eq, PartialEq, Debug, Deserialize, Serialize, Default)]
|
#[derive(Clone, Eq, PartialEq, Debug, Deserialize, Serialize, Default)]
|
||||||
pub struct Xvb {
|
pub struct Xvb {
|
||||||
pub token: String,
|
pub token: String,
|
||||||
|
pub hero: bool,
|
||||||
pub node: XvbNode,
|
pub node: XvbNode,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,36 +330,6 @@ impl Default for P2pool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Xvb {
|
|
||||||
pub async fn is_token_exist(address: String, token: String) -> Result<()> {
|
|
||||||
let https = HttpsConnector::new();
|
|
||||||
let client = hyper::Client::builder().build(https);
|
|
||||||
if let Ok(request) = hyper::Request::builder()
|
|
||||||
.method("GET")
|
|
||||||
.uri(format!(
|
|
||||||
"{}/cgi-bin/p2pool_bonus_history_api.cgi?address={}&token={}",
|
|
||||||
XVB_URL, address, token
|
|
||||||
))
|
|
||||||
.body(hyper::Body::empty())
|
|
||||||
{
|
|
||||||
match client.request(request).await {
|
|
||||||
Ok(resp) => match resp.status() {
|
|
||||||
StatusCode::OK => Ok(()),
|
|
||||||
StatusCode::UNPROCESSABLE_ENTITY => {
|
|
||||||
bail!("the token is invalid for this xmr address.")
|
|
||||||
}
|
|
||||||
_ => bail!("The status of the response is not expected"),
|
|
||||||
},
|
|
||||||
Err(err) => {
|
|
||||||
bail!("error from response: {}", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
bail!("request could not be build")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Xmrig {
|
impl Xmrig {
|
||||||
fn with_threads(max_threads: usize, current_threads: usize) -> Self {
|
fn with_threads(max_threads: usize, current_threads: usize) -> Self {
|
||||||
let xmrig = Self::default();
|
let xmrig = Self::default();
|
||||||
|
|
|
@ -99,6 +99,7 @@ mod test {
|
||||||
|
|
||||||
[xvb]
|
[xvb]
|
||||||
token = ""
|
token = ""
|
||||||
|
hero = false
|
||||||
node = "Europe"
|
node = "Europe"
|
||||||
[version]
|
[version]
|
||||||
gupax = "v1.3.0"
|
gupax = "v1.3.0"
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
|
use anyhow::{bail, Result};
|
||||||
|
use bytes::Bytes;
|
||||||
use derive_more::Display;
|
use derive_more::Display;
|
||||||
use hyper::client::HttpConnector;
|
use hyper::client::HttpConnector;
|
||||||
|
use hyper::StatusCode;
|
||||||
use hyper_tls::HttpsConnector;
|
use hyper_tls::HttpsConnector;
|
||||||
use log::{debug, error, info, warn};
|
use log::{debug, error, info, warn};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
@ -10,8 +13,8 @@ use std::{
|
||||||
time::Instant,
|
time::Instant,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::utils::constants::XVB_URL;
|
||||||
use crate::{
|
use crate::{
|
||||||
disk::state::Xvb,
|
|
||||||
helper::{ProcessSignal, ProcessState},
|
helper::{ProcessSignal, ProcessState},
|
||||||
utils::{
|
utils::{
|
||||||
constants::{HORI_CONSOLE, XVB_URL_PUBLIC_API},
|
constants::{HORI_CONSOLE, XVB_URL_PUBLIC_API},
|
||||||
|
@ -69,8 +72,8 @@ impl Helper {
|
||||||
let gui_api = Arc::clone(&lock!(helper).gui_api_xvb);
|
let gui_api = Arc::clone(&lock!(helper).gui_api_xvb);
|
||||||
let pub_api = Arc::clone(&lock!(helper).pub_api_xvb);
|
let pub_api = Arc::clone(&lock!(helper).pub_api_xvb);
|
||||||
let process = Arc::clone(&lock!(helper).xvb);
|
let process = Arc::clone(&lock!(helper).xvb);
|
||||||
let state_xvb = state_xvb.clone();
|
let state_xvb_check = state_xvb.clone();
|
||||||
let state_p2pool = state_p2pool.clone();
|
let state_p2pool_check = state_p2pool.clone();
|
||||||
|
|
||||||
// 2. Set process state
|
// 2. Set process state
|
||||||
debug!("XvB | Setting process state...");
|
debug!("XvB | Setting process state...");
|
||||||
|
@ -83,7 +86,7 @@ impl Helper {
|
||||||
// verify if token and address are existent on XvB server
|
// verify if token and address are existent on XvB server
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
let resp: anyhow::Result<()> = rt.block_on(async move {
|
let resp: anyhow::Result<()> = rt.block_on(async move {
|
||||||
Xvb::is_token_exist(state_p2pool.address, state_xvb.token).await?;
|
XvbPrivStats::request_api(&state_p2pool_check.address, &state_xvb_check.token).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
match resp {
|
match resp {
|
||||||
|
@ -105,9 +108,17 @@ impl Helper {
|
||||||
lock2!(helper, xvb).state = ProcessState::NotMining;
|
lock2!(helper, xvb).state = ProcessState::NotMining;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let state_xvb_thread = state_xvb.clone();
|
||||||
|
let state_p2pool_thread = state_p2pool.clone();
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
Self::spawn_xvb_watchdog(client, gui_api, pub_api, process);
|
Self::spawn_xvb_watchdog(
|
||||||
|
client,
|
||||||
|
gui_api,
|
||||||
|
pub_api,
|
||||||
|
process,
|
||||||
|
&state_xvb_thread,
|
||||||
|
&state_p2pool_thread,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
@ -116,6 +127,8 @@ impl Helper {
|
||||||
gui_api: Arc<Mutex<PubXvbApi>>,
|
gui_api: Arc<Mutex<PubXvbApi>>,
|
||||||
pub_api: Arc<Mutex<PubXvbApi>>,
|
pub_api: Arc<Mutex<PubXvbApi>>,
|
||||||
process: Arc<Mutex<Process>>,
|
process: Arc<Mutex<Process>>,
|
||||||
|
state_xvb: &crate::disk::state::Xvb,
|
||||||
|
state_p2pool: &crate::disk::state::P2pool,
|
||||||
) {
|
) {
|
||||||
info!("XvB started");
|
info!("XvB started");
|
||||||
|
|
||||||
|
@ -142,14 +155,11 @@ impl Helper {
|
||||||
// if since is 0, send request because it's the first time.
|
// if since is 0, send request because it's the first time.
|
||||||
let since = lock!(gui_api).tick;
|
let since = lock!(gui_api).tick;
|
||||||
if since >= 60 || since == 0 {
|
if since >= 60 || since == 0 {
|
||||||
// *lock!(pub_api) = PubXvbApi::new();
|
debug!("XvB Watchdog | Attempting HTTP public API request...");
|
||||||
// *lock!(gui_api) = PubXvbApi::new();
|
match XvbPubStats::request_api(client.clone()).await {
|
||||||
debug!("XvB Watchdog | Attempting HTTP API request...");
|
|
||||||
match PubXvbApi::request_xvb_public_api(client.clone(), XVB_URL_PUBLIC_API).await {
|
|
||||||
Ok(new_data) => {
|
Ok(new_data) => {
|
||||||
debug!("XvB Watchdog | HTTP API request OK");
|
debug!("XvB Watchdog | HTTP API request OK");
|
||||||
*lock!(&pub_api) = new_data;
|
lock!(&pub_api).stats_pub = new_data;
|
||||||
lock!(gui_api).tick += 0;
|
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!(
|
warn!(
|
||||||
|
@ -168,6 +178,45 @@ impl Helper {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
debug!("XvB Watchdog | Attempting HTTP private API request...");
|
||||||
|
match XvbPrivStats::request_api(&state_p2pool.address, &state_xvb.token).await {
|
||||||
|
Ok(b) => {
|
||||||
|
debug!("XvB Watchdog | HTTP API request OK");
|
||||||
|
let new_data = match serde_json::from_slice::<XvbPrivStats>(&b) {
|
||||||
|
Ok(data) => data,
|
||||||
|
Err(e) => {
|
||||||
|
warn!("XvB Watchdog | Data provided from private API is not deserializ-able.Error: {}", e);
|
||||||
|
// output the error to console
|
||||||
|
if let Err(e) = writeln!(
|
||||||
|
lock!(gui_api).output,
|
||||||
|
"XvB Watchdog | Data provided from private API is not deserializ-able.Error: {}", e
|
||||||
|
) {
|
||||||
|
error!("XvB Watchdog | GUI status write failed: {}", e);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
lock!(&pub_api).stats_priv = new_data;
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
warn!(
|
||||||
|
"XvB Watchdog | Could not send HTTP private API request to: {}\n:{}",
|
||||||
|
XVB_URL, err
|
||||||
|
);
|
||||||
|
// output the error to console
|
||||||
|
if let Err(e) = writeln!(
|
||||||
|
lock!(gui_api).output,
|
||||||
|
"Failure to retrieve private stats from {}",
|
||||||
|
XVB_URL
|
||||||
|
) {
|
||||||
|
error!("XvB Watchdog | GUI status write failed: {}", e);
|
||||||
|
}
|
||||||
|
lock!(process).state = ProcessState::Failed;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lock!(gui_api).tick += 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
lock!(gui_api).tick += 1;
|
lock!(gui_api).tick += 1;
|
||||||
|
@ -188,14 +237,17 @@ impl Helper {
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------------------------------- Public XvB API
|
//---------------------------------------------------------------------------------------------------- Public XvB API
|
||||||
use serde_this_or_that::as_u64;
|
use serde_this_or_that::as_u64;
|
||||||
#[derive(Debug, Clone, Default, Deserialize)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct PubXvbApi {
|
pub struct PubXvbApi {
|
||||||
#[serde(skip)]
|
|
||||||
pub output: String,
|
pub output: String,
|
||||||
#[serde(skip)]
|
|
||||||
pub uptime: HumanTime,
|
pub uptime: HumanTime,
|
||||||
#[serde(skip)]
|
|
||||||
pub tick: u8,
|
pub tick: u8,
|
||||||
|
pub stats_pub: XvbPubStats,
|
||||||
|
pub stats_priv: XvbPrivStats,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, Deserialize)]
|
||||||
|
pub struct XvbPubStats {
|
||||||
pub time_remain: u32, // remaining time of round in minutes
|
pub time_remain: u32, // remaining time of round in minutes
|
||||||
pub bonus_hr: f64,
|
pub bonus_hr: f64,
|
||||||
pub donate_hr: f64, // donated hr from all donors
|
pub donate_hr: f64, // donated hr from all donors
|
||||||
|
@ -217,6 +269,62 @@ pub struct PubXvbApi {
|
||||||
pub reward_yearly: Vec<f64>,
|
pub reward_yearly: Vec<f64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl XvbPubStats {
|
||||||
|
#[inline]
|
||||||
|
// Send an HTTP request to XvB's API, serialize it into [Self] and return it
|
||||||
|
async fn request_api(
|
||||||
|
client: hyper::Client<HttpsConnector<HttpConnector>>,
|
||||||
|
) -> std::result::Result<Self, anyhow::Error> {
|
||||||
|
let request = hyper::Request::builder()
|
||||||
|
.method("GET")
|
||||||
|
.uri(XVB_URL_PUBLIC_API)
|
||||||
|
.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)?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl XvbPrivStats {
|
||||||
|
pub async fn request_api(address: &str, token: &str) -> Result<Bytes> {
|
||||||
|
let https = HttpsConnector::new();
|
||||||
|
let client = hyper::Client::builder().build(https);
|
||||||
|
if let Ok(request) = hyper::Request::builder()
|
||||||
|
.method("GET")
|
||||||
|
.uri(format!(
|
||||||
|
"{}/cgi-bin/p2pool_bonus_history_api.cgi?address={}&token={}",
|
||||||
|
XVB_URL, address, token
|
||||||
|
))
|
||||||
|
.body(hyper::Body::empty())
|
||||||
|
{
|
||||||
|
match client.request(request).await {
|
||||||
|
Ok(mut resp) => match resp.status() {
|
||||||
|
StatusCode::OK => Ok(hyper::body::to_bytes(resp.body_mut()).await?),
|
||||||
|
StatusCode::UNPROCESSABLE_ENTITY => {
|
||||||
|
bail!("the token is invalid for this xmr address.")
|
||||||
|
}
|
||||||
|
_ => bail!("The status of the response is not expected"),
|
||||||
|
},
|
||||||
|
Err(err) => {
|
||||||
|
bail!("error from response: {}", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bail!("request could not be build")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, Deserialize)]
|
||||||
|
pub struct XvbPrivStats {
|
||||||
|
pub fails: u8,
|
||||||
|
pub donor_1hr_avg: f32,
|
||||||
|
pub donor_24hr_avg: f32,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Display, Deserialize)]
|
#[derive(Debug, Clone, Default, Display, Deserialize)]
|
||||||
pub enum XvbRound {
|
pub enum XvbRound {
|
||||||
#[default]
|
#[default]
|
||||||
|
@ -257,24 +365,6 @@ impl PubXvbApi {
|
||||||
..pub_api.clone()
|
..pub_api.clone()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#[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)?)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signal_interrupt(
|
fn signal_interrupt(
|
||||||
|
@ -323,8 +413,7 @@ fn signal_interrupt(
|
||||||
mod test {
|
mod test {
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
|
||||||
use super::PubXvbApi;
|
use super::XvbPubStats;
|
||||||
use crate::utils::constants::XVB_URL_PUBLIC_API;
|
|
||||||
use hyper::Client;
|
use hyper::Client;
|
||||||
use hyper_tls::HttpsConnector;
|
use hyper_tls::HttpsConnector;
|
||||||
|
|
||||||
|
@ -337,9 +426,7 @@ mod test {
|
||||||
dbg!(new_data);
|
dbg!(new_data);
|
||||||
}
|
}
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn corr(client: Client<HttpsConnector<hyper::client::HttpConnector>>) -> PubXvbApi {
|
async fn corr(client: Client<HttpsConnector<hyper::client::HttpConnector>>) -> XvbPubStats {
|
||||||
PubXvbApi::request_xvb_public_api(client, XVB_URL_PUBLIC_API)
|
XvbPubStats::request_api(client).await.unwrap()
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -411,6 +411,12 @@ pub const XVB_HELP: &str = "You need to register an account by clicking on the l
|
||||||
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";
|
pub const XVB_URL_PUBLIC_API: &str = "https://xmrvsbeast.com/p2pool/stats";
|
||||||
pub const XVB_TOKEN_LEN: usize = 9;
|
pub const XVB_TOKEN_LEN: usize = 9;
|
||||||
|
pub const XVB_HERO_SELECT: &str =
|
||||||
|
"Donate all spared hashrate to the raffle, even if there is more than enough to be in the most highest round type possible";
|
||||||
|
pub const XVB_TOKEN_FIELD: &str = "Token";
|
||||||
|
pub const XVB_FAILURE_FIELD: &str = "Failures";
|
||||||
|
pub const XVB_DONATED_1H_FIELD: &str = "Donated last hour";
|
||||||
|
pub const XVB_DONATED_24H_FIELD: &str = "Donated last 24 hours";
|
||||||
|
|
||||||
// CLI argument messages
|
// CLI argument messages
|
||||||
pub const ARG_HELP: &str = r#"USAGE: ./gupax [--flag]
|
pub const ARG_HELP: &str = r#"USAGE: ./gupax [--flag]
|
||||||
|
|
Loading…
Reference in a new issue