diff --git a/README.md b/README.md index 58210d2..978012c 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ In addition to static vs dynamic typing, C# and Python have very different conve - Parameter names are `camelCased`. - The chia RPC uses unsigned integers where dotnet might use signed. In cases where chia expects an unsigned number, it is unsigned on the dotnet side. - `ulong` is used for the python 64 bit unsigned int. -- `BigInteger` is used for the python 128 bit unsigned int. +- `System.UInt128` is used for the python 128 bit unsigned int. - Where the RPC return a scalar value, the dotnet code will as well. If it is optional in python it will be `Nullable<T>` in dotnet - Where the RPC returns a list of named scalar values, they are returned as a Tuple with named fields. - Lists of things are returned as [`IEnumberable<T>`](https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.ienumerable-1?view=net-5.0). diff --git a/src/chia-dotnet.tests/chia-dotnet.tests.csproj b/src/chia-dotnet.tests/chia-dotnet.tests.csproj index 2e6d9ee..88f43c5 100644 --- a/src/chia-dotnet.tests/chia-dotnet.tests.csproj +++ b/src/chia-dotnet.tests/chia-dotnet.tests.csproj @@ -1,7 +1,7 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> - <TargetFramework>net7.0</TargetFramework> + <TargetFramework>net8.0</TargetFramework> <IsPackable>false</IsPackable> <RootNamespace>chia.dotnet.tests</RootNamespace> <UserSecretsId>chia.dotnet.tests</UserSecretsId> diff --git a/src/chia-dotnet/CATWallet.cs b/src/chia-dotnet/CATWallet.cs index e89b4dd..176590d 100644 --- a/src/chia-dotnet/CATWallet.cs +++ b/src/chia-dotnet/CATWallet.cs @@ -9,17 +9,13 @@ namespace chia.dotnet /// <summary> /// Wraps a CAT wallet /// </summary> - public sealed class CATWallet : Wallet + /// <remarks> + /// ctor + /// </remarks> + /// <param name="walletId">The wallet_id to wrap</param> + /// <param name="walletProxy">Wallet RPC proxy to use for communication</param> + public sealed class CATWallet(uint walletId, WalletProxy walletProxy) : Wallet(walletId, walletProxy) { - /// <summary> - /// ctor - /// </summary> - /// <param name="walletId">The wallet_id to wrap</param> - /// <param name="walletProxy">Wallet RPC proxy to use for communication</param> - public CATWallet(uint walletId, WalletProxy walletProxy) - : base(walletId, walletProxy) - { - } /// <summary> /// Validates that <see cref="Wallet.WalletId"/> is a <see cref="WalletType.CAT"/> diff --git a/src/chia-dotnet/CRCATWallet.cs b/src/chia-dotnet/CRCATWallet.cs index 4bde132..8fb0208 100644 --- a/src/chia-dotnet/CRCATWallet.cs +++ b/src/chia-dotnet/CRCATWallet.cs @@ -7,17 +7,13 @@ namespace chia.dotnet /// <summary> /// Wraps a CRCAT Wallet /// </summary> - public sealed class CRCATWallet : Wallet + /// <remarks> + /// ctor + /// </remarks> + /// <param name="walletId">The wallet_id to wrap</param> + /// <param name="walletProxy">Wallet RPC proxy to use for communication</param> + public sealed class CRCATWallet(uint walletId, WalletProxy walletProxy) : Wallet(walletId, walletProxy) { - /// <summary> - /// ctor - /// </summary> - /// <param name="walletId">The wallet_id to wrap</param> - /// <param name="walletProxy">Wallet RPC proxy to use for communication</param> - public CRCATWallet(uint walletId, WalletProxy walletProxy) - : base(walletId, walletProxy) - { - } /// <summary> /// Validates that <see cref="Wallet.WalletId"/> is a <see cref="WalletType.CRCAT"/> diff --git a/src/chia-dotnet/ChiaTypes/Announcement.cs b/src/chia-dotnet/ChiaTypes/Announcement.cs index 91fe0a4..e7b4c02 100644 --- a/src/chia-dotnet/ChiaTypes/Announcement.cs +++ b/src/chia-dotnet/ChiaTypes/Announcement.cs @@ -4,6 +4,6 @@ public record Announcement { public string OriginInfo { get; init; } = string.Empty; public string Message { get; init; } = string.Empty; - public string MorphBytes { get; init; } = string.Empty; + public string? MorphBytes { get; init; } } } diff --git a/src/chia-dotnet/ChiaTypes/AutoClaimSettings.cs b/src/chia-dotnet/ChiaTypes/AutoClaimSettings.cs index f9aecf0..0d16b82 100644 --- a/src/chia-dotnet/ChiaTypes/AutoClaimSettings.cs +++ b/src/chia-dotnet/ChiaTypes/AutoClaimSettings.cs @@ -5,6 +5,6 @@ public record AutoClaimSettings public bool Enabled { get; init; } public ulong TxFee { get; init; } public ulong MinAmount { get; init; } - public ushort BatchSize { get; init; } + public ushort BatchSize { get; init; } = 50; } } diff --git a/src/chia-dotnet/ChiaTypes/BlockRecord.cs b/src/chia-dotnet/ChiaTypes/BlockRecord.cs index f808916..dbfaa2d 100644 --- a/src/chia-dotnet/ChiaTypes/BlockRecord.cs +++ b/src/chia-dotnet/ChiaTypes/BlockRecord.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Numerics; using Newtonsoft.Json; @@ -91,11 +90,11 @@ public record BlockRecord /// <summary> /// Total number of VDF iterations since genesis, including this block /// </summary> - public BigInteger TotalIters { get; init; } + public UInt128 TotalIters { get; init; } /// <summary> /// Total cumulative difficulty of all ancestor blocks since genesis /// </summary> - public BigInteger Weight { get; init; } + public UInt128 Weight { get; init; } [JsonIgnore] public DateTime? DateTimestamp => Timestamp.ToDateTime(); [JsonIgnore] diff --git a/src/chia-dotnet/ChiaTypes/BlockSpendWithConditions.cs b/src/chia-dotnet/ChiaTypes/BlockSpendWithConditions.cs index a813367..5b15e7d 100644 --- a/src/chia-dotnet/ChiaTypes/BlockSpendWithConditions.cs +++ b/src/chia-dotnet/ChiaTypes/BlockSpendWithConditions.cs @@ -5,6 +5,6 @@ namespace chia.dotnet public record BlockSpendWithConditions { public CoinSpend CoinSpend { get; init; } = new(); - public IEnumerable<ConditionWithArgs> Conditions { get; init; } = new List<ConditionWithArgs>(); + public IEnumerable<ConditionWithVars> Conditions { get; init; } = new List<ConditionWithVars>(); } } diff --git a/src/chia-dotnet/ChiaTypes/BlockchainState.cs b/src/chia-dotnet/ChiaTypes/BlockchainState.cs index 15848fc..730ecb9 100644 --- a/src/chia-dotnet/ChiaTypes/BlockchainState.cs +++ b/src/chia-dotnet/ChiaTypes/BlockchainState.cs @@ -1,6 +1,4 @@ -using System.Numerics; - -namespace chia.dotnet +namespace chia.dotnet { /// <summary> /// The node's view of the blockchain. @@ -17,7 +15,7 @@ public record BlockchainState public long MempoolMaxTotalCost { get; init; } public long BlockMaxCost { get; init; } public BlockRecord? Peak { get; init; } - public BigInteger Space { get; init; } + public System.UInt128 Space { get; init; } public ulong SubSlotIters { get; init; } public SyncState Sync { get; init; } = new(); public uint AverageBlockTime { get; init; } diff --git a/src/chia-dotnet/ChiaTypes/Coin.cs b/src/chia-dotnet/ChiaTypes/Coin.cs index 9a04af8..addc122 100644 --- a/src/chia-dotnet/ChiaTypes/Coin.cs +++ b/src/chia-dotnet/ChiaTypes/Coin.cs @@ -10,7 +10,7 @@ public record Coin { public string ParentCoinInfo { get; init; } = string.Empty; public string PuzzleHash { get; init; } = string.Empty; - public ulong Amount { get; init; } + public System.UInt128 Amount { get; init; } /// <summary> /// The <see cref="Amount"/> as a hex string diff --git a/src/chia-dotnet/ChiaTypes/CoinAnnouncement.cs b/src/chia-dotnet/ChiaTypes/CoinAnnouncement.cs index 8515a99..d3a644a 100644 --- a/src/chia-dotnet/ChiaTypes/CoinAnnouncement.cs +++ b/src/chia-dotnet/ChiaTypes/CoinAnnouncement.cs @@ -4,6 +4,6 @@ public record CoinAnnouncement { public string CoinId { get; init; } = string.Empty; public string Message { get; init; } = string.Empty; - public string MorphBytes { get; init; } = string.Empty; + public string? MorphBytes { get; init; } } } diff --git a/src/chia-dotnet/ChiaTypes/Condition.cs b/src/chia-dotnet/ChiaTypes/Condition.cs index 8860dc7..e5885c4 100644 --- a/src/chia-dotnet/ChiaTypes/Condition.cs +++ b/src/chia-dotnet/ChiaTypes/Condition.cs @@ -14,6 +14,6 @@ namespace chia.dotnet public record Condition { public string ConditionOpcode { get; init; } = string.Empty; - public IEnumerable<ConditionWithArgs> Args { get; init; } = new List<ConditionWithArgs>(); + public IEnumerable<ConditionWithVars> Args { get; init; } = new List<ConditionWithVars>(); } } diff --git a/src/chia-dotnet/ChiaTypes/ConditionConverter.cs b/src/chia-dotnet/ChiaTypes/ConditionConverter.cs index 2563e9c..36d41ab 100644 --- a/src/chia-dotnet/ChiaTypes/ConditionConverter.cs +++ b/src/chia-dotnet/ChiaTypes/ConditionConverter.cs @@ -16,13 +16,13 @@ internal sealed class ConditionConverter : JsonConverter<Condition> var opcode = reader.ReadAsString(); // the opcode is stored without a name (as part of an unnamed tuple (aka array in json)) _ = reader.Read(); // move ahead to the start of the collection - var args = serializer.Deserialize<IEnumerable<ConditionWithArgs>>(reader); + var args = serializer.Deserialize<IEnumerable<ConditionWithVars>>(reader); _ = reader.Read(); return new Condition() { ConditionOpcode = opcode ?? string.Empty, - Args = args ?? new List<ConditionWithArgs>() + Args = args ?? new List<ConditionWithVars>() }; } diff --git a/src/chia-dotnet/ChiaTypes/ConditionValidTimes.cs b/src/chia-dotnet/ChiaTypes/ConditionValidTimes.cs new file mode 100644 index 0000000..559fc9d --- /dev/null +++ b/src/chia-dotnet/ChiaTypes/ConditionValidTimes.cs @@ -0,0 +1,14 @@ +namespace chia.dotnet +{ + public record ConditionValidTimes + { + public ulong? MinSecsSinceCreated { get; init; } + public ulong? MinTime { get; init; } + public ulong? MinBlocksSinceCreated { get; init; } + public uint? MinHeight { get; init; } + public ulong? MaxSecAfterCreated { get; init; } + public ulong? MaxTime { get; init; } + public uint? MaxBlocksAfterCreated { get; init; } + public uint? MaxHeight { get; init; } + } +} diff --git a/src/chia-dotnet/ChiaTypes/ConditionWithArgs.cs b/src/chia-dotnet/ChiaTypes/ConditionWithVars.cs similarity index 91% rename from src/chia-dotnet/ChiaTypes/ConditionWithArgs.cs rename to src/chia-dotnet/ChiaTypes/ConditionWithVars.cs index 7d02fa6..9113838 100644 --- a/src/chia-dotnet/ChiaTypes/ConditionWithArgs.cs +++ b/src/chia-dotnet/ChiaTypes/ConditionWithVars.cs @@ -6,7 +6,7 @@ namespace chia.dotnet /// This structure is used to store parsed CLVM conditions /// Conditions in CLVM have either format of(opcode, var1) or(opcode, var1, var2) /// </summary> - public record ConditionWithArgs + public record ConditionWithVars { public ushort Opcode { get; init; } public IEnumerable<string> Vars { get; init; } = new List<string>(); diff --git a/src/chia-dotnet/ChiaTypes/PuzzleAnnouncement.cs b/src/chia-dotnet/ChiaTypes/PuzzleAnnouncement.cs index eec1d74..c9c53a9 100644 --- a/src/chia-dotnet/ChiaTypes/PuzzleAnnouncement.cs +++ b/src/chia-dotnet/ChiaTypes/PuzzleAnnouncement.cs @@ -4,6 +4,6 @@ public record PuzzleAnnouncement { public string PuzzleHash { get; init; } = string.Empty; public string Message { get; init; } = string.Empty; - public string MorphBytes { get; init; } = string.Empty; + public string? MorphBytes { get; init; } } } diff --git a/src/chia-dotnet/ChiaTypes/RewardChainBlock.cs b/src/chia-dotnet/ChiaTypes/RewardChainBlock.cs index 2cfe1a1..4efd561 100644 --- a/src/chia-dotnet/ChiaTypes/RewardChainBlock.cs +++ b/src/chia-dotnet/ChiaTypes/RewardChainBlock.cs @@ -1,12 +1,10 @@ -using System.Numerics; - -namespace chia.dotnet +namespace chia.dotnet { public record RewardChainBlock { - public BigInteger Weight { get; init; } + public System.UInt128 Weight { get; init; } public uint Height { get; init; } - public BigInteger TotalIters { get; init; } + public System.UInt128 TotalIters { get; init; } public byte SignagePointIndex { get; init; } public string PosSsCcChallengeHash { get; init; } = string.Empty; public ProofOfSpace ProofOfSpace { get; init; } = new(); diff --git a/src/chia-dotnet/ChiaTypes/RewardChainBlockUnfinished.cs b/src/chia-dotnet/ChiaTypes/RewardChainBlockUnfinished.cs index cce22bc..160086e 100644 --- a/src/chia-dotnet/ChiaTypes/RewardChainBlockUnfinished.cs +++ b/src/chia-dotnet/ChiaTypes/RewardChainBlockUnfinished.cs @@ -1,10 +1,8 @@ -using System.Numerics; - -namespace chia.dotnet +namespace chia.dotnet { public record RewardChainBlockUnfinished { - public BigInteger TotalIters { get; init; } + public System.UInt128 TotalIters { get; init; } public byte SignagePointIndex { get; init; } public string PosSsCcChallengeHash { get; init; } = string.Empty; public ProofOfSpace ProofOfSpace { get; init; } = new(); diff --git a/src/chia-dotnet/ChiaTypes/TransactionRecord.cs b/src/chia-dotnet/ChiaTypes/TransactionRecord.cs index 188b459..ad3f022 100644 --- a/src/chia-dotnet/ChiaTypes/TransactionRecord.cs +++ b/src/chia-dotnet/ChiaTypes/TransactionRecord.cs @@ -46,5 +46,6 @@ public record TransactionRecord public uint WalletId { get; init; } [JsonIgnore] public DateTime CreatedAtDateTime => CreatedAtTime.ToDateTime(); + public ConditionValidTimes ValidTimes { get; init; } = new(); } } diff --git a/src/chia-dotnet/ChiaTypes/TransactionTypeFilter.cs b/src/chia-dotnet/ChiaTypes/TransactionTypeFilter.cs index 849624b..e777b08 100644 --- a/src/chia-dotnet/ChiaTypes/TransactionTypeFilter.cs +++ b/src/chia-dotnet/ChiaTypes/TransactionTypeFilter.cs @@ -1,10 +1,11 @@ -namespace chia.dotnet +using System.Collections.Generic; + +namespace chia.dotnet { public record TransactionTypeFilter { - public string AssetId { get; init; } = string.Empty; - public string Name { get; init; } = string.Empty; - public uint FirstSeenHeight { get; init; } - public string SenderPuzzleHash { get; init; } = string.Empty; + public IEnumerable<byte> Values { get; init; } = new List<byte>(); + + public FilterMode Mode { get; init; } = FilterMode.Exlude; } } diff --git a/src/chia-dotnet/ChiaTypes/WalletBalance.cs b/src/chia-dotnet/ChiaTypes/WalletBalance.cs index a808c7a..17e353b 100644 --- a/src/chia-dotnet/ChiaTypes/WalletBalance.cs +++ b/src/chia-dotnet/ChiaTypes/WalletBalance.cs @@ -2,11 +2,11 @@ { public record WalletBalance { - public ulong ConfirmedWalletBalance { get; init; } - public ulong UnconfirmedWalletBalance { get; init; } - public ulong SpendableBalance { get; init; } - public ulong PendingChange { get; init; } - public ulong MaxSendAmount { get; init; } + public System.UInt128 ConfirmedWalletBalance { get; init; } + public System.UInt128 UnconfirmedWalletBalance { get; init; } + public System.UInt128 SpendableBalance { get; init; } + public System.UInt128 PendingChange { get; init; } + public System.UInt128 MaxSendAmount { get; init; } public int UnspentCoinCount { get; init; } public int PendingCoinRemovalCount { get; init; } public WalletType WalletType { get; init; } diff --git a/src/chia-dotnet/CrawlerProxy.cs b/src/chia-dotnet/CrawlerProxy.cs index 15af2ca..814f787 100644 --- a/src/chia-dotnet/CrawlerProxy.cs +++ b/src/chia-dotnet/CrawlerProxy.cs @@ -9,17 +9,13 @@ namespace chia.dotnet /// <summary> /// Proxy that communicates with the crawler /// </summary> - public sealed class CrawlerProxy : ServiceProxy + /// <remarks> + /// ctor + /// </remarks> + /// <param name="rpcClient"><see cref="IRpcClient"/> instance to use for rpc communication</param> + /// <param name="originService"><see cref="Message.Origin"/></param> + public sealed class CrawlerProxy(IRpcClient rpcClient, string originService) : ServiceProxy(rpcClient, ServiceNames.Crawler, originService) { - /// <summary> - /// ctor - /// </summary> - /// <param name="rpcClient"><see cref="IRpcClient"/> instance to use for rpc communication</param> - /// <param name="originService"><see cref="Message.Origin"/></param> - public CrawlerProxy(IRpcClient rpcClient, string originService) - : base(rpcClient, ServiceNames.Crawler, originService) - { - } /// <summary> /// Retrieves aggregate information about peers diff --git a/src/chia-dotnet/DAOWallet.cs b/src/chia-dotnet/DAOWallet.cs index 2f90d6d..933b1df 100644 --- a/src/chia-dotnet/DAOWallet.cs +++ b/src/chia-dotnet/DAOWallet.cs @@ -7,17 +7,13 @@ namespace chia.dotnet /// <summary> /// Wraps a DAO Wallet /// </summary> - public sealed class DAOWallet : Wallet + /// <remarks> + /// ctor + /// </remarks> + /// <param name="walletId">The wallet_id to wrap</param> + /// <param name="walletProxy">Wallet RPC proxy to use for communication</param> + public sealed class DAOWallet(uint walletId, WalletProxy walletProxy) : Wallet(walletId, walletProxy) { - /// <summary> - /// ctor - /// </summary> - /// <param name="walletId">The wallet_id to wrap</param> - /// <param name="walletProxy">Wallet RPC proxy to use for communication</param> - public DAOWallet(uint walletId, WalletProxy walletProxy) - : base(walletId, walletProxy) - { - } /// <summary> /// Validates that <see cref="Wallet.WalletId"/> is a <see cref="WalletType.DAO"/> @@ -106,7 +102,7 @@ public async Task<IDictionary<string, object>> ParseProposal(string proposalId, /// </summary> /// <param name="cancellationToken">A token to allow the call to be cancelled</param> /// <returns></returns> - public async Task<IDictionary<string, ulong>> GetTreasuryBalance(CancellationToken cancellationToken = default) + public async Task<IDictionary<string, System.UInt128>> GetTreasuryBalance(CancellationToken cancellationToken = default) { dynamic data = CreateWalletDataObject(); return await WalletProxy.SendMessage<IDictionary<string, ulong>>("dao_get_treasury_balance", data, cancellationToken).ConfigureAwait(false); diff --git a/src/chia-dotnet/DIDWallet.cs b/src/chia-dotnet/DIDWallet.cs index 5ec5a4d..02b7f10 100644 --- a/src/chia-dotnet/DIDWallet.cs +++ b/src/chia-dotnet/DIDWallet.cs @@ -9,17 +9,13 @@ namespace chia.dotnet /// <summary> /// Wraps a Distributed Identity Wallet /// </summary> - public sealed class DIDWallet : Wallet + /// <remarks> + /// ctor + /// </remarks> + /// <param name="walletId">The wallet_id to wrap</param> + /// <param name="walletProxy">Wallet RPC proxy to use for communication</param> + public sealed class DIDWallet(uint walletId, WalletProxy walletProxy) : Wallet(walletId, walletProxy) { - /// <summary> - /// ctor - /// </summary> - /// <param name="walletId">The wallet_id to wrap</param> - /// <param name="walletProxy">Wallet RPC proxy to use for communication</param> - public DIDWallet(uint walletId, WalletProxy walletProxy) - : base(walletId, walletProxy) - { - } /// <summary> /// Validates that <see cref="Wallet.WalletId"/> is a <see cref="WalletType.DISTRIBUTED_ID"/> @@ -40,10 +36,7 @@ public override async Task Validate(CancellationToken cancellationToken = defaul /// <returns>An awaitable <see cref="Task"/></returns> public async Task UpdateRecoveryIds(IEnumerable<string> newList, ulong? numVerificationsRequired = null, bool? reusePuzhash = null, CancellationToken cancellationToken = default) { - if (newList is null) - { - throw new ArgumentNullException(nameof(newList)); - } + ArgumentNullException.ThrowIfNull(newList); dynamic data = CreateWalletDataObject(); data.new_list = newList.ToList(); @@ -62,10 +55,7 @@ public async Task UpdateRecoveryIds(IEnumerable<string> newList, ulong? numVerif /// <returns>An awaitable <see cref="Task"/></returns> public async Task UpdateRecoveryIds(IEnumerable<string> newList, ulong numVerificationsRequired, CancellationToken cancellationToken = default) { - if (newList is null) - { - throw new ArgumentNullException(nameof(newList)); - } + ArgumentNullException.ThrowIfNull(newList); dynamic data = CreateWalletDataObject(); data.new_list = newList.ToList(); @@ -212,10 +202,7 @@ public async Task<SpendBundle> UpdateMetadata(string metadata, bool? reusePuzhas /// <returns>An awaitable <see cref="Task"/></returns> public async Task RecoverySpend(IEnumerable<string> attestData, string? pubkey, string? puzzlehash, CancellationToken cancellationToken = default) { - if (attestData is null) - { - throw new ArgumentNullException(nameof(attestData)); - } + ArgumentNullException.ThrowIfNull(attestData); dynamic data = CreateWalletDataObject(); data.attest_data = attestData.ToList(); diff --git a/src/chia-dotnet/DaemonProxy.cs b/src/chia-dotnet/DaemonProxy.cs index 24d63dc..95ca505 100644 --- a/src/chia-dotnet/DaemonProxy.cs +++ b/src/chia-dotnet/DaemonProxy.cs @@ -12,17 +12,13 @@ namespace chia.dotnet /// The daemon can be used to proxy messages to and from other chia services as well /// as controlling the <see cref="PlotterProxy"/> and having it's own procedures /// </summary> - public sealed class DaemonProxy : ServiceProxy + /// <remarks> + /// ctor + /// </remarks> + /// <param name="rpcClient"><see cref="IRpcClient"/> instance to use for rpc communication</param> + /// <param name="originService"><see cref="Message.Origin"/></param> + public sealed class DaemonProxy(WebSocketRpcClient rpcClient, string originService) : ServiceProxy(rpcClient, ServiceNames.Daemon, originService) { - /// <summary> - /// ctor - /// </summary> - /// <param name="rpcClient"><see cref="IRpcClient"/> instance to use for rpc communication</param> - /// <param name="originService"><see cref="Message.Origin"/></param> - public DaemonProxy(WebSocketRpcClient rpcClient, string originService) - : base(rpcClient, ServiceNames.Daemon, originService) - { - } /// <summary> /// Sends ping message to the service @@ -42,7 +38,7 @@ public async Task Ping(CancellationToken cancellationToken = default) /// <remarks>This only works for daemons because they can forward messages to other services through their <see cref="WebSocketRpcClient"/></remarks> public T CreateProxyFrom<T>() where T : ServiceProxy { - var constructor = typeof(T).GetConstructor(new Type[] { typeof(IRpcClient), typeof(string) }); + var constructor = typeof(T).GetConstructor([typeof(IRpcClient), typeof(string)]); return constructor is null || constructor.Invoke(new object[] { RpcClient, OriginService }) is not T proxy ? throw new InvalidOperationException($"Cannot create a {typeof(T).Name}") : proxy; diff --git a/src/chia-dotnet/DataLayerProxy.cs b/src/chia-dotnet/DataLayerProxy.cs index b1ce9bc..4482982 100644 --- a/src/chia-dotnet/DataLayerProxy.cs +++ b/src/chia-dotnet/DataLayerProxy.cs @@ -10,17 +10,13 @@ namespace chia.dotnet /// <summary> /// Proxy that communicates with the Data Layer /// </summary> - public sealed class DataLayerProxy : ServiceProxy + /// <remarks> + /// ctor + /// </remarks> + /// <param name="rpcClient"><see cref="IRpcClient"/> instance to use for rpc communication</param> + /// <param name="originService"><see cref="Message.Origin"/></param> + public sealed class DataLayerProxy(IRpcClient rpcClient, string originService) : ServiceProxy(rpcClient, ServiceNames.DataLayer, originService) { - /// <summary> - /// ctor - /// </summary> - /// <param name="rpcClient"><see cref="IRpcClient"/> instance to use for rpc communication</param> - /// <param name="originService"><see cref="Message.Origin"/></param> - public DataLayerProxy(IRpcClient rpcClient, string originService) - : base(rpcClient, ServiceNames.DataLayer, originService) - { - } /// <summary> /// Adds a mirror diff --git a/src/chia-dotnet/DataLayerWallet.cs b/src/chia-dotnet/DataLayerWallet.cs index ba3afc4..cb64b9f 100644 --- a/src/chia-dotnet/DataLayerWallet.cs +++ b/src/chia-dotnet/DataLayerWallet.cs @@ -9,17 +9,13 @@ namespace chia.dotnet /// <summary> /// Wraps a Data Layer Wallet /// </summary> - public sealed class DataLayerWallet : Wallet + /// <remarks> + /// ctor + /// </remarks> + /// <param name="walletId">The wallet_id to wrap</param> + /// <param name="walletProxy">Wallet RPC proxy to use for communication</param> + public sealed class DataLayerWallet(uint walletId, WalletProxy walletProxy) : Wallet(walletId, walletProxy) { - /// <summary> - /// ctor - /// </summary> - /// <param name="walletId">The wallet_id to wrap</param> - /// <param name="walletProxy">Wallet RPC proxy to use for communication</param> - public DataLayerWallet(uint walletId, WalletProxy walletProxy) - : base(walletId, walletProxy) - { - } /// <summary> /// Validates that <see cref="Wallet.WalletId"/> is a <see cref="WalletType.DATA_LAYER"/> diff --git a/src/chia-dotnet/Extensions.cs b/src/chia-dotnet/Extensions.cs index 231b23f..11f50e0 100644 --- a/src/chia-dotnet/Extensions.cs +++ b/src/chia-dotnet/Extensions.cs @@ -86,7 +86,7 @@ public static string AsChia(this ulong mojo, string? format, IFormatProvider? pr /// <remarks>Adapted from https://stackoverflow.com/questions/281640/how-do-i-get-a-human-readable-file-size-in-bytes-abbreviation-using-net </remarks> public static string ToBytesString(this BigInteger byteCount, string format = "N3") { - string[] suffixes = { "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "YiB" }; + string[] suffixes = ["B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "YiB"]; if (byteCount.IsZero) { return $"{0.0.ToString(format)} {suffixes[0]}"; @@ -104,6 +104,33 @@ public static string ToBytesString(this BigInteger byteCount, string format = "N return $"{num.ToString(format)} {suffixes[place]}"; } + /// <summary> + /// Format a number of bytes in human readable format + /// </summary> + /// <param name="byteCount">The number of bytes</param> + /// <param name="format">Return string culture format</param> + /// <returns>A human readable string</returns> + /// <remarks>Adapted from https://stackoverflow.com/questions/281640/how-do-i-get-a-human-readable-file-size-in-bytes-abbreviation-using-net </remarks> + public static string ToBytesString(this UInt128 byteCount, string format = "N3") + { + string[] suffixes = ["B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "YiB"]; + if (byteCount == 0) + { + return $"{0.0.ToString(format)} {suffixes[0]}"; + } + + var abs = BigInteger.Abs(byteCount); // in case byteCount is negative + var place = Convert.ToInt32(Math.Floor(BigInteger.Log(abs, 1024))); + var pow = Math.Pow(1024, place); + + // since we need to do this with integer math, get the quotient and remainder + var quotient = BigInteger.DivRem(abs, new BigInteger(pow), out var remainder); + // convert the remainder to a ratio and add both back together as doubles, putting the sign back + var num = UInt128.Sign(byteCount) * (Math.Floor((double)quotient) + ((double)remainder / pow)); + + return $"{num.ToString(format)} {suffixes[place]}"; + } + /// <summary> /// Format a number of bytes in human readable format /// </summary> @@ -113,7 +140,7 @@ public static string ToBytesString(this BigInteger byteCount, string format = "N /// <remarks>Adapted from https://stackoverflow.com/questions/281640/how-do-i-get-a-human-readable-file-size-in-bytes-abbreviation-using-net </remarks> public static string ToBytesString(this ulong byteCount, string format = "N3") { - string[] suffixes = { "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "YiB" }; + string[] suffixes = ["B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "YiB"]; if (byteCount == 0) { return $"{0.0.ToString(format)} {suffixes[0]}"; @@ -176,7 +203,7 @@ public static string ToBytesString(this long byteCount, string format = "N3") /// <returns>A human readable string</returns> public static string ToBytesString(this double byteCount, string format = "N3") { - string[] suffixes = { "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "YiB" }; + string[] suffixes = ["B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "YiB"]; if (byteCount == 0) { return $"{0.0.ToString(format)} {suffixes[0]}"; diff --git a/src/chia-dotnet/FarmerProxy.cs b/src/chia-dotnet/FarmerProxy.cs index f44aad2..a994844 100644 --- a/src/chia-dotnet/FarmerProxy.cs +++ b/src/chia-dotnet/FarmerProxy.cs @@ -10,17 +10,13 @@ namespace chia.dotnet /// <summary> /// Proxy that communicates with the farmer /// </summary> - public sealed class FarmerProxy : ServiceProxy + /// <remarks> + /// ctor + /// </remarks> + /// <param name="rpcClient"><see cref="IRpcClient"/> instance to use for rpc communication</param> + /// <param name="originService"><see cref="Message.Origin"/></param> + public sealed class FarmerProxy(IRpcClient rpcClient, string originService) : ServiceProxy(rpcClient, ServiceNames.Farmer, originService) { - /// <summary> - /// ctor - /// </summary> - /// <param name="rpcClient"><see cref="IRpcClient"/> instance to use for rpc communication</param> - /// <param name="originService"><see cref="Message.Origin"/></param> - public FarmerProxy(IRpcClient rpcClient, string originService) - : base(rpcClient, ServiceNames.Farmer, originService) - { - } /// <summary> /// Get the farm and pool reward targets @@ -56,7 +52,7 @@ public FarmerProxy(IRpcClient rpcClient, string originService) /// <returns>The farm and pool reward targets</returns> public async Task<(string FarmerTarget, string PoolTarget, bool HaveFarmerSk, bool HavePoolSk)> GetRewardTargetsIncludingPrivateKey(CancellationToken cancellationToken = default) { - return await GetRewardTargetsIncludingPrivateKey(cancellationToken: cancellationToken).ConfigureAwait(false); + return await GetRewardTargetsIncludingPrivateKey(500, cancellationToken: cancellationToken).ConfigureAwait(false); } /// <summary> diff --git a/src/chia-dotnet/FullNodeProxy.cs b/src/chia-dotnet/FullNodeProxy.cs index 247132a..c8d94a2 100644 --- a/src/chia-dotnet/FullNodeProxy.cs +++ b/src/chia-dotnet/FullNodeProxy.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Dynamic; using System.Linq; -using System.Numerics; using System.Threading; using System.Threading.Tasks; using Newtonsoft.Json; @@ -12,17 +11,13 @@ namespace chia.dotnet /// <summary> /// Proxy that communicates with the full node /// </summary> - public sealed class FullNodeProxy : ServiceProxy + /// <remarks> + /// ctor + /// </remarks> + /// <param name="rpcClient"><see cref="IRpcClient"/> instance to use for rpc communication</param> + /// <param name="originService"><see cref="Message.Origin"/></param> + public sealed class FullNodeProxy(IRpcClient rpcClient, string originService) : ServiceProxy(rpcClient, ServiceNames.FullNode, originService) { - /// <summary> - /// ctor - /// </summary> - /// <param name="rpcClient"><see cref="IRpcClient"/> instance to use for rpc communication</param> - /// <param name="originService"><see cref="Message.Origin"/></param> - public FullNodeProxy(IRpcClient rpcClient, string originService) - : base(rpcClient, ServiceNames.FullNode, originService) - { - } /// <summary> /// Will wait until <see cref="GetBlockchainState(CancellationToken)"/> indicates @@ -290,10 +285,7 @@ public async Task<IEnumerable<CoinRecord>> GetCoinRecordsByPuzzleHash(string puz /// <returns>A list of <see cref="CoinRecord"/>s</returns> public async Task<IEnumerable<CoinRecord>> GetCoinRecordsByNames(IEnumerable<string> names, bool includeSpentCoins, uint? startHeight = null, uint? endHeight = null, CancellationToken cancellationToken = default) { - if (names is null) - { - throw new ArgumentNullException(nameof(names)); - } + ArgumentNullException.ThrowIfNull(names); dynamic data = new ExpandoObject(); data.names = names.ToList(); @@ -315,10 +307,7 @@ public async Task<IEnumerable<CoinRecord>> GetCoinRecordsByNames(IEnumerable<str /// <returns>A list of <see cref="CoinRecord"/>s</returns> public async Task<IEnumerable<CoinRecord>> GetCoinRecordsByPuzzleHashes(IEnumerable<string> puzzlehashes, bool includeSpentCoins, uint? startHeight = null, uint? endHeight = null, CancellationToken cancellationToken = default) { - if (puzzlehashes is null) - { - throw new ArgumentNullException(nameof(puzzlehashes)); - } + ArgumentNullException.ThrowIfNull(puzzlehashes); dynamic data = new ExpandoObject(); data.puzzle_hashes = puzzlehashes.ToList(); @@ -341,10 +330,7 @@ public async Task<IEnumerable<CoinRecord>> GetCoinRecordsByPuzzleHashes(IEnumera /// <returns>A list of <see cref="CoinRecord"/>s</returns> public async Task<IEnumerable<CoinRecord>> GetCoinRecordsByParentIds(IEnumerable<string> parentIds, bool includeSpentCoins, uint? startHeight = null, uint? endHeight = null, CancellationToken cancellationToken = default) { - if (parentIds is null) - { - throw new ArgumentNullException(nameof(parentIds)); - } + ArgumentNullException.ThrowIfNull(parentIds); dynamic data = new ExpandoObject(); data.parent_ids = parentIds.ToList(); @@ -492,8 +478,8 @@ public async Task<IEnumerable<MempoolItem>> GetMemmpoolItemsByCoinName(string co /// <param name="newerBlockHeaderhash"></param> /// <param name="olderBlockHeaderhash"></param> /// <param name="cancellationToken">A token to allow the call to be cancelled</param> - /// <returns><see cref="BigInteger"/> of network space in bytes</returns> - public async Task<BigInteger> GetNetworkSpace(string newerBlockHeaderhash, string olderBlockHeaderhash, CancellationToken cancellationToken = default) + /// <returns><see cref="UInt128"/> of network space in bytes</returns> + public async Task<UInt128> GetNetworkSpace(string newerBlockHeaderhash, string olderBlockHeaderhash, CancellationToken cancellationToken = default) { if (string.IsNullOrEmpty(newerBlockHeaderhash)) { @@ -535,10 +521,7 @@ public async Task<BigInteger> GetNetworkSpace(string newerBlockHeaderhash, strin /// <returns>Indicator of whether the spend bundle was successfully included in the mempool</returns> public async Task<bool> PushTx(SpendBundle spendBundle, CancellationToken cancellationToken = default) { - if (spendBundle is null) - { - throw new ArgumentNullException(nameof(spendBundle)); - } + ArgumentNullException.ThrowIfNull(spendBundle); dynamic data = new ExpandoObject(); data.spend_bundle = spendBundle; diff --git a/src/chia-dotnet/HarvesterProxy.cs b/src/chia-dotnet/HarvesterProxy.cs index 0f119db..c770249 100644 --- a/src/chia-dotnet/HarvesterProxy.cs +++ b/src/chia-dotnet/HarvesterProxy.cs @@ -9,17 +9,13 @@ namespace chia.dotnet /// <summary> /// Proxy that communicates with the harvester /// </summary> - public sealed class HarvesterProxy : ServiceProxy + /// <remarks> + /// ctor + /// </remarks> + /// <param name="rpcClient"><see cref="IRpcClient"/> instance to use for rpc communication</param> + /// <param name="originService"><see cref="Message.Origin"/></param> + public sealed class HarvesterProxy(IRpcClient rpcClient, string originService) : ServiceProxy(rpcClient, ServiceNames.Harvester, originService) { - /// <summary> - /// ctor - /// </summary> - /// <param name="rpcClient"><see cref="IRpcClient"/> instance to use for rpc communication</param> - /// <param name="originService"><see cref="Message.Origin"/></param> - public HarvesterProxy(IRpcClient rpcClient, string originService) - : base(rpcClient, ServiceNames.Harvester, originService) - { - } /// <summary> /// Gets harvester configuration. diff --git a/src/chia-dotnet/NFTWallet.cs b/src/chia-dotnet/NFTWallet.cs index 5a20dde..3ab9a91 100644 --- a/src/chia-dotnet/NFTWallet.cs +++ b/src/chia-dotnet/NFTWallet.cs @@ -8,17 +8,13 @@ namespace chia.dotnet /// <summary> /// Wraps an NFT wallet /// </summary> - public sealed class NFTWallet : Wallet + /// <remarks> + /// ctor + /// </remarks> + /// <param name="walletId">The wallet_id to wrap</param> + /// <param name="walletProxy">Wallet RPC proxy to use for communication</param> + public sealed class NFTWallet(uint walletId, WalletProxy walletProxy) : Wallet(walletId, walletProxy) { - /// <summary> - /// ctor - /// </summary> - /// <param name="walletId">The wallet_id to wrap</param> - /// <param name="walletProxy">Wallet RPC proxy to use for communication</param> - public NFTWallet(uint walletId, WalletProxy walletProxy) - : base(walletId, walletProxy) - { - } /// <summary> /// Validates that <see cref="Wallet.WalletId"/> is a <see cref="WalletType.NFT"/> diff --git a/src/chia-dotnet/PlotterProxy.cs b/src/chia-dotnet/PlotterProxy.cs index f11d1cc..3fc3ab1 100644 --- a/src/chia-dotnet/PlotterProxy.cs +++ b/src/chia-dotnet/PlotterProxy.cs @@ -10,18 +10,14 @@ namespace chia.dotnet /// <summary> /// Class to manage plotting /// </summary> - public sealed class PlotterProxy : ServiceProxy + /// <remarks> + /// ctor + /// </remarks> + /// <param name="rpcClient"><see cref="IRpcClient"/> instance to use for rpc communication</param> + /// <param name="originService"><see cref="Message.Origin"/></param> + /// <remarks>The daemon endpoint handles plotting commands, so the rpc client has to us a websocket client and dameon endpoint</remarks> + public sealed class PlotterProxy(WebSocketRpcClient rpcClient, string originService) : ServiceProxy(rpcClient, ServiceNames.Daemon, originService) { - /// <summary> - /// ctor - /// </summary> - /// <param name="rpcClient"><see cref="IRpcClient"/> instance to use for rpc communication</param> - /// <param name="originService"><see cref="Message.Origin"/></param> - /// <remarks>The daemon endpoint handles plotting commands, so the rpc client has to us a websocket client and dameon endpoint</remarks> - public PlotterProxy(WebSocketRpcClient rpcClient, string originService) - : base(rpcClient, ServiceNames.Daemon, originService) - { - } /// <summary> /// Registers this instance as a plotter and retreives the plot queue @@ -44,10 +40,7 @@ public async Task<IEnumerable<QueuedPlotInfo>> RegisterPlotter(CancellationToken /// <returns>An awaitable <see cref="Task"/></returns> public async Task<IEnumerable<string>> StartPlotting(PlotterConfig config, CancellationToken cancellationToken = default) { - if (config == null) - { - throw new ArgumentNullException(nameof(config)); - } + ArgumentNullException.ThrowIfNull(config); dynamic data = config.PrepareForSerialization(); return await SendMessage<IEnumerable<string>>("start_plotting", data, "ids", cancellationToken).ConfigureAwait(false); diff --git a/src/chia-dotnet/PoolWallet.cs b/src/chia-dotnet/PoolWallet.cs index 9cd87b6..0135f4d 100644 --- a/src/chia-dotnet/PoolWallet.cs +++ b/src/chia-dotnet/PoolWallet.cs @@ -8,17 +8,13 @@ namespace chia.dotnet /// <summary> /// Wraps a Pool Wallet /// </summary> - public sealed class PoolWallet : Wallet + /// <remarks> + /// ctor + /// </remarks> + /// <param name="walletId">The wallet_id to wrap</param> + /// <param name="walletProxy">Wallet RPC proxy to use for communication</param> + public sealed class PoolWallet(uint walletId, WalletProxy walletProxy) : Wallet(walletId, walletProxy) { - /// <summary> - /// ctor - /// </summary> - /// <param name="walletId">The wallet_id to wrap</param> - /// <param name="walletProxy">Wallet RPC proxy to use for communication</param> - public PoolWallet(uint walletId, WalletProxy walletProxy) - : base(walletId, walletProxy) - { - } /// <summary> /// Validates that <see cref="Wallet.WalletId"/> is a <see cref="WalletType.POOLING_WALLET"/> diff --git a/src/chia-dotnet/ResponseException.cs b/src/chia-dotnet/ResponseException.cs index e6cba38..693c66a 100644 --- a/src/chia-dotnet/ResponseException.cs +++ b/src/chia-dotnet/ResponseException.cs @@ -6,7 +6,13 @@ namespace chia.dotnet /// Exception thrown when the RPC endpoint returns a response <see cref="Message"/> but Data.success is false /// oro there is a communication error on the websocket of http channgel /// </summary> - public sealed class ResponseException : Exception + /// <remarks> + /// ctor + /// </remarks> + /// <param name="request">The request sent to the service</param> + /// <param name="message"><see cref="Exception.Message"/></param> + /// <param name="innerException"><see cref="Exception.InnerException"/></param> + public sealed class ResponseException(Message request, string message, Exception? innerException) : Exception(message, innerException) { /// <summary> /// ctor @@ -27,21 +33,9 @@ public ResponseException(Message request, string message) { } - /// <summary> - /// ctor - /// </summary> - /// <param name="request">The request sent to the service</param> - /// <param name="message"><see cref="Exception.Message"/></param> - /// <param name="innerException"><see cref="Exception.InnerException"/></param> - public ResponseException(Message request, string message, Exception? innerException) - : base(message, innerException) - { - Request = request; - } - /// <summary> /// The request sent to the service /// </summary> - public Message Request { get; init; } + public Message Request { get; init; } = request; } } diff --git a/src/chia-dotnet/TradeManager.cs b/src/chia-dotnet/TradeManager.cs index 5413741..c48393d 100644 --- a/src/chia-dotnet/TradeManager.cs +++ b/src/chia-dotnet/TradeManager.cs @@ -10,14 +10,9 @@ namespace chia.dotnet /// <summary> /// API wrapper for those wallet RPC methods dealing with trades and offers /// </summary> - public sealed class TradeManager + public sealed class TradeManager(WalletProxy walletProxy) { - public WalletProxy WalletProxy { get; init; } - - public TradeManager(WalletProxy walletProxy) - { - WalletProxy = walletProxy ?? throw new ArgumentNullException(nameof(walletProxy)); - } + public WalletProxy WalletProxy { get; init; } = walletProxy ?? throw new ArgumentNullException(nameof(walletProxy)); /// <summary> /// Retrieves the number of offers. @@ -271,10 +266,7 @@ public async Task<OfferSummary> GetOfferSummary(string offer, bool advanced = fa /// <returns>An awaitable <see cref="Task"/></returns> public async Task<OfferRecord> CreateOffer(IDictionary<uint, long> walletIdsAndMojoAmounts, ulong minCoinAmount = 0, ulong maxCoinAmount = 0, bool validateOnly = false, IDictionary<string, string>? driver = null, IDictionary<string, string>? solver = null, bool? reusePuzhash = null, ulong fee = 0, CancellationToken cancellationToken = default) { - if (walletIdsAndMojoAmounts is null) - { - throw new ArgumentNullException(nameof(walletIdsAndMojoAmounts)); - } + ArgumentNullException.ThrowIfNull(walletIdsAndMojoAmounts); dynamic data = new ExpandoObject(); data.offer = walletIdsAndMojoAmounts; diff --git a/src/chia-dotnet/VerifiedCredentialManager.cs b/src/chia-dotnet/VerifiedCredentialManager.cs index 6024b83..ce52d86 100644 --- a/src/chia-dotnet/VerifiedCredentialManager.cs +++ b/src/chia-dotnet/VerifiedCredentialManager.cs @@ -9,14 +9,9 @@ namespace chia.dotnet /// <summary> /// API wrapper for those wallet RPC methods dealing with verified credentials /// </summary> - public sealed class VerifiedCredentialManager + public sealed class VerifiedCredentialManager(WalletProxy walletProxy) { - public WalletProxy WalletProxy { get; init; } - - public VerifiedCredentialManager(WalletProxy walletProxy) - { - WalletProxy = walletProxy ?? throw new ArgumentNullException(nameof(walletProxy)); - } + public WalletProxy WalletProxy { get; init; } = walletProxy ?? throw new ArgumentNullException(nameof(walletProxy)); /// <summary> /// Given a launcher ID get the verified credential. diff --git a/src/chia-dotnet/Wallet.cs b/src/chia-dotnet/Wallet.cs index 1842288..3c8deea 100644 --- a/src/chia-dotnet/Wallet.cs +++ b/src/chia-dotnet/Wallet.cs @@ -11,28 +11,23 @@ namespace chia.dotnet /// Base class representing a specific wallet (i.e. anything with a WalletID) /// </summary> /// <remarks>When not dervied from this represents a <see cref="WalletType.STANDARD_WALLET"/></remarks> - public class Wallet + /// <remarks> + /// ctor + /// </remarks> + /// <param name="walletId">The wallet_id to wrap</param> + /// <param name="walletProxy">Wallet RPC proxy to use for communication</param> + public class Wallet(uint walletId, WalletProxy walletProxy) { - /// <summary> - /// ctor - /// </summary> - /// <param name="walletId">The wallet_id to wrap</param> - /// <param name="walletProxy">Wallet RPC proxy to use for communication</param> - public Wallet(uint walletId, WalletProxy walletProxy) - { - WalletId = walletId; - WalletProxy = walletProxy ?? throw new ArgumentNullException(nameof(walletProxy)); - } /// <summary> /// The id of the wallet /// </summary> - public uint WalletId { get; init; } + public uint WalletId { get; init; } = walletId; /// <summary> /// Wallet RPC proxy for communication /// </summary> - public WalletProxy WalletProxy { get; init; } + public WalletProxy WalletProxy { get; init; } = walletProxy ?? throw new ArgumentNullException(nameof(walletProxy)); /// <summary> /// Creates a dynamic object and sets its wallet_id property to <see cref="WalletId"/> @@ -294,10 +289,7 @@ public async Task<TransactionRecord> SendTransaction(string address, /// <returns>The <see cref="TransactionRecord"/></returns> public async Task<TransactionRecord> SendTransactionMulti(IEnumerable<Coin> additions, IEnumerable<Coin>? coins = null, ulong fee = 0, CancellationToken cancellationToken = default) { - if (additions is null) - { - throw new ArgumentNullException(nameof(additions)); - } + ArgumentNullException.ThrowIfNull(additions); dynamic data = CreateWalletDataObject(); data.additions = additions.ToList(); diff --git a/src/chia-dotnet/WalletProxy.cs b/src/chia-dotnet/WalletProxy.cs index f62ff97..677fe24 100644 --- a/src/chia-dotnet/WalletProxy.cs +++ b/src/chia-dotnet/WalletProxy.cs @@ -11,17 +11,13 @@ namespace chia.dotnet /// <summary> /// Proxy that communicates with the wallet endpoint /// </summary> - public sealed class WalletProxy : ServiceProxy + /// <remarks> + /// ctor + /// </remarks> + /// <param name="rpcClient"><see cref="IRpcClient"/> instance to use for rpc communication</param> + /// <param name="originService"><see cref="Message.Origin"/></param> + public sealed class WalletProxy(IRpcClient rpcClient, string originService) : ServiceProxy(rpcClient, ServiceNames.Wallet, originService) { - /// <summary> - /// ctor - /// </summary> - /// <param name="rpcClient"><see cref="IRpcClient"/> instance to use for rpc communication</param> - /// <param name="originService"><see cref="Message.Origin"/></param> - public WalletProxy(IRpcClient rpcClient, string originService) - : base(rpcClient, ServiceNames.Wallet, originService) - { - } /// <summary> /// Gets basic info about a pool that is used for pool wallet creation @@ -240,10 +236,7 @@ public async Task<TransactionRecord> GetTransaction(string transactionId, Cancel /// <returns>Indicator of whether the spend bundle was successfully included in the mempool</returns> public async Task<bool> PushTx(SpendBundle spendBundle, CancellationToken cancellationToken = default) { - if (spendBundle is null) - { - throw new ArgumentNullException(nameof(spendBundle)); - } + ArgumentNullException.ThrowIfNull(spendBundle); dynamic data = new ExpandoObject(); data.spend_bundle = spendBundle; @@ -261,10 +254,7 @@ public async Task<bool> PushTx(SpendBundle spendBundle, CancellationToken cancel /// <returns>An awaitable task</returns> public async Task PushTransactions(IEnumerable<TransactionRecord> transactions, CancellationToken cancellationToken = default) { - if (transactions is null) - { - throw new ArgumentNullException(nameof(transactions)); - } + ArgumentNullException.ThrowIfNull(transactions); dynamic data = new ExpandoObject(); data.transactions = transactions.ToList(); @@ -280,10 +270,7 @@ public async Task PushTransactions(IEnumerable<TransactionRecord> transactions, /// <returns>The new key's fingerprint</returns> public async Task<uint> AddKey(IEnumerable<string> mnemonic, CancellationToken cancellationToken = default) { - if (mnemonic is null) - { - throw new ArgumentNullException(nameof(mnemonic)); - } + ArgumentNullException.ThrowIfNull(mnemonic); dynamic data = new ExpandoObject(); data.mnemonic = mnemonic.ToList(); @@ -505,10 +492,7 @@ public async Task<NFTInfo> GetNFTInfo(string coinId, bool latest = true, bool ig /// <returns>Information about the wallet</returns> public async Task<(WalletType Type, string myDID, uint walletId)> CreateDIDWallet(IEnumerable<string> backupDIDs, ulong numOfBackupIdsNeeded, string name, IDictionary<string, string>? metaData = null, ulong fee = 0, CancellationToken cancellationToken = default) { - if (backupDIDs is null) - { - throw new ArgumentNullException(nameof(backupDIDs)); - } + ArgumentNullException.ThrowIfNull(backupDIDs); dynamic data = new ExpandoObject(); data.wallet_type = "did_wallet"; @@ -585,10 +569,7 @@ public async Task<NFTInfo> GetNFTInfo(string coinId, bool latest = true, bool ig public async Task<(TransactionRecord transaction, string launcherId, string p2SingletonHash)> CreatePoolWallet(PoolState initialTargetState, ulong? p2SingletonDelayTime = null, string? p2SingletonDelayedPH = null, CancellationToken cancellationToken = default) { - if (initialTargetState is null) - { - throw new ArgumentNullException(nameof(initialTargetState)); - } + ArgumentNullException.ThrowIfNull(initialTargetState); dynamic data = new ExpandoObject(); data.wallet_type = "pool_wallet"; @@ -657,10 +638,7 @@ public async Task<NFTInfo> GetNFTInfo(string coinId, bool latest = true, bool ig ulong fee = 0, CancellationToken cancellationToken = default) { - if (additions is null) - { - throw new ArgumentNullException(nameof(additions)); - } + ArgumentNullException.ThrowIfNull(additions); dynamic data = new ExpandoObject(); data.additions = additions.ToList(); @@ -695,19 +673,6 @@ public async Task<NFTInfo> GetNFTInfo(string coinId, bool latest = true, bool ig ); } - /// <summary> - /// Create but do not send a transaction - /// </summary> - /// <param name="additions">Additions to the block chain</param> - /// <param name="fee">Fee amount (in units of mojos)</param> - /// <param name="cancellationToken">A token to allow the call to be cancelled</param> - /// <returns>The signed <see cref="TransactionRecord"/></returns> - public async Task<TransactionRecord> CreateSignedTransaction(IEnumerable<Coin> additions, ulong fee = 0, CancellationToken cancellationToken = default) - { - return await CreateSignedTransaction(additions, fee: fee, cancellationToken).ConfigureAwait(false); - } - - /// <summary> /// Retrieves the coins for given coin IDs /// </summary> @@ -719,10 +684,7 @@ public async Task<TransactionRecord> CreateSignedTransaction(IEnumerable<Coin> a /// <returns>A list of <see cref="CoinRecord"/>s</returns> public async Task<IEnumerable<CoinRecord>> GetCoinRecordsByNames(IEnumerable<string> names, bool includeSpentCoins, uint? startHeight = null, uint? endHeight = null, CancellationToken cancellationToken = default) { - if (names is null) - { - throw new ArgumentNullException(nameof(names)); - } + ArgumentNullException.ThrowIfNull(names); dynamic data = new ExpandoObject(); data.names = names.ToList(); diff --git a/src/chia-dotnet/bech32/Bech32M.cs b/src/chia-dotnet/bech32/Bech32M.cs index 13be724..ee93aae 100644 --- a/src/chia-dotnet/bech32/Bech32M.cs +++ b/src/chia-dotnet/bech32/Bech32M.cs @@ -12,25 +12,20 @@ namespace chia.dotnet.bech32 /// Bech32M implementation for encoding addresses /// </summary> /// <remarks>adapted from https://github.com/Playwo/ChiaRPC.Net/blob/master/ChiaRPC.Net/Utils/Bech32M.cs</remarks> - public class Bech32M + /// <remarks> + /// ctor + /// </remarks> + /// <param name="prefix">Address prefix</param> + public class Bech32M(string prefix = "xch") { /// <summary> /// Address prefix to use /// </summary> /// <value>xch</value> - public string AddressPrefix { get; init; } = "xch"; + public string AddressPrefix { get; init; } = prefix; private const string Charset = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"; private const int M = 0x2BC830A3; - private static readonly int[] Generator = new int[] { 0x3B6A57B2, 0x26508E6D, 0x1EA119FA, 0x3D4233DD, 0x2A1462B3 }; - - /// <summary> - /// ctor - /// </summary> - /// <param name="prefix">Address prefix</param> - public Bech32M(string prefix = "xch") - { - AddressPrefix = prefix; - } + private static readonly int[] Generator = [0x3B6A57B2, 0x26508E6D, 0x1EA119FA, 0x3D4233DD, 0x2A1462B3]; /// <summary> /// Converts a puzzle hash to an address using <see cref="AddressPrefix"/> @@ -199,7 +194,7 @@ private static string Encode(string hrp, List<int> data) /// <returns></returns> private static (string?, List<int>?) Decode(string bech) { - if (bech.ToLower() != bech && bech.ToUpper() != bech) + if (!bech.Equals(bech, StringComparison.OrdinalIgnoreCase) && !bech.Equals(bech, StringComparison.OrdinalIgnoreCase)) { return (null, null); } @@ -213,7 +208,7 @@ private static (string?, List<int>?) Decode(string bech) } bech = bech.ToLower(); - var lastOnePosition = bech.LastIndexOf("1"); + var lastOnePosition = bech.LastIndexOf('1'); if (lastOnePosition < 1 || lastOnePosition + 7 > bech.Length || bech.Length > 90) { diff --git a/src/chia-dotnet/bech32/HexBytes.cs b/src/chia-dotnet/bech32/HexBytes.cs index e38ae1b..d6df6ab 100644 --- a/src/chia-dotnet/bech32/HexBytes.cs +++ b/src/chia-dotnet/bech32/HexBytes.cs @@ -8,34 +8,28 @@ namespace chia.dotnet.bech32 /// Utility to perform operations on an array of bytes and represent them as a Hex string /// </summary> /// <remarks>adapted from https://github.com/Playwo/ChiaRPC.Net/blob/master/ChiaRPC.Net/Utils/Bech32M.cs</remarks> - public readonly struct HexBytes + /// <remarks> + /// ctor + /// </remarks> + /// <param name="hex"></param> + /// <param name="bytes"></param> + public readonly struct HexBytes(string hex, byte[] bytes) { /// <summary> /// <see cref="Bytes"/> hex string representation /// </summary> - public string Hex { get; init; } + public string Hex { get; init; } = hex ?? string.Empty; /// <summary> /// The array of bytes /// </summary> - public byte[] Bytes { get; init; } + public byte[] Bytes { get; init; } = bytes ?? []; /// <summary> /// FLag indicating that the array is empty /// </summary> public bool IsEmpty => string.IsNullOrWhiteSpace(Hex); - /// <summary> - /// ctor - /// </summary> - /// <param name="hex"></param> - /// <param name="bytes"></param> - public HexBytes(string hex, byte[] bytes) - { - Hex = hex ?? string.Empty; - Bytes = bytes ?? Array.Empty<byte>(); - } - /// <summary> /// SHA256 encoded copy /// </summary> @@ -50,7 +44,7 @@ public HexBytes Sha256() public override bool Equals(object? obj) { - return obj is HexBytes other && Hex.ToUpperInvariant() == other.Hex.ToUpperInvariant(); + return obj is HexBytes other && Hex.Equals(other.Hex, StringComparison.OrdinalIgnoreCase); } public override int GetHashCode() @@ -91,12 +85,12 @@ public override string ToString() public static bool operator ==(HexBytes a, HexBytes b) { - return a.Hex.ToUpperInvariant() == b.Hex.ToUpperInvariant(); + return a.Hex.Equals(b.Hex, StringComparison.OrdinalIgnoreCase); } public static bool operator !=(HexBytes a, HexBytes b) { - return a.Hex.ToUpperInvariant() != b.Hex.ToUpperInvariant(); + return !a.Hex.Equals(b.Hex, StringComparison.OrdinalIgnoreCase); } public static HexBytes FromHex(string hex) @@ -136,6 +130,6 @@ public static HexBytes FromBytes(byte[] bytes) /// <summary> /// /// </summary> - public static HexBytes Empty => new(string.Empty, Array.Empty<byte>()); + public static HexBytes Empty => new(string.Empty, []); } } diff --git a/src/chia-dotnet/chia-dotnet.csproj b/src/chia-dotnet/chia-dotnet.csproj index a34775c..5e31e69 100644 --- a/src/chia-dotnet/chia-dotnet.csproj +++ b/src/chia-dotnet/chia-dotnet.csproj @@ -1,13 +1,13 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> - <TargetFramework>net6.0</TargetFramework> + <TargetFramework>net8.0</TargetFramework> <RootNamespace>chia.dotnet</RootNamespace> <EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild> <GenerateDocumentationFile>true</GenerateDocumentationFile> <NoWarn>$(NoWarn);CS1591</NoWarn> <GeneratePackageOnBuild>true</GeneratePackageOnBuild> - <Version>2.2.1</Version> + <Version>3.0.0</Version> <Authors>dkackman</Authors> <Company>dkackman</Company> <Description>A .net client library for chia™ RPC interfaces that runs on linux and windows.</Description> @@ -18,11 +18,12 @@ <RepositoryUrl>https://github.com/dkackman/chia-dotnet</RepositoryUrl> <RepositoryType>git</RepositoryType> <PackageTags>chia, 2.1.2</PackageTags> - <PackageReleaseNotes>Add Dao Wallet</PackageReleaseNotes> + <PackageReleaseNotes>.NET 8 +UInt 128</PackageReleaseNotes> <PackageIcon>chia-leaf-logo-384x384.png</PackageIcon> <PackageIconUrl /> - <AssemblyVersion>2.2.1.0</AssemblyVersion> - <FileVersion>2.2.1.0</FileVersion> + <AssemblyVersion>3.0.0.0</AssemblyVersion> + <FileVersion>3.0.0.0</FileVersion> <Nullable>enable</Nullable> <Title>chia.dotnet</Title> <PackageReadmeFile>README.md</PackageReadmeFile> diff --git a/src/docfx/docfx.csproj b/src/docfx/docfx.csproj index d351ec5..cbb58ed 100644 --- a/src/docfx/docfx.csproj +++ b/src/docfx/docfx.csproj @@ -1,7 +1,7 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> - <TargetFramework>net6.0</TargetFramework> + <TargetFramework>net8.0</TargetFramework> <RunPostBuildEvent>OnOutputUpdated</RunPostBuildEvent> </PropertyGroup>