public TransactionPreviewViewModel(Wallet wallet, TransactionInfo info)
        {
            _wallet = wallet;
            _labels = SmartLabel.Empty;
            _info   = info;

            SetupCancel(enableCancel: true, enableCancelOnEscape: true, enableCancelOnPressed: false);
            EnableBack = true;

            AddressText        = info.Address.ToString();
            PayJoinUrl         = info.PayJoinClient?.PaymentUrl.AbsoluteUri;
            IsPayJoin          = PayJoinUrl is not null;
            AdjustFeeAvailable = !TransactionFeeHelper.AreTransactionFeesEqual(_wallet);

            if (PreferPsbtWorkflow)
            {
                SkipCommand = ReactiveCommand.CreateFromTask(OnConfirmAsync);

                NextCommand = ReactiveCommand.CreateFromTask(OnExportPsbtAsync);

                _nextButtonText = "Save PSBT file";
            }
            else
            {
                NextCommand = ReactiveCommand.CreateFromTask(OnConfirmAsync);

                _nextButtonText = "Confirm";
            }

            AdjustFeeCommand = ReactiveCommand.CreateFromTask(OnAdjustFeeAsync);

            AvoidChangeCommand = ReactiveCommand.CreateFromTask(OnAvoidChangeAsync);

            ChangePocketsCommand = ReactiveCommand.CreateFromTask(OnChangePocketsAsync);
        }
    private void UpdateFeeAndEstimate(double confirmationTarget)
    {
        CurrentSatoshiPerByte = GetSatoshiPerByte(confirmationTarget);
        var targetBlock   = (int)Math.Ceiling(confirmationTarget);
        var estimatedTime = TransactionFeeHelper.CalculateConfirmationTime(targetBlock);

        CurrentConfirmationTargetString = ConfirmationTimeLabel.SliderLabel(estimatedTime);
    }
Beispiel #3
0
    public static string AxisLabel(TimeSpan timeSpan)
    {
        if (timeSpan <= TransactionFeeHelper.CalculateConfirmationTime(WalletWasabi.Helpers.Constants.FastestConfirmationTarget))
        {
            return("fastest");
        }

        return(TimeSpanFormatter.Format(timeSpan, new TimeSpanFormatter.Configuration("d", "h", "m")));
    }
Beispiel #4
0
    public static string SliderLabel(TimeSpan timeSpan)
    {
        if (timeSpan <= TransactionFeeHelper.CalculateConfirmationTime(WalletWasabi.Helpers.Constants.FastestConfirmationTarget))
        {
            return("fastest");
        }

        return("~" + TimeSpanFormatter.Format(timeSpan, new TimeSpanFormatter.Configuration(" days", " hours", " minutes")));
    }
        protected override void OnNavigatedTo(bool isInHistory, CompositeDisposable disposables)
        {
            IsBusy = true;

            base.OnNavigatedTo(isInHistory, disposables);

            var feeProvider = _wallet.FeeProvider;

            Observable
            .FromEventPattern(feeProvider, nameof(feeProvider.AllFeeEstimateChanged))
            .Select(x => (x.EventArgs as AllFeeEstimate) !.Estimations)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(estimations =>
            {
                FeeChart.UpdateFeeEstimates(TransactionFeeHelper.GetFeeEstimates(_wallet));
            })
            .DisposeWith(disposables);

            RxApp.MainThreadScheduler.Schedule(async() =>
            {
                while (feeProvider.AllFeeEstimate is null)
                {
                    await Task.Delay(100);
                }

                FeeChart.UpdateFeeEstimates(TransactionFeeHelper.GetFeeEstimates(_wallet));

                if (_transactionInfo.FeeRate != FeeRate.Zero)
                {
                    FeeChart.InitCurrentConfirmationTarget(_transactionInfo.FeeRate);
                }

                if (_isSilent)
                {
                    var satPerByteThreshold  = Services.Config.SatPerByteThreshold;
                    var blockTargetThreshold = Services.Config.BlockTargetThreshold;
                    var estimations          = FeeChart.GetValues();

                    var blockTarget = GetBestBlockTarget(estimations, satPerByteThreshold, blockTargetThreshold);

                    FeeChart.CurrentConfirmationTarget    = blockTarget;
                    _transactionInfo.ConfirmationTimeSpan = CalculateConfirmationTime(blockTarget);

                    Complete();
                }
                else
                {
                    IsBusy = false;
                }
            });
        }
    public SendFeeViewModel(Wallet wallet, TransactionInfo transactionInfo, bool isSilent)
    {
        _isSilent        = isSilent;
        IsBusy           = isSilent;
        _wallet          = wallet;
        _transactionInfo = transactionInfo;

        FeeChart = new FeeChartViewModel();

        SetupCancel(false, true, false);
        EnableBack = true;

        NextCommand = ReactiveCommand.Create(() =>
        {
            _transactionInfo.ConfirmationTimeSpan = TransactionFeeHelper.CalculateConfirmationTime(FeeChart.CurrentConfirmationTarget);

            Complete();
        });
    }
    protected override void OnNavigatedTo(bool isInHistory, CompositeDisposable disposables)
    {
        IsBusy = true;

        base.OnNavigatedTo(isInHistory, disposables);

        var feeProvider = _wallet.FeeProvider;

        Observable
        .FromEventPattern(feeProvider, nameof(feeProvider.AllFeeEstimateChanged))
        .Select(x => (x.EventArgs as AllFeeEstimate) !.Estimations)
        .ObserveOn(RxApp.MainThreadScheduler)
        .Subscribe(estimations => FeeChart.UpdateFeeEstimates(TransactionFeeHelper.GetFeeEstimates(_wallet), _transactionInfo.MaximumPossibleFeeRate))
        .DisposeWith(disposables);

        RxApp.MainThreadScheduler.Schedule(async() =>
        {
            while (feeProvider.AllFeeEstimate is null)
            {
                await Task.Delay(100);
            }

            FeeChart.UpdateFeeEstimates(TransactionFeeHelper.GetFeeEstimates(_wallet), _transactionInfo.MaximumPossibleFeeRate);

            if (_transactionInfo.FeeRate != FeeRate.Zero)
            {
                FeeChart.InitCurrentConfirmationTarget(_transactionInfo.FeeRate);
            }

            if (_isSilent)
            {
                _transactionInfo.ConfirmationTimeSpan = TransactionFeeHelper.CalculateConfirmationTime(FeeChart.CurrentConfirmationTarget);

                Complete();
            }
            else
            {
                IsBusy = false;
            }
        });
    }
Beispiel #8
0
    public TransactionPreviewViewModel(Wallet wallet, TransactionInfo info, BitcoinAddress destination, bool isFixedAmount)
    {
        _wallet                  = wallet;
        _info                    = info;
        _destination             = destination;
        _isFixedAmount           = isFixedAmount;
        _cancellationTokenSource = new CancellationTokenSource();

        PrivacySuggestions        = new PrivacySuggestionsFlyoutViewModel();
        CurrentTransactionSummary = new TransactionSummaryViewModel(this, _wallet, _info, destination);
        PreviewTransactionSummary = new TransactionSummaryViewModel(this, _wallet, _info, destination, true);

        TransactionSummaries = new List <TransactionSummaryViewModel>
        {
            CurrentTransactionSummary,
            PreviewTransactionSummary
        };

        DisplayedTransactionSummary = CurrentTransactionSummary;

        PrivacySuggestions.WhenAnyValue(x => x.PreviewSuggestion)
        .Subscribe(x =>
        {
            if (x is ChangeAvoidanceSuggestionViewModel ca)
            {
                UpdateTransaction(PreviewTransactionSummary, ca.TransactionResult);
            }
            else
            {
                DisplayedTransactionSummary = CurrentTransactionSummary;
            }
        });

        PrivacySuggestions.WhenAnyValue(x => x.SelectedSuggestion)
        .SubscribeAsync(async x =>
        {
            PrivacySuggestions.IsOpen             = false;
            PrivacySuggestions.SelectedSuggestion = null;

            if (x is ChangeAvoidanceSuggestionViewModel ca)
            {
                _info.ChangelessCoins = ca.TransactionResult.SpentCoins;
                UpdateTransaction(CurrentTransactionSummary, ca.TransactionResult);

                await PrivacySuggestions.BuildPrivacySuggestionsAsync(_wallet, _info, _destination, ca.TransactionResult, _isFixedAmount, _cancellationTokenSource.Token);
            }
            else if (x is PocketSuggestionViewModel)
            {
                await OnChangePocketsAsync();
            }
        });

        PrivacySuggestions.WhenAnyValue(x => x.IsOpen)
        .Subscribe(x =>
        {
            if (!x)
            {
                DisplayedTransactionSummary = CurrentTransactionSummary;
            }
        });

        SetupCancel(enableCancel: true, enableCancelOnEscape: true, enableCancelOnPressed: false);
        EnableBack = true;

        AdjustFeeAvailable = !TransactionFeeHelper.AreTransactionFeesEqual(_wallet);

        if (PreferPsbtWorkflow)
        {
            SkipCommand = ReactiveCommand.CreateFromTask(OnConfirmAsync);

            NextCommand = ReactiveCommand.CreateFromTask(OnExportPsbtAsync);

            _nextButtonText = "Save PSBT file";
        }
        else
        {
            NextCommand = ReactiveCommand.CreateFromTask(OnConfirmAsync);

            _nextButtonText = "Confirm";
        }

        AdjustFeeCommand = ReactiveCommand.CreateFromTask(async() =>
        {
            if (_info.IsCustomFeeUsed)
            {
                await ShowAdvancedDialogAsync();
            }
            else
            {
                await OnAdjustFeeAsync();
            }
        });
    }