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