Skip to content

Commit

Permalink
feat: add estimated earnings (#13)
Browse files Browse the repository at this point in the history
Add estimated earnings
  • Loading branch information
stringhandler authored Aug 2, 2024
1 parent 4a0ec21 commit d955ca1
Show file tree
Hide file tree
Showing 9 changed files with 2,142 additions and 112 deletions.
2,118 changes: 2,024 additions & 94 deletions src-tauri/Cargo.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ tauri-build = { version = "1", features = ["isolation"] }
[dependencies]
tari_common = { git = "https://github.com/tari-project/tari.git", branch = "development" }
tari_shutdown = { git = "https://github.com/tari-project/tari.git", branch = "development" }
minotari_node_grpc_client = { git = "https://github.com/tari-project/tari.git", branch = "development" }
tari_core = { git = "https://github.com/tari-project/tari.git", branch = "development", features = ["transactions"] }

anyhow = "1"
dirs-next = "2.0.0"
Expand Down
27 changes: 21 additions & 6 deletions src-tauri/src/cpu_miner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ use crate::{CpuMinerConfig, CpuMinerConnection, CpuMinerConnectionStatus, CpuMin
use log::warn;
use std::path::PathBuf;
use sysinfo::{CpuRefreshKind, RefreshKind, System};
use tari_core::transactions::tari_amount::MicroMinotari;
use tari_shutdown::{Shutdown, ShutdownSignal};
use tauri::async_runtime::JoinHandle;
use tokio::select;
use tokio::time::MissedTickBehavior;

const RANDOMX_BLOCKS_PER_DAY: u64 = 350;
const LOG_TARGET: &str = "tari::universe::cpu_miner";
pub enum CpuMinerEvent {
Stdout(String),
Expand Down Expand Up @@ -132,7 +134,11 @@ impl CpuMiner {
Ok(())
}

pub async fn status(&self) -> Result<CpuMinerStatus, anyhow::Error> {
pub async fn status(
&self,
network_hash_rate: u64,
block_reward: MicroMinotari,
) -> Result<CpuMinerStatus, anyhow::Error> {
let mut s =
System::new_with_specifics(RefreshKind::new().with_cpu(CpuRefreshKind::everything()));

Expand All @@ -141,27 +147,36 @@ impl CpuMiner {
// Refresh CPUs again.
s.refresh_cpu_all();

// let cpu_brand = s.get_global_processor_info().unwrap().brand().to_string();
let mut cpu_brand = "Unknown";
for cpu in s.cpus() {
cpu_brand = cpu.brand();
println!("{}", cpu.brand());
println!("{}", cpu.name());
break;
}

let cpu_usage = s.global_cpu_usage() as u32;

match &self.api_client {
Some(client) => {
let xmrig_status = client.summary().await?;
let hash_rate = xmrig_status.hashrate.total[0].unwrap_or_default();
dbg!(hash_rate, network_hash_rate, block_reward);
let estimated_earnings = (block_reward.as_u64() as f64
* (hash_rate / network_hash_rate as f64 * RANDOMX_BLOCKS_PER_DAY as f64))
as u64;
// Can't be more than the max reward for a day
let estimated_earnings = std::cmp::min(
estimated_earnings,
block_reward.as_u64() * RANDOMX_BLOCKS_PER_DAY,
);

Ok(CpuMinerStatus {
is_mining: xmrig_status.hashrate.total.len() > 0
&& xmrig_status.hashrate.total[0].is_some()
&& xmrig_status.hashrate.total[0].unwrap() > 0.0,
hash_rate: xmrig_status.hashrate.total[0].unwrap_or_default(),
hash_rate,
cpu_usage: cpu_usage as u32,
cpu_brand: cpu_brand.to_string(),
estimated_earnings: 0,
estimated_earnings: MicroMinotari(estimated_earnings).as_u64(),
connection: CpuMinerConnectionStatus {
is_connected: xmrig_status.connection.uptime > 0,
// error: if xmrig_status.connection.error_log.is_empty() {
Expand Down
19 changes: 17 additions & 2 deletions src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ use serde::Serialize;
use std::sync::Arc;
use std::thread::sleep;
use std::{panic, process};
use tari_core::transactions::tari_amount::MicroMinotari;
use tari_shutdown::Shutdown;
use tauri::{RunEvent, UpdaterEvent};
use tauri::{api, RunEvent, UpdaterEvent};
use tokio::sync::RwLock;

#[tauri::command]
Expand Down Expand Up @@ -89,7 +90,21 @@ async fn stop_mining<'r>(state: tauri::State<'r, UniverseAppState>) -> Result<()
#[tauri::command]
async fn status(state: tauri::State<'_, UniverseAppState>) -> Result<AppStatus, String> {
let cpu_miner = state.cpu_miner.read().await;
let cpu = match cpu_miner.status().await.map_err(|e| e.to_string()) {
let (sha_hash_rate, randomx_hash_rate, block_reward) = match state
.node_manager
.get_network_hash_rate_and_block_reward()
.await
{
Ok((sha_hash_rate, randomx_hash_rate, block_reward)) => {
(sha_hash_rate, randomx_hash_rate, block_reward)
}
Err(e) => (0, 0, MicroMinotari(0)),
};
let cpu = match cpu_miner
.status(randomx_hash_rate, block_reward)
.await
.map_err(|e| e.to_string())
{
Ok(cpu) => cpu,
Err(e) => {
eprintln!("Error getting cpu miner status: {:?}", e);
Expand Down
40 changes: 38 additions & 2 deletions src-tauri/src/minotari_node_adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ use anyhow::Error;
use async_trait::async_trait;
use dirs_next::data_local_dir;
use log::info;
use minotari_node_grpc_client::grpc::{HeightRequest, NewBlockTemplateRequest, PowAlgo};
use minotari_node_grpc_client::BaseNodeGrpcClient;
use std::path::PathBuf;
use tari_core::transactions::tari_amount::MicroMinotari;
use tari_shutdown::Shutdown;
use tokio::select;
use tokio::task::JoinHandle;
Expand Down Expand Up @@ -106,8 +109,6 @@ pub struct MinotariNodeInstance {
handle: Option<JoinHandle<Result<(), anyhow::Error>>>,
}

pub struct MinotariNodeStatusMonitor {}

#[async_trait]
impl ProcessInstance for MinotariNodeInstance {
fn ping(&self) -> bool {
Expand All @@ -124,9 +125,44 @@ impl ProcessInstance for MinotariNodeInstance {
Ok(res)
}
}
pub struct MinotariNodeStatusMonitor {}

impl StatusMonitor for MinotariNodeStatusMonitor {
fn status(&self) -> Result<(), Error> {
todo!()
}
}

impl MinotariNodeStatusMonitor {
pub async fn get_network_hash_rate_and_block_reward(
&self,
) -> Result<(u64, u64, MicroMinotari), Error> {
// TODO: use GRPC port returned from process
let mut client = BaseNodeGrpcClient::connect("http://127.0.0.1:18142").await?;
let res = client
.get_new_block_template(NewBlockTemplateRequest {
algo: Some(PowAlgo { pow_algo: 1 }),
max_weight: 0,
})
.await?;
let mut res = res.into_inner();
let reward = res.miner_data.unwrap().reward;
let res = client
.get_network_difficulty(HeightRequest {
from_tip: 1,
start_height: 0,
end_height: 0,
})
.await?;
let mut res = res.into_inner();
while let Some(difficulty) = res.message().await? {
return Ok((
difficulty.sha3x_estimated_hash_rate,
difficulty.randomx_estimated_hash_rate,
MicroMinotari(reward),
));
}
// Really unlikely to arrive here
Err(anyhow::anyhow!("No difficulty found"))
}
}
19 changes: 17 additions & 2 deletions src-tauri/src/node_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::minotari_node_adapter::MinotariNodeAdapter;
use crate::process_watcher::ProcessWatcher;
use std::path::PathBuf;
use std::sync::Arc;
use tari_core::transactions::tari_amount::MicroMinotari;
use tari_shutdown::ShutdownSignal;
use tokio::sync::RwLock;

Expand All @@ -23,8 +24,8 @@ impl NodeManager {
use_tor = false;
}

let sidecar_adapter = MinotariNodeAdapter::new(use_tor);
let process_watcher = ProcessWatcher::new(sidecar_adapter);
let adapter = MinotariNodeAdapter::new(use_tor);
let process_watcher = ProcessWatcher::new(adapter);

Self {
watcher: Arc::new(RwLock::new(process_watcher)),
Expand Down Expand Up @@ -64,6 +65,20 @@ impl NodeManager {
Ok(0)
}

/// Returns Sha hashrate, Rx hashrate and block reward
pub async fn get_network_hash_rate_and_block_reward(
&self,
) -> Result<(u64, u64, MicroMinotari), anyhow::Error> {
let status_monitor_lock = self.watcher.read().await;
let status_monitor = status_monitor_lock
.status_monitor
.as_ref()
.ok_or_else(|| anyhow::anyhow!("Node not started"))?;
status_monitor
.get_network_hash_rate_and_block_reward()
.await
}

pub async fn stop(&self) -> Result<(), anyhow::Error> {
let mut process_watcher = self.watcher.write().await;
process_watcher.stop().await?;
Expand Down
8 changes: 5 additions & 3 deletions src-tauri/src/process_adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ pub trait ProcessAdapter {
) -> Result<(Self::Instance, Self::StatusMonitor), anyhow::Error>;
fn name(&self) -> &str;

fn spawn(&self, base_folder: PathBuf) -> Result<Self::Instance, anyhow::Error> {
let (instance, _) = self.spawn_inner(base_folder)?;
Ok(instance)
fn spawn(
&self,
base_folder: PathBuf,
) -> Result<(Self::Instance, Self::StatusMonitor), anyhow::Error> {
self.spawn_inner(base_folder)
}
}

Expand Down
7 changes: 5 additions & 2 deletions src-tauri/src/process_watcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ use tauri::async_runtime::JoinHandle;
use tokio::select;
use tokio::time::MissedTickBehavior;

pub struct ProcessWatcher<TAdapter> {
pub struct ProcessWatcher<TAdapter: ProcessAdapter> {
adapter: TAdapter,
watcher_task: Option<JoinHandle<Result<(), anyhow::Error>>>,
internal_shutdown: Shutdown,
poll_time: tokio::time::Duration,
pub(crate) status_monitor: Option<TAdapter::StatusMonitor>,
}

impl<TAdapter: ProcessAdapter> ProcessWatcher<TAdapter> {
Expand All @@ -19,6 +20,7 @@ impl<TAdapter: ProcessAdapter> ProcessWatcher<TAdapter> {
watcher_task: None,
internal_shutdown: Shutdown::new(),
poll_time: tokio::time::Duration::from_secs(1),
status_monitor: None,
}
}
}
Expand All @@ -39,7 +41,8 @@ impl<TAdapter: ProcessAdapter> ProcessWatcher<TAdapter> {

let poll_time = self.poll_time;

let mut child = self.adapter.spawn(base_path)?;
let (mut child, status_monitor) = self.adapter.spawn(base_path)?;
self.status_monitor = Some(status_monitor);

let mut app_shutdown = app_shutdown.clone();
self.watcher_task = Some(tauri::async_runtime::spawn(async move {
Expand Down
14 changes: 13 additions & 1 deletion src/containers/SideBar/Miner/Miner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,18 @@ estimatedEarnings: state.estimatedEarnings
return str.slice(0, num) + '...';
};

function formatNumber(value: number): string {
if (value < 0) {
return value.toPrecision(1);
} else if (value >= 1_000_000) {
return (value / 1_000_000).toFixed(1).replace(/\.0$/, '') + 'm';
} else if (value >= 1_000) {
return (value / 1_000).toFixed(1).replace(/\.0$/, '') + 'k';
} else {
return value.toString();
}
}

return (
<MinerContainer>
<AutoMiner />
Expand All @@ -30,7 +42,7 @@ estimatedEarnings: state.estimatedEarnings
<Tile title="Hashrate (to remove)" stats={hashRate + ' H/s'} />
<Tile title="CPU Utilization" stats={cpuUsage + '%'} />
<Tile title="CHIP/GPU" stats={truncateString(cpuBrand, 10)} />
<Tile title="Est Earnings" stats={ estimatedEarnings + " XTM/24h"} />
<Tile title="Est Earnings" stats={ formatNumber(estimatedEarnings / 1000000) + " XTM/24h"} />
</TileContainer>
</MinerContainer>
);
Expand Down

0 comments on commit d955ca1

Please sign in to comment.