Example #1
0
        public NavBarViewModel(TargettedNavigationStack mainScreen, WalletManagerViewModel walletManager)
        {
            _walletManager = walletManager;
            _topItems      = new ObservableCollection <NavBarItemViewModel>();
            _bottomItems   = new ObservableCollection <NavBarItemViewModel>();

            mainScreen.WhenAnyValue(x => x.CurrentPage)
            .OfType <NavBarItemViewModel>()
            .Subscribe(x => CurrentPageChanged(x, walletManager));

            this.WhenAnyValue(x => x.SelectedItem)
            .OfType <NavBarItemViewModel>()
            .Subscribe(NavigateItem);

            this.WhenAnyValue(x => x.Items.Count)
            .Subscribe(x =>
            {
                if (x > 0 && SelectedItem is null)
                {
                    SelectedItem = Items.FirstOrDefault();
                }
            });

            this.WhenAnyValue(x => x.IsOpen)
            .Subscribe(x =>
            {
                if (SelectedItem is { })
                {
                    SelectedItem.IsExpanded = x;
                }
            });
Example #2
0
        public ConnectHardwareWalletViewModel(string walletName, WalletManagerViewModel walletManagerViewModel)
        {
            _message       = "";
            WalletName     = walletName;
            WalletManager  = walletManagerViewModel.Model;
            Wallets        = walletManagerViewModel.Wallets;
            AbandonedTasks = new AbandonedTasks();
            CancelCts      = new CancellationTokenSource();

            NextCommand = ReactiveCommand.Create(() =>
            {
                if (DetectedDevice is { } device)
                {
                    NavigateToNext(device);
                    return;
                }

                StartDetection();
            });

            OpenBrowserCommand = ReactiveCommand.CreateFromTask(async() =>
                                                                await IoHelpers.OpenBrowserAsync("https://docs.wasabiwallet.io/using-wasabi/ColdWasabi.html#using-hardware-wallet-step-by-step"));

            NavigateToExistingWalletLoginCommand = ReactiveCommand.Create(() =>
            {
                var navBar = NavigationManager.Get <NavBarViewModel>();

                if (ExistingWallet is { } && navBar is { })
        public ConnectHardwareWalletViewModel(WalletManagerViewModel owner) : base("Hardware Wallet")
        {
            Global        = Locator.Current.GetService <Global>();
            WalletManager = Global.WalletManager;
            Owner         = owner;
            Wallets       = new ObservableCollection <HardwareWalletViewModel>();
            IsHwWalletSearchTextVisible = false;

            this.WhenAnyValue(x => x.SelectedWallet)
            .Where(x => x is null)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(_ =>
            {
                SelectedWallet = Wallets.FirstOrDefault();
                SetLoadButtonText();
            });

            Wallets
            .ToObservableChangeSet()
            .ToCollection()
            .Where(items => items.Any() && SelectedWallet is null)
            .Select(items => items.First())
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(x => SelectedWallet = x);

            this.WhenAnyValue(x => x.IsBusy, x => x.IsHardwareBusy)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(_ => SetLoadButtonText());

            LoadCommand           = ReactiveCommand.CreateFromTask(LoadWalletAsync, this.WhenAnyValue(x => x.SelectedWallet, x => x.IsBusy).Select(x => x.Item1 is { } && !x.Item2));
Example #4
0
        public RecoverWalletViewModel(WalletManagerViewModel owner) : base("Recover Wallet")
        {
            Global        = Locator.Current.GetService <Global>();
            WalletManager = Global.WalletManager;

            this.ValidateProperty(x => x.Password, ValidatePassword);
            this.ValidateProperty(x => x.MinGapLimit, ValidateMinGapLimit);
            this.ValidateProperty(x => x.AccountKeyPath, ValidateAccountKeyPath);

            MnemonicWords = "";

            var canExecute = Observable
                             .Merge(Observable.FromEventPattern(this, nameof(ErrorsChanged)).Select(_ => Unit.Default))
                             .Merge(this.WhenAnyValue(x => x.MnemonicWords).Select(_ => Unit.Default))
                             .ObserveOn(RxApp.MainThreadScheduler)
                             .Select(_ => !Validations.AnyErrors && MnemonicWords.Split(' ', StringSplitOptions.RemoveEmptyEntries).Length == 12);

            RecoverCommand = ReactiveCommand.Create(() => RecoverWallet(owner), canExecute);

            this.WhenAnyValue(x => x.MnemonicWords).Subscribe(UpdateSuggestions);

            _suggestions = new ObservableCollection <SuggestionViewModel>();

            RecoverCommand.ThrownExceptions
            .ObserveOn(RxApp.TaskpoolScheduler)
            .Subscribe(ex => Logger.LogError(ex));
        }
        protected ClosedWalletViewModel(WalletManagerViewModel walletManagerViewModel, Wallet wallet)
            : base(wallet)
        {
            _smartHeaderChain = Services.BitcoinStore.SmartHeaderChain;

            OpenCommand = ReactiveCommand.Create(() => OnOpen(walletManagerViewModel));
        }
        public RecoverWalletViewModel(WalletManagerViewModel owner) : base("Recover Wallet")
        {
            Global        = Locator.Current.GetService <Global>();
            WalletManager = Global.WalletManager;

            this.ValidateProperty(x => x.Password, ValidatePassword);
            this.ValidateProperty(x => x.MinGapLimit, ValidateMinGapLimit);
            this.ValidateProperty(x => x.AccountKeyPath, ValidateAccountKeyPath);

            MnemonicWords = "";

            RecoverCommand = ReactiveCommand.Create(() =>
            {
                RecoverWallet(owner);
            },
                                                    Observable.FromEventPattern(this, nameof(ErrorsChanged))
                                                    .ObserveOn(RxApp.MainThreadScheduler)
                                                    .Select(_ => !Validations.AnyErrors)
                                                    );

            this.WhenAnyValue(x => x.MnemonicWords).Subscribe(UpdateSuggestions);

            _suggestions = new ObservableCollection <SuggestionViewModel>();

            RecoverCommand.ThrownExceptions
            .ObserveOn(RxApp.TaskpoolScheduler)
            .Subscribe(ex => Logger.LogError(ex));
        }
 public static WalletViewModelBase Create(WalletManagerViewModel walletManager, Wallet wallet)
 {
     return(wallet.KeyManager.IsHardwareWallet
                         ? new ClosedHardwareWalletViewModel(walletManager, wallet)
                         : wallet.KeyManager.IsWatchOnly
                                 ? new ClosedWatchOnlyWalletViewModel(walletManager, wallet)
                                 : new ClosedWalletViewModel(walletManager, wallet));
 }
        public NavBarViewModel(NavigationStateViewModel navigationState, RoutingState router, WalletManagerViewModel walletManager, AddWalletPageViewModel addWalletPage)
        {
            Router         = router;
            _walletManager = walletManager;
            _topItems      = new ObservableCollection <NavBarItemViewModel>();
            _bottomItems   = new ObservableCollection <NavBarItemViewModel>();

            var homePage     = new HomePageViewModel(navigationState, walletManager, addWalletPage);
            var settingsPage = new SettingsPageViewModel(navigationState);
            var searchPage   = new SearchPageViewModel(navigationState, walletManager, addWalletPage, settingsPage, homePage);

            _selectedItem = homePage;

            _topItems.Add(SelectedItem);
            _bottomItems.Add(searchPage);
            _bottomItems.Add(settingsPage);
            _bottomItems.Add(addWalletPage);

            Router.CurrentViewModel
            .OfType <NavBarItemViewModel>()
            .Subscribe(
                x =>
            {
                if (walletManager.Items.Contains(x) || _topItems.Contains(x) || _bottomItems.Contains(x))
                {
                    if (!_isNavigating)
                    {
                        _isNavigating = true;
                        SelectedItem  = x;
                        _isNavigating = false;
                    }
                }
            });

            this.WhenAnyValue(x => x.SelectedItem)
            .OfType <NavBarItemViewModel>()
            .Subscribe(
                x =>
            {
                if (!_isNavigating)
                {
                    _isNavigating = true;
                    x.NavigateToSelfAndReset(x.CurrentTarget);
                    CollapseOnClickAction?.Invoke();

                    _isNavigating = false;
                }
            });

            Observable.FromEventPattern(Router.NavigationStack, nameof(Router.NavigationStack.CollectionChanged))
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(_ => IsBackButtonVisible = Router.NavigationStack.Count > 1);

            this.WhenAnyValue(x => x.IsOpen)
            .Subscribe(x => SelectedItem.IsExpanded = x);
        }
Example #9
0
        public RecoverWalletViewModel(
            string walletName,
            WalletManagerViewModel walletManagerViewModel)
        {
            Suggestions = new Mnemonic(Wordlist.English, WordCount.Twelve).WordList.GetWords();
            var walletManager = walletManagerViewModel.WalletManager;
            var network       = walletManager.Network;

            Mnemonics.ToObservableChangeSet().ToCollection()
            .Select(x => x.Count == 12 ? new Mnemonic(GetTagsAsConcatString().ToLowerInvariant()) : default)
        public GenerateWalletViewModel(WalletManagerViewModel owner) : base("Generate Wallet")
        {
            Global = Locator.Current.GetService <Global>();
            Owner  = owner;

            this.ValidateProperty(x => x.Password, ValidatePassword);

            NextCommand = ReactiveCommand.Create(DoNextCommand, this.WhenAnyValue(x => x.Validations.Any).Select(x => !x));

            NextCommand.ThrownExceptions
            .ObserveOn(RxApp.TaskpoolScheduler)
            .Subscribe(ex => Logger.LogError(ex));
        }
        public GenerateWalletViewModel(WalletManagerViewModel owner) : base("Generate Wallet")
        {
            Global = Locator.Current.GetService <Global>();
            Owner  = owner;

            IObservable <bool> canGenerate = this.WhenAnyValue(x => x.Password).Select(pw => !ValidatePassword().HasErrors);

            NextCommand = ReactiveCommand.Create(DoNextCommand, canGenerate);

            NextCommand.ThrownExceptions
            .ObserveOn(RxApp.TaskpoolScheduler)
            .Subscribe(ex => Logger.LogError(ex));
        }
Example #12
0
        private async Task OnNext(WalletManagerViewModel walletManagerViewModel, ClosedWalletViewModel closedWalletViewModel, Wallet wallet)
        {
            string?compatibilityPasswordUsed = null;

            var isPasswordCorrect = await Task.Run(() => wallet.TryLogin(Password, out compatibilityPasswordUsed));

            if (!isPasswordCorrect)
            {
                ErrorMessage = "The password is incorrect! Try Again.";
                return;
            }

            if (compatibilityPasswordUsed is { })
Example #13
0
        public SearchPageViewModel(NavigationStateViewModel navigationState, WalletManagerViewModel walletManager, AddWalletPageViewModel addWalletPage, SettingsPageViewModel settingsPage, HomePageViewModel homePage) : base(navigationState)
        {
            Title = "Search";

            _showSettings = true;
            _showWallets  = false;

            var generalCategory       = new SearchCategory("General", 0);
            var generalCategorySource = new SourceList <SearchItemViewModel>();

            generalCategorySource.Add(CreateHomeSearchItem(generalCategory, 0, homePage));
            generalCategorySource.Add(CreateSettingsSearchItem(generalCategory, 1, settingsPage));
            generalCategorySource.Add(CreateAddWalletSearchItem(generalCategory, 2, addWalletPage));

            var settingsCategory       = new SearchCategory("Settings", 1);
            var settingsCategorySource = new SourceList <SearchItemViewModel>();

            settingsCategorySource.AddRange(CreateSettingsSearchItems(settingsCategory, settingsPage));

            var walletCategory = new SearchCategory("Wallets", 2);
            var wallets        = walletManager.Items
                                 .ToObservableChangeSet()
                                 .Transform(x => CreateWalletSearchItem(walletCategory, 0, x))
                                 .Sort(SortExpressionComparer <SearchItemViewModel> .Ascending(i => i.Title));

            var searchItems = generalCategorySource.Connect();

            if (_showSettings)
            {
                searchItems = searchItems.Merge(settingsCategorySource.Connect());
            }

            if (_showWallets)
            {
                searchItems = searchItems.Merge(wallets);
            }

            var queryFilter = this.WhenValueChanged(t => t.SearchQuery)
                              .Throttle(TimeSpan.FromMilliseconds(100))
                              .Select(SearchQueryFilter)
                              .DistinctUntilChanged();

            searchItems
            .Filter(queryFilter)
            .GroupWithImmutableState(x => x.Category)
            .Transform(grouping => new SearchResult(grouping.Key, grouping.Items.OrderBy(x => x.Order).ThenBy(x => x.Title)))
            .Sort(SortExpressionComparer <SearchResult> .Ascending(i => i.Category.Order).ThenByAscending(i => i.Category.Title))
            .ObserveOn(RxApp.MainThreadScheduler)
            .Bind(out _searchResults)
            .AsObservableList();
        }
Example #14
0
        private bool _disposedValue = false;         // To detect redundant calls

        public LoadWalletViewModel(WalletManagerViewModel owner, LoadWalletType loadWalletType)
            : base(loadWalletType == LoadWalletType.Password ? "Test Password" : "Load Wallet")
        {
            Global = Locator.Current.GetService <Global>();

            Owner          = owner;
            Password       = "";
            LoadWalletType = loadWalletType;

            this.ValidateProperty(x => x.Password, ValidatePassword);

            RootList = new SourceList <WalletViewModelBase>();
            RootList.Connect()
            .AutoRefresh(model => model.WalletState)
            .Filter(x => (!IsPasswordRequired || !x.Wallet.KeyManager.IsWatchOnly))
            .Sort(SortExpressionComparer <WalletViewModelBase>
                  .Descending(p => p.Wallet.KeyManager.GetLastAccessTime()),
                  resort: ResortTrigger.AsObservable())
            .ObserveOn(RxApp.MainThreadScheduler)
            .Bind(out _wallets)
            .DisposeMany()
            .Subscribe()
            .DisposeWith(Disposables);

            Observable.FromEventPattern <Wallet>(Global.WalletManager, nameof(Global.WalletManager.WalletAdded))
            .ObserveOn(RxApp.MainThreadScheduler)
            .Select(x => x.EventArgs)
            .Subscribe(wallet => RootList.Add(new WalletViewModelBase(wallet)))
            .DisposeWith(Disposables);

            this.WhenAnyValue(x => x.SelectedWallet)
            .Where(x => x is null)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(_ => SelectedWallet = Wallets.FirstOrDefault());

            Wallets
            .ToObservableChangeSet()
            .ToCollection()
            .Where(items => items.Any() && SelectedWallet is null)
            .Select(items => items.First())
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(x => SelectedWallet = x);

            LoadCommand = ReactiveCommand.Create(() =>
                                                 RxApp.MainThreadScheduler
                                                 .Schedule(async() => await LoadWalletAsync())
                                                 .DisposeWith(Disposables),
                                                 this.WhenAnyValue(x => x.SelectedWallet, x => x?.WalletState)
                                                 .Select(x => x == WalletState.Uninitialized));

            TestPasswordCommand = ReactiveCommand.Create(LoadKeyManager, this.WhenAnyValue(x => x.SelectedWallet).Select(x => x is { }));
        public GenerateWalletSuccessViewModel(WalletManagerViewModel owner, KeyManager keyManager, Mnemonic mnemonic) : base("Wallet Generated Successfully!")
        {
            _mnemonicWords = mnemonic.ToString();

            ConfirmCommand = ReactiveCommand.Create(() =>
            {
                keyManager.ToFile();
                NotificationHelpers.Success("Wallet was generated.");
                owner.SelectTestPassword();
            });

            ConfirmCommand.ThrownExceptions
            .ObserveOn(RxApp.TaskpoolScheduler)
            .Subscribe(ex => Logger.LogError(ex));
        }
        public GenerateWalletSuccessViewModel(WalletManagerViewModel owner, KeyManager keyManager, Mnemonic mnemonic) : base("Wallet Generated Successfully!")
        {
            _mnemonicWords = mnemonic.ToString();
            var global = Locator.Current.GetService <Global>();

            ConfirmCommand = ReactiveCommand.Create(() =>
            {
                var wallet = global.WalletManager.AddWallet(keyManager);
                NotificationHelpers.Success("Wallet was generated.");
                owner.SelectTestPassword(wallet.WalletName);
            });

            ConfirmCommand.ThrownExceptions
            .ObserveOn(RxApp.TaskpoolScheduler)
            .Subscribe(ex => Logger.LogError(ex));
        }
        protected ClosedWalletViewModel(WalletManagerViewModel walletManagerViewModel, Wallet wallet)
            : base(wallet)
        {
            _items = new ObservableCollection <NavBarItemViewModel>();

            OpenCommand = ReactiveCommand.Create(() =>
            {
                if (!Wallet.IsLoggedIn)
                {
                    Navigate().To(new LoginViewModel(walletManagerViewModel, this), NavigationMode.Clear);
                }
                else
                {
                    Navigate().To(this, NavigationMode.Clear);
                }
            });
        }
Example #18
0
        private void DisplayWalletManager()
        {
            var walletManagerViewModel = new WalletManagerViewModel();

            IoC.Get <IShell>().AddDocument(walletManagerViewModel);

            var isAnyDesktopWalletAvailable = Directory.Exists(Global.WalletsDir) && Directory.EnumerateFiles(Global.WalletsDir).Any();

            if (isAnyDesktopWalletAvailable)
            {
                walletManagerViewModel.SelectLoadWallet();
            }
            else
            {
                walletManagerViewModel.SelectGenerateWallet();
            }
        }
Example #19
0
        public LoginViewModel(WalletManagerViewModel walletManagerViewModel, ClosedWalletViewModel closedWalletViewModel)
        {
            var wallet = closedWalletViewModel.Wallet;

            IsPasswordNeeded = !wallet.KeyManager.IsWatchOnly;
            WalletName       = wallet.WalletName;
            _password        = "";
            _errorMessage    = "";
            WalletType       = WalletHelpers.GetType(closedWalletViewModel.Wallet.KeyManager);

            NextCommand = ReactiveCommand.CreateFromTask(async() => await OnNextAsync(walletManagerViewModel, closedWalletViewModel, wallet));

            OkCommand = ReactiveCommand.Create(OnOk);

            ForgotPasswordCommand = ReactiveCommand.Create(() => OnForgotPassword(wallet));

            EnableAutoBusyOn(NextCommand);
        }
        private void RecoverWallet(WalletManagerViewModel owner)
        {
            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 = WalletManager.WalletDirectories.GetWalletFilePaths(WalletName).walletFilePath;

            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
            {
                var minGapLimit = int.Parse(MinGapLimit);
                var keyPath     = KeyPath.Parse(AccountKeyPath);

                try
                {
                    var mnemonic = new Mnemonic(MnemonicWords);
                    var km       = KeyManager.Recover(mnemonic, Password, filePath: null, keyPath, minGapLimit);
                    km.SetNetwork(Global.Network);
                    km.SetFilePath(walletFilePath);
                    WalletManager.AddWallet(km);

                    NotificationHelpers.Success("Wallet was recovered.");

                    owner.SelectLoadWallet(km);
                }
                catch (Exception ex)
                {
                    Logger.LogError(ex);
                    NotificationHelpers.Error(ex.ToUserFriendlyString());
                }
            }
        }
Example #21
0
        public LoginViewModel(WalletManagerViewModel walletManagerViewModel, ClosedWalletViewModel closedWalletViewModel)
        {
            var wallet = closedWalletViewModel.Wallet;

            IsPasswordNeeded = !wallet.KeyManager.IsWatchOnly;
            WalletName       = wallet.WalletName;
            _password        = "";
            _errorMessage    = "";
            WalletIcon       = wallet.KeyManager.Icon;
            IsHardwareWallet = wallet.KeyManager.IsHardwareWallet;

            NextCommand = ReactiveCommand.CreateFromTask(async() =>
            {
                string?compatibilityPasswordUsed = null;

                var isPasswordCorrect = await Task.Run(() => wallet.TryLogin(Password, out compatibilityPasswordUsed));

                if (!isPasswordCorrect)
                {
                    ErrorMessage = "The password is incorrect! Try Again.";
                    return;
                }

                if (compatibilityPasswordUsed is { })
                {
                    await ShowErrorAsync(Title, PasswordHelper.CompatibilityPasswordWarnMessage, "Compatibility password was used");
                }

                var legalResult = await ShowLegalAsync(walletManagerViewModel.LegalChecker);

                if (legalResult)
                {
                    await LoginWalletAsync(walletManagerViewModel, closedWalletViewModel);
                }
                else
                {
                    wallet.Logout();
                    ErrorMessage = "You must accept the Terms and Conditions!";
                }
            });
Example #22
0
        public GenerateWalletSuccessViewModel(WalletManagerViewModel owner, KeyManager keyManager, Mnemonic mnemonic) : base("Wallet Generated Successfully!")
        {
            _mnemonicWords = new List <string>(mnemonic.Words.Length);

            for (int i = 0; i < mnemonic.Words.Length; i++)
            {
                _mnemonicWords.Add($"{i + 1}. {mnemonic.Words[i]}");
            }

            var global = Locator.Current.GetService <Global>();

            ConfirmCommand = ReactiveCommand.Create(() =>
            {
                var wallet = global.WalletManager.AddWallet(keyManager);
                NotificationHelpers.Success("Wallet was generated.");
                owner.SelectTestPassword(wallet.WalletName);
            }, this.WhenAnyValue(x => x.IsConfirmed));

            ConfirmCommand.ThrownExceptions
            .ObserveOn(RxApp.TaskpoolScheduler)
            .Subscribe(ex => Logger.LogError(ex));
        }
        public LoadWalletViewModel(WalletManagerViewModel owner, LoadWalletType loadWalletType)
            : base(loadWalletType == LoadWalletType.Password ? "Test Password" : loadWalletType == LoadWalletType.Desktop ? "Load Wallet" : "Hardware Wallet")
        {
            Global = Locator.Current.GetService <Global>();

            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(LoadWalletAsync, this.WhenAnyValue(x => x.CanLoadWallet));
            TestPasswordCommand = ReactiveCommand.CreateFromTask(LoadKeyManagerAsync, this.WhenAnyValue(x => x.CanTestPassword));
            OpenFolderCommand   = ReactiveCommand.Create(OpenWalletsFolder);
            OpenBrowserCommand  = ReactiveCommand.CreateFromTask <string>(IoHelpers.OpenBrowserAsync);

            Observable
            .Merge(OpenBrowserCommand.ThrownExceptions)
            .Merge(LoadCommand.ThrownExceptions)
            .Merge(TestPasswordCommand.ThrownExceptions)
            .Merge(OpenFolderCommand.ThrownExceptions)
            .ObserveOn(RxApp.TaskpoolScheduler)
            .Subscribe(ex =>
            {
                Logger.LogError(ex);
                NotificationHelpers.Error(ex.ToUserFriendlyString());
            });

            SetLoadButtonText();
        }
Example #24
0
        public AddWalletPageViewModel(
            WalletManagerViewModel walletManagerViewModel,
            BitcoinStore store)
        {
            Title         = "Add Wallet";
            SelectionMode = NavBarItemSelectionMode.Button;
            var walletManager = walletManagerViewModel.WalletManager;
            var network       = walletManager.Network;

            var enableBack = default(IDisposable);

            this.WhenAnyValue(x => x.CurrentTarget)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(x =>
            {
                enableBack?.Dispose();
                enableBack = Navigate()
                             .WhenAnyValue(y => y.CanNavigateBack)
                             .Subscribe(y => EnableBack = y);
            });

            this.WhenAnyValue(x => x.WalletName)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Select(x => !string.IsNullOrWhiteSpace(x))
            .Subscribe(x => OptionsEnabled = x && !Validations.Any);

            RecoverWalletCommand = ReactiveCommand.Create(() => OnRecoverWallet(walletManagerViewModel));

            ImportWalletCommand = ReactiveCommand.CreateFromTask(async() => await OnImportWallet(walletManager));

            ConnectHardwareWalletCommand = ReactiveCommand.Create(() => OnConnectHardwareWallet(walletManagerViewModel));

            CreateWalletCommand = ReactiveCommand.CreateFromTask(async() => await OnCreateWallet(walletManager, store, network));

            this.ValidateProperty(x => x.WalletName, errors => ValidateWalletName(errors, walletManager, WalletName));

            EnableAutoBusyOn(CreateWalletCommand);
        }
        public ConnectHardwareWalletViewModel(string walletName, WalletManagerViewModel walletManagerViewModel)
        {
            _message       = "";
            WalletName     = walletName;
            WalletManager  = walletManagerViewModel.WalletManager;
            Wallets        = walletManagerViewModel.Wallets;
            AbandonedTasks = new AbandonedTasks();
            CancelCts      = new CancellationTokenSource();

            EnableCancel = true;

            EnableBack = true;

            NextCommand = ReactiveCommand.Create(OnNext);

            OpenBrowserCommand = ReactiveCommand.CreateFromTask(async() =>
                                                                await IoHelpers.OpenBrowserAsync("https://docs.wasabiwallet.io/using-wasabi/ColdWasabi.html#using-hardware-wallet-step-by-step"));

            NavigateToExistingWalletLoginCommand = ReactiveCommand.Create(execute: OnNavigateToExistingWalletLogin);

            this.WhenAnyValue(x => x.Message)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(message => ConfirmationRequired = !string.IsNullOrEmpty(message));
        }
Example #26
0
 internal ClosedHardwareWalletViewModel(WalletManagerViewModel walletManager, Wallet wallet) : base(walletManager, wallet)
 {
 }
Example #27
0
        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 = Global.WalletManager.WalletDirectories.GetWalletFilePaths(WalletName).walletFilePath;

                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 was recovered.");

                        owner.SelectLoadWallet();
                    }
                    catch (Exception ex)
                    {
                        Logger.LogError(ex);
                        NotificationHelpers.Error(ex.ToUserFriendlyString());
                    }
                }
            });

            this.WhenAnyValue(x => x.MnemonicWords).Subscribe(UpdateSuggestions);

            _suggestions = new ObservableCollection <SuggestionViewModel>();

            RecoverCommand.ThrownExceptions
            .ObserveOn(RxApp.TaskpoolScheduler)
            .Subscribe(ex => Logger.LogError(ex));
        }
Example #28
0
 private void OnRecoverWallet(WalletManagerViewModel walletManagerViewModel)
 {
     Navigate().To(new RecoverWalletViewModel(WalletName, walletManagerViewModel));
 }
Example #29
0
 private void OnConnectHardwareWallet(WalletManagerViewModel walletManagerViewModel)
 {
     Navigate().To(new ConnectHardwareWalletViewModel(WalletName, walletManagerViewModel));
 }
Example #30
0
        public AddWalletPageViewModel(
            WalletManagerViewModel walletManagerViewModel,
            BitcoinStore store)
        {
            Title         = "Add Wallet";
            SelectionMode = NavBarItemSelectionMode.Button;
            var walletManager = walletManagerViewModel.Model;
            var network       = walletManager.Network;

            var enableBack = default(IDisposable);

            this.WhenAnyValue(x => x.CurrentTarget)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(x =>
            {
                enableBack?.Dispose();
                enableBack = Navigate()
                             .WhenAnyValue(y => y.CanNavigateBack)
                             .Subscribe(y => EnableBack = y);
            });

            this.WhenAnyValue(x => x.WalletName)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Select(x => !string.IsNullOrWhiteSpace(x))
            .Subscribe(x => OptionsEnabled = x && !Validations.Any);

            RecoverWalletCommand = ReactiveCommand.Create(
                () => Navigate().To(new RecoverWalletViewModel(WalletName, walletManagerViewModel)));

            ImportWalletCommand = ReactiveCommand.CreateFromTask(async() =>
            {
                try
                {
                    var filePath = await FileDialogHelper.ShowOpenFileDialogAsync("Import wallet file", new[] { "json" });

                    if (filePath is null)
                    {
                        return;
                    }

                    var keyManager = await ImportWalletHelper.ImportWalletAsync(walletManager, WalletName, filePath);

                    // TODO: get the type from the wallet file
                    Navigate().To(new AddedWalletPageViewModel(walletManager, keyManager));
                }
                catch (Exception ex)
                {
                    Logger.LogError(ex);
                    await ShowErrorAsync(ex.ToUserFriendlyString(), "The wallet file was not valid or compatible with Wasabi.");
                }
            });

            ConnectHardwareWalletCommand = ReactiveCommand.Create(() => Navigate().To(new ConnectHardwareWalletViewModel(WalletName, walletManagerViewModel)));

            CreateWalletCommand = ReactiveCommand.CreateFromTask(
                async() =>
            {
                var dialogResult = await NavigateDialog(
                    new EnterPasswordViewModel("Type the password of the wallet and click Continue."));

                if (dialogResult.Result is { } password)
                {
                    var(km, mnemonic) = await Task.Run(
                        () =>
                    {
                        var walletGenerator = new WalletGenerator(
                            walletManager.WalletDirectories.WalletsDir,
                            network)
                        {
                            TipHeight = store.SmartHeaderChain.TipHeight
                        };
                        return(walletGenerator.GenerateWallet(WalletName, password));
                    });

                    Navigate().To(new RecoveryWordsViewModel(km, mnemonic, walletManager));
                }
            });

            this.ValidateProperty(x => x.WalletName, errors => ValidateWalletName(errors, walletManager, WalletName));

            EnableAutoBusyOn(CreateWalletCommand);
        }