feat: manage XvB like a new process

feat: maj TODO
fix: use Vec2 instead of separating height and witdh as args in functions
feat: status of XvB process
feat: button to autostart XvB process into Gupax Tab
feat: autostart XvB if button is checked
feat: buttons to start/stop/restart XvB process in XvB Tab
feat: check token and address inputs before allowing to start XvB
feat: add description to buttons when hovering
fix: adjust test
feat: function to verify if token exist on XvB API
clippy auto and manual fix
This commit is contained in:
Louis-Marie Baer 2024-03-12 12:25:34 +01:00
parent bbb61d8268
commit 74355605e9
22 changed files with 934 additions and 616 deletions

View file

@ -12,19 +12,20 @@
- [x] link to website
- [ ] message overing explaining registration and needs to read the rules.
- [ ] token input
- [ ] information
- [ ] status of h/s received by the raffle, authenfication by token.
- [ ] hero checkbox
- [ ] log section
- [ ] status of h/s received by the raffle, authentication by token.
- [ ] status of 1h and 24h average h/s sent to raffle from this instance
- [ ] number of failures
- [ ] log section
- [ ] winner of round
- [ ] round in
- [ ] hero checkbox
- [x] status process XvB
- [x] public information from [API](https://xmrvsbeast.com/p2pool/stats)
- [ ] if not enough hashrate for min round and share acquirement OR no share acquired, node destination for xmrig is only p2pool.
- [ ] if share acquired and enough hashrate to keep up round min hashrate and share acquirement, switch node destination for xmrig between p2pool and raffle giving raffle minimum round requirement + buffer.
- [ ] if hero checked, give maximum hasrate to raffle while keeping enough for p2pool.
- [ ] round type in
- [ ] win or loose
- [ ] new process for XvB
- [x] status process XvB
- [x] public information from [API](https://xmrvsbeast.com/p2pool/stats)
- [x] stop, start, restart buttons
- [x] button to autostart
- [ ] distribute hashrate conforming to the algorithm.
- [ ] output log to console in XvB tab
- [ ] edit metadata of project
- [ ] cargo package metadata
- [ ] pgp signatures

View file

@ -35,19 +35,25 @@ impl eframe::App for App {
let xmrig_is_waiting = xmrig.is_waiting();
let xmrig_state = xmrig.state;
drop(xmrig);
debug!("App | Locking and collecting XvB state...");
let xvb = lock!(self.xvb);
let xvb_is_alive = xvb.is_alive();
let xvb_is_waiting = xvb.is_waiting();
let xvb_state = xvb.state;
drop(xvb);
// This sets the top level Ui dimensions.
// Used as a reference for other uis.
debug!("App | Setting width/height");
CentralPanel::default().show(ctx, |ui| {
let available_width = ui.available_width();
if self.width != available_width {
self.width = available_width;
if self.size.x != available_width {
self.size.x = available_width;
if self.now.elapsed().as_secs() > 5 {
self.must_resize = true;
}
};
self.height = ui.available_height();
self.size.y = ui.available_height();
});
self.resize(ctx);
@ -77,12 +83,15 @@ impl eframe::App for App {
ctx,
p2pool_state,
xmrig_state,
xvb_state,
&key,
wants_input,
p2pool_is_waiting,
xmrig_is_waiting,
xvb_is_waiting,
p2pool_is_alive,
xmrig_is_alive,
xvb_is_alive,
);
self.middle_panel(ctx, frame, key, p2pool_is_alive, xmrig_is_alive);
}

View file

@ -37,6 +37,7 @@ use crate::APP_DEFAULT_WIDTH;
use crate::GUPAX_VERSION;
use crate::OS;
use eframe::CreationContext;
use egui::vec2;
use egui::Vec2;
use log::debug;
use log::error;
@ -61,9 +62,8 @@ pub mod resize;
// actual inner state of the tab settings.
pub struct App {
// Misc state
pub tab: Tab, // What tab are we on?
pub width: f32, // Top-level width
pub height: f32, // Top-level height
pub tab: Tab, // What tab are we on?
pub size: Vec2, // Top-level width and Top-level height
// Alpha (transparency)
// This value is used to incrementally increase/decrease
// the transparency when resizing. Basically, it fades
@ -102,6 +102,7 @@ pub struct App {
pub pub_sys: Arc<Mutex<Sys>>, // [Sys] state, read by [Status], mutated by [Helper]
pub p2pool: Arc<Mutex<Process>>, // [P2Pool] process state
pub xmrig: Arc<Mutex<Process>>, // [XMRig] process state
pub xvb: Arc<Mutex<Process>>, // [Xvb] process state
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 xvb_api: Arc<Mutex<PubXvbApi>>, // Public XvB API
@ -181,6 +182,11 @@ impl App {
String::new(),
PathBuf::new()
));
let xvb = arc_mut!(Process::new(
ProcessName::Xvb,
String::new(),
PathBuf::new()
));
let p2pool_api = arc_mut!(PubP2poolApi::new());
let xmrig_api = arc_mut!(PubXmrigApi::new());
let xvb_api = arc_mut!(PubXvbApi::new());
@ -220,8 +226,7 @@ impl App {
let mut app = Self {
tab: Tab::default(),
ping: arc_mut!(Ping::new()),
width: APP_DEFAULT_WIDTH,
height: APP_DEFAULT_HEIGHT,
size: vec2(APP_DEFAULT_WIDTH, APP_DEFAULT_HEIGHT),
must_resize: false,
og: arc_mut!(State::new()),
state: State::new(),
@ -244,6 +249,7 @@ impl App {
pub_sys.clone(),
p2pool.clone(),
xmrig.clone(),
xvb.clone(),
p2pool_api.clone(),
xmrig_api.clone(),
xvb_api.clone(),
@ -253,6 +259,7 @@ impl App {
)),
p2pool,
xmrig,
xvb,
p2pool_api,
xvb_api,
xmrig_api,

File diff suppressed because it is too large Load diff

View file

@ -22,8 +22,7 @@ impl Gupax {
file_window: &Arc<Mutex<FileWindow>>,
error_state: &mut ErrorState,
restart: &Arc<Mutex<Restart>>,
width: f32,
height: f32,
size: Vec2,
_frame: &mut eframe::Frame,
_ctx: &egui::Context,
ui: &mut egui::Ui,
@ -32,16 +31,16 @@ impl Gupax {
debug!("Gupax Tab | Rendering [Update] button + progress bar");
ui.group(|ui| {
let button = if self.simple {
height / 5.0
size.y / 5.0
} else {
height / 15.0
size.y / 15.0
};
let height = if self.simple {
height / 5.0
size.y / 5.0
} else {
height / 10.0
size.y / 10.0
};
let width = width - SPACE;
let width = size.x - SPACE;
let updating = *lock2!(update, updating);
ui.vertical(|ui| {
// If [Gupax] is being built for a Linux distro,
@ -68,60 +67,53 @@ impl Gupax {
let msg = format!("{}\n{}{}", *lock2!(update, msg), prog, "%");
ui.add_sized([width, height * 1.4], Label::new(RichText::new(msg)));
let height = height / 2.0;
let size = vec2(width, height);
if updating {
ui.add_sized([width, height], Spinner::new().size(height));
ui.add_sized(size, Spinner::new().size(height));
} else {
ui.add_sized([width, height], Label::new("..."));
ui.add_sized(size, Label::new("..."));
}
ui.add_sized(
[width, height],
ProgressBar::new(lock2!(update, prog).round() / 100.0),
);
ui.add_sized(size, ProgressBar::new(lock2!(update, prog).round() / 100.0));
});
});
debug!("Gupax Tab | Rendering bool buttons");
ui.horizontal(|ui| {
ui.group(|ui| {
let width = (width - SPACE * 12.0) / 6.0;
let width = (size.x - SPACE * 12.0) / 6.0;
let height = if self.simple {
height / 10.0
size.y / 10.0
} else {
height / 15.0
size.y / 15.0
};
let size = vec2(width, height);
ui.style_mut().override_text_style = Some(egui::TextStyle::Small);
ui.add_sized(
[width, height],
size,
Checkbox::new(&mut self.update_via_tor, "Update via Tor"),
)
.on_hover_text(GUPAX_UPDATE_VIA_TOR);
ui.separator();
ui.add_sized(
[width, height],
Checkbox::new(&mut self.auto_update, "Auto-Update"),
)
.on_hover_text(GUPAX_AUTO_UPDATE);
ui.add_sized(size, Checkbox::new(&mut self.auto_update, "Auto-Update"))
.on_hover_text(GUPAX_AUTO_UPDATE);
ui.separator();
ui.add_sized(size, Checkbox::new(&mut self.auto_p2pool, "Auto-P2Pool"))
.on_hover_text(GUPAX_AUTO_P2POOL);
ui.separator();
ui.add_sized(size, Checkbox::new(&mut self.auto_xmrig, "Auto-XMRig"))
.on_hover_text(GUPAX_AUTO_XMRIG);
ui.separator();
ui.add_sized(size, Checkbox::new(&mut self.auto_xvb, "Auto-XvB"))
.on_hover_text(GUPAX_AUTO_XVB);
ui.separator();
ui.add_sized(
[width, height],
Checkbox::new(&mut self.auto_p2pool, "Auto-P2Pool"),
)
.on_hover_text(GUPAX_AUTO_P2POOL);
ui.separator();
ui.add_sized(
[width, height],
Checkbox::new(&mut self.auto_xmrig, "Auto-XMRig"),
)
.on_hover_text(GUPAX_AUTO_XMRIG);
ui.separator();
ui.add_sized(
[width, height],
size,
Checkbox::new(&mut self.ask_before_quit, "Ask before quit"),
)
.on_hover_text(GUPAX_ASK_BEFORE_QUIT);
ui.separator();
ui.add_sized(
[width, height],
size,
Checkbox::new(&mut self.save_before_quit, "Save before quit"),
)
.on_hover_text(GUPAX_SAVE_BEFORE_QUIT);
@ -134,7 +126,7 @@ impl Gupax {
debug!("Gupax Tab | Rendering P2Pool/XMRig path selection");
// P2Pool/XMRig binary path selection
let height = height / 28.0;
let height = size.y / 28.0;
let text_edit = (ui.available_width() / 10.0) - SPACE;
ui.group(|ui| {
ui.add_sized(
@ -238,7 +230,8 @@ impl Gupax {
// Saved [Tab]
debug!("Gupax Tab | Rendering [Tab] selector");
ui.group(|ui| {
let width = (width / 5.0) - (SPACE * 1.93);
let width = (size.x / 5.0) - (SPACE * 1.93);
let size = vec2(width, height);
ui.add_sized(
[ui.available_width(), height / 2.0],
Label::new(RichText::new("Default Tab").underline().color(LIGHT_GRAY)),
@ -247,10 +240,7 @@ impl Gupax {
ui.separator();
ui.horizontal(|ui| {
if ui
.add_sized(
[width, height],
SelectableLabel::new(self.tab == Tab::About, "About"),
)
.add_sized(size, SelectableLabel::new(self.tab == Tab::About, "About"))
.on_hover_text(GUPAX_TAB_ABOUT)
.clicked()
{
@ -259,7 +249,7 @@ impl Gupax {
ui.separator();
if ui
.add_sized(
[width, height],
size,
SelectableLabel::new(self.tab == Tab::Status, "Status"),
)
.on_hover_text(GUPAX_TAB_STATUS)
@ -269,10 +259,7 @@ impl Gupax {
}
ui.separator();
if ui
.add_sized(
[width, height],
SelectableLabel::new(self.tab == Tab::Gupax, "Gupax"),
)
.add_sized(size, SelectableLabel::new(self.tab == Tab::Gupax, "Gupax"))
.on_hover_text(GUPAX_TAB_GUPAX)
.clicked()
{
@ -281,7 +268,7 @@ impl Gupax {
ui.separator();
if ui
.add_sized(
[width, height],
size,
SelectableLabel::new(self.tab == Tab::P2pool, "P2Pool"),
)
.on_hover_text(GUPAX_TAB_P2POOL)
@ -291,10 +278,7 @@ impl Gupax {
}
ui.separator();
if ui
.add_sized(
[width, height],
SelectableLabel::new(self.tab == Tab::Xmrig, "XMRig"),
)
.add_sized(size, SelectableLabel::new(self.tab == Tab::Xmrig, "XMRig"))
.on_hover_text(GUPAX_TAB_XMRIG)
.clicked()
{
@ -317,7 +301,7 @@ impl Gupax {
.on_hover_text(GUPAX_ADJUST);
ui.separator();
ui.vertical(|ui| {
let width = width / 10.0;
let width = size.x / 10.0;
ui.spacing_mut().icon_width = width / 25.0;
ui.spacing_mut().slider_width = width * 7.6;
match self.ratio {
@ -334,17 +318,18 @@ impl Gupax {
}
}
let height = height / 3.5;
let size = vec2(width, height);
ui.horizontal(|ui| {
ui.set_enabled(self.ratio != Ratio::Height);
ui.add_sized(
[width, height],
size,
Label::new(format!(
" Width [{}-{}]:",
APP_MIN_WIDTH as u16, APP_MAX_WIDTH as u16
)),
);
ui.add_sized(
[width, height],
size,
Slider::new(
&mut self.selected_width,
APP_MIN_WIDTH as u16..=APP_MAX_WIDTH as u16,
@ -355,14 +340,14 @@ impl Gupax {
ui.horizontal(|ui| {
ui.set_enabled(self.ratio != Ratio::Width);
ui.add_sized(
[width, height],
size,
Label::new(format!(
"Height [{}-{}]:",
APP_MIN_HEIGHT as u16, APP_MAX_HEIGHT as u16
)),
);
ui.add_sized(
[width, height],
size,
Slider::new(
&mut self.selected_height,
APP_MIN_HEIGHT as u16..=APP_MAX_HEIGHT as u16,
@ -372,11 +357,11 @@ impl Gupax {
});
ui.horizontal(|ui| {
ui.add_sized(
[width, height],
size,
Label::new(format!("Scaling [{APP_MIN_SCALE}..{APP_MAX_SCALE}]:")),
);
ui.add_sized(
[width, height],
size,
Slider::new(&mut self.selected_scale, APP_MIN_SCALE..=APP_MAX_SCALE)
.step_by(0.1),
)
@ -388,10 +373,11 @@ impl Gupax {
// Width/Height locks
ui.horizontal(|ui| {
use Ratio::*;
let width = (width / 4.0) - (SPACE * 1.5);
let width = (size.x / 4.0) - (SPACE * 1.5);
let size = vec2(width, height);
if ui
.add_sized(
[width, height],
size,
SelectableLabel::new(self.ratio == Width, "Lock to width"),
)
.on_hover_text(GUPAX_LOCK_WIDTH)
@ -402,7 +388,7 @@ impl Gupax {
ui.separator();
if ui
.add_sized(
[width, height],
size,
SelectableLabel::new(self.ratio == Height, "Lock to height"),
)
.on_hover_text(GUPAX_LOCK_HEIGHT)
@ -412,17 +398,14 @@ impl Gupax {
}
ui.separator();
if ui
.add_sized(
[width, height],
SelectableLabel::new(self.ratio == None, "No lock"),
)
.add_sized(size, SelectableLabel::new(self.ratio == None, "No lock"))
.on_hover_text(GUPAX_NO_LOCK)
.clicked()
{
self.ratio = None;
}
if ui
.add_sized([width, height], Button::new("Set"))
.add_sized(size, Button::new("Set"))
.on_hover_text(GUPAX_SET)
.clicked()
{

View file

@ -24,8 +24,8 @@ impl crate::app::App {
debug!("App | Rendering CENTRAL_PANEL (tab contents)");
CentralPanel::default().show(ctx, |ui| {
// This sets the Ui dimensions after Top/Bottom are filled
self.width = ui.available_width();
self.height = ui.available_height();
self.size.x = ui.available_width();
self.size.y = ui.available_height();
ui.style_mut().override_text_style = Some(TextStyle::Body);
match self.tab {
Tab::About => {
@ -85,8 +85,8 @@ path_xmr: {:#?}\n
self.now.elapsed().as_secs_f32(),
self.state.gupax.selected_width,
self.state.gupax.selected_height,
self.width,
self.height,
self.size.x,
self.size.y,
OS_NAME,
self.max_threads,
self.pid,
@ -117,24 +117,25 @@ path_xmr: {:#?}\n
);
self.error_state.set(debug_info, ErrorFerris::Cute, ErrorButtons::Debug);
}
let width = self.width;
let height = self.height/30.0;
let max_height = self.height;
let width = self.size.x;
let height = self.size.y/30.0;
let max_height = self.size.y;
let size = vec2(width, height);
ui.add_space(10.0);
ui.vertical_centered(|ui| {
ui.set_max_height(max_height);
// Display [Gupax] banner
let link_width = width/14.0;
ui.add_sized(Vec2::new(width, height*3.0), Image::from_bytes("bytes://banner.png", BYTES_BANNER));
ui.add_sized([width, height], Label::new("is a GUI for mining"));
ui.add_sized(size, Label::new("is a GUI for mining"));
ui.add_sized([link_width, height], Hyperlink::from_label_and_url("[Monero]", "https://www.github.com/monero-project/monero"));
ui.add_sized([width, height], Label::new("on"));
ui.add_sized(size, Label::new("on"));
ui.add_sized([link_width, height], Hyperlink::from_label_and_url("[P2Pool]", "https://www.github.com/SChernykh/p2pool"));
ui.add_sized([width, height], Label::new("using"));
ui.add_sized(size, Label::new("using"));
ui.add_sized([link_width, height], Hyperlink::from_label_and_url("[XMRig]", "https://www.github.com/xmrig/xmrig"));
ui.add_space(SPACE*2.0);
ui.add_sized([width, height], Label::new(KEYBOARD_SHORTCUTS));
ui.add_sized(size, Label::new(KEYBOARD_SHORTCUTS));
ui.add_space(SPACE*2.0);
if cfg!(debug_assertions) { ui.label(format!("Gupax is running in debug mode - {}", self.now.elapsed().as_secs_f64())); }
@ -143,23 +144,23 @@ path_xmr: {:#?}\n
}
Tab::Status => {
debug!("App | Entering [Status] Tab");
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);
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.size, ctx, ui);
}
Tab::Gupax => {
debug!("App | Entering [Gupax] Tab");
crate::disk::state::Gupax::show(&mut self.state.gupax, &self.og, &self.state_path, &self.update, &self.file_window, &mut self.error_state, &self.restart, self.width, self.height, frame, ctx, ui);
crate::disk::state::Gupax::show(&mut self.state.gupax, &self.og, &self.state_path, &self.update, &self.file_window, &mut self.error_state, &self.restart, self.size, frame, ctx, ui);
}
Tab::P2pool => {
debug!("App | Entering [P2Pool] Tab");
crate::disk::state::P2pool::show(&mut self.state.p2pool, &mut self.node_vec, &self.og, &self.ping, &self.p2pool, &self.p2pool_api, &mut self.p2pool_stdin, self.width, self.height, ctx, ui);
crate::disk::state::P2pool::show(&mut self.state.p2pool, &mut self.node_vec, &self.og, &self.ping, &self.p2pool, &self.p2pool_api, &mut self.p2pool_stdin, self.size, ctx, ui);
}
Tab::Xmrig => {
debug!("App | Entering [XMRig] Tab");
crate::disk::state::Xmrig::show(&mut self.state.xmrig, &mut self.pool_vec, &self.xmrig, &self.xmrig_api, &mut self.xmrig_stdin, self.width, self.height, ctx, ui);
crate::disk::state::Xmrig::show(&mut self.state.xmrig, &mut self.pool_vec, &self.xmrig, &self.xmrig_api, &mut self.xmrig_stdin, self.size, ctx, ui);
}
Tab::Xvb => {
debug!("App | Entering [XvB] Tab");
crate::disk::state::Xvb::show(self.width, self.height, ctx, ui);
crate::disk::state::Xvb::show(self.size, ctx, ui);
}
}
});

View file

@ -18,7 +18,7 @@ use crate::helper::p2pool::PubP2poolApi;
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
use crate::{components::node::*, constants::*, helper::*, macros::*, utils::regex::Regexes};
use egui::{Color32, Label, RichText, TextEdit, TextStyle::*};
use egui::{Color32, Label, RichText, TextEdit, TextStyle::*, Vec2};
use log::*;
use std::sync::{Arc, Mutex};
@ -37,18 +37,19 @@ impl P2pool {
process: &Arc<Mutex<Process>>,
api: &Arc<Mutex<PubP2poolApi>>,
buffer: &mut String,
width: f32,
height: f32,
size: Vec2,
_ctx: &egui::Context,
ui: &mut egui::Ui,
) {
let text_edit = height / 25.0;
let height = size.y;
let width = size.x;
let text_edit = size.y / 25.0;
//---------------------------------------------------------------------------------------------------- [Simple] Console
debug!("P2Pool Tab | Rendering [Console]");
ui.group(|ui| {
if self.simple {
let height = height / 2.8;
let width = width - SPACE;
let height = size.y / 2.8;
let width = size.x - SPACE;
egui::Frame::none().fill(DARK_GRAY).show(ui, |ui| {
ui.style_mut().override_text_style = Some(Name("MonospaceSmall".into()));
egui::ScrollArea::vertical()

View file

@ -3,7 +3,7 @@ use std::sync::{Arc, Mutex};
use crate::{
app::Benchmark, disk::state::Status, helper::xmrig::PubXmrigApi, utils::human::HumanNumber,
};
use egui::{Hyperlink, ProgressBar, Spinner};
use egui::{Hyperlink, ProgressBar, Spinner, Vec2};
use crate::utils::macros::lock;
@ -13,22 +13,23 @@ use log::*;
impl Status {
pub(super) fn benchmarks(
&mut self,
width: f32,
height: f32,
size: Vec2,
ui: &mut egui::Ui,
benchmarks: &[Benchmark],
xmrig_alive: bool,
xmrig_api: &Arc<Mutex<PubXmrigApi>>,
) {
debug!("Status Tab | Rendering [Benchmarks]");
let text = height / 20.0;
let text = size.x / 20.0;
let double = text * 2.0;
let log = height / 3.0;
let log = size.y / 3.0;
let width = size.x;
let height = size.y;
// [0], The user's CPU (most likely).
let cpu = &benchmarks[0];
ui.horizontal(|ui| {
let width = (width / 2.0) - (SPACE * 1.666);
let width = (size.x / 2.0) - (SPACE * 1.666);
let min_height = log;
ui.group(|ui| {
ui.vertical(|ui| {

View file

@ -15,6 +15,8 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
use egui::Vec2;
use crate::{
app::Benchmark,
disk::{gupax_p2pool_api::GupaxP2poolApi, state::Status, status::*},
@ -47,8 +49,7 @@ impl Status {
max_threads: usize,
gupax_p2pool_api: &Arc<Mutex<GupaxP2poolApi>>,
benchmarks: &[Benchmark],
width: f32,
height: f32,
size: Vec2,
_ctx: &egui::Context,
ui: &mut egui::Ui,
) {
@ -56,8 +57,7 @@ impl Status {
if self.submenu == Submenu::Processes {
self.processes(
sys,
width,
height,
size,
ui,
p2pool_alive,
p2pool_api,
@ -70,17 +70,10 @@ impl Status {
);
//---------------------------------------------------------------------------------------------------- [P2Pool]
} else if self.submenu == Submenu::P2pool {
self.p2pool(
width,
height,
ui,
gupax_p2pool_api,
p2pool_alive,
p2pool_api,
);
self.p2pool(size, ui, gupax_p2pool_api, p2pool_alive, p2pool_api);
//---------------------------------------------------------------------------------------------------- [Benchmarks]
} else if self.submenu == Submenu::Benchmarks {
self.benchmarks(width, height, ui, benchmarks, xmrig_alive, xmrig_api)
self.benchmarks(size, ui, benchmarks, xmrig_alive, xmrig_api)
}
}
}

View file

@ -1,6 +1,6 @@
use std::sync::{Arc, Mutex};
use egui::{Label, RichText, SelectableLabel, Slider, TextEdit};
use egui::{Label, RichText, SelectableLabel, Slider, TextEdit, Vec2};
use crate::{
disk::{
@ -15,14 +15,15 @@ use crate::{
impl Status {
pub fn p2pool(
&mut self,
width: f32,
height: f32,
size: Vec2,
ui: &mut egui::Ui,
gupax_p2pool_api: &Arc<Mutex<GupaxP2poolApi>>,
p2pool_alive: bool,
p2pool_api: &Arc<Mutex<PubP2poolApi>>,
) {
let api = lock!(gupax_p2pool_api);
let height = size.y;
let width = size.x;
let text = height / 25.0;
let log = height / 2.8;
// Payout Text + PayoutView buttons

View file

@ -1,4 +1,4 @@
use egui::{ScrollArea, Ui};
use egui::{ScrollArea, Ui, Vec2};
use std::sync::{Arc, Mutex};
use crate::disk::state::Status;
@ -17,8 +17,7 @@ impl Status {
pub(super) fn processes(
&mut self,
sys: &Arc<Mutex<Sys>>,
width: f32,
height: f32,
size: Vec2,
ui: &mut egui::Ui,
p2pool_alive: bool,
p2pool_api: &Arc<Mutex<PubP2poolApi>>,
@ -29,9 +28,9 @@ impl Status {
xvb_api: &Arc<Mutex<PubXvbApi>>,
max_threads: usize,
) {
let width = (width / 4.0) - (SPACE * 1.7500);
let min_height = height - SPACE;
let height = height / 25.0;
let width = (size.x / 4.0) - (SPACE * 1.7500);
let min_height = size.y - SPACE;
let height = size.y / 25.0;
ui.horizontal(|ui| {
// [Gupax]
gupax(ui, min_height, width, height, sys);
@ -261,6 +260,7 @@ fn p2pool(
})
});
}
#[allow(clippy::too_many_arguments)]
fn xmrig(
ui: &mut Ui,
min_height: f32,
@ -432,14 +432,14 @@ fn xvb(ui: &mut Ui, min_height: f32, width: f32, height: f32, xvb_api: &Arc<Mute
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)));
ui.add_sized([width, height], Label::new(api.share_effort.to_string()));
// 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)));
ui.add_sized([width, height], Label::new(api.block_reward.to_string()));
// reward yearly
ui.add_sized(
[width, height],

View file

@ -23,7 +23,8 @@ use crate::regex::REGEXES;
use crate::utils::regex::Regexes;
use crate::{constants::*, macros::*};
use egui::{
Button, Checkbox, ComboBox, Label, RichText, SelectableLabel, Slider, TextEdit, TextStyle::*,
vec2, Button, Checkbox, ComboBox, Label, RichText, SelectableLabel, Slider, TextEdit,
TextStyle::*, Vec2,
};
use log::*;
@ -38,18 +39,18 @@ impl Xmrig {
process: &Arc<Mutex<Process>>,
api: &Arc<Mutex<PubXmrigApi>>,
buffer: &mut String,
width: f32,
height: f32,
size: Vec2,
_ctx: &egui::Context,
ui: &mut egui::Ui,
) {
let text_edit = height / 25.0;
let text_edit = size.y / 25.0;
//---------------------------------------------------------------------------------------------------- [Simple] Console
debug!("XMRig Tab | Rendering [Console]");
ui.group(|ui| {
if self.simple {
let height = height / 1.5;
let width = width - SPACE;
let height = size.y / 1.5;
let width = size.x - SPACE;
let size = vec2(width, height);
egui::Frame::none().fill(DARK_GRAY).show(ui, |ui| {
ui.style_mut().override_text_style = Some(Name("MonospaceSmall".into()));
egui::ScrollArea::vertical()
@ -59,15 +60,16 @@ impl Xmrig {
.auto_shrink([false; 2])
.show_viewport(ui, |ui, _| {
ui.add_sized(
[width, height],
size,
TextEdit::multiline(&mut lock!(api).output.as_str()),
);
});
});
//---------------------------------------------------------------------------------------------------- [Advanced] Console
} else {
let height = height / 2.8;
let width = width - SPACE;
let height = size.y / 2.8;
let width = size.x - SPACE;
let size = vec2(width, height);
egui::Frame::none().fill(DARK_GRAY).show(ui, |ui| {
ui.style_mut().override_text_style = Some(Name("MonospaceSmall".into()));
egui::ScrollArea::vertical()
@ -77,7 +79,7 @@ impl Xmrig {
.auto_shrink([false; 2])
.show_viewport(ui, |ui, _| {
ui.add_sized(
[width, height],
size,
TextEdit::multiline(&mut lock!(api).output.as_str()),
);
});
@ -109,7 +111,7 @@ impl Xmrig {
debug!("XMRig Tab | Rendering [Arguments]");
ui.group(|ui| {
ui.horizontal(|ui| {
let width = (width / 10.0) - SPACE;
let width = (size.x / 10.0) - SPACE;
ui.add_sized([width, text_edit], Label::new("Command arguments:"));
ui.add_sized(
[ui.available_width(), text_edit],
@ -126,7 +128,7 @@ impl Xmrig {
//---------------------------------------------------------------------------------------------------- Address
debug!("XMRig Tab | Rendering [Address]");
ui.group(|ui| {
let width = width - SPACE;
let width = size.x - SPACE;
ui.spacing_mut().text_edit_width = (width) - (SPACE * 3.0);
let text;
let color;
@ -160,7 +162,7 @@ impl Xmrig {
}
debug!("XMRig Tab | Rendering [Threads]");
ui.vertical(|ui| {
let width = width / 10.0;
let width = size.x / 10.0;
let text_width = width * 2.4;
ui.spacing_mut().slider_width = width * 6.5;
ui.spacing_mut().icon_width = width / 25.0;
@ -471,22 +473,17 @@ impl Xmrig {
ui.horizontal(|ui| {
let width = (ui.available_width() / 2.0) - 11.0;
let height = text_edit * 2.0;
let size = vec2(width, height);
// let mut style = (*ctx.style()).clone();
// style.spacing.icon_width_inner = width / 8.0;
// style.spacing.icon_width = width / 6.0;
// style.spacing.icon_spacing = 20.0;
// ctx.set_style(style);
ui.add_sized(
[width, height],
Checkbox::new(&mut self.tls, "TLS Connection"),
)
.on_hover_text(XMRIG_TLS);
ui.add_sized(size, Checkbox::new(&mut self.tls, "TLS Connection"))
.on_hover_text(XMRIG_TLS);
ui.separator();
ui.add_sized(
[width, height],
Checkbox::new(&mut self.keepalive, "Keepalive"),
)
.on_hover_text(XMRIG_KEEPALIVE);
ui.add_sized(size, Checkbox::new(&mut self.keepalive, "Keepalive"))
.on_hover_text(XMRIG_KEEPALIVE);
});
});
});

View file

@ -1,12 +1,12 @@
use egui::{Hyperlink, Image};
use egui::{Hyperlink, Image, Vec2};
use crate::constants::{BYTES_XVB, SPACE};
impl crate::disk::state::Xvb {
#[inline(always)] // called once
pub fn show(width: f32, height: f32, _ctx: &egui::Context, ui: &mut egui::Ui) {
let website_height = height / 10.0;
let width = width - SPACE;
pub fn show(size: Vec2, _ctx: &egui::Context, ui: &mut egui::Ui) {
let website_height = size.y / 10.0;
let width = size.x - SPACE;
// ui.add_sized(
// [width, website_height],
// Hyperlink::from_label_and_url("XMRvsBeast", "https://xmrvsbeast.com"),

View file

@ -23,8 +23,8 @@ impl crate::app::App {
CentralPanel::default().show(ctx, |ui| {
ui.vertical_centered(|ui| {
// Set width/height/font
let width = self.width;
let height = self.height / 4.0;
let width = self.size.x;
let height = self.size.y / 4.0;
ui.style_mut().override_text_style = Some(Name("MonospaceLarge".into()));
// Display ferris

View file

@ -8,8 +8,8 @@ impl crate::app::App {
pub fn top_panel(&mut self, ctx: &egui::Context) {
debug!("App | Rendering TOP tabs");
TopBottomPanel::top("top").show(ctx, |ui| {
let width = (self.width - (SPACE * 11.0)) / 6.0;
let height = self.height / 15.0;
let width = (self.size.x - (SPACE * 11.0)) / 6.0;
let height = self.size.y / 15.0;
ui.add_space(4.0);
ui.horizontal(|ui| {
ui.style_mut().override_text_style = Some(Name("Tab".into()));

View file

@ -50,9 +50,9 @@ impl App {
ctx.request_repaint();
info!(
"App | Resizing frame to match new internal resolution: [{}x{}]",
self.width, self.height
self.size.x, self.size.y
);
init_text_styles(ctx, self.width, self.state.gupax.selected_scale);
init_text_styles(ctx, self.size.x, self.state.gupax.selected_scale);
self.resizing = false;
}
});

View file

@ -1,3 +1,6 @@
use anyhow::{bail, Result};
use hyper::StatusCode;
use super::*;
use crate::{components::node::RemoteNode, disk::status::*};
//---------------------------------------------------------------------------------------------------- [State] Impl
@ -175,6 +178,7 @@ pub struct Gupax {
pub auto_update: bool,
pub auto_p2pool: bool,
pub auto_xmrig: bool,
pub auto_xvb: bool,
// pub auto_monero: bool,
pub ask_before_quit: bool,
pub save_before_quit: bool,
@ -240,8 +244,15 @@ pub struct Xmrig {
#[derive(Clone, Eq, PartialEq, Debug, Deserialize, Serialize, Default)]
pub struct Xvb {
pub token_confirmed: String,
pub token_inserted: String,
pub token: String,
pub node: XvbNode,
}
#[derive(Clone, Eq, PartialEq, Debug, Deserialize, Serialize, Default)]
pub enum XvbNode {
NorthAmerica,
#[default]
Europe,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
@ -272,6 +283,7 @@ impl Default for Gupax {
auto_update: true,
auto_p2pool: false,
auto_xmrig: false,
auto_xvb: true,
ask_before_quit: true,
save_before_quit: true,
update_via_tor: true,
@ -314,6 +326,36 @@ impl Default for P2pool {
}
}
}
impl Xvb {
pub async fn is_token_exist(address: String, token: String) -> Result<()> {
let client: hyper::Client<hyper::client::HttpConnector> =
hyper::Client::builder().build(hyper::client::HttpConnector::new());
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())
{
if let Ok(resp) = client.request(request).await {
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"),
}
} else {
bail!("error from response")
}
} else {
bail!("request could not be build")
}
}
}
impl Xmrig {
fn with_threads(max_threads: usize, current_threads: usize) -> Self {
let xmrig = Self::default();

View file

@ -31,6 +31,7 @@ mod test {
auto_update = true
auto_p2pool = false
auto_xmrig = false
auto_xvb = false
ask_before_quit = true
save_before_quit = true
update_via_tor = true
@ -97,8 +98,8 @@ mod test {
selected_port = "3333"
[xvb]
token_confirmed = ""
token_inserted = ""
token = ""
node = "Europe"
[version]
gupax = "v1.3.0"
p2pool = "v2.5"

View file

@ -72,6 +72,7 @@ pub struct Helper {
pub pub_sys: Arc<Mutex<Sys>>, // The public API for [sysinfo] that the [Status] tab reads from
pub p2pool: Arc<Mutex<Process>>, // P2Pool process state
pub xmrig: Arc<Mutex<Process>>, // XMRig process state
pub xvb: Arc<Mutex<Process>>, // XvB process state
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_xvb: Arc<Mutex<PubXvbApi>>, // XMRig API state (for GUI thread)
@ -246,6 +247,7 @@ impl Default for ProcessSignal {
pub enum ProcessName {
P2pool,
Xmrig,
Xvb,
}
impl std::fmt::Display for ProcessState {
@ -263,6 +265,7 @@ impl std::fmt::Display for ProcessName {
match *self {
ProcessName::P2pool => write!(f, "P2Pool"),
ProcessName::Xmrig => write!(f, "XMRig"),
ProcessName::Xvb => write!(f, "XvB"),
}
}
}
@ -276,6 +279,7 @@ impl Helper {
pub_sys: Arc<Mutex<Sys>>,
p2pool: Arc<Mutex<Process>>,
xmrig: Arc<Mutex<Process>>,
xvb: Arc<Mutex<Process>>,
gui_api_p2pool: Arc<Mutex<PubP2poolApi>>,
gui_api_xmrig: Arc<Mutex<PubXmrigApi>>,
gui_api_xvb: Arc<Mutex<PubXvbApi>>,
@ -293,6 +297,7 @@ impl Helper {
// These are created when initializing [App], since it needs a handle to it as well
p2pool,
xmrig,
xvb,
gui_api_p2pool,
gui_api_xmrig,
gui_api_xvb,

View file

@ -1,26 +1,98 @@
use derive_more::Display;
use hyper::client::HttpConnector;
use hyper_tls::HttpsConnector;
use log::{debug, info, warn};
use log::{debug, error, info, warn};
use serde::Deserialize;
use std::fmt::Write;
use std::{
sync::{Arc, Mutex},
thread,
time::Instant,
};
use crate::utils::{constants::XVB_URL_PUBLIC_API, macros::lock};
use crate::{
disk::state::Xvb,
helper::{ProcessSignal, ProcessState},
utils::{
constants::{HORI_CONSOLE, XVB_URL_PUBLIC_API},
human::HumanTime,
macros::{lock, lock2, sleep},
},
};
use super::Helper;
use super::{Helper, Process};
impl Helper {
pub fn start_xvb(helper: &Arc<Mutex<Self>>) {
// Just sets some signals for the watchdog thread to pick up on.
pub fn stop_xvb(helper: &Arc<Mutex<Self>>) {
info!("XvB | Attempting to stop...");
lock2!(helper, p2pool).signal = ProcessSignal::Stop;
lock2!(helper, p2pool).state = ProcessState::Middle;
}
pub fn restart_xvb(
helper: &Arc<Mutex<Self>>,
state_xvb: &crate::disk::state::Xvb,
state_p2pool: &crate::disk::state::P2pool,
) {
info!("XvB | Attempting to restart...");
lock2!(helper, p2pool).signal = ProcessSignal::Restart;
lock2!(helper, p2pool).state = ProcessState::Middle;
let helper = helper.clone();
let state_xvb = state_xvb.clone();
let state_p2pool = state_p2pool.clone();
// This thread lives to wait, start xmrig then die.
thread::spawn(move || {
while lock2!(helper, xvb).state != ProcessState::Waiting {
warn!("XvB | Want to restart but process is still alive, waiting...");
sleep!(1000);
}
// Ok, process is not alive, start the new one!
info!("XvB | Old process seems dead, starting new one!");
Self::start_xvb(&helper, &state_xvb, &state_p2pool);
});
info!("XMRig | Restart ... OK");
}
pub fn start_xvb(
helper: &Arc<Mutex<Self>>,
state_xvb: &crate::disk::state::Xvb,
state_p2pool: &crate::disk::state::P2pool,
) {
lock2!(helper, xvb).state = ProcessState::Middle;
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);
let process = Arc::clone(&lock!(helper).xvb);
let state_xvb = state_xvb.clone();
let state_p2pool = state_p2pool.clone();
// two first verifications should be done before starting the process and giving the possibility to start it.
// verify if address is inserted
// if state_p2pool.address.is_empty() {
// warn!("Xvb | Start ... Failed because payout address is not inserted in P2pool tab");
// lock2!(helper, xvb).state = ProcessState::Failed;
// return;
// }
// verify if token exist
// if state_xvb.token.is_empty() {
// warn!("Xvb | Start ... Failed because valid token is not inserted in XvB tab");
// lock2!(helper, xvb).state = ProcessState::Failed;
// return;
// }
// verify if token and address are existent on XvB server
let rt = tokio::runtime::Runtime::new().unwrap();
if !rt.block_on(async move {
Xvb::is_token_exist(state_p2pool.address, state_xvb.token)
.await
.is_ok()
}) {
warn!("Xvb | Start ... Failed because token and associated address are not existent on XvB server");
lock2!(helper, xvb).state = ProcessState::Failed;
return;
}
thread::spawn(move || {
Self::spawn_xvb_watchdog(client, gui_api, pub_api);
Self::spawn_xvb_watchdog(client, gui_api, pub_api, process);
});
}
#[tokio::main]
@ -28,16 +100,31 @@ impl Helper {
client: hyper::Client<HttpsConnector<HttpConnector>>,
gui_api: Arc<Mutex<PubXvbApi>>,
pub_api: Arc<Mutex<PubXvbApi>>,
process: Arc<Mutex<Process>>,
) {
info!("XvB started");
// 2. Set process state
debug!("XvB | Setting process state...");
{
let mut lock = lock!(process);
lock.state = ProcessState::Middle;
lock.signal = ProcessSignal::None;
lock.start = Instant::now();
}
// Reset stats before loop
*lock!(pub_api) = PubXvbApi::new();
*lock!(gui_api) = PubXvbApi::new();
let start = lock!(process).start;
info!("XvB | Entering watchdog mode... woof!");
loop {
// Set timer
let now = Instant::now();
// check signal
if signal_interrupt(process.clone(), start, gui_api.clone()) {
break;
}
debug!("XvB Watchdog | ----------- Start of loop -----------");
// Send an HTTP API request
debug!("XvB Watchdog | Attempting HTTP API request...");
@ -57,7 +144,7 @@ impl Helper {
// 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;
let sleep = 60 - elapsed;
debug!("XvB Watchdog | END OF LOOP - Sleeping for [{}]s...", sleep);
std::thread::sleep(std::time::Duration::from_secs(sleep))
} else {
@ -70,6 +157,10 @@ impl Helper {
use serde_this_or_that::as_u64;
#[derive(Debug, Clone, Default, Deserialize)]
pub struct PubXvbApi {
#[serde(skip)]
pub output: String,
#[serde(skip)]
pub uptime: HumanTime,
pub time_remain: u32, // remaining time of round in minutes
pub bonus_hr: f64,
pub donate_hr: f64, // donated hr from all donors
@ -139,6 +230,57 @@ impl PubXvbApi {
Ok(serde_json::from_slice::<Self>(&body)?)
}
}
fn signal_interrupt(
process: Arc<Mutex<Process>>,
start: Instant,
gui_api: Arc<Mutex<PubXvbApi>>,
) -> bool {
// Check SIGNAL
// check if STOP or RESTART Signal is given.
// if STOP, will put Signal to None, if Restart to Wait
// in either case, will break from loop.
if lock!(process).signal == ProcessSignal::Stop {
debug!("P2Pool Watchdog | Stop SIGNAL caught");
// Wait to get the exit status
let uptime = HumanTime::into_human(start.elapsed());
info!("Xvb Watchdog | Stopped ... Uptime was: [{}]", uptime);
// insert the signal into output of XvB
// This is written directly into the GUI API, because sometimes the 900ms event loop can't catch it.
if let Err(e) = writeln!(
lock!(gui_api).output,
"{}\nXvb stopped | Uptime: [{}] | \n{}\n\n\n\n",
HORI_CONSOLE,
uptime,
HORI_CONSOLE
) {
error!("XvB Watchdog | GUI Uptime/Exit status write failed: {}", e);
}
debug!("XvB Watchdog | Stop SIGNAL done, breaking");
lock!(process).signal = ProcessSignal::None;
return true;
// Check RESTART
} else if lock!(process).signal == ProcessSignal::Restart {
debug!("XvB Watchdog | Restart SIGNAL caught");
let uptime = HumanTime::into_human(start.elapsed());
info!("XvB Watchdog | Stopped ... Uptime was: [{}]", uptime);
// insert the signal into output of XvB
// This is written directly into the GUI API, because sometimes the 900ms event loop can't catch it.
if let Err(e) = writeln!(
lock!(gui_api).output,
"{}\nXvb stopped | Uptime: [{}] | \n{}\n\n\n\n",
HORI_CONSOLE,
uptime,
HORI_CONSOLE
) {
error!("XvB Watchdog | GUI Uptime/Exit status write failed: {}", e);
}
debug!("XvB Watchdog | Restart SIGNAL done, breaking");
lock!(process).state = ProcessState::Waiting;
return true;
}
false
}
//---------------------------------------------------------------------------------------------------- TEST
#[cfg(test)]
mod test {

View file

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

View file

@ -101,6 +101,13 @@ pub const XMRIG_FAILED: &str = "XMRig is offline and failed when exiting";
pub const XMRIG_MIDDLE: &str = "XMRig is in the middle of (re)starting/stopping";
pub const XMRIG_NOT_MINING: &str = "XMRig is online, but not mining to any pool";
pub const XVB_ALIVE: &str =
"XvB process is configured and distributing hashrate, XvB node is online";
pub const XVB_DEAD: &str = "XvB process is offline";
pub const XVB_FAILED: &str = "XvB process is misconfigured or the XvB node is offline";
pub const XVB_MIDDLE: &str = "XvB is in the middle of (re)starting/stopping";
pub const XVB_NOT_CONFIGURED: &str = "You need to insert an existent token before starting XvB";
// This is the typical space added when using
// [ui.separator()] or [ui.group()]
// Used for subtracting the width/height so
@ -266,6 +273,7 @@ pub const GUPAX_ASK_BEFORE_QUIT: &str = "Ask before quitting Gupax";
pub const GUPAX_SAVE_BEFORE_QUIT: &str = "Automatically save any changed settings before quitting";
pub const GUPAX_AUTO_P2POOL: &str = "Automatically start P2Pool on Gupax startup. If you are using [P2Pool Simple], this will NOT wait for your [Auto-Ping] to finish, it will start P2Pool on the pool you already have selected. This option will fail if your P2Pool settings aren't valid!";
pub const GUPAX_AUTO_XMRIG: &str = "Automatically start XMRig on Gupax startup. This option will fail if your XMRig settings aren't valid!";
pub const GUPAX_AUTO_XVB: &str = "Automatically start XvB on Gupax startup. This option will fail if your XvB settings aren't valid!";
pub const GUPAX_ADJUST: &str = "Adjust and set the width/height of the Gupax window";
pub const GUPAX_WIDTH: &str = "Set the width of the Gupax window";
pub const GUPAX_HEIGHT: &str = "Set the height of the Gupax window";