public void GenerateBlocksOn_PowNetwork_ReturnsSuccess() { var powNode = new Mock <IFullNode>(); var consensusManager = new Mock <IConsensusManager>(); var walletManager = new Mock <IWalletManager>(); walletManager.Setup(f => f.GetWalletsNames()).Returns(new List <string> { wallet }); walletManager.Setup(f => f.GetAccounts(wallet)).Returns(new List <HdAccount> { new HdAccount { Name = account } }); HdAddress address = WalletTestsHelpers.CreateAddress(); walletManager.Setup(f => f.GetUnusedAddress(new WalletAccountReference(wallet, account))).Returns(address); var powMining = new Mock <IPowMining>(); powMining.Setup(f => f.GenerateBlocks(It.Is <ReserveScript>(r => r.ReserveFullNodeScript == address.Pubkey), 1, int.MaxValue)).Returns(new List <uint256> { new uint256(1255632623) }); powNode.Setup(f => f.NodeFeature <MiningFeature>(false)).Returns(new MiningFeature(new ConnectionManagerSettings(NodeSettings.Default(this.network)), KnownNetworks.RegTest, new MinerSettings(NodeSettings.Default(this.network)), NodeSettings.Default(this.network), this.loggerFactory, new Mock <ITimeSyncBehaviorState>().Object, powMining.Object, null)); var controller = new MiningController(consensusManager.Object, powNode.Object, this.loggerFactory, KnownNetworks.RegTest, powMining.Object, walletManager.Object); IActionResult result = controller.Generate(new MiningRequest { BlockCount = 1 }); powMining.VerifyAll(); walletManager.VerifyAll(); Assert.NotNull(result); var viewResult = Assert.IsType <JsonResult>(result); var resultValue = Assert.IsType <GenerateBlocksModel>(viewResult.Value); Assert.NotNull(resultValue); }
public NodeControllerTest() { this.network = KnownNetworks.TestNet; this.chainIndexer = WalletTestsHelpers.GenerateChainWithHeight(3, this.network); this.chainState = new Mock <IChainState>(); this.connectionManager = new Mock <IConnectionManager>(); this.connectionManager.Setup(c => c.Network).Returns(this.network); this.dateTimeProvider = new Mock <IDateTimeProvider>(); this.fullNode = new Mock <IFullNode>(); this.initialBlockDownloadState = new Mock <InitialBlockDownloadState>(this.chainState.Object, this.network, null, new Checkpoints(), DateTimeProvider.Default); this.nodeSettings = new NodeSettings(networksSelector: Networks.Networks.Bitcoin); this.consensusManager = new Mock <IConsensusManager>(); this.blockStore = new Mock <IBlockStore>(); this.getUnspentTransaction = new Mock <IGetUnspentTransaction>(); this.networkDifficulty = new Mock <INetworkDifficulty>(); this.pooledGetUnspentTransaction = new Mock <IPooledGetUnspentTransaction>(); this.pooledTransaction = new Mock <IPooledTransaction>(); this.asyncProvider = new Mock <IAsyncProvider>(); this.selfEndpointTracker = new Mock <ISelfEndpointTracker>(); this.controller = new NodeController( this.chainIndexer, this.chainState.Object, this.connectionManager.Object, this.dateTimeProvider.Object, this.fullNode.Object, this.LoggerFactory.Object, this.nodeSettings, this.network, this.asyncProvider.Object, this.selfEndpointTracker.Object, this.consensusManager.Object, this.blockStore.Object, this.initialBlockDownloadState.Object, new Mock <ISignals>().Object, this.getUnspentTransaction.Object, this.networkDifficulty.Object, this.pooledGetUnspentTransaction.Object, this.pooledTransaction.Object); }
public void ProcessBlock_NewBlock_PreviousHashSameAsWalletTip_PassesBlockToManagerWithoutReorg() { var result = WalletTestsHelpers.GenerateChainAndBlocksWithHeight(5, Network.StratisMain); this.chain = result.Chain; var blocks = result.Blocks; var lightWalletSyncManager = new LightWalletSyncManagerOverride(this.LoggerFactory.Object, this.walletManager.Object, this.chain, this.network, this.blockNotification.Object, this.signals.Object, this.nodeLifetime.Object, this.asyncLoopFactory.Object); lightWalletSyncManager.SetWalletTip(this.chain.GetBlock(3)); var blockToProcess = blocks[3]; lightWalletSyncManager.ProcessBlock(blockToProcess); //4th block in the list has same prevhash as which is loaded var expectedBlockHash = this.chain.GetBlock(4).Header.GetHash(); Assert.Equal(expectedBlockHash, lightWalletSyncManager.WalletTip.Header.GetHash()); this.walletManager.Verify(w => w.ProcessBlock(It.Is <Block>(b => b.GetHash() == blockToProcess.GetHash()), It.Is <ChainedBlock>(c => c.Header.GetHash() == expectedBlockHash))); }
public FullNodeControllerTest() { this.initialBlockSignature = Block.BlockSignature; Block.BlockSignature = false; this.fullNode = new Mock <IFullNode>(); this.chainState = new Mock <IChainState>(); this.connectionManager = new Mock <IConnectionManager>(); this.network = Network.TestNet; this.chain = WalletTestsHelpers.GenerateChainWithHeight(3, this.network); this.nodeSettings = new NodeSettings(); this.pooledTransaction = new Mock <IPooledTransaction>(); this.pooledGetUnspentTransaction = new Mock <IPooledGetUnspentTransaction>(); this.getUnspentTransaction = new Mock <IGetUnspentTransaction>(); this.consensusLoop = new Mock <IConsensusLoop>(); this.networkDifficulty = new Mock <INetworkDifficulty>(); this.controller = new FullNodeController(this.LoggerFactory.Object, this.pooledTransaction.Object, this.pooledGetUnspentTransaction.Object, this.getUnspentTransaction.Object, this.networkDifficulty.Object, this.consensusLoop.Object, this.fullNode.Object, this.nodeSettings, this.network, this.chain, this.chainState.Object, this.connectionManager.Object); }
public void StartStaking_ValidWalletAndPassword_StartsStaking_ReturnsOk() { Wallet.Wallet wallet = WalletTestsHelpers.GenerateBlankWallet("myWallet", "password1"); this.walletManager.Setup(w => w.GetWallet("myWallet")) .Returns(wallet); this.fullNode.Setup(f => f.NodeService <IWalletManager>(false)) .Returns(this.walletManager.Object); this.fullNode.Setup(f => f.NodeFeature <MiningFeature>(true)) .Returns(new MiningFeature(KnownNetworks.Main, new MinerSettings(Configuration.NodeSettings.Default()), Configuration.NodeSettings.Default(), this.LoggerFactory.Object, this.timeSyncBehaviorState.Object, null, this.posMinting.Object)); IActionResult result = this.controller.StartStaking(new StartStakingRequest() { Name = "myWallet", Password = "******" }); Assert.IsType <OkResult>(result); this.posMinting.Verify(p => p.Stake(It.Is <WalletSecret>(s => s.WalletName == "myWallet" && s.WalletPassword == "password1")), Times.Exactly(1)); }
public void ProcessBlock_NewBlock_BlockOnBestChain_WalletTipAfterNewTip_StartsSyncFromNewTip() { (ConcurrentChain Chain, List <Block> Blocks)result = WalletTestsHelpers.GenerateChainAndBlocksWithHeight(5, KnownNetworks.StratisMain); this.chain = result.Chain; List <Block> blocks = result.Blocks; var lightWalletSyncManager = new LightWalletSyncManagerOverride(this.LoggerFactory.Object, this.walletManager.Object, this.chain, this.network, this.blockNotification.Object, this.signals.Object, this.nodeLifetime.Object, this.asyncLoopFactory.Object, this.consensusManager.Object); // set 2nd block as tip lightWalletSyncManager.SetWalletTip(this.chain.GetBlock(4)); //process 4th block in the list does not have same prevhash as which is loaded Block blockToProcess = blocks[3]; lightWalletSyncManager.ProcessBlock(blockToProcess); uint256 expectedBlockHash = this.chain.GetBlock(4).Header.GetHash(); Assert.Equal(expectedBlockHash, lightWalletSyncManager.WalletTip.Header.GetHash()); this.walletManager.Verify(w => w.ProcessBlock(ExpectBlock(blocks[3]), ExpectChainedBlock(this.chain.GetBlock(4)))); }
public void SyncFromDate_ChainTipBeforeGivenDate_StartsAsyncLoopToCatchupChain() { var asyncLoop = new Mock <IAsyncLoop>(); this.chain = WalletTestsHelpers.GenerateChainWithHeight(2, this.network); var lightWalletSyncManager = new LightWalletSyncManager(this.LoggerFactory.Object, this.walletManager.Object, this.chain, this.network, this.blockNotification.Object, this.signals.Object, this.nodeLifetime.Object, this.asyncLoopFactory.Object, this.consensusManager.Object); lightWalletSyncManager.SyncFromDate(this.chain.Tip.Header.BlockTime.DateTime.AddDays(15)); this.asyncLoopFactory.Verify( a => a.RunUntil( "LightWalletSyncManager.SyncFromDate", It.IsAny <CancellationToken>(), It.IsAny <Func <bool> >(), It.IsAny <Action>(), It.IsAny <Action <Exception> >(), TimeSpans.FiveSeconds)); this.nodeLifetime.VerifyGet(n => n.ApplicationStopping); }
public void Start_WalletTipOnChain_NotHavingEarliestWalletHeight_StartsSyncFromOldestWalletCreationTime() { this.chain = WalletTestsHelpers.GenerateChainWithHeight(3, this.network); this.walletManager.Setup(w => w.ContainsWallets) .Returns(true); this.walletManager.Setup(w => w.WalletTipHash) .Returns(this.chain.GetBlock(2).HashBlock); this.walletManager.Setup(w => w.GetEarliestWalletHeight()) .Returns((int?)null); this.walletManager.Setup(w => w.GetOldestWalletCreationTime()) .Returns(new DateTimeOffset(new DateTime(2017, 1, 2))); var lightWalletSyncManager = new LightWalletSyncManager(this.LoggerFactory.Object, this.walletManager.Object, this.chain, this.network, this.blockNotification.Object, this.signals.Object, this.nodeLifetime.Object, this.asyncLoopFactory.Object, this.consensusManager.Object); lightWalletSyncManager.Start(); Assert.Equal(lightWalletSyncManager.WalletTip.HashBlock, this.chain.GetBlock(2).HashBlock); this.blockNotification.Verify(b => b.SyncFrom(this.chain.GetBlock(2).HashBlock)); }
public void Given_GetMaximumSpendableAmountIsCalled_When_ThereAreNoConfirmedSpendableFound_Then_MaxAmountReturnsAsTheSumOfUnconfirmedTxs() { DataFolder dataFolder = CreateDataFolder(this); var walletFeePolicy = new Mock <IWalletFeePolicy>(); walletFeePolicy.Setup(w => w.GetFeeRate(FeeType.Low.ToConfirmations())).Returns(new FeeRate(20000)); var walletManager = new WalletManager(this.LoggerFactory.Object, this.Network, new ChainIndexer(this.Network), new WalletSettings(NodeSettings.Default(this.Network)), dataFolder, new Mock <IWalletFeePolicy>().Object, new Mock <IAsyncProvider>().Object, new NodeLifetime(), DateTimeProvider.Default, this.scriptAddressReader); var walletTransactionHandler = new WalletTransactionHandler(this.LoggerFactory.Object, walletManager, walletFeePolicy.Object, this.Network, this.standardTransactionPolicy); HdAccount account = WalletTestsHelpers.CreateAccount("account 1"); HdAddress accountAddress1 = WalletTestsHelpers.CreateAddress(); accountAddress1.Transactions.Add(WalletTestsHelpers.CreateTransaction(new uint256(1), new Money(15000), null, null, null, new Key().ScriptPubKey)); accountAddress1.Transactions.Add(WalletTestsHelpers.CreateTransaction(new uint256(2), new Money(10000), null, null, null, new Key().ScriptPubKey)); HdAddress accountAddress2 = WalletTestsHelpers.CreateAddress(); accountAddress2.Transactions.Add(WalletTestsHelpers.CreateTransaction(new uint256(3), new Money(20000), null, null, null, new Key().ScriptPubKey)); accountAddress2.Transactions.Add(WalletTestsHelpers.CreateTransaction(new uint256(4), new Money(120000), null, null, null, new Key().ScriptPubKey)); account.ExternalAddresses.Add(accountAddress1); account.InternalAddresses.Add(accountAddress2); Types.Wallet wallet = WalletTestsHelpers.CreateWallet("wallet1"); wallet.AccountsRoot.Add(new AccountRoot() { Accounts = new List <HdAccount> { account } }); walletManager.Wallets.Add(wallet); (Money max, Money fee)result = walletTransactionHandler.GetMaximumSpendableAmount(new WalletAccountReference("wallet1", "account 1"), FeeType.Low, true); Assert.Equal(new Money(165000), result.max + result.fee); }
public void GetBlockCount_ReturnsHeightFromChainState() { var logger = new Mock <ILoggerFactory>(); var store = new Mock <IBlockStore>(); var chainState = new Mock <IChainState>(); var addressIndexer = new Mock <IAddressIndexer>(); ChainIndexer chainIndexer = WalletTestsHelpers.GenerateChainWithHeight(3, KnownNetworks.StratisTest); logger.Setup(l => l.CreateLogger(It.IsAny <string>())).Returns(Mock.Of <ILogger>); chainState.Setup(c => c.ConsensusTip) .Returns(chainIndexer.GetHeader(2)); var controller = new BlockStoreController(KnownNetworks.StratisTest, logger.Object, store.Object, chainState.Object, chainIndexer, addressIndexer.Object); var json = (JsonResult)controller.GetBlockCount(); int result = int.Parse(json.Value.ToString()); Assert.Equal(2, result); }
public NodeControllerTest() { this.fullNode = new Mock <IFullNode>(); this.blockStore = new Mock <IBlockStore>(); this.chainState = new Mock <IChainState>(); this.dateTimeProvider = new Mock <IDateTimeProvider>(); this.connectionManager = new Mock <IConnectionManager>(); this.network = KnownNetworks.TestNet; this.connectionManager.Setup(c => c.Network).Returns(this.network); this.chain = WalletTestsHelpers.GenerateChainWithHeight(3, this.network); this.nodeSettings = new NodeSettings(); this.pooledTransaction = new Mock <IPooledTransaction>(); this.pooledGetUnspentTransaction = new Mock <IPooledGetUnspentTransaction>(); this.getUnspentTransaction = new Mock <IGetUnspentTransaction>(); this.networkDifficulty = new Mock <INetworkDifficulty>(); 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, this.blockStore.Object); }
public void Given_GetMaximumSpendableAmountIsCalledForConfirmedTransactions_When_ThereAreNoConfirmedSpendableFound_Then_MaxAmountReturnsAsZero() { DataFolder dataFolder = CreateDataFolder(this); var walletManager = new WalletManager(this.LoggerFactory.Object, this.Network, new ChainIndexer(this.Network), new WalletSettings(NodeSettings.Default(this.Network)), dataFolder, new Mock <IWalletFeePolicy>().Object, new Mock <IAsyncProvider>().Object, new NodeLifetime(), DateTimeProvider.Default, this.scriptAddressReader); var walletTransactionHandler = new WalletTransactionHandler(this.LoggerFactory.Object, walletManager, It.IsAny <WalletFeePolicy>(), this.Network, this.standardTransactionPolicy); HdAccount account = WalletTestsHelpers.CreateAccount("account 1"); Types.Wallet wallet = WalletTestsHelpers.CreateWallet("wallet1"); HdAddress accountAddress1 = WalletTestsHelpers.CreateAddress(); wallet.walletStore.InsertOrUpdate(WalletTestsHelpers.CreateTransaction(new uint256(1), new Money(15000), null, address: accountAddress1.Address)); wallet.walletStore.InsertOrUpdate(WalletTestsHelpers.CreateTransaction(new uint256(2), new Money(10000), null, address: accountAddress1.Address)); HdAddress accountAddress2 = WalletTestsHelpers.CreateAddress(); wallet.walletStore.InsertOrUpdate(WalletTestsHelpers.CreateTransaction(new uint256(3), new Money(20000), null, address: accountAddress2.Address)); wallet.walletStore.InsertOrUpdate(WalletTestsHelpers.CreateTransaction(new uint256(4), new Money(120000), null, address: accountAddress2.Address)); account.ExternalAddresses.Add(accountAddress1); account.InternalAddresses.Add(accountAddress2); wallet.AccountsRoot.Add(new AccountRoot() { Accounts = new List <HdAccount> { account } }); walletManager.Wallets.Add(wallet); (Money max, Money fee)result = walletTransactionHandler.GetMaximumSpendableAmount(new WalletAccountReference("wallet1", "account 1"), FeeType.Low, false); Assert.Equal(Money.Zero, result.max); Assert.Equal(Money.Zero, result.fee); }
public void ProcessBlock_NewBlock_PreviousHashSameAsWalletTip_PassesBlockToManagerWithoutReorg() { (ChainIndexer Chain, List <Block> Blocks)result = WalletTestsHelpers.GenerateChainAndBlocksWithHeight(5, KnownNetworks.StratisMain); this.chainIndexer = result.Chain; List <Block> blocks = result.Blocks; var walletSyncManager = new WalletSyncManagerOverride(this.LoggerFactory.Object, this.walletManager.Object, this.chainIndexer, KnownNetworks.StratisMain, this.blockStore.Object, this.storeSettings, this.signals, this.asyncProvider); walletSyncManager.SetWalletTip(this.chainIndexer.GetHeader(3)); Block blockToProcess = blocks[3]; blockToProcess.SetPrivatePropertyValue("BlockSize", 1L); walletSyncManager.ProcessBlock(blockToProcess); //4th block in the list has same prevhash as which is loaded uint256 expectedBlockHash = this.AssertTipBlockHash(walletSyncManager, 4); this.AssertTipBlockHash(walletSyncManager, 4); this.walletManager.Verify(w => w.ProcessBlock(It.Is <Block>(b => b.GetHash() == blockToProcess.GetHash()), It.Is <ChainedHeader>(c => c.Header.GetHash() == expectedBlockHash))); }
public void ProcessBlock_NewBlock_BlockOnBestChain_WalletTipBeforeNewTip_StartsSyncFromWalletTipWithoutProcessingBlock() { (ConcurrentChain Chain, List <Block> Blocks)result = WalletTestsHelpers.GenerateChainAndBlocksWithHeight(5, Network.StratisMain); this.chain = result.Chain; List <Block> blocks = result.Blocks; var lightWalletSyncManager = new LightWalletSyncManagerOverride(this.LoggerFactory.Object, this.walletManager.Object, this.chain, this.network, this.blockNotification.Object, this.signals.Object, this.nodeLifetime.Object, this.asyncLoopFactory.Object); // set 2nd block as tip lightWalletSyncManager.SetWalletTip(this.chain.GetBlock(2)); //process 4th block in the list does not have same prevhash as which is loaded Block blockToProcess = blocks[3]; lightWalletSyncManager.ProcessBlock(blockToProcess); this.blockNotification.Verify(b => b.SyncFrom(this.chain.GetBlock(2).HashBlock)); uint256 expectedBlockHash = this.chain.GetBlock(2).Header.GetHash(); Assert.Equal(expectedBlockHash, lightWalletSyncManager.WalletTip.Header.GetHash()); this.walletManager.Verify(w => w.ProcessBlock(It.IsAny <Block>(), It.IsAny <ChainedHeader>()), Times.Exactly(0)); }
public void Generate_Blocks_ReturnsSuccess() { const string wallet = "wallet"; const string account = "account"; this.walletManager.Setup(w => w.GetWalletsNames()).Returns(new List <string> { wallet }); this.walletManager.Setup(w => w.GetAccounts(wallet)).Returns(new List <HdAccount> { new HdAccount { Name = account } }); HdAddress address = WalletTestsHelpers.CreateAddress(); this.walletManager.Setup(w => w.GetUnusedAddress(new WalletAccountReference(wallet, account))).Returns(address); this.powMining.Setup(p => p.GenerateBlocks(It.Is <ReserveScript>(r => r.ReserveFullNodeScript == address.Pubkey), 1, int.MaxValue)) .Returns(new List <uint256> { new uint256(1255632623) }); this.controller = new MiningController(this.powMining.Object, this.LoggerFactory.Object, this.walletManager.Object); IActionResult result = this.controller.Generate(new MiningRequest { BlockCount = 1 }); this.walletManager.VerifyAll(); this.powMining.VerifyAll(); Assert.NotNull(result); var viewResult = Assert.IsType <JsonResult>(result); var resultValue = Assert.IsType <GenerateBlocksModel>(viewResult.Value); Assert.NotNull(resultValue); }
/// <summary> /// Creates a new wallet. /// </summary> /// <remarks> /// If it's the first time this wallet is created within this class, it is added to a collection for use by other tests. /// If the same parameters have already been used to create a wallet, the wallet will be retrieved from the internal collection and a copy of this wallet will be returned. /// </remarks> /// <param name="name">The name.</param> /// <param name="password">The password.</param> /// <returns>The generated wallet.</returns> public Features.Wallet.Types.Wallet GenerateBlankWallet(string name, string password) { if (this.walletsGenerated.TryGetValue((name, password), out Features.Wallet.Types.Wallet existingWallet)) { string serializedExistingWallet = JsonConvert.SerializeObject(existingWallet, Formatting.None); var wal1 = JsonConvert.DeserializeObject <Features.Wallet.Types.Wallet>(serializedExistingWallet); wal1.BlockLocator = existingWallet.BlockLocator; wal1.AccountsRoot.Single().LastBlockSyncedHash = existingWallet.AccountsRoot.Single().LastBlockSyncedHash; wal1.AccountsRoot.Single().LastBlockSyncedHeight = existingWallet.AccountsRoot.Single().LastBlockSyncedHeight; wal1.walletStore = new WalletMemoryStore(); var data1 = wal1.walletStore.GetData(); data1.BlockLocator = existingWallet.BlockLocator; data1.WalletName = existingWallet.Name; data1.WalletTip = new Utilities.HashHeightPair(existingWallet.AccountsRoot.Single().LastBlockSyncedHash, existingWallet.AccountsRoot.Single().LastBlockSyncedHeight.Value); wal1.walletStore.SetData(data1); return(wal1); } Features.Wallet.Types.Wallet newWallet = WalletTestsHelpers.GenerateBlankWallet(name, password); this.walletsGenerated.Add((name, password), newWallet); string serializedNewWallet = JsonConvert.SerializeObject(newWallet, Formatting.None); var wal = JsonConvert.DeserializeObject <Features.Wallet.Types.Wallet>(serializedNewWallet); wal.walletStore = new WalletMemoryStore(); wal.BlockLocator = newWallet.BlockLocator; wal.AccountsRoot.Single().LastBlockSyncedHash = newWallet.AccountsRoot.Single().LastBlockSyncedHash; wal.AccountsRoot.Single().LastBlockSyncedHeight = newWallet.AccountsRoot.Single().LastBlockSyncedHeight; var data = wal.walletStore.GetData(); data.BlockLocator = wal.BlockLocator; data.WalletName = wal.Name; data.WalletTip = new Utilities.HashHeightPair(wal.AccountsRoot.Single().LastBlockSyncedHash, wal.AccountsRoot.Single().LastBlockSyncedHeight.Value); wal.walletStore.SetData(data); return(wal); }
public void Stop_DisposesDependencies() { this.chain = WalletTestsHelpers.GenerateChainWithHeight(1, this.network); var blockSub = new Mock <IDisposable>(); var transSub = new Mock <IDisposable>(); this.signals.Setup(s => s.SubscribeForBlocksConnected(It.IsAny <BlockObserver>())) .Returns(blockSub.Object); this.signals.Setup(s => s.SubscribeForTransactions(It.IsAny <TransactionObserver>())) .Returns(transSub.Object); this.walletManager.SetupGet(w => w.ContainsWallets) .Returns(false); var asyncLoop = new Mock <IAsyncLoop>(); this.asyncLoopFactory.Setup( a => a.RunUntil( "LightWalletSyncManager.SyncFromHeight", It.IsAny <CancellationToken>(), It.IsAny <Func <bool> >(), It.IsAny <Action>(), It.IsAny <Action <Exception> >(), TimeSpans.FiveSeconds)) .Returns(asyncLoop.Object); var lightWalletSyncManager = new LightWalletSyncManager(this.LoggerFactory.Object, this.walletManager.Object, this.chain, this.network, this.blockNotification.Object, this.signals.Object, this.nodeLifetime.Object, this.asyncLoopFactory.Object, this.consensusManager.Object); lightWalletSyncManager.Start(); lightWalletSyncManager.SyncFromHeight(3); lightWalletSyncManager.Stop(); asyncLoop.Verify(b => b.Dispose()); blockSub.Verify(b => b.Dispose()); transSub.Verify(b => b.Dispose()); }
public NodeControllerTest() { this.network = KnownNetworks.TestNet; this.chainIndexer = WalletTestsHelpers.GenerateChainWithHeight(3, this.network); this.chainState = new Mock <IChainState>(); this.connectionManager = new Mock <IConnectionManager>(); this.connectionManager.Setup(c => c.Network).Returns(this.network); this.dateTimeProvider = new Mock <IDateTimeProvider>(); this.fullNode = new Mock <IFullNode>(); this.nodeSettings = new NodeSettings(networksSelector: Networks.Bitcoin.Networks.Bitcoin); this.peerBanning = new Mock <IPeerBanning>(); this.blockStore = new Mock <IBlockStore>(); this.getUnspentTransaction = new Mock <IGetUnspentTransaction>(); this.networkDifficulty = new Mock <INetworkDifficulty>(); this.pooledGetUnspentTransaction = new Mock <IPooledGetUnspentTransaction>(); this.pooledTransaction = new Mock <IPooledTransaction>(); this.asyncProvider = new Mock <IAsyncProvider>(); this.selfEndpointTracker = new Mock <ISelfEndpointTracker>(); this.consensusManager = new Mock <IConsensusManager>(); this.CreateNewController(); }
public void StartStaking_InvalidWalletPassword_ReturnsBadRequest() { Wallet.Wallet wallet = WalletTestsHelpers.GenerateBlankWallet("myWallet", "password1"); this.walletManager.Setup(w => w.GetWallet("myWallet")) .Returns(wallet); this.fullNode.Setup(f => f.NodeService <IWalletManager>(false)) .Returns(this.walletManager.Object); IActionResult result = this.controller.StartStaking(new StartStakingRequest() { Name = "myWallet", Password = "******" }); var errorResult = Assert.IsType <ErrorResult>(result); var errorResponse = Assert.IsType <ErrorResponse>(errorResult.Value); Assert.Single(errorResponse.Errors); ErrorModel error = errorResponse.Errors[0]; Assert.Equal(400, error.Status); Assert.Equal("Invalid password (or invalid Network)", error.Message); }
public void BuildTransactionFeeTooLowDefaultsToMinimumFee() { var walletFeePolicy = new Mock <IWalletFeePolicy>(); walletFeePolicy.Setup(w => w.GetFeeRate(FeeType.Low.ToConfirmations())) .Returns(new FeeRate(0)); Types.Wallet wallet = WalletTestsHelpers.GenerateBlankWallet("myWallet1", "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)destinationKeys = WalletTestsHelpers.GenerateAddressKeys(wallet, accountKeys.ExtPubKey, "0/1"); (PubKey PubKey, BitcoinPubKeyAddress Address)changeKeys = WalletTestsHelpers.GenerateAddressKeys(wallet, accountKeys.ExtPubKey, "1/0"); var address = 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 chain = new ChainIndexer(wallet.Network); WalletTestsHelpers.AddBlocksWithCoinbaseToChain(wallet.walletStore as WalletMemoryStore, wallet.Network, chain, address); wallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount { Index = 0, Name = "account1", HdPath = "m/44'/0'/0'", ExtendedPubKey = accountKeys.ExtPubKey, ExternalAddresses = new List <HdAddress> { address }, InternalAddresses = new List <HdAddress> { 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>() } } }); string dataDir = "TestData/WalletTransactionHandlerTest/BuildTransactionFeeTooLowThrowsWalletException"; var nodeSettings = new NodeSettings(network: this.Network, args: new string[] { $"-datadir={dataDir}" }); var walletManager = new WalletManager(this.LoggerFactory.Object, this.Network, chain, new WalletSettings(nodeSettings), new DataFolder(nodeSettings.DataDir), walletFeePolicy.Object, new Mock <IAsyncProvider>().Object, new NodeLifetime(), DateTimeProvider.Default, this.scriptAddressReader); var walletTransactionHandler = new WalletTransactionHandler(this.LoggerFactory.Object, walletManager, walletFeePolicy.Object, this.Network, this.standardTransactionPolicy); walletManager.Wallets.Add(wallet); var walletReference = new WalletAccountReference { AccountName = "account1", WalletName = "myWallet1" }; TransactionBuildContext context = CreateContext(this.Network, walletReference, "password", destinationKeys.PubKey.ScriptPubKey, new Money(7500), FeeType.Low, 0); Transaction transaction = walletTransactionHandler.BuildTransaction(context); Assert.Equal(new Money(this.Network.MinTxFee, MoneyUnit.Satoshi), context.TransactionFee); }
private WalletTransactionHandlerTestContext SetupWallet() { DataFolder dataFolder = CreateDataFolder(this); Types.Wallet wallet = WalletTestsHelpers.GenerateBlankWallet("myWallet1", "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)destinationKeys = WalletTestsHelpers.GenerateAddressKeys(wallet, accountKeys.ExtPubKey, "0/1"); var address = 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 chain = new ChainIndexer(wallet.Network); WalletTestsHelpers.AddBlocksWithCoinbaseToChain(wallet.walletStore as WalletMemoryStore, wallet.Network, chain, address); TransactionOutputData addressTransaction = wallet.walletStore.GetForAddress(address.Address).First(); wallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount { Index = 0, Name = "account1", HdPath = "m/44'/0'/0'", ExtendedPubKey = accountKeys.ExtPubKey, ExternalAddresses = new List <HdAddress> { address }, InternalAddresses = new List <HdAddress>() }); var walletFeePolicy = new Mock <IWalletFeePolicy>(); walletFeePolicy.Setup(w => w.GetFeeRate(FeeType.Low.ToConfirmations())) .Returns(new FeeRate(20000)); var walletManager = new WalletManager(this.LoggerFactory.Object, this.Network, chain, new WalletSettings(NodeSettings.Default(this.Network)), dataFolder, walletFeePolicy.Object, new Mock <IAsyncProvider>().Object, new NodeLifetime(), DateTimeProvider.Default, this.scriptAddressReader); var walletTransactionHandler = new WalletTransactionHandler(this.LoggerFactory.Object, walletManager, walletFeePolicy.Object, this.Network, this.standardTransactionPolicy); walletManager.Wallets.Add(wallet); var walletReference = new WalletAccountReference { AccountName = "account1", WalletName = "myWallet1" }; return(new WalletTransactionHandlerTestContext { Wallet = wallet, AccountKeys = accountKeys, DestinationKeys = destinationKeys, AddressTransaction = addressTransaction, WalletTransactionHandler = walletTransactionHandler, WalletReference = walletReference }); }
/// <summary> /// Creates a new wallet. /// </summary> /// <param name="name">The name.</param> /// <param name="password">The password.</param> /// <returns>The generated wallet.</returns> public (Features.Wallet.Wallet, ExtKey) GenerateBlankWallet(string name, string password, IWalletRepository walletRepository = null) { (Features.Wallet.Wallet newWallet, ExtKey extKey) = WalletTestsHelpers.GenerateBlankWalletWithExtKey(name, password, walletRepository); return(newWallet, extKey); }
public void FundTransaction_Given__a_wallet_has_enough_inputs__When__adding_inputs_to_an_existing_transaction__Then__the_transaction_is_funded_successfully() { DataFolder dataFolder = CreateDataFolder(this); Types.Wallet wallet = WalletTestsHelpers.GenerateBlankWallet("myWallet1", "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)destinationKeys1 = WalletTestsHelpers.GenerateAddressKeys(wallet, accountKeys.ExtPubKey, "0/1"); (PubKey PubKey, BitcoinPubKeyAddress Address)destinationKeys2 = WalletTestsHelpers.GenerateAddressKeys(wallet, accountKeys.ExtPubKey, "0/2"); (PubKey PubKey, BitcoinPubKeyAddress Address)destinationKeys3 = WalletTestsHelpers.GenerateAddressKeys(wallet, accountKeys.ExtPubKey, "0/3"); var address = 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>() }; // wallet with 4 coinbase outputs of 50 = 200 Bitcoin var chain = new ChainIndexer(wallet.Network); WalletTestsHelpers.AddBlocksWithCoinbaseToChain(wallet.walletStore as WalletMemoryStore, wallet.Network, chain, address, 4); wallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount { Index = 0, Name = "account1", HdPath = "m/44'/0'/0'", ExtendedPubKey = accountKeys.ExtPubKey, ExternalAddresses = new List <HdAddress> { address }, InternalAddresses = new List <HdAddress>() }); var walletFeePolicy = new Mock <IWalletFeePolicy>(); walletFeePolicy.Setup(w => w.GetFeeRate(FeeType.Low.ToConfirmations())).Returns(new FeeRate(20000)); var overrideFeeRate = new FeeRate(20000); var walletManager = new WalletManager(this.LoggerFactory.Object, this.Network, chain, new WalletSettings(NodeSettings.Default(this.Network)), dataFolder, walletFeePolicy.Object, new Mock <IAsyncProvider>().Object, new NodeLifetime(), DateTimeProvider.Default, this.scriptAddressReader); var walletTransactionHandler = new WalletTransactionHandler(this.LoggerFactory.Object, walletManager, walletFeePolicy.Object, this.Network, this.standardTransactionPolicy); walletManager.Wallets.Add(wallet); var walletReference = new WalletAccountReference { AccountName = "account1", WalletName = "myWallet1" }; // create a trx with 3 outputs 50 + 50 + 50 = 150 BTC var context = new TransactionBuildContext(this.Network) { AccountReference = walletReference, MinConfirmations = 0, FeeType = FeeType.Low, WalletPassword = "******", Recipients = new[] { new Recipient { Amount = new Money(50, MoneyUnit.BTC), ScriptPubKey = destinationKeys1.PubKey.ScriptPubKey }, new Recipient { Amount = new Money(50, MoneyUnit.BTC), ScriptPubKey = destinationKeys2.PubKey.ScriptPubKey }, new Recipient { Amount = new Money(50, MoneyUnit.BTC), ScriptPubKey = destinationKeys3.PubKey.ScriptPubKey } }.ToList() }; Transaction fundTransaction = walletTransactionHandler.BuildTransaction(context); Assert.Equal(4, fundTransaction.Inputs.Count); // 4 inputs Assert.Equal(4, fundTransaction.Outputs.Count); // 3 outputs with change // remove the change output fundTransaction.Outputs.Remove(fundTransaction.Outputs.First(f => f.ScriptPubKey == context.ChangeAddress.ScriptPubKey)); // remove 3 inputs they will be added back by fund transaction fundTransaction.Inputs.RemoveAt(3); fundTransaction.Inputs.RemoveAt(2); fundTransaction.Inputs.RemoveAt(1); Assert.Single(fundTransaction.Inputs); // 4 inputs Transaction fundTransactionClone = this.Network.CreateTransaction(fundTransaction.ToBytes()); var fundContext = new TransactionBuildContext(this.Network) { AccountReference = walletReference, MinConfirmations = 0, FeeType = FeeType.Low, WalletPassword = "******", Recipients = new List <Recipient>() }; fundContext.OverrideFeeRate = overrideFeeRate; walletTransactionHandler.FundTransaction(fundContext, fundTransaction); foreach (TxIn input in fundTransactionClone.Inputs) // all original inputs are still in the trx { Assert.Contains(fundTransaction.Inputs, a => a.PrevOut == input.PrevOut); } Assert.Equal(4, fundTransaction.Inputs.Count); // we expect 4 inputs Assert.Equal(4, fundTransaction.Outputs.Count); // we expect 4 outputs Assert.Equal(new Money(200, MoneyUnit.BTC) - fundContext.TransactionFee, fundTransaction.TotalOut); Assert.Contains(fundTransaction.Outputs, a => a.ScriptPubKey == destinationKeys1.PubKey.ScriptPubKey); Assert.Contains(fundTransaction.Outputs, a => a.ScriptPubKey == destinationKeys2.PubKey.ScriptPubKey); Assert.Contains(fundTransaction.Outputs, a => a.ScriptPubKey == destinationKeys3.PubKey.ScriptPubKey); }
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 ProcessBlock_NewBlock_BlockNotOnBestChain_ReOrgWalletManagerUsingBlockStoreCache() { (ChainIndexer LeftChain, ChainIndexer RightChain, List <Block> LeftForkBlocks, List <Block> RightForkBlocks)result = WalletTestsHelpers.GenerateForkedChainAndBlocksWithHeight(5, KnownNetworks.StratisMain, 2); // left side chain containing the 'old' fork. ChainIndexer leftChainIndexer = result.LeftChain; // right side chain containing the 'new' fork. Work on this. this.chainIndexer = result.RightChain; var walletSyncManager = new WalletSyncManagerOverride(this.LoggerFactory.Object, this.walletManager.Object, this.chainIndexer, KnownNetworks.StratisMain, this.blockStore.Object, this.storeSettings, this.signals, this.asyncProvider); // setup blockstore to return blocks on the chain. this.blockStore.Setup(b => b.GetBlock(It.IsAny <uint256>())) .Returns((uint256 hashblock) => { return(result.LeftForkBlocks.Union(result.RightForkBlocks).Single(b => b.GetHash() == hashblock)); }); // set 4th block of the old chain as tip. 2 ahead of the fork thus not being on the right chain. walletSyncManager.SetWalletTip(leftChainIndexer.GetHeader(result.LeftForkBlocks[3].Header.GetHash())); //process 5th block from the right side of the fork in the list does not have same prevhash as which is loaded. Block blockToProcess = result.RightForkBlocks[4]; blockToProcess.SetPrivatePropertyValue("BlockSize", 1L); walletSyncManager.ProcessBlock(blockToProcess); this.AssertTipBlockHash(walletSyncManager, 5); // walletmanager removes all blocks up to the fork. this.walletManager.Verify(w => w.RemoveBlocks(ExpectChainedBlock(this.chainIndexer.GetHeader(2)))); //verify manager processes each missing block until caught up. // height 3 this.walletManager.Verify(w => w.ProcessBlock(ExpectBlock(result.RightForkBlocks[2]), ExpectChainedBlock(this.chainIndexer.GetHeader(3)))); // height 4 this.walletManager.Verify(w => w.ProcessBlock(ExpectBlock(result.RightForkBlocks[3]), ExpectChainedBlock(this.chainIndexer.GetHeader(4)))); // height 5 this.walletManager.Verify(w => w.ProcessBlock(ExpectBlock(result.RightForkBlocks[4]), ExpectChainedBlock(this.chainIndexer.GetHeader(5))), Times.Exactly(2)); }
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); }
public MiningRPCControllerFixture() { this.wallet = WalletTestsHelpers.GenerateBlankWallet("myWallet", "password1"); }
public void GetHistoryWithValidModelWithSkipAndTakeReturnsWalletHistoryModel() { ulong gasPrice = SmartContractMempoolValidator.MinGasPrice; int vmVersion = 1; var gasLimit = (Stratis.SmartContracts.RuntimeObserver.Gas)(SmartContractFormatLogic.GasLimitMaximum / 2); var contractTxData = new ContractTxData(vmVersion, gasPrice, gasLimit, new byte[] { 0, 1, 2, 3 }); var callDataSerializer = new CallDataSerializer(new ContractPrimitiveSerializer(new SmartContractsRegTest())); var contractCreateScript = new Script(callDataSerializer.Serialize(contractTxData)); string walletName = "myWallet"; HdAddress address = WalletTestsHelpers.CreateAddress(); const int totalHistoryLength = 100; const int toSkip = 10; const int toTake = 10; for (int i = 0; i < totalHistoryLength; i++) { TransactionData createTransaction = WalletTestsHelpers.CreateTransaction(new uint256((ulong)i), new Money(500000), 100 + i); createTransaction.SpendingDetails = new SpendingDetails { BlockHeight = 100 + i, CreationTime = DateTimeOffset.Now, TransactionId = new uint256((ulong)i), Payments = new List <PaymentDetails> { new PaymentDetails { Amount = new Money(100000), DestinationScriptPubKey = contractCreateScript } } }; address.Transactions.Add(createTransaction); } var addresses = new List <HdAddress> { address }; Features.Wallet.Wallet wallet = WalletTestsHelpers.CreateWallet(walletName); var account = new HdAccount { ExternalAddresses = addresses }; wallet.AccountsRoot.Add(new AccountRoot() { Accounts = new List <HdAccount> { account } }); List <FlatHistory> flat = addresses.SelectMany(s => s.Transactions.Select(t => new FlatHistory { Address = s, Transaction = t })).ToList(); var accountsHistory = new List <AccountHistory> { new AccountHistory { History = flat, Account = account } }; this.walletManager.Setup(w => w.GetHistory(walletName, It.IsAny <string>())).Returns(accountsHistory); this.walletManager.Setup(w => w.GetWalletByName(walletName)).Returns(wallet); this.walletManager.Setup(w => w.GetAccounts(walletName)).Returns(new List <HdAccount> { account }); var receipt = new Receipt(null, 12345, new Log[0], null, null, null, uint160.Zero, true, null, null, 2, 100000); var receiptList = new List <Receipt>(); for (int i = 0; i < totalHistoryLength; i++) { receiptList.Add(receipt); } this.receiptRepository.Setup(x => x.RetrieveMany(It.IsAny <IList <uint256> >())) .Returns(receiptList); this.callDataSerializer.Setup(x => x.Deserialize(It.IsAny <byte[]>())) .Returns(Result.Ok(new ContractTxData(0, 0, (Stratis.SmartContracts.RuntimeObserver.Gas) 0, new uint160(0), null, null))); var controller = new SmartContractWalletController( this.broadcasterManager.Object, this.callDataSerializer.Object, this.connectionManager.Object, this.loggerFactory.Object, this.network, this.receiptRepository.Object, this.walletManager.Object, this.smartContractTransactionService.Object); var request = new GetHistoryRequest { Address = address.Address, WalletName = walletName, Skip = toSkip, Take = toTake }; IActionResult result = controller.GetHistory(request); JsonResult viewResult = Assert.IsType <JsonResult>(result); var model = viewResult.Value as IEnumerable <ContractTransactionItem>; Assert.NotNull(model); Assert.Equal(toTake, model.Count()); Assert.Equal(new uint256(toSkip), model.ElementAt(toTake - 1).Hash); Assert.Equal(new uint256(toSkip + toTake - 1), model.ElementAt(0).Hash); }
public void ProcessBlock_BlockNotOnBestChain_ReorgWalletTipAfterNewTip_StartProcessingFromFork() { (ConcurrentChain LeftChain, ConcurrentChain RightChain, List <Block> LeftForkBlocks, List <Block> RightForkBlocks)result = WalletTestsHelpers.GenerateForkedChainAndBlocksWithHeight(5, KnownNetworks.StratisMain, 2); // left side chain containing the 'old' fork. ConcurrentChain leftChain = result.LeftChain; // right side chain containing the 'new' fork. Work on this. this.chain = result.RightChain; var lightWalletSyncManager = new LightWalletSyncManagerOverride(this.LoggerFactory.Object, this.walletManager.Object, this.chain, this.network, this.blockNotification.Object, this.signals.Object, this.nodeLifetime.Object, this.asyncLoopFactory.Object, this.consensusManager.Object); // set 4th block of the old chain as tip. 2 ahead of the fork thus not being on the right chain. lightWalletSyncManager.SetWalletTip(leftChain.GetBlock(result.LeftForkBlocks[3].Header.GetHash())); //process 2nd block from the right side of the fork in the list does not have same prevhash as which is loaded. Block blockToProcess = result.RightForkBlocks[1]; lightWalletSyncManager.ProcessBlock(blockToProcess); // walletmanager removes all blocks up to the fork. this.walletManager.Verify(w => w.RemoveBlocks(ExpectChainedBlock(this.chain.GetBlock(2)))); //expect the wallet tip to be set to the fork and do not start the sync to be started from that block. Assert.Equal(this.chain.GetBlock(2).HashBlock, lightWalletSyncManager.WalletTip.HashBlock); this.blockNotification.Verify(w => w.SyncFrom(It.IsAny <uint256>()), Times.Exactly(0)); // expect the block to be processed. this.walletManager.Verify(w => w.ProcessBlock(ExpectBlock(result.RightForkBlocks[1]), ExpectChainedBlock(this.chain.GetBlock(2)))); }
public void GetHistoryWithValidModelWithoutTransactionSpendingDetailsReturnsWalletHistoryModel() { ulong gasPrice = SmartContractMempoolValidator.MinGasPrice; int vmVersion = 1; Gas gasLimit = (Gas)(SmartContractFormatRule.GasLimitMaximum / 2); var contractTxData = new ContractTxData(vmVersion, gasPrice, gasLimit, new byte[] { 0, 1, 2, 3 }); var callDataSerializer = new CallDataSerializer(new ContractPrimitiveSerializer(new SmartContractsRegTest())); var contractCreateScript = new Script(callDataSerializer.Serialize(contractTxData)); string walletName = "myWallet"; HdAddress address = WalletTestsHelpers.CreateAddress(); TransactionData normalTransaction = WalletTestsHelpers.CreateTransaction(new uint256(1), new Money(500000), 1); TransactionData createTransaction = WalletTestsHelpers.CreateTransaction(new uint256(1), new Money(500000), 1); createTransaction.SpendingDetails = new SpendingDetails { BlockHeight = 100, CreationTime = DateTimeOffset.Now, TransactionId = uint256.One, Payments = new List <PaymentDetails> { new PaymentDetails { Amount = new Money(100000), DestinationScriptPubKey = contractCreateScript } } }; address.Transactions.Add(normalTransaction); address.Transactions.Add(createTransaction); var addresses = new List <HdAddress> { address }; Features.Wallet.Wallet wallet = WalletTestsHelpers.CreateWallet(walletName); var account = new HdAccount { ExternalAddresses = addresses }; wallet.AccountsRoot.Add(new AccountRoot() { Accounts = new List <HdAccount> { account } }); List <FlatHistory> flat = addresses.SelectMany(s => s.Transactions.Select(t => new FlatHistory { Address = s, Transaction = t })).ToList(); var accountsHistory = new List <AccountHistory> { new AccountHistory { History = flat, Account = account } }; this.walletManager.Setup(w => w.GetHistory(walletName, It.IsAny <string>())).Returns(accountsHistory); this.walletManager.Setup(w => w.GetWalletByName(walletName)).Returns(wallet); this.walletManager.Setup(w => w.GetAccounts(walletName)).Returns(new List <HdAccount> { account }); this.receiptRepository.Setup(x => x.Retrieve(It.IsAny <uint256>())) .Returns(new Receipt(null, 0, new Log[0], null, null, null, uint160.Zero, true, null)); this.callDataSerializer.Setup(x => x.Deserialize(It.IsAny <byte[]>())) .Returns(Result.Ok(new ContractTxData(0, 0, (Gas)0, new uint160(0), null, null))); var controller = new SmartContractWalletController( this.broadcasterManager.Object, this.callDataSerializer.Object, this.connectionManager.Object, this.loggerFactory.Object, this.network, this.receiptRepository.Object, this.walletManager.Object); IActionResult result = controller.GetHistory(walletName, address.Address); var viewResult = Assert.IsType <JsonResult>(result); var model = viewResult.Value as IEnumerable <ContractTransactionItem>; Assert.NotNull(model); Assert.Equal(3, model.Count()); ContractTransactionItem resultingTransaction = model.ElementAt(2); ContractTransactionItem resultingCreate = model.ElementAt(0); Assert.Equal(ContractTransactionItemType.ContractCreate, resultingCreate.Type); Assert.Equal(createTransaction.SpendingDetails.TransactionId, resultingCreate.Hash); Assert.Equal(createTransaction.SpendingDetails.Payments.First().Amount.ToUnit(MoneyUnit.BTC), resultingCreate.Amount); Assert.Equal(uint160.Zero.ToBase58Address(this.network), resultingCreate.To); Assert.Equal((uint)createTransaction.SpendingDetails.BlockHeight, resultingCreate.BlockHeight); Assert.Equal(ContractTransactionItemType.Received, resultingTransaction.Type); Assert.Equal(address.Address, resultingTransaction.To); Assert.Equal(normalTransaction.Id, resultingTransaction.Hash); Assert.Equal(normalTransaction.Amount.ToUnit(MoneyUnit.BTC), resultingTransaction.Amount); Assert.Equal((uint)1, resultingTransaction.BlockHeight); }