Skip to content

Add ledger support in CLI and GUI wallet #1949

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

Draft
wants to merge 1 commit into
base: feature/ledger_signer_provider
Choose a base branch
from
Draft
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
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -310,4 +310,4 @@ opt-level = 2
[features]
trezor = []
ledger = []
default = ["trezor", "ledger"]
default = ["trezor"]
3 changes: 2 additions & 1 deletion node-gui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,5 @@ winres = "0.1"

[features]
trezor = ["wallet-controller/trezor", "wallet-types/trezor", "wallet-cli-commands/trezor", "node-gui-backend/trezor"]
default = ["trezor"]
ledger = ["wallet-controller/ledger", "wallet-types/ledger", "wallet-cli-commands/ledger", "node-gui-backend/ledger"]
default = ["trezor", "ledger"]
2 changes: 2 additions & 0 deletions node-gui/backend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,5 @@ rstest.workspace = true

[features]
trezor = ["wallet/trezor", "wallet-controller/trezor", "wallet-types/trezor", "wallet-rpc-lib/trezor", "wallet-rpc-client/trezor", "wallet-cli-commands/trezor"]
ledger = ["wallet/ledger", "wallet-controller/ledger", "wallet-types/ledger", "wallet-rpc-lib/ledger", "wallet-rpc-client/ledger", "wallet-cli-commands/ledger"]
default = ["trezor", "ledger"]
74 changes: 74 additions & 0 deletions node-gui/backend/src/backend_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,10 +351,44 @@ 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)
}
#[cfg(feature = "ledger")]
(WalletType::Ledger, ColdHotNodeController::Cold) => {
return Err(BackendError::ColdTrezorNotSupported)
}
(WalletType::Hot, ColdHotNodeController::Cold) => {
return Err(BackendError::HotNotSupported)
}
Expand Down Expand Up @@ -563,10 +597,50 @@ 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)
}
#[cfg(feature = "ledger")]
(WalletType::Ledger, ColdHotNodeController::Cold) => {
return Err(BackendError::ColdTrezorNotSupported)
}
(WalletType::Hot, ColdHotNodeController::Cold) => {
return Err(BackendError::HotNotSupported)
}
Expand Down
39 changes: 34 additions & 5 deletions node-gui/src/main_window/main_menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ fn make_menu_file<'a>(wallet_mode: WalletMode) -> Item<'a, MenuMessage, Theme, i
labeled_button("File", MenuMessage::NoOp),
Menu::new(match wallet_mode {
WalletMode::Hot => {
let menu = vec![
let mut menu = vec![];
menu.extend([
menu_item(
"Create new Software wallet",
MenuMessage::CreateNewWallet {
Expand All @@ -126,10 +127,9 @@ fn make_menu_file<'a>(wallet_mode: WalletMode) -> Item<'a, MenuMessage, Theme, i
// TODO: enable setting when needed
// menu_item("Settings", MenuMessage::NoOp),
menu_item("Exit", MenuMessage::Exit),
];
]);
#[cfg(feature = "trezor")]
{
let mut menu = menu;
menu.insert(
1,
menu_item(
Expand Down Expand Up @@ -157,9 +157,38 @@ fn make_menu_file<'a>(wallet_mode: WalletMode) -> Item<'a, MenuMessage, Theme, i
},
),
);
menu
}
#[cfg(not(feature = "trezor"))]
#[cfg(feature = "ledger")]
{
menu.insert(
1,
menu_item(
"Create new Ledger wallet",
MenuMessage::CreateNewWallet {
wallet_type: WalletType::Ledger,
},
),
);
menu.insert(
4,
menu_item(
"Recover from Ledger wallet",
MenuMessage::RecoverWallet {
wallet_type: WalletType::Ledger,
},
),
);
menu.insert(
7,
menu_item(
"Open Ledger wallet",
MenuMessage::OpenWallet {
wallet_type: WalletType::Ledger,
},
),
);
}

menu
}
WalletMode::Cold => {
Expand Down
39 changes: 39 additions & 0 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 @@ -122,6 +122,10 @@ pub fn view_left_panel(
WalletType::Trezor => {
wallet_info.best_block.1.next_height() < node_state.chain_info.best_block_height
}
#[cfg(feature = "ledger")]
WalletType::Ledger => {
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
}
Expand Down Expand Up @@ -214,6 +218,41 @@ pub fn view_left_panel(
)
]
}
#[cfg(feature = "ledger")]
WalletType::Ledger => {
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,
)
]
}
WalletType::Cold => {
column![
panel_button(
Expand Down
6 changes: 6 additions & 0 deletions node-gui/src/main_window/main_widget/tabs/wallet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,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 @@ -488,6 +490,10 @@ impl Tab for WalletTab {
WalletType::Trezor => {
wallet_info.best_block.1.next_height() < node_state.chain_info.best_block_height
}
#[cfg(feature = "ledger")]
WalletType::Ledger => {
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
}
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};

#[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 @@ -866,6 +874,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 @@ -890,6 +908,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
3 changes: 1 addition & 2 deletions wallet/src/signer/ledger_signer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1152,9 +1152,8 @@ impl LedgerSignerProvider {
pub async fn load_from_database(
chain_config: Arc<ChainConfig>,
db_tx: &(impl WalletStorageReadLocked + Sync),
_device_id: Option<String>,
//_device_id: Option<String>,
) -> WalletResult<Self> {
//let (client, data) = find_trezor_device_from_db(db_tx, device_id)?;
let (mut client, data) = find_ledger_device().await?;

check_public_keys_against_db(db_tx, &mut client, chain_config).await?;
Expand Down
5 changes: 2 additions & 3 deletions wallet/src/signer/software_signer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@ use crypto::key::{
};
use randomness::make_true_rng;
use wallet_storage::{
StoreLocalReadWriteUnlocked, StoreTxRwUnlocked, WalletStorageReadLocked,
WalletStorageReadUnlocked,
StoreLocalReadWriteUnlocked, WalletStorageReadLocked, WalletStorageReadUnlocked,
};
use wallet_types::{
hw_data::HardwareWalletData, partially_signed_transaction::PartiallySignedTransaction,
Expand Down Expand Up @@ -448,7 +447,7 @@ pub struct SoftwareSignerProvider {
impl SoftwareSignerProvider {
pub fn new_from_mnemonic<B: storage::Backend>(
chain_config: Arc<ChainConfig>,
db_tx: &mut StoreTxRwUnlocked<B>,
db_tx: &mut StoreLocalReadWriteUnlocked<B>,
mnemonic_str: &str,
passphrase: Option<&str>,
save_seed_phrase: StoreSeedPhrase,
Expand Down
Loading
Loading