public ColdStakingController( ILoggerFactory loggerFactory, IWalletManager walletManager, IWalletTransactionHandler walletTransactionHandler) { Guard.NotNull(loggerFactory, nameof(loggerFactory)); Guard.NotNull(walletManager, nameof(walletManager)); Guard.NotNull(walletTransactionHandler, nameof(walletTransactionHandler)); this.ColdStakingManager = walletManager as ColdStakingManager; Guard.NotNull(this.ColdStakingManager, nameof(this.ColdStakingManager)); this.logger = loggerFactory.CreateLogger(this.GetType().FullName); this.walletTransactionHandler = walletTransactionHandler; }
public ColdStakingController( ILoggerFactory loggerFactory, IWalletManager walletManager, IWalletTransactionHandler walletTransactionHandler) { Guard.NotNull(loggerFactory, nameof(loggerFactory)); Guard.NotNull(walletManager, nameof(walletManager)); Guard.NotNull(walletTransactionHandler, nameof(walletTransactionHandler)); this.ColdStakingManager = walletManager as ColdStakingManager; Guard.NotNull(this.ColdStakingManager, nameof(this.ColdStakingManager)); this.logger = loggerFactory.CreateLogger("Impleum.Bitcoin.Fullnode"); this.walletTransactionHandler = walletTransactionHandler; }
/// <summary> /// Initializes each test case. /// </summary> /// <param name="callingMethod">The test method being executed.</param> private void Initialize([System.Runtime.CompilerServices.CallerMemberName] string callingMethod = "") { DataFolder dataFolder = CreateDataFolder(this, callingMethod); this.nodeSettings = new NodeSettings(this.Network, ProtocolVersion.ALT_PROTOCOL_VERSION); this.dateTimeProvider = DateTimeProvider.Default; var walletSettings = new WalletSettings(this.nodeSettings); this.loggerFactory = this.nodeSettings.LoggerFactory; this.coldStakingManager = new ColdStakingManager(this.Network, new ConcurrentChain(this.Network), walletSettings, this.nodeSettings.DataFolder, new Mock <IWalletFeePolicy>().Object, new Mock <IAsyncLoopFactory>().Object, new NodeLifetime(), new ScriptAddressReader(), this.loggerFactory, DateTimeProvider.Default); var walletTransactionHandler = new WalletTransactionHandler(this.loggerFactory, this.coldStakingManager, new Mock <IWalletFeePolicy>().Object, this.Network, new StandardTransactionPolicy(this.Network)); this.coldStakingController = new ColdStakingController(this.loggerFactory, this.coldStakingManager, walletTransactionHandler); }
public void ProcessTransactionWithValidColdStakingSetupLoadsTransactionsIntoWalletIfMatching() { DataFolder dataFolder = CreateDataFolder(this); Directory.CreateDirectory(dataFolder.WalletPath); Wallet.Wallet wallet = this.walletFixture.GenerateBlankWallet("myWallet", "password"); (ExtKey ExtKey, string ExtPubKey)accountKeys = WalletTestsHelpers.GenerateAccountKeys(wallet, "password", "m/44'/0'/0'"); (PubKey PubKey, BitcoinPubKeyAddress Address)spendingKeys = WalletTestsHelpers.GenerateAddressKeys(wallet, accountKeys.ExtPubKey, "0/0"); (PubKey PubKey, BitcoinPubKeyAddress Address)changeKeys = WalletTestsHelpers.GenerateAddressKeys(wallet, accountKeys.ExtPubKey, "1/0"); Wallet.Wallet coldWallet = this.walletFixture.GenerateBlankWallet("myColdWallet", "password"); (ExtKey ExtKey, string ExtPubKey)accountColdKeys = WalletTestsHelpers.GenerateAccountKeys(coldWallet, "password", $"m/44'/0'/{ColdStakingManager.ColdWalletAccountIndex}'"); (PubKey PubKey, BitcoinPubKeyAddress Address)destinationColdKeys = WalletTestsHelpers.GenerateAddressKeys(coldWallet, accountColdKeys.ExtPubKey, "0/0"); Wallet.Wallet hotWallet = this.walletFixture.GenerateBlankWallet("myHotWallet", "password"); (ExtKey ExtKey, string ExtPubKey)accountHotKeys = WalletTestsHelpers.GenerateAccountKeys(hotWallet, "password", $"m/44'/0'/{ColdStakingManager.HotWalletAccountIndex}'"); (PubKey PubKey, BitcoinPubKeyAddress Address)destinationHotKeys = WalletTestsHelpers.GenerateAddressKeys(hotWallet, accountHotKeys.ExtPubKey, "0/0"); var spendingAddress = new HdAddress { Index = 0, HdPath = $"m/44'/0'/0'/0/0", Address = spendingKeys.Address.ToString(), Pubkey = spendingKeys.PubKey.ScriptPubKey, ScriptPubKey = spendingKeys.Address.ScriptPubKey, Transactions = new List <TransactionData>() }; var destinationColdAddress = new HdAddress { Index = 0, HdPath = $"m/44'/0'/{ColdStakingManager.ColdWalletAccountIndex}'/0/0", Address = destinationColdKeys.Address.ToString(), Pubkey = destinationColdKeys.PubKey.ScriptPubKey, ScriptPubKey = destinationColdKeys.Address.ScriptPubKey, Transactions = new List <TransactionData>() }; var destinationHotAddress = new HdAddress { Index = 0, HdPath = $"m/44'/0'/{ColdStakingManager.HotWalletAccountIndex}'/0/0", Address = destinationHotKeys.Address.ToString(), Pubkey = destinationHotKeys.PubKey.ScriptPubKey, ScriptPubKey = destinationHotKeys.Address.ScriptPubKey, Transactions = new List <TransactionData>() }; var changeAddress = new HdAddress { Index = 0, HdPath = $"m/44'/0'/0'/1/0", Address = changeKeys.Address.ToString(), Pubkey = changeKeys.PubKey.ScriptPubKey, ScriptPubKey = changeKeys.Address.ScriptPubKey, Transactions = new List <TransactionData>() }; // Generate a spendable transaction (ChainIndexer chain, uint256 blockhash, Block block)chainInfo = WalletTestsHelpers.CreateChainAndCreateFirstBlockWithPaymentToAddress(wallet.Network, spendingAddress); TransactionData spendingTransaction = WalletTestsHelpers.CreateTransactionDataFromFirstBlock(chainInfo); spendingAddress.Transactions.Add(spendingTransaction); wallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount { Index = 0, Name = "account 0", HdPath = "m/44'/0'/0'", ExtendedPubKey = accountKeys.ExtPubKey, ExternalAddresses = new List <HdAddress> { spendingAddress }, InternalAddresses = new List <HdAddress> { changeAddress } }); coldWallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount { Index = ColdStakingManager.ColdWalletAccountIndex, Name = ColdStakingManager.ColdWalletAccountName, HdPath = $"m/44'/0'/{ColdStakingManager.ColdWalletAccountIndex}'", ExtendedPubKey = accountColdKeys.ExtPubKey, ExternalAddresses = new List <HdAddress> { destinationColdAddress }, InternalAddresses = new List <HdAddress> { } }); hotWallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount { Index = ColdStakingManager.HotWalletAccountIndex, Name = ColdStakingManager.HotWalletAccountName, HdPath = $"m/44'/0'/{ColdStakingManager.HotWalletAccountIndex}'", ExtendedPubKey = accountHotKeys.ExtPubKey, ExternalAddresses = new List <HdAddress> { destinationHotAddress }, InternalAddresses = new List <HdAddress> { } }); var walletFeePolicy = new Mock <IWalletFeePolicy>(); walletFeePolicy.Setup(w => w.GetMinimumFee(258, 50)) .Returns(new Money(5000)); var walletSettings = new WalletSettings(new NodeSettings(network: this.Network)); var coldWalletManager = new ColdStakingManager(this.Network, chainInfo.chain, walletSettings, dataFolder, walletFeePolicy.Object, new Mock <IAsyncProvider>().Object, new NodeLifetime(), new ScriptAddressReader(), this.LoggerFactory.Object, DateTimeProvider.Default, new Mock <ISignals>().Object, new Mock <IBroadcasterManager>().Object); coldWalletManager.Wallets.Add(wallet); coldWalletManager.Wallets.Add(coldWallet); coldWalletManager.LoadKeysLookupLock(); // Create another instance for the hot wallet as it is not allowed to have both wallets on the same instance. var hotWalletManager = new ColdStakingManager(this.Network, chainInfo.chain, walletSettings, dataFolder, walletFeePolicy.Object, new Mock <IAsyncProvider>().Object, new NodeLifetime(), new ScriptAddressReader(), this.LoggerFactory.Object, DateTimeProvider.Default, new Mock <ISignals>().Object, new Mock <IBroadcasterManager>().Object); hotWalletManager.Wallets.Add(hotWallet); hotWalletManager.LoadKeysLookupLock(); // Create a cold staking setup transaction. Transaction transaction = this.CreateColdStakingSetupTransaction(wallet, "password", spendingAddress, destinationColdKeys.PubKey, destinationHotKeys.PubKey, changeAddress, new Money(7500), new Money(5000)); coldWalletManager.ProcessTransaction(transaction); hotWalletManager.ProcessTransaction(transaction); HdAddress spentAddressResult = wallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(0); Assert.Equal(1, spendingAddress.Transactions.Count); Assert.Equal(transaction.GetHash(), spentAddressResult.Transactions.ElementAt(0).SpendingDetails.TransactionId); Assert.Equal(transaction.Outputs[1].Value, spentAddressResult.Transactions.ElementAt(0).SpendingDetails.Payments.ElementAt(0).Amount); Assert.Equal(transaction.Outputs[1].ScriptPubKey, spentAddressResult.Transactions.ElementAt(0).SpendingDetails.Payments.ElementAt(0).DestinationScriptPubKey); Assert.Equal(1, wallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).InternalAddresses.ElementAt(0).Transactions.Count); TransactionData changeAddressResult = wallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).InternalAddresses.ElementAt(0).Transactions.ElementAt(0); Assert.Equal(transaction.GetHash(), changeAddressResult.Id); Assert.Equal(transaction.Outputs[0].Value, changeAddressResult.Amount); Assert.Equal(transaction.Outputs[0].ScriptPubKey, changeAddressResult.ScriptPubKey); // Verify that the transaction has been recorded in the cold wallet. Assert.Equal(1, coldWallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(0).Transactions.Count); TransactionData destinationColdAddressResult = coldWallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(0).Transactions.ElementAt(0); Assert.Equal(transaction.GetHash(), destinationColdAddressResult.Id); Assert.Equal(transaction.Outputs[1].Value, destinationColdAddressResult.Amount); Assert.Equal(transaction.Outputs[1].ScriptPubKey, destinationColdAddressResult.ScriptPubKey); // Verify that the transaction has been recorded in the hot wallet. Assert.Equal(1, hotWallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(0).Transactions.Count); TransactionData destinationHotAddressResult = hotWallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(0).Transactions.ElementAt(0); Assert.Equal(transaction.GetHash(), destinationHotAddressResult.Id); Assert.Equal(transaction.Outputs[1].Value, destinationHotAddressResult.Amount); Assert.Equal(transaction.Outputs[1].ScriptPubKey, destinationHotAddressResult.ScriptPubKey); // Try withdrawing from the cold staking setup. Wallet.Wallet withdrawalWallet = this.walletFixture.GenerateBlankWallet("myWithDrawalWallet", "password"); (ExtKey ExtKey, string ExtPubKey)withdrawalAccountKeys = WalletTestsHelpers.GenerateAccountKeys(wallet, "password", "m/44'/0'/0'"); (PubKey PubKey, BitcoinPubKeyAddress Address)withdrawalKeys = WalletTestsHelpers.GenerateAddressKeys(withdrawalWallet, withdrawalAccountKeys.ExtPubKey, "0/0"); // Withdrawing to this address. var withdrawalAddress = new HdAddress { Index = 0, HdPath = $"m/44'/0'/0'/0/0", Address = withdrawalKeys.Address.ToString(), Pubkey = withdrawalKeys.PubKey.ScriptPubKey, ScriptPubKey = withdrawalKeys.Address.ScriptPubKey, Transactions = new List <TransactionData>() }; withdrawalWallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount { Index = 0, Name = "account 0", HdPath = "m/44'/0'/0'", ExtendedPubKey = accountKeys.ExtPubKey, ExternalAddresses = new List <HdAddress> { withdrawalAddress }, InternalAddresses = new List <HdAddress> { } }); // Will spend from the cold stake address and send the change back to the same address. var coldStakeAddress = coldWallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(0); Transaction withdrawalTransaction = this.CreateColdStakingWithdrawalTransaction(coldWallet, "password", coldStakeAddress, withdrawalKeys.PubKey, ColdStakingScriptTemplate.Instance.GenerateScriptPubKey(destinationColdKeys.PubKey.Hash, destinationHotKeys.PubKey.Hash), new Money(750), new Money(262)); // Wallet manager for the wallet receiving the funds. var receivingWalletManager = new ColdStakingManager(this.Network, chainInfo.chain, walletSettings, dataFolder, walletFeePolicy.Object, new Mock <IAsyncProvider>().Object, new NodeLifetime(), new ScriptAddressReader(), this.LoggerFactory.Object, DateTimeProvider.Default, new Mock <ISignals>().Object, new Mock <IBroadcasterManager>().Object); receivingWalletManager.Wallets.Add(withdrawalWallet); receivingWalletManager.LoadKeysLookupLock(); // Process the transaction in the cold wallet manager. coldWalletManager.ProcessTransaction(withdrawalTransaction); // Process the transaction in the hot wallet manager. hotWalletManager.ProcessTransaction(withdrawalTransaction); // Process the transaction in the receiving wallet manager. receivingWalletManager.ProcessTransaction(withdrawalTransaction); // Verify that the transaction has been recorded in the withdrawal wallet. Assert.Equal(1, withdrawalWallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(0).Transactions.Count); TransactionData withdrawalAddressResult = withdrawalWallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(0).Transactions.ElementAt(0); Assert.Equal(withdrawalTransaction.GetHash(), withdrawalAddressResult.Id); Assert.Equal(withdrawalTransaction.Outputs[1].Value, withdrawalAddressResult.Amount); Assert.Equal(withdrawalTransaction.Outputs[1].ScriptPubKey, withdrawalAddressResult.ScriptPubKey); // Verify that the transaction has been recorded in the cold wallet. Assert.Equal(2, coldWallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(0).Transactions.Count); TransactionData coldAddressResult = coldWallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(0).Transactions.ElementAt(1); Assert.Equal(withdrawalTransaction.GetHash(), coldAddressResult.Id); Assert.Equal(withdrawalTransaction.Outputs[0].Value, coldAddressResult.Amount); Assert.Equal(withdrawalTransaction.Outputs[0].ScriptPubKey, coldAddressResult.ScriptPubKey); // Verify that the transaction has been recorded in the hot wallet. Assert.Equal(2, hotWallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(0).Transactions.Count); TransactionData hotAddressResult = hotWallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(0).Transactions.ElementAt(1); Assert.Equal(withdrawalTransaction.GetHash(), hotAddressResult.Id); Assert.Equal(withdrawalTransaction.Outputs[0].Value, hotAddressResult.Amount); Assert.Equal(withdrawalTransaction.Outputs[0].ScriptPubKey, hotAddressResult.ScriptPubKey); // Verify the hot amount returned by GetBalances. AccountBalance hotBalance = hotWalletManager.GetBalances("myHotWallet", ColdStakingManager.HotWalletAccountName).FirstOrDefault(); Assert.Equal(hotBalance.AmountUnconfirmed, hotAddressResult.Amount); // Verify the cold amount returned by GetBalances. AccountBalance coldBalance = coldWalletManager.GetBalances("myColdWallet", ColdStakingManager.ColdWalletAccountName).FirstOrDefault(); Assert.Equal(coldBalance.AmountUnconfirmed, coldAddressResult.Amount); }
public void ProcessTransactionWithValidColdStakingSetupLoadsTransactionsIntoWalletIfMatching() { DataFolder dataFolder = CreateDataFolder(this); Directory.CreateDirectory(dataFolder.WalletPath); var chain = new ChainIndexer(this.Network); var walletFeePolicy = new Mock <IWalletFeePolicy>(); walletFeePolicy.Setup(w => w.GetMinimumFee(258, 50)) .Returns(new Money(5000)); var walletSettings = new WalletSettings(new NodeSettings(network: this.Network)); IScriptAddressReader scriptAddressReader = new ColdStakingDestinationReader(new ScriptAddressReader()); var walletRepository = new SQLiteWalletRepository(this.LoggerFactory.Object, dataFolder, this.Network, DateTimeProvider.Default, scriptAddressReader); walletRepository.TestMode = true; var walletManager = new ColdStakingManager(this.Network, chain, walletSettings, dataFolder, walletFeePolicy.Object, new Mock <IAsyncProvider>().Object, new NodeLifetime(), new ScriptAddressReader(), this.LoggerFactory.Object, DateTimeProvider.Default, walletRepository, new Mock <IBroadcasterManager>().Object); walletManager.Start(); (Wallet.Wallet wallet, ExtKey walletExtKey) = this.walletFixture.GenerateBlankWallet("myWallet", "password", walletRepository); (Wallet.Wallet coldWallet, ExtKey coldWalletExtKey) = this.walletFixture.GenerateBlankWallet("myColdWallet", "password", walletRepository); (Wallet.Wallet hotWallet, ExtKey hotWalletExtKey) = this.walletFixture.GenerateBlankWallet("myHotWallet", "password", walletRepository); (Wallet.Wallet withdrawalWallet, ExtKey withdrawalWalletExtKey) = this.walletFixture.GenerateBlankWallet("myWithDrawalWallet", "password", walletRepository); HdAccount withdrawalAccount = withdrawalWallet.AddNewAccount("password"); HdAddress withdrawalAddress = withdrawalAccount.ExternalAddresses.ElementAt(0); PubKey withdrawalPubKey = withdrawalAddress.Pubkey.GetDestinationPublicKeys(this.Network)[0]; HdAccount account = wallet.AddNewAccount("password"); HdAddress changeAddress = account.InternalAddresses.ElementAt(0); HdAddress spendingAddress = account.ExternalAddresses.ElementAt(0); HdAccount coldWalletAccount = coldWallet.AddNewAccount("password", ColdStakingManager.ColdWalletAccountIndex, ColdStakingManager.ColdWalletAccountName); HdAddress destinationColdAddress = coldWalletAccount.ExternalAddresses.ElementAt(0); PubKey destinationColdPubKey = destinationColdAddress.Pubkey.GetDestinationPublicKeys(this.Network)[0]; HdAccount hotWalletAccount = hotWallet.AddNewAccount("password", ColdStakingManager.HotWalletAccountIndex, ColdStakingManager.HotWalletAccountName); HdAddress destinationHotAddress = hotWalletAccount.ExternalAddresses.ElementAt(0); PubKey destinationHotPubKey = destinationHotAddress.Pubkey.GetDestinationPublicKeys(this.Network)[0]; // Generate a spendable transaction (uint256 blockhash, Block block)chainInfo = WalletTestsHelpers.CreateFirstBlockWithPaymentToAddress(chain, wallet.Network, spendingAddress); walletManager.ProcessBlock(chainInfo.block); // Create a cold staking setup transaction. Transaction transaction = this.CreateColdStakingSetupTransaction(wallet, "password", spendingAddress, destinationColdPubKey, destinationHotPubKey, changeAddress, new Money(7500), new Money(5000)); walletManager.ProcessBlock(WalletTestsHelpers.AppendTransactionInNewBlockToChain(chain, transaction)); HdAddress spentAddressResult = wallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(0); Assert.Single(spendingAddress.Transactions); Assert.Equal(transaction.GetHash(), spentAddressResult.Transactions.ElementAt(0).SpendingDetails.TransactionId); Assert.Equal(2, transaction.Outputs.Count); Assert.True(spentAddressResult.Transactions.ElementAt(0).SpendingDetails.Payments.Any(p => p.DestinationScriptPubKey == transaction.Outputs[1].ScriptPubKey && p.Amount == transaction.Outputs[1].Value)); Assert.Single(wallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).InternalAddresses.ElementAt(0).Transactions); TransactionData changeAddressResult = wallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).InternalAddresses.ElementAt(0).Transactions.ElementAt(0); Assert.Equal(transaction.GetHash(), changeAddressResult.Id); Assert.Equal(transaction.Outputs[0].Value, changeAddressResult.Amount); Assert.Equal(transaction.Outputs[0].ScriptPubKey, changeAddressResult.ScriptPubKey); // Verify that the transaction has been recorded in the cold wallet. var coldAccounts = coldWallet.GetAccounts(Wallet.Wallet.AllAccounts); Assert.Single(coldAccounts.ElementAt(0).ExternalAddresses.ElementAt(0).Transactions); TransactionData destinationColdAddressResult = coldAccounts.ElementAt(0).ExternalAddresses.ElementAt(0).Transactions.ElementAt(0); Assert.Equal(transaction.GetHash(), destinationColdAddressResult.Id); Assert.Equal(transaction.Outputs[1].Value, destinationColdAddressResult.Amount); Assert.Equal(transaction.Outputs[1].ScriptPubKey, destinationColdAddressResult.ScriptPubKey); // Verify that the transaction has been recorded in the hot wallet. var hotAccounts = hotWallet.GetAccounts(Wallet.Wallet.AllAccounts); Assert.Single(hotAccounts.ElementAt(0).ExternalAddresses.ElementAt(0).Transactions); TransactionData destinationHotAddressResult = hotAccounts.ElementAt(0).ExternalAddresses.ElementAt(0).Transactions.ElementAt(0); Assert.Equal(transaction.GetHash(), destinationHotAddressResult.Id); Assert.Equal(transaction.Outputs[1].Value, destinationHotAddressResult.Amount); Assert.Equal(transaction.Outputs[1].ScriptPubKey, destinationHotAddressResult.ScriptPubKey); // Will spend from the cold stake address and send the change back to the same address. Money balance = walletManager.GetSpendableTransactionsInAccount(new WalletAccountReference(coldWallet.Name, coldWalletAccount.Name), 0).Sum(x => x.Transaction.Amount); var coldStakeAddress = coldWallet.GetAccounts(Wallet.Wallet.AllAccounts).ElementAt(0).ExternalAddresses.ElementAt(0); Transaction withdrawalTransaction = this.CreateColdStakingWithdrawalTransaction(coldWallet, "password", coldStakeAddress, withdrawalPubKey, ColdStakingScriptTemplate.Instance.GenerateScriptPubKey(destinationHotPubKey.Hash, destinationColdPubKey.Hash), new Money(750), new Money(263)); // Process the transaction. walletManager.ProcessBlock(WalletTestsHelpers.AppendTransactionInNewBlockToChain(chain, withdrawalTransaction)); // Verify that the transaction has been recorded in the withdrawal wallet. Assert.Single(withdrawalWallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(0).Transactions); TransactionData withdrawalAddressResult = withdrawalWallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(0).Transactions .Where(t => t.Id == withdrawalTransaction.GetHash()).First(); Assert.Equal(withdrawalTransaction.GetHash(), withdrawalAddressResult.Id); Assert.Equal(withdrawalTransaction.Outputs[1].Value, withdrawalAddressResult.Amount); Assert.Equal(withdrawalTransaction.Outputs[1].ScriptPubKey, withdrawalAddressResult.ScriptPubKey); // Verify that the transaction has been recorded in the cold wallet. Assert.Equal(2, coldWallet.GetAccounts(Wallet.Wallet.AllAccounts).ElementAt(0).ExternalAddresses.ElementAt(0).Transactions.Count); TransactionData coldAddressResult = coldWallet.GetAccounts(Wallet.Wallet.AllAccounts).ElementAt(0).ExternalAddresses.ElementAt(0).Transactions .Where(t => t.Id == withdrawalTransaction.GetHash()).First(); Assert.Equal(withdrawalTransaction.GetHash(), coldAddressResult.Id); Assert.Equal(withdrawalTransaction.Outputs[0].Value, coldAddressResult.Amount); Assert.Equal(withdrawalTransaction.Outputs[0].ScriptPubKey, coldAddressResult.ScriptPubKey); // Verify that the transaction has been recorded in the hot wallet. Assert.Equal(2, hotWallet.GetAccounts(Wallet.Wallet.AllAccounts).ElementAt(0).ExternalAddresses.ElementAt(0).Transactions.Count); TransactionData hotAddressResult = hotWallet.GetAccounts(Wallet.Wallet.AllAccounts).ElementAt(0).ExternalAddresses.ElementAt(0).Transactions .Where(t => t.Id == withdrawalTransaction.GetHash()).First(); Assert.Equal(withdrawalTransaction.GetHash(), hotAddressResult.Id); Assert.Equal(withdrawalTransaction.Outputs[0].Value, hotAddressResult.Amount); Assert.Equal(withdrawalTransaction.Outputs[0].ScriptPubKey, hotAddressResult.ScriptPubKey); // Verify the hot amount returned by GetBalances. AccountBalance hotBalance = walletManager.GetBalances("myHotWallet", ColdStakingManager.HotWalletAccountName).FirstOrDefault(); Assert.Equal(hotBalance.AmountConfirmed, hotAddressResult.Amount); // Verify the cold amount returned by GetBalances. AccountBalance coldBalance = walletManager.GetBalances("myColdWallet", ColdStakingManager.ColdWalletAccountName).FirstOrDefault(); Assert.Equal(coldBalance.AmountConfirmed, coldAddressResult.Amount); }