예제 #1
0
        public async Task GetTaskAsync_Verbose_BlockNotFoundOnChain_ReturnsTransactionVerboseModelWithoutBlockInformationAsync()
        {
            Transaction transaction = this.CreateTransaction();
            uint256     txId        = new uint256(12142124);

            this.pooledTransaction.Setup(p => p.GetTransaction(txId))
            .ReturnsAsync(transaction);
            var blockStore = new Mock <IBlockStore>();

            blockStore.Setup(b => b.GetTrxBlockIdAsync(txId))
            .ReturnsAsync((uint256)null);
            this.fullNode.Setup(f => f.NodeFeature <IBlockStore>(false))
            .Returns(blockStore.Object);
            this.controller = new NodeController(this.fullNode.Object, this.LoggerFactory.Object,
                                                 this.dateTimeProvider.Object, this.chainState.Object, this.nodeSettings,
                                                 this.connectionManager.Object, this.chain, this.network, this.pooledTransaction.Object,
                                                 this.pooledGetUnspentTransaction.Object, this.getUnspentTransaction.Object, this.networkDifficulty.Object);
            string txid    = txId.ToString();
            bool   verbose = true;

            var json = (JsonResult)await this.controller.GetRawTransactionAsync(txid, verbose).ConfigureAwait(false);

            TransactionVerboseModel resultModel = (TransactionVerboseModel)json.Value;

            Assert.NotNull(resultModel);
            var model = Assert.IsType <TransactionVerboseModel>(resultModel);

            Assert.Null(model.BlockHash);
            Assert.Null(model.Confirmations);
            Assert.Null(model.Time);
            Assert.Null(model.BlockTime);
        }
예제 #2
0
        public async Task GetRawTransactionWithNonZeroIntegerParameterReperesentingAsync()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                // Arrange.
                CoreNode node = builder.CreateStratisPosNode(this.network).WithReadyBlockchainData(ReadyBlockchain.StratisRegTest150Miner).Start();

                // Get the last block we have.
                string lastBlockHash = await $"http://localhost:{node.ApiPort}/api"
                                       .AppendPathSegment("consensus/getbestblockhash")
                                       .GetJsonAsync <string>();

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

                // Act.
                RPCClient   rpc      = node.CreateRPCClient();
                RPCResponse response = await rpc.SendCommandAsync(RPCOperations.getrawtransaction, tip.Transactions.First(), 1);

                // Assert.
                TransactionVerboseModel transaction = response.Result.ToObject <TransactionVerboseModel>();
                transaction.TxId.Should().Be((string)tip.Transactions.First());
                transaction.VOut.First().ScriptPubKey.Addresses.Count.Should().Be(1);
            }
        }
예제 #3
0
        public async Task <IActionResult> GetTransactionAsync(string id)
        {
            if (!this.ModelState.IsValid)
            {
                return(ModelStateErrors.BuildErrorResponse(this.ModelState));
            }

            if (string.IsNullOrWhiteSpace(id))
            {
                throw new ArgumentNullException("id", "id must be specified");
            }

            try
            {
                Transaction trx = await this.blockRepository.GetTransactionByIdAsync(new uint256(id));

                var model = new TransactionVerboseModel(trx, this.network);
                return(Json(model));
            }
            catch (Exception e)
            {
                this.logger.LogError("Exception occurred: {0}", e.ToString());
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString()));
            }
        }
        public TransactionModelsTest()
        {
            var network = Network.Main;

            this.txBlock10CoinbaseModelBrief       = new TransactionBriefModel(network.CreateTransaction(TxBlock10Hex));
            this.txBlock460373CoinbaseModelVerbose = new TransactionVerboseModel(network.CreateTransaction(TxBlock460373CoinbaseHex), network);
            this.txTwoInTwoOutModelVerbose         = new TransactionVerboseModel(network.CreateTransaction(TxTwoInTwoOutHex), network);
        }
        internal TransactionVerboseModel GetTransactionInfo(uint256 transactionId)
        {
            Transaction   transaction     = this.blockStore?.GetTransactionById(transactionId);
            ChainedHeader block           = this.GetTransactionBlock(transactionId, this.fullNode, this.chainIndexer);
            var           transactionInfo = new TransactionVerboseModel(transaction, this.network, block, this.chainState?.ConsensusTip);

            return(transactionInfo);
        }
예제 #6
0
        public TransactionModelsTest()
        {
            Block.BlockSignature  = false;
            Transaction.TimeStamp = false;

            this.txBlock10CoinbaseModelBrief       = new TransactionBriefModel(Transaction.Parse(TxBlock10Hex));
            this.txBlock460373CoinbaseModelVerbose = new TransactionVerboseModel(Transaction.Parse(TxBlock460373CoinbaseHex), Network.PurpleMain);
            this.txTwoInTwoOutModelVerbose         = new TransactionVerboseModel(Transaction.Parse(TxTwoInTwoOutHex), Network.PurpleMain);
        }
예제 #7
0
        public async Task GetTaskAsync_Verbose_ReturnsTransactionVerboseModelAsync()
        {
            this.chainState.Setup(c => c.ConsensusTip)
            .Returns(this.chain.Tip);
            var         block       = this.chain.GetBlock(1);
            Transaction transaction = this.CreateTransaction();
            uint256     txId        = new uint256(12142124);

            this.pooledTransaction.Setup(p => p.GetTransaction(txId))
            .ReturnsAsync(transaction);
            var blockStore = new Mock <IBlockStore>();

            blockStore.Setup(b => b.GetTrxBlockIdAsync(txId))
            .ReturnsAsync(block.HashBlock);
            this.fullNode.Setup(f => f.NodeFeature <IBlockStore>(false))
            .Returns(blockStore.Object);
            this.controller = new NodeController(this.fullNode.Object, this.LoggerFactory.Object,
                                                 this.dateTimeProvider.Object, this.chainState.Object, this.nodeSettings,
                                                 this.connectionManager.Object, this.chain, this.network, this.pooledTransaction.Object,
                                                 this.pooledGetUnspentTransaction.Object, this.getUnspentTransaction.Object, this.networkDifficulty.Object);
            string txid    = txId.ToString();
            bool   verbose = true;

            var json = (JsonResult)await this.controller.GetRawTransactionAsync(txid, verbose).ConfigureAwait(false);

            TransactionVerboseModel resultModel = (TransactionVerboseModel)json.Value;

            Assert.NotNull(resultModel);
            var model = Assert.IsType <TransactionVerboseModel>(resultModel);

            Assert.Equal(transaction.GetHash().ToString(), model.TxId);
            Assert.Equal(transaction.GetSerializedSize(), model.Size);
            Assert.Equal(transaction.Version, model.Version);
            Assert.Equal((uint)transaction.LockTime, model.LockTime);
            Assert.Equal(transaction.ToHex(), model.Hex);
            Assert.Equal(block.HashBlock.ToString(), model.BlockHash);
            Assert.Equal(3, model.Confirmations);
            Assert.Equal(Utils.DateTimeToUnixTime(block.Header.BlockTime), model.Time);
            Assert.Equal(Utils.DateTimeToUnixTime(block.Header.BlockTime), model.BlockTime);
            Assert.NotEmpty(model.VIn);
            var input         = model.VIn[0];
            var expectedInput = new Vin(transaction.Inputs[0].PrevOut, transaction.Inputs[0].Sequence, transaction.Inputs[0].ScriptSig);

            Assert.Equal(expectedInput.Coinbase, input.Coinbase);
            Assert.Equal(expectedInput.ScriptSig, input.ScriptSig);
            Assert.Equal(expectedInput.Sequence, input.Sequence);
            Assert.Equal(expectedInput.TxId, input.TxId);
            Assert.Equal(expectedInput.VOut, input.VOut);
            Assert.NotEmpty(model.VOut);
            var output         = model.VOut[0];
            var expectedOutput = new Vout(0, transaction.Outputs[0], this.network);

            Assert.Equal(expectedOutput.Value, output.Value);
            Assert.Equal(expectedOutput.N, output.N);
            Assert.Equal(expectedOutput.ScriptPubKey.Hex, output.ScriptPubKey.Hex);
        }
 internal ListTransactionsModel GetTransactionsModel(TransactionVerboseModel transactionInfo)
 {
     var transactionResult = new ListTransactionsModel
     {
         Confirmations = transactionInfo.Confirmations ?? 0,
         BlockHash = transactionInfo.BlockHash ?? string.Empty,
         BlockTime = transactionInfo.BlockTime ?? 0,
         TransactionId = transactionInfo.TxId,
         TransactionTime = (long)(transactionInfo.Time ?? 0),
         Amount = transactionInfo.VOut.Sum(a => a.Value)
     };
     return transactionResult;
 }
예제 #9
0
        public TransactionModel DecodeRawTransaction(string hex)
        {
            try
            {
                var transaction = new TransactionVerboseModel(this.FullNode.Network.CreateTransaction(hex), this.Network);

                // Clear hex to not include it into the output. Hex is already known to the client. This will reduce response size.
                transaction.Hex = null;
                return(transaction);
            }
            catch (FormatException ex)
            {
                throw new ArgumentException(nameof(hex), ex.Message);
            }
            catch (Exception)
            {
                return(null);
            }
        }
예제 #10
0
        public void ProcessTransaction(Transaction transaction, int?blockHeight = null, Block block = null)
        {
            var hash = transaction.GetHash();

            this.logger.LogDebug($"watch only wallet received transaction - hash: {hash}, coin: {this.coinType}");

            // check the outputs
            foreach (TxOut utxo in transaction.Outputs)
            {
                TransactionVerboseModel model = new TransactionVerboseModel(transaction, this.network);

                // check if the outputs contain one of our addresses
                if (this.Wallet.Scripts.Contains(utxo.ScriptPubKey) && this.Wallet.Transactions.All(t => t.hex != model.hex))
                {
                    this.Wallet.Transactions.Add(model);
                    this.SaveToFile();
                }
            }
        }
 public void Dispose()
 {
     this.txBlock10CoinbaseModelBrief       = null;
     this.txBlock460373CoinbaseModelVerbose = null;
     this.txTwoInTwoOutModelVerbose         = null;
 }
 public TransactionModelsTest()
 {
     this.txBlock10CoinbaseModelBrief       = new TransactionBriefModel(Transaction.Parse(txBlock10Hex));
     this.txBlock460373CoinbaseModelVerbose = new TransactionVerboseModel(Transaction.Parse(txBlock460373CoinbaseHex), Network.Main);
     this.txTwoInTwoOutModelVerbose         = new TransactionVerboseModel(Transaction.Parse(txTwoInTwoOutHex), Network.Main);
 }
        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"));
            }
        }