Nethereum.Util
5.8.0
Prefix Reserved
dotnet add package Nethereum.Util --version 5.8.0
NuGet\Install-Package Nethereum.Util -Version 5.8.0
<PackageReference Include="Nethereum.Util" Version="5.8.0" />
<PackageVersion Include="Nethereum.Util" Version="5.8.0" />
<PackageReference Include="Nethereum.Util" />
paket add Nethereum.Util --version 5.8.0
#r "nuget: Nethereum.Util, 5.8.0"
#:package Nethereum.Util@5.8.0
#addin nuget:?package=Nethereum.Util&version=5.8.0
#tool nuget:?package=Nethereum.Util&version=5.8.0
Nethereum.Util
Core utilities for Ethereum development including Keccak-256 hashing, address checksum validation, and wei/ether unit conversions.
Overview
Nethereum.Util provides essential utility functions for Ethereum development. It includes the Keccak-256 (SHA-3) hashing implementation used throughout Ethereum, EIP-55 mixed-case checksum address handling, and comprehensive unit conversion between wei, gwei, ether, and other denominations.
Key Features
- Keccak-256 Hashing (SHA-3): Ethereum's primary cryptographic hash function
- Address Utilities: EIP-55 checksum address creation and validation
- Unit Conversion: Convert between wei, gwei, ether, and 20+ Ethereum unit denominations
- BigDecimal Support: High-precision decimal arithmetic for large value conversions
- Address Comparison: Case-insensitive address equality with checksum awareness
- Transaction Utilities: Helper methods for transaction handling
Installation
dotnet add package Nethereum.Util
Dependencies
- Nethereum.Hex - Hexadecimal encoding/decoding
- Nethereum.RLP - RLP (Recursive Length Prefix) encoding
Key Concepts
Keccak-256 (SHA-3)
Ethereum uses Keccak-256, the original SHA-3 submission before FIPS 202 standardization. This hash function is used for:
- Generating Ethereum addresses from public keys
- Creating function selectors for smart contracts
- Computing storage slot keys
- Generating message hashes for signing
EIP-55 Checksum Addresses
EIP-55 defines a backward-compatible mixed-case checksum format for Ethereum addresses:
- Uses Keccak-256 hash of the lowercase address
- Capitalizes hex digits at positions where the hash has a value ≥ 8
- Provides error detection without changing address format
- Example:
0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed
Unit Conversion
Ethereum uses wei as the smallest unit (10^-18 ether). Common denominations:
| Unit | Wei Value | Common Usage |
|---|---|---|
| Wei | 1 | Smart contract precision |
| Gwei | 10^9 | Gas prices |
| Ether | 10^18 | User-facing amounts |
The UnitConversion class handles conversions between 20+ denominations including wei, kwei, mwei, gwei, szabo, finney, ether, kether, and more.
Quick Start
using Nethereum.Util;
using System.Numerics;
// Keccak-256 hashing
var hasher = new Sha3Keccack();
string hash = hasher.CalculateHash("Hello, Ethereum!");
// Result: hex string of the keccak-256 hash
// Create checksum address
var addressUtil = new AddressUtil();
string checksumAddress = addressUtil.ConvertToChecksumAddress(
"0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed"
);
// Result: "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"
// Convert ether to wei
var conversion = new UnitConversion();
BigInteger weiAmount = conversion.ToWei(1.5m, UnitConversion.EthUnit.Ether);
// Result: 1500000000000000000 wei
// Convert wei to ether
decimal etherAmount = conversion.FromWei(
BigInteger.Parse("1500000000000000000"),
UnitConversion.EthUnit.Ether
);
// Result: 1.5 ether
Usage Examples
Example 1: Keccak-256 Hashing
using Nethereum.Util;
using Nethereum.Hex.HexConvertors.Extensions;
var keccak = new Sha3Keccack();
// Hash a string (UTF-8 encoded)
string textHash = keccak.CalculateHash("Ethereum");
Console.WriteLine($"Hash: 0x{textHash}");
// Hash byte array
byte[] data = new byte[] { 0x01, 0x02, 0x03 };
byte[] hashBytes = keccak.CalculateHash(data);
string hashHex = hashBytes.ToHex();
// Hash from hex values (useful for contract data)
string combinedHash = keccak.CalculateHashFromHex(
"0x1234",
"0x5678",
"0xabcd"
);
// Hashes the concatenation: 0x12345678abcd
// Get hash as bytes (for further processing)
byte[] hashAsBytes = keccak.CalculateHashAsBytes("test");
Example 2: EIP-55 Checksum Addresses
using Nethereum.Util;
var addressUtil = new AddressUtil();
// Create checksum address from lowercase
string address1 = "0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed";
string checksum1 = addressUtil.ConvertToChecksumAddress(address1);
// Result: "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"
// Create checksum address from uppercase
string address2 = "0xFB6916095CA1DF60BB79CE92CE3EA74C37C5D359";
string checksum2 = addressUtil.ConvertToChecksumAddress(address2);
// Result: "0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359"
// Verify if address is properly checksummed
bool isValid = addressUtil.IsChecksumAddress(
"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"
); // true
bool isInvalid = addressUtil.IsChecksumAddress(
"0x5aaeb6053F3E94C9b9A09f33669435E7Ef1BeAed" // wrong case
); // false
Example 3: Address Validation and Comparison
using Nethereum.Util;
var addressUtil = new AddressUtil();
// Validate address format (40 hex chars with 0x prefix)
bool valid = addressUtil.IsValidEthereumAddressHexFormat(
"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"
); // true
bool invalid = addressUtil.IsValidEthereumAddressHexFormat(
"0x5aAeb6053F3E" // too short
); // false
// Check address length
bool correctLength = addressUtil.IsValidAddressLength(
"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"
); // true
// Compare addresses (case-insensitive)
string addr1 = "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed";
string addr2 = "0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed";
bool same = addressUtil.AreAddressesTheSame(addr1, addr2); // true
// Using extension method
bool same2 = addr1.IsTheSameAddress(addr2); // true
Example 4: Empty Address Handling
using Nethereum.Util;
var addressUtil = new AddressUtil();
// Check if address is empty
bool isEmpty1 = addressUtil.IsAnEmptyAddress(null); // true
bool isEmpty2 = addressUtil.IsAnEmptyAddress(""); // true
bool isEmpty3 = addressUtil.IsAnEmptyAddress("0x0"); // true
bool isEmpty4 = addressUtil.IsAnEmptyAddress(" "); // true
// Get address or empty constant
string addr = null;
string result = addressUtil.AddressValueOrEmpty(addr);
// Result: "0x0" (AddressUtil.AddressEmptyAsHex)
// Check if not empty
bool notEmpty = addressUtil.IsNotAnEmptyAddress(
"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"
); // true
// Using extension methods
bool isEmpty = "0x0".IsAnEmptyAddress(); // true
bool notEmpty2 = "0x1234...".IsNotAnEmptyAddress(); // true
// Zero address constant
string zeroAddress = AddressUtil.ZERO_ADDRESS;
// "0x0000000000000000000000000000000000000000"
Example 5: Wei/Ether Conversions
From: Nethereum Playground Example 1014
using Nethereum.Util;
using System.Numerics;
var conversion = new UnitConversion();
// Convert ether to wei
BigInteger wei1 = conversion.ToWei(1m, UnitConversion.EthUnit.Ether);
// Result: 1000000000000000000
BigInteger wei2 = conversion.ToWei(0.001m, UnitConversion.EthUnit.Ether);
// Result: 1000000000000000 (0.001 ETH)
// Convert gwei to wei (for gas prices)
BigInteger gasWei = conversion.ToWei(
20,
UnitConversion.EthUnit.Gwei
);
// Result: 20000000000 (20 gwei)
// Convert wei to ether
decimal ether = conversion.FromWei(
BigInteger.Parse("1000000000000000000"),
UnitConversion.EthUnit.Ether
);
// Result: 1.0
// Convert wei to gwei
decimal gwei = conversion.FromWei(
BigInteger.Parse("20000000000"),
UnitConversion.EthUnit.Gwei
);
// Result: 20.0
// Using static accessor
BigInteger wei3 = UnitConversion.Convert.ToWei(
2.5m,
UnitConversion.EthUnit.Ether
);
// Result: 2500000000000000000
Example 6: High-Precision Conversions with BigDecimal
using Nethereum.Util;
using System.Numerics;
var conversion = new UnitConversion();
// Standard decimal has precision limits (29 digits)
// For very large or precise values, use BigDecimal
// Convert wei to BigDecimal (no precision loss)
BigDecimal precise = conversion.FromWeiToBigDecimal(
BigInteger.Parse("1111111111111111111111111111111"),
UnitConversion.EthUnit.Ether
);
// Result: 1111111111111.111111111111111111 (exact)
// Convert with more than 29 digits
BigDecimal veryLarge = conversion.FromWeiToBigDecimal(
BigInteger.Parse("1111111111111111111111111111111111111111111111111"),
UnitConversion.EthUnit.Tether
);
// Maintains full precision
// Convert BigDecimal back to wei
BigDecimal amount = new BigDecimal(1) / new BigDecimal(3);
BigInteger weiFromBigDecimal = conversion.ToWei(
amount,
UnitConversion.EthUnit.Ether
);
// Result: 333333333333333333 (1/3 ETH in wei)
Example 7: Working with Different Units
using Nethereum.Util;
using System.Numerics;
var conversion = new UnitConversion();
// Finney (milliether) - 0.001 ETH
BigInteger finneyWei = conversion.ToWei(
100,
UnitConversion.EthUnit.Finney
);
// Result: 100000000000000000 (0.1 ETH)
// Szabo (microether) - 0.000001 ETH
BigInteger szaboWei = conversion.ToWei(
1000000,
UnitConversion.EthUnit.Szabo
);
// Result: 1000000000000 (0.001 ETH)
// Kether (grand) - 1000 ETH
BigInteger ketherWei = conversion.ToWei(
1,
UnitConversion.EthUnit.Kether
);
// Result: 1000000000000000000000
// Convert using custom decimal places
BigInteger customWei = conversion.ToWei(
100m,
6 // USDC has 6 decimal places
);
// Result: 100000000
// Convert from custom decimal places
decimal customAmount = conversion.FromWei(
BigInteger.Parse("100000000"),
6 // USDC decimals
);
// Result: 100.0
Example 8: Unique Address Collections
using Nethereum.Util;
// UniqueAddressList uses case-insensitive address comparison
var addresses = new UniqueAddressList();
addresses.Add("0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed");
addresses.Add("0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed"); // Same address, different case
Console.WriteLine(addresses.Count); // 1 (duplicates ignored)
// Check if contains (case-insensitive)
bool contains = addresses.Contains(
"0x5AAEB6053F3E94C9B9A09F33669435E7EF1BEAED"
); // true
// Custom equality comparer for address dictionaries
var addressComparer = new AddressEqualityComparer();
var dict = new Dictionary<string, int>(addressComparer);
dict["0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"] = 100;
dict["0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed"] = 200; // Overwrites
Console.WriteLine(dict.Count); // 1
Example 9: Address Conversion and Padding
using Nethereum.Util;
var addressUtil = new AddressUtil();
// Convert short address to valid 20-byte address (pad with zeros)
string shortAddr = "0x1234";
string paddedAddr = addressUtil.ConvertToValid20ByteAddress(shortAddr);
// Result: "0x0000000000000000000000000000000000001234"
// Handle null addresses
string nullAddr = null;
string paddedNull = addressUtil.ConvertToValid20ByteAddress(nullAddr);
// Result: "0x0000000000000000000000000000000000000000"
// Convert byte array to checksum address
byte[] addressBytes = new byte[20] {
0x5a, 0xAe, 0xb6, 0x05, 0x3F, 0x3E, 0x94, 0xC9,
0xb9, 0xA0, 0x9f, 0x33, 0x66, 0x94, 0x35, 0xE7,
0xEf, 0x1B, 0xeA, 0xed
};
string checksumFromBytes = addressUtil.ConvertToChecksumAddress(addressBytes);
// Result: "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"
// Handles addresses longer than 20 bytes (takes last 20)
byte[] longAddress = new byte[32]; // e.g., from uint256 in Solidity
// ... populate longAddress ...
string fromLong = addressUtil.ConvertToChecksumAddress(longAddress);
// Uses last 20 bytes
API Reference
Sha3Keccack
Keccak-256 hashing implementation.
public class Sha3Keccack
{
public static Sha3Keccack Current { get; }
// Hash string (UTF-8)
public string CalculateHash(string value);
public byte[] CalculateHashAsBytes(string value);
// Hash bytes
public byte[] CalculateHash(byte[] value);
// Hash concatenated hex values
public string CalculateHashFromHex(params string[] hexValues);
}
AddressUtil
Ethereum address utilities and validation.
public class AddressUtil
{
public static AddressUtil Current { get; }
public const string AddressEmptyAsHex = "0x0";
public const string ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
// Checksum address creation
public string ConvertToChecksumAddress(string address);
public string ConvertToChecksumAddress(byte[] address);
// Validation
public bool IsValidEthereumAddressHexFormat(string address);
public bool IsValidAddressLength(string address);
public bool IsChecksumAddress(string address);
// Empty address checks
public bool IsAnEmptyAddress(string address);
public bool IsNotAnEmptyAddress(string address);
public string AddressValueOrEmpty(string address);
// Comparison
public bool AreAddressesTheSame(string address1, string address2);
public bool IsEmptyOrEqualsAddress(string address1, string candidate);
// Conversion
public string ConvertToValid20ByteAddress(string address);
}
UnitConversion
Convert between wei and various Ethereum denominations.
public class UnitConversion
{
public static UnitConversion Convert { get; }
public enum EthUnit
{
Wei, Kwei, Mwei, Gwei, Szabo, Finney, Ether,
Kether, Mether, Gether, Tether, /* and more */
}
// To Wei
public BigInteger ToWei(decimal amount, EthUnit fromUnit = EthUnit.Ether);
public BigInteger ToWei(BigDecimal amount, EthUnit fromUnit = EthUnit.Ether);
public BigInteger ToWei(decimal amount, int decimalPlacesFromUnit);
public BigInteger ToWeiFromUnit(BigDecimal amount, BigInteger fromUnit);
// From Wei (returns decimal, may lose precision > 29 digits)
public decimal FromWei(BigInteger value, EthUnit toUnit = EthUnit.Ether);
public decimal FromWei(BigInteger value, int decimalPlacesToUnit);
public decimal FromWei(BigInteger value, BigInteger toUnit);
// From Wei to BigDecimal (no precision loss)
public BigDecimal FromWeiToBigDecimal(BigInteger value, EthUnit toUnit = EthUnit.Ether);
public BigDecimal FromWeiToBigDecimal(BigInteger value, int decimalPlacesToUnit);
public BigDecimal FromWeiToBigDecimal(BigInteger value, BigInteger toUnit);
// Unit value helpers
public BigInteger GetEthUnitValue(EthUnit ethUnit);
public bool TryValidateUnitValue(BigInteger ethUnit);
}
Extension Methods
AddressExtensions
public static class AddressExtensions
{
// Address validation
public static bool IsValidEthereumAddressHexFormat(this string address);
public static bool IsChecksumAddress(this string address);
// Empty checks
public static bool IsAnEmptyAddress(this string address);
public static bool IsNotAnEmptyAddress(this string address);
public static string AddressValueOrEmpty(this string address);
// Comparison
public static bool IsTheSameAddress(this string address1, string address2);
// Conversion
public static string ConvertToEthereumChecksumAddress(this string address);
public static string ConvertToValid20ByteAddress(this string address);
}
BigDecimal
High-precision decimal arithmetic for large value conversions.
public class BigDecimal
{
public BigDecimal(BigInteger mantissa, int exponent);
public BigInteger Mantissa { get; }
public int Exponent { get; }
// Arithmetic operators
public static BigDecimal operator +(BigDecimal left, BigDecimal right);
public static BigDecimal operator -(BigDecimal left, BigDecimal right);
public static BigDecimal operator *(BigDecimal left, BigDecimal right);
public static BigDecimal operator /(BigDecimal left, BigDecimal right);
// Conversions
public static explicit operator decimal(BigDecimal value);
public static implicit operator BigDecimal(decimal value);
public BigInteger FloorToBigInteger();
}
Additional Utilities
DateTimeHelper
public static class DateTimeHelper
{
public static DateTime UnixTimeStampToDateTime(ulong unixTimeStamp);
public static ulong GetUnixTimeStampSeconds(DateTime dateTime);
}
ByteUtil
public static class ByteUtil
{
public static byte[] Merge(params byte[][] arrays);
public static bool AreEqual(byte[] a, byte[] b);
}
Related Packages
Used By (Consumers)
Almost all Nethereum packages depend on Nethereum.Util:
- Nethereum.Signer - Uses Keccak for signing and address derivation
- Nethereum.RPC - Uses unit conversion for transaction values
- Nethereum.Contracts - Uses address validation and hashing
- Nethereum.Accounts - Uses address utilities and checksums
- Nethereum.Web3 - Uses all utility functions throughout
- Nethereum.ABI - Uses Keccak for function selector generation
Dependencies
- Nethereum.Hex - Hexadecimal encoding/decoding
- Nethereum.RLP - RLP encoding (for some utilities)
Important Notes
Decimal Precision Limits
When converting from wei to decimal using FromWei(), C# decimal type has a 29-digit limit. Values with more than 29 significant digits will be rounded:
// This rounds the least significant digits
decimal rounded = conversion.FromWei(
BigInteger.Parse("111111111111111111111111111111"), // 30 digits
18
);
// Use FromWeiToBigDecimal() for exact precision
For values requiring more than 29 digits of precision, use FromWeiToBigDecimal() which returns BigDecimal instead.
Keccak vs SHA3
Ethereum uses Keccak-256, which is different from the final NIST SHA-3 standard (FIPS 202). Do not use standard SHA-3 libraries for Ethereum - always use Nethereum's Sha3Keccack class.
Address Comparison Performance
Address comparison is case-insensitive and uses string comparison (not BigInteger). This is optimized for performance while maintaining correctness:
// Fast: string comparison
bool same = address1.IsTheSameAddress(address2);
// Both handle mixed-case addresses correctly
Unit Validation
Unit values must be powers of 10. The library validates this:
conversion.ToWeiFromUnit(100m, new BigInteger(10)); // OK
conversion.ToWeiFromUnit(100m, new BigInteger(7)); // Throws Exception
Additional Resources
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. 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 is compatible. 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 is compatible. 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 was computed. 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. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net451 is compatible. net452 was computed. net46 was computed. net461 is compatible. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETFramework 4.5.1
- Nethereum.Hex (>= 5.8.0)
- Nethereum.RLP (>= 5.8.0)
- Newtonsoft.Json (>= 11.0.2 && < 14.0.0)
-
.NETFramework 4.6.1
- Nethereum.Hex (>= 5.8.0)
- Nethereum.RLP (>= 5.8.0)
- Newtonsoft.Json (>= 11.0.2 && < 14.0.0)
-
.NETStandard 2.0
- Nethereum.Hex (>= 5.8.0)
- Nethereum.RLP (>= 5.8.0)
- NETStandard.Library (>= 2.0.3)
- Newtonsoft.Json (>= 11.0.2 && < 14.0.0)
-
net6.0
- Nethereum.Hex (>= 5.8.0)
- Nethereum.RLP (>= 5.8.0)
- Newtonsoft.Json (>= 11.0.2 && < 14.0.0)
-
net8.0
- Nethereum.Hex (>= 5.8.0)
- Nethereum.RLP (>= 5.8.0)
- Newtonsoft.Json (>= 11.0.2 && < 14.0.0)
-
net9.0
- Nethereum.Hex (>= 5.8.0)
- Nethereum.RLP (>= 5.8.0)
- Newtonsoft.Json (>= 11.0.2 && < 14.0.0)
NuGet packages (56)
Showing the top 5 NuGet packages that depend on Nethereum.Util:
| Package | Downloads |
|---|---|
|
Nethereum.Signer
Nethereum signer library to sign and verify messages, RLP and transactions using an Ethereum account |
|
|
Nethereum.Model
Nethereum.Model Ethereum Core Model Class Library |
|
|
Nethereum.ABI
Encoding and decoding of ABI Types, functions, events of Ethereum contracts |
|
|
Nethereum.RPC
Nethereum.RPC Ethereum Core RPC Class Library to interact via RPC with an Ethereum client, for example geth. |
|
|
Nethereum.Web3
Nethereum.Web3 Ethereum Web3 Class Library to interact via RPC with an Ethereum client, for example geth. Including contract interaction, deployment, transaction, encoding / decoding and event filters |
GitHub repositories (2)
Showing the top 2 popular GitHub repositories that depend on Nethereum.Util:
| Repository | Stars |
|---|---|
|
yc-l/yc.boilerplate
YC. Boilerplate is a set of loose coupling, flexible combination, complete functions, convenient development, and reduces the workload of development.
|
|
|
biheBlockChain/MyLinkToken
开源链克口袋,玩客币钱包
|
| Version | Downloads | Last Updated |
|---|---|---|
| 5.8.0 | 3,359 | 1/6/2026 |
| 5.0.0 | 342,547 | 5/28/2025 |
| 4.29.0 | 386,740 | 2/10/2025 |
| 4.28.0 | 67,534 | 1/7/2025 |
| 4.27.1 | 14,526 | 12/24/2024 |
| 4.27.0 | 2,500 | 12/24/2024 |
| 4.26.0 | 158,862 | 10/1/2024 |
| 4.25.0 | 25,352 | 9/19/2024 |
| 4.21.4 | 108,584 | 8/9/2024 |
| 4.21.3 | 21,192 | 7/22/2024 |
| 4.21.2 | 100,499 | 6/26/2024 |
| 4.21.1 | 3,491 | 6/26/2024 |
| 4.21.0 | 15,337 | 6/18/2024 |
| 4.20.0 | 396,322 | 3/28/2024 |
| 4.19.0 | 101,802 | 2/16/2024 |
| 4.18.0 | 326,020 | 11/21/2023 |
| 4.17.1 | 185,877 | 9/28/2023 |
| 4.17.0 | 18,740 | 9/27/2023 |
| 4.16.0 | 127,853 | 8/14/2023 |
| 4.15.2 | 136,477 | 7/11/2023 |
| 4.15.1 | 5,551 | 7/11/2023 |
| 4.15.0 | 5,999 | 7/11/2023 |
| 4.14.0 | 252,627 | 3/19/2023 |
| 4.13.0 | 148,084 | 2/18/2023 |
| 4.12.0 | 284,978 | 12/9/2022 |
| 4.11.0 | 265,428 | 10/27/2022 |
| 4.9.0 | 260,640 | 9/27/2022 |
| 4.8.0 | 230,630 | 8/24/2022 |
| 4.7.0 | 224,261 | 7/20/2022 |
| 4.6.1 | 146,969 | 6/18/2022 |
| 4.6.0 | 13,216 | 6/16/2022 |
| 4.5.0 | 442,972 | 5/13/2022 |
| 4.4.1 | 124,377 | 4/27/2022 |
| 4.4.0 | 17,396 | 4/27/2022 |
| 4.3.0 | 84,155 | 4/12/2022 |
| 4.2.0 | 193,084 | 2/18/2022 |
| 4.1.1 | 601,336 | 11/4/2021 |
| 4.1.0 | 33,782 | 10/15/2021 |
| 4.0.5 | 160,354 | 8/12/2021 |
| 4.0.4 | 10,230 | 8/10/2021 |
| 4.0.3 | 28,605 | 8/8/2021 |
| 4.0.2 | 9,363 | 8/5/2021 |
| 4.0.1 | 16,899 | 7/28/2021 |
| 4.0.0 | 22,875 | 7/26/2021 |
| 3.8.0 | 446,976 | 7/3/2020 |
| 3.7.1 | 129,800 | 2/13/2020 |
| 3.7.0 | 11,754 | 2/13/2020 |
| 3.6.0 | 35,807 | 1/27/2020 |
| 3.5.0 | 27,539 | 12/31/2019 |
| 3.4.0 | 160,411 | 7/29/2019 |
| 3.3.0 | 87,789 | 4/23/2019 |
| 3.2.0 | 54,884 | 4/8/2019 |
| 3.1.2 | 25,243 | 3/13/2019 |
| 3.1.1 | 7,433 | 3/12/2019 |
| 3.1.0 | 28,389 | 3/12/2019 |
| 3.0.0 | 193,952 | 11/28/2018 |
| 3.0.0-rc3 | 6,563 | 10/25/2018 |
| 3.0.0-rc2 | 4,262 | 10/24/2018 |
| 3.0.0-rc1 | 10,762 | 7/25/2018 |
| 2.5.1 | 194,186 | 6/5/2018 |
| 2.5.0 | 6,732 | 6/4/2018 |
| 2.4.0 | 58,378 | 3/11/2018 |
| 2.3.1 | 8,531 | 3/7/2018 |
| 2.3.0 | 6,846 | 3/6/2018 |
| 2.2.3 | 22,049 | 12/16/2017 |
| 2.2.2 | 6,697 | 12/16/2017 |
| 2.2.0 | 6,814 | 12/8/2017 |
| 2.1.0 | 14,004 | 10/23/2017 |
| 2.0.1 | 6,686 | 10/4/2017 |
| 2.0.0 | 17,476 | 9/26/2017 |
| 2.0.0-rc7 | 4,446 | 8/17/2017 |
| 2.0.0-rc6-2 | 4,088 | 7/29/2017 |
| 2.0.0-rc6.1 | 1,229 | 7/26/2017 |
| 2.0.0-rc5 | 4,100 | 6/19/2017 |
| 2.0.0-rc4 | 4,082 | 6/6/2017 |
| 2.0.0-rc3 | 3,730 | 4/11/2017 |
| 2.0.0-rc2-fix | 4,057 | 4/6/2017 |
| 2.0.0-rc2 | 1,335 | 4/5/2017 |
| 2.0.0-rc1 | 3,706 | 2/8/2017 |