Ecng.Net.SocketIO 1.0.508

dotnet add package Ecng.Net.SocketIO --version 1.0.508
                    
NuGet\Install-Package Ecng.Net.SocketIO -Version 1.0.508
                    
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.508" />
                    
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.508" />
                    
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.508
                    
#r "nuget: Ecng.Net.SocketIO, 1.0.508"
                    
#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.508
                    
#: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.508
                    
Install as a Cake Addin
#tool nuget:?package=Ecng.Net.SocketIO&version=1.0.508
                    
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.508 0 1/7/2026
1.0.507 48 1/6/2026
1.0.506 46 1/6/2026
1.0.505 58 1/5/2026
1.0.504 70 1/4/2026
1.0.503 73 1/1/2026
1.0.502 81 12/31/2025
1.0.501 92 12/30/2025
1.0.500 86 12/30/2025
1.0.499 93 12/29/2025
1.0.498 89 12/29/2025
1.0.497 95 12/26/2025
1.0.496 87 12/26/2025
1.0.495 84 12/26/2025
1.0.494 105 12/26/2025
1.0.493 176 12/25/2025
1.0.492 180 12/25/2025
1.0.491 186 12/24/2025
1.0.490 181 12/23/2025
1.0.489 173 12/22/2025
1.0.488 170 12/22/2025
1.0.487 178 12/22/2025
1.0.486 165 12/21/2025
1.0.485 220 12/19/2025
1.0.484 239 12/19/2025
1.0.483 285 12/18/2025
1.0.482 284 12/17/2025
1.0.481 281 12/15/2025
1.0.480 255 12/15/2025
1.0.479 232 12/14/2025
1.0.478 161 12/14/2025
1.0.477 163 12/13/2025
1.0.476 177 12/13/2025
1.0.475 144 12/12/2025
1.0.474 127 12/12/2025
1.0.473 120 12/12/2025
1.0.472 123 12/12/2025
1.0.471 117 12/12/2025
1.0.470 123 12/12/2025
1.0.469 124 12/12/2025
1.0.468 727 12/2/2025
1.0.467 681 12/2/2025
1.0.466 681 12/2/2025
1.0.465 278 11/30/2025
1.0.464 148 11/29/2025
1.0.463 143 11/28/2025
1.0.462 148 11/28/2025
1.0.461 193 11/27/2025
1.0.460 236 11/24/2025
1.0.459 205 11/24/2025
1.0.458 201 11/23/2025
1.0.457 176 11/23/2025
1.0.456 229 11/22/2025
1.0.455 441 11/20/2025
1.0.454 416 11/20/2025
1.0.453 412 11/20/2025
1.0.452 437 11/18/2025
1.0.451 416 11/18/2025
1.0.450 344 11/13/2025
1.0.449 281 11/10/2025
1.0.448 1,102 11/1/2025
1.0.447 212 10/31/2025
1.0.446 220 10/28/2025
1.0.445 339 10/27/2025
1.0.444 207 10/27/2025
1.0.443 138 10/25/2025
1.0.442 164 10/24/2025
1.0.441 277 10/20/2025
1.0.440 310 10/12/2025
1.0.439 159 10/11/2025
1.0.438 296 10/7/2025
1.0.437 237 10/6/2025
1.0.436 277 10/3/2025
1.0.435 249 10/1/2025
1.0.434 218 10/1/2025
1.0.433 217 9/30/2025
1.0.432 220 9/28/2025
1.0.431 236 9/25/2025
1.0.430 3,085 9/5/2025
1.0.429 248 9/2/2025
1.0.428 605 8/30/2025
1.0.427 271 8/30/2025
1.0.426 274 8/20/2025
1.0.425 217 8/20/2025
1.0.424 229 8/19/2025
1.0.423 240 8/15/2025
1.0.422 333 8/10/2025
1.0.421 1,054 7/16/2025
1.0.420 287 7/14/2025
1.0.419 259 7/13/2025
1.0.418 234 7/13/2025
1.0.417 209 7/12/2025
1.0.416 700 7/8/2025
1.0.415 269 7/4/2025
1.0.414 267 7/2/2025
1.0.413 429 6/24/2025
1.0.412 1,037 6/16/2025
1.0.411 418 6/9/2025
1.0.410 299 6/8/2025
1.0.409 622 5/21/2025
1.0.408 268 5/21/2025
1.0.407 255 5/17/2025
1.0.406 659 5/12/2025
1.0.405 354 5/12/2025
1.0.404 322 5/12/2025
1.0.403 245 5/11/2025
1.0.402 254 5/11/2025
1.0.401 213 5/10/2025
1.0.400 172 5/10/2025
1.0.399 293 5/6/2025
1.0.398 225 5/3/2025
1.0.397 389 4/17/2025
1.0.396 339 4/15/2025
1.0.395 240 4/12/2025
1.0.394 312 4/9/2025
1.0.393 273 4/6/2025
1.0.392 225 4/5/2025
1.0.391 1,101 3/22/2025
1.0.390 294 3/20/2025
1.0.389 287 3/20/2025
1.0.388 274 3/19/2025
1.0.387 843 2/26/2025
1.0.386 251 2/26/2025
1.0.385 773 2/8/2025
1.0.384 256 2/8/2025
1.0.383 229 2/8/2025
1.0.382 230 2/6/2025
1.0.381 220 2/6/2025
1.0.380 238 2/6/2025
1.0.379 244 2/6/2025
1.0.378 220 2/6/2025
1.0.377 222 2/5/2025
1.0.376 227 2/5/2025
1.0.375 244 2/5/2025
1.0.374 268 2/3/2025
1.0.373 250 2/2/2025
1.0.372 269 2/1/2025
1.0.371 249 1/31/2025
1.0.370 255 1/30/2025
1.0.369 239 1/26/2025
1.0.368 272 1/21/2025
1.0.367 258 1/20/2025
1.0.366 223 1/20/2025
1.0.365 238 1/19/2025
1.0.364 225 1/19/2025
1.0.363 250 1/15/2025
1.0.362 221 1/15/2025
1.0.361 215 1/14/2025
1.0.360 208 1/12/2025
1.0.359 199 1/12/2025
1.0.358 213 1/12/2025
1.0.357 183 1/12/2025
1.0.356 235 1/10/2025
1.0.355 1,071 12/30/2024
1.0.354 257 12/27/2024
1.0.353 281 12/19/2024
1.0.352 745 11/20/2024
1.0.351 258 11/19/2024
1.0.350 241 11/19/2024
1.0.349 800 11/18/2024
1.0.348 474 11/15/2024
1.0.347 227 11/14/2024
1.0.346 249 11/14/2024
1.0.345 255 11/14/2024
1.0.344 206 11/14/2024
1.0.343 230 11/14/2024
1.0.342 272 11/7/2024
1.0.341 282 10/31/2024
1.0.340 338 10/20/2024
1.0.339 263 10/20/2024
1.0.338 277 10/20/2024
1.0.337 270 10/19/2024
1.0.336 280 10/19/2024
1.0.335 282 10/19/2024
1.0.334 279 10/19/2024
1.0.333 277 10/19/2024
1.0.332 257 10/19/2024
1.0.331 284 10/19/2024
1.0.330 313 10/18/2024
1.0.329 271 10/17/2024
1.0.328 232 10/17/2024
1.0.327 253 10/17/2024
1.0.326 808 10/14/2024
1.0.325 237 10/13/2024
1.0.324 235 10/13/2024
1.0.323 254 10/12/2024
1.0.322 448 10/9/2024
1.0.321 254 10/9/2024
1.0.320 449 10/5/2024
1.0.319 780 9/18/2024
1.0.318 237 9/18/2024
1.0.317 257 9/18/2024
1.0.316 251 9/17/2024
1.0.315 749 9/3/2024
1.0.314 297 9/1/2024
1.0.313 967 8/9/2024
1.0.312 253 8/9/2024
1.0.311 274 8/8/2024
1.0.310 712 7/25/2024
1.0.309 271 7/23/2024
1.0.308 294 7/17/2024
1.0.307 561 7/4/2024
1.0.306 621 6/12/2024
1.0.305 262 6/12/2024
1.0.304 261 6/12/2024
1.0.303 453 5/28/2024
1.0.302 618 5/4/2024
1.0.301 410 4/23/2024
1.0.300 274 4/21/2024
1.0.299 299 4/14/2024
1.0.298 567 3/28/2024
1.0.297 338 3/17/2024
1.0.296 541 3/9/2024
1.0.295 359 2/23/2024
1.0.294 287 2/23/2024
1.0.293 498 2/18/2024
1.0.292 287 2/18/2024
1.0.291 263 2/17/2024
1.0.290 281 2/16/2024
1.0.289 399 2/14/2024
1.0.288 282 2/13/2024
1.0.287 352 2/8/2024
1.0.286 356 2/5/2024
1.0.285 274 2/4/2024
1.0.284 443 1/23/2024
1.0.283 262 1/23/2024
1.0.282 331 1/12/2024
1.0.281 699 1/2/2024
1.0.280 315 12/29/2023
1.0.279 364 12/17/2023
1.0.278 522 12/15/2023
1.0.277 292 12/15/2023
1.0.276 272 12/15/2023
1.0.275 306 12/13/2023
1.0.274 300 12/13/2023
1.0.273 306 12/10/2023
1.0.272 686 11/18/2023
1.0.271 230 11/18/2023
1.0.270 256 11/18/2023
1.0.269 239 11/17/2023
1.0.268 213 11/12/2023
1.0.267 212 11/12/2023
1.0.266 232 11/10/2023
1.0.265 199 11/10/2023
1.0.264 238 11/9/2023
1.0.263 199 11/9/2023
1.0.262 218 11/9/2023
1.0.261 242 11/3/2023
1.0.260 230 11/1/2023
1.0.259 210 11/1/2023
1.0.258 1,477 9/8/2023
1.0.257 269 9/8/2023
1.0.256 285 9/3/2023
1.0.255 350 8/27/2023
1.0.254 279 8/24/2023
1.0.253 243 8/21/2023
1.0.252 320 8/15/2023
1.0.251 288 8/14/2023
1.0.250 267 8/14/2023
1.0.249 300 8/10/2023
1.0.248 1,017 7/29/2023
1.0.247 1,093 7/1/2023
1.0.246 309 6/29/2023
1.0.245 802 5/27/2023
1.0.244 355 5/21/2023
1.0.243 298 5/19/2023
1.0.242 1,085 5/8/2023
1.0.241 355 5/7/2023
1.0.240 343 5/7/2023
1.0.239 321 5/7/2023
1.0.238 370 5/1/2023
1.0.237 414 4/22/2023
1.0.236 373 4/21/2023
1.0.235 341 4/21/2023
1.0.234 1,236 4/13/2023
1.0.233 1,137 4/3/2023
1.0.232 491 3/27/2023
1.0.231 435 3/21/2023
1.0.230 436 3/17/2023
1.0.229 429 3/13/2023
1.0.228 1,186 3/6/2023
1.0.227 499 2/26/2023
1.0.226 942 2/21/2023
1.0.225 456 2/20/2023
1.0.224 473 2/16/2023
1.0.223 457 2/15/2023
1.0.222 432 2/14/2023
1.0.221 428 2/14/2023
1.0.220 1,359 2/9/2023
1.0.219 835 2/7/2023
1.0.218 488 2/4/2023
1.0.217 471 2/4/2023
1.0.216 487 2/3/2023
1.0.215 448 2/3/2023
1.0.214 445 2/3/2023
1.0.213 888 2/2/2023
1.0.212 834 1/30/2023
1.0.211 468 1/30/2023
1.0.210 510 1/25/2023
1.0.209 505 1/23/2023
1.0.208 456 1/23/2023
1.0.207 490 1/18/2023
1.0.206 518 1/15/2023
1.0.205 517 1/6/2023
1.0.204 1,418 1/1/2023
1.0.203 485 12/31/2022
1.0.202 973 12/30/2022
1.0.201 503 12/29/2022
1.0.200 513 12/23/2022
1.0.199 1,392 12/12/2022
1.0.198 1,073 12/8/2022
1.0.197 489 12/4/2022
1.0.196 491 12/4/2022
1.0.195 495 12/2/2022
1.0.194 518 11/30/2022
1.0.193 481 11/29/2022
1.0.192 477 11/28/2022
1.0.191 522 11/26/2022
1.0.190 516 11/26/2022
1.0.189 517 11/25/2022
1.0.188 515 11/25/2022
1.0.187 531 11/18/2022
1.0.186 1,599 11/11/2022
1.0.185 554 11/11/2022
1.0.184 510 11/10/2022
1.0.183 575 11/5/2022
1.0.182 553 11/4/2022
1.0.181 532 11/2/2022
1.0.180 524 11/2/2022
1.0.179 1,437 11/1/2022
1.0.178 1,661 10/16/2022
1.0.177 744 9/25/2022
1.0.176 673 9/10/2022
1.0.175 2,984 9/8/2022
1.0.174 654 9/8/2022
1.0.173 663 9/8/2022
1.0.172 636 9/4/2022
1.0.171 636 9/4/2022
1.0.170 5,357 8/24/2022
1.0.169 719 8/8/2022
1.0.168 640 8/8/2022
1.0.167 1,270 7/31/2022
1.0.166 659 7/31/2022
1.0.165 670 7/26/2022
1.0.164 635 7/26/2022
1.0.163 3,204 7/21/2022
1.0.162 692 7/19/2022
1.0.161 3,159 7/18/2022
1.0.160 697 7/13/2022
1.0.159 678 7/8/2022
1.0.158 698 6/30/2022
1.0.157 710 6/20/2022
1.0.156 660 6/18/2022
1.0.155 704 6/6/2022
1.0.154 749 5/27/2022
1.0.153 5,217 4/30/2022
1.0.152 690 4/20/2022
1.0.151 718 4/10/2022
1.0.150 685 4/7/2022
1.0.149 667 4/7/2022
1.0.148 721 4/2/2022
1.0.147 680 3/29/2022
1.0.146 670 3/27/2022
1.0.145 671 3/27/2022
1.0.144 3,923 3/24/2022
1.0.143 2,689 2/20/2022
1.0.142 649 2/20/2022
1.0.141 658 2/20/2022
1.0.140 691 2/20/2022
1.0.139 708 2/20/2022
1.0.138 671 2/20/2022
1.0.137 663 2/20/2022
1.0.136 681 2/20/2022
1.0.135 686 2/20/2022
1.0.134 675 2/19/2022
1.0.133 4,570 2/10/2022
1.0.132 782 1/27/2022
1.0.131 710 1/27/2022
1.0.130 3,573 1/24/2022
1.0.129 655 1/24/2022
1.0.128 695 1/23/2022
1.0.127 7,022 12/29/2021
1.0.126 547 12/27/2021
1.0.125 488 12/27/2021
1.0.124 511 12/27/2021
1.0.123 1,767 12/20/2021
1.0.122 552 12/17/2021
1.0.121 541 12/16/2021
1.0.120 525 12/15/2021
1.0.119 513 12/14/2021
1.0.118 538 12/14/2021
1.0.117 495 12/13/2021
1.0.116 658 12/12/2021
1.0.115 1,636 12/10/2021
1.0.114 546 12/7/2021
1.0.113 546 12/7/2021
1.0.112 1,979 12/6/2021
1.0.111 543 12/6/2021
1.0.110 546 12/5/2021
1.0.109 1,239 12/3/2021
1.0.108 1,045 12/3/2021
1.0.107 580 12/2/2021
1.0.106 2,460 11/29/2021
1.0.105 5,272 11/23/2021
1.0.104 535 11/23/2021
1.0.103 1,619 11/22/2021
1.0.102 629 11/17/2021
1.0.101 585 11/14/2021
1.0.100 1,749 11/13/2021
1.0.99 597 11/11/2021
1.0.98 580 11/11/2021
1.0.97 564 11/10/2021
1.0.96 574 11/9/2021
1.0.95 2,604 11/6/2021
1.0.94 608 11/6/2021
1.0.93 2,172 11/5/2021
1.0.92 633 11/5/2021
1.0.91 592 11/4/2021
1.0.90 564 11/4/2021
1.0.89 621 11/3/2021
1.0.88 687 10/30/2021
1.0.87 2,053 10/21/2021
1.0.86 658 10/17/2021
1.0.85 668 10/17/2021
1.0.84 3,055 10/14/2021
1.0.83 593 10/13/2021
1.0.82 610 10/13/2021
1.0.81 588 10/12/2021
1.0.80 2,144 10/11/2021
1.0.79 572 10/9/2021
1.0.78 1,956 10/7/2021
1.0.77 2,157 10/7/2021
1.0.76 570 10/7/2021
1.0.75 604 10/6/2021
1.0.74 659 9/28/2021
1.0.73 2,368 9/23/2021
1.0.72 707 9/11/2021
1.0.71 607 9/10/2021
1.0.70 675 9/9/2021
1.0.69 575 9/8/2021
1.0.68 635 9/8/2021
1.0.67 2,160 9/6/2021
1.0.66 708 8/31/2021
1.0.65 567 8/30/2021
1.0.64 2,615 7/31/2021
1.0.63 3,048 7/30/2021
1.0.62 687 7/26/2021
1.0.61 4,485 7/5/2021
1.0.60 643 7/1/2021
1.0.59 3,825 6/4/2021
1.0.58 5,076 4/26/2021
1.0.57 2,186 4/19/2021
1.0.56 5,728 4/8/2021
1.0.55 1,810 4/7/2021
1.0.54 621 4/7/2021
1.0.53 1,890 4/3/2021
1.0.52 7,988 3/22/2021
1.0.51 5,775 3/4/2021
1.0.50 2,164 2/26/2021
1.0.49 8,282 2/2/2021
1.0.48 3,232 1/26/2021
1.0.47 3,003 1/24/2021
1.0.46 662 1/24/2021
1.0.45 718 1/23/2021
1.0.44 3,905 1/20/2021
1.0.43 720 1/20/2021
1.0.42 2,089 1/18/2021
1.0.41 635 1/18/2021
1.0.40 2,067 1/16/2021
1.0.39 6,318 12/17/2020
1.0.38 698 12/16/2020
1.0.37 3,218 12/14/2020
1.0.36 2,128 12/9/2020
1.0.35 679 12/9/2020
1.0.34 688 12/7/2020
1.0.33 791 12/6/2020
1.0.32 743 12/2/2020
1.0.31 713 12/2/2020
1.0.30 2,211 12/1/2020
1.0.29 7,371 11/12/2020
1.0.29-atestpub 567 11/11/2020
1.0.28 3,343 10/11/2020
1.0.27 8,622 9/9/2020
1.0.26 2,632 9/3/2020
1.0.25 2,694 8/20/2020
1.0.24 6,164 8/9/2020
1.0.23 2,710 7/28/2020
1.0.22 2,648 7/19/2020
1.0.21 4,460 7/6/2020
1.0.20 6,631 6/6/2020
1.0.19 2,623 6/4/2020
1.0.18 4,387 5/29/2020
1.0.17 4,428 5/21/2020
1.0.16 770 5/17/2020
1.0.15 4,525 5/12/2020
1.0.14 8,245 5/4/2020
1.0.13 792 4/24/2020
1.0.12 773 4/22/2020
1.0.11 760 4/22/2020
1.0.10 780 4/21/2020
1.0.9 3,231 4/18/2020
1.0.8 2,582 4/16/2020
1.0.7 787 4/16/2020
1.0.6 2,259 4/15/2020
1.0.5 2,671 4/11/2020
1.0.4 2,564 4/3/2020
1.0.3 782 4/1/2020
1.0.2 2,492 3/27/2020
1.0.1 2,608 3/22/2020
1.0.0 895 3/22/2020