/// <summary>
        ///
        /// This method will deploy all contracts needed to run Wonka on-chain, using all the data provided.
        ///
        /// <returns>None</returns>
        /// </summary>
        public static async Task <bool> DeployContractsClassicAsync(this WonkaEthEngineInitialization poEngineInitData)
        {
            bool bResult = true;

            var EngineProps = poEngineInitData.Engine;

            if (EngineProps == null)
            {
                throw new Exception("ERROR!  No engine properties provided.");
            }

            if ((EngineProps.RulesEngine == null) && !String.IsNullOrEmpty(EngineProps.RulesMarkupXml))
            {
                var account = new Account(poEngineInitData.EthPassword);

                Nethereum.Web3.Web3 web3 = null;
                if (!String.IsNullOrEmpty(poEngineInitData.Web3HttpUrl))
                {
                    web3 = new Nethereum.Web3.Web3(account, poEngineInitData.Web3HttpUrl);
                }
                else
                {
                    web3 = new Nethereum.Web3.Web3(account);
                }

                if (String.IsNullOrEmpty(poEngineInitData.RulesEngineContractAddress))
                {
                    var EngineDeployment = new Autogen.WonkaEngine.WonkaEngineDeploymentClassic();

                    HexBigInteger nDeployGas = new HexBigInteger(CONST_DEPLOY_ENGINE_CONTRACT_GAS_COST);

                    poEngineInitData.RulesEngineContractAddress =
                        await EngineDeployment.DeployContractAsync(web3, poEngineInitData.RulesEngineABI, poEngineInitData.EthSenderAddress, nDeployGas, poEngineInitData.Web3HttpUrl).ConfigureAwait(false);
                }

                if (String.IsNullOrEmpty(poEngineInitData.RegistryContractAddress))
                {
                    var RegistryDeployment = new Autogen.WonkaRegistry.WonkaRegistryDeployment();

                    HexBigInteger nDeployGas = new HexBigInteger(CONST_DEPLOY_DEFAULT_CONTRACT_GAS_COST);

                    poEngineInitData.RegistryContractAddress =
                        await RegistryDeployment.DeployContractAsync(web3, poEngineInitData.RegistryContractABI, poEngineInitData.EthSenderAddress, nDeployGas, poEngineInitData.Web3HttpUrl).ConfigureAwait(false);
                }

                if (String.IsNullOrEmpty(poEngineInitData.StorageContractAddress))
                {
                    var TestContractDeployment = new Autogen.WonkaTestContract.WonkaTestContractDeployment();

                    HexBigInteger nDeployGas = new HexBigInteger(CONST_DEPLOY_DEFAULT_CONTRACT_GAS_COST);

                    poEngineInitData.StorageContractAddress =
                        await TestContractDeployment.DeployContractAsync(web3, poEngineInitData.StorageContractABI, poEngineInitData.EthSenderAddress, nDeployGas, poEngineInitData.Web3HttpUrl).ConfigureAwait(false);
                }
            }

            return(bResult);
        }
        /// <summary>
        ///
        /// This method will deploy all contracts needed to run Wonka on-chain, using all the data provided.
        ///
        /// <returns>None</returns>
        /// </summary>
        public static async Task <bool> DeployContractsAsync(this WonkaEthEngineInitialization poEngineInitData)
        {
            bool bResult = true;

            var EngineProps = poEngineInitData.Engine;

            if (EngineProps == null)
            {
                throw new Exception("ERROR!  No engine properties provided.");
            }

            if ((EngineProps.RulesEngine == null) && !String.IsNullOrEmpty(EngineProps.RulesMarkupXml))
            {
                var account = new Account(poEngineInitData.EthPassword);

                Nethereum.Web3.Web3 web3 = null;
                if (!String.IsNullOrEmpty(poEngineInitData.Web3HttpUrl))
                {
                    web3 = new Nethereum.Web3.Web3(account, poEngineInitData.Web3HttpUrl);
                }
                else
                {
                    web3 = new Nethereum.Web3.Web3(account);
                }

                if (String.IsNullOrEmpty(poEngineInitData.RulesEngineContractAddress))
                {
                    var WonkaLibABI         = Autogen.WonkaLibrary.WonkaLibraryDeployment.ABI;
                    var WonkaLibPlaceHolder = Autogen.WonkaLibrary.WonkaLibraryDeployment.PLACEHOLDER_KEY;

                    var EngineDeployment = new Autogen.WonkaEngine.WonkaEngineDeploymentClassic();

                    var WonkaLibDeployment = new Autogen.WonkaLibrary.WonkaLibraryDeployment();

                    HexBigInteger nDeployGas = new HexBigInteger(CONST_DEPLOY_ENGINE_CONTRACT_GAS_COST);

                    // Deploy the library contract first
                    var LibraryContractAddress =
                        await WonkaLibDeployment.DeployContractAsync(web3, WonkaLibABI, poEngineInitData.EthSenderAddress, nDeployGas, poEngineInitData.Web3HttpUrl).ConfigureAwait(false);

                    var libraryMapping =
                        new ByteCodeLibrary()
                    {
                        Address = LibraryContractAddress, PlaceholderKey = WonkaLibPlaceHolder
                    };

                    // Link main contract byte code with the library, in preparation for deployment
                    var contractByteCode = Autogen.WonkaEngine.WonkaEngineDeployment.BYTECODE;
                    var libraryMappings  = new ByteCodeLibrary[] { libraryMapping };
                    var libraryLinker    = new ByteCodeLibraryLinker();

                    var contractByteCodeLinked = libraryLinker.LinkByteCode(contractByteCode, libraryMappings);

                    // Deploy linked contract
                    var DeployEngineReceipt
                        = await web3.Eth.DeployContract.SendRequestAndWaitForReceiptAsync(contractByteCodeLinked, poEngineInitData.EthSenderAddress, nDeployGas, null, null, null).ConfigureAwait(false);

                    poEngineInitData.RulesEngineContractAddress = DeployEngineReceipt.ContractAddress;
                }

                if (String.IsNullOrEmpty(poEngineInitData.RegistryContractAddress))
                {
                    var RegistryDeployment = new Autogen.WonkaRegistry.WonkaRegistryDeployment();

                    HexBigInteger nDeployGas = new HexBigInteger(CONST_DEPLOY_DEFAULT_CONTRACT_GAS_COST);

                    poEngineInitData.RegistryContractAddress =
                        await RegistryDeployment.DeployContractAsync(web3, poEngineInitData.RegistryContractABI, poEngineInitData.EthSenderAddress, nDeployGas, poEngineInitData.Web3HttpUrl).ConfigureAwait(false);
                }

                if (String.IsNullOrEmpty(poEngineInitData.StorageContractAddress))
                {
                    var TestContractDeployment = new Autogen.WonkaTestContract.WonkaTestContractDeployment();

                    HexBigInteger nDeployGas = new HexBigInteger(CONST_DEPLOY_DEFAULT_CONTRACT_GAS_COST);

                    poEngineInitData.StorageContractAddress =
                        await TestContractDeployment.DeployContractAsync(web3, poEngineInitData.StorageContractABI, poEngineInitData.EthSenderAddress, nDeployGas, poEngineInitData.Web3HttpUrl).ConfigureAwait(false);
                }
            }

            return(bResult);
        }
        /// <summary>
        ///
        /// This method will initialize an instance of the Wonka.Net engine, using all the data provided.
        ///
        /// <returns>None</returns>
        /// </summary>
        public static async Task <bool> InitEngineAsync(this WonkaEthEngineInitialization poEngineInitData, bool pbRequireRetrieveValueMethod = true)
        {
            bool bResult = true;

            var EngineProps = poEngineInitData.Engine;

            if (EngineProps == null)
            {
                throw new Exception("ERROR!  No engine properties provided.");
            }

            if ((EngineProps.RulesEngine == null) && !String.IsNullOrEmpty(EngineProps.RulesMarkupXml))
            {
                if (pbRequireRetrieveValueMethod && (EngineProps.DotNetRetrieveMethod == null))
                {
                    throw new WonkaEthInitException("ERROR!  Retrieve method not provided for the Wonka.NET engine.", poEngineInitData);
                }

                if (EngineProps.MetadataSource == null)
                {
                    throw new WonkaEthInitException("ERROR!  No metadata source has been provided.", poEngineInitData);
                }

                // Using the metadata source, we create an instance of a defined data domain
                WonkaRefEnvironment WonkaRefEnv = WonkaRefEnvironment.CreateInstance(false, EngineProps.MetadataSource);

                var account = new Account(poEngineInitData.EthPassword);

                Nethereum.Web3.Web3 web3 = null;
                if (!String.IsNullOrEmpty(poEngineInitData.Web3HttpUrl))
                {
                    web3 = new Nethereum.Web3.Web3(account, poEngineInitData.Web3HttpUrl);
                }
                else
                {
                    web3 = new Nethereum.Web3.Web3(account);
                }

                if (String.IsNullOrEmpty(poEngineInitData.RulesEngineContractAddress))
                {
                    var EngineDeployment = new Autogen.WonkaEngine.WonkaEngineDeployment();

                    HexBigInteger nDeployGas = new HexBigInteger(CONST_DEPLOY_ENGINE_CONTRACT_GAS_COST);

                    poEngineInitData.RulesEngineContractAddress =
                        await EngineDeployment.DeployContractAsync(web3, poEngineInitData.RulesEngineABI, poEngineInitData.EthSenderAddress, nDeployGas, poEngineInitData.Web3HttpUrl).ConfigureAwait(false);
                }

                if (String.IsNullOrEmpty(poEngineInitData.RegistryContractAddress))
                {
                    var RegistryDeployment = new Autogen.WonkaRegistry.WonkaRegistryDeployment();

                    HexBigInteger nDeployGas = new HexBigInteger(CONST_DEPLOY_DEFAULT_CONTRACT_GAS_COST);

                    poEngineInitData.RegistryContractAddress =
                        await RegistryDeployment.DeployContractAsync(web3, poEngineInitData.RegistryContractABI, poEngineInitData.EthSenderAddress, nDeployGas, poEngineInitData.Web3HttpUrl).ConfigureAwait(false);
                }

                if (String.IsNullOrEmpty(poEngineInitData.StorageContractAddress))
                {
                    var TestContractDeployment = new Autogen.WonkaTestContract.WonkaTestContractDeployment();

                    HexBigInteger nDeployGas = new HexBigInteger(CONST_DEPLOY_DEFAULT_CONTRACT_GAS_COST);

                    poEngineInitData.StorageContractAddress =
                        await TestContractDeployment.DeployContractAsync(web3, poEngineInitData.StorageContractABI, poEngineInitData.EthSenderAddress, nDeployGas, poEngineInitData.Web3HttpUrl).ConfigureAwait(false);
                }

                if ((EngineProps.SourceMap == null) || (EngineProps.SourceMap.Count == 0))
                {
                    EngineProps.SourceMap = new Dictionary <string, WonkaBizSource>();

                    // Here a mapping is created, where each Attribute points to a specific contract and its "accessor" methods
                    // - the class that contains this information (contract, accessors, etc.) is of the WonkaBreSource type
                    foreach (WonkaRefAttr TempAttr in WonkaRefEnv.AttrCache)
                    {
                        WonkaBizSource TempSource =
                            new WonkaBizSource(poEngineInitData.StorageDefaultSourceId,
                                               poEngineInitData.EthSenderAddress,
                                               poEngineInitData.EthPassword,
                                               poEngineInitData.StorageContractAddress,
                                               poEngineInitData.StorageContractABI,
                                               poEngineInitData.StorageGetterMethod,
                                               poEngineInitData.StorageSetterMethod,
                                               EngineProps.DotNetRetrieveMethod);

                        EngineProps.SourceMap[TempAttr.AttrName] = TempSource;
                    }
                }

                EngineProps.RulesEngine =
                    new WonkaBizRulesEngine(new StringBuilder(EngineProps.RulesMarkupXml), EngineProps.SourceMap, EngineProps.MetadataSource);

                EngineProps.RulesEngine.DefaultSource = poEngineInitData.StorageDefaultSourceId;

                //NOTE: These Ethereum ops will not currently execute correctly within .NET during Async mode, since the Wonka.NET must then also be refactored to execute in Async
                //EngineProps.RulesEngine.SetDefaultStdOps(poEngineInitData.EthPassword, poEngineInitData.Web3HttpUrl);
            }

            return(bResult);
        }