Skip to content

Commit

Permalink
wip: add minimum block height
Browse files Browse the repository at this point in the history
  • Loading branch information
cilki committed Jun 10, 2024
1 parent 28cca58 commit 88883f7
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 33 deletions.
25 changes: 16 additions & 9 deletions src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,27 @@ use axum::{
response::{IntoResponse, Response},
};
use cached::proc_macro::once;
use monero_rpc::monero::Amount;
use chrono::{DateTime, Utc};
use rust_embed::Embed;
use tracing::instrument;

#[derive(Debug, Clone)]
pub struct Transaction {
pub amount: String,
pub timestamp: u64,
}

#[derive(Template, Debug, Clone)]
#[derive(Template, Debug, Clone, Default)]
#[template(path = "index.html")]
pub struct IndexTemplate {
#[cfg(feature = "monero")]
monero_balance: String,
#[cfg(feature = "monero")]
monero_wallet_address: String,
#[cfg(feature = "monero")]
monero_network: String,

monero_block_height: u64,
transactions: Vec<Transaction>,
}

#[once(time = "60")]
#[instrument(ret)]
pub async fn index(State(state): State<AppState>) -> IndexTemplate {
IndexTemplate {
#[cfg(feature = "monero")]
Expand All @@ -39,13 +36,20 @@ pub async fn index(State(state): State<AppState>) -> IndexTemplate {
),
#[cfg(feature = "monero")]
monero_wallet_address: state.monero.wallet_address.to_string(),
#[cfg(feature = "monero")]
monero_network: match state.monero.wallet_address.network {
monero_rpc::monero::Network::Mainnet => "Main",
monero_rpc::monero::Network::Stagenet => "Stage",
monero_rpc::monero::Network::Testnet => "Test",
}
.to_string(),
transactions: Vec::new(),
#[cfg(feature = "monero")]
monero_block_height: state.monero.wallet.get_height().await.unwrap().get(),
transactions: vec![Transaction {
amount: "123".into(),
timestamp: 123,
}],
..Default::default()
}
}

Expand Down Expand Up @@ -95,14 +99,17 @@ pub async fn refresh(State(state): State<AppState>) {
for contributor in repo.contributors.iter() {
match contributor.address.clone() {
crate::currency::Address::BTC(_) => todo!(),
#[cfg(feature = "monero")]
crate::currency::Address::XMR(address) => {
let transfer_count = state.monero.count_transfers(&address).await.unwrap();
for commit_id in contributor.commits.iter().skip(transfer_count) {
state
.monero
.transfer(
&address,
Amount::from_pico(contributor.compute_payout(commit_id.clone())),
monero::Amount::from_pico(
contributor.compute_payout(commit_id.clone()),
),
)
.await
.unwrap();
Expand Down
12 changes: 11 additions & 1 deletion src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ pub struct ServeArgs {
#[clap(long, default_value_t = 9000)]
pub monero_rpc_port: u16,

/// Minimum block height
#[cfg(feature = "monero")]
#[clap(long, default_value_t = 3167951)]
pub monero_block_height: u64,

#[cfg(feature = "monero")]
#[clap(long)]
pub monero_wallet_password: String,
Expand All @@ -51,7 +56,12 @@ pub struct ServeArgs {
/// Restore wallet from a mnemonic seed phrase given by the environment variable:
/// MONERO_WALLET_SEED.
#[cfg(feature = "monero")]
#[clap(long, conflicts_with = "monero_wallet_path", default_value_t = false)]
#[clap(
long,
num_args = 0,
conflicts_with = "monero_wallet_path",
default_value_t = false
)]
pub monero_wallet_seed: bool,

#[cfg(feature = "monero")]
Expand Down
50 changes: 35 additions & 15 deletions src/currency/monero.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
use crate::{cli::ServeArgs, CommandLine};
use anyhow::Result;
use axum::{
extract::{FromRef, State},
http::StatusCode,
Json,
};
use cached::proc_macro::once;
use monero_rpc::{
monero::{Address, Amount},
AddressData, GetTransfersCategory, GetTransfersSelector, RestoreDeterministicWalletArgs,
RpcClientBuilder, TransferOptions, TransferPriority, WalletClient,
AddressData, BlockHeightFilter, GetTransfersCategory, GetTransfersSelector, GotTransfer,
RestoreDeterministicWalletArgs, RpcClientBuilder, TransferOptions, TransferPriority,
WalletClient,
};
use serde::{Deserialize, Serialize};
use std::str::FromStr;
use std::{
collections::HashMap,
Expand All @@ -23,10 +17,11 @@ use tracing::{debug, info, instrument};

#[derive(Clone, Debug)]
pub struct MoneroState {
wallet: WalletClient,
pub wallet: WalletClient,
wallet_process: Option<Arc<Child>>,
pub wallet_address: Address,
account_index: u32,
minimum_block_height: u64,
}

// impl Drop for MoneroState {
Expand Down Expand Up @@ -84,7 +79,7 @@ impl MoneroState {
autosave_current: None,
filename: "turbine".into(),
password: args.monero_wallet_password.clone(),
restore_height: None,
restore_height: Some(args.monero_block_height),
seed: std::env::var("MONERO_WALLET_SEED")?,
seed_offset: None,
})
Expand All @@ -105,25 +100,28 @@ impl MoneroState {
wallet_address: wallet.get_address(0, None).await?.address,
wallet,
account_index: 0,
minimum_block_height: args.monero_block_height,
})
}

#[instrument(ret)]
pub async fn get_balance(&self) -> Result<u64> {
let balance = self.wallet.get_balance(self.account_index, None).await?;
debug!(balance = ?balance, "Current Monero wallet balance");
Ok(balance.unlocked_balance.as_pico())
}

/// Count outbound transfers to the given address.
#[instrument(ret)]
pub async fn count_transfers(&self, address: &str) -> Result<usize> {
let transfers = self
.wallet
.get_transfers(GetTransfersSelector {
category_selector: HashMap::from([(GetTransfersCategory::Out, true)]),
account_index: Some(self.account_index),
subaddr_indices: None,
block_height_filter: None,
block_height_filter: Some(BlockHeightFilter {
min_height: Some(self.minimum_block_height),
max_height: None,
}),
})
.await?;

Expand All @@ -135,8 +133,30 @@ impl MoneroState {
.count())
}

#[instrument(ret)]
/// Get all outbound transfers.
pub async fn get_transfers(&self) -> Result<Vec<GotTransfer>> {
let transfers = self
.wallet
.get_transfers(GetTransfersSelector {
category_selector: HashMap::from([(GetTransfersCategory::Out, true)]),
account_index: Some(self.account_index),
subaddr_indices: None,
block_height_filter: Some(BlockHeightFilter {
min_height: Some(self.minimum_block_height),
max_height: None,
}),
})
.await?;

Ok(transfers
.get(&GetTransfersCategory::Out)
.unwrap_or(&vec![])
.to_owned())
}

/// Transfer the given amount of Monero.
pub async fn transfer(&self, address: &str, amount: Amount) -> Result<()> {
info!(amount = ?amount, dest = ?address, "Transferring Monero");
self.wallet
.transfer(
HashMap::from([(Address::from_str(address)?, amount)]),
Expand Down
3 changes: 2 additions & 1 deletion src/repo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ impl TurbineRepo {
}

/// Verify a commit's GPG signature and return its key ID.
#[instrument(ret)]
#[instrument(ret, level = "trace")]
fn verify_signature(&self, commit: &Commit) -> Result<String> {
// Receive the public key first
Command::new("gpg")
Expand Down Expand Up @@ -159,6 +159,7 @@ impl TurbineRepo {

if let Ok(key_id) = self.verify_signature(&commit) {
if let Some(message) = commit.message() {
#[cfg(feature = "monero")]
if let Some((_, address)) = message.split_once("XMR") {
let address = address.trim().to_string();
if let Some(contributor) = self
Expand Down
26 changes: 19 additions & 7 deletions templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,20 @@
background-image: linear-gradient(to right, #4a4a4a 1px, transparent 1px), linear-gradient(to bottom, #4a4a4a 1px, transparent 1px);
}

ul {
list-style-type: none;
display: flex;
flex-direction: column;
}

li {
margin-bottom: 10px;
padding: 10px;
border-radius: 5px;
color: #2ecc71;
background-color: #dff0d8;
}

.container {
text-align: center;
background-color: #fff;
Expand Down Expand Up @@ -104,6 +118,7 @@
padding: 20px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
margin-left: 20px;
}

.list-item {
Expand All @@ -121,7 +136,7 @@
<img src="/assets/turbine.svg">
</div>
<div class="wallet-info">
<p>Network: {{ monero_network }}</p>
<p>Network: {{ monero_network }} ({{ monero_block_height }})</p>
<p>Balance:</p>
{% if monero_balance != "0" %}
<p class="balance-positive">{{ monero_balance }}</p>
Expand All @@ -140,12 +155,9 @@
</div>
<div class="list-container">
<ul>
<li class="list-item">Item 1</li>
<li class="list-item">Item 2</li>
<li class="list-item">Item 3</li>
<li class="list-item">Item 4</li>
<li class="list-item">Item 5</li>
<!-- Add more list items as needed -->
{% for transaction in transactions %}
<li class="list-item">{{ transaction.amount }}</li>
{% endfor %}
</ul>
</div>

Expand Down

0 comments on commit 88883f7

Please sign in to comment.