Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/Data/Repositories/ChannelFeeStateRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,22 @@ public ChannelFeeStateRepository(IDbContextFactory<ApplicationDbContext> dbConte
.FirstOrDefaultAsync(x => x.ChannelId == channelId);
}

public async Task<List<ChannelFeeState>> GetByManagedNodePubKey(string managedNodePubKey)
{
await using var context = await _dbContextFactory.CreateDbContextAsync();

// ChannelFeeState carries no node pubkey; the owning node lives on ChannelRoutingState
// (1:1 with the same Channel), so filter through it.
var channelIds = context.ChannelRoutingStates
.Where(s => s.ManagedNodePubKey == managedNodePubKey)
.Select(s => s.ChannelId);

return await context.ChannelFeeStates
.Include(x => x.Channel)
.Where(x => channelIds.Contains(x.ChannelId))
.ToListAsync();
}

public async Task UpsertByChannelId(ChannelFeeState state)
{
await using var context = await _dbContextFactory.CreateDbContextAsync();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,12 @@ public interface IChannelFeeStateRepository
{
Task<ChannelFeeState?> GetByChannelId(int channelId);

/// <summary>
/// All fee-state rows for channels owned by the given managed node (joined to
/// ChannelRoutingState, which holds the owning-node pubkey), with their Channel loaded.
/// Used by the fee engine to batch per-node state and to drive restore-on-disable.
/// </summary>
Task<List<ChannelFeeState>> GetByManagedNodePubKey(string managedNodePubKey);

Task UpsertByChannelId(ChannelFeeState state);
}
8 changes: 8 additions & 0 deletions src/Data/Repositories/Interfaces/IRebalanceRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@ public interface IRebalanceRepository
/// </summary>
Task<int> GetInFlightByNode(int nodeId);

/// <summary>
/// True when a non-terminal rebalance (Pending/InFlight) has this channel as its source.
/// The Phase 2 fee engine uses this to enforce the fee-vs-rebalance authority split: while
/// a rebalance is moving a channel's ratio, the fee engine must not react to that manufactured
/// signal. <paramref name="sourceChannelId"/> is the <see cref="Channel"/> primary key.
/// </summary>
Task<bool> HasInFlightRebalanceBySourceChannel(int sourceChannelId);

/// <summary>
/// Budget consumption for a node since <paramref name="since"/> (by CreationDatetime):
/// non-terminal rows count MAX(FeePaidSats, ReservedFeeSats) so in-flight spend counts
Expand Down
9 changes: 9 additions & 0 deletions src/Data/Repositories/RebalanceRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,15 @@ public async Task<int> GetInFlightByNode(int nodeId)
&& (r.Status == RebalanceStatus.Pending || r.Status == RebalanceStatus.InFlight));
}

public async Task<bool> HasInFlightRebalanceBySourceChannel(int sourceChannelId)
{
await using var context = await _dbContextFactory.CreateDbContextAsync();

return await context.Rebalances
.AnyAsync(r => r.SourceChannelId == sourceChannelId
&& (r.Status == RebalanceStatus.Pending || r.Status == RebalanceStatus.InFlight));
}

public async Task<long> GetConsumedFeesSince(int nodeId, DateTimeOffset since)
{
await using var context = await _dbContextFactory.CreateDbContextAsync();
Expand Down
Loading