diff --git a/src/Helpers/Constants.cs b/src/Helpers/Constants.cs
index 046ec18c..fdfa1592 100644
--- a/src/Helpers/Constants.cs
+++ b/src/Helpers/Constants.cs
@@ -75,6 +75,7 @@ public class Constants
public static readonly decimal MAXIMUM_WITHDRAWAL_BTC_AMOUNT = 21_000_000;
public static readonly int TRANSACTION_CONFIRMATION_MINIMUM_BLOCKS;
public static readonly long ANCHOR_CLOSINGS_MINIMUM_SATS;
+ public static readonly long MINIMUM_SWEEP_TRANSACTION_AMOUNT_SATS = 25_000_000; //25M sats
public static readonly string DEFAULT_DERIVATION_PATH = "48'/1'";
public static readonly int SESSION_TIMEOUT_MILLISECONDS = 3_600_000;
@@ -86,6 +87,11 @@ public class Constants
///
public static decimal MAX_TX_FEE_RATIO = 0.5m;
+ ///
+ /// The target number of confirmations blocks (fee rate) for the sweep transaction
+ ///
+ public static int SWEEP_CONF_TARGET = 6;
+
public const string IsFrozenTag = "frozen";
public const string IsManuallyFrozenTag = "manually_frozen";
@@ -217,6 +223,13 @@ static Constants()
var anchorClosingMinSats = GetEnvironmentalVariableOrThrowIfNotTesting("ANCHOR_CLOSINGS_MINIMUM_SATS");
if (anchorClosingMinSats != null) ANCHOR_CLOSINGS_MINIMUM_SATS = long.Parse(anchorClosingMinSats); // Check https://github.com/lightningnetwork/lnd/issues/6505#issuecomment-1120364460 to understand, we need 100K+ to support anchor channel closings
+ var sweepConfTarget = Environment.GetEnvironmentVariable("SWEEP_CONF_TARGET");
+ if (sweepConfTarget != null) SWEEP_CONF_TARGET = int.Parse(sweepConfTarget);
+
+ var minSweepTransactionAmount = Environment.GetEnvironmentVariable("MINIMUM_SWEEP_TRANSACTION_AMOUNT_SATS");
+ if (minSweepTransactionAmount != null) MINIMUM_SWEEP_TRANSACTION_AMOUNT_SATS = long.Parse(minSweepTransactionAmount);
+
+
DEFAULT_DERIVATION_PATH = GetEnvironmentalVariableOrThrowIfNotTesting("DEFAULT_DERIVATION_PATH") ?? DEFAULT_DERIVATION_PATH;
var timeout = Environment.GetEnvironmentVariable("SESSION_TIMEOUT_MILLISECONDS");
diff --git a/src/Jobs/SweepNodeWalletsJob.cs b/src/Jobs/SweepNodeWalletsJob.cs
index 19d5f818..ca5a72d9 100644
--- a/src/Jobs/SweepNodeWalletsJob.cs
+++ b/src/Jobs/SweepNodeWalletsJob.cs
@@ -44,7 +44,7 @@ public SweepNodeWalletsJob(ILogger logger,
INBXplorerService nbXplorerService,
ILightningClientService lightningClientService)
{
-
+
_logger = logger;
_nodeRepository = nodeRepository;
_walletRepository = walletRepository;
@@ -66,7 +66,7 @@ public async Task Execute(IJobExecutionContext context)
#region Local functions
async Task SweepFunds(Node node, Wallet wallet, Lightning.LightningClient lightningClient
- ,List utxos)
+ , List utxos)
{
if (node == null) throw new ArgumentNullException(nameof(node));
if (wallet == null) throw new ArgumentNullException(nameof(wallet));
@@ -81,9 +81,9 @@ async Task SweepFunds(Node node, Wallet wallet, Lightning.LightningClient lightn
if (node.ChannelAdminMacaroon != null)
{
var lndChangeAddress = await lightningClient.NewAddressAsync(new NewAddressRequest
- {
- Type = AddressType.UnusedWitnessPubkeyHash
- },
+ {
+ Type = AddressType.UnusedWitnessPubkeyHash
+ },
new Metadata
{
{
@@ -92,21 +92,21 @@ async Task SweepFunds(Node node, Wallet wallet, Lightning.LightningClient lightn
});
var totalSatsAvailable = utxos.Sum(x => x.AmountSat);
- if (returningAddress != null && lndChangeAddress != null && utxos.Any() && totalSatsAvailable > requiredAnchorChannelClosingAmount)
+ if (returningAddress != null && lndChangeAddress != null && utxos.Any() && totalSatsAvailable > Constants.MINIMUM_SWEEP_TRANSACTION_AMOUNT_SATS)
{
- var sweepedFundsAmount = (long)((totalSatsAvailable - requiredAnchorChannelClosingAmount) * 0.9); // We should let requiredAnchorChannelClosingAmount sats as a UTXO in in the hot wallet for channel closings
+ // We need to maintain onchain balance to be at least RequiredAnchorChannelClosingAmount but also we apply a 10% buffer to pay for this sweep fees and let some more money on the wallet
+ var sweepedFundsAmount = (long)((totalSatsAvailable - requiredAnchorChannelClosingAmount) * 0.9);
var sendManyResponse = await lightningClient.SendManyAsync(new SendManyRequest()
- {
- AddrToAmount =
+ {
+ AddrToAmount =
{
{returningAddress.Address.ToString(), sweepedFundsAmount}, //Sweeped funds
- {lndChangeAddress.Address, requiredAnchorChannelClosingAmount},
},
- MinConfs = 1,
- Label = $"Hot wallet Sweep tx on {DateTime.UtcNow.ToString("O")} to walletId:{wallet.Id}",
- SpendUnconfirmed = false,
- TargetConf = 1 // 1 for now TODO Maybe this can be set as a global env var for all the Target blocks of the FM..
- },
+ MinConfs = 6,
+ Label = $"Hot wallet Sweep tx on {DateTime.UtcNow.ToString("O")} to walletId:{wallet.Id}",
+ SpendUnconfirmed = false,
+ TargetConf = Constants.SWEEP_CONF_TARGET
+ },
new Metadata
{
{
@@ -157,9 +157,9 @@ async Task SweepFunds(Node node, Wallet wallet, Lightning.LightningClient lightn
try
{
-
+
var client = _lightningClientService.GetLightningClient(node.Endpoint);
-
+
var unspentResponse = await client.ListUnspentAsync(new ListUnspentRequest { MinConfs = 1, MaxConfs = Int32.MaxValue }, new Metadata
{
{