MCWrapper

A simple .NET Core wrapper aimed at supporting MultiChain Core blockchain networks

MCWrapper implements JSON-RPC and Command Line Interface (CLI) C# clients compatible the MultiChain Core blockchain library.

Execute RPC and CLI commands against the targeted MultiChain Core blockchain(s) using clients individually or in combination.

MCWrapper is available in three separate functional packages compatible with .NET Standard and .NET Core framworks.

MCWrapper.RPC, MCWrapper.CLI and therefore MCWrapper all depend on three additional NuGet packages we maintain, containing common and shared response class models, constants, and extension methods.

MCWrapper.Data.Models, MCWrapper.Ledger.Actions, and MCWrapper.Ledger.Entities are the three additional packages that will be installed when using any of the MCWrapper libraries.

The MCWrapper.RPC package only supports JSON-RPC communication with MultiChain Core ledgers.

Install the MCWrapper.RPC package from NuGet, download the source code from GitHub, and view our Unit tests.

The MCWrapper.CLI package is limited to direct interaction with the MultiChain Core executables installed on the local environment.

Install the MCWrapper.CLI package from NuGet, download the source code from GitHub, and view our Unit tests.

Note: MCWrapper.CLI has only been unit tested under Windows environments. We are working on Linux support now.

The MCWrapper package is a collaboration of projects, between the MCWrapper.RPC package and the MCWrapper.CLI package, offering an additional extension method and client factory. Install the package from NuGet, download the source code from GitHub, and view our Unit tests.

Need help configuring MCWrapper, MCWraper.RPC, or MCWrapper.CLI? Learn to configure the necessary RpcOptions and CliOptions class properties at our configure options page.

At the configure options page we make an effort to break down the configuration types that are available to consumers.

Web API

Example Web API using MCWrapper


An example solution file is hosted at GitHub demostrates using MCWrapper as a .NET Core WebAPI

Web APP

Example Web Application using MCWrapper


An example solution file is hosted at GitHub demostrates using MCWrapper as a .NET Core Web Application

Console application

Example console application using MCWrapper.CLI


Learn to create a .NET Core Console App using the MCWrapper library to interact with MultiChain-based blockchain networks.

The Console Application below demonstrates how easy it can be to create a new MultiChain Core blockchain ledger node using the MCWrapper.CLI NuGet package.

The example project is available on GitHub.


/// Disclaimer: I am not associated or affiliated with the MultiChain team.
///             I simply enjoy their product and decided to write a few packages
///             for personal use, then ended up sharing them with the public. Thanks.
///
///             MCWrapper.CLI - C# 8.0 / .NET Core 2.1, 2.2, and 3.0 Command Line Interface
///             (multichain-cli.exe) support for the MultiChain Core library.
///             https://www.nuget.org/packages/MCWrapper.CLI/
///
///             MCWrapper.RPC - C# 8.0 / .NET Core 2.1, 2.2, and 3.0 JSON-RPC support for the
///             MultiChain Core library.
///             https://www.nuget.org/packages/MCWrapper.RPC/
///
///             MCWrapper - A combining of MCWrapper.CLI and MCWrapper.RPC into a single 
///             convenient package.
///             New Extension method and ClientFactory class are available too.
///             https://www.nuget.org/packages/MCWrapper/
///
/// Note 1: MultiChain Core must be downloaded and installed to your local system before compiling the
///         code below. For the easiest configuration ensure that you place the uncompressed files at
///         C:\multichain (Win) or /usr/bin/local (Linux) and the MultiChain Core binaries will be 
///         automatically detected by the MCWrapper.CLI ForgeClient class.
/// 
/// (Courtesy of https://www.multichain.com/download-community/)
/// Installing MultiChain Community on Linux
///   su(enter root password)
///   cd /tmp
///   wget https://www.multichain.com/download/multichain-2.0.3.tar.gz
///   tar -xvzf multichain-2.0.3.tar.gz
///   cd multichain-2.0.3
///   mv multichaind multichain-cli multichain-util /usr/local/bin
///   exit(to return to your regular user)
///
/// Installing MultiChain Community on Windows
///     Download https://www.multichain.com/download/multichain-windows-2.0.3.zip and extract its contents
///     to C:\ or C:\multichain (this way you avoid needing to configure the MCWrapper.CLI CliOptions
///     'ChainBinaryLocation' property.
///     MCWrapper.CLI will automatcially look at either of these default locations for the necessary
///     MultiChain Core exe file(s)) when using any MCWrapper.CLI client
///
///
/// Note 2: At a minimum a 'blockchainName' parameter must either be passed to all MCWrapper.CLI methods
///         explicitly or when permitted the 'blockchainName' parameter can be inferred if stored in
///         the local Environment Variable store as Key: ChainName and Value: Your desired MultiChain
///         blockchain name goes here.
///         Furthermore, consumers may populate the 'ChainName' variable to an appsettings.json file 
///         which will be inferred from the IConfiguration pipeline, generally.
///
/// Note 3: The MCWrapper.CLI ForgeClient class methods always require a 'blockchainName' parameter.
///         This is to ensure the value is always present, obviously.
///
/// Note 4: The MCWrapper.CLI CliClient's all contain explicit and inferred 'blockchainName' methods.
///         An exception is thrown when no 'blockchainName' parameter is present due to lack of 
///         consumer configuration or is absent due to lack of explicit statement.
///
/// Note 5: The demo uses a MultiChain blockchain that does not generate native currency since that 
///         requires additional params.dat configuration we are not going to cover during this 
///         tutorial.
///
/// That's it for now.
///     Go get started, make some mistakes, learn a few things, and don't forget to have fun.
///
using MCWrapper.CLI.Ledger.Clients;
using MCWrapper.Ledger.Entities.ErrorHandling;
using MCWrapperConsole.ServicePipeline;
using System;
using System.Threading.Tasks;

namespace MCWrapperConsole
{
    class Program
    {
        // MCWrapper Command Line Interface (Cli) factory serves up all available CliClient services.
        // Included in the package at, MCWrapper.CLI.Ledger.Clients.
        // The ServicePipelineHelper class is available at the bottom of this page.
        private static readonly CliClientFactory _factory 
            = ServicePipelineHelper.GetService<CliClientFactory>();

        // Program entry point.
        static async Task Main(string[] args)
        {
            // *****************************************************************
            // Blockchain name to be used for this demo.
            //
            const string BLOCKCHAIN_NAME = "ExampleChain";

            // *****************************************************************
            // Attempt to create the example blockchain named 'ExampleChain'.
            //
            // Note: To increase stability a 'blockchainName' parameter is always required by the
            // ForgeClient.CreateBlockchainAsync() method.
            //
            var create = await _factory.ForgeClient.CreateBlockchainAsync(BLOCKCHAIN_NAME);
            if (!create.Success)
                throw new ServiceException($"Unable to create blockchain"); // custom exception

            // *****************************************************************
            // Attempt to start the new blockchain.
            //
            // Note: To increase stability a 'blockchainName' parameter is always required by the
            //       ForgeClient.StartBlockchainAsync() method.
            //
            var start = await _factory.ForgeClient.StartBlockchainAsync(BLOCKCHAIN_NAME);
            if (!start.Success)
                throw new ServiceException($"Unable to start blockchain"); // custom exception

            // *****************************************************************
            // Attempt to use the 'getblockchaininfo' blockchain method.
            //
            // Additionally, instead of explicitly passing the blockchain name,
            // consumers may also choose to infer the 'blockchainName' through the local
            // Environment Variable store or via the IConfiguration pipeline (appsettings.json).
            // Simply name the Key 'ChainName' and set the Value to whatever you want to or have 
            // already named your MultiChain blockchain.
            //
            // Example: var info = await _factory.BlockchainCliClient.GetBlockchainInfoAsync();
            //
            var info = await _factory.BlockchainCliClient.GetBlockchainInfoAsync(BLOCKCHAIN_NAME);
            foreach (var prop in info.Result.GetType().GetProperties()) // interate each property.
                Console.WriteLine($"{prop.Name}: {prop.GetValue(info.Result)}"); // print

            // *****************************************************************
            // Attempt to stop the new blockchain.
            //
            // Note: To increase stability a 'blockchainName' parameter is always required by the
            //       ForgeClient.StopBlockchainAsync() method.
            //
            var stop = await _factory.ForgeClient.StopBlockchainAsync(BLOCKCHAIN_NAME);
            if (!stop.Success)
                throw new ServiceException($"Unable to stop blockchain"); // custom exception

            // *****************************************************************
            // Super easy, right! In the next tutorial we will create a cold node based on the 
            // hote node we just created. Thanks.
            //
            // Questions? Use my contact form at https://ryangoodwin.dev (Hint: it's at the
            // bottom of the page).
        }
    }
    
    // Expected Console output, some values may differ slightly or entirely
    //
    // Chain: main
    // ChainName: ExampleChain
    // Description: MultiChain ExampleChain
    // Protocol: multichain
    // SetupBlocks: 60
    // ReIndex: False
    // Blocks: 2
    // Headers: 2
    // BestBlockHash: 007c75caba6f82a6b4f9773a0c147f3da457fe086b19849711bf3d2713bf877c
    // Difficulty: 5.9604645E-08
    // VerificationProgress: 1
    // Chainwork: 0000000000000000000000000000000000000000000000000000000000000300
    // ChainRewards: 0
    //
}

Below is the ServicePipelineHelper class that is necessary as a psuedo-dependency injection pipeline in the Console App example documented above. The ServicePipelineHelper is also available on GitHub


using MCWrapper.CLI.Extensions;
using MCWrapper.Ledger.Entities.ErrorHandling;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;

namespace MCWrapperConsole.ServicePipeline
{
    // ServiceHelper object creates a psuedo Dependency Injection pipeline.
    internal static class ServicePipelineHelper
    {
        //  Encapsulate service provider and services collection.
        private static IServiceProvider Provider;
        private static IServiceCollection Services;

        // Locate and return service type.
        // Automatically initiliaze the IServiceProvider on firt use.
        public static T GetService<T>()
        {
            // null detection attemtps to reinitialize the service provider.
            if (Provider == null)
                InitializeServiceProvider();

            // lookup service by Type.
            var service = Provider.GetService<T>();

            // null detection throws on no service found.
            if (service == null)
                throw new ServiceException("Service type unavailable");

            // service located successfully; return to subscriber.
            return service;
        }

        // Build service collection and provider.
        private static void InitializeServiceProvider()
        {
            // map configuration builder to local copy of appsettings.json file.
            var builder = new ConfigurationBuilder()
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);

            // fetch key/value pairs from appsettings.json file.
            IConfiguration configuration = builder.Build();

            // good place to instantiate our services collection.
            Services = new ServiceCollection();

            // Add MCWrapper MultiChain services to the services collection
            // dependency pipeline. WARNING! If this step is not completed
            // MCWrapper will not function properly MCWrapper is heavily
            // dependent on some sort of DI Pipeline.
            Services.AddMultiChainCoreCliServices(configuration);

            // build the local service provider.
            Provider = Services.BuildServiceProvider();
        }
    }
}