Skip to content

Commit 96adc23

Browse files
authored
Merge pull request #7 from SubstrateGaming/fix/custom-nodes
Add support for extrinsics + account storage from genesis hash
2 parents f713645 + a01793d commit 96adc23

32 files changed

+653
-47
lines changed

Substrate.NET.Metadata.Node.Tests/ConvertToV14Test.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using Substrate.NET.Metadata.V11;
44
using Substrate.NET.Metadata.V12;
55
using Substrate.NET.Metadata.V13;
6+
using Substrate.NET.Metadata.V14;
67
using Substrate.NET.Metadata.V9;
78
using Substrate.NetApi;
89
using Substrate.NetApi.Model.Extrinsics;
@@ -18,7 +19,7 @@ public class ConvertToV14Test
1819
public async Task SetupAsync()
1920
{
2021
//_substrateClient = new SubstrateClient(new Uri("wss://polkadot-rpc.dwellir.com"), ChargeTransactionPayment.Default());
21-
_substrateClient = new SubstrateClient(new Uri("wss://polkadot.api.onfinality.io/public-ws"), ChargeTransactionPayment.Default());
22+
_substrateClient = new SubstrateClient(new Uri("wss://dot-rpc.stakeworld.io"), ChargeTransactionPayment.Default());
2223

2324
await _substrateClient.ConnectAsync();
2425
Assert.That(_substrateClient.IsConnected, Is.True);
@@ -59,6 +60,7 @@ public void Teardown()
5960
[TestCase("0xddca674d4e6e4935b1e5e81ed697f7ce027c2a9602523424bcc8dee3184e4863", 13)]
6061
[TestCase("0x4b34bd42835a084af0f441c5986d216b18a85abb4d03762096692e6f06365203", 13)]
6162
[TestCase("0x8192df1609d4478d1c1fcf5d39975596a8162d42d745c141c22148b0931708f2", 13)]
63+
[TestCase("0x2395e78d44a83c11eaf3a7019554091229d542c4f709e5233f7a54b4c8635004", 14)]
6264
public async Task ConvertMetadataToV14_ShouldSucceedAsync(string blockHash, int version)
6365
{
6466
var metadataHex = await _substrateClient.State.GetMetaDataAsync(Utils.HexToByteArray(blockHash), CancellationToken.None);
@@ -70,6 +72,7 @@ public async Task ConvertMetadataToV14_ShouldSucceedAsync(string blockHash, int
7072
11 => new MetadataV11(metadataHex),
7173
12 => new MetadataV12(metadataHex),
7274
13 => new MetadataV13(metadataHex),
75+
14 => new MetadataV14(metadataHex),
7376
_ => throw new Exception()
7477
};
7578

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
using Newtonsoft.Json.Linq;
2+
using Substrate.NetApi;
3+
using Substrate.NetApi.Model.Extrinsics;
4+
using Substrate.NetApi.Model.Types.Base;
5+
using System;
6+
using System.Collections.Generic;
7+
using System.Linq;
8+
using System.Text;
9+
using System.Threading.Tasks;
10+
using static System.Runtime.InteropServices.JavaScript.JSType;
11+
12+
namespace Substrate.NET.Metadata.Node.Tests.Storage
13+
{
14+
internal class AccountInfoTests
15+
{
16+
17+
18+
private SubstrateClient _substrateClient;
19+
20+
[OneTimeSetUp]
21+
public async Task SetupAsync()
22+
{
23+
//_substrateClient = new SubstrateClient(new Uri("wss://polkadot-rpc.dwellir.com"), ChargeTransactionPayment.Default());
24+
_substrateClient = new SubstrateClient(new Uri("wss://polkadot.api.onfinality.io/public-ws"), ChargeTransactionPayment.Default());
25+
26+
await _substrateClient.ConnectAsync();
27+
Assert.That(_substrateClient.IsConnected, Is.True);
28+
}
29+
30+
[OneTimeTearDown]
31+
public void Teardown()
32+
{
33+
_substrateClient.Dispose();
34+
}
35+
36+
/// <summary>
37+
/// Blockchain : Polkadot
38+
/// Fetch Account Info from block 1
39+
/// </summary>
40+
/// <returns></returns>
41+
[Test]
42+
public async Task AccountInfo_MetadataV11_ShouldBeCorrectlyInstanciatedAsync()
43+
{
44+
var accountId32 = new AccountId32();
45+
accountId32.Create(Utils.GetPublicKeyFrom("12H7nsDUrJUSCQQJrTKAFfyCWSactiSdjoVUixqcd9CZHTGt"));
46+
47+
var parameters = RequestGenerator.GetStorage("System", "Account", Substrate.NetApi.Model.Meta.Storage.Type.Map, [Substrate.NetApi.Model.Meta.Storage.Hasher.BlakeTwo128Concat], [accountId32]);
48+
49+
var result = await _substrateClient.GetStorageAsync<AccountInfoOldVersion>(parameters, "0xC0096358534EC8D21D01D34B836EED476A1C343F8724FA2153DC0725AD797A90", CancellationToken.None);
50+
51+
Assert.That(result.Data, Is.Not.Null);
52+
}
53+
}
54+
55+
public sealed class AccountInfoOldVersion : BaseType
56+
{
57+
// https://docs.rs/frame-system/2.0.0/frame_system/struct.AccountInfo.html
58+
public Substrate.NetApi.Model.Types.Primitive.U32 Nonce { get; set; } = default!;
59+
public Substrate.NetApi.Model.Types.Primitive.U8 RefCount { get; set; } = default!;
60+
public AccountDataOldVersion Data { get; set; } = default!;
61+
62+
public override System.String TypeName()
63+
{
64+
return "AccountInfo";
65+
}
66+
67+
public override System.Byte[] Encode()
68+
{
69+
var result = new List<byte>();
70+
result.AddRange(Nonce.Encode());
71+
//result.AddRange(Consumers.Encode());
72+
//result.AddRange(Providers.Encode());
73+
//result.AddRange(Sufficients.Encode());
74+
result.AddRange(RefCount.Encode());
75+
result.AddRange(Data.Encode());
76+
return result.ToArray();
77+
}
78+
79+
public override void Decode(byte[] byteArray, ref int p)
80+
{
81+
var start = p;
82+
Nonce = new Substrate.NetApi.Model.Types.Primitive.U32();
83+
Nonce.Decode(byteArray, ref p);
84+
RefCount = new Substrate.NetApi.Model.Types.Primitive.U8();
85+
RefCount.Decode(byteArray, ref p);
86+
Data = new AccountDataOldVersion();
87+
Data.Decode(byteArray, ref p);
88+
var bytesLength = p - start;
89+
TypeSize = bytesLength;
90+
Bytes = new byte[bytesLength];
91+
System.Array.Copy(byteArray, start, Bytes, 0, bytesLength);
92+
}
93+
}
94+
95+
public sealed class AccountDataOldVersion : BaseType
96+
{
97+
// https://docs.rs/pallet-balances/2.0.1/pallet_balances/struct.Instance0.html
98+
99+
public Substrate.NetApi.Model.Types.Primitive.U128 Free { get; set; } = default!;
100+
public Substrate.NetApi.Model.Types.Primitive.U128 Reserved { get; set; } = default!;
101+
public Substrate.NetApi.Model.Types.Primitive.U128 MiscFrozen { get; set; } = default!;
102+
public Substrate.NetApi.Model.Types.Primitive.U128 FeeFrozen { get; set; } = default!;
103+
104+
public override System.String TypeName()
105+
{
106+
return "AccountData";
107+
}
108+
109+
public override System.Byte[] Encode()
110+
{
111+
var result = new List<byte>();
112+
result.AddRange(Free.Encode());
113+
result.AddRange(Reserved.Encode());
114+
result.AddRange(MiscFrozen.Encode());
115+
result.AddRange(FeeFrozen.Encode());
116+
return result.ToArray();
117+
}
118+
119+
public override void Decode(byte[] byteArray, ref int p)
120+
{
121+
var start = p;
122+
Free = new Substrate.NetApi.Model.Types.Primitive.U128();
123+
Free.Decode(byteArray, ref p);
124+
Reserved = new Substrate.NetApi.Model.Types.Primitive.U128();
125+
Reserved.Decode(byteArray, ref p);
126+
MiscFrozen = new Substrate.NetApi.Model.Types.Primitive.U128();
127+
MiscFrozen.Decode(byteArray, ref p);
128+
FeeFrozen = new Substrate.NetApi.Model.Types.Primitive.U128();
129+
FeeFrozen.Decode(byteArray, ref p);
130+
var bytesLength = p - start;
131+
TypeSize = bytesLength;
132+
Bytes = new byte[bytesLength];
133+
System.Array.Copy(byteArray, start, Bytes, 0, bytesLength);
134+
}
135+
}
136+
137+
public sealed class AccountId32 : BaseType
138+
{
139+
public Substrate.NetApi.Model.Types.Primitive.U8[] Value { get; set; } = default!;
140+
141+
public override System.String TypeName()
142+
{
143+
return "AccountId32";
144+
}
145+
146+
public override int TypeSize
147+
{
148+
get
149+
{
150+
return 32;
151+
}
152+
}
153+
154+
public override System.Byte[] Encode()
155+
{
156+
var result = new List<byte>();
157+
foreach (var v in Value)
158+
{
159+
result.AddRange(v.Encode());
160+
}
161+
162+
return result.ToArray();
163+
}
164+
165+
public override void Decode(byte[] byteArray, ref int p)
166+
{
167+
var start = p;
168+
var array = new Substrate.NetApi.Model.Types.Primitive.U8[TypeSize];
169+
for (var i = 0; i < array.Length; i++)
170+
{
171+
var t = new Substrate.NetApi.Model.Types.Primitive.U8();
172+
t.Decode(byteArray, ref p);
173+
array[i] = t;
174+
}
175+
176+
var bytesLength = p - start;
177+
Bytes = new byte[bytesLength];
178+
System.Array.Copy(byteArray, start, Bytes, 0, bytesLength);
179+
Value = array;
180+
}
181+
182+
public void Create(Substrate.NetApi.Model.Types.Primitive.U8[] array)
183+
{
184+
Value = array;
185+
Bytes = Encode();
186+
}
187+
}
188+
}

Substrate.NET.Metadata.Tests/Conversion/ConversionBuilderTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
using System.Text;
1010
using System.Threading.Tasks;
1111

12-
namespace Substrate.NET.Metadata.Conversion.Tests
12+
namespace Substrate.NET.Metadata.Tests.Conversion
1313
{
1414
internal class ConversionBuilderTest
1515
{
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
using Substrate.NET.Metadata.Base;
2+
using Substrate.NET.Metadata.Base.Portable;
3+
using Substrate.NET.Metadata.Conversion.Internal;
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Linq;
7+
using System.Text;
8+
using System.Threading.Tasks;
9+
10+
namespace Substrate.NET.Metadata.Tests.Conversion
11+
{
12+
internal class CustomNodesBuilderTests
13+
{
14+
[Test]
15+
public void CreateCustomComposite_ShouldReturnCompositeBuilder()
16+
{
17+
var conversion = new ConversionBuilder(new List<PortableType>());
18+
var customNodeBuilder = new CustomNodeBuilder();
19+
20+
var accountInfoBuilder = customNodeBuilder
21+
.CreateCustomComposite()
22+
.AddField("nonce", "Index")
23+
.AddField("refcount", "u8")
24+
.AddField("data", "AccountData")
25+
.WithPath("frame_system", "accountInfo")
26+
.Build(conversion);
27+
28+
Assert.That(accountInfoBuilder, Is.Not.Null);
29+
}
30+
31+
[Test]
32+
public void CreateCustomComposite_WhenCallByParentNode_ShouldReturnTheOverrideOne()
33+
{
34+
var conversion = new ConversionBuilder(new List<PortableType>());
35+
var customNodeBuilder = new CustomNodeBuilder();
36+
37+
var accountDataBuilder = customNodeBuilder
38+
.CreateCustomComposite()
39+
.AddField("free", "Balance")
40+
.AddField("notFree", "Balance")
41+
.WithPath("pallet_balance", "types", "AccountData");
42+
43+
customNodeBuilder.Build(conversion);
44+
45+
var res = conversion.BuildPortableTypes("AccountInfo");
46+
47+
// We should get the AccountInfo from v14 but with our override of AccountData
48+
var accountInfo = conversion.PortableTypes.SingleOrDefault(x => x.Id.Value == res.Value);
49+
50+
Assert.That(accountInfo, Is.Not.Null);
51+
52+
var accountInfoComposite = accountInfo.Ty.TypeDef.Value2 as TypeDefComposite;
53+
54+
var accountData = conversion.PortableTypes.SingleOrDefault(x => x.Id.Value == accountInfoComposite!.Fields.Value[^1].FieldTy.Value);
55+
var accountDataComposite = accountData!.Ty.TypeDef.Value2 as TypeDefComposite;
56+
57+
Assert.Multiple(() =>
58+
{
59+
Assert.That(accountDataComposite!.Fields.Value[0].Name.Value.Value, Is.EqualTo("free"));
60+
Assert.That(accountDataComposite!.Fields.Value[1].Name.Value.Value, Is.EqualTo("notFree"));
61+
});
62+
}
63+
64+
[Test]
65+
public void CustomComposite_WithSpecifiedVersionRange()
66+
{
67+
var customNodeBuilder = new CustomNodeBuilder();
68+
69+
var accountDataBuilder = customNodeBuilder
70+
.CreateCustomComposite()
71+
.FromVersion(10)
72+
.ToVersion(20);
73+
74+
Assert.Multiple(() =>
75+
{
76+
Assert.That(accountDataBuilder.IsVersionValid(10), Is.True);
77+
Assert.That(accountDataBuilder.IsVersionValid(20), Is.True);
78+
Assert.That(accountDataBuilder.IsVersionValid(15), Is.True);
79+
Assert.That(accountDataBuilder.IsVersionValid(9), Is.False);
80+
Assert.That(accountDataBuilder.IsVersionValid(30), Is.False);
81+
});
82+
}
83+
84+
[Test]
85+
public void CustomComposite_WithNoVersionSpecified()
86+
{
87+
var customNodeBuilder = new CustomNodeBuilder();
88+
89+
var accountDataBuilder = customNodeBuilder
90+
.CreateCustomComposite();
91+
92+
Assert.That(accountDataBuilder.IsVersionValid(10), Is.True);
93+
}
94+
}
95+
}

Substrate.NET.Metadata.Tests/MetadataServiceV13Test.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using Substrate.NET.Metadata.Conversion;
33
using Substrate.NET.Metadata.Service;
44
using Substrate.NET.Metadata.V13;
5+
using Substrate.NET.Metadata.V14;
56

67
namespace Substrate.NET.Metadata.Tests
78
{
@@ -66,5 +67,16 @@ public void StorageEntryMetadataV13_WhenNMap_ShouldThrowException()
6667

6768
Assert.Throws<MetadataConversionException>(() => storageEntry.ToStorageEntryMetadataV14(new Metadata.Conversion.Internal.ConversionBuilder(new List<Base.Portable.PortableType>())));
6869
}
70+
71+
[Test]
72+
public void MetadataV13_WithSpecificVersion_ConvertToNetApiMetadata_ShouldSucceed()
73+
{
74+
var metadata = new MetadataV13(readMetadataFromFile("V13\\MetadataV13_9050"));
75+
76+
var tov14 = metadata.ToMetadataV14(9050);
77+
var netApiMetadata = tov14.ToNetApiMetadata();
78+
79+
Assert.That(netApiMetadata, Is.Not.Null);
80+
}
6981
}
7082
}

Substrate.NET.Metadata.Tests/MetadataServiceV14Test.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,12 @@ public void MetadataV14_V9270_And_V9280_PalletHasChanged_ShouldSucceed()
111111
}
112112

113113
[Test]
114-
public void MetadataV14_ConvertToNetApiMetadata_ShouldSucceed()
114+
[TestCase("V14\\MetadataV14_1003000")]
115+
[TestCase("V14\\MetadataV14_1002007")]
116+
[TestCase("V14\\MetadataV14_9270")]
117+
public void MetadataV14_ConvertToNetApiMetadata_ShouldSucceed(string metadataPath)
115118
{
116-
var metadata = new MetadataV14(readMetadataFromFile("V14\\MetadataV14_9270"));
119+
var metadata = new MetadataV14(readMetadataFromFile(metadataPath));
117120
var netApiMetadata = metadata.ToNetApiMetadata();
118121

119122
Assert.That(netApiMetadata, Is.Not.Null);

Substrate.NET.Metadata.Tests/Mocks/V14/MetadataV14_1002007.txt

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

Substrate.NET.Metadata.Tests/Mocks/V14/MetadataV14_1003000.txt

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

Substrate.NET.Metadata.Tests/Substrate.NET.Metadata.Tests.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@
9494
<None Update="Mocks\V13\MetadataV13_9100.txt">
9595
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
9696
</None>
97+
<None Update="Mocks\V14\MetadataV14_1003000.txt">
98+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
99+
</None>
97100
<None Update="Mocks\V14\MetadataV14_9110.txt">
98101
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
99102
</None>
@@ -112,6 +115,9 @@
112115
<None Update="Mocks\V14\MetadataV14_9420.txt">
113116
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
114117
</None>
118+
<None Update="Mocks\V14\MetadataV14_1002007.txt">
119+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
120+
</None>
115121
<None Update="Mocks\V14\MetadataV14_9430.txt">
116122
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
117123
</None>

Substrate.NET.Metadata.sln

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Substrate.NET.Metadata", "S
77
EndProject
88
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Substrate.NET.Metadata.Tests", "Substrate.NET.Metadata.Tests\Substrate.NET.Metadata.Tests.csproj", "{4698095E-1C43-40BA-925B-B9333599E0E4}"
99
EndProject
10-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Substrate.NET.Metadata.Node.Tests", "Substrate.NET.Metadata.Node.Tests\Substrate.NET.Metadata.Node.Tests.csproj", "{07CC3754-3F83-494B-A2D2-49D1F93FA30B}"
10+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Substrate.NET.Metadata.Node.Tests", "Substrate.NET.Metadata.Node.Tests\Substrate.NET.Metadata.Node.Tests.csproj", "{07CC3754-3F83-494B-A2D2-49D1F93FA30B}"
1111
EndProject
1212
Global
1313
GlobalSection(SolutionConfigurationPlatforms) = preSolution

0 commit comments

Comments
 (0)