public IActionResult GetBalance()
        {
            try
            {
                FederationWallet wallet = this.walletManager.GetWallet();
                if (wallet == null)
                {
                    return(this.NotFound("No federation wallet found."));
                }

                (Money ConfirmedAmount, Money UnConfirmedAmount)result = this.walletManager.GetSpendableAmount();

                var balance = new AccountBalanceModel
                {
                    CoinType          = this.coinType,
                    AmountConfirmed   = result.ConfirmedAmount,
                    AmountUnconfirmed = result.UnConfirmedAmount,
                };

                var model = new WalletBalanceModel();
                model.AccountsBalances.Add(balance);

                return(this.Json(model));
            }
            catch (Exception e)
            {
                this.logger.LogError("Exception occurred: {0}", e.ToString());
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString()));
            }
        }
        // GET: Client/WalletBalance
        public ActionResult balanceTransfer()
        {
            WalletBalanceModel          walletBalance = new WalletBalanceModel();
            Dictionary <string, string> PurposeList   = _walletUser.GetProposeList();

            walletBalance.PurposeList = ApplicationUtilities.SetDDLValue(PurposeList, "", "--Propose--");
            return(View(walletBalance));
        }
        public ActionResult balanceTransfer(WalletBalanceModel walletBalance)
        {
            Dictionary <string, string> PurposeList = _walletUser.GetProposeList();

            walletBalance.PurposeList = ApplicationUtilities.SetDDLValue(PurposeList, "", "--Propose--");

            if ((Convert.ToDecimal(walletBalance.Amount) > 1000 || Convert.ToDecimal(walletBalance.Amount) < 10) && walletBalance.Type == "T")
            {
                ModelState.AddModelError("Amount", "Amount should be between 10-1000");
                return(View(walletBalance));
            }

            if (walletBalance.Type == "R")
            {
                ModelState.Remove(("Propose"));
                if ((Convert.ToDecimal(walletBalance.Amount) > 1000 || Convert.ToDecimal(walletBalance.Amount) < 10))
                {
                    ModelState.AddModelError("Amount", "Amount should be between 10-1000");
                    return(View(walletBalance));
                }
            }
            string           usertype = Session["UserType"].ToString();
            string           agentid  = Session["AgentId"].ToString();
            CommonDbResponse response = _walletUser.CheckMobileNumber(agentid, walletBalance.ReceiverAgentId, usertype, "tb");

            if (response.Code != 0)
            {
                ModelState.AddModelError("ReceiverAgentId", "Invalid User Detail");
                return(View(walletBalance));
            }
            else
            {
                ModelState.Remove("ReceiverAgentId");
            }
            if (ModelState.IsValid)
            {
                //walletBalance.AgentId = Session["AgentId"].ToString();
                walletBalance.ActionUser = Session["UserName"].ToString();
                walletBalance.IpAddress  = ApplicationUtilities.GetIP();
                WalletBalanceCommon walletBalanceCommon = walletBalance.MapObject <WalletBalanceCommon>();
                CommonDbResponse    dbResponse          = _walletUser.WalletBalanceRT(walletBalanceCommon);
                if (dbResponse.Code == 0)
                {
                    dbResponse.SetMessageInTempData(this, "balanceTransfer");
                    return(RedirectToAction("balanceTransfer", ControllerName));
                }
                dbResponse.SetMessageInTempData(this, "balanceTransfer");
                return(RedirectToAction("balanceTransfer"));
            }
            else
            {
                return(View(walletBalance));
            }

            return(RedirectToAction("balanceTransfer"));
        }
Esempio n. 4
0
        public void GetBalance()
        {
            this.fedWallet.MultiSigAddress = new MultiSigAddress();

            IActionResult      result = this.controller.GetBalance();
            WalletBalanceModel model  = this.ActionResultToModel <WalletBalanceModel>(result);

            Assert.Single(model.AccountsBalances);
            Assert.Equal(CoinType.Stratis, model.AccountsBalances.First().CoinType);
            Assert.Equal(0, model.AccountsBalances.First().AmountConfirmed.Satoshi);
        }
        public IActionResult GetBalance([FromQuery] WalletBalanceRequest request)
        {
            // checks the request is valid
            if (!this.ModelState.IsValid)
            {
                var errors = this.ModelState.Values.SelectMany(e => e.Errors.Select(m => m.ErrorMessage));
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, "Formatting error", string.Join(Environment.NewLine, errors)));
            }

            try
            {
                WalletBalanceModel model = new WalletBalanceModel {
                    AccountsBalances = new List <AccountBalance>()
                };

                var accounts = this.walletManager.GetAccountsByCoinType(request.WalletName, this.coinType).ToList();
                foreach (var account in accounts)
                {
                    var allTransactions = account.ExternalAddresses.SelectMany(a => a.Transactions)
                                          .Concat(account.InternalAddresses.SelectMany(i => i.Transactions)).ToList();

                    AccountBalance balance = new AccountBalance
                    {
                        CoinType          = this.coinType,
                        Name              = account.Name,
                        HdPath            = account.HdPath,
                        AmountConfirmed   = allTransactions.Sum(t => t.SpendableAmount(true)),
                        AmountUnconfirmed = allTransactions.Sum(t => t.SpendableAmount(false)),
                    };

                    model.AccountsBalances.Add(balance);
                }

                return(this.Json(model));
            }
            catch (Exception e)
            {
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString()));
            }
        }
        public IActionResult GetBalance([FromQuery] WalletBalanceRequest request)
        {
            Guard.NotNull(request, nameof(request));

            // checks the request is valid
            if (!this.ModelState.IsValid)
            {
                var errors = this.ModelState.Values.SelectMany(e => e.Errors.Select(m => m.ErrorMessage));
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, "Formatting error", string.Join(Environment.NewLine, errors)));
            }

            try
            {
                WalletBalanceModel model = new WalletBalanceModel();

                var accounts = this.walletManager.GetAccounts(request.WalletName).ToList();
                foreach (var account in accounts)
                {
                    var result = account.GetSpendableAmount();

                    AccountBalance balance = new AccountBalance
                    {
                        CoinType          = this.coinType,
                        Name              = account.Name,
                        HdPath            = account.HdPath,
                        AmountConfirmed   = result.ConfirmedAmount,
                        AmountUnconfirmed = result.UnConfirmedAmount,
                    };

                    model.AccountsBalances.Add(balance);
                }

                return(this.Json(model));
            }
            catch (Exception e)
            {
                this.logger.LogError("Exception occurred: {0}", e.ToString());
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString()));
            }
        }
        public async Task GetHistoryFromMiningNode()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                // Arrange.
                // Create a mining node.
                CoreNode miningNode = builder.CreateStratisPosNode(this.network).WithWallet().Start();

                TestHelper.MineBlocks(miningNode, 5);

                // Check balances.
                WalletBalanceModel sendingNodeBalances = await $"http://localhost:{miningNode.ApiPort}/api"
                                                         .AppendPathSegment("wallet/balance")
                                                         .SetQueryParams(new { walletName = "mywallet" })
                                                         .GetJsonAsync <WalletBalanceModel>();

                AccountBalanceModel sendingAccountBalance = sendingNodeBalances.AccountsBalances.Single();
                (sendingAccountBalance.AmountConfirmed + sendingAccountBalance.AmountUnconfirmed).Should().Be(new Money(98000000 + (4 * 4), MoneyUnit.BTC));

                // Act.
                WalletHistoryModel firstAccountHistory = await $"http://localhost:{miningNode.ApiPort}/api"
                                                         .AppendPathSegment("wallet/history")
                                                         .SetQueryParams(new { walletName = "mywallet", accountName = "account 0" })
                                                         .GetJsonAsync <WalletHistoryModel>();

                // Assert.
                firstAccountHistory.AccountsHistoryModel.Should().NotBeEmpty();

                ICollection <TransactionItemModel> history = firstAccountHistory.AccountsHistoryModel.First().TransactionsHistory;
                history.Should().NotBeEmpty();
                history.Count.Should().Be(5);

                TransactionItemModel firstItem = history.First(); // First item in the list but last item to have occurred.
                firstItem.Amount.Should().Be(new Money(4, MoneyUnit.BTC));
                firstItem.BlockIndex.Should().Be(0);
                firstItem.ConfirmedInBlock.Should().Be(5);
                firstItem.ToAddress.Should().NotBeNullOrEmpty();
                firstItem.Fee.Should().BeNull();
            }
        }
        public async Task GetBalancesAsync()
        {
            int sendingAccountBalanceOnStart   = 98000596;
            int receivingAccountBalanceOnStart = 0;

            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                // Arrange.
                // Create a sending and a receiving node.
                CoreNode node1 = builder.CreateStratisPosNode(this.network).WithReadyBlockchainData(ReadyBlockchain.StratisRegTest10Miner).Start();

                // Act.
                WalletBalanceModel node1Balances = await $"http://localhost:{node1.ApiPort}/api"
                                                   .AppendPathSegment("wallet/balance")
                                                   .SetQueryParams(new { walletName = "mywallet" })
                                                   .GetJsonAsync <WalletBalanceModel>();

                // Assert.
                AccountBalanceModel node1Balance = node1Balances.AccountsBalances.Single();
                node1Balance.AmountConfirmed.Should().Be(new Money(98000036, MoneyUnit.BTC)); // premine is 98M + 9 blocks * 4.
                node1Balance.AmountUnconfirmed.Should().Be(Money.Zero);
                node1Balance.SpendableAmount.Should().Be(Money.Zero);                         // Maturity for StratisregTest is 10, so at block 10, no coin is spendable.

                // Arrange.
                // Create a sending and a receiving node.
                CoreNode node2 = builder.CreateStratisPosNode(this.network).WithReadyBlockchainData(ReadyBlockchain.StratisRegTest100Miner).Start();

                // Act.
                WalletBalanceModel node2Balances = await $"http://localhost:{node2.ApiPort}/api"
                                                   .AppendPathSegment("wallet/balance")
                                                   .SetQueryParams(new { walletName = "mywallet" })
                                                   .GetJsonAsync <WalletBalanceModel>();

                // Assert.
                AccountBalanceModel node2Balance = node2Balances.AccountsBalances.Single();
                node2Balance.AmountConfirmed.Should().Be(new Money(98000396, MoneyUnit.BTC));      // premine is 98M + 99 blocks * 4.
                node2Balance.AmountUnconfirmed.Should().Be(Money.Zero);
                node2Balance.SpendableAmount.Should().Be(new Money(98000396 - 40, MoneyUnit.BTC)); // Maturity for StratisregTest is 10, so at block 100, the coins in the last 10 blocks (10*4) are not spendable.
            }
        }
Esempio n. 9
0
        /// <summary>
        /// Gets the balance of a wallet.
        /// </summary>
        /// <param name="request">The request parameters.</param>
        /// <returns></returns>
        public WalletBalanceModel GetBalance(WalletBalanceRequest request)
        {
            Guard.NotNull(request, nameof(request));

            // checks the request is valid
            //if (!this.ModelState.IsValid)
            //{
            //    return BuildErrorResponse(this.ModelState);
            //}

            try
            {
                WalletBalanceModel model = new WalletBalanceModel();

                IEnumerable <AccountBalance> balances = this.walletManager.GetBalances(request.WalletName, request.AccountName);

                foreach (AccountBalance balance in balances)
                {
                    HdAccount account = balance.Account;
                    model.AccountsBalances.Add(new AccountBalanceModel
                    {
                        CoinType          = this.coinType,
                        Name              = account.Name,
                        HdPath            = account.HdPath,
                        AmountConfirmed   = balance.AmountConfirmed,
                        AmountUnconfirmed = balance.AmountUnconfirmed
                    });
                }

                return(model);
            }
            catch (Exception e)
            {
                this.logger.LogError("Exception occurred: {0}", e.ToString());
                //return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
                throw;
            }
        }
        public async Task SendingATransactionWithAnOpReturn()
        {
            int sendingAccountBalanceOnStart   = 98000596;
            int receivingAccountBalanceOnStart = 0;

            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                // Arrange.
                // Create a sending and a receiving node.
                CoreNode sendingNode   = builder.CreateStratisPosNode(this.network).WithReadyBlockchainData(ReadyBlockchain.StratisRegTest150Miner).Start();
                CoreNode receivingNode = builder.CreateStratisPosNode(this.network).WithReadyBlockchainData(ReadyBlockchain.StratisRegTest150Listener).Start();
                TestHelper.ConnectAndSync(sendingNode, receivingNode);

                // Check balances.
                WalletBalanceModel sendingNodeBalances = await $"http://localhost:{sendingNode.ApiPort}/api"
                                                         .AppendPathSegment("wallet/balance")
                                                         .SetQueryParams(new { walletName = "mywallet" })
                                                         .GetJsonAsync <WalletBalanceModel>();

                AccountBalanceModel sendingAccountBalance = sendingNodeBalances.AccountsBalances.Single();
                (sendingAccountBalance.AmountConfirmed + sendingAccountBalance.AmountUnconfirmed).Should().Be(new Money(sendingAccountBalanceOnStart, MoneyUnit.BTC));

                WalletBalanceModel receivingNodeBalances = await $"http://localhost:{receivingNode.ApiPort}/api"
                                                           .AppendPathSegment("wallet/balance")
                                                           .SetQueryParams(new { walletName = "mywallet" })
                                                           .GetJsonAsync <WalletBalanceModel>();

                AccountBalanceModel receivingAccountBalance = receivingNodeBalances.AccountsBalances.Single();
                (receivingAccountBalance.AmountConfirmed + receivingAccountBalance.AmountUnconfirmed).Should().Be(new Money(receivingAccountBalanceOnStart));

                // Act.
                // Get an address to send to.
                IEnumerable <string> unusedaddresses = await $"http://localhost:{receivingNode.ApiPort}/api"
                                                       .AppendPathSegment("wallet/unusedAddresses")
                                                       .SetQueryParams(new { walletName = "mywallet", accountName = "account 0", count = 1 })
                                                       .GetJsonAsync <IEnumerable <string> >();

                // Build and send the transaction with an Op_Return.
                WalletBuildTransactionModel buildTransactionModel = await $"http://localhost:{sendingNode.ApiPort}/api"
                                                                    .AppendPathSegment("wallet/build-transaction")
                                                                    .PostJsonAsync(new BuildTransactionRequest
                {
                    WalletName       = "mywallet",
                    AccountName      = "account 0",
                    FeeType          = "low",
                    Password         = "******",
                    ShuffleOutputs   = true,
                    AllowUnconfirmed = true,
                    Recipients       = unusedaddresses.Select(address => new RecipientModel
                    {
                        DestinationAddress = address,
                        Amount             = "1"
                    }).ToList(),
                    OpReturnData   = "some data to send",
                    OpReturnAmount = "1"
                })
                                                                    .ReceiveJson <WalletBuildTransactionModel>();

                await $"http://localhost:{sendingNode.ApiPort}/api"
                .AppendPathSegment("wallet/send-transaction")
                .PostJsonAsync(new SendTransactionRequest
                {
                    Hex = buildTransactionModel.Hex
                })
                .ReceiveJson <WalletSendTransactionModel>();

                // Assert.
                // Mine and sync so that we make sure the receiving node is up to date.
                TestHelper.MineBlocks(sendingNode, 1);
                TestHelper.WaitForNodeToSync(sendingNode, receivingNode);

                // The receiving node should have coins.
                receivingNodeBalances = await $"http://localhost:{receivingNode.ApiPort}/api"
                                        .AppendPathSegment("wallet/balance")
                                        .SetQueryParams(new { walletName = "mywallet" })
                                        .GetJsonAsync <WalletBalanceModel>();

                receivingAccountBalance = receivingNodeBalances.AccountsBalances.Single();
                (receivingAccountBalance.AmountConfirmed).Should().Be(new Money(receivingAccountBalanceOnStart + 1, MoneyUnit.BTC));

                // The sending node should have fewer coins.
                sendingNodeBalances = await $"http://localhost:{sendingNode.ApiPort}/api"
                                      .AppendPathSegment("wallet/balance")
                                      .SetQueryParams(new { walletName = "mywallet" })
                                      .GetJsonAsync <WalletBalanceModel>();

                sendingAccountBalance = sendingNodeBalances.AccountsBalances.Single();
                (sendingAccountBalance.AmountConfirmed).Should().Be(new Money(sendingAccountBalanceOnStart + 4 - 2, MoneyUnit.BTC));

                // Check the transaction.
                string lastBlockHash = await $"http://localhost:{receivingNode.ApiPort}/api"
                                       .AppendPathSegment("consensus/getbestblockhash")
                                       .GetJsonAsync <string>();

                BlockTransactionDetailsModel block = await $"http://localhost:{receivingNode.ApiPort}/api"
                                                     .AppendPathSegment("blockstore/block")
                                                     .SetQueryParams(new { hash = lastBlockHash, showTransactionDetails = true, outputJson = true })
                                                     .GetJsonAsync <BlockTransactionDetailsModel>();

                TransactionVerboseModel trx = block.Transactions.SingleOrDefault(t => t.TxId == buildTransactionModel.TransactionId.ToString());
                trx.Should().NotBeNull();

                Vout opReturnOutputFromBlock = trx.VOut.Single(t => t.ScriptPubKey.Type == "nulldata");
                opReturnOutputFromBlock.Value.Should().Be(1);
                var      script = opReturnOutputFromBlock.ScriptPubKey.Asm;
                string[] ops    = script.Split(" ");
                ops[0].Should().Be("OP_RETURN");
                Encoders.Hex.DecodeData(ops[1]).Should().BeEquivalentTo(System.Text.Encoding.UTF8.GetBytes("some data to send"));
            }
        }
        public async Task SendingFromManyAddressesToOneAddress()
        {
            int sendingAccountBalanceOnStart   = 98000596;
            int receivingAccountBalanceOnStart = 0;

            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                // Arrange.
                // Create a sending and a receiving node.
                CoreNode sendingNode   = builder.CreateStratisPosNode(this.network).WithWallet().Start();
                CoreNode receivingNode = builder.CreateStratisPosNode(this.network).WithWallet().Start();

                // Mine a few blocks to fund the sending node and connect the nodes.
                IEnumerable <string> addressesToFund = await $"http://localhost:{sendingNode.ApiPort}/api"
                                                       .AppendPathSegment("wallet/unusedAddresses")
                                                       .SetQueryParams(new { walletName = "mywallet", accountName = "account 0", count = 150 })
                                                       .GetJsonAsync <IEnumerable <string> >();

                foreach (string address in addressesToFund)
                {
                    TestHelper.MineBlocks(sendingNode, 1, syncNode: false, miningAddress: address);
                }

                TestHelper.ConnectAndSync(sendingNode, receivingNode);

                // Check balances.
                WalletBalanceModel sendingNodeBalances = await $"http://localhost:{sendingNode.ApiPort}/api"
                                                         .AppendPathSegment("wallet/balance")
                                                         .SetQueryParams(new { walletName = "mywallet" })
                                                         .GetJsonAsync <WalletBalanceModel>();

                AccountBalanceModel sendingAccountBalance = sendingNodeBalances.AccountsBalances.Single();
                (sendingAccountBalance.AmountConfirmed + sendingAccountBalance.AmountUnconfirmed).Should().Be(new Money(sendingAccountBalanceOnStart, MoneyUnit.BTC));

                WalletBalanceModel receivingNodeBalances = await $"http://localhost:{receivingNode.ApiPort}/api"
                                                           .AppendPathSegment("wallet/balance")
                                                           .SetQueryParams(new { walletName = "mywallet" })
                                                           .GetJsonAsync <WalletBalanceModel>();

                AccountBalanceModel receivingAccountBalance = receivingNodeBalances.AccountsBalances.Single();
                (receivingAccountBalance.AmountConfirmed + receivingAccountBalance.AmountUnconfirmed).Should().Be(new Money(receivingAccountBalanceOnStart));

                // Check max spendable amount.
                var maxBalanceResponse = await $"http://localhost:{sendingNode.ApiPort}/api"
                                         .AppendPathSegment("wallet/maxbalance")
                                         .SetQueryParams(new { walletName = "mywallet", accountName = "account 0", feetype = "low", allowunconfirmed = true })
                                         .GetJsonAsync <MaxSpendableAmountModel>();

                Money totalToSpend = maxBalanceResponse.MaxSpendableAmount + maxBalanceResponse.Fee;

                // Act.
                // Get an address to send to.
                IEnumerable <string> unusedaddresses = await $"http://localhost:{receivingNode.ApiPort}/api"
                                                       .AppendPathSegment("wallet/unusedAddresses")
                                                       .SetQueryParams(new { walletName = "mywallet", accountName = "account 0", count = 1 })
                                                       .GetJsonAsync <IEnumerable <string> >();

                // Build and send the transaction with 50 recipients.
                WalletBuildTransactionModel buildTransactionModel = await $"http://localhost:{sendingNode.ApiPort}/api"
                                                                    .AppendPathSegment("wallet/build-transaction")
                                                                    .PostJsonAsync(new BuildTransactionRequest
                {
                    WalletName       = "mywallet",
                    AccountName      = "account 0",
                    FeeAmount        = maxBalanceResponse.Fee.ToString(),
                    Password         = "******",
                    ShuffleOutputs   = true,
                    AllowUnconfirmed = true,
                    Recipients       = unusedaddresses.Select(address => new RecipientModel
                    {
                        DestinationAddress = address,
                        Amount             = maxBalanceResponse.MaxSpendableAmount.ToString()
                    }).ToList()
                })
                                                                    .ReceiveJson <WalletBuildTransactionModel>();

                await $"http://localhost:{sendingNode.ApiPort}/api"
                .AppendPathSegment("wallet/send-transaction")
                .PostJsonAsync(new SendTransactionRequest
                {
                    Hex = buildTransactionModel.Hex
                })
                .ReceiveJson <WalletSendTransactionModel>();

                // Assert.
                // The sending node should have 50 (+ fee) fewer coins.
                sendingNodeBalances = await $"http://localhost:{sendingNode.ApiPort}/api"
                                      .AppendPathSegment("wallet/balance")
                                      .SetQueryParams(new { walletName = "mywallet" })
                                      .GetJsonAsync <WalletBalanceModel>();

                sendingAccountBalance = sendingNodeBalances.AccountsBalances.Single();
                (sendingAccountBalance.AmountConfirmed + sendingAccountBalance.AmountUnconfirmed).Should().Be(new Money(sendingAccountBalanceOnStart, MoneyUnit.BTC) - totalToSpend);

                // Mine and sync so that we make sure the receiving node is up to date.
                TestHelper.MineBlocks(sendingNode, 1);
                TestHelper.WaitForNodeToSync(sendingNode, receivingNode);

                // The receiving node should have 50 more coins.
                receivingNodeBalances = await $"http://localhost:{receivingNode.ApiPort}/api"
                                        .AppendPathSegment("wallet/balance")
                                        .SetQueryParams(new { walletName = "mywallet" })
                                        .GetJsonAsync <WalletBalanceModel>();

                receivingAccountBalance = receivingNodeBalances.AccountsBalances.Single();
                (receivingAccountBalance.AmountConfirmed + receivingAccountBalance.AmountUnconfirmed).Should().Be(new Money(receivingAccountBalanceOnStart) + maxBalanceResponse.MaxSpendableAmount);
            }
        }
        public async Task SendingFromOneAddressToFiftyAddresses()
        {
            int sendingAccountBalanceOnStart   = 98000596;
            int receivingAccountBalanceOnStart = 0;

            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                // Arrange.
                // Create a sending and a receiving node.
                CoreNode sendingNode   = builder.CreateStratisPosNode(this.network).WithReadyBlockchainData(ReadyBlockchain.StratisRegTest150Miner).Start();
                CoreNode receivingNode = builder.CreateStratisPosNode(this.network).WithReadyBlockchainData(ReadyBlockchain.StratisRegTest150Listener).Start();
                TestHelper.ConnectAndSync(sendingNode, receivingNode);

                // Check balances.
                WalletBalanceModel sendingNodeBalances = await $"http://localhost:{sendingNode.ApiPort}/api"
                                                         .AppendPathSegment("wallet/balance")
                                                         .SetQueryParams(new { walletName = "mywallet" })
                                                         .GetJsonAsync <WalletBalanceModel>();

                AccountBalanceModel sendingAccountBalance = sendingNodeBalances.AccountsBalances.Single();
                (sendingAccountBalance.AmountConfirmed + sendingAccountBalance.AmountUnconfirmed).Should().Be(new Money(sendingAccountBalanceOnStart, MoneyUnit.BTC));

                WalletBalanceModel receivingNodeBalances = await $"http://localhost:{receivingNode.ApiPort}/api"
                                                           .AppendPathSegment("wallet/balance")
                                                           .SetQueryParams(new { walletName = "mywallet" })
                                                           .GetJsonAsync <WalletBalanceModel>();

                AccountBalanceModel receivingAccountBalance = receivingNodeBalances.AccountsBalances.Single();
                (receivingAccountBalance.AmountConfirmed + receivingAccountBalance.AmountUnconfirmed).Should().Be(new Money(receivingAccountBalanceOnStart));

                // Act.
                // Get 50 addresses to send to.
                IEnumerable <string> unusedaddresses = await $"http://localhost:{receivingNode.ApiPort}/api"
                                                       .AppendPathSegment("wallet/unusedAddresses")
                                                       .SetQueryParams(new { walletName = "mywallet", accountName = "account 0", count = 50 })
                                                       .GetJsonAsync <IEnumerable <string> >();

                // Build and send the transaction with 50 recipients.
                WalletBuildTransactionModel buildTransactionModel = await $"http://localhost:{sendingNode.ApiPort}/api"
                                                                    .AppendPathSegment("wallet/build-transaction")
                                                                    .PostJsonAsync(new BuildTransactionRequest
                {
                    WalletName       = "mywallet",
                    AccountName      = "account 0",
                    FeeType          = "low",
                    Password         = "******",
                    ShuffleOutputs   = true,
                    AllowUnconfirmed = true,
                    Recipients       = unusedaddresses.Select(address => new RecipientModel
                    {
                        DestinationAddress = address,
                        Amount             = "1"
                    }).ToList()
                })
                                                                    .ReceiveJson <WalletBuildTransactionModel>();

                await $"http://localhost:{sendingNode.ApiPort}/api"
                .AppendPathSegment("wallet/send-transaction")
                .PostJsonAsync(new SendTransactionRequest
                {
                    Hex = buildTransactionModel.Hex
                })
                .ReceiveJson <WalletSendTransactionModel>();

                // Assert.
                // The sending node should have 50 (+ fee) fewer coins.
                sendingNodeBalances = await $"http://localhost:{sendingNode.ApiPort}/api"
                                      .AppendPathSegment("wallet/balance")
                                      .SetQueryParams(new { walletName = "mywallet" })
                                      .GetJsonAsync <WalletBalanceModel>();

                sendingAccountBalance = sendingNodeBalances.AccountsBalances.Single();
                (sendingAccountBalance.AmountConfirmed + sendingAccountBalance.AmountUnconfirmed).Should().Be(new Money(sendingAccountBalanceOnStart - 50 - buildTransactionModel.Fee.ToDecimal(MoneyUnit.BTC), MoneyUnit.BTC));

                // Mine and sync so that we make sure the receiving node is up to date.
                TestHelper.MineBlocks(sendingNode, 1);

                // The receiving node should have 50 more coins.
                receivingNodeBalances = await $"http://localhost:{receivingNode.ApiPort}/api"
                                        .AppendPathSegment("wallet/balance")
                                        .SetQueryParams(new { walletName = "mywallet" })
                                        .GetJsonAsync <WalletBalanceModel>();

                receivingAccountBalance = receivingNodeBalances.AccountsBalances.Single();
                (receivingAccountBalance.AmountConfirmed + receivingAccountBalance.AmountUnconfirmed).Should().Be(new Money(receivingAccountBalanceOnStart + 50, MoneyUnit.BTC));
            }
        }
Esempio n. 13
0
        /// <inheritdoc />
        public async Task TumbleAsync(string originWalletName, string destinationWalletName, string originWalletPassword)
        {
            // Make sure it won't start new tumbling round if already started
            if (this.State == TumbleState.Tumbling)
            {
                this.logger.LogDebug("Tumbler is already running");
                throw new Exception("Tumbling is already running");
            }

            this.tumblingState.TumblerUri = new Uri(this.TumblerAddress);

            // Check if in initial block download
            if (!this.chain.IsDownloaded())
            {
                this.logger.LogDebug("Chain is still being downloaded: " + this.chain.Tip);
                throw new Exception("Chain is still being downloaded");
            }

            Wallet destinationWallet = this.walletManager.GetWallet(destinationWalletName);
            Wallet originWallet      = this.walletManager.GetWallet(originWalletName);

            // Check if origin wallet has a balance
            WalletBalanceModel model = new WalletBalanceModel();

            var originWalletAccounts = this.walletManager.GetAccounts(originWallet.Name).ToList();
            var originConfirmed      = new Money(0);
            var originUnconfirmed    = new Money(0);

            foreach (var originAccount in originWallet.GetAccountsByCoinType(this.tumblingState.CoinType))
            {
                var result = originAccount.GetSpendableAmount();

                originConfirmed   += result.ConfirmedAmount;
                originUnconfirmed += result.UnConfirmedAmount;
            }

            // Should ideally take network transaction fee into account too, but that is dynamic
            if ((originConfirmed + originUnconfirmed) <= (this.TumblerParameters.Denomination + this.TumblerParameters.Fee))
            {
                this.logger.LogDebug("Insufficient funds in origin wallet");
                throw new Exception("Insufficient funds in origin wallet");
            }

            // TODO: Check if password is valid before starting any cycles

            // Update the state and save
            this.tumblingState.DestinationWallet     = destinationWallet ?? throw new Exception($"Destination wallet not found. Have you created a wallet with name {destinationWalletName}?");
            this.tumblingState.DestinationWalletName = destinationWalletName;
            this.tumblingState.OriginWallet          = originWallet ?? throw new Exception($"Origin wallet not found. Have you created a wallet with name {originWalletName}?");
            this.tumblingState.OriginWalletName      = originWalletName;
            this.tumblingState.OriginWalletPassword  = originWalletPassword;

            var accounts = this.tumblingState.DestinationWallet.GetAccountsByCoinType(this.tumblingState.CoinType);
            // TODO: Possibly need to preserve destination account name in tumbling state. Default to first account for now
            string accountName = null;

            foreach (var account in accounts)
            {
                if (account.Index == 0)
                {
                    accountName = account.Name;
                }
            }
            var destAccount = this.tumblingState.DestinationWallet.GetAccountByCoinType(accountName, this.tumblingState.CoinType);

            var key     = destAccount.ExtendedPubKey;
            var keyPath = new KeyPath("0");

            // Stop and dispose onlymonitor
            if (this.broadcasterJob != null && this.broadcasterJob.Started)
            {
                await this.broadcasterJob.Stop().ConfigureAwait(false);
            }
            this.runtime?.Dispose();

            // Bypass Tor for integration tests
            FullNodeTumblerClientConfiguration config;

            if (this.TumblerAddress.Contains("127.0.0.1"))
            {
                config = new FullNodeTumblerClientConfiguration(this.tumblingState, onlyMonitor: false,
                                                                connectionTest: false, useProxy: false);
            }
            else
            {
                config = new FullNodeTumblerClientConfiguration(this.tumblingState, onlyMonitor: false,
                                                                connectionTest: false, useProxy: true);
            }

            this.runtime = await TumblerClientRuntime.FromConfigurationAsync(config).ConfigureAwait(false);

            var extPubKey = new BitcoinExtPubKey(key, this.runtime.Network);

            if (key != null)
            {
                this.runtime.DestinationWallet =
                    new ClientDestinationWallet(extPubKey, keyPath, this.runtime.Repository, this.runtime.Network);
            }
            this.TumblerParameters = this.runtime.TumblerParameters;
            // Run onlymonitor mode
            this.broadcasterJob = this.runtime.CreateBroadcasterJob();
            this.broadcasterJob.Start();

            // Run tumbling mode
            this.stateMachine = new StateMachinesExecutor(this.runtime);
            this.stateMachine.Start();

            this.State = TumbleState.Tumbling;

            return;
        }
Esempio n. 14
0
        private async Task <bool> CheckWalletRequirementsAsync(NodeType nodeType, int apiPort)
        {
            var chainName     = nodeType == NodeType.MainChain ? "STRAX" : "CIRRUS";
            var amountToCheck = nodeType == NodeType.MainChain ? CollateralRequirement : FeeRequirement;
            var chainTicker   = nodeType == NodeType.MainChain ? this.mainchainNetwork.CoinTicker : this.sidechainNetwork.CoinTicker;

            Console.WriteLine($"Please enter the name of the {chainName} wallet that contains the required collateral of {amountToCheck} {chainTicker}:");

            var walletName = Console.ReadLine();

            WalletInfoModel walletInfoModel = await $"http://localhost:{apiPort}/api".AppendPathSegment("Wallet/list-wallets").GetJsonAsync <WalletInfoModel>();

            if (walletInfoModel.WalletNames.Contains(walletName))
            {
                Console.WriteLine($"SUCCESS: Wallet with name '{chainName}' found.");
            }
            else
            {
                Console.WriteLine($"{chainName} wallet with name '{walletName}' does not exist.");

                ConsoleKeyInfo key;
                do
                {
                    Console.WriteLine($"Would you like to restore you {chainName} wallet that holds the required amount of {amountToCheck} {chainTicker} now? Enter (Y) to continue or (N) to exit.");
                    key = Console.ReadKey();
                    if (key.Key == ConsoleKey.Y || key.Key == ConsoleKey.N)
                    {
                        break;
                    }
                } while (true);

                if (key.Key == ConsoleKey.N)
                {
                    Console.WriteLine($"You have chosen to exit the registration script.");
                    return(false);
                }

                if (!await RestoreWalletAsync(apiPort, chainName, walletName))
                {
                    return(false);
                }
            }

            // Check wallet height (sync) status.
            do
            {
                var walletNameRequest = new WalletName()
                {
                    Name = walletName
                };
                WalletGeneralInfoModel walletInfo = await $"http://localhost:{apiPort}/api".AppendPathSegment("wallet/general-info").SetQueryParams(walletNameRequest).GetJsonAsync <WalletGeneralInfoModel>();
                StatusModel            blockModel = await $"http://localhost:{apiPort}/api".AppendPathSegment("node/status").GetJsonAsync <StatusModel>();

                if (walletInfo.LastBlockSyncedHeight > (blockModel.ConsensusHeight - 50))
                {
                    Console.WriteLine($"{chainName} wallet is synced.");
                    break;
                }

                Console.WriteLine($"Syncing {chainName} wallet, current height {walletInfo.LastBlockSyncedHeight}...");
                await Task.Delay(TimeSpan.FromSeconds(3));
            } while (true);

            // Check wallet balance.
            try
            {
                var walletBalanceRequest = new WalletBalanceRequest()
                {
                    WalletName = walletName
                };
                WalletBalanceModel walletBalanceModel = await $"http://localhost:{apiPort}/api"
                                                        .AppendPathSegment("wallet/balance")
                                                        .SetQueryParams(walletBalanceRequest)
                                                        .GetJsonAsync <WalletBalanceModel>();

                if (walletBalanceModel.AccountsBalances[0].SpendableAmount / 100000000 > amountToCheck)
                {
                    Console.WriteLine($"SUCCESS: The {chainName} wallet contains the required amount of {amountToCheck} {chainTicker}.");
                    return(true);
                }

                Console.WriteLine($"ERROR: The {chainName} wallet does not contain the required amount of {amountToCheck} {chainTicker}.");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"ERROR: An exception occurred trying to check the wallet balance: {ex}");
            }

            return(false);
        }