public async Task <IActionResult> WalletSettings( [ModelBinder(typeof(WalletIdModelBinder))] WalletId walletId) { var derivationSchemeSettings = GetDerivationSchemeSettings(walletId); if (derivationSchemeSettings == null || derivationSchemeSettings.Network.ReadonlyWallet) { return(NotFound()); } var store = (await Repository.FindStore(walletId.StoreId, GetUserId())); var vm = new WalletSettingsViewModel() { Label = derivationSchemeSettings.Label, DerivationScheme = derivationSchemeSettings.AccountDerivation.ToString(), DerivationSchemeInput = derivationSchemeSettings.AccountOriginal, SelectedSigningKey = derivationSchemeSettings.SigningKey.ToString() }; vm.AccountKeys = derivationSchemeSettings.AccountKeySettings .Select(e => new WalletSettingsAccountKeyViewModel() { AccountKey = e.AccountKey.ToString(), MasterFingerprint = e.RootFingerprint is HDFingerprint fp ? fp.ToString() : null, AccountKeyPath = e.AccountKeyPath == null ? "" : $"m/{e.AccountKeyPath}" }).ToList();
protected WalletViewModel(Wallet wallet) : base(wallet) { Disposables = Disposables is null ? new CompositeDisposable() : throw new NotSupportedException($"Cannot open {GetType().Name} before closing it."); Settings = new WalletSettingsViewModel(this); var balanceChanged = Observable.FromEventPattern( Wallet.TransactionProcessor, nameof(Wallet.TransactionProcessor.WalletRelevantTransactionProcessed)) .Select(_ => Unit.Default) .Merge(Observable.FromEventPattern(Wallet, nameof(Wallet.NewFilterProcessed)) .Select(_ => Unit.Default)) .Merge(Services.UiConfig.WhenAnyValue(x => x.PrivacyMode).Select(_ => Unit.Default)) .Merge(Wallet.Synchronizer.WhenAnyValue(x => x.UsdExchangeRate).Select(_ => Unit.Default)) .Merge(Settings.WhenAnyValue(x => x.AnonScoreTarget).Select(_ => Unit.Default).Skip(1).Throttle(TimeSpan.FromMilliseconds(3000)) .Throttle(TimeSpan.FromSeconds(0.1)) .ObserveOn(RxApp.MainThreadScheduler)); History = new HistoryViewModel(this, balanceChanged); balanceChanged .Subscribe(_ => IsWalletBalanceZero = wallet.Coins.TotalAmount() == Money.Zero) .DisposeWith(Disposables); if (Services.HostedServices.GetOrDefault <CoinJoinManager>() is { } coinJoinManager) {
protected WalletViewModel(Wallet wallet) : base(wallet) { Disposables = Disposables is null ? new CompositeDisposable() : throw new NotSupportedException($"Cannot open {GetType().Name} before closing it."); Settings = new WalletSettingsViewModel(this); var balanceChanged = Observable.FromEventPattern( Wallet.TransactionProcessor, nameof(Wallet.TransactionProcessor.WalletRelevantTransactionProcessed)) .Select(_ => Unit.Default) .Merge(Observable.FromEventPattern(Wallet, nameof(Wallet.NewFilterProcessed)) .Select(_ => Unit.Default)) .Merge(Services.UiConfig.WhenAnyValue(x => x.PrivacyMode).Select(_ => Unit.Default)) .Merge(Wallet.Synchronizer.WhenAnyValue(x => x.UsdExchangeRate).Select(_ => Unit.Default)) .Merge(Settings.WhenAnyValue(x => x.MinAnonScoreTarget, x => x.MaxAnonScoreTarget).Select(_ => Unit.Default).Skip(1).Throttle(TimeSpan.FromMilliseconds(3000)) .Throttle(TimeSpan.FromSeconds(0.1)) .ObserveOn(RxApp.MainThreadScheduler)); History = new HistoryViewModel(this, balanceChanged); balanceChanged .Subscribe(_ => IsWalletBalanceZero = wallet.Coins.TotalAmount() == Money.Zero) .DisposeWith(Disposables); if (Services.HostedServices.GetOrDefault <CoinJoinManager>() is { } coinJoinManager) { Observable .FromEventPattern <WalletStatusChangedEventArgs>(coinJoinManager, nameof(CoinJoinManager.WalletStatusChanged)) .Select(args => args.EventArgs) .Where(e => e.Wallet == Wallet) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(e => IsCoinJoining = e.IsCoinJoining) .DisposeWith(Disposables); } this.WhenAnyValue(x => x.History.IsTransactionHistoryEmpty) .Subscribe(x => IsEmptyWallet = x); _smallLayoutHeightBreakpoint = double.MaxValue; _wideLayoutWidthBreakpoint = double.MaxValue; _smallLayoutIndex = 0; _normalLayoutIndex = 1; _wideLayoutIndex = 2; Layouts = wallet.KeyManager.IsWatchOnly ? TileHelper.GetWatchOnlyWalletLayout() : TileHelper.GetNormalWalletLayout(); LayoutIndex = _normalLayoutIndex; _tiles = wallet.KeyManager.IsWatchOnly ? TileHelper.GetWatchOnlyWalletTiles(this, balanceChanged) : TileHelper.GetNormalWalletTiles(this, balanceChanged); this.WhenAnyValue(x => x.LayoutIndex) .Subscribe(x => { SetLayoutFlag(x); NotifyLayoutChanged(); UpdateTiles(); }); this.WhenAnyValue(x => x.WidthSource) .Subscribe(x => LayoutSelector(x, _heightSource)); this.WhenAnyValue(x => x.HeightSource) .Subscribe(x => LayoutSelector(_widthSource, x)); this.WhenAnyValue(x => x.IsWalletBalanceZero) .Subscribe(_ => IsSendButtonVisible = !IsWalletBalanceZero && (!wallet.KeyManager.IsWatchOnly || wallet.KeyManager.IsHardwareWallet)); SendCommand = ReactiveCommand.Create(() => Navigate(NavigationTarget.DialogScreen).To(new SendViewModel(wallet))); ReceiveCommand = ReactiveCommand.Create(() => Navigate(NavigationTarget.DialogScreen).To(new ReceiveViewModel(wallet))); WalletInfoCommand = ReactiveCommand.CreateFromTask(async() => { if (!string.IsNullOrEmpty(wallet.Kitchen.SaltSoup())) { var pwAuthDialog = new PasswordAuthDialogViewModel(wallet); var res = await NavigateDialogAsync(pwAuthDialog, NavigationTarget.CompactDialogScreen); if (!res.Result && res.Kind == DialogResultKind.Normal) { await ShowErrorAsync("Wallet Info", "The password is incorrect! Try Again.", ""); return; } else if (res.Kind is DialogResultKind.Back or DialogResultKind.Cancel) { return; } } Navigate(NavigationTarget.DialogScreen).To(new WalletInfoViewModel(this)); }); WalletStatisticsCommand = ReactiveCommand.Create(() => Navigate(NavigationTarget.DialogScreen).To(new WalletStatsViewModel(this))); WalletSettingsCommand = ReactiveCommand.Create(() => Navigate(NavigationTarget.DialogScreen).To(Settings)); WalletCoinsCommand = ReactiveCommand.Create(() => Navigate(NavigationTarget.DialogScreen).To(new WalletCoinsViewModel(this, balanceChanged))); CoinJoinStateViewModel = new CoinJoinStateViewModel(this, balanceChanged); }