public static string ToFriendlyString(this DequeueReason me) { return(me switch { DequeueReason.UserRequested => "User requested.", DequeueReason.TransactionBuilding => "Using coin for transaction building.", DequeueReason.Banned => "Coin is banned.", DequeueReason.NotEnoughFundsEnqueued => "Not enough funds enqueued.", DequeueReason.CoordinatorFeeChanged => "Coordinator fee changed.", DequeueReason.ApplicationExit => "Application is exiting.", DequeueReason.Spent => "Coin is spent.", DequeueReason.Mixing => "Coin is being mixed.", _ => me.ToString() });
private void WalletManager_OnDequeue(object?sender, DequeueResult e) { try { foreach (var success in e.Successful.Where(x => x.Value.Any())) { DequeueReason reason = success.Key; if (reason == DequeueReason.ApplicationExit) { SleepingCoins = success.Value; } } } catch (Exception ex) { Logger.LogWarning(ex); } }
public CoinJoinViewModel(ChaincaseWalletManager walletManager, Config config, INotificationManager notificationManager, SelectCoinsViewModel selectCoinsViewModel) { _walletManager = walletManager; _config = config; _notificationManager = notificationManager; CoinList = selectCoinsViewModel; if (Disposables != null) { throw new Exception("Wallet opened before it was closed."); } Disposables = new CompositeDisposable(); // Infer coordinator fee var registrableRound = _walletManager.CurrentWallet?.ChaumianClient?.State?.GetRegistrableRoundOrDefault(); CoordinatorFeePercent = registrableRound?.State?.CoordinatorFeePercent.ToString() ?? "0.003"; // Select most advanced coin join round ClientRound mostAdvancedRound = _walletManager.CurrentWallet?.ChaumianClient?.State?.GetMostAdvancedRoundOrDefault(); if (mostAdvancedRound != default) { RoundPhaseState = new RoundPhaseState(mostAdvancedRound.State.Phase, _walletManager.CurrentWallet.ChaumianClient?.State.IsInErrorState ?? false); RoundTimesout = mostAdvancedRound.State.Phase == RoundPhase.InputRegistration ? mostAdvancedRound.State.InputRegistrationTimesout : DateTimeOffset.UtcNow; PeersRegistered = mostAdvancedRound.State.RegisteredPeerCount; PeersQueued = mostAdvancedRound.State.QueuedPeerCount; PeersNeeded = mostAdvancedRound.State.RequiredPeerCount; RequiredBTC = mostAdvancedRound.State.CalculateRequiredAmount(); } else { RoundPhaseState = new RoundPhaseState(RoundPhase.InputRegistration, false); RoundTimesout = DateTimeOffset.UtcNow; PeersRegistered = 0; PeersQueued = 0; PeersNeeded = 100; RequiredBTC = Money.Parse("0.01"); } // Set time left in round this.WhenAnyValue(x => x.RoundTimesout) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(_ => { TimeLeftTillRoundTimeout = TimeUntilOffset(RoundTimesout); }); Task.Run(async() => { while (_walletManager.CurrentWallet?.ChaumianClient == null) { await Task.Delay(50).ConfigureAwait(false); } // Update view model state on chaumian client state updates Observable.FromEventPattern(_walletManager.CurrentWallet.ChaumianClient, nameof(_walletManager.CurrentWallet.ChaumianClient.CoinQueued)) .Merge(Observable.FromEventPattern(_walletManager.CurrentWallet.ChaumianClient, nameof(_walletManager.CurrentWallet.ChaumianClient.OnDequeue))) .Merge(Observable.FromEventPattern(_walletManager.CurrentWallet.ChaumianClient, nameof(_walletManager.CurrentWallet.ChaumianClient.StateUpdated))) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(_ => UpdateStates()) .DisposeWith(Disposables); // Remove notification on unconfirming status in coin join round Observable.FromEventPattern(_walletManager.CurrentWallet.ChaumianClient, nameof(_walletManager.CurrentWallet.ChaumianClient.OnDequeue)) .Subscribe(pattern => { var e = (DequeueResult)pattern.EventArgs; try { foreach (var success in e.Successful.Where(x => x.Value.Any())) { DequeueReason reason = success.Key; if (reason == DequeueReason.UserRequested) { _notificationManager.RemoveAllPendingNotifications(); } } } catch (Exception ex) { Logger.LogWarning(ex); } }) .DisposeWith(Disposables); }); // Update timeout label Observable.Interval(TimeSpan.FromSeconds(1)) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(_ => { TimeLeftTillRoundTimeout = TimeUntilOffset(RoundTimesout); }).DisposeWith(Disposables); }
public CoinJoinViewModel(CoinListViewModel coinList) : base(Locator.Current.GetService <IViewStackService>()) { Global = Locator.Current.GetService <Global>(); SetBalance(); notificationManager = Global.NotificationManager; if (Disposables != null) { throw new Exception("Wallet opened before it was closed."); } Disposables = new CompositeDisposable(); CoinList = coinList; Observable .FromEventPattern <SmartCoin>(CoinList, nameof(CoinList.DequeueCoinsPressed)) .Subscribe(async x => await DoDequeueAsync(x.EventArgs)); this.WhenAnyValue(x => x.RoundTimesout) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(_ => { TimeSpan left = RoundTimesout - DateTimeOffset.UtcNow; TimeLeftTillRoundTimeout = left > TimeSpan.Zero ? left : TimeSpan.Zero; // Make sure cannot be less than zero. }); AmountQueued = Money.Zero; var registrableRound = Global.Wallet.ChaumianClient.State.GetRegistrableRoundOrDefault(); CoordinatorFeePercent = registrableRound?.State?.CoordinatorFeePercent.ToString() ?? "0.003"; Observable.FromEventPattern(Global.Wallet.ChaumianClient, nameof(Global.Wallet.ChaumianClient.CoinQueued)) .Merge(Observable.FromEventPattern(Global.Wallet.ChaumianClient, nameof(Global.Wallet.ChaumianClient.OnDequeue))) .Merge(Observable.FromEventPattern(Global.Wallet.ChaumianClient, nameof(Global.Wallet.ChaumianClient.StateUpdated))) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(_ => UpdateStates()) .DisposeWith(Disposables); Observable.FromEventPattern(Global.Wallet.ChaumianClient, nameof(Global.Wallet.ChaumianClient.OnDequeue)) .Subscribe(pattern => { var e = (DequeueResult)pattern.EventArgs; try { foreach (var success in e.Successful.Where(x => x.Value.Any())) { DequeueReason reason = success.Key; if (reason == DequeueReason.UserRequested) { notificationManager.RemoveAllPendingNotifications(); } } } catch (Exception ex) { Logger.LogWarning(ex); } }) .DisposeWith(Disposables); ClientRound mostAdvancedRound = Global.Wallet.ChaumianClient?.State?.GetMostAdvancedRoundOrDefault(); if (mostAdvancedRound != default) { RoundPhaseState = new RoundPhaseState(mostAdvancedRound.State.Phase, Global.Wallet.ChaumianClient?.State.IsInErrorState ?? false); RoundTimesout = mostAdvancedRound.State.Phase == RoundPhase.InputRegistration ? mostAdvancedRound.State.InputRegistrationTimesout : DateTimeOffset.UtcNow; PeersRegistered = mostAdvancedRound.State.RegisteredPeerCount; PeersNeeded = mostAdvancedRound.State.RequiredPeerCount; } else { RoundPhaseState = new RoundPhaseState(RoundPhase.InputRegistration, false); RoundTimesout = DateTimeOffset.UtcNow; PeersRegistered = 0; PeersNeeded = 100; } Observable.Interval(TimeSpan.FromSeconds(1)) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(_ => { TimeSpan left = RoundTimesout - DateTimeOffset.UtcNow; TimeLeftTillRoundTimeout = left > TimeSpan.Zero ? left : TimeSpan.Zero; // Make sure cannot be less than zero. }).DisposeWith(Disposables); CoinJoinCommand = ReactiveCommand.CreateFromTask <string, bool>(DoEnqueueAsync); ExitCoinJoinCommand = ReactiveCommand.CreateFromTask(ExitCoinJoinAsync); var canPromptPassword = this.WhenAnyValue( x => x.CoinList.SelectedAmount, x => x.RequiredBTC, (amnt, rBTC) => { return(!(rBTC is null) && !(amnt is null) && amnt >= rBTC); });