Пример #1
0
        private async Task OnNext(TransactionBroadcaster broadcaster)
        {
            var transactionInfo       = _transactionInfo;
            var wallet                = _owner.Wallet;
            var targetAnonymitySet    = wallet.ServiceConfiguration.GetMixUntilAnonymitySetValue();
            var mixedCoins            = wallet.Coins.Where(x => x.HdPubKey.AnonymitySet >= targetAnonymitySet).ToList();
            var totalMixedCoinsAmount = Money.FromUnit(mixedCoins.Sum(coin => coin.Amount), MoneyUnit.Satoshi);

            if (transactionInfo.Amount <= totalMixedCoinsAmount)
            {
                try
                {
                    try
                    {
                        var txRes = await Task.Run(() => TransactionHelpers.BuildTransaction(wallet, transactionInfo.Address, transactionInfo.Amount, transactionInfo.Labels, transactionInfo.FeeRate, mixedCoins, subtractFee: false));

                        Navigate().To(new OptimisePrivacyViewModel(wallet, transactionInfo, broadcaster, txRes));
                        return;
                    }
                    catch (InsufficientBalanceException)
                    {
                        var txRes = await Task.Run(() => TransactionHelpers.BuildTransaction(wallet, transactionInfo.Address, totalMixedCoinsAmount, transactionInfo.Labels, transactionInfo.FeeRate, mixedCoins, subtractFee: true));

                        var dialog = new InsufficientBalanceDialogViewModel(BalanceType.Private, txRes, wallet.Synchronizer.UsdExchangeRate);
                        var result = await NavigateDialog(dialog, NavigationTarget.DialogScreen);

                        if (result.Result)
                        {
                            Navigate().To(new OptimisePrivacyViewModel(wallet, transactionInfo, broadcaster, txRes));
                            return;
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.LogError(ex);
                    await ShowErrorAsync("Transaction Building", ex.ToUserFriendlyString(), "Wasabi was unable to create your transaction.");

                    return;
                }
            }

            Navigate().To(new PrivacyControlViewModel(wallet, transactionInfo, broadcaster));
        }
Пример #2
0
        private async Task OnNext(Wallet wallet, TransactionInfo transactionInfo, TransactionBroadcaster broadcaster, IObservableList <PocketViewModel> selectedList)
        {
            var coins = selectedList.Items.SelectMany(x => x.Coins).ToArray();

            try
            {
                try
                {
                    var transactionResult = await Task.Run(() => TransactionHelpers.BuildTransaction(_wallet, transactionInfo.Address, transactionInfo.Amount, transactionInfo.Labels, transactionInfo.FeeRate, coins, subtractFee: false));

                    Navigate().To(new OptimisePrivacyViewModel(wallet, transactionInfo, broadcaster, transactionResult));
                }
                catch (InsufficientBalanceException)
                {
                    var transactionResult = await Task.Run(() => TransactionHelpers.BuildTransaction(_wallet, transactionInfo.Address, transactionInfo.Amount, transactionInfo.Labels, transactionInfo.FeeRate, coins, subtractFee: true));

                    var dialog = new InsufficientBalanceDialogViewModel(BalanceType.Pocket, transactionResult, wallet.Synchronizer.UsdExchangeRate);
                    var result = await NavigateDialog(dialog, NavigationTarget.DialogScreen);

                    if (result.Result)
                    {
                        Navigate().To(new OptimisePrivacyViewModel(wallet, transactionInfo, broadcaster, transactionResult));
                    }
                    else
                    {
                        Navigate().BackTo <SendViewModel>();
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.LogError(ex);
                await ShowErrorAsync("Transaction Building", ex.ToUserFriendlyString(), "Wasabi was unable to create your transaction.");

                Navigate().BackTo <SendViewModel>();
            }
        }
Пример #3
0
        public SendViewModel(WalletViewModel walletVm, TransactionBroadcaster broadcaster) : base(NavigationMode.Normal)
        {
            _to                    = "";
            _owner                 = walletVm;
            _transactionInfo       = new TransactionInfo();
            _labels                = new ObservableCollection <string>();
            _lastXAxisCurrentValue = _xAxisCurrentValue;

            ExchangeRate = walletVm.Wallet.Synchronizer.UsdExchangeRate;
            PriorLabels  = new();

            this.ValidateProperty(x => x.To, ValidateToField);
            this.ValidateProperty(x => x.AmountBtc, ValidateAmount);

            this.WhenAnyValue(x => x.To)
            .Subscribe(ParseToField);

            this.WhenAnyValue(x => x.AmountBtc)
            .Subscribe(x => _transactionInfo.Amount = new Money(x, MoneyUnit.BTC));

            this.WhenAnyValue(x => x.XAxisCurrentValue)
            .Subscribe(x =>
            {
                if (x > 0)
                {
                    _transactionInfo.FeeRate = new FeeRate(GetYAxisValueFromXAxisCurrentValue(x));
                    SetXAxisCurrentValueIndex(x);
                }
            });

            this.WhenAnyValue(x => x.XAxisCurrentValueIndex)
            .Subscribe(SetXAxisCurrentValue);

            Labels.ToObservableChangeSet().Subscribe(x =>
            {
                _transactionInfo.Labels = new SmartLabel(_labels.ToArray());
            });

            PasteCommand = ReactiveCommand.CreateFromTask(async() =>
            {
                var text = await Application.Current.Clipboard.GetTextAsync();

                _parsingUrl = true;

                if (!TryParseUrl(text))
                {
                    To = text;
                    // todo validation errors.
                }

                _parsingUrl = false;
            });

            var nextCommandCanExecute =
                this.WhenAnyValue(x => x.Labels, x => x.AmountBtc, x => x.To, x => x.XAxisCurrentValue).Select(_ => Unit.Default)
                .Merge(Observable.FromEventPattern(Labels, nameof(Labels.CollectionChanged)).Select(_ => Unit.Default))
                .Select(_ =>
            {
                var allFilled = !string.IsNullOrEmpty(To) && AmountBtc > 0 && Labels.Any();
                var hasError  = Validations.Any;

                return(allFilled && !hasError);
            });

            NextCommand = ReactiveCommand.CreateFromTask(async() =>
            {
                var transactionInfo       = _transactionInfo;
                var wallet                = _owner.Wallet;
                var targetAnonymitySet    = wallet.ServiceConfiguration.GetMixUntilAnonymitySetValue();
                var mixedCoins            = wallet.Coins.Where(x => x.HdPubKey.AnonymitySet >= targetAnonymitySet).ToList();
                var totalMixedCoinsAmount = Money.FromUnit(mixedCoins.Sum(coin => coin.Amount), MoneyUnit.Satoshi);


                if (transactionInfo.Amount <= totalMixedCoinsAmount)
                {
                    try
                    {
                        try
                        {
                            var txRes = await Task.Run(() => TransactionHelpers.BuildTransaction(wallet, transactionInfo.Address, transactionInfo.Amount, transactionInfo.Labels, transactionInfo.FeeRate, mixedCoins, subtractFee: false));
                            Navigate().To(new OptimisePrivacyViewModel(wallet, transactionInfo, broadcaster, txRes));
                            return;
                        }
                        catch (InsufficientBalanceException)
                        {
                            var dialog = new InsufficientBalanceDialogViewModel(BalanceType.Private);
                            var result = await NavigateDialog(dialog, NavigationTarget.DialogScreen);

                            if (result.Result)
                            {
                                var txRes = await Task.Run(() => TransactionHelpers.BuildTransaction(wallet, transactionInfo.Address, totalMixedCoinsAmount, transactionInfo.Labels, transactionInfo.FeeRate, mixedCoins, subtractFee: true));
                                Navigate().To(new OptimisePrivacyViewModel(wallet, transactionInfo, broadcaster, txRes));
                                return;
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Logger.LogError(ex);
                        await ShowErrorAsync("Transaction Building", ex.ToUserFriendlyString(), "Wasabi was unable to create your transaction.");
                        return;
                    }
                }

                Navigate().To(new PrivacyControlViewModel(wallet, transactionInfo, broadcaster));
            }, nextCommandCanExecute);

            EnableAutoBusyOn(NextCommand);
        }
Пример #4
0
        public PrivacyControlViewModel(Wallet wallet, TransactionInfo transactionInfo, TransactionBroadcaster broadcaster)
        {
            _wallet = wallet;

            _pocketSource = new SourceList <PocketViewModel>();

            _pocketSource.Connect()
            .Bind(out _pockets)
            .Subscribe();

            var selected = _pocketSource.Connect()
                           .AutoRefresh()
                           .Filter(x => x.IsSelected);

            var selectedList = selected.AsObservableList();

            selected.Sum(x => x.TotalBtc)
            .Subscribe(x =>
            {
                StillNeeded    = transactionInfo.Amount.ToDecimal(MoneyUnit.BTC) - x;
                EnoughSelected = StillNeeded <= 0;
            });

            StillNeeded = transactionInfo.Amount.ToDecimal(MoneyUnit.BTC);

            NextCommand = ReactiveCommand.CreateFromTask(
                async() =>
            {
                var coins = selectedList.Items.SelectMany(x => x.Coins).ToArray();

                try
                {
                    try
                    {
                        var transactionResult = await Task.Run(() => TransactionHelpers.BuildTransaction(_wallet, transactionInfo.Address, transactionInfo.Amount, transactionInfo.Labels, transactionInfo.FeeRate, coins, subtractFee: false));
                        Navigate().To(new TransactionPreviewViewModel(wallet, transactionInfo, broadcaster, transactionResult));
                    }
                    catch (InsufficientBalanceException)
                    {
                        var dialog = new InsufficientBalanceDialogViewModel(BalanceType.Pocket);
                        var result = await NavigateDialog(dialog, NavigationTarget.DialogScreen);

                        if (result.Result)
                        {
                            var transactionResult = await Task.Run(() => TransactionHelpers.BuildTransaction(_wallet, transactionInfo.Address, transactionInfo.Amount, transactionInfo.Labels, transactionInfo.FeeRate, coins, subtractFee: true));
                            Navigate().To(new TransactionPreviewViewModel(wallet, transactionInfo, broadcaster, transactionResult));
                        }
                        else
                        {
                            Navigate().BackTo <SendViewModel>();
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.LogError(ex);
                    await ShowErrorAsync("Transaction Building", ex.ToUserFriendlyString(), "Wasabi was unable to create your transaction.");
                    Navigate().BackTo <SendViewModel>();
                }
            },
                this.WhenAnyValue(x => x.EnoughSelected));

            EnableAutoBusyOn(NextCommand);
        }