/// <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.Types.Wallet wallet = this.GetWalletByName(walletName); IHdAccount account = this.GetColdStakingAccount(wallet, isColdWalletAddress); if (account == null) { this.logger.LogTrace("(-)[ACCOUNT_DOES_NOT_EXIST]:null"); return(null); } HdAddress address = account.GetFirstUnusedReceivingAddress(wallet.walletStore); 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.UpdateKeysLookup(wallet, newAddresses); address = newAddresses.First(); } this.logger.LogTrace("(-):'{0}'", address.Address); return(address); }
/// <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.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> public IHdAccount GetOrCreateColdStakingAccount(string walletName, bool isColdWalletAccount, string walletPassword) { Wallet.Types.Wallet wallet = this.GetWalletByName(walletName); IHdAccount 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, this.dateTimeProvider.GetTimeOffset(), accountIndex, accountName); // Maintain at least one unused address at all times. This will ensure that wallet recovery will also work. IEnumerable <HdAddress> newAddresses = account.CreateAddresses(wallet.Network, 1, false); this.UpdateKeysLookup(wallet, newAddresses); // Save the changes to the file. this.SaveWallet(wallet); this.logger.LogTrace("(-):'{0}'", account.Name); return(account); }