コード例 #1
0
        public override void OnOpen()
        {
            base.OnOpen();

            Disposables = Disposables is null ? new CompositeDisposable() : throw new NotSupportedException($"Cannot open {GetType().Name} before closing it.");

            TargetPrivacy = Global.Config.GetTargetPrivacy();

            var registrableRound = Global.WalletService.ChaumianClient.State.GetRegistrableRoundOrDefault();

            UpdateRequiredBtcLabel(registrableRound);

            CoordinatorFeePercent = registrableRound?.State?.CoordinatorFeePercent.ToString() ?? "0.003";

            Observable.FromEventPattern(Global.WalletService.ChaumianClient, nameof(Global.WalletService.ChaumianClient.CoinQueued))
            .Merge(Observable.FromEventPattern(Global.WalletService.ChaumianClient, nameof(Global.WalletService.ChaumianClient.OnDequeue)))
            .Merge(Observable.FromEventPattern(Global.WalletService.ChaumianClient, nameof(Global.WalletService.ChaumianClient.StateUpdated)))
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(_ => UpdateStates())
            .DisposeWith(Disposables);

            ClientRound mostAdvancedRound = Global.WalletService.ChaumianClient?.State?.GetMostAdvancedRoundOrDefault();

            if (mostAdvancedRound != default)
            {
                RoundId         = mostAdvancedRound.State.RoundId;
                RoundPhaseState = new RoundPhaseState(mostAdvancedRound.State.Phase, Global.WalletService.ChaumianClient?.State.IsInErrorState ?? false);
                RoundTimesout   = mostAdvancedRound.State.Phase == RoundPhase.InputRegistration ? mostAdvancedRound.State.InputRegistrationTimesout : DateTimeOffset.UtcNow;
                PeersRegistered = mostAdvancedRound.State.RegisteredPeerCount;
                PeersNeeded     = mostAdvancedRound.State.RequiredPeerCount;
            }
            else
            {
                RoundId         = -1;
                RoundPhaseState = new RoundPhaseState(RoundPhase.InputRegistration, false);
                RoundTimesout   = DateTimeOffset.UtcNow;
                PeersRegistered = 0;
                PeersNeeded     = 100;
            }

            Global.UiConfig.WhenAnyValue(x => x.LurkingWifeMode).ObserveOn(RxApp.MainThreadScheduler).Subscribe(_ =>
            {
                this.RaisePropertyChanged(nameof(AmountQueued));
                this.RaisePropertyChanged(nameof(IsLurkingWifeMode));
            }).DisposeWith(Disposables);

            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);
        }
コード例 #2
0
        private void UpdateStates()
        {
            var chaumianClient = _walletManager.CurrentWallet.ChaumianClient;

            if (chaumianClient is null)
            {
                return;
            }

            AmountQueued = chaumianClient.State.SumAllQueuedCoinAmounts();

            var registrableRound = chaumianClient.State.GetRegistrableRoundOrDefault();

            if (registrableRound != default)
            {
                CoordinatorFeePercent = registrableRound.State.CoordinatorFeePercent.ToString();
                UpdateRequiredBtcLabel(registrableRound);
            }

            var mostAdvancedRound = chaumianClient.State.GetMostAdvancedRoundOrDefault();

            if (mostAdvancedRound != default)
            {
                if (!chaumianClient.State.IsInErrorState)
                {
                    RoundPhaseState = new RoundPhaseState(mostAdvancedRound.State.Phase, false);
                    if (mostAdvancedRound.State?.InputRegistrationTimesout > RoundTimesout &&
                        AmountQueued > Money.Zero)
                    {   // Seems like this is getting triggered twice.
                        ScheduleConfirmNotification(mostAdvancedRound.State.InputRegistrationTimesout);
                    }
                    RoundTimesout = mostAdvancedRound.State.Phase == RoundPhase.InputRegistration ? mostAdvancedRound.State.InputRegistrationTimesout : DateTimeOffset.UtcNow;
                }
                else
                {
                    RoundPhaseState = new RoundPhaseState(RoundPhaseState.Phase, true);
                }

                this.RaisePropertyChanged(nameof(RoundPhaseState));
                this.RaisePropertyChanged(nameof(RoundTimesout));
                PeersRegistered = mostAdvancedRound.State.RegisteredPeerCount;
                PeersQueued     = mostAdvancedRound.State.QueuedPeerCount;
                PeersNeeded     = mostAdvancedRound.State.RequiredPeerCount;
            }
        }
コード例 #3
0
        private void UpdateStates()
        {
            var chaumianClient = Global?.WalletService?.ChaumianClient;

            if (chaumianClient is null)
            {
                return;
            }

            AmountQueued = chaumianClient.State.SumAllQueuedCoinAmounts();
            MainWindowViewModel.Instance.CanClose = AmountQueued == Money.Zero;

            var registrableRound = chaumianClient.State.GetRegistrableRoundOrDefault();

            if (registrableRound != default)
            {
                CoordinatorFeePercent = registrableRound.State.CoordinatorFeePercent.ToString();
                UpdateRequiredBtcLabel(registrableRound);
            }
            var mostAdvancedRound = chaumianClient.State.GetMostAdvancedRoundOrDefault();

            if (mostAdvancedRound != default)
            {
                RoundId = mostAdvancedRound.State.RoundId;
                if (!chaumianClient.State.IsInErrorState)
                {
                    RoundPhaseState = new RoundPhaseState(mostAdvancedRound.State.Phase, false);
                    RoundTimesout   = mostAdvancedRound.State.Phase == RoundPhase.InputRegistration ? mostAdvancedRound.State.InputRegistrationTimesout : DateTimeOffset.UtcNow;
                }
                else
                {
                    RoundPhaseState = new RoundPhaseState(RoundPhaseState.Phase, true);
                }

                this.RaisePropertyChanged(nameof(RoundPhaseState));
                this.RaisePropertyChanged(nameof(RoundTimesout));
                PeersRegistered = mostAdvancedRound.State.RegisteredPeerCount;
                PeersNeeded     = mostAdvancedRound.State.RequiredPeerCount;
            }
        }
コード例 #4
0
        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);
        }
コード例 #5
0
        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);
            });
コード例 #6
0
 private string FormatPhaseLabel(RoundPhaseState rps)
 {
     _phaseStringConverter.TryConvert(rps, typeof(string), null, out var phaseString);
     return("Phase: " + phaseString);
 }