public async Task <IActionResult> WalletTransactions(
            [ModelBinder(typeof(WalletIdModelBinder))]
            WalletId walletId)
        {
            var store = await _Repo.FindStore(walletId.StoreId, GetUserId());

            DerivationStrategy paymentMethod = GetPaymentMethod(walletId, store);

            if (paymentMethod == null)
            {
                return(NotFound());
            }

            var wallet       = _walletProvider.GetWallet(paymentMethod.Network);
            var transactions = await wallet.FetchTransactions(paymentMethod.DerivationStrategyBase);

            var model = new ListTransactionsViewModel();

            foreach (var tx in transactions.UnconfirmedTransactions.Transactions.Concat(transactions.ConfirmedTransactions.Transactions))
            {
                var vm = new ListTransactionsViewModel.TransactionViewModel();
                model.Transactions.Add(vm);
                vm.Id        = tx.TransactionId.ToString();
                vm.Link      = string.Format(CultureInfo.InvariantCulture, paymentMethod.Network.BlockExplorerLink, vm.Id);
                vm.Timestamp = tx.Timestamp;
                vm.Positive  = tx.BalanceChange >= Money.Zero;
                vm.Balance   = tx.BalanceChange.ToString();
            }
            model.Transactions = model.Transactions.OrderByDescending(t => t.Timestamp).ToList();
            return(View(model));
        }
        /// <summary>
        /// Checks the address for received transactions and returns highest number of confimations from all transactions.
        /// </summary>
        /// <param name="merkleRoot">The private key of the source hash</param>
        /// <returns>-1 = no Timestamps, 0 = unconfirmed tx, above 0 is the number of confimations</returns>
        public AddressTimestamp GetTimestamp(byte[] merkleRoot)
        {
            var result  = new AddressTimestamp();
            var key     = new Key(DerivationStrategy.GetKey(merkleRoot));
            var address = key.PubKey.GetAddress(Network);

            result.Address = address.Hash.ToBytes();                                                // Address without Network format

            var balance = Repository.GetReceivedAsync(address.ToString()).GetAwaiter().GetResult(); //.ToWif());

            if (balance == null || balance.Operations == null)
            {
                return(result);
            }

            var operation = balance.Operations.FirstOrDefault();

            if (operation == null)
            {
                return(result);
            }

            //var operation = operations.ToList()[0];

            result.Time          = operation.FirstSeen.ToUniversalTime().ToUnixTimeSeconds();
            result.Confirmations = operation.Confirmations;

            return(result);
        }
        public async Task <IActionResult> WalletRescan(
            [ModelBinder(typeof(WalletIdModelBinder))]
            WalletId walletId, RescanWalletModel vm)
        {
            if (walletId?.StoreId == null)
            {
                return(NotFound());
            }
            var store = await Repository.FindStore(walletId.StoreId, GetUserId());

            DerivationStrategy paymentMethod = GetPaymentMethod(walletId, store);

            if (paymentMethod == null)
            {
                return(NotFound());
            }
            var explorer = ExplorerClientProvider.GetExplorerClient(walletId.CryptoCode);

            try
            {
                await explorer.ScanUTXOSetAsync(paymentMethod.DerivationStrategyBase, vm.BatchSize, vm.GapLimit, vm.StartingIndex);
            }
            catch (NBXplorerException ex) when(ex.Error.Code == "scanutxoset-in-progress")
            {
            }
            return(RedirectToAction());
        }
        public async Task <NetworkCoins> GetCoins(DerivationStrategy strategy, KnownState state, CancellationToken cancellation = default(CancellationToken))
        {
            var client = _Client.GetExplorerClient(strategy.Network);

            if (client == null)
            {
                return new NetworkCoins()
                       {
                           TimestampedCoins = new NetworkCoins.TimestampedCoin[0], State = null, Strategy = strategy
                       }
            }
            ;
            var changes = await client.SyncAsync(strategy.DerivationStrategyBase, state?.ConfirmedHash, state?.UnconfirmedHash, true, cancellation).ConfigureAwait(false);

            return(new NetworkCoins()
            {
                TimestampedCoins = changes.Confirmed.UTXOs.Concat(changes.Unconfirmed.UTXOs).Select(c => new NetworkCoins.TimestampedCoin()
                {
                    Coin = c.AsCoin(), DateTime = c.Timestamp
                }).ToArray(),
                State = new KnownState()
                {
                    ConfirmedHash = changes.Confirmed.Hash, UnconfirmedHash = changes.Unconfirmed.Hash
                },
                Strategy = strategy,
            });
        }
        public async Task <BitcoinAddress> ReserveAddressAsync(DerivationStrategy derivationStrategy)
        {
            var client   = _Client.GetExplorerClient(derivationStrategy.Network);
            var pathInfo = await client.GetUnusedAsync(derivationStrategy.DerivationStrategyBase, DerivationFeature.Deposit, 0, true).ConfigureAwait(false);

            return(pathInfo.ScriptPubKey.GetDestinationAddress(client.Network));
        }
        public async Task <Money> GetBalance(DerivationStrategy derivationStrategy)
        {
            var client = _Client.GetExplorerClient(derivationStrategy.Network);
            var result = await client.SyncAsync(derivationStrategy.DerivationStrategyBase, null, true);

            return(result.Confirmed.UTXOs.Select(u => u.Value)
                   .Concat(result.Unconfirmed.UTXOs.Select(u => u.Value))
                   .Sum());
        }
Exemple #7
0
        public async Task <IActionResult> WalletSend(
            [ModelBinder(typeof(WalletIdModelBinder))]
            WalletId walletId, string defaultDestination = null, string defaultAmount = null)
        {
            if (walletId?.StoreId == null)
            {
                return(NotFound());
            }
            var store = await Repository.FindStore(walletId.StoreId, GetUserId());

            DerivationStrategy paymentMethod = GetPaymentMethod(walletId, store);

            if (paymentMethod == null)
            {
                return(NotFound());
            }

            var storeData = store.GetStoreBlob();
            var rateRules = store.GetStoreBlob().GetRateRules(NetworkProvider);

            rateRules.Spread = 0.0m;
            var         currencyPair = new Rating.CurrencyPair(paymentMethod.PaymentId.CryptoCode, GetCurrencyCode(storeData.DefaultLang) ?? "USD");
            WalletModel model        = new WalletModel()
            {
                DefaultAddress = defaultDestination,
                DefaultAmount  = defaultAmount,
                ServerUrl      = GetLedgerWebsocketUrl(this.HttpContext, walletId.CryptoCode, paymentMethod.DerivationStrategyBase),
                CryptoCurrency = walletId.CryptoCode
            };

            using (CancellationTokenSource cts = new CancellationTokenSource())
            {
                try
                {
                    cts.CancelAfter(TimeSpan.FromSeconds(5));
                    var result = await RateFetcher.FetchRate(currencyPair, rateRules).WithCancellation(cts.Token);

                    if (result.BidAsk != null)
                    {
                        model.Rate         = result.BidAsk.Center;
                        model.Divisibility = _currencyTable.GetNumberFormatInfo(currencyPair.Right, true).CurrencyDecimalDigits;
                        model.Fiat         = currencyPair.Right;
                    }
                    else
                    {
                        model.RateError = $"{result.EvaluatedRule} ({string.Join(", ", result.Errors.OfType<object>().ToArray())})";
                    }
                }
                catch (Exception ex) { model.RateError = ex.Message; }
            }
            return(View(model));
        }
        public async Task <IActionResult> WalletRescan(
            [ModelBinder(typeof(WalletIdModelBinder))]
            WalletId walletId)
        {
            if (walletId?.StoreId == null)
            {
                return(NotFound());
            }
            var store = await Repository.FindStore(walletId.StoreId, GetUserId());

            DerivationStrategy paymentMethod = GetPaymentMethod(walletId, store);

            if (paymentMethod == null)
            {
                return(NotFound());
            }

            var vm = new RescanWalletModel();

            vm.IsFullySync = _dashboard.IsFullySynched(walletId.CryptoCode, out var unused);
            // We need to ensure it is segwit,
            // because hardware wallet support need the parent transactions to sign, which NBXplorer don't have. (Nor does a pruned node)
            vm.IsSegwit              = paymentMethod.DerivationStrategyBase.IsSegwit();
            vm.IsServerAdmin         = User.Claims.Any(c => c.Type == Policies.CanModifyServerSettings.Key && c.Value == "true");
            vm.IsSupportedByCurrency = _dashboard.Get(walletId.CryptoCode)?.Status?.BitcoinStatus?.Capabilities?.CanScanTxoutSet == true;
            var explorer     = ExplorerClientProvider.GetExplorerClient(walletId.CryptoCode);
            var scanProgress = await explorer.GetScanUTXOSetInformationAsync(paymentMethod.DerivationStrategyBase);

            if (scanProgress != null)
            {
                vm.PreviousError = scanProgress.Error;
                if (scanProgress.Status == ScanUTXOStatus.Queued || scanProgress.Status == ScanUTXOStatus.Pending)
                {
                    if (scanProgress.Progress == null)
                    {
                        vm.Progress = 0;
                    }
                    else
                    {
                        vm.Progress      = scanProgress.Progress.OverallProgress;
                        vm.RemainingTime = TimeSpan.FromSeconds(scanProgress.Progress.RemainingSeconds).PrettyPrint();
                    }
                }
                if (scanProgress.Status == ScanUTXOStatus.Complete)
                {
                    vm.LastSuccess = scanProgress.Progress;
                    vm.TimeOfScan  = (scanProgress.Progress.CompletedAt.Value - scanProgress.Progress.StartedAt).PrettyPrint();
                }
            }
            return(View(vm));
        }
        private IActionResult ShowAddresses(DerivationSchemeViewModel vm, DerivationStrategy strategy)
        {
            vm.DerivationScheme = strategy.DerivationStrategyBase.ToString();
            if (!string.IsNullOrEmpty(vm.DerivationScheme))
            {
                var line = strategy.DerivationStrategyBase.GetLineFor(DerivationFeature.Deposit);

                for (int i = 0; i < 10; i++)
                {
                    var address = line.Derive((uint)i);
                    vm.AddressSamples.Add((DerivationStrategyBase.GetKeyPath(DerivationFeature.Deposit).Derive((uint)i).ToString(), address.ScriptPubKey.GetDestinationAddress(strategy.Network.NBitcoinNetwork).ToString()));
                }
            }
            vm.Confirmation = true;
            return(View(vm));
        }
        /// <summary>
        /// Submits transactions on the hash address.
        /// </summary>
        /// <param name="merkleRoot">The hash of the merkle root node</param>
        /// <param name="fundingKey">The server private key used for funding</param>
        /// <param name="previousTx">Output transaction from the last timestamp</param>
        /// <returns>The output transactions, can be used as input transaction for the next timestamp before confimation</returns>
        public IList <byte[]> Send(byte[] merkleRoot, byte[] fundingKey, IList <byte[]> previousTx = null)
        {
            var serverKey     = new Key(fundingKey);
            var serverAddress = serverKey.PubKey.GetAddress(ScriptPubKeyType.Legacy, Network);
            var txs           = new List <byte[]>();

            Key merkleRootKey = new Key(DerivationStrategy.GetKey(merkleRoot));

            var fee = Repository.GetEstimatedFee().FeePerK;

            var coins = GetCoins(previousTx, fee, serverAddress);

            if (EnsureFee(fee, coins) > 0)
            {
                throw new ApplicationException("Not enough coin to spend.");
            }

            IDestination targetAddress = merkleRootKey.PubKey.GetAddress(ScriptPubKeyType.Legacy, Network);

            var sourceTx = Network.CreateTransactionBuilder()
                           .AddCoins(coins)
                           .AddKeys(serverKey)
                           .Send(targetAddress, fee) // Send to Batch address
                           .SendFees(fee)
                           .SetChange(serverAddress)
                           .BuildTransaction(true);

            Repository.BroadcastAsync(sourceTx).GetAwaiter().GetResult();

            txs.Add(sourceTx.ToBytes());

            var txNota = Network.CreateTransactionBuilder()
                         .AddCoins(sourceTx.Outputs.AsCoins())
                         .SendOP_Return(merkleRoot) // Put batch root on the OP_Return out tx
                         .AddKeys(merkleRootKey)
                         .SendFees(fee)
                         .SetChange(serverAddress)
                         .BuildTransaction(true);

            Repository.BroadcastAsync(txNota).GetAwaiter().GetResult();

            txs.Add(txNota.ToBytes());

            return(txs);
        }
        public async Task <IActionResult> WalletSendLedger(
            [ModelBinder(typeof(WalletIdModelBinder))]
            WalletId walletId, WalletSendLedgerModel vm)
        {
            if (walletId?.StoreId == null)
            {
                return(NotFound());
            }
            var store = await Repository.FindStore(walletId.StoreId, GetUserId());

            DerivationStrategy paymentMethod = GetPaymentMethod(walletId, store);

            if (paymentMethod == null)
            {
                return(NotFound());
            }
            var network = this.NetworkProvider.GetNetwork(walletId?.CryptoCode);

            if (network == null)
            {
                return(NotFound());
            }
            return(View(vm));
        }
        public async Task <IActionResult> AddDerivationScheme(string storeId, DerivationSchemeViewModel vm, string cryptoCode)
        {
            vm.CryptoCode = cryptoCode;
            var store = HttpContext.GetStoreData();

            if (store == null)
            {
                return(NotFound());
            }

            var network = cryptoCode == null ? null : _ExplorerProvider.GetNetwork(cryptoCode);

            if (network == null)
            {
                return(NotFound());
            }
            vm.RootKeyPath = network.GetRootKeyPath();
            var wallet = _WalletProvider.GetWallet(network);

            if (wallet == null)
            {
                return(NotFound());
            }

            PaymentMethodId paymentMethodId = new PaymentMethodId(network.CryptoCode, PaymentTypes.BTCLike);
            var             exisingStrategy = store.GetSupportedPaymentMethods(_NetworkProvider)
                                              .Where(c => c.PaymentId == paymentMethodId)
                                              .OfType <DerivationStrategy>()
                                              .Select(c => c.DerivationStrategyBase.ToString())
                                              .FirstOrDefault();
            DerivationStrategy strategy = null;

            try
            {
                if (!string.IsNullOrEmpty(vm.DerivationScheme))
                {
                    strategy            = ParseDerivationStrategy(vm.DerivationScheme, null, network);
                    vm.DerivationScheme = strategy.ToString();
                }
            }
            catch
            {
                ModelState.AddModelError(nameof(vm.DerivationScheme), "Invalid Derivation Scheme");
                vm.Confirmation = false;
                return(View(vm));
            }
            var storeBlob      = store.GetStoreBlob();
            var wasExcluded    = storeBlob.GetExcludedPaymentMethods().Match(paymentMethodId);
            var willBeExcluded = !vm.Enabled;

            var showAddress = // Show addresses if:
                              // - If the user is testing the hint address in confirmation screen
                              (vm.Confirmation && !string.IsNullOrWhiteSpace(vm.HintAddress)) ||
                              // - The user is setting a new derivation scheme
                              (!vm.Confirmation && strategy != null && exisingStrategy != strategy.DerivationStrategyBase.ToString()) ||
                              // - The user is clicking on continue without changing anything
                              (!vm.Confirmation && willBeExcluded == wasExcluded);

            showAddress = showAddress && strategy != null;
            if (!showAddress)
            {
                try
                {
                    if (strategy != null)
                    {
                        await wallet.TrackAsync(strategy.DerivationStrategyBase);
                    }
                    store.SetSupportedPaymentMethod(paymentMethodId, strategy);
                    storeBlob.SetExcluded(paymentMethodId, willBeExcluded);
                    store.SetStoreBlob(storeBlob);
                }
                catch
                {
                    ModelState.AddModelError(nameof(vm.DerivationScheme), "Invalid Derivation Scheme");
                    return(View(vm));
                }

                await _Repo.UpdateStore(store);

                StatusMessage = $"Derivation scheme for {network.CryptoCode} has been modified.";
                return(RedirectToAction(nameof(UpdateStore), new { storeId = storeId }));
            }
            else if (!string.IsNullOrEmpty(vm.HintAddress))
            {
                BitcoinAddress address = null;
                try
                {
                    address = BitcoinAddress.Create(vm.HintAddress, network.NBitcoinNetwork);
                }
                catch
                {
                    ModelState.AddModelError(nameof(vm.HintAddress), "Invalid hint address");
                    return(ShowAddresses(vm, strategy));
                }

                try
                {
                    strategy = ParseDerivationStrategy(vm.DerivationScheme, address.ScriptPubKey, network);
                }
                catch
                {
                    ModelState.AddModelError(nameof(vm.HintAddress), "Impossible to find a match with this address");
                    return(ShowAddresses(vm, strategy));
                }
                vm.HintAddress   = "";
                vm.StatusMessage = "Address successfully found, please verify that the rest is correct and click on \"Confirm\"";
                ModelState.Remove(nameof(vm.HintAddress));
                ModelState.Remove(nameof(vm.DerivationScheme));
            }
            return(ShowAddresses(vm, strategy));
        }
        public async Task <IActionResult> WalletSend(
            [ModelBinder(typeof(WalletIdModelBinder))]
            WalletId walletId, string defaultDestination = null, string defaultAmount = null)
        {
            if (walletId?.StoreId == null)
            {
                return(NotFound());
            }
            var store = await Repository.FindStore(walletId.StoreId, GetUserId());

            DerivationStrategy paymentMethod = GetPaymentMethod(walletId, store);

            if (paymentMethod == null)
            {
                return(NotFound());
            }
            var network = this.NetworkProvider.GetNetwork(walletId?.CryptoCode);

            if (network == null)
            {
                return(NotFound());
            }
            var storeData = store.GetStoreBlob();
            var rateRules = store.GetStoreBlob().GetRateRules(NetworkProvider);

            rateRules.Spread = 0.0m;
            var             currencyPair = new Rating.CurrencyPair(paymentMethod.PaymentId.CryptoCode, GetCurrencyCode(storeData.DefaultLang) ?? "USD");
            WalletSendModel model        = new WalletSendModel()
            {
                Destination = defaultDestination,
                CryptoCode  = walletId.CryptoCode
            };

            if (double.TryParse(defaultAmount, out var amount))
            {
                model.Amount = (decimal)amount;
            }

            var feeProvider     = _feeRateProvider.CreateFeeProvider(network);
            var recommendedFees = feeProvider.GetFeeRateAsync();
            var balance         = _walletProvider.GetWallet(network).GetBalance(paymentMethod.DerivationStrategyBase);

            model.CurrentBalance            = (await balance).ToDecimal(MoneyUnit.BTC);
            model.RecommendedSatoshiPerByte = (int)(await recommendedFees).GetFee(1).Satoshi;
            model.FeeSatoshiPerByte         = model.RecommendedSatoshiPerByte;

            using (CancellationTokenSource cts = new CancellationTokenSource())
            {
                try
                {
                    cts.CancelAfter(TimeSpan.FromSeconds(5));
                    var result = await RateFetcher.FetchRate(currencyPair, rateRules).WithCancellation(cts.Token);

                    if (result.BidAsk != null)
                    {
                        model.Rate         = result.BidAsk.Center;
                        model.Divisibility = _currencyTable.GetNumberFormatInfo(currencyPair.Right, true).CurrencyDecimalDigits;
                        model.Fiat         = currencyPair.Right;
                    }
                    else
                    {
                        model.RateError = $"{result.EvaluatedRule} ({string.Join(", ", result.Errors.OfType<object>().ToArray())})";
                    }
                }
                catch (Exception ex) { model.RateError = ex.Message; }
            }
            return(View(model));
        }
Exemple #14
0
        public async Task <IActionResult> AddDerivationScheme(string storeId, DerivationSchemeViewModel vm, string cryptoCode)
        {
            vm.ServerUrl  = GetStoreUrl(storeId);
            vm.CryptoCode = cryptoCode;
            var store = HttpContext.GetStoreData();

            if (store == null)
            {
                return(NotFound());
            }

            var network = cryptoCode == null ? null : _ExplorerProvider.GetNetwork(cryptoCode);

            if (network == null)
            {
                return(NotFound());
            }
            vm.RootKeyPath = network.GetRootKeyPath();
            var wallet = _WalletProvider.GetWallet(network);

            if (wallet == null)
            {
                return(NotFound());
            }

            PaymentMethodId    paymentMethodId = new PaymentMethodId(network.CryptoCode, PaymentTypes.BTCLike);
            DerivationStrategy strategy        = null;

            try
            {
                if (!string.IsNullOrEmpty(vm.DerivationScheme))
                {
                    strategy            = ParseDerivationStrategy(vm.DerivationScheme, null, network);
                    vm.DerivationScheme = strategy.ToString();
                }
            }
            catch
            {
                ModelState.AddModelError(nameof(vm.DerivationScheme), "Invalid Derivation Scheme");
                vm.Confirmation = false;
                return(View(vm));
            }

            if (!vm.Confirmation && strategy != null)
            {
                return(ShowAddresses(vm, strategy));
            }

            if (vm.Confirmation && !string.IsNullOrWhiteSpace(vm.HintAddress))
            {
                BitcoinAddress address = null;
                try
                {
                    address = BitcoinAddress.Create(vm.HintAddress, network.NBitcoinNetwork);
                }
                catch
                {
                    ModelState.AddModelError(nameof(vm.HintAddress), "Invalid hint address");
                    return(ShowAddresses(vm, strategy));
                }

                try
                {
                    strategy = ParseDerivationStrategy(vm.DerivationScheme, address.ScriptPubKey, network);
                }
                catch
                {
                    ModelState.AddModelError(nameof(vm.HintAddress), "Impossible to find a match with this address");
                    return(ShowAddresses(vm, strategy));
                }
                vm.HintAddress   = "";
                vm.StatusMessage = "Address successfully found, please verify that the rest is correct and click on \"Confirm\"";
                ModelState.Remove(nameof(vm.HintAddress));
                ModelState.Remove(nameof(vm.DerivationScheme));
                return(ShowAddresses(vm, strategy));
            }
            else
            {
                try
                {
                    if (strategy != null)
                    {
                        await wallet.TrackAsync(strategy.DerivationStrategyBase);
                    }
                    store.SetSupportedPaymentMethod(paymentMethodId, strategy);
                }
                catch
                {
                    ModelState.AddModelError(nameof(vm.DerivationScheme), "Invalid Derivation Scheme");
                    return(View(vm));
                }

                await _Repo.UpdateStore(store);

                StatusMessage = $"Derivation scheme for {network.CryptoCode} has been modified.";
                return(RedirectToAction(nameof(UpdateStore), new { storeId = storeId }));
            }
        }
Exemple #15
0
 public async Task TrackAsync(DerivationStrategy derivationStrategy)
 {
     var client = _Client.GetExplorerClient(derivationStrategy.Network);
     await client.TrackAsync(derivationStrategy.DerivationStrategyBase);
 }
        public async Task <IActionResult> AddDerivationScheme(string storeId, DerivationSchemeViewModel vm)
        {
            vm.ServerUrl = GetStoreUrl(storeId);
            var store = await _Repo.FindStore(storeId, GetUserId());

            if (store == null)
            {
                return(NotFound());
            }

            var network = vm.CryptoCurrency == null ? null : _ExplorerProvider.GetNetwork(vm.CryptoCurrency);

            vm.SetCryptoCurrencies(_ExplorerProvider, vm.CryptoCurrency);
            if (network == null)
            {
                ModelState.AddModelError(nameof(vm.CryptoCurrency), "Invalid network");
                return(View(vm));
            }
            var wallet = _WalletProvider.GetWallet(network);

            if (wallet == null)
            {
                ModelState.AddModelError(nameof(vm.CryptoCurrency), "Invalid network");
                return(View(vm));
            }

            PaymentMethodId    paymentMethodId = new PaymentMethodId(network.CryptoCode, PaymentTypes.BTCLike);
            DerivationStrategy strategy        = null;

            try
            {
                if (!string.IsNullOrEmpty(vm.DerivationScheme))
                {
                    strategy            = ParseDerivationStrategy(vm.DerivationScheme, vm.DerivationSchemeFormat, network);
                    vm.DerivationScheme = strategy.ToString();
                }
                store.SetSupportedPaymentMethod(paymentMethodId, strategy);
            }
            catch
            {
                ModelState.AddModelError(nameof(vm.DerivationScheme), "Invalid Derivation Scheme");
                vm.Confirmation = false;
                return(View(vm));
            }


            if (vm.Confirmation)
            {
                try
                {
                    if (strategy != null)
                    {
                        await wallet.TrackAsync(strategy.DerivationStrategyBase);
                    }
                    store.SetSupportedPaymentMethod(paymentMethodId, strategy);
                }
                catch
                {
                    ModelState.AddModelError(nameof(vm.DerivationScheme), "Invalid Derivation Scheme");
                    return(View(vm));
                }

                await _Repo.UpdateStore(store);

                StatusMessage = $"Derivation scheme for {network.CryptoCode} has been modified.";
                return(RedirectToAction(nameof(UpdateStore), new { storeId = storeId }));
            }
            else
            {
                if (!string.IsNullOrEmpty(vm.DerivationScheme))
                {
                    var line = strategy.DerivationStrategyBase.GetLineFor(DerivationFeature.Deposit);

                    for (int i = 0; i < 10; i++)
                    {
                        var address = line.Derive((uint)i);
                        vm.AddressSamples.Add((DerivationStrategyBase.GetKeyPath(DerivationFeature.Deposit).Derive((uint)i).ToString(), address.ScriptPubKey.GetDestinationAddress(network.NBitcoinNetwork).ToString()));
                    }
                }
                vm.Confirmation = true;
                return(View(vm));
            }
        }