Skip to content

Commit

Permalink
Add support for merging specific addresses
Browse files Browse the repository at this point in the history
  • Loading branch information
Swtrse committed Jan 13, 2019
1 parent 517edd2 commit 6d2c950
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 34 deletions.
42 changes: 35 additions & 7 deletions BusinessLogic/ProcessWallet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -246,15 +246,42 @@ private void MoveToCollectAddress(List<string> addresses)
WaitTillAllConfirmed(transactions);
}

private void MergeExcludedAddressInputs(string[] addresses)
{
Log.Debug("Call of method: void ProcessWallet.MergeExcludedAddressInputs(List<string> addresses).");
Log.Verbose("Parameter addresses: {@addresses}.", addresses);
if (!Settings.Address.MergeInputs)
{
Log.Information("Input merge deactivated. No inputs will be merged.");
return;
}

foreach (string address in addresses.Where(a => a != Settings.Stake.DedicatedCollectingAddress && a != Settings.Stake.DedicatedStakingAddress))
{
List<string> transactions;
do
{
transactions = ProcessInputs(new List<string> {address}, 2, targetAddress: address);
WaitTillAllConfirmed(transactions);
} while (transactions.Count > 1);
}
}

[NotNull]
private List<string> ProcessInputs([NotNull] List<string> addresses, int minimunNeededInputs, decimal amountLock = decimal.MaxValue)
private List<string> ProcessInputs([NotNull] List<string> addresses, int minimunNeededInputs, decimal amountLock = decimal.MaxValue, [CanBeNull] string targetAddress = null)
{
Log.Debug("Call of method: List<string> ProcessWallet.ProcessInputs(List<string> addresses, int minimunNeededInputs).");
Log.Verbose("Parameter addresses: {@addresses}.", addresses);
Log.Verbose("Parameter minimunNeededInputs: {minimunNeededInputs}.", minimunNeededInputs);
Log.Verbose("Parameter amount: {amountLock}.", amountLock);
Log.Verbose("Parameter amount: {targetAddress}.", targetAddress);

if (string.IsNullOrWhiteSpace(targetAddress))
{
targetAddress = Settings.Stake.DedicatedCollectingAddress;
}

if (addresses.Count == 0)
if (addresses.Count == 0 || string.IsNullOrWhiteSpace(targetAddress))
{
var erg = new List<string>();
Log.Verbose("Returnvalue of ProcessWallet.ProcessInputs(List<string> addresses, int minimunNeededInputs): {@ret}.", erg);
Expand All @@ -277,7 +304,7 @@ private List<string> ProcessInputs([NotNull] List<string> addresses, int minimun
if (transactions.Count >= minimunNeededInputs)
{
string plural = transactions.Count > 1 ? "s" : string.Empty;
Log.Information($"Merge {transactions.Count} input{plural} to {Settings.Stake.DedicatedCollectingAddress}.");
Log.Information($"Merge {transactions.Count} input{plural} to {targetAddress}.");
foreach (ListUnspentResponse trans in transactions)
{
Log.Debug($"Include Transaction: {trans.TxId}.");
Expand All @@ -290,8 +317,8 @@ private List<string> ProcessInputs([NotNull] List<string> addresses, int minimun
continue;
}

Log.Information($"Move {amount} coins to {Settings.Stake.DedicatedCollectingAddress} without fee.");
outputs.Add(Settings.Stake.DedicatedCollectingAddress, amount);
Log.Information($"Move {amount} coins to {targetAddress} without fee.");
outputs.Add(targetAddress, amount);
transactionList.Add(Send(inputs, outputs));
tCount = 0;
inputs = new List<CreateRawTransactionInput>();
Expand All @@ -302,8 +329,8 @@ private List<string> ProcessInputs([NotNull] List<string> addresses, int minimun

if (tCount > 0)
{
Log.Information($"Move {amount} coins to {Settings.Stake.DedicatedCollectingAddress} without fee.");
outputs.Add(Settings.Stake.DedicatedCollectingAddress, amount);
Log.Information($"Move {amount} coins to {targetAddress} without fee.");
outputs.Add(targetAddress, amount);
transactionList.Add(Send(inputs, outputs));
}

Expand All @@ -330,6 +357,7 @@ public void Run()
MoveSmallStakesToCollectAddress();
MinimizeInputs();
GenerateStakingInputs();
MergeExcludedAddressInputs(Settings.Address.ExcludeAddresses);
Log.Information("Lock wallet.");
AccessWallet.WalletLock();
Log.Information("Unlock wallet for staking only.");
Expand Down
4 changes: 2 additions & 2 deletions BusinessLogic/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@
<value>{0}{1}Please check your settings.</value>
</data>
<data name="SettingsHelper_DisplayHelp_Text" xml:space="preserve">
<value>General settings{0}-? or --help: Displays this help{0}{0}Settings regarding the stake function{0}-s=&lt;true/false&gt; or --stakes=&lt;true/false&gt; : Enables or disables modifications of inputs at the stake address. Default: true{0}-a=&lt;address&gt; or --stakeaddress=&lt;addres&gt; : Sets the dedicated stake address. Mandatory.{0}-c=&lt;address&gt; or --collectaddress=&lt;address&gt; : Sets the dedicated collect address. Mandatory.{0}-w=&lt;days&gt; or --patience=&lt;days&gt; : Sets the number of days when a input should stake at least once. Default: 7{0}-q=&lt;password&gt; or --walletpassword=&lt;password&gt;: Sets the password for the wallet. Mandatory.{0}{0}Settings regarding all other addresses in the wallet{0}-i=&lt;true/false&gt; or --collectinputs=&lt;true/false&gt; : Moves all inputs from other addresses to the collect address. Default: true{0}-e=&lt;adr_1&gt;{{,&lt;adr_n&gt;}} or --excludeaddress=&lt;adr_1&gt;{{,&lt;adr_n&gt;}}: Comma seperated list of addresses that will be excluded.{0}{0}Settings regarding the rpc connection to the wallet{0}-u=&lt;user&gt; or --user=&lt;user&gt; : The user for the rpc connection. Mandatory.{0}-p=&lt;password&gt; or --password=&lt;password&gt;: The password for the rpc connection. Mandatory.{0}-o=&lt;uri&gt; or --uri=&lt;uri&gt; : The uri for the rpc connection. Mandatory.{0}</value>
<value>General settings{0}-? or --help: Displays this help{0}{0}Settings regarding the stake function{0}-s=&lt;true/false&gt; or --stakes=&lt;true/false&gt; : Enables or disables modifications of inputs at the stake address. Default: true{0}-a=&lt;address&gt; or --stakeaddress=&lt;addres&gt; : Sets the dedicated stake address. Mandatory.{0}-c=&lt;address&gt; or --collectaddress=&lt;address&gt; : Sets the dedicated collect address. Mandatory.{0}-w=&lt;days&gt; or --patience=&lt;days&gt; : Sets the number of days when a input should stake at least once. Default: 7{0}-q=&lt;password&gt; or --walletpassword=&lt;password&gt;: Sets the password for the wallet. Mandatory.{0}{0}Settings regarding all other addresses in the wallet{0}-i=&lt;true/false&gt; or --collectinputs=&lt;true/false&gt; : Moves all inputs from other addresses to the collect address. Default: true{0}-e=&lt;adr_1&gt;{{,&lt;adr_n&gt;}} or --excludeaddress=&lt;adr_1&gt;{{,&lt;adr_n&gt;}}: Comma seperated list of addresses that will be excluded.{0}-x=&lt;true/false&gt; or --mergeInputs: : Merge all inputs inside an excluded address to one. Default: false{0}{0}Settings regarding the rpc connection to the wallet{0}-u=&lt;user&gt; or --user=&lt;user&gt; : The user for the rpc connection. Mandatory.{0}-p=&lt;password&gt; or --password=&lt;password&gt;: The password for the rpc connection. Mandatory.{0}-o=&lt;uri&gt; or --uri=&lt;uri&gt; : The uri for the rpc connection. Mandatory.</value>
</data>
<data name="SettingsHelper_DisplayHelp_Header" xml:space="preserve">
<value>StakeMaster commandline arguments:</value>
Expand All @@ -153,7 +153,7 @@
<data name="FreeTransactionNotPossibleException_Size_Name" xml:space="preserve">
<value>Calculated transaction size:</value>
</data>
<data name="TransactionHelper_TransactionHelper_Confirms_OutOfRange" xml:space="preserve">
<data name="TransactionHelper_TransactionHelper_Confirms_OutOfRange" xml:space="preserve">
<value>Confirms must be greater 0.</value>
</data>
</root>
4 changes: 3 additions & 1 deletion BusinessLogic/SettingsHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,9 @@ private static OtherAddressSettings ReadOtherAddressSettings([NotNull] string[]
{
string[] excludes = ExtractArgumentStringArrayValue(args, "-e=", "--excludeaddress=");
excludes = excludes.Concat(new[] {dedicatedStakingAddress, dedicatedCollectingAddress}).ToArray();
return new OtherAddressSettings(ExtractArgumentBoolValue(args, "-i=", "--collectinputs=", true), excludes);
bool merge = ExtractArgumentBoolValue(args, "-x=", "--mergeInputs=", false);
bool collect = ExtractArgumentBoolValue(args, "-i=", "--collectinputs=", true);
return new OtherAddressSettings(collect, excludes, merge);
}

[NotNull]
Expand Down
47 changes: 30 additions & 17 deletions StakeMasterBussinessLogic.Test/TransactionHelperTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public void Constructor_SetBaseDate()
//Arrange
var expectedBaseDate = new DateTime(2016, 11, 20);
//Act
var result = new TransactionHelper(1, 1, 581, 1, new DateTime(2016, 11, 20), 60);
var result = new TransactionHelper(1, 1, 581, 1, new DateTime(2016, 11, 20), 60, 1);
//Assert
Assert.AreEqual(expectedBaseDate, result.BaseDate);
}
Expand All @@ -38,7 +38,7 @@ public void Constructor_SetConnectionTimeout()
//Arrange
const int expectedTimeout = 60;
//Act
var result = new TransactionHelper(1, 1, 581, 1, DateTime.Now, 60);
var result = new TransactionHelper(1, 1, 581, 1, DateTime.Now, 60, 1);
//Assert
Assert.AreEqual(expectedTimeout, result.ConnectionTimeout);
}
Expand All @@ -49,7 +49,7 @@ public void Constructor_SetFreeByteLimit()
//Arrange
const int expectedFree = 985;
//Act
var result = new TransactionHelper(1, 1, 1, 985, DateTime.Now, 60);
var result = new TransactionHelper(1, 1, 1, 985, DateTime.Now, 60, 1);
//Assert
Assert.AreEqual(expectedFree, result.FreeTransactionByteLimit);
}
Expand All @@ -60,7 +60,7 @@ public void Constructor_SetInputSize()
//Arrange
const int expectedInputs = 167;
//Act
var result = new TransactionHelper(167, 1, 1, 1, DateTime.Now, 60);
var result = new TransactionHelper(167, 1, 1, 1, DateTime.Now, 60, 1);
//Assert
Assert.AreEqual(expectedInputs, result.InputSize);
}
Expand All @@ -71,7 +71,7 @@ public void Constructor_SetOutputSize()
//Arrange
const int expectedOutputs = 289;
//Act
var result = new TransactionHelper(1, 289, 1, 1, DateTime.Now, 60);
var result = new TransactionHelper(1, 289, 1, 1, DateTime.Now, 60, 1);
//Assert
Assert.AreEqual(expectedOutputs, result.OutputSize);
}
Expand All @@ -82,27 +82,39 @@ public void Constructor_SetOverheadSize()
//Arrange
const int expectedOverhead = 581;
//Act
var result = new TransactionHelper(1, 1, 581, 1, DateTime.Now, 60);
var result = new TransactionHelper(1, 1, 581, 1, DateTime.Now, 60, 1);
//Assert
Assert.AreEqual(expectedOverhead, result.TransactionOverhead);
}

[TestMethod]
public void Constructor_SetConfirms()
{
//Arrange
const int expectedConfirms = 13;
//Act
var result = new TransactionHelper(1, 1, 581, 1, DateTime.Now, 60, 13);
//Assert
Assert.AreEqual(expectedConfirms, result.Confirms);
}

[DataTestMethod]
[DataRow(23, 3, 62, 200, 3, "2017-05-16", 60, 5)]
[DataRow(17, 12, 100, 1200, 20, "2017-05-16", 60, 50)]
[DataRow(10, 11, 12, 77, 5, "2017-05-16", 60, 1)]
[DataRow(23, 3, 62, 200, 3, "2017-05-16", 60, 1, 5)]
[DataRow(17, 12, 100, 1200, 20, "2017-05-16", 60, 2, 50)]
[DataRow(10, 11, 12, 77, 5, "2017-05-16", 60, 3, 1)]
public void GetMaxPossibleInputCountForFreeTransaction_Default(int inputSize,
int outputSize,
int overhead,
int byteLimit,
int outputs,
string date,
int timeout,
int confirms,
int expectedResult)
{
//Arrange
DateTime dateTime = DateTime.ParseExact(date, "yyyy-MM-dd", CultureInfo.InvariantCulture);
var test = new TransactionHelper(inputSize, outputSize, overhead, byteLimit, dateTime, timeout);
var test = new TransactionHelper(inputSize, outputSize, overhead, byteLimit, dateTime, timeout, confirms);
//Act
int result = test.GetMaxPossibleInputCountForFreeTransaction(outputs);
//Assert
Expand All @@ -114,7 +126,7 @@ public void GetMaxPossibleInputCountForFreeTransaction_Default(int inputSize,
public void GetMaxPossibleInputCountForFreeTransaction_NotPossibleException()
{
//Arrange
var test = new TransactionHelper(10, 11, 12, 76, DateTime.Now, 60);
var test = new TransactionHelper(10, 11, 12, 76, DateTime.Now, 60, 1);
const int outputs = 5;
//Act
test.GetMaxPossibleInputCountForFreeTransaction(outputs);
Expand All @@ -123,21 +135,22 @@ public void GetMaxPossibleInputCountForFreeTransaction_NotPossibleException()
}

[DataTestMethod]
[DataRow(23, 3, 62, 200, 3, "2017-05-16", 60, 23)]
[DataRow(17, 12, 100, 1200, 20, "2017-05-16", 60, 63)]
[DataRow(10, 11, 12, 73, 5, "2017-05-16", 60, 1)]
[DataRow(23, 3, 62, 200, 3, "2017-05-16", 60, 1, 23)]
[DataRow(17, 12, 100, 1200, 20, "2017-05-16", 60, 2, 63)]
[DataRow(10, 11, 12, 73, 5, "2017-05-16", 60, 3, 1)]
public void GetMaxPossibleOutputCountForFreeTransaction_Default(int inputSize,
int outputSize,
int overhead,
int byteLimit,
int inputs,
string date,
int timeout,
int confirms,
int expectedResult)
{
//Arrange
DateTime dateTime = DateTime.ParseExact(date, "yyyy-MM-dd", CultureInfo.InvariantCulture);
var test = new TransactionHelper(inputSize, outputSize, overhead, byteLimit, dateTime, timeout);
var test = new TransactionHelper(inputSize, outputSize, overhead, byteLimit, dateTime, timeout, confirms);
//Act
int result = test.GetMaxPossibleOutputCountForFreeTransaction(inputs);
//Assert
Expand All @@ -149,7 +162,7 @@ public void GetMaxPossibleOutputCountForFreeTransaction_Default(int inputSize,
public void GetMaxPossibleOutputCountForFreeTransaction_NotPossibleException()
{
//Arrange5
var test = new TransactionHelper(10, 11, 12, 72, DateTime.Now, 60);
var test = new TransactionHelper(10, 11, 12, 72, DateTime.Now, 60, 1);
const int inputs = 5;
//Act
test.GetMaxPossibleOutputCountForFreeTransaction(inputs);
Expand All @@ -161,7 +174,7 @@ public void GetMaxPossibleOutputCountForFreeTransaction_NotPossibleException()
public void GetTransactionSize_Default()
{
//Arrange
var test = new TransactionHelper(12, 3, 50, 200, DateTime.Now, 60);
var test = new TransactionHelper(12, 3, 50, 200, DateTime.Now, 60, 1);
const int inputs = 5;
const int outputs = 7;
const int expectedSize = 131;
Expand Down
6 changes: 4 additions & 2 deletions StakeMasterEntities.Test/OtherAddressSettingsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@ public void Constructor_AllParametersSet()
//Arrange
var excludeAddresses = new[] {"Dummy1", "Dummy2"};
//Act
var result = new OtherAddressSettings(false, excludeAddresses);
var result = new OtherAddressSettings(false, excludeAddresses, true);
//Assert
Assert.IsFalse(result.CollectInputs);
Assert.IsTrue(result.MergeInputs);
Assert.AreEqual(2, result.ExcludeAddresses.Length);
Assert.IsTrue(result.ExcludeAddresses.Contains(excludeAddresses[0]));
Assert.IsTrue(result.ExcludeAddresses.Contains(excludeAddresses[1]));
Expand All @@ -40,9 +41,10 @@ public void Constructor_ParameterAddressIsNull()
//Arrange
string[] excludeAddresses = null;
//Act
var result = new OtherAddressSettings(true, excludeAddresses);
var result = new OtherAddressSettings(true, excludeAddresses, false);
//Assert
Assert.IsTrue(result.CollectInputs);
Assert.IsFalse(result.MergeInputs);
Assert.IsNotNull(result.ExcludeAddresses);
Assert.AreEqual(0, result.ExcludeAddresses.Length);
}
Expand Down
6 changes: 3 additions & 3 deletions StakeMasterEntities.Test/SettingsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public void Constructor_AllParametersSet()
{
//Arrange
var stake = new StakeSettings(true, "DummyStakeAddress", "DummyCollectingAddress", 7, "pass");
var address = new OtherAddressSettings(true, null);
var address = new OtherAddressSettings(true, null, false);
var connection = new ConnectionSettings(new Uri("http://someuriitis:12345", UriKind.Absolute), "DummyUser", "DummyPassword");
//Act
var result = new Settings(stake, address, connection);
Expand Down Expand Up @@ -58,7 +58,7 @@ public void Constructor_ParameterConnectionIsNull()
{
//Arrange
var stake = new StakeSettings(true, "DummyStakeAddress", "DummyCollectingAddress", 7, "pass");
var address = new OtherAddressSettings(true, null);
var address = new OtherAddressSettings(true, null, false);
ConnectionSettings connection = null;
//Act
new Settings(stake, address, connection);
Expand All @@ -74,7 +74,7 @@ public void Constructor_ParameterStakeIsNull()
{
//Arrange
StakeSettings stake = null;
var address = new OtherAddressSettings(true, null);
var address = new OtherAddressSettings(true, null, false);
var connection = new ConnectionSettings(new Uri("http://someuriitis:12345", UriKind.Absolute), "DummyUser", "DummyPassword");
//Act
new Settings(stake, address, connection);
Expand Down
13 changes: 12 additions & 1 deletion StakeMasterEntities/OtherAddressSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ public sealed class OtherAddressSettings
/// <see cref="StakeSettings.DedicatedCollectingAddress" />.
/// </param>
/// <param name="excludeAddresses">A list of addresses that are excluded from the move.</param>
public OtherAddressSettings(bool collectInputs, [CanBeNull] string[] excludeAddresses)
public OtherAddressSettings(bool collectInputs, [CanBeNull] string[] excludeAddresses, bool mergeInputs)
{
CollectInputs = collectInputs;
MergeInputs = mergeInputs;
ExcludeAddresses = excludeAddresses ?? new string[0];
}

Expand All @@ -42,6 +43,16 @@ public OtherAddressSettings(bool collectInputs, [CanBeNull] string[] excludeAddr
/// </summary>
public bool CollectInputs { get; }

/// <summary>
/// When
/// <value>true</value>
/// inputs of excluded addresses will be merged to one.
/// When
/// <value>false</value>
/// no input will be merged.
/// </summary>
public bool MergeInputs { get; }

/// <summary>
/// Contains a list of addresses that will not be moved even if <see cref="CollectInputs" /> is
/// <value>true</value>
Expand Down
12 changes: 11 additions & 1 deletion StakeMasterEntities/StakeMasterE.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 6d2c950

Please sign in to comment.