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); }
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"))); }
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; } }); }
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(); } }); }