Ecng.Net.SocketIO 1.0.497

dotnet add package Ecng.Net.SocketIO --version 1.0.497
                    
NuGet\Install-Package Ecng.Net.SocketIO -Version 1.0.497
                    
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.497" />
                    
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.497" />
                    
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.497
                    
#r "nuget: Ecng.Net.SocketIO, 1.0.497"
                    
#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.497
                    
#: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.497
                    
Install as a Cake Addin
#tool nuget:?package=Ecng.Net.SocketIO&version=1.0.497
                    
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 26 12/26/2025
1.0.496 31 12/26/2025
1.0.495 28 12/26/2025
1.0.494 50 12/26/2025
1.0.493 120 12/25/2025
1.0.492 125 12/25/2025
1.0.491 149 12/24/2025
1.0.490 162 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 220 12/14/2025
1.0.478 152 12/14/2025
1.0.477 155 12/13/2025
1.0.476 165 12/13/2025
1.0.475 131 12/12/2025
1.0.474 115 12/12/2025
1.0.473 111 12/12/2025
1.0.472 113 12/12/2025
1.0.471 108 12/12/2025
1.0.470 115 12/12/2025
1.0.469 114 12/12/2025
1.0.468 716 12/2/2025
1.0.467 670 12/2/2025
1.0.466 669 12/2/2025
1.0.465 268 11/30/2025
1.0.464 137 11/29/2025
1.0.463 133 11/28/2025
1.0.462 140 11/28/2025
1.0.461 184 11/27/2025
1.0.460 224 11/24/2025
1.0.459 194 11/24/2025
1.0.458 190 11/23/2025
1.0.457 166 11/23/2025
1.0.456 219 11/22/2025
1.0.455 432 11/20/2025
1.0.454 405 11/20/2025
1.0.453 405 11/20/2025
1.0.452 426 11/18/2025
1.0.451 405 11/18/2025
1.0.450 334 11/13/2025
1.0.449 272 11/10/2025
1.0.448 1,091 11/1/2025
1.0.447 202 10/31/2025
1.0.446 211 10/28/2025
1.0.445 317 10/27/2025
1.0.444 198 10/27/2025
1.0.443 128 10/25/2025
1.0.442 154 10/24/2025
1.0.441 265 10/20/2025
1.0.440 301 10/12/2025
1.0.439 149 10/11/2025
1.0.438 289 10/7/2025
1.0.437 227 10/6/2025
1.0.436 269 10/3/2025
1.0.435 243 10/1/2025
1.0.434 208 10/1/2025
1.0.433 208 9/30/2025
1.0.432 212 9/28/2025
1.0.431 227 9/25/2025
1.0.430 2,988 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 265 8/20/2025
1.0.425 210 8/20/2025
1.0.424 220 8/19/2025
1.0.423 230 8/15/2025
1.0.422 321 8/10/2025
1.0.421 1,046 7/16/2025
1.0.420 277 7/14/2025
1.0.419 249 7/13/2025
1.0.418 223 7/13/2025
1.0.417 202 7/12/2025
1.0.416 687 7/8/2025
1.0.415 260 7/4/2025
1.0.414 256 7/2/2025
1.0.413 420 6/24/2025
1.0.412 1,030 6/16/2025
1.0.411 410 6/9/2025
1.0.410 286 6/8/2025
1.0.409 613 5/21/2025
1.0.408 260 5/21/2025
1.0.407 248 5/17/2025
1.0.406 650 5/12/2025
1.0.405 344 5/12/2025
1.0.404 313 5/12/2025
1.0.403 236 5/11/2025
1.0.402 244 5/11/2025
1.0.401 200 5/10/2025
1.0.400 164 5/10/2025
1.0.399 284 5/6/2025
1.0.398 212 5/3/2025
1.0.397 381 4/17/2025
1.0.396 332 4/15/2025
1.0.395 232 4/12/2025
1.0.394 304 4/9/2025
1.0.393 263 4/6/2025
1.0.392 215 4/5/2025
1.0.391 1,089 3/22/2025
1.0.390 284 3/20/2025
1.0.389 277 3/20/2025
1.0.388 263 3/19/2025
1.0.387 833 2/26/2025
1.0.386 241 2/26/2025
1.0.385 763 2/8/2025
1.0.384 248 2/8/2025
1.0.383 221 2/8/2025
1.0.382 222 2/6/2025
1.0.381 213 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 236 2/5/2025
1.0.374 258 2/3/2025
1.0.373 241 2/2/2025
1.0.372 260 2/1/2025
1.0.371 242 1/31/2025
1.0.370 244 1/30/2025
1.0.369 225 1/26/2025
1.0.368 263 1/21/2025
1.0.367 247 1/20/2025
1.0.366 213 1/20/2025
1.0.365 227 1/19/2025
1.0.364 214 1/19/2025
1.0.363 242 1/15/2025
1.0.362 212 1/15/2025
1.0.361 204 1/14/2025
1.0.360 198 1/12/2025
1.0.359 189 1/12/2025
1.0.358 203 1/12/2025
1.0.357 175 1/12/2025
1.0.356 222 1/10/2025
1.0.355 1,059 12/30/2024
1.0.354 250 12/27/2024
1.0.353 274 12/19/2024
1.0.352 733 11/20/2024
1.0.351 247 11/19/2024
1.0.350 232 11/19/2024
1.0.349 791 11/18/2024
1.0.348 463 11/15/2024
1.0.347 218 11/14/2024
1.0.346 240 11/14/2024
1.0.345 245 11/14/2024
1.0.344 197 11/14/2024
1.0.343 220 11/14/2024
1.0.342 263 11/7/2024
1.0.341 274 10/31/2024
1.0.340 331 10/20/2024
1.0.339 256 10/20/2024
1.0.338 267 10/20/2024
1.0.337 260 10/19/2024
1.0.336 271 10/19/2024
1.0.335 272 10/19/2024
1.0.334 269 10/19/2024
1.0.333 269 10/19/2024
1.0.332 250 10/19/2024
1.0.331 275 10/19/2024
1.0.330 306 10/18/2024
1.0.329 265 10/17/2024
1.0.328 224 10/17/2024
1.0.327 242 10/17/2024
1.0.326 798 10/14/2024
1.0.325 229 10/13/2024
1.0.324 225 10/13/2024
1.0.323 246 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 770 9/18/2024
1.0.318 229 9/18/2024
1.0.317 249 9/18/2024
1.0.316 243 9/17/2024
1.0.315 741 9/3/2024
1.0.314 285 9/1/2024
1.0.313 956 8/9/2024
1.0.312 245 8/9/2024
1.0.311 266 8/8/2024
1.0.310 700 7/25/2024
1.0.309 259 7/23/2024
1.0.308 287 7/17/2024
1.0.307 551 7/4/2024
1.0.306 613 6/12/2024
1.0.305 253 6/12/2024
1.0.304 248 6/12/2024
1.0.303 443 5/28/2024
1.0.302 607 5/4/2024
1.0.301 402 4/23/2024
1.0.300 265 4/21/2024
1.0.299 292 4/14/2024
1.0.298 559 3/28/2024
1.0.297 328 3/17/2024
1.0.296 534 3/9/2024
1.0.295 350 2/23/2024
1.0.294 281 2/23/2024
1.0.293 490 2/18/2024
1.0.292 280 2/18/2024
1.0.291 254 2/17/2024
1.0.290 272 2/16/2024
1.0.289 392 2/14/2024
1.0.288 272 2/13/2024
1.0.287 342 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 253 1/23/2024
1.0.282 320 1/12/2024
1.0.281 688 1/2/2024
1.0.280 304 12/29/2023
1.0.279 355 12/17/2023
1.0.278 512 12/15/2023
1.0.277 283 12/15/2023
1.0.276 262 12/15/2023
1.0.275 293 12/13/2023
1.0.274 291 12/13/2023
1.0.273 295 12/10/2023
1.0.272 683 11/18/2023
1.0.271 226 11/18/2023
1.0.270 253 11/18/2023
1.0.269 235 11/17/2023
1.0.268 211 11/12/2023
1.0.267 208 11/12/2023
1.0.266 230 11/10/2023
1.0.265 196 11/10/2023
1.0.264 236 11/9/2023
1.0.263 196 11/9/2023
1.0.262 214 11/9/2023
1.0.261 239 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 265 9/8/2023
1.0.256 283 9/3/2023
1.0.255 347 8/27/2023
1.0.254 277 8/24/2023
1.0.253 242 8/21/2023
1.0.252 317 8/15/2023
1.0.251 286 8/14/2023
1.0.250 266 8/14/2023
1.0.249 296 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 295 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 411 4/22/2023
1.0.236 372 4/21/2023
1.0.235 337 4/21/2023
1.0.234 1,232 4/13/2023
1.0.233 1,135 4/3/2023
1.0.232 487 3/27/2023
1.0.231 431 3/21/2023
1.0.230 434 3/17/2023
1.0.229 427 3/13/2023
1.0.228 1,184 3/6/2023
1.0.227 497 2/26/2023
1.0.226 939 2/21/2023
1.0.225 455 2/20/2023
1.0.224 468 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,355 2/9/2023
1.0.219 831 2/7/2023
1.0.218 485 2/4/2023
1.0.217 467 2/4/2023
1.0.216 481 2/3/2023
1.0.215 445 2/3/2023
1.0.214 440 2/3/2023
1.0.213 885 2/2/2023
1.0.212 832 1/30/2023
1.0.211 466 1/30/2023
1.0.210 508 1/25/2023
1.0.209 504 1/23/2023
1.0.208 455 1/23/2023
1.0.207 489 1/18/2023
1.0.206 514 1/15/2023
1.0.205 513 1/6/2023
1.0.204 1,417 1/1/2023
1.0.203 480 12/31/2022
1.0.202 969 12/30/2022
1.0.201 499 12/29/2022
1.0.200 509 12/23/2022
1.0.199 1,389 12/12/2022
1.0.198 1,071 12/8/2022
1.0.197 487 12/4/2022
1.0.196 490 12/4/2022
1.0.195 492 12/2/2022
1.0.194 517 11/30/2022
1.0.193 480 11/29/2022
1.0.192 475 11/28/2022
1.0.191 516 11/26/2022
1.0.190 514 11/26/2022
1.0.189 516 11/25/2022
1.0.188 512 11/25/2022
1.0.187 526 11/18/2022
1.0.186 1,595 11/11/2022
1.0.185 550 11/11/2022
1.0.184 506 11/10/2022
1.0.183 572 11/5/2022
1.0.182 548 11/4/2022
1.0.181 531 11/2/2022
1.0.180 523 11/2/2022
1.0.179 1,432 11/1/2022
1.0.178 1,656 10/16/2022
1.0.177 739 9/25/2022
1.0.176 668 9/10/2022
1.0.175 2,979 9/8/2022
1.0.174 653 9/8/2022
1.0.173 659 9/8/2022
1.0.172 633 9/4/2022
1.0.171 635 9/4/2022
1.0.170 5,353 8/24/2022
1.0.169 714 8/8/2022
1.0.168 636 8/8/2022
1.0.167 1,267 7/31/2022
1.0.166 654 7/31/2022
1.0.165 666 7/26/2022
1.0.164 632 7/26/2022
1.0.163 3,200 7/21/2022
1.0.162 686 7/19/2022
1.0.161 3,157 7/18/2022
1.0.160 691 7/13/2022
1.0.159 673 7/8/2022
1.0.158 692 6/30/2022
1.0.157 708 6/20/2022
1.0.156 658 6/18/2022
1.0.155 699 6/6/2022
1.0.154 745 5/27/2022
1.0.153 5,210 4/30/2022
1.0.152 685 4/20/2022
1.0.151 713 4/10/2022
1.0.150 677 4/7/2022
1.0.149 663 4/7/2022
1.0.148 718 4/2/2022
1.0.147 677 3/29/2022
1.0.146 667 3/27/2022
1.0.145 668 3/27/2022
1.0.144 3,919 3/24/2022
1.0.143 2,686 2/20/2022
1.0.142 645 2/20/2022
1.0.141 657 2/20/2022
1.0.140 687 2/20/2022
1.0.139 700 2/20/2022
1.0.138 665 2/20/2022
1.0.137 660 2/20/2022
1.0.136 677 2/20/2022
1.0.135 682 2/20/2022
1.0.134 669 2/19/2022
1.0.133 4,566 2/10/2022
1.0.132 781 1/27/2022
1.0.131 707 1/27/2022
1.0.130 3,568 1/24/2022
1.0.129 653 1/24/2022
1.0.128 693 1/23/2022
1.0.127 7,019 12/29/2021
1.0.126 542 12/27/2021
1.0.125 483 12/27/2021
1.0.124 504 12/27/2021
1.0.123 1,761 12/20/2021
1.0.122 547 12/17/2021
1.0.121 537 12/16/2021
1.0.120 520 12/15/2021
1.0.119 511 12/14/2021
1.0.118 532 12/14/2021
1.0.117 492 12/13/2021
1.0.116 652 12/12/2021
1.0.115 1,631 12/10/2021
1.0.114 542 12/7/2021
1.0.113 540 12/7/2021
1.0.112 1,975 12/6/2021
1.0.111 540 12/6/2021
1.0.110 542 12/5/2021
1.0.109 1,233 12/3/2021
1.0.108 1,041 12/3/2021
1.0.107 577 12/2/2021
1.0.106 2,455 11/29/2021
1.0.105 5,268 11/23/2021
1.0.104 529 11/23/2021
1.0.103 1,615 11/22/2021
1.0.102 622 11/17/2021
1.0.101 579 11/14/2021
1.0.100 1,744 11/13/2021
1.0.99 592 11/11/2021
1.0.98 577 11/11/2021
1.0.97 562 11/10/2021
1.0.96 569 11/9/2021
1.0.95 2,598 11/6/2021
1.0.94 604 11/6/2021
1.0.93 2,170 11/5/2021
1.0.92 630 11/5/2021
1.0.91 589 11/4/2021
1.0.90 562 11/4/2021
1.0.89 615 11/3/2021
1.0.88 682 10/30/2021
1.0.87 2,047 10/21/2021
1.0.86 654 10/17/2021
1.0.85 662 10/17/2021
1.0.84 3,049 10/14/2021
1.0.83 588 10/13/2021
1.0.82 607 10/13/2021
1.0.81 586 10/12/2021
1.0.80 2,140 10/11/2021
1.0.79 570 10/9/2021
1.0.78 1,951 10/7/2021
1.0.77 2,154 10/7/2021
1.0.76 567 10/7/2021
1.0.75 599 10/6/2021
1.0.74 656 9/28/2021
1.0.73 2,366 9/23/2021
1.0.72 705 9/11/2021
1.0.71 603 9/10/2021
1.0.70 669 9/9/2021
1.0.69 572 9/8/2021
1.0.68 630 9/8/2021
1.0.67 2,157 9/6/2021
1.0.66 702 8/31/2021
1.0.65 562 8/30/2021
1.0.64 2,613 7/31/2021
1.0.63 3,042 7/30/2021
1.0.62 684 7/26/2021
1.0.61 4,484 7/5/2021
1.0.60 640 7/1/2021
1.0.59 3,822 6/4/2021
1.0.58 5,072 4/26/2021
1.0.57 2,183 4/19/2021
1.0.56 5,723 4/8/2021
1.0.55 1,807 4/7/2021
1.0.54 618 4/7/2021
1.0.53 1,886 4/3/2021
1.0.52 7,985 3/22/2021
1.0.51 5,772 3/4/2021
1.0.50 2,161 2/26/2021
1.0.49 8,277 2/2/2021
1.0.48 3,230 1/26/2021
1.0.47 3,000 1/24/2021
1.0.46 658 1/24/2021
1.0.45 713 1/23/2021
1.0.44 3,900 1/20/2021
1.0.43 716 1/20/2021
1.0.42 2,085 1/18/2021
1.0.41 631 1/18/2021
1.0.40 2,064 1/16/2021
1.0.39 6,314 12/17/2020
1.0.38 697 12/16/2020
1.0.37 3,214 12/14/2020
1.0.36 2,123 12/9/2020
1.0.35 675 12/9/2020
1.0.34 684 12/7/2020
1.0.33 788 12/6/2020
1.0.32 738 12/2/2020
1.0.31 707 12/2/2020
1.0.30 2,201 12/1/2020
1.0.29 7,364 11/12/2020
1.0.29-atestpub 564 11/11/2020
1.0.28 3,339 10/11/2020
1.0.27 8,617 9/9/2020
1.0.26 2,628 9/3/2020
1.0.25 2,687 8/20/2020
1.0.24 6,159 8/9/2020
1.0.23 2,708 7/28/2020
1.0.22 2,644 7/19/2020
1.0.21 4,453 7/6/2020
1.0.20 6,625 6/6/2020
1.0.19 2,615 6/4/2020
1.0.18 4,384 5/29/2020
1.0.17 4,425 5/21/2020
1.0.16 768 5/17/2020
1.0.15 4,521 5/12/2020
1.0.14 8,240 5/4/2020
1.0.13 788 4/24/2020
1.0.12 769 4/22/2020
1.0.11 755 4/22/2020
1.0.10 776 4/21/2020
1.0.9 3,229 4/18/2020
1.0.8 2,579 4/16/2020
1.0.7 782 4/16/2020
1.0.6 2,255 4/15/2020
1.0.5 2,667 4/11/2020
1.0.4 2,558 4/3/2020
1.0.3 777 4/1/2020
1.0.2 2,488 3/27/2020
1.0.1 2,607 3/22/2020
1.0.0 891 3/22/2020