public void Given_AWatchedAddress_When_ATransactionIsReceivedInABlock_ThenCanCalculateRelativeBalance() { // Arrange. DataFolder dataFolder = CreateDataFolder(this); // Create the wallet to watch. WatchOnlyWallet wallet = this.CreateAndPersistAWatchOnlyWallet(dataFolder); // Create the address to watch. Script newScript = BitcoinAddress.Create("mnSmvy2q4dFNKQF18EBsrZrS7WEy6CieEE", this.networkTestNet).ScriptPubKey; string newAddress = newScript.GetDestinationAddress(this.networkTestNet).ToString(); // Create a transaction to be received. string transactionHex = "010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff230384041200fe0eb3a959fe1af507000963676d696e6572343208000000000000000000ffffffff02155e8b09000000001976a9144bfe90c8e6c6352c034b3f57d50a9a6e77a62a0788ac0000000000000000266a24aa21a9ed0bc6e4bfe82e04a1c52e66b72b199c5124794dd8c3c368f6ab95a0ba6cde277d0120000000000000000000000000000000000000000000000000000000000000000000000000"; Transaction transaction = this.networkTestNet.CreateTransaction(transactionHex); Block block = this.networkTestNet.Consensus.ConsensusFactory.CreateBlock(); block.AddTransaction(transaction); block.UpdateMerkleRoot(); // Act. var walletManager = new WatchOnlyWalletManager(DateTimeProvider.Default, this.LoggerFactory.Object, this.networkTestNet, dataFolder, this.signals); walletManager.Initialize(); walletManager.WatchAddress("mnSmvy2q4dFNKQF18EBsrZrS7WEy6CieEE"); walletManager.ProcessBlock(block); // Assert. Money balance = walletManager.GetRelativeBalance("mnSmvy2q4dFNKQF18EBsrZrS7WEy6CieEE"); Assert.Equal(Money.Coins(1.60128533m), balance); }
public void Given_AWatchedAddress_And_A_WatchedTransaction_CanPopulateLookup() { DataFolder dataFolder = CreateDataFolder(this); WatchOnlyWallet watchOnlyWallet = this.CreateAndPersistAWatchOnlyWallet(dataFolder); // Only need to watch a single address/transaction Script newScript = BitcoinAddress.Create("mnSmvy2q4dFNKQF18EBsrZrS7WEy6CieEE", this.networkTestNet).ScriptPubKey; string transactionHex = "010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff230384041200fe0eb3a959fe1af507000963676d696e6572343208000000000000000000ffffffff02155e8b09000000001976a9144bfe90c8e6c6352c034b3f57d50a9a6e77a62a0788ac0000000000000000266a24aa21a9ed0bc6e4bfe82e04a1c52e66b72b199c5124794dd8c3c368f6ab95a0ba6cde277d0120000000000000000000000000000000000000000000000000000000000000000000000000"; // Ensure transaction appears in block Transaction transaction = this.networkTestNet.CreateTransaction(transactionHex); Block block = this.networkTestNet.Consensus.ConsensusFactory.CreateBlock(); block.AddTransaction(transaction); block.UpdateMerkleRoot(); var walletManager = new WatchOnlyWalletManager(DateTimeProvider.Default, this.LoggerFactory.Object, this.networkTestNet, dataFolder, this.signals); walletManager.Initialize(); walletManager.WatchAddress("mnSmvy2q4dFNKQF18EBsrZrS7WEy6CieEE"); walletManager.StoreTransaction(new WatchTransactionData() { Id = transaction.GetHash(), Hex = transactionHex }); walletManager.ProcessBlock(block); WatchOnlyWallet wallet = walletManager.GetWatchOnlyWallet(); // Artificially remove info from the watched address version of the transaction WatchedAddress addressInWallet = wallet.WatchedAddresses[newScript.ToString()]; WatchTransactionData watchedTransaction = addressInWallet.Transactions.Values.First(); watchedTransaction.MerkleProof = null; watchedTransaction.BlockHash = null; // Now populate lookup ConcurrentDictionary <uint256, WatchTransactionData> lookup = wallet.GetWatchedTransactions(); // Expect that the cached version of the transaction has a // Merkle proof and block hash WatchTransactionData lookupTransaction = lookup[transaction.GetHash()]; Assert.NotNull(lookupTransaction.MerkleProof); Assert.NotNull(lookupTransaction.BlockHash); }
public void Given_AWatchedAddress_When_ATransactionIsReceivedInABlock_ThenTransactionDataIsAddedToTheAddress() { // Arrange. string dir = AssureEmptyDir("TestData/WatchOnlyWalletManagerTest/Given_AWatchedAddress_When_ATransactionIsReceivedInABlock_ThenTransactionDataIsAddedToTheAddress"); var dataFolder = new DataFolder(new NodeSettings { DataDir = dir }); // Create the wallet to watch. var wallet = this.CreateAndPersistAWatchOnlyWallet(dataFolder); // Create the address to watch. Script newScript = BitcoinAddress.Create("mnSmvy2q4dFNKQF18EBsrZrS7WEy6CieEE", Network.TestNet).ScriptPubKey; string newAddress = newScript.GetDestinationAddress(Network.TestNet).ToString(); // Create a transaction to be received. string transactionHex = "010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff230384041200fe0eb3a959fe1af507000963676d696e6572343208000000000000000000ffffffff02155e8b09000000001976a9144bfe90c8e6c6352c034b3f57d50a9a6e77a62a0788ac0000000000000000266a24aa21a9ed0bc6e4bfe82e04a1c52e66b72b199c5124794dd8c3c368f6ab95a0ba6cde277d0120000000000000000000000000000000000000000000000000000000000000000000000000"; Transaction transaction = new Transaction(transactionHex); var block = new Block(); block.AddTransaction(transaction); block.UpdateMerkleRoot(); // Act. var walletManager = new WatchOnlyWalletManager(DateTimeProvider.Default, this.LoggerFactory.Object, Network.TestNet, dataFolder); walletManager.Initialize(); walletManager.WatchAddress("mnSmvy2q4dFNKQF18EBsrZrS7WEy6CieEE"); walletManager.ProcessBlock(block); // Assert. var returnedWallet = walletManager.GetWatchOnlyWallet(); Assert.NotNull(returnedWallet); var addressInWallet = returnedWallet.WatchedAddresses[newScript.ToString()]; Assert.NotNull(addressInWallet); Assert.False(addressInWallet.Transactions.IsEmpty); Assert.Single(addressInWallet.Transactions); var transactionExpected = addressInWallet.Transactions.Single().Value; Assert.Equal(transactionHex, transactionExpected.Hex); Assert.NotNull(transactionExpected.BlockHash); Assert.NotNull(transactionExpected.MerkleProof); }
public void Given_AWatchedAddress_ThenCanCalculateComplexRelativeBalance() { DataFolder dataFolder = CreateDataFolder(this); // Create transactions to be received. var transactionsHex = new[] { "01000000018161735257ebaf9586bac9fd71955cbb833ea88a845d3a146d462c925c951c97010000001716001463a186b12a8e7c03d80eddc84c73f88e7ac41e3cffffffff02c03b4703000000001976a91454e37ad52373b08ad47dac9c909e2a86562740c088acfa4fc8fa0000000017a9148d26b9dc3a4d6105164567e37fe3a8e53fb60e958700000000", "0100000001cfc7db3f85932c636170ea95f3f77ea674283f981a6a1b36c9b2fd9a8248ea2c000000006b483045022100ba70c4538193e4a228666b8db58256c6bb9225f6fe39441a949f49f6964a947d022048508c50ed4a30df1f222d3dd010c10d5a0852d47843e96277c5b730b3194843012102a31bf228b4508abe3f0aa5f91c53732dfd49233c2fef3c5cfa68f2aa12cc71b4ffffffff02b0e13403000000001976a914546f3bb7a70a077d51bed1bf6acb55dead27024388ace0c810000000000017a914e3925ce02760a2fec19871938b0ae5c740fa2b908700000000", "0100000001a6391afc9adf3f385bd7261d6e120511203b60a9dacd3e99cc7010c7a22722ce0100000017160014096a4e906d7807137a10824ce68a0297a3d14e50ffffffff02e09da301000000001976a91454e37ad52373b08ad47dac9c909e2a86562740c088acb94b56e90000000017a91421649ed0b7412724abba0b27c3224beb3a7530e18700000000", "010000000180f6a5f49b79029333d1ab406424da4bd5f4378b19b1f8246b496f32cf215dc6000000006a4730440220080b0dfa1a93e8f4ebf9415727f60504df95c3a7dea7fe4e4053d0bb3f54540202202e9d02bbb642d7c55d637bd9a56265f42dc1626e933031d638507223846a5e53012102a31bf228b4508abe3f0aa5f91c53732dfd49233c2fef3c5cfa68f2aa12cc71b4ffffffff02225b9101000000001976a914e15f2eb7b19ae02102a1c24452fbd3f516dca8f888ace0c810000000000017a914585cffb7dc06ac82119fba0e36e1e95b534443958700000000", "01000000017f926a306647e0bf3ad12c86fca22dbce2f31161006d0723041963dbf31b17ae0100000017160014c72367e145246374dbb748fa274661cd7aece41effffffff02f0ced100000000001976a91454e37ad52373b08ad47dac9c909e2a86562740c088acf120a8d80000000017a9149bdfb11d7b870c364b4167d921339284b52ba1dc8700000000", "0100000001dd19f894733ab950ae8e772ef781fe299f80f4e813ee4cb6ac067fedea3a052c000000006b483045022100d4d6570c054bcbafa8178e9074f2be32b078e0761537bfe4fb7ad1eea949ab66022022e31d6f43d9418b6dc02147aefb380a4730386364bd406365e790826400570b012102a31bf228b4508abe3f0aa5f91c53732dfd49233c2fef3c5cfa68f2aa12cc71b4ffffffff029e90bf00000000001976a914128240d302a4aadcdd08d241b54fa4ef11acb21388ace0c810000000000017a914188d767b139ef64ce4efa091c2957c6137fbe0ce8700000000" }; var block = this.networkTestNet.Consensus.ConsensusFactory.CreateBlock(); foreach (string transactionHex in transactionsHex) { block.AddTransaction(this.networkTestNet.CreateTransaction(transactionHex)); } block.UpdateMerkleRoot(); var walletManager = new WatchOnlyWalletManager(DateTimeProvider.Default, this.LoggerFactory.Object, this.networkTestNet, dataFolder, this.signals); walletManager.Initialize(); walletManager.WatchAddress("moFoZk1figjfEe1Z49GUePXy2KqYr6DioL"); walletManager.ProcessBlock(block); // Manual calculation of expected result // 2cea48829afdb2c9361b6a1a983f2874a67ef7f395ea7061632c93853fdbc7cf +0.55 // c65d21cf326f496b24f8b1198b37f4d54bda246440abd1339302799bf4a5f680 +0.275 // 2c053aeaed7f06acb64cee13e8f4809f29fe81f72e778eae50b93a7394f819dd +0.1375 // 15c4f72e80a7607d87911969a418b18cc513b70588d27694179073ccdcf966f1 -0.1375 // 3aeabae1ec7bd6362babf02b0bb51e4b5c183f30fbe593e170365afcdd5a6f7c -0.275 // 240afed9840527f55f0087f4594a245219759307b034a983378d5dda91ea08a0 -0.55 = 0 // Block explorer confirmation: https://testnet.smartbit.com.au/address/moFoZk1figjfEe1Z49GUePXy2KqYr6DioL Money balance = walletManager.GetRelativeBalance("moFoZk1figjfEe1Z49GUePXy2KqYr6DioL"); Assert.Equal(Money.Coins(0m), balance); }