Ecng.Net.SocketIO 1.0.494

There is a newer version of this package available.
See the version list below for details.
dotnet add package Ecng.Net.SocketIO --version 1.0.494
                    
NuGet\Install-Package Ecng.Net.SocketIO -Version 1.0.494
                    
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.494" />
                    
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.494" />
                    
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.494
                    
#r "nuget: Ecng.Net.SocketIO, 1.0.494"
                    
#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.494
                    
#: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.494
                    
Install as a Cake Addin
#tool nuget:?package=Ecng.Net.SocketIO&version=1.0.494
                    
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.497 39 12/26/2025
1.0.496 33 12/26/2025
1.0.495 30 12/26/2025
1.0.494 51 12/26/2025
1.0.493 120 12/25/2025
1.0.492 125 12/25/2025
1.0.491 151 12/24/2025
1.0.490 163 12/23/2025
1.0.489 164 12/22/2025
1.0.488 161 12/22/2025
1.0.487 169 12/22/2025
1.0.486 154 12/21/2025
1.0.485 211 12/19/2025
1.0.484 230 12/19/2025
1.0.483 274 12/18/2025
1.0.482 275 12/17/2025
1.0.481 273 12/15/2025
1.0.480 247 12/15/2025
1.0.479 221 12/14/2025
1.0.478 153 12/14/2025
1.0.477 155 12/13/2025
1.0.476 166 12/13/2025
1.0.475 132 12/12/2025
1.0.474 116 12/12/2025
1.0.473 111 12/12/2025
1.0.472 113 12/12/2025
1.0.471 109 12/12/2025
1.0.470 115 12/12/2025
1.0.469 115 12/12/2025
1.0.468 717 12/2/2025
1.0.467 671 12/2/2025
1.0.466 669 12/2/2025
1.0.465 269 11/30/2025
1.0.464 138 11/29/2025
1.0.463 134 11/28/2025
1.0.462 140 11/28/2025
1.0.461 185 11/27/2025
1.0.460 225 11/24/2025
1.0.459 195 11/24/2025
1.0.458 190 11/23/2025
1.0.457 167 11/23/2025
1.0.456 220 11/22/2025
1.0.455 432 11/20/2025
1.0.454 406 11/20/2025
1.0.453 405 11/20/2025
1.0.452 427 11/18/2025
1.0.451 406 11/18/2025
1.0.450 336 11/13/2025
1.0.449 272 11/10/2025
1.0.448 1,092 11/1/2025
1.0.447 202 10/31/2025
1.0.446 211 10/28/2025
1.0.445 318 10/27/2025
1.0.444 199 10/27/2025
1.0.443 128 10/25/2025
1.0.442 155 10/24/2025
1.0.441 265 10/20/2025
1.0.440 302 10/12/2025
1.0.439 149 10/11/2025
1.0.438 290 10/7/2025
1.0.437 228 10/6/2025
1.0.436 270 10/3/2025
1.0.435 243 10/1/2025
1.0.434 209 10/1/2025
1.0.433 209 9/30/2025
1.0.432 212 9/28/2025
1.0.431 228 9/25/2025
1.0.430 3,001 9/5/2025
1.0.429 241 9/2/2025
1.0.428 597 8/30/2025
1.0.427 261 8/30/2025
1.0.426 267 8/20/2025
1.0.425 211 8/20/2025
1.0.424 222 8/19/2025
1.0.423 231 8/15/2025
1.0.422 322 8/10/2025
1.0.421 1,047 7/16/2025
1.0.420 278 7/14/2025
1.0.419 249 7/13/2025
1.0.418 224 7/13/2025
1.0.417 203 7/12/2025
1.0.416 687 7/8/2025
1.0.415 260 7/4/2025
1.0.414 257 7/2/2025
1.0.413 422 6/24/2025
1.0.412 1,030 6/16/2025
1.0.411 411 6/9/2025
1.0.410 287 6/8/2025
1.0.409 615 5/21/2025
1.0.408 261 5/21/2025
1.0.407 249 5/17/2025
1.0.406 651 5/12/2025
1.0.405 345 5/12/2025
1.0.404 313 5/12/2025
1.0.403 237 5/11/2025
1.0.402 245 5/11/2025
1.0.401 201 5/10/2025
1.0.400 164 5/10/2025
1.0.399 284 5/6/2025
1.0.398 213 5/3/2025
1.0.397 382 4/17/2025
1.0.396 333 4/15/2025
1.0.395 232 4/12/2025
1.0.394 305 4/9/2025
1.0.393 264 4/6/2025
1.0.392 216 4/5/2025
1.0.391 1,091 3/22/2025
1.0.390 285 3/20/2025
1.0.389 277 3/20/2025
1.0.388 264 3/19/2025
1.0.387 834 2/26/2025
1.0.386 242 2/26/2025
1.0.385 764 2/8/2025
1.0.384 250 2/8/2025
1.0.383 221 2/8/2025
1.0.382 223 2/6/2025
1.0.381 214 2/6/2025
1.0.380 231 2/6/2025
1.0.379 234 2/6/2025
1.0.378 213 2/6/2025
1.0.377 214 2/5/2025
1.0.376 219 2/5/2025
1.0.375 237 2/5/2025
1.0.374 260 2/3/2025
1.0.373 241 2/2/2025
1.0.372 261 2/1/2025
1.0.371 243 1/31/2025
1.0.370 245 1/30/2025
1.0.369 226 1/26/2025
1.0.368 263 1/21/2025
1.0.367 249 1/20/2025
1.0.366 213 1/20/2025
1.0.365 228 1/19/2025
1.0.364 215 1/19/2025
1.0.363 243 1/15/2025
1.0.362 213 1/15/2025
1.0.361 205 1/14/2025
1.0.360 199 1/12/2025
1.0.359 191 1/12/2025
1.0.358 205 1/12/2025
1.0.357 176 1/12/2025
1.0.356 223 1/10/2025
1.0.355 1,060 12/30/2024
1.0.354 251 12/27/2024
1.0.353 275 12/19/2024
1.0.352 733 11/20/2024
1.0.351 249 11/19/2024
1.0.350 232 11/19/2024
1.0.349 792 11/18/2024
1.0.348 464 11/15/2024
1.0.347 219 11/14/2024
1.0.346 240 11/14/2024
1.0.345 246 11/14/2024
1.0.344 198 11/14/2024
1.0.343 221 11/14/2024
1.0.342 263 11/7/2024
1.0.341 274 10/31/2024
1.0.340 332 10/20/2024
1.0.339 257 10/20/2024
1.0.338 268 10/20/2024
1.0.337 261 10/19/2024
1.0.336 272 10/19/2024
1.0.335 274 10/19/2024
1.0.334 271 10/19/2024
1.0.333 269 10/19/2024
1.0.332 251 10/19/2024
1.0.331 277 10/19/2024
1.0.330 306 10/18/2024
1.0.329 265 10/17/2024
1.0.328 225 10/17/2024
1.0.327 243 10/17/2024
1.0.326 800 10/14/2024
1.0.325 229 10/13/2024
1.0.324 227 10/13/2024
1.0.323 247 10/12/2024
1.0.322 440 10/9/2024
1.0.321 246 10/9/2024
1.0.320 442 10/5/2024
1.0.319 771 9/18/2024
1.0.318 230 9/18/2024
1.0.317 250 9/18/2024
1.0.316 244 9/17/2024
1.0.315 741 9/3/2024
1.0.314 287 9/1/2024
1.0.313 958 8/9/2024
1.0.312 246 8/9/2024
1.0.311 267 8/8/2024
1.0.310 701 7/25/2024
1.0.309 260 7/23/2024
1.0.308 288 7/17/2024
1.0.307 552 7/4/2024
1.0.306 613 6/12/2024
1.0.305 254 6/12/2024
1.0.304 250 6/12/2024
1.0.303 444 5/28/2024
1.0.302 607 5/4/2024
1.0.301 402 4/23/2024
1.0.300 266 4/21/2024
1.0.299 293 4/14/2024
1.0.298 560 3/28/2024
1.0.297 329 3/17/2024
1.0.296 534 3/9/2024
1.0.295 351 2/23/2024
1.0.294 281 2/23/2024
1.0.293 491 2/18/2024
1.0.292 281 2/18/2024
1.0.291 255 2/17/2024
1.0.290 273 2/16/2024
1.0.289 393 2/14/2024
1.0.288 273 2/13/2024
1.0.287 344 2/8/2024
1.0.286 347 2/5/2024
1.0.285 265 2/4/2024
1.0.284 434 1/23/2024
1.0.283 254 1/23/2024
1.0.282 321 1/12/2024
1.0.281 690 1/2/2024
1.0.280 306 12/29/2023
1.0.279 356 12/17/2023
1.0.278 513 12/15/2023
1.0.277 283 12/15/2023
1.0.276 263 12/15/2023
1.0.275 294 12/13/2023
1.0.274 292 12/13/2023
1.0.273 296 12/10/2023
1.0.272 683 11/18/2023
1.0.271 227 11/18/2023
1.0.270 253 11/18/2023
1.0.269 236 11/17/2023
1.0.268 213 11/12/2023
1.0.267 209 11/12/2023
1.0.266 232 11/10/2023
1.0.265 196 11/10/2023
1.0.264 237 11/9/2023
1.0.263 197 11/9/2023
1.0.262 215 11/9/2023
1.0.261 240 11/3/2023
1.0.260 228 11/1/2023
1.0.259 210 11/1/2023
1.0.258 1,473 9/8/2023
1.0.257 266 9/8/2023
1.0.256 284 9/3/2023
1.0.255 349 8/27/2023
1.0.254 278 8/24/2023
1.0.253 243 8/21/2023
1.0.252 318 8/15/2023
1.0.251 287 8/14/2023
1.0.250 266 8/14/2023
1.0.249 296 8/10/2023
1.0.248 1,016 7/29/2023
1.0.247 1,089 7/1/2023
1.0.246 309 6/29/2023
1.0.245 799 5/27/2023
1.0.244 351 5/21/2023
1.0.243 296 5/19/2023
1.0.242 1,082 5/8/2023
1.0.241 354 5/7/2023
1.0.240 341 5/7/2023
1.0.239 317 5/7/2023
1.0.238 366 5/1/2023
1.0.237 411 4/22/2023
1.0.236 372 4/21/2023
1.0.235 338 4/21/2023
1.0.234 1,233 4/13/2023
1.0.233 1,135 4/3/2023
1.0.232 488 3/27/2023
1.0.231 433 3/21/2023
1.0.230 436 3/17/2023
1.0.229 427 3/13/2023
1.0.228 1,185 3/6/2023
1.0.227 497 2/26/2023
1.0.226 940 2/21/2023
1.0.225 455 2/20/2023
1.0.224 469 2/16/2023
1.0.223 455 2/15/2023
1.0.222 432 2/14/2023
1.0.221 427 2/14/2023
1.0.220 1,357 2/9/2023
1.0.219 833 2/7/2023
1.0.218 486 2/4/2023
1.0.217 467 2/4/2023
1.0.216 483 2/3/2023
1.0.215 446 2/3/2023
1.0.214 441 2/3/2023
1.0.213 886 2/2/2023
1.0.212 832 1/30/2023
1.0.211 466 1/30/2023
1.0.210 509 1/25/2023
1.0.209 504 1/23/2023
1.0.208 455 1/23/2023
1.0.207 490 1/18/2023
1.0.206 515 1/15/2023
1.0.205 513 1/6/2023
1.0.204 1,417 1/1/2023
1.0.203 482 12/31/2022
1.0.202 970 12/30/2022
1.0.201 500 12/29/2022
1.0.200 510 12/23/2022
1.0.199 1,389 12/12/2022
1.0.198 1,072 12/8/2022
1.0.197 489 12/4/2022
1.0.196 491 12/4/2022
1.0.195 493 12/2/2022
1.0.194 517 11/30/2022
1.0.193 481 11/29/2022
1.0.192 477 11/28/2022
1.0.191 517 11/26/2022
1.0.190 515 11/26/2022
1.0.189 517 11/25/2022
1.0.188 513 11/25/2022
1.0.187 528 11/18/2022
1.0.186 1,596 11/11/2022
1.0.185 551 11/11/2022
1.0.184 507 11/10/2022
1.0.183 574 11/5/2022
1.0.182 550 11/4/2022
1.0.181 532 11/2/2022
1.0.180 523 11/2/2022
1.0.179 1,433 11/1/2022
1.0.178 1,657 10/16/2022
1.0.177 740 9/25/2022
1.0.176 669 9/10/2022
1.0.175 2,980 9/8/2022
1.0.174 654 9/8/2022
1.0.173 660 9/8/2022
1.0.172 635 9/4/2022
1.0.171 635 9/4/2022
1.0.170 5,355 8/24/2022
1.0.169 716 8/8/2022
1.0.168 637 8/8/2022
1.0.167 1,268 7/31/2022
1.0.166 655 7/31/2022
1.0.165 668 7/26/2022
1.0.164 633 7/26/2022
1.0.163 3,201 7/21/2022
1.0.162 688 7/19/2022
1.0.161 3,158 7/18/2022
1.0.160 693 7/13/2022
1.0.159 674 7/8/2022
1.0.158 693 6/30/2022
1.0.157 709 6/20/2022
1.0.156 658 6/18/2022
1.0.155 700 6/6/2022
1.0.154 746 5/27/2022
1.0.153 5,211 4/30/2022
1.0.152 686 4/20/2022
1.0.151 714 4/10/2022
1.0.150 678 4/7/2022
1.0.149 665 4/7/2022
1.0.148 720 4/2/2022
1.0.147 678 3/29/2022
1.0.146 668 3/27/2022
1.0.145 669 3/27/2022
1.0.144 3,919 3/24/2022
1.0.143 2,686 2/20/2022
1.0.142 647 2/20/2022
1.0.141 657 2/20/2022
1.0.140 688 2/20/2022
1.0.139 701 2/20/2022
1.0.138 666 2/20/2022
1.0.137 660 2/20/2022
1.0.136 678 2/20/2022
1.0.135 682 2/20/2022
1.0.134 671 2/19/2022
1.0.133 4,567 2/10/2022
1.0.132 781 1/27/2022
1.0.131 707 1/27/2022
1.0.130 3,570 1/24/2022
1.0.129 654 1/24/2022
1.0.128 693 1/23/2022
1.0.127 7,021 12/29/2021
1.0.126 543 12/27/2021
1.0.125 483 12/27/2021
1.0.124 505 12/27/2021
1.0.123 1,763 12/20/2021
1.0.122 548 12/17/2021
1.0.121 538 12/16/2021
1.0.120 521 12/15/2021
1.0.119 511 12/14/2021
1.0.118 532 12/14/2021
1.0.117 493 12/13/2021
1.0.116 653 12/12/2021
1.0.115 1,632 12/10/2021
1.0.114 543 12/7/2021
1.0.113 542 12/7/2021
1.0.112 1,976 12/6/2021
1.0.111 541 12/6/2021
1.0.110 543 12/5/2021
1.0.109 1,234 12/3/2021
1.0.108 1,043 12/3/2021
1.0.107 577 12/2/2021
1.0.106 2,457 11/29/2021
1.0.105 5,270 11/23/2021
1.0.104 531 11/23/2021
1.0.103 1,616 11/22/2021
1.0.102 624 11/17/2021
1.0.101 581 11/14/2021
1.0.100 1,744 11/13/2021
1.0.99 594 11/11/2021
1.0.98 578 11/11/2021
1.0.97 562 11/10/2021
1.0.96 571 11/9/2021
1.0.95 2,599 11/6/2021
1.0.94 605 11/6/2021
1.0.93 2,171 11/5/2021
1.0.92 630 11/5/2021
1.0.91 590 11/4/2021
1.0.90 563 11/4/2021
1.0.89 616 11/3/2021
1.0.88 682 10/30/2021
1.0.87 2,049 10/21/2021
1.0.86 654 10/17/2021
1.0.85 663 10/17/2021
1.0.84 3,050 10/14/2021
1.0.83 589 10/13/2021
1.0.82 607 10/13/2021
1.0.81 587 10/12/2021
1.0.80 2,141 10/11/2021
1.0.79 571 10/9/2021
1.0.78 1,952 10/7/2021
1.0.77 2,155 10/7/2021
1.0.76 569 10/7/2021
1.0.75 599 10/6/2021
1.0.74 657 9/28/2021
1.0.73 2,367 9/23/2021
1.0.72 706 9/11/2021
1.0.71 605 9/10/2021
1.0.70 670 9/9/2021
1.0.69 572 9/8/2021
1.0.68 631 9/8/2021
1.0.67 2,158 9/6/2021
1.0.66 703 8/31/2021
1.0.65 563 8/30/2021
1.0.64 2,614 7/31/2021
1.0.63 3,043 7/30/2021
1.0.62 686 7/26/2021
1.0.61 4,484 7/5/2021
1.0.60 641 7/1/2021
1.0.59 3,822 6/4/2021
1.0.58 5,073 4/26/2021
1.0.57 2,184 4/19/2021
1.0.56 5,724 4/8/2021
1.0.55 1,808 4/7/2021
1.0.54 619 4/7/2021
1.0.53 1,887 4/3/2021
1.0.52 7,985 3/22/2021
1.0.51 5,773 3/4/2021
1.0.50 2,162 2/26/2021
1.0.49 8,277 2/2/2021
1.0.48 3,231 1/26/2021
1.0.47 3,000 1/24/2021
1.0.46 660 1/24/2021
1.0.45 715 1/23/2021
1.0.44 3,901 1/20/2021
1.0.43 716 1/20/2021
1.0.42 2,087 1/18/2021
1.0.41 632 1/18/2021
1.0.40 2,065 1/16/2021
1.0.39 6,315 12/17/2020
1.0.38 697 12/16/2020
1.0.37 3,214 12/14/2020
1.0.36 2,124 12/9/2020
1.0.35 676 12/9/2020
1.0.34 685 12/7/2020
1.0.33 790 12/6/2020
1.0.32 740 12/2/2020
1.0.31 708 12/2/2020
1.0.30 2,202 12/1/2020
1.0.29 7,365 11/12/2020
1.0.29-atestpub 565 11/11/2020
1.0.28 3,340 10/11/2020
1.0.27 8,618 9/9/2020
1.0.26 2,629 9/3/2020
1.0.25 2,688 8/20/2020
1.0.24 6,160 8/9/2020
1.0.23 2,709 7/28/2020
1.0.22 2,645 7/19/2020
1.0.21 4,453 7/6/2020
1.0.20 6,627 6/6/2020
1.0.19 2,618 6/4/2020
1.0.18 4,385 5/29/2020
1.0.17 4,427 5/21/2020
1.0.16 768 5/17/2020
1.0.15 4,522 5/12/2020
1.0.14 8,241 5/4/2020
1.0.13 790 4/24/2020
1.0.12 770 4/22/2020
1.0.11 755 4/22/2020
1.0.10 777 4/21/2020
1.0.9 3,229 4/18/2020
1.0.8 2,580 4/16/2020
1.0.7 784 4/16/2020
1.0.6 2,255 4/15/2020
1.0.5 2,669 4/11/2020
1.0.4 2,558 4/3/2020
1.0.3 778 4/1/2020
1.0.2 2,489 3/27/2020
1.0.1 2,607 3/22/2020
1.0.0 892 3/22/2020