diff --git a/Substrate.NetApi.Test/Substrate.NetApi.Test.csproj b/Substrate.NetApi.Test/Substrate.NetApi.Test.csproj index 017d6a9..f95e7f8 100644 --- a/Substrate.NetApi.Test/Substrate.NetApi.Test.csproj +++ b/Substrate.NetApi.Test/Substrate.NetApi.Test.csproj @@ -8,8 +8,8 @@ - - + + diff --git a/Substrate.NetApi.TestNode/BasicTest.cs b/Substrate.NetApi.TestNode/BasicTest.cs index dea3f99..9258788 100644 --- a/Substrate.NetApi.TestNode/BasicTest.cs +++ b/Substrate.NetApi.TestNode/BasicTest.cs @@ -145,38 +145,6 @@ public async Task GetBlocknumberAtBlockHashTestAsync() Assert.AreEqual(currentBlocknumber.Value, result.Value); } - /// - /// Simple extrinsic tester - /// - /// - /// - private static void ActionExtrinsicUpdate(string subscriptionId, ExtrinsicStatus extrinsicUpdate) - { - switch (extrinsicUpdate.ExtrinsicState) - { - case ExtrinsicState.None: - Assert.IsTrue(true); - Assert.IsTrue(extrinsicUpdate.InBlock.Value.Length > 0 || extrinsicUpdate.Finalized.Value.Length > 0); - break; - - case ExtrinsicState.Future: - Assert.IsTrue(false); - break; - - case ExtrinsicState.Ready: - Assert.IsTrue(true); - break; - - case ExtrinsicState.Dropped: - Assert.IsTrue(false); - break; - - case ExtrinsicState.Invalid: - Assert.IsTrue(false); - break; - } - } - /// /// >> 1 - Array /// diff --git a/Substrate.NetApi.TestNode/ExtrinsicsTest.cs b/Substrate.NetApi.TestNode/ExtrinsicsTest.cs new file mode 100644 index 0000000..9bba304 --- /dev/null +++ b/Substrate.NetApi.TestNode/ExtrinsicsTest.cs @@ -0,0 +1,148 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Substrate.NetApi.Model.Extrinsics; +using Substrate.NetApi.Model.Rpc; +using Substrate.NetApi.Model.Types; +using Substrate.NetApi.Model.Types.Base; +using Substrate.NetApi.Model.Types.Primitive; +using NUnit.Framework; +using Schnorrkel.Keys; + +namespace Substrate.NetApi.TestNode +{ + public class ExtrinsicsTest + { + public MiniSecret MiniSecretAlice => new MiniSecret(Utils.HexToByteArray("0xe5be9a5092b81bca64be81d212e7f2f9eba183bb7a90954f7b76361f6edb5c0a"), ExpandMode.Ed25519); + public Account Alice => Account.Build(KeyType.Sr25519, MiniSecretAlice.ExpandToSecret().ToBytes(), MiniSecretAlice.GetPair().Public.Key); + public MiniSecret MiniSecretBob => new MiniSecret(Utils.HexToByteArray("0x398f0c28f98885e046333d4a41c19cee4c37368a9832c6502f6cfd182e2aef89"), ExpandMode.Ed25519); + public Account Bob => Account.Build(KeyType.Sr25519, MiniSecretBob.ExpandToSecret().ToBytes(), MiniSecretBob.GetPair().Public.Key); + + protected const string WebSocketUrl = "ws://127.0.0.1:9944"; + + protected SubstrateClient _substrateClient; + + protected ChargeType _chargeType; + + [SetUp] + public async Task ConnectAsync() + { + await _substrateClient.ConnectAsync(); + } + + [TearDown] + public async Task CloseAsync() + { + await _substrateClient.CloseAsync(); + } + + [OneTimeSetUp] + public void CreateClient() + { + _chargeType = ChargeAssetTxPayment.Default(); + _substrateClient = new SubstrateClient(new Uri(WebSocketUrl), _chargeType); + } + + [OneTimeTearDown] + public void DisposeClient() + { + _substrateClient.Dispose(); + } + + /// + /// Extrinsic Remark test + /// + /// + [Test] + public async Task Extrinsic_RemarkAsync() + { + var method = new Method(0, "System", 0, "remark", new byte[] { 0x04, 0xFF }); + + var taskCompletionSource = new TaskCompletionSource(); + await _substrateClient.Author.SubmitAndWatchExtrinsicAsync((string subscriptionId, ExtrinsicStatus extrinsicUpdate) => Callback(subscriptionId, extrinsicUpdate, taskCompletionSource), method, Alice, _chargeType, 64, CancellationToken.None); + + var finished = await Task.WhenAny(taskCompletionSource.Task, Task.Delay(TimeSpan.FromMinutes(1))); // 5 minutes or any appropriate timeout + Assert.AreEqual(taskCompletionSource.Task, finished, "Test timed out waiting for final callback"); + } + + /// + /// Extrinsic Transfer Callback test + /// + /// + /// + /// + private static void Callback(string subscriptionId, ExtrinsicStatus extrinsicUpdate, TaskCompletionSource taskCompletionSource) + { + ActionExtrinsicUpdate(subscriptionId, extrinsicUpdate); + if (extrinsicUpdate.ExtrinsicState == ExtrinsicState.Finalized || + extrinsicUpdate.ExtrinsicState == ExtrinsicState.Dropped || + extrinsicUpdate.ExtrinsicState == ExtrinsicState.Invalid) + { + taskCompletionSource.SetResult(true); + } + } + + /// + /// Simple extrinsic tester + /// + /// + /// + private static void ActionExtrinsicUpdate(string subscriptionId, ExtrinsicStatus extrinsicUpdate) + { + if (subscriptionId == null || subscriptionId.Length == 0) + { + Assert.IsTrue(false); + } + + switch (extrinsicUpdate.ExtrinsicState) + { + case ExtrinsicState.Future: + Assert.IsTrue(false); + break; + + case ExtrinsicState.Ready: + Assert.IsTrue(true); + break; + + case ExtrinsicState.Dropped: + Assert.IsTrue(false); + break; + + case ExtrinsicState.Invalid: + Assert.IsTrue(false); + break; + + case ExtrinsicState.Broadcast: + Assert.IsTrue(extrinsicUpdate.Broadcast != null); + break; + + case ExtrinsicState.InBlock: + Assert.IsTrue(extrinsicUpdate.Hash.Value.Length > 0); + break; + + case ExtrinsicState.Retracted: + Assert.IsTrue(extrinsicUpdate.Hash.Value.Length > 0); + break; + + case ExtrinsicState.FinalityTimeout: + Assert.IsTrue(extrinsicUpdate.Hash.Value.Length > 0); + break; + + case ExtrinsicState.Finalized: + Assert.IsTrue(extrinsicUpdate.Hash.Value.Length > 0); + break; + + case ExtrinsicState.Usurped: + Assert.IsTrue(extrinsicUpdate.Hash.Value.Length > 0); + break; + + default: + Assert.IsTrue(false); + break; + + } + } + } +} \ No newline at end of file diff --git a/Substrate.NetApi.TestNode/QueryAllTest.cs b/Substrate.NetApi.TestNode/QueryAllTest.cs index 3886b46..ebc5988 100644 --- a/Substrate.NetApi.TestNode/QueryAllTest.cs +++ b/Substrate.NetApi.TestNode/QueryAllTest.cs @@ -1,21 +1,18 @@ -using Substrate.NetApi.Model.Extrinsics; -using NUnit.Framework; +using NUnit.Framework; +using Substrate.NetApi.Model.Types; +using Substrate.NetApi.Model.Types.Base; +using Substrate.NetApi.Model.Types.Primitive; using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; -using System.Text; -using System.Threading.Tasks; using System.Threading; -using Substrate.NetApi.Model.Types.Base; -using Substrate.NetApi.Model.Types.Primitive; -using Substrate.NetApi.Model.Types; -using System.Diagnostics; +using System.Threading.Tasks; namespace Substrate.NetApi.TestNode { public class QueryAllTest : NodeTest { - [Test] public async Task GetAllStorageTestAsync() { @@ -43,10 +40,10 @@ public async Task GetAllStorageTestAsync() Assert.IsNotNull(allPages); Assert.AreNotEqual(0, allPages.Count); - Assert.Greater(10000, stopwatch.ElapsedMilliseconds, "Get all storage did use more then 10 sec., verify!"); + Assert.Greater(20000, stopwatch.ElapsedMilliseconds, "Get all storage did use more then 10 sec., verify!"); } - public async Task> GetAllStoragePagedAsync(string module, string item, byte[] startKey, uint page, string blockHash, CancellationToken token) + public async Task> GetAllStoragePagedAsync(string module, string item, byte[] startKey, uint page, string blockHash, CancellationToken token) where T1 : IType, new() where T2 : IType, new() { @@ -250,4 +247,4 @@ public void Create(U8[] array) Bytes = Encode(); } } -} +} \ No newline at end of file diff --git a/Substrate.NetApi.TestNode/Substrate.NetApi.TestNode.csproj b/Substrate.NetApi.TestNode/Substrate.NetApi.TestNode.csproj index 3e90df7..846957e 100644 --- a/Substrate.NetApi.TestNode/Substrate.NetApi.TestNode.csproj +++ b/Substrate.NetApi.TestNode/Substrate.NetApi.TestNode.csproj @@ -7,10 +7,10 @@ - + - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Substrate.NetApi/Model/Extrinsics/Extrinsic.cs b/Substrate.NetApi/Model/Extrinsics/Extrinsic.cs index 927714c..cd5b709 100644 --- a/Substrate.NetApi/Model/Extrinsics/Extrinsic.cs +++ b/Substrate.NetApi/Model/Extrinsics/Extrinsic.cs @@ -92,7 +92,7 @@ internal Extrinsic(Memory memory, ChargeType chargeType) // nonce Nonce = CompactInteger.Decode(memory.ToArray(), ref p); - // chargeAssetTxPayment + // charge type Charge = chargeType; Charge.Decode(memory.ToArray(), ref p); } diff --git a/Substrate.NetApi/Model/Rpc/ExtrinsicStatus.cs b/Substrate.NetApi/Model/Rpc/ExtrinsicStatus.cs index 512d70b..8a6b590 100644 --- a/Substrate.NetApi/Model/Rpc/ExtrinsicStatus.cs +++ b/Substrate.NetApi/Model/Rpc/ExtrinsicStatus.cs @@ -5,18 +5,18 @@ namespace Substrate.NetApi.Model.Rpc { public enum ExtrinsicState { - None, Future, Ready, Dropped, Invalid + Future, Ready, Broadcast, InBlock, Retracted, FinalityTimeout, Finalized, Usurped, Dropped, Invalid } public class ExtrinsicStatus { public ExtrinsicState ExtrinsicState { get; set; } + public string[] Broadcast { get; set; } - public Hash InBlock { get; set; } - public Hash Retracted { get; set; } - public Hash FinalityTimeout { get; set; } - public Hash Finalized { get; set; } - public Hash Usurped { get; set; } + + public Hash Hash { get; set; } + + //public ulong? TxIndex { get; set; } public override string ToString() { diff --git a/Substrate.NetApi/Substrate.NetApi.csproj b/Substrate.NetApi/Substrate.NetApi.csproj index 24a4286..e2cf831 100644 --- a/Substrate.NetApi/Substrate.NetApi.csproj +++ b/Substrate.NetApi/Substrate.NetApi.csproj @@ -3,7 +3,7 @@ Substrate.NET.API netstandard2.0;netstandard2.1;net6.0 - 0.9.9 + 0.9.10 Substrate Gaming Substrate Gaming true diff --git a/Substrate.NetApi/TypeConverters/ExtrinsicJsonConverter.cs b/Substrate.NetApi/TypeConverters/ExtrinsicJsonConverter.cs index 1926da4..1925f79 100644 --- a/Substrate.NetApi/TypeConverters/ExtrinsicJsonConverter.cs +++ b/Substrate.NetApi/TypeConverters/ExtrinsicJsonConverter.cs @@ -1,19 +1,15 @@ -using System; +using Newtonsoft.Json; using Substrate.NetApi.Model.Extrinsics; -using Newtonsoft.Json; -using Serilog; +using System; namespace Substrate.NetApi.TypeConverters { /// - ///
+ /// Extrinsic Json Converter ///
internal class ExtrinsicJsonConverter : JsonConverter { - /// The logger. - private static readonly ILogger Logger = new LoggerConfiguration().CreateLogger(); - - private ChargeType _chargeType; + private readonly ChargeType _chargeType; public ExtrinsicJsonConverter(ChargeType chargeType) { diff --git a/Substrate.NetApi/TypeConverters/ExtrinsicStatusJsonConverter.cs b/Substrate.NetApi/TypeConverters/ExtrinsicStatusJsonConverter.cs index 36ec466..b365c03 100644 --- a/Substrate.NetApi/TypeConverters/ExtrinsicStatusJsonConverter.cs +++ b/Substrate.NetApi/TypeConverters/ExtrinsicStatusJsonConverter.cs @@ -1,8 +1,8 @@ -using System; -using System.Collections.Generic; +using Newtonsoft.Json; using Substrate.NetApi.Model.Rpc; using Substrate.NetApi.Model.Types.Base; -using Newtonsoft.Json; +using System; +using System.Collections.Generic; namespace Substrate.NetApi.TypeConverters { @@ -23,7 +23,7 @@ public class ExtrinsicStatusJsonConverter : JsonConverter public override ExtrinsicStatus ReadJson(JsonReader reader, Type objectType, ExtrinsicStatus existingValue, bool hasExistingValue, JsonSerializer serializer) { - var extrinsicStatus = new ExtrinsicStatus(); + var extrinsicStatus = hasExistingValue ? existingValue : new ExtrinsicStatus(); if (reader.TokenType == JsonToken.String && Enum.TryParse((string)reader.Value, true, out ExtrinsicState extrinsicState)) @@ -32,82 +32,46 @@ public override ExtrinsicStatus ReadJson(JsonReader reader, Type objectType, Ext } else if (reader.TokenType == JsonToken.StartObject) { - reader.Read(); - - while (reader.TokenType != JsonToken.EndObject) + while (reader.Read()) { - switch (reader.TokenType) - { - case JsonToken.PropertyName: - - if (reader.ValueType == typeof(string)) - switch (reader.Value) - { - case "broadcast": - reader.Read(); - if (reader.TokenType == JsonToken.StartArray) - { - var broadcastList = new List(); - while (reader.TokenType != JsonToken.EndArray) - { - if (reader.ValueType == typeof(string)) - broadcastList.Add((string)reader.Value); - reader.Read(); - } - - extrinsicStatus.Broadcast = broadcastList.ToArray(); - } - - break; - - case "inBlock": - reader.Read(); - var inBlock = new Hash(); - inBlock.Create((string)reader.Value); - extrinsicStatus.InBlock = inBlock; - break; + if (reader.TokenType == JsonToken.EndObject) + break; - case "finalized": - reader.Read(); - var finalized = new Hash(); - finalized.Create((string)reader.Value); - extrinsicStatus.Finalized = finalized; - break; - - case "finalityTimeout": - reader.Read(); - var finalityTimeout = new Hash(); - finalityTimeout.Create((string)reader.Value); - extrinsicStatus.FinalityTimeout = finalityTimeout; - break; - - case "retracted": - reader.Read(); - var retracted = new Hash(); - retracted.Create((string)reader.Value); - extrinsicStatus.Retracted = retracted; - break; - - case "usurped": - reader.Read(); - var usurped = new Hash(); - usurped.Create((string)reader.Value); - extrinsicStatus.Usurped = usurped; - break; - - default: - throw new NotImplementedException( - $"Unimplemented {reader.TokenType} of type '{reader.ValueType}' and value '{reader.Value}'."); - } - - break; - - default: - throw new NotImplementedException( - $"Unimplemented {reader.TokenType} of type '{reader.ValueType}' and value '{reader.Value}'."); + if (reader.TokenType == JsonToken.PropertyName) + { + var propertyName = reader.Value.ToString(); + if (Enum.TryParse(propertyName, true, out extrinsicState)) + { + extrinsicStatus.ExtrinsicState = extrinsicState; + reader.Read(); + + switch (extrinsicState) + { + case ExtrinsicState.Broadcast: + var broadcastList = new List(); + while (reader.Read() && reader.TokenType != JsonToken.EndArray) + { + if (reader.TokenType == JsonToken.String) + broadcastList.Add(reader.Value.ToString()); + } + extrinsicStatus.Broadcast = broadcastList.ToArray(); + break; + + case ExtrinsicState.InBlock: + case ExtrinsicState.Finalized: + case ExtrinsicState.FinalityTimeout: + case ExtrinsicState.Retracted: + case ExtrinsicState.Usurped: + if (reader.TokenType == JsonToken.String) + extrinsicStatus.Hash = new Hash(reader.Value.ToString()); + break; + + default: + throw new NotImplementedException( + $"Unimplemented state {extrinsicState} with value '{reader.Value}'."); + } + } } - - reader.Read(); } }