├── .gitattributes ├── .github └── workflows │ └── dotnet.yml ├── .gitignore ├── DemoApiTest ├── DemoApiTest.csproj ├── Info.txt ├── JtonConnectFour.json └── Program.cs ├── DemoWalletTest ├── DemoWalletTest.csproj ├── Program.cs └── wallet.dat ├── IntegrationTest ├── IntegrationTest.csproj └── LocalNodeTests.cs ├── LICENSE ├── README.md ├── Sandbox ├── Program.cs ├── Sandbox.csproj └── dotmogMetaData.json ├── SubstrateNetApi.sln ├── SubstrateNetApi ├── CompactInteger.cs ├── Constants.cs ├── Doxyfile ├── Exceptions │ ├── ClientNotConnectedException.cs │ ├── ConverterAlreadyRegisteredException.cs │ ├── MissingConverterException.cs │ ├── MissingModuleOrItemException.cs │ └── MissingParameterException.cs ├── HashExtension.cs ├── ITypeConverter.cs ├── MetaDataParser.cs ├── Mnemonic.cs ├── Model │ ├── Calls │ │ └── GenericExtrinsicCall.cs │ ├── Custom │ │ ├── DOTMog │ │ │ ├── DOTMog.json │ │ │ ├── DOTMogCalls.cs │ │ │ └── DOTMogTypes.cs │ │ ├── Kusama │ │ │ ├── KusamaCalls.cs │ │ │ └── KusamaTypes.cs │ │ ├── Polkadot │ │ │ ├── PolkadotCalls.cs │ │ │ └── PolkadotTypes.cs │ │ └── UniqueTestnet │ │ │ ├── UniqueTestnet.json │ │ │ ├── UniqueTestnetCalls.cs │ │ │ └── UniqueTestnetTypes.cs │ ├── Extrinsics │ │ ├── Era.cs │ │ ├── Extrinsic.cs │ │ ├── Method.cs │ │ ├── Payload.cs │ │ ├── SignedExtensions.cs │ │ └── UnCheckedExtrinsic.cs │ ├── Meta │ │ ├── Argument.cs │ │ ├── Call.cs │ │ ├── Const.cs │ │ ├── Error.cs │ │ ├── Event.cs │ │ ├── Function.cs │ │ ├── Item.cs │ │ ├── MetaData.cs │ │ ├── Module.cs │ │ └── Storage.cs │ ├── Rpc │ │ ├── Block.cs │ │ ├── BlockData.cs │ │ ├── Digest.cs │ │ ├── ExtrinsicStatus.cs │ │ ├── Header.cs │ │ ├── Health.cs │ │ ├── RuntimeVersion.cs │ │ └── StorageChangeSet.cs │ └── Types │ │ ├── Account.cs │ │ ├── Base │ │ ├── AccountId.cs │ │ ├── Assets.cs │ │ ├── Balance.cs │ │ ├── BlockNumber.cs │ │ ├── Bool.cs │ │ ├── Hash.cs │ │ ├── InheritedBaseTypes.cs │ │ ├── U128.cs │ │ ├── U16.cs │ │ ├── U32.cs │ │ ├── U64.cs │ │ └── U8.cs │ │ ├── BaseType.cs │ │ ├── Enum │ │ ├── BalanceStatus.cs │ │ ├── DispatchClass.cs │ │ ├── ElectionCompute.cs │ │ ├── Pays.cs │ │ ├── PhaseState.cs │ │ ├── ProxyType.cs │ │ └── VoteThreshold.cs │ │ ├── EnumType.cs │ │ ├── ExtEnumType.cs │ │ ├── IEncodable.cs │ │ ├── IType.cs │ │ ├── Struct │ │ ├── AccountData.cs │ │ ├── AccountInfo.cs │ │ ├── Assets.cs │ │ ├── BaseEvent.cs │ │ ├── Dispatchinfo.cs │ │ ├── EventRecord.cs │ │ ├── EventRecords.cs │ │ ├── InheritedStructTypes.cs │ │ ├── Option.cs │ │ ├── Phase.cs │ │ ├── RustTuple.cs │ │ ├── Timepoint.cs │ │ └── Vec.cs │ │ ├── StructType.cs │ │ ├── TypeUtil.cs │ │ └── UnimplementedTypes.cs ├── Modules │ ├── Author.cs │ ├── Chain.cs │ ├── State.cs │ └── System.cs ├── RequestGenerator.cs ├── SubscriptionListener.cs ├── SubstrateClient.cs ├── SubstrateNetApi.csproj ├── TypeConverters │ ├── ExtrinsicJsonConverter.cs │ ├── ExtrinsicStatusJsonConverter.cs │ └── GenericTypeConverter.cs └── Utils.cs ├── SubstrateNetApiTest ├── ClientTests │ ├── ClientTests.cs │ └── GetStorageTests.cs ├── CompactIntegerTests.cs ├── CustomTests │ ├── CustomExtrinsicTests.cs │ ├── CustomStorageTests.cs │ ├── CustomTypeConverters.cs │ └── CustomTypes.cs ├── DOTMogNET.json ├── Extrinsic │ ├── EraTest.cs │ ├── MethodTest.cs │ ├── PayloadTest.cs │ ├── SignedExtensionsTest.cs │ └── UnCheckedExtrinsicTest.cs ├── HashExtensionTests.cs ├── Keys │ ├── Ed25519Tests.cs │ └── Sr25519Tests.cs ├── MemonicTest.cs ├── RequestGeneratorTests.cs ├── Subscription │ └── SubscriptionTest.cs ├── SubstrateNetApiTests.csproj ├── SystemInteraction.cs ├── TypeConverters │ ├── EventDecodeTest.cs │ ├── TypeConverterTest.cs │ ├── TypeEncodingTest.cs │ └── TypesMapperTest.cs ├── UtilsTests.cs └── Values │ └── ValueTests.cs ├── SubstrateNetWallet ├── Caching.cs ├── ChainInfo.cs ├── ManagedAes.cs ├── SubstrateNetWallet.csproj ├── SystemInteraction.cs ├── Wallet.cs └── WalletFile.cs ├── SubstrateNetWalletTest ├── README.md ├── SubstrateNetWalletTests.csproj ├── WalletTest.cs └── dev_wallet.dat ├── TestExtrinsic ├── Program.cs └── TestExtrinsic.csproj ├── appveyor.yml └── images ├── advanced_architecture.png ├── basic_architecture.png └── dependencies.png /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.github/workflows/dotnet.yml: -------------------------------------------------------------------------------- 1 | name: .NET 2 | 3 | on: 4 | push: 5 | branches: [ origin ] 6 | pull_request: 7 | branches: [ origin ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | strategy: 14 | matrix: 15 | dotnet-version: ["3.1.x"] 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Setup .NET Core SDK ${{matrix.dotnet-version}} 20 | uses: actions/setup-dotnet@v1 21 | with: 22 | dotnet-version: ${{matrix.dotnet-version}} 23 | - name: Restore dependencies 24 | run: dotnet restore 25 | - name: Build 26 | run: dotnet build --no-restore 27 | - name: Test 28 | run: dotnet test --filter SubstrateNetApi\!~IntegrationTest --no-build --verbosity normal 29 | - name: Publish SubstrateNetApi 30 | uses: brandedoutcast/publish-nuget@v2.5.2 31 | with: 32 | PROJECT_FILE_PATH: SubstrateNetApi/SubstrateNetApi/SubstrateNetApi.csproj 33 | NUGET_KEY: ${{secrets.NUGET_API_KEY}} 34 | -------------------------------------------------------------------------------- /DemoApiTest/DemoApiTest.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /DemoApiTest/Info.txt: -------------------------------------------------------------------------------- 1 | cargo test -p node-runtime -- --nocapture 2 | 3 | ############################################## 4 | Call: Call::Balances(transfer(Address::Id(d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d (5GrwvaEF...)), 100)) 5 | Call Encoded: [6, 0, 255, 212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125, 145, 1] 6 | Extra: (CheckSpecVersion, CheckTxVersion, CheckGenesis, CheckMortality(Era::Mortal(2048, 99)), CheckNonce(0), CheckWeight, ChargeTransactionPayment<0>) 7 | Extra Encoded: [58, 6, 0, 0] 8 | Additional Signed: (259, 1, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, (), (), ()) 9 | Additional Signed Encoded: [3, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 10 | ############################################## 11 | Raw Payload: [6, 0, 255, 212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125, 145, 1, 58, 6, 0, 0, 3, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] -------------------------------------------------------------------------------- /DemoWalletTest/DemoWalletTest.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | Always 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /DemoWalletTest/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Threading.Tasks; 4 | using SubstrateNetApi.Model.Types.Struct; 5 | using SubstrateNetWallet; 6 | 7 | namespace DemoWalletTest 8 | { 9 | internal class Program 10 | { 11 | private static async Task Main(string[] args) 12 | { 13 | SystemInteraction.ReadData = f => File.ReadAllText(Path.Combine(Environment.CurrentDirectory, f)); 14 | SystemInteraction.DataExists = f => File.Exists(Path.Combine(Environment.CurrentDirectory, f)); 15 | SystemInteraction.ReadPersistent = f => File.ReadAllText(Path.Combine(Environment.CurrentDirectory, f)); 16 | SystemInteraction.PersistentExists = f => File.Exists(Path.Combine(Environment.CurrentDirectory, f)); 17 | SystemInteraction.Persist = (f, c) => File.WriteAllText(Path.Combine(Environment.CurrentDirectory, f), c); 18 | 19 | // create new wallet with password and persist 20 | var wallet = new Wallet(); 21 | 22 | wallet.ChainInfoUpdated += Wallet_ChainInfoUpdated; 23 | 24 | wallet.AccountInfoUpdated += Wallet_AccountInfoUpdated; 25 | 26 | await wallet.StartAsync(); 27 | 28 | if (!wallet.IsConnected) return; 29 | 30 | if (wallet.Load()) 31 | { 32 | Console.WriteLine("wallet unlocked"); 33 | await wallet.UnlockAsync("Aa123456"); 34 | } 35 | else if (!wallet.IsCreated) 36 | { 37 | Console.WriteLine("wallet created"); 38 | await wallet.CreateAsync("Aa123456"); 39 | } 40 | 41 | Console.WriteLine(wallet.Account.Value); 42 | 43 | Console.ReadKey(); 44 | 45 | await wallet.StopAsync(); 46 | } 47 | 48 | private static void Wallet_AccountInfoUpdated(object sender, AccountInfo accountInfo) 49 | { 50 | Console.WriteLine($"CallBack[AccountInfo]: {accountInfo}"); 51 | } 52 | 53 | private static void Wallet_ChainInfoUpdated(object sender, ChainInfo chainInfo) 54 | { 55 | Console.WriteLine($"CallBack[ChainInfo]: {chainInfo}"); 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /DemoWalletTest/wallet.dat: -------------------------------------------------------------------------------- 1 | {"PublicKey":"E38P/IkE9Cqqv2PU7ICGL1CHqLBZJgwZFAHgPAODZ2c=","EncryptedSeed":"Eh8sWgjyZBa4bleAFQUyBr2nq5m6YP9rudzfNK45MA2y0h3IP7V8FuIBJs1D5Gla+nECMqbPacKPlEffyPVc6qbZfmRgNt2NtIquXD4Od+o=","Salt":"7JWPWnzW3xWqlkw7LGBGHQ=="} -------------------------------------------------------------------------------- /IntegrationTest/IntegrationTest.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SubstrateNetApi (NETStandard2.0) 2 | *Just another Substrate .NET API* 3 | [![Build status](https://ci.appveyor.com/api/projects/status/jsei7yv376en17rr?svg=true)](https://ci.appveyor.com/project/darkfriend77/substratenetapi) 4 | [![nuget](https://img.shields.io/nuget/v/SubstrateNetApi)](https://ci.appveyor.com/project/darkfriend77/substratenetapi/build/artifacts) 5 | [![GitHub issues](https://img.shields.io/github/issues/darkfriend77/SubstrateNetApi.svg)](https://github.com/darkfriend77/SubstrateNetApi/issues) 6 | [![license](https://img.shields.io/github/license/darkfriend77/SubstrateNetApi)](https://github.com/darkfriend77/SubstrateNetApi/blob/origin/LICENSE) 7 | [![contributors](https://img.shields.io/github/contributors/darkfriend77/SubstrateNetApi)](https://github.com/darkfriend77/SubstrateNetApi/graphs/contributors) 8 | 9 | SubstrateNetApi is written in [NETStandard2.0](https://docs.microsoft.com/en-us/dotnet/standard/net-standard) to provide maximum compatibility for [Unity3D](https://docs.unity3d.com/2020.2/Documentation/Manual/dotnetProfileSupport.html). Feedback, constructive critisme and disscussions are welcome and will help us to improve the API! (Telegram: @darkfriend77, Discord: darkfriend77#3753) 10 | 11 | If you enjoy using SubstrateNetApi consider supporting me at [buymeacoffee.com/darkfriend77](https://www.buymeacoffee.com/darkfriend77) 12 | 13 | ## Substrate Version 14 | **Important** This API is for the major release [**Substrate v3.0/0.9 – Apollo 14**](https://github.com/paritytech/substrate/releases/tag/v3.0.0), for releases [monthly-2021-10](https://github.com/paritytech/substrate/releases/tag/monthly-2021-10) and newer please refere to the [Ajuna.NetApi](https://github.com/ajuna-network/Ajuna.NetApi) 15 | 16 | ## General information 17 | 18 | This project has been started by darkfriend77 as a proove of concept in october'20, the goal was to proove Unity3D compatibility towards substrate. [Substrate](https://substrate.dev/) is a modular framework that enables you to create purpose-built blockchains by composing custom or pre-built components. After succeding every aspect crucial for developing mobile games on unity against substrate, the project decided to work further with the API and apply for a first [open-grant](https://github.com/w3f/Grants-Program/blob/master/applications/dotmog.md) from the Web3 Foundation. 19 | 20 | ![ajuna-Header-1080p_with_logo](https://user-images.githubusercontent.com/17710198/136851142-2e4158ff-a6a7-4d26-9ea5-9833d62da3fa.png) 21 | 22 | The project behind the SubstrateNetApi, is [Ajuna Network](https://ajuna.io/) and the flagship game [DOTMog](dotmog.com), backed by the swiss company BloGa Tech AG. 23 | 24 | ## Table of Content 25 | 26 | 1. [Home](https://github.com/JetonNetwork/SubstrateNetApi/wiki) 27 | 1. [Requirements](https://github.com/JetonNetwork/SubstrateNetApi/wiki/Requirements) 28 | 1. [Installation](https://github.com/JetonNetwork/SubstrateNetApi/wiki/Installation) 29 | - [NuGet](https://github.com/JetonNetwork/SubstrateNetApi/wiki/Installation#substrate-in-net) 30 | - [Unity3D](https://github.com/JetonNetwork/SubstrateNetApi/wiki/Installation#substrate-in-unity3d) 31 | 1. [Usage](https://github.com/JetonNetwork/SubstrateNetApi/wiki/Usage) 32 | 1. [Types](https://github.com/JetonNetwork/SubstrateNetApi/wiki/Types#types) 33 | - [Base Types](https://github.com/JetonNetwork/SubstrateNetApi/wiki/Types#base-types) 34 | - [Enum Types](https://github.com/JetonNetwork/SubstrateNetApi/wiki/Types#enum-types) 35 | - [Struct Types](https://github.com/JetonNetwork/SubstrateNetApi/wiki/Types#struct-types) 36 | 1. [Wallet](https://github.com/JetonNetwork/SubstrateNetApi/wiki/Wallet) 37 | - [Create](https://github.com/JetonNetwork/SubstrateNetApi/wiki/Wallet#create-a-new-wallet) 38 | - [Mnemonic / Restore](https://github.com/JetonNetwork/SubstrateNetApi/wiki/Wallet#mnemonic--restore) 39 | - [Wallet File](https://github.com/JetonNetwork/SubstrateNetApi/wiki/Wallet#wallet-file) 40 | 1. [Extension](https://github.com/JetonNetwork/SubstrateNetApi/wiki/Extension#extension) 41 | 1. [Testing](https://github.com/JetonNetwork/SubstrateNetApi/wiki/Testing) 42 | - [Guide](https://github.com/JetonNetwork/SubstrateNetApi/wiki/Testing#guide) 43 | - [Node-Template](https://github.com/JetonNetwork/SubstrateNetApi/wiki/Testing#node-template) 44 | 1. [Project](https://github.com/JetonNetwork/SubstrateNetApi/wiki/Project#project) 45 | - [Substrate Version](https://github.com/JetonNetwork/SubstrateNetApi/wiki/Project#substrate-version) 46 | - [Upgrading Substrate Version](https://github.com/JetonNetwork/SubstrateNetApi/wiki/Project#upgrading-substrate-version) 47 | 48 | ## Other Projects 49 | 50 | Those projects are related to the SubstrateNetApi, by either implementing the API or being supported in the API. 51 | 52 | - [SubstrateNetApiExt](https://github.com/JetonNetwork/SubstrateNetApiExt), SubstrateNetApi Extension Template a simple template for custom extension that integrate a pallet or set of pallets functionality for SubstrateNetApi. 53 | - [Unity3DExample](https://github.com/dotmog/Unity3DExample), basic example of two test scenes implementing the substrate net api. 54 | - [SubstrateUnityWalletSimple](https://github.com/dotmog/SubstrateUnityWalletSimple), simple test wallet integrating the substrate net wallet. 55 | - [JtonNodeTemplate](https://github.com/JetonNetwork/JtonNodeTemplate), basic node-template currently used for the integration test and as development base for pallets. 56 | - [jton-pallet-template](https://github.com/JetonNetwork/jton-pallet-template), Jeton Network Pallet Template, This is a template for a Jeton Network pallet which lives as its own crate so it can be imported into multiple runtimes. It is based on the "template" pallet that is included with the Substrate node template. 57 | 58 | ## Special Thanks 59 | - https://github.com/gautamdhameja/sr25519-dotnet 60 | - https://github.com/usetech-llc/polkadot_api_dotnet 61 | -------------------------------------------------------------------------------- /Sandbox/Sandbox.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /SubstrateNetApi/Constants.cs: -------------------------------------------------------------------------------- 1 | namespace SubstrateNetApi 2 | { 3 | public class Constants 4 | { 5 | public const ulong ExtrinsicEraPeriodDefault = 64; 6 | 7 | /// The extrinsic version 8 | public const byte ExtrinsicVersion = 4; // aka the 2. TRANSACTION_VERSION 9 | // https://github.com/paritytech/substrate/blob/c0cb70419798eb7fd38806da668bec05f8cfd7f1/primitives/runtime/src/generic/unchecked_extrinsic.rs#L33 10 | 11 | // https://polkadot.js.org/docs/api/FAQ/ 12 | // 0 = AccountId (no prefix), 1 = IndicesLookup (0xFF), 2 = MutiAddress (https://github.com/paritytech/substrate/pull/7380) 13 | public static uint AddressVersion = 2; 14 | } 15 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Exceptions/ClientNotConnectedException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SubstrateNetApi.Exceptions 4 | { 5 | public class ClientNotConnectedException : Exception 6 | { 7 | public ClientNotConnectedException(string message) 8 | : base(message) 9 | { } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /SubstrateNetApi/Exceptions/ConverterAlreadyRegisteredException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SubstrateNetApi.Exceptions 4 | { 5 | public class ConverterAlreadyRegisteredException : Exception 6 | { 7 | public ConverterAlreadyRegisteredException(string message) 8 | : base(message) 9 | { } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /SubstrateNetApi/Exceptions/MissingConverterException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SubstrateNetApi.Exceptions 4 | { 5 | public class MissingConverterException : Exception 6 | { 7 | public MissingConverterException(string message) : 8 | base(message) 9 | { } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /SubstrateNetApi/Exceptions/MissingModuleOrItemException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SubstrateNetApi.Exceptions 4 | { 5 | public class MissingModuleOrItemException : Exception 6 | { 7 | public MissingModuleOrItemException(string message) 8 | : base(message) 9 | { 10 | 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /SubstrateNetApi/Exceptions/MissingParameterException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SubstrateNetApi.Exceptions 4 | { 5 | public class MissingParameterException : Exception 6 | { 7 | public MissingParameterException(string message) 8 | : base(message) 9 | { } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /SubstrateNetApi/HashExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Blake2Core; 5 | using Extensions.Data; 6 | using SubstrateNetApi.Model.Meta; 7 | 8 | namespace SubstrateNetApi 9 | { 10 | public class HashExtension 11 | { 12 | public static byte[] Hash(Storage.Hasher hasher, byte[] bytes) 13 | { 14 | switch (hasher) 15 | { 16 | case Storage.Hasher.Identity: 17 | return bytes; 18 | 19 | case Storage.Hasher.BlakeTwo128: 20 | return Blake2(bytes, 128); 21 | 22 | case Storage.Hasher.BlakeTwo256: 23 | return Blake2(bytes, 256); 24 | 25 | case Storage.Hasher.BlakeTwo128Concat: 26 | return Blake2Concat(bytes, 128); 27 | 28 | case Storage.Hasher.Twox128: 29 | return Twox128(bytes); 30 | 31 | case Storage.Hasher.Twox256: 32 | return Twox256(bytes); 33 | 34 | case Storage.Hasher.Twox64Concat: 35 | return Twox64Concat(bytes); 36 | 37 | case Storage.Hasher.None: 38 | default: 39 | throw new NotSupportedException(); 40 | } 41 | } 42 | 43 | /// Blake2 hashed the specified bytes. 44 | /// The bytes. 45 | /// The size. 46 | /// The key. 47 | /// 48 | ///
49 | ///
50 | public static byte[] Blake2(byte[] bytes, int size = 128, IReadOnlyList key = null) 51 | { 52 | var config = new Blake2BConfig {OutputSizeInBits = size, Key = null}; 53 | return Blake2B.ComputeHash(bytes, config); 54 | } 55 | 56 | /// Blake2 hashed with bytes concated at the end. 57 | /// The bytes. 58 | /// The size. 59 | /// 60 | ///
61 | ///
62 | public static byte[] Blake2Concat(byte[] bytes, int size = 128) 63 | { 64 | var config = new Blake2BConfig {OutputSizeInBits = size, Key = null}; 65 | return Blake2B.ComputeHash(bytes, config).Concat(bytes).ToArray(); 66 | } 67 | 68 | /// Blake2 hashed the specified ss prefixed. 69 | /// The ss prefixed. 70 | /// The start. 71 | /// The count. 72 | /// 73 | ///
74 | ///
75 | internal static byte[] Blake2(byte[] ssPrefixed, int start, int count) 76 | { 77 | return Blake2B.ComputeHash(ssPrefixed, start, count); 78 | } 79 | 80 | /// XXHash 128 bytes. 81 | /// The bytes. 82 | /// 83 | ///
84 | ///
85 | public static byte[] Twox128(byte[] bytes) 86 | { 87 | return BitConverter.GetBytes(XXHash.XXH64(bytes, 0)) 88 | .Concat(BitConverter.GetBytes(XXHash.XXH64(bytes, 1))) 89 | .ToArray(); 90 | } 91 | 92 | /// XXHash 256 bytes. 93 | /// The bytes. 94 | /// 95 | ///
96 | ///
97 | public static byte[] Twox256(byte[] bytes) 98 | { 99 | return BitConverter.GetBytes(XXHash.XXH64(bytes, 0)) 100 | .Concat(BitConverter.GetBytes(XXHash.XXH64(bytes, 1))) 101 | .Concat(BitConverter.GetBytes(XXHash.XXH64(bytes, 2))) 102 | .Concat(BitConverter.GetBytes(XXHash.XXH64(bytes, 3))) 103 | .ToArray(); 104 | } 105 | 106 | /// XXHashed 64 hashed with bytes concated at the end. 107 | /// The bytes. 108 | /// 109 | ///
110 | ///
111 | public static byte[] Twox64Concat(byte[] bytes) 112 | { 113 | return BitConverter.GetBytes(XXHash.XXH64(bytes)).Concat(bytes).ToArray().ToArray(); 114 | } 115 | } 116 | } -------------------------------------------------------------------------------- /SubstrateNetApi/ITypeConverter.cs: -------------------------------------------------------------------------------- 1 | namespace SubstrateNetApi 2 | { 3 | /// Interface for type converter. 4 | /// 19.09.2020. 5 | public interface ITypeConverter 6 | { 7 | /// Gets the name of the type. 8 | /// The name of the type. 9 | string TypeName { get; } 10 | 11 | /// Creates a new object. 12 | /// The value. 13 | /// An object. 14 | object Create(string value); 15 | } 16 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Mnemonic.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using System.Security.Cryptography; 3 | using Schnorrkel.Keys; 4 | using System; 5 | using dotnetstandard_bip39; 6 | using System.IO; 7 | 8 | namespace SubstrateNetApi 9 | { 10 | public static class Mnemonic 11 | { 12 | /// 13 | /// Rfc2898DeriveBytes, with HMACSHA512 usable for .NETStandard 2.0 14 | /// 15 | /// 16 | /// 17 | /// 18 | /// 19 | /// 20 | public static byte[] PBKDF2Sha512GetBytes(int dklen, byte[] password, byte[] salt, int iterationCount) 21 | { 22 | using (var hmac = new HMACSHA512(password)) 23 | { 24 | int hashLength = hmac.HashSize / 8; 25 | if ((hmac.HashSize & 7) != 0) 26 | hashLength++; 27 | int keyLength = dklen / hashLength; 28 | if (dklen > (0xFFFFFFFFL * hashLength) || dklen < 0) 29 | { 30 | throw new ArgumentOutOfRangeException("dklen"); 31 | } 32 | if (dklen % hashLength != 0) 33 | { 34 | keyLength++; 35 | } 36 | byte[] extendedkey = new byte[salt.Length + 4]; 37 | Buffer.BlockCopy(salt, 0, extendedkey, 0, salt.Length); 38 | using (var ms = new MemoryStream()) 39 | { 40 | for (int i = 0; i < keyLength; i++) 41 | { 42 | extendedkey[salt.Length] = (byte)(((i + 1) >> 24) & 0xFF); 43 | extendedkey[salt.Length + 1] = (byte)(((i + 1) >> 16) & 0xFF); 44 | extendedkey[salt.Length + 2] = (byte)(((i + 1) >> 8) & 0xFF); 45 | extendedkey[salt.Length + 3] = (byte)(((i + 1)) & 0xFF); 46 | byte[] u = hmac.ComputeHash(extendedkey); 47 | Array.Clear(extendedkey, salt.Length, 4); 48 | byte[] f = u; 49 | for (int j = 1; j < iterationCount; j++) 50 | { 51 | u = hmac.ComputeHash(u); 52 | for (int k = 0; k < f.Length; k++) 53 | { 54 | f[k] ^= u[k]; 55 | } 56 | } 57 | ms.Write(f, 0, f.Length); 58 | Array.Clear(u, 0, u.Length); 59 | Array.Clear(f, 0, f.Length); 60 | } 61 | byte[] dk = new byte[dklen]; 62 | ms.Position = 0; 63 | ms.Read(dk, 0, dklen); 64 | ms.Position = 0; 65 | for (long i = 0; i < ms.Length; i++) 66 | { 67 | ms.WriteByte(0); 68 | } 69 | Array.Clear(extendedkey, 0, extendedkey.Length); 70 | return dk; 71 | } 72 | } 73 | } 74 | 75 | /// 76 | /// Get seed from entropy bytes, make sure entropy is a byte array from a correctly recovered and checksumed BIP39. 77 | /// Following slices are supported: 78 | /// + 16 bytes for 12 words. 79 | /// + 20 bytes for 15 words. 80 | /// + 24 bytes for 18 words. 81 | /// + 28 bytes for 21 words. 82 | /// + 32 bytes for 24 words. 83 | /// Other slices will lead to a InvalidEntropy error. 84 | /// https://github.com/paritytech/substrate-bip39/blob/eef2f86337d2dab075806c12948e8a098aa59d59/src/lib.rs#L45 85 | /// 86 | /// 87 | /// 88 | /// 89 | public static byte[] SeedFromEntropy(byte[] entropyBytes, string password) 90 | { 91 | if (entropyBytes.Length < 16 || entropyBytes.Length > 32 || entropyBytes.Length % 4 != 0) 92 | { 93 | throw new Exception($"InvalidEntropy, length not allowed '{entropyBytes.Length}'"); 94 | } 95 | var saltBytes = Encoding.UTF8.GetBytes("mnemonic" + password); 96 | return PBKDF2Sha512GetBytes(64, entropyBytes, saltBytes, 2048); 97 | } 98 | 99 | /// 100 | /// 101 | /// 102 | /// 103 | /// 104 | /// 105 | public static string GetEntropy(string mnemonic, BIP39Wordlist bIP39Wordlist) 106 | => new BIP39().MnemonicToEntropy(mnemonic, bIP39Wordlist); 107 | 108 | /// 109 | /// Get secret key from mnemonic 110 | /// 111 | /// 112 | /// 113 | /// 114 | /// 115 | public static byte[] GetSecretKeyFromMnemonic(string mnemonic, string password, BIP39Wordlist bIP39Wordlist) 116 | { 117 | var entropyBytes = Utils.HexToByteArray(GetEntropy(mnemonic, bIP39Wordlist)); 118 | var seedBytes = SeedFromEntropy(entropyBytes, password); 119 | return seedBytes.AsMemory().Slice(0, 32).ToArray(); 120 | } 121 | 122 | /// 123 | /// Get a key pair from mnemonic 124 | /// 125 | /// 126 | /// 127 | /// 128 | /// 129 | /// 130 | public static KeyPair GetKeyPairFromMnemonic(string mnemonic, string password, BIP39Wordlist bIP39Wordlist, ExpandMode expandMode) 131 | { 132 | var secretBytes = GetSecretKeyFromMnemonic(mnemonic, password, bIP39Wordlist); 133 | var miniSecret = new MiniSecret(secretBytes, expandMode); 134 | return new KeyPair(miniSecret.ExpandToPublic(), miniSecret.ExpandToSecret()); 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Calls/GenericExtrinsicCall.cs: -------------------------------------------------------------------------------- 1 | using SubstrateNetApi.Model.Types; 2 | using System.Collections.Generic; 3 | using System.Numerics; 4 | using SubstrateNetApi.Model.Types.Base; 5 | 6 | namespace SubstrateNetApi.Model.Calls 7 | { 8 | public class GenericExtrinsicCall : IEncodable 9 | { 10 | public string ModuleName { get; } 11 | 12 | public string CallName { get; } 13 | 14 | public List CallArguments; 15 | 16 | public GenericExtrinsicCall(string moduleName, string callName, params IType[] list) 17 | { 18 | ModuleName = moduleName; 19 | 20 | CallName = callName; 21 | 22 | CallArguments = new List(); 23 | 24 | foreach (var element in list) 25 | { 26 | CallArguments.Add(element); 27 | } 28 | } 29 | 30 | public byte[] Encode() 31 | { 32 | var byteList = new List(); 33 | foreach (var callArgument in CallArguments) 34 | { 35 | byteList.AddRange(callArgument.Encode()); 36 | } 37 | return byteList.ToArray(); 38 | } 39 | } 40 | 41 | public class ExtrinsicCall 42 | { 43 | public static GenericExtrinsicCall BalanceTransfer(string address, BigInteger balanceAmount) 44 | { 45 | var accountId = new AccountId(); 46 | accountId.Create(Utils.GetPublicKeyFrom(address)); 47 | 48 | var balance = new Balance(); 49 | balance.Create(balanceAmount); 50 | 51 | return BalanceTransfer(accountId, balance); 52 | } 53 | 54 | public static GenericExtrinsicCall BalanceTransfer(AccountId dest, Balance value) 55 | { 56 | return new GenericExtrinsicCall("Balances", "transfer", dest, value); 57 | } 58 | 59 | public static GenericExtrinsicCall BalanceSetBalance(AccountId who, Balance newFree, Balance newReserved) 60 | { 61 | return new GenericExtrinsicCall("Balances", "set_balance", who, newFree, newReserved); 62 | } 63 | 64 | public static GenericExtrinsicCall BalanceForceTransfer(AccountId source, AccountId dest, Balance value) 65 | { 66 | return new GenericExtrinsicCall("Balances", "force_transfer", source, dest, value); 67 | } 68 | 69 | public static GenericExtrinsicCall BalanceTransferKeepAlive(AccountId dest, Balance value) 70 | { 71 | return new GenericExtrinsicCall("Balances", "transfer_keep_alive", dest, value); 72 | } 73 | 74 | public static GenericExtrinsicCall SystemSuicide() 75 | { 76 | return new GenericExtrinsicCall("System", "suicide"); 77 | } 78 | 79 | public static GenericExtrinsicCall TimestampSet(Moment moment) 80 | { 81 | return new GenericExtrinsicCall("Timestamp", "set"); 82 | } 83 | 84 | 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Custom/Kusama/KusamaCalls.cs: -------------------------------------------------------------------------------- 1 | using SubstrateNetApi.Model.Types; 2 | using SubstrateNetApi.Model.Types.Base; 3 | using SubstrateNetApi.Model.Types.Custom; 4 | using SubstrateNetApi.Model.Types.Enum; 5 | using SubstrateNetApi.Model.Types.Struct; 6 | using System.Linq; 7 | using System.Numerics; 8 | using System.Text; 9 | 10 | namespace SubstrateNetApi.Model.Calls 11 | { 12 | public class KusamaCall 13 | { 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Custom/Kusama/KusamaTypes.cs: -------------------------------------------------------------------------------- 1 | using SubstrateNetApi.Model.Types.Base; 2 | using SubstrateNetApi.Model.Types.Enum; 3 | using SubstrateNetApi.Model.Types.Struct; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Numerics; 7 | using System.Text; 8 | 9 | namespace SubstrateNetApi.Model.Types.Custom 10 | { 11 | #region BASE_TYPES 12 | 13 | #endregion 14 | 15 | #region ENUM_TYPES 16 | 17 | #endregion 18 | 19 | #region STRUCT_TYPES 20 | 21 | #endregion 22 | 23 | #region INHERITED_TYPES 24 | 25 | #endregion 26 | 27 | 28 | } 29 | -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Custom/Polkadot/PolkadotCalls.cs: -------------------------------------------------------------------------------- 1 | using SubstrateNetApi.Model.Types; 2 | using SubstrateNetApi.Model.Types.Base; 3 | using SubstrateNetApi.Model.Types.Custom; 4 | using SubstrateNetApi.Model.Types.Enum; 5 | using SubstrateNetApi.Model.Types.Struct; 6 | using System.Linq; 7 | using System.Numerics; 8 | using System.Text; 9 | 10 | namespace SubstrateNetApi.Model.Calls 11 | { 12 | public class PolkaDotCall 13 | { 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Custom/Polkadot/PolkadotTypes.cs: -------------------------------------------------------------------------------- 1 | using SubstrateNetApi.Model.Types.Base; 2 | using SubstrateNetApi.Model.Types.Enum; 3 | using SubstrateNetApi.Model.Types.Struct; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Numerics; 7 | using System.Text; 8 | 9 | namespace SubstrateNetApi.Model.Types.Custom 10 | { 11 | #region BASE_TYPES 12 | 13 | #endregion 14 | 15 | #region ENUM_TYPES 16 | 17 | #endregion 18 | 19 | #region STRUCT_TYPES 20 | 21 | #endregion 22 | 23 | #region INHERITED_TYPES 24 | 25 | #endregion 26 | 27 | 28 | } 29 | -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Custom/UniqueTestnet/UniqueTestnetCalls.cs: -------------------------------------------------------------------------------- 1 | using SubstrateNetApi.Model.Types; 2 | using SubstrateNetApi.Model.Types.Base; 3 | using SubstrateNetApi.Model.Types.Custom; 4 | using SubstrateNetApi.Model.Types.Enum; 5 | using SubstrateNetApi.Model.Types.Struct; 6 | using System.Linq; 7 | using System.Numerics; 8 | using System.Text; 9 | 10 | namespace SubstrateNetApi.Model.Calls 11 | { 12 | public class UniqueCall 13 | { 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Extrinsics/Era.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using SubstrateNetApi.Model.Types; 3 | using System; 4 | 5 | namespace SubstrateNetApi.Model.Extrinsics 6 | { 7 | public class Era : IEncodable 8 | { 9 | public bool IsImmortal { get; } 10 | 11 | public ulong Period { get; } 12 | 13 | public ulong Phase { get; } 14 | 15 | public ulong EraStart(ulong currentBlockNumber) => IsImmortal ? 0 : (Math.Max(currentBlockNumber, Phase) - Phase) / Period * Period + Phase; 16 | 17 | /// 18 | /// Initializes a new instance of the class. 19 | /// 20 | /// The period. 21 | /// The phase. 22 | /// if set to true [is immortal]. 23 | public Era(ulong period, ulong phase, bool isImmortal) 24 | { 25 | Period = period; 26 | Phase = phase; 27 | IsImmortal = isImmortal; 28 | 29 | } 30 | 31 | override 32 | public string ToString() 33 | { 34 | return JsonConvert.SerializeObject(this); 35 | } 36 | 37 | /// 38 | /// Creates the specified life time. 39 | /// 40 | /// The life time. 41 | /// The finalized header block number. 42 | /// 43 | public static Era Create(uint lifeTime, ulong finalizedHeaderBlockNumber) 44 | { 45 | if (lifeTime == 0) 46 | { 47 | return new Era(0, 0, true); 48 | } 49 | 50 | // NODE: { "IsImmortal":false,"Period":64,"Phase":49} 51 | // API: { "IsImmortal":false,"Period":64,"Phase":61} 52 | 53 | // RUST Implementation 54 | //let period = period.checked_next_power_of_two() 55 | // .unwrap_or(1 << 16) 56 | // .max(4) 57 | // .min(1 << 16); 58 | //let phase = current % period; 59 | //let quantize_factor = (period >> 12).max(1); 60 | //let quantized_phase = phase / quantize_factor * quantize_factor; 61 | //Era::Mortal(period, quantized_phase) 62 | 63 | ulong period = (ulong)Math.Pow(2, Math.Round(Math.Log(lifeTime, 2))); 64 | period = Math.Max(period, 4); 65 | period = Math.Min(period, 65536); 66 | ulong phase = finalizedHeaderBlockNumber % period; 67 | var quantize_factor = Math.Max(period >> 12, 1); 68 | var quantized_phase = phase / quantize_factor * quantize_factor; 69 | 70 | return new Era(period, quantized_phase, false); 71 | } 72 | 73 | /// 74 | /// Encodes this instance. 75 | /// 76 | /// 77 | public byte[] Encode() 78 | { 79 | if (IsImmortal) 80 | { 81 | return new byte[] { 0x00 }; 82 | } 83 | var quantizeFactor = Math.Max(1, Period / 4096); 84 | var lastBit = Period & (ulong)-(long)Period; 85 | //var rest = _period; 86 | //var lastBit = 1; 87 | //while (rest % 2 == 0 && rest != 0) 88 | //{ 89 | // rest /= 2; 90 | // lastBit *= 2; 91 | //} 92 | var logOf2 = lastBit != 0 ? Math.Log(lastBit, 2) : 64; 93 | var low = (ushort)Math.Min(15, Math.Max(1, logOf2 - 1)); 94 | var high = (ushort)(Phase / quantizeFactor << 4); 95 | var encoded = (ushort)(low | high); 96 | 97 | return BitConverter.GetBytes(encoded); 98 | } 99 | 100 | /// 101 | /// Decodes the specified bytes. 102 | /// 103 | /// The bytes. 104 | /// 105 | /// 106 | /// 0, 0, true 107 | /// or 108 | /// 0, 0, true 109 | /// 110 | public static Era Decode(byte[] bytes) 111 | { 112 | if (bytes.Length == 1 && bytes[0] == 0x00) 113 | { 114 | return new Era(0, 0, true); 115 | 116 | } 117 | else if (bytes.Length == 2) 118 | { 119 | var ul0 = (ulong)bytes[0]; 120 | var ul1 = (ulong)bytes[1]; 121 | var encoded = ul0 + (ul1 << 8); 122 | var period = 2UL << (int)(encoded % (1 << 4)); 123 | var quantizeFactor = Math.Max(1, period >> 12); 124 | var phase = (encoded >> 4) * quantizeFactor; 125 | if (period < 4 || phase >= period) 126 | { 127 | throw new ArgumentException($"{Utils.Bytes2HexString(new byte[] { bytes[0], bytes[1] })} is not a valid representation of Era."); 128 | } 129 | return new Era(period, phase, false); 130 | } 131 | else 132 | { 133 | throw new Exception("Invalid byte array to get era."); 134 | } 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Extrinsics/Method.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using SubstrateNetApi.Model.Meta; 3 | using System.Collections.Generic; 4 | 5 | namespace SubstrateNetApi.Model.Extrinsics 6 | { 7 | public class Method 8 | { 9 | public string ModuleName; 10 | 11 | public byte ModuleIndex; 12 | 13 | public string CallName; 14 | 15 | public byte CallIndex; 16 | 17 | public Argument[] Arguments; 18 | 19 | public byte[] Parameters; 20 | 21 | /// 22 | /// Initializes a new instance of the class. 23 | /// 24 | /// Index of the module. 25 | /// Index of the call. 26 | /// The parameters. 27 | public Method(byte moduleIndex, byte callIndex, byte[] parameters) 28 | { 29 | ModuleIndex = moduleIndex; 30 | CallIndex = callIndex; 31 | Parameters = parameters ?? new byte[0]; 32 | } 33 | 34 | /// 35 | /// Initializes a new instance of the class. 36 | /// 37 | /// Index of the module. 38 | /// Index of the call. 39 | public Method(byte moduleIndex, byte callIndex) 40 | { 41 | ModuleIndex = moduleIndex; 42 | CallIndex = callIndex; 43 | Parameters = new byte[0]; 44 | } 45 | 46 | /// 47 | /// Initializes a new instance of the class. 48 | /// 49 | /// The module. 50 | /// The call. 51 | /// The parameters. 52 | public Method(Module module, Call call, byte[] parameters) 53 | { 54 | ModuleName = module.Name; 55 | ModuleIndex = module.Index; 56 | CallName = call.Name; 57 | CallIndex = module.IndexOf(call); 58 | Parameters = parameters; 59 | } 60 | 61 | /// 62 | /// Encodes this instance. 63 | /// 64 | /// 65 | public byte[] Encode() 66 | { 67 | var result = new List(); 68 | result.Add(ModuleIndex); 69 | result.Add(CallIndex); 70 | result.AddRange(Parameters); 71 | return result.ToArray(); 72 | } 73 | 74 | public override string ToString() 75 | { 76 | return JsonConvert.SerializeObject(this); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Extrinsics/Payload.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | 3 | namespace SubstrateNetApi.Model.Extrinsics 4 | { 5 | public class Payload 6 | { 7 | private Method _call; 8 | private SignedExtensions _signedExtension; 9 | 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// 13 | /// The call. 14 | /// The signed extensions. 15 | public Payload(Method call, SignedExtensions signedExtensions) 16 | { 17 | _call = call; 18 | _signedExtension = signedExtensions; 19 | } 20 | 21 | /// 22 | /// Encodes this instance. 23 | /// 24 | /// 25 | public byte[] Encode() 26 | { 27 | byte[] bytes = _call.Encode().Concat(_signedExtension.Encode()).ToArray(); 28 | return bytes; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Extrinsics/SignedExtensions.cs: -------------------------------------------------------------------------------- 1 | using SubstrateNetApi.Model.Types; 2 | using System.Collections.Generic; 3 | using SubstrateNetApi.Model.Types.Base; 4 | 5 | namespace SubstrateNetApi.Model.Extrinsics 6 | { 7 | public class SignedExtensions 8 | { 9 | private uint _specVersion; 10 | 11 | private uint _txVersion; 12 | 13 | private Hash _genesis; 14 | 15 | private Hash _startEra; 16 | 17 | private Era _mortality; 18 | 19 | private CompactInteger _nonce; 20 | 21 | private CompactInteger _chargeTransactionPayment; 22 | 23 | /// 24 | /// Initializes a new instance of the class. 25 | /// 26 | /// The spec version. 27 | /// The tx version. 28 | /// The genesis. 29 | /// The start era. 30 | /// The mortality. 31 | /// The nonce. 32 | /// The charge transaction payment. 33 | public SignedExtensions(uint specVersion, uint txVersion, Hash genesis, Hash startEra, Era mortality, CompactInteger nonce, CompactInteger chargeTransactionPayment) 34 | { 35 | _specVersion = specVersion; 36 | _txVersion = txVersion; 37 | _genesis = genesis; 38 | _startEra = startEra; 39 | _mortality = mortality; 40 | _nonce = nonce; 41 | _chargeTransactionPayment = chargeTransactionPayment; 42 | } 43 | 44 | /// 45 | /// Gets the extra. 46 | /// 47 | /// 48 | public byte[] GetExtra() 49 | { 50 | var bytes = new List(); 51 | 52 | // CheckMortality 53 | bytes.AddRange(_mortality.Encode()); 54 | 55 | // CheckNonce 56 | bytes.AddRange(_nonce.Encode()); 57 | 58 | // ChargeTransactionPayment 59 | bytes.AddRange(_chargeTransactionPayment.Encode()); 60 | 61 | return bytes.ToArray(); 62 | } 63 | 64 | /// 65 | /// Gets the additional signed. 66 | /// 67 | /// 68 | public byte[] GetAdditionalSigned() 69 | { 70 | var bytes = new List(); 71 | 72 | // CheckSpecVersion 73 | bytes.AddRange(Utils.Value2Bytes(_specVersion)); 74 | 75 | // CheckTxVersion 76 | bytes.AddRange(Utils.Value2Bytes(_txVersion)); 77 | 78 | // CheckGenesis 79 | bytes.AddRange(_genesis.Bytes); 80 | 81 | // CheckMortality, Additional Blockhash check. Immortal = genesis_hash, Mortal = logic 82 | bytes.AddRange(_startEra.Bytes); 83 | 84 | return bytes.ToArray(); 85 | } 86 | 87 | /// 88 | /// Encodes this instance. 89 | /// 90 | /// 91 | public byte[] Encode() 92 | { 93 | var bytes = new List(); 94 | 95 | // Extra: Era, Nonce & Tip 96 | bytes.AddRange(GetExtra()); 97 | 98 | // Additional Signed: SpecVersion, TxVersion, Genesis, Blockhash 99 | bytes.AddRange(GetAdditionalSigned()); 100 | 101 | return bytes.ToArray(); 102 | } 103 | 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Extrinsics/UnCheckedExtrinsic.cs: -------------------------------------------------------------------------------- 1 | using SubstrateNetApi.Model.Types; 2 | using System; 3 | using System.Collections.Generic; 4 | using SubstrateNetApi.Model.Rpc; 5 | using SubstrateNetApi.Model.Types.Base; 6 | 7 | namespace SubstrateNetApi.Model.Extrinsics 8 | { 9 | public class UnCheckedExtrinsic : Extrinsic 10 | { 11 | private readonly Hash _genesis; 12 | 13 | private readonly Hash _startEra; 14 | 15 | /// 16 | /// Initializes a new instance of the class. 17 | /// 18 | /// if set to true [signed]. 19 | /// The account. 20 | /// The method. 21 | /// The era. 22 | /// The nonce. 23 | /// The tip. 24 | /// The genesis. 25 | /// The start era. 26 | public UnCheckedExtrinsic(bool signed, Account account, Method method, Era era, CompactInteger nonce, CompactInteger tip, Hash genesis, Hash startEra) 27 | : base(signed, account, nonce, method, era, tip) 28 | { 29 | _genesis = genesis; 30 | _startEra = startEra; 31 | } 32 | 33 | /// 34 | /// Gets the payload. 35 | /// 36 | /// The runtime. 37 | /// 38 | public Payload GetPayload(RuntimeVersion runtime) 39 | { 40 | return new Payload(Method, new SignedExtensions(runtime.SpecVersion, runtime.TransactionVersion, _genesis, _startEra, Era, Nonce, Tip)); 41 | } 42 | 43 | /// 44 | /// Adds the payload signature. 45 | /// 46 | /// The signature. 47 | public void AddPayloadSignature(byte[] signature) 48 | { 49 | Signature = signature; 50 | } 51 | 52 | /// 53 | /// Encodes this instance. 54 | /// 55 | /// 56 | /// Missing payload signature for signed transaction. 57 | public byte[] Encode() 58 | { 59 | if (Signed && Signature == null) 60 | { 61 | throw new Exception("Missing payload signature for signed transaction."); 62 | } 63 | 64 | var list = new List(); 65 | 66 | // 4 is the TRANSACTION_VERSION constant and it is 7 bits long, the highest bit 1 for signed transaction, 0 for unsigned. 67 | list.Add((byte)(Constants.ExtrinsicVersion | (Signed ? 0x80 : 0))); 68 | 69 | // 32 bytes + prefix depending on address encoding in chain, see Constants.Address_version 70 | list.AddRange(Account.Encode()); 71 | 72 | // key type ed = 00 and sr = FF 73 | list.Add(Account.KeyTypeByte); 74 | 75 | // add signature if exists 76 | if (Signature != null) 77 | { 78 | list.AddRange(Signature); 79 | } 80 | else 81 | { 82 | 83 | } 84 | 85 | list.AddRange(Era.Encode()); 86 | 87 | list.AddRange(Nonce.Encode()); 88 | 89 | list.AddRange(Tip.Encode()); 90 | 91 | list.AddRange(Method.Encode()); 92 | 93 | return Utils.SizePrefixedByteArray(list); 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Meta/Argument.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace SubstrateNetApi.Model.Meta 4 | { 5 | public class Argument 6 | { 7 | public string Name { get; set; } 8 | public string Type { get; set; } 9 | 10 | [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] 11 | public object Value { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Meta/Call.cs: -------------------------------------------------------------------------------- 1 | namespace SubstrateNetApi.Model.Meta 2 | { 3 | public class Call 4 | { 5 | public string Name { get; set; } 6 | public Argument[] Arguments { get; set; } 7 | public string[] Documentations { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Meta/Const.cs: -------------------------------------------------------------------------------- 1 | namespace SubstrateNetApi.Model.Meta 2 | { 3 | public class Const 4 | { 5 | public string Name { get; set; } 6 | public string Type { get; set; } 7 | public string Value { get; set; } 8 | public string[] Documentations { get; set; } 9 | } 10 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Meta/Error.cs: -------------------------------------------------------------------------------- 1 | namespace SubstrateNetApi.Model.Meta 2 | { 3 | public class Error 4 | { 5 | public string[] Documentations { get; set; } 6 | public string Name { get; set; } 7 | } 8 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Meta/Event.cs: -------------------------------------------------------------------------------- 1 | namespace SubstrateNetApi.Model.Meta 2 | { 3 | public class Event 4 | { 5 | public string[] Documentations { get; set; } 6 | public string Name { get; set; } 7 | public string[] EventArgs { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Meta/Function.cs: -------------------------------------------------------------------------------- 1 | namespace SubstrateNetApi.Model.Meta 2 | { 3 | public class Function 4 | { 5 | public Storage.Hasher Hasher { get; internal set; } 6 | public string Key1 { get; internal set; } 7 | public string Key2 { get; internal set; } 8 | public string Value { get; internal set; } 9 | public bool? IsLinked { get; internal set; } 10 | public Storage.Hasher Key2Hasher { get; internal set; } 11 | } 12 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Meta/Item.cs: -------------------------------------------------------------------------------- 1 | namespace SubstrateNetApi.Model.Meta 2 | { 3 | public class Item 4 | { 5 | public string Name { get; set; } 6 | public Storage.Modifier Modifier { get; set; } 7 | public Storage.Type Type { get; set; } 8 | public Function Function { get; set; } 9 | public string FallBack { get; set; } 10 | public string[] Documentations { get; set; } 11 | } 12 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Meta/MetaData.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Newtonsoft.Json.Converters; 3 | using System; 4 | 5 | namespace SubstrateNetApi.Model.Meta 6 | { 7 | public class MetaData 8 | { 9 | public MetaData(string origin = "unknown") 10 | { 11 | Origin = origin; 12 | } 13 | public string Origin { get; set; } 14 | public string Magic { get; set; } 15 | public string Version { get; set; } 16 | public Module[] Modules { get; set; } 17 | public string[] ExtrinsicExtensions { get; set; } 18 | 19 | public bool TryGetModuleByName(string name, out Module result) 20 | { 21 | result = null; 22 | foreach (Module module in Modules) 23 | { 24 | if (module.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase)) 25 | { 26 | result = module; 27 | return true; 28 | } 29 | } 30 | 31 | return false; 32 | } 33 | 34 | public string Serialize() 35 | { 36 | return JsonConvert.SerializeObject(this, new StringEnumConverter()); 37 | } 38 | 39 | 40 | } 41 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Meta/Module.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SubstrateNetApi.Model.Meta 4 | { 5 | public class Module 6 | { 7 | public string Name { get; set; } 8 | 9 | public byte Index { get; set; } 10 | public Storage Storage { get; set; } 11 | public Call[] Calls { get; set; } 12 | public Event[] Events { get; set; } 13 | public Const[] Consts { get; set; } 14 | public Error[] Errors { get; set; } 15 | 16 | public bool TryGetStorageItemByName(string name, out Item result) 17 | { 18 | result = null; 19 | if (Storage is null) 20 | { 21 | return false; 22 | } 23 | 24 | foreach (Item item in Storage.Items) 25 | { 26 | if (item.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase)) 27 | { 28 | result = item; 29 | return true; 30 | } 31 | } 32 | 33 | return false; 34 | } 35 | 36 | internal bool TryGetCallByName(string name, out Call result) 37 | { 38 | result = null; 39 | foreach (Call call in Calls) 40 | { 41 | if (call.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase)) 42 | { 43 | result = call; 44 | return true; 45 | } 46 | } 47 | 48 | return false; 49 | } 50 | 51 | public byte IndexOf(Call call) 52 | { 53 | return (byte)Array.IndexOf(Calls, call); 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Meta/Storage.cs: -------------------------------------------------------------------------------- 1 | namespace SubstrateNetApi.Model.Meta 2 | { 3 | public class Storage 4 | { 5 | public enum Type 6 | { 7 | Plain, Map, DoubleMap 8 | } 9 | 10 | public enum Modifier 11 | { 12 | Optional, 13 | Default 14 | } 15 | 16 | public enum Hasher 17 | { 18 | None = -1, 19 | BlakeTwo128, 20 | BlakeTwo256, 21 | BlakeTwo128Concat, 22 | Twox128, 23 | Twox256, 24 | Twox64Concat, 25 | Identity 26 | } 27 | 28 | public string Prefix { get; set; } 29 | public Item[] Items { get; set; } 30 | 31 | } 32 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Rpc/Block.cs: -------------------------------------------------------------------------------- 1 | using SubstrateNetApi.Model.Extrinsics; 2 | 3 | namespace SubstrateNetApi.Model.Rpc 4 | { 5 | public class Block 6 | { 7 | public Extrinsic[] Extrinsics { get; set; } 8 | public Header Header { get; set; } 9 | 10 | } 11 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Rpc/BlockData.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace SubstrateNetApi.Model.Rpc 4 | { 5 | public class BlockData 6 | { 7 | 8 | public BlockData(Block block, object justification) 9 | { 10 | Block = block; 11 | Justification = justification; 12 | } 13 | 14 | public Block Block { get; set; } 15 | public object Justification { get; set; } 16 | 17 | public override string ToString() 18 | { 19 | return JsonConvert.SerializeObject(this); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Rpc/Digest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace SubstrateNetApi.Model.Rpc 4 | { 5 | public class Digest 6 | { 7 | public IList Logs { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Rpc/ExtrinsicStatus.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using SubstrateNetApi.Model.Types; 3 | using SubstrateNetApi.Model.Types.Base; 4 | 5 | namespace SubstrateNetApi.Model.Rpc 6 | { 7 | public enum ExtrinsicState 8 | { 9 | None, Future, Ready, Dropped, Invalid 10 | } 11 | 12 | public class ExtrinsicStatus 13 | { 14 | public ExtrinsicState ExtrinsicState { get; set; } 15 | public string[] Broadcast { get; set; } 16 | public Hash InBlock { get; set; } 17 | public Hash Retracted { get; set; } 18 | public Hash FinalityTimeout { get; set; } 19 | public Hash Finalized { get; set; } 20 | public Hash Usurped { get; set; } 21 | 22 | public override string ToString() 23 | { 24 | return JsonConvert.SerializeObject(this); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Rpc/Header.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using SubstrateNetApi.Model.Types; 3 | using SubstrateNetApi.Model.Types.Base; 4 | using SubstrateNetApi.TypeConverters; 5 | 6 | namespace SubstrateNetApi.Model.Rpc 7 | { 8 | public class Header 9 | { 10 | public Digest Digest { get; set; } 11 | 12 | [JsonConverter(typeof(GenericTypeConverter))] 13 | public Hash ExtrinsicsRoot { get; set; } 14 | 15 | [JsonConverter(typeof(GenericTypeConverter))] 16 | public U64 Number { get; set; } 17 | 18 | [JsonConverter(typeof(GenericTypeConverter))] 19 | public Hash ParentHash { get; set; } 20 | 21 | [JsonConverter(typeof(GenericTypeConverter))] 22 | public Hash StateRoot { get; set; } 23 | 24 | public override string ToString() 25 | { 26 | return JsonConvert.SerializeObject(this); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Rpc/Health.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace SubstrateNetApi.Model.Rpc 4 | { 5 | public class Health 6 | { 7 | public bool IsSyncing { get; set; } 8 | public int Peers { get; set; } 9 | public bool ShouldHavePeers { get; set; } 10 | public override string ToString() 11 | { 12 | return JsonConvert.SerializeObject(this); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Rpc/RuntimeVersion.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace SubstrateNetApi.Model.Rpc 6 | { 7 | public class RuntimeVersion 8 | { 9 | public object[][] Apis { get; set; } 10 | public int AuthoringVersion { get; set; } 11 | public string ImplName { get; set; } 12 | public uint ImplVersion { get; set; } 13 | public string SpecName { get; set; } 14 | public uint SpecVersion { get; set; } 15 | public uint TransactionVersion { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Rpc/StorageChangeSet.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using SubstrateNetApi.Model.Types; 3 | using SubstrateNetApi.Model.Types.Base; 4 | using SubstrateNetApi.Model.Types.Struct; 5 | using SubstrateNetApi.TypeConverters; 6 | 7 | namespace SubstrateNetApi.Model.Rpc 8 | { 9 | public class StorageChangeSet 10 | { 11 | [JsonConverter(typeof(GenericTypeConverter))] 12 | public Hash Block { get; set; } 13 | 14 | 15 | public string[][] Changes { get; set; } 16 | //[JsonConverter(typeof(GenericTypeConverter>>))] 17 | //public Vec> Changes { get; set; } 18 | 19 | public override string ToString() 20 | { 21 | return JsonConvert.SerializeObject(this); 22 | } 23 | } 24 | 25 | /// 26 | /// TODO: This needs to be verified, if we can use it to convert straight 27 | /// 28 | /// pub struct StorageChangeSet { 29 | /// pub block: Hash, 30 | /// pub changes: Vec<(StorageKey, Option)>, 31 | /// } 32 | /// 33 | public class NewStorageChangeSet 34 | { 35 | [JsonConverter(typeof(GenericTypeConverter))] 36 | public Hash Block { get; set; } 37 | 38 | [JsonConverter(typeof(GenericTypeConverter>>))] 39 | public Vec> Changes { get; set; } 40 | 41 | public override string ToString() 42 | { 43 | return JsonConvert.SerializeObject(this); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/Account.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Newtonsoft.Json; 3 | using SubstrateNetApi.Model.Types.Base; 4 | 5 | namespace SubstrateNetApi.Model.Types 6 | { 7 | public enum KeyType 8 | { 9 | Ed25519, 10 | Sr25519 11 | } 12 | 13 | public class Account : AccountId 14 | { 15 | public KeyType KeyType; 16 | 17 | [JsonIgnore] 18 | public byte KeyTypeByte 19 | { 20 | get 21 | { 22 | switch (KeyType) 23 | { 24 | case KeyType.Ed25519: 25 | return 0; 26 | case KeyType.Sr25519: 27 | return 1; 28 | default: 29 | throw new Exception($"Unknown key type found '{KeyType}'."); 30 | } 31 | } 32 | } 33 | 34 | [JsonIgnore] public byte[] PrivateKey { get; private set; } 35 | 36 | public void Create(KeyType keyType, byte[] privateKey, byte[] publicKey) 37 | { 38 | KeyType = keyType; 39 | PrivateKey = privateKey; 40 | base.Create(publicKey); 41 | } 42 | 43 | public void Create(KeyType keyType, byte[] publicKey) 44 | { 45 | Create(keyType, null, publicKey); 46 | } 47 | 48 | public static Account Build(KeyType keyType, byte[] privateKey, byte[] publicKey) 49 | { 50 | var account = new Account(); 51 | account.Create(keyType, privateKey, publicKey); 52 | return account; 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/Base/AccountId.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace SubstrateNetApi.Model.Types.Base 5 | { 6 | public class AccountId : BaseType 7 | { 8 | // TODO: ::Source -- RawAccountId is unprefixed Address 9 | public override string Name() => "T::AccountId"; 10 | 11 | // TODO: might have to change this based on the address type. 12 | public override int Size() => 32; 13 | 14 | public override byte[] Encode() 15 | { 16 | var bytes = new List(); 17 | switch (Constants.AddressVersion) 18 | { 19 | case 0: 20 | return Bytes; 21 | case 1: 22 | bytes.Add(0xFF); 23 | bytes.AddRange(Bytes); 24 | return bytes.ToArray(); 25 | case 2: 26 | bytes.Add(0x00); 27 | bytes.AddRange(Bytes); 28 | return bytes.ToArray(); 29 | default: 30 | throw new NotImplementedException("Unknown address version please refer to Constants.cs"); 31 | } 32 | } 33 | 34 | public override void Create(byte[] byteArray) 35 | { 36 | Bytes = byteArray; 37 | Value = Utils.GetAddressFrom(byteArray); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/Base/Assets.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace SubstrateNetApi.Model.Types.Base 6 | { 7 | public class AssetId : U32 8 | { 9 | public override string Name() => "AssetId"; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/Base/Balance.cs: -------------------------------------------------------------------------------- 1 | using System.Numerics; 2 | 3 | namespace SubstrateNetApi.Model.Types.Base 4 | { 5 | public class Balance : BaseType 6 | { 7 | public override string Name() => "T::Balance"; 8 | 9 | public override int Size() => 16; 10 | 11 | public override byte[] Encode() 12 | { 13 | return new CompactInteger(Value).Encode(); 14 | } 15 | 16 | public override void Create(byte[] byteArray) 17 | { 18 | Bytes = byteArray; 19 | Value = new BigInteger(byteArray); 20 | } 21 | 22 | public void Create(BigInteger value) 23 | { 24 | Bytes = value.ToByteArray(); 25 | Value = value; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/Base/BlockNumber.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SubstrateNetApi.Model.Types.Base 4 | { 5 | public class BlockNumber : BaseType 6 | { 7 | public override string Name() => "T::BlockNumber"; 8 | 9 | public override int Size() => 4; 10 | 11 | public override byte[] Encode() 12 | { 13 | var reversed = Bytes; 14 | Array.Reverse(reversed); 15 | return reversed; 16 | } 17 | 18 | public override void Create(byte[] byteArray) 19 | { 20 | Bytes = byteArray; 21 | Value = BitConverter.ToUInt32(byteArray, 0); 22 | } 23 | 24 | public void Create(uint value) 25 | { 26 | Bytes = BitConverter.GetBytes(value); 27 | Value = value; 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/Base/Bool.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SubstrateNetApi.Model.Types.Base 4 | { 5 | public class Bool : BaseType 6 | { 7 | public override string Name() => "bool"; 8 | 9 | public override int Size() => 1; 10 | 11 | public override byte[] Encode() 12 | { 13 | return Bytes; 14 | } 15 | 16 | public override void Create(byte[] byteArray) 17 | { 18 | Bytes = byteArray; 19 | Value = byteArray[0] > 0; 20 | } 21 | 22 | public void Create(bool value) 23 | { 24 | Bytes = new byte[] { (byte)(value ? 0x01 : 0x00) }; 25 | Value = value; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/Base/Hash.cs: -------------------------------------------------------------------------------- 1 | namespace SubstrateNetApi.Model.Types.Base 2 | { 3 | public class Hash : BaseType 4 | { 5 | public override string Name() => "T::Hash"; 6 | 7 | public override int Size() => 32; 8 | 9 | public override byte[] Encode() 10 | { 11 | return Bytes; 12 | } 13 | 14 | public override void Create(byte[] byteArray) 15 | { 16 | Bytes = byteArray; 17 | Value = Utils.Bytes2HexString(Bytes); 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/Base/InheritedBaseTypes.cs: -------------------------------------------------------------------------------- 1 | namespace SubstrateNetApi.Model.Types.Base 2 | { 3 | public class AuthorityId : AccountId 4 | { 5 | public override string Name() => "AuthorityId"; 6 | } 7 | 8 | public class AuthorityWeight : U64 9 | { 10 | public override string Name() => "AuthorityWeight"; 11 | } 12 | 13 | public class Topic : Hash 14 | { 15 | public override string Name() => "Topic"; 16 | } 17 | 18 | public class EraIndex : U32 19 | { 20 | public override string Name() => "EraIndex"; 21 | } 22 | 23 | public class AccountIndex : U32 24 | { 25 | public override string Name() => "AccountIndex"; 26 | } 27 | 28 | public class ApplyExtrinsic : U32 29 | { 30 | public override string Name() => "ApplyExtrinsic"; 31 | } 32 | 33 | public class BountyIndex : U32 34 | { 35 | public override string Name() => "BountyIndex"; 36 | } 37 | 38 | public class CallHash : Hash 39 | { 40 | public override string Name() => "CallHash"; 41 | } 42 | 43 | public class MemberCount : U32 44 | { 45 | public override string Name() => "MemberCount"; 46 | } 47 | 48 | public class PropIndex : U32 49 | { 50 | public override string Name() => "PropIndex"; 51 | } 52 | 53 | public class SessionIndex : U32 54 | { 55 | public override string Name() => "SessionIndex"; 56 | } 57 | 58 | public class ProposalIndex : U32 59 | { 60 | public override string Name() => "ProposalIndex"; 61 | } 62 | 63 | public class ReferendumIndex : U32 64 | { 65 | public override string Name() => "ReferendumIndex"; 66 | } 67 | 68 | public class RefCount : U32 69 | { 70 | public override string Name() => "RefCount"; 71 | } 72 | 73 | public class RegistrarIndex : U32 74 | { 75 | public override string Name() => "RegistrarIndex"; 76 | } 77 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/Base/U128.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SubstrateNetApi.Model.Types.Base 4 | { 5 | public class U128 : BaseType 6 | { 7 | public override string Name() => "u128"; 8 | 9 | public override int Size() => 16; 10 | 11 | public override byte[] Encode() 12 | { 13 | var reversed = Bytes; 14 | //Array.Reverse(reversed); 15 | return reversed; 16 | } 17 | 18 | public override void CreateFromJson(string str) 19 | { 20 | var bytes = Utils.HexToByteArray(str, true); 21 | Array.Reverse(bytes); 22 | Create(bytes); 23 | } 24 | 25 | public override void Create(byte[] byteArray) 26 | { 27 | if (byteArray.Length < Size()) 28 | { 29 | var newByteArray = new byte[Size()]; 30 | byteArray.CopyTo(newByteArray, 0); 31 | byteArray = newByteArray; 32 | } 33 | 34 | Bytes = byteArray; 35 | Value = BitConverter.ToUInt64(byteArray, 0); 36 | } 37 | 38 | public void Create(ulong value) 39 | { 40 | Bytes = BitConverter.GetBytes(value); 41 | Value = value; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/Base/U16.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SubstrateNetApi.Model.Types.Base 4 | { 5 | public class U16 : BaseType 6 | { 7 | public override string Name() => "u16"; 8 | 9 | public override int Size() => 2; 10 | 11 | public override byte[] Encode() 12 | { 13 | var reversed = Bytes; 14 | //Array.Reverse(reversed); 15 | return reversed; 16 | } 17 | 18 | public override void CreateFromJson(string str) 19 | { 20 | var bytes = Utils.HexToByteArray(str, true); 21 | Array.Reverse(bytes); 22 | var result = new byte[Size()]; 23 | bytes.CopyTo(result, 0); 24 | Create(result); 25 | } 26 | 27 | public override void Create(byte[] byteArray) 28 | { 29 | if (byteArray.Length < Size()) 30 | { 31 | var newByteArray = new byte[Size()]; 32 | byteArray.CopyTo(newByteArray, 0); 33 | byteArray = newByteArray; 34 | } 35 | 36 | Bytes = byteArray; 37 | Value = BitConverter.ToUInt16(byteArray, 0); 38 | } 39 | 40 | public void Create(ushort value) 41 | { 42 | Bytes = BitConverter.GetBytes(value); 43 | Value = value; 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/Base/U32.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SubstrateNetApi.Model.Types.Base 4 | { 5 | public class U32 : BaseType 6 | { 7 | public override string Name() => "u32"; 8 | 9 | public override int Size() => 4; 10 | 11 | public override byte[] Encode() 12 | { 13 | var reversed = Bytes; 14 | //Array.Reverse(reversed); 15 | return reversed; 16 | } 17 | 18 | public override void CreateFromJson(string str) 19 | { 20 | var bytes = Utils.HexToByteArray(str, true); 21 | Array.Reverse(bytes); 22 | var result = new byte[Size()]; 23 | bytes.CopyTo(result, 0); 24 | Create(result); 25 | } 26 | 27 | public override void Create(byte[] byteArray) 28 | { 29 | if (byteArray.Length < Size()) 30 | { 31 | var newByteArray = new byte[Size()]; 32 | byteArray.CopyTo(newByteArray, 0); 33 | byteArray = newByteArray; 34 | } 35 | 36 | Bytes = byteArray; 37 | Value = BitConverter.ToUInt32(byteArray, 0); 38 | } 39 | 40 | public void Create(uint value) 41 | { 42 | Bytes = BitConverter.GetBytes(value); 43 | Value = value; 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/Base/U64.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SubstrateNetApi.Model.Types.Base 4 | { 5 | public class U64 : BaseType 6 | { 7 | public override string Name() => "u64"; 8 | 9 | public override int Size() => 8; 10 | 11 | public override byte[] Encode() 12 | { 13 | var reversed = Bytes; 14 | //Array.Reverse(reversed); 15 | return reversed; 16 | } 17 | 18 | public override void CreateFromJson(string str) 19 | { 20 | var bytes = Utils.HexToByteArray(str, true); 21 | Array.Reverse(bytes); 22 | Create(bytes); 23 | } 24 | 25 | public override void Create(byte[] byteArray) 26 | { 27 | if (byteArray.Length < Size()) 28 | { 29 | var newByteArray = new byte[Size()]; 30 | byteArray.CopyTo(newByteArray, 0); 31 | byteArray = newByteArray; 32 | } 33 | 34 | Bytes = byteArray; 35 | Value = BitConverter.ToUInt64(byteArray, 0); 36 | } 37 | 38 | public void Create(ulong value) 39 | { 40 | Bytes = BitConverter.GetBytes(value); 41 | Value = value; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/Base/U8.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SubstrateNetApi.Model.Types.Base 4 | { 5 | public class U8 : BaseType 6 | { 7 | public override string Name() => "u8"; 8 | 9 | public override int Size() => 1; 10 | 11 | public override byte[] Encode() 12 | { 13 | return Bytes; 14 | } 15 | 16 | public override void Create(byte[] byteArray) 17 | { 18 | Bytes = byteArray; 19 | Value = byteArray[0]; 20 | } 21 | 22 | public void Create(byte value) 23 | { 24 | Bytes = new byte[] { value }; 25 | Value = value; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/BaseType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Newtonsoft.Json; 3 | 4 | namespace SubstrateNetApi.Model.Types 5 | { 6 | public abstract class BaseType : IType 7 | { 8 | public abstract string Name(); 9 | public abstract int Size(); 10 | 11 | [JsonIgnore] 12 | public byte[] Bytes { get; internal set; } 13 | 14 | public abstract byte[] Encode(); 15 | 16 | public void Decode(byte[] byteArray, ref int p) 17 | { 18 | var memory = byteArray.AsMemory(); 19 | var result = memory.Span.Slice(p, Size()).ToArray(); 20 | p += Size(); 21 | Create(result); 22 | } 23 | 24 | public virtual void Create(string str) => Create(Utils.HexToByteArray(str)); 25 | 26 | public virtual void CreateFromJson(string str) => Create(Utils.HexToByteArray(str)); 27 | 28 | public abstract void Create(byte[] byteArray); 29 | 30 | public IType New() => this; 31 | 32 | public override string ToString() => JsonConvert.SerializeObject(Value); 33 | 34 | public T Value { get; internal set; } 35 | 36 | } 37 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/Enum/BalanceStatus.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace SubstrateNetApi.Model.Types.Enum 6 | { 7 | public enum BalanceStatus 8 | { 9 | Free, Reserved 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/Enum/DispatchClass.cs: -------------------------------------------------------------------------------- 1 | namespace SubstrateNetApi.Model.Types.Enum 2 | { 3 | public enum DispatchClass 4 | { 5 | Normal, 6 | Operational, 7 | Mandatory 8 | } 9 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/Enum/ElectionCompute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace SubstrateNetApi.Model.Types.Enum 6 | { 7 | public enum ElectionCompute 8 | { 9 | OnChain, Signed, Unsigned 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/Enum/Pays.cs: -------------------------------------------------------------------------------- 1 | namespace SubstrateNetApi.Model.Types.Enum 2 | { 3 | public enum Pays 4 | { 5 | Yes, 6 | No 7 | } 8 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/Enum/PhaseState.cs: -------------------------------------------------------------------------------- 1 | namespace SubstrateNetApi.Model.Types.Enum 2 | { 3 | public enum PhaseState 4 | { 5 | None, 6 | Finalization, 7 | Initialization 8 | } 9 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/Enum/ProxyType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace SubstrateNetApi.Model.Types.Enum 6 | { 7 | public enum ProxyType 8 | { 9 | Any, NonTransfer, Governance, Staking 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/Enum/VoteThreshold.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace SubstrateNetApi.Model.Types.Enum 6 | { 7 | public enum VoteThreshold 8 | { 9 | SuperMajorityApprove, SuperMajorityAgainst, SimpleMajority 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/EnumType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Newtonsoft.Json; 3 | using Newtonsoft.Json.Converters; 4 | 5 | namespace SubstrateNetApi.Model.Types 6 | { 7 | public class EnumType : IType where T : System.Enum 8 | { 9 | public string Name() => typeof(T).Name; 10 | 11 | public int Size() => 1; 12 | 13 | [JsonIgnore] 14 | public byte[] Bytes { get; internal set; } 15 | 16 | public byte[] Encode() 17 | { 18 | return Bytes; 19 | } 20 | 21 | public void Decode(byte[] byteArray, ref int p) 22 | { 23 | var memory = byteArray.AsMemory(); 24 | var result = memory.Span.Slice(p, Size()).ToArray(); 25 | p += Size(); 26 | Create(result); 27 | } 28 | 29 | public virtual void Create(string str) => Create(Utils.HexToByteArray(str)); 30 | 31 | public virtual void CreateFromJson(string str) => Create(Utils.HexToByteArray(str)); 32 | 33 | public void Create(T t) 34 | { 35 | //var byteArray = BitConverter.GetBytes(Convert.ToInt32(t)); 36 | //if (byteArray.Length < Size()) 37 | //{ 38 | // var newByteArray = new byte[Size()]; 39 | // byteArray.CopyTo(newByteArray, 0); 40 | // byteArray = newByteArray; 41 | //} 42 | //Bytes = byteArray; 43 | Bytes = BitConverter.GetBytes(Convert.ToInt32(t)); 44 | Value = t; 45 | } 46 | 47 | public void Create(byte[] byteArray) 48 | { 49 | Bytes = byteArray; 50 | Value = (T) System.Enum.Parse(typeof(T), byteArray[0].ToString(), true); 51 | 52 | //if (byteArray.Length < Size()) 53 | //{ 54 | // var newByteArray = new byte[Size()]; 55 | // byteArray.CopyTo(newByteArray, 0); 56 | // byteArray = newByteArray; 57 | //} 58 | 59 | //Bytes = byteArray; 60 | //Value = (T)System.Enum.Parse(typeof(T), BitConverter.ToUInt32(byteArray, 0).ToString(), true); 61 | } 62 | 63 | public IType New() => this; 64 | 65 | public override string ToString() => JsonConvert.SerializeObject(Value); 66 | 67 | [JsonConverter(typeof(StringEnumConverter))] 68 | public T Value { get; internal set; } 69 | 70 | } 71 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/ExtEnumType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Newtonsoft.Json; 3 | using Newtonsoft.Json.Converters; 4 | 5 | namespace SubstrateNetApi.Model.Types 6 | { 7 | public class NullType : IType 8 | { 9 | public string Name() => "NullType"; 10 | public int Size() => 0; 11 | 12 | public void Create(string str) 13 | { 14 | throw new NotImplementedException(); 15 | } 16 | 17 | public void Create(byte[] byteArray) 18 | { 19 | throw new NotImplementedException(); 20 | } 21 | 22 | public void CreateFromJson(string str) 23 | { 24 | throw new NotImplementedException(); 25 | } 26 | 27 | public void Decode(byte[] byteArray, ref int p) 28 | { 29 | throw new NotImplementedException(); 30 | } 31 | 32 | public byte[] Encode() 33 | { 34 | throw new NotImplementedException(); 35 | } 36 | 37 | public IType New() 38 | { 39 | throw new NotImplementedException(); 40 | } 41 | } 42 | 43 | public class ExtEnumType : IType 44 | where T0 : System.Enum 45 | where T1 : IType, new() 46 | where T2 : IType, new() 47 | where T3 : IType, new() 48 | where T4 : IType, new() 49 | where T5 : IType, new() 50 | where T6 : IType, new() 51 | where T7 : IType, new() 52 | where T8 : IType, new() 53 | where T9 : IType, new() 54 | { 55 | public virtual string Name() => typeof(T0).Name; 56 | 57 | private int _size; 58 | public int Size() => _size; 59 | 60 | [JsonIgnore] 61 | public byte[] Bytes { get; internal set; } 62 | 63 | public byte[] Encode() 64 | { 65 | return Bytes; 66 | } 67 | 68 | public void Decode(byte[] byteArray, ref int p) 69 | { 70 | var start = p; 71 | var enumByte = byteArray[p]; 72 | 73 | Value = (T0)System.Enum.Parse(typeof(T0), enumByte.ToString(), true); 74 | p += 1; 75 | 76 | Value2 = DecodeOneOf(enumByte, byteArray, ref p); 77 | 78 | _size = p - start; 79 | } 80 | 81 | private IType DecodeOneOf(byte value, byte[] byteArray, ref int p) 82 | { 83 | IType result; 84 | switch (value) 85 | { 86 | case 0x00: 87 | result = new T1(); 88 | if (result.GetType().Name == "NullType") 89 | return null; 90 | result.Decode(byteArray, ref p); 91 | return result; 92 | case 0x01: 93 | result = new T2(); 94 | if (result.GetType().Name == "NullType") 95 | return null; 96 | result.Decode(byteArray, ref p); 97 | return result; 98 | case 0x02: 99 | result = new T3(); 100 | if (result.GetType().Name == "NullType") 101 | return null; 102 | result.Decode(byteArray, ref p); 103 | return result; 104 | case 0x03: 105 | result = new T4(); 106 | if (result.GetType().Name == "NullType") 107 | return null; 108 | result.Decode(byteArray, ref p); 109 | return result; 110 | case 0x04: 111 | result = new T5(); 112 | if (result.GetType().Name == "NullType") 113 | return null; 114 | result.Decode(byteArray, ref p); 115 | return result; 116 | case 0x05: 117 | result = new T6(); 118 | if (result.GetType().Name == "NullType") 119 | return null; 120 | result.Decode(byteArray, ref p); 121 | return result; 122 | case 0x06: 123 | result = new T7(); 124 | if (result.GetType().Name == "NullType") 125 | return null; 126 | result.Decode(byteArray, ref p); 127 | return result; 128 | case 0x07: 129 | result = new T8(); 130 | if (result.GetType().Name == "NullType") 131 | return null; 132 | result.Decode(byteArray, ref p); 133 | return result; 134 | case 0x08: 135 | result = new T9(); 136 | if (result.GetType().Name == "NullType") 137 | return null; 138 | result.Decode(byteArray, ref p); 139 | return result; 140 | default: 141 | return null; 142 | } 143 | } 144 | 145 | public virtual void Create(string str) => Create(Utils.HexToByteArray(str)); 146 | 147 | public virtual void CreateFromJson(string str) => Create(Utils.HexToByteArray(str)); 148 | 149 | public void Create(T0 t, IType value2) 150 | { 151 | Bytes = BitConverter.GetBytes(Convert.ToInt32(t)); 152 | Value = t; 153 | Value2 = value2; 154 | } 155 | 156 | public void Create(byte[] byteArray) 157 | { 158 | int p = 0; 159 | Decode(byteArray, ref p); 160 | } 161 | 162 | public IType New() => this; 163 | 164 | public override string ToString() => JsonConvert.SerializeObject(Value); 165 | 166 | [JsonConverter(typeof(StringEnumConverter))] 167 | public T0 Value { get; internal set; } 168 | 169 | public IType Value2 { get; internal set; } 170 | 171 | } 172 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/IEncodable.cs: -------------------------------------------------------------------------------- 1 | namespace SubstrateNetApi.Model.Types 2 | { 3 | public interface IEncodable 4 | { 5 | byte[] Encode(); 6 | } 7 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/IType.cs: -------------------------------------------------------------------------------- 1 | namespace SubstrateNetApi.Model.Types 2 | { 3 | /// 4 | /// Reference to the polkadot js types implementation 5 | /// https://github.com/polkadot-js/api/tree/master/packages/types/src 6 | /// 7 | public interface IType 8 | { 9 | /// 10 | /// Names this instance. 11 | /// 12 | /// 13 | string Name(); 14 | 15 | /// 16 | /// Sizes this instance. 17 | /// 18 | /// 19 | int Size(); 20 | 21 | /// 22 | /// Encodes this instance. 23 | /// 24 | /// 25 | byte[] Encode(); 26 | 27 | /// 28 | /// Decodes the specified byte array. 29 | /// 30 | /// The byte array. 31 | /// The p. 32 | void Decode(byte[] byteArray, ref int p); 33 | 34 | /// 35 | /// Creates the specified string. 36 | /// 37 | /// The string. 38 | void Create(string str); 39 | 40 | /// 41 | /// Creates from json. 42 | /// 43 | /// The string. 44 | void CreateFromJson(string str); 45 | 46 | /// 47 | /// Creates the specified byte array. 48 | /// 49 | /// The byte array. 50 | void Create(byte[] byteArray); 51 | 52 | /// 53 | /// News this instance. 54 | /// 55 | /// 56 | IType New(); 57 | } 58 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/Struct/AccountData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SubstrateNetApi.Model.Types.Base; 3 | 4 | namespace SubstrateNetApi.Model.Types.Struct 5 | { 6 | public class AccountData : StructType 7 | { 8 | public override string Name() => "AccountData"; 9 | 10 | private int _size; 11 | public override int Size() => _size; 12 | 13 | 14 | public override byte[] Encode() 15 | { 16 | throw new NotImplementedException(); 17 | } 18 | 19 | public override void Decode(byte[] byteArray, ref int p) 20 | { 21 | var start = p; 22 | 23 | Free = new Balance(); 24 | Free.Decode(byteArray, ref p); 25 | 26 | Reserved = new Balance(); 27 | Reserved.Decode(byteArray, ref p); 28 | 29 | MiscFrozen = new Balance(); 30 | MiscFrozen.Decode(byteArray, ref p); 31 | 32 | FeeFrozen = new Balance(); 33 | FeeFrozen.Decode(byteArray, ref p); 34 | 35 | _size = p - start; 36 | } 37 | 38 | public Balance Free { get; private set; } 39 | public Balance Reserved { get; private set; } 40 | public Balance MiscFrozen { get; private set; } 41 | public Balance FeeFrozen { get; private set; } 42 | } 43 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/Struct/AccountInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SubstrateNetApi.Model.Types.Base; 3 | 4 | namespace SubstrateNetApi.Model.Types.Struct 5 | { 6 | public class AccountInfo : StructType 7 | { 8 | public override string Name() => "AccountInfo"; 9 | 10 | private int _size; 11 | public override int Size() => _size; 12 | 13 | public override byte[] Encode() 14 | { 15 | throw new NotImplementedException(); 16 | } 17 | 18 | public override void Decode(byte[] byteArray, ref int p) 19 | { 20 | var start = p; 21 | 22 | Nonce = new U32(); 23 | Nonce.Decode(byteArray, ref p); 24 | 25 | Consumers = new RefCount(); 26 | Consumers.Decode(byteArray, ref p); 27 | 28 | Providers = new RefCount(); 29 | Providers.Decode(byteArray, ref p); 30 | 31 | AccountData = new AccountData(); 32 | AccountData.Decode(byteArray, ref p); 33 | 34 | _size = p - start; 35 | } 36 | 37 | public U32 Nonce { get; private set; } 38 | public RefCount Consumers { get; private set; } 39 | public RefCount Providers { get; private set; } 40 | public AccountData AccountData { get; private set; } 41 | } 42 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/Struct/Assets.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace SubstrateNetApi.Model.Types.Base 6 | { 7 | public class AssetBalance : StructType 8 | { 9 | public override string Name() => "AssetBalance"; 10 | 11 | private int _size; 12 | public override int Size() => _size; 13 | 14 | public override byte[] Encode() 15 | { 16 | throw new NotImplementedException(); 17 | } 18 | 19 | public override void Decode(byte[] byteArray, ref int p) 20 | { 21 | var start = p; 22 | 23 | Balance = new U32(); 24 | Balance.Decode(byteArray, ref p); 25 | 26 | IsFrozen = new Bool(); 27 | IsFrozen.Decode(byteArray, ref p); 28 | 29 | Sufficient = new Bool(); 30 | Sufficient.Decode(byteArray, ref p); 31 | 32 | //Extra = new Extra(); 33 | //Extra.Decode(byteArray, ref p); 34 | 35 | _size = p - start; 36 | } 37 | 38 | public U32 Balance { get; private set; } 39 | public Bool IsFrozen { get; private set; } 40 | public Bool Sufficient { get; private set; } 41 | //public Extra Extra { get; private set; } 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/Struct/BaseEvent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Newtonsoft.Json; 4 | using SubstrateNetApi.Model.Meta; 5 | using SubstrateNetApi.Model.Types.Base; 6 | using SubstrateNetApi.Model.Types.Enum; 7 | 8 | namespace SubstrateNetApi.Model.Types.Struct 9 | { 10 | public partial class BaseEvent : StructType 11 | { 12 | public override string Name() => "Event"; 13 | 14 | private int _size; 15 | public override int Size() => _size; 16 | 17 | private readonly MetaData _metaData; 18 | public BaseEvent() { } 19 | 20 | public BaseEvent(MetaData metaData) 21 | { 22 | _metaData = metaData; 23 | } 24 | 25 | public override byte[] Encode() 26 | { 27 | throw new NotImplementedException(); 28 | } 29 | 30 | 31 | 32 | public override void Decode(byte[] byteArray, ref int p) 33 | { 34 | if (_metaData is null) 35 | { 36 | throw new NotImplementedException("Need MetaData in ctor to decode."); 37 | } 38 | 39 | ModuleIndex = new U8(); 40 | ModuleIndex.Decode(byteArray, ref p); 41 | 42 | var module = _metaData.Modules[ModuleIndex.Value]; 43 | ModuleName = module.Name; 44 | 45 | EventIndex = new U8(); 46 | EventIndex.Decode(byteArray, ref p); 47 | 48 | var moduleEvent = module.Events[EventIndex.Value]; 49 | EventName = moduleEvent.Name; 50 | 51 | EventArgs = new IType[moduleEvent.EventArgs.Length]; 52 | for (var i = 0; i < moduleEvent.EventArgs.Length; i++) 53 | { 54 | var eventArgStr = moduleEvent.EventArgs[i]; 55 | EventArgs[i] = TypeUtil.Mapper(eventArgStr, byteArray, ref p); 56 | } 57 | } 58 | 59 | [JsonIgnore] 60 | public U8 ModuleIndex; 61 | public string ModuleName; 62 | [JsonIgnore] 63 | public U8 EventIndex; 64 | public string EventName; 65 | public IType[] EventArgs; 66 | } 67 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/Struct/Dispatchinfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SubstrateNetApi.Model.Types.Base; 3 | using SubstrateNetApi.Model.Types.Enum; 4 | 5 | namespace SubstrateNetApi.Model.Types.Struct 6 | { 7 | public class DispatchInfo : StructType 8 | { 9 | public override string Name() => "DispatchInfo"; 10 | 11 | private int _size; 12 | public override int Size() => _size; 13 | 14 | public override byte[] Encode() 15 | { 16 | throw new NotImplementedException(); 17 | } 18 | 19 | public override void Decode(byte[] byteArray, ref int p) 20 | { 21 | var start = p; 22 | 23 | Weight = new U64(); 24 | Weight.Decode(byteArray, ref p); 25 | 26 | 27 | DispatchClass = new EnumType(); 28 | DispatchClass.Decode(byteArray, ref p); 29 | 30 | Pays = new EnumType(); 31 | Pays.Decode(byteArray, ref p); 32 | 33 | _size = p - start; 34 | } 35 | 36 | public U64 Weight { get; set; } 37 | public EnumType DispatchClass { get; set; } 38 | public EnumType Pays { get; set; } 39 | } 40 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/Struct/EventRecord.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using Newtonsoft.Json; 4 | using SubstrateNetApi.Model.Meta; 5 | using SubstrateNetApi.Model.Types.Base; 6 | 7 | namespace SubstrateNetApi.Model.Types.Struct 8 | { 9 | public class EventRecord : StructType 10 | { 11 | public override string Name() => "EventRecord"; 12 | 13 | private int _size; 14 | public override int Size() => _size; 15 | 16 | private MetaData _metaData; 17 | 18 | public EventRecord() 19 | { 20 | } 21 | 22 | public EventRecord(MetaData metaData) 23 | { 24 | _metaData = metaData; 25 | } 26 | 27 | public override byte[] Encode() 28 | { 29 | throw new NotImplementedException(); 30 | } 31 | 32 | public override void Decode(byte[] byteArray, ref int p) 33 | { 34 | if (_metaData is null) 35 | { 36 | throw new NotImplementedException("Need MetaData in ctor to decode."); 37 | } 38 | 39 | var start = p; 40 | 41 | Phase = new Phase(); 42 | Phase.Decode(byteArray, ref p); 43 | 44 | BaseEvent = new BaseEvent(_metaData); 45 | BaseEvent.Decode(byteArray, ref p); 46 | 47 | Topics = new Vec(); 48 | Topics.Decode(byteArray, ref p); 49 | 50 | _size = p - start; 51 | } 52 | 53 | public Phase Phase; 54 | public BaseEvent BaseEvent; 55 | public Vec Topics; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/Struct/EventRecords.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using SubstrateNetApi.Model.Meta; 4 | 5 | namespace SubstrateNetApi.Model.Types.Struct 6 | { 7 | public class EventRecords : StructType 8 | { 9 | public override string Name() => $"Vec>"; 10 | 11 | private int _size; 12 | public override int Size() => _size; 13 | 14 | private MetaData _metaData; 15 | 16 | public EventRecords() 17 | { 18 | } 19 | 20 | public EventRecords(MetaData metaData) 21 | { 22 | _metaData = metaData; 23 | } 24 | 25 | public override byte[] Encode() 26 | { 27 | throw new NotImplementedException(); 28 | } 29 | 30 | public override void Decode(byte[] byteArray, ref int p) 31 | { 32 | if (_metaData is null) 33 | { 34 | throw new NotImplementedException("Need MetaData in ctor to decode."); 35 | } 36 | 37 | var start = p; 38 | 39 | var list = new List(); 40 | 41 | var length = CompactInteger.Decode(byteArray, ref p); 42 | for (var i = 0; i < length; i++) 43 | { 44 | var t = new EventRecord(_metaData); 45 | t.Decode(byteArray, ref p); 46 | list.Add(t); 47 | } 48 | 49 | Bytes = byteArray; 50 | Value = list; 51 | 52 | _size = p - start; 53 | } 54 | 55 | public List Value { get; internal set; } 56 | } 57 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/Struct/InheritedStructTypes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using SubstrateNetApi.Model.Types.Base; 5 | 6 | namespace SubstrateNetApi.Model.Types.Struct 7 | { 8 | public class AuthorityList : Vec> 9 | { 10 | public override string Name() => "AuthorityList"; 11 | } 12 | 13 | public class StorageKey : Vec 14 | { 15 | public override string Name() => "StorageKey"; 16 | } 17 | 18 | public class StorageData : Vec 19 | { 20 | public override string Name() => "StorageData"; 21 | } 22 | 23 | public class OpaqueTimeSlot : Vec 24 | { 25 | public override string Name() => "OpaqueTimeSlot"; 26 | } 27 | 28 | public class TaskAddress : RustTuple 29 | { 30 | public override string Name() => "TaskAddress"; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/Struct/Option.cs: -------------------------------------------------------------------------------- 1 | using SubstrateNetApi.Model.Types.Base; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | namespace SubstrateNetApi.Model.Types.Struct 7 | { 8 | public class Option : StructType where T : IType, new() 9 | { 10 | public override string Name() => $"Option<{new T().Name()}>"; 11 | 12 | private int _size; 13 | public override int Size() => _size; 14 | 15 | public bool OptionFlag { get; set; } 16 | 17 | public override byte[] Encode() 18 | { 19 | var bytes = new List(); 20 | if (OptionFlag) 21 | { 22 | bytes.Add(1); 23 | bytes.AddRange(Value.Encode()); 24 | 25 | } else 26 | { 27 | bytes.Add(0); 28 | } 29 | 30 | return bytes.ToArray(); 31 | } 32 | 33 | public override void Decode(byte[] byteArray, ref int p) 34 | { 35 | var start = p; 36 | 37 | var optionByte = new U8(); 38 | optionByte.Decode(byteArray, ref p); 39 | 40 | OptionFlag = optionByte.Value > 0; 41 | 42 | T t = default; 43 | if (optionByte.Value > 0) 44 | { 45 | t = new T(); 46 | t.Decode(byteArray, ref p); 47 | } 48 | 49 | _size = p - start; 50 | 51 | var bytes = new byte[_size]; 52 | Array.Copy(byteArray, start, bytes, 0, _size); 53 | 54 | Bytes = bytes; 55 | Value = t != null ? t : default; 56 | } 57 | 58 | public override void CreateFromJson(string str) 59 | { 60 | Create(Utils.HexToByteArray(str)); 61 | } 62 | 63 | public T Value { get; internal set; } 64 | 65 | public void Create(T value) 66 | { 67 | OptionFlag = value != null; 68 | Value = value; 69 | Bytes = Encode(); 70 | } 71 | 72 | } 73 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/Struct/Phase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SubstrateNetApi.Model.Types.Base; 3 | using SubstrateNetApi.Model.Types.Enum; 4 | 5 | namespace SubstrateNetApi.Model.Types.Struct 6 | { 7 | public class Phase : StructType 8 | { 9 | public override string Name() => "Phase"; 10 | 11 | private int _size; 12 | public override int Size() => _size; 13 | 14 | public override byte[] Encode() 15 | { 16 | throw new NotImplementedException(); 17 | } 18 | 19 | public override void Decode(byte[] byteArray, ref int p) 20 | { 21 | var start = p; 22 | 23 | PhaseState = new EnumType(); 24 | PhaseState.Decode(byteArray, ref p); 25 | 26 | if (PhaseState.Value == Enum.PhaseState.None) 27 | { 28 | ApplyExtrinsic = new ApplyExtrinsic(); 29 | ApplyExtrinsic.Decode(byteArray, ref p); 30 | } 31 | 32 | _size = p - start; 33 | } 34 | 35 | public ApplyExtrinsic ApplyExtrinsic { get; set; } 36 | public EnumType PhaseState { get; set; } 37 | } 38 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/Struct/RustTuple.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace SubstrateNetApi.Model.Types.Struct 5 | { 6 | public class RustTuple : StructType where T1 : IType, new() 7 | where T2 : IType, new() 8 | { 9 | public override string Name() => $"({new T1().Name()},{new T2().Name()})"; 10 | 11 | private int _size; 12 | public override int Size() => _size; 13 | 14 | public override byte[] Encode() 15 | { 16 | throw new NotImplementedException(); 17 | } 18 | 19 | public override void Decode(byte[] byteArray, ref int p) 20 | { 21 | var start = p; 22 | 23 | Value = new IType[2]; 24 | 25 | var t1 = new T1(); 26 | t1.Decode(byteArray, ref p); 27 | Value[0] = t1; 28 | 29 | var t2 = new T2(); 30 | t2.Decode(byteArray, ref p); 31 | Value[1] = t2; 32 | 33 | _size = p - start; 34 | 35 | Bytes = new byte[_size]; 36 | Array.Copy(byteArray, start, Bytes, 0, _size); 37 | } 38 | 39 | public IType[] Value { get; internal set; } 40 | } 41 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/Struct/Timepoint.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using SubstrateNetApi.Model.Types.Base; 5 | 6 | namespace SubstrateNetApi.Model.Types.Struct 7 | { 8 | public class Timepoint : StructType 9 | { 10 | public override string Name() => "Timepoint"; 11 | 12 | private int _size; 13 | public override int Size() => _size; 14 | 15 | public override byte[] Encode() 16 | { 17 | throw new NotImplementedException(); 18 | } 19 | 20 | public override void Decode(byte[] byteArray, ref int p) 21 | { 22 | var start = p; 23 | 24 | Height = new BlockNumber(); 25 | Height.Decode(byteArray, ref p); 26 | 27 | Index = new U32(); 28 | Index.Decode(byteArray, ref p); 29 | 30 | _size = p - start; 31 | } 32 | 33 | public BlockNumber Height { get; private set; } 34 | public U32 Index { get; private set; } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/Struct/Vec.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace SubstrateNetApi.Model.Types.Struct 6 | { 7 | public class Vec : StructType where T : IType, new() 8 | { 9 | public override string Name() => $"Vec<{new T().Name()}>"; 10 | 11 | private int _size; 12 | public override int Size() => _size; 13 | 14 | public override byte[] Encode() 15 | { 16 | List result = new List(); 17 | for(int i = 0; i < Value.Count; i++) 18 | { 19 | result.AddRange(Value[i].Encode()); 20 | } 21 | return Utils.SizePrefixedByteArray(result); 22 | } 23 | 24 | public override void Decode(byte[] byteArray, ref int p) 25 | { 26 | var start = p; 27 | 28 | var list = new List(); 29 | 30 | var length = CompactInteger.Decode(byteArray, ref p); 31 | for (var i = 0; i < length; i++) 32 | { 33 | var t = new T(); 34 | t.Decode(byteArray, ref p); 35 | list.Add(t); 36 | } 37 | 38 | _size = p - start; 39 | 40 | var bytes = new byte[_size]; 41 | Array.Copy(byteArray, start, bytes, 0, _size); 42 | 43 | Bytes = bytes; 44 | Value = list; 45 | } 46 | 47 | public override void CreateFromJson(string str) 48 | { 49 | Create(Utils.HexToByteArray(str)); 50 | } 51 | 52 | public List Value { get; internal set; } 53 | 54 | public void Create(List list) 55 | { 56 | Value = list; 57 | Bytes = Encode(); 58 | } 59 | 60 | } 61 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/StructType.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace SubstrateNetApi.Model.Types 4 | { 5 | public abstract class StructType : IType 6 | { 7 | public abstract string Name(); 8 | 9 | public abstract int Size(); 10 | 11 | [JsonIgnore] 12 | public byte[] Bytes { get; internal set; } 13 | 14 | public abstract byte[] Encode(); 15 | 16 | public abstract void Decode(byte[] byteArray, ref int p); 17 | 18 | public virtual void Create(string str) => Create(Utils.HexToByteArray(str)); 19 | 20 | public virtual void CreateFromJson(string str) => Create(Utils.HexToByteArray(str)); 21 | 22 | public void Create(byte[] byteArray) 23 | { 24 | var p = 0; 25 | Decode(byteArray, ref p); 26 | } 27 | 28 | 29 | public IType New() => this; 30 | 31 | public override string ToString() => JsonConvert.SerializeObject(this); 32 | } 33 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Model/Types/UnimplementedTypes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SubstrateNetApi.Model.Types 4 | { 5 | public class DispatchError 6 | { 7 | public static DispatchError Decode(Memory byteArray, ref int p) 8 | { 9 | throw new NotImplementedException("DispatchError"); 10 | } 11 | } 12 | 13 | public class DispatchResult 14 | { 15 | public static DispatchResult Decode(Memory byteArray, ref int p) 16 | { 17 | throw new NotImplementedException("DispatchResult"); 18 | } 19 | } 20 | 21 | public class Kind 22 | { 23 | public static Kind Decode(Memory byteArray, ref int p) 24 | { 25 | throw new NotImplementedException("Kind"); 26 | } 27 | } 28 | 29 | public class Moment 30 | { 31 | public byte[] Encode() 32 | { 33 | throw new NotImplementedException("Moment"); 34 | } 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Modules/State.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using Newtonsoft.Json.Linq; 5 | using SubstrateNetApi.Model.Rpc; 6 | 7 | namespace SubstrateNetApi.Modules 8 | { 9 | /// A state. 10 | /// 19.09.2020. 11 | public class State 12 | { 13 | /// The client. 14 | private readonly SubstrateClient _client; 15 | 16 | /// Constructor. 17 | /// 19.09.2020. 18 | /// The client. 19 | internal State(SubstrateClient client) 20 | { 21 | _client = client; 22 | } 23 | 24 | public async Task GetMetaDataAsync() 25 | { 26 | return await GetMetaDataAsync(CancellationToken.None); 27 | } 28 | 29 | public async Task GetMetaDataAsync(CancellationToken token) 30 | { 31 | return await _client.InvokeAsync("state_getMetadata", null, token); 32 | } 33 | 34 | public async Task GetPairsAsync(byte[] keyPrefix) 35 | { 36 | return await GetPairsAsync(keyPrefix, CancellationToken.None); 37 | } 38 | 39 | public async Task GetPairsAsync(byte[] keyPrefix, CancellationToken token) 40 | { 41 | return await _client.InvokeAsync("state_getPairs", new object[] {Utils.Bytes2HexString(keyPrefix)}, token); 42 | } 43 | 44 | public async Task GetKeysPagedAsync(byte[] keyPrefix, uint pageCount, byte[] startKey) 45 | { 46 | return await GetKeysPagedAsync(keyPrefix, pageCount, startKey, CancellationToken.None); 47 | } 48 | 49 | public async Task GetKeysPagedAsync(byte[] keyPrefix, uint pageCount, byte[] startKey, 50 | CancellationToken token) 51 | { 52 | return startKey.Length == 0 53 | ? await _client.InvokeAsync("state_getKeysPaged", 54 | new object[] {Utils.Bytes2HexString(keyPrefix), pageCount}, token) 55 | : await _client.InvokeAsync("state_getKeysPaged", 56 | new object[] {Utils.Bytes2HexString(keyPrefix), pageCount, Utils.Bytes2HexString(startKey)}, token); 57 | } 58 | 59 | public async Task GetStorageAsync(byte[] parameters, CancellationToken token) 60 | { 61 | return await _client.InvokeAsync("state_getStorage", new object[] { Utils.Bytes2HexString(parameters) }, token); 62 | } 63 | 64 | public async Task GetStorageHashAsync(byte[] key, CancellationToken token) 65 | { 66 | return await _client.InvokeAsync("state_getStorageHash", new object[] { Utils.Bytes2HexString(key) }, token); 67 | } 68 | 69 | public async Task GetRuntimeVersionAsync() 70 | { 71 | return await GetRuntimeVersionAsync(CancellationToken.None); 72 | } 73 | 74 | public async Task GetRuntimeVersionAsync(CancellationToken token) 75 | { 76 | return await _client.InvokeAsync("state_getRuntimeVersion", null, token); 77 | } 78 | 79 | public async Task SubscribeRuntimeVersionAsync() 80 | { 81 | return await SubscribeRuntimeVersionAsync(CancellationToken.None); 82 | } 83 | 84 | public async Task SubscribeRuntimeVersionAsync(CancellationToken token) 85 | { 86 | return await _client.InvokeAsync("state_subscribeRuntimeVersion", null, token); 87 | } 88 | 89 | public async Task UnsubscribeRuntimeVersionAsync(string subscriptionId) 90 | { 91 | return await UnsubscribeRuntimeVersionAsync(subscriptionId, CancellationToken.None); 92 | } 93 | 94 | public async Task UnsubscribeRuntimeVersionAsync(string subscriptionId, CancellationToken token) 95 | { 96 | return await _client.InvokeAsync("state_unsubscribeRuntimeVersion", new object[] {subscriptionId}, 97 | token); 98 | } 99 | 100 | public async Task SubscribeStorageAsync(JArray keys, Action callback) 101 | { 102 | return await SubscribeStorageAsync(keys, callback, CancellationToken.None); 103 | } 104 | 105 | public async Task SubscribeStorageAsync(JArray keys, Action callback, 106 | CancellationToken token) 107 | { 108 | var subscriptionId = 109 | await _client.InvokeAsync("state_subscribeStorage", new object[] {keys}, token); 110 | _client.Listener.RegisterCallBackHandler(subscriptionId, callback); 111 | return subscriptionId; 112 | } 113 | 114 | public async Task UnsubscribeStorageAsync(string subscriptionId) 115 | { 116 | return await UnsubscribeStorageAsync(subscriptionId, CancellationToken.None); 117 | } 118 | 119 | public async Task UnsubscribeStorageAsync(string subscriptionId, CancellationToken token) 120 | { 121 | return await _client.InvokeAsync("state_unsubscribeStorage", new object[] {subscriptionId}, token); 122 | } 123 | } 124 | } -------------------------------------------------------------------------------- /SubstrateNetApi/Modules/System.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using SubstrateNetApi.Model.Rpc; 4 | 5 | namespace SubstrateNetApi.Modules 6 | { 7 | /// A system. 8 | /// 19.09.2020. 9 | public class System 10 | { 11 | /// The client. 12 | private readonly SubstrateClient _client; 13 | 14 | /// Constructor. 15 | /// 19.09.2020. 16 | /// The client. 17 | internal System(SubstrateClient client) 18 | { 19 | _client = client; 20 | } 21 | 22 | /// Chain asynchronous. 23 | /// 19.09.2020. 24 | /// The chain. 25 | public async Task ChainAsync() 26 | { 27 | return await ChainAsync(CancellationToken.None); 28 | } 29 | 30 | /// Chain asynchronous. 31 | /// 19.09.2020. 32 | /// A token that allows processing to be cancelled. 33 | /// The chain. 34 | public async Task ChainAsync(CancellationToken token) 35 | { 36 | return await _client.InvokeAsync("system_chain", null, token); 37 | } 38 | 39 | /// Name asynchronous. 40 | /// 19.09.2020. 41 | /// The name. 42 | public async Task NameAsync() 43 | { 44 | return await NameAsync(CancellationToken.None); 45 | } 46 | 47 | /// Name asynchronous. 48 | /// 19.09.2020. 49 | /// A token that allows processing to be cancelled. 50 | /// The name. 51 | public async Task NameAsync(CancellationToken token) 52 | { 53 | return await _client.InvokeAsync("system_name", null, token); 54 | } 55 | 56 | /// Version asynchronous. 57 | /// 19.09.2020. 58 | /// The version. 59 | public async Task VersionAsync() 60 | { 61 | return await VersionAsync(CancellationToken.None); 62 | } 63 | 64 | /// Version asynchronous. 65 | /// 19.09.2020. 66 | /// A token that allows processing to be cancelled. 67 | /// The version. 68 | public async Task VersionAsync(CancellationToken token) 69 | { 70 | return await _client.InvokeAsync("system_version", null, token); 71 | } 72 | 73 | public async Task AccountNextIndexAsync(string address, CancellationToken token) 74 | { 75 | return await _client.InvokeAsync("system_accountNextIndex", new object[] {address}, token); 76 | } 77 | 78 | public async Task HealthAsync() 79 | { 80 | return await HealthAsync(CancellationToken.None); 81 | } 82 | 83 | public async Task HealthAsync(CancellationToken token) 84 | { 85 | return await _client.InvokeAsync("system_health", null, token); 86 | } 87 | } 88 | } -------------------------------------------------------------------------------- /SubstrateNetApi/SubscriptionListener.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Newtonsoft.Json.Linq; 4 | using NLog; 5 | using StreamJsonRpc; 6 | using SubstrateNetApi.Model.Rpc; 7 | 8 | namespace SubstrateNetApi 9 | { 10 | public class SubscriptionListener 11 | { 12 | private static readonly ILogger Logger = LogManager.GetCurrentClassLogger(); 13 | 14 | private readonly Dictionary _headerCallbacks = new Dictionary(); 15 | 16 | private readonly Dictionary> _pendingHeaders = new Dictionary>(); 17 | 18 | /// 19 | /// Registers the call back handler. 20 | /// 21 | /// 22 | /// The subscription identifier. 23 | /// The callback. 24 | public void RegisterCallBackHandler(string subscriptionId, Action callback) 25 | { 26 | if (!_headerCallbacks.ContainsKey(subscriptionId)) 27 | { 28 | Logger.Debug($"Register {callback} for subscription '{subscriptionId}'"); 29 | _headerCallbacks.Add(subscriptionId, callback); 30 | } 31 | 32 | if (_pendingHeaders.ContainsKey(subscriptionId)) 33 | { 34 | foreach (var h in _pendingHeaders[subscriptionId]) 35 | // we don't wait on the tasks to finish 36 | callback(subscriptionId, (T) h); 37 | _pendingHeaders.Remove(subscriptionId); 38 | } 39 | } 40 | 41 | /// 42 | /// Unregisters the header handler. 43 | /// 44 | /// The subscription identifier. 45 | public void UnregisterHeaderHandler(string subscriptionId) 46 | { 47 | if (_headerCallbacks.ContainsKey(subscriptionId)) 48 | { 49 | Logger.Debug($"Unregister subscription '{subscriptionId}'"); 50 | _headerCallbacks.Remove(subscriptionId); 51 | } 52 | } 53 | 54 | private void GenericCallBack(string subscription, T result) 55 | { 56 | Logger.Debug($"{subscription}: {result}"); 57 | 58 | if (_headerCallbacks.ContainsKey(subscription)) 59 | { 60 | ((Action) _headerCallbacks[subscription])(subscription, result); 61 | } 62 | else 63 | { 64 | if (!_pendingHeaders.ContainsKey(subscription)) _pendingHeaders.Add(subscription, new List()); 65 | _pendingHeaders[subscription].Add(result); 66 | } 67 | } 68 | 69 | /// 70 | /// Chains all head. 71 | /// 72 | /// The subscription. 73 | /// The result. 74 | [JsonRpcMethod("chain_allHead")] 75 | public void ChainAllHead(string subscription, Header result) 76 | { 77 | GenericCallBack(subscription, result); 78 | } 79 | 80 | /// 81 | /// Chains the new head. 82 | /// 83 | /// The subscription. 84 | /// The result. 85 | [JsonRpcMethod("chain_newHead")] 86 | public void ChainNewHead(string subscription, Header result) 87 | { 88 | GenericCallBack(subscription, result); 89 | } 90 | 91 | /// 92 | /// Chains the finalized head. 93 | /// 94 | /// The subscription. 95 | /// The result. 96 | [JsonRpcMethod("chain_finalizedHead")] 97 | public void ChainFinalizedHead(string subscription, Header result) 98 | { 99 | GenericCallBack(subscription, result); 100 | } 101 | 102 | /// 103 | /// States the runtime version. 104 | /// 105 | /// The subscription. 106 | /// The result. 107 | [JsonRpcMethod("state_runtimeVersion")] 108 | public void StateRuntimeVersion(string subscription, JObject result) 109 | { 110 | GenericCallBack(subscription, result); 111 | } 112 | 113 | /// 114 | /// States the storage. 115 | /// 116 | /// The subscription. 117 | /// The result. 118 | /// 119 | [JsonRpcMethod("state_storage")] 120 | public void StateStorage(string subscription, StorageChangeSet result) 121 | { 122 | GenericCallBack(subscription, result); 123 | } 124 | 125 | /// 126 | /// Authors the submit and watch extrinsic. 127 | /// 128 | /// The subscription. 129 | /// The result. 130 | /// 131 | [JsonRpcMethod("author_extrinsicUpdate")] 132 | public void AuthorSubmitAndWatchExtrinsic(string subscription, ExtrinsicStatus result) 133 | { 134 | GenericCallBack(subscription, result); 135 | } 136 | } 137 | } -------------------------------------------------------------------------------- /SubstrateNetApi/SubstrateNetApi.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0 5 | true 6 | BloGa Tech AG 7 | Cedric Decoster 8 | Just another Substrate .NET API, written in NETStandard2.0 to provide maximum compatibility for Unity3D. 9 | https://github.com/JetonNetwork/SubstrateNetApi/tree/origin/SubstrateNetApi 10 | LICENSE 11 | https://github.com/JetonNetwork/SubstrateNetApi 12 | git 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | True 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /SubstrateNetApi/TypeConverters/ExtrinsicJsonConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Newtonsoft.Json; 3 | using NLog; 4 | using SubstrateNetApi.Model.Extrinsics; 5 | 6 | namespace SubstrateNetApi.TypeConverters 7 | { 8 | /// 9 | ///
10 | ///
11 | internal class ExtrinsicJsonConverter : JsonConverter 12 | { 13 | /// The logger 14 | private static readonly ILogger Logger = LogManager.GetCurrentClassLogger(); 15 | 16 | /// Reads the JSON representation of the object. 17 | /// The to read from. 18 | /// Type of the object. 19 | /// The existing value of object being read. If there is no existing value then null will be used. 20 | /// The existing value has a value. 21 | /// The calling serializer. 22 | /// The object value. 23 | public override Extrinsic ReadJson(JsonReader reader, Type objectType, Extrinsic existingValue, 24 | bool hasExistingValue, JsonSerializer serializer) 25 | { 26 | return new Extrinsic((string) reader.Value); 27 | } 28 | 29 | /// Writes the JSON representation of the object. 30 | /// The to write to. 31 | /// The value. 32 | /// The calling serializer. 33 | /// 34 | public override void WriteJson(JsonWriter writer, Extrinsic value, JsonSerializer serializer) 35 | { 36 | throw new NotImplementedException(); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /SubstrateNetApi/TypeConverters/GenericTypeConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Newtonsoft.Json; 3 | using SubstrateNetApi.Model.Types; 4 | 5 | namespace SubstrateNetApi.TypeConverters 6 | { 7 | public class GenericTypeConverter : JsonConverter, ITypeConverter where T : IType, new() 8 | { 9 | /// Gets the name of the type. 10 | /// The name of the type. 11 | public string TypeName { get; } = new T().Name(); 12 | 13 | /// Creates a new object. 14 | /// The value. 15 | /// An object. 16 | public object Create(string value) 17 | { 18 | if (string.IsNullOrEmpty(value)) return null; 19 | 20 | var baseType = new T(); 21 | baseType.Create(value); 22 | return baseType; 23 | } 24 | 25 | /// Reads the JSON representation of the object. 26 | /// The to read from. 27 | /// Type of the object. 28 | /// The existing value of object being read. If there is no existing value then null will be used. 29 | /// The existing value has a value. 30 | /// The calling serializer. 31 | /// The object value. 32 | public override T ReadJson(JsonReader reader, Type objectType, T existingValue, bool hasExistingValue, 33 | JsonSerializer serializer) 34 | { 35 | var baseType = new T(); 36 | baseType.CreateFromJson((string) reader.Value); 37 | return baseType; 38 | } 39 | 40 | /// Writes the JSON representation of the object. 41 | /// The to write to. 42 | /// The value. 43 | /// The calling serializer. 44 | public override void WriteJson(JsonWriter writer, T value, JsonSerializer serializer) 45 | { 46 | writer.WriteValue(value.ToString()); 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /SubstrateNetApiTest/ClientTests/ClientTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using NLog; 4 | using NLog.Config; 5 | using NLog.Targets; 6 | using NUnit.Framework; 7 | using SubstrateNetApi; 8 | using SubstrateNetApi.Exceptions; 9 | using SubstrateNetApi.Model.Types.Custom; 10 | using SubstrateNetApi.Model.Types.Struct; 11 | using SubstrateNetApi.TypeConverters; 12 | 13 | namespace SubstrateNetApiTests.ClientTests 14 | { 15 | internal class ClientTests 16 | { 17 | private const string WebSocketUrl = "wss://rpc.polkadot.io"; 18 | 19 | private SubstrateClient _substrateClient; 20 | 21 | [SetUp] 22 | public void Setup() 23 | { 24 | var config = new LoggingConfiguration(); 25 | 26 | // Targets where to log to: File and Console 27 | var console = new ConsoleTarget("logconsole"); 28 | 29 | // Rules for mapping loggers to targets 30 | config.AddRule(LogLevel.Debug, LogLevel.Fatal, console); 31 | 32 | // Apply config 33 | LogManager.Configuration = config; 34 | 35 | _substrateClient = new SubstrateClient(new Uri(WebSocketUrl)); 36 | } 37 | 38 | [TearDown] 39 | public void TearDown() 40 | { 41 | _substrateClient.Dispose(); 42 | } 43 | 44 | [Test] 45 | public async Task MultipleConnectionsTestAsync() 46 | { 47 | await _substrateClient.ConnectAsync(); 48 | Assert.IsTrue(_substrateClient.IsConnected); 49 | await _substrateClient.CloseAsync(); 50 | Assert.IsFalse(_substrateClient.IsConnected); 51 | await _substrateClient.ConnectAsync(); 52 | Assert.IsTrue(_substrateClient.IsConnected); 53 | await _substrateClient.CloseAsync(); 54 | } 55 | 56 | [Test] 57 | public async Task ConnectWhileConnectedTestAsync() 58 | { 59 | await _substrateClient.ConnectAsync(); 60 | Assert.IsTrue(_substrateClient.IsConnected); 61 | await _substrateClient.ConnectAsync(); 62 | Assert.IsTrue(_substrateClient.IsConnected); 63 | await _substrateClient.CloseAsync(); 64 | Assert.IsFalse(_substrateClient.IsConnected); 65 | } 66 | 67 | [Test] 68 | public void MultipleConverterTest() 69 | { 70 | _substrateClient.RegisterTypeConverter(new GenericTypeConverter()); 71 | Assert.Throws(() => 72 | _substrateClient.RegisterTypeConverter(new GenericTypeConverter())); 73 | } 74 | 75 | [Test] 76 | public async Task GetMethodSystemNameTestAsync() 77 | { 78 | await _substrateClient.ConnectAsync(); 79 | 80 | var result = await _substrateClient.GetMethodAsync("system_name"); 81 | Assert.AreEqual("Parity Polkadot", result); 82 | 83 | await _substrateClient.CloseAsync(); 84 | } 85 | 86 | [Test] 87 | public async Task GetMethodChainNameTestAsync() 88 | { 89 | await _substrateClient.ConnectAsync(); 90 | 91 | var result = await _substrateClient.GetMethodAsync("system_chain"); 92 | Assert.AreEqual("Polkadot", result); 93 | 94 | await _substrateClient.CloseAsync(); 95 | } 96 | 97 | [Test] 98 | public void GetMethodNotConnectedTest() 99 | { 100 | Assert.ThrowsAsync(async () => 101 | await _substrateClient.GetMethodAsync("system_name")); 102 | } 103 | } 104 | } -------------------------------------------------------------------------------- /SubstrateNetApiTest/ClientTests/GetStorageTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using NLog; 4 | using NLog.Config; 5 | using NLog.Targets; 6 | using NUnit.Framework; 7 | using SubstrateNetApi; 8 | using SubstrateNetApi.Exceptions; 9 | using SubstrateNetApi.Model.Types.Base; 10 | using SubstrateNetApi.Model.Types.Struct; 11 | 12 | namespace SubstrateNetApiTests.ClientTests 13 | { 14 | public class GetStorageTests 15 | { 16 | private const string WebSocketUrl = "wss://rpc.polkadot.io"; 17 | 18 | private SubstrateClient _substrateClient; 19 | 20 | [OneTimeSetUp] 21 | public void Setup() 22 | { 23 | var config = new LoggingConfiguration(); 24 | 25 | // Targets where to log to: File and Console 26 | var logconsole = new ConsoleTarget("logconsole"); 27 | 28 | // Rules for mapping loggers to targets 29 | config.AddRule(LogLevel.Debug, LogLevel.Fatal, logconsole); 30 | 31 | // Apply config 32 | LogManager.Configuration = config; 33 | 34 | _substrateClient = new SubstrateClient(new Uri(WebSocketUrl)); 35 | } 36 | 37 | [OneTimeTearDown] 38 | public void TearDown() 39 | { 40 | _substrateClient.Dispose(); 41 | } 42 | 43 | [Test] 44 | public async Task BasicStorageTestNoParameterAsync1() 45 | { 46 | await _substrateClient.ConnectAsync(); 47 | 48 | var reqResult = await _substrateClient.GetStorageAsync("System", "Number"); 49 | Assert.AreEqual("BlockNumber", reqResult.GetType().Name); 50 | Assert.IsTrue(reqResult is BlockNumber); 51 | 52 | await _substrateClient.CloseAsync(); 53 | } 54 | 55 | [Test] 56 | public async Task BasicStorageTestWithParameterAsync1() 57 | { 58 | await _substrateClient.ConnectAsync(); 59 | 60 | var reqResult = await _substrateClient.GetStorageAsync("System", "Account", new string[] { Utils.Bytes2HexString(Utils.GetPublicKeyFrom("13RDY9nrJpyTDBSUdBw12dGwhk19sGwsrVZ2bxkzYHBSagP2")) }); 61 | Assert.AreEqual("AccountInfo", reqResult.GetType().Name); 62 | Assert.IsTrue(reqResult is AccountInfo); 63 | 64 | await _substrateClient.CloseAsync(); 65 | } 66 | 67 | [Test] 68 | public async Task InvalidStorageNameTestAsync() 69 | { 70 | await _substrateClient.ConnectAsync(); 71 | 72 | Assert.ThrowsAsync(async () => 73 | await _substrateClient.GetStorageAsync("Invalid", "Name")); 74 | 75 | await _substrateClient.CloseAsync(); 76 | } 77 | 78 | [Test] 79 | public void InvalidConnectionStateTest() 80 | { 81 | Assert.ThrowsAsync(async () => 82 | await _substrateClient.GetStorageAsync("Invalid", "Name")); 83 | } 84 | 85 | [Test] 86 | public async Task MissingTypeConverterTestAsync() 87 | { 88 | await _substrateClient.ConnectAsync(); 89 | 90 | Assert.ThrowsAsync(async () => 91 | await _substrateClient.GetStorageAsync("Timestamp", "Now")); 92 | 93 | await _substrateClient.CloseAsync(); 94 | } 95 | } 96 | } -------------------------------------------------------------------------------- /SubstrateNetApiTest/CustomTests/CustomStorageTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using NUnit.Framework; 4 | using SubstrateNetApi; 5 | using SubstrateNetApi.Model.Types.Struct; 6 | using SubstrateNetApi.Model.Types.Base; 7 | using NLog.Config; 8 | using NLog; 9 | using System.Threading.Tasks; 10 | using SubstrateNetApi.Exceptions; 11 | using NLog.Targets; 12 | using SubstrateNetApi.Model.Types; 13 | using SubstrateNetApi.Model.Rpc; 14 | using SubstrateNetApi.Model.Extrinsics; 15 | using SubstrateNetApi.TypeConverters; 16 | 17 | namespace SubstrateNetApiTests 18 | { 19 | public class CustomStorageTests 20 | { 21 | private const string WebSocketUrl = "wss://mogiway-01.dotmog.com"; 22 | 23 | private SubstrateClient _substrateClient; 24 | 25 | [OneTimeSetUp] 26 | public void Setup() 27 | { 28 | var config = new LoggingConfiguration(); 29 | 30 | // Targets where to log to: File and Console 31 | var logconsole = new ConsoleTarget("logconsole"); 32 | 33 | // Rules for mapping loggers to targets 34 | config.AddRule(LogLevel.Debug, LogLevel.Fatal, logconsole); 35 | 36 | // Apply config 37 | LogManager.Configuration = config; 38 | 39 | _substrateClient = new SubstrateClient(new Uri(WebSocketUrl)); 40 | 41 | } 42 | 43 | [OneTimeTearDown] 44 | public void TearDown() 45 | { 46 | _substrateClient.Dispose(); 47 | } 48 | 49 | [Test] 50 | public async Task BasicTestAsync() 51 | { 52 | await _substrateClient.ConnectAsync(); 53 | 54 | var reqResult = await _substrateClient.GetStorageAsync("Sudo", "Key"); 55 | Assert.AreEqual("AccountId", reqResult.GetType().Name); 56 | Assert.IsTrue(reqResult is AccountId); 57 | 58 | var accountId = (AccountId)reqResult; 59 | Assert.AreEqual("5DAriiitbj77Dz6RyfFCFJagg2W9zptpEqBgBKPKtLvzw23c", accountId.Value); 60 | 61 | await _substrateClient.CloseAsync(); 62 | } 63 | 64 | [Test] 65 | public async Task ParameterizedTestAsync() 66 | { 67 | await _substrateClient.ConnectAsync(); 68 | 69 | var countMogwais = await _substrateClient.GetStorageAsync("DotMogModule", "AllMogwaisCount"); 70 | Assert.AreEqual("U64", countMogwais.GetType().Name); 71 | 72 | var request = await _substrateClient.GetStorageAsync("DotMogModule", "AllMogwaisArray", new[] { "0" }); 73 | Assert.AreEqual("Hash", request.GetType().Name); 74 | Assert.IsTrue(request is Hash); 75 | 76 | await _substrateClient.CloseAsync(); 77 | } 78 | 79 | [Test] 80 | public async Task ParameterizedTest2Async() 81 | { 82 | var accountZurich = Account.Build( 83 | KeyType.Ed25519, 84 | Utils.HexToByteArray( 85 | "0xf5e5767cf153319517630f226876b86c8160cc583bc013744c6bf255f5cc0ee5278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e"), 86 | Utils.GetPublicKeyFrom("5CxW5DWQDpXi4cpACd62wzbPjbYrx4y67TZEmRXBcvmDTNaM")); 87 | 88 | _substrateClient.RegisterTypeConverter(new GenericTypeConverter()); 89 | await _substrateClient.ConnectAsync(); 90 | 91 | 92 | var request = await _substrateClient.GetStorageAsync("Assets", "Account", new[] { "0" }, new[] { Utils.Bytes2HexString(accountZurich.Bytes) }); 93 | Assert.AreEqual("AssetBalance", request.GetType().Name); 94 | Assert.IsTrue(request is AssetBalance); 95 | var assetBalance = (AssetBalance)request; 96 | Assert.AreEqual(100, assetBalance.Balance.Value); 97 | 98 | await _substrateClient.CloseAsync(); 99 | 100 | } 101 | 102 | [Test] 103 | public async Task MissingParameterTestAsync() 104 | { 105 | await _substrateClient.ConnectAsync(); 106 | 107 | Assert.ThrowsAsync(async () => 108 | await _substrateClient.GetStorageAsync("DotMogModule", "AllMogwaisArray")); 109 | 110 | await _substrateClient.CloseAsync(); 111 | } 112 | 113 | [Test] 114 | public async Task InvalidStorageNameTestAsync() 115 | { 116 | await _substrateClient.ConnectAsync(); 117 | 118 | Assert.ThrowsAsync(async () => 119 | await _substrateClient.GetStorageAsync("Invalid", "Name")); 120 | 121 | await _substrateClient.CloseAsync(); 122 | } 123 | 124 | [Test] 125 | public void InvalidConnectionStateTest() 126 | { 127 | Assert.ThrowsAsync(async () => 128 | await _substrateClient.GetStorageAsync("Invalid", "Name")); 129 | } 130 | 131 | [Test] 132 | public async Task MissingTypeConverterTestAsync() 133 | { 134 | await _substrateClient.ConnectAsync(); 135 | 136 | Assert.ThrowsAsync(async () => 137 | await _substrateClient.GetStorageAsync("DotMogModule", "Mogwais", new[] 138 | { 139 | "0xAD35415CB5B574819C8521B9192FFFDA772C0770FED9A55494293B2D728F104C" 140 | })); 141 | 142 | await _substrateClient.CloseAsync(); 143 | } 144 | } 145 | } -------------------------------------------------------------------------------- /SubstrateNetApiTest/CustomTests/CustomTypeConverters.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using NUnit.Framework; 4 | using SubstrateNetApi; 5 | using SubstrateNetApi.Model.Types.Struct; 6 | using SubstrateNetApi.Model.Types.Base; 7 | using SubstrateNetApi.Model.Types; 8 | using SubstrateNetApi.Model.Types.Enum; 9 | using SubstrateNetApi.TypeConverters; 10 | using System.Numerics; 11 | using SubstrateNetApi.Model.Types.Custom; 12 | 13 | namespace SubstrateNetApiTests 14 | { 15 | public class CustomTypeConverters 16 | { 17 | [SetUp] 18 | public void Setup() 19 | { 20 | } 21 | 22 | [Test] 23 | public void MogwaiStructTypeConverterTest() 24 | { 25 | var tc = new GenericTypeConverter(); 26 | var actual = 27 | tc.Create( 28 | "0x89ab510f57802886c16922685a376edb536f762584dda569cda67381c4e4dec889ab510f57802886c16922685a376edb536f762584dda569cda67381c4e4dec871000000000000000000000000000000000000000000000000"); 29 | Assert.IsTrue(actual is MogwaiStruct); 30 | var hash = new Hash(); 31 | hash.Create("0x89ab510f57802886c16922685a376edb536f762584dda569cda67381c4e4dec8"); 32 | Assert.AreEqual(hash.Value, (actual as MogwaiStruct).Id.Value); 33 | } 34 | 35 | [Test] 36 | public void MogwaiBiosTypeConverterTest() 37 | { 38 | var tc = new GenericTypeConverter(); 39 | var actual = 40 | tc.Create("0xe2d3965c287d92c7cf45dc3ff832e8060607cc8eb7f85ae598b4030338f59587" + 41 | "00000000" + 42 | "08" + 43 | "f27a7c4788ef094b6e4d8d6eaa0732c4" + 44 | "844cbb8fb0ab077a7aba7f7a7baba77a" + 45 | "000000000000000000000000" + 46 | "0000000001" + 47 | "040c1f020000"); 48 | Assert.IsTrue(actual is MogwaiBios); 49 | var mogwaiBios = actual as MogwaiBios; 50 | Assert.AreEqual("0xe2d3965c287d92c7cf45dc3ff832e8060607cc8eb7f85ae598b4030338f59587", 51 | mogwaiBios.Id.Value.ToLower()); 52 | Assert.AreEqual(0, mogwaiBios.State.Value); 53 | Assert.AreEqual("0xf27a7c4788ef094b6e4d8d6eaa0732c4", 54 | (mogwaiBios.MetaXy.Value[0].Value as string).ToLower()); 55 | Assert.AreEqual("0x844cbb8fb0ab077a7aba7f7a7baba77a", 56 | (mogwaiBios.MetaXy.Value[1].Value as string).ToLower()); 57 | Assert.AreEqual(new BigInteger(0), mogwaiBios.Intrinsic.Value); 58 | Assert.AreEqual(1, mogwaiBios.Level.Value); 59 | Assert.AreEqual(139020, mogwaiBios.Phases.Value[0].Value); 60 | Assert.AreEqual(0, mogwaiBios.Adaptations.Value.Count); 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /SubstrateNetApiTest/CustomTests/CustomTypes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using NUnit.Framework; 4 | using SubstrateNetApi; 5 | using SubstrateNetApi.Model.Types.Struct; 6 | using SubstrateNetApi.Model.Types.Base; 7 | using SubstrateNetApi.Model.Types; 8 | using SubstrateNetApi.Model.Types.Enum; 9 | using SubstrateNetApi.TypeConverters; 10 | using System.Numerics; 11 | using SubstrateNetApi.Model.Types.Custom; 12 | 13 | namespace SubstrateNetApiTests 14 | { 15 | public class CustomTypes 16 | { 17 | [SetUp] 18 | public void Setup() 19 | { 20 | } 21 | 22 | [Test] 23 | public void MogwaiStructTest() 24 | { 25 | var mogwaiStructStr = "0x89ab510f57802886c16922685a376edb536f762584dda569cda67381c4e4dec889ab510f57802886c16922685a376edb536f762584dda569cda67381c4e4dec871000000000000000000000000000000000000000000000000"; 26 | var mogwaiStructA = new MogwaiStruct(); 27 | mogwaiStructA.Create(mogwaiStructStr); 28 | 29 | 30 | var mogwaiStructB = new MogwaiStruct(); 31 | 32 | var id = new Hash(); 33 | id.Create(mogwaiStructA.Id.Value); 34 | 35 | var dna = new Hash(); 36 | dna.Create(mogwaiStructA.Dna.Value); 37 | 38 | var genesis = new BlockNumber(); 39 | genesis.Create(mogwaiStructA.Genesis.Value); 40 | 41 | var price = new Balance(); 42 | price.Create(mogwaiStructA.Price.Value); 43 | 44 | var gen = new U32(); 45 | gen.Create(mogwaiStructA.Gen.Value); 46 | 47 | var rarity = new EnumType(); 48 | rarity.Create(mogwaiStructA.Rarity.Bytes); 49 | 50 | mogwaiStructB.Create(id, dna, genesis, price, gen, rarity); 51 | 52 | Assert.AreEqual(mogwaiStructB.Id.Value, mogwaiStructA.Id.Value); 53 | Assert.AreEqual(mogwaiStructB.Dna.Value, mogwaiStructA.Dna.Value); 54 | Assert.AreEqual(mogwaiStructB.Genesis.Value, mogwaiStructA.Genesis.Value); 55 | Assert.AreEqual(mogwaiStructB.Price.Value, mogwaiStructA.Price.Value); 56 | Assert.AreEqual(mogwaiStructB.Gen.Value, mogwaiStructA.Gen.Value); 57 | Assert.AreEqual(mogwaiStructB.Rarity.Value, mogwaiStructA.Rarity.Value); 58 | } 59 | 60 | [Test] 61 | public void MogwaiBiosTest() 62 | { 63 | var mogwaiBiosStr = "0x0b1b9f0f79a9e3971baf6188ed98623284f1c3bb275883602164b7097789523f000000000881f7a106cc0f747e85deedaf2946297ebacbe008a7a4887c334448fcc4c4888c00000000000000000000000000000000010426df010000"; 64 | var mogwaiBiosA = new MogwaiBios(); 65 | mogwaiBiosA.Create(mogwaiBiosStr); 66 | 67 | var mogwaiBiosB = new MogwaiBios(); 68 | 69 | var id = new Hash(); 70 | id.Create(mogwaiBiosA.Id.Value); 71 | Assert.AreEqual("0x0B1B9F0F79A9E3971BAF6188ED98623284F1C3BB275883602164B7097789523F", mogwaiBiosA.Id.Value); 72 | 73 | var state = new U32(); 74 | state.Create(mogwaiBiosA.State.Value); 75 | Assert.AreEqual(0, mogwaiBiosA.State.Value); 76 | 77 | var metaXy = new Vec(); 78 | metaXy.Create(mogwaiBiosA.MetaXy.Bytes); 79 | 80 | Assert.AreEqual(2, mogwaiBiosA.MetaXy.Value.Count); 81 | Assert.AreEqual("0x0881F7A106CC0F747E85DEEDAF2946297EBACBE008A7A4887C334448FCC4C4888C", Utils.Bytes2HexString(mogwaiBiosA.MetaXy.Bytes)); 82 | Assert.AreEqual("0x81F7A106CC0F747E85DEEDAF2946297E", Utils.Bytes2HexString(metaXy.Value[0].Bytes)); 83 | 84 | var intrinsic = new Balance(); 85 | intrinsic.Create(mogwaiBiosA.Intrinsic.Value); 86 | 87 | var level = new U8(); 88 | level.Create(mogwaiBiosA.Level.Value); 89 | 90 | var phases = new Vec(); 91 | phases.Create(mogwaiBiosA.Phases.Bytes); 92 | 93 | var adaptations = new Vec(); 94 | adaptations.Create(mogwaiBiosA.Adaptations.Bytes); 95 | 96 | mogwaiBiosB.Create(id, state, metaXy, intrinsic, level, phases, adaptations); 97 | 98 | Assert.AreEqual(mogwaiBiosB.Id.Value, mogwaiBiosA.Id.Value); 99 | Assert.AreEqual(mogwaiBiosB.State.Value, mogwaiBiosA.State.Value); 100 | Assert.AreEqual(mogwaiBiosB.MetaXy.Value[0].Bytes, mogwaiBiosA.MetaXy.Value[0].Bytes); 101 | Assert.AreEqual(mogwaiBiosB.Intrinsic.Value, mogwaiBiosA.Intrinsic.Value); 102 | Assert.AreEqual(mogwaiBiosB.Level.Value, mogwaiBiosA.Level.Value); 103 | Assert.AreEqual(mogwaiBiosB.Phases.Value[0].Bytes, mogwaiBiosA.Phases.Value[0].Bytes); 104 | Assert.AreEqual(mogwaiBiosB.Adaptations.Value, mogwaiBiosA.Adaptations.Value); 105 | } 106 | 107 | } 108 | } -------------------------------------------------------------------------------- /SubstrateNetApiTest/Extrinsic/EraTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | using SubstrateNetApi; 4 | using SubstrateNetApi.Model.Extrinsics; 5 | 6 | namespace SubstrateNetApiTests.Extrinsic 7 | { 8 | public class EraTest 9 | { 10 | private Random _random; 11 | 12 | [OneTimeSetUp] 13 | public void Setup() 14 | { 15 | _random = new Random(); 16 | } 17 | 18 | [OneTimeTearDown] 19 | public void TearDown() 20 | { 21 | } 22 | 23 | [Test] 24 | public void EraEncodeDecodeTest() 25 | { 26 | var era1 = Era.Decode(new byte[] {58, 6}); 27 | Assert.AreEqual(2048, era1.Period); 28 | Assert.AreEqual(99, era1.Phase); 29 | Assert.AreEqual(new byte[] {58, 6}, era1.Encode()); 30 | 31 | var era2 = Era.Decode(Utils.HexToByteArray("0x4503")); 32 | Assert.AreEqual(64, era2.Period); 33 | Assert.AreEqual(52, era2.Phase); 34 | Assert.AreEqual(new byte[] {69, 3}, era2.Encode()); 35 | 36 | var era3 = Era.Decode(Utils.HexToByteArray("0xF502")); 37 | Assert.AreEqual(64, era3.Period); 38 | Assert.AreEqual(47, era3.Phase); 39 | Assert.AreEqual(new byte[] {245, 2}, era3.Encode()); 40 | } 41 | 42 | [Test] 43 | public void EraBeginTest() 44 | { 45 | var era = new Era(64, 49, false); 46 | Assert.AreEqual(1585, era.EraStart(1587)); 47 | } 48 | 49 | [Test] 50 | public void EraCreateTest() 51 | { 52 | var era = Era.Create(12, 15686); 53 | Assert.AreEqual(16, era.Period); 54 | Assert.AreEqual(6, era.Phase); 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /SubstrateNetApiTest/Extrinsic/MethodTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using NUnit.Framework; 4 | using SubstrateNetApi; 5 | using SubstrateNetApi.Model.Extrinsics; 6 | 7 | namespace SubstrateNetApiTests.Extrinsic 8 | { 9 | public class MethodTest 10 | { 11 | private Random _random; 12 | 13 | [OneTimeSetUp] 14 | public void Setup() 15 | { 16 | _random = new Random(); 17 | } 18 | 19 | [OneTimeTearDown] 20 | public void TearDown() 21 | { 22 | } 23 | 24 | [Test] 25 | public void MethodEncodeTest() 26 | { 27 | Assert.True("0x0602".Equals(Utils.Bytes2HexString(new Method(0x06, 0x02).Encode()), 28 | StringComparison.InvariantCultureIgnoreCase)); 29 | 30 | Assert.True("0x06000100000000000000".Equals( 31 | Utils.Bytes2HexString(new Method(0x06, 0x00, Utils.HexToByteArray("0x0100000000000000")).Encode()), 32 | StringComparison.InvariantCultureIgnoreCase)); 33 | 34 | var parameters = new List(); 35 | parameters.Add(0xFF); 36 | parameters.AddRange(Utils.GetPublicKeyFrom("5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY")); 37 | Assert.AreEqual("0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d".ToUpper(), 38 | Utils.Bytes2HexString(Utils.GetPublicKeyFrom("5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY")) 39 | .ToUpper()); 40 | parameters.AddRange(new CompactInteger(100).Encode()); 41 | var balanceTransfer = new Method(0x04, 0x00, parameters.ToArray()); 42 | Assert.True("0x0400ffd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d9101".Equals( 43 | Utils.Bytes2HexString(balanceTransfer.Encode()), StringComparison.InvariantCultureIgnoreCase)); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /SubstrateNetApiTest/Extrinsic/PayloadTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using NUnit.Framework; 4 | using SubstrateNetApi; 5 | using SubstrateNetApi.Model.Extrinsics; 6 | using SubstrateNetApi.Model.Types.Base; 7 | 8 | namespace SubstrateNetApiTests.Extrinsic 9 | { 10 | public class PayloadTest 11 | { 12 | private Random _random; 13 | 14 | [OneTimeSetUp] 15 | public void Setup() 16 | { 17 | _random = new Random(); 18 | } 19 | 20 | [OneTimeTearDown] 21 | public void TearDown() 22 | { 23 | } 24 | 25 | [Test] 26 | public void EncodeExtraTest() 27 | { 28 | var genesisHash = new byte[] 29 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 30 | var blockHash = new byte[] 31 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 32 | 33 | var era = new Era(2048, 99, false); 34 | 35 | var paramsList = new List(); 36 | paramsList.Add(0xFF); 37 | paramsList.AddRange( 38 | Utils.HexToByteArray( 39 | "d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d")); // Utils.GetPublicKeyFrom("5FfBQ3kwXrbdyoqLPvcXRp7ikWydXawpNs2Ceu3WwFdhZ8W4"); 40 | CompactInteger amount = 100; 41 | paramsList.AddRange(amount.Encode()); 42 | var parameters = paramsList.ToArray(); 43 | 44 | var method = new Method(0x06, 0x00, parameters); 45 | var methodBytes = Utils.StringValueArrayBytesArray( 46 | "6, 0, 255, 212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125, 145, 1"); 47 | 48 | Assert.AreEqual(methodBytes, method.Encode()); 49 | 50 | var genesis = new Hash(); 51 | genesis.Create(genesisHash); 52 | 53 | var startEra = new Hash(); 54 | startEra.Create(blockHash); 55 | 56 | var signedExtensions = new SignedExtensions(259, 1, genesis, startEra, era, 0, 0); 57 | 58 | var payload = new Payload(method, signedExtensions); 59 | 60 | var payloadBytes = Utils.StringValueArrayBytesArray( 61 | "6, 0, 255, 212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125, 145, 1, 58, 6, 0, 0, 3, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0"); 62 | 63 | Assert.AreEqual(payloadBytes, payload.Encode()); 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /SubstrateNetApiTest/Extrinsic/SignedExtensionsTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | using SubstrateNetApi; 4 | using SubstrateNetApi.Model.Extrinsics; 5 | using SubstrateNetApi.Model.Types.Base; 6 | 7 | namespace SubstrateNetApiTests.Extrinsic 8 | { 9 | public class SignedExtensionsTest 10 | { 11 | private Random _random; 12 | 13 | [OneTimeSetUp] 14 | public void Setup() 15 | { 16 | _random = new Random(); 17 | } 18 | 19 | [OneTimeTearDown] 20 | public void TearDown() 21 | { 22 | } 23 | 24 | [Test] 25 | public void EncodeExtraTest() 26 | { 27 | var genesisHash = new byte[] 28 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 29 | var blockHash = new byte[] 30 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 31 | 32 | var era = new Era(2048, 99, false); 33 | 34 | var genesis = new Hash(); 35 | genesis.Create(genesisHash); 36 | 37 | var startEra = new Hash(); 38 | startEra.Create(blockHash); 39 | 40 | var signedExtensions = new SignedExtensions(259, 1, genesis, startEra, era, 0, 0); 41 | 42 | var bytes = Utils.StringValueArrayBytesArray( 43 | "58, 6, 0, 0, 3, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0"); 44 | 45 | Assert.AreEqual(bytes.AsMemory().Slice(0, 4).ToArray(), signedExtensions.GetExtra()); 46 | Assert.AreEqual(bytes.AsMemory().Slice(4, 72).ToArray(), signedExtensions.GetAdditionalSigned()); 47 | Assert.AreEqual(bytes, signedExtensions.Encode()); 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /SubstrateNetApiTest/HashExtensionTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using NUnit.Framework; 4 | using SubstrateNetApi; 5 | using SubstrateNetApi.Model.Meta; 6 | 7 | namespace SubstrateNetApiTests 8 | { 9 | public class HashExtensionTests 10 | { 11 | [SetUp] 12 | public void Setup() 13 | { 14 | } 15 | 16 | [Test] 17 | public void XXHash128() 18 | { 19 | var bytes1 = Encoding.ASCII.GetBytes("Sudo"); 20 | var hashBytes1 = HashExtension.Twox128(bytes1); 21 | Assert.AreEqual("5C0D1176A568C1F92944340DBFED9E9C", BitConverter.ToString(hashBytes1).Replace("-", "")); 22 | 23 | var bytes2 = Encoding.ASCII.GetBytes("Key"); 24 | var hashBytes2 = HashExtension.Twox128(bytes2); 25 | Assert.AreEqual("530EBCA703C85910E7164CB7D1C9E47B", BitConverter.ToString(hashBytes2).Replace("-", "")); 26 | } 27 | 28 | [Test] 29 | public void BlakeTwo128Test() 30 | { 31 | var bytes = Utils.HexToByteArray("0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"); 32 | var hashBytes = HashExtension.Hash(Storage.Hasher.BlakeTwo128, bytes); 33 | Assert.AreEqual( 34 | "DE1E86A9A8C739864CF3CC5EC2BEA59F", 35 | BitConverter.ToString(hashBytes).Replace("-", "")); 36 | } 37 | 38 | [Test] 39 | public void BlakeTwo256Test() 40 | { 41 | var bytes = Utils.HexToByteArray("0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"); 42 | var hashBytes = HashExtension.Hash(Storage.Hasher.BlakeTwo256, bytes); 43 | Assert.AreEqual( 44 | "2E3FB4C297A84C5CEBC0E78257D213D0927CCC7596044C6BA013DD05522AACBA", 45 | BitConverter.ToString(hashBytes).Replace("-", "")); 46 | } 47 | 48 | [Test] 49 | public void BlakeTwo128ConcatTest() 50 | { 51 | var bytes = Utils.HexToByteArray("0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"); 52 | var hashBytes = HashExtension.Hash(Storage.Hasher.BlakeTwo128Concat, bytes); 53 | Assert.AreEqual( 54 | "DE1E86A9A8C739864CF3CC5EC2BEA59FD43593C715FDD31C61141ABD04A99FD6822C8558854CCDE39A5684E7A56DA27D", 55 | BitConverter.ToString(hashBytes).Replace("-", "")); 56 | } 57 | 58 | [Test] 59 | public void Twox128Test() 60 | { 61 | var bytes = Utils.HexToByteArray("0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"); 62 | var hashBytes = HashExtension.Hash(Storage.Hasher.Twox128, bytes); 63 | Assert.AreEqual( 64 | "518366B5B1BC7C99BAE0BA710AF1AC66", 65 | BitConverter.ToString(hashBytes).Replace("-", "")); 66 | } 67 | 68 | [Test] 69 | public void Twox256Test() 70 | { 71 | var bytes = Utils.HexToByteArray("0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"); 72 | var hashBytes = HashExtension.Hash(Storage.Hasher.Twox256, bytes); 73 | Assert.AreEqual( 74 | "518366B5B1BC7C99BAE0BA710AF1AC66ECC0FD2F7C15BBE1EB86DBF45C7899E8", 75 | BitConverter.ToString(hashBytes).Replace("-", "")); 76 | } 77 | 78 | [Test] 79 | public void Twox64ConcatTest() 80 | { 81 | var bytes = Utils.HexToByteArray("0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"); 82 | var hashBytes = HashExtension.Hash(Storage.Hasher.Twox64Concat, bytes); 83 | Assert.AreEqual( 84 | "518366B5B1BC7C99D43593C715FDD31C61141ABD04A99FD6822C8558854CCDE39A5684E7A56DA27D", 85 | BitConverter.ToString(hashBytes).Replace("-", "")); 86 | } 87 | } 88 | } -------------------------------------------------------------------------------- /SubstrateNetApiTest/Keys/Ed25519Tests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using NUnit.Framework; 4 | using SubstrateNetApi; 5 | using SubstrateNetApi.Model.Types.Base; 6 | 7 | namespace SubstrateNetApiTests.Keys 8 | { 9 | public class Ed25519Tests 10 | { 11 | private Random _random; 12 | 13 | [OneTimeSetUp] 14 | public void Setup() 15 | { 16 | _random = new Random(); 17 | } 18 | 19 | [OneTimeTearDown] 20 | public void TearDown() 21 | { 22 | } 23 | 24 | [Test] 25 | public void Ed25519KeyPairTest() 26 | { 27 | var priKey0x = 28 | "0xf5e5767cf153319517630f226876b86c8160cc583bc013744c6bf255f5cc0ee5278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e"; 29 | var pubKey0x = "0x278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e"; 30 | 31 | var priKey = Utils.HexToByteArray(priKey0x); 32 | var pubKey = Utils.HexToByteArray(pubKey0x); 33 | var seed = priKey.Take(32).ToArray(); 34 | 35 | Chaos.NaCl.Ed25519.KeyPairFromSeed(out pubKey, out priKey, seed); 36 | 37 | Assert.AreEqual("0xF5E5767CF153319517630F226876B86C8160CC583BC013744C6BF255F5CC0EE5", 38 | Utils.Bytes2HexString(seed)); 39 | Assert.AreEqual( 40 | "0xF5E5767CF153319517630F226876B86C8160CC583BC013744C6BF255F5CC0EE5278117FC144C72340F67D0F2316E8386CEFFBF2B2428C9C51FEF7C597F1D426E", 41 | Utils.Bytes2HexString(priKey)); 42 | Assert.AreEqual("0x278117FC144C72340F67D0F2316E8386CEFFBF2B2428C9C51FEF7C597F1D426E", 43 | Utils.Bytes2HexString(pubKey)); 44 | 45 | var accountId = new AccountId(); 46 | accountId.Create("0x278117FC144C72340F67D0F2316E8386CEFFBF2B2428C9C51FEF7C597F1D426E"); 47 | Assert.AreEqual("5CxW5DWQDpXi4cpACd62wzbPjbYrx4y67TZEmRXBcvmDTNaM", accountId.Value); 48 | } 49 | 50 | [Test] 51 | public void Ed25519KeyPairTest2() 52 | { 53 | var seed = Utils.HexToByteArray("0xf5e5767cf153319517630f226876b86c8160cc583bc013744c6bf255f5cc0ee5"); 54 | byte[] pubKey, priKey; 55 | Chaos.NaCl.Ed25519.KeyPairFromSeed(out pubKey, out priKey, seed); 56 | 57 | Assert.AreEqual( 58 | Utils.HexToByteArray( 59 | "0xf5e5767cf153319517630f226876b86c8160cc583bc013744c6bf255f5cc0ee5278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e"), 60 | Chaos.NaCl.Ed25519.ExpandedPrivateKeyFromSeed(seed)); 61 | } 62 | 63 | [Test] 64 | public void Ed25519SignatureTest() 65 | { 66 | var priKey0x = 67 | "0xf5e5767cf153319517630f226876b86c8160cc583bc013744c6bf255f5cc0ee5278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e"; 68 | var pubKey0x = "0x278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e"; 69 | 70 | var priKey = Utils.HexToByteArray(priKey0x); 71 | var pubKey = Utils.HexToByteArray(pubKey0x); 72 | 73 | var messageLength = _random.Next(10, 200); 74 | var message = new byte[messageLength]; 75 | _random.NextBytes(message); 76 | 77 | //var message = signaturePayloadBytes.AsMemory().Slice(0, (int)payloadLength).ToArray(); 78 | var simpleSign = Chaos.NaCl.Ed25519.Sign(message, priKey); 79 | 80 | Assert.True(Chaos.NaCl.Ed25519.Verify(simpleSign, message, pubKey)); 81 | } 82 | 83 | [Test] 84 | public void SignatureVerifySignedOnNodeByAccount() 85 | { 86 | var priKey0x = 87 | "0xf5e5767cf153319517630f226876b86c8160cc583bc013744c6bf255f5cc0ee5278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e"; 88 | var pubKey0x = "0x278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e"; 89 | var privateKey = Utils.HexToByteArray(priKey0x); 90 | var publicKey = Utils.GetPublicKeyFrom("5CxW5DWQDpXi4cpACd62wzbPjbYrx4y67TZEmRXBcvmDTNaM"); 91 | 92 | var messag1 = Utils.HexToByteArray("0xA81056D713AF1FF17B599E60D287952E89301B5208324A0529B62DC7369C745D"); 93 | var signedByAcc1 = 94 | Utils.HexToByteArray( 95 | "0x10b6aacb0beca6ca60b712fb5db54e957cec304489366544d96f3e59ac2d4328be7b6602ec98e622c0f16ab427eb497d6ef053e00ddfdb3d3f3b6496b0b17a0c"); 96 | Assert.True(Chaos.NaCl.Ed25519.Verify(signedByAcc1, messag1, publicKey)); 97 | 98 | var messag2 = 99 | Utils.HexToByteArray( 100 | "0x0400FF8EAF04151687736326C9FEA17E25FC5287613693C912909CB226AA4794F26A484913DC4F62090B18B6893C1431369461069EE3E9C1DA7F9F9A8C097C0CEBBEAC2BB9"); 101 | var signedByAcc2 = 102 | Utils.HexToByteArray( 103 | "0x1c7921583e992bae122ba4a754eb84071ac8a627cc4d050047e3d0dbdaa64718a3728e8f87deb2cb9249527853f85833d1b1c2e3af1c60724c060c1b78670b02"); 104 | Assert.True(Chaos.NaCl.Ed25519.Verify(signedByAcc2, messag2, publicKey)); 105 | 106 | var simpleSign = Chaos.NaCl.Ed25519.Sign(messag2, privateKey); 107 | var simpleSignStr = Utils.Bytes2HexString(simpleSign); 108 | Assert.True(Chaos.NaCl.Ed25519.Verify(simpleSign, messag2, publicKey)); 109 | } 110 | 111 | [Test] 112 | public void SignatureVerifyOnNodeSignedHereByAccount() 113 | { 114 | // https://polkadot.js.org/apps/#/signing/verify 115 | 116 | Assert.True(true); 117 | } 118 | } 119 | } -------------------------------------------------------------------------------- /SubstrateNetApiTest/Keys/Sr25519Tests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using NUnit.Framework; 4 | using Schnorrkel.Keys; 5 | using SubstrateNetApi; 6 | using SubstrateNetApi.Model.Types.Base; 7 | 8 | namespace SubstrateNetApiTests.Keys 9 | { 10 | public class Sr25519Tests 11 | { 12 | private Random _random; 13 | 14 | [OneTimeSetUp] 15 | public void Setup() 16 | { 17 | _random = new Random(); 18 | } 19 | 20 | [OneTimeTearDown] 21 | public void TearDown() 22 | { 23 | } 24 | 25 | [Test] 26 | public void Sr25519KeyPairTest() 27 | { 28 | // Secret Key URI `//Alice` is account: 29 | // Secret seed: 0xe5be9a5092b81bca64be81d212e7f2f9eba183bb7a90954f7b76361f6edb5c0a 30 | // Public key(hex): 0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d 31 | // Account ID: 0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d 32 | // SS58 Address: 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY 33 | 34 | var miniSecretAlice = new MiniSecret(Utils.HexToByteArray("0xe5be9a5092b81bca64be81d212e7f2f9eba183bb7a90954f7b76361f6edb5c0a"), ExpandMode.Ed25519); 35 | var keyPairAlice = miniSecretAlice.GetPair(); 36 | 37 | Assert.AreEqual("0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d", Utils.Bytes2HexString(keyPairAlice.Public.Key).ToLower()); 38 | Assert.AreEqual("0x925a225d97aa00682d6a59b95b18780c10d7032336e88f3442b42361f4a66011", Utils.Bytes2HexString(keyPairAlice.Secret.nonce).ToLower()); 39 | Assert.AreEqual("5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", Utils.GetAddressFrom(keyPairAlice.Public.Key)); 40 | 41 | // Secret Key URI `//Bob` is account: 42 | // Secret seed: 0x398f0c28f98885e046333d4a41c19cee4c37368a9832c6502f6cfd182e2aef89 43 | // Public key(hex): 0x8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48 44 | // Account ID: 0x8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48 45 | // SS58 Address: 5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty 46 | 47 | var miniSecretBob = new MiniSecret(Utils.HexToByteArray("0x398f0c28f98885e046333d4a41c19cee4c37368a9832c6502f6cfd182e2aef89"), ExpandMode.Ed25519); 48 | var keyPairBob = miniSecretBob.GetPair(); 49 | 50 | Assert.AreEqual("0x8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48", Utils.Bytes2HexString(keyPairBob.Public.Key).ToLower()); 51 | Assert.AreEqual("0x41ae88f85d0c1bfc37be41c904e1dfc01de8c8067b0d6d5df25dd1ac0894a325", Utils.Bytes2HexString(keyPairBob.Secret.nonce).ToLower()); 52 | Assert.AreEqual("5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty", Utils.GetAddressFrom(keyPairBob.Public.Key)); 53 | } 54 | 55 | [Test] 56 | public void Sr25519SignatureTest() 57 | { 58 | var miniSecretAlice = new MiniSecret(Utils.HexToByteArray("0xe5be9a5092b81bca64be81d212e7f2f9eba183bb7a90954f7b76361f6edb5c0a"), ExpandMode.Ed25519); 59 | var keyPairAlice = miniSecretAlice.GetPair(); 60 | 61 | var messageLength = _random.Next(10, 200); 62 | var message = new byte[messageLength]; 63 | _random.NextBytes(message); 64 | 65 | var simpleSign = Schnorrkel.Sr25519v091.SignSimple(keyPairAlice, message); 66 | 67 | Assert.True(Schnorrkel.Sr25519v091.Verify(simpleSign, keyPairAlice.Public.Key, message)); 68 | } 69 | 70 | [Test] 71 | public void SignatureVerifyOnNodeSignedHereByAccount() 72 | { 73 | // https://polkadot.js.org/apps/#/signing/verify 74 | 75 | Assert.True(true); 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /SubstrateNetApiTest/RequestGeneratorTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using SubstrateNetApi; 3 | using SubstrateNetApi.Model.Meta; 4 | 5 | namespace SubstrateNetApiTests 6 | { 7 | public class RequestGeneratorTests 8 | { 9 | [SetUp] 10 | public void Setup() 11 | { 12 | } 13 | 14 | [Test] 15 | public void GetStorageTest() 16 | { 17 | var module = new Module {Name = "Sudo"}; 18 | var item = new Item {Name = "Key"}; 19 | var result = RequestGenerator.GetStorage(module, item); 20 | Assert.AreEqual("0x5C0D1176A568C1F92944340DBFED9E9C530EBCA703C85910E7164CB7D1C9E47B", result); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /SubstrateNetApiTest/Subscription/SubscriptionTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Numerics; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | using NLog; 6 | using NLog.Config; 7 | using NLog.Targets; 8 | using NUnit.Framework; 9 | using SubstrateNetApi; 10 | using SubstrateNetApi.Model.Rpc; 11 | using SubstrateNetApi.Model.Types.Base; 12 | 13 | namespace SubstrateNetApiTests 14 | { 15 | public class SubscriptionTest 16 | { 17 | private const string WebSocketUrl = "wss://rpc.polkadot.io"; 18 | 19 | private SubstrateClient _substrateClient; 20 | 21 | [OneTimeSetUp] 22 | public void Setup() 23 | { 24 | var config = new LoggingConfiguration(); 25 | 26 | // Targets where to log to: File and Console 27 | var logconsole = new ConsoleTarget("logconsole"); 28 | 29 | // Rules for mapping loggers to targets 30 | config.AddRule(LogLevel.Debug, LogLevel.Fatal, logconsole); 31 | 32 | // Apply config 33 | LogManager.Configuration = config; 34 | 35 | _substrateClient = new SubstrateClient(new Uri(WebSocketUrl)); 36 | } 37 | 38 | [OneTimeTearDown] 39 | public void TearDown() 40 | { 41 | _substrateClient.Dispose(); 42 | } 43 | 44 | [Test] 45 | public async Task BasicSubscriptionTestAsync() 46 | { 47 | await _substrateClient.ConnectAsync(); 48 | 49 | Header currentHeader = null; 50 | 51 | Action callAllHeads = (subscriptionId, eventObject) => 52 | { 53 | currentHeader = eventObject; 54 | }; 55 | 56 | await _substrateClient.Chain.SubscribeAllHeadsAsync(callAllHeads, CancellationToken.None); 57 | 58 | Thread.Sleep(1000); 59 | 60 | var value1 = currentHeader.Number.Value; 61 | 62 | Assert.IsTrue(value1 > 1); 63 | 64 | Thread.Sleep(10000); 65 | 66 | Assert.IsTrue(value1 < currentHeader.Number.Value); 67 | 68 | await _substrateClient.CloseAsync(); 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /SubstrateNetApiTest/SubstrateNetApiTests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | PreserveNewest 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /SubstrateNetApiTest/SystemInteraction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace SubstrateNetWallet 5 | { 6 | public static class SystemInteraction 7 | { 8 | public static Func ReadData { get; set; } 9 | public static Func DataExists { get; set; } 10 | public static Func ReadPersistent { get; set; } 11 | public static Func PersistentExists { get; set; } 12 | public static Action Persist { get; set; } 13 | 14 | public static string ReadAllText(string path) 15 | { 16 | // First check if file exists in persistent store. 17 | if (PersistentExists(path)) return ReadPersistent(path); 18 | 19 | // Then check if file exists in data store. 20 | if (DataExists(path)) return ReadData(path); 21 | 22 | throw new FileNotFoundException(path); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /SubstrateNetApiTest/TypeConverters/EventDecodeTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text; 5 | using Newtonsoft.Json; 6 | using NUnit.Framework; 7 | using SubstrateNetApi.Model.Meta; 8 | using SubstrateNetApi.Model.Rpc; 9 | using SubstrateNetApi.Model.Types.Base; 10 | using SubstrateNetApi.Model.Types.Enum; 11 | using SubstrateNetApi.Model.Types.Struct; 12 | using SubstrateNetApi.TypeConverters; 13 | using SubstrateNetWallet; 14 | 15 | namespace SubstrateNetApiTests.TypeConverters 16 | { 17 | public class EventDecodeTest 18 | { 19 | private MetaData _metaData; 20 | 21 | [SetUp] 22 | public void Setup() 23 | { 24 | SystemInteraction.ReadData = f => File.ReadAllText(Path.Combine(Environment.CurrentDirectory, f)); 25 | SystemInteraction.DataExists = f => File.Exists(Path.Combine(Environment.CurrentDirectory, f)); 26 | SystemInteraction.ReadPersistent = f => File.ReadAllText(Path.Combine(Environment.CurrentDirectory, f)); 27 | SystemInteraction.PersistentExists = f => File.Exists(Path.Combine(Environment.CurrentDirectory, f)); 28 | SystemInteraction.Persist = (f, c) => File.WriteAllText(Path.Combine(Environment.CurrentDirectory, f), c); 29 | 30 | var metaDataJson = File.ReadAllText(Path.Combine(Environment.CurrentDirectory, "DOTMogNET.json")); 31 | _metaData = JsonConvert.DeserializeObject(metaDataJson); 32 | } 33 | 34 | [Test] 35 | public void BasicEvent1() 36 | { 37 | Assert.NotNull(_metaData); 38 | 39 | var eventStr = "0x04000000000000005095a20900000000020000"; 40 | var eventRecords = new EventRecords(_metaData); 41 | eventRecords.Create(eventStr); 42 | 43 | Assert.AreEqual(1, eventRecords.Value.Count); 44 | Assert.AreEqual(PhaseState.None, eventRecords.Value[0].Phase.PhaseState.Value); 45 | Assert.AreEqual(0, eventRecords.Value[0].Phase.ApplyExtrinsic.Value); 46 | 47 | Assert.AreEqual("System", eventRecords.Value[0].BaseEvent.ModuleName); 48 | Assert.AreEqual("ExtrinsicSuccess", eventRecords.Value[0].BaseEvent.EventName); 49 | Assert.AreEqual(1, eventRecords.Value[0].BaseEvent.EventArgs.Length); 50 | Assert.AreEqual("DispatchInfo", eventRecords.Value[0].BaseEvent.EventArgs[0].GetType().Name); 51 | var dispetchInfo = (DispatchInfo) eventRecords.Value[0].BaseEvent.EventArgs[0]; 52 | Assert.AreEqual(161650000, dispetchInfo.Weight.Value); 53 | } 54 | 55 | [Test] 56 | public void BasicEvent2() 57 | { 58 | Assert.NotNull(_metaData); 59 | 60 | var eventStr = "0x08000000000000005095a20900000000020000000100000000000000000000000000020000"; 61 | var eventRecords = new EventRecords(_metaData); 62 | eventRecords.Create(eventStr); 63 | 64 | // TODO add asserts 65 | Assert.True(true); 66 | } 67 | 68 | [Test] 69 | public void BasicEvent3() 70 | { 71 | Assert.NotNull(_metaData); 72 | 73 | var eventStr = "0x1802130100020800bc0000007f9267dfabb62a000000000000000000ac9baa9c3eff7f000000" + 74 | "00000000000000021006ac9baa9c3eff7f000000000000000000000209006e0400000000000000000000" + 75 | "5095a20900000000020000010f00087c932416d1f140d6351d3b6b09ff6fee66ff240bdb92976d36c2ef" + 76 | "5b13d83c7f0100000000000000490b83057d01d315d27e2b607c31754419bce23df85e39db096abce127" + 77 | "16470b010000000000000000"; 78 | var eventRecords = new EventRecords(_metaData); 79 | eventRecords.Create(eventStr); 80 | 81 | // TODO add asserts 82 | Assert.True(true); 83 | } 84 | 85 | [Test] 86 | public void AdvancedJsonConverter1() 87 | { 88 | string state_storage_response = 89 | "{\r\n\"block\":\"0x30712fe96155dcce61b9e3e41844f13e7a6f642f27a745e44a483b0009191c77\",\r\n\"changes\":[\r\n[\r\n\"0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9438d5c56935253cd6d9ea70f2bf95d60137f0ffc8904f42aaabf63d4ec80862f5087a8b059260c191401e03c03836767\",\r\nnull\r\n]\r\n]\r\n}"; 90 | StorageChangeSet storageChangeSet = JsonConvert.DeserializeObject(state_storage_response); 91 | 92 | Assert.AreEqual("0x30712FE96155DCCE61B9E3E41844F13E7A6F642F27A745E44A483B0009191C77", storageChangeSet.Block.Value); 93 | 94 | //NewStorageChangeSet newStorageChangeSet = JsonConvert.DeserializeObject(state_storage_response); 95 | //Assert.AreEqual("0x30712FE96155DCCE61B9E3E41844F13E7A6F642F27A745E44A483B0009191C77", newStorageChangeSet.Block.Value); 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /SubstrateNetApiTest/TypeConverters/TypeConverterTest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Numerics; 3 | using NUnit.Framework; 4 | using SubstrateNetApi; 5 | using SubstrateNetApi.Model.Types.Base; 6 | using SubstrateNetApi.Model.Types.Struct; 7 | using SubstrateNetApi.TypeConverters; 8 | 9 | namespace SubstrateNetApiTests 10 | { 11 | public class TypeConverterTest 12 | { 13 | [Test] 14 | public void BoolTypeConverterTest() 15 | { 16 | var tc = new GenericTypeConverter(); 17 | var actual = (Bool)tc.Create("0x00"); 18 | Assert.AreEqual(false, actual.Value); 19 | actual = (Bool)tc.Create("0x01"); 20 | Assert.AreEqual(true, actual.Value); 21 | } 22 | 23 | [Test] 24 | public void U16TypeConverterTest() 25 | { 26 | var tc = new GenericTypeConverter(); 27 | var actual = (U16) tc.Create("0xf142"); 28 | Assert.AreEqual((short) 0x42f1, actual.Value); 29 | } 30 | 31 | [Test] 32 | public void U32TypeConverterTest() 33 | { 34 | var tc = new GenericTypeConverter(); 35 | var actual = (U32) tc.Create("0xf142bca0"); 36 | Assert.AreEqual(0xa0bc42f1, actual.Value); 37 | } 38 | 39 | [Test] 40 | public void U64TypeConverterTest() 41 | { 42 | var tc = new GenericTypeConverter(); 43 | var actual = (U64) tc.Create("0x01de99faf142bca0"); 44 | Assert.AreEqual(0xa0bc42f1fa99de01, actual.Value); 45 | } 46 | 47 | [Test] 48 | public void VecU8TypeConverterTest() 49 | { 50 | var tc = new GenericTypeConverter>(); 51 | var actual = (Vec) tc.Create("0x200101020304050607"); 52 | Assert.AreEqual(1, actual.Value[0].Value); 53 | Assert.AreEqual(1, actual.Value[1].Value); 54 | Assert.AreEqual(2, actual.Value[2].Value); 55 | Assert.AreEqual(3, actual.Value[3].Value); 56 | Assert.AreEqual(4, actual.Value[4].Value); 57 | Assert.AreEqual(5, actual.Value[5].Value); 58 | Assert.AreEqual(6, actual.Value[6].Value); 59 | Assert.AreEqual(7, actual.Value[7].Value); 60 | } 61 | 62 | } 63 | } -------------------------------------------------------------------------------- /SubstrateNetApiTest/TypeConverters/TypeEncodingTest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Numerics; 3 | using NUnit.Framework; 4 | using SubstrateNetApi; 5 | using SubstrateNetApi.Model.Types; 6 | using SubstrateNetApi.Model.Types.Base; 7 | using SubstrateNetApi.Model.Types.Custom; 8 | using SubstrateNetApi.Model.Types.Enum; 9 | using SubstrateNetApi.Model.Types.Struct; 10 | using SubstrateNetApi.TypeConverters; 11 | 12 | namespace SubstrateNetApiTests 13 | { 14 | public class TypeEncodingTest 15 | { 16 | [Test] 17 | public void VecU8EncodingTest() 18 | { 19 | var tc = new GenericTypeConverter>(); 20 | var actual = (Vec)tc.Create("0x200101020304050607"); 21 | 22 | Assert.AreEqual(actual.Bytes, actual.Encode()); 23 | 24 | var t1 = new U8(); t1.Create(actual.Value[0].Value); 25 | var t2 = new U8(); t2.Create(actual.Value[1].Value); 26 | var t3 = new U8(); t3.Create(actual.Value[2].Value); 27 | var t4 = new U8(); t4.Create(actual.Value[3].Value); 28 | var t5 = new U8(); t5.Create(actual.Value[4].Value); 29 | var t6 = new U8(); t6.Create(actual.Value[5].Value); 30 | var t7 = new U8(); t7.Create(actual.Value[6].Value); 31 | var t8 = new U8(); t8.Create(actual.Value[7].Value); 32 | 33 | List list = new List() 34 | { 35 | t1,t2,t3,t4,t5,t6,t7,t8 36 | }; 37 | 38 | var vecU8 = new Vec(); 39 | vecU8.Create(list); 40 | 41 | Assert.AreEqual("0x200101020304050607", Utils.Bytes2HexString(vecU8.Bytes)); 42 | 43 | } 44 | 45 | [Test] 46 | public void EnumEncodingTest() 47 | { 48 | var dispatchClass1 = new EnumType(); 49 | var dispatchClass2 = new EnumType(); 50 | 51 | 52 | dispatchClass1.Create("0x00"); 53 | dispatchClass2.Create(DispatchClass.Normal); 54 | 55 | Assert.AreEqual(DispatchClass.Normal, dispatchClass1.Value); 56 | Assert.AreEqual(dispatchClass2.Value, dispatchClass1.Value); 57 | 58 | dispatchClass1.Create("0x01"); 59 | dispatchClass2.Create(DispatchClass.Operational); 60 | 61 | Assert.AreEqual(DispatchClass.Operational, dispatchClass1.Value); 62 | Assert.AreEqual(dispatchClass2.Value, dispatchClass1.Value); 63 | 64 | dispatchClass1.Create("0x02"); 65 | dispatchClass2.Create(DispatchClass.Mandatory); 66 | 67 | Assert.AreEqual(DispatchClass.Mandatory, dispatchClass1.Value); 68 | Assert.AreEqual(dispatchClass2.Value, dispatchClass1.Value); 69 | 70 | } 71 | 72 | [Test] 73 | public void OptionEncodingTest() 74 | { 75 | var optionU8Null = new Option(); 76 | var optionU8One = new Option(); 77 | 78 | optionU8Null.Create("0x00"); 79 | optionU8One.Create("0x0100"); 80 | 81 | Assert.AreEqual(null, optionU8Null.Value); 82 | Assert.AreEqual(0, optionU8One.Value.Value); 83 | 84 | Assert.AreEqual("0x00", Utils.Bytes2HexString(optionU8Null.Bytes)); 85 | Assert.AreEqual("0x0100", Utils.Bytes2HexString(optionU8One.Bytes)); 86 | } 87 | 88 | [Test] 89 | public void ExtEnumEncodingTest() 90 | { 91 | var extEnumType = new ExtEnumType(); 92 | 93 | int p = 0; 94 | extEnumType.Decode(new byte[] { 0x00, 0x01 }, ref p); 95 | 96 | Assert.AreEqual(PhaseState.None, extEnumType.Value); 97 | Assert.AreEqual("U8", extEnumType.Value2.GetType().Name); 98 | Assert.AreEqual(1, (extEnumType.Value2 as U8).Value); 99 | 100 | } 101 | } 102 | } -------------------------------------------------------------------------------- /SubstrateNetApiTest/TypeConverters/TypesMapperTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Numerics; 4 | using NUnit.Framework; 5 | using SubstrateNetApi; 6 | using SubstrateNetApi.Model.Types; 7 | using SubstrateNetApi.Model.Types.Base; 8 | using SubstrateNetApi.Model.Types.Enum; 9 | using SubstrateNetApi.Model.Types.Struct; 10 | using SubstrateNetApi.TypeConverters; 11 | 12 | namespace SubstrateNetApiTests 13 | { 14 | public class TypesMapperTest 15 | { 16 | [Test] 17 | public void TypeUtilTest() 18 | { 19 | Type type = null; 20 | Assert.IsTrue(TypeUtil.TryGetType("U8", out type)); 21 | Assert.AreEqual("SubstrateNetApi.Model.Types.Base.U8", type.FullName); 22 | 23 | Assert.IsTrue(TypeUtil.TryGetType("BalanceStatus", out type)); 24 | Assert.AreEqual("SubstrateNetApi.Model.Types.Enum.BalanceStatus", type.FullName); 25 | 26 | Assert.IsTrue(TypeUtil.TryGetType("AccountData", out type)); 27 | Assert.AreEqual("SubstrateNetApi.Model.Types.Struct.AccountData", type.FullName); 28 | 29 | Assert.IsTrue(TypeUtil.TryGetType("MogwaiStruct", out type)); 30 | Assert.AreEqual("SubstrateNetApi.Model.Types.Custom.MogwaiStruct", type.FullName); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /SubstrateNetApiTest/UtilsTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | using SubstrateNetApi; 4 | 5 | namespace SubstrateNetApiTests 6 | { 7 | public class UtilsTests 8 | { 9 | [SetUp] 10 | public void Setup() 11 | { 12 | } 13 | 14 | [Test] 15 | public void GetPublicKeyFromTest() 16 | { 17 | var address = "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"; 18 | var bytes = Utils.GetPublicKeyFrom(address); 19 | Assert.AreEqual("D43593C715FDD31C61141ABD04A99FD6822C8558854CCDE39A5684E7A56DA27D", 20 | BitConverter.ToString(bytes).Replace("-", "")); 21 | } 22 | 23 | [Test] 24 | public void GetAddressFromTest() 25 | { 26 | var publicKeyString = "0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"; 27 | var publickey = Utils.HexToByteArray(publicKeyString); 28 | var address = Utils.GetAddressFrom(publickey); 29 | Assert.AreEqual("5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", address); 30 | } 31 | 32 | [Test] 33 | public void LittleEndianIntegerTest() 34 | { 35 | Assert.AreEqual(259, Utils.Bytes2Value(Utils.HexToByteArray("0x0301"))); 36 | Assert.AreEqual("0x0301", Utils.Bytes2HexString(Utils.Value2Bytes((ushort)259))); 37 | } 38 | 39 | [Test] 40 | public void StringValueArrayBytesArrayTest() 41 | { 42 | Assert.AreEqual(new byte[] { 0x01, 0x02, 0x03, 0x04 }, Utils.StringValueArrayBytesArray("[ 1, 2, 3, 4]")); 43 | Assert.AreEqual(new byte[] { 0x0C, 0x0D, 0x0E, 0x0F }, Utils.StringValueArrayBytesArray("12, 13, 14, 15")); 44 | Assert.AreEqual(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF }, Utils.StringValueArrayBytesArray("255,255,255,255")); 45 | } 46 | 47 | [Test] 48 | public void StringValueArrayBytesArrayFailedTest() 49 | { 50 | Assert.Throws(delegate { Utils.StringValueArrayBytesArray("Test"); }); 51 | } 52 | 53 | [Test] 54 | public void Byte2ValueTest() 55 | { 56 | var ushortValue = (ushort)Utils.Bytes2Value(new byte[] { 0xFF, 0xFF }); 57 | Assert.AreEqual(65535, ushortValue); 58 | 59 | var uintValue = (uint)Utils.Bytes2Value(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF }); 60 | Assert.AreEqual(4294967295, uintValue); 61 | 62 | var ulongValue = (ulong)Utils.Bytes2Value(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }); 63 | Assert.AreEqual(18446744073709551615, ulongValue); 64 | 65 | Assert.AreEqual(0x1312, Utils.Bytes2Value(new byte[] {0x13,0x12}, false)); 66 | 67 | Assert.Throws(delegate 68 | { 69 | Utils.Bytes2Value(new byte[] {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}); 70 | }); 71 | } 72 | 73 | [Test] 74 | public void HexToByteArrayFailedTest() 75 | { 76 | Assert.Throws(delegate { Utils.HexToByteArray("111"); }); 77 | } 78 | 79 | [Test] 80 | public void HexToByteArrayZeroTest() 81 | { 82 | Assert.AreEqual(new byte[] { 0x00 }, Utils.HexToByteArray("0x0")); 83 | } 84 | 85 | [Test] 86 | public void HexToByteArrayUnevenTest() 87 | { 88 | Assert.AreEqual(new byte[] { 0x01, 0x11 }, Utils.HexToByteArray("0x111", true)); 89 | } 90 | 91 | [Test] 92 | public void Value2BytesTest() 93 | { 94 | Assert.AreEqual(new byte[] { 0x12, 0x11 }, Utils.Value2Bytes((ushort)0x1112)); 95 | Assert.AreEqual(new byte[] { 0x15, 0x14, 0x13, 0x12 }, Utils.Value2Bytes((uint)0x12131415)); 96 | Assert.AreEqual(new byte[] { 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x09, 0x08 }, Utils.Value2Bytes((ulong)0x0809101112131415)); 97 | Assert.AreEqual(new byte[] { 0x11, 0x12 }, Utils.Value2Bytes((ushort)0x1112, false)); 98 | Assert.Throws(delegate { Utils.Value2Bytes(1.4); }); 99 | } 100 | 101 | [Test] 102 | public void Bytes2HexStringTest() 103 | { 104 | Assert.AreEqual("0x1213", Utils.Bytes2HexString(new byte[]{0x12, 0x13})); 105 | Assert.AreEqual("1213", Utils.Bytes2HexString(new byte[] { 0x12, 0x13 }, Utils.HexStringFormat.Pure)); 106 | Assert.AreEqual("12-13", Utils.Bytes2HexString(new byte[] { 0x12, 0x13 }, Utils.HexStringFormat.Dash)); 107 | } 108 | } 109 | } -------------------------------------------------------------------------------- /SubstrateNetApiTest/Values/ValueTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using SubstrateNetApi; 3 | using SubstrateNetApi.Model.Calls; 4 | using SubstrateNetApi.Model.Types.Base; 5 | using SubstrateNetApi.Model.Types.Struct; 6 | 7 | namespace SubstrateNetApiTests 8 | { 9 | public class ValueTests 10 | { 11 | [Test] 12 | public void EncodingTest() 13 | { 14 | var accountId = new AccountId(); 15 | accountId.Create("0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"); 16 | 17 | var balance = new Balance(); 18 | balance.Create(100); 19 | 20 | var callArguments = new GenericExtrinsicCall("", "", accountId, balance); 21 | switch (Constants.AddressVersion) 22 | { 23 | case 0: 24 | Assert.AreEqual("D43593C715FDD31C61141ABD04A99FD6822C8558854CCDE39A5684E7A56DA27D9101", 25 | Utils.Bytes2HexString(callArguments.Encode(), Utils.HexStringFormat.Pure)); 26 | break; 27 | case 1: 28 | Assert.AreEqual("FFD43593C715FDD31C61141ABD04A99FD6822C8558854CCDE39A5684E7A56DA27D9101", 29 | Utils.Bytes2HexString(callArguments.Encode(), Utils.HexStringFormat.Pure)); 30 | break; 31 | case 2: 32 | Assert.AreEqual("00D43593C715FDD31C61141ABD04A99FD6822C8558854CCDE39A5684E7A56DA27D9101", 33 | Utils.Bytes2HexString(callArguments.Encode(), Utils.HexStringFormat.Pure)); 34 | break; 35 | } 36 | } 37 | 38 | [Test] 39 | public void BalanceTest() 40 | { 41 | var balance1 = new Balance(); 42 | balance1.Create("0x518fd3f9a8503a4f7e00000000000000"); 43 | Assert.AreEqual("2329998717451725147985", balance1.Value.ToString()); 44 | 45 | var balance2 = new Balance(); 46 | balance2.Create(Utils.HexToByteArray("518fd3f9a8503a4f7e00000000000000")); 47 | Assert.AreEqual("2329998717451725147985", balance2.Value.ToString()); 48 | } 49 | 50 | [Test] 51 | public void AccountDataTest() 52 | { 53 | var accountData = new AccountData(); 54 | accountData.Create(Utils.HexToByteArray( 55 | "518fd3f9a8503a4f7e0000000000000000c040b571e8030000000000000000000000c16ff2862300000000000000000000000000000000000000000000000000")); 56 | Assert.AreEqual("2329998717451725147985", accountData.Free.Value.ToString()); 57 | Assert.AreEqual("1100000000000000", accountData.Reserved.Value.ToString()); 58 | Assert.AreEqual("0", accountData.FeeFrozen.Value.ToString()); 59 | Assert.AreEqual("10000000000000000", accountData.MiscFrozen.Value.ToString()); 60 | } 61 | 62 | [Test] 63 | public void AccountInfoTest() 64 | { 65 | var accountInfo = new AccountInfo(); 66 | accountInfo.Create(Utils.HexToByteArray( 67 | "0500000000000000010000001d58857016a4755a6c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")); 68 | Assert.AreEqual(5, accountInfo.Nonce.Value); 69 | Assert.AreEqual(0, accountInfo.Consumers.Value); 70 | Assert.AreEqual(1, accountInfo.Providers.Value); 71 | Assert.AreEqual("1998766656412604258333", accountInfo.AccountData.Free.Value.ToString()); 72 | Assert.AreEqual("0", accountInfo.AccountData.Reserved.Value.ToString()); 73 | Assert.AreEqual("0", accountInfo.AccountData.FeeFrozen.Value.ToString()); 74 | Assert.AreEqual("0", accountInfo.AccountData.MiscFrozen.Value.ToString()); 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /SubstrateNetWallet/Caching.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Newtonsoft.Json; 3 | using NLog; 4 | 5 | namespace SubstrateNetWallet 6 | { 7 | public class Caching 8 | { 9 | private static readonly ILogger Logger = LogManager.GetCurrentClassLogger(); 10 | 11 | /// 12 | /// Tries the read file. 13 | /// 14 | /// 15 | /// The path. 16 | /// The object. 17 | /// 18 | public static bool TryReadFile(string path, out T obj) 19 | { 20 | obj = default; 21 | 22 | try 23 | { 24 | var objDecrypted = Decrypt(SystemInteraction.ReadAllText(path)); 25 | obj = JsonConvert.DeserializeObject(objDecrypted); 26 | return true; 27 | } 28 | catch (Exception e) 29 | { 30 | Logger.Error($"TryReadFile<{obj?.GetType()}>: {e}"); 31 | return false; 32 | } 33 | } 34 | 35 | /// 36 | /// Persists the specified path. 37 | /// 38 | /// 39 | /// The path. 40 | /// The object. 41 | public static void Persist(string path, T obj) 42 | { 43 | var objEncrypted = Encrypt(JsonConvert.SerializeObject(obj)); 44 | SystemInteraction.Persist(path, objEncrypted); 45 | } 46 | 47 | //unused, already encrypted maybe for later 48 | private static string Encrypt(string str) 49 | { 50 | return str; 51 | } 52 | 53 | //unused, already encrypted maybe for later 54 | private static string Decrypt(string str) 55 | { 56 | return str; 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /SubstrateNetWallet/ChainInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Newtonsoft.Json; 3 | using SubstrateNetApi.Model.Rpc; 4 | 5 | namespace SubstrateNetWallet 6 | { 7 | /// 8 | /// Chain Info 9 | /// 10 | /// 11 | public class ChainInfo : EventArgs 12 | { 13 | /// 14 | /// Initializes a new instance of the class. 15 | /// 16 | /// The name. 17 | /// The version. 18 | /// The chain. 19 | /// The runtime. 20 | public ChainInfo(string name, string version, string chain, RuntimeVersion runtime) 21 | { 22 | Name = name; 23 | Version = version; 24 | Chain = chain; 25 | RuntimeVersion = runtime; 26 | } 27 | 28 | /// 29 | /// Gets the name. 30 | /// 31 | /// 32 | /// The name. 33 | /// 34 | public string Name { get; } 35 | 36 | /// 37 | /// Gets the version. 38 | /// 39 | /// 40 | /// The version. 41 | /// 42 | public string Version { get; } 43 | 44 | /// 45 | /// Gets the chain. 46 | /// 47 | /// 48 | /// The chain. 49 | /// 50 | public string Chain { get; } 51 | 52 | /// 53 | /// Gets the runtime version. 54 | /// 55 | /// 56 | /// The runtime version. 57 | /// 58 | public RuntimeVersion RuntimeVersion { get; } 59 | 60 | /// 61 | /// Gets the block number. 62 | /// 63 | /// 64 | /// The block number. 65 | /// 66 | public ulong BlockNumber { get; private set; } 67 | 68 | internal void UpdateFinalizedHeader(Header header) 69 | { 70 | BlockNumber = header.Number.Value; 71 | } 72 | 73 | /// 74 | /// Converts to string. 75 | /// 76 | /// 77 | /// A that represents this instance. 78 | /// 79 | public override string ToString() 80 | { 81 | return JsonConvert.SerializeObject(this); 82 | } 83 | } 84 | } -------------------------------------------------------------------------------- /SubstrateNetWallet/ManagedAes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Security.Cryptography; 4 | 5 | namespace SubstrateNetWallet 6 | { 7 | /// 8 | /// AesManaged Class 9 | /// Using AES Provides a managed implementation of the Advanced Encryption Standard (AES) symmetric algorithm. 10 | /// For further information please visit 11 | /// https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.aesmanaged?view=netstandard-2.0 12 | /// 13 | public class ManagedAes 14 | { 15 | public static byte[] EncryptStringToBytes_Aes(string plainText, byte[] Key, byte[] IV) 16 | { 17 | // Check arguments. 18 | if (plainText == null || plainText.Length <= 0) 19 | throw new ArgumentNullException("plainText"); 20 | if (Key == null || Key.Length <= 0) 21 | throw new ArgumentNullException("Key"); 22 | if (IV == null || IV.Length <= 0) 23 | throw new ArgumentNullException("IV"); 24 | byte[] encrypted; 25 | 26 | // Create an Aes object 27 | // with the specified key and IV. 28 | using (var aesAlg = Aes.Create()) 29 | { 30 | aesAlg.Key = Key; 31 | aesAlg.IV = IV; 32 | 33 | // Create an encryptor to perform the stream transform. 34 | var encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV); 35 | 36 | // Create the streams used for encryption. 37 | using (var msEncrypt = new MemoryStream()) 38 | { 39 | using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) 40 | { 41 | using (var swEncrypt = new StreamWriter(csEncrypt)) 42 | { 43 | //Write all data to the stream. 44 | swEncrypt.Write(plainText); 45 | } 46 | 47 | encrypted = msEncrypt.ToArray(); 48 | } 49 | } 50 | } 51 | 52 | // Return the encrypted bytes from the memory stream. 53 | return encrypted; 54 | } 55 | 56 | /// 57 | /// Decrypts the string from bytes aes. 58 | /// 59 | /// The cipher text. 60 | /// The key. 61 | /// The iv. 62 | /// 63 | /// 64 | /// cipherText 65 | /// or 66 | /// Key 67 | /// or 68 | /// IV 69 | /// 70 | public static string DecryptStringFromBytes_Aes(byte[] cipherText, byte[] Key, byte[] IV) 71 | { 72 | // Check arguments. 73 | if (cipherText == null || cipherText.Length <= 0) 74 | throw new ArgumentNullException("cipherText"); 75 | if (Key == null || Key.Length <= 0) 76 | throw new ArgumentNullException("Key"); 77 | if (IV == null || IV.Length <= 0) 78 | throw new ArgumentNullException("IV"); 79 | 80 | // Declare the string used to hold 81 | // the decrypted text. 82 | string plaintext = null; 83 | 84 | // Create an Aes object 85 | // with the specified key and IV. 86 | using (var aesAlg = Aes.Create()) 87 | { 88 | aesAlg.Key = Key; 89 | aesAlg.IV = IV; 90 | 91 | // Create a decryptor to perform the stream transform. 92 | var decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV); 93 | 94 | // Create the streams used for decryption. 95 | using (var msDecrypt = new MemoryStream(cipherText)) 96 | { 97 | using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) 98 | { 99 | using (var srDecrypt = new StreamReader(csDecrypt)) 100 | { 101 | // Read the decrypted bytes from the decrypting stream 102 | // and place them in a string. 103 | plaintext = srDecrypt.ReadToEnd(); 104 | } 105 | } 106 | } 107 | } 108 | 109 | return plaintext; 110 | } 111 | } 112 | } -------------------------------------------------------------------------------- /SubstrateNetWallet/SubstrateNetWallet.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | true 6 | BloGa Tech AG 7 | Cedric Decoster 8 | A basic wallet implementation with the SubstrateNetApi. 9 | https://github.com/JetonNetwork/SubstrateNetApi/tree/origin/SubstrateNetWallet 10 | LICENSE 11 | https://github.com/JetonNetwork/SubstrateNetApi 12 | git 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | True 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /SubstrateNetWallet/SystemInteraction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace SubstrateNetWallet 5 | { 6 | public static class SystemInteraction 7 | { 8 | /// 9 | /// Gets or sets the read data. 10 | /// 11 | /// 12 | /// The read data. 13 | /// 14 | public static Func ReadData { get; set; } 15 | 16 | /// 17 | /// Gets or sets the data exists. 18 | /// 19 | /// 20 | /// The data exists. 21 | /// 22 | public static Func DataExists { get; set; } 23 | 24 | /// 25 | /// Gets or sets the read persistent. 26 | /// 27 | /// 28 | /// The read persistent. 29 | /// 30 | public static Func ReadPersistent { get; set; } 31 | 32 | /// 33 | /// Gets or sets the persistent exists. 34 | /// 35 | /// 36 | /// The persistent exists. 37 | /// 38 | public static Func PersistentExists { get; set; } 39 | 40 | /// 41 | /// Gets or sets the persist. 42 | /// 43 | /// 44 | /// The persist. 45 | /// 46 | public static Action Persist { get; set; } 47 | 48 | /// 49 | /// Reads all text. 50 | /// 51 | /// The path. 52 | /// 53 | /// 54 | public static string ReadAllText(string path) 55 | { 56 | // First check if file exists in persistent store. 57 | if (PersistentExists(path)) return ReadPersistent(path); 58 | 59 | // Then check if file exists in data store. 60 | if (DataExists(path)) return ReadData(path); 61 | 62 | throw new FileNotFoundException(path); 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /SubstrateNetWallet/WalletFile.cs: -------------------------------------------------------------------------------- 1 | using SubstrateNetApi.Model.Types; 2 | 3 | namespace SubstrateNetWallet 4 | { 5 | /// 6 | /// Wallet File description. 7 | /// 8 | public class WalletFile 9 | { 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// 13 | /// Type of the key. 14 | /// The public key. 15 | /// The encrypted seed. 16 | /// The salt. 17 | public WalletFile(KeyType keyType, byte[] publicKey, byte[] encryptedSeed, byte[] salt) 18 | { 19 | KeyType = keyType; 20 | PublicKey = publicKey; 21 | EncryptedSeed = encryptedSeed; 22 | Salt = salt; 23 | } 24 | 25 | /// 26 | /// Gets the type of the key. 27 | /// 28 | /// 29 | /// The type of the key. 30 | /// 31 | public KeyType KeyType { get; } 32 | 33 | /// 34 | /// Gets the public key. 35 | /// 36 | /// 37 | /// The public key. 38 | /// 39 | public byte[] PublicKey { get; } 40 | 41 | /// 42 | /// Gets the encrypted seed. 43 | /// 44 | /// 45 | /// The encrypted seed. 46 | /// 47 | public byte[] EncryptedSeed { get; } 48 | 49 | /// 50 | /// Gets the salt. 51 | /// 52 | /// 53 | /// The salt. 54 | /// 55 | public byte[] Salt { get; } 56 | } 57 | } -------------------------------------------------------------------------------- /SubstrateNetWalletTest/README.md: -------------------------------------------------------------------------------- 1 | # Initial Test Setup 2 | 3 | For a successful Test environment, make sure the chain has been setup with the initial actions. 4 | 5 | This applies to tests on the dotmog environment, for other substrate chains, just adjust the test setup. 6 | 7 | | Step | Action | 8 | | ------------- | ------------- | 9 | | 1. | SEND 1 DMOG to **5FfzQe73TTQhmSQCgvYocrr6vh1jJXEKB8xUB6tExfpKVCEZ** | 10 | | 2. | CREATE 1 MOGWAI on **5FfzQe73TTQhmSQCgvYocrr6vh1jJXEKB8xUB6tExfpKVCEZ** | 11 | 12 | -------------------------------------------------------------------------------- /SubstrateNetWalletTest/SubstrateNetWalletTests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | Always 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /SubstrateNetWalletTest/dev_wallet.dat: -------------------------------------------------------------------------------- 1 | {"KeyType":0,"PublicKey":"n54BhZZyCmeLir4glnLK+jIGHT9uBADZ1unbIo7hWk4=","EncryptedSeed":"F+OaxlyJTsJjOW6bhyDXinpf4MtsXAXcMudW3z1dLZYi2/20HODJBnuBC7A+Hc6cic/AYfuwY7YW/5HzqjFJgVhjKjVgHJHf7l2oadRPqKQ=","Salt":"NPBifbfJvxtYCllxImIulQ=="} -------------------------------------------------------------------------------- /TestExtrinsic/TestExtrinsic.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 1.0.{build} 2 | image: Visual Studio 2019 3 | dotnet_csproj: 4 | patch: true 5 | file: '**\*.csproj' 6 | version: '{version}' 7 | package_version: '{version}' 8 | assembly_version: '{version}' 9 | file_version: '{version}' 10 | informational_version: '{version}' 11 | environment: 12 | TARGET_CONFIGURATION: Release 13 | build_script: 14 | - cmd: >- 15 | dotnet build -p:Version=%APPVEYOR_BUILD_VERSION% --configuration %TARGET_CONFIGURATION% 16 | 17 | appveyor PushArtifact %APPVEYOR_BUILD_FOLDER%/SubstrateNetApi/bin/Release/SubstrateNetApi.%APPVEYOR_BUILD_VERSION%.nupkg -FileName SubstrateNetApi.%APPVEYOR_BUILD_VERSION%.nupkg -DeploymentName SubstrateNetApi 18 | 19 | appveyor PushArtifact %APPVEYOR_BUILD_FOLDER%/SubstrateNetWallet/bin/Release/SubstrateNetWallet.%APPVEYOR_BUILD_VERSION%.nupkg -FileName SubstrateNetWallet.%APPVEYOR_BUILD_VERSION%.nupkg -DeploymentName SubstrateNetWallet 20 | 21 | test_script: 22 | - cmd: >- 23 | dotnet test --configuration Release ./SubstrateNetApiTest 24 | 25 | dotnet test --configuration Release ./SubstrateNetWalletTest 26 | 27 | deploy: 28 | - provider: NuGet 29 | api_key: 30 | secure: CsUZhCNrxpwndMW1eqb3Cy0UdkDMOR+zjA9tnhe0ePq2569Vgp6r7p9xNpJ9Arr1 31 | artifact: /.*.nupkg/ 32 | -------------------------------------------------------------------------------- /images/advanced_architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ajuna-network/SubstrateNetApi/bd914f6c71d0d7bd5f1cae828ed1f179f7e256a1/images/advanced_architecture.png -------------------------------------------------------------------------------- /images/basic_architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ajuna-network/SubstrateNetApi/bd914f6c71d0d7bd5f1cae828ed1f179f7e256a1/images/basic_architecture.png -------------------------------------------------------------------------------- /images/dependencies.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ajuna-network/SubstrateNetApi/bd914f6c71d0d7bd5f1cae828ed1f179f7e256a1/images/dependencies.png --------------------------------------------------------------------------------