diff --git a/Substrate.NET.Metadata.Node.Tests/ConvertToV14Test.cs b/Substrate.NET.Metadata.Node.Tests/ConvertToV14Test.cs
new file mode 100644
index 0000000..ab23f57
--- /dev/null
+++ b/Substrate.NET.Metadata.Node.Tests/ConvertToV14Test.cs
@@ -0,0 +1,86 @@
+using Substrate.NET.Metadata.Conversion;
+using Substrate.NET.Metadata.V10;
+using Substrate.NET.Metadata.V11;
+using Substrate.NET.Metadata.V12;
+using Substrate.NET.Metadata.V13;
+using Substrate.NET.Metadata.V9;
+using Substrate.NetApi;
+using Substrate.NetApi.Model.Extrinsics;
+using Substrate.NetApi.Model.Meta;
+
+namespace Substrate.NET.Metadata.Node.Tests
+{
+    public class ConvertToV14Test
+    {
+        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();
+        }
+
+        [Test]
+        [TestCase("0xc0096358534ec8d21d01d34b836eed476a1c343f8724fa2153dc0725ad797a90", 11)]
+        [TestCase("0xa15bf122d7a9b2cd07956c3af8f7eda61298aff0a3bd1193018df413d982a4ef", 11)]
+        [TestCase("0x49a695416fcf55487adf9b9f5808619cee6618bd285a0119a78db60c5a7f3e13", 11)]
+        [TestCase("0xdab56553594fd489adc085d2f83f3dcb65f5de5b1878325d5547fcf72b6dd6b3", 11)]
+        [TestCase("0xaff11447ba47e853bcadb73920c0780013e581a0286831eadce0e48bf1db9942", 11)]
+        [TestCase("0x4eba9b7a60fb063fbd8b9ceb8028c1c7b5a3cc2ea7b0ad703885ce580dee327c", 11)]
+        [TestCase("0x773e8d8c1fdcbc94d79bb2cdcaf2f7fca5ff869d34c50171fe50ac1640f3e05c", 11)]
+        [TestCase("0x209d24943d81e5910bfb7a57c8a5c3037c4a434af7c486a536d4f96a2160c9f5", 11)]
+        [TestCase("0x3eef3df8dd7eedfe6baaed544dcef9c36ee7a142035bd6ae3fd7fd2969ad5933", 11)]
+        [TestCase("0x4f61e8e6017cce5a10e2de7340061a037895411c19e7bc27f607953d8a56a943", 11)]
+        [TestCase("0x7cf0e5e3671b02ca341ab439453e1a9ca6616c6e351bdfa8cbb6f5124a8224b8", 11)]
+        [TestCase("0x349399f6b6481070047626f184d0152699bd02cb71040ef045adefc4f8daec5b", 11)]
+        [TestCase("0xab6f40697e72d0a4ab0d105145b1ddc1bd8cead0bb1d6a13f4ac1a05508b1882", 11)]
+        [TestCase("0x78433cba37c0cbc777faad71f27e21094defe24451033dd4d9a0443a1dc291b2", 11)]
+        [TestCase("0x9a18fb9522d9688eadefb59bf7389fc0deaf219b080a462d6db5ee1d3ec79562", 11)]
+        [TestCase("0xe187cabcfb9d30b66fae7257f3820b947c89b65e6e20f6ead2af4fd78926825f", 11)]
+        [TestCase("0xd85988f4f7bc3594200fd5f8e738153260f2ba342b56d9bf4edabf9209c65ae0", 11)]
+        [TestCase("0x8a0f28f399d3a85643413435e5a001c4ade7b8195eaf7e91f399549f192a56c7", 11)]
+        [TestCase("0x0b40f111395a0871b1a59da4bd8587bcddf662e3e7b4ba06d8862a44dacf6256", 12)]
+        [TestCase("0x780cd3091ef9cdc3a94dbcdfa7908d6120f5e037a1e534b4f18249c37005a533", 12)]
+        [TestCase("0x26fa4c7e27aad01f5a8367aefece17f8c0940b75423628d52a8c07a203bd2458", 12)]
+        [TestCase("0xd00026d2bdca30cd20f7c361544e9651041107a1fd35ea447d8dfabb5001960f", 12)]
+        [TestCase("0x766a02e9abe37328ad0dee3a64aad557dd1bade9e9f27849a9cf5838c0e7e6bb", 12)]
+        [TestCase("0x8a8a7aa9ac863359b2cc609b836e3ebd7086d775c31f8c177f183ed9ffa71fa5", 12)]
+        [TestCase("0x89f4608b568a05a89737bc826a32f8677f2646a5773312d7dee3a667458e5a98", 13)]
+        [TestCase("0xddca674d4e6e4935b1e5e81ed697f7ce027c2a9602523424bcc8dee3184e4863", 13)]
+        [TestCase("0x4b34bd42835a084af0f441c5986d216b18a85abb4d03762096692e6f06365203", 13)]
+        [TestCase("0x8192df1609d4478d1c1fcf5d39975596a8162d42d745c141c22148b0931708f2", 13)]
+        public async Task ConvertMetadataToV14_ShouldSucceedAsync(string blockHash, int version)
+        {
+            var metadataHex = await _substrateClient.State.GetMetaDataAsync(Utils.HexToByteArray(blockHash), CancellationToken.None);
+
+            IMetadataToV14 metadata = version switch
+            {
+                9 => new MetadataV9(metadataHex),
+                10 => new MetadataV10(metadataHex),
+                11 => new MetadataV11(metadataHex),
+                12 => new MetadataV12(metadataHex),
+                13 => new MetadataV13(metadataHex),
+                _ => throw new Exception()
+            };
+
+            var v14 = metadata.ToMetadataV14();
+
+            Assert.That(v14, Is.Not.Null);
+
+            // Now let's convert to NetApi classes (ok this should be done in another UT)
+            var v14NetApi = v14.ToNetApiMetadata();
+
+            Assert.That(v14NetApi, Is.Not.Null);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Substrate.NET.Metadata.Node.Tests/GlobalUsings.cs b/Substrate.NET.Metadata.Node.Tests/GlobalUsings.cs
new file mode 100644
index 0000000..cefced4
--- /dev/null
+++ b/Substrate.NET.Metadata.Node.Tests/GlobalUsings.cs
@@ -0,0 +1 @@
+global using NUnit.Framework;
\ No newline at end of file
diff --git a/Substrate.NET.Metadata.Node.Tests/Substrate.NET.Metadata.Node.Tests.csproj b/Substrate.NET.Metadata.Node.Tests/Substrate.NET.Metadata.Node.Tests.csproj
new file mode 100644
index 0000000..df76951
--- /dev/null
+++ b/Substrate.NET.Metadata.Node.Tests/Substrate.NET.Metadata.Node.Tests.csproj
@@ -0,0 +1,30 @@
+
+
+  
+    net8.0
+    enable
+    enable
+
+    false
+    true
+  
+
+  
+    
+    
+    
+    
+      all
+      runtime; build; native; contentfiles; analyzers; buildtransitive
+    
+    
+      all
+      runtime; build; native; contentfiles; analyzers; buildtransitive
+    
+  
+
+  
+    
+  
+
+
diff --git a/Substrate.NET.Metadata.Tests/Conversion/ConversionBuilderTest.cs b/Substrate.NET.Metadata.Tests/Conversion/ConversionBuilderTest.cs
new file mode 100644
index 0000000..ea47c54
--- /dev/null
+++ b/Substrate.NET.Metadata.Tests/Conversion/ConversionBuilderTest.cs
@@ -0,0 +1,170 @@
+using Microsoft.VisualBasic;
+using Substrate.NET.Metadata.Base;
+using Substrate.NET.Metadata.Base.Portable;
+using Substrate.NET.Metadata.Conversion.Internal;
+using Substrate.NetApi.Model.Types.Base;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Substrate.NET.Metadata.Conversion.Tests
+{
+    internal class ConversionBuilderTest
+    {
+        private ConversionBuilder _builder;
+        #region Setup
+        [SetUp]
+        public void Setup() {
+            _builder = new ConversionBuilder(InitPortableRegistry().ToList());
+        }
+
+        private static PortableType[] InitPortableRegistry()
+        {
+            var portableRegistry = new PortableRegistry();
+            portableRegistry.Create(new List().ToArray());
+            var pt = portableRegistry.Value;
+            Assert.That(pt.Length, Is.EqualTo(0));
+            return pt;
+        }
+        #endregion
+
+        [Test]
+        [TestCase("u32")]
+        public void GetNode_FromPrimitive_ShouldSucceed(string primitiveType)
+        {
+            var res = _builder.GetPortableType(primitiveType);
+
+            Assert.That(res.portableType.Ty.TypeDef.Value, Is.EqualTo(TypeDefEnum.Primitive));
+            Assert.That(((BaseEnum)res.portableType.Ty.TypeDef.Value2).Value, Is.EqualTo(TypeDefPrimitive.U32));
+        }
+
+        [Test]
+        [TestCase("Vec>", "System")]
+        public void GetSystemEvent_WhenOverrided_ShouldReturnOverride(string rustType, string palletContext = "")
+        {
+            _builder.CurrentPallet = palletContext;
+            _builder.CreateEventBlockchainRuntimeEvent();
+            //_builder.AddEventRuntimeLookup(palletContext, new Variant[0]);
+            var res = _builder.BuildPortableTypes(rustType);
+
+            Assert.That(res.Value, Is.EqualTo(18), "Index are not equals");
+        }
+
+        [Test]
+        [TestCase("TaskAddress", 29, 2)]
+        [TestCase("SignedSubmissionOf", 504, 61)]
+        [TestCase("BalanceOf", 6, 1)]
+        [TestCase("SubmissionIndicesOf", 502, 5)]
+        [TestCase("[BalanceOf; 4]", 1000, 2)]
+        [TestCase("Approvals", 14, 2)]
+        [TestCase("(Vec>,\n BalanceOf)", 1000, 9)]
+        [TestCase("&[u8]", 10, 2, "Claims")]
+        [TestCase("Vec>", 1000, 5)]
+        [TestCase("Vec>", 1000, 2)]
+        [TestCase("LeasePeriod", 4, 1)]
+        [TestCase("LockIdentifier", 125, 2)]
+        [TestCase("(T::BlockNumber, Hash)", 1000, 5)]
+        [TestCase("(BalanceOf, Vec)", 1000, 6)]
+        [TestCase("AuthorityId", 46, 4, "ImOnline")]
+        [TestCase("AuthorityId", 137, 4, "Babe")]
+        [TestCase("Vec<(AuthorityId, BabeAuthorityWeight)>", 367, 7, "Babe")]
+        [TestCase("Vec", 48, 10)]
+        [TestCase("Vec<(T::ValidatorId, T::Keys)>", 411, 14)]
+        [TestCase("Vec", 55, 4)]
+        [TestCase("ReportIdOf", 9, 3)]
+        [TestCase("(T::AccountId, slashing::SpanIndex)", 400, 5)]
+        [TestCase("slashing::SpanRecord>", 406, 2)]
+        [TestCase("(EraIndex, T::AccountId)", 396, 5)]
+        [TestCase("Exposure>", 50, 8)]
+        [TestCase("Multiplier", 384, 2)]
+        [TestCase("MaybeRandomness", 370, 3)]
+        [TestCase("AccountInfo", 3, 4)]
+        [TestCase("schnorrkel::Randomness", 1, 2)]
+        [TestCase("[u8;32]", 1, 2)]
+        [TestCase("Option>", 30, 3)]
+        [TestCase("Vec<(T::BlockNumber, EventIndex)>", 105, 3)]
+        [TestCase("Vec<(EraIndex, SessionIndex)>", 105, 3)]
+        [TestCase("u32", 4, 1)]
+        [TestCase("ExtrinsicsWeight", 7, 2)] // Should be bound with PerDispatchClass
+        [TestCase("DispatchInfo", 22, 4)]
+        [TestCase("Weight", 8, 1)]
+        [TestCase("T::BlockNumber", 4, 1)]
+        [TestCase("T::AccountId", 0, 3)]
+        [TestCase("Vec", 55, 4)]
+        //[TestCase("Vec>", 22, 4)]
+        public void GetIndex_FromRustClass_ShouldSucceed(string rustType, int indexExpected, int lengthExpected, string palletContext = "")
+        {
+            _builder.CurrentPallet = palletContext;
+            var res = _builder.BuildPortableTypes(rustType);
+
+            Assert.That(res.Value, Is.EqualTo(indexExpected), "Index are not equals");
+            Assert.That(_builder.PortableTypes.Count, Is.EqualTo(lengthExpected), "Portable elements are not equals");
+        }
+
+        [Test]
+        [TestCase("Vec")] // 61
+        [TestCase("Vec<(ParaId, T::BlockNumber)>")]
+        [TestCase("Vec<(AccountId, Balance)>")]
+        [TestCase("Vec>")]
+        public void Build_FromSequence_ShouldSucceed(string sequenceClass)
+        {
+            var node = new NodeBuilderTypeUndefined(sequenceClass, string.Empty);
+            var res = ConversionBuilderTree.Build(node);
+
+            Assert.That(res, Is.Not.Null);
+            Assert.That(res.TypeDef == TypeDefEnum.Sequence);
+        }
+
+        [Test]
+        [TestCase("AccountId, Balance", new string[] { "AccountId", "Balance" })]
+        [TestCase("Toto, Titi", new string[] { "Toto", "Titi" })]
+        [TestCase("Titi, Toto", new string[] { "Titi", "Toto" })]
+        [TestCase("Titi, B>, Titi, L>", new string[] { "Titi, B>", "Titi, L>" })]
+        public void ExtractParameters_ShouldSucceed(string input, string[] expected)
+        {
+            var res = ConversionBuilderTree.ExtractParameters(input);
+
+            Assert.That(res, Is.Not.Null);
+            Assert.That(res.Count, Is.EqualTo(expected.Length));
+
+            for (int i = 0; i < res.Count; i++)
+            {
+                Assert.That(res[i], Is.EqualTo(expected[i]));
+            }
+        }
+
+        [Test]
+        [TestCase("[u8; 4]", "u8", 4)]
+        public void ExtractArray_ShouldSucceed(string input, string typeExpected, int lengthExpected)
+        {
+            var res = ConversionBuilderTree.ExtractArray(new NodeBuilderTypeUndefined(input, ""));
+
+            Assert.That(res, Is.Not.Null);
+            Assert.That(res.Children[0].Adapted, Is.EqualTo(typeExpected));
+            Assert.That(res.Length, Is.EqualTo(lengthExpected));
+        }
+
+        [Test]
+        public void ExtractPrimitive_ShouldSucceed()
+        {
+            var res = ConversionBuilderTree.ExtractPrimitive(new NodeBuilderTypeUndefined("u32", ""));
+
+            Assert.That(res, Is.Not.Null);
+            Assert.That(res.Primitive, Is.EqualTo(TypeDefPrimitive.U32));
+        }
+
+        [Test]
+        [TestCase("Vec", typeof(NodeBuilderTypeSequence))]
+        [TestCase("Option", typeof(NodeBuilderTypeOption))]
+        [TestCase("AccountData", typeof(NodeBuilderTypeComposite))]
+        public void ExtractGeneric_ShouldSucceed(string input, Type typeDefExpected)
+        {
+            var res = ConversionBuilderTree.ExtractGeneric(new NodeBuilderTypeUndefined(input, ""));
+
+            Assert.That(res, Is.Not.Null);
+            Assert.That(res.GetType(), Is.EqualTo(typeDefExpected));
+        }
+    }
+}
diff --git a/Substrate.NET.Metadata.Tests/Conversion/ConversionUtilsTests.cs b/Substrate.NET.Metadata.Tests/Conversion/ConversionUtilsTests.cs
new file mode 100644
index 0000000..78091eb
--- /dev/null
+++ b/Substrate.NET.Metadata.Tests/Conversion/ConversionUtilsTests.cs
@@ -0,0 +1,67 @@
+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 ConversionUtilsTests
+    {
+        [Test]
+        public void EndsWithArray_ShouldReturnTrue()
+        {
+            var array1 = new[] { 1, 2, 3, 4, 5 };
+            var array2 = new[] { 4, 5 };
+
+            var result = ConversionUtils.EndsWithArray(array1, array2);
+
+            Assert.That(result);
+        }
+
+        [Test]
+        public void EndsWithArray_ShouldReturnFalse()
+        {
+            var array1 = new[] { 1, 2, 3, 4, 5 };
+            var array2 = new[] { 4, 6 };
+
+            var result = ConversionUtils.EndsWithArray(array1, array2);
+
+            Assert.That(result, Is.False);
+        }
+
+        [Test]
+        public void AreArraysIdentical_WhenEquals_ShouldReturnTrue()
+        {
+            var array1 = new[] { 1, 2, 3, 4, 5 };
+            var array2 = new[] { 1, 2, 3, 4, 5 };
+
+            var result = ConversionUtils.AreArraysIdentical(array1, array2);
+
+            Assert.That(result);
+        }
+
+        [Test]
+        public void AreArraysIdentical_WhenNotSameSize_ShouldReturnFalse()
+        {
+            var array1 = new[] { 1, 2, 3, 4, 5 };
+            var array2 = new[] { 1, 2, 3, 4 };
+
+            var result = ConversionUtils.AreArraysIdentical(array1, array2);
+
+            Assert.That(result, Is.False);
+        }
+
+        [Test]
+        public void AreArraysIdentical_WhenDifferent_ShouldReturnFalse()
+        {
+            var array1 = new[] { 1, 2, 3, 4, 5 };
+            var array2 = new[] { 1, 2, 3, 4, 6 };
+
+            var result = ConversionUtils.AreArraysIdentical(array1, array2);
+
+            Assert.That(result, Is.False);
+        }
+    }
+}
diff --git a/Substrate.NET.Metadata.Tests/ImplementationCheckTests.cs b/Substrate.NET.Metadata.Tests/ImplementationCheckTests.cs
new file mode 100644
index 0000000..d85753b
--- /dev/null
+++ b/Substrate.NET.Metadata.Tests/ImplementationCheckTests.cs
@@ -0,0 +1,60 @@
+using Substrate.NetApi.Model.Types.Base;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Substrate.NET.Metadata.Tests
+{
+    internal class ImplementationCheckTests
+    {
+        [Test]
+        public void AllBaseTypeSubclasses_ShouldImplementEncode_ReturnsByteArray()
+        {
+            // Load the assembly containing Substrate.NET.Metadata classes
+            Assembly assembly = Assembly.Load("Substrate.NET.Metadata");
+
+            // Get all types that inherit from BaseType
+            var baseType = typeof(BaseType);
+            var types = assembly.GetTypes()
+                                .Where(t => baseType.IsAssignableFrom(t) && t.IsClass && !t.IsAbstract);
+
+            foreach (var type in types)
+            {
+                // Instantiate the class using its parameterless constructor (if available)
+                object instance = null;
+                try
+                {
+                    instance = Activator.CreateInstance(type);
+                }
+                catch (Exception ex)
+                {
+                    Assert.Fail($"Failed to instantiate type {type.Name}: {ex.Message}");
+                }
+
+                // Ensure the class has the Encode method
+                MethodInfo encodeMethod = type!.GetMethod("Encode");
+                Assert.That(encodeMethod, Is.Not.Null, $"Class {type.Name} does not implement the Encode() method.");
+
+                try
+                {
+                    _ = (byte[])encodeMethod!.Invoke(instance, null);
+                }
+                catch (TargetInvocationException ex) when (ex.InnerException is NotImplementedException)
+                {
+                    Assert.Fail($"Class {type.Name} throws NotImplementedException in Encode() method.");
+                }
+                catch (TargetInvocationException ex) when (ex.InnerException is NullReferenceException)
+                {
+                    Assert.Pass($"Class {type.Name} throws NullReferenceException in Encode() method. This is fine");
+                }
+                catch (Exception ex)
+                {
+                    Assert.Fail($"An unexpected exception occurred when invoking Encode() on {type.Name}: {ex.Message}");
+                }
+            }
+        }
+    }
+}
diff --git a/Substrate.NET.Metadata.Tests/MetadataServiceBasicTest.cs b/Substrate.NET.Metadata.Tests/MetadataServiceBasicTest.cs
index d2a1d59..096b33d 100644
--- a/Substrate.NET.Metadata.Tests/MetadataServiceBasicTest.cs
+++ b/Substrate.NET.Metadata.Tests/MetadataServiceBasicTest.cs
@@ -11,14 +11,6 @@ namespace Substrate.NET.Metadata.Tests
 {
     public class MetadataServiceBasicTest : MetadataBaseTest
     {
-        private MetadataService _metadataService;
-
-        [SetUp]
-        public void Setup()
-        {
-            _metadataService = new MetadataService();
-        }
-
         private IList generatePalletCallMetadataV9(int nb)
         {
             return Enumerable.Range(1, nb).Select(x => new PalletCallMetadataV9()
@@ -81,7 +73,7 @@ public void MetadataV9_PalletCallDiff_ShouldSuceed()
             calls2[2].Args.Value[0].CallType.Value = "Changed !";
             var calls_2 = new List() { calls2[1], calls2[2], calls2[3] };
 
-            var res = _metadataService.CompareName(calls_1, calls_2).ToList();
+            var res = MetadataUtils.CompareName(calls_1, calls_2).ToList();
 
             Assert.That(res, Is.Not.Null);
             Assert.That(res[0], Is.EqualTo((CompareStatus.Added, calls2[3])));
@@ -99,7 +91,7 @@ public void MetadataV9_PalletEventDiff_ShouldSuceed()
             calls2[2].Args.Value[0].Value = "Changed !";
             var calls_2 = new List() { calls2[1], calls2[2], calls2[3] };
 
-            var res = _metadataService.CompareName(calls_1, calls_2).ToList();
+            var res = MetadataUtils.CompareName(calls_1, calls_2).ToList();
 
             Assert.That(res, Is.Not.Null);
             Assert.That(res[0], Is.EqualTo((CompareStatus.Added, calls2[3])));
@@ -117,7 +109,7 @@ public void MetadataV9_PalletConstantDiff_ShouldSuceed()
             calls2[2].ConstantType.Value = "Changed !";
             var calls_2 = new List() { calls2[1], calls2[2], calls2[3] };
 
-            var res = _metadataService.CompareName(calls_1, calls_2).ToList();
+            var res = MetadataUtils.CompareName(calls_1, calls_2).ToList();
 
             Assert.That(res, Is.Not.Null);
             Assert.That(res[0], Is.EqualTo((CompareStatus.Added, calls2[3])));
@@ -135,7 +127,7 @@ public void MetadataV9_PalletErrorDiff_ShouldSuceed()
             calls2[2].Docs.Value[0].Value = "Changed !";
             var calls_2 = new List() { calls2[1], calls2[2], calls2[3] };
 
-            var res = _metadataService.CompareName(calls_1, calls_2).ToList();
+            var res = MetadataUtils.CompareName(calls_1, calls_2).ToList();
 
             Assert.That(res, Is.Not.Null);
             Assert.That(res[0], Is.EqualTo((CompareStatus.Added, calls2[3])));
@@ -177,25 +169,25 @@ public void Metadata_CheckDifferentialPallet_ShouldSuceed()
                 }
             };
 
-            Assert.That(_metadataService.CompareName(null, null).Count(), Is.EqualTo(0));
+            Assert.That(MetadataUtils.CompareName(null, null).Count(), Is.EqualTo(0));
 
-            var resOnlyFirstListNull = _metadataService.CompareName(m1, null);
+            var resOnlyFirstListNull = MetadataUtils.CompareName(m1, null);
             Assert.That(resOnlyFirstListNull.All(x => x.Item1 == CompareStatus.Removed), Is.True);
             Assert.That(resOnlyFirstListNull.Count(), Is.EqualTo(m1.Count));
 
-            var resOnlyFirstListEmpty = _metadataService.CompareName(m1, new List());
+            var resOnlyFirstListEmpty = MetadataUtils.CompareName(m1, new List());
             Assert.That(resOnlyFirstListEmpty.All(x => x.Item1 == CompareStatus.Removed), Is.True);
             Assert.That(resOnlyFirstListEmpty.Count(), Is.EqualTo(m1.Count));
 
-            var resOnlySecondListNull = _metadataService.CompareName(null, m2);
+            var resOnlySecondListNull = MetadataUtils.CompareName(null, m2);
             Assert.That(resOnlySecondListNull.All(x => x.Item1 == CompareStatus.Added), Is.True);
             Assert.That(resOnlySecondListNull.Count(), Is.EqualTo(m2.Count));
 
-            var resOnlySecondListEmpty = _metadataService.CompareName(null, m2);
+            var resOnlySecondListEmpty = MetadataUtils.CompareName(null, m2);
             Assert.That(resOnlySecondListEmpty.All(x => x.Item1 == CompareStatus.Added), Is.True);
             Assert.That(resOnlySecondListEmpty.Count(), Is.EqualTo(m2.Count));
 
-            var res = _metadataService.CompareName(m1, m2).ToList();
+            var res = MetadataUtils.CompareName(m1, m2).ToList();
             Assert.That(res[0].Item1, Is.EqualTo(CompareStatus.Added));
             Assert.That(res[1].Item1, Is.EqualTo(CompareStatus.Removed));
 
@@ -204,7 +196,7 @@ public void Metadata_CheckDifferentialPallet_ShouldSuceed()
         [Test]
         public void DifferentMetadataMajorVersion_ShouldFail()
         {
-            Assert.Throws(() => _metadataService.EnsureMetadataVersion(
+            Assert.Throws(() => MetadataUtils.EnsureMetadataVersion(
                 readMetadataFromFile("V11\\MetadataV11_0"), 
                 readMetadataFromFile("V14\\MetadataV14_9420")));
         }
@@ -213,7 +205,7 @@ public void DifferentMetadataMajorVersion_ShouldFail()
         public void MetadataV14_GetMetadataVersion_ShouldSucceed()
         {
             Assert.That(
-                _metadataService.GetMetadataVersion(readMetadataFromFile("V14\\MetadataV14_9420")), 
+                MetadataUtils.GetMetadataVersion(readMetadataFromFile("V14\\MetadataV14_9420")), 
                 Is.EqualTo(MetadataVersion.V14));
         }
     }
diff --git a/Substrate.NET.Metadata.Tests/MetadataServiceV10Test.cs b/Substrate.NET.Metadata.Tests/MetadataServiceV10Test.cs
index ca3579e..8be6fea 100644
--- a/Substrate.NET.Metadata.Tests/MetadataServiceV10Test.cs
+++ b/Substrate.NET.Metadata.Tests/MetadataServiceV10Test.cs
@@ -12,12 +12,12 @@ namespace Substrate.NET.Metadata.Tests
 {
     public class MetadataServiceV10Test : MetadataBaseTest
     {
-        private MetadataService _metadataService;
-
-        [SetUp]
-        public void Setup()
+        [Test]
+        public void MetadataV10_Encode_ShouldSucceed()
         {
-            _metadataService = new MetadataService();
+            var metadataSource = readMetadataFromFile("V10\\MetadataV10_Kusama_1032");
+
+            Assert.That(new MetadataV10(metadataSource).Encode(), Is.Not.Null);
         }
 
         [Test]
@@ -29,7 +29,7 @@ public void MetadataV10_SpecVersionCompare_V1032_And_V1039_ShouldSucceed()
             // TODO : debug this
             //Assert.That(_metadataService.EnsureMetadataVersion(metadataSource, metadataDestination), Is.EqualTo(MetadataVersion.V10));
 
-            var res = _metadataService.MetadataCompareV10(
+            var res = MetadataUtils.MetadataCompareV10(
                 new MetadataV10(metadataSource),
                 new MetadataV10(metadataDestination));
 
@@ -42,9 +42,9 @@ public void MetadataV10_SpecVersionCompare_V1039_And_V1040_ShouldSucceed()
             var metadataSource = readMetadataFromFile("V10\\MetadataV10_Kusama_1039");
             var metadataDestination = readMetadataFromFile("V10\\MetadataV10_Kusama_1040");
 
-            Assert.That(_metadataService.EnsureMetadataVersion(metadataSource, metadataDestination), Is.EqualTo(MetadataVersion.V10));
+            Assert.That(MetadataUtils.EnsureMetadataVersion(metadataSource, metadataDestination), Is.EqualTo(MetadataVersion.V10));
 
-            var res = _metadataService.MetadataCompareV10(
+            var res = MetadataUtils.MetadataCompareV10(
                 new MetadataV10(metadataSource),
                 new MetadataV10(metadataDestination));
 
@@ -58,8 +58,8 @@ public void MetadataV10_V1039_And_V1040_PalletHasChanged_ShouldSucceed()
             var metadataSource = readMetadataFromFile("V10\\MetadataV10_Kusama_1039");
             var metadataDestination = readMetadataFromFile("V10\\MetadataV10_Kusama_1040");
 
-            Assert.That(_metadataService.HasPalletChangedVersionBetween("Society", metadataSource, metadataDestination), Is.False);
-            Assert.That(_metadataService.HasPalletChangedVersionBetween("Balances", metadataSource, metadataDestination), Is.False);
+            Assert.That(MetadataUtils.HasPalletChangedVersionBetween("Society", metadataSource, metadataDestination), Is.False);
+            Assert.That(MetadataUtils.HasPalletChangedVersionBetween("Balances", metadataSource, metadataDestination), Is.False);
         }
     }
 }
diff --git a/Substrate.NET.Metadata.Tests/MetadataServiceV11Test.cs b/Substrate.NET.Metadata.Tests/MetadataServiceV11Test.cs
index 5c5c0d0..2abfb6c 100644
--- a/Substrate.NET.Metadata.Tests/MetadataServiceV11Test.cs
+++ b/Substrate.NET.Metadata.Tests/MetadataServiceV11Test.cs
@@ -1,17 +1,18 @@
 using Substrate.NET.Metadata.Base;
 using Substrate.NET.Metadata.Service;
 using Substrate.NET.Metadata.V11;
+using Substrate.NET.Metadata.V9;
 
 namespace Substrate.NET.Metadata.Tests
 {
     public class MetadataServiceV11Test : MetadataBaseTest
     {
-        private MetadataService _metadataService;
-
-        [SetUp]
-        public void Setup()
+        [Test]
+        public void MetadataV11_Encode_ShouldSucceed()
         {
-            _metadataService = new MetadataService();
+            var metadataSource = readMetadataFromFile("V11\\MetadataV11_0");
+
+            Assert.That(new MetadataV11(metadataSource).Encode(), Is.Not.Null);
         }
 
         [Test]
@@ -20,9 +21,9 @@ public void MetadataV11_SpecVersionCompare_V0_And_V1_ShouldSucceed()
             var metadataSource = readMetadataFromFile("V11\\MetadataV11_0");
             var metadataDestination = readMetadataFromFile("V11\\MetadataV11_1");
 
-            Assert.That(_metadataService.EnsureMetadataVersion(metadataSource, metadataDestination), Is.EqualTo(MetadataVersion.V11));
+            Assert.That(MetadataUtils.EnsureMetadataVersion(metadataSource, metadataDestination), Is.EqualTo(MetadataVersion.V11));
 
-            var res = _metadataService.MetadataCompareV11(
+            var res = MetadataUtils.MetadataCompareV11(
                 new MetadataV11(metadataSource),
                 new MetadataV11(metadataDestination));
 
@@ -51,9 +52,9 @@ public void MetadataV11_SpecVersionCompare_V6_And_V7_ShouldSucceed()
             var metadataSource = readMetadataFromFile("V11\\MetadataV11_6");
             var metadataDestination = readMetadataFromFile("V11\\MetadataV11_7");
 
-            Assert.That(_metadataService.EnsureMetadataVersion(metadataSource, metadataDestination), Is.EqualTo(MetadataVersion.V11));
+            Assert.That(MetadataUtils.EnsureMetadataVersion(metadataSource, metadataDestination), Is.EqualTo(MetadataVersion.V11));
 
-            var res = _metadataService.MetadataCompareV11(
+            var res = MetadataUtils.MetadataCompareV11(
                 new MetadataV11(metadataSource),
                 new MetadataV11(metadataDestination));
 
@@ -81,9 +82,9 @@ public void MetadataV11_SpecVersionCompare_V23_And_V24_ShouldSucceed()
             var metadataSource = readMetadataFromFile("V11\\MetadataV11_23");
             var metadataDestination = readMetadataFromFile("V11\\MetadataV11_24");
 
-            Assert.That(_metadataService.EnsureMetadataVersion(metadataSource, metadataDestination), Is.EqualTo(MetadataVersion.V11));
+            Assert.That(MetadataUtils.EnsureMetadataVersion(metadataSource, metadataDestination), Is.EqualTo(MetadataVersion.V11));
 
-            var res = _metadataService.MetadataCompareV11(
+            var res = MetadataUtils.MetadataCompareV11(
                 new MetadataV11(metadataSource),
                 new MetadataV11(metadataDestination));
 
@@ -133,10 +134,21 @@ public void MetadataV11_V23_And_V24_PalletHasChanged_ShouldSucceed()
             var metadataSource = readMetadataFromFile("V11\\MetadataV11_23");
             var metadataDestination = readMetadataFromFile("V11\\MetadataV11_24");
 
-            Assert.That(_metadataService.HasPalletChangedVersionBetween("Multisig", metadataSource, metadataDestination), Is.True);
+            Assert.That(MetadataUtils.HasPalletChangedVersionBetween("Multisig", metadataSource, metadataDestination));
 
             // Purschase has been removed, but does not count as changed
-            Assert.That(_metadataService.HasPalletChangedVersionBetween("Purchase", metadataSource, metadataDestination), Is.False);
+            Assert.That(MetadataUtils.HasPalletChangedVersionBetween("Purchase", metadataSource, metadataDestination), Is.False);
+        }
+
+        [Test]
+        public void MetadataV11_ConvertToV14_ShouldSucceed()
+        {
+            var metadataV11 = new MetadataV11(readMetadataFromFile("V11\\MetadataV11_0"));
+            Assert.That(metadataV11, Is.Not.Null);
+
+            var metadataV14 = metadataV11.ToMetadataV14();
+
+            Assert.That(metadataV14, Is.Not.Null);
         }
     }
 }
diff --git a/Substrate.NET.Metadata.Tests/MetadataServiceV12Test.cs b/Substrate.NET.Metadata.Tests/MetadataServiceV12Test.cs
index 47c169c..aeabdd1 100644
--- a/Substrate.NET.Metadata.Tests/MetadataServiceV12Test.cs
+++ b/Substrate.NET.Metadata.Tests/MetadataServiceV12Test.cs
@@ -6,12 +6,12 @@ namespace Substrate.NET.Metadata.Tests
 {
     public class MetadataServiceV12Test : MetadataBaseTest
     {
-        private MetadataService _metadataService;
-
-        [SetUp]
-        public void Setup()
+        [Test]
+        public void MetadataV12_Encode_ShouldSucceed()
         {
-            _metadataService = new MetadataService();
+            var metadataSource = readMetadataFromFile("V12\\MetadataV12_27");
+
+            Assert.That(new MetadataV12(metadataSource).Encode(), Is.Not.Null);
         }
 
         [Test]
@@ -20,9 +20,9 @@ public void MetadataV12_SpecVersionCompare_V27_And_V28_ShouldSucceed()
             var metadataSource = readMetadataFromFile("V12\\MetadataV12_27");
             var metadataDestination = readMetadataFromFile("V12\\MetadataV12_28");
 
-            Assert.That(_metadataService.EnsureMetadataVersion(metadataSource, metadataDestination), Is.EqualTo(MetadataVersion.V12));
+            Assert.That(MetadataUtils.EnsureMetadataVersion(metadataSource, metadataDestination), Is.EqualTo(MetadataVersion.V12));
 
-            var res = _metadataService.MetadataCompareV12(
+            var res = MetadataUtils.MetadataCompareV12(
                 new MetadataV12(metadataSource),
                 new MetadataV12(metadataDestination));
 
@@ -40,7 +40,7 @@ public void MetadataV12_SpecVersionCompare_V27_And_V28_ShouldSucceed()
             Assert.That(changedModules[0].ModuleName, Is.EqualTo("Babe"));
             Assert.That(changedModules[0].Storage.First().Item2.status, Is.EqualTo(CompareStatus.Added));
             Assert.That(changedModules[0].Storage.First().Item2.storage.Name.Value, Is.EqualTo("NextAuthorities"));
-            Assert.That(changedModules[0].HasStorageAdded("NextAuthorities"), Is.True);
+            Assert.That(changedModules[0].HasStorageAdded("NextAuthorities"));
 
             // Now let's test ElectionsPhragmen which changed a lot
             var electionPhragmenModule = changedModules[1];
@@ -53,32 +53,32 @@ public void MetadataV12_SpecVersionCompare_V27_And_V28_ShouldSucceed()
             var electionPhragmenCalls = electionPhragmenModule.Calls.ToList();
             Assert.That(electionPhragmenCalls[0].Item1, Is.EqualTo(CompareStatus.Added));
             Assert.That(electionPhragmenCalls[0].Item2.Name.Value, Is.EqualTo("clean_defunct_voters"));
-            Assert.That(electionPhragmenModule.HasCallAdded("clean_defunct_voters"), Is.True);
+            Assert.That(electionPhragmenModule.HasCallAdded("clean_defunct_voters"));
 
             Assert.That(electionPhragmenCalls[1].Item1, Is.EqualTo(CompareStatus.Removed));
             Assert.That(electionPhragmenCalls[1].Item2.Name.Value, Is.EqualTo("report_defunct_voter"));
-            Assert.That(electionPhragmenModule.HasCallRemoved("report_defunct_voter"), Is.True);
+            Assert.That(electionPhragmenModule.HasCallRemoved("report_defunct_voter"));
 
             var electionPhragmenConstants = electionPhragmenModule.Constants.ToList();
             Assert.That(electionPhragmenConstants[0].Item1, Is.EqualTo(CompareStatus.Added));
             Assert.That(electionPhragmenConstants[0].Item2.Name.Value, Is.EqualTo("VotingBondBase"));
-            Assert.That(electionPhragmenModule.HasConstantAdded("VotingBondBase"), Is.True);
+            Assert.That(electionPhragmenModule.HasConstantAdded("VotingBondBase"));
 
             Assert.That(electionPhragmenConstants[1].Item1, Is.EqualTo(CompareStatus.Added));
             Assert.That(electionPhragmenConstants[1].Item2.Name.Value, Is.EqualTo("VotingBondFactor"));
 
             Assert.That(electionPhragmenConstants[2].Item1, Is.EqualTo(CompareStatus.Removed));
             Assert.That(electionPhragmenConstants[2].Item2.Name.Value, Is.EqualTo("VotingBond"));
-            Assert.That(electionPhragmenModule.HasConstantRemoved("VotingBond"), Is.True);
+            Assert.That(electionPhragmenModule.HasConstantRemoved("VotingBond"));
 
             var electionPhragmenEvents = electionPhragmenModule.Events.ToList();
             Assert.That(electionPhragmenEvents[0].Item1, Is.EqualTo(CompareStatus.Added));
             Assert.That(electionPhragmenEvents[0].Item2.Name.Value, Is.EqualTo("Renounced"));
-            Assert.That(electionPhragmenModule.HasEventAdded("Renounced"), Is.True);
+            Assert.That(electionPhragmenModule.HasEventAdded("Renounced"));
 
             Assert.That(electionPhragmenEvents[1].Item1, Is.EqualTo(CompareStatus.Removed));
             Assert.That(electionPhragmenEvents[1].Item2.Name.Value, Is.EqualTo("MemberRenounced"));
-            Assert.That(electionPhragmenModule.HasEventRemoved("MemberRenounced"), Is.True);
+            Assert.That(electionPhragmenModule.HasEventRemoved("MemberRenounced"));
 
             Assert.That(electionPhragmenEvents[2].Item1, Is.EqualTo(CompareStatus.Removed));
             Assert.That(electionPhragmenEvents[2].Item2.Name.Value, Is.EqualTo("VoterReported"));
@@ -86,7 +86,7 @@ public void MetadataV12_SpecVersionCompare_V27_And_V28_ShouldSucceed()
             var electionPhragmenErrors = electionPhragmenModule.Errors.ToList();
             Assert.That(electionPhragmenErrors[0].Item1, Is.EqualTo(CompareStatus.Added));
             Assert.That(electionPhragmenErrors[0].Item2.Name.Value, Is.EqualTo("RunnerUpSubmit"));
-            Assert.That(electionPhragmenModule.HasErrorAdded("RunnerUpSubmit"), Is.True);
+            Assert.That(electionPhragmenModule.HasErrorAdded("RunnerUpSubmit"));
 
             Assert.That(electionPhragmenErrors[1].Item1, Is.EqualTo(CompareStatus.Added));
             Assert.That(electionPhragmenErrors[1].Item2.Name.Value, Is.EqualTo("InvalidWitnessData"));
@@ -96,7 +96,7 @@ public void MetadataV12_SpecVersionCompare_V27_And_V28_ShouldSucceed()
 
             Assert.That(electionPhragmenErrors[3].Item1, Is.EqualTo(CompareStatus.Removed));
             Assert.That(electionPhragmenErrors[3].Item2.Name.Value, Is.EqualTo("InvalidCandidateCount"));
-            Assert.That(electionPhragmenModule.HasErrorRemoved("InvalidCandidateCount"), Is.True);
+            Assert.That(electionPhragmenModule.HasErrorRemoved("InvalidCandidateCount"));
         }
 
         [Test]
@@ -105,9 +105,9 @@ public void MetadataV12_V27_And_V28_PalletHasChanged_ShouldSucceed()
             var metadataSource = readMetadataFromFile("V12\\MetadataV12_27");
             var metadataDestination = readMetadataFromFile("V12\\MetadataV12_28");
 
-            Assert.That(_metadataService.HasPalletChangedVersionBetween("ElectionsPhragmen", metadataSource, metadataDestination), Is.True);
+            Assert.That(MetadataUtils.HasPalletChangedVersionBetween("ElectionsPhragmen", metadataSource, metadataDestination));
 
-            Assert.That(_metadataService.HasPalletChangedVersionBetween("Balances", metadataSource, metadataDestination), Is.False);
+            Assert.That(MetadataUtils.HasPalletChangedVersionBetween("Balances", metadataSource, metadataDestination), Is.False);
         }
     }
 }
diff --git a/Substrate.NET.Metadata.Tests/MetadataServiceV13Test.cs b/Substrate.NET.Metadata.Tests/MetadataServiceV13Test.cs
index 7b0e717..3bb270c 100644
--- a/Substrate.NET.Metadata.Tests/MetadataServiceV13Test.cs
+++ b/Substrate.NET.Metadata.Tests/MetadataServiceV13Test.cs
@@ -1,4 +1,5 @@
 using Substrate.NET.Metadata.Base;
+using Substrate.NET.Metadata.Conversion;
 using Substrate.NET.Metadata.Service;
 using Substrate.NET.Metadata.V13;
 
@@ -6,12 +7,12 @@ namespace Substrate.NET.Metadata.Tests
 {
     public class MetadataServiceV13Test : MetadataBaseTest
     {
-        private MetadataService _metadataService;
-
-        [SetUp]
-        public void Setup()
+        [Test]
+        public void MetadataV13_Encode_ShouldSucceed()
         {
-            _metadataService = new MetadataService();
+            var metadataSource = readMetadataFromFile("V13\\MetadataV13_9080");
+
+            Assert.That(new MetadataV13(metadataSource).Encode(), Is.Not.Null);
         }
 
         [Test]
@@ -20,9 +21,9 @@ public void MetadataV13_SpecVersionCompare_V9080_And_V9090_ShouldSucceed()
             var metadataSource = readMetadataFromFile("V13\\MetadataV13_9080");
             var metadataDestination = readMetadataFromFile("V13\\MetadataV13_9090");
 
-            Assert.That(_metadataService.EnsureMetadataVersion(metadataSource, metadataDestination), Is.EqualTo(MetadataVersion.V13));
+            Assert.That(MetadataUtils.EnsureMetadataVersion(metadataSource, metadataDestination), Is.EqualTo(MetadataVersion.V13));
 
-            var res = _metadataService.MetadataCompareV13(
+            var res = MetadataUtils.MetadataCompareV13(
                 new MetadataV13(metadataSource),
                 new MetadataV13(metadataDestination));
 
@@ -30,16 +31,16 @@ public void MetadataV13_SpecVersionCompare_V9080_And_V9090_ShouldSucceed()
             var changedModules = res.ChangedModules.ToList();
 
             Assert.That(changedModules[0].ModuleName, Is.EqualTo("Authorship"));
-            Assert.That(changedModules[0].HasConstantAdded("UncleGenerations"), Is.True);
+            Assert.That(changedModules[0].HasConstantAdded("UncleGenerations"));
 
             Assert.That(changedModules[1].ModuleName, Is.EqualTo("Balances"));
-            Assert.That(changedModules[1].HasConstantAdded("MaxLocks"), Is.True);
-            Assert.That(changedModules[1].HasConstantAdded("MaxReserves"), Is.True);
+            Assert.That(changedModules[1].HasConstantAdded("MaxLocks"));
+            Assert.That(changedModules[1].HasConstantAdded("MaxReserves"));
 
             Assert.That(changedModules[2].ModuleName, Is.EqualTo("Democracy"));
             Assert.That(changedModules[2].Constants.Count(), Is.EqualTo(2));
-            Assert.That(changedModules[2].HasConstantAdded("InstantAllowed"), Is.True);
-            Assert.That(changedModules[2].HasConstantAdded("MaxProposals"), Is.True);
+            Assert.That(changedModules[2].HasConstantAdded("InstantAllowed"));
+            Assert.That(changedModules[2].HasConstantAdded("MaxProposals"));
             Assert.That(changedModules[2].Errors.Count(), Is.EqualTo(5));
             Assert.That(changedModules[2].HasErrorAdded("test"), Is.False);
             Assert.That(changedModules[2].HasErrorRemoved("test2"), Is.False);
@@ -51,8 +52,19 @@ public void MetadataV13_V9080_And_V9090_PalletHasChanged_ShouldSucceed()
             var metadataSource = readMetadataFromFile("V13\\MetadataV13_9080");
             var metadataDestination = readMetadataFromFile("V13\\MetadataV13_9090");
 
-            Assert.That(_metadataService.HasPalletChangedVersionBetween("Balances", metadataSource, metadataDestination), Is.True);
-            Assert.That(_metadataService.HasPalletChangedVersionBetween("Babe", metadataSource, metadataDestination), Is.False);
+            Assert.That(MetadataUtils.HasPalletChangedVersionBetween("Balances", metadataSource, metadataDestination));
+            Assert.That(MetadataUtils.HasPalletChangedVersionBetween("Babe", metadataSource, metadataDestination), Is.False);
+        }
+
+        [Test]
+        public void StorageEntryMetadataV13_WhenNMap_ShouldThrowException()
+        {
+            var storageEntry = new StorageEntryMetadataV13();
+            storageEntry.StorageType = new NetApi.Model.Types.Base.BaseEnumExt();
+            
+            storageEntry.StorageType.Value = StorageType.Type.NMap;
+
+            Assert.Throws(() => storageEntry.ToStorageEntryMetadataV14(new Metadata.Conversion.Internal.ConversionBuilder(new List())));
         }
     }
 }
diff --git a/Substrate.NET.Metadata.Tests/MetadataServiceV14Test.cs b/Substrate.NET.Metadata.Tests/MetadataServiceV14Test.cs
index 1c0a4ad..4c23bcf 100644
--- a/Substrate.NET.Metadata.Tests/MetadataServiceV14Test.cs
+++ b/Substrate.NET.Metadata.Tests/MetadataServiceV14Test.cs
@@ -6,12 +6,12 @@ namespace Substrate.NET.Metadata.Tests
 {
     public class MetadataServiceV14Test : MetadataBaseTest
     {
-        private MetadataService _metadataService;
-
-        [SetUp]
-        public void Setup()
+        [Test]
+        public void MetadataV14_Encode_ShouldSucceed()
         {
-            _metadataService = new MetadataService();
+            var metadataSource = readMetadataFromFile("V14\\MetadataV14_9110");
+
+            Assert.That(new MetadataV14(metadataSource).Encode(), Is.Not.Null);
         }
 
         [Test]
@@ -20,9 +20,9 @@ public void MetadataV14_SpecVersionCompare_V9110_And_V9122_ShouldSucceed()
             var metadataSource = readMetadataFromFile("V14\\MetadataV14_9110");
             var metadataDestination = readMetadataFromFile("V14\\MetadataV14_9122");
 
-            Assert.That(_metadataService.EnsureMetadataVersion(metadataSource, metadataDestination), Is.EqualTo(MetadataVersion.V14));
+            Assert.That(MetadataUtils.EnsureMetadataVersion(metadataSource, metadataDestination), Is.EqualTo(MetadataVersion.V14));
 
-            var res = _metadataService.MetadataCompareV14(
+            var res = MetadataUtils.MetadataCompareV14(
                 new MetadataV14(metadataSource),
                 new MetadataV14(metadataDestination));
 
@@ -35,9 +35,9 @@ public void MetadataV14_SpecVersionCompare_V9420_And_V9430_ShouldSucceed()
             var metadataSource = readMetadataFromFile("V14\\MetadataV14_9420");
             var metadataDestination = readMetadataFromFile("V14\\MetadataV14_9430");
 
-            Assert.That(_metadataService.EnsureMetadataVersion(metadataSource, metadataDestination), Is.EqualTo(MetadataVersion.V14));
+            Assert.That(MetadataUtils.EnsureMetadataVersion(metadataSource, metadataDestination), Is.EqualTo(MetadataVersion.V14));
 
-            var res = _metadataService.MetadataCompareV14(
+            var res = MetadataUtils.MetadataCompareV14(
                 new MetadataV14(metadataSource),
                 new MetadataV14(metadataDestination));
 
@@ -50,31 +50,31 @@ public void MetadataV14_SpecVersionCompare_V9370_And_V9420_ShouldSucceed()
             var metadataSource = readMetadataFromFile("V14\\MetadataV14_9370");
             var metadataDestination = readMetadataFromFile("V14\\MetadataV14_9420");
 
-            Assert.That(_metadataService.EnsureMetadataVersion(metadataSource, metadataDestination), Is.EqualTo(MetadataVersion.V14));
+            Assert.That(MetadataUtils.EnsureMetadataVersion(metadataSource, metadataDestination), Is.EqualTo(MetadataVersion.V14));
 
-            var res = _metadataService.MetadataCompareV14(
+            var res = MetadataUtils.MetadataCompareV14(
                 new MetadataV14(metadataSource),
                 new MetadataV14(metadataDestination));
 
             Assert.That(res, Is.Not.Null);
 
-            Assert.That(res.AddedModules.Any(x => x.ModuleName == "ConvictionVoting"), Is.True);
-            Assert.That(res.AddedModules.Any(x => x.ModuleName == "Referenda"), Is.True);
-            Assert.That(res.AddedModules.Any(x => x.ModuleName == "Whitelist"), Is.True);
+            Assert.That(res.AddedModules.Any(x => x.ModuleName == "ConvictionVoting"));
+            Assert.That(res.AddedModules.Any(x => x.ModuleName == "Referenda"));
+            Assert.That(res.AddedModules.Any(x => x.ModuleName == "Whitelist"));
 
             // Some basic other assertions on Balance pallet I checked with file compare
             var palletBalance = res.ChangedModules.FirstOrDefault(x => x.ModuleName == "Balances");
 
 
             // Some calls has been added and one has been removed
-            var callsMethodChanged = palletBalance.Calls.LookupDifferentialType.TypeVariant.Elems;
+            var callsMethodChanged = palletBalance!.Calls.LookupDifferentialType.TypeVariant.Elems;
             Assert.That(callsMethodChanged.Count(), Is.GreaterThan(1)); 
-            Assert.That(callsMethodChanged.Any(x => x.Item1 == CompareStatus.Added && x.Item2.Name.Value == "set_balance_deprecated"), Is.True);
-            Assert.That(callsMethodChanged.Any(x => x.Item1 == CompareStatus.Removed && x.Item2.Name.Value == "set_balance"), Is.True);
+            Assert.That(callsMethodChanged.Any(x => x.Item1 == CompareStatus.Added && x.Item2.Name.Value == "set_balance_deprecated"));
+            Assert.That(callsMethodChanged.Any(x => x.Item1 == CompareStatus.Removed && x.Item2.Name.Value == "set_balance"));
 
-            Assert.That(callsMethodChanged.Any(x => x.Item1 == CompareStatus.Added && x.Item2.Name.Value == "transfer_allow_death"), Is.True);
-            Assert.That(callsMethodChanged.Any(x => x.Item1 == CompareStatus.Added && x.Item2.Name.Value == "set_balance_deprecated"), Is.True);
-            Assert.That(callsMethodChanged.Any(x => x.Item1 == CompareStatus.Added && x.Item2.Name.Value == "force_set_balance"), Is.True);
+            Assert.That(callsMethodChanged.Any(x => x.Item1 == CompareStatus.Added && x.Item2.Name.Value == "transfer_allow_death"));
+            Assert.That(callsMethodChanged.Any(x => x.Item1 == CompareStatus.Added && x.Item2.Name.Value == "set_balance_deprecated"));
+            Assert.That(callsMethodChanged.Any(x => x.Item1 == CompareStatus.Added && x.Item2.Name.Value == "force_set_balance"));
 
             var upgradeAccounts = callsMethodChanged.FirstOrDefault(x => x.Item1 == CompareStatus.Added && x.Item2.Name.Value == "upgrade_accounts");
             Assert.That(upgradeAccounts.Item2.VariantFields.Value.Count(), Is.EqualTo(1));
@@ -87,9 +87,9 @@ public void MetadataV14_SpecVersionCompare_V9270_And_V9280_ShouldSucceed()
             var metadataSource = readMetadataFromFile("V14\\MetadataV14_9270");
             var metadataDestination = readMetadataFromFile("V14\\MetadataV14_9280");
 
-            Assert.That(_metadataService.EnsureMetadataVersion(metadataSource, metadataDestination), Is.EqualTo(MetadataVersion.V14));
+            Assert.That(MetadataUtils.EnsureMetadataVersion(metadataSource, metadataDestination), Is.EqualTo(MetadataVersion.V14));
 
-            var res = _metadataService.MetadataCompareV14(
+            var res = MetadataUtils.MetadataCompareV14(
                 new MetadataV14(metadataSource),
                 new MetadataV14(metadataDestination));
 
@@ -105,9 +105,18 @@ public void MetadataV14_V9270_And_V9280_PalletHasChanged_ShouldSucceed()
             var metadataSource = readMetadataFromFile("V14\\MetadataV14_9270");
             var metadataDestination = readMetadataFromFile("V14\\MetadataV14_9280");
 
-            Assert.That(_metadataService.HasPalletChangedVersionBetween("Auctions", metadataSource, metadataDestination), Is.True);
+            Assert.That(MetadataUtils.HasPalletChangedVersionBetween("Auctions", metadataSource, metadataDestination));
+
+            Assert.That(MetadataUtils.HasPalletChangedVersionBetween("AuthorityDiscovery", metadataSource, metadataDestination), Is.False);
+        }
+
+        [Test]
+        public void MetadataV14_ConvertToNetApiMetadata_ShouldSucceed()
+        {
+            var metadata = new MetadataV14(readMetadataFromFile("V14\\MetadataV14_9270"));
+            var netApiMetadata = metadata.ToNetApiMetadata();
 
-            Assert.That(_metadataService.HasPalletChangedVersionBetween("AuthorityDiscovery", metadataSource, metadataDestination), Is.False);
+            Assert.That(netApiMetadata, Is.Not.Null);
         }
     }
 }
diff --git a/Substrate.NET.Metadata.Tests/MetadataServiceV15Test.cs b/Substrate.NET.Metadata.Tests/MetadataServiceV15Test.cs
index 73f7612..ae1ad2a 100644
--- a/Substrate.NET.Metadata.Tests/MetadataServiceV15Test.cs
+++ b/Substrate.NET.Metadata.Tests/MetadataServiceV15Test.cs
@@ -8,12 +8,13 @@ namespace Substrate.NET.Metadata.Tests
 {
     public class MetadataServiceV15Test : MetadataBaseTest
     {
-        private MetadataService _metadataService;
-
-        [SetUp]
-        public void Setup()
+        [Test]
+        public void MetadataV15_Encode_ShouldSucceed()
         {
-            _metadataService = new MetadataService();
+            var metadataSource = readMetadataFromFile("V15\\MetadataV15_FromPolkadotJs");
+
+            Assert.That(new MetadataV15(metadataSource).Encode(), Is.Not.Null);
+            Assert.That(new MetadataV15(metadataSource).Encode(), Is.Not.Null);
         }
 
         [Test]
@@ -21,21 +22,21 @@ public void MetadataV15_WhenInstanciate_ShouldSucceed()
         {
             var metadataHex = readMetadataFromFile("V15\\MetadataV15_FromPolkadotJs");
 
-            Assert.That(_metadataService.GetMetadataVersion(metadataHex), Is.EqualTo(MetadataVersion.V15));
+            Assert.That(MetadataUtils.GetMetadataVersion(metadataHex), Is.EqualTo(MetadataVersion.V15));
 
             var res = new MetadataV15(metadataHex);
 
             Assert.That(res, Is.Not.Null);
             Assert.That(res.Version, Is.EqualTo(MetadataVersion.V15));
 
-            Assert.That(res.RuntimeMetadataData.Lookup.Value.Length, Is.GreaterThan(0));
-            Assert.That(res.RuntimeMetadataData.Modules.Value.Length, Is.GreaterThan(0));
+            Assert.That(res.RuntimeMetadataData.Types.Value, Has.Length.GreaterThan(0));
+            Assert.That(res.RuntimeMetadataData.Modules.Value, Has.Length.GreaterThan(0));
             
             Assert.That((int)res.RuntimeMetadataData.OuterEnums.CallType.Value, Is.GreaterThanOrEqualTo(0));
             Assert.That((int)res.RuntimeMetadataData.OuterEnums.ErrorType.Value, Is.GreaterThanOrEqualTo(0));
             Assert.That((int)res.RuntimeMetadataData.OuterEnums.EventType.Value, Is.GreaterThanOrEqualTo(0));
             
-            Assert.That(res.RuntimeMetadataData.Apis.Value.Length, Is.GreaterThan(0));
+            Assert.That(res.RuntimeMetadataData.Apis.Value, Has.Length.GreaterThan(0));
 
             Assert.That(res.RuntimeMetadataData.Custom.Map.Value, Is.Not.Null);
         }
diff --git a/Substrate.NET.Metadata.Tests/MetadataServiceV9Test.cs b/Substrate.NET.Metadata.Tests/MetadataServiceV9Test.cs
index c71181c..ac017ab 100644
--- a/Substrate.NET.Metadata.Tests/MetadataServiceV9Test.cs
+++ b/Substrate.NET.Metadata.Tests/MetadataServiceV9Test.cs
@@ -1,5 +1,6 @@
 using Substrate.NET.Metadata.Base;
 using Substrate.NET.Metadata.Service;
+using Substrate.NET.Metadata.V10;
 using Substrate.NET.Metadata.V11;
 using Substrate.NET.Metadata.V9;
 using System;
@@ -12,13 +13,12 @@ namespace Substrate.NET.Metadata.Tests
 {
     public class MetadataServiceV9Test : MetadataBaseTest
     {
-
-        private MetadataService _metadataService;
-
-        [SetUp]
-        public void Setup()
+        [Test]
+        public void MetadataV9_Encode_ShouldSucceed()
         {
-            _metadataService = new MetadataService();
+            var metadataSource = readMetadataFromFile("V9\\MetadataV9_Kusama_1020");
+
+            Assert.That(new MetadataV9(metadataSource).Encode(), Is.Not.Null);
         }
 
         [Test]
@@ -27,9 +27,9 @@ public void MetadataV9_SpecVersionCompare_V1020_And_V1022_ShouldSucceed()
             var metadataSource = readMetadataFromFile("V9\\MetadataV9_Kusama_1020");
             var metadataDestination = readMetadataFromFile("V9\\MetadataV9_Kusama_1022");
 
-            Assert.That(_metadataService.EnsureMetadataVersion(metadataSource, metadataDestination), Is.EqualTo(MetadataVersion.V9));
+            Assert.That(MetadataUtils.EnsureMetadataVersion(metadataSource, metadataDestination), Is.EqualTo(MetadataVersion.V9));
 
-            var res = _metadataService.MetadataCompareV9(
+            var res = MetadataUtils.MetadataCompareV9(
                 new MetadataV9(metadataSource),
                 new MetadataV9(metadataDestination));
 
@@ -42,8 +42,8 @@ public void MetadataV9_V1020_And_V1022_PalletHasChanged_ShouldSucceed()
             var metadataSource = readMetadataFromFile("V9\\MetadataV9_Kusama_1020");
             var metadataDestination = readMetadataFromFile("V9\\MetadataV9_Kusama_1022");
 
-            Assert.That(_metadataService.HasPalletChangedVersionBetween("Democracy", metadataSource, metadataDestination), Is.True);
-            Assert.That(_metadataService.HasPalletChangedVersionBetween("Balances", metadataSource, metadataDestination), Is.False);
+            Assert.That(MetadataUtils.HasPalletChangedVersionBetween("Democracy", metadataSource, metadataDestination));
+            Assert.That(MetadataUtils.HasPalletChangedVersionBetween("Balances", metadataSource, metadataDestination), Is.False);
         }
     }
 }
diff --git a/Substrate.NET.Metadata.Tests/Substrate.NET.Metadata.Tests.csproj b/Substrate.NET.Metadata.Tests/Substrate.NET.Metadata.Tests.csproj
index e12c31f..5f38b11 100644
--- a/Substrate.NET.Metadata.Tests/Substrate.NET.Metadata.Tests.csproj
+++ b/Substrate.NET.Metadata.Tests/Substrate.NET.Metadata.Tests.csproj
@@ -1,7 +1,7 @@
 
 
   
-    net6.0
+    net8.0
     enable
     enable
     11
@@ -9,10 +9,10 @@
   
 
   
-    
-    
-    
-    
+    
+    
+    
+    
       all
       runtime; build; native; contentfiles; analyzers; buildtransitive
     
@@ -20,7 +20,7 @@
       all
       runtime; build; native; contentfiles; analyzers; buildtransitive
     
-    
+    
   
 
   
@@ -115,9 +115,6 @@
     
       PreserveNewest
     
-    
-      PreserveNewest
-    
     
       PreserveNewest
     
diff --git a/Substrate.NET.Metadata.Tests/TypeDefsTests.cs b/Substrate.NET.Metadata.Tests/TypeDefsTests.cs
new file mode 100644
index 0000000..2a674b4
--- /dev/null
+++ b/Substrate.NET.Metadata.Tests/TypeDefsTests.cs
@@ -0,0 +1,22 @@
+using Substrate.NET.Metadata.Base;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Numerics;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Substrate.NET.Metadata.Tests
+{
+    internal class TypeDefsTests
+    {
+        [Test]
+        public void TType_FromUint_ShouldBeConverted()
+        {
+            var converted = TType.From(10u);
+
+            Assert.That(converted, Is.Not.Null);
+            Assert.That(converted.Value.Value, Is.EqualTo(new BigInteger(10)));
+        }
+    }
+}
diff --git a/Substrate.NET.Metadata.sln b/Substrate.NET.Metadata.sln
index 7cf9a59..ef72fde 100644
--- a/Substrate.NET.Metadata.sln
+++ b/Substrate.NET.Metadata.sln
@@ -3,9 +3,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00
 # Visual Studio Version 17
 VisualStudioVersion = 17.5.33414.496
 MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Substrate.NET.Metadata", "Substrate.NET.Metadata\Substrate.NET.Metadata.csproj", "{E79A1FD5-DB32-4B1A-91BC-1419AFF47517}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Substrate.NET.Metadata", "Substrate.NET.Metadata\Substrate.NET.Metadata.csproj", "{E79A1FD5-DB32-4B1A-91BC-1419AFF47517}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Substrate.NET.Metadata.Tests", "Substrate.NET.Metadata.Tests\Substrate.NET.Metadata.Tests.csproj", "{4698095E-1C43-40BA-925B-B9333599E0E4}"
+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}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -21,6 +23,10 @@ Global
 		{4698095E-1C43-40BA-925B-B9333599E0E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{4698095E-1C43-40BA-925B-B9333599E0E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{4698095E-1C43-40BA-925B-B9333599E0E4}.Release|Any CPU.Build.0 = Release|Any CPU
+		{07CC3754-3F83-494B-A2D2-49D1F93FA30B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{07CC3754-3F83-494B-A2D2-49D1F93FA30B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{07CC3754-3F83-494B-A2D2-49D1F93FA30B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{07CC3754-3F83-494B-A2D2-49D1F93FA30B}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/Substrate.NET.Metadata/Base/BaseMetadata.cs b/Substrate.NET.Metadata/Base/BaseMetadata.cs
index 724d68e..26f4cfd 100644
--- a/Substrate.NET.Metadata/Base/BaseMetadata.cs
+++ b/Substrate.NET.Metadata/Base/BaseMetadata.cs
@@ -1,8 +1,9 @@
-using Substrate.NetApi.Model.Types.Base;
+using Newtonsoft.Json.Linq;
+using Substrate.NetApi.Model.Types.Base;
 
 namespace Substrate.NET.Metadata.Base
 {
-    public abstract class BaseMetadata : BaseType
+    public abstract class BaseMetadata : BaseType, IMetaDataInfo
         where T : BaseType, new()
     {
         protected BaseMetadata()
@@ -18,7 +19,10 @@ protected BaseMetadata(string hex)
 
         public override byte[] Encode()
         {
-            throw new NotImplementedException();
+            var result = new List();
+            result.AddRange(MetaDataInfo.Encode());
+            result.AddRange(RuntimeMetadataData.Encode());
+            return result.ToArray();
         }
 
         public override void Decode(byte[] byteArray, ref int p)
@@ -34,7 +38,7 @@ public override void Decode(byte[] byteArray, ref int p)
             TypeSize = p - start;
         }
 
-        public MetaDataInfo MetaDataInfo { get; private set; }
-        public T RuntimeMetadataData { get; private set; }
+        public MetaDataInfo MetaDataInfo { get; internal set; } = default!;
+        public T RuntimeMetadataData { get; internal set; } = default!;
     }
 }
diff --git a/Substrate.NET.Metadata/Base/Field.cs b/Substrate.NET.Metadata/Base/Field.cs
index e86ec66..9340186 100644
--- a/Substrate.NET.Metadata/Base/Field.cs
+++ b/Substrate.NET.Metadata/Base/Field.cs
@@ -6,11 +6,26 @@ namespace Substrate.NET.Metadata.Base
 {
     public class Field : BaseType, IMetadataType
     {
+        public Field() { }
+
+        public Field(BaseOpt name, TType fieldTy, BaseOpt fieldTypeName, BaseVec docs)
+        {
+            Name = name;
+            FieldTy = fieldTy;
+            FieldTypeName = fieldTypeName;
+            Docs = docs;
+        }
+
         public override string TypeName() => "Field";
 
         public override byte[] Encode()
         {
-            throw new NotImplementedException();
+            var result = new List();
+            result.AddRange(Name.Encode());
+            result.AddRange(FieldTy.Encode());
+            result.AddRange(FieldTypeName.Encode());
+            result.AddRange(Docs.Encode());
+            return result.ToArray();
         }
 
         public override void Decode(byte[] byteArray, ref int p)
diff --git a/Substrate.NET.Metadata/Base/IMetaDataInfo.cs b/Substrate.NET.Metadata/Base/IMetaDataInfo.cs
new file mode 100644
index 0000000..6916cd5
--- /dev/null
+++ b/Substrate.NET.Metadata/Base/IMetaDataInfo.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Substrate.NET.Metadata.Base
+{
+    public interface IMetaDataInfo
+    {
+        MetaDataInfo MetaDataInfo { get; }
+    }
+}
diff --git a/Substrate.NET.Metadata/Base/MetaDataInfo.cs b/Substrate.NET.Metadata/Base/MetaDataInfo.cs
index e9634ed..ab1f5a7 100644
--- a/Substrate.NET.Metadata/Base/MetaDataInfo.cs
+++ b/Substrate.NET.Metadata/Base/MetaDataInfo.cs
@@ -5,6 +5,7 @@
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using System.Xml.Linq;
 
 namespace Substrate.NET.Metadata.Base
 {
@@ -12,7 +13,10 @@ public class MetaDataInfo : BaseType
     {
         public override byte[] Encode()
         {
-            throw new NotImplementedException();
+            var result = new List();
+            result.AddRange(Magic.Encode());
+            result.AddRange(Version.Encode());
+            return result.ToArray();
         }
 
         public override void Decode(byte[] byteArray, ref int p)
diff --git a/Substrate.NET.Metadata/Base/Portable/PortableType.cs b/Substrate.NET.Metadata/Base/Portable/PortableType.cs
index b856b3a..db32d58 100644
--- a/Substrate.NET.Metadata/Base/Portable/PortableType.cs
+++ b/Substrate.NET.Metadata/Base/Portable/PortableType.cs
@@ -1,4 +1,5 @@
 using System;
+using System.Reflection.PortableExecutable;
 using Substrate.NetApi;
 using Substrate.NetApi.Model.Types.Base;
 using Substrate.NetApi.Model.Types.Primitive;
@@ -7,11 +8,22 @@ namespace Substrate.NET.Metadata.Base.Portable
 {
     public class PortableType : BaseType
     {
+        public PortableType() { }
+
+        internal PortableType(U32 id, TypePortableForm ty) 
+        {
+            Id = id;
+            Ty = ty;
+        }
+
         public override string TypeName() => "PortableType";
 
         public override byte[] Encode()
         {
-            throw new NotImplementedException();
+            var result = new List();
+            result.AddRange(Id.Encode());
+            result.AddRange(Ty.Encode());
+            return result.ToArray();
         }
 
         public override void Decode(byte[] byteArray, ref int p)
@@ -28,7 +40,7 @@ public override void Decode(byte[] byteArray, ref int p)
             TypeSize = p - start;
         }
 
-        public U32 Id { get; private set; }
-        public TypePortableForm Ty { get; private set; }
+        public U32 Id { get; internal set; }
+        public TypePortableForm Ty { get; internal set; }
     }
 }
\ No newline at end of file
diff --git a/Substrate.NET.Metadata/Base/Portable/TypePortableForm.cs b/Substrate.NET.Metadata/Base/Portable/TypePortableForm.cs
index 806b540..151f051 100644
--- a/Substrate.NET.Metadata/Base/Portable/TypePortableForm.cs
+++ b/Substrate.NET.Metadata/Base/Portable/TypePortableForm.cs
@@ -1,15 +1,36 @@
-using Substrate.NetApi.Model.Types.Base;
+using Substrate.NET.Metadata.Conversion;
+using Substrate.NetApi;
+using Substrate.NetApi.Model.Meta;
+using Substrate.NetApi.Model.Types.Base;
 using Substrate.NetApi.Model.Types.Primitive;
 
 namespace Substrate.NET.Metadata.Base.Portable
 {
     public class TypePortableForm : BaseType
     {
+        public TypePortableForm() { }
+
+        internal TypePortableForm(Path path,
+                                  BaseVec typeParams,
+                                  BaseEnumExt, TypeDefCompact, TypeDefBitSequence, BaseVoid> typeDef,
+                                  BaseVec docs)
+        {
+            Path = path;
+            TypeParams = typeParams;
+            TypeDef = typeDef;
+            Docs = docs;
+        }
+
         public override string TypeName() => "Type";
 
         public override byte[] Encode()
         {
-            throw new NotImplementedException();
+            var result = new List();
+            result.AddRange(Path.Encode());
+            result.AddRange(TypeParams.Encode());
+            result.AddRange(TypeDef.Encode());
+            result.AddRange(Docs.Encode());
+            return result.ToArray();
         }
 
         public override void Decode(byte[] byteArray, ref int p)
@@ -31,10 +52,45 @@ public override void Decode(byte[] byteArray, ref int p)
             TypeSize = p - start;
         }
 
-        public Path Path { get; private set; }
-        public BaseVec TypeParams { get; private set; }
-        public BaseEnumExt, TypeDefCompact, TypeDefBitSequence, BaseVoid> TypeDef { get; private set; }
-        public BaseVec Docs { get; private set; }
+        public Path Path { get; internal set; }
+        public BaseVec TypeParams { get; internal set; }
+        public BaseEnumExt, TypeDefCompact, TypeDefBitSequence, BaseVoid> TypeDef { get; internal set; }
+        public BaseVec Docs { get; internal set; }
+
+        public static TypePortableForm CreatePrimitive(NodeTypePrimitive nodeTypePrimitive)
+        {
+            var ty = CreateCommon(nodeTypePrimitive);
+
+            ty.TypeDef = new BaseEnumExt, TypeDefCompact, TypeDefBitSequence, BaseVoid>();
+
+            var mapPrimitive = Enum.Parse(typeof(TypeDefPrimitive), nodeTypePrimitive.Primitive.ToString());
+            if(mapPrimitive == null)
+            {
+                throw new MetadataConversionException($"Unable to find {nodeTypePrimitive.Primitive} into enum {typeof(TypeDefPrimitive)}");
+            }
+
+            ty.TypeDef.Create(TypeDefEnum.Primitive, new BaseEnum((TypeDefPrimitive)nodeTypePrimitive.Primitive));
+
+            return ty;
+        }
+
+        private static TypePortableForm CreateCommon(NodeType nodeTypePrimitive)
+        {
+            var ty = new TypePortableForm();
+
+            ty.Path = new Path();
+            ty.Path.Create(nodeTypePrimitive.Path.Select(x => new Str(x)).ToArray());
+
+            ty.TypeParams = new BaseVec(
+                nodeTypePrimitive.TypeParams.Select(x => new TypeParameter(new Str(x.Name), x.TypeId != null ? new BaseOpt(TType.From(x.TypeId.Value)) : new BaseOpt())).ToArray());
+
+            ty.Docs = new BaseVec();
+            ty.Docs.Create(nodeTypePrimitive.Docs.Select(x => new Str(x)).ToArray());
+
+            //ty.TypeDef
+
+            return ty;
+        }
     }
 
     public class Path : BaseVec
@@ -44,11 +100,22 @@ public class Path : BaseVec
 
     public class TypeParameter : BaseType, IMetadataName
     {
+        public TypeParameter() { }
+
+        public TypeParameter(Str name, BaseOpt typeParameterType)
+        {
+            Name = name;
+            TypeParameterType = typeParameterType;
+        }
+
         public override string TypeName() => "TypeParameter";
 
         public override byte[] Encode()
         {
-            throw new NotImplementedException();
+            var result = new List();
+            result.AddRange(Name.Encode());
+            result.AddRange(TypeParameterType.Encode());
+            return result.ToArray();
         }
 
         public override void Decode(byte[] byteArray, ref int p)
@@ -64,7 +131,7 @@ public override void Decode(byte[] byteArray, ref int p)
             TypeSize = p - start;
         }
 
-        public Str Name { get; private set; }
-        public BaseOpt TypeParameterType { get; private set; }
+        public Str Name { get; internal set; } = default!;
+        public BaseOpt TypeParameterType { get; internal set; } = default!;
     }
 }
\ No newline at end of file
diff --git a/Substrate.NET.Metadata/Base/StorageEntryTypeDoubleMap.cs b/Substrate.NET.Metadata/Base/StorageEntryTypeDoubleMap.cs
index 3e4a522..2a56929 100644
--- a/Substrate.NET.Metadata/Base/StorageEntryTypeDoubleMap.cs
+++ b/Substrate.NET.Metadata/Base/StorageEntryTypeDoubleMap.cs
@@ -1,10 +1,15 @@
-using Substrate.NetApi.Model.Types.Base;
+using Substrate.NET.Metadata.Conversion;
+using Substrate.NET.Metadata.Conversion.Internal;
+using Substrate.NET.Metadata.V14;
+using Substrate.NetApi.Model.Types.Base;
 using Substrate.NetApi.Model.Types.Primitive;
 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using System.Xml.Linq;
+using static Substrate.NET.Metadata.StorageType;
 
 namespace Substrate.NET.Metadata.Base
 {
@@ -15,17 +20,23 @@ namespace Substrate.NET.Metadata.Base
     public class StorageEntryTypeDoubleMap : BaseType
         where THasher : Enum
     {
-        public BaseEnum Key1Hasher { get; private set; }
-        public BaseEnum Key2Hasher { get; private set; }
+        public BaseEnum Key1Hasher { get; private set; } = default!;
+        public BaseEnum Key2Hasher { get; private set; } = default!;
 
-        public Str Key1 { get; private set; }
-        public Str Key2 { get; private set; }
+        public Str Key1 { get; private set; } = default!;
+        public Str Key2 { get; private set; } = default!;
 
-        public Str Value { get; private set; }
+        public Str Value { get; private set; } = default!;
 
         public override byte[] Encode()
         {
-            throw new NotImplementedException();
+            var result = new List();
+            result.AddRange(Key1Hasher.Encode());
+            result.AddRange(Key1.Encode());
+            result.AddRange(Key2.Encode());
+            result.AddRange(Value.Encode());
+            result.AddRange(Key2Hasher.Encode());
+            return result.ToArray();
         }
 
         public override void Decode(byte[] byteArray, ref int p)
@@ -49,5 +60,21 @@ public override void Decode(byte[] byteArray, ref int p)
 
             TypeSize = p - num;
         }
+
+        internal StorageEntryTypeMapV14 ToStorageEntryTypeMapV14(ConversionBuilder conversionBuilder)
+        {
+            var result = new StorageEntryTypeMapV14();
+
+            result.Hashers = new BaseVec>(
+            [
+                new BaseEnum((Hasher)Enum.Parse(typeof(THasher), Key1Hasher.Value.ToString())),
+                new BaseEnum((Hasher)Enum.Parse(typeof(THasher), Key2Hasher.Value.ToString())),
+            ]);
+
+            result.Key = TType.From(conversionBuilder.BuildPortableTypes($"({Key1.Value}, {Key2.Value})").Value);
+            result.Value = TType.From(conversionBuilder.BuildPortableTypes(Value.Value).Value);
+
+            return result;
+        }
     }
 }
diff --git a/Substrate.NET.Metadata/Base/StorageEntryTypeMap.cs b/Substrate.NET.Metadata/Base/StorageEntryTypeMap.cs
index e307ebc..9b014b0 100644
--- a/Substrate.NET.Metadata/Base/StorageEntryTypeMap.cs
+++ b/Substrate.NET.Metadata/Base/StorageEntryTypeMap.cs
@@ -1,10 +1,10 @@
-using Substrate.NetApi.Model.Types.Base;
+using Substrate.NET.Metadata.Base.Portable;
+using Substrate.NET.Metadata.Conversion;
+using Substrate.NET.Metadata.Conversion.Internal;
+using Substrate.NET.Metadata.V14;
+using Substrate.NetApi.Model.Types.Base;
 using Substrate.NetApi.Model.Types.Primitive;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using static Substrate.NET.Metadata.StorageType;
 
 namespace Substrate.NET.Metadata.Base
 {
@@ -15,16 +15,21 @@ namespace Substrate.NET.Metadata.Base
     public abstract class StorageEntryTypeMap : BaseType
         where THasher : Enum
     {
-        public BaseEnum Hasher { get; private set; }
+        public BaseEnum Hasher { get; private set; } = default!;
 
-        public Str Key { get; private set; }
+        public Str Key { get; private set; } = default!;
 
-        public Str Value { get; private set; }
-        public Bool Linked { get; private set; }
+        public Str Value { get; private set; } = default!;
+        public Bool Linked { get; private set; } = default;
 
         public override byte[] Encode()
         {
-            throw new NotImplementedException();
+            var result = new List();
+            result.AddRange(Hasher.Encode());
+            result.AddRange(Key.Encode());
+            result.AddRange(Value.Encode());
+            result.AddRange(Linked.Encode());
+            return result.ToArray();
         }
 
         public override void Decode(byte[] byteArray, ref int p)
@@ -45,5 +50,20 @@ public override void Decode(byte[] byteArray, ref int p)
 
             TypeSize = p - num;
         }
+
+        internal StorageEntryTypeMapV14 ToStorageEntryTypeMapV14(ConversionBuilder conversionBuilder)
+        {
+            var result = new StorageEntryTypeMapV14();
+
+            result.Hashers = new BaseVec>(
+            [
+                new BaseEnum((Hasher)Enum.Parse(typeof(Hasher), Hasher.Value.ToString()))
+            ]);
+
+            result.Key = TType.From(conversionBuilder.BuildPortableTypes(Key.Value).Value);
+            result.Value = TType.From(conversionBuilder.BuildPortableTypes(Value.Value).Value);
+
+            return result;
+        }
     }
 }
diff --git a/Substrate.NET.Metadata/Base/StorageEntryTypeNMap.cs b/Substrate.NET.Metadata/Base/StorageEntryTypeNMap.cs
index d1e02bb..6f783c3 100644
--- a/Substrate.NET.Metadata/Base/StorageEntryTypeNMap.cs
+++ b/Substrate.NET.Metadata/Base/StorageEntryTypeNMap.cs
@@ -2,6 +2,7 @@
 using Substrate.NetApi.Model.Types.Primitive;
 using System;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
@@ -12,18 +13,23 @@ namespace Substrate.NET.Metadata.Base
     /// Represent a "NMap" storage with generic Hasher
     /// 
     /// 
+    [ExcludeFromCodeCoverage] // Should never happened. Here just for consistency
     public class StorageEntryTypeNMap : BaseType
         where THasher : Enum
     {
-        public BaseVec> Hashers { get; private set; }
+        public BaseVec> Hashers { get; private set; } = default!;
 
-        public BaseVec KeyVec { get; private set; }
+        public BaseVec KeyVec { get; private set; } = default!;
 
-        public Str Value { get; private set; }
+        public Str Value { get; private set; } = default!;
 
         public override byte[] Encode()
         {
-            throw new NotImplementedException();
+            var result = new List();
+            result.AddRange(Hashers.Encode());
+            result.AddRange(KeyVec.Encode());
+            result.AddRange(Value.Encode());
+            return result.ToArray();
         }
 
         public override void Decode(byte[] byteArray, ref int p)
diff --git a/Substrate.NET.Metadata/Base/TypeDefs.cs b/Substrate.NET.Metadata/Base/TypeDefs.cs
index cdf82fa..8bfe0ce 100644
--- a/Substrate.NET.Metadata/Base/TypeDefs.cs
+++ b/Substrate.NET.Metadata/Base/TypeDefs.cs
@@ -1,7 +1,9 @@
 using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
 using Substrate.NetApi;
 using Substrate.NetApi.Model.Types;
 using Substrate.NetApi.Model.Types.Base;
+using Substrate.NetApi.Model.Types.Metadata.Base;
 using Substrate.NetApi.Model.Types.Primitive;
 
 namespace Substrate.NET.Metadata.Base
@@ -49,6 +51,14 @@ public byte[] Encode()
     public class TType : CompactIntegerType
     {
         public override string TypeName() => "T::Type";
+
+        public static TType From(uint i)
+        {
+            var compactIntegerType = new TType();
+            compactIntegerType.Value = new CompactInteger(new U32(i));
+
+            return compactIntegerType;
+        }
     }
 
     public enum TypeDefEnum
@@ -84,7 +94,9 @@ public class TypeDefComposite : BaseType
 
         public override byte[] Encode()
         {
-            throw new NotImplementedException();
+            var result = new List();
+            result.AddRange(Fields.Encode());
+            return result.ToArray();
         }
 
         public override void Decode(byte[] byteArray, ref int p)
@@ -97,7 +109,14 @@ public override void Decode(byte[] byteArray, ref int p)
             TypeSize = p - start;
         }
 
-        public BaseVec Fields { get; private set; }
+        public BaseVec Fields { get; internal set; }
+
+        public NetApi.Model.Types.Metadata.Base.TypeDefComposite ToNetApi()
+        {
+            var result = new Substrate.NetApi.Model.Types.Metadata.Base.TypeDefComposite();
+            result.Create(Encode());
+            return result;
+        }
     }
 
     public class TypeDefVariant : BaseType
@@ -106,7 +125,9 @@ public class TypeDefVariant : BaseType
 
         public override byte[] Encode()
         {
-            throw new NotImplementedException();
+            var result = new List();
+            result.AddRange(TypeParam.Encode());
+            return result.ToArray();
         }
 
         public override void Decode(byte[] byteArray, ref int p)
@@ -119,7 +140,14 @@ public override void Decode(byte[] byteArray, ref int p)
             TypeSize = p - start;
         }
 
-        public BaseVec TypeParam { get; private set; }
+        public BaseVec TypeParam { get; internal set; }
+
+        public NetApi.Model.Types.Metadata.Base.TypeDefVariant ToNetApi()
+        {
+            var result = new Substrate.NetApi.Model.Types.Metadata.Base.TypeDefVariant();
+            result.Create(Encode());
+            return result;
+        }
     }
 
     public class TypeDefSequence : BaseType, IMetadataType
@@ -128,7 +156,9 @@ public class TypeDefSequence : BaseType, IMetadataType
 
         public override byte[] Encode()
         {
-            throw new NotImplementedException();
+            var result = new List();
+            result.AddRange(ElemType.Encode());
+            return result.ToArray();
         }
 
         public override void Decode(byte[] byteArray, ref int p)
@@ -141,7 +171,14 @@ public override void Decode(byte[] byteArray, ref int p)
             TypeSize = p - start;
         }
 
-        public TType ElemType { get; private set; }
+        public TType ElemType { get; internal set; }
+
+        public NetApi.Model.Types.Metadata.Base.TypeDefSequence ToNetApi()
+        {
+            var result = new Substrate.NetApi.Model.Types.Metadata.Base.TypeDefSequence();
+            result.Create(Encode());
+            return result;
+        }
     }
 
     public class TypeDefArray : BaseType, IMetadataType
@@ -150,7 +187,10 @@ public class TypeDefArray : BaseType, IMetadataType
 
         public override byte[] Encode()
         {
-            throw new NotImplementedException();
+            var result = new List();
+            result.AddRange(Len.Encode());
+            result.AddRange(ElemType.Encode());
+            return result.ToArray();
         }
 
         public override void Decode(byte[] byteArray, ref int p)
@@ -166,8 +206,15 @@ public override void Decode(byte[] byteArray, ref int p)
             TypeSize = p - start;
         }
 
-        public U32 Len { get; private set; }
-        public TType ElemType { get; private set; }
+        public U32 Len { get; internal set; } = default!;
+        public TType ElemType { get; internal set; } = default!;
+
+        public NetApi.Model.Types.Metadata.Base.TypeDefArray ToNetApi()
+        {
+            var result = new Substrate.NetApi.Model.Types.Metadata.Base.TypeDefArray();
+            result.Create(Encode());
+            return result;
+        }
     }
 
     public class TypeDefTuple : BaseType
@@ -176,7 +223,9 @@ public class TypeDefTuple : BaseType
 
         public override byte[] Encode()
         {
-            throw new NotImplementedException();
+            var result = new List();
+            result.AddRange(Fields.Encode());
+            return result.ToArray();
         }
 
         public override void Decode(byte[] byteArray, ref int p)
@@ -189,7 +238,14 @@ public override void Decode(byte[] byteArray, ref int p)
             TypeSize = p - start;
         }
 
-        public BaseVec Fields { get; private set; }
+        public BaseVec Fields { get; internal set; }
+
+        public NetApi.Model.Types.Metadata.Base.TypeDefTuple ToNetApi()
+        {
+            var result = new Substrate.NetApi.Model.Types.Metadata.Base.TypeDefTuple();
+            result.Create(Encode());
+            return result;
+        }
     }
 
     public enum TypeDefPrimitive
@@ -246,7 +302,9 @@ public class TypeDefCompact : BaseType, IMetadataType
 
         public override byte[] Encode()
         {
-            throw new NotImplementedException();
+            var result = new List();
+            result.AddRange(ElemType.Encode());
+            return result.ToArray();
         }
 
         public override void Decode(byte[] byteArray, ref int p)
@@ -260,6 +318,13 @@ public override void Decode(byte[] byteArray, ref int p)
         }
 
         public TType ElemType { get; private set; }
+
+        public NetApi.Model.Types.Metadata.Base.TypeDefCompact ToNetApi()
+        {
+            var result = new Substrate.NetApi.Model.Types.Metadata.Base.TypeDefCompact();
+            result.Create(Encode());
+            return result;
+        }
     }
 
     public class TypeDefBitSequence : BaseType
@@ -268,7 +333,10 @@ public class TypeDefBitSequence : BaseType
 
         public override byte[] Encode()
         {
-            throw new NotImplementedException();
+            var result = new List();
+            result.AddRange(BitStoreType.Encode());
+            result.AddRange(BitOrderType.Encode());
+            return result.ToArray();
         }
 
         public override void Decode(byte[] byteArray, ref int p)
@@ -286,5 +354,12 @@ public override void Decode(byte[] byteArray, ref int p)
 
         public TType BitStoreType { get; private set; }
         public TType BitOrderType { get; private set; }
+
+        public NetApi.Model.Types.Metadata.Base.TypeDefBitSequence ToNetApi()
+        {
+            var result = new Substrate.NetApi.Model.Types.Metadata.Base.TypeDefBitSequence();
+            result.Create(Encode());
+            return result;
+        }
     }
 }
\ No newline at end of file
diff --git a/Substrate.NET.Metadata/Base/Variant.cs b/Substrate.NET.Metadata/Base/Variant.cs
index 413c010..9235f34 100644
--- a/Substrate.NET.Metadata/Base/Variant.cs
+++ b/Substrate.NET.Metadata/Base/Variant.cs
@@ -6,11 +6,26 @@ namespace Substrate.NET.Metadata.Base
 {
     public class Variant : BaseType, IMetadataName
     {
+        public Variant() { }
+
+        public Variant(Str name, BaseVec variantFields, U8 index, BaseVec docs)
+        {
+            Name = name;
+            VariantFields = variantFields;
+            Index = index;
+            Docs = docs;
+        }
+
         public override string TypeName() => "Variant";
 
         public override byte[] Encode()
         {
-            throw new NotImplementedException();
+            var result = new List();
+            result.AddRange(Name.Encode());
+            result.AddRange(VariantFields.Encode());
+            result.AddRange(Index.Encode());
+            result.AddRange(Docs.Encode());
+            return result.ToArray();
         }
 
         public override void Decode(byte[] byteArray, ref int p)
@@ -32,9 +47,9 @@ public override void Decode(byte[] byteArray, ref int p)
             TypeSize = p - start;
         }
 
-        public Str Name { get; private set; }
-        public BaseVec VariantFields { get; private set; }
-        public U8 Index { get; private set; }
-        public BaseVec Docs { get; private set; }
+        public Str Name { get; internal set; }
+        public BaseVec VariantFields { get; internal set; }
+        public U8 Index { get; internal set; }
+        public BaseVec Docs { get; internal set; }
     }
 }
\ No newline at end of file
diff --git a/Substrate.NET.Metadata/Common/Metadata.cs b/Substrate.NET.Metadata/Common/Metadata.cs
new file mode 100644
index 0000000..adeb9e6
--- /dev/null
+++ b/Substrate.NET.Metadata/Common/Metadata.cs
@@ -0,0 +1,455 @@
+//using Substrate.NetApi.Model.Meta;
+//using Substrate.NetApi;
+//using Newtonsoft.Json.Converters;
+//using Newtonsoft.Json;
+//using Substrate.NetApi.Model.Types.Base;
+//using Substrate.NET.Metadata.V11;
+//using Substrate.NET.Metadata.V12;
+//using Substrate.NET.Metadata.V13;
+//using Substrate.NET.Metadata.V14;
+//using Substrate.NET.Metadata.V15;
+//using Substrate.NET.Metadata.V9;
+//using Substrate.NET.Metadata.V10;
+//using Substrate.NET.Metadata.Base;
+//using Substrate.NetApi.Model.Types.Metadata.Base;
+
+//namespace Substrate.NET.Metadata.Common
+//{
+//    /// 
+//    /// Reresents the a unique structure of metadata.
+//    /// Build this same structure for all versions of metadata (v9 to v15)
+//    /// 
+//    /// Based on 
+//    /// 
+//    public class MetaData
+//    {
+//        public MetaData(IMetaDataInfo metadata, string origin = "unknown")
+//        {
+//            Origin = origin;
+//            Magic = Utils.Bytes2HexString(metadata.MetaDataInfo.Magic.Bytes);
+//            Version = metadata.MetaDataInfo.Version.Value;
+
+//            // Ensure that the parameter is known
+//            if (metadata is MetadataV9 metadataV9)
+//            {
+//                buildFromV9(metadataV9);
+//            }
+//            else if (metadata is MetadataV10 metadataV10)
+//            {
+//                buildFromV10(metadataV10);
+//            }
+//            if (metadata is MetadataV11 metadataV11)
+//            {
+//                buildFromV11(metadataV11);
+//            }
+//            else if (metadata is MetadataV12 metadataV12)
+//            {
+//                buildFromV12(metadataV12);
+//            }
+//            else if (metadata is MetadataV13 metadataV13)
+//            {
+//                buildFromV13(metadataV13);
+//            }
+//            else if (metadata is MetadataV14 metadataV14)
+//            {
+//                buildFromV14(metadataV14);
+//            }
+//            else if (metadata is MetadataV15 metadataV15)
+//            {
+//                buildFromV15(metadataV15);
+//            }
+//            else
+//            {
+//                throw new Exception("Unknown metadata type");
+//            }
+
+            
+//        }
+
+//        /// 
+//        /// Origin
+//        /// 
+//        public string Origin { get; set; }
+
+//        /// 
+//        /// Magic
+//        /// 
+//        public string Magic { get; set; }
+
+//        /// 
+//        /// Version
+//        /// 
+//        public byte Version { get; set; }
+
+//        public NodeMetadataV14 NodeMetadata { get; set; }
+
+//        public string Serialize()
+//        {
+//            return JsonConvert.SerializeObject(this, new StringEnumConverter());
+//        }
+
+//        private void buildFromV9(MetadataV9 v9)
+//        {
+//            NodeMetadata = new NodeMetadataV14()
+//            {
+//                Types = CreateNodeTypeDict(v14.RuntimeMetadataData.Lookup.Value),
+//                Modules = CreateModuleDict(v14.RuntimeMetadataData.Modules.Value),
+//                Extrinsic = CreateExtrinsic(v14.RuntimeMetadataData.Extrinsic),
+//                TypeId = (uint)v14.RuntimeMetadataData.TypeId.Value
+//            };
+//        }
+
+//        private void buildFromV10(MetadataV10 v10)
+//        {
+
+//        }
+
+//        private void buildFromV11(MetadataV11 v11)
+//        {
+
+//        }
+
+//        private void buildFromV12(MetadataV12 v12)
+//        {
+
+//        }
+
+//        private void buildFromV13(MetadataV13 v13)
+//        {
+
+//        }
+
+//        private void buildFromV14(MetadataV14 v14)
+//        {
+//            Magic = Utils.Bytes2HexString(v14.MetaDataInfo.Magic.Bytes);
+//            Version = v14.MetaDataInfo.Version.Value;
+//            NodeMetadata = new NodeMetadataV14()
+//            {
+//                Types = CreateNodeTypeDict(v14.RuntimeMetadataData.Lookup.Value),
+//                Modules = CreateModuleDict(v14.RuntimeMetadataData.Modules.Value),
+//                Extrinsic = CreateExtrinsic(v14.RuntimeMetadataData.Extrinsic),
+//                TypeId = (uint)v14.RuntimeMetadataData.TypeId.Value
+//            };
+
+//            /// 
+//            /// Create Node Type Dictionary
+//            /// 
+//            /// 
+//            /// 
+//            static Dictionary CreateNodeTypeDict(Base.Portable.PortableType[] types)
+//            {
+//                var result = new Dictionary();
+
+//                foreach (var type in types)
+//                {
+//                    var path = type.Ty.Path.Value.Length == 0 ? null : type.Ty.Path.Value.Select(p => p.Value).ToArray();
+//                    var typeParams = type.Ty.TypeParams.Value.Length == 0 ? null : type.Ty.TypeParams.Value.Select(p =>
+//                    {
+//                        return new NodeTypeParam()
+//                        {
+//                            Name = p.TypeParameterName.Value,
+//                            TypeId = p.TypeParameterType.Value?.Value
+//                        };
+//                    }).ToArray();
+//                    var typeDefValue = type.Ty.TypeDef.Value;
+//                    var docs = type.Ty.Docs == null || type.Ty.Docs.Value.Length == 0 ? null : type.Ty.Docs.Value.Select(p => p.Value).ToArray();
+
+//                    NodeType nodeType = null;
+//                    switch (typeDefValue)
+//                    {
+//                        case TypeDefEnum.Composite:
+//                            {
+//                                var typeDef = type.Ty.TypeDef.Value2 as TypeDefComposite;
+//                                nodeType = new NodeTypeComposite()
+//                                {
+//                                    Id = type.Id.Value,
+//                                    Path = path,
+//                                    TypeParams = typeParams,
+//                                    TypeDef = typeDefValue,
+//                                    TypeFields = typeDef.Fields.Value.Length == 0 ? null : typeDef.Fields.Value.Select(p =>
+//                                    {
+//                                        var fDocs = p.Docs == null || p.Docs.Value.Length == 0 ? null : p.Docs.Value.Select(q => q.Value).ToArray();
+//                                        return new NodeTypeField()
+//                                        {
+//                                            Name = p.FieldName.Value?.Value,
+//                                            TypeName = p.FieldTypeName.Value?.Value,
+//                                            TypeId = p.FieldTy.Value,
+//                                            Docs = fDocs
+//                                        };
+//                                    }).ToArray(),
+//                                    Docs = docs
+//                                };
+//                            }
+//                            break;
+
+//                        case TypeDefEnum.Variant:
+//                            {
+//                                var typeDef = type.Ty.TypeDef.Value2 as TypeDefVariant;
+//                                nodeType = new NodeTypeVariant()
+//                                {
+//                                    Id = type.Id.Value,
+//                                    Path = path,
+//                                    TypeParams = typeParams,
+//                                    TypeDef = typeDefValue,
+//                                    Variants = typeDef.TypeParam.Value.Length == 0 ? null : typeDef.TypeParam.Value.Select(p =>
+//                                    {
+//                                        var vDocs = p.Docs == null || p.Docs.Value.Length == 0 ? null : p.Docs.Value.Select(q => q.Value).ToArray();
+//                                        return new TypeVariant()
+//                                        {
+//                                            Name = p.VariantName.Value,
+//                                            TypeFields = p.VariantFields.Value.Length == 0 ? null : p.VariantFields.Value.Select(q =>
+//                                            {
+//                                                var fDocs = q.Docs == null || q.Docs.Value.Length == 0 ? null : q.Docs.Value.Select(r => r.Value).ToArray();
+//                                                return new NodeTypeField()
+//                                                {
+//                                                    Name = q.FieldName.Value?.Value,
+//                                                    TypeName = q.FieldTypeName.Value?.Value,
+//                                                    TypeId = q.FieldTy.Value,
+//                                                    Docs = fDocs
+//                                                };
+//                                            }).ToArray(),
+//                                            Index = p.Index.Value,
+//                                            Docs = vDocs
+//                                        };
+//                                    }).ToArray(),
+//                                    Docs = docs
+//                                };
+//                            }
+//                            break;
+
+//                        case TypeDefEnum.Sequence:
+//                            {
+//                                var typeDef = type.Ty.TypeDef.Value2 as TypeDefSequence;
+//                                nodeType = new NodeTypeSequence()
+//                                {
+//                                    Id = type.Id.Value,
+//                                    Path = path,
+//                                    TypeParams = typeParams,
+//                                    TypeDef = typeDefValue,
+//                                    TypeId = typeDef.TypeParam.Value,
+//                                    Docs = docs
+//                                };
+//                            }
+//                            break;
+
+//                        case TypeDefEnum.Array:
+//                            {
+//                                var typeDef = type.Ty.TypeDef.Value2 as TypeDefArray;
+//                                nodeType = new NodeTypeArray()
+//                                {
+//                                    Id = type.Id.Value,
+//                                    Path = path,
+//                                    TypeParams = typeParams,
+//                                    TypeDef = typeDefValue,
+//                                    TypeId = typeDef.TypeParam.Value,
+//                                    Length = typeDef.Len.Value,
+//                                    Docs = docs
+//                                };
+//                            }
+//                            break;
+
+//                        case TypeDefEnum.Tuple:
+//                            {
+//                                var typeDef = type.Ty.TypeDef.Value2 as TypeDefTuple;
+//                                nodeType = new NodeTypeTuple()
+//                                {
+//                                    Id = type.Id.Value,
+//                                    Path = path,
+//                                    TypeParams = typeParams,
+//                                    TypeDef = typeDefValue,
+//                                    TypeIds = typeDef.Fields.Value.Select(p => (uint)p.Value).ToArray(),
+//                                    Docs = docs
+//                                };
+//                            }
+//                            break;
+
+//                        case TypeDefEnum.Primitive:
+//                            {
+//                                var typeDef = (TypeDefPrimitive)Enum.Parse(typeof(TypeDefPrimitive), type.Ty.TypeDef.Value2.ToString());
+//                                nodeType = new NodeTypePrimitive()
+//                                {
+//                                    Id = type.Id.Value,
+//                                    Path = path,
+//                                    TypeParams = typeParams,
+//                                    TypeDef = typeDefValue,
+//                                    Primitive = typeDef,
+//                                    Docs = docs
+//                                };
+//                            }
+//                            break;
+
+//                        case TypeDefEnum.Compact:
+//                            {
+//                                var typeDef = type.Ty.TypeDef.Value2 as TypeDefCompact;
+//                                nodeType = new NodeTypeCompact()
+//                                {
+//                                    Id = type.Id.Value,
+//                                    Path = path,
+//                                    TypeParams = typeParams,
+//                                    TypeDef = typeDefValue,
+//                                    TypeId = typeDef.TypeParam.Value,
+//                                    Docs = docs
+//                                };
+//                            }
+//                            break;
+
+//                        case TypeDefEnum.BitSequence:
+//                            {
+//                                var typeDef = type.Ty.TypeDef.Value2 as TypeDefBitSequence;
+//                                nodeType = new NodeTypeBitSequence()
+//                                {
+//                                    Id = type.Id.Value,
+//                                    Path = path,
+//                                    TypeParams = typeParams,
+//                                    TypeDef = typeDefValue,
+//                                    TypeIdOrder = typeDef.BitOrderType.Value,
+//                                    TypeIdStore = typeDef.BitStoreType.Value,
+//                                    Docs = docs
+//                                };
+//                            }
+//                            break;
+//                    }
+
+//                    if (nodeType != null)
+//                    {
+//                        result.Add(nodeType.Id, nodeType);
+//                    }
+//                }
+
+//                return result;
+//            }
+
+//            /// 
+//            /// Create Module Dictionary
+//            /// 
+//            /// 
+//            /// 
+//            /// 
+//            static Dictionary CreateModuleDict(PalletMetadata[] modules)
+//            {
+//                var result = new Dictionary();
+
+//                foreach (var module in modules)
+//                {
+//                    var palletModule = new PalletModule()
+//                    {
+//                        Name = module.PalletName.Value,
+//                        Index = module.Index.Value,
+//                    };
+//                    result.Add(module.Index.Value, palletModule);
+
+//                    if (module.PalletStorage.OptionFlag)
+//                    {
+//                        var storage = module.PalletStorage.Value;
+//                        palletModule.Storage = new PalletStorage()
+//                        {
+//                            Prefix = storage.Prefix.Value,
+//                        };
+
+//                        palletModule.Storage.Entries = new Entry[storage.Entries.Value.Length];
+//                        for (int i = 0; i < storage.Entries.Value.Length; i++)
+//                        {
+//                            var entry = storage.Entries.Value[i];
+//                            palletModule.Storage.Entries[i] = new Entry()
+//                            {
+//                                Name = entry.StorageName.Value,
+//                                Modifier = entry.StorageModifier.Value,
+//                                StorageType = entry.StorageType.Value,
+//                                Default = entry.StorageDefault.Value.Select(p => p.Value).ToArray(),
+//                                Docs = entry.Documentation.Value.Select(p => p.Value).ToArray(),
+//                            };
+
+//                            switch (entry.StorageType.Value)
+//                            {
+//                                case Storage.Type.Plain:
+//                                    palletModule.Storage.Entries[i].TypeMap = (((TType)entry.StorageType.Value2).Value, null);
+//                                    break;
+
+//                                case Storage.Type.Map:
+//                                    var typeMap = ((StorageEntryTypeMap)entry.StorageType.Value2);
+//                                    palletModule.Storage.Entries[i].TypeMap = (0, new TypeMap()
+//                                    {
+//                                        Hashers = typeMap.Hashers.Value.Select(p => p.Value).ToArray(),
+//                                        Key = (uint)typeMap.Key.Value,
+//                                        Value = (uint)typeMap.Value.Value
+//                                    });
+//                                    break;
+
+//                                default:
+//                                    throw new NotImplementedException();
+//                            }
+//                        }
+//                    }
+
+//                    if (module.PalletCalls.OptionFlag)
+//                    {
+//                        var calls = module.PalletCalls.Value;
+//                        palletModule.Calls = new PalletCalls()
+//                        {
+//                            TypeId = (uint)calls.CallType.Value
+//                        };
+//                    }
+
+//                    if (module.PalletEvents.OptionFlag)
+//                    {
+//                        var events = module.PalletEvents.Value;
+//                        palletModule.Events = new PalletEvents()
+//                        {
+//                            TypeId = (uint)events.EventType.Value
+//                        };
+//                    }
+
+//                    var constants = module.PalletConstants.Value;
+//                    palletModule.Constants = new PalletConstant[constants.Length];
+//                    for (int i = 0; i < constants.Length; i++)
+//                    {
+//                        PalletConstantMetadata constant = constants[i];
+//                        palletModule.Constants[i] = new PalletConstant()
+//                        {
+//                            Name = constant.ConstantName.Value,
+//                            TypeId = (uint)constant.ConstantType.Value,
+//                            Value = constant.ConstantValue.Value.Select(p => p.Value).ToArray(),
+//                            Docs = constant.Documentation.Value.Select(p => p.Value).ToArray()
+//                        };
+//                    }
+
+//                    if (module.PalletErrors.OptionFlag)
+//                    {
+//                        var errors = module.PalletErrors.Value;
+//                        palletModule.Errors = new PalletErrors()
+//                        {
+//                            TypeId = (uint)errors.ErrorType.Value
+//                        };
+//                    }
+//                }
+
+//                return result;
+//            }
+
+//            /// 
+//            /// Create Extrinsic
+//            /// 
+//            /// 
+//            /// 
+//            static ExtrinsicMetadata CreateExtrinsic(ExtrinsicMetadataStruct extrinsic)
+//            {
+//                return new ExtrinsicMetadata()
+//                {
+//                    TypeId = (uint)extrinsic.ExtrinsicType.Value,
+//                    Version = (int)extrinsic.Version.Value,
+//                    SignedExtensions = extrinsic.SignedExtensions.Value.Select(p => new SignedExtensionMetadata()
+//                    {
+//                        SignedIdentifier = p.SignedIdentifier.Value,
+//                        SignedExtType = (uint)p.SignedExtType.Value,
+//                        AddSignedExtType = (uint)p.AddSignedExtType.Value,
+//                    }).ToArray()
+//                };
+//            }
+//        }
+
+//        private void buildFromV15(MetadataV15 v15)
+//        {
+
+//        }
+//    }
+//}
diff --git a/Substrate.NET.Metadata/Conversion/IMetadataToV14.cs b/Substrate.NET.Metadata/Conversion/IMetadataToV14.cs
new file mode 100644
index 0000000..5c65fc2
--- /dev/null
+++ b/Substrate.NET.Metadata/Conversion/IMetadataToV14.cs
@@ -0,0 +1,21 @@
+using Substrate.NET.Metadata.Base;
+using Substrate.NET.Metadata.Conversion.Internal;
+using Substrate.NET.Metadata.V14;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Substrate.NET.Metadata.Conversion
+{
+    public interface IMetadataToV14
+    {
+        /// 
+        /// Convert the metadata to V14 metadata
+        /// This is use to keep the metadata in the same format and compatible with the Substrate.NET.Toolchain (https://github.com/SubstrateGaming/Substrate.NET.Toolchain)
+        /// 
+        /// 
+        MetadataV14 ToMetadataV14();
+    }
+}
diff --git a/Substrate.NET.Metadata/Conversion/Internal/ConversionBuilder.cs b/Substrate.NET.Metadata/Conversion/Internal/ConversionBuilder.cs
new file mode 100644
index 0000000..4a5ae0e
--- /dev/null
+++ b/Substrate.NET.Metadata/Conversion/Internal/ConversionBuilder.cs
@@ -0,0 +1,470 @@
+using Substrate.NET.Metadata.Base;
+using Substrate.NET.Metadata.Base.Portable;
+using Substrate.NET.Metadata.V14;
+using Substrate.NetApi;
+using Substrate.NetApi.Model.Types.Base;
+using Substrate.NetApi.Model.Types.Primitive;
+using System;
+using System.Runtime.CompilerServices;
+using System.Text.RegularExpressions;
+using static Substrate.NET.Metadata.Conversion.Internal.SearchV14;
+using TypeDefExt = Substrate.NetApi.Model.Types.Base.BaseEnumExt<
+    Substrate.NET.Metadata.Base.TypeDefEnum,
+    Substrate.NET.Metadata.Base.TypeDefComposite,
+    Substrate.NET.Metadata.Base.TypeDefVariant,
+    Substrate.NET.Metadata.Base.TypeDefSequence,
+    Substrate.NET.Metadata.Base.TypeDefArray,
+    Substrate.NET.Metadata.Base.TypeDefTuple,
+    Substrate.NetApi.Model.Types.Base.BaseEnum,
+    Substrate.NET.Metadata.Base.TypeDefCompact,
+    Substrate.NET.Metadata.Base.TypeDefBitSequence,
+    Substrate.NetApi.Model.Types.Base.BaseVoid>;
+
+[assembly: InternalsVisibleToAttribute("Substrate.NET.Metadata.Tests")]
+[assembly: InternalsVisibleToAttribute("Substrate.NET.Metadata.Node.Tests")]
+namespace Substrate.NET.Metadata.Conversion.Internal
+{
+    /// 
+    /// Class to keep track of converted types
+    /// 
+    internal class ConversionElementState
+    {
+        public ConversionElementState(string className, NodeBuilderType nodeBuilderType)
+        {
+            ClassName = className;
+            NodeBuilderType = nodeBuilderType;
+        }
+
+        /// 
+        /// The Rust struct name
+        /// 
+        public string ClassName { get; set; }
+
+        /// 
+        /// 
+        /// 
+        public NodeBuilderType NodeBuilderType { get; set; }
+
+        /// 
+        /// Facultative index found in v14
+        /// 
+        public uint? IndexFoundInV14 { get; set; }
+
+        /// 
+        /// Facultative index of created node
+        /// 
+        public uint? IndexCreated { get; set; }
+
+        public bool IsSuccessfullyMapped
+        {
+            get
+            {
+                return IndexFoundInV14 != null || IndexCreated != null;
+            }
+        }
+
+        public override string ToString()
+        {
+            return $"{ClassName} (=> {NodeBuilderType.Adapted}) | V14 = {IndexFoundInV14} | CustomIndex = {IndexCreated} | Mapped = {IsSuccessfullyMapped}";
+        }
+    }
+
+    /// 
+    /// This class make the transition between metadatas prev v14 and v14
+    /// It helps to build the list of PortableType
+    /// 
+    internal class ConversionBuilder
+    {
+        public List PortableTypes { get; init; }
+        public List ElementsState { get; init; }
+        public IDictionary OverrideTypeMapping { get; init; }
+        public string CurrentPallet { get; set; } = string.Empty;
+        public uint? UnknowIndex { get; set; } = null;
+        public uint? PolkadotRuntimeEventIndex { get; private set; } = null;
+
+        public const int START_INDEX = 1_000;
+
+        public ConversionBuilder(List portableTypes)
+        {
+            PortableTypes = portableTypes;
+            ElementsState = new List();
+            OverrideTypeMapping = new Dictionary();
+        }
+
+        /// 
+        /// Conversion that are not handle by the  because it is not necessary or too complex
+        /// 
+        public readonly List NotHandledConversion =
+        [
+            "Vec