Skip to content

Commit

Permalink
feat: start implementing transaction history view
Browse files Browse the repository at this point in the history
  • Loading branch information
MishkaRogachev committed Oct 10, 2024
1 parent c1d2717 commit 4dc9f90
Show file tree
Hide file tree
Showing 8 changed files with 197 additions and 19 deletions.
8 changes: 6 additions & 2 deletions src/core/balance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ impl BalanceValue {
pub fn new(value: f64, usd_value: f64) -> Self {
Self { value, usd_value }
}

pub fn to_string(&self) -> String {
format!("{:.6} ({:.2} USD)", self.value, self.usd_value)
}
}

impl Balance {
Expand All @@ -30,7 +34,7 @@ impl Balance {

pub fn to_string(&self) -> String {
let summary = self.summary();
format!("{:.6} {} ({:.2} USD)", summary.value, self.currency, summary.usd_value)
summary.to_string()
}

pub fn summary(&self) -> BalanceValue {
Expand All @@ -39,7 +43,7 @@ impl Balance {
})
}

pub fn from_test_network(&self) -> bool {
pub fn is_from_test_network(&self) -> bool {
self.chain_values.keys().any(|k| k.is_test_network())
}

Expand Down
1 change: 1 addition & 0 deletions src/tui/screens/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ mod account_import_finalize;
// Main
mod porfolio;
mod porfolio_accounts;
mod porfolio_transactions;
mod account_delete;
mod mnemonic_access;
mod mnemonic_delete;
29 changes: 20 additions & 9 deletions src/tui/screens/porfolio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ use crate::tui::{widgets::controls, app::{AppCommand, AppScreen}};
const POPUP_WIDTH: u16 = 60;
const POPUP_HEIGHT: u16 = 30;

#[derive(Clone, PartialEq, Eq, Hash)]
enum ManageOption {
Networks,
AccessMnemonic,
DeleteAccount,
}

pub struct Screen {
command_tx: mpsc::Sender<AppCommand>,
session: Session,
Expand All @@ -26,13 +33,6 @@ pub struct Screen {
popup: Option<Box<dyn AppScreen + Send>>,
}

#[derive(Clone, PartialEq, Eq, Hash)]
enum ManageOption {
Networks,
AccessMnemonic,
DeleteAccount,
}

impl Screen {
pub fn new(command_tx: mpsc::Sender<AppCommand>, session: Session) -> Self {
let infura_token = std::env::var("INFURA_TOKEN")
Expand All @@ -44,8 +44,8 @@ impl Screen {
let crypto = Arc::new(Mutex::new(crypto));

let mode_switch = controls::MultiSwitch::new(vec![
controls::Button::new("Accounts", Some('a')).disable(),
controls::Button::new("Transactions", Some('t')).disable(),
controls::Button::new("Accounts", Some('a')),
controls::Button::new("Transactions", Some('t')),
controls::Button::new("Charts", Some('c')).disable(),
controls::Button::new("Settings", Some('s')).disable(),
]);
Expand Down Expand Up @@ -120,7 +120,18 @@ impl AppScreen for Screen {
}

if let Some(index) = self.mode_switch.handle_event(&event) {
// TODO: switch to enum
match index {
0 => {
self.mode = Some(Box::new(
super::porfolio_accounts::Screen::new(self.session.clone(), self.crypto.clone())
));
},
1 => {
self.mode = Some(Box::new(
super::porfolio_transactions::Screen::new(self.session.clone(), self.crypto.clone())
));
},
_ => {} // TODO: implement modes
}
return Ok(false);
Expand Down
7 changes: 4 additions & 3 deletions src/tui/screens/porfolio_accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ pub struct Screen {
crypto: Arc<Mutex<Crypto>>,
last_update: Option<tokio::time::Instant>,

accounts: Vec<account::Account>,
accounts: Vec<account::AccountDisplay>,
busy: controls::Busy,
scroll: controls::Scroll,
}

impl Screen {
pub fn new(session: Session, crypto: Arc<Mutex<Crypto>>) -> Self {
let accounts = vec![account::Account::new(session.account)];
let accounts = vec![account::AccountDisplay::new(session.account)];
let busy = controls::Busy::new("Loading..");
let scroll = controls::Scroll::new();

Expand Down Expand Up @@ -118,7 +118,8 @@ impl AppScreen for Screen {
}));

let mut total_content_height = 0;
for (account, account_layout) in self.accounts.iter_mut().zip(accounts_layout.iter()) {
for (account, account_layout) in self.accounts
.iter_mut().zip(accounts_layout.iter()) {
account.scroll_offset = self.scroll.position;
account.render(frame, *account_layout);
total_content_height += account.implicit_height();
Expand Down
102 changes: 102 additions & 0 deletions src/tui/screens/porfolio_transactions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
use std::sync::Arc;
use tokio::sync::Mutex;
use ratatui::{
crossterm::event::Event,
layout::{Alignment, Constraint, Direction, Layout, Margin, Rect},
style::{Color, Style},
widgets::Paragraph, Frame
};

use crate::service::{crypto:: Crypto, session::Session};
use crate::tui::{widgets::{controls, transaction}, app::AppScreen};

const TITLE_HEIGHT: u16 = 2;
const TITLE_TEXT: &str = "Transaction history:";

const TRANSACTION_CNT_PER_PAGE: usize = 10;

pub struct Screen {
crypto: Arc<Mutex<Crypto>>,

transactions: Vec<transaction::TransactionDisplay>,
busy: controls::Busy,
scroll: controls::Scroll,
}

impl Screen {
pub fn new(session: Session, crypto: Arc<Mutex<Crypto>>) -> Self {
let transactions = session.db.get_transactions(
session.account, 0, TRANSACTION_CNT_PER_PAGE).expect(
"Failed to get transactions"
);

let transactions = transactions.into_iter().map(|tx| {
transaction::TransactionDisplay::new(tx, transaction::TransactionDisplayType::Incoming)
}).collect();

let busy = controls::Busy::new("Loading..");
let scroll = controls::Scroll::new();

Self {
crypto,
transactions,
busy,
scroll
}
}
}

#[async_trait::async_trait]
impl AppScreen for Screen {
async fn handle_event(&mut self, event: Event) -> anyhow::Result<bool> {
self.scroll.handle_event(&event);
Ok(false)
}

async fn update(&mut self) {
let crypto = self.crypto.lock().await;

}

fn render(&mut self, frame: &mut Frame, area: Rect) {
let content_layout = Layout::default()
.direction(Direction::Vertical)
.constraints([
Constraint::Length(TITLE_HEIGHT),
Constraint::Fill(0), // Fill height for trasnactions
])
.split(area);

let summary = Layout::default()
.direction(Direction::Horizontal)
.constraints([
Constraint::Percentage(35),
Constraint::Percentage(65),
])
.split(content_layout[0]);

let summary_label = Paragraph::new(TITLE_TEXT)
.style(Style::default().fg(Color::Yellow).add_modifier(ratatui::style::Modifier::BOLD))
.alignment(Alignment::Left);
frame.render_widget(summary_label, summary[0]);

let transactions_layout = Layout::default()
.direction(Direction::Vertical)
.constraints(self.transactions.iter().map(|_| Constraint::Fill(1)).collect::<Vec<_>>().as_slice())
.split(content_layout[1].inner(Margin {
vertical: 0,
horizontal: 1,
}));

let mut total_content_height = 0;
for (transaction, transaction_layout) in self.transactions
.iter_mut().zip(transactions_layout.iter()) {
//transaction.scroll_offset = self.scroll.position;
transaction.render(frame, *transaction_layout);
total_content_height += transaction.implicit_height();
}

self.scroll.total = total_content_height;
self.scroll.render(frame, content_layout[1]);
}
}
8 changes: 4 additions & 4 deletions src/tui/widgets/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ use super::controls;

const HEADER_HEIGHT: usize = 3;

pub struct Account {
pub struct AccountDisplay {
pub name: String,
pub address: web3::types::Address,
pub balances: Option<Balances>,
pub scroll_offset: usize,
busy: controls::Busy,
}

impl Account {
impl AccountDisplay {
pub fn new(address: web3::types::Address) -> Self {
let busy = controls::Busy::new("Loading..");

Expand All @@ -41,7 +41,7 @@ impl Account {
balances.iter().fold((0.0, false), |(total_usd, from_test), balance| {
(
total_usd + balance.summary().usd_value,
from_test || balance.from_test_network(),
from_test || balance.is_from_test_network(),
)
})
})
Expand Down Expand Up @@ -119,7 +119,7 @@ impl Account {
.style(Style::default().fg(Color::Yellow))
.alignment(Alignment::Left);

let token_value_color = if balance.from_test_network() { Color::Red } else { Color::Yellow };
let token_value_color = if balance.is_from_test_network() { Color::Red } else { Color::Yellow };
let token_value_label = Paragraph::new(balance.to_string())
.style(Style::default().fg(token_value_color))
.alignment(Alignment::Right);
Expand Down
3 changes: 2 additions & 1 deletion src/tui/widgets/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod controls;
pub mod ascii;
pub mod mnemonic;
pub mod account;
pub mod account;
pub mod transaction;
58 changes: 58 additions & 0 deletions src/tui/widgets/transaction.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
use ratatui::{
layout::{Alignment, Margin, Rect},
style::{Color, Style},
widgets::Paragraph,
Frame
};

use crate::core::transaction::TransactionResult;

const TRANSACTION_HEIGHT: usize = 3;

pub enum TransactionDisplayType {
Incoming,
Outgoing,
Swap,
}

pub struct TransactionDisplay {
transaction: TransactionResult,
transaction_type: TransactionDisplayType,
}

impl TransactionDisplay {
pub fn new(transaction: TransactionResult, transaction_type: TransactionDisplayType) -> Self {
Self {
transaction,
transaction_type,
}
}

pub fn implicit_height(&self) -> usize {
TRANSACTION_HEIGHT
}

pub fn get_transaction_str(&self) -> String {
let amount = self.transaction.amount;
let currency = "ETH"; // TODO: different blockchains & tokens
let from = self.transaction.from.unwrap_or_default();
let to = self.transaction.to.unwrap_or_default();

match self.transaction_type {
TransactionDisplayType::Incoming =>
format!("↓ Received {} {} from {}", amount, currency, from),
TransactionDisplayType::Outgoing =>
format!("↑ Sent {} {} to {}", amount, currency, to),
TransactionDisplayType::Swap =>
format!("↕ Swap {} {} from {} to {}", amount, currency, from, to),
}
}

pub fn render(&mut self, frame: &mut Frame, area: Rect) {
let inner = area.inner(Margin { vertical: 1, horizontal: 1 });

let paragraph = Paragraph::new(self.get_transaction_str())
.style(Style::default().fg(Color::Yellow))
.alignment(Alignment::Left);
}
}

0 comments on commit 4dc9f90

Please sign in to comment.