public void Given_GetMaximumSpendableAmountIsCalled_When_ThereAreNoTransactions_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"); HdAddress accountAddress1 = WalletTestsHelpers.CreateAddress(); HdAddress accountAddress2 = WalletTestsHelpers.CreateAddress(); 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(Money.Zero, result.max); Assert.Equal(Money.Zero, result.fee); }
public TumblingState(ILoggerFactory loggerFactory, ConcurrentChain chain, WalletManager walletManager, IWatchOnlyWalletManager watchOnlyWalletManager, Network network, WalletTransactionHandler walletTransactionHandler, WalletSyncManager walletSyncManager, IWalletFeePolicy walletFeePolicy, NodeSettings nodeSettings, IBroadcasterManager broadcasterManager, ConnectionManager connectionManager) { this.Logger = loggerFactory.CreateLogger(this.GetType().FullName); this.Chain = chain; this.WalletManager = walletManager; this.WatchOnlyWalletManager = watchOnlyWalletManager; this.CoinType = (CoinType)network.Consensus.CoinType; this.WalletTransactionHandler = walletTransactionHandler; this.WalletSyncManager = walletSyncManager; this.TumblerNetwork = network; this.WalletFeePolicy = walletFeePolicy; this.NodeSettings = nodeSettings; this.BroadcasterManager = broadcasterManager; this.ConnectionManager = connectionManager; }
public void WalletMaxSpendableTest2() { DataFolder dataFolder = CreateDataFolder(this); IWalletRepository walletRepository = new SQLiteWalletRepository(this.LoggerFactory.Object, dataFolder, this.Network, DateTimeProvider.Default, new ScriptAddressReader()) { TestMode = true }; 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, walletRepository); walletManager.Start(); var reserveUtxoService = new ReserveUtxoService(this.loggerFactory, new Mock <ISignals>().Object); var walletTransactionHandler = new WalletTransactionHandler(this.LoggerFactory.Object, walletManager, It.IsAny <WalletFeePolicy>(), this.Network, this.standardTransactionPolicy, reserveUtxoService); (Wallet wallet, ExtKey extKey) = WalletTestsHelpers.GenerateBlankWalletWithExtKey("wallet1", "password", walletRepository); // Passing a null extpubkey into account creation causes problems later, so we need to obtain it first int accountIndex = 0; ExtKey addressExtKey = extKey.Derive(new KeyPath($"m/44'/{this.Network.Consensus.CoinType}'/{accountIndex}'")); ExtPubKey extPubKey = addressExtKey.Neuter(); wallet.AddNewAccount(extPubKey, accountName: "account 1"); (Money max, Money fee)result = walletTransactionHandler.GetMaximumSpendableAmount(new WalletAccountReference("wallet1", "account 1"), FeeType.Low, true); Assert.Equal(Money.Zero, result.max); Assert.Equal(Money.Zero, result.fee); }
public void Given_GetMaximumSpendableAmountIsCalled_When_ThereAreNoTransactions_Then_MaxAmountReturnsAsZero() { string dir = AssureEmptyDir("TestData/WalletManagerTest/Given_GetMaximumSpendableAmountIsCalled_When_ThereAreNoTransactions_Then_MaxAmountReturnsAsZero"); var dataFolder = new DataFolder(new NodeSettings { DataDir = dir }); var walletManager = new WalletManager(this.LoggerFactory.Object, Network.Main, new ConcurrentChain(Network.Main.GetGenesis().Header), NodeSettings.Default(), dataFolder, new Mock <IWalletFeePolicy>().Object, new Mock <IAsyncLoopFactory>().Object, new NodeLifetime(), DateTimeProvider.Default); var walletTransactionHandler = new WalletTransactionHandler(this.LoggerFactory.Object, It.IsAny <ConcurrentChain>(), walletManager, It.IsAny <WalletFeePolicy>(), Network.Main); HdAccount account = WalletTestsHelpers.CreateAccount("account 1"); HdAddress accountAddress1 = WalletTestsHelpers.CreateAddress(); HdAddress accountAddress2 = WalletTestsHelpers.CreateAddress(); account.ExternalAddresses.Add(accountAddress1); account.InternalAddresses.Add(accountAddress2); var 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(Money.Zero, result.max); Assert.Equal(Money.Zero, result.fee); }
public void Given_AnInvalidAccountIsUsed_When_GetMaximumSpendableAmountIsCalled_Then_AnExceptionIsThrown() { string dir = AssureEmptyDir("TestData/WalletManagerTest/Given_AnInvalidAccountIsUsed_When_GetMaximumSpendableAmountIsCalled_Then_AnExceptionIsThrown"); var dataFolder = new DataFolder(new NodeSettings { DataDir = dir }); var walletManager = new WalletManager(this.LoggerFactory.Object, Network.Main, new Mock <ConcurrentChain>().Object, NodeSettings.Default(), dataFolder, new Mock <IWalletFeePolicy>().Object, new Mock <IAsyncLoopFactory>().Object, new NodeLifetime(), DateTimeProvider.Default); var walletTransactionHandler = new WalletTransactionHandler(this.LoggerFactory.Object, It.IsAny <ConcurrentChain>(), walletManager, It.IsAny <WalletFeePolicy>(), Network.Main); var wallet = WalletTestsHelpers.CreateWallet("wallet1"); wallet.AccountsRoot.Add(new AccountRoot() { Accounts = new List <HdAccount> { WalletTestsHelpers.CreateAccount("account 1") } }); walletManager.Wallets.Add(wallet); Exception ex = Assert.Throws <WalletException>(() => walletTransactionHandler.GetMaximumSpendableAmount(new WalletAccountReference("wallet1", "noaccount"), FeeType.Low, true)); Assert.NotNull(ex); Assert.NotNull(ex.Message); Assert.NotEqual(string.Empty, ex.Message); Assert.IsType <WalletException>(ex); }
public void Given_AnInvalidAccountIsUsed_When_GetMaximumSpendableAmountIsCalled_Then_AnExceptionIsThrown() { DataFolder dataFolder = CreateDataFolder(this); var chain = new ChainIndexer(this.Network); var walletManager = new WalletManager(this.LoggerFactory.Object, this.Network, chain, new WalletSettings(NodeSettings.Default(this.Network)), dataFolder, new Mock <IWalletFeePolicy>().Object, new Mock <IAsyncProvider>().Object, new NodeLifetime(), DateTimeProvider.Default, new ScriptAddressReader()); var walletTransactionHandler = new WalletTransactionHandler(this.LoggerFactory.Object, walletManager, It.IsAny <WalletFeePolicy>(), this.Network, this.standardTransactionPolicy); Types.Wallet wallet = WalletTestsHelpers.CreateWallet("wallet1"); wallet.AccountsRoot.Add(new AccountRoot() { Accounts = new List <HdAccount> { WalletTestsHelpers.CreateAccount("account 1") } }); walletManager.Wallets.Add(wallet); Exception ex = Assert.Throws <WalletException>(() => walletTransactionHandler.GetMaximumSpendableAmount(new WalletAccountReference("wallet1", "noaccount"), FeeType.Low, true)); Assert.NotNull(ex); Assert.NotNull(ex.Message); Assert.NotEqual(string.Empty, ex.Message); Assert.IsType <WalletException>(ex); }
public void BuildTransactionNoSpendableTransactionsThrowsWalletException() { Assert.Throws <WalletException>(() => { var wallet = WalletTestsHelpers.GenerateBlankWallet("myWallet1", "password"); wallet.AccountsRoot.ElementAt(0).Accounts.Add( new HdAccount { Name = "account1", ExternalAddresses = new List <HdAddress>(), InternalAddresses = new List <HdAddress>() }); var chain = new Mock <ConcurrentChain>(); chain.Setup(c => c.Tip).Returns(new ChainedBlock(new BlockHeader(), 1)); var walletManager = new WalletManager(this.LoggerFactory.Object, Network.Main, chain.Object, NodeSettings.Default(), new DataFolder(new NodeSettings { DataDir = "TestData/WalletTransactionHandlerTest/BuildTransactionNoSpendableTransactionsThrowsWalletException" }), new Mock <IWalletFeePolicy>().Object, new Mock <IAsyncLoopFactory>().Object, new NodeLifetime(), DateTimeProvider.Default); var walletTransactionHandler = new WalletTransactionHandler(this.LoggerFactory.Object, chain.Object, walletManager, new Mock <IWalletFeePolicy>().Object, Network.Main); walletManager.Wallets.Add(wallet); var walletReference = new WalletAccountReference { AccountName = "account1", WalletName = "myWallet1" }; walletTransactionHandler.BuildTransaction(CreateContext(walletReference, "password", new Script(), new Money(500), FeeType.Medium, 2)); }); }
public void BuildTransactionNoSpendableTransactionsThrowsWalletException() { Assert.Throws <WalletException>(() => { Types.Wallet wallet = WalletTestsHelpers.GenerateBlankWallet("myWallet1", "password"); wallet.AccountsRoot.ElementAt(0).Accounts.Add( new HdAccount { Name = "account1", ExternalAddresses = new List <HdAddress>(), InternalAddresses = new List <HdAddress>() }); BlockHeader blockHeader = this.Network.Consensus.ConsensusFactory.CreateBlockHeader(); var chain = new ChainIndexer(this.Network, new ChainedHeader(blockHeader, blockHeader.GetHash(), 1)); string dataDir = "TestData/WalletTransactionHandlerTest/BuildTransactionNoSpendableTransactionsThrowsWalletException"; 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), new Mock <IWalletFeePolicy>().Object, new Mock <IAsyncProvider>().Object, new NodeLifetime(), DateTimeProvider.Default, new ScriptAddressReader()); var walletTransactionHandler = new WalletTransactionHandler(this.LoggerFactory.Object, walletManager, new Mock <IWalletFeePolicy>().Object, this.Network, new StandardTransactionPolicy(this.Network)); walletManager.Wallets.Add(wallet); var walletReference = new WalletAccountReference { AccountName = "account1", WalletName = "myWallet1" }; walletTransactionHandler.BuildTransaction(CreateContext(this.Network, walletReference, "password", new Script(), new Money(500), FeeType.Medium, 2)); }); }
public void Given_AnInvalidAccountIsUsed_When_GetMaximumSpendableAmountIsCalled_Then_AnExceptionIsThrown() { DataFolder dataFolder = CreateDataFolder(this); var chain = new ChainIndexer(this.Network); IWalletRepository walletRepository = new SQLiteWalletRepository(this.LoggerFactory.Object, dataFolder, this.Network, DateTimeProvider.Default, new ScriptAddressReader()); var walletManager = new WalletManager(this.LoggerFactory.Object, this.Network, chain, new WalletSettings(NodeSettings.Default(this.Network)), dataFolder, new Mock <IWalletFeePolicy>().Object, new Mock <IAsyncProvider>().Object, new NodeLifetime(), DateTimeProvider.Default, new ScriptAddressReader(), walletRepository); walletManager.Start(); var reserveUtxoService = new ReserveUtxoService(this.loggerFactory, new Mock <ISignals>().Object); var walletTransactionHandler = new WalletTransactionHandler(this.LoggerFactory.Object, walletManager, It.IsAny <WalletFeePolicy>(), this.Network, this.standardTransactionPolicy, reserveUtxoService); Wallet wallet = WalletTestsHelpers.CreateWallet("wallet1", walletRepository); HdAccount account = wallet.AddNewAccount((ExtPubKey)null, accountName: "account 1"); Exception ex = Assert.Throws <WalletException>(() => walletTransactionHandler.GetMaximumSpendableAmount(new WalletAccountReference("wallet1", "noaccount"), FeeType.Low, true)); Assert.NotNull(ex); Assert.NotNull(ex.Message); Assert.NotEqual(string.Empty, ex.Message); Assert.IsType <WalletException>(ex); }
WalletAccountReference walletReference) SetupWallet() { DataFolder dataFolder = CreateDataFolder(this); 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 ConcurrentChain(wallet.Network); WalletTestsHelpers.AddBlocksWithCoinbaseToChain(wallet.Network, chain, address); TransactionData addressTransaction = address.Transactions.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, NodeSettings.Default(), new Mock <WalletSettings>().Object, dataFolder, walletFeePolicy.Object, new Mock <IAsyncLoopFactory>().Object, new NodeLifetime(), DateTimeProvider.Default); var walletTransactionHandler = new WalletTransactionHandler(this.LoggerFactory.Object, walletManager, walletFeePolicy.Object, this.network); walletManager.Wallets.Add(wallet); var walletReference = new WalletAccountReference { AccountName = "account1", WalletName = "myWallet1" }; return(wallet, accountKeys, destinationKeys, addressTransaction, walletTransactionHandler, walletReference); }
public void BuildTransactionThrowsWalletExceptionWhenMoneyIsZero() { Assert.Throws <WalletException>(() => { var walletTransactionHandler = new WalletTransactionHandler(this.LoggerFactory.Object, new Mock <IWalletManager>().Object, new Mock <IWalletFeePolicy>().Object, this.Network, this.standardTransactionPolicy); Transaction result = walletTransactionHandler.BuildTransaction(CreateContext(this.Network, new WalletAccountReference(), "password", new Script(), Money.Zero, FeeType.Medium, 2)); }); }
public TumbleBitManager(ILoggerFactory loggerFactory, WalletManager walletManager, WatchOnlyWalletManager watchOnlyWalletManager, ConcurrentChain chain, Network network, Signals signals, WalletTransactionHandler walletTransactionHandler, BlockStoreManager blockStoreManager, MempoolManager mempoolManager, WalletSyncManager walletSyncManager) { this.walletManager = walletManager; this.watchOnlyWalletManager = watchOnlyWalletManager; this.walletSyncManager = walletSyncManager; this.walletTransactionHandler = walletTransactionHandler; this.chain = chain; this.signals = signals; this.network = network; this.loggerFactory = loggerFactory; this.logger = loggerFactory.CreateLogger(this.GetType().FullName); this.blockStoreManager = blockStoreManager; this.mempoolManager = mempoolManager; this.tumblingState = new TumblingState(loggerFactory, this.chain, this.walletManager, this.watchOnlyWalletManager, this.network, this.walletTransactionHandler, this.blockStoreManager, this.mempoolManager, this.walletSyncManager); }
public void Given_GetMaximumSpendableAmountIsCalled_When_ThereAreNoConfirmedSpendableFound_Then_MaxAmountReturnsAsTheSumOfUnconfirmedTxs() { string dir = AssureEmptyDir("TestData/WalletManagerTest/Given_GetMaximumSpendableAmountIsCalledForConfirmedTransactions_When_ThereAreNoConfirmedSpendableFound_Then_MaxAmountReturnsAsZero"); var dataFolder = new DataFolder(new NodeSettings { DataDir = dir }); var walletFeePolicy = new Mock <IWalletFeePolicy>(); walletFeePolicy.Setup(w => w.GetFeeRate(FeeType.Low.ToConfirmations())).Returns(new FeeRate(20000)); var walletManager = new WalletManager(this.LoggerFactory.Object, Network.Main, new ConcurrentChain(Network.Main.GetGenesis().Header), NodeSettings.Default(), dataFolder, new Mock <IWalletFeePolicy>().Object, new Mock <IAsyncLoopFactory>().Object, new NodeLifetime(), DateTimeProvider.Default); var walletTransactionHandler = new WalletTransactionHandler(this.LoggerFactory.Object, It.IsAny <ConcurrentChain>(), walletManager, walletFeePolicy.Object, Network.Main); 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); var 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 WalletMaxSpendableTest1() { DataFolder dataFolder = CreateDataFolder(this); var walletFeePolicy = new Mock <IWalletFeePolicy>(); walletFeePolicy.Setup(w => w.GetFeeRate(FeeType.Low.ToConfirmations())).Returns(new FeeRate(20000)); IWalletRepository walletRepository = new SQLiteWalletRepository(this.LoggerFactory.Object, dataFolder, this.Network, DateTimeProvider.Default, new ScriptAddressReader()) { TestMode = true }; 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, walletRepository); walletManager.Start(); var reserveUtxoService = new ReserveUtxoService(this.loggerFactory, new Mock <ISignals>().Object); var walletTransactionHandler = new WalletTransactionHandler(this.LoggerFactory.Object, walletManager, walletFeePolicy.Object, this.Network, this.standardTransactionPolicy, reserveUtxoService); (Wallet wallet, ExtKey extKey) = WalletTestsHelpers.GenerateBlankWalletWithExtKey("wallet1", "password", walletRepository); // Passing a null extpubkey into account creation causes problems later, so we need to obtain it first int accountIndex = 0; ExtKey addressExtKey = extKey.Derive(new KeyPath($"m/44'/{this.Network.Consensus.CoinType}'/{accountIndex}'")); ExtPubKey extPubKey = addressExtKey.Neuter(); HdAccount account = wallet.AddNewAccount(extPubKey, accountName: "account 1"); HdAddress accountAddress1 = account.ExternalAddresses.First(); accountAddress1.Transactions.Add(WalletTestsHelpers.CreateTransaction(new uint256(1), new Money(15000), null, null, null, accountAddress1.ScriptPubKey)); accountAddress1.Transactions.Add(WalletTestsHelpers.CreateTransaction(new uint256(2), new Money(10000), null, null, null, accountAddress1.ScriptPubKey)); HdAddress accountAddress2 = account.InternalAddresses.Skip(1).First(); accountAddress2.Transactions.Add(WalletTestsHelpers.CreateTransaction(new uint256(3), new Money(20000), null, null, null, accountAddress2.ScriptPubKey)); accountAddress2.Transactions.Add(WalletTestsHelpers.CreateTransaction(new uint256(4), new Money(120000), null, null, null, accountAddress2.ScriptPubKey)); (Money max, Money fee)result = walletTransactionHandler.GetMaximumSpendableAmount(new WalletAccountReference("wallet1", "account 1"), FeeType.Low, true); Assert.Equal(new Money(165000), result.max + result.fee); }
/// <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 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"); Types.Wallet wallet = WalletTestsHelpers.CreateWallet("wallet1"); HdAddress accountAddress1 = WalletTestsHelpers.CreateAddress(); wallet.walletStore.InsertOrUpdate(WalletTestsHelpers.CreateTransaction(new uint256(1), new Money(15000), null, null, null, new Key().ScriptPubKey, accountAddress1.Address)); wallet.walletStore.InsertOrUpdate(WalletTestsHelpers.CreateTransaction(new uint256(2), new Money(10000), null, null, null, new Key().ScriptPubKey, accountAddress1.Address)); HdAddress accountAddress2 = WalletTestsHelpers.CreateAddress(); wallet.walletStore.InsertOrUpdate(WalletTestsHelpers.CreateTransaction(new uint256(3), new Money(20000), null, null, null, new Key().ScriptPubKey, accountAddress2.Address)); wallet.walletStore.InsertOrUpdate(WalletTestsHelpers.CreateTransaction(new uint256(4), new Money(120000), null, null, null, new Key().ScriptPubKey, 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, true); Assert.Equal(new Money(165000), result.max + result.fee); }
public TumblingState(ILoggerFactory loggerFactory, ConcurrentChain chain, WalletManager walletManager, WatchOnlyWalletManager watchOnlyWalletManager, Network network, WalletTransactionHandler walletTransactionHandler, BlockStoreManager blockStoreManager, MempoolManager mempoolManager, WalletSyncManager walletSyncManager) { this.logger = loggerFactory.CreateLogger(this.GetType().FullName); this.chain = chain; this.walletManager = walletManager; this.watchOnlyWalletManager = watchOnlyWalletManager; this.coinType = (CoinType)network.Consensus.CoinType; this.walletTransactionHandler = walletTransactionHandler; this.blockStoreManager = blockStoreManager; this.mempoolManager = mempoolManager; this.walletSyncManager = walletSyncManager; }
public void Given_GetMaximumSpendableAmountIsCalled_When_ThereAreNoSpendableFound_Then_MaxAmountReturnsAsZero() { DataFolder dataFolder = CreateDataFolder(this); var walletManager = new WalletManager(this.LoggerFactory.Object, this.network, new ConcurrentChain(this.network), NodeSettings.Default(), new Mock <WalletSettings>().Object, dataFolder, new Mock <IWalletFeePolicy>().Object, new Mock <IAsyncLoopFactory>().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"); HdAddress accountAddress1 = WalletTestsHelpers.CreateAddress(); accountAddress1.Transactions.Add(WalletTestsHelpers.CreateTransaction(new uint256(1), new Money(15000), 1, new SpendingDetails())); accountAddress1.Transactions.Add(WalletTestsHelpers.CreateTransaction(new uint256(2), new Money(10000), 1, new SpendingDetails())); HdAddress accountAddress2 = WalletTestsHelpers.CreateAddress(); accountAddress2.Transactions.Add(WalletTestsHelpers.CreateTransaction(new uint256(3), new Money(20000), 3, new SpendingDetails())); accountAddress2.Transactions.Add(WalletTestsHelpers.CreateTransaction(new uint256(4), new Money(120000), 4, new SpendingDetails())); account.ExternalAddresses.Add(accountAddress1); account.InternalAddresses.Add(accountAddress2); 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(Money.Zero, result.max); Assert.Equal(Money.Zero, result.fee); }
public void Given_GetMaximumSpendableAmountIsCalledForConfirmedTransactions_When_ThereAreNoConfirmedSpendableFound_Then_MaxAmountReturnsAsZero() { DataFolder dataFolder = CreateDataFolder(this); var walletManager = new WalletManager(this.LoggerFactory.Object, Network.Main, new ConcurrentChain(Network.Main.GetGenesis().Header), NodeSettings.Default(), dataFolder, new Mock <IWalletFeePolicy>().Object, new Mock <IAsyncLoopFactory>().Object, new NodeLifetime(), DateTimeProvider.Default); var walletTransactionHandler = new WalletTransactionHandler(this.LoggerFactory.Object, It.IsAny <ConcurrentChain>(), walletManager, It.IsAny <WalletFeePolicy>(), Network.Main); HdAccount account = WalletTestsHelpers.CreateAccount("account 1"); HdAddress accountAddress1 = WalletTestsHelpers.CreateAddress(); accountAddress1.Transactions.Add(WalletTestsHelpers.CreateTransaction(new uint256(1), new Money(15000), null)); accountAddress1.Transactions.Add(WalletTestsHelpers.CreateTransaction(new uint256(2), new Money(10000), null)); HdAddress accountAddress2 = WalletTestsHelpers.CreateAddress(); accountAddress2.Transactions.Add(WalletTestsHelpers.CreateTransaction(new uint256(3), new Money(20000), null)); accountAddress2.Transactions.Add(WalletTestsHelpers.CreateTransaction(new uint256(4), new Money(120000), null)); account.ExternalAddresses.Add(accountAddress1); account.InternalAddresses.Add(accountAddress2); var 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, false); Assert.Equal(Money.Zero, result.max); Assert.Equal(Money.Zero, result.fee); }
public TumbleBitManager( ILoggerFactory loggerFactory, NodeSettings nodeSettings, IWalletManager walletManager, IWatchOnlyWalletManager watchOnlyWalletManager, ConcurrentChain chain, Network network, Signals signals, IWalletTransactionHandler walletTransactionHandler, IWalletSyncManager walletSyncManager, IWalletFeePolicy walletFeePolicy, IBroadcasterManager broadcasterManager, FullNode fullNode, ConfigurationOptionWrapper <string>[] configurationOptions) { this.walletManager = walletManager as WalletManager; this.watchOnlyWalletManager = watchOnlyWalletManager; this.walletSyncManager = walletSyncManager as WalletSyncManager; this.walletTransactionHandler = walletTransactionHandler as WalletTransactionHandler; this.chain = chain; this.signals = signals; this.network = network; this.nodeSettings = nodeSettings; this.loggerFactory = loggerFactory; this.logger = loggerFactory.CreateLogger(this.GetType().FullName); this.walletFeePolicy = walletFeePolicy; this.broadcasterManager = broadcasterManager; this.connectionManager = fullNode.ConnectionManager as ConnectionManager; this.fullNode = fullNode; foreach (var option in configurationOptions) { if (option.Name.Equals("RegistrationStoreDirectory")) { if (option.Value != null) { this.registrationStore = new RegistrationStore(option.Value); } else { this.registrationStore = new RegistrationStore(this.nodeSettings.DataDir); } } if (option.Name.Equals("MasterNodeUri")) { if (option.Value != null) { this.TumblerAddress = option.Value; } } } this.tumblingState = new TumblingState( this.loggerFactory, this.chain, this.walletManager, this.watchOnlyWalletManager, this.network, this.walletTransactionHandler, this.walletSyncManager, this.walletFeePolicy, this.nodeSettings, this.broadcasterManager, this.connectionManager); // Load saved state e.g. previously selected server if (File.Exists(this.tumblingState.GetStateFilePath())) { try { this.tumblingState.LoadStateFromMemory(); } catch (NullReferenceException) { // The file appears to get corrupted sometimes, not clear why // May be if the node is not shut down correctly } } this.tumblingState.Save(); // If there was a server address saved, that means we were previously // connected to it, and should try to reconnect to it by default when // the connect method is invoked by the UI if ((this.TumblerAddress == null) && (this.tumblingState.TumblerUri != null)) { this.TumblerAddress = this.tumblingState.TumblerUri.ToString(); } // Remove the progress file from previous session as it is now stale ProgressInfo.RemoveProgressFile(); }
private WalletTransactionHandlerTestContext SetupWallet(FeeRate feeRate = null, int coinBaseBlocks = 1) { DataFolder dataFolder = CreateDataFolder(this); IWalletRepository walletRepository = new SQLiteWalletRepository(this.LoggerFactory.Object, dataFolder, this.Network, DateTimeProvider.Default, new ScriptAddressReader()) { TestMode = true }; var walletFeePolicy = new Mock <IWalletFeePolicy>(); walletFeePolicy.Setup(w => w.GetFeeRate(FeeType.Low.ToConfirmations())) .Returns(feeRate ?? new FeeRate(20000)); var chain = new ChainIndexer(this.Network); 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, walletRepository); var reserveUtxoService = new ReserveUtxoService(this.loggerFactory, new Mock <ISignals>().Object); var walletTransactionHandler = new WalletTransactionHandler(this.LoggerFactory.Object, walletManager, walletFeePolicy.Object, this.Network, this.standardTransactionPolicy, reserveUtxoService); walletManager.Start(); var walletReference = new WalletAccountReference { AccountName = "account1", WalletName = "myWallet1" }; Wallet wallet = WalletTestsHelpers.GenerateBlankWallet(walletReference.WalletName, "password", walletRepository); (ExtKey ExtKey, string ExtPubKey)accountKeys = WalletTestsHelpers.GenerateAccountKeys(wallet, "password", $"m/44'/{this.Network.Consensus.CoinType}'/0'"); var account = wallet.AddNewAccount(accountKeys.ExtKey.Neuter(), accountName: walletReference.AccountName); var destinationAddress = account.ExternalAddresses.Skip(1).First(); (PubKey PubKey, BitcoinPubKeyAddress Address)destinationKeys = (destinationAddress.Pubkey.GetDestinationPublicKeys(this.Network).First(), new BitcoinPubKeyAddress(destinationAddress.Address, this.Network)); HdAddress address = account.ExternalAddresses.ElementAt(0); TransactionData addressTransaction = null; if (coinBaseBlocks != 0) { WalletTestsHelpers.AddBlocksWithCoinbaseToChain(wallet.Network, chain, address, coinBaseBlocks); addressTransaction = address.Transactions.First(); } return(new WalletTransactionHandlerTestContext { Wallet = wallet, AccountKeys = accountKeys, DestinationKeys = destinationKeys, AddressTransaction = addressTransaction, WalletTransactionHandler = walletTransactionHandler, WalletReference = walletReference }); }
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 BuildTransactionFeeTooLowThrowsWalletException() { Assert.Throws <WalletException>(() => { var walletFeePolicy = new Mock <IWalletFeePolicy>(); walletFeePolicy.Setup(w => w.GetFeeRate(FeeType.Low.ToConfirmations())) .Returns(new FeeRate(0)); var wallet = WalletTestsHelpers.GenerateBlankWallet("myWallet1", "password"); var accountKeys = WalletTestsHelpers.GenerateAccountKeys(wallet, "password", "m/44'/0'/0'"); var spendingKeys = WalletTestsHelpers.GenerateAddressKeys(wallet, accountKeys.ExtPubKey, "0/0"); var destinationKeys = WalletTestsHelpers.GenerateAddressKeys(wallet, accountKeys.ExtPubKey, "0/1"); var 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 ConcurrentChain(wallet.Network.GetGenesis().Header); WalletTestsHelpers.AddBlocksWithCoinbaseToChain(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>() } } }); var walletManager = new WalletManager(this.LoggerFactory.Object, Network.Main, chain, NodeSettings.Default(), new DataFolder(new NodeSettings { DataDir = "TestData/WalletTransactionHandlerTest/BuildTransactionFeeTooLowThrowsWalletException" }), walletFeePolicy.Object, new Mock <IAsyncLoopFactory>().Object, new NodeLifetime(), DateTimeProvider.Default); var walletTransactionHandler = new WalletTransactionHandler(this.LoggerFactory.Object, chain, walletManager, walletFeePolicy.Object, Network.Main); walletManager.Wallets.Add(wallet); var walletReference = new WalletAccountReference { AccountName = "account1", WalletName = "myWallet1" }; walletTransactionHandler.BuildTransaction(CreateContext(walletReference, "password", destinationKeys.PubKey.ScriptPubKey, new Money(7500), FeeType.Low, 0)); }); }
public void EstimateFeeWithLowFeeMatchesBuildTxLowFee() { var dataFolder = CreateDataFolder(this); Wallet wallet = WalletTestsHelpers.GenerateBlankWallet("myWallet1", "password"); var accountKeys = WalletTestsHelpers.GenerateAccountKeys(wallet, "password", "m/44'/0'/0'"); var spendingKeys = WalletTestsHelpers.GenerateAddressKeys(wallet, accountKeys.ExtPubKey, "0/0"); var destinationKeys = WalletTestsHelpers.GenerateAddressKeys(wallet, accountKeys.ExtPubKey, "0/1"); HdAddress 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>() }; ConcurrentChain chain = new ConcurrentChain(wallet.Network.GetGenesis().Header); WalletTestsHelpers.AddBlocksWithCoinbaseToChain(wallet.Network, chain, address); TransactionData addressTransaction = address.Transactions.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, Network.Main, chain, NodeSettings.Default(), dataFolder, walletFeePolicy.Object, new Mock <IAsyncLoopFactory>().Object, new NodeLifetime(), DateTimeProvider.Default); WalletTransactionHandler walletTransactionHandler = new WalletTransactionHandler(this.LoggerFactory.Object, chain, walletManager, walletFeePolicy.Object, Network.Main); walletManager.Wallets.Add(wallet); WalletAccountReference walletReference = new WalletAccountReference { AccountName = "account1", WalletName = "myWallet1" }; // Context to build requires password in order to sign transaction. TransactionBuildContext buildContext = CreateContext(walletReference, "password", destinationKeys.PubKey.ScriptPubKey, new Money(7500), FeeType.Low, 0); walletTransactionHandler.BuildTransaction(buildContext); // Context for estimate does not need password. TransactionBuildContext estimateContext = CreateContext(walletReference, null, destinationKeys.PubKey.ScriptPubKey, new Money(7500), FeeType.Low, 0); Money fee = walletTransactionHandler.EstimateFee(estimateContext); Assert.Equal(fee, buildContext.TransactionFee); }
public TumbleBitManager( ILoggerFactory loggerFactory, NodeSettings nodeSettings, IWalletManager walletManager, IWatchOnlyWalletManager watchOnlyWalletManager, ConcurrentChain chain, Network network, Signals signals, IWalletTransactionHandler walletTransactionHandler, IWalletSyncManager walletSyncManager, IWalletFeePolicy walletFeePolicy, IBroadcasterManager broadcasterManager, FullNode fullNode, ConfigurationOptionWrapper <string> registrationStoreDirectory) { this.walletManager = walletManager as WalletManager; this.watchOnlyWalletManager = watchOnlyWalletManager; this.walletSyncManager = walletSyncManager as WalletSyncManager; this.walletTransactionHandler = walletTransactionHandler as WalletTransactionHandler; this.chain = chain; this.signals = signals; this.network = network; this.nodeSettings = nodeSettings; this.loggerFactory = loggerFactory; this.logger = loggerFactory.CreateLogger(this.GetType().FullName); this.walletFeePolicy = walletFeePolicy; this.broadcasterManager = broadcasterManager; this.fullNode = fullNode; if (registrationStoreDirectory.Value != null) { this.registrationStore = new RegistrationStore(registrationStoreDirectory.Value); } else { this.registrationStore = new RegistrationStore(this.nodeSettings.DataDir); } this.tumblingState = new TumblingState( this.loggerFactory, this.chain, this.walletManager, this.watchOnlyWalletManager, this.network, this.walletTransactionHandler, this.walletSyncManager, this.walletFeePolicy, this.nodeSettings, this.broadcasterManager); // Load saved state e.g. previously selected server if (File.Exists(this.tumblingState.GetStateFilePath())) { try { this.tumblingState.LoadStateFromMemory(); } catch (NullReferenceException) { // The file appears to get corrupted sometimes, not clear why // May be if the node is not shut down correctly } } this.tumblingState.Save(); // Remove the progress file from previous session as it is now stale ProgressInfo.RemoveProgressFile(); }
public void BuildTransactionNoChangeAdressesLeftCreatesNewChangeAddress() { DataFolder dataFolder = CreateDataFolder(this); var wallet = WalletTestsHelpers.GenerateBlankWallet("myWallet1", "password"); var accountKeys = WalletTestsHelpers.GenerateAccountKeys(wallet, "password", "m/44'/0'/0'"); var spendingKeys = WalletTestsHelpers.GenerateAddressKeys(wallet, accountKeys.ExtPubKey, "0/0"); var 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 ConcurrentChain(wallet.Network.GetGenesis().Header); WalletTestsHelpers.AddBlocksWithCoinbaseToChain(wallet.Network, chain, address); var addressTransaction = address.Transactions.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, Network.Main, chain, NodeSettings.Default(), dataFolder, walletFeePolicy.Object, new Mock <IAsyncLoopFactory>().Object, new NodeLifetime(), DateTimeProvider.Default); var walletTransactionHandler = new WalletTransactionHandler(this.LoggerFactory.Object, chain, walletManager, walletFeePolicy.Object, Network.Main); walletManager.Wallets.Add(wallet); var walletReference = new WalletAccountReference { AccountName = "account1", WalletName = "myWallet1" }; var context = CreateContext(walletReference, "password", destinationKeys.PubKey.ScriptPubKey, new Money(7500), FeeType.Low, 0); var transactionResult = walletTransactionHandler.BuildTransaction(context); var result = new Transaction(transactionResult.ToHex()); var expectedChangeAddressKeys = WalletTestsHelpers.GenerateAddressKeys(wallet, accountKeys.ExtPubKey, "1/0"); Assert.Single(result.Inputs); Assert.Equal(addressTransaction.Id, result.Inputs[0].PrevOut.Hash); Assert.Equal(2, result.Outputs.Count); var output = result.Outputs[0]; Assert.Equal((addressTransaction.Amount - context.TransactionFee - 7500), output.Value); Assert.Equal(expectedChangeAddressKeys.Address.ScriptPubKey, output.ScriptPubKey); output = result.Outputs[1]; Assert.Equal(7500, output.Value); Assert.Equal(destinationKeys.PubKey.ScriptPubKey, output.ScriptPubKey); Assert.Equal(addressTransaction.Amount - context.TransactionFee, result.TotalOut); Assert.NotNull(transactionResult.GetHash()); Assert.Equal(result.GetHash(), transactionResult.GetHash()); }
public void FundTransaction_Given__a_wallet_has_enough_inputs__When__adding_inputs_to_an_existing_transaction__Then__the_transaction_is_funded_successfully() { var dataFolder = AssureEmptyDirAsDataFolder("TestData/WalletTransactionHandlerTest/FundTransaction_Given__a_wallet_has_enough_inputs__When__adding_inputs_to_an_existing_transaction__Then__the_transaction_is_funded_successfully"); var wallet = WalletTestsHelpers.GenerateBlankWallet("myWallet1", "password"); var accountKeys = WalletTestsHelpers.GenerateAccountKeys(wallet, "password", "m/44'/0'/0'"); var spendingKeys = WalletTestsHelpers.GenerateAddressKeys(wallet, accountKeys.ExtPubKey, "0/0"); var destinationKeys1 = WalletTestsHelpers.GenerateAddressKeys(wallet, accountKeys.ExtPubKey, "0/1"); var destinationKeys2 = WalletTestsHelpers.GenerateAddressKeys(wallet, accountKeys.ExtPubKey, "0/2"); var 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 ConcurrentChain(wallet.Network.GetGenesis().Header); WalletTestsHelpers.AddBlocksWithCoinbaseToChain(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, Network.Main, chain, NodeSettings.Default(), dataFolder, walletFeePolicy.Object, new Mock <IAsyncLoopFactory>().Object, new NodeLifetime(), DateTimeProvider.Default); var walletTransactionHandler = new WalletTransactionHandler(this.LoggerFactory.Object, chain, walletManager, walletFeePolicy.Object, Network.Main); walletManager.Wallets.Add(wallet); var walletReference = new WalletAccountReference { AccountName = "account1", WalletName = "myWallet1" }; // create a trx with 3 outputs 50 + 50 + 49 = 149 BTC var context = new TransactionBuildContext(walletReference, 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(49, MoneyUnit.BTC), ScriptPubKey = destinationKeys3.PubKey.ScriptPubKey } } .ToList(), "password") { MinConfirmations = 0, FeeType = FeeType.Low }; var fundTransaction = walletTransactionHandler.BuildTransaction(context); Assert.Equal(3, fundTransaction.Inputs.Count); // 3 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 2 inputs they will be added back by fund transaction fundTransaction.Inputs.RemoveAt(2); fundTransaction.Inputs.RemoveAt(1); Assert.Single(fundTransaction.Inputs); // 3 inputs var fundTransactionClone = fundTransaction.Clone(); var fundContext = new TransactionBuildContext(walletReference, new List <Recipient>(), "password") { MinConfirmations = 0, FeeType = FeeType.Low }; fundContext.OverrideFeeRate = overrideFeeRate; walletTransactionHandler.FundTransaction(fundContext, fundTransaction); foreach (var input in fundTransactionClone.Inputs) // all original inputs are still in the trx { Assert.Contains(fundTransaction.Inputs, a => a.PrevOut == input.PrevOut); } Assert.Equal(3, fundTransaction.Inputs.Count); // we expect 3 inputs Assert.Equal(4, fundTransaction.Outputs.Count); // we expect 4 outputs Assert.Equal(new Money(150, 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); }
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 }); }
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); }
public void When_BuildTransactionIsCalledWithoutTransactionFee_Then_MultipleSubtractFeeRecipients_ThrowsException() { DataFolder dataFolder = CreateDataFolder(this); IWalletRepository walletRepository = new SQLiteWalletRepository(this.LoggerFactory.Object, dataFolder, this.Network, DateTimeProvider.Default, new ScriptAddressReader()) { TestMode = true }; 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, walletFeePolicy.Object, new Mock <IAsyncProvider>().Object, new NodeLifetime(), DateTimeProvider.Default, this.scriptAddressReader, walletRepository); walletManager.Start(); var reserveUtxoService = new ReserveUtxoService(this.loggerFactory, new Mock <ISignals>().Object); var walletTransactionHandler = new WalletTransactionHandler(this.LoggerFactory.Object, walletManager, walletFeePolicy.Object, this.Network, this.standardTransactionPolicy, reserveUtxoService); (Wallet wallet, ExtKey extKey) = WalletTestsHelpers.GenerateBlankWalletWithExtKey("myWallet1", "password", walletRepository); walletManager.Wallets.Add(wallet); int accountIndex = 0; ExtKey addressExtKey = extKey.Derive(new KeyPath($"m/44'/{this.Network.Consensus.CoinType}'/{accountIndex}'")); ExtPubKey extPubKey = addressExtKey.Neuter(); HdAccount account = wallet.AddNewAccount(extPubKey, accountName: "account1"); var address = account.ExternalAddresses.First(); var destination = account.InternalAddresses.First(); var destination2 = account.InternalAddresses.Skip(1).First(); var destination3 = account.InternalAddresses.Skip(2).First(); // Wallet with 4 coinbase outputs of 50 = 200. var chain = new ChainIndexer(wallet.Network); WalletTestsHelpers.AddBlocksWithCoinbaseToChain(wallet.Network, chain, address, 4); var walletReference = new WalletAccountReference { AccountName = "account1", WalletName = "myWallet1" }; // Create a transaction with 3 outputs 50 + 50 + 50 = 150 but with fees charged to recipients. 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 = destination.ScriptPubKey, SubtractFeeFromAmount = true }, new Recipient { Amount = new Money(50, MoneyUnit.BTC), ScriptPubKey = destination2.ScriptPubKey, SubtractFeeFromAmount = true }, new Recipient { Amount = new Money(50, MoneyUnit.BTC), ScriptPubKey = destination3.ScriptPubKey, SubtractFeeFromAmount = false } }.ToList() }; Assert.Throws <WalletException>(() => walletTransactionHandler.BuildTransaction(context)); }