public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { return(null); } if (reader.TokenType != JsonToken.String) { return(null); } if (TrackedSource.TryParse(reader.Value.ToString(), out var v, Network)) { return(v); } throw new JsonObjectException("Invalid TrackedSource", reader); }
public async Task <IActionResult> ConnectWebSocket( string cryptoCode, bool includeTransaction = true, CancellationToken cancellation = default) { if (!HttpContext.WebSockets.IsWebSocketRequest) { return(NotFound()); } GetNetwork(cryptoCode, false); // Internally check if cryptoCode is correct string listenAllDerivationSchemes = null; string listenAllTrackedSource = null; var listenedBlocks = new ConcurrentDictionary <string, string>(); var listenedDerivations = new ConcurrentDictionary <(Network, DerivationStrategyBase), DerivationStrategyBase>(); var listenedTrackedSource = new ConcurrentDictionary <(Network, TrackedSource), TrackedSource>(); WebsocketMessageListener server = new WebsocketMessageListener(await HttpContext.WebSockets.AcceptWebSocketAsync(), _SerializerSettings); CompositeDisposable subscriptions = new CompositeDisposable(); subscriptions.Add(_EventAggregator.Subscribe <Models.NewBlockEvent>(async o => { if (listenedBlocks.ContainsKey(o.CryptoCode)) { await server.Send(o); } })); subscriptions.Add(_EventAggregator.Subscribe <Models.NewTransactionEvent>(async o => { var network = Waiters.GetWaiter(o.CryptoCode); if (network == null) { return; } bool forward = false; var derivationScheme = (o.TrackedSource as DerivationSchemeTrackedSource)?.DerivationStrategy; if (derivationScheme != null) { forward |= listenAllDerivationSchemes == "*" || listenAllDerivationSchemes == o.CryptoCode || listenedDerivations.ContainsKey((network.Network.NBitcoinNetwork, derivationScheme)); } forward |= listenAllTrackedSource == "*" || listenAllTrackedSource == o.CryptoCode || listenedTrackedSource.ContainsKey((network.Network.NBitcoinNetwork, o.TrackedSource)); if (forward) { var derivation = (o.TrackedSource as DerivationSchemeTrackedSource)?.DerivationStrategy; await server.Send(o); } })); try { while (server.Socket.State == WebSocketState.Open) { object message = await server.NextMessageAsync(cancellation); switch (message) { case Models.NewBlockEventRequest r: r.CryptoCode = r.CryptoCode ?? cryptoCode; listenedBlocks.TryAdd(r.CryptoCode, r.CryptoCode); break; case Models.NewTransactionEventRequest r: var network = Waiters.GetWaiter(r.CryptoCode)?.Network; if (r.DerivationSchemes != null) { r.CryptoCode = r.CryptoCode ?? cryptoCode; if (network != null) { foreach (var derivation in r.DerivationSchemes) { var parsed = new DerivationStrategyFactory(network.NBitcoinNetwork).Parse(derivation); listenedDerivations.TryAdd((network.NBitcoinNetwork, parsed), parsed); } } } else if ( // Back compat: If no derivation scheme precised and ListenAllDerivationSchemes not set, we listen all (r.TrackedSources == null && r.ListenAllDerivationSchemes == null) || (r.ListenAllDerivationSchemes != null && r.ListenAllDerivationSchemes.Value)) { listenAllDerivationSchemes = r.CryptoCode; } if (r.ListenAllTrackedSource != null && r.ListenAllTrackedSource.Value) { listenAllTrackedSource = r.CryptoCode; } else if (r.TrackedSources != null) { r.CryptoCode = r.CryptoCode ?? cryptoCode; if (network != null) { foreach (var trackedSource in r.TrackedSources) { if (TrackedSource.TryParse(trackedSource, out var parsed, network.NBitcoinNetwork)) { listenedTrackedSource.TryAdd((network.NBitcoinNetwork, parsed), parsed); } } } } break; default: break; } } } catch when(server.Socket.State != WebSocketState.Open) { } finally { subscriptions.Dispose(); await server.DisposeAsync(cancellation); } return(new EmptyResult()); }