Refactor remote wallet#8423
Conversation
- Introduced a new `errors.rs` file to define `RemoteWalletError` for better error management. - Updated `keypair.rs` files to remove redundant imports and improve clarity. - Enhanced the `README.md` to provide comprehensive documentation on features and supported hardware wallets. - Implemented a transport layer for USB HID communication with hardware wallets. - Added support for Ledger wallets, including error handling and device management. - Created a modular structure for wallet implementations and error types.
- Introduced a new `errors.rs` file to define `RemoteWalletError` for better error management. - Updated `keypair.rs` files to remove redundant imports and improve clarity. - Enhanced the `README.md` to provide comprehensive documentation on features and supported hardware wallets. - Implemented a transport layer for USB HID communication with hardware wallets. - Added support for Ledger wallets, including error handling and device management. - Created a modular structure for wallet implementations and error types.
…actor_remote_wallet # Conflicts: # remote-wallet/src/lib.rs # remote-wallet/src/remote_wallet.rs # remote-wallet/src/wallet/ledger/ledger.rs
joncinque
left a comment
There was a problem hiding this comment.
Apologies for the very late review on this, I was waiting for the Trezor support to land with #8378 before taking a look. You might want to look at those changes, since we did a bit to support more than just Ledger there too.
There's a lot of great stuff here, but I do want to keep things simple as much as possible, by avoiding unnecessary complication. Let me know what you think about my suggestions. Since I know you mostly want to land #7252, let's keep the refactors here as simple as possible to land the Keystone integration quicker.
From a quick look, the actual Keystone wallet implementation looks good over there, but you'll need to publish ur-registry and ur-parse-lib to crates.io if you want us to integrate, since solana-remote-wallet is also published to crates.io.
So to summarize:
- let's keep this refactor simple. The rebase might be gnarly, so it might simpler to start from scratch, apologies for that 🙏
- please publish those crates
- we land some version of #7252
How does all that sound?
| pub trait HardwareWalletError: Error { | ||
| fn code(&self) -> u16; | ||
| fn description(&self) -> String; | ||
| } |
There was a problem hiding this comment.
I don't see the utility of this trait, is it supposed to be used as a trait ever? If not, let's remove it and have the different wallets return RemoteWalletError
| pub trait WalletProbe { | ||
| fn is_supported_device(&self, device_info: &hidapi::DeviceInfo) -> bool; | ||
|
|
||
| fn open(&self, usb: &mut HidApi, devinfo: DeviceInfo) -> Result<Device, RemoteWalletError>; | ||
| } |
There was a problem hiding this comment.
I'm not seeing the usefulness of this trait, since it obfuscates device discovery code. How about removing this and just adding new device discovery in the update_devices directly?
| pub mod errors; | ||
| pub mod ledger; | ||
| pub mod types; |
There was a problem hiding this comment.
This directory setup is a bit overkill, since to use ledger you need to import solana_remote_wallet::wallet::ledger::wallet::LedgerWallet, which is more than a little repetitive 😅
Can we just put wallet implementations at the top level? If you really want, we can have move ledger_error.rs into ledger/error.rs and have the wallet in ledger/mod.rs, but I'd honestly just keep it as it is, or move LedgerError into ledger.rs.
| pub trait Transport: Send { | ||
| fn write(&self, data: &[u8]) -> Result<usize, String>; | ||
| fn read(&self) -> Result<Vec<u8>, String>; | ||
| } |
There was a problem hiding this comment.
This trait also looks unnecessary as just a wrapper over HidDevice, so let's remove it and keep the code as it was
There was a problem hiding this comment.
nit: let's call the file error.rs to be consistent with how the code was before, ie ledger_error.rs
| // Logging messages | ||
| const LOG_DEVICE_SINGULAR: &str = ""; | ||
| const LOG_DEVICE_PLURAL: &str = "s"; |
There was a problem hiding this comment.
nit: Since these are only used in one place, it's more confusing to factor out these strings -- let's just use "" and "s" at the call site
| // Small delay to avoid excessive polling | ||
| std::thread::sleep(Duration::from_millis(100)); |
There was a problem hiding this comment.
If we want to back off, we should let the sleep be configurable so that people's code isn't stopping in confusing ways. For example, remote-wallet is used in async runtimes in the CLI, so doing a thread::sleep could stop the whole async runtime.
Unless there's a particular use-case you're worried about, let's remove this
| /// | ||
| /// Returns the number of devices added (can be negative if devices were removed) | ||
| #[cfg(feature = "hidapi")] | ||
| pub fn update_devices(&self) -> Result<usize, RemoteWalletError> { |
There was a problem hiding this comment.
With the removal of the traits as suggested, I think this function will mostly revert back to its previous implementation. You can feel free to separate into multiple functions if it helps readability
| /// # Type Parameters | ||
| /// * `T` - The device info type (typically `hidapi::DeviceInfo`) | ||
| #[allow(unused_variables)] | ||
| pub trait RemoteWallet<T> { |
There was a problem hiding this comment.
Feel free to move this trait into another file if you prefer, maybe src/trait.rs?
| /// Check if this device has an error | ||
| pub fn has_error(&self) -> bool { | ||
| self.error.is_some() | ||
| } | ||
|
|
||
| /// Get the error message if any | ||
| pub fn error_message(&self) -> Option<String> { | ||
| self.error.as_ref().map(|e| e.to_string()) | ||
| } | ||
|
|
||
| /// Check if this device is ready for use (no error and valid pubkey) | ||
| pub fn is_ready(&self) -> bool { | ||
| self.error.is_none() && self.pubkey != Pubkey::default() | ||
| } |
There was a problem hiding this comment.
Same with these, is there a use planned for these? If not, let's remove
|
hi@joncinque ,Thanks for the careful review! Regarding these methods. Since there have been many updates to the remote-wallet implementation recently, I’ve been re-evaluating the entire logic. I’ll incorporate your feedback and submit a fresh PR with the latest changes soon. Thanks again for pointing that out! |
|
Hi @joncinque, I’ve opened a new PR based on the latest version. Could you please take a look when you have a chance? Thanks! #11944 |
Problem
Summary of Changes
Introduced a new errors.rs file to define RemoteWalletError for better error management.
Updated keypair.rs files to remove redundant imports and improve clarity.
Enhanced the README.md to provide comprehensive documentation on features and supported hardware wallets.
Implemented a transport layer for USB HID communication with hardware wallets.
Created a modular structure for wallet implementations and error types.
Fixes #