Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add get_confirmations() RPC and add to dashboard #56

Merged
merged 8 commits into from
Oct 14, 2023
Merged
3 changes: 2 additions & 1 deletion src/bin/dashboard_src/overview_screen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use super::screen::Screen;
#[derive(Debug, Clone)]
pub struct OverviewData {
synced_balance: Option<Amount>,
confirmations: Option<usize>,
confirmations: Option<u64>,
synchronization_percentage: Option<f64>,

network: Network,
Expand Down Expand Up @@ -199,6 +199,7 @@ impl OverviewScreen {
own_overview_data.syncing=resp.syncing;
own_overview_data.synced_balance = Some(resp.synced_balance);
own_overview_data.is_mining = resp.is_mining;
own_overview_data.confirmations = resp.confirmations;
dan-da marked this conversation as resolved.
Show resolved Hide resolved
}

reset_poller!(dashboard_overview_data, Duration::from_secs(3));
Expand Down
39 changes: 35 additions & 4 deletions src/models/state/wallet/wallet_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -820,32 +820,63 @@ impl WalletState {
self.allocate_sufficient_input_funds_from_lock(&mut lock, requested_amount, block)
}

pub async fn get_balance_history(&self) -> Vec<(Digest, Duration, Amount, Sign)> {
/// Retrieve wallet balance history
///
/// todo: ignore abandoned/unsynced utxo.
/// see: https://github.com/Neptune-Crypto/neptune-core/issues/28
pub async fn get_balance_history(&self) -> Vec<(Digest, Duration, BlockHeight, Amount, Sign)> {
let db_lock = self.wallet_db.lock().await;
let monitored_utxos = db_lock.monitored_utxos.clone();
let num_monitored_utxos = monitored_utxos.len();
let mut history = vec![];
for i in 0..num_monitored_utxos {
let monitored_utxo: MonitoredUtxo = monitored_utxos.get(i);
if let Some((confirming_block, confirmation_timestamp, _)) =
if let Some((confirming_block, confirmation_timestamp, confirmation_height)) =
monitored_utxo.confirmed_in_block
{
let amount = monitored_utxo.utxo.get_native_coin_amount();
history.push((
confirming_block,
confirmation_timestamp,
confirmation_height,
amount,
Sign::NonNegative,
));
if let Some((spending_block, spending_timestamp, _block_height)) =
if let Some((spending_block, spending_timestamp, spending_height)) =
monitored_utxo.spent_in_block
{
history.push((spending_block, spending_timestamp, amount, Sign::Negative));
history.push((
spending_block,
spending_timestamp,
spending_height,
amount,
Sign::Negative,
));
}
}
}
history
}

/// Retrieve block height of last change to wallet balance.
///
/// todo: ignore abandoned/unsynced utxo.
/// also an issue for get_balance_history().
/// see: https://github.com/Neptune-Crypto/neptune-core/issues/28
pub async fn get_latest_balance_height(&self) -> Option<BlockHeight> {
let db_lock = self.wallet_db.lock().await;
let len = db_lock.monitored_utxos.len();
if len > 0 {
let utxo = db_lock.monitored_utxos.get(len - 1);
if let Some((.., confirmation_height)) = utxo.confirmed_in_block {
if let Some((.., spending_height)) = utxo.spent_in_block {
return Some(spending_height);
}
return Some(confirmation_height);
}
}
None
}
}

#[cfg(test)]
Expand Down
37 changes: 35 additions & 2 deletions src/rpc_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ pub struct DashBoardOverviewDataFromClient {

// `None` symbolizes failure to get mining status
pub is_mining: Option<bool>,

// # of confirmations since last wallet balance change.
// `None` indicates that wallet balance has never changed.
pub confirmations: Option<u64>,
}

#[tarpc::service]
Expand All @@ -52,6 +56,13 @@ pub trait RPC {
/// Returns the current block height.
async fn block_height() -> BlockHeight;

/// Returns the number of blocks (confirmations) since wallet balance last changed.
///
/// returns Option<u64>
///
/// return value will be None if wallet has not received any incoming funds.
async fn get_confirmations() -> Option<u64>;

/// Returns info about the peers we are connected to
async fn get_peer_info() -> Vec<PeerInfo>;

Expand Down Expand Up @@ -132,6 +143,7 @@ impl RPC for NeptuneRPCServer {
type GetNetworkFut = Ready<Network>;
type GetListenAddressForPeersFut = Ready<Option<SocketAddr>>;
type BlockHeightFut = Ready<BlockHeight>;
type GetConfirmationsFut = Ready<Option<u64>>;
type GetPeerInfoFut = Ready<Vec<PeerInfo>>;
type HeadFut = Ready<Digest>;
type HeadsFut = Ready<Vec<Digest>>;
Expand Down Expand Up @@ -178,6 +190,24 @@ impl RPC for NeptuneRPCServer {
future::ready(latest_block_header.height)
}

fn get_confirmations(self, _: context::Context) -> Self::GetConfirmationsFut {
match executor::block_on(self.state.wallet_state.get_latest_balance_height()) {
Some(latest_balance_height) => {
let tip_block_header =
executor::block_on(self.state.chain.light_state.get_latest_block_header());

assert!(tip_block_header.height >= latest_balance_height);
dan-da marked this conversation as resolved.
Show resolved Hide resolved
assert!(tip_block_header.height - latest_balance_height <= u64::MAX.into());

// subtract latest balance height from chain tip.
// the cast to u64 is safe given we passed the above asserts.
let confirmations: u64 = (tip_block_header.height - latest_balance_height) as u64;
future::ready(Some(confirmations))
}
None => future::ready(None),
}
}

fn head(self, _: context::Context) -> Self::HeadFut {
let latest_block = executor::block_on(self.state.chain.light_state.get_latest_block());
future::ready(latest_block.hash)
Expand Down Expand Up @@ -317,7 +347,7 @@ impl RPC for NeptuneRPCServer {
// sort
let mut display_history: Vec<(Duration, Amount, Sign)> = history
.iter()
.map(|(_h, t, a, s)| (*t, *a, *s))
.map(|(_h, t, _bh, a, s)| (*t, *a, *s))
.collect::<Vec<_>>();
display_history.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap());

Expand All @@ -327,7 +357,7 @@ impl RPC for NeptuneRPCServer {

fn get_dashboard_overview_data(
self,
_context: tarpc::context::Context,
context: tarpc::context::Context,
) -> Self::GetDashboardOverviewDataFut {
let tip_header = executor::block_on(self.state.chain.light_state.get_latest_block_header());
let wallet_status = executor::block_on(self.state.get_wallet_status_for_tip());
Expand All @@ -346,6 +376,8 @@ impl RPC for NeptuneRPCServer {
Err(_) => None,
};

let confirmations = executor::block_on(self.get_confirmations(context));

future::ready(DashBoardOverviewDataFromClient {
tip_header,
syncing,
Expand All @@ -354,6 +386,7 @@ impl RPC for NeptuneRPCServer {
mempool_tx_count,
peer_count,
is_mining,
confirmations,
})
}

Expand Down
Loading