public GenerateWalletViewModel(WalletManagerViewModel owner) : base("Generate Wallet") { Owner = owner; GenerateCommand = ReactiveCommand.Create(() => { DoGenerateCommand(); }, this.WhenAnyValue(x => x.TermsAccepted)); this.WhenAnyValue(x => x.Password).Subscribe(x => { if (x.NotNullAndNotEmpty()) { char lastChar = x.Last(); if (lastChar == '\r' || lastChar == '\n') // If the last character is cr or lf then act like it'd be a sign to do the job. { Password = x.TrimEnd('\r', '\n'); } } }); this.WhenAnyValue(x => x.PasswordConfirmation).Subscribe(x => { if (x.NotNullAndNotEmpty()) { char lastChar = x.Last(); if (lastChar == '\r' || lastChar == '\n') // If the last character is cr or lf then act like it'd be a sign to do the job. { PasswordConfirmation = x.TrimEnd('\r', '\n'); DoGenerateCommand(); } } }); }
public GenerateWalletViewModel(WalletManagerViewModel owner) : base("Generate Wallet") { Disposables = new CompositeDisposable(); Owner = owner; GenerateCommand = ReactiveCommand.Create(() => { DoGenerateCommand(); }, this.WhenAnyValue(x => x.TermsAccepted)).DisposeWith(Disposables); this.WhenAnyValue(x => x.Password).Subscribe(x => { try { if (x.NotNullAndNotEmpty()) { char lastChar = x.Last(); if (lastChar == '\r' || lastChar == '\n') // If the last character is cr or lf then act like it'd be a sign to do the job. { Password = x.TrimEnd('\r', '\n'); if (TermsAccepted) { DoGenerateCommand(); } } } } catch (Exception ex) { Logger.LogTrace(ex); } }).DisposeWith(Disposables); }
public GenerateWalletSuccessViewModel(WalletManagerViewModel owner, Mnemonic mnemonic) : base("Wallet Generated Successfully!") { _mnemonicWords = mnemonic.ToString(); ConfirmCommand = ReactiveCommand.Create(() => { owner.SelectTestPassword(); }); }
public RecoverWalletViewModel(WalletManagerViewModel owner) : base("Recover Wallet") { RecoverCommand = ReactiveCommand.Create(() => { WalletName = Guard.Correct(WalletName); MnemonicWords = Guard.Correct(MnemonicWords); Password = Guard.Correct(Password); // Don't let whitespaces to the beginning and to the end. string walletFilePath = Path.Combine(Global.WalletsDir, $"{WalletName}.json"); if (TermsAccepted == false) { ValidationMessage = "Terms are not accepted."; } else if (string.IsNullOrWhiteSpace(WalletName)) { ValidationMessage = $"The name {WalletName} is not valid."; } else if (File.Exists(walletFilePath)) { ValidationMessage = $"The name {WalletName} is already taken."; } else if (string.IsNullOrWhiteSpace(MnemonicWords)) { ValidationMessage = $"Mnemonic words were not supplied."; } else { try { var mnemonic = new Mnemonic(MnemonicWords); KeyManager.Recover(mnemonic, Password, walletFilePath); owner.SelectLoadWallet(); } catch (Exception ex) { ValidationMessage = ex.ToTypeMessageString(); Logger.LogError <LoadWalletViewModel>(ex); } } }, this.WhenAnyValue(x => x.TermsAccepted)); this.WhenAnyValue(x => x.MnemonicWords).Subscribe(x => UpdateSuggestions(x)); this.WhenAnyValue(x => x.Password).Subscribe(x => { if (x.NotNullAndNotEmpty()) { char lastChar = x.Last(); if (lastChar == '\r' || lastChar == '\n') // If the last character is cr or lf then act like it'd be a sign to do the job. { Password = x.TrimEnd('\r', '\n'); } } }); }
public GenerateWalletSuccessViewModel(WalletManagerViewModel owner, Mnemonic mnemonic) : base("Wallet Generated Successfully!") { _mnemonicWords = mnemonic.ToString(); ConfirmCommand = ReactiveCommand.Create(() => owner.SelectTestPassword()); ConfirmCommand.ThrownExceptions .ObserveOn(RxApp.TaskpoolScheduler) .Subscribe(ex => Logger.LogError(ex)); }
public GenerateWalletViewModel(WalletManagerViewModel owner) : base("Generate Wallet") { Owner = owner; IObservable<bool> canGenerate = Observable.CombineLatest( this.WhenAnyValue(x => x.TermsAccepted), this.WhenAnyValue(x => x.Password).Select(pw => !ValidatePassword().HasErrors), (terms, pw) => terms && pw); GenerateCommand = ReactiveCommand.Create(DoGenerateCommand, canGenerate); }
public GenerateWalletSuccessViewModel(WalletManagerViewModel owner, Mnemonic mnemonic) : base("Wallet Generated Successfully!") { Disposables = new CompositeDisposable(); _mnemonicWords = mnemonic.ToString(); ConfirmCommand = ReactiveCommand.Create(() => { owner.SelectTestPassword(); }).DisposeWith(Disposables); }
public LoadWalletViewModel(WalletManagerViewModel owner, LoadWalletType loadWalletType) : base(loadWalletType == LoadWalletType.Password ? "Test Password" : (loadWalletType == LoadWalletType.Desktop ? "Load Wallet" : "Hardware Wallet")) { Owner = owner; Password = ""; LoadWalletType = loadWalletType; Wallets = new ObservableCollection <LoadWalletEntry>(); WalletLock = new object(); this.WhenAnyValue(x => x.SelectedWallet) .Subscribe(selectedWallet => TrySetWalletStates()); this.WhenAnyValue(x => x.IsWalletOpened) .Subscribe(isWalletOpened => TrySetWalletStates()); this.WhenAnyValue(x => x.IsBusy) .Subscribe(x => TrySetWalletStates()); this.WhenAnyValue(x => x.Password).Subscribe(async x => { try { if (x.NotNullAndNotEmpty()) { char lastChar = x.Last(); if (lastChar == '\r' || lastChar == '\n') // If the last character is cr or lf then act like it'd be a sign to do the job. { Password = x.TrimEnd('\r', '\n'); await LoadKeyManagerAsync(requirePassword: true, isHardwareWallet: false); } } } catch (Exception ex) { Logger.LogTrace(ex); } }); LoadCommand = ReactiveCommand.CreateFromTask(async() => await LoadWalletAsync(), this.WhenAnyValue(x => x.CanLoadWallet)); TestPasswordCommand = ReactiveCommand.CreateFromTask(async() => await LoadKeyManagerAsync(requirePassword: true, isHardwareWallet: false), this.WhenAnyValue(x => x.CanTestPassword)); OpenFolderCommand = ReactiveCommand.Create(OpenWalletsFolder); LoadCommand.ThrownExceptions.Subscribe(ex => Logger.LogWarning <LoadWalletViewModel>(ex)); TestPasswordCommand.ThrownExceptions.Subscribe(ex => Logger.LogWarning <LoadWalletViewModel>(ex)); OpenFolderCommand.ThrownExceptions.Subscribe(ex => Logger.LogWarning <LoadWalletViewModel>(ex)); SetLoadButtonText(); IsHwWalletSearchTextVisible = LoadWalletType == LoadWalletType.Hardware; }
public GenerateWalletViewModel(WalletManagerViewModel owner) : base("Generate Wallet") { Owner = owner; IObservable <bool> canGenerate = Observable.CombineLatest( this.WhenAnyValue(x => x.TermsAccepted), this.WhenAnyValue(x => x.Password).Select(pw => !ValidatePassword().HasErrors), (terms, pw) => terms && pw); NextCommand = ReactiveCommand.Create(DoNextCommand, canGenerate); NextCommand.ThrownExceptions .ObserveOn(RxApp.TaskpoolScheduler) .Subscribe(ex => Logger.LogError(ex)); }
public RecoverWalletViewModel(WalletManagerViewModel owner) : base("Recover Wallet") { RecoverCommand = ReactiveCommand.Create(() => { WalletName = Guard.Correct(WalletName); MnemonicWords = Guard.Correct(MnemonicWords); string walletFilePath = Path.Combine(Global.WalletsDir, $"{WalletName}.json"); if (TermsAccepted == false) { ValidationMessage = "Terms are not accepted."; } else if (string.IsNullOrWhiteSpace(WalletName)) { ValidationMessage = $"The name {WalletName} is not valid."; } else if (File.Exists(walletFilePath)) { ValidationMessage = $"The name {WalletName} is already taken."; } else if (string.IsNullOrWhiteSpace(MnemonicWords)) { ValidationMessage = $"Mnemonic words were not supplied."; } else { try { var mnemonic = new Mnemonic(MnemonicWords); KeyManager.Recover(mnemonic, Password, walletFilePath); owner.SelectLoadWallet(); } catch (Exception ex) { ValidationMessage = ex.ToTypeMessageString(); Logger.LogError <LoadWalletViewModel>(ex); } } }, this.WhenAnyValue(x => x.TermsAccepted)); this.WhenAnyValue(x => x.MnemonicWords).Subscribe(x => UpdateSuggestions(x)); }
public LoadWalletViewModel(WalletManagerViewModel owner) : base("Load Wallet") { Owner = owner; _wallets = new ObservableCollection <string>(); this.WhenAnyValue(x => x.SelectedWallet) .Subscribe(selectedWallet => CanLoadWallet = !string.IsNullOrEmpty(selectedWallet) && !IsWalletOpened); this.WhenAnyValue(x => x.IsWalletOpened) .Subscribe(isWalletOpened => CanLoadWallet = !string.IsNullOrEmpty(SelectedWallet) && !isWalletOpened); this.WhenAnyValue(x => x.IsWalletOpened) .Subscribe(isWalletOpened => WarningMessage = isWalletOpened ? "There is already an open wallet. Restart the application to open another one." : string.Empty); LoadCommand = ReactiveCommand.Create(LoadWalletAsync, this.WhenAnyValue(x => x.CanLoadWallet)); OpenFolderCommand = ReactiveCommand.Create(OpenWalletsFolder); SetLoadButtonText(IsBusy); }
public GenerateWalletViewModel(WalletManagerViewModel owner) : base("Generate Wallet") { GenerateCommand = ReactiveCommand.Create(() => { WalletName = Guard.Correct(WalletName); string walletFilePath = Path.Combine(Global.WalletsDir, $"{WalletName}.json"); if (TermsAccepted == false) { ValidationMessage = "Terms are not accepted."; } else if (string.IsNullOrWhiteSpace(WalletName)) { ValidationMessage = $"The name {WalletName} is not valid."; } else if (File.Exists(walletFilePath)) { ValidationMessage = $"The name {WalletName} is already taken."; } else if (Password != PasswordConfirmation) { ValidationMessage = $"The passwords do not match."; } else { try { KeyManager.CreateNew(out Mnemonic mnemonic, Password, walletFilePath); owner.CurrentView = new GenerateWalletSuccessViewModel(owner, mnemonic); } catch (Exception ex) { ValidationMessage = ex.ToTypeMessageString(); Logger.LogError <GenerateWalletViewModel>(ex); } } }, this.WhenAnyValue(x => x.TermsAccepted)); }
public LoadWalletViewModel(WalletManagerViewModel owner, bool requirePassword) : base(requirePassword ? "Test Password" : "Load Wallet") { Disposables = new CompositeDisposable(); Owner = owner; Password = ""; RequirePassword = requirePassword; Wallets = new ObservableCollection <string>(); this.WhenAnyValue(x => x.SelectedWallet) .Subscribe(selectedWallet => SetWalletStates()).DisposeWith(Disposables); this.WhenAnyValue(x => x.IsWalletOpened) .Subscribe(isWalletOpened => SetWalletStates()).DisposeWith(Disposables); this.WhenAnyValue(x => x.Password).Subscribe(x => { try { if (x.NotNullAndNotEmpty()) { char lastChar = x.Last(); if (lastChar == '\r' || lastChar == '\n') // If the last character is cr or lf then act like it'd be a sign to do the job. { Password = x.TrimEnd('\r', '\n'); LoadKeyManager(requirePassword: true); } } } catch (Exception ex) { Logger.LogTrace(ex); } }).DisposeWith(Disposables); LoadCommand = ReactiveCommand.Create(LoadWalletAsync, this.WhenAnyValue(x => x.CanLoadWallet)).DisposeWith(Disposables); TestPasswordCommand = ReactiveCommand.Create(() => LoadKeyManager(requirePassword: true), this.WhenAnyValue(x => x.CanTestPassword)).DisposeWith(Disposables); OpenFolderCommand = ReactiveCommand.Create(OpenWalletsFolder).DisposeWith(Disposables); SetLoadButtonText(IsBusy); }
public RecoverWalletViewModel(WalletManagerViewModel owner) : base("Recover Wallet") { MnemonicWords = ""; RecoverCommand = ReactiveCommand.Create(() => { WalletName = Guard.Correct(WalletName); MnemonicWords = Guard.Correct(MnemonicWords); Password = Guard.Correct(Password); // Don't let whitespaces to the beginning and to the end. string walletFilePath = Path.Combine(Global.WalletsDir, $"{WalletName}.json"); if (string.IsNullOrWhiteSpace(WalletName)) { ValidationMessage = $"The name {WalletName} is not valid."; } else if (File.Exists(walletFilePath)) { ValidationMessage = $"The name {WalletName} is already taken."; } else if (string.IsNullOrWhiteSpace(MnemonicWords)) { ValidationMessage = "Recovery Words were not supplied."; } else if (string.IsNullOrWhiteSpace(AccountKeyPath)) { ValidationMessage = "The account key path is not valid."; } else if (MinGapLimit < KeyManager.AbsoluteMinGapLimit) { ValidationMessage = $"Min Gap Limit cannot be smaller than {KeyManager.AbsoluteMinGapLimit}."; } else if (MinGapLimit > 1_000_000) { ValidationMessage = $"Min Gap Limit cannot be larger than {1_000_000}."; } else if (!KeyPath.TryParse(AccountKeyPath, out KeyPath keyPath)) { ValidationMessage = "The account key path is not a valid derivation path."; } else { try { var mnemonic = new Mnemonic(MnemonicWords); KeyManager.Recover(mnemonic, Password, walletFilePath, keyPath, MinGapLimit); owner.SelectLoadWallet(); } catch (Exception ex) { ValidationMessage = ex.ToTypeMessageString(); Logger.LogError <LoadWalletViewModel>(ex); } } }); this.WhenAnyValue(x => x.MnemonicWords).Subscribe(x => UpdateSuggestions(x)); this.WhenAnyValue(x => x.Password).Subscribe(x => { try { if (x.NotNullAndNotEmpty()) { char lastChar = x.Last(); if (lastChar == '\r' || lastChar == '\n') // If the last character is cr or lf then act like it'd be a sign to do the job. { Password = x.TrimEnd('\r', '\n'); } } } catch (Exception ex) { Logger.LogTrace(ex); } }); this.WhenAnyValue(x => x.CaretIndex).Subscribe(_ => { if (CaretIndex != MnemonicWords.Length) { CaretIndex = MnemonicWords.Length; } }); _suggestions = new ObservableCollection <SuggestionViewModel>(); }
public LoadWalletViewModel(WalletManagerViewModel owner, LoadWalletType loadWalletType) : base(loadWalletType == LoadWalletType.Password ? "Test Password" : (loadWalletType == LoadWalletType.Desktop ? "Load Wallet" : "Hardware Wallet")) { Owner = owner; Password = ""; LoadWalletType = loadWalletType; Wallets = new ObservableCollection <LoadWalletEntry>(); WalletLock = new object(); this.WhenAnyValue(x => x.SelectedWallet) .Subscribe(selectedWallet => TrySetWalletStates()); this.WhenAnyValue(x => x.IsWalletOpened) .Subscribe(isWalletOpened => TrySetWalletStates()); this.WhenAnyValue(x => x.IsBusy) .Subscribe(x => TrySetWalletStates()); this.WhenAnyValue(x => x.Password).Subscribe(async x => { try { if (x.NotNullAndNotEmpty()) { char lastChar = x.Last(); if (lastChar == '\r' || lastChar == '\n') // If the last character is cr or lf then act like it'd be a sign to do the job. { Password = x.TrimEnd('\r', '\n'); await LoadKeyManagerAsync(requirePassword: true, isHardwareWallet: false); } } } catch (Exception ex) { Logger.LogTrace(ex); } }); LoadCommand = ReactiveCommand.CreateFromTask(async() => await LoadWalletAsync(), this.WhenAnyValue(x => x.CanLoadWallet)); TestPasswordCommand = ReactiveCommand.CreateFromTask(async() => await LoadKeyManagerAsync(requirePassword: true, isHardwareWallet: false), this.WhenAnyValue(x => x.CanTestPassword)); OpenFolderCommand = ReactiveCommand.Create(OpenWalletsFolder); ImportColdcardCommand = ReactiveCommand.CreateFromTask(async() => { try { var ofd = new OpenFileDialog { AllowMultiple = false, Title = "Import Coldcard" }; if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { ofd.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal); } var selected = await ofd.ShowAsync(Application.Current.MainWindow, fallBack: true); if (selected != null && selected.Any()) { var path = selected.First(); var jsonString = await File.ReadAllTextAsync(path); var json = JObject.Parse(jsonString); var xpubString = json["ExtPubKey"].ToString(); var mfpString = json["MasterFingerprint"].ToString(); // https://github.com/zkSNACKs/WalletWasabi/pull/1663#issuecomment-508073066 // Coldcard 2.1.0 improperly implemented Wasabi skeleton fingerpring at first, so we must reverse byte order. // The solution was to add a ColdCardFirmwareVersion json field from 2.1.1 and correct the one generated by 2.1.0. var coldCardVersionString = json["ColdCardFirmwareVersion"]?.ToString(); var reverseByteOrder = false; if (coldCardVersionString is null) { reverseByteOrder = true; } else { Version coldCardVersion = new Version(coldCardVersionString); if (coldCardVersion == new Version("2.1.0")) // Should never happen though. { reverseByteOrder = true; } } HDFingerprint mfp = NBitcoinHelpers.BetterParseHDFingerprint(mfpString, reverseByteOrder: reverseByteOrder); ExtPubKey extPubKey = NBitcoinHelpers.BetterParseExtPubKey(xpubString); Logger.LogInfo <LoadWalletViewModel>("Creating new wallet file."); var walletName = Global.GetNextHardwareWalletName(customPrefix: "Coldcard"); var walletFullPath = Global.GetWalletFullPath(walletName); KeyManager.CreateNewHardwareWalletWatchOnly(mfp, extPubKey, walletFullPath); owner.SelectLoadWallet(); } } catch (Exception ex) { SetWarningMessage(ex.ToTypeMessageString()); Logger.LogError <LoadWalletViewModel>(ex); } }, outputScheduler: RxApp.MainThreadScheduler); OpenBrowserCommand = ReactiveCommand.Create <string>(x => { IoHelpers.OpenBrowser(x); }); OpenBrowserCommand.ThrownExceptions.Subscribe(Logger.LogWarning <LoadWalletViewModel>); LoadCommand.ThrownExceptions.Subscribe(Logger.LogWarning <LoadWalletViewModel>); TestPasswordCommand.ThrownExceptions.Subscribe(Logger.LogWarning <LoadWalletViewModel>); OpenFolderCommand.ThrownExceptions.Subscribe(Logger.LogWarning <LoadWalletViewModel>); ImportColdcardCommand.ThrownExceptions.Subscribe(Logger.LogWarning <LoadWalletViewModel>); SetLoadButtonText(); IsHwWalletSearchTextVisible = LoadWalletType == LoadWalletType.Hardware; }
public LoadWalletViewModel(WalletManagerViewModel owner, LoadWalletType loadWalletType) : base(loadWalletType == LoadWalletType.Password ? "Test Password" : (loadWalletType == LoadWalletType.Desktop ? "Load Wallet" : "Hardware Wallet")) { Owner = owner; Password = ""; LoadWalletType = loadWalletType; Wallets = new ObservableCollection <LoadWalletEntry>(); IsHwWalletSearchTextVisible = false; this.WhenAnyValue(x => x.SelectedWallet) .Subscribe(_ => TrySetWalletStates()); this.WhenAnyValue(x => x.IsWalletOpened) .Subscribe(_ => TrySetWalletStates()); this.WhenAnyValue(x => x.IsBusy) .Subscribe(_ => TrySetWalletStates()); LoadCommand = ReactiveCommand.CreateFromTask(async() => await LoadWalletAsync(), this.WhenAnyValue(x => x.CanLoadWallet)); TestPasswordCommand = ReactiveCommand.CreateFromTask(async() => await LoadKeyManagerAsync(requirePassword: true, isHardwareWallet: false), this.WhenAnyValue(x => x.CanTestPassword)); OpenFolderCommand = ReactiveCommand.Create(OpenWalletsFolder); ImportColdcardCommand = ReactiveCommand.CreateFromTask(async() => { var ofd = new OpenFileDialog { AllowMultiple = false, Title = "Import Coldcard" }; if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { ofd.Directory = Path.Combine("/media", Environment.UserName); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { ofd.Directory = Environment.GetFolderPath(Environment.SpecialFolder.Personal); } var window = (Application.Current.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime).MainWindow; var selected = await ofd.ShowAsync(window, fallBack: true); if (selected != null && selected.Any()) { var path = selected.First(); var jsonString = await File.ReadAllTextAsync(path); var json = JObject.Parse(jsonString); var xpubString = json["ExtPubKey"].ToString(); var mfpString = json["MasterFingerprint"].ToString(); // https://github.com/zkSNACKs/WalletWasabi/pull/1663#issuecomment-508073066 // Coldcard 2.1.0 improperly implemented Wasabi skeleton fingerprint at first, so we must reverse byte order. // The solution was to add a ColdCardFirmwareVersion json field from 2.1.1 and correct the one generated by 2.1.0. var coldCardVersionString = json["ColdCardFirmwareVersion"]?.ToString(); var reverseByteOrder = false; if (coldCardVersionString is null) { reverseByteOrder = true; } else { Version coldCardVersion = new Version(coldCardVersionString); if (coldCardVersion == new Version("2.1.0")) // Should never happen though. { reverseByteOrder = true; } } HDFingerprint mfp = NBitcoinHelpers.BetterParseHDFingerprint(mfpString, reverseByteOrder: reverseByteOrder); ExtPubKey extPubKey = NBitcoinHelpers.BetterParseExtPubKey(xpubString); Logger.LogInfo("Creating a new wallet file."); var walletName = Global.GetNextHardwareWalletName(customPrefix: "Coldcard"); var walletFullPath = Global.GetWalletFullPath(walletName); KeyManager.CreateNewHardwareWalletWatchOnly(mfp, extPubKey, walletFullPath); owner.SelectLoadWallet(); } }); EnumerateHardwareWalletsCommand = ReactiveCommand.CreateFromTask(async() => await EnumerateHardwareWalletsAsync()); OpenBrowserCommand = ReactiveCommand.Create <string>(x => IoHelpers.OpenBrowser(x)); Observable.Merge(OpenBrowserCommand.ThrownExceptions) .Merge(LoadCommand.ThrownExceptions) .Merge(TestPasswordCommand.ThrownExceptions) .Merge(OpenFolderCommand.ThrownExceptions) .Merge(ImportColdcardCommand.ThrownExceptions) .Merge(EnumerateHardwareWalletsCommand.ThrownExceptions) .Subscribe(ex => { NotificationHelpers.Error(ex.ToTypeMessageString()); Logger.LogError(ex); }); SetLoadButtonText(); }
public RecoverWalletViewModel(WalletManagerViewModel owner) : base("Recover Wallet") { Global = owner.Global; MnemonicWords = ""; RecoverCommand = ReactiveCommand.Create(() => { WalletName = Guard.Correct(WalletName); MnemonicWords = Guard.Correct(MnemonicWords); Password = Guard.Correct(Password); // Do not let whitespaces to the beginning and to the end. string walletFilePath = Path.Combine(Global.WalletsDir, $"{WalletName}.json"); if (string.IsNullOrWhiteSpace(WalletName)) { ValidationMessage = $"The name {WalletName} is not valid."; } else if (File.Exists(walletFilePath)) { ValidationMessage = $"The name {WalletName} is already taken."; } else if (string.IsNullOrWhiteSpace(MnemonicWords)) { ValidationMessage = "Recovery Words were not supplied."; } else if (string.IsNullOrWhiteSpace(AccountKeyPath)) { ValidationMessage = "The account key path is not valid."; } else if (MinGapLimit < KeyManager.AbsoluteMinGapLimit) { ValidationMessage = $"Min Gap Limit cannot be smaller than {KeyManager.AbsoluteMinGapLimit}."; } else if (MinGapLimit > 1_000_000) { ValidationMessage = $"Min Gap Limit cannot be larger than {1_000_000}."; } else if (!KeyPath.TryParse(AccountKeyPath, out KeyPath keyPath)) { ValidationMessage = "The account key path is not a valid derivation path."; } else { try { var mnemonic = new Mnemonic(MnemonicWords); KeyManager.Recover(mnemonic, Password, walletFilePath, keyPath, MinGapLimit); owner.SelectLoadWallet(); } catch (Exception ex) { ValidationMessage = ex.ToTypeMessageString(); Logger.LogError(ex); } } }); this.WhenAnyValue(x => x.MnemonicWords).Subscribe(UpdateSuggestions); _suggestions = new ObservableCollection <SuggestionViewModel>(); }
public GenerateWalletViewModel(WalletManagerViewModel owner) : base("Generate Wallet") { Owner = owner; GenerateCommand = ReactiveCommand.Create(DoGenerateCommand, this.WhenAnyValue(x => x.TermsAccepted)); }
public RecoverWalletViewModel(WalletManagerViewModel owner) : base("Recover Wallet") { Global = Locator.Current.GetService <Global>(); MnemonicWords = ""; RecoverCommand = ReactiveCommand.Create(() => { WalletName = Guard.Correct(WalletName); MnemonicWords = Guard.Correct(MnemonicWords); Password = Guard.Correct(Password); // Do not let whitespaces to the beginning and to the end. string walletFilePath = Path.Combine(Global.WalletsDir, $"{WalletName}.json"); if (string.IsNullOrWhiteSpace(WalletName)) { NotificationHelpers.Error("Invalid wallet name."); } else if (File.Exists(walletFilePath)) { NotificationHelpers.Error("Wallet name is already taken."); } else if (string.IsNullOrWhiteSpace(MnemonicWords)) { NotificationHelpers.Error("Recovery Words were not supplied."); } else if (string.IsNullOrWhiteSpace(AccountKeyPath)) { NotificationHelpers.Error("The account key path is not valid."); } else if (MinGapLimit < KeyManager.AbsoluteMinGapLimit) { NotificationHelpers.Error($"Min Gap Limit cannot be smaller than {KeyManager.AbsoluteMinGapLimit}."); } else if (MinGapLimit > 1_000_000) { NotificationHelpers.Error($"Min Gap Limit cannot be larger than {1_000_000}."); } else if (!KeyPath.TryParse(AccountKeyPath, out KeyPath keyPath)) { NotificationHelpers.Error("The account key path is not a valid derivation path."); } else { try { var mnemonic = new Mnemonic(MnemonicWords); var km = KeyManager.Recover(mnemonic, Password, filePath: null, keyPath, MinGapLimit); km.SetNetwork(Global.Network); km.SetFilePath(walletFilePath); km.ToFile(); NotificationHelpers.Success("Wallet is successfully recovered!"); owner.SelectLoadWallet(); } catch (Exception ex) { NotificationHelpers.Error(ex.ToTypeMessageString()); Logger.LogError(ex); } } }); this.WhenAnyValue(x => x.MnemonicWords).Subscribe(UpdateSuggestions); _suggestions = new ObservableCollection <SuggestionViewModel>(); RecoverCommand.ThrownExceptions .ObserveOn(RxApp.TaskpoolScheduler) .Subscribe(ex => Logger.LogError(ex)); }