Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions node-gui/backend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,4 @@ ledger = [
"wallet-rpc-client/ledger",
"wallet-cli-commands/ledger",
]
default = ["trezor", "ledger"]
78 changes: 76 additions & 2 deletions node-gui/backend/src/backend_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -354,9 +354,43 @@ impl Backend {

(wallet_data, accounts_info, best_block)
}
#[cfg(feature = "ledger")]
(WalletType::Ledger, ColdHotNodeController::Hot(controller)) => {
let handles_client = WalletHandlesClient::new(
controller.chainstate.clone(),
controller.mempool.clone(),
controller.block_prod.clone(),
controller.p2p.clone(),
)
.await
.map_err(|e| BackendError::WalletError(e.to_string()))?;

let (wallet_rpc, command_handler, best_block, accounts_info, accounts_data) = self
.create_wallet(
handles_client,
file_path.clone(),
wallet_args,
import,
wallet_events,
)
.await?;

let wallet_data = WalletData {
controller: GuiHotColdController::Hot(wallet_rpc, command_handler),
accounts: accounts_data,
best_block,
updated: false,
};

(wallet_data, accounts_info, best_block)
}
#[cfg(feature = "trezor")]
(WalletType::Trezor, ColdHotNodeController::Cold) => {
return Err(BackendError::ColdTrezorNotSupported)
return Err(BackendError::HardwareWalletNotSupportedInColdMode)
}
#[cfg(feature = "ledger")]
(WalletType::Ledger, ColdHotNodeController::Cold) => {
return Err(BackendError::HardwareWalletNotSupportedInColdMode)
}
(WalletType::Hot, ColdHotNodeController::Cold) => {
return Err(BackendError::HotNotSupported)
Expand Down Expand Up @@ -593,9 +627,49 @@ impl Backend {

(wallet_data, accounts_info, best_block, encryption_state)
}
#[cfg(feature = "ledger")]
(WalletType::Ledger, ColdHotNodeController::Hot(controller)) => {
let handles_client = WalletHandlesClient::new(
controller.chainstate.clone(),
controller.mempool.clone(),
controller.block_prod.clone(),
controller.p2p.clone(),
)
.await
.map_err(|e| BackendError::WalletError(e.to_string()))?;

let (
wallet_rpc,
command_handler,
encryption_state,
best_block,
accounts_info,
accounts_data,
) = self
.open_wallet(
handles_client,
file_path.clone(),
wallet_events,
Some(HardwareWalletType::Ledger),
)
.await?;

let wallet_data = WalletData {
controller: GuiHotColdController::Hot(wallet_rpc, command_handler),
accounts: accounts_data,
best_block,
updated: false,
};

(wallet_data, accounts_info, best_block, encryption_state)
}
#[cfg(feature = "trezor")]
(WalletType::Trezor, ColdHotNodeController::Cold) => {
return Err(BackendError::ColdTrezorNotSupported)
return Err(BackendError::HardwareWalletNotSupportedInColdMode)
}
#[cfg(feature = "ledger")]
(WalletType::Ledger, ColdHotNodeController::Cold) => {
return Err(BackendError::HardwareWalletNotSupportedInColdMode)
}
(WalletType::Hot, ColdHotNodeController::Cold) => {
return Err(BackendError::HotNotSupported)
Expand Down
4 changes: 2 additions & 2 deletions node-gui/backend/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ pub enum BackendError {
ColdWallet,
#[error("Cannot interact with a hot wallet when in Cold wallet mode")]
HotNotSupported,
#[error("Cannot use a Trezor wallet in a Cold wallet mode")]
ColdTrezorNotSupported,
#[error("Cannot use a Hardware wallet in a Cold wallet mode")]
HardwareWalletNotSupportedInColdMode,
#[error("Invalid console command: {0}")]
InvalidConsoleCommand(String),
#[error("Empty console command")]
Expand Down
22 changes: 22 additions & 0 deletions node-gui/src/main_window/main_menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,27 @@ fn make_menu_file<'a>(wallet_mode: WalletMode) -> Item<'a, MenuMessage, Theme, i
},
),
];
#[cfg(feature = "ledger")]
{
menu.push(menu_item(
"(Beta) Create new Ledger wallet",
MenuMessage::CreateNewWallet {
wallet_type: WalletType::Ledger,
},
));
menu.push(menu_item(
"(Beta) Recover from Ledger wallet",
MenuMessage::RecoverWallet {
wallet_type: WalletType::Ledger,
},
));
menu.push(menu_item(
"(Beta) Open Ledger wallet",
MenuMessage::OpenWallet {
wallet_type: WalletType::Ledger,
},
));
}
#[cfg(feature = "trezor")]
{
menu.push(menu_item(
Expand All @@ -146,6 +167,7 @@ fn make_menu_file<'a>(wallet_mode: WalletMode) -> Item<'a, MenuMessage, Theme, i
},
));
}

// TODO: enable setting when needed
// menu.push(menu_item("Settings", MenuMessage::NoOp));
menu.push(menu_item("Exit", MenuMessage::Exit));
Expand Down
86 changes: 45 additions & 41 deletions node-gui/src/main_window/main_widget/tabs/wallet/left_panel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,17 +118,48 @@ pub fn view_left_panel(
.on_press(WalletMessage::SelectPanel(panel))
.padding(panel_button_row_padding)
};
let is_cold_wallet = wallet_info.wallet_type == WalletType::Cold;

// `next_height` is used to prevent flickering when a new block is found
let show_scan_progress = match wallet_info.wallet_type {
WalletType::Cold => false,
#[cfg(feature = "trezor")]
WalletType::Trezor => {
wallet_info.best_block.1.next_height() < node_state.chain_info.best_block_height
}
WalletType::Hot => {
wallet_info.best_block.1.next_height() < node_state.chain_info.best_block_height
}
let show_scan_progress = if is_cold_wallet {
false
} else {
wallet_info.best_block.1.next_height() < node_state.chain_info.best_block_height
};

let hardware_wallet_panels = || {
column![
panel_button(
"Transactions",
SelectedPanel::Transactions,
selected_panel,
TRANSACTIONS_TOOLTIP_TEXT
),
panel_button(
"Addresses",
SelectedPanel::Addresses,
selected_panel,
ADDRESSES_TOOLTIP_TEXT
),
panel_button(
"Send",
SelectedPanel::Send,
selected_panel,
SEND_TOOLTIP_TEXT
),
panel_button(
"Delegation",
SelectedPanel::Delegation,
selected_panel,
DELEGATION_TOOLTIP_TEXT
),
panel_button(
"Console",
SelectedPanel::Console,
selected_panel,
CONSOLE_TOOLTIP_TEXT,
)
]
};

let scan_progress_widget = if show_scan_progress {
Expand Down Expand Up @@ -188,38 +219,11 @@ pub fn view_left_panel(
match wallet_info.wallet_type {
#[cfg(feature = "trezor")]
WalletType::Trezor => {
column![
panel_button(
"Transactions",
SelectedPanel::Transactions,
selected_panel,
TRANSACTIONS_TOOLTIP_TEXT
),
panel_button(
"Addresses",
SelectedPanel::Addresses,
selected_panel,
ADDRESSES_TOOLTIP_TEXT
),
panel_button(
"Send",
SelectedPanel::Send,
selected_panel,
SEND_TOOLTIP_TEXT
),
panel_button(
"Delegation",
SelectedPanel::Delegation,
selected_panel,
DELEGATION_TOOLTIP_TEXT
),
panel_button(
"Console",
SelectedPanel::Console,
selected_panel,
CONSOLE_TOOLTIP_TEXT,
)
]
hardware_wallet_panels()
}
#[cfg(feature = "ledger")]
WalletType::Ledger => {
hardware_wallet_panels()
}
WalletType::Cold => {
column![
Expand Down
17 changes: 8 additions & 9 deletions node-gui/src/main_window/main_widget/tabs/wallet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ impl WalletTab {
WalletType::Cold => SelectedPanel::Addresses,
#[cfg(feature = "trezor")]
WalletType::Trezor => SelectedPanel::Transactions,
#[cfg(feature = "ledger")]
WalletType::Ledger => SelectedPanel::Transactions,
};

WalletTab {
Expand Down Expand Up @@ -490,15 +492,12 @@ impl Tab for WalletTab {
.get(&self.selected_account)
.expect("selected account must be known");

let still_syncing = match wallet_info.wallet_type {
WalletType::Cold => false,
#[cfg(feature = "trezor")]
WalletType::Trezor => {
wallet_info.best_block.1.next_height() < node_state.chain_info.best_block_height
}
WalletType::Hot => {
wallet_info.best_block.1.next_height() < node_state.chain_info.best_block_height
}
let is_cold_wallet = wallet_info.wallet_type == WalletType::Cold;

let still_syncing = if is_cold_wallet {
false
} else {
wallet_info.best_block.1.next_height() < node_state.chain_info.best_block_height
}
.then_some(WalletMessage::StillSyncing);

Expand Down
30 changes: 29 additions & 1 deletion node-gui/src/main_window/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ use wallet_cli_commands::ConsoleCommand;
use wallet_controller::types::WalletTypeArgs;
use wallet_types::{seed_phrase::StoreSeedPhrase, wallet_type::WalletType, ImportOrCreate};

#[cfg(feature = "trezor")]
#[cfg(any(feature = "trezor", feature = "ledger"))]
use crate::widgets::create_hw_wallet::hw_wallet_create_dialog;
use crate::{
main_window::{main_menu::MenuMessage, main_widget::MainWidgetMessage},
Expand Down Expand Up @@ -148,6 +148,8 @@ pub enum WalletArgs {
},
#[cfg(feature = "trezor")]
Trezor,
#[cfg(feature = "ledger")]
Ledger,
}

impl From<&WalletArgs> for WalletType {
Expand All @@ -165,6 +167,8 @@ impl From<&WalletArgs> for WalletType {
}
#[cfg(feature = "trezor")]
WalletArgs::Trezor => WalletType::Trezor,
#[cfg(feature = "ledger")]
WalletArgs::Ledger => WalletType::Ledger,
}
}
}
Expand Down Expand Up @@ -291,6 +295,8 @@ impl MainWindow {
},
#[cfg(feature = "trezor")]
WalletType::Trezor => WalletArgs::Trezor,
#[cfg(feature = "ledger")]
WalletType::Ledger => WalletArgs::Ledger,
};
self.active_dialog = ActiveDialog::WalletCreate { wallet_args };
Task::none()
Expand Down Expand Up @@ -733,6 +739,8 @@ impl MainWindow {
}
#[cfg(feature = "trezor")]
WalletArgs::Trezor => WalletTypeArgs::Trezor { device_id: None },
#[cfg(feature = "ledger")]
WalletArgs::Ledger => WalletTypeArgs::Ledger,
};

self.file_dialog_active = true;
Expand Down Expand Up @@ -864,6 +872,16 @@ impl MainWindow {
ImportOrCreate::Create,
)
.into(),
#[cfg(feature = "ledger")]
WalletArgs::Ledger => hw_wallet_create_dialog(
Box::new(move || MainWindowMessage::ImportWalletMnemonic {
args: WalletArgs::Ledger,
import: ImportOrCreate::Create,
}),
Box::new(|| MainWindowMessage::CloseDialog),
ImportOrCreate::Create,
)
.into(),
},
ActiveDialog::WalletRecover { wallet_type } => {
let is_cold = *wallet_type == WalletType::Cold;
Expand All @@ -888,6 +906,16 @@ impl MainWindow {
ImportOrCreate::Import,
)
.into(),
#[cfg(feature = "ledger")]
WalletType::Ledger => hw_wallet_create_dialog(
Box::new(move || MainWindowMessage::ImportWalletMnemonic {
args: WalletArgs::Ledger,
import: ImportOrCreate::Create,
}),
Box::new(|| MainWindowMessage::CloseDialog),
ImportOrCreate::Import,
)
.into(),
}
}

Expand Down
12 changes: 6 additions & 6 deletions wallet/src/key_chain/master_key_chain/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ use crypto::key::hdkd::u31::U31;
use crypto::vrf::ExtendedVRFPrivateKey;
use std::sync::Arc;
use wallet_storage::{
StoreTxRwUnlocked, WalletStorageReadLocked, WalletStorageReadUnlocked,
WalletStorageWriteLocked, WalletStorageWriteUnlocked,
WalletStorageReadLocked, WalletStorageReadUnlocked, WalletStorageWriteLocked,
WalletStorageWriteUnlocked,
};
use wallet_types::seed_phrase::{SerializableSeedPhrase, StoreSeedPhrase};

Expand Down Expand Up @@ -59,9 +59,9 @@ impl MasterKeyChain {
))
}

pub fn new_from_mnemonic<B: storage::Backend>(
pub fn new_from_mnemonic(
chain_config: Arc<ChainConfig>,
db_tx: &mut StoreTxRwUnlocked<B>,
db_tx: &mut impl WalletStorageWriteUnlocked,
mnemonic_str: &str,
passphrase: Option<&str>,
save_seed_phrase: StoreSeedPhrase,
Expand All @@ -80,9 +80,9 @@ impl MasterKeyChain {
)
}

fn new_from_root_key<B: storage::Backend>(
fn new_from_root_key(
chain_config: Arc<ChainConfig>,
db_tx: &mut StoreTxRwUnlocked<B>,
db_tx: &mut impl WalletStorageWriteUnlocked,
root_key: ExtendedPrivateKey,
root_vrf_key: ExtendedVRFPrivateKey,
seed_phrase: Option<SerializableSeedPhrase>,
Expand Down
Loading
Loading