Ecng.Net.SocketIO 1.0.492

dotnet add package Ecng.Net.SocketIO --version 1.0.492
                    
NuGet\Install-Package Ecng.Net.SocketIO -Version 1.0.492
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Ecng.Net.SocketIO" Version="1.0.492" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Ecng.Net.SocketIO" Version="1.0.492" />
                    
Directory.Packages.props
<PackageReference Include="Ecng.Net.SocketIO" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Ecng.Net.SocketIO --version 1.0.492
                    
#r "nuget: Ecng.Net.SocketIO, 1.0.492"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Ecng.Net.SocketIO@1.0.492
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Ecng.Net.SocketIO&version=1.0.492
                    
Install as a Cake Addin
#tool nuget:?package=Ecng.Net.SocketIO&version=1.0.492
                    
Install as a Cake Tool

Ecng.Net.SocketIO

A high-performance .NET client library for WebSocket communication with automatic reconnection, message resending, and comprehensive connection state management.

Features

  • WebSocket Client Implementation - Full-featured WebSocket client with async/await support
  • Automatic Reconnection - Configurable reconnection attempts with exponential backoff
  • Command Resending - Automatic resend of commands after reconnection
  • Connection State Tracking - Track and aggregate connection states across multiple connections
  • JSON Serialization - Built-in JSON serialization for object messages
  • Flexible Logging - Customizable logging hooks for info, error, and verbose messages
  • RestSharp Integration - Helper methods for REST API calls with authentication
  • Thread-Safe - Safe to use in multi-threaded environments

Installation

Add the package reference to your project:

<PackageReference Include="Ecng.Net.SocketIO" Version="x.x.x" />

Quick Start

Basic WebSocket Connection

using Ecng.Net;

var socket = new WebSocketClient(
    url: "wss://example.com/socket",
    stateChanged: state => Console.WriteLine($"State: {state}"),
    error: ex => Console.WriteLine($"Error: {ex.Message}"),
    process: (msg, ct) =>
    {
        Console.WriteLine($"Received: {msg.AsString()}");
        return ValueTask.CompletedTask;
    },
    infoLog: (fmt, args) => Console.WriteLine(fmt, args),
    errorLog: (fmt, args) => Console.Error.WriteLine(fmt, args),
    verboseLog: (fmt, args) => Console.WriteLine($"[VERBOSE] {fmt}", args)
);

await socket.ConnectAsync(CancellationToken.None);

Sending Messages

// Send JSON object
await socket.SendAsync(new { type = "subscribe", channel = "trades" });

// Send string
await socket.SendAsync("Hello, WebSocket!");

// Send raw bytes
byte[] data = Encoding.UTF8.GetBytes("Raw message");
await socket.SendAsync(data, WebSocketMessageType.Text);

Core Components

WebSocketClient

The main class for WebSocket communication.

Constructor Parameters
public WebSocketClient(
    string url,                              // WebSocket URL (ws:// or wss://)
    Action<ConnectionStates> stateChanged,   // Connection state change callback
    Action<Exception> error,                 // Error handler
    Func<WebSocketMessage, CancellationToken, ValueTask> process,  // Message processor
    Action<string, object> infoLog,          // Info log handler
    Action<string, object> errorLog,         // Error log handler
    Action<string, object> verboseLog        // Verbose log handler (can be null)
)
Configuration Properties
// Reconnection settings
socket.ReconnectAttempts = 10;              // -1 for infinite, 0 for no reconnect
socket.ReconnectInterval = TimeSpan.FromSeconds(5);
socket.ResendInterval = TimeSpan.FromSeconds(2);
socket.ResendTimeout = TimeSpan.FromMilliseconds(500);

// Message encoding
socket.Encoding = Encoding.UTF8;

// Buffer sizes
socket.BufferSize = 1024 * 1024;            // 1MB for compressed data
socket.BufferSizeUncompress = 10 * 1024 * 1024; // 10MB for uncompressed

// JSON serialization
socket.Indent = true;
socket.SendSettings = new JsonSerializerSettings { ... };

// Auto-resend control
socket.DisableAutoResend = false;
Connection Management
// Connect
await socket.ConnectAsync(cancellationToken);
socket.Connect(); // Synchronous version

// Disconnect
socket.Disconnect();

// Check connection state
bool isConnected = socket.IsConnected;
ConnectionStates currentState = socket.State;

// Abort connection immediately
socket.Abort();
Sending Messages with Subscription Tracking
// Send with subscription ID for automatic resend after reconnect
long subscriptionId = 12345;
await socket.SendAsync(
    obj: new { action = "subscribe", symbol = "BTCUSD" },
    subId: subscriptionId
);

// Unsubscribe (negative ID removes from resend queue)
await socket.SendAsync(
    obj: new { action = "unsubscribe", symbol = "BTCUSD" },
    subId: -subscriptionId
);

// Manual resend management
socket.RemoveResend(subscriptionId);  // Remove specific subscription
socket.RemoveResend();                 // Remove all subscriptions
Advanced Features
// Custom initialization
socket.Init += ws =>
{
    ws.Options.SetRequestHeader("X-Custom-Header", "value");
    ws.Options.KeepAliveInterval = TimeSpan.FromSeconds(30);
};

// Post-connect hook
socket.PostConnect += async (isReconnect, ct) =>
{
    if (isReconnect)
        Console.WriteLine("Reconnected! Resubscribing...");

    await Task.CompletedTask;
};

// Pre-process received data (e.g., decompression)
socket.PreProcess2 = (input, output) =>
{
    // Decompress or transform data
    input.CopyTo(output);
    return input.Length;
};

// Send ping frame
await socket.SendOpCode(0x9);

WebSocketMessage

Represents an incoming message from the WebSocket.

// In your message processor
Func<WebSocketMessage, CancellationToken, ValueTask> process = (msg, ct) =>
{
    // Get as string
    string text = msg.AsString();

    // Deserialize to object
    var trade = msg.AsObject<TradeData>();

    // Deserialize to dynamic
    dynamic data = msg.AsObject();

    // Get JSON reader for streaming
    using var reader = msg.AsReader();

    // Access raw bytes
    ReadOnlyMemory<byte> bytes = msg.Memory;

    return ValueTask.CompletedTask;
};

Connection States

The ConnectionStates enum represents the current state of the connection:

public enum ConnectionStates
{
    Disconnected,   // Not connected
    Disconnecting,  // In process of disconnecting
    Connecting,     // In process of connecting
    Connected,      // Successfully connected
    Reconnecting,   // Attempting to reconnect
    Restored,       // Connection restored after reconnect
    Failed          // Connection failed
}

ConnectionStateTracker

Track and aggregate states across multiple connections.

var tracker = new ConnectionStateTracker();

// Add connections
tracker.Add(socket1);
tracker.Add(socket2);

// Monitor overall state
tracker.StateChanged += state =>
    Console.WriteLine($"Overall state: {state}");

// Connect all
await tracker.ConnectAsync(CancellationToken.None);

// Disconnect all
tracker.Disconnect();

// Remove connections
tracker.Remove(socket1);

The tracker aggregates states with the following logic:

  • Connected: All connections are connected
  • Reconnecting: Any connection is reconnecting
  • Restored: All connections are connected or restored
  • Failed: All connections have failed
  • Disconnected: All connections are disconnected or failed

IConnection Interface

Standard interface for connection management:

public interface IConnection
{
    event Action<ConnectionStates> StateChanged;
    ValueTask ConnectAsync(CancellationToken cancellationToken);
    void Disconnect();
}

Both WebSocketClient and ConnectionStateTracker implement this interface.

RestSharp Integration

The library includes helper methods for REST API calls, often used alongside WebSocket connections.

Basic REST Request

using Ecng.Net;
using RestSharp;

var request = new RestRequest(Method.Get);
request.AddQueryParameter("symbol", "BTCUSD");

var response = await request.InvokeAsync<PriceData>(
    url: new Uri("https://api.example.com/price"),
    caller: this,
    logVerbose: (fmt, args) => Console.WriteLine(fmt, args),
    token: CancellationToken.None
);

Console.WriteLine($"Price: {response.Price}");

Authentication

// Bearer token authentication
request.SetBearer(secureToken);

// Custom authenticator
var authenticator = new MyCustomAuthenticator();
var response = await request.InvokeAsync2<Data>(
    url: apiUrl,
    caller: this,
    logVerbose: logger,
    token: cancellationToken,
    auth: authenticator
);

Error Handling

try
{
    var response = await request.InvokeAsync<Data>(url, this, logger, token);
}
catch (RestSharpException ex)
{
    Console.WriteLine($"HTTP {ex.Response.StatusCode}: {ex.Response.Content}");
    Console.WriteLine($"Error: {ex.Message}");
}

Advanced REST Features

// Custom content converter
var response = await request.InvokeAsync<Data>(
    url: apiUrl,
    caller: this,
    logVerbose: logger,
    token: cancellationToken,
    contentConverter: content => content.Replace("null", "\"\"")
);

// Handle specific error status codes
var response = await request.InvokeAsync3<Data>(
    url: apiUrl,
    caller: this,
    logVerbose: logger,
    token: cancellationToken,
    handleErrorStatus: statusCode =>
    {
        if (statusCode == HttpStatusCode.TooManyRequests)
        {
            // Custom handling
            return true; // Handled
        }
        return false; // Not handled, will throw
    }
);

// Add body as string
request.AddBodyAsStr("{\"key\": \"value\"}");

// Remove parameters
request.RemoveWhere(p => p.Name == "old_param");

// Convert parameters to query string
string queryString = request.Parameters.ToQueryString();

JWT Decoding

string token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...";
var parts = token.DecodeJWT();

foreach (var part in parts)
{
    Console.WriteLine(part);
}

Complete Examples

Crypto Exchange WebSocket Client

public class CryptoExchangeClient : IDisposable
{
    private readonly WebSocketClient _socket;
    private long _subscriptionCounter;

    public CryptoExchangeClient(string wsUrl)
    {
        _socket = new WebSocketClient(
            url: wsUrl,
            stateChanged: OnStateChanged,
            error: OnError,
            process: ProcessMessage,
            infoLog: (fmt, args) => Console.WriteLine($"[INFO] {fmt}", args),
            errorLog: (fmt, args) => Console.Error.WriteLine($"[ERROR] {fmt}", args),
            verboseLog: null
        )
        {
            ReconnectAttempts = -1,  // Infinite reconnection
            ReconnectInterval = TimeSpan.FromSeconds(5),
            ResendTimeout = TimeSpan.FromSeconds(1)
        };

        _socket.Init += ws =>
        {
            ws.Options.KeepAliveInterval = TimeSpan.FromSeconds(20);
        };

        _socket.PostConnect += async (isReconnect, ct) =>
        {
            if (isReconnect)
            {
                Console.WriteLine("Reconnected! Subscriptions will be restored automatically.");
            }
        };
    }

    public async Task ConnectAsync()
    {
        await _socket.ConnectAsync(CancellationToken.None);
    }

    public async Task SubscribeToTradesAsync(string symbol)
    {
        var subId = ++_subscriptionCounter;

        await _socket.SendAsync(
            obj: new
            {
                type = "subscribe",
                channel = "trades",
                symbol = symbol
            },
            subId: subId
        );

        Console.WriteLine($"Subscribed to {symbol} trades (ID: {subId})");
    }

    public async Task UnsubscribeFromTradesAsync(long subscriptionId, string symbol)
    {
        await _socket.SendAsync(
            obj: new
            {
                type = "unsubscribe",
                channel = "trades",
                symbol = symbol
            },
            subId: -subscriptionId  // Negative to remove from resend queue
        );
    }

    private void OnStateChanged(ConnectionStates state)
    {
        Console.WriteLine($"Connection state: {state}");

        if (state == ConnectionStates.Connected)
        {
            // Connection established
        }
        else if (state == ConnectionStates.Restored)
        {
            // Connection restored after disconnect
        }
        else if (state == ConnectionStates.Failed)
        {
            // Connection failed after all retry attempts
        }
    }

    private void OnError(Exception ex)
    {
        Console.Error.WriteLine($"WebSocket error: {ex}");
    }

    private async ValueTask ProcessMessage(WebSocketMessage msg, CancellationToken ct)
    {
        try
        {
            var message = msg.AsObject<dynamic>();

            if (message.type == "trade")
            {
                Console.WriteLine($"Trade: {message.symbol} @ {message.price}");
            }
            else if (message.type == "error")
            {
                Console.Error.WriteLine($"Server error: {message.message}");
            }
        }
        catch (Exception ex)
        {
            Console.Error.WriteLine($"Error processing message: {ex.Message}");
        }

        await ValueTask.CompletedTask;
    }

    public void Dispose()
    {
        _socket?.Disconnect();
        _socket?.Dispose();
    }
}

// Usage
await using var client = new CryptoExchangeClient("wss://api.exchange.com/ws");
await client.ConnectAsync();
await client.SubscribeToTradesAsync("BTCUSD");

// Keep running
await Task.Delay(Timeout.Infinite);

Multi-Connection Manager

public class MultiExchangeClient
{
    private readonly ConnectionStateTracker _tracker;
    private readonly WebSocketClient _exchangeA;
    private readonly WebSocketClient _exchangeB;

    public MultiExchangeClient()
    {
        _tracker = new ConnectionStateTracker();

        _exchangeA = CreateClient("wss://exchange-a.com/ws", "Exchange A");
        _exchangeB = CreateClient("wss://exchange-b.com/ws", "Exchange B");

        _tracker.Add(_exchangeA);
        _tracker.Add(_exchangeB);

        _tracker.StateChanged += state =>
        {
            Console.WriteLine($"Overall connection state: {state}");

            if (state == ConnectionStates.Connected)
            {
                Console.WriteLine("All exchanges connected!");
            }
        };
    }

    private WebSocketClient CreateClient(string url, string name)
    {
        return new WebSocketClient(
            url: url,
            stateChanged: state => Console.WriteLine($"{name}: {state}"),
            error: ex => Console.Error.WriteLine($"{name} error: {ex.Message}"),
            process: (msg, ct) =>
            {
                Console.WriteLine($"{name}: {msg.AsString()}");
                return ValueTask.CompletedTask;
            },
            infoLog: (fmt, args) => Console.WriteLine($"[{name}] {fmt}", args),
            errorLog: (fmt, args) => Console.Error.WriteLine($"[{name}] {fmt}", args),
            verboseLog: null
        )
        {
            ReconnectAttempts = 5,
            ReconnectInterval = TimeSpan.FromSeconds(3)
        };
    }

    public async Task ConnectAllAsync()
    {
        await _tracker.ConnectAsync(CancellationToken.None);
    }

    public void DisconnectAll()
    {
        _tracker.Disconnect();
    }
}

WebSocket with REST API Integration

public class TradingClient
{
    private readonly WebSocketClient _wsClient;
    private readonly Uri _restApiUrl;

    public TradingClient(string wsUrl, string restUrl)
    {
        _restApiUrl = new Uri(restUrl);
        _wsClient = new WebSocketClient(
            url: wsUrl,
            stateChanged: state => Console.WriteLine($"WS State: {state}"),
            error: ex => Console.Error.WriteLine($"WS Error: {ex}"),
            process: ProcessWebSocketMessage,
            infoLog: (fmt, args) => Console.WriteLine(fmt, args),
            errorLog: (fmt, args) => Console.Error.WriteLine(fmt, args),
            verboseLog: null
        );
    }

    public async Task<AccountInfo> GetAccountInfoAsync()
    {
        var request = new RestRequest("/account", Method.Get);
        request.SetBearer(GetAuthToken());

        try
        {
            var account = await request.InvokeAsync<AccountInfo>(
                url: new Uri(_restApiUrl, request.Resource),
                caller: this,
                logVerbose: (fmt, args) => Console.WriteLine(fmt, args),
                token: CancellationToken.None
            );

            return account;
        }
        catch (RestSharpException ex)
        {
            Console.Error.WriteLine($"REST API Error: {ex.Message}");
            Console.Error.WriteLine($"Status: {ex.Response.StatusCode}");
            Console.Error.WriteLine($"Content: {ex.Response.Content}");
            throw;
        }
    }

    public async Task PlaceOrderAsync(string symbol, decimal price, decimal quantity)
    {
        var request = new RestRequest("/orders", Method.Post);
        request.SetBearer(GetAuthToken());
        request.AddBodyAsStr(new
        {
            symbol = symbol,
            price = price,
            quantity = quantity
        }.ToJson());

        var order = await request.InvokeAsync<Order>(
            url: new Uri(_restApiUrl, request.Resource),
            caller: this,
            logVerbose: (fmt, args) => Console.WriteLine(fmt, args),
            token: CancellationToken.None
        );

        Console.WriteLine($"Order placed: {order.Id}");
    }

    private async ValueTask ProcessWebSocketMessage(WebSocketMessage msg, CancellationToken ct)
    {
        var data = msg.AsObject<dynamic>();

        if (data.type == "order_update")
        {
            Console.WriteLine($"Order {data.orderId} status: {data.status}");
        }

        await ValueTask.CompletedTask;
    }

    private SecureString GetAuthToken()
    {
        // Return your authentication token
        throw new NotImplementedException();
    }
}

Best Practices

  1. Always handle errors: Provide error handlers to catch and log exceptions.

  2. Configure reconnection: Set appropriate reconnection attempts and intervals based on your use case.

  3. Use subscription IDs: Track subscriptions with IDs for automatic resend after reconnection.

  4. Monitor connection states: React to state changes to update your UI or trigger business logic.

  5. Dispose properly: Always dispose of WebSocketClient when done to clean up resources.

  6. Use async/await: Prefer async methods for better scalability.

  7. Implement backoff: Use increasing reconnection intervals to avoid overwhelming the server.

  8. Log appropriately: Use different log levels (info, error, verbose) for debugging and monitoring.

Thread Safety

The WebSocketClient class is designed to be thread-safe for the following operations:

  • Sending messages
  • Connection/disconnection
  • State management
  • Subscription tracking

However, you should not share a single WebSocketMessage instance across threads, as it contains read-only memory references.

Performance Considerations

  • Buffer Sizes: Adjust BufferSize and BufferSizeUncompress based on your message sizes.
  • Resend Interval: Lower intervals increase network traffic; higher intervals delay recovery.
  • Reconnect Attempts: Balance between reliability and resource usage.
  • Verbose Logging: Disable in production for better performance.

License

This library is part of the Ecng framework.

Support

For issues, questions, or contributions, please refer to the main StockSharp repository.

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (6)

Showing the top 5 NuGet packages that depend on Ecng.Net.SocketIO:

Package Downloads
StockSharp.AlphaVantage

AlphaVantage

StockSharp.IEX

Trading and algorithmic trading platform (stock markets, forex, bitcoins and options). .NET API for InteractiveBrokers, GainCapital, OANDA, FIX/FAST, Binance etc. More info on web site https://stocksharp.com/store/api/

StockSharp.Binance

Binance

StockSharp.Okex

OKX connector

StockSharp.Bitmex

Bitmex

GitHub repositories (1)

Showing the top 1 popular GitHub repositories that depend on Ecng.Net.SocketIO:

Repository Stars
StockSharp/StockSharp
Algorithmic trading and quantitative trading open source platform to develop trading robots (stock markets, forex, crypto, bitcoins, and options).
Version Downloads Last Updated
1.0.492 0 12/25/2025
1.0.491 60 12/24/2025
1.0.490 75 12/23/2025
1.0.489 78 12/22/2025
1.0.488 75 12/22/2025
1.0.487 84 12/22/2025
1.0.486 85 12/21/2025
1.0.485 208 12/19/2025
1.0.484 227 12/19/2025
1.0.483 271 12/18/2025
1.0.482 273 12/17/2025
1.0.481 271 12/15/2025
1.0.480 245 12/15/2025
1.0.479 217 12/14/2025
1.0.478 150 12/14/2025
1.0.477 153 12/13/2025
1.0.476 162 12/13/2025
1.0.475 129 12/12/2025
1.0.474 112 12/12/2025
1.0.473 107 12/12/2025
1.0.472 110 12/12/2025
1.0.471 105 12/12/2025
1.0.470 111 12/12/2025
1.0.469 111 12/12/2025
1.0.468 713 12/2/2025
1.0.467 667 12/2/2025
1.0.466 666 12/2/2025
1.0.465 266 11/30/2025
1.0.464 133 11/29/2025
1.0.463 130 11/28/2025
1.0.462 138 11/28/2025
1.0.461 181 11/27/2025
1.0.460 221 11/24/2025
1.0.459 191 11/24/2025
1.0.458 187 11/23/2025
1.0.457 164 11/23/2025
1.0.456 217 11/22/2025
1.0.455 429 11/20/2025
1.0.454 402 11/20/2025
1.0.453 403 11/20/2025
1.0.452 423 11/18/2025
1.0.451 403 11/18/2025
1.0.450 332 11/13/2025
1.0.449 270 11/10/2025
1.0.448 1,089 11/1/2025
1.0.447 199 10/31/2025
1.0.446 209 10/28/2025
1.0.445 302 10/27/2025
1.0.444 196 10/27/2025
1.0.443 126 10/25/2025
1.0.442 152 10/24/2025
1.0.441 263 10/20/2025
1.0.440 299 10/12/2025
1.0.439 146 10/11/2025
1.0.438 287 10/7/2025
1.0.437 224 10/6/2025
1.0.436 267 10/3/2025
1.0.435 241 10/1/2025
1.0.434 206 10/1/2025
1.0.433 205 9/30/2025
1.0.432 210 9/28/2025
1.0.431 225 9/25/2025
1.0.430 2,981 9/5/2025
1.0.429 239 9/2/2025
1.0.428 595 8/30/2025
1.0.427 258 8/30/2025
1.0.426 263 8/20/2025
1.0.425 207 8/20/2025
1.0.424 218 8/19/2025
1.0.423 227 8/15/2025
1.0.422 319 8/10/2025
1.0.421 1,043 7/16/2025
1.0.420 275 7/14/2025
1.0.419 247 7/13/2025
1.0.418 220 7/13/2025
1.0.417 200 7/12/2025
1.0.416 684 7/8/2025
1.0.415 257 7/4/2025
1.0.414 252 7/2/2025
1.0.413 417 6/24/2025
1.0.412 1,027 6/16/2025
1.0.411 408 6/9/2025
1.0.410 284 6/8/2025
1.0.409 611 5/21/2025
1.0.408 258 5/21/2025
1.0.407 245 5/17/2025
1.0.406 647 5/12/2025
1.0.405 341 5/12/2025
1.0.404 311 5/12/2025
1.0.403 234 5/11/2025
1.0.402 241 5/11/2025
1.0.401 198 5/10/2025
1.0.400 162 5/10/2025
1.0.399 282 5/6/2025
1.0.398 209 5/3/2025
1.0.397 379 4/17/2025
1.0.396 330 4/15/2025
1.0.395 229 4/12/2025
1.0.394 301 4/9/2025
1.0.393 260 4/6/2025
1.0.392 213 4/5/2025
1.0.391 1,087 3/22/2025
1.0.390 282 3/20/2025
1.0.389 275 3/20/2025
1.0.388 260 3/19/2025
1.0.387 831 2/26/2025
1.0.386 239 2/26/2025
1.0.385 760 2/8/2025
1.0.384 246 2/8/2025
1.0.383 219 2/8/2025
1.0.382 220 2/6/2025
1.0.381 210 2/6/2025
1.0.380 229 2/6/2025
1.0.379 232 2/6/2025
1.0.378 210 2/6/2025
1.0.377 211 2/5/2025
1.0.376 216 2/5/2025
1.0.375 232 2/5/2025
1.0.374 256 2/3/2025
1.0.373 239 2/2/2025
1.0.372 257 2/1/2025
1.0.371 239 1/31/2025
1.0.370 242 1/30/2025
1.0.369 223 1/26/2025
1.0.368 261 1/21/2025
1.0.367 245 1/20/2025
1.0.366 211 1/20/2025
1.0.365 224 1/19/2025
1.0.364 212 1/19/2025
1.0.363 239 1/15/2025
1.0.362 210 1/15/2025
1.0.361 202 1/14/2025
1.0.360 195 1/12/2025
1.0.359 186 1/12/2025
1.0.358 201 1/12/2025
1.0.357 173 1/12/2025
1.0.356 219 1/10/2025
1.0.355 1,057 12/30/2024
1.0.354 247 12/27/2024
1.0.353 271 12/19/2024
1.0.352 730 11/20/2024
1.0.351 244 11/19/2024
1.0.350 230 11/19/2024
1.0.349 789 11/18/2024
1.0.348 461 11/15/2024
1.0.347 215 11/14/2024
1.0.346 237 11/14/2024
1.0.345 243 11/14/2024
1.0.344 194 11/14/2024
1.0.343 217 11/14/2024
1.0.342 261 11/7/2024
1.0.341 272 10/31/2024
1.0.340 329 10/20/2024
1.0.339 254 10/20/2024
1.0.338 265 10/20/2024
1.0.337 258 10/19/2024
1.0.336 269 10/19/2024
1.0.335 270 10/19/2024
1.0.334 267 10/19/2024
1.0.333 266 10/19/2024
1.0.332 248 10/19/2024
1.0.331 272 10/19/2024
1.0.330 304 10/18/2024
1.0.329 263 10/17/2024
1.0.328 221 10/17/2024
1.0.327 240 10/17/2024
1.0.326 796 10/14/2024
1.0.325 227 10/13/2024
1.0.324 223 10/13/2024
1.0.323 243 10/12/2024
1.0.322 437 10/9/2024
1.0.321 243 10/9/2024
1.0.320 440 10/5/2024
1.0.319 767 9/18/2024
1.0.318 227 9/18/2024
1.0.317 247 9/18/2024
1.0.316 241 9/17/2024
1.0.315 738 9/3/2024
1.0.314 283 9/1/2024
1.0.313 952 8/9/2024
1.0.312 243 8/9/2024
1.0.311 264 8/8/2024
1.0.310 697 7/25/2024
1.0.309 256 7/23/2024
1.0.308 284 7/17/2024
1.0.307 549 7/4/2024
1.0.306 610 6/12/2024
1.0.305 250 6/12/2024
1.0.304 246 6/12/2024
1.0.303 441 5/28/2024
1.0.302 605 5/4/2024
1.0.301 400 4/23/2024
1.0.300 263 4/21/2024
1.0.299 290 4/14/2024
1.0.298 556 3/28/2024
1.0.297 325 3/17/2024
1.0.296 532 3/9/2024
1.0.295 348 2/23/2024
1.0.294 279 2/23/2024
1.0.293 488 2/18/2024
1.0.292 278 2/18/2024
1.0.291 252 2/17/2024
1.0.290 269 2/16/2024
1.0.289 389 2/14/2024
1.0.288 270 2/13/2024
1.0.287 339 2/8/2024
1.0.286 344 2/5/2024
1.0.285 262 2/4/2024
1.0.284 431 1/23/2024
1.0.283 250 1/23/2024
1.0.282 317 1/12/2024
1.0.281 686 1/2/2024
1.0.280 302 12/29/2023
1.0.279 353 12/17/2023
1.0.278 510 12/15/2023
1.0.277 280 12/15/2023
1.0.276 260 12/15/2023
1.0.275 290 12/13/2023
1.0.274 289 12/13/2023
1.0.273 293 12/10/2023
1.0.272 683 11/18/2023
1.0.271 225 11/18/2023
1.0.270 252 11/18/2023
1.0.269 235 11/17/2023
1.0.268 211 11/12/2023
1.0.267 207 11/12/2023
1.0.266 229 11/10/2023
1.0.265 195 11/10/2023
1.0.264 235 11/9/2023
1.0.263 196 11/9/2023
1.0.262 214 11/9/2023
1.0.261 238 11/3/2023
1.0.260 227 11/1/2023
1.0.259 210 11/1/2023
1.0.258 1,472 9/8/2023
1.0.257 263 9/8/2023
1.0.256 283 9/3/2023
1.0.255 347 8/27/2023
1.0.254 276 8/24/2023
1.0.253 241 8/21/2023
1.0.252 315 8/15/2023
1.0.251 286 8/14/2023
1.0.250 266 8/14/2023
1.0.249 295 8/10/2023
1.0.248 1,015 7/29/2023
1.0.247 1,088 7/1/2023
1.0.246 308 6/29/2023
1.0.245 798 5/27/2023
1.0.244 350 5/21/2023
1.0.243 294 5/19/2023
1.0.242 1,080 5/8/2023
1.0.241 353 5/7/2023
1.0.240 339 5/7/2023
1.0.239 317 5/7/2023
1.0.238 365 5/1/2023
1.0.237 410 4/22/2023
1.0.236 371 4/21/2023
1.0.235 335 4/21/2023
1.0.234 1,231 4/13/2023
1.0.233 1,134 4/3/2023
1.0.232 487 3/27/2023
1.0.231 431 3/21/2023
1.0.230 433 3/17/2023
1.0.229 426 3/13/2023
1.0.228 1,184 3/6/2023
1.0.227 496 2/26/2023
1.0.226 939 2/21/2023
1.0.225 454 2/20/2023
1.0.224 467 2/16/2023
1.0.223 455 2/15/2023
1.0.222 430 2/14/2023
1.0.221 425 2/14/2023
1.0.220 1,353 2/9/2023
1.0.219 830 2/7/2023
1.0.218 484 2/4/2023
1.0.217 466 2/4/2023
1.0.216 480 2/3/2023
1.0.215 445 2/3/2023
1.0.214 439 2/3/2023
1.0.213 884 2/2/2023
1.0.212 832 1/30/2023
1.0.211 465 1/30/2023
1.0.210 508 1/25/2023
1.0.209 504 1/23/2023
1.0.208 451 1/23/2023
1.0.207 489 1/18/2023
1.0.206 513 1/15/2023
1.0.205 512 1/6/2023
1.0.204 1,416 1/1/2023
1.0.203 479 12/31/2022
1.0.202 969 12/30/2022
1.0.201 498 12/29/2022
1.0.200 508 12/23/2022
1.0.199 1,388 12/12/2022
1.0.198 1,070 12/8/2022
1.0.197 485 12/4/2022
1.0.196 487 12/4/2022
1.0.195 491 12/2/2022
1.0.194 515 11/30/2022
1.0.193 479 11/29/2022
1.0.192 474 11/28/2022
1.0.191 515 11/26/2022
1.0.190 513 11/26/2022
1.0.189 515 11/25/2022
1.0.188 511 11/25/2022
1.0.187 525 11/18/2022
1.0.186 1,594 11/11/2022
1.0.185 547 11/11/2022
1.0.184 505 11/10/2022
1.0.183 571 11/5/2022
1.0.182 545 11/4/2022
1.0.181 530 11/2/2022
1.0.180 521 11/2/2022
1.0.179 1,431 11/1/2022
1.0.178 1,655 10/16/2022
1.0.177 737 9/25/2022
1.0.176 666 9/10/2022
1.0.175 2,978 9/8/2022
1.0.174 651 9/8/2022
1.0.173 657 9/8/2022
1.0.172 631 9/4/2022
1.0.171 634 9/4/2022
1.0.170 5,352 8/24/2022
1.0.169 713 8/8/2022
1.0.168 635 8/8/2022
1.0.167 1,265 7/31/2022
1.0.166 653 7/31/2022
1.0.165 664 7/26/2022
1.0.164 631 7/26/2022
1.0.163 3,198 7/21/2022
1.0.162 684 7/19/2022
1.0.161 3,155 7/18/2022
1.0.160 689 7/13/2022
1.0.159 672 7/8/2022
1.0.158 690 6/30/2022
1.0.157 706 6/20/2022
1.0.156 655 6/18/2022
1.0.155 697 6/6/2022
1.0.154 744 5/27/2022
1.0.153 5,209 4/30/2022
1.0.152 683 4/20/2022
1.0.151 711 4/10/2022
1.0.150 676 4/7/2022
1.0.149 662 4/7/2022
1.0.148 717 4/2/2022
1.0.147 675 3/29/2022
1.0.146 663 3/27/2022
1.0.145 666 3/27/2022
1.0.144 3,917 3/24/2022
1.0.143 2,684 2/20/2022
1.0.142 644 2/20/2022
1.0.141 655 2/20/2022
1.0.140 685 2/20/2022
1.0.139 699 2/20/2022
1.0.138 664 2/20/2022
1.0.137 658 2/20/2022
1.0.136 674 2/20/2022
1.0.135 680 2/20/2022
1.0.134 667 2/19/2022
1.0.133 4,565 2/10/2022
1.0.132 779 1/27/2022
1.0.131 706 1/27/2022
1.0.130 3,567 1/24/2022
1.0.129 650 1/24/2022
1.0.128 691 1/23/2022
1.0.127 7,018 12/29/2021
1.0.126 541 12/27/2021
1.0.125 482 12/27/2021
1.0.124 502 12/27/2021
1.0.123 1,758 12/20/2021
1.0.122 546 12/17/2021
1.0.121 536 12/16/2021
1.0.120 519 12/15/2021
1.0.119 509 12/14/2021
1.0.118 530 12/14/2021
1.0.117 490 12/13/2021
1.0.116 651 12/12/2021
1.0.115 1,630 12/10/2021
1.0.114 541 12/7/2021
1.0.113 539 12/7/2021
1.0.112 1,973 12/6/2021
1.0.111 538 12/6/2021
1.0.110 539 12/5/2021
1.0.109 1,232 12/3/2021
1.0.108 1,040 12/3/2021
1.0.107 574 12/2/2021
1.0.106 2,453 11/29/2021
1.0.105 5,267 11/23/2021
1.0.104 527 11/23/2021
1.0.103 1,614 11/22/2021
1.0.102 620 11/17/2021
1.0.101 577 11/14/2021
1.0.100 1,742 11/13/2021
1.0.99 591 11/11/2021
1.0.98 576 11/11/2021
1.0.97 561 11/10/2021
1.0.96 566 11/9/2021
1.0.95 2,597 11/6/2021
1.0.94 602 11/6/2021
1.0.93 2,168 11/5/2021
1.0.92 628 11/5/2021
1.0.91 588 11/4/2021
1.0.90 561 11/4/2021
1.0.89 613 11/3/2021
1.0.88 681 10/30/2021
1.0.87 2,046 10/21/2021
1.0.86 652 10/17/2021
1.0.85 660 10/17/2021
1.0.84 3,046 10/14/2021
1.0.83 585 10/13/2021
1.0.82 606 10/13/2021
1.0.81 585 10/12/2021
1.0.80 2,138 10/11/2021
1.0.79 568 10/9/2021
1.0.78 1,950 10/7/2021
1.0.77 2,152 10/7/2021
1.0.76 566 10/7/2021
1.0.75 598 10/6/2021
1.0.74 654 9/28/2021
1.0.73 2,365 9/23/2021
1.0.72 703 9/11/2021
1.0.71 602 9/10/2021
1.0.70 668 9/9/2021
1.0.69 570 9/8/2021
1.0.68 629 9/8/2021
1.0.67 2,156 9/6/2021
1.0.66 699 8/31/2021
1.0.65 560 8/30/2021
1.0.64 2,610 7/31/2021
1.0.63 3,040 7/30/2021
1.0.62 682 7/26/2021
1.0.61 4,483 7/5/2021
1.0.60 639 7/1/2021
1.0.59 3,821 6/4/2021
1.0.58 5,070 4/26/2021
1.0.57 2,182 4/19/2021
1.0.56 5,722 4/8/2021
1.0.55 1,805 4/7/2021
1.0.54 617 4/7/2021
1.0.53 1,885 4/3/2021
1.0.52 7,983 3/22/2021
1.0.51 5,772 3/4/2021
1.0.50 2,160 2/26/2021
1.0.49 8,275 2/2/2021
1.0.48 3,229 1/26/2021
1.0.47 2,999 1/24/2021
1.0.46 657 1/24/2021
1.0.45 711 1/23/2021
1.0.44 3,899 1/20/2021
1.0.43 714 1/20/2021
1.0.42 2,084 1/18/2021
1.0.41 629 1/18/2021
1.0.40 2,062 1/16/2021
1.0.39 6,313 12/17/2020
1.0.38 695 12/16/2020
1.0.37 3,213 12/14/2020
1.0.36 2,122 12/9/2020
1.0.35 674 12/9/2020
1.0.34 681 12/7/2020
1.0.33 787 12/6/2020
1.0.32 737 12/2/2020
1.0.31 706 12/2/2020
1.0.30 2,198 12/1/2020
1.0.29 7,363 11/12/2020
1.0.29-atestpub 563 11/11/2020
1.0.28 3,335 10/11/2020
1.0.27 8,616 9/9/2020
1.0.26 2,626 9/3/2020
1.0.25 2,685 8/20/2020
1.0.24 6,158 8/9/2020
1.0.23 2,707 7/28/2020
1.0.22 2,641 7/19/2020
1.0.21 4,452 7/6/2020
1.0.20 6,624 6/6/2020
1.0.19 2,614 6/4/2020
1.0.18 4,383 5/29/2020
1.0.17 4,424 5/21/2020
1.0.16 766 5/17/2020
1.0.15 4,520 5/12/2020
1.0.14 8,239 5/4/2020
1.0.13 787 4/24/2020
1.0.12 767 4/22/2020
1.0.11 753 4/22/2020
1.0.10 773 4/21/2020
1.0.9 3,227 4/18/2020
1.0.8 2,577 4/16/2020
1.0.7 781 4/16/2020
1.0.6 2,254 4/15/2020
1.0.5 2,665 4/11/2020
1.0.4 2,557 4/3/2020
1.0.3 776 4/1/2020
1.0.2 2,486 3/27/2020
1.0.1 2,605 3/22/2020
1.0.0 889 3/22/2020