start adding notifications in hub for onchain related acitvity

This commit is contained in:
Kukks 2023-08-17 15:03:37 +02:00 committed by Dennis Reimann
parent 71f9cb27b6
commit dabf1d4159
No known key found for this signature in database
GPG key ID: 5009E1797F03F8D0
4 changed files with 138 additions and 14 deletions

View file

@ -5,15 +5,23 @@ namespace BTCPayApp.CommonServer
{
public interface IBTCPayAppServerClient
{
Task<string> ClientMethod1(string user, string message);
Task ClientMethod2();
Task<string> ClientMethod3(string user, string message, CancellationToken cancellationToken); // ca
Task OnTransactionDetected(string txid);
void NewBlock(string block);
}
public interface IBTCPayAppServerHub
{
Task<string> SendMessage(string user, string message);
Task SomeHubMethod();
Task Handshake(AppHandshake handshake);
}
public class AppHandshake
{
public string DerivationScheme { get; set; }
}
}

View file

@ -8,6 +8,8 @@ public static class BTCPayAppExtensions
public static IServiceCollection AddBTCPayApp(this IServiceCollection serviceCollection)
{
serviceCollection.AddSingleton<BtcPayAppService>();
serviceCollection.AddSingleton<BTCPayAppState>();
serviceCollection.AddHostedService(serviceProvider => serviceProvider.GetRequiredService<BTCPayAppState>());
return serviceCollection;
}
@ -18,4 +20,4 @@ public static class BTCPayAppExtensions
routeBuilder.MapHub<BTCPayAppHub>("hub/btcpayapp");
});
}
}
}

View file

@ -1,21 +1,135 @@
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using BTCPayApp.CommonServer;
using BTCPayServer.Abstractions.Constants;
using BTCPayServer.Data;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using NBitcoin;
using NBXplorer;
using NBXplorer.Models;
using NewBlockEvent = BTCPayServer.Events.NewBlockEvent;
namespace BTCPayServer.Controllers;
public class BTCPayAppHub : Hub<IBTCPayAppServerClient>, IBTCPayAppServerHub
public class BTCPayAppState : IHostedService
{
public async Task<string> SendMessage(string user, string message)
private readonly IHubContext<BTCPayAppHub, IBTCPayAppServerClient> _hubContext;
private readonly ILogger<BTCPayAppState> _logger;
private readonly ExplorerClientProvider _explorerClientProvider;
private readonly BTCPayNetworkProvider _networkProvider;
private readonly EventAggregator _eventAggregator;
private CompositeDisposable? _compositeDisposable;
private ExplorerClient _explorerClient;
private DerivationSchemeParser _derivationSchemeParser;
private readonly ConcurrentDictionary<string, TrackedSource> _connectionScheme = new();
public BTCPayAppState(
IHubContext<BTCPayAppHub, IBTCPayAppServerClient> hubContext,
ILogger<BTCPayAppState> logger,
ExplorerClientProvider explorerClientProvider,
BTCPayNetworkProvider networkProvider,
EventAggregator eventAggregator)
{
await Clients.All.ClientMethod1(user, message);
return $"[Success] Call SendMessage : {user}, {message}";
_hubContext = hubContext;
_logger = logger;
_explorerClientProvider = explorerClientProvider;
_networkProvider = networkProvider;
_eventAggregator = eventAggregator;
}
public async Task SomeHubMethod()
public Task StartAsync(CancellationToken cancellationToken)
{
await Clients.Caller.ClientMethod2();
_explorerClient = _explorerClientProvider.GetExplorerClient("BTC");
_derivationSchemeParser = new DerivationSchemeParser(_networkProvider.BTC);
_compositeDisposable = new();
_compositeDisposable.Add(
_eventAggregator.Subscribe<NewBlockEvent>(OnNewBlock));
_compositeDisposable.Add(
_eventAggregator.Subscribe<NewTransactionEvent>(OnNewTransaction));
return Task.CompletedTask;
}
private void OnNewTransaction(NewTransactionEvent obj)
{
if (obj.CryptoCode != "BTC")
return;
_connectionScheme.Where(pair => pair.Value == obj.TrackedSource)
.Select(pair => pair.Key)
.ToList()
.ForEach(connectionId =>
{
_hubContext.Clients.Client(connectionId)
.OnTransactionDetected(obj.TransactionData.TransactionHash.ToString());
});
}
private void OnNewBlock(NewBlockEvent obj)
{
if (obj.CryptoCode != "BTC")
return;
_hubContext.Clients.All.NewBlock(obj.Hash.ToString());
}
public Task StopAsync(CancellationToken cancellationToken)
{
_compositeDisposable?.Dispose();
return Task.CompletedTask;
}
public async Task Handshake(string contextConnectionId, AppHandshake handshake)
{
try
{
var ts =
TrackedSource.Create(_derivationSchemeParser.Parse(handshake.DerivationScheme));
await _explorerClient.TrackAsync(ts);
_connectionScheme.AddOrReplace(contextConnectionId, ts);
}
catch (Exception e)
{
_logger.LogError(e, "Error during handshake");
throw;
}
}
public void RemoveConnection(string contextConnectionId)
{
_connectionScheme.TryRemove(contextConnectionId, out _);
}
}
[Authorize(AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
public class BTCPayAppHub : Hub<IBTCPayAppServerClient>, IBTCPayAppServerHub
{
private readonly BTCPayAppState _appState;
public BTCPayAppHub(BTCPayAppState appState)
{
_appState = appState;
}
public override async Task OnConnectedAsync()
{
}
public override Task OnDisconnectedAsync(Exception exception)
{
_appState.RemoveConnection(Context.ConnectionId);
return base.OnDisconnectedAsync(exception);
}
public Task Handshake(AppHandshake handshake)
{
return _appState.Handshake(Context.ConnectionId, handshake);
}
}

View file

@ -1,11 +1,11 @@
namespace BTCPayServer.Events
{
public class NewBlockEvent
public class NewBlockEvent:NBXplorer.Models.NewBlockEvent
{
public string CryptoCode { get; set; }
public override string ToString()
{
return $"{CryptoCode}: New block";
}
}
}