diff --git a/assets/github.svg b/assets/github.svg index 37fa923..d5e6491 100644 --- a/assets/github.svg +++ b/assets/github.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/api/mod.rs b/src/api/mod.rs index f7a08cb..a1b33a6 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -35,7 +35,7 @@ pub async fn index(State(state): State) -> IndexTemplate { IndexTemplate { monero_enabled: cfg!(feature = "monero"), #[cfg(feature = "monero")] - monero_balance: format!("{}", PrettyPrintFloat(monero_balance)), + monero_balance: format!("{:.5}", PrettyPrintFloat(monero_balance)), #[cfg(feature = "monero")] monero_block_height: state.monero.wallet.get_height().await.unwrap().get(), #[cfg(feature = "monero")] @@ -55,11 +55,11 @@ pub async fn index(State(state): State) -> IndexTemplate { .await .unwrap() .iter() - .filter_map(|transfer| repo.monero_transfer(transfer).ok()) + .filter_map(|transfer| repo.find_monero_transaction(transfer).ok()) .collect(), #[cfg(feature = "monero")] monero_balance_usd: format!( - "{}", + "{:.2}", PrettyPrintFloat(crate::currency::lookup("XMR").await.unwrap_or(0.0) * monero_balance) ), ..Default::default() diff --git a/src/cli.rs b/src/cli.rs index 952f201..a3eb4ad 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -92,6 +92,9 @@ pub async fn serve(args: &ServeArgs) -> Result { #[cfg(feature = "monero")] let app = app.route("/xmr/balance", get(crate::currency::monero::balance)); + #[cfg(feature = "monero")] + let app = app.route("/xmr/payouts", get(crate::currency::monero::payouts)); + // Refresh every hour let every_hour = every(1) .hour() diff --git a/src/currency/mod.rs b/src/currency/mod.rs index bb2b920..e0c284f 100644 --- a/src/currency/mod.rs +++ b/src/currency/mod.rs @@ -6,7 +6,7 @@ use cached::proc_macro::once; #[cfg(feature = "monero")] pub mod monero; -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq, Eq)] pub enum Address { BTC(String), #[cfg(feature = "monero")] diff --git a/src/currency/monero.rs b/src/currency/monero.rs index d8965e0..5fe4f8f 100644 --- a/src/currency/monero.rs +++ b/src/currency/monero.rs @@ -19,7 +19,7 @@ use std::{ time::Duration, }; use std::{str::FromStr, sync::Mutex}; -use tracing::{debug, info}; +use tracing::{debug, info, instrument}; #[derive(Clone, Debug)] pub struct MoneroState { @@ -119,7 +119,7 @@ impl MoneroState { pub async fn get_balance(&self) -> Result { let balance = self.wallet.get_balance(self.account_index, None).await?; debug!(balance = ?balance, "Current Monero wallet balance"); - Ok(balance.unlocked_balance) + Ok(balance.balance) } /// Count outbound transfers to the given address. @@ -146,6 +146,7 @@ impl MoneroState { } /// Get all outbound transfers. + #[instrument(skip_all, ret)] pub async fn get_transfers(&self) -> Result> { let transfers = self .wallet @@ -200,3 +201,14 @@ pub async fn balance(State(state): State) -> impl IntoResponse { ), ) } + +/// Return an SVG badge with the total number of payouts. +pub async fn payouts(State(state): State) -> impl IntoResponse { + ( + [(header::CONTENT_TYPE, "image/svg+xml")], + crate::badge::generate( + "payouts", + &format!("{}", state.monero.get_transfers().await.unwrap().len()), + ), + ) +} diff --git a/src/repo.rs b/src/repo.rs index 2b2a8f2..fb28b4b 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -3,19 +3,22 @@ use anyhow::{bail, Result}; use base64::prelude::*; use chrono::{DateTime, Utc}; use git2::{Commit, Oid, Repository, Sort}; -use std::process::{Command}; +use std::process::Command; use tempfile::TempDir; use tracing::{debug, info, instrument}; #[derive(Debug)] pub struct Contributor { pub address: Address, - pub last_payout: Option>, + /// Paid commits + pub commits: Vec, /// The user's GPG public key ID which must remain constant pub key_id: String, - /// Paid commits - pub commits: Vec, + pub last_payout: Option>, + + /// The contributor's public name from git history + pub name: String, } impl Contributor { @@ -108,33 +111,29 @@ impl TurbineRepo { Ok(repo) } - /// Find the contributor that created the given commit. - pub fn find_contributor<'a>(&'a self, commit_id: String) -> Result<&'a Contributor> { - let commit = self.container.find_commit(Oid::from_str(&commit_id)?)?; - let key_id = get_public_key_id(&commit)?; - - Ok(self + #[cfg(feature = "monero")] + #[instrument(skip(self), ret)] + pub fn find_monero_transaction( + &self, + transfer: &monero_rpc::GotTransfer, + ) -> Result { + if let Some(contributor) = self .contributors .iter() - .find(|contributor| contributor.key_id == key_id) - .unwrap()) - } - - #[cfg(feature = "monero")] - pub fn monero_transfer(&self, transfer: &monero_rpc::GotTransfer) -> Result { - if let Ok(_contributor) = self.find_contributor(transfer.payment_id.to_string()) { + .find(|contributor| contributor.address == Address::XMR(transfer.address.to_string())) + { Ok(Transaction { amount: format!("{}", transfer.amount.as_xmr()), timestamp: transfer.timestamp.timestamp() as u64, - contributor_name: "test".into(), + contributor_name: contributor.name.clone(), }) } else { - bail!(""); + bail!("Transaction not found"); } } /// Verify a commit's GPG signature and return its key ID. - #[instrument(ret, level = "trace")] + #[instrument(skip(self), ret, level = "trace")] fn verify_signature(&self, commit: &Commit) -> Result { // Receive the public key first Command::new("gpg") @@ -217,6 +216,7 @@ impl TurbineRepo { last_payout: None, key_id, commits: Vec::new(), + name: commit.author().name().unwrap_or("").to_string(), }; info!(contributor = ?contributor, "Adding new contributor"); diff --git a/templates/index.html b/templates/index.html index 269f620..9f484e2 100644 --- a/templates/index.html +++ b/templates/index.html @@ -103,7 +103,7 @@ max-height: 20px; } - .address { + .wallet-address-container { white-space: nowrap; } @@ -123,7 +123,7 @@ } #wallet-address { - width: 80px; + width: 100%; } .summary-block { @@ -140,10 +140,11 @@ height: 200px; overflow-y: auto; border: 1px solid rgb(62, 68, 70); - padding: 10px; + padding-top: 10px; + padding-left: 20px; + padding-right: 20px; text-align: left; background-color: rgb(24, 26, 27); - padding: 20px; border-radius: 8px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); margin-left: 10px; @@ -175,6 +176,18 @@ .tooltip:hover .tooltiptext { visibility: visible; } + + a { + color: #007bff; + text-decoration: none; + transition: color 0.3s ease; + font-weight: bold; + } + + a:hover { + color: #0056b3; + text-decoration: underline; + } @@ -199,7 +212,7 @@

{{ monero_balance }} XMR

{% endif %}

Network: {{ monero_network }} ({{ monero_block_height }})

-
+
+

Transaction log

    {% for transaction in monero_transactions %}
  • {{ transaction.amount }} XMR