Skip to content

Commit

Permalink
Merge pull request #7 from SubstrateGaming/fix/custom-nodes
Browse files Browse the repository at this point in the history
Add support for extrinsics + account storage from genesis hash
  • Loading branch information
darkfriend77 authored Oct 18, 2024
2 parents f713645 + a01793d commit 96adc23
Show file tree
Hide file tree
Showing 32 changed files with 653 additions and 47 deletions.
5 changes: 4 additions & 1 deletion Substrate.NET.Metadata.Node.Tests/ConvertToV14Test.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Substrate.NET.Metadata.V11;
using Substrate.NET.Metadata.V12;
using Substrate.NET.Metadata.V13;
using Substrate.NET.Metadata.V14;
using Substrate.NET.Metadata.V9;
using Substrate.NetApi;
using Substrate.NetApi.Model.Extrinsics;
Expand All @@ -18,7 +19,7 @@ public class ConvertToV14Test
public async Task SetupAsync()
{
//_substrateClient = new SubstrateClient(new Uri("wss://polkadot-rpc.dwellir.com"), ChargeTransactionPayment.Default());
_substrateClient = new SubstrateClient(new Uri("wss://polkadot.api.onfinality.io/public-ws"), ChargeTransactionPayment.Default());
_substrateClient = new SubstrateClient(new Uri("wss://dot-rpc.stakeworld.io"), ChargeTransactionPayment.Default());

await _substrateClient.ConnectAsync();
Assert.That(_substrateClient.IsConnected, Is.True);
Expand Down Expand Up @@ -59,6 +60,7 @@ public void Teardown()
[TestCase("0xddca674d4e6e4935b1e5e81ed697f7ce027c2a9602523424bcc8dee3184e4863", 13)]
[TestCase("0x4b34bd42835a084af0f441c5986d216b18a85abb4d03762096692e6f06365203", 13)]
[TestCase("0x8192df1609d4478d1c1fcf5d39975596a8162d42d745c141c22148b0931708f2", 13)]
[TestCase("0x2395e78d44a83c11eaf3a7019554091229d542c4f709e5233f7a54b4c8635004", 14)]
public async Task ConvertMetadataToV14_ShouldSucceedAsync(string blockHash, int version)
{
var metadataHex = await _substrateClient.State.GetMetaDataAsync(Utils.HexToByteArray(blockHash), CancellationToken.None);
Expand All @@ -70,6 +72,7 @@ public async Task ConvertMetadataToV14_ShouldSucceedAsync(string blockHash, int
11 => new MetadataV11(metadataHex),
12 => new MetadataV12(metadataHex),
13 => new MetadataV13(metadataHex),
14 => new MetadataV14(metadataHex),
_ => throw new Exception()
};

Expand Down
188 changes: 188 additions & 0 deletions Substrate.NET.Metadata.Node.Tests/Storage/AccountInfoTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
using Newtonsoft.Json.Linq;
using Substrate.NetApi;
using Substrate.NetApi.Model.Extrinsics;
using Substrate.NetApi.Model.Types.Base;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Runtime.InteropServices.JavaScript.JSType;

namespace Substrate.NET.Metadata.Node.Tests.Storage
{
internal class AccountInfoTests
{


private SubstrateClient _substrateClient;

[OneTimeSetUp]
public async Task SetupAsync()
{
//_substrateClient = new SubstrateClient(new Uri("wss://polkadot-rpc.dwellir.com"), ChargeTransactionPayment.Default());
_substrateClient = new SubstrateClient(new Uri("wss://polkadot.api.onfinality.io/public-ws"), ChargeTransactionPayment.Default());

await _substrateClient.ConnectAsync();
Assert.That(_substrateClient.IsConnected, Is.True);
}

[OneTimeTearDown]
public void Teardown()
{
_substrateClient.Dispose();
}

/// <summary>
/// Blockchain : Polkadot
/// Fetch Account Info from block 1
/// </summary>
/// <returns></returns>
[Test]
public async Task AccountInfo_MetadataV11_ShouldBeCorrectlyInstanciatedAsync()
{
var accountId32 = new AccountId32();
accountId32.Create(Utils.GetPublicKeyFrom("12H7nsDUrJUSCQQJrTKAFfyCWSactiSdjoVUixqcd9CZHTGt"));

var parameters = RequestGenerator.GetStorage("System", "Account", Substrate.NetApi.Model.Meta.Storage.Type.Map, [Substrate.NetApi.Model.Meta.Storage.Hasher.BlakeTwo128Concat], [accountId32]);

var result = await _substrateClient.GetStorageAsync<AccountInfoOldVersion>(parameters, "0xC0096358534EC8D21D01D34B836EED476A1C343F8724FA2153DC0725AD797A90", CancellationToken.None);

Assert.That(result.Data, Is.Not.Null);
}
}

public sealed class AccountInfoOldVersion : BaseType
{
// https://docs.rs/frame-system/2.0.0/frame_system/struct.AccountInfo.html
public Substrate.NetApi.Model.Types.Primitive.U32 Nonce { get; set; } = default!;
public Substrate.NetApi.Model.Types.Primitive.U8 RefCount { get; set; } = default!;
public AccountDataOldVersion Data { get; set; } = default!;

public override System.String TypeName()
{
return "AccountInfo";
}

public override System.Byte[] Encode()
{
var result = new List<byte>();
result.AddRange(Nonce.Encode());
//result.AddRange(Consumers.Encode());
//result.AddRange(Providers.Encode());
//result.AddRange(Sufficients.Encode());
result.AddRange(RefCount.Encode());
result.AddRange(Data.Encode());
return result.ToArray();
}

public override void Decode(byte[] byteArray, ref int p)
{
var start = p;
Nonce = new Substrate.NetApi.Model.Types.Primitive.U32();
Nonce.Decode(byteArray, ref p);
RefCount = new Substrate.NetApi.Model.Types.Primitive.U8();
RefCount.Decode(byteArray, ref p);
Data = new AccountDataOldVersion();
Data.Decode(byteArray, ref p);
var bytesLength = p - start;
TypeSize = bytesLength;
Bytes = new byte[bytesLength];
System.Array.Copy(byteArray, start, Bytes, 0, bytesLength);
}
}

public sealed class AccountDataOldVersion : BaseType
{
// https://docs.rs/pallet-balances/2.0.1/pallet_balances/struct.Instance0.html

public Substrate.NetApi.Model.Types.Primitive.U128 Free { get; set; } = default!;
public Substrate.NetApi.Model.Types.Primitive.U128 Reserved { get; set; } = default!;
public Substrate.NetApi.Model.Types.Primitive.U128 MiscFrozen { get; set; } = default!;
public Substrate.NetApi.Model.Types.Primitive.U128 FeeFrozen { get; set; } = default!;

public override System.String TypeName()
{
return "AccountData";
}

public override System.Byte[] Encode()
{
var result = new List<byte>();
result.AddRange(Free.Encode());
result.AddRange(Reserved.Encode());
result.AddRange(MiscFrozen.Encode());
result.AddRange(FeeFrozen.Encode());
return result.ToArray();
}

public override void Decode(byte[] byteArray, ref int p)
{
var start = p;
Free = new Substrate.NetApi.Model.Types.Primitive.U128();
Free.Decode(byteArray, ref p);
Reserved = new Substrate.NetApi.Model.Types.Primitive.U128();
Reserved.Decode(byteArray, ref p);
MiscFrozen = new Substrate.NetApi.Model.Types.Primitive.U128();
MiscFrozen.Decode(byteArray, ref p);
FeeFrozen = new Substrate.NetApi.Model.Types.Primitive.U128();
FeeFrozen.Decode(byteArray, ref p);
var bytesLength = p - start;
TypeSize = bytesLength;
Bytes = new byte[bytesLength];
System.Array.Copy(byteArray, start, Bytes, 0, bytesLength);
}
}

public sealed class AccountId32 : BaseType
{
public Substrate.NetApi.Model.Types.Primitive.U8[] Value { get; set; } = default!;

public override System.String TypeName()
{
return "AccountId32";
}

public override int TypeSize
{
get
{
return 32;
}
}

public override System.Byte[] Encode()
{
var result = new List<byte>();
foreach (var v in Value)
{
result.AddRange(v.Encode());
}

return result.ToArray();
}

public override void Decode(byte[] byteArray, ref int p)
{
var start = p;
var array = new Substrate.NetApi.Model.Types.Primitive.U8[TypeSize];
for (var i = 0; i < array.Length; i++)
{
var t = new Substrate.NetApi.Model.Types.Primitive.U8();
t.Decode(byteArray, ref p);
array[i] = t;
}

var bytesLength = p - start;
Bytes = new byte[bytesLength];
System.Array.Copy(byteArray, start, Bytes, 0, bytesLength);
Value = array;
}

public void Create(Substrate.NetApi.Model.Types.Primitive.U8[] array)
{
Value = array;
Bytes = Encode();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
using System.Text;
using System.Threading.Tasks;

namespace Substrate.NET.Metadata.Conversion.Tests
namespace Substrate.NET.Metadata.Tests.Conversion
{
internal class ConversionBuilderTest
{
Expand Down
95 changes: 95 additions & 0 deletions Substrate.NET.Metadata.Tests/Conversion/CustomNodesBuilderTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
using Substrate.NET.Metadata.Base;
using Substrate.NET.Metadata.Base.Portable;
using Substrate.NET.Metadata.Conversion.Internal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Substrate.NET.Metadata.Tests.Conversion
{
internal class CustomNodesBuilderTests
{
[Test]
public void CreateCustomComposite_ShouldReturnCompositeBuilder()
{
var conversion = new ConversionBuilder(new List<PortableType>());
var customNodeBuilder = new CustomNodeBuilder();

var accountInfoBuilder = customNodeBuilder
.CreateCustomComposite()
.AddField("nonce", "Index")
.AddField("refcount", "u8")
.AddField("data", "AccountData")
.WithPath("frame_system", "accountInfo")
.Build(conversion);

Assert.That(accountInfoBuilder, Is.Not.Null);
}

[Test]
public void CreateCustomComposite_WhenCallByParentNode_ShouldReturnTheOverrideOne()
{
var conversion = new ConversionBuilder(new List<PortableType>());
var customNodeBuilder = new CustomNodeBuilder();

var accountDataBuilder = customNodeBuilder
.CreateCustomComposite()
.AddField("free", "Balance")
.AddField("notFree", "Balance")
.WithPath("pallet_balance", "types", "AccountData");

customNodeBuilder.Build(conversion);

var res = conversion.BuildPortableTypes("AccountInfo");

// We should get the AccountInfo from v14 but with our override of AccountData
var accountInfo = conversion.PortableTypes.SingleOrDefault(x => x.Id.Value == res.Value);

Assert.That(accountInfo, Is.Not.Null);

var accountInfoComposite = accountInfo.Ty.TypeDef.Value2 as TypeDefComposite;

var accountData = conversion.PortableTypes.SingleOrDefault(x => x.Id.Value == accountInfoComposite!.Fields.Value[^1].FieldTy.Value);
var accountDataComposite = accountData!.Ty.TypeDef.Value2 as TypeDefComposite;

Assert.Multiple(() =>
{
Assert.That(accountDataComposite!.Fields.Value[0].Name.Value.Value, Is.EqualTo("free"));
Assert.That(accountDataComposite!.Fields.Value[1].Name.Value.Value, Is.EqualTo("notFree"));
});
}

[Test]
public void CustomComposite_WithSpecifiedVersionRange()
{
var customNodeBuilder = new CustomNodeBuilder();

var accountDataBuilder = customNodeBuilder
.CreateCustomComposite()
.FromVersion(10)
.ToVersion(20);

Assert.Multiple(() =>
{
Assert.That(accountDataBuilder.IsVersionValid(10), Is.True);
Assert.That(accountDataBuilder.IsVersionValid(20), Is.True);
Assert.That(accountDataBuilder.IsVersionValid(15), Is.True);
Assert.That(accountDataBuilder.IsVersionValid(9), Is.False);
Assert.That(accountDataBuilder.IsVersionValid(30), Is.False);
});
}

[Test]
public void CustomComposite_WithNoVersionSpecified()
{
var customNodeBuilder = new CustomNodeBuilder();

var accountDataBuilder = customNodeBuilder
.CreateCustomComposite();

Assert.That(accountDataBuilder.IsVersionValid(10), Is.True);
}
}
}
12 changes: 12 additions & 0 deletions Substrate.NET.Metadata.Tests/MetadataServiceV13Test.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Substrate.NET.Metadata.Conversion;
using Substrate.NET.Metadata.Service;
using Substrate.NET.Metadata.V13;
using Substrate.NET.Metadata.V14;

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

Assert.Throws<MetadataConversionException>(() => storageEntry.ToStorageEntryMetadataV14(new Metadata.Conversion.Internal.ConversionBuilder(new List<Base.Portable.PortableType>())));
}

[Test]
public void MetadataV13_WithSpecificVersion_ConvertToNetApiMetadata_ShouldSucceed()
{
var metadata = new MetadataV13(readMetadataFromFile("V13\\MetadataV13_9050"));

var tov14 = metadata.ToMetadataV14(9050);
var netApiMetadata = tov14.ToNetApiMetadata();

Assert.That(netApiMetadata, Is.Not.Null);
}
}
}
7 changes: 5 additions & 2 deletions Substrate.NET.Metadata.Tests/MetadataServiceV14Test.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,12 @@ public void MetadataV14_V9270_And_V9280_PalletHasChanged_ShouldSucceed()
}

[Test]
public void MetadataV14_ConvertToNetApiMetadata_ShouldSucceed()
[TestCase("V14\\MetadataV14_1003000")]
[TestCase("V14\\MetadataV14_1002007")]
[TestCase("V14\\MetadataV14_9270")]
public void MetadataV14_ConvertToNetApiMetadata_ShouldSucceed(string metadataPath)
{
var metadata = new MetadataV14(readMetadataFromFile("V14\\MetadataV14_9270"));
var metadata = new MetadataV14(readMetadataFromFile(metadataPath));
var netApiMetadata = metadata.ToNetApiMetadata();

Assert.That(netApiMetadata, Is.Not.Null);
Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@
<None Update="Mocks\V13\MetadataV13_9100.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Mocks\V14\MetadataV14_1003000.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Mocks\V14\MetadataV14_9110.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Expand All @@ -112,6 +115,9 @@
<None Update="Mocks\V14\MetadataV14_9420.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Mocks\V14\MetadataV14_1002007.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Mocks\V14\MetadataV14_9430.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Expand Down
2 changes: 1 addition & 1 deletion Substrate.NET.Metadata.sln
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Substrate.NET.Metadata", "S
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Substrate.NET.Metadata.Tests", "Substrate.NET.Metadata.Tests\Substrate.NET.Metadata.Tests.csproj", "{4698095E-1C43-40BA-925B-B9333599E0E4}"
EndProject
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}"
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}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down
Loading

0 comments on commit 96adc23

Please sign in to comment.