/// <summary> /// Adds a spendable cold staking transaction to a wallet. /// </summary> /// <param name="wallet">Wallet to add the transaction to.</param> /// <returns>The spendable transaction that was added to the wallet.</returns> private Transaction AddSpendableColdstakingTransactionToWallet(Wallet.Wallet wallet) { // Get first unused cold staking address. this.coldStakingManager.GetOrCreateColdStakingAccount(wallet.Name, true, walletPassword); HdAddress address = this.coldStakingManager.GetFirstUnusedColdStakingAddress(wallet.Name, true); TxDestination hotPubKey = BitcoinAddress.Create(hotWalletAddress1, wallet.Network).ScriptPubKey.GetDestination(wallet.Network); TxDestination coldPubKey = BitcoinAddress.Create(coldWalletAddress2, wallet.Network).ScriptPubKey.GetDestination(wallet.Network); var scriptPubKey = new Script(OpcodeType.OP_DUP, OpcodeType.OP_HASH160, OpcodeType.OP_ROT, OpcodeType.OP_IF, OpcodeType.OP_CHECKCOLDSTAKEVERIFY, Op.GetPushOp(hotPubKey.ToBytes()), OpcodeType.OP_ELSE, Op.GetPushOp(coldPubKey.ToBytes()), OpcodeType.OP_ENDIF, OpcodeType.OP_EQUALVERIFY, OpcodeType.OP_CHECKSIG); var transaction = this.Network.CreateTransaction(); transaction.Outputs.Add(new TxOut(Money.Coins(101), scriptPubKey)); address.Transactions.Add(new TransactionData() { Hex = transaction.ToHex(this.Network), Amount = transaction.Outputs[0].Value, Id = transaction.GetHash(), BlockHeight = 0, Index = 0, IsCoinBase = false, IsCoinStake = false, IsPropagated = true, BlockHash = this.Network.GenesisHash, ScriptPubKey = scriptPubKey }); return(transaction); }
public void StartStaking_InvalidTimeSyncState_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); this.timeSyncBehaviorState.Setup(ts => ts.IsSystemTimeOutOfSync).Returns(true); 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 = "******" }); 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.Contains("Staking cannot start", error.Message); this.posMinting.Verify(pm => pm.Stake(It.IsAny <WalletSecret>()), Times.Never); }
public void VerifyThatColdStakeTransactionCanBeFiltered() { this.Initialize(); this.CreateMempoolManager(); this.coldStakingManager.CreateWallet(walletPassword, walletName1, walletPassphrase, new Mnemonic(walletMnemonic1)); Wallet.Wallet wallet1 = this.coldStakingManager.GetWalletByName(walletName1); Transaction prevTran = this.AddSpendableTransactionToWallet(wallet1); IActionResult result = this.coldStakingController.SetupColdStaking(new SetupColdStakingRequest { HotWalletAddress = hotWalletAddress1, ColdWalletAddress = coldWalletAddress2, WalletName = walletName1, WalletAccount = walletAccount, WalletPassword = walletPassword, Amount = "100", Fees = "0.01" }); var jsonResult = Assert.IsType <JsonResult>(result); var response = Assert.IsType <SetupColdStakingResponse>(jsonResult.Value); var transaction = Assert.IsType <PosTransaction>(this.Network.CreateTransaction(response.TransactionHex)); Assert.Equal("OP_DUP OP_HASH160 OP_ROT OP_IF OP_CHECKCOLDSTAKEVERIFY 90c582cb91d6b6d777c31c891d4943fed4edac3a OP_ELSE 92dfb829d31cefe6a0731f3432dea41596a278d9 OP_ENDIF OP_EQUALVERIFY OP_CHECKSIG", transaction.Outputs[1].ScriptPubKey.ToString()); // Get the ColdStaking script template if available. Dictionary <string, ScriptTemplate> templates = this.coldStakingManager.GetValidStakingTemplates(); ScriptTemplate coldStakingTemplate = templates["ColdStaking"]; Assert.True(coldStakingTemplate.CheckScriptPubKey(transaction.Outputs[1].ScriptPubKey)); }
/// <summary> /// Gets the first unused cold staking address. Creates a new address if required. /// </summary> /// <param name="walletName">The name of the wallet providing the cold staking address.</param> /// <param name="isColdWalletAddress">Indicates whether we need the cold wallet address (versus the hot wallet address).</param> /// <returns>The cold staking address or <c>null</c> if the required account does not exist.</returns> internal HdAddress GetFirstUnusedColdStakingAddress(string walletName, bool isColdWalletAddress) { Guard.NotNull(walletName, nameof(walletName)); Wallet.Wallet wallet = this.GetWalletByName(walletName); HdAccount account = this.GetColdStakingAccount(wallet, isColdWalletAddress); if (account == null) { this.logger.LogTrace("(-)[ACCOUNT_DOES_NOT_EXIST]:null"); return(null); } HdAddress address = account.GetFirstUnusedReceivingAddress(); if (address == null) { this.logger.LogDebug("No unused address exists on account '{0}'. Adding new address.", account.Name); IEnumerable <HdAddress> newAddresses = account.CreateAddresses(wallet.Network, 1); this.UpdateKeysLookupLocked(newAddresses); address = newAddresses.First(); } this.logger.LogTrace("(-):'{0}'", address.Address); return(address); }
/// <summary> /// Gets the first unused cold staking address. Creates a new address if required. /// </summary> /// <param name="walletName">The name of the wallet providing the cold staking address.</param> /// <param name="isColdWalletAddress">Indicates whether we need the cold wallet address (versus the hot wallet address).</param> /// <returns>The cold staking address or <c>null</c> if the required account does not exist.</returns> internal HdAddress GetFirstUnusedColdStakingAddress(string walletName, bool isColdWalletAddress) { Guard.NotNull(walletName, nameof(walletName)); this.logger.LogTrace("({0}:'{1}',{2}:{3})", nameof(walletName), walletName, nameof(isColdWalletAddress), isColdWalletAddress); Wallet.Wallet wallet = this.GetWalletByName(walletName); HdAccount account = this.GetColdStakingAccount(wallet, isColdWalletAddress); if (account == null) { this.logger.LogTrace("(-)[ACCOUNT_DOES_NOT_EXIST]:null"); return(null); } HdAddress address = account.GetFirstUnusedReceivingAddress(); if (address == null) { this.logger.LogTrace("No unused address exists on account '{0}'. Adding new address.", account.Name); address = account.CreateAddresses(wallet.Network, 1).First(); } this.logger.LogTrace("(-):'{0}'", address.Address); return(address); }
public async Task GenerateBlocksAsync_does_not_use_small_coins() { var walletSecret = new WalletSecret() { WalletName = "wallet", WalletPassword = "******" }; var wallet = new Wallet.Wallet() { Network = this.network }; var milliseconds550MinutesAgo = (uint)Math.Max(this.chain.Tip.Header.Time - TimeSpan.FromMinutes(550).Milliseconds, 0); this.AddAccountWithSpendableOutputs(wallet); var spendableTransactions = wallet.GetAllSpendableTransactions(CoinType.Stratis, this.chain.Tip.Height, 0).ToList(); this.walletManager.Setup(w => w.GetSpendableTransactionsInWallet(It.IsAny <string>(), It.IsAny <int>())) .Returns(spendableTransactions); var fetchedUtxos = spendableTransactions .Select(t => new UnspentOutputs(t.Transaction.Id, new Coins() { CoinBase = false, CoinStake = false, Height = 0, Outputs = { new TxOut(t.Transaction.Amount ?? Money.Zero, t.Address.ScriptPubKey) }, Time = milliseconds550MinutesAgo, Version = 1 })) .ToArray(); var fetchCoinsResponse = new FetchCoinsResponse(fetchedUtxos, this.chain.Tip.HashBlock); fetchCoinsResponse.UnspentOutputs .Where(u => u.Outputs.Any(o => o.Value < this.posMinting.MinimumStakingCoinValue)).Should() .NotBeEmpty("otherwise we are not sure the code actually excludes them"); fetchCoinsResponse.UnspentOutputs .Where(u => u.Outputs.Any(o => o.Value >= this.posMinting.MinimumStakingCoinValue)).Should() .NotBeEmpty("otherwise we are not sure the code actually includes them"); this.coinView.Setup(c => c.FetchCoinsAsync(It.IsAny <uint256[]>(), It.IsAny <CancellationToken>())) .Returns(Task.FromResult(fetchCoinsResponse)); this.consensusManager.Setup(c => c.Tip).Returns(this.chain.Tip); this.dateTimeProvider.Setup(c => c.GetAdjustedTimeAsUnixTimestamp()) .Returns(this.chain.Tip.Header.Time + 16); var ct = CancellationToken.None; var utxoStakeDescriptions = await this.posMinting.GetUtxoStakeDescriptionsAsync(walletSecret, ct); utxoStakeDescriptions.Select(d => d.TxOut.Value).Where(v => v < this.posMinting.MinimumStakingCoinValue) .Should().BeEmpty("small coins should not be included"); utxoStakeDescriptions.Select(d => d.TxOut.Value).Where(v => v >= this.posMinting.MinimumStakingCoinValue) .Should().NotBeEmpty("big enough coins should be included"); var expectedAmounts = spendableTransactions.Select(s => s.Transaction.Amount) .Where(a => a >= this.posMinting.MinimumStakingCoinValue).ToArray(); utxoStakeDescriptions.Count.Should().Be(expectedAmounts.Length); utxoStakeDescriptions.Select(d => d.TxOut.Value).Should().Contain(expectedAmounts); }
public void StopStaking_Returns_Ok() { { 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(new ConnectionManagerSettings(NodeSettings.Default(this.Network)), KnownNetworks.Main, new MinerSettings(NodeSettings.Default(this.Network)), NodeSettings.Default(this.Network), this.LoggerFactory.Object, this.timeSyncBehaviorState.Object, null, this.posMinting.Object)); IActionResult startStakingResult = this.controller.StartStaking(new StartStakingRequest() { Name = "myWallet", Password = "******" }); Assert.IsType <OkResult>(startStakingResult); IActionResult stopStakingResult = this.controller.StopStaking(); Assert.IsType <OkResult>(stopStakingResult); } }
public IActionResult StakingExpiry([FromBody] StakingExpiryRequest request) { try { if (!this.fullNode.Network.Consensus.IsProofOfStake) { return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.MethodNotAllowed, "Method not allowed", "Method not available for Proof of Stake")); } if (!this.minerSettings.EnforceStakingFlag) { return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.Forbidden, "Operation not allowed", "This operation is only allowed if EnforceStakingFlag is true")); } Wallet.Wallet wallet = this.walletManager.GetWallet(request.WalletName); foreach (Wallet.HdAccount account in wallet.GetAccounts(account => true)) { foreach (Wallet.HdAddress address in account.GetCombinedAddresses()) { if ((address.Address == request.Address) || address.Bech32Address == request.Address) { address.StakingExpiry = request.StakingExpiry; } } } return(this.Ok()); } catch (Exception e) { this.logger.LogError("Exception occurred: {0}", e.ToString()); return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString())); } }
public void RecoverWalletSuccessfullyReturnsWalletModel() { Wallet.Wallet wallet = new Wallet.Wallet { Name = "myWallet", Network = WalletHelpers.GetNetwork("mainnet") }; var mockWalletWrapper = new Mock <IWalletManager>(); mockWalletWrapper.Setup(w => w.LoadWallet(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>())).Returns(wallet); var controller = new WalletController(mockWalletWrapper.Object, new Mock <ITracker>().Object); // Act var result = controller.Load(new WalletLoadRequest { Name = "myWallet", FolderPath = "", Password = "" }); // Assert mockWalletWrapper.VerifyAll(); var viewResult = Assert.IsType <JsonResult>(result); Assert.NotNull(viewResult.Value); Assert.IsType <WalletModel>(viewResult.Value); var model = viewResult.Value as WalletModel; Assert.Equal("Main", model.Network); }
/// <summary> /// change categories accessibility for wallet. /// </summary> /// <param name="wallet"></param> /// <param name="category">category to change</param> public void SwitchCategoryPermission(Wallet.Wallet wallet, Category category) { if (!Wallets.Contains(wallet)) { throw new UserException("can not switch categories if you are not owner"); } if (!Categories.Contains(category)) { throw new UserException("user hasn't this category"); } if (wallet is null) { throw new UserException("user hasn't this wallet"); } if (wallet.RestrictedCategories.Contains(category)) { wallet.RestrictedCategories.Remove(category); } else { wallet.RestrictedCategories.Add(category); } }
/// <summary> /// Creates a cold staking account and ensures that it has at least one address. /// If the account already exists then the existing account is returned. /// </summary> /// <remarks> /// <para>In order to keep track of cold staking addresses and balances we are using <see cref="HdAccount"/>'s /// with indexes starting from the value defined in <see cref="Wallet.Wallet.SpecialPurposeAccountIndexesStart"/>. /// </para><para> /// We are using two such accounts, one when the wallet is in the role of cold wallet, and another one when /// the wallet is in the role of hot wallet. For this reason we specify the required account when calling this /// method. /// </para></remarks> /// <param name="walletName">The name of the wallet where we wish to create the account.</param> /// <param name="isColdWalletAccount">Indicates whether we need the cold wallet account (versus the hot wallet account).</param> /// <param name="walletPassword">The wallet password which will be used to create the account.</param> /// <returns>The new or existing cold staking account.</returns> internal HdAccount GetOrCreateColdStakingAccount(string walletName, bool isColdWalletAccount, string walletPassword) { Wallet.Wallet wallet = this.GetWallet(walletName); HdAccount account = this.GetColdStakingAccount(wallet, isColdWalletAccount); if (account != null) { this.logger.LogTrace("(-)[ACCOUNT_ALREADY_EXIST]:'{0}'", account.Name); return(account); } this.logger.LogDebug("The {0} wallet account for '{1}' does not exist and will now be created.", isColdWalletAccount ? "cold" : "hot", wallet.Name); int accountIndex; string accountName; if (isColdWalletAccount) { accountIndex = ColdWalletAccountIndex; accountName = ColdWalletAccountName; } else { accountIndex = HotWalletAccountIndex; accountName = HotWalletAccountName; } account = wallet.AddNewAccount(walletPassword, accountIndex, accountName, this.dateTimeProvider.GetTimeOffset()); this.logger.LogTrace("(-):'{0}'", account.Name); return(account); }
public IActionResult StartStaking([FromBody] StartStakingRequest request) { Guard.NotNull(request, nameof(request)); try { if (!this.ModelState.IsValid) { IEnumerable <string> errors = this.ModelState.Values.SelectMany(e => e.Errors.Select(m => m.ErrorMessage)); return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, "Formatting error", string.Join(Environment.NewLine, errors))); } Wallet.Wallet wallet = this.walletManager.GetWallet(request.Name); // Check the password try { Key.Parse(wallet.EncryptedSeed, request.Password, wallet.Network); } catch (Exception ex) { throw new SecurityException(ex.Message); } this.fullNode.NodeFeature <MiningFeature>(true).StartStaking(request.Name, request.Password); return(this.Ok()); } catch (Exception e) { this.logger.LogError("Exception occurred: {0}", e.ToString()); return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString())); } }
public Transaction CreateColdStakingWithdrawalTransaction(Wallet.Wallet wallet, string password, HdAddress spendingAddress, PubKey destinationPubKey, Script changeScript, Money amount, Money fee) { TransactionData spendingTransaction = spendingAddress.Transactions.ElementAt(0); var coin = new Coin(spendingTransaction.Id, (uint)spendingTransaction.Index, spendingTransaction.Amount, spendingTransaction.ScriptPubKey); Key privateKey = Key.Parse(wallet.EncryptedSeed, password, wallet.Network); Script script = destinationPubKey.ScriptPubKey; var builder = new TransactionBuilder(wallet.Network); builder.Extensions.Add(new ColdStakingBuilderExtension(false)); Transaction tx = builder .AddCoins(new List <Coin> { coin }) .AddKeys(new ExtKey(privateKey, wallet.ChainCode).Derive(new KeyPath(spendingAddress.HdPath)).GetWif(wallet.Network)) .Send(script, amount) .SetChange(changeScript) .SendFees(fee) .BuildTransaction(true); if (!builder.Verify(tx)) { throw new WalletException("Could not build transaction, please make sure you entered the correct data."); } return(tx); }
/// <summary> /// Adds a spendable cold staking transaction to a normal account, as oppose to dedicated special account. /// </summary> /// <param name="wallet">Wallet to add the transaction to.</param> /// <returns>The spendable transaction that was added to the wallet.</returns> private Transaction AddSpendableColdstakingTransactionToNormalWallet(Wallet.Wallet wallet, bool script = false) { // This will always be added to the secondary address. HdAddress address = wallet.GetAllAddresses().ToArray()[1]; var transaction = this.Network.CreateTransaction(); // Use the normal wallet address here. TxDestination hotPubKey = BitcoinAddress.Create(address.Address, wallet.Network).ScriptPubKey.GetDestination(wallet.Network); TxDestination coldPubKey = BitcoinAddress.Create(coldWalletAddress2, wallet.Network).ScriptPubKey.GetDestination(wallet.Network); var scriptPubKey = new Script(OpcodeType.OP_DUP, OpcodeType.OP_HASH160, OpcodeType.OP_ROT, OpcodeType.OP_IF, OpcodeType.OP_CHECKCOLDSTAKEVERIFY, Op.GetPushOp(hotPubKey.ToBytes()), OpcodeType.OP_ELSE, Op.GetPushOp(coldPubKey.ToBytes()), OpcodeType.OP_ENDIF, OpcodeType.OP_EQUALVERIFY, OpcodeType.OP_CHECKSIG); transaction.Outputs.Add(new TxOut(Money.Coins(202), script ? scriptPubKey.WitHash.ScriptPubKey : scriptPubKey)); address.Transactions.Add(new TransactionData() { Hex = transaction.ToHex(this.Network), Amount = transaction.Outputs[0].Value, Id = transaction.GetHash(), BlockHeight = 0, Index = 0, IsCoinBase = false, IsCoinStake = false, IsColdCoinStake = true, IsPropagated = true, BlockHash = this.Network.GenesisHash, ScriptPubKey = script ? scriptPubKey.WitHash.ScriptPubKey : scriptPubKey, }); return(transaction); }
public bool StartStaking(string walletName, string walletPassword) { this.logger.LogTrace("({0}:{1})", nameof(walletName), walletName); WalletManager walletManager = this.fullNode.NodeService <IWalletManager>() as WalletManager; Wallet.Wallet wallet = walletManager.Wallets.FirstOrDefault(w => w.Name == walletName); if (wallet == null) { this.logger.LogError("Exception occurred: {0}", $"The specified wallet is unknown: '{walletName}'"); throw new RPCServerException(NBitcoin.RPC.RPCErrorCode.RPC_INVALID_REQUEST, "Wallet not found"); } else { // Check the password try { Key.Parse(wallet.EncryptedSeed, walletPassword, wallet.Network); } catch (Exception ex) { throw new SecurityException(ex.Message); } } this.fullNode.NodeFeature <MiningFeature>(true).StartStaking(walletName, walletPassword); return(true); }
public void GenerateBlocks_does_not_use_small_coins() { var walletSecret = new WalletSecret() { WalletName = "wallet", WalletPassword = "******" }; var wallet = new Wallet.Wallet(this.network); var milliseconds550MinutesAgo = (uint)Math.Max(this.chainIndexer.Tip.Header.Time - TimeSpan.FromMinutes(550).Milliseconds, 0); this.AddAccountWithSpendableOutputs(wallet); var spendableTransactions = wallet.GetAllSpendableTransactions(this.chainIndexer.Tip.Height, 0).ToList(); this.walletManager.Setup(w => w.GetSpendableTransactionsInWalletForStaking(It.IsAny <string>(), It.IsAny <int>())) .Returns(spendableTransactions); var fetchedUtxos = spendableTransactions .Select(t => new UnspentOutput( new OutPoint(t.Transaction.Id, 0), new Utilities.Coins(0, new TxOut(t.Transaction.Amount ?? Money.Zero, t.Address.ScriptPubKey), false, false))) .ToArray(); var fetchCoinsResponse = new FetchCoinsResponse(); foreach (var fetch in fetchedUtxos) { fetchCoinsResponse.UnspentOutputs.Add(fetch.OutPoint, fetch); } fetchCoinsResponse.UnspentOutputs .Where(u => u.Value.Coins.TxOut.Value < this.posMinting.MinimumStakingCoinValue).Should() .NotBeEmpty("otherwise we are not sure the code actually excludes them"); fetchCoinsResponse.UnspentOutputs .Where(u => u.Value.Coins.TxOut.Value >= this.posMinting.MinimumStakingCoinValue).Should() .NotBeEmpty("otherwise we are not sure the code actually includes them"); this.coinView.Setup(c => c.FetchCoins(It.IsAny <OutPoint[]>())) .Returns(fetchCoinsResponse); this.consensusManager.Setup(c => c.Tip).Returns(this.chainIndexer.Tip); this.dateTimeProvider.Setup(c => c.GetAdjustedTimeAsUnixTimestamp()) .Returns(this.chainIndexer.Tip.Header.Time + 16); var ct = CancellationToken.None; var utxoStakeDescriptions = this.posMinting.GetUtxoStakeDescriptions(walletSecret, ct); utxoStakeDescriptions.Select(d => d.TxOut.Value).Where(v => v < this.posMinting.MinimumStakingCoinValue) .Should().BeEmpty("small coins should not be included"); utxoStakeDescriptions.Select(d => d.TxOut.Value).Where(v => v >= this.posMinting.MinimumStakingCoinValue) .Should().NotBeEmpty("big enough coins should be included"); var expectedAmounts = spendableTransactions.Select(s => s.Transaction.Amount) .Where(a => a >= this.posMinting.MinimumStakingCoinValue).ToArray(); utxoStakeDescriptions.Count.Should().Be(expectedAmounts.Length); utxoStakeDescriptions.Select(d => d.TxOut.Value).Should().Contain(expectedAmounts); }
private void calculateOutputs(Wallet.Wallet wallet) { if (Inputs != null) { long balance = BalanceHelper.GetBalanceOfAddresses(Inputs.Select(i => i.Key).ToArray()); Outputs.Add(new Output(wallet.NewAddress().Key, balance - TransactionFee - Outputs.Select(o => o.Amount).Sum())); } }
public Transaction(List <Input> inputs, Wallet.Wallet wallet, List <Output> outputs, long transactionFee = 0, byte[] data = null) { Inputs = inputs; Data = data; Outputs = outputs; TransactionFee = transactionFee; calculateOutputs(wallet); signInputs(wallet); }
/// <summary> /// Add cold staking cold account when a wallet is recovered, this means every recovered wallet will automatical /// track addresses under the <see cref="ColdWalletAccountIndex"/> HD account. /// </summary> /// <inheritdoc /> public override Wallet.Wallet RecoverWallet(string password, string name, string mnemonic, DateTime creationTime, string passphrase, int?coinType = null) { Wallet.Wallet wallet = base.RecoverWallet(password, name, mnemonic, creationTime, passphrase, coinType); this.GetOrCreateColdStakingAccount(wallet.Name, false, password); this.GetOrCreateColdStakingAccount(wallet.Name, true, password); return(wallet); }
public Wallet.Wallet CreateNewWallet(string name, decimal startBalance, string description, string currency, Guid guid) { //create wallet and assign it to user Wallet.Wallet wallet = Wallet.Wallet.CreateWalletForUser(this, name, startBalance, description, currency, guid); return(wallet); }
public async void Unarchive_NullAddress_ArgumentNulException() { await Assert.ThrowsAsync <ArgumentNullException>(async() => { using (BlockchainApiHelper apiHelper = UnitTestUtil.GetFakeHelper()) { Wallet.Wallet wallet = this.GetWallet(apiHelper); await wallet.UnarchiveAddressAsync(null); } }); }
public async void GetAddress_BadParameters_ArgumentExceptions() { await Assert.ThrowsAsync <ArgumentNullException>(async() => { using (BlockchainApiHelper apiHelper = UnitTestUtil.GetFakeHelper()) { Wallet.Wallet wallet = this.GetWallet(apiHelper); await wallet.GetAddressAsync(null); } }); }
public void VerifyThatColdStakeTransactionCanBeFiltered() { this.Initialize(); this.CreateMempoolManager(); this.coldStakingManager.CreateWallet(walletPassword, walletName1, walletPassphrase, new Mnemonic(walletMnemonic1)); Wallet.Wallet wallet1 = this.coldStakingManager.GetWalletByName(walletName1); // This will add a normal account to our wallet. Transaction trx1 = this.AddSpendableTransactionToWallet(wallet1); // This will add a secondary account to our wallet. Transaction trx2 = this.AddSpendableColdstakingTransactionToWallet(wallet1); // THis will add a cold staking transaction to the secondary normal account address. This simulates activation of cold staking onto any normal address. Transaction trx3 = this.AddSpendableColdstakingTransactionToNormalWallet(wallet1); var accounts = wallet1.GetAccounts(Wallet.Wallet.AllAccounts).ToArray(); // We should have 2 accounts in our wallet. Assert.Equal(2, accounts.Length); // But not if we use default or specify to only return normal accounts. Assert.Single(wallet1.GetAccounts().ToArray()); // Defaults to NormalAccounts Assert.Single(wallet1.GetAccounts(Wallet.Wallet.NormalAccounts).ToArray()); // Verify that we actually have an cold staking activation UTXO in the wallet of 202 coins. // This should normally not be returned by the GetAllTransactions, and should never be included in balance calculations. Assert.True(accounts[0].ExternalAddresses.ToArray()[1].Transactions.ToArray()[0].IsColdCoinStake); Assert.Equal(new Money(202, MoneyUnit.BTC), accounts[0].ExternalAddresses.ToArray()[1].Transactions.ToArray()[0].Amount); Assert.Single(wallet1.GetAllTransactions().ToArray()); // Default to NormalAccounts, should filter out cold staking (trx3) from normal wallet. Assert.Single(wallet1.GetAllTransactions(Wallet.Wallet.NormalAccounts).ToArray()); Assert.Single(wallet1.GetAllSpendableTransactions(5, 0, Wallet.Wallet.NormalAccounts).ToArray()); // Default to NormalAccounts Assert.Equal(2, wallet1.GetAllTransactions(Wallet.Wallet.AllAccounts).ToArray().Length); Assert.Equal(2, wallet1.GetAllSpendableTransactions(5, 0, Wallet.Wallet.AllAccounts).ToArray().Length); // Specified AllAccounts, should include cold-staking transaction. // Verify balance on normal account var balance1 = accounts[0].GetBalances(true); var balance2 = accounts[0].GetBalances(false); Assert.Equal(new Money(101, MoneyUnit.BTC), balance1.ConfirmedAmount); Assert.Equal(new Money(303, MoneyUnit.BTC), balance2.ConfirmedAmount); // Verify balance on special account. // Verify balance on normal account var balance3 = accounts[1].GetBalances(true); var balance4 = accounts[1].GetBalances(false); // The only transaction that exists in the cold staking wallet, is a normal one, and should be returned for both balance queries. Assert.Equal(new Money(101, MoneyUnit.BTC), balance3.ConfirmedAmount); Assert.Equal(new Money(101, MoneyUnit.BTC), balance4.ConfirmedAmount); }
public async void ListAddresses_NegativeConfirmations_ArgumentOutOfRangeException() { await Assert.ThrowsAsync <ArgumentOutOfRangeException>(async() => { using (BlockchainApiHelper apiHelper = UnitTestUtil.GetFakeHelper()) { Wallet.Wallet wallet = this.GetWallet(apiHelper); await wallet.ListAddressesAsync(-1); } }); }
public async void SendPayment_SendBtc_NoFreeOutputs() { ServerApiException apiException = await Assert.ThrowsAsync <ServerApiException>(async() => { using (BlockchainApiHelper apiHelper = new BlockchainApiHelper()) { Wallet.Wallet wallet = apiHelper.InitializeWallet(WalletTests.WALLET_ID, WalletTests.WALLET_PASSWORD, WalletTests.WALLET_PASSWORD2); await wallet.SendAsync(WalletTests.FIRST_ADDRESS, BitcoinValue.FromBtc(1)); } }); Assert.Contains("No free", apiException.Message); }
public async void GetAddresses_Valid() { using (BlockchainApiHelper apiHelper = new BlockchainApiHelper()) { Wallet.Wallet wallet = apiHelper.InitializeWallet(WalletTests.WALLET_ID, WalletTests.WALLET_PASSWORD, WalletTests.WALLET_PASSWORD2); List <WalletAddress> addresses = await wallet.ListAddressesAsync(); Assert.NotNull(addresses); Assert.NotEmpty(addresses); Assert.True(addresses.Any(a => string.Equals(a.AddressStr, WalletTests.FIRST_ADDRESS))); } }
public async void Unarchive_BadAddress_ServerApiException() { ServerApiException apiException = await Assert.ThrowsAsync <ServerApiException>(async() => { using (BlockchainApiHelper apiHelper = new BlockchainApiHelper()) { Wallet.Wallet walletHelper = apiHelper.InitializeWallet(WalletTests.WALLET_ID, WalletTests.WALLET_PASSWORD, WalletTests.WALLET_PASSWORD2); await walletHelper.UnarchiveAddressAsync("BadAddress"); } }); Assert.Contains("Checksum", apiException.Message); }
/// <summary> /// Gets a cold staking account. /// </summary> /// <remarks> /// <para>In order to keep track of cold staking addresses and balances we are using <see cref="HdAccount"/>'s /// with indexes starting from the value defined in <see cref="Wallet.SpecialPurposeAccountIndexesStart"/>. /// </para><para> /// We are using two such accounts, one when the wallet is in the role of cold wallet, and another one when /// the wallet is in the role of hot wallet. For this reason we specify the required account when calling this /// method. /// </para></remarks> /// <param name="wallet">The wallet where we wish to create the account.</param> /// <param name="isColdWalletAccount">Indicates whether we need the cold wallet account (versus the hot wallet account).</param> /// <returns>The cold staking account or <c>null</c> if the account does not exist.</returns> internal HdAccount GetColdStakingAccount(Wallet.Wallet wallet, bool isColdWalletAccount) { HdAccount account = wallet.GetAccount(isColdWalletAccount ? ColdWalletAccountName : HotWalletAccountName); if (account == null) { this.logger.LogTrace("(-)[ACCOUNT_DOES_NOT_EXIST]:null"); return(null); } this.logger.LogTrace("(-):'{0}'", account.Name); return(account); }
/// <summary> /// Returns information related to cold staking. /// </summary> /// <param name="walletName">The wallet to return the information for.</param> /// <returns>A <see cref="Models.GetColdStakingInfoResponse"/> object containing the information.</returns> internal Models.GetColdStakingInfoResponse GetColdStakingInfo(string walletName) { Wallet.Wallet wallet = this.GetWalletByName(walletName); var response = new Models.GetColdStakingInfoResponse() { ColdWalletAccountExists = this.GetColdStakingAccount(wallet, true) != null, HotWalletAccountExists = this.GetColdStakingAccount(wallet, false) != null }; this.logger.LogTrace("(-):'{0}'", response); return(response); }
/// <summary> /// Gets a cold staking account. /// </summary> /// <remarks> /// <para>In order to keep track of cold staking addresses and balances we are using <see cref="HdAccount"/>'s /// with indexes starting from the value defined in <see cref="Wallet.SpecialPurposeAccountIndexesStart"/>. /// </para><para> /// We are using two such accounts, one when the wallet is in the role of cold wallet, and another one when /// the wallet is in the role of hot wallet. For this reason we specify the required account when calling this /// method. /// </para></remarks> /// <param name="wallet">The wallet where we wish to create the account.</param> /// <param name="isColdWalletAccount">Indicates whether we need the cold wallet account (versus the hot wallet account).</param> /// <returns>The cold staking account or <c>null</c> if the account does not exist.</returns> public HdAccount GetColdStakingAccount(Wallet.Wallet wallet, bool isColdWalletAccount) { var coinType = wallet.Network.Consensus.CoinType; HdAccount account = wallet.GetAccount(isColdWalletAccount ? ColdWalletAccountName : HotWalletAccountName); if (account == null) { this.logger.LogTrace("(-)[ACCOUNT_DOES_NOT_EXIST]:null"); return(null); } this.logger.LogTrace("(-):'{0}'", account.Name); return(account); }